ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NEW_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
443  NodeType depType;
444  SgNode * sgNode;
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  virtual void writeDotAndHighlightAllowedEdgesOnly(char *filename, std::set<DependenceGraph::EdgeType> );
847 
848  protected:
849  // ! Maps a DependenceNode to a copy unique to this DependenceGraph
851  // ! Maps an SgNode to a DependenceNode unique to this DependenceGraph
853  std::map<SgNode*,DependenceNode*> sgNodeToDepNodeMap;
854  std::map<DependenceNode::NodeType,std::map<SgNode*,DependenceNode*> > nodeTypeToDepNodeMapMap;
855 
856  // ! The InterproceduralInfo associated with this DependenceGraph
858 
859  typedef std::pair < DependenceNode *, DependenceNode * >Edge;
860 
861  // ! a map from EdgeType to all the edges of that type
862  std::map < EdgeType, std::set < Edge > >edgeTypeMap;
863 
864 // DQ (8/30/2009): Debugging ROSE compiling ROSE (this statement does not compile using ROSE). The error is:
865 // sage_gen_be.C:5286: SgEnumDeclaration* sage_gen_enum_definition(a_type*, SgDeclarationStatement*&, DataRequiredForComputationOfSourcePostionInformation*): Assertion `forwardDeclaration->get_parent() != __null' failed.
866 #ifndef USE_ROSE
867 
868  // ! a map from an edge to all the variants of that edge in the graph
869  std::map < Edge, std::set < EdgeType > >edgeMap;
870 #else
871  std::map < Edge, std::set < int > >edgeMap;
872 #endif
873 
875  {
876  if (sgFD == NULL) return false;
877  else if (sgFD->get_definition() != NULL) return true;
878  else return false;
879  };
880 };
881 
882 
883 /* ! \class ControlDependenceGraph
884 
885  This class is a DependenceGraph which expresses control dependences for a
886  given procedure. Control dependences essentially link decision points in
887  CFGs with the nodes affected by those decisions. The implementation of this
888  class depends on the calculation of Dominator Trees and Dominance
889  Frontiers.
890 
891  If interprocedural analysis is specified (by passing in a non-null
892  InterproceduralInfo object), building this graph will also initialize the
893  InterproceduralInfo object by creating the required formal-in, formal-out,
894  actual-in, actual-out and entry nodes (as well as any required call nodes)
895  for the procedure, and creating the appropriate control dependences: - all
896  actual-in and actual-out nodes are control dependent on the call site - all
897  formal-in and formal-out nodes are control dependent on the entry node -
898  the call site node is control dependent on the DependenceNode representing
899  the function call.
900 
901 
902  The use of this class requires that DominanceFrontier.h exist. Also, the
903  use of this class requires linking against libDominance.
904 
905 */
906 
908 {
909 
910  public:
911 
912  /* ! \brief Contstructor for ControlDependenceGraph
913 
914  Params: - SgNode * head: The root of the AST that you want to build the
915  CDG for - InterproceduralInfo * ii: the InterproceduralInfo object for
916  storing interprocedural information
917 
918  Side effects: - initializes _interprocedural
919 
920  If ii is NULL, we assume that we are not doing interprocedural
921  analysis. Otherwise, we assume that ii is a newly allocated (but not
922  yet initialized) object. */
924 
925  /* ! \brief create a DependenceNode wrapping cnode
926 
927  Params: - ControlNode * cnode: The ControlNode we want to wrap in a
928  DependenceNode
929 
930  Return: If we have already wrapped this node, we return the existing
931  DependenceNode. Otherwise we create a new DependenceNode (of type
932  CONTROL) and return it.
933 
934  Side effects: If a new DependenceNode is created, cnode is mapped to it
935  by _cnode_map.
936 
937  */
938  // DependenceNode *createNodeC(ControlNode * cnode);
939  //DependenceNode *createNodeC(DominatorTreesAndDominanceFrontiers::ControlNode * cnode);
940 
941  //DependenceNode * getNode(SgNode * src);
942 
943  // ! calls establishEdge with EdgeType defaulted to CONTROL
944  /* virtual void establishEdge(DependenceNode * from, DependenceNode * to)
945  {
946  DependenceGraph::establishEdge(from, to, CONTROL);
947  }*/
948  void computeInterproceduralInformation(InterproceduralInfo * ii);
949  void computeAdditionalFunctioncallDepencencies();
950  private:
951 
952  Rose_STL_Container < SgNode * > functionCalls;
953  void processDependence(int aID,int bID);
954  void createSyntacticDependencies();
955  // control-flow-graph for this function
956  SliceCFGNode source,sink;
957 
958  SliceDominatorTree dominatorTree;
959 
960  void addDependence(int source, int to,EdgeType edge=CONTROL);
961 
962  // SliceDominanceFrontier dominanceFrontier;
963  // ! The root of the AST that the ControlDependenceGraph represents
964  SgNode *head;
965  SgNode *decl,*def;
966 
967  void buildCDG();
968 
969 
970  //everzthing from here on is deprecated
971  // ! builds the CDG
972  void _buildCDG();
973 
974  // ! if we're performing interprocedural analysis, initializes the
975  // InterproceduralInfo object
976  void _buildInterprocedural();
977 
978  // ! DEPRECATED. Not used anymore.
979  void _addDependence(SgNode * from, SgNode * to);
980 
981 
982  // ! The control flow graph for the AST
983  // DominatorTreesAndDominanceFrontiers::ControlFlowGraph * _cfg;
984  // ! The dominator tree for the CFG
985  // DominatorTreesAndDominanceFrontiers::DominatorTree * _dt;
986  // ! The dominance frontier for nodes in the CFG
987  // DominatorTreesAndDominanceFrontiers::DominanceFrontier * _df;
988 
989  // ! Maps ControlNodes (nodes in the CFG) to DependenceNodes unique to
990  // this CDG
991  // std::map < DominatorTreesAndDominanceFrontiers::ControlNode *, DependenceNode * >_cnode_map;
992 };
993 
994 /* ! \class DataDependenceGraph
995 
996  This class is a DependenceGraph which expresses data dependences for a
997  given procedure. Data dependences link statement that define variables with
998  the statements that may use those definitions. The implementation of this
999  class depends on the calculation of DefUseChains, and so must link against
1000  librose.
1001 
1002  If interprocedural analysis is specified (by passing in a non-null
1003  InterproceduralInfo object which has been initialized by
1004  ControlDependenceGraph), building this graph will create the appropriate
1005  data dependences: - if a statement uses a variable defined in the parameter
1006  list for the function, it is data dependent on the formal-in node - if a
1007  statement defs a variable used as a function parameter in a call, the
1008  actual-in node for the parameter is data dependent on the statement - if a
1009  statement uses a variable returned from a function, it is data dependent on
1010  the actual-out node - if a statement is a return statement, the formal-out
1011  return is data dependent on it.
1012 
1013  @todo Currently, there is no way to link defs that reach the end of the
1014  function (other than return statements) to the appropriate actual-out nodes
1015  (in the case of pass-by-reference arguments). */
1016 
1018 {
1019 
1020  public:
1021 
1022  /* ! \brief Contstructor for DataDependenceGraph
1023 
1024  Params: - SgNode * head: The root of the AST that you want to build the
1025  DDG for - InterproceduralInfo * ii: the InterproceduralInfo object for
1026  storing interprocedural information
1027 
1028  Side effects: - adds data dependence edges to nodes from
1029  _interprocedural
1030 
1031  If ii is NULL, we assume that we are not doing interprocedural
1032  analysis. Otherwise, we assume that ii is an InterproceduralInfo object
1033  that has been initialized by the CDG for the same procedure */
1034 #ifdef NEWDU
1035  DataDependenceGraph(SgNode * head,EDefUse * du, InterproceduralInfo * ii = NULL);
1036 #else
1037  DataDependenceGraph(SgNode * head, InterproceduralInfo * ii = NULL);
1038 #endif
1039 
1040  // ! calls establishEdge with EdgeType defaulted to DATA
1041  /* virtual void establishEdge(DependenceNode * from, DependenceNode * to)
1042  {
1043  DependenceGraph::establishEdge(from, to, DATA);
1044  }*/
1045  void computeInterproceduralInformation(InterproceduralInfo * ii);
1046  private:
1047 #ifdef NEWDU
1048  EDefUse * defuse;
1049 #endif
1050 
1052  SgFunctionDefinition * functionDef;
1053  SgFunctionDeclaration *functionDecl;
1054  // ! builds the def-use chains for the procedure
1055  void _buildDefUseChains(SgFunctionDefinition * fD);
1056 
1057  // ! uses def-use chains to build the data dependence graph
1058  void buildDDG();
1059  void _buildDDG();
1060 
1061  // ! if doing interprocedural, adds the data dependences from return
1062  // statements to formal-out statements
1063  void _processReturns();
1064 
1065  /* ! \brief Finds the function argument that use is in
1066 
1067  Params: - SgNode * &funcArg: Placeholder for function argument that use
1068  is in - SgNode * use: The variable use we are trying to find the
1069  argument for
1070 
1071  Return: If use was in a function argument, returns the function call
1072  expression the argument was in. Otherwise returns NULL
1073 
1074  Side effects: if returning non-NULL, funcArg is the function argument
1075  that use was in. */
1076  SgFunctionCallExp *_findArgExprFromRef(SgNode * &funcArg, SgNode * use);
1077 
1078  // ! The function that we are building the DDG for
1079  SgFunctionDefinition *_head;
1080 
1081  // ! The def use chains for the function
1082  DefaultDUchain _defuse;
1083 
1084 };
1085 
1086 /* ! \class MergedDependenceGraph
1087 
1088  This class provides a mechanism for merging together multiple
1089  DependenceGraphs. It also provides a mechanism for getting backwards
1090  reachable nodes given a specific start node and using specified edge types.
1091  This can be called by the abstract function getSlice to create specific
1092  types of slices (i.e. intraprocedural or interprocedural).
1093 
1094 */
1096 {
1097 
1098  public:
1099 
1100  /* ! \brief creates a new dependence node that reflects the argument (not
1101  a direct copy)
1102 
1103  Params: - DependenceNode * node: The node we want to make a "copy" of
1104 
1105  Return: If we've already "copied" the node, return the existing
1106  DependenceNode. Otherwise create a new one.
1107 
1108  Side effects: calls createNode appropriately to perform "copies," so
1109  _sgnode_map or _depend_map may be updated.
1110 
1111  If the node we are adding is an interprocedural node, we want to copy
1112  the _interproc pointer, not node itself. If it's an SgNode, we want to
1113  build the DependenceNode around that, as opposed to node. If it's
1114  neither, we just copy the argument. */
1115  DependenceNode * _importNode(DependenceNode * node);
1116 
1117  /* ! \brief creates a backward slice starting from node
1118 
1119  Params: - SgNode * node: the slicing criterion
1120 
1121  Return: returns a set of SgNodes which belong in the slice with slicing
1122  criterion node.
1123 
1124  This function calls getSlice, and prunes the returned values to find
1125  just the SgNodes. */
1126  std::set < SgNode * >slice(SgNode * node);
1127 
1128  /* ! \brief creates a backward slice starting from node
1129 
1130  Params: - DependenceNode * node: the slicing criterion
1131 
1132  Return: returns a set of DependenceNodes which belong in the slice with
1133  slicing criterion node.
1134 
1135  This is a more general version of slice, which operates on any
1136  DependenceNode. */
1137  virtual std::set < DependenceNode * >getSlice(DependenceNode * node) = 0;
1138 
1139  protected:
1140 
1141  /* ! \brief performs a backwards reachability analysis starting from nodes
1142  in start
1143 
1144  Params: - set<DependenceNode *> start: the starting nodes for the
1145  backwards reachability analysis - int edgeTypesToFollow: a bit-vector
1146  whose set bits indicate the types of edges to consider for
1147  reachability. */
1148  std::set < DependenceNode * >_getReachable(std::set < DependenceNode * >start,
1149  int edgeTypesToFollow = 0);
1150 
1151  /* ! \brief merges graph into the current MergedDependenceGraph
1152 
1153  Params: - DependenceGraph * graph: the DependenceGraph we want to merge
1154  into the current graph
1155 
1156  Side effects: Any new nodes and edges from graph are added to the
1157  MergedDependenceGraph */
1158  void _mergeGraph(DependenceGraph * graph);
1159  void mergeGraph(DependenceGraph * graph);
1160 
1161 };
1162 
1163 /* ! \class FunctionDependenceGraph
1164 
1165  This is a MergedDependenceGraph which merges a ControlDependenceGraph and a
1166  DataDependenceGraph for a specific procedure, thus representing a complete
1167  DependenceGraph for one procedure. If we are planning on doing
1168  interprocedural analysis (i.e. we've passed in a non-null
1169  InterproceduralInfo object), then we also create summary edges between the
1170  actual-in nodes for a call and the appropriate actual-out nodes.
1171 
1172  @todo Right now, we assume that the function will have no side-effects, and
1173  simply create a summary between all the actual-in nodes and the actual-out
1174  node representing the return. This should be extended to create real
1175  summary edges as defined in the paper by Horwitz et al. However, because we
1176  can't correctly handle defs that reach the end of functions, we can't
1177  properly summarize, and so we skip this for now.
1178 
1179 */
1180 
1182 {
1183 
1184  public:
1185  /* ! \brief Constructor for FunctionDependenceGraph, initialized with the
1186  CDG and DDG for the function.
1187 
1188  Params: - ControlDependenceGraph * cdg: a previously built CDG for the
1189  function - DataDependenceGraph * ddg: a previously build DDG for the
1190  function - InterproceduralInfo * ii: If NULL, we aren't doing
1191  interprocedural. Otherwise, the fully initialized InterproceduralInfo
1192  object for the function.
1193 
1194  */
1196  InterproceduralInfo * ii = NULL);
1197 
1198  /* ! \brief gets a slice with slicing criterion node
1199 
1200  This simply does a backwards reachability across all edges to produce
1201  the slice. */
1202  virtual std::set < DependenceNode * >getSlice(DependenceNode * node);
1203 
1204  private:
1205 
1207  void completeFDG();
1208 
1209  // ! DEPRECATED not used anymore
1210  void _addCDG();
1211  // ! DEPRECATED not used anymore
1212  void _mergeDDG();
1213 
1214  /* ! \brief creates summary edges for interprocedural analysis
1215 
1216  Currently, this simply points all the actual-in edges of a call to the
1217  actual-out return statement. This means we assume two things: # All
1218  functions are pass-by-value (so actual-out nodes for parameters are
1219  irrelevant) # Every parameter in the function is relevant (there are no
1220  unused arguments).
1221 
1222  @todo Should replace with attribute-grammar method for creating summary
1223  edges (see Horwitz et al). There is a preliminary start at writing the
1224  classes required to do this in the subdirectory summary/. However it is
1225  not complete and possibly has some structural issues which would
1226  require the entire thing to be rewritten. */
1227  void _summarize();
1228 
1229  // ! The ControlDependenceGraph for the function
1230  ControlDependenceGraph *_cdg;
1231  // ! The DataDependenceGraph for the function
1232  DataDependenceGraph *_ddg;
1233 
1234 };
1235 
1236 /* ! \class SystemDependenceGraph
1237 
1238  This class is a MergedGraph which merges together FunctionDependenceGraphs
1239  representing all procedures in the program. It assumes that the merged
1240  FunctionDependenceGraphs have defined InterproceduralInfo objects. A slice
1241  performed on this graph is an interprocedural slice as defined in the paper
1242  by Horwitz et al.
1243 
1244  @todo _getPossibleFuncs simply assumes that the AST correctly resolves
1245  every SgFunctionCallExp to a specific SgFunctionDeclaration with an
1246  existing SgFunctionDefinition. This should be redone to take advantage of
1247  call graph analysis, which will let us slice codes which have more
1248  ambiguous function calls. */
1249 
1251 {
1252 
1253  std::vector<SDGLibraryExtender *> libraryExtenders;
1254  public:
1256  {
1257  if (le!=NULL)
1258  libraryExtenders.push_back(le);
1259  }
1260  SystemDependenceGraph(){debug=false;}
1261  SgNode *getMainFunction();
1262  void createSafeConfiguration(SgFunctionDeclaration *fDef);
1263  bool isKnownLibraryFunction(SgFunctionDeclaration *fDec);
1264  void createConnectionsForLibaryFunction(SgFunctionDeclaration *fDec);
1265  void parseProject(SgProject *project);
1266 
1268  void performInterproceduralAnalysis();
1269  void computeSummaryEdges();
1270  void cleanUp(std::set<SgNode*> preserve);
1271 
1272  /* ! \brief adds a PDG to our SDG
1273 
1274  Params: - FunctionDependenceGraph * pdg: The PDG to add to the SDG
1275 
1276  Side effects: Merges PDG in using _mergeGraph. Maps function PDG
1277  represents to the PDG itself in _funcs_map. */
1278  void addFunction(FunctionDependenceGraph * pdg);
1279  void createFunctionStub(InterproceduralInfo * info);
1280 
1281  void addFunction(ControlDependenceGraph * cdg, DataDependenceGraph * ddg);
1282 
1284  {
1285  if (interproceduralInformation.count(dec )>0)
1286  {
1287  return (interproceduralInformation[dec]);
1288  }
1289  else
1290  return NULL;
1291  }
1293  {
1294  if (interproceduralInformation.count( info->getFunctionDeclaration() )>0)
1295  // if (interproceduralInformation.count( info->foo() )>0)
1296  std::cerr<<"Warning: Interprocedural Information for this function already available"<<std::endl;
1297  else
1298  {
1299  interproceduralInformation[info->getFunctionDeclaration()]=info;
1300  interproceduralInformationList.push_back(info);
1301  }
1302  }
1303  void doInterproceduralConnections(InterproceduralInfo * ii);
1304 
1305 
1306 
1307  /* ! \brief links all the functions together
1308 
1309  After the PDGs have been merged into the SDG, each call site is linked
1310  to the PDG associated with the function that it calls: - The callsite
1311  node is linked to the entry node with a "call" edge - Each actual-in
1312  node is linked to the formal-in node with a "call" edge - Each
1313  formal-out node is linked to the actual-out node with a "return" edge */
1314  void process();
1315 
1316  /* ! \brief performs a backwards slice with slicing criterion node
1317 
1318  getSlice is defined according to the paper by Horowitz et al. as a two
1319  phase operation. The first operation does backwards reachability to
1320  "mark" nodes while not traversing return edges. Thus it ignores functin
1321  calls. The second phase does backwards reachability from all marked
1322  nodes while not traversing call edges. Thus it ignores calling
1323  functions. The final set of reachable nodes is the interprocedural
1324  slice. */
1325  virtual std::set < DependenceNode * >getSlice(DependenceNode * node);
1326 
1327  /* ! \brief retrieve the PDGs in the graph
1328 
1329  Returns: a set of FunctionDependenceGraph that comprise the
1330  SystemDependenceGraph */
1331  std::set < FunctionDependenceGraph * >getPDGs();
1332 
1333  private:
1334  Rose_STL_Container<InterproceduralInfo *>interproceduralInformationList;
1335  std::map<SgFunctionDeclaration *,InterproceduralInfo *> interproceduralInformation;
1336 
1337  /* ! \brief links the call sites in PDG to the PDGs of the function it
1338  calls
1339 
1340  Params: - FunctionDependenceGraph * pdg: the PDG whose call sites we
1341  want to process
1342 
1343  Side effects: The interprocedural nodes for the call sites are linked
1344  to the interprocedural nodes for the appropriate entry sites */
1345  void _processFunction(FunctionDependenceGraph * pdg);
1346  bool debug;
1347 
1348  /* ! \brief get a list of functions that funcCall could be referring to
1349 
1350  Params: - SgFunctionCallExp * funcCall: the function call we are
1351  analyzing
1352 
1353  Return: A list of SgFunctionDeclarations that funcCall could
1354  potentially call.
1355 
1356  */
1357  std::vector<InterproceduralInfo*> getPossibleFuncs(SgFunctionCallExp * funcCall);
1358  Rose_STL_Container < SgFunctionDeclaration * >_getPossibleFuncs(SgFunctionCallExp * funcCall);
1359 
1360  // ! a mapping of funciton declarations to the FunctionDependenceGraph
1361  // that represents them
1362  //CI (01/12/2007): This map is only used to access the Interprocedural information,
1363  // rewrite to use only interprocedural-information on the way
1364  std::map < SgFunctionDeclaration *, FunctionDependenceGraph * >_funcs_map;
1365  //CI (01/12/2007): add
1366  std::map <SgFunctionDeclaration *, InterproceduralInfo * > functionToInterfunctionalMap;
1367 
1368 };
1369 
1370 #endif