1#ifndef BACKSTROKE_CFG_H
2#define BACKSTROKE_CFG_H
6#include <boost/graph/adjacency_list.hpp>
7#include <boost/bind.hpp>
8#include <boost/foreach.hpp>
9#include <boost/tuple/tuple.hpp>
10#include <boost/graph/graphviz.hpp>
11#include <boost/graph/dominator_tree.hpp>
12#include <boost/graph/reverse_graph.hpp>
13#include <boost/graph/transpose_graph.hpp>
14#include <boost/algorithm/string.hpp>
20#define foreach BOOST_FOREACH
24template <
class CFGNodeType>
25void writeCFGNode(std::ostream& out,
const CFGNodeType& cfgNode)
27 SgNode* node = cfgNode.getNode();
30 std::string nodeColor =
"black";
31 if (isSgStatement(node))
33 else if (isSgExpression(node))
35 else if (isSgInitializedName(node))
42 std::string funcName = funcDef->get_declaration()->get_name().str();
43 if (cfgNode.getIndex() == 0)
44 label =
"Entry\\n" + funcName;
45 else if (cfgNode.getIndex() == 3)
46 label =
"Exit\\n" + funcName;
49 if (!isSgScopeStatement(node) && !isSgCaseOptionStmt(node) && !isSgDefaultOptionStmt(node))
52 boost::replace_all(content,
"\"",
"\\\"");
53 boost::replace_all(content,
"\\n",
"\\\\n");
62 out <<
"[label=\"" << label <<
"\", color=\"" << nodeColor <<
63 "\", style=\"" << (cfgNode.isInteresting()?
"solid" :
"dotted") <<
"\"]";
68template <
class CFGEdgeType>
69void writeCFGEdge(std::ostream& out,
const CFGEdgeType& e)
71 out <<
"[label=\"" << escapeString(e.toString()) <<
72 "\", style=\"" <<
"solid" <<
"\"]";
77template <
class CFGNodeFilter>
class CFG;
114template <
class CFGNodeFilter>
115class CFG :
public boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS,
116 boost::shared_ptr<VirtualCFG::FilteredCFGNode<CFGNodeFilter> >,
117 boost::shared_ptr<VirtualCFG::FilteredCFGEdge<CFGNodeFilter> > >
119 typedef typename boost::graph_traits<CFG<CFGNodeFilter> > GraphTraits;
125 typedef boost::shared_ptr<CFGNodeType> CFGNodePtr;
126 typedef boost::shared_ptr<CFGEdgeType> CFGEdgePtr;
128 typedef typename GraphTraits::vertex_descriptor
Vertex;
129 typedef typename GraphTraits::edge_descriptor
Edge;
131 typedef std::map<Vertex, Vertex> VertexVertexMap;
155 std::map<CFGNodeType, Vertex> getNodeVert() {
162 entry_(GraphTraits::null_vertex()),
163 exit_(GraphTraits::null_vertex())
170 entry_(GraphTraits::null_vertex()),
171 exit_(GraphTraits::null_vertex())
202 void toDot(
const std::string& filename)
const;
227 void buildCFG(
const CFGNodeType& node,
228 std::map<CFGNodeType, Vertex>& nodesAdded,
229 std::set<CFGNodeType>& nodesProcessed);
237 writeCFGNode(out, *(*
this)[node]);
244 writeCFGEdge(out, *(*
this)[edge]);
252 : cfg1(g1), cfg2(g2) {}
255 { cfg2[v2] = cfg1[v1]; }
265 : cfg1(g1), cfg2(g2) {}
267 void operator()(
const Edge& e1,
Edge& e2)
const
268 { cfg2[e2] = cfg1[e1]; }
277template <
class CFGNodeFilter>
280 std::ofstream ofile(filename.c_str(), std::ios::out);
281 boost::write_graphviz(ofile, *
this,
286template <
class CFGNodeFilter>
289 ROSE_ASSERT(funcDef);
293 nodesToVertices_.clear();
294 std::set<CFGNodeType> nodesProcessed;
298 entry_ = GraphTraits::null_vertex();
299 exit_ = GraphTraits::null_vertex();
306 ROSE_ASSERT(isSgFunctionDefinition((*
this)[entry_]->getNode()));
307 ROSE_ASSERT(isSgFunctionDefinition((*
this)[exit_]->getNode()));
310template <
class CFGNodeFilter>
313 foreach (
Vertex v, boost::vertices(*
this))
315 CFGNodePtr node = (*this)[v];
316 if (isSgFunctionDefinition(node->getNode()))
318 if (node->getIndex() == 0)
320 else if (node->getIndex() == 3)
327 if (exit_ == GraphTraits::null_vertex())
329 std::cerr <<
"This function may contain an infinite loop "
330 "inside so that its CFG cannot be built" << std::endl;
331 exit_ = add_vertex(*
this);
332 (*this)[exit_] = CFGNodePtr(
new CFGNodeType(funcDef_->cfgForEnd()));
335 ROSE_ASSERT(entry_ != GraphTraits::null_vertex());
336 ROSE_ASSERT(exit_ != GraphTraits::null_vertex());
339template <
class CFGNodeFilter>
342 std::map<CFGNodeType, Vertex>& nodesAdded,
343 std::set<CFGNodeType>& nodesProcessed)
345 ROSE_ASSERT(node.getNode());
347 if (nodesProcessed.count(node) > 0)
349 nodesProcessed.insert(node);
351 typename std::map<CFGNodeType, Vertex>::iterator iter;
357 ROSE_ASSERT(src.getNode());
359 boost::tie(iter, inserted) = nodesAdded.insert(std::make_pair(src,
Vertex()));
363 from = add_vertex(*
this);
372 std::vector<CFGEdgeType> outEdges = node.outEdges();
378 ROSE_ASSERT(tar.getNode());
380 boost::tie(iter, inserted) = nodesAdded.insert(std::make_pair(tar,
Vertex()));
384 to = add_vertex(*
this);
394 Edge edge = add_edge(from, to, *
this).first;
395 (*this)[edge] = CFGEdgePtr(
new CFGEdgeType(cfgEdge));
398 buildCFG(tar, nodesAdded, nodesProcessed);
402template <
class CFGNodeFilter>
405 if (!dominatorTree_.empty())
406 return dominatorTree_;
408 boost::associative_property_map<VertexVertexMap> domTreePredMap(dominatorTree_);
411 boost::lengauer_tarjan_dominator_tree(*
this, entry_, domTreePredMap);
412 return dominatorTree_;
415template <
class CFGNodeFilter>
418 if (!postdominatorTree_.empty())
419 return postdominatorTree_;
421 boost::associative_property_map<VertexVertexMap> postdomTreePredMap(postdominatorTree_);
424 boost::lengauer_tarjan_dominator_tree(boost::make_reverse_graph(*
this), exit_, postdomTreePredMap);
425 return postdominatorTree_;
428template <
class CFGNodeFilter>
433 boost::transpose_graph(*
this, reverseCFG,
438 reverseCFG.
entry_ = this->exit_;
439 reverseCFG.
exit_ = this->entry_;
444template <
class CFGNodeFilter>
445std::vector<typename CFG<CFGNodeFilter>::CFGNodePtr>
448 std::vector<CFGNodePtr> allNodes;
449 foreach (
Vertex v, boost::vertices(*
this))
450 allNodes.push_back((*
this)[v]);
466template <
class CFGNodeFilter>
467std::vector<typename CFG<CFGNodeFilter>::CFGEdgePtr>
470 std::vector<CFGEdgePtr> allEdges;
471 foreach (
const Edge& e, boost::edges(*
this))
472 allEdges.push_back((*
this)[e]);
476template <
class CFGNodeFilter>
479 typename std::map<CFGNodeType, Vertex>::const_iterator vertexIter = nodesToVertices_.find(node);
480 if (vertexIter == nodesToVertices_.end())
481 return GraphTraits::null_vertex();
484 ROSE_ASSERT(*(*
this)[vertexIter->second] == node);
485 return vertexIter->second;
489template <
class CFGNodeFilter>
492 std::vector<Edge> backEdges;
497 foreach (
const Edge& e, boost::edges(*
this))
499 Vertex src = boost::source(e, *
this);
500 Vertex tar = boost::target(e, *
this);
503 typename VertexVertexMap::const_iterator iter = dominatorTree_.find(src);
504 while (iter != dominatorTree_.end())
506 if (iter->second == tar)
508 backEdges.push_back(e);
511 iter = dominatorTree_.find(iter->second);
518template <
class CFGNodeFilter>
521 std::vector<Edge> backEdges = getAllBackEdges();
522 std::vector<Vertex> headers;
523 foreach (
Edge e, backEdges)
524 headers.push_back(boost::target(e, *
this));
A class holding a Control Flow Graph.
std::map< CFGNodeType, Vertex > nodesToVertices_
A map from a CFG node to the corresponding vertex.
std::vector< Edge > getAllBackEdges()
Get all back edges in the CFG. A back edge is one whose target dominates its source.
const VertexVertexMap & getPostdominatorTree()
Build the postdominator tree of this CFG.
CFG< CFGNodeFilter > makeReverseCopy() const
Build a reverse CFG.
void setEntryAndExit()
Find the entry and exit of this CFG and set the corresponding members.
const VertexVertexMap & getDominatorTree()
Build the dominator tree of this CFG.
void toDot(const std::string &filename) const
Output the graph to a DOT file.
Vertex entry_
The entry node.
void build(SgFunctionDefinition *funcDef)
Build the actual CFG for the given function.
const Vertex & getEntry() const
Get the entry node of the CFG.
void writeGraphNode(std::ostream &out, const Vertex &node) const
This function helps to write the DOT file for vertices.
CFG(SgFunctionDefinition *funcDef)
The constructor building the CFG.
Vertex getVertexForNode(const CFGNodeType &node) const
Given a CFG node, returns the corresponding vertex in the graph.
SgFunctionDefinition * funcDef_
The function definition of this CFG.
Vertex exit_
The exit node.
void writeGraphEdge(std::ostream &out, const Edge &edge) const
This function helps to write the DOT file for edges.
VertexVertexMap postdominatorTree_
The postdominator tree of this CFG.
std::vector< CFGNodePtr > getAllNodes() const
Get all CFG nodes in this graph.
std::vector< Vertex > getAllLoopHeaders()
Get all loop headers in this CFG. A natural loop only has one header.
VertexVertexMap dominatorTree_
The dominator tree of this CFG.
bool isReducible() const
Return if this CFG is reducible (if all loops are natural loops, the CFG is reducible).
CFG()
The default constructor.
SgFunctionDefinition * getFunctionDefinition() const
Get the function definition of this CFG.
std::vector< CFGEdgePtr > getAllEdges() const
Get all CFG edges in this graph.
void buildCFG(const CFGNodeType &node, std::map< CFGNodeType, Vertex > &nodesAdded, std::set< CFGNodeType > &nodesProcessed)
A internal funtion which builds the actual CFG (boost::graph).
const Vertex & getExit() const
Get the exit node of the CFG.
This class represents the concept of a scope in C++ (e.g. global scope, fuction scope,...
This class represents the base class for all IR nodes within Sage III.
VirtualCFG::CFGNode cfgForBeginning()
Returns the CFG node for just before this AST node.
virtual std::string unparseToString(SgUnparse_Info *info) const
This function unparses the AST node (excluding comments and unnecessary white space)
virtual std::string class_name() const
returns a string representing the class name
A node in the control flow graph.
bool isInteresting() const
Test whether this node satisfies a (fairly arbitrary) standard for "interestingness".
This class is used to copy edges when calling copy_graph().
This class is used to copy vertices when calling copy_graph().