ROSE 0.11.145.147
CallGraphTraverse.h
1#include <featureTests.h>
2#ifdef ROSE_ENABLE_SOURCE_ANALYSIS
3
4#ifndef CALL_GRAPH_TRAVERSE_H
5#define CALL_GRAPH_TRAVERSE_H
6
7#include <sage3.h>
8#include "CallGraph.h"
9#include <map>
10#include <set>
11#include <list>
12#include <string>
13#include <utility>
14
15/* !!! NOTE: TraverseCallGraphDataflow LIMITED TO NON-RECURSIVE PROGRAMS (I.E. CONTROL FLOW GRAPHS WITH NO CYCLES) !!! */
16
18{
19 protected:
21
22 public:
23 Function() = delete;
24
25 Function(std::string name);
26
28
30
31 Function(SgFunctionCallExp* funcCall);
32
33 void init(SgFunctionDeclaration* sample);
34
35 public:
36 Function& operator=(const Function &) = default; // removes warning regarding copy constructor
37 Function(const Function &);
38 Function(const Function *);
39
40 // returns a unique SgFunctionDeclaration* that is the canonical AST node that represents the given function
41 // A canonial declaration means a defining function declaration if available, or the first non-defining declaration
42 static SgFunctionDeclaration* getCanonicalDecl(SgFunctionDeclaration* decl);
43
44 bool eq(const Function &that) const;
45
46 bool operator == (const Function &that) const;
47 bool operator != (const Function &that) const;
48
49 protected:
50 bool lessThan(const Function &that) const;
51 public:
52 bool operator < (const Function &that) const;
53 bool operator > (const Function &that) const;
54 bool operator <= (const Function &that) const;
55 bool operator >= (const Function &that) const;
56
57 SgName get_name() const;
58
59 // returns this function's definition or NULL of it does not have one
60 SgFunctionDefinition* get_definition() const;
61
62 // returns one of this function's declarations. it is guaranteed to be the same each time get_declaration is called
63 SgFunctionDeclaration* get_declaration() const;
64
65 // returns the file_info of the definition or one of the declarations if there is no definition
66 Sg_File_Info* get_file_info() const;
67
68 // returns the parameters of this function
69 SgInitializedNamePtrList get_params() const;
70
71 std::string str(std::string indent="") const;
72};
73
74// extension of the generic function class that also contains all the SgGraphNodes that refer to the function
75class CGFunction : public Function
76{
77 std::set<SgGraphNode*> cgNodes;
79
80 public:
81 CGFunction(std::string name, SgIncidenceDirectedGraph* graph);
82
84
86
87 CGFunction(const CGFunction &that);
88
89 CGFunction(const CGFunction *that);
90
91 protected:
92 // initializes the cgNodes set
93 void initCGNodes();
94
95 public:
96 bool operator == (const CGFunction &that) const;
97 bool operator != (const CGFunction &that) const;
98
99 bool operator < (const CGFunction &that) const;
100 bool operator > (const CGFunction &that) const;
101 bool operator <= (const CGFunction &that) const;
102 bool operator >= (const CGFunction &that) const;
103
104 // Traverses the callers or callees of this function
105 // A call graph may have multiple nodes for a same function, each node may have multiple in or out edges.
106 // So the iterator actually works on two levels:
107 // level 1: iterate through all nodes for a given function
108 // level 2: iterate through all in or out edges for each node, return the source or destination node
110 {
111 // direction in which the iterator is going
112 //SgIncidenceDirectedGraph::EdgeDirection iterDir;
113 // side of an edge that we're going to be following
114 //SgIncidenceDirectedGraph::EdgeDirection edgeDir;
115
116 // Direction in which the iterator is going (fw: from callers to callees, bw: from callees to callers)
117 public:
118 //typedef enum direction {fw=0, bw=1};
119 enum direction {fw=0, bw=1};
120 protected:
121 direction dir;
122
123 std::set<SgGraphNode*>::iterator itn;
124 std::set<SgDirectedGraphEdge*> edges; // The current SgGraphNode's (*itn) incoming or outgoing edges
125 std::set<SgDirectedGraphEdge*>::iterator ite; // The current edge in edges
126
127 // The set the SgGraphNodes that have already been visited by this iterator
128 // used to eliminate duplicates
129 std::set<SgGraphNode*> visitedCGNodes;
130
131 const CGFunction* func;
132
133 // =true if this iterator has reached the end of all the edges and =false if not
134 bool finished;
135
136 public:
137 iterator()
138 {
139 finished = true;
140 }
141
142 iterator(const CGFunction* const func, direction dir)
143 {
144 this->func = func;
145 this->dir = dir;
146
147 finished=false;
148
149 itn = func->cgNodes.begin();
150 if(dir == fw) edges = func->graph->computeEdgeSetOut(*itn);
151 else edges = func->graph->computeEdgeSetIn(*itn);
152 ite = edges.begin();
153
154 advanceToNextValidPoint();
155 }
156
157 // Returns a reference to CGFunction that matches the current SgGraphNode that this iterator refers to,
158 // pulling the reference from the given set of CGFunctions
159 const CGFunction* getTarget(std::set<CGFunction> &functions)
160 {
161 //printf("getTarget finished=%d\n", finished);
162 SgGraphNode* target = (dir == fw ? (*ite)->get_to() : (*ite)->get_from());
163 ROSE_ASSERT(isSgFunctionDeclaration(target->get_SgNode()));
164 assert(!isSgTemplateFunctionDeclaration(target->get_SgNode()));
165
166 // Compiler-generated functions do not appear as nodes in the call graph
167 if(isSgFunctionDeclaration(target->get_SgNode())->get_file_info()->isCompilerGenerated()) return NULL;
168
169 // Find the CGFunction in functions that matches the target SgGraphNode
170 for(std::set<CGFunction>::const_iterator it = functions.begin(); it!=functions.end(); it++)
171 {
172 //printf(" iteration. current: %s isCompilerGenerated=%d, target=%s, isCompilerGenerated=%d\n", (*it).get_name().str(), (*it).get_declaration()->get_file_info()->isCompilerGenerated(), target->functionDeclaration->get_name().str(), target->functionDeclaration->get_file_info()->isCompilerGenerated());
173 // If the target SgGraphNode can be found in the current CGFunction
174 if((&(*it))->cgNodes.find(target) != (&(*it))->cgNodes.end())
175 return &(*it);
176 }
177
178 //printf("getTarget returning NULL\n");
179
180 // If we can't find it, return NULL
181 ROSE_ASSERT(!"Error finding the target function of a call graph edge when the target is not compiler generated!");
182 return NULL;
183 }
184
185 // Returns the function that this iterator is currently referring to
186 Function getTarget()
187 {
188 SgGraphNode* target = (dir == fw ? (*ite)->get_to() : (*ite)->get_from());
189 ROSE_ASSERT(isSgFunctionDeclaration(target->get_SgNode()));
190 assert(!isSgTemplateFunctionDeclaration(target->get_SgNode()));
191 Function result(isSgFunctionDeclaration(target->get_SgNode()));
192 return result;
193 }
194
195 void operator ++( int )
196 {
197 ite++;
198
199 advanceToNextValidPoint();
200 }
201
202 // If the current <itn, ite> pair refers to a specific CallGraph node, does nothing.
203 // otherwise, advances the <itn, ite> pair until it does refer to a specific CallGraph node
204 void advanceToNextValidPoint()
205 {
206 //printf("Function::iterator::advanceToNextValidPoint()\n");
207 // Loop for as long as ite is not pointing to a valid node and hasn't reached the end of the node list
208 while(1)
209 {
210 // If ite is the last incoming/outgoing edge of the current SgGraphNode
211 if(ite == edges.end())
212 {
213 //printf("Function::iterator::advanceToNextValidPoint() while()\n");
214 // Advance to the next SgGraphNode in cgNodes
215 itn++;
216
217 // If this is not the last SgGraphNode in cgNodes
218 if(itn != func->cgNodes.end())
219 {
220 // Set edges to the incoming/outgoing edges of the new SgGraphNode and set ite to refer to the first edge
221 if(dir == fw) edges = func->graph->computeEdgeSetOut(*itn);
222 else edges = func->graph->computeEdgeSetIn(*itn);
223 ite = edges.begin();
224 }
225 // otherwise, leave the loop since this iterator has reached the end
226 else
227 {
228 finished=true;
229 break;
230 }
231 }
232 // Else, if it is not the last edges
233 else
234 {
235 SgGraphNode* target = (dir == fw ? (*ite)->get_to() : (*ite)->get_from());
236 // If we've already seen this node
237 if(visitedCGNodes.find(target) != visitedCGNodes.end())
238 ite++;
239 // Else, we have a valid node. Record that we've visited it and break out since we've found a valid upstream/downstream node
240 else {
241 visitedCGNodes.insert(target);
242 break;
243 }
244 }
245 }
246 }
247
248 bool operator == (const iterator& that)
249 {
250 // if either iterators are finished, then they're equal iff the other is finished, ignoring any other fields
251 if(finished) return that.finished;
252 else if(that.finished) return finished;
253
254 // otherwise, they're equal only if all their other members are equal
255 return (dir == that.dir) &&
256 (itn == that.itn) &&
257 (edges == that.edges) &&
258 (ite == that.ite) &&
259 (func == that.func);
260 }
261
262 bool operator != (const iterator& that)
263 { return !((*this) == that); }
264 };
265
266 // Returns an iterator that traverses the callees of this function
267 iterator callees() const
268 {
269 iterator b(this, iterator::fw);
270 return b;
271 }
272 iterator successors() const
273 {
274 iterator b(this, iterator::fw);
275 return b;
276 }
277
278 // Returns an iterator that traverses all the callers of this function
279 iterator callers() const
280 {
281 iterator b(this, iterator::bw);
282 return b;
283 }
284 iterator predecessors() const
285 {
286 iterator b(this, iterator::bw);
287 return b;
288 }
289
290 iterator end() const
291 {
292 iterator b;
293 return b;
294 }
295};
296
298{
299 protected:
301
302 // The set of functions in this program
303 std::set<CGFunction> functions;
304
305 // The number of functions that call each given function
306 std::map<const CGFunction*, int> numCallers;
307
308 // set of all the SgFunctionDefinition for all functions that are not called from other functions
309 // Set of functions that are not called from other functions.
310 // Just contains pointers to the CGFunction objects inside the functions set.
311 std::set<const CGFunction*> noPred;
312
313 public:
315
316 // Returns a pointer to a CGFunction that matches the given declaration.
317 // The memory of the object persists for the entire lifetime of this TraverseCallGraph object.
318 const CGFunction* getFunc(SgFunctionDeclaration* decl);
319
320 // Returns a pointer to a CGFunction object that matches the given Function object.
321 // The memory of the object persists for the entire lifetime of this TraverseCallGraph object.
322 const CGFunction* getFunc(const Function& func);
323};
324
325/* Un-ordered traversal of the call graph */
327{
328 public:
330
331 void traverse();
332
333 virtual void visit(const CGFunction* func)=0;
334
336};
337
338template <class InheritedAttribute>
340{
341 class funcRecord
342 {
343 public:
344 // the inherited attributes passed down from callers
345 std::list<InheritedAttribute> fromCallers;
346 };
347
348 public:
350
351 void traverse();
352
353 virtual InheritedAttribute visit(const CGFunction* func, std::list<InheritedAttribute>& fromCallers)=0;
354
355 virtual InheritedAttribute defaultAttrVal() { InheritedAttribute val; return val; }
356
357 protected:
358 void traverse_rec(const CGFunction* fd,
359 std::map<const CGFunction*, funcRecord> &visitRecords,
360 std::set<std::pair<const CGFunction*, const CGFunction*> > &touchedEdges,
361 InheritedAttribute &fromCaller);
362
363 public:
365};
366
367
368template <class SynthesizedAttribute>
370{
371 public:
373
374 void traverse();
375
376 virtual SynthesizedAttribute visit(const CGFunction* func, std::list<SynthesizedAttribute> fromCallees)=0;
377
378 virtual SynthesizedAttribute defaultAttrVal() { SynthesizedAttribute val; return val; }
379
380 protected:
381 SynthesizedAttribute traverse_rec(const CGFunction* fd,
382 std::map<const CGFunction*, SynthesizedAttribute> &visitRecords,
383 std::set<std::pair<const CGFunction*, const CGFunction*> > &touchedEdges);
384
385 public:
387};
388
389// CallGraph traversal useful for inter-procedural dataflow analyses because it starts
390// at the functions that are not called by any other function and allows such
391// analyses to keep adding more nodes depending on how function dataflow information changes
393{
394 public:
395 // list of functions that still remain to be processed;
396 std::list<const CGFunction*> remaining;
397
399
400 void traverse();
401
402 virtual void visit(const CGFunction* func)=0;
403
404 // adds func to the back of the remaining list, if its not already there
405 void addToRemaining(const CGFunction* func);
406
408};
409
410/*********************************************************
411 *** numCallersAnnotator ***
412 *** Annotates every function's SgFunctionDefinition ***
413 *** node with a numCallersAttribute that contains the ***
414 *** number of functions that call the given function. ***
415 *********************************************************/
416
417// The attribute that is associated with each function's declaration to
418// record its number of callers.
420{
421 int numCallers;
422
423 public:
425 {
426 numCallers = 0;
427 }
428
429 numCallersAttribute(int numCallers)
430 {
431 this->numCallers = numCallers;
432 }
433
435 {
436 this->numCallers = that.numCallers;
437 }
438
439 int getNumCallers()
440 {
441 return numCallers;
442 }
443};
444
445// Uses the numCallersAnnotator class to annotate every function's SgFunctionDefinition node
446// with a numCallersAttribute that contains the number of functions that call the given function.
447void annotateNumCallers(SgIncidenceDirectedGraph* graph);
448
449// Returns the number of functions that call this function or 0 if the function is compiler-generated.
450int getNumCallers(const Function* fDecl);
451
452#endif
453#endif
Base class for all IR node attribute values.
This class represents the concept of a C++ function call (which is an expression).
This class represents the concept of a function declaration statement.
This class represents the concept of a scope in C++ (e.g. global scope, fuction scope,...
virtual Sg_File_Info * get_file_info() const override
Interface function to implement original SAGE interface to SgFile_Info objects.
This class represents strings within the IR nodes.
This class represents the location of the code associated with the IR node in the original source cod...
bool isCompilerGenerated() const
Returns true only if compiler generated (either by the front-end or by ROSE).