[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