• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //== CallGraph.cpp - Call graph building ------------------------*- C++ -*--==//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file defined the CallGraph and CGBuilder classes.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/Index/CallGraph.h"
15 
16 #include "clang/AST/ASTContext.h"
17 #include "clang/AST/StmtVisitor.h"
18 
19 #include "llvm/Support/GraphWriter.h"
20 
21 using namespace clang;
22 using namespace idx;
23 
24 namespace {
25 class CGBuilder : public StmtVisitor<CGBuilder> {
26 
27   CallGraph &G;
28   FunctionDecl *FD;
29 
30   Entity CallerEnt;
31 
32   CallGraphNode *CallerNode;
33 
34 public:
CGBuilder(CallGraph & g,FunctionDecl * fd,Entity E,CallGraphNode * N)35   CGBuilder(CallGraph &g, FunctionDecl *fd, Entity E, CallGraphNode *N)
36     : G(g), FD(fd), CallerEnt(E), CallerNode(N) {}
37 
VisitStmt(Stmt * S)38   void VisitStmt(Stmt *S) { VisitChildren(S); }
39 
40   void VisitCallExpr(CallExpr *CE);
41 
VisitChildren(Stmt * S)42   void VisitChildren(Stmt *S) {
43     for (Stmt::child_range I = S->children(); I; ++I)
44       if (*I)
45         static_cast<CGBuilder*>(this)->Visit(*I);
46   }
47 };
48 }
49 
VisitCallExpr(CallExpr * CE)50 void CGBuilder::VisitCallExpr(CallExpr *CE) {
51   if (FunctionDecl *CalleeDecl = CE->getDirectCallee()) {
52     Entity Ent = Entity::get(CalleeDecl, G.getProgram());
53     CallGraphNode *CalleeNode = G.getOrInsertFunction(Ent);
54     CallerNode->addCallee(ASTLocation(FD, CE), CalleeNode);
55   }
56 }
57 
CallGraph(Program & P)58 CallGraph::CallGraph(Program &P) : Prog(P), Root(0) {
59   ExternalCallingNode = getOrInsertFunction(Entity());
60 }
61 
~CallGraph()62 CallGraph::~CallGraph() {
63   if (!FunctionMap.empty()) {
64     for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
65         I != E; ++I)
66       delete I->second;
67     FunctionMap.clear();
68   }
69 }
70 
addTU(ASTContext & Ctx)71 void CallGraph::addTU(ASTContext& Ctx) {
72   DeclContext *DC = Ctx.getTranslationUnitDecl();
73   for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
74        I != E; ++I) {
75 
76     if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
77       if (FD->doesThisDeclarationHaveABody()) {
78         // Set caller's ASTContext.
79         Entity Ent = Entity::get(FD, Prog);
80         CallGraphNode *Node = getOrInsertFunction(Ent);
81         CallerCtx[Node] = &Ctx;
82 
83         // If this function has external linkage, anything could call it.
84         if (FD->isGlobal())
85           ExternalCallingNode->addCallee(idx::ASTLocation(), Node);
86 
87         // Set root node to 'main' function.
88         if (FD->getNameAsString() == "main")
89           Root = Node;
90 
91         CGBuilder builder(*this, FD, Ent, Node);
92         builder.Visit(FD->getBody());
93       }
94     }
95   }
96 }
97 
getOrInsertFunction(Entity F)98 CallGraphNode *CallGraph::getOrInsertFunction(Entity F) {
99   CallGraphNode *&Node = FunctionMap[F];
100   if (Node)
101     return Node;
102 
103   return Node = new CallGraphNode(F);
104 }
105 
getDecl(CallGraphNode * Node)106 Decl *CallGraph::getDecl(CallGraphNode *Node) {
107   // Get the function's context.
108   ASTContext *Ctx = CallerCtx[Node];
109 
110   return Node->getDecl(*Ctx);
111 }
112 
print(llvm::raw_ostream & os)113 void CallGraph::print(llvm::raw_ostream &os) {
114   for (iterator I = begin(), E = end(); I != E; ++I) {
115     if (I->second->hasCallee()) {
116       os << "function: " << I->first.getPrintableName()
117          << " calls:\n";
118       for (CallGraphNode::iterator CI = I->second->begin(),
119              CE = I->second->end(); CI != CE; ++CI) {
120         os << "    " << CI->second->getName();
121       }
122       os << '\n';
123     }
124   }
125 }
126 
dump()127 void CallGraph::dump() {
128   print(llvm::errs());
129 }
130 
ViewCallGraph() const131 void CallGraph::ViewCallGraph() const {
132   llvm::ViewGraph(*this, "CallGraph");
133 }
134 
135 namespace llvm {
136 
137 template <>
138 struct DOTGraphTraits<CallGraph> : public DefaultDOTGraphTraits {
139 
DOTGraphTraitsllvm::DOTGraphTraits140   DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
141 
getNodeLabelllvm::DOTGraphTraits142   static std::string getNodeLabel(const CallGraphNode *Node,
143                                   const CallGraph &CG) {
144     return Node->getName();
145 
146   }
147 
148 };
149 
150 }
151