boostGraphCFG.h

Go to the documentation of this file.
00001 #pragma once
00002 
00003 
00004 #include <rose.h>
00005 #include <boost/graph/adjacency_list.hpp>
00006 #include <boost/bind.hpp>
00007 #include <boost/foreach.hpp>
00008 #include <boost/tuple/tuple.hpp>
00009 #include <boost/graph/graphviz.hpp>
00010 #include <boost/graph/dominator_tree.hpp>
00011 #include <boost/graph/reverse_graph.hpp>
00012 #include <boost/graph/transpose_graph.hpp>
00013 #include <boost/algorithm/string.hpp>
00014 
00015 namespace ssa_private
00016 {
00017 
00019 template <class CFGNodeT, class CFGEdgeT>
00020 class CFG : public boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, 
00021         boost::shared_ptr<CFGNodeT>, boost::shared_ptr<CFGEdgeT> >
00022 {
00023 public:
00024     typedef typename boost::graph_traits<CFG<CFGNodeT, CFGEdgeT> > GraphTraits;
00025 
00026 
00027     typedef CFGNodeT CFGNodeType;
00028     typedef CFGEdgeT CFGEdgeType;
00029 
00030     typedef boost::shared_ptr<CFGNodeType> CFGNodePtr;
00031     typedef boost::shared_ptr<CFGEdgeType> CFGEdgePtr;
00032 
00033     typedef typename GraphTraits::vertex_descriptor Vertex;
00034     typedef typename GraphTraits::edge_descriptor Edge;
00035 
00036     typedef std::map<Vertex, Vertex> VertexVertexMap;
00037 
00038 protected:
00039 
00041     SgFunctionDefinition* funcDef_;
00042 
00044     Vertex entry_;
00045 
00047     Vertex exit_;
00048 
00050     std::map<CFGNodeType, Vertex> nodesToVertices_;
00051 
00053     VertexVertexMap dominatorTree_;
00054 
00056     VertexVertexMap postdominatorTree_;
00057 
00058 public:
00059 
00061     CFG()
00062     :    funcDef_(NULL),
00063         entry_(GraphTraits::null_vertex()),
00064         exit_(GraphTraits::null_vertex())
00065     {
00066     }
00067 
00069     explicit CFG(SgFunctionDefinition* funcDef)
00070     :    funcDef_(funcDef),
00071         entry_(GraphTraits::null_vertex()),
00072         exit_(GraphTraits::null_vertex())
00073     {
00074         build(funcDef);
00075     }
00076 
00078     void build(SgFunctionDefinition* funcDef);
00079 
00081     SgFunctionDefinition* getFunctionDefinition() const
00082     { return funcDef_; }
00083 
00085     const Vertex& getEntry() const
00086     { return entry_; }
00087 
00089     const Vertex& getExit() const
00090     { return exit_; }
00091 
00094     const VertexVertexMap& getDominatorTree();
00095 
00097     const VertexVertexMap& getPostdominatorTree();
00098 
00100     CFG<CFGNodeT, CFGEdgeT> makeReverseCopy() const;
00101 
00103     std::vector<CFGNodePtr> getAllNodes() const;
00104 
00106     std::vector<CFGEdgePtr> getAllEdges() const;
00107 
00110     Vertex getVertexForNode(const CFGNodeType &node) const;
00111 
00113     std::vector<Edge> getAllBackEdges();
00114 
00116     std::vector<Vertex> getAllLoopHeaders();
00117 
00118 protected:
00119 
00121     void buildCFG(const CFGNodeType& node,
00122             std::map<CFGNodeType, Vertex>& nodesAdded,
00123             std::set<CFGNodeType>& nodesProcessed);
00124 
00126     void setEntryAndExit();
00127 
00129     struct VertexCopier
00130     {
00131         VertexCopier(const CFG<CFGNodeT, CFGEdgeT>& g1, CFG<CFGNodeT, CFGEdgeT>& g2)
00132         : cfg1(g1), cfg2(g2) {}
00133 
00134         void operator()(const Vertex& v1, Vertex& v2) const
00135         { cfg2[v2] = cfg1[v1]; }
00136         
00137         const CFG<CFGNodeT, CFGEdgeT>& cfg1;
00138         CFG<CFGNodeT, CFGEdgeT>& cfg2;
00139     };
00140 
00142     struct EdgeCopier
00143     {
00144         EdgeCopier(const CFG<CFGNodeT, CFGEdgeT>& g1, CFG<CFGNodeT, CFGEdgeT>& g2)
00145         : cfg1(g1), cfg2(g2) {}
00146 
00147         void operator()(const Edge& e1, Edge& e2) const
00148         { cfg2[e2] = cfg1[e1]; }
00149 
00150         const CFG<CFGNodeT, CFGEdgeT>& cfg1;
00151         CFG<CFGNodeT, CFGEdgeT>& cfg2;
00152     };
00153 };
00154 
00155 
00156 
00157 
00158 
00159 template <class CFGNodeT, class CFGEdgeT>
00160 void CFG<CFGNodeT, CFGEdgeT>::build(SgFunctionDefinition* funcDef)
00161 {
00162     ROSE_ASSERT(funcDef);
00163     funcDef_ = funcDef;
00164 
00165     // The following two variables are used to record the nodes traversed.
00166     nodesToVertices_.clear();
00167     std::set<CFGNodeType> nodesProcessed;
00168 
00169     // Remove all nodes and edges first.
00170     this->clear();
00171     entry_ = GraphTraits::null_vertex();
00172     exit_ = GraphTraits::null_vertex();
00173 
00174     buildCFG(CFGNodeType(funcDef->cfgForBeginning()), nodesToVertices_, nodesProcessed);
00175 
00176     // Find the entry and exit of this CFG.
00177     setEntryAndExit();
00178 
00179     ROSE_ASSERT(isSgFunctionDefinition((*this)[entry_]->getNode()));
00180     ROSE_ASSERT(isSgFunctionDefinition((*this)[exit_]->getNode()));
00181 }
00182 
00183 template <class CFGNodeT, class CFGEdgeT>
00184 void CFG<CFGNodeT, CFGEdgeT>::setEntryAndExit()
00185 {
00186     BOOST_FOREACH (Vertex v, boost::vertices(*this))
00187     {
00188         CFGNodePtr node = (*this)[v];
00189         if (isSgFunctionDefinition(node->getNode()))
00190         {
00191             if (node->getIndex() == 0)
00192                 entry_ = v;
00193             else if (node->getIndex() == 3)
00194                 exit_ = v;
00195         }
00196     }
00197 
00198     //In graphs with an infinite loop, we might never get to the end vertex
00199     //In those cases, we need to add it explicitly
00200     if (exit_ == GraphTraits::null_vertex())
00201     {
00202         std::cerr << "This function may contain an infinite loop "
00203                 "inside so that its CFG cannot be built" << std::endl;
00204         exit_ = add_vertex(*this);
00205         (*this)[exit_] = CFGNodePtr(new CFGNodeType(funcDef_->cfgForEnd()));
00206     }
00207 
00208     ROSE_ASSERT(entry_ != GraphTraits::null_vertex());
00209     ROSE_ASSERT(exit_ != GraphTraits::null_vertex());
00210 }
00211 
00212 template <class CFGNodeT, class CFGEdgeT>
00213 void CFG<CFGNodeT, CFGEdgeT>::buildCFG(
00214         const CFGNodeType& node,
00215         std::map<CFGNodeType, Vertex>& nodesAdded,
00216         std::set<CFGNodeType>& nodesProcessed)
00217 {
00218     ROSE_ASSERT(node.getNode());
00219 
00220     if (nodesProcessed.count(node) > 0)
00221         return;
00222     nodesProcessed.insert(node);
00223 
00224     typename std::map<CFGNodeType, Vertex>::iterator iter;
00225     bool inserted;
00226     Vertex from, to;
00227 
00228     // Add the source node.
00229     const CFGNodeType& src = node;
00230     ROSE_ASSERT(src.getNode());
00231 
00232     boost::tie(iter, inserted) = nodesAdded.insert(std::make_pair(src, Vertex()));
00233 
00234     if (inserted)
00235     {
00236         from = add_vertex(*this);
00237         (*this)[from] = CFGNodePtr(new CFGNodeType(src));
00238         iter->second = from;
00239     }
00240     else
00241     {
00242         from = iter->second;
00243     }
00244 
00245     std::vector<CFGEdgeType> outEdges = node.outEdges();
00246 
00247     BOOST_FOREACH(const CFGEdgeType& cfgEdge, outEdges)
00248     {
00249         // For each out edge, add the target node.
00250         CFGNodeType tar = cfgEdge.target();
00251         ROSE_ASSERT(tar.getNode());
00252 
00253         boost::tie(iter, inserted) = nodesAdded.insert(std::make_pair(tar, Vertex()));
00254 
00255         if (inserted)
00256         {
00257             to = add_vertex(*this);
00258             (*this)[to] = CFGNodePtr(new CFGNodeType(tar));
00259             iter->second = to;
00260         }
00261         else
00262         {
00263             to = iter->second;
00264         }
00265 
00266         // Add the edge.
00267         Edge edge = add_edge(from, to, *this).first;
00268         (*this)[edge] = CFGEdgePtr(new CFGEdgeType(cfgEdge));
00269 
00270         // Build the CFG recursively.
00271         buildCFG(tar, nodesAdded, nodesProcessed);
00272     }
00273 }
00274 
00275 template <class CFGNodeT, class CFGEdgeT>
00276 const typename CFG<CFGNodeT, CFGEdgeT>::VertexVertexMap& CFG<CFGNodeT, CFGEdgeT>::getDominatorTree()
00277 {
00278     if (!dominatorTree_.empty())
00279         return dominatorTree_;
00280 
00281     boost::associative_property_map<VertexVertexMap> domTreePredMap(dominatorTree_);
00282 
00283     // Here we use the algorithm in boost::graph to build a map from each node to its immediate dominator.
00284     boost::lengauer_tarjan_dominator_tree(*this, entry_, domTreePredMap);
00285     return dominatorTree_;
00286 }
00287 
00288 template <class CFGNodeT, class CFGEdgeT>
00289 const typename CFG<CFGNodeT, CFGEdgeT>::VertexVertexMap& CFG<CFGNodeT, CFGEdgeT>::getPostdominatorTree()
00290 {
00291     if (!postdominatorTree_.empty())
00292         return postdominatorTree_;
00293     
00294     boost::associative_property_map<VertexVertexMap> postdomTreePredMap(postdominatorTree_);
00295 
00296     // Here we use the algorithm in boost::graph to build an map from each node to its immediate dominator.
00297     boost::lengauer_tarjan_dominator_tree(boost::make_reverse_graph(*this), exit_, postdomTreePredMap);
00298     return postdominatorTree_;
00299 }
00300 
00301 template <class CFGNodeT, class CFGEdgeT>
00302 CFG<CFGNodeT, CFGEdgeT> CFG<CFGNodeT, CFGEdgeT>::makeReverseCopy() const
00303 {
00304     CFG<CFGNodeT, CFGEdgeT> reverseCFG;
00305     // The following function makes a reverse CFG copy.
00306     boost::transpose_graph(*this, reverseCFG, 
00307         boost::vertex_copy(VertexCopier(*this, reverseCFG)).
00308         edge_copy(EdgeCopier(*this, reverseCFG)));
00309 
00310     // Swap entry and exit.
00311     reverseCFG.entry_ = this->exit_;
00312     reverseCFG.exit_ = this->entry_;
00313     return reverseCFG;
00314 }
00315 
00316 template <class CFGNodeT, class CFGEdgeT>
00317 std::vector<typename CFG<CFGNodeT, CFGEdgeT>::CFGNodePtr>
00318 CFG<CFGNodeT, CFGEdgeT>::getAllNodes() const
00319 {
00320     std::vector<CFGNodePtr> allNodes;
00321     BOOST_FOREACH (Vertex v, boost::vertices(*this))
00322         allNodes.push_back((*this)[v]);
00323     return allNodes;
00324 }
00325 
00326 template <class CFGNodeT, class CFGEdgeT>
00327 std::vector<typename CFG<CFGNodeT, CFGEdgeT>::CFGEdgePtr>
00328 CFG<CFGNodeT, CFGEdgeT>::getAllEdges() const
00329 {
00330     std::vector<CFGEdgePtr> allEdges;
00331     BOOST_FOREACH (const Edge& e, boost::edges(*this))
00332         allEdges.push_back((*this)[e]);
00333     return allEdges;
00334 }
00335 
00336 template <class CFGNodeT, class CFGEdgeT>
00337 typename CFG<CFGNodeT, CFGEdgeT>::Vertex CFG<CFGNodeT, CFGEdgeT>::getVertexForNode(const CFGNodeType &node) const
00338 {
00339     typename std::map<CFGNodeType, Vertex>::const_iterator vertexIter = nodesToVertices_.find(node);
00340     if (vertexIter == nodesToVertices_.end())
00341         return GraphTraits::null_vertex();
00342     else
00343     {
00344         ROSE_ASSERT(*(*this)[vertexIter->second] == node);
00345         return vertexIter->second;
00346     }
00347 }
00348 
00349 template <class CFGNodeT, class CFGEdgeT>
00350 std::vector<typename CFG<CFGNodeT, CFGEdgeT>::Edge> CFG<CFGNodeT, CFGEdgeT>::getAllBackEdges()
00351 {
00352     std::vector<Edge> backEdges;
00353 
00354     // If the dominator tree is not built yet, build it now.
00355     getDominatorTree();
00356 
00357     BOOST_FOREACH (const Edge& e, boost::edges(*this))
00358     {
00359         Vertex src = boost::source(e, *this);
00360         Vertex tar = boost::target(e, *this);
00361 
00362         //Vertex v = *(dominatorTree.find(src));
00363         typename VertexVertexMap::const_iterator iter = dominatorTree_.find(src);
00364         while (iter != dominatorTree_.end())
00365         {
00366             if (iter->second == tar)
00367             {
00368                 backEdges.push_back(e);
00369                 break; // break the while loop
00370             }
00371             iter = dominatorTree_.find(iter->second);
00372         }
00373     }
00374 
00375     return backEdges;
00376 }
00377 
00378 template <class CFGNodeT, class CFGEdgeT>
00379 std::vector<typename CFG<CFGNodeT, CFGEdgeT>::Vertex> CFG<CFGNodeT, CFGEdgeT>::getAllLoopHeaders()
00380 {
00381     std::vector<Edge> backEdges = getAllBackEdges();
00382     std::vector<Vertex> headers;
00383     BOOST_FOREACH (Edge e, backEdges)
00384         headers.push_back(boost::target(e, *this));
00385     return headers;
00386 }
00387 
00388 }
00389 
00390 
00391 

Generated on Wed May 16 06:17:53 2012 for ROSE by  doxygen 1.4.7