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
00025
00026
00027 #include "ClassHierarchyGraph.h"
00028
00029
00030
00031 namespace CallTargetSet
00032 {
00033 typedef Rose_STL_Container<SgFunctionDeclaration *> SgFunctionDeclarationPtrList;
00034 typedef Rose_STL_Container<SgClassDefinition *> SgClassDefinitionPtrList;
00035
00036 std::vector<SgFunctionDeclaration*> solveFunctionPointerCall ( SgPointerDerefExp *, SgProject * );
00037
00038
00039 std::vector<SgFunctionDeclaration*> solveMemberFunctionPointerCall ( SgExpression *,ClassHierarchyWrapper * );
00040 Rose_STL_Container<SgFunctionDeclaration*> solveFunctionPointerCallsFunctional(SgNode* node, SgFunctionType* functionType );
00041
00042
00043
00044 std::vector<SgFunctionDeclaration*> solveMemberFunctionCall (
00045 SgClassType *, ClassHierarchyWrapper *, SgMemberFunctionDeclaration *, bool , bool includePureVirtualFunc = false );
00046
00051 std::vector<SgFunctionDeclaration*> solveConstructorInitializer ( SgConstructorInitializer* sgCtorInit);
00052
00053
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
00075
00076
00077 void getExpressionsForDefinition(SgFunctionDefinition* targetDef,
00078 ClassHierarchyWrapper* classHierarchy,
00079 Rose_STL_Container<SgExpression*>& exps);
00080
00081
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
00125
00126
00127 boost::unordered_map<SgFunctionDeclaration*, SgGraphNode*>& getGraphNodesMapping(){ return graphNodes; }
00128
00129 private:
00130 SgProject *project;
00131 SgIncidenceDirectedGraph *graph;
00132
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
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
00162 while (i != allFunctions.end())
00163 {
00164 SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i);
00165 ROSE_ASSERT(functionDeclaration != NULL);
00166
00167
00168 if (isSgMemberFunctionDeclaration(functionDeclaration))
00169 {
00170
00171 SgDeclarationStatement *nonDefDeclInClass =
00172 isSgMemberFunctionDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
00173
00174 if (nonDefDeclInClass)
00175 functionDeclaration = isSgMemberFunctionDeclaration(nonDefDeclInClass);
00176 }
00177 else
00178 {
00179
00180 SgFunctionDeclaration *nonDefDecl = isSgFunctionDeclaration(functionDeclaration->get_firstNondefiningDeclaration());
00181 if (nonDefDecl)
00182 functionDeclaration = nonDefDecl;
00183 }
00184
00185
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
00197 SgIncidenceDirectedGraph *returnGraph = new SgIncidenceDirectedGraph();
00198 ROSE_ASSERT(returnGraph != NULL);
00199
00200
00201
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
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
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
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
00281 #endif
00282