CallGraph.h

Go to the documentation of this file.
00001 
00002 #ifndef CALL_GRAPH_H
00003 #define CALL_GRAPH_H
00004 
00005 #include <AstInterface.h>
00006 #include <GraphDotOutput.h>
00007 #include <VirtualGraphCreate.h>
00008 
00009 #include "AstDiagnostics.h"
00010 
00011 #include <sstream>
00012 #include <iostream>
00013 #include <string>
00014 #include <functional>
00015 #include <queue>
00016 #include <boost/foreach.hpp>
00017 #include <boost/unordered_map.hpp>
00018 
00019 class FunctionData;
00020 
00021 typedef Rose_STL_Container<SgFunctionDeclaration *> SgFunctionDeclarationPtrList;
00022 typedef Rose_STL_Container<SgClassDefinition *> SgClassDefinitionPtrList;
00023 
00024 // DQ (1/31/2006): Changed name and made global function type symbol table a static data member.
00025 // extern SgFunctionTypeTable Sgfunc_type_table;
00026 // This header has to be here since it uses type SgFunctionDeclarationPtrList 
00027 #include "ClassHierarchyGraph.h"
00028 
00029 
00030 //AS(090707) Added the CallTargetSet namespace to replace the CallGraphFunctionSolver class
00031 namespace CallTargetSet
00032 {
00033   typedef Rose_STL_Container<SgFunctionDeclaration *> SgFunctionDeclarationPtrList;
00034   typedef Rose_STL_Container<SgClassDefinition *> SgClassDefinitionPtrList;
00035   // returns the list of declarations of all functions that may get called via the specified pointer
00036   std::vector<SgFunctionDeclaration*> solveFunctionPointerCall ( SgPointerDerefExp *, SgProject * );
00037 
00038   // returns the list of declarations of all functions that may get called via a member function pointer
00039   std::vector<SgFunctionDeclaration*> solveMemberFunctionPointerCall ( SgExpression *,ClassHierarchyWrapper * );
00040   Rose_STL_Container<SgFunctionDeclaration*> solveFunctionPointerCallsFunctional(SgNode* node, SgFunctionType* functionType );
00041 
00042   // returns the list of declarations of all functions that may get called via a
00043   // member function (non/polymorphic) call
00044   std::vector<SgFunctionDeclaration*> solveMemberFunctionCall ( 
00045           SgClassType *, ClassHierarchyWrapper *, SgMemberFunctionDeclaration *, bool , bool includePureVirtualFunc = false );
00046 
00051   std::vector<SgFunctionDeclaration*> solveConstructorInitializer ( SgConstructorInitializer* sgCtorInit);
00052 
00053   // Populates functionList with Properties of all functions that may get called.
00054   void getPropertiesForExpression(SgExpression* exp,
00055                                     ClassHierarchyWrapper* classHierarchy,
00056                                     Rose_STL_Container<SgFunctionDeclaration*>& propList,
00057                                     bool includePureVirtualFunc = false);
00058 
00063   void getDefinitionsForExpression(SgExpression* exp,
00064                                     ClassHierarchyWrapper* classHierarchy,
00065                                     Rose_STL_Container<SgFunctionDefinition*>& calleeList);
00066 
00069   void getDeclarationsForExpression(SgExpression* exp,
00070                                     ClassHierarchyWrapper* classHierarchy,
00071                                     Rose_STL_Container<SgFunctionDeclaration*>& calleeList,
00072                                     bool includePureVirtualFunc = false);
00073 
00074   // Gets a vector of SgExpressions that are associated with the current SgFunctionDefinition.
00075   // This functionality is necessary for virtual, interprocedural control flow graphs. However, 
00076   // it is costly and should be used infrequently (or optimized!).
00077   void getExpressionsForDefinition(SgFunctionDefinition* targetDef, 
00078                                    ClassHierarchyWrapper* classHierarchy,
00079                                    Rose_STL_Container<SgExpression*>& exps);
00080   
00081   // Gets the latest implementation of the member function from the ancestor hierarchy
00082   SgFunctionDeclaration * getFirstVirtualFunctionDefinitionFromAncestors(SgClassType *crtClass, 
00083                                    SgMemberFunctionDeclaration *memberFunctionDeclaration, 
00084                                    ClassHierarchyWrapper *classHierarchy);
00085   
00086 };
00087 
00088 class FunctionData
00089 {
00090   public:
00091 
00092     bool hasDefinition;
00093 
00094     bool isDefined (); 
00095 
00096     FunctionData(SgFunctionDeclaration* functionDeclaration, SgProject *project, ClassHierarchyWrapper * );
00097 
00099     Rose_STL_Container<SgFunctionDeclaration *> functionList;
00100 
00101     SgFunctionDeclaration* functionDeclaration;
00102 
00103     Rose_STL_Container<SgMemberFunctionDeclaration*> *findPointsToVirtualFunctions ( SgMemberFunctionDeclaration * );
00104     bool compareFunctionDeclarations( SgFunctionDeclaration *f1, SgFunctionDeclaration *f2 );
00105 };
00106 
00108 struct dummyFilter : public std::unary_function<bool,SgFunctionDeclaration*>
00109 {
00110   bool operator() (SgFunctionDeclaration* node) const;
00111 }; 
00112 
00113 class CallGraphBuilder
00114 {
00115   public:
00116     CallGraphBuilder( SgProject *proj);
00118     void buildCallGraph();
00120     template<typename Predicate>
00121       void buildCallGraph(Predicate pred);
00123     SgIncidenceDirectedGraph *getGraph(); 
00124     //void classifyCallGraph();
00125 
00126     //We map each function to the corresponding graph node
00127     boost::unordered_map<SgFunctionDeclaration*, SgGraphNode*>& getGraphNodesMapping(){ return graphNodes; }
00128 
00129   private:
00130     SgProject *project;
00131     SgIncidenceDirectedGraph *graph;
00132     //We map each function to the corresponding graph node
00133     boost::unordered_map<SgFunctionDeclaration*, SgGraphNode*> graphNodes;
00134 
00135 };
00137 void GenerateDotGraph ( SgIncidenceDirectedGraph *graph, std::string fileName );
00138 
00139 class GetOneFuncDeclarationPerFunction :  public std::unary_function<SgNode*, Rose_STL_Container<SgNode*> >
00140 {
00141   public:
00142     result_type operator()(SgNode* node );
00143 };
00144 
00145 template<typename Predicate>
00146   void
00147 CallGraphBuilder::buildCallGraph(Predicate pred)
00148 {
00149     Rose_STL_Container<FunctionData> callGraphData;
00150 
00151     //AS (09/23/06) Query the memory pool instead of subtree of project
00152     VariantVector vv(V_SgFunctionDeclaration);
00153     GetOneFuncDeclarationPerFunction defFunc;
00154     Rose_STL_Container<SgNode *> allFunctions = NodeQuery::queryMemoryPool(defFunc, &vv);
00155 
00156     ClassHierarchyWrapper classHierarchy(project);
00157     Rose_STL_Container<SgNode *>::iterator i = allFunctions.begin();
00158 
00159     graphNodes.clear();
00160     
00161     //Iterate through all the functions found and resolve all the call expressions in each function with a body
00162     while (i != allFunctions.end())
00163     {
00164         SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i);
00165         ROSE_ASSERT(functionDeclaration != NULL);
00166 
00167         // determining the in-class declaration
00168         if (isSgMemberFunctionDeclaration(functionDeclaration))
00169         {
00170             // always saving the in-class declaration, so we need to find that one
00171             SgDeclarationStatement *nonDefDeclInClass =
00172                     isSgMemberFunctionDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
00173             // functionDeclaration is outside the class (so it must have a definition)
00174             if (nonDefDeclInClass)
00175                 functionDeclaration = isSgMemberFunctionDeclaration(nonDefDeclInClass);
00176         }
00177         else
00178         {
00179             // we need to have only one declaration for regular functions as well
00180             SgFunctionDeclaration *nonDefDecl = isSgFunctionDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
00181             if (nonDefDecl)
00182                 functionDeclaration = nonDefDecl;
00183         }
00184 
00185         //AS(032806) Filter out functions based on criteria in predicate
00186         if (pred(functionDeclaration) == true)
00187         {
00188             FunctionData functionData(functionDeclaration, project, &classHierarchy);
00189             ROSE_ASSERT(functionData.functionDeclaration != NULL);
00190 
00191             callGraphData.push_back(functionData);
00192         }
00193         i++;
00194     }
00195 
00196     // Build the graph
00197     SgIncidenceDirectedGraph *returnGraph = new SgIncidenceDirectedGraph();
00198     ROSE_ASSERT(returnGraph != NULL);
00199 
00200     
00201     //Instantiate all the nodes in the graph, one for each function we found
00202     BOOST_FOREACH(FunctionData& currentFunction, callGraphData)
00203     {
00204         std::string functionName;
00205         ROSE_ASSERT(currentFunction.functionDeclaration);
00206         functionName = currentFunction.functionDeclaration->get_qualified_name().getString();
00207 
00208         // Generate a unique name to test against later
00209         SgFunctionDeclaration* id = currentFunction.functionDeclaration;
00210         SgDeclarationStatement *nonDefDeclInClass = isSgMemberFunctionDeclaration(id->get_firstNondefiningDeclaration());
00211         if (nonDefDeclInClass)
00212             ROSE_ASSERT(id == nonDefDeclInClass);
00213         SgGraphNode* graphNode = new SgGraphNode(functionName);
00214         graphNode->set_SgNode(currentFunction.functionDeclaration);
00215 
00216         if (SgProject::get_verbose() >= DIAGNOSTICS_VERBOSE_LEVEL)
00217         {
00218             std::cout << "Function: "
00219                     << currentFunction.functionDeclaration->get_scope()->get_qualified_name().getString() +
00220                     currentFunction.functionDeclaration->get_mangled_name().getString()
00221                     << " has declaration " << currentFunction.isDefined() << "\n";
00222         }
00223         
00224         graphNodes[currentFunction.functionDeclaration] = graphNode;
00225 
00226         returnGraph->addNode(graphNode);
00227     }
00228 
00229     if (SgProject::get_verbose() >= DIAGNOSTICS_VERBOSE_LEVEL)
00230         std::cout << "NodeList size: " << graphNodes.size() << "\n";
00231 
00232     //We have all the nodes. Now instantiate all the graph edges
00233     int totEdges = 0;
00234     BOOST_FOREACH(FunctionData& currentFunction, callGraphData)
00235     {
00236         ROSE_ASSERT(currentFunction.functionDeclaration != NULL);
00237         
00238         boost::unordered_map<SgFunctionDeclaration*, SgGraphNode*>::iterator iter
00239                 = graphNodes.find(currentFunction.functionDeclaration);
00240         ROSE_ASSERT(iter != graphNodes.end());
00241         SgGraphNode* startingNode = iter->second;
00242 
00243         Rose_STL_Container<SgFunctionDeclaration*> & functionCallees = currentFunction.functionList;
00244 
00245         BOOST_FOREACH(SgFunctionDeclaration* calleeDeclaration, functionCallees)
00246         {
00247                         ROSE_ASSERT(calleeDeclaration != NULL);
00248 
00249                         //This function has been filtered out
00250                         if (pred(calleeDeclaration) == false)
00251                         {
00252                                 continue;
00253                         }
00254 
00255                         iter = graphNodes.find(calleeDeclaration);
00256                         ROSE_ASSERT(iter != graphNodes.end());
00257                         SgGraphNode *endNode = iter->second;
00258 
00259                         if (returnGraph->checkIfDirectedGraphEdgeExists(startingNode, endNode) == false)
00260                         {
00261                                 ROSE_ASSERT(startingNode != NULL && endNode != NULL);
00262                                 returnGraph->addDirectedEdge(startingNode, endNode);
00263                         }
00264                         else if (SgProject::get_verbose() >= DIAGNOSTICS_VERBOSE_LEVEL)
00265                         {
00266                                 std::cout << "Did not add edge since it already exist" << std::endl;
00267                                 std::cout << "\tEndNode " << calleeDeclaration->get_name().str() << "\n";
00268                         }
00269 
00270             totEdges++;
00271         }
00272     }
00273     
00274     if (SgProject::get_verbose() >= DIAGNOSTICS_VERBOSE_LEVEL)
00275         std::cout << "Total number of edges: " << totEdges << "\n";
00276 
00277     graph = returnGraph;
00278 }
00279 
00280 // endif for CALL_GRAPH_H
00281 #endif
00282 

Generated on Wed May 16 06:17:53 2012 for ROSE by  doxygen 1.4.7