[cfe-commits] r75873 - in /cfe/trunk: include/clang/Analysis/CallGraph.h lib/Analysis/CallGraph.cpp
Zhongxing Xu
xuzhongxing at gmail.com
Wed Jul 15 17:54:13 PDT 2009
Author: zhongxingxu
Date: Wed Jul 15 19:54:12 2009
New Revision: 75873
URL: http://llvm.org/viewvc/llvm-project?rev=75873&view=rev
Log:
Commit the initial implementation of call graph building.
Added:
cfe/trunk/include/clang/Analysis/CallGraph.h
cfe/trunk/lib/Analysis/CallGraph.cpp
Added: cfe/trunk/include/clang/Analysis/CallGraph.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/CallGraph.h?rev=75873&view=auto
==============================================================================
--- cfe/trunk/include/clang/Analysis/CallGraph.h (added)
+++ cfe/trunk/include/clang/Analysis/CallGraph.h Wed Jul 15 19:54:12 2009
@@ -0,0 +1,84 @@
+//== CallGraph.cpp - Call graph building ------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defined the CallGraph and CallGraphNode classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH
+#define LLVM_CLANG_ANALYSIS_CALLGRAPH
+
+#include "clang/Index/ASTLocation.h"
+#include "clang/Index/Entity.h"
+#include "clang/Index/Program.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "llvm/ADT/DenseMap.h"
+#include <vector>
+
+namespace clang {
+
+class CallGraphNode {
+ idx::Entity *F;
+ typedef std::pair<idx::ASTLocation, CallGraphNode*> CallRecord;
+ std::vector<CallRecord> CalledFunctions;
+
+public:
+ CallGraphNode(idx::Entity *f) : F(f) {}
+
+ typedef std::vector<CallRecord>::iterator iterator;
+ typedef std::vector<CallRecord>::const_iterator const_iterator;
+
+ iterator begin() { return CalledFunctions.begin(); }
+ iterator end() { return CalledFunctions.end(); }
+ const_iterator begin() const { return CalledFunctions.begin(); }
+ const_iterator end() const { return CalledFunctions.end(); }
+
+ void addCallee(idx::ASTLocation L, CallGraphNode *Node) {
+ CalledFunctions.push_back(std::make_pair(L, Node));
+ }
+
+ const char *getName(ASTContext &Ctx) { return F->getName(Ctx); }
+};
+
+class CallGraph {
+ /// Program manages all Entities.
+ idx::Program Prog;
+
+ typedef llvm::DenseMap<idx::Entity *, CallGraphNode *> FunctionMapTy;
+
+ /// FunctionMap owns all CallGraphNodes.
+ FunctionMapTy FunctionMap;
+
+ /// CallerCtx maps a caller to its ASTContext.
+ llvm::DenseMap<CallGraphNode *, ASTContext *> CallerCtx;
+
+public:
+ ~CallGraph();
+
+ typedef FunctionMapTy::iterator iterator;
+ typedef FunctionMapTy::const_iterator const_iterator;
+
+ iterator begin() { return FunctionMap.begin(); }
+ iterator end() { return FunctionMap.end(); }
+ const_iterator begin() const { return FunctionMap.begin(); }
+ const_iterator end() const { return FunctionMap.end(); }
+
+ void addTU(ASTUnit &AST);
+
+ idx::Program &getProgram() { return Prog; }
+
+ CallGraphNode *getOrInsertFunction(idx::Entity *F);
+
+ void print(llvm::raw_ostream &os);
+ void dump();
+};
+
+}
+
+#endif
Added: cfe/trunk/lib/Analysis/CallGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CallGraph.cpp?rev=75873&view=auto
==============================================================================
--- cfe/trunk/lib/Analysis/CallGraph.cpp (added)
+++ cfe/trunk/lib/Analysis/CallGraph.cpp Wed Jul 15 19:54:12 2009
@@ -0,0 +1,121 @@
+//== CallGraph.cpp - Call graph building ------------------------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defined the CallGraph and CGBuilder classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/CallGraph.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/StmtVisitor.h"
+
+using namespace clang;
+using namespace idx;
+
+namespace {
+class CGBuilder : public StmtVisitor<CGBuilder> {
+
+ CallGraph &G;
+ FunctionDecl *FD;
+
+ Entity *CallerEnt;
+
+ CallGraphNode *CallerNode;
+
+public:
+ CGBuilder(CallGraph &g, FunctionDecl *fd, Entity *E, CallGraphNode *N)
+ : G(g), FD(fd), CallerEnt(E), CallerNode(N) {}
+
+ void VisitCompoundStmt(CompoundStmt *S) {
+ VisitChildren(S);
+ }
+
+ void VisitCallExpr(CallExpr *CE);
+
+ void VisitChildren(Stmt *S) {
+ for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I != E;++I)
+ if (*I)
+ static_cast<CGBuilder*>(this)->Visit(*I);
+ }
+};
+}
+
+void CGBuilder::VisitCallExpr(CallExpr *CE) {
+ Expr *Callee = CE->getCallee();
+
+ if (CastExpr *CE = dyn_cast<CastExpr>(Callee))
+ Callee = CE->getSubExpr();
+
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Callee)) {
+ Decl *D = DRE->getDecl();
+ if (FunctionDecl *CalleeDecl = dyn_cast<FunctionDecl>(D)) {
+
+ Entity *Ent = Entity::get(CalleeDecl, G.getProgram());
+
+ CallGraphNode *CalleeNode = G.getOrInsertFunction(Ent);
+
+ CallerNode->addCallee(ASTLocation(FD, CE), CalleeNode);
+ }
+ }
+}
+
+CallGraph::~CallGraph() {
+ if (!FunctionMap.empty()) {
+ for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
+ I != E; ++I)
+ delete I->second;
+ FunctionMap.clear();
+ }
+}
+
+void CallGraph::addTU(ASTUnit &AST) {
+ ASTContext &Ctx = AST.getASTContext();
+ DeclContext *DC = Ctx.getTranslationUnitDecl();
+
+ for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
+ I != E; ++I) {
+
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
+ if (FD->isThisDeclarationADefinition()) {
+ // Set caller's ASTContext.
+ Entity *Ent = Entity::get(FD, Prog);
+ CallGraphNode *Node = getOrInsertFunction(Ent);
+ CallerCtx[Node] = &Ctx;
+
+ CGBuilder builder(*this, FD, Ent, Node);
+ builder.Visit(FD->getBody());
+ }
+ }
+ }
+}
+
+CallGraphNode *CallGraph::getOrInsertFunction(Entity *F) {
+ CallGraphNode *&Node = FunctionMap[F];
+ if (Node)
+ return Node;
+
+ return Node = new CallGraphNode(F);
+}
+
+void CallGraph::print(llvm::raw_ostream &os) {
+ for (iterator I = begin(), E = end(); I != E; ++I) {
+ ASTContext &Ctx = *CallerCtx[I->second];
+ os << "function: " << I->first->getName(Ctx) << " calls:\n";
+ for (CallGraphNode::iterator CI = I->second->begin(), CE = I->second->end();
+ CI != CE; ++CI) {
+ os << " " << CI->second->getName(Ctx);
+ }
+ os << '\n';
+ }
+}
+
+void CallGraph::dump() {
+ print(llvm::errs());
+}
More information about the cfe-commits
mailing list