ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
boostGraphCFG.h
Go to the documentation of this file.
1 #pragma once
2 
3 
4 #include <rose.h>
5 #include <boost/graph/adjacency_list.hpp>
6 #include <boost/bind.hpp>
7 #include <boost/foreach.hpp>
8 #include <boost/tuple/tuple.hpp>
9 #include <boost/graph/graphviz.hpp>
10 #include <boost/graph/dominator_tree.hpp>
11 #include <boost/graph/reverse_graph.hpp>
12 #include <boost/graph/transpose_graph.hpp>
13 #include <boost/algorithm/string.hpp>
14 
15 namespace ssa_private
16 {
17 
19 template <class CFGNodeT, class CFGEdgeT>
20 class CFG : public boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS,
21  boost::shared_ptr<CFGNodeT>, boost::shared_ptr<CFGEdgeT> >
22 {
23 public:
24  typedef typename boost::graph_traits<CFG<CFGNodeT, CFGEdgeT> > GraphTraits;
25 
26 
27  typedef CFGNodeT CFGNodeType;
28  typedef CFGEdgeT CFGEdgeType;
29 
30  typedef boost::shared_ptr<CFGNodeType> CFGNodePtr;
31  typedef boost::shared_ptr<CFGEdgeType> CFGEdgePtr;
32 
33  typedef typename GraphTraits::vertex_descriptor Vertex;
34  typedef typename GraphTraits::edge_descriptor Edge;
35 
36  typedef std::map<Vertex, Vertex> VertexVertexMap;
37 
38 protected:
39 
42 
45 
48 
50  std::map<CFGNodeType, Vertex> nodesToVertices_;
51 
54 
57 
58 public:
59 
61  CFG()
62  : funcDef_(NULL),
63  entry_(GraphTraits::null_vertex()),
64  exit_(GraphTraits::null_vertex())
65  {
66  }
67 
69  explicit CFG(SgFunctionDefinition* funcDef)
70  : funcDef_(funcDef),
71  entry_(GraphTraits::null_vertex()),
72  exit_(GraphTraits::null_vertex())
73  {
74  build(funcDef);
75  }
76 
78  void build(SgFunctionDefinition* funcDef);
79 
82  { return funcDef_; }
83 
85  const Vertex& getEntry() const
86  { return entry_; }
87 
89  const Vertex& getExit() const
90  { return exit_; }
91 
95 
98 
101 
103  std::vector<CFGNodePtr> getAllNodes() const;
104 
106  std::vector<CFGEdgePtr> getAllEdges() const;
107 
110  Vertex getVertexForNode(const CFGNodeType &node) const;
111 
113  std::vector<Edge> getAllBackEdges();
114 
116  std::vector<Vertex> getAllLoopHeaders();
117 
118 protected:
119 
121  void buildCFG(const CFGNodeType& node,
122  std::map<CFGNodeType, Vertex>& nodesAdded,
123  std::set<CFGNodeType>& nodesProcessed);
124 
126  void setEntryAndExit();
127 
130  {
132  : cfg1(g1), cfg2(g2) {}
133 
134  void operator()(const Vertex& v1, Vertex& v2) const
135  { cfg2[v2] = cfg1[v1]; }
136 
139  };
140 
142  struct EdgeCopier
143  {
145  : cfg1(g1), cfg2(g2) {}
146 
147  void operator()(const Edge& e1, Edge& e2) const
148  { cfg2[e2] = cfg1[e1]; }
149 
152  };
153 };
154 
155 
156 
157 
158 
159 template <class CFGNodeT, class CFGEdgeT>
161 {
162  ROSE_ASSERT(funcDef);
163  funcDef_ = funcDef;
164 
165  // The following two variables are used to record the nodes traversed.
166  nodesToVertices_.clear();
167  std::set<CFGNodeType> nodesProcessed;
168 
169  // Remove all nodes and edges first.
170  this->clear();
171  entry_ = GraphTraits::null_vertex();
172  exit_ = GraphTraits::null_vertex();
173 
174  buildCFG(CFGNodeType(funcDef->cfgForBeginning()), nodesToVertices_, nodesProcessed);
175 
176  // Find the entry and exit of this CFG.
177  setEntryAndExit();
178 
179  ROSE_ASSERT(isSgFunctionDefinition((*this)[entry_]->getNode()));
180  ROSE_ASSERT(isSgFunctionDefinition((*this)[exit_]->getNode()));
181 }
182 
183 template <class CFGNodeT, class CFGEdgeT>
185 {
186  BOOST_FOREACH (Vertex v, boost::vertices(*this))
187  {
188  CFGNodePtr node = (*this)[v];
189  if (isSgFunctionDefinition(node->getNode()))
190  {
191  if (node->getIndex() == 0)
192  entry_ = v;
193  else if (node->getIndex() == 3)
194  exit_ = v;
195  }
196  }
197 
198  //In graphs with an infinite loop, we might never get to the end vertex
199  //In those cases, we need to add it explicitly
200  if (exit_ == GraphTraits::null_vertex())
201  {
202  std::cerr << "This function may contain an infinite loop "
203  "inside so that its CFG cannot be built" << std::endl;
204  exit_ = add_vertex(*this);
205  (*this)[exit_] = CFGNodePtr(new CFGNodeType(funcDef_->cfgForEnd()));
206  }
207 
208  ROSE_ASSERT(entry_ != GraphTraits::null_vertex());
209  ROSE_ASSERT(exit_ != GraphTraits::null_vertex());
210 }
211 
212 template <class CFGNodeT, class CFGEdgeT>
214  const CFGNodeType& node,
215  std::map<CFGNodeType, Vertex>& nodesAdded,
216  std::set<CFGNodeType>& nodesProcessed)
217 {
218  ROSE_ASSERT(node.getNode());
219 
220  if (nodesProcessed.count(node) > 0)
221  return;
222  nodesProcessed.insert(node);
223 
224  typename std::map<CFGNodeType, Vertex>::iterator iter;
225  bool inserted;
226  Vertex from, to;
227 
228  // Add the source node.
229  const CFGNodeType& src = node;
230  ROSE_ASSERT(src.getNode());
231 
232  boost::tie(iter, inserted) = nodesAdded.insert(std::make_pair(src, Vertex()));
233 
234  if (inserted)
235  {
236  from = add_vertex(*this);
237  (*this)[from] = CFGNodePtr(new CFGNodeType(src));
238  iter->second = from;
239  }
240  else
241  {
242  from = iter->second;
243  }
244 
245  std::vector<CFGEdgeType> outEdges = node.outEdges();
246 
247  BOOST_FOREACH(const CFGEdgeType& cfgEdge, outEdges)
248  {
249  // For each out edge, add the target node.
250  CFGNodeType tar = cfgEdge.target();
251  ROSE_ASSERT(tar.getNode());
252 
253  boost::tie(iter, inserted) = nodesAdded.insert(std::make_pair(tar, Vertex()));
254 
255  if (inserted)
256  {
257  to = add_vertex(*this);
258  (*this)[to] = CFGNodePtr(new CFGNodeType(tar));
259  iter->second = to;
260  }
261  else
262  {
263  to = iter->second;
264  }
265 
266  // Add the edge.
267  Edge edge = add_edge(from, to, *this).first;
268  (*this)[edge] = CFGEdgePtr(new CFGEdgeType(cfgEdge));
269 
270  // Build the CFG recursively.
271  buildCFG(tar, nodesAdded, nodesProcessed);
272  }
273 }
274 
275 template <class CFGNodeT, class CFGEdgeT>
277 {
278  if (!dominatorTree_.empty())
279  return dominatorTree_;
280 
281  boost::associative_property_map<VertexVertexMap> domTreePredMap(dominatorTree_);
282 
283  // Here we use the algorithm in boost::graph to build a map from each node to its immediate dominator.
284  boost::lengauer_tarjan_dominator_tree(*this, entry_, domTreePredMap);
285  return dominatorTree_;
286 }
287 
288 template <class CFGNodeT, class CFGEdgeT>
290 {
291  if (!postdominatorTree_.empty())
292  return postdominatorTree_;
293 
294  boost::associative_property_map<VertexVertexMap> postdomTreePredMap(postdominatorTree_);
295 
296  // Here we use the algorithm in boost::graph to build an map from each node to its immediate dominator.
297  boost::lengauer_tarjan_dominator_tree(boost::make_reverse_graph(*this), exit_, postdomTreePredMap);
298  return postdominatorTree_;
299 }
300 
301 template <class CFGNodeT, class CFGEdgeT>
303 {
304  CFG<CFGNodeT, CFGEdgeT> reverseCFG;
305  // The following function makes a reverse CFG copy.
306  boost::transpose_graph(*this, reverseCFG,
307  boost::vertex_copy(VertexCopier(*this, reverseCFG)).
308  edge_copy(EdgeCopier(*this, reverseCFG)));
309 
310  // Swap entry and exit.
311  reverseCFG.entry_ = this->exit_;
312  reverseCFG.exit_ = this->entry_;
313  return reverseCFG;
314 }
315 
316 template <class CFGNodeT, class CFGEdgeT>
319 {
320  std::vector<CFGNodePtr> allNodes;
321  BOOST_FOREACH (Vertex v, boost::vertices(*this))
322  allNodes.push_back((*this)[v]);
323  return allNodes;
324 }
325 
326 template <class CFGNodeT, class CFGEdgeT>
329 {
330  std::vector<CFGEdgePtr> allEdges;
331  BOOST_FOREACH (const Edge& e, boost::edges(*this))
332  allEdges.push_back((*this)[e]);
333  return allEdges;
334 }
335 
336 template <class CFGNodeT, class CFGEdgeT>
338 {
339  typename std::map<CFGNodeType, Vertex>::const_iterator vertexIter = nodesToVertices_.find(node);
340  if (vertexIter == nodesToVertices_.end())
341  return GraphTraits::null_vertex();
342  else
343  {
344  ROSE_ASSERT(*(*this)[vertexIter->second] == node);
345  return vertexIter->second;
346  }
347 }
348 
349 template <class CFGNodeT, class CFGEdgeT>
350 std::vector<typename CFG<CFGNodeT, CFGEdgeT>::Edge> CFG<CFGNodeT, CFGEdgeT>::getAllBackEdges()
351 {
352  std::vector<Edge> backEdges;
353 
354  // If the dominator tree is not built yet, build it now.
355  getDominatorTree();
356 
357  BOOST_FOREACH (const Edge& e, boost::edges(*this))
358  {
359  Vertex src = boost::source(e, *this);
360  Vertex tar = boost::target(e, *this);
361 
362  //Vertex v = *(dominatorTree.find(src));
363  typename VertexVertexMap::const_iterator iter = dominatorTree_.find(src);
364  while (iter != dominatorTree_.end())
365  {
366  if (iter->second == tar)
367  {
368  backEdges.push_back(e);
369  break; // break the while loop
370  }
371  iter = dominatorTree_.find(iter->second);
372  }
373  }
374 
375  return backEdges;
376 }
377 
378 template <class CFGNodeT, class CFGEdgeT>
379 std::vector<typename CFG<CFGNodeT, CFGEdgeT>::Vertex> CFG<CFGNodeT, CFGEdgeT>::getAllLoopHeaders()
380 {
381  std::vector<Edge> backEdges = getAllBackEdges();
382  std::vector<Vertex> headers;
383  BOOST_FOREACH (Edge e, backEdges)
384  headers.push_back(boost::target(e, *this));
385  return headers;
386 }
387 
388 }
389 
390 
391