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().