ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DependenceGraph.h
Go to the documentation of this file.
1 #ifndef _DEPENDENCEGRAPH_H_
2 #define _DEPENDENCEGRAPH_H_
3 
4 #include "DebugTool.h"
5 #define NEWDU
6 
7 #include <AstInterface.h>
8 #include <StmtInfoCollect.h>
9 #include <ReachingDefinition.h>
10 #include <DefUseChain.h>
11 #include "CallGraph.h"
12 #include <ostream>
13 #include <string>
14 #include <map>
15 #include <utility>
16 #include <set>
17 //#include "DominanceFrontier.h"
18 #include "SimpleDirectedGraph.h"
19 
20 // #include "rose.h"
21 #include "SDGLibraryExtender.h"
22 //nclude "../newImDomImpl/filteredCFG.h"
23 #include <virtualCFG.h>
24 #include "filteredCFG.h"
25 #include "DominatorTree.h"
26 #include "DominanceFrontier.h"
27 #ifdef NEWDU
28 //#include "DefUseAnalysis.h"
29 #include "EDefUse.h"
30 #endif
31 
32 
33 // DQ (12/30/2005): This is a Bad Bad thing to do (I can explain)
34 // it hides names in the global namespace and causes errors in
35 // otherwise valid and useful code. Where it is needed it should
36 // appear only in *.C files (and only ones not included for template
37 // instantiation reasons) else they effect user who use ROSE unexpectedly.
38 // using namespace std;
39 
40 // CI (01/31/2007): DependenceGraph uses a deprecated graph structure, due to time constraints, I was not able to refactor this to use the standart rose-graphs, this might be done in the future!
41 
42 
43 /* ! \class DependenceNode
44 
45  This class represents a node in a dependence graph. By inheriting from
46  SimpleDirectedGraphNode, it keeps track of both its successors and its
47  predecessors. The node can be one of several different types, indicating
48  its role in a dependence graph. The node may also contain a pointer to an
49  SgNode.
50 
51  The use of this class requires that the file SimpleDirectedGraph.h exist.
52 
53 */
54 using namespace VirtualCFG;
55 using namespace::DominatorTreesAndDominanceFrontiers;
58 
59 
60 NodeQuerySynthesizedAttributeType queryIsImportantForSliceType(SgNode * astNode);
61 NodeQuerySynthesizedAttributeType queryIsImportantForSliceTypeWithCalls(SgNode * astNode);
63 {
64  bool operator() (CFGNode cfgn) const
65  {
66  SgNode * n=cfgn.getNode();
67  // modify the is interesting for for,while,do-while and if construct
68  // the exit-branch of the cfg needs to be on the controling expression, this if take care of that
69  /* if (isSgWhileStmt(n) && cfgn.getIndex()!=0) return false;
70  else if (isSgForStatement(n) && cfgn.getIndex()!=1) return false;
71  else if (isSgDoWhileStmt(n) && cfgn.getIndex()!=1) return false;
72  else if (isSgIfStmt(n) && cfgn.getIndex()!=2) return false;*/
73 
74  //Jim Leek: 2/21/2009: Added to fix problem with dupicate nodes appearing in Dominance Tree.
75  if(isSgExprStatement(n)) {
76  return false;
77  }
78 
79 #if 1
81  {
82  return false;
83  /*
84  if (cfgn.getIndex()!=0)
85  return false;*/
86  //else continue to the user-defined filter
87  }
88  // not a loop -> normal isInteresting
89  else
90  {
91  if (!cfgn.isInteresting())
92  return false;
93  }
94  return IsImportantForSliceSgFilter(cfgn.getNode());
95 #endif
96  // return cfgn.isInteresting();
97  /*
98  #if 0
99  // get rid of all beginning nodes if (!cfgn.isInteresting()) return false;
100  SgNode *n = cfgn.getNode(); if (isSgExprStatement(n)) return true;
101  if (isSgReturnStmt(n)) return true; // the following should not be necessary
102  if (isSgFunctionDefinition(n)) return true; // if (isSgStatement(n)) return true;
103  // check for for-loop incremental expression
104  if ((isSgBinaryOp(n) || isSgUnaryOp(n)) && isSgExpression(n)) {
105  // if the parent is a for statement, then true else false
106  SgNode *current = n;
107  while (isSgExpression(current->get_parent()))
108  {
109  current = current->get_parent();
110  }
111  if (isSgForStatement(current->get_parent()))
112  return true;
113 
114  }
115  return false;
116  #endif
117  // get rid of all beginning nodes
118  if (!cfgn.isInteresting())
119  return false;
120  SgNode *n = cfgn.getNode();
121  if (isSgStatement(n))
122  return true;
123  return false;
124  if (isSgExprStatement(n))
125  return true;
126  if (isSgReturnStmt(n))
127  return true;
128  // function calls are interesting, but ONLY if they are not yet shown in another way..
129  if (isSgFunctionCallExp(n))
130  {
131 
132  return true;
133  }
134  // the following should not be necessary
135  if (isSgFunctionDefinition(n))
136  return true;
137  // if (isSgStatement(n)) return true;
138  // check for for-loop incremental expression
139  if ((isSgBinaryOp(n) || isSgUnaryOp(n)) && isSgExpression(n))
140  {
141  // if the parent is a for statement, then true else false
142  SgNode *current = n;
143  while (isSgExpression(current->get_parent()))
144  {
145  current = current->get_parent();
146  }
147  if (isSgForStatement(current->get_parent()))
148  return true;
149  }
150  return false;
151  */
152  };
153 };
156 //typedef TemplatedDominatorTree<int> SliceDominatorTree;
157 typedef TemplatedDominatorTree<IsImportantForSliceCFGFilter> SliceDominatorTree;
158 typedef TemplatedDominanceFrontier<IsImportantForSliceCFGFilter> SliceDominanceFrontier;
159 
160 
161 
162 
164 {
165  // Han: moved to lower
166  /*
167  protected:
168  bool highlight;
169  */
170 
171  public:
172 
173  // ! This enum notes what type of node this is
174  enum NodeType // NO_STRINGIFY
175  {
176  CONTROL=0, /* !< Used to indicate a dummy node for
177  control dependence */
178  SGNODE=1, /* !< Used to indicate a node with an SgNode
179  in it */
180  CALLSITE=2, /* !< Used to indicate a call-site node for
181  interprocedural slicing */
182  ACTUALIN=3, /* !< Used to indicate the arguments at a call
183  site */
184  ACTUALOUT=4, /* !< Used to indicate returned values at a call site*/
185 
186  FORMALIN=5, /* !< Used to indicate the arguments into a
187  function */
188  FORMALOUT=6, /* !< Used to indicate the return values from
189  a function */
190  ENTRY=7, /* !< Used to indicate the entry point of a
191  function */
192  ACTUALRETURN=8, /* ! since it may happen that an actual out has the same identifiyer as the actual out from the return, an ew id was introduces*/
193  FORMALRETURN=9,
194  NUM_NODE_TYPES /* !< Must be last enum in list to establish
195  number of types */
196  };
197  bool isDummyNode()
198  {
199  if (depType== ACTUALOUT
200  ||depType== FORMALOUT
201  ||depType== CONTROL
202  ||depType== ENTRY)return true;
203  else return false;
204  }
205 
206  /* ! \brief Holds C-strings associated with the node types
207 
208  The array is initialized in DependenceGraph.C */
209  static const char *typeNames[NUM_NODE_TYPES];
210 
211  /* !
212 
213  \brief Constructor for DependenceNode, defines type, SgNode it
214  contains, and name
215 
216  Every DependenceNode has a type. Some types have an associated SgNode
217  with them: - SGNODE: the SgNode that the DependenceNode represents -
218  CALLSITE: the SgFunctionCallExp associated with the function call -
219  ENTRY: the SgFunctionDeclaration for the function - ACTUALIN/OUT: the
220  SgExpressions that are the arguments to the function call
221 
222  The FORMALIN/OUT nodes have a name associated with them (the name of
223  the variable in the parameter list).
224 
225  CONTROL nodes have neither associated SgNodes nor names.
226 
227  If we build a node using this constructor, the _copiedfrom member is
228  NULL. */
229 
230  DependenceNode(SgNode * node):depType(SGNODE),sgNode(node),name(escapeString(node->unparseToString())),highlight(false)
231  {}
232 
233  DependenceNode(NodeType type, SgNode * node = NULL, std::string depName= ""):depType(type),
234  sgNode(node),name(depName),highlight(false)
235  {
236  }
237  // ! If only a name is provided, we assume that there is no associated
238  // SgNode
239  // Han: changed the order of initialization
240  DependenceNode(NodeType type, std::string depName):depType(type), sgNode(NULL),
241  name(depName), highlight(false)
242  {
243  }
244 
245  // Han: added virtual destructor
246  virtual ~DependenceNode() {};
247 
249  {
250  highlight=true;
251  }
253  {
254  highlight=false;
255  }
257  {
258  return highlight;
259  }
260 
261  // ! returns the associated SgNode
263  {
264  return sgNode;
265  }
266 
267  // ! returns the type
269  {
270  return depType;
271  }
272 
273  // ! returns the associated name
274  std::string getName()
275  {
276  return name;
277  }
278 
279  void setName(std::string newName)
280  {
281  name=newName;
282  }
283 
284  /* ! \brief returns whether a node has an interprocedural type
285 
286  Certain node types are only used during interprocedural slicing (i.e.
287  when we use a SystemDependenceGraph. These are: - CALLSITE - ACTUALIN -
288  ACTUALOUT - FORMALIN - FORMALOUT - ENTRY */
289  bool isInterproc()
290  {
291  switch (depType)
292  {
293  case CALLSITE:
294  case ACTUALIN:
295  case ACTUALOUT:
296  case FORMALIN:
297  case FORMALOUT:
298  case ENTRY:
299  return true;
300  default:
301  return false;
302  }
303  }
304 
305  // ! returns whether a node is a formal argument
306  bool isFormal()
307  {
308  switch (depType)
309  {
310  case FORMALIN:
311  case FORMALOUT:
312  return true;
313  default:
314  return false;
315  }
316  }
317 
318  // ! returns whether a node is an actual argument
319  bool isActual()
320  {
321  switch (depType)
322  {
323  case ACTUALIN:
324  case ACTUALOUT:
325  return true;
326  default:
327  return false;
328  }
329  }
331  {
332  if (depType == FORMALRETURN && isSgFunctionDeclaration(sgNode))
333  return true;
334  else
335  return false;
336 
337  }
338 
339  // ! Prints the contents of the node to os.
340  virtual void writeOut(std::ostream & os)
341  {
342 
343  switch(depType)
344  {
345  case SGNODE:
346  // no output for normal nodes
347  break;
348  // os << "SGNODE\\n";break;
349  case CONTROL:
350  os << "CONTROL\\n";break;
351  case CALLSITE:
352  os << "CALLSITE\\n";break;
353  case ACTUALIN:
354  os << "ACTUALIN\\n";break;
355  case ACTUALOUT:
356  os<<"ACTUALOUT\\n";break;
357  case FORMALIN:
358  os<<"FORMALIN\\n";break;
359  case FORMALOUT:
360  os<<"FORMALOUT\\n";break;
361  case FORMALRETURN:
362  os<<"FORMALRETURN\\n";break;
363  case ACTUALRETURN:
364  os<<"ACTUALRETURN\\n";break;
365  case ENTRY:
366  os<<"ENTRY\\n";break;
367  default:
368  os<<"NULL!!!!";break;
369  }
370  if (sgNode != NULL) {
371 #ifdef DOT_OUT_VERBOSE
372  switch(depType)
373  {
374  default:
375  os << sgNode->class_name() << "\\n";
376  if (isSgExpressionRoot(sgNode))
377  {
378  os << "[" << escapeString(isSgExpressionRoot(sgNode)->get_operand()->unparseToString()) << "]";
379  }
380  else if (isSgFunctionDeclaration(sgNode))
381  {
382  os << "[" << isSgFunctionDeclaration(sgNode)->get_name().str() << "]";
383  }
384  else if (isSgFunctionDefinition(sgNode))
385  {
386  os<< "Entry ("+isSgFunctionDefinition(sgNode)->get_declaration()->get_name().getString()+")";
387  // os << name;
388  //os << "[" << isSgFunctionDeclaration(sgNode)->get_name().str() << "]";
389  }
390  else if (isSgInitializedName(sgNode))
391  {
392  os << "["<<isSgInitializedName(sgNode)->get_qualified_name().getString()<<"]";
393  }
394  else
395  {
396  // std::cout <<"node"<<sgNode->class_name()<<std::endl;
397  os << "[" << escapeString(sgNode->unparseToString()) << "]";
398  }
399  break;
400  case FORMALOUT:
401  {
402  if (isSgFunctionDeclaration(sgNode))
403  // RETURN
404  os <<"RETURN of"<<isSgFunctionDeclaration(sgNode)->get_name().str();
405  else
406  if (isSgInitializedName(sgNode))
407  os << "["<<isSgInitializedName(sgNode)->get_qualified_name().getString()<<"]";
408 
409  }
410  }
411 #else
412  if (isSgExpressionRoot(sgNode))
413  {
414  os << escapeString(isSgExpressionRoot(sgNode)->get_operand()->unparseToString());
415  }
416  else if (isSgFunctionDeclaration(sgNode))
417  {
418  os << isSgFunctionDeclaration(sgNode)->get_name().str() ;
419  }
420  else if (isSgFunctionDefinition(sgNode))
421  {
423  // os << name;
424  //os << "[" << isSgFunctionDeclaration(sgNode)->get_name().str() << "]";
425  }
426  else if (isSgInitializedName(sgNode))
427  {
429  }
430  else
431  {
432  // std::cout <<"node"<<sgNode->class_name()<<std::endl;
433  os << escapeString(sgNode->unparseToString());
434  }
435 
436 #endif
437  }
438  }
439 
440  private:
441 
442  // Han: changed the order of declaration
445 
446  std::string name;
447 
448  protected:
449  bool highlight;
450 };
451 
452 
453 
454 /* ! \class InterproceduralInfo
455 
456  This class holds information necessary to perform interprocedural slicing.
457  As specified in the paper by Horowitz et al, every function in a program
458  requires: - An "entry" node - A "formal-in" node for each parameter - A
459  "formal-out" node for each return parameter
460 
461  Similarly, every function call in a procedure requires: - A "call-site"
462  node - An "actual-in" node for every argument to the function - An
463  "actual-out" node for every return variable
464 
465  There should be one InterproceduralInfo object associated with each
466  procedure in a program. It is initialized by passing in a newly created
467  object to the constructor of a ControlDependenceGraph. It must then be
468  passed to the constructor of a DataDependenceGraph. At this point, it
469  contains all the appropriate intraprocedural edges and nodes as specified
470  above.
471 
472 */
473 #if 0
475 {
476  public:
477  // ! the nodes required to fully represent a call site in the PDG
478  struct CallSiteStructure
479  {
481  SgNode* sliceImportantNode;
483  SgNode* sgFunctionCallExpNode;
484  // ! the callsite - one per SgFunctionCallExp
485  DependenceNode *callSiteDepNode;
486  // ! the actual-in nodes - one per argument
487  std::vector<SgExpression*> actual_in;
488  // std::vector<SgExpression*
489  // std::map < SgExpression *, DependenceNode * >actual_in;
490  // ! the actual-out nodes - one per argument
491  // std::map < SgExpression *, DependenceNode * >actual_out;
492  // ! a list which records the order of the function arguments
493  // std::list < SgExpression * >expr_order;
494  // ! an actual-out node representing the return value of the function
495  // call
496  SgNode *actual_return;
497  };
498  SgNode * getActualReturn(int id)
499  {
500  return callSites[id].actual_return;
501  }
502  SgNode * getActualIn(int id,int varNr)
503  {
504  return callSites[id].actual_in[varNr];
505  }
506  int getActualInCount(int id)
507  {
508  return callSites[id].actual_in.size();
509  }
510  void addActualIn(int id,SgExpression * node)
511  {
512  callSites[id].actual_in.push_back(node);
513  }
514  void setSliceImportantNode(int id,SgNode * node)
515  {
516  callSites[id].sliceImportantNode=node;
517  }
518  void setActualReturn(int id,SgNode * node)
519  {
520  callSites[id].actual_return=node;
521  }
522 
524  SgNode * getSliceImportantFunctionCallNode(int i)
525  {
526  return callSites[i].sliceImportantNode;
527  }
528  std::set<SgNode *> getExitNodes()
529  {
530  return exitNodes;
531  }
532  void addParameterToFunctionCall(SgNode * functionCall,SgExpression * param)
533  {
534  }
535 
536  int callSiteCount()
537  {
538  return callSites.size();
539  }
540  SgNode * getFunctionCallExpNode(int i)
541  {
542  return callSites[i].sgFunctionCallExpNode;
543  }
544  SgNode * getFunctionEntry()
545  {
546  return entry;
547  }
548  protected:
549  SgFunctionDeclaration * decl;
550  SgFunctionDefinition * def;
551  SgNode * entry;
552 
553  // ! the nodes required to fully represent a procedure entry in the PDG
554  // ! an entry node - one per function declaration
555  // ! the formal-in nodes - one per function parameter
556  // std::map < SgInitializedName *, DependenceNode * >formal_in;
557  // ! the formal-out nodes - one per function parameter
558  std::map < SgInitializedName *, DependenceNode * >formal_out;
559  // ! a list which records the order of the parameters
560  Rose_STL_Container < SgInitializedName * >arg_order;
561  // ! a formal out node representing the return value of the function
562  SgNode * formal_return;
563  std::vector<SgNode*> formal_in;
564  // DependenceNode *formal_return;
565  // list containing the nodes from the function that exit...
566  std::set<SgNode *> exitNodes;
567 
568  // ! The entry node for a procedure
569  // ProcedureEntryStructure procedureEntry;
570  std::vector<CallSiteStructure> callSites;
571 
572  std::map<SgNode *, int> callSitesMap;
573 
574 
575  public:
576  int getFormalInCount()
577  {
578  return formal_in.size();
579  }
580  SgNode * getFormalIn(int nr)
581  {
582  if (formal_in.size()>nr && nr>=0)
583  return formal_in[nr];
584  ROSE_ASSERT(false);
585  }
586 
587  SgNode * getFormalReturn()
588  {
589  return formal_return;
590  }
591  // add this DependenceNode to the list of nodes which lead to exiting this function
592  void addExitNode(SgNode * node)
593  {
594  exitNodes.insert(node);
595  }
596 
597  InterproceduralInfo(SgFunctionDeclaration* functionDeclaration)
598  {
599  std::cout << "creating interprocedural info\n";
600  decl=functionDeclaration;
601  def=functionDeclaration->get_definition();
602  if (def==NULL) entry=decl;
603  else entry=def;
604  // create formal stuff
605  formal_return=functionDeclaration;
606 
607  Rose_STL_Container<SgInitializedName*> argList=functionDeclaration->get_args();
608  for (Rose_STL_Container<SgInitializedName*>::iterator i=argList.begin();i!=argList.end();i++)
609  {
610  std::cout << "\tadding formal in "<<*i<<"\n";
611  formal_in.push_back(*i);
612  }
613 
614  }
615 
616  /* ! \brief Gets the function declaration that the InterproceduralInfo object is for.
617  Returns: The SgFunctionDeclaration node that is associated with this object */
618  SgFunctionDeclaration * foo(){return decl;}
619 
620  SgFunctionDeclaration * getFunctionDeclaration()
621  {
622  return decl;
623  }
624 
625  // adds an function call to the tracking list, this will alter on be used to analyse the calls site in the ...
626  // void addFunctionCall(SgNode * sliceImportantNode,SgNode * functionCall,SgNode * actualReturnIdentifier=NULL)
627  int addFunctionCall(SgNode * functionCall)
628  {
629  CallSiteStructure cs;
630  cs.sliceImportantNode=NULL;//sliceImportantNode;
631  cs.sgFunctionCallExpNode=functionCall;
632  cs.callSiteDepNode=NULL;
633  cs.actual_return=NULL;
634  callSites.push_back(cs);
635  callSitesMap[functionCall]=callSites.size()-1;
636  return callSites.size()-1;
637  }
638 
642  /* static std::list < SgFunctionCallExp * >extractFunctionCalls(SgNode * node)
643  {
644  std::list < SgFunctionCallExp * >retval;
645  std::list < SgNode * >calls = NodeQuery::querySubTree(node, V_SgFunctionCallExp);
646  for (std::list < SgNode * >::iterator i = calls.begin(); i != calls.end(); i++)
647  {
648  SgFunctionCallExp *fce = isSgFunctionCallExp(*i);
649  ROSE_ASSERT(fce != NULL);
650  retval.push_back(fce);
651  }
652 
653  return retval;
654  }*/
655  // ! maps function calls to the call site structure that represents them
656  // std::map < SgFunctionCallExp *, CallSiteStructure > callsite_map;
657 };
658 #else
659 #include "InterproceduralInfo.h"
660 #endif
661 
662 /* ! \class DependenceGraph
663 
664  This class is a SimpleDirectedGraph which uses DependenceNodes. However,
665  unlike a standard SimpleDirectedGraph, the SimpleDependenceGraph may
666  contain several different types of edges, as indicated by EdgeType.
667 
668  The use of this class requires that the file SimpleDirectedGraph.h exist
669 
670 */
671 
673 {
674  protected:
675  bool debugme;
676  public:
677  DependenceGraph() {debugme=false;}
678  virtual ~DependenceGraph(){};
680  {
681  std::set<SimpleDirectedGraphNode *>::iterator i;
682  for (i=_nodes.begin();i!=_nodes.end();i++)
683  {
684  std::cout<<"\t\t"<<(*i)<<"\n";
685  }
686  }
687 
688  /* ! \brief This enum marks what type of edge connects two DependenceNodes
689 
690  This enum is used in conjunction with bit vector representations, so
691  some of the values are powers of two */
692  enum EdgeType // NO_STRINGIFY
693  {
694  // control information
695  CONTROL = 0x1, /* !< A control dependence edge */
696  CALL = 0x4, /* !< An edge between a call site and a function entry, or from actual-in to formal-in nodes */
697  CALL_RETURN = 0x5, /* !return to the call-site */
698  // data information
699  DATA = 0x2, /* !< A data dependence edge */
700  SUMMARY = 0x3, /* !< A summary edge between actual-in and actual-out nodes (used for interprocedural */
701  PARAMETER_IN = 0x7,
702  PARAMETER_OUT = 0x8,
703  // SYNTACTIC
704  SYNTACTIC = 0xe,
705 
706  // RETURN = 0x6, /* !< An edge from formal-out nodes to actual-in nodes */
707  DATA_HELPER = 0x9,
708  CONTROL_HELPER = 0xa,
709  GLOBALVAR_HELPER= 0xb,
710  COMPLETENESS_HELPER=0xc,
711  // nice, but completely useless
712  BELONGS_TO = 0xd, /* shows for floating nodes, to which statement/node they belong to*/
713  // NUM_EDGE_TYPES = 0x11 /* !< Set to be 1 more than the last entry, to fix size of the name array */
714 
715  // Jim Leek, 2009/6/3: DO_NOT_FOLLOW is A special type of edge for controlling reachability. It can keep an edge from
716  // being traversed by _getReachable without changing the type of the edge
717  DO_NOT_FOLLOW = 0x10,
718  };
719  /* ! \brief an array of C-strings for each EdgeType
720  This array is initialized in DependenceGraph.C */
721  static const char *edgeNameArray[8];
722  const char *getEdgeName(EdgeType type);
723  /*
724  static char *getEdgeName(EdgeType type)
725  {
726  int offset=0;
727  switch(type)
728  {
729  case CONTROL:
730  return "CONTROL";
731  case DATA:
732  return "DATA";
733  case SUMMARY:
734  return "SUMMARY";
735  `case CALL:
736  return "CALL";
737  case RETURN:
738  return "RETURN";
739  case PARAMETER_IN:
740  return "PARAMETER_IN";
741  case PARAMETER_OUT:
742  return "PARAMETER_OUT";
743  case DATA_HELPER:
744  return "DATA_HELPER
745  default:
746  return "UNKNOWN"
747  }
748  }*/
749  // static char *edgeNames[NUM_EDGE_TYPES];
750 
751  /* ! \brief create a new DependenceNode that is a copy of node
752 
753  Params: - DependenceNode * node: the node we want to copy
754 
755  Return: Either a newly created copy, or, if this has been copied
756  before, the previous copy
757 
758  Side effects: If we created a new copy, we insert a mapping from node
759  to the newly created copy in _depnode_map. */
760  // DependenceNode *createNode(DependenceNode * node);
761 
762  /* ! \brief retrieve the DependenceNode associated with node
763 
764  Params: - DependenceNode * node: the node we want to find a copy for
765 
766  Return: If node exists in _depnode_map, we return the associated copy,
767  otherwise we return NULL. */
768  // DependenceNode *getNode(DependenceNode * node);
769 
770  /* ! \brief create a new DependenceNode which contains node
771 
772  Params: - SgNode * node: the SgNode we want to wrap in a DependenceNode
773 
774  Return: Either a new DependenceNode or, if we've already wrapped this
775  SgNode, the existing DependenceNode containing node
776 
777  Side effects: If we created a new DependenceNode, we insert a mapping
778  from node to the newly created DependenceNode in _sgnode_map. */
779  DependenceNode *createNode(DependenceNode::NodeType type,SgNode * identifyingNode);
780  DependenceNode *createNode(SgNode * node);
781  void deleteNode(DependenceNode * node);
782 
783  /* ! \brief retrieve the DependenceNode that wraps node
784 
785  Params: - SgNode * node: the SgNode for which we want to find the
786  associated DependenceNode
787 
788  Return: If there is a wrapper DependenceNode in _sgnode_map, we return
789  it. Otherwise, we return NULL. */
790  DependenceNode *getNode(SgNode * node);
791  // (NodeType type, SgNode * node = NULL, std::string depName= "")
792  DependenceNode *getNode(DependenceNode::NodeType type,SgNode * identifyingNode);
793 
794  DependenceNode * getExistingNode(SgNode * node);
795  DependenceNode * getExistingNode(DependenceNode::NodeType type,SgNode * identifyingNode);
796 
797  // ! return the InterproceduralInfo object associated with the
798  // DependenceGraph
800  {
801  return NULL;
803  }
804 
805  /* ! \brief create an edge of type e between from and to
806 
807  Params: - DependenceNode * from: the source of the edge -
808  DependenceNode * to: the sink of the edge - EdgeType e: the type of the
809  edge
810 
811  Side effects: Inserts the Edge (from, to) into the set associated with
812  e by _edgetype_map. Inserts e into the set associated with Edge(from,
813  to) by _edge_map.
814 
815  */
816  virtual void establishEdge(DependenceNode * from, DependenceNode * to, EdgeType e=CONTROL);
817  virtual void removeEdge(DependenceNode * from, DependenceNode * to, EdgeType e=CONTROL);
818  /* ! \brief determine if there is an edge of type e between from and to
819 
820  Params: - DependenceNode * from: the source of the edge -
821  DependenceNode * to: the sink of the edge - EdgeType e: the type of the
822  edge
823 
824  Return: true if e is in the set associated with Edge(from, to) by
825  _edge_map. */
826  bool edgeExists(DependenceNode * from, DependenceNode * to, EdgeType e);
827  bool hasOutgingEdge(DependenceNode * src,EdgeType compare);
828 
829  /* ! \brief returns all edges between from and to
830 
831  Params: - DependenceNode * from: the source of the edge -
832  DependenceNode * to: the sink of the edge
833 
834  Return: the set of EdgeTypes associated with Edge(from, to) by
835  _edge_map.
836 
837  */
838  std::set < EdgeType > edgeType(DependenceNode * from, DependenceNode * to);
839  /* std::list <DependenceNode*> getParents(DependenceNode * current)
840  {
841  std::list <DependenceNode*> parentList;
842  return parentList;
843  }*/
844  // ! writes a dot file representing this dependence graph to filename
845  virtual void writeDot(char *filename);
846 
847  protected:
848  // ! Maps a DependenceNode to a copy unique to this DependenceGraph
850  // ! Maps an SgNode to a DependenceNode unique to this DependenceGraph
852  std::map<SgNode*,DependenceNode*> sgNodeToDepNodeMap;
853  std::map<DependenceNode::NodeType,std::map<SgNode*,DependenceNode*> > nodeTypeToDepNodeMapMap;
854 
855  // ! The InterproceduralInfo associated with this DependenceGraph
857 
858  typedef std::pair < DependenceNode *, DependenceNode * >Edge;
859 
860  // ! a map from EdgeType to all the edges of that type
861  std::map < EdgeType, std::set < Edge > >edgeTypeMap;
862 
863 // DQ (8/30/2009): Debugging ROSE compiling ROSE (this statement does not compile using ROSE). The error is:
864 // sage_gen_be.C:5286: SgEnumDeclaration* sage_gen_enum_definition(a_type*, SgDeclarationStatement*&, DataRequiredForComputationOfSourcePostionInformation*): Assertion `forwardDeclaration->get_parent() != __null' failed.
865 #ifndef USE_ROSE
866 
867  // ! a map from an edge to all the variants of that edge in the graph
868  std::map < Edge, std::set < EdgeType > >edgeMap;
869 #else
870  std::map < Edge, std::set < int > >edgeMap;
871 #endif
872 
874  {
875  if (sgFD == NULL) return false;
876  else if (sgFD->get_definition() != NULL) return true;
877  else return false;
878  };
879 };
880 
881 
882 /* ! \class ControlDependenceGraph
883 
884  This class is a DependenceGraph which expresses control dependences for a
885  given procedure. Control dependences essentially link decision points in
886  CFGs with the nodes affected by those decisions. The implementation of this
887  class depends on the calculation of Dominator Trees and Dominance
888  Frontiers.
889 
890  If interprocedural analysis is specified (by passing in a non-null
891  InterproceduralInfo object), building this graph will also initialize the
892  InterproceduralInfo object by creating the required formal-in, formal-out,
893  actual-in, actual-out and entry nodes (as well as any required call nodes)
894  for the procedure, and creating the appropriate control dependences: - all
895  actual-in and actual-out nodes are control dependent on the call site - all
896  formal-in and formal-out nodes are control dependent on the entry node -
897  the call site node is control dependent on the DependenceNode representing
898  the function call.
899 
900 
901  The use of this class requires that DominanceFrontier.h exist. Also, the
902  use of this class requires linking against libDominance.
903 
904 */
905 
907 {
908 
909  public:
910 
911  /* ! \brief Contstructor for ControlDependenceGraph
912 
913  Params: - SgNode * head: The root of the AST that you want to build the
914  CDG for - InterproceduralInfo * ii: the InterproceduralInfo object for
915  storing interprocedural information
916 
917  Side effects: - initializes _interprocedural
918 
919  If ii is NULL, we assume that we are not doing interprocedural
920  analysis. Otherwise, we assume that ii is a newly allocated (but not
921  yet initialized) object. */
923 
924  /* ! \brief create a DependenceNode wrapping cnode
925 
926  Params: - ControlNode * cnode: The ControlNode we want to wrap in a
927  DependenceNode
928 
929  Return: If we have already wrapped this node, we return the existing
930  DependenceNode. Otherwise we create a new DependenceNode (of type
931  CONTROL) and return it.
932 
933  Side effects: If a new DependenceNode is created, cnode is mapped to it
934  by _cnode_map.
935 
936  */
937  // DependenceNode *createNodeC(ControlNode * cnode);
938  //DependenceNode *createNodeC(DominatorTreesAndDominanceFrontiers::ControlNode * cnode);
939 
940  //DependenceNode * getNode(SgNode * src);
941 
942  // ! calls establishEdge with EdgeType defaulted to CONTROL
943  /* virtual void establishEdge(DependenceNode * from, DependenceNode * to)
944  {
945  DependenceGraph::establishEdge(from, to, CONTROL);
946  }*/
947  void computeInterproceduralInformation(InterproceduralInfo * ii);
948  void computeAdditionalFunctioncallDepencencies();
949  private:
950 
951  Rose_STL_Container < SgNode * > functionCalls;
952  void processDependence(int aID,int bID);
953  void createSyntacticDependencies();
954  // control-flow-graph for this function
956 
958 
959  void addDependence(int source, int to,EdgeType edge=CONTROL);
960 
961  // SliceDominanceFrontier dominanceFrontier;
962  // ! The root of the AST that the ControlDependenceGraph represents
964  SgNode *decl,*def;
965 
966  void buildCDG();
967 
968 
969  //everzthing from here on is deprecated
970  // ! builds the CDG
971  void _buildCDG();
972 
973  // ! if we're performing interprocedural analysis, initializes the
974  // InterproceduralInfo object
975  void _buildInterprocedural();
976 
977  // ! DEPRECATED. Not used anymore.
978  void _addDependence(SgNode * from, SgNode * to);
979 
980 
981  // ! The control flow graph for the AST
982  // DominatorTreesAndDominanceFrontiers::ControlFlowGraph * _cfg;
983  // ! The dominator tree for the CFG
984  // DominatorTreesAndDominanceFrontiers::DominatorTree * _dt;
985  // ! The dominance frontier for nodes in the CFG
986  // DominatorTreesAndDominanceFrontiers::DominanceFrontier * _df;
987 
988  // ! Maps ControlNodes (nodes in the CFG) to DependenceNodes unique to
989  // this CDG
990  // std::map < DominatorTreesAndDominanceFrontiers::ControlNode *, DependenceNode * >_cnode_map;
991 };
992 
993 /* ! \class DataDependenceGraph
994 
995  This class is a DependenceGraph which expresses data dependences for a
996  given procedure. Data dependences link statement that define variables with
997  the statements that may use those definitions. The implementation of this
998  class depends on the calculation of DefUseChains, and so must link against
999  librose.
1000 
1001  If interprocedural analysis is specified (by passing in a non-null
1002  InterproceduralInfo object which has been initialized by
1003  ControlDependenceGraph), building this graph will create the appropriate
1004  data dependences: - if a statement uses a variable defined in the parameter
1005  list for the function, it is data dependent on the formal-in node - if a
1006  statement defs a variable used as a function parameter in a call, the
1007  actual-in node for the parameter is data dependent on the statement - if a
1008  statement uses a variable returned from a function, it is data dependent on
1009  the actual-out node - if a statement is a return statement, the formal-out
1010  return is data dependent on it.
1011 
1012  @todo Currently, there is no way to link defs that reach the end of the
1013  function (other than return statements) to the appropriate actual-out nodes
1014  (in the case of pass-by-reference arguments). */
1015 
1017 {
1018 
1019  public:
1020 
1021  /* ! \brief Contstructor for DataDependenceGraph
1022 
1023  Params: - SgNode * head: The root of the AST that you want to build the
1024  DDG for - InterproceduralInfo * ii: the InterproceduralInfo object for
1025  storing interprocedural information
1026 
1027  Side effects: - adds data dependence edges to nodes from
1028  _interprocedural
1029 
1030  If ii is NULL, we assume that we are not doing interprocedural
1031  analysis. Otherwise, we assume that ii is an InterproceduralInfo object
1032  that has been initialized by the CDG for the same procedure */
1033 #ifdef NEWDU
1034  DataDependenceGraph(SgNode * head,EDefUse * du, InterproceduralInfo * ii = NULL);
1035 #else
1036  DataDependenceGraph(SgNode * head, InterproceduralInfo * ii = NULL);
1037 #endif
1038 
1039  // ! calls establishEdge with EdgeType defaulted to DATA
1040  /* virtual void establishEdge(DependenceNode * from, DependenceNode * to)
1041  {
1042  DependenceGraph::establishEdge(from, to, DATA);
1043  }*/
1044  void computeInterproceduralInformation(InterproceduralInfo * ii);
1045  private:
1046 #ifdef NEWDU
1048 #endif
1049 
1052  // ! builds the def-use chains for the procedure
1053  void _buildDefUseChains(SgFunctionDefinition * fD);
1054 
1055  // ! uses def-use chains to build the data dependence graph
1056  void buildDDG();
1057  void _buildDDG();
1058 
1059  // ! if doing interprocedural, adds the data dependences from return
1060  // statements to formal-out statements
1061  void _processReturns();
1062 
1063  /* ! \brief Finds the function argument that use is in
1064 
1065  Params: - SgNode * &funcArg: Placeholder for function argument that use
1066  is in - SgNode * use: The variable use we are trying to find the
1067  argument for
1068 
1069  Return: If use was in a function argument, returns the function call
1070  expression the argument was in. Otherwise returns NULL
1071 
1072  Side effects: if returning non-NULL, funcArg is the function argument
1073  that use was in. */
1074  SgFunctionCallExp *_findArgExprFromRef(SgNode * &funcArg, SgNode * use);
1075 
1076  // ! The function that we are building the DDG for
1078 
1079  // ! The def use chains for the function
1081 
1082 };
1083 
1084 /* ! \class MergedDependenceGraph
1085 
1086  This class provides a mechanism for merging together multiple
1087  DependenceGraphs. It also provides a mechanism for getting backwards
1088  reachable nodes given a specific start node and using specified edge types.
1089  This can be called by the abstract function getSlice to create specific
1090  types of slices (i.e. intraprocedural or interprocedural).
1091 
1092 */
1094 {
1095 
1096  public:
1097 
1098  /* ! \brief creates a new dependence node that reflects the argument (not
1099  a direct copy)
1100 
1101  Params: - DependenceNode * node: The node we want to make a "copy" of
1102 
1103  Return: If we've already "copied" the node, return the existing
1104  DependenceNode. Otherwise create a new one.
1105 
1106  Side effects: calls createNode appropriately to perform "copies," so
1107  _sgnode_map or _depend_map may be updated.
1108 
1109  If the node we are adding is an interprocedural node, we want to copy
1110  the _interproc pointer, not node itself. If it's an SgNode, we want to
1111  build the DependenceNode around that, as opposed to node. If it's
1112  neither, we just copy the argument. */
1113  DependenceNode * _importNode(DependenceNode * node);
1114 
1115  /* ! \brief creates a backward slice starting from node
1116 
1117  Params: - SgNode * node: the slicing criterion
1118 
1119  Return: returns a set of SgNodes which belong in the slice with slicing
1120  criterion node.
1121 
1122  This function calls getSlice, and prunes the returned values to find
1123  just the SgNodes. */
1124  std::set < SgNode * >slice(SgNode * node);
1125 
1126  /* ! \brief creates a backward slice starting from node
1127 
1128  Params: - DependenceNode * node: the slicing criterion
1129 
1130  Return: returns a set of DependenceNodes which belong in the slice with
1131  slicing criterion node.
1132 
1133  This is a more general version of slice, which operates on any
1134  DependenceNode. */
1135  virtual std::set < DependenceNode * >getSlice(DependenceNode * node) = 0;
1136 
1137  protected:
1138 
1139  /* ! \brief performs a backwards reachability analysis starting from nodes
1140  in start
1141 
1142  Params: - set<DependenceNode *> start: the starting nodes for the
1143  backwards reachability analysis - int edgeTypesToFollow: a bit-vector
1144  whose set bits indicate the types of edges to consider for
1145  reachability. */
1146  std::set < DependenceNode * >_getReachable(std::set < DependenceNode * >start,
1147  int edgeTypesToFollow = 0);
1148 
1149  /* ! \brief merges graph into the current MergedDependenceGraph
1150 
1151  Params: - DependenceGraph * graph: the DependenceGraph we want to merge
1152  into the current graph
1153 
1154  Side effects: Any new nodes and edges from graph are added to the
1155  MergedDependenceGraph */
1156  void _mergeGraph(DependenceGraph * graph);
1157  void mergeGraph(DependenceGraph * graph);
1158 
1159 };
1160 
1161 /* ! \class FunctionDependenceGraph
1162 
1163  This is a MergedDependenceGraph which merges a ControlDependenceGraph and a
1164  DataDependenceGraph for a specific procedure, thus representing a complete
1165  DependenceGraph for one procedure. If we are planning on doing
1166  interprocedural analysis (i.e. we've passed in a non-null
1167  InterproceduralInfo object), then we also create summary edges between the
1168  actual-in nodes for a call and the appropriate actual-out nodes.
1169 
1170  @todo Right now, we assume that the function will have no side-effects, and
1171  simply create a summary between all the actual-in nodes and the actual-out
1172  node representing the return. This should be extended to create real
1173  summary edges as defined in the paper by Horwitz et al. However, because we
1174  can't correctly handle defs that reach the end of functions, we can't
1175  properly summarize, and so we skip this for now.
1176 
1177 */
1178 
1180 {
1181 
1182  public:
1183  /* ! \brief Constructor for FunctionDependenceGraph, initialized with the
1184  CDG and DDG for the function.
1185 
1186  Params: - ControlDependenceGraph * cdg: a previously built CDG for the
1187  function - DataDependenceGraph * ddg: a previously build DDG for the
1188  function - InterproceduralInfo * ii: If NULL, we aren't doing
1189  interprocedural. Otherwise, the fully initialized InterproceduralInfo
1190  object for the function.
1191 
1192  */
1194  InterproceduralInfo * ii = NULL);
1195 
1196  /* ! \brief gets a slice with slicing criterion node
1197 
1198  This simply does a backwards reachability across all edges to produce
1199  the slice. */
1200  virtual std::set < DependenceNode * >getSlice(DependenceNode * node);
1201 
1202  private:
1203 
1205  void completeFDG();
1206 
1207  // ! DEPRECATED not used anymore
1208  void _addCDG();
1209  // ! DEPRECATED not used anymore
1210  void _mergeDDG();
1211 
1212  /* ! \brief creates summary edges for interprocedural analysis
1213 
1214  Currently, this simply points all the actual-in edges of a call to the
1215  actual-out return statement. This means we assume two things: # All
1216  functions are pass-by-value (so actual-out nodes for parameters are
1217  irrelevant) # Every parameter in the function is relevant (there are no
1218  unused arguments).
1219 
1220  @todo Should replace with attribute-grammar method for creating summary
1221  edges (see Horwitz et al). There is a preliminary start at writing the
1222  classes required to do this in the subdirectory summary/. However it is
1223  not complete and possibly has some structural issues which would
1224  require the entire thing to be rewritten. */
1225  void _summarize();
1226 
1227  // ! The ControlDependenceGraph for the function
1229  // ! The DataDependenceGraph for the function
1231 
1232 };
1233 
1234 /* ! \class SystemDependenceGraph
1235 
1236  This class is a MergedGraph which merges together FunctionDependenceGraphs
1237  representing all procedures in the program. It assumes that the merged
1238  FunctionDependenceGraphs have defined InterproceduralInfo objects. A slice
1239  performed on this graph is an interprocedural slice as defined in the paper
1240  by Horwitz et al.
1241 
1242  @todo _getPossibleFuncs simply assumes that the AST correctly resolves
1243  every SgFunctionCallExp to a specific SgFunctionDeclaration with an
1244  existing SgFunctionDefinition. This should be redone to take advantage of
1245  call graph analysis, which will let us slice codes which have more
1246  ambiguous function calls. */
1247 
1249 {
1250 
1251  std::vector<SDGLibraryExtender *> libraryExtenders;
1252  public:
1254  {
1255  if (le!=NULL)
1256  libraryExtenders.push_back(le);
1257  }
1258  SystemDependenceGraph(){debug=false;}
1259  SgNode *getMainFunction();
1260  void createSafeConfiguration(SgFunctionDeclaration *fDef);
1261  bool isKnownLibraryFunction(SgFunctionDeclaration *fDec);
1262  void createConnectionsForLibaryFunction(SgFunctionDeclaration *fDec);
1263  void parseProject(SgProject *project);
1264 
1266  void performInterproceduralAnalysis();
1267  void computeSummaryEdges();
1268  void cleanUp(std::set<SgNode*> preserve);
1269 
1270  /* ! \brief adds a PDG to our SDG
1271 
1272  Params: - FunctionDependenceGraph * pdg: The PDG to add to the SDG
1273 
1274  Side effects: Merges PDG in using _mergeGraph. Maps function PDG
1275  represents to the PDG itself in _funcs_map. */
1276  void addFunction(FunctionDependenceGraph * pdg);
1277  void createFunctionStub(InterproceduralInfo * info);
1278 
1279  void addFunction(ControlDependenceGraph * cdg, DataDependenceGraph * ddg);
1280 
1282  {
1283  if (interproceduralInformation.count(dec )>0)
1284  {
1285  return (interproceduralInformation[dec]);
1286  }
1287  else
1288  return NULL;
1289  }
1291  {
1292  if (interproceduralInformation.count( info->getFunctionDeclaration() )>0)
1293  // if (interproceduralInformation.count( info->foo() )>0)
1294  std::cerr<<"Warning: Interprocedural Information for this function already available"<<std::endl;
1295  else
1296  {
1297  interproceduralInformation[info->getFunctionDeclaration()]=info;
1298  interproceduralInformationList.push_back(info);
1299  }
1300  }
1301  void doInterproceduralConnections(InterproceduralInfo * ii);
1302 
1303 
1304 
1305  /* ! \brief links all the functions together
1306 
1307  After the PDGs have been merged into the SDG, each call site is linked
1308  to the PDG associated with the function that it calls: - The callsite
1309  node is linked to the entry node with a "call" edge - Each actual-in
1310  node is linked to the formal-in node with a "call" edge - Each
1311  formal-out node is linked to the actual-out node with a "return" edge */
1312  void process();
1313 
1314  /* ! \brief performs a backwards slice with slicing criterion node
1315 
1316  getSlice is defined according to the paper by Horowitz et al. as a two
1317  phase operation. The first operation does backwards reachability to
1318  "mark" nodes while not traversing return edges. Thus it ignores functin
1319  calls. The second phase does backwards reachability from all marked
1320  nodes while not traversing call edges. Thus it ignores calling
1321  functions. The final set of reachable nodes is the interprocedural
1322  slice. */
1323  virtual std::set < DependenceNode * >getSlice(DependenceNode * node);
1324 
1325  /* ! \brief retrieve the PDGs in the graph
1326 
1327  Returns: a set of FunctionDependenceGraph that comprise the
1328  SystemDependenceGraph */
1329  std::set < FunctionDependenceGraph * >getPDGs();
1330 
1331  private:
1332  Rose_STL_Container<InterproceduralInfo *>interproceduralInformationList;
1333  std::map<SgFunctionDeclaration *,InterproceduralInfo *> interproceduralInformation;
1334 
1335  /* ! \brief links the call sites in PDG to the PDGs of the function it
1336  calls
1337 
1338  Params: - FunctionDependenceGraph * pdg: the PDG whose call sites we
1339  want to process
1340 
1341  Side effects: The interprocedural nodes for the call sites are linked
1342  to the interprocedural nodes for the appropriate entry sites */
1343  void _processFunction(FunctionDependenceGraph * pdg);
1344  bool debug;
1345 
1346  /* ! \brief get a list of functions that funcCall could be referring to
1347 
1348  Params: - SgFunctionCallExp * funcCall: the function call we are
1349  analyzing
1350 
1351  Return: A list of SgFunctionDeclarations that funcCall could
1352  potentially call.
1353 
1354  */
1355  std::vector<InterproceduralInfo*> getPossibleFuncs(SgFunctionCallExp * funcCall);
1356  Rose_STL_Container < SgFunctionDeclaration * >_getPossibleFuncs(SgFunctionCallExp * funcCall);
1357 
1358  // ! a mapping of funciton declarations to the FunctionDependenceGraph
1359  // that represents them
1360  //CI (01/12/2007): This map is only used to access the Interprocedural information,
1361  // rewrite to use only interprocedural-information on the way
1362  std::map < SgFunctionDeclaration *, FunctionDependenceGraph * >_funcs_map;
1363  //CI (01/12/2007): add
1364  std::map <SgFunctionDeclaration *, InterproceduralInfo * > functionToInterfunctionalMap;
1365 
1366 };
1367 
1368 #endif