00001 #ifndef BACKSTROKE_CFG_H
00002 #define BACKSTROKE_CFG_H
00003
00004
00005 #include <rose.h>
00006 #include <boost/graph/adjacency_list.hpp>
00007 #include <boost/bind.hpp>
00008 #include <boost/foreach.hpp>
00009 #include <boost/tuple/tuple.hpp>
00010 #include <boost/graph/graphviz.hpp>
00011 #include <boost/graph/dominator_tree.hpp>
00012 #include <boost/graph/reverse_graph.hpp>
00013 #include <boost/graph/transpose_graph.hpp>
00014 #include <boost/algorithm/string.hpp>
00015
00016
00017 namespace Backstroke
00018 {
00019
00020 #define foreach BOOST_FOREACH
00021
00022
00024 template <class CFGNodeType>
00025 void writeCFGNode(std::ostream& out, const CFGNodeType& cfgNode)
00026 {
00027 SgNode* node = cfgNode.getNode();
00028 ROSE_ASSERT(node);
00029
00030 std::string nodeColor = "black";
00031 if (isSgStatement(node))
00032 nodeColor = "blue";
00033 else if (isSgExpression(node))
00034 nodeColor = "green";
00035 else if (isSgInitializedName(node))
00036 nodeColor = "red";
00037
00038 std::string label;
00039
00040 if (SgFunctionDefinition* funcDef = isSgFunctionDefinition(node))
00041 {
00042 std::string funcName = funcDef->get_declaration()->get_name().str();
00043 if (cfgNode.getIndex() == 0)
00044 label = "Entry\\n" + funcName;
00045 else if (cfgNode.getIndex() == 3)
00046 label = "Exit\\n" + funcName;
00047 }
00048
00049 if (!isSgScopeStatement(node) && !isSgCaseOptionStmt(node) && !isSgDefaultOptionStmt(node))
00050 {
00051 std::string content = node->unparseToString();
00052 boost::replace_all(content, "\"", "\\\"");
00053 boost::replace_all(content, "\\n", "\\\\n");
00054 label += content;
00055 }
00056 else
00057 label += "<" + node->class_name() + ">";
00058
00059 if (label == "")
00060 label += "<" + node->class_name() + ">";
00061
00062 out << "[label=\"" << label << "\", color=\"" << nodeColor <<
00063 "\", style=\"" << (cfgNode.isInteresting()? "solid" : "dotted") << "\"]";
00064 }
00065
00066
00068 template <class CFGEdgeType>
00069 void writeCFGEdge(std::ostream& out, const CFGEdgeType& e)
00070 {
00071 out << "[label=\"" << escapeString(e.toString()) <<
00072 "\", style=\"" << "solid" << "\"]";
00073 }
00074
00075
00076
00077 template <class CFGNodeFilter> class CFG;
00078
00079 struct FullCFGNodeFilter
00080 {
00081 bool operator()(const VirtualCFG::CFGNode& cfgNode) const
00082 { return true; }
00083 };
00084
00085 struct InterestingCFGNodeFilter
00086 {
00087 bool operator()(const VirtualCFG::CFGNode& cfgNode) const
00088 { return cfgNode.isInteresting(); }
00089 };
00090
00092 typedef CFG<FullCFGNodeFilter> FullCFG;
00093
00094
00096 typedef CFG<InterestingCFGNodeFilter> FilteredCFG;
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00113
00114 template <class CFGNodeFilter>
00115 class CFG : public boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS,
00116 boost::shared_ptr<VirtualCFG::FilteredCFGNode<CFGNodeFilter> >,
00117 boost::shared_ptr<VirtualCFG::FilteredCFGEdge<CFGNodeFilter> > >
00118 {
00119 typedef typename boost::graph_traits<CFG<CFGNodeFilter> > GraphTraits;
00120
00121 public:
00122 typedef VirtualCFG::FilteredCFGNode<CFGNodeFilter> CFGNodeType;
00123 typedef VirtualCFG::FilteredCFGEdge<CFGNodeFilter> CFGEdgeType;
00124
00125 typedef boost::shared_ptr<CFGNodeType> CFGNodePtr;
00126 typedef boost::shared_ptr<CFGEdgeType> CFGEdgePtr;
00127
00128 typedef typename GraphTraits::vertex_descriptor Vertex;
00129 typedef typename GraphTraits::edge_descriptor Edge;
00130
00131 typedef std::map<Vertex, Vertex> VertexVertexMap;
00133 Vertex entry_;
00134
00136 Vertex exit_;
00137
00138
00139 protected:
00140
00142 SgFunctionDefinition* funcDef_;
00143
00144
00146 std::map<CFGNodeType, Vertex> nodesToVertices_;
00147
00149 VertexVertexMap dominatorTree_;
00150
00152 VertexVertexMap postdominatorTree_;
00153
00154 public:
00155 std::map<CFGNodeType, Vertex> getNodeVert() {
00156 return nodesToVertices_;
00157 }
00158
00160 CFG()
00161 : funcDef_(NULL),
00162 entry_(GraphTraits::null_vertex()),
00163 exit_(GraphTraits::null_vertex())
00164 {
00165 }
00166
00168 explicit CFG(SgFunctionDefinition* funcDef)
00169 : funcDef_(funcDef),
00170 entry_(GraphTraits::null_vertex()),
00171 exit_(GraphTraits::null_vertex())
00172 {
00173 build(funcDef);
00174 }
00175
00177 void build(SgFunctionDefinition* funcDef);
00178
00180 SgFunctionDefinition* getFunctionDefinition() const
00181 { return funcDef_; }
00182
00184 const Vertex& getEntry() const
00185 { return entry_; }
00186
00188 const Vertex& getExit() const
00189 { return exit_; }
00190
00193 const VertexVertexMap& getDominatorTree();
00194
00196 const VertexVertexMap& getPostdominatorTree();
00197
00199 CFG<CFGNodeFilter> makeReverseCopy() const;
00200
00202 void toDot(const std::string& filename) const;
00203
00205 std::vector<CFGNodePtr> getAllNodes() const;
00206
00208 std::vector<CFGEdgePtr> getAllEdges() const;
00209
00212 Vertex getVertexForNode(const CFGNodeType &node) const;
00213
00216 bool isReducible() const { return true; }
00217
00219 std::vector<Edge> getAllBackEdges();
00220
00222 std::vector<Vertex> getAllLoopHeaders();
00223
00224 protected:
00225
00227 void buildCFG(const CFGNodeType& node,
00228 std::map<CFGNodeType, Vertex>& nodesAdded,
00229 std::set<CFGNodeType>& nodesProcessed);
00230
00232 void setEntryAndExit();
00233
00235 void writeGraphNode(std::ostream& out, const Vertex& node) const
00236 {
00237 writeCFGNode(out, *(*this)[node]);
00238
00239 }
00240
00242 void writeGraphEdge(std::ostream& out, const Edge& edge) const
00243 {
00244 writeCFGEdge(out, *(*this)[edge]);
00245
00246 }
00247
00249 struct VertexCopier
00250 {
00251 VertexCopier(const CFG<CFGNodeFilter>& g1, CFG<CFGNodeFilter>& g2)
00252 : cfg1(g1), cfg2(g2) {}
00253
00254 void operator()(const Vertex& v1, Vertex& v2) const
00255 { cfg2[v2] = cfg1[v1]; }
00256
00257 const CFG<CFGNodeFilter>& cfg1;
00258 CFG<CFGNodeFilter>& cfg2;
00259 };
00260
00262 struct EdgeCopier
00263 {
00264 EdgeCopier(const CFG<CFGNodeFilter>& g1, CFG<CFGNodeFilter>& g2)
00265 : cfg1(g1), cfg2(g2) {}
00266
00267 void operator()(const Edge& e1, Edge& e2) const
00268 { cfg2[e2] = cfg1[e1]; }
00269
00270 const CFG<CFGNodeFilter>& cfg1;
00271 CFG<CFGNodeFilter>& cfg2;
00272 };
00273 };
00274
00275
00276
00277 template <class CFGNodeFilter>
00278 void CFG<CFGNodeFilter>::toDot(const std::string& filename) const
00279 {
00280 std::ofstream ofile(filename.c_str(), std::ios::out);
00281 boost::write_graphviz(ofile, *this,
00282 boost::bind(&CFG<CFGNodeFilter>::writeGraphNode, this, ::_1, ::_2),
00283 boost::bind(&CFG<CFGNodeFilter>::writeGraphEdge, this, ::_1, ::_2));
00284 }
00285
00286 template <class CFGNodeFilter>
00287 void CFG<CFGNodeFilter>::build(SgFunctionDefinition* funcDef)
00288 {
00289 ROSE_ASSERT(funcDef);
00290 funcDef_ = funcDef;
00291
00292
00293 nodesToVertices_.clear();
00294 std::set<CFGNodeType> nodesProcessed;
00295
00296
00297 this->clear();
00298 entry_ = GraphTraits::null_vertex();
00299 exit_ = GraphTraits::null_vertex();
00300
00301 buildCFG(CFGNodeType(funcDef->cfgForBeginning()), nodesToVertices_, nodesProcessed);
00302
00303
00304 setEntryAndExit();
00305
00306 ROSE_ASSERT(isSgFunctionDefinition((*this)[entry_]->getNode()));
00307 ROSE_ASSERT(isSgFunctionDefinition((*this)[exit_]->getNode()));
00308 }
00309
00310 template <class CFGNodeFilter>
00311 void CFG<CFGNodeFilter>::setEntryAndExit()
00312 {
00313 foreach (Vertex v, boost::vertices(*this))
00314 {
00315 CFGNodePtr node = (*this)[v];
00316 if (isSgFunctionDefinition(node->getNode()))
00317 {
00318 if (node->getIndex() == 0)
00319 entry_ = v;
00320 else if (node->getIndex() == 3)
00321 exit_ = v;
00322 }
00323 }
00324
00325
00326
00327 if (exit_ == GraphTraits::null_vertex())
00328 {
00329 std::cerr << "This function may contain an infinite loop "
00330 "inside so that its CFG cannot be built" << std::endl;
00331 exit_ = add_vertex(*this);
00332 (*this)[exit_] = CFGNodePtr(new CFGNodeType(funcDef_->cfgForEnd()));
00333 }
00334
00335 ROSE_ASSERT(entry_ != GraphTraits::null_vertex());
00336 ROSE_ASSERT(exit_ != GraphTraits::null_vertex());
00337 }
00338
00339 template <class CFGNodeFilter>
00340 void CFG<CFGNodeFilter>::buildCFG(
00341 const CFGNodeType& node,
00342 std::map<CFGNodeType, Vertex>& nodesAdded,
00343 std::set<CFGNodeType>& nodesProcessed)
00344 {
00345 ROSE_ASSERT(node.getNode());
00346
00347 if (nodesProcessed.count(node) > 0)
00348 return;
00349 nodesProcessed.insert(node);
00350
00351 typename std::map<CFGNodeType, Vertex>::iterator iter;
00352 bool inserted;
00353 Vertex from, to;
00354
00355
00356 const CFGNodeType& src = node;
00357 ROSE_ASSERT(src.getNode());
00358
00359 boost::tie(iter, inserted) = nodesAdded.insert(std::make_pair(src, Vertex()));
00360
00361 if (inserted)
00362 {
00363 from = add_vertex(*this);
00364 (*this)[from] = CFGNodePtr(new CFGNodeType(src));
00365 iter->second = from;
00366 }
00367 else
00368 {
00369 from = iter->second;
00370 }
00371
00372 std::vector<CFGEdgeType> outEdges = node.outEdges();
00373
00374 foreach(const CFGEdgeType& cfgEdge, outEdges)
00375 {
00376
00377 CFGNodeType tar = cfgEdge.target();
00378 ROSE_ASSERT(tar.getNode());
00379
00380 boost::tie(iter, inserted) = nodesAdded.insert(std::make_pair(tar, Vertex()));
00381
00382 if (inserted)
00383 {
00384 to = add_vertex(*this);
00385 (*this)[to] = CFGNodePtr(new CFGNodeType(tar));
00386 iter->second = to;
00387 }
00388 else
00389 {
00390 to = iter->second;
00391 }
00392
00393
00394 Edge edge = add_edge(from, to, *this).first;
00395 (*this)[edge] = CFGEdgePtr(new CFGEdgeType(cfgEdge));
00396
00397
00398 buildCFG(tar, nodesAdded, nodesProcessed);
00399 }
00400 }
00401
00402 template <class CFGNodeFilter>
00403 const typename CFG<CFGNodeFilter>::VertexVertexMap& CFG<CFGNodeFilter>::getDominatorTree()
00404 {
00405 if (!dominatorTree_.empty())
00406 return dominatorTree_;
00407
00408 boost::associative_property_map<VertexVertexMap> domTreePredMap(dominatorTree_);
00409
00410
00411 boost::lengauer_tarjan_dominator_tree(*this, entry_, domTreePredMap);
00412 return dominatorTree_;
00413 }
00414
00415 template <class CFGNodeFilter>
00416 const typename CFG<CFGNodeFilter>::VertexVertexMap& CFG<CFGNodeFilter>::getPostdominatorTree()
00417 {
00418 if (!postdominatorTree_.empty())
00419 return postdominatorTree_;
00420
00421 boost::associative_property_map<VertexVertexMap> postdomTreePredMap(postdominatorTree_);
00422
00423
00424 boost::lengauer_tarjan_dominator_tree(boost::make_reverse_graph(*this), exit_, postdomTreePredMap);
00425 return postdominatorTree_;
00426 }
00427
00428 template <class CFGNodeFilter>
00429 CFG<CFGNodeFilter> CFG<CFGNodeFilter>::makeReverseCopy() const
00430 {
00431 CFG<CFGNodeFilter> reverseCFG;
00432
00433 boost::transpose_graph(*this, reverseCFG,
00434 boost::vertex_copy(VertexCopier(*this, reverseCFG)).
00435 edge_copy(EdgeCopier(*this, reverseCFG)));
00436
00437
00438 reverseCFG.entry_ = this->exit_;
00439 reverseCFG.exit_ = this->entry_;
00440 return reverseCFG;
00441 }
00442
00443
00444 template <class CFGNodeFilter>
00445 std::vector<typename CFG<CFGNodeFilter>::CFGNodePtr>
00446 CFG<CFGNodeFilter>::getAllNodes() const
00447 {
00448 std::vector<CFGNodePtr> allNodes;
00449 foreach (Vertex v, boost::vertices(*this))
00450 allNodes.push_back((*this)[v]);
00451 return allNodes;
00452 }
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 template <class CFGNodeFilter>
00467 std::vector<typename CFG<CFGNodeFilter>::CFGEdgePtr>
00468 CFG<CFGNodeFilter>::getAllEdges() const
00469 {
00470 std::vector<CFGEdgePtr> allEdges;
00471 foreach (const Edge& e, boost::edges(*this))
00472 allEdges.push_back((*this)[e]);
00473 return allEdges;
00474 }
00475
00476 template <class CFGNodeFilter>
00477 typename CFG<CFGNodeFilter>::Vertex CFG<CFGNodeFilter>::getVertexForNode(const CFGNodeType &node) const
00478 {
00479 typename std::map<CFGNodeType, Vertex>::const_iterator vertexIter = nodesToVertices_.find(node);
00480 if (vertexIter == nodesToVertices_.end())
00481 return GraphTraits::null_vertex();
00482 else
00483 {
00484 ROSE_ASSERT(*(*this)[vertexIter->second] == node);
00485 return vertexIter->second;
00486 }
00487 }
00488
00489 template <class CFGNodeFilter>
00490 std::vector<typename CFG<CFGNodeFilter>::Edge> CFG<CFGNodeFilter>::getAllBackEdges()
00491 {
00492 std::vector<Edge> backEdges;
00493
00494
00495 getDominatorTree();
00496
00497 foreach (const Edge& e, boost::edges(*this))
00498 {
00499 Vertex src = boost::source(e, *this);
00500 Vertex tar = boost::target(e, *this);
00501
00502
00503 typename VertexVertexMap::const_iterator iter = dominatorTree_.find(src);
00504 while (iter != dominatorTree_.end())
00505 {
00506 if (iter->second == tar)
00507 {
00508 backEdges.push_back(e);
00509 break;
00510 }
00511 iter = dominatorTree_.find(iter->second);
00512 }
00513 }
00514
00515 return backEdges;
00516 }
00517
00518 template <class CFGNodeFilter>
00519 std::vector<typename CFG<CFGNodeFilter>::Vertex> CFG<CFGNodeFilter>::getAllLoopHeaders()
00520 {
00521 std::vector<Edge> backEdges = getAllBackEdges();
00522 std::vector<Vertex> headers;
00523 foreach (Edge e, backEdges)
00524 headers.push_back(boost::target(e, *this));
00525 return headers;
00526 }
00527
00528 #undef foreach
00529
00530 }
00531
00532
00533 #endif