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
00166 nodesToVertices_.clear();
00167 std::set<CFGNodeType> nodesProcessed;
00168
00169
00170 this->clear();
00171 entry_ = GraphTraits::null_vertex();
00172 exit_ = GraphTraits::null_vertex();
00173
00174 buildCFG(CFGNodeType(funcDef->cfgForBeginning()), nodesToVertices_, nodesProcessed);
00175
00176
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
00199
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
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
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
00267 Edge edge = add_edge(from, to, *this).first;
00268 (*this)[edge] = CFGEdgePtr(new CFGEdgeType(cfgEdge));
00269
00270
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
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
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
00306 boost::transpose_graph(*this, reverseCFG,
00307 boost::vertex_copy(VertexCopier(*this, reverseCFG)).
00308 edge_copy(EdgeCopier(*this, reverseCFG)));
00309
00310
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
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
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;
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