diff options
| author | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
|---|---|---|
| committer | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
| commit | 967be9e750221ab2ab783f95df79bb26d290a45e (patch) | |
| tree | 6802900a5e975f9f68b169f0f503f040056d6952 /tiger-compiler/src/callgraph | |
Diffstat (limited to 'tiger-compiler/src/callgraph')
| -rw-r--r-- | tiger-compiler/src/callgraph/call-graph-visitor.cc | 56 | ||||
| -rw-r--r-- | tiger-compiler/src/callgraph/call-graph-visitor.hh | 38 | ||||
| -rw-r--r-- | tiger-compiler/src/callgraph/fundec-graph.hh | 76 | ||||
| -rw-r--r-- | tiger-compiler/src/callgraph/fundec-graph.hxx | 56 | ||||
| -rw-r--r-- | tiger-compiler/src/callgraph/libcallgraph.cc | 36 | ||||
| -rw-r--r-- | tiger-compiler/src/callgraph/libcallgraph.hh | 28 | ||||
| -rw-r--r-- | tiger-compiler/src/callgraph/local.am | 14 | ||||
| -rw-r--r-- | tiger-compiler/src/callgraph/parent-graph-visitor.cc | 42 | ||||
| -rw-r--r-- | tiger-compiler/src/callgraph/parent-graph-visitor.hh | 36 | ||||
| -rw-r--r-- | tiger-compiler/src/callgraph/tasks.cc | 52 | ||||
| -rw-r--r-- | tiger-compiler/src/callgraph/tasks.hh | 46 |
11 files changed, 480 insertions, 0 deletions
diff --git a/tiger-compiler/src/callgraph/call-graph-visitor.cc b/tiger-compiler/src/callgraph/call-graph-visitor.cc new file mode 100644 index 0000000..6ad31c5 --- /dev/null +++ b/tiger-compiler/src/callgraph/call-graph-visitor.cc @@ -0,0 +1,56 @@ +/** + ** \file callgraph/call-graph-visitor.cc + ** \brief Implementation of callgraph::CallGraphVisitor. + **/ + +#include <ast/call-exp.hh> +#include <ast/function-dec.hh> +#include <callgraph/call-graph-visitor.hh> + +namespace callgraph +{ + const CallGraph* CallGraphVisitor::create(const ast::Ast& tree) + { + // Create a new empty callgraph + callgraph_ = new CallGraph(); + + // Launch visitor. + tree.accept(*this); + + // Return created callgraph. + return callgraph_; + } + + CallGraph* CallGraphVisitor::create(ast::Ast& tree) + { + return const_cast<CallGraph*>(create(const_cast<const ast::Ast&>(tree))); + } + + /*-----------. + | Visiting. | + `-----------*/ + + void CallGraphVisitor::operator()(const ast::CallExp& e) + { + // FIXME: Some code was deleted here (Link the Caller with the CallExp's declaration). + } + + void CallGraphVisitor::operator()(const ast::FunctionChunk& e) + { + // First define the nodes for each defined function. + for (ast::FunctionDec* f : e) + callgraph_->fundec_add(f); + // Now bind callers and callees. + super_type::operator()(e); + } + + void CallGraphVisitor::operator()(const ast::FunctionDec& e) + { + // Current function becomes temporarily the caller function. + ast::FunctionDec* save = caller; + caller = const_cast<ast::FunctionDec*>(&e); + super_type::operator()(e); + caller = save; + } + +} // namespace callgraph diff --git a/tiger-compiler/src/callgraph/call-graph-visitor.hh b/tiger-compiler/src/callgraph/call-graph-visitor.hh new file mode 100644 index 0000000..97d79b4 --- /dev/null +++ b/tiger-compiler/src/callgraph/call-graph-visitor.hh @@ -0,0 +1,38 @@ +/** + ** \file callgraph/call-graph-visitor.hh + ** \brief Definition of callgraph::CallGraphVisitor. + **/ +#pragma once + +#include <ast/default-visitor.hh> +#include <ast/non-assert-visitor.hh> +#include <ast/non-object-visitor.hh> +#include <callgraph/fundec-graph.hh> + +namespace callgraph +{ + /// Computes the CallGraph. + class CallGraphVisitor + : protected ast::DefaultConstVisitor + , protected ast::NonObjectConstVisitor + , protected ast::NonAssertConstVisitor + { + public: + using super_type = ast::DefaultConstVisitor; + using super_type::operator(); + const CallGraph* create(const ast::Ast& tree); + CallGraph* create(ast::Ast& tree); + + protected: + void operator()(const ast::CallExp& e) override; + void operator()(const ast::FunctionChunk& e) override; + void operator()(const ast::FunctionDec& e) override; + + protected: + /// Current function. + ast::FunctionDec* caller = nullptr; + /// Call graph. + CallGraph* callgraph_ = nullptr; + }; + +} // namespace callgraph diff --git a/tiger-compiler/src/callgraph/fundec-graph.hh b/tiger-compiler/src/callgraph/fundec-graph.hh new file mode 100644 index 0000000..1addd0d --- /dev/null +++ b/tiger-compiler/src/callgraph/fundec-graph.hh @@ -0,0 +1,76 @@ +/** + ** \file callgraph/fundec-graph.hh + ** \brief Declare and define fundec graph. + */ + +#pragma once + +#include <map> + +#include <boost/graph/adjacency_list.hpp> + +#include <ast/function-dec.hh> +#include <misc/graph.hh> + +namespace callgraph +{ + /*--------------. + | FundecGraph. | + `--------------*/ + + class FundecGraph : public misc::directed_graph<ast::FunctionDec*> + { + public: + /// Add a vertex to the graph, and attach a function definition to it. + void fundec_add(ast::FunctionDec* f); + /// Create an edge between two vertices, identified by the + /// FunctionDec attached to each of them. + void fundec_link(ast::FunctionDec* fu, ast::FunctionDec* fv); + + /// Retrieve the vertex handle corresponding to a FunctionDec. + vertex_descriptor hfundec_get(ast::FunctionDec* f) const; + + // Search if FunctionDec 'searched' is 'start' or one of its parent. + ast::FunctionDec* hfundec_deep_get(ast::FunctionDec* start, + ast::FunctionDec* searched) const; + + protected: + /// Print the label of vertex of a graph. + std::ostream& vertex_print(vertex_descriptor v, + std::ostream& ostr) const override; + + using hfundecs_type = std::map<ast::FunctionDec*, vertex_descriptor>; + + hfundecs_type hfundecs; + }; + + using CallGraph = FundecGraph; + using ParentGraph = FundecGraph; + + /*------------. + | Iterators. | + `------------*/ + + /// Iterator on the vertices of a FundecGraph. + using fundecgraph_vertex_iter_type = + boost::graph_traits<FundecGraph>::vertex_iterator; + /// Iterator on the edges of a FundecGraph. + using fundecgraph_edge_iter_type = + boost::graph_traits<FundecGraph>::edge_iterator; + /// Iterator on the neighborhood of a vertex of a FundecGraph. + using fundecgraph_neighb_iter_type = + boost::graph_traits<FundecGraph>::adjacency_iterator; + + /// \name Aliases. + /// \{ + /// Iterator on the vertices of a CallGraph. + using callgraph_vertex_iter_type = fundecgraph_vertex_iter_type; + /// Iterator on the neighborhood of a vertex of a CallGraph. + using callgraph_neighb_iter_type = fundecgraph_neighb_iter_type; + /// Iterator on the neighborhood of a vertex of a ParentGraph. + using parentgraph_neighb_iter_type = fundecgraph_neighb_iter_type; + /// \} + +} // namespace callgraph + +#include <callgraph/fundec-graph.hxx> diff --git a/tiger-compiler/src/callgraph/fundec-graph.hxx b/tiger-compiler/src/callgraph/fundec-graph.hxx new file mode 100644 index 0000000..d5d863e --- /dev/null +++ b/tiger-compiler/src/callgraph/fundec-graph.hxx @@ -0,0 +1,56 @@ +/** + ** \file callgraph/fundec-graph.hxx + ** \brief Inline methods for callgraph/fundec-graph.hh. + */ + +#pragma once + +#include <callgraph/fundec-graph.hh> + +namespace callgraph +{ + inline void FundecGraph::fundec_add(ast::FunctionDec* f) + { + hfundecs[f] = this->vertex_add(f); + } + + inline void FundecGraph::fundec_link(ast::FunctionDec* fu, + ast::FunctionDec* fv) + { + vertex_descriptor u = hfundecs[fu]; + vertex_descriptor v = hfundecs[fv]; + boost::add_edge(u, v, *this); + } + + inline FundecGraph::vertex_descriptor + FundecGraph::hfundec_get(ast::FunctionDec* f) const + { + hfundecs_type::const_iterator i = hfundecs.find(f); + assertion(i != hfundecs.end()); + return i->second; + } + + inline ast::FunctionDec* + FundecGraph::hfundec_deep_get(ast::FunctionDec* start, + ast::FunctionDec* searched) const + { + if (start == searched) + return searched; + + hfundecs_type::const_iterator i = hfundecs.find(start); + parentgraph_neighb_iter_type parent = + boost::adjacent_vertices(i->second, *this).first; + + if ((*this)[*parent] == start) + return nullptr; + + return hfundec_deep_get((*this)[*parent], searched); + } + + inline std::ostream& FundecGraph::vertex_print(vertex_descriptor v, + std::ostream& ostr) const + { + return ostr << (*this)[v]->name_get(); + } + +} // namespace callgraph diff --git a/tiger-compiler/src/callgraph/libcallgraph.cc b/tiger-compiler/src/callgraph/libcallgraph.cc new file mode 100644 index 0000000..be23b16 --- /dev/null +++ b/tiger-compiler/src/callgraph/libcallgraph.cc @@ -0,0 +1,36 @@ +/** + ** \file callgraph/libcallgraph.cc + ** \brief Define exported callgraph functions. + */ + +#include <callgraph/call-graph-visitor.hh> +#include <callgraph/libcallgraph.hh> +#include <callgraph/parent-graph-visitor.hh> + +#include <misc/contract.hh> +#include <misc/set.hh> + +namespace callgraph +{ + + // Build the callgraph. + const CallGraph* callgraph_compute(const ast::Ast& tree) + { + CallGraphVisitor callgraph_visitor; + return callgraph_visitor.create(tree); + } + + CallGraph* callgraph_compute(ast::Ast& tree) + { + CallGraphVisitor callgraph_visitor; + return callgraph_visitor.create(tree); + } + + // Build the parentgraph. + ParentGraph* parentgraph_compute(ast::Ast& tree) + { + ParentGraphVisitor parentgraph_visitor; + return parentgraph_visitor.create(tree); + } + +} // namespace callgraph diff --git a/tiger-compiler/src/callgraph/libcallgraph.hh b/tiger-compiler/src/callgraph/libcallgraph.hh new file mode 100644 index 0000000..b928bac --- /dev/null +++ b/tiger-compiler/src/callgraph/libcallgraph.hh @@ -0,0 +1,28 @@ +/** + ** \file callgraph/libcallgraph.hh + ** \brief Declare functions and variables exported by callgraph module. + */ + +#pragma once + +#include <ast/fwd.hh> +#include <callgraph/fundec-graph.hh> + +/// Computing static link related information. +namespace callgraph +{ + +#ifdef SWIG + %newobject callgraph_compute; +#endif + /// Build the callgraph. + const CallGraph* callgraph_compute(const ast::Ast& tree); + CallGraph* callgraph_compute(ast::Ast& tree); + +#ifdef SWIG + %newobject parentgraph_compute; +#endif + /// Build the parentgraph. + ParentGraph* parentgraph_compute(ast::Ast& tree); + +} // namespace callgraph diff --git a/tiger-compiler/src/callgraph/local.am b/tiger-compiler/src/callgraph/local.am new file mode 100644 index 0000000..695075f --- /dev/null +++ b/tiger-compiler/src/callgraph/local.am @@ -0,0 +1,14 @@ +## module callgraph. + +# Compiling. +# Libcallgraph +src_libtc_la_SOURCES += \ + %D%/libcallgraph.hh %D%/libcallgraph.cc \ + %D%/fundec-graph.hh %D%/fundec-graph.hxx \ + %D%/call-graph-visitor.hh %D%/call-graph-visitor.cc \ + %D%/parent-graph-visitor.hh %D%/parent-graph-visitor.cc + +src_libtc_la_LDFLAGS += $(BOOST_GRAPH_LDFLAGS) +src_libtc_la_LIBADD += $(BOOST_GRAPH_LIBS) + +TASKS += %D%/tasks.hh %D%/tasks.cc diff --git a/tiger-compiler/src/callgraph/parent-graph-visitor.cc b/tiger-compiler/src/callgraph/parent-graph-visitor.cc new file mode 100644 index 0000000..f99121d --- /dev/null +++ b/tiger-compiler/src/callgraph/parent-graph-visitor.cc @@ -0,0 +1,42 @@ +/** + ** \file callgraph/parent-graph-visitor.cc + ** \brief Implementation for callgraph::ParentGraphVisitor. + **/ + +#include <ast/function-dec.hh> +#include <callgraph/parent-graph-visitor.hh> + +namespace callgraph +{ + ParentGraph* ParentGraphVisitor::create(ast::Ast& tree) + { + // Create a new empty parentgraph + parentgraph = new ParentGraph(); + + // Launch visitor. + tree.accept(*this); + + // Return created parentgraph. + return parentgraph; + } + + void ParentGraphVisitor::operator()(ast::FunctionChunk& e) + { + for (ast::FunctionDec* f : e) + { + parentgraph->fundec_add(f); + parentgraph->fundec_link(f, parent); + } + super_type::operator()(e); + } + + void ParentGraphVisitor::operator()(ast::FunctionDec& e) + { + // Current function becomes temporarily the parent function. + ast::FunctionDec* tmp = parent; + parent = &e; + super_type::operator()(e); + parent = tmp; + } + +} // namespace callgraph diff --git a/tiger-compiler/src/callgraph/parent-graph-visitor.hh b/tiger-compiler/src/callgraph/parent-graph-visitor.hh new file mode 100644 index 0000000..be16987 --- /dev/null +++ b/tiger-compiler/src/callgraph/parent-graph-visitor.hh @@ -0,0 +1,36 @@ +/** + ** \file callgraph/parent-graph-visitor.hh + ** \brief Definition of callgraph::ParentGraphVisitor. + **/ +#pragma once + +#include <ast/default-visitor.hh> +#include <ast/non-assert-visitor.hh> +#include <ast/non-object-visitor.hh> +#include <callgraph/fundec-graph.hh> + +namespace callgraph +{ + /// Compute the ParentGraph. + class ParentGraphVisitor + : public ast::DefaultVisitor + , public ast::NonObjectVisitor + , public ast::NonAssertVisitor + { + using super_type = ast::DefaultVisitor; + using super_type::operator(); + + public: + ParentGraph* create(ast::Ast& tree); + + void operator()(ast::FunctionChunk& e) override; + void operator()(ast::FunctionDec& e) override; + + protected: + /// Current function. + ast::FunctionDec* parent = nullptr; + /// Parent graph. + ParentGraph* parentgraph = nullptr; + }; + +} // namespace callgraph diff --git a/tiger-compiler/src/callgraph/tasks.cc b/tiger-compiler/src/callgraph/tasks.cc new file mode 100644 index 0000000..e4d003b --- /dev/null +++ b/tiger-compiler/src/callgraph/tasks.cc @@ -0,0 +1,52 @@ +/** + ** \file callgraph/tasks.cc + ** \brief Callgraph module related tasks' implementation. + */ + +#include <ostream> + +#include <ast/libast.hh> +#include <ast/tasks.hh> +#define DEFINE_TASKS 1 +#include <callgraph/tasks.hh> +#undef DEFINE_TASKS +#include <callgraph/libcallgraph.hh> + +namespace callgraph::tasks +{ + /*------------. + | CallGraph. | + `------------*/ + + static std::unique_ptr<CallGraph> callgraph; + + void callgraph_compute() + { + callgraph.reset(::callgraph::callgraph_compute(*ast::tasks::the_program)); + } + + void callgraph_dump() + { + precondition(callgraph.get()); + callgraph->print("call"); + } + + /*--------------. + | ParentGraph. | + `--------------*/ + + static std::unique_ptr<ParentGraph> parentgraph; + + void parentgraph_compute() + { + parentgraph.reset( + ::callgraph::parentgraph_compute(*ast::tasks::the_program)); + } + + void parentgraph_dump() + { + precondition(parentgraph.get()); + parentgraph->print("parent"); + } + +} // namespace callgraph::tasks diff --git a/tiger-compiler/src/callgraph/tasks.hh b/tiger-compiler/src/callgraph/tasks.hh new file mode 100644 index 0000000..e1fc584 --- /dev/null +++ b/tiger-compiler/src/callgraph/tasks.hh @@ -0,0 +1,46 @@ +/** + ** \file callgraph/tasks.hh + ** \brief Callgraph module related tasks. + */ + +#pragma once + +#include <callgraph/fundec-graph.hh> +#include <task/libtask.hh> + +/// The Tasks of the escapes module. +namespace callgraph::tasks +{ + TASK_GROUP("3. Callgraph"); + + /*-------------. + | Call graph. | + `-------------*/ + + /// Build the call graph. + TASK_DECLARE("callgraph-compute", + "build the call graph", + callgraph_compute, + "bindings-compute"); + /// Dump the callgraph. + TASK_DECLARE("callgraph-dump", + "dump the call graph", + callgraph_dump, + "callgraph-compute"); + + /*---------------. + | Parent graph. | + `---------------*/ + + /// Build the parent graph. + TASK_DECLARE("parentgraph-compute", + "build the parent graph", + parentgraph_compute, + "parse"); + /// Dump the parentgraph. + TASK_DECLARE("parentgraph-dump", + "dump the parent graph", + parentgraph_dump, + "parentgraph-compute"); + +} // namespace callgraph::tasks |
