ROSE 0.11.145.147
boostGraphCFG.h
1#pragma once
2
3
4// DQ (10/5/2014): This is more strict now that we include rose_config.h in the sage3basic.h.
5// #include "rose.h"
6// rose.h and sage3basic.h should not be included in librose header files. [Robb P. Matzke 2014-10-15]
7// #include "sage3basic.h"
8
9#include <boost/graph/adjacency_list.hpp>
10#include <boost/bind/bind.hpp>
11#include <boost/tuple/tuple.hpp>
12#include <boost/graph/graphviz.hpp>
13#include <boost/graph/dominator_tree.hpp>
14#include <boost/graph/reverse_graph.hpp>
15#include <boost/graph/transpose_graph.hpp>
16#include <boost/algorithm/string.hpp>
17
18namespace ssa_private
19{
20
22template <class CFGNodeT, class CFGEdgeT>
23class CFG : public boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS,
24 boost::shared_ptr<CFGNodeT>, boost::shared_ptr<CFGEdgeT> >
25{
26public:
27 typedef typename boost::graph_traits<CFG<CFGNodeT, CFGEdgeT> > GraphTraits;
28
29
30 typedef CFGNodeT CFGNodeType;
31 typedef CFGEdgeT CFGEdgeType;
32
33 typedef boost::shared_ptr<CFGNodeType> CFGNodePtr;
34 typedef boost::shared_ptr<CFGEdgeType> CFGEdgePtr;
35
36 typedef typename GraphTraits::vertex_descriptor Vertex;
37 typedef typename GraphTraits::edge_descriptor Edge;
38
39 typedef std::map<Vertex, Vertex> VertexVertexMap;
40
41protected:
42
45
48
51
53 std::map<CFGNodeType, Vertex> nodesToVertices_;
54
56 VertexVertexMap dominatorTree_;
57
59 VertexVertexMap postdominatorTree_;
60
61public:
62
65 : funcDef_(NULL),
66 entry_(GraphTraits::null_vertex()),
67 exit_(GraphTraits::null_vertex())
68 {
69 }
70
72 explicit CFG(SgFunctionDefinition* funcDef)
73 : funcDef_(funcDef),
74 entry_(GraphTraits::null_vertex()),
75 exit_(GraphTraits::null_vertex())
76 {
77 build(funcDef);
78 }
79
81 void build(SgFunctionDefinition* funcDef);
82
86
88 const Vertex& getEntry() const
89 { return entry_; }
90
92 const Vertex& getExit() const
93 { return exit_; }
94
97 const VertexVertexMap& getDominatorTree();
98
100 const VertexVertexMap& getPostdominatorTree();
101
104
106 std::vector<CFGNodePtr> getAllNodes() const;
107
109 std::vector<CFGEdgePtr> getAllEdges() const;
110
113 Vertex getVertexForNode(const CFGNodeType &node) const;
114
116 std::vector<Edge> getAllBackEdges();
117
119 std::vector<Vertex> getAllLoopHeaders();
120
121protected:
122
124 void buildCFG(const CFGNodeType& node,
125 std::map<CFGNodeType, Vertex>& nodesAdded,
126 std::set<CFGNodeType>& nodesProcessed);
127
129 void setEntryAndExit();
130
133 {
135 : cfg1(g1), cfg2(g2) {}
136
137 void operator()(const Vertex& v1, Vertex& v2) const
138 { cfg2[v2] = cfg1[v1]; }
139
140 const CFG<CFGNodeT, CFGEdgeT>& cfg1;
142 };
143
146 {
148 : cfg1(g1), cfg2(g2) {}
149
150 void operator()(const Edge& e1, Edge& e2) const
151 { cfg2[e2] = cfg1[e1]; }
152
153 const CFG<CFGNodeT, CFGEdgeT>& cfg1;
155 };
156};
157
158
159
160
161
162template <class CFGNodeT, class CFGEdgeT>
164{
165 ROSE_ASSERT(funcDef);
166 funcDef_ = funcDef;
167
168 // The following two variables are used to record the nodes traversed.
169 nodesToVertices_.clear();
170 std::set<CFGNodeType> nodesProcessed;
171
172 // Remove all nodes and edges first.
173 this->clear();
174 entry_ = GraphTraits::null_vertex();
175 exit_ = GraphTraits::null_vertex();
176
177 buildCFG(CFGNodeType(funcDef->cfgForBeginning()), nodesToVertices_, nodesProcessed);
178
179 // Find the entry and exit of this CFG.
180 setEntryAndExit();
181
182 ROSE_ASSERT(isSgFunctionDefinition((*this)[entry_]->getNode()));
183 ROSE_ASSERT(isSgFunctionDefinition((*this)[exit_]->getNode()));
184}
185
186template <class CFGNodeT, class CFGEdgeT>
188{
189 BOOST_FOREACH (Vertex v, boost::vertices(*this))
190 {
191 CFGNodePtr node = (*this)[v];
192 if (isSgFunctionDefinition(node->getNode()))
193 {
194 if (node->getIndex() == 0)
195 entry_ = v;
196 else if (node->getIndex() == 3)
197 exit_ = v;
198 }
199 }
200
201 //In graphs with an infinite loop, we might never get to the end vertex
202 //In those cases, we need to add it explicitly
203 if (exit_ == GraphTraits::null_vertex())
204 {
205 std::cerr << "This function may contain an infinite loop "
206 "inside so that its CFG cannot be built" << std::endl;
207 exit_ = add_vertex(*this);
208 (*this)[exit_] = CFGNodePtr(new CFGNodeType(funcDef_->cfgForEnd()));
209 }
210
211 ROSE_ASSERT(entry_ != GraphTraits::null_vertex());
212 ROSE_ASSERT(exit_ != GraphTraits::null_vertex());
213}
214
215template <class CFGNodeT, class CFGEdgeT>
217 const CFGNodeType& node,
218 std::map<CFGNodeType, Vertex>& nodesAdded,
219 std::set<CFGNodeType>& nodesProcessed)
220{
221 ROSE_ASSERT(node.getNode());
222
223 if (nodesProcessed.count(node) > 0)
224 return;
225 nodesProcessed.insert(node);
226
227 typename std::map<CFGNodeType, Vertex>::iterator iter;
228 bool inserted;
229 Vertex from, to;
230
231 // Add the source node.
232 const CFGNodeType& src = node;
233 ROSE_ASSERT(src.getNode());
234
235 boost::tie(iter, inserted) = nodesAdded.insert(std::make_pair(src, Vertex()));
236
237 if (inserted)
238 {
239 from = add_vertex(*this);
240 (*this)[from] = CFGNodePtr(new CFGNodeType(src));
241 iter->second = from;
242 }
243 else
244 {
245 from = iter->second;
246 }
247
248 std::vector<CFGEdgeType> outEdges = node.outEdges();
249
250 BOOST_FOREACH(const CFGEdgeType& cfgEdge, outEdges)
251 {
252 // For each out edge, add the target node.
253 CFGNodeType tar = cfgEdge.target();
254 ROSE_ASSERT(tar.getNode());
255
256 boost::tie(iter, inserted) = nodesAdded.insert(std::make_pair(tar, Vertex()));
257
258 if (inserted)
259 {
260 to = add_vertex(*this);
261 (*this)[to] = CFGNodePtr(new CFGNodeType(tar));
262 iter->second = to;
263 }
264 else
265 {
266 to = iter->second;
267 }
268
269 // Add the edge.
270 Edge edge = add_edge(from, to, *this).first;
271 (*this)[edge] = CFGEdgePtr(new CFGEdgeType(cfgEdge));
272
273 // Build the CFG recursively.
274 buildCFG(tar, nodesAdded, nodesProcessed);
275 }
276}
277
278template <class CFGNodeT, class CFGEdgeT>
279const typename CFG<CFGNodeT, CFGEdgeT>::VertexVertexMap& CFG<CFGNodeT, CFGEdgeT>::getDominatorTree()
280{
281 if (!dominatorTree_.empty())
282 return dominatorTree_;
283
284 boost::associative_property_map<VertexVertexMap> domTreePredMap(dominatorTree_);
285
286 // Here we use the algorithm in boost::graph to build a map from each node to its immediate dominator.
287 boost::lengauer_tarjan_dominator_tree(*this, entry_, domTreePredMap);
288 return dominatorTree_;
289}
290
291template <class CFGNodeT, class CFGEdgeT>
292const typename CFG<CFGNodeT, CFGEdgeT>::VertexVertexMap& CFG<CFGNodeT, CFGEdgeT>::getPostdominatorTree()
293{
294 if (!postdominatorTree_.empty())
295 return postdominatorTree_;
296
297 boost::associative_property_map<VertexVertexMap> postdomTreePredMap(postdominatorTree_);
298
299 // Here we use the algorithm in boost::graph to build an map from each node to its immediate dominator.
300 boost::lengauer_tarjan_dominator_tree(boost::make_reverse_graph(*this), exit_, postdomTreePredMap);
301 return postdominatorTree_;
302}
303
304template <class CFGNodeT, class CFGEdgeT>
306{
307 CFG<CFGNodeT, CFGEdgeT> reverseCFG;
308 // The following function makes a reverse CFG copy.
309 boost::transpose_graph(*this, reverseCFG,
310 boost::vertex_copy(VertexCopier(*this, reverseCFG)).
311 edge_copy(EdgeCopier(*this, reverseCFG)));
312
313 // Swap entry and exit.
314 reverseCFG.entry_ = this->exit_;
315 reverseCFG.exit_ = this->entry_;
316 return reverseCFG;
317}
318
319template <class CFGNodeT, class CFGEdgeT>
320std::vector<typename CFG<CFGNodeT, CFGEdgeT>::CFGNodePtr>
322{
323 std::vector<CFGNodePtr> allNodes;
324 BOOST_FOREACH (Vertex v, boost::vertices(*this))
325 allNodes.push_back((*this)[v]);
326 return allNodes;
327}
328
329template <class CFGNodeT, class CFGEdgeT>
330std::vector<typename CFG<CFGNodeT, CFGEdgeT>::CFGEdgePtr>
332{
333 std::vector<CFGEdgePtr> allEdges;
334 BOOST_FOREACH (const Edge& e, boost::edges(*this))
335 allEdges.push_back((*this)[e]);
336 return allEdges;
337}
338
339template <class CFGNodeT, class CFGEdgeT>
340typename CFG<CFGNodeT, CFGEdgeT>::Vertex CFG<CFGNodeT, CFGEdgeT>::getVertexForNode(const CFGNodeType &node) const
341{
342 typename std::map<CFGNodeType, Vertex>::const_iterator vertexIter = nodesToVertices_.find(node);
343 if (vertexIter == nodesToVertices_.end())
344 return GraphTraits::null_vertex();
345 else
346 {
347 ROSE_ASSERT(*(*this)[vertexIter->second] == node);
348 return vertexIter->second;
349 }
350}
351
352template <class CFGNodeT, class CFGEdgeT>
353std::vector<typename CFG<CFGNodeT, CFGEdgeT>::Edge> CFG<CFGNodeT, CFGEdgeT>::getAllBackEdges()
354{
355 std::vector<Edge> backEdges;
356
357 // If the dominator tree is not built yet, build it now.
358 getDominatorTree();
359
360 BOOST_FOREACH (const Edge& e, boost::edges(*this))
361 {
362 Vertex src = boost::source(e, *this);
363 Vertex tar = boost::target(e, *this);
364
365 //Vertex v = *(dominatorTree.find(src));
366 typename VertexVertexMap::const_iterator iter = dominatorTree_.find(src);
367 while (iter != dominatorTree_.end())
368 {
369 if (iter->second == tar)
370 {
371 backEdges.push_back(e);
372 break; // break the while loop
373 }
374 iter = dominatorTree_.find(iter->second);
375 }
376 }
377
378 return backEdges;
379}
380
381template <class CFGNodeT, class CFGEdgeT>
382std::vector<typename CFG<CFGNodeT, CFGEdgeT>::Vertex> CFG<CFGNodeT, CFGEdgeT>::getAllLoopHeaders()
383{
384 std::vector<Edge> backEdges = getAllBackEdges();
385 std::vector<Vertex> headers;
386 BOOST_FOREACH (Edge e, backEdges)
387 headers.push_back(boost::target(e, *this));
388 return headers;
389}
390
391}
392
393
394
This class represents the concept of a scope in C++ (e.g. global scope, fuction scope,...
VirtualCFG::CFGNode cfgForBeginning()
Returns the CFG node for just before this AST node.
A class holding a Control Flow 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).
SgFunctionDefinition * getFunctionDefinition() const
Get the function definition of this CFG.
VertexVertexMap postdominatorTree_
The postdominator tree of this CFG.
std::vector< CFGEdgePtr > getAllEdges() const
Get all CFG edges in this graph.
VertexVertexMap dominatorTree_
The dominator tree of this CFG.
void setEntryAndExit()
Find the entry and exit of this CFG and set the corresponding members.
std::vector< Vertex > getAllLoopHeaders()
Get all loop headers in this CFG. A natural loop only has one header.
std::map< CFGNodeType, Vertex > nodesToVertices_
A map from a CFG node to the corresponding vertex.
void build(SgFunctionDefinition *funcDef)
Build the actual CFG for the given function.
Vertex exit_
The exit node.
std::vector< CFGNodePtr > getAllNodes() const
Get all CFG nodes in this graph.
Vertex getVertexForNode(const CFGNodeType &node) const
Given a CFG node, returns the corresponding vertex in the graph.
std::vector< Edge > getAllBackEdges()
Get all back edges in the CFG. A back edge is one whose target dominates its source.
const Vertex & getExit() const
Get the exit node of the CFG.
const Vertex & getEntry() const
Get the entry node of the CFG.
CFG()
The default constructor.
const VertexVertexMap & getDominatorTree()
Build the dominator tree of this CFG.
Vertex entry_
The entry node.
CFG(SgFunctionDefinition *funcDef)
The constructor building the CFG.
CFG< CFGNodeT, CFGEdgeT > makeReverseCopy() const
Build a reverse CFG.
SgFunctionDefinition * funcDef_
The function definition of this CFG.
const VertexVertexMap & getPostdominatorTree()
Build the postdominator tree of this CFG.
This class is used to copy edges when calling copy_graph().
This class is used to copy vertices when calling copy_graph().