blob: 1e28411eb4668ee06b05b96e4747e1e72297d1a0 [file] [log] [blame]
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +00001//== 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/Analysis/CallGraph.h"
15
16#include "clang/AST/ASTContext.h"
17#include "clang/AST/StmtVisitor.h"
18
Zhongxing Xu16a705f2009-07-23 09:04:23 +000019#include "llvm/Support/GraphWriter.h"
20
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000021using namespace clang;
22using namespace idx;
23
24namespace {
25class CGBuilder : public StmtVisitor<CGBuilder> {
26
27 CallGraph &G;
28 FunctionDecl *FD;
29
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000030 Entity CallerEnt;
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000031
32 CallGraphNode *CallerNode;
33
34public:
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000035 CGBuilder(CallGraph &g, FunctionDecl *fd, Entity E, CallGraphNode *N)
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000036 : G(g), FD(fd), CallerEnt(E), CallerNode(N) {}
37
Zhongxing Xu93cbae32009-07-18 08:49:07 +000038 void VisitStmt(Stmt *S) { VisitChildren(S); }
Zhongxing Xu24ff0302009-07-17 05:49:16 +000039
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000040 void VisitCallExpr(CallExpr *CE);
41
42 void VisitChildren(Stmt *S) {
43 for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I != E;++I)
44 if (*I)
45 static_cast<CGBuilder*>(this)->Visit(*I);
46 }
47};
48}
49
50void CGBuilder::VisitCallExpr(CallExpr *CE) {
Zhongxing Xua0042542009-07-17 07:29:51 +000051 if (FunctionDecl *CalleeDecl = CE->getDirectCallee()) {
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000052 Entity Ent = Entity::get(CalleeDecl, G.getProgram());
Zhongxing Xua0042542009-07-17 07:29:51 +000053 CallGraphNode *CalleeNode = G.getOrInsertFunction(Ent);
Zhongxing Xu7f66bd22009-07-17 07:36:20 +000054
55 Decl *Parent = ASTLocation::FindImmediateParent(FD, CE);
56
57 CallerNode->addCallee(ASTLocation(Parent, CE), CalleeNode);
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000058 }
59}
60
Zhongxing Xu56a5d802009-07-23 13:39:38 +000061CallGraph::CallGraph() : Root(0) {
62 ExternalCallingNode = getOrInsertFunction(Entity());
63}
64
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000065CallGraph::~CallGraph() {
66 if (!FunctionMap.empty()) {
67 for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
68 I != E; ++I)
69 delete I->second;
70 FunctionMap.clear();
71 }
72}
73
74void CallGraph::addTU(ASTUnit &AST) {
75 ASTContext &Ctx = AST.getASTContext();
76 DeclContext *DC = Ctx.getTranslationUnitDecl();
77
78 for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
79 I != E; ++I) {
80
81 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
82 if (FD->isThisDeclarationADefinition()) {
83 // Set caller's ASTContext.
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000084 Entity Ent = Entity::get(FD, Prog);
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000085 CallGraphNode *Node = getOrInsertFunction(Ent);
86 CallerCtx[Node] = &Ctx;
Zhongxing Xu56a5d802009-07-23 13:39:38 +000087
88 // If this function has external linkage, anything could call it.
89 if (FD->isGlobal())
90 ExternalCallingNode->addCallee(idx::ASTLocation(), Node);
91
92 // Set root node to 'main' function.
93 if (FD->getNameAsString() == "main")
94 Root = Node;
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000095
96 CGBuilder builder(*this, FD, Ent, Node);
97 builder.Visit(FD->getBody());
98 }
99 }
100 }
101}
102
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000103CallGraphNode *CallGraph::getOrInsertFunction(Entity F) {
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +0000104 CallGraphNode *&Node = FunctionMap[F];
105 if (Node)
106 return Node;
107
108 return Node = new CallGraphNode(F);
109}
110
Zhongxing Xue3e643f2009-07-24 03:41:11 +0000111Decl *CallGraph::getDecl(CallGraphNode *Node) {
112 // Get the function's context.
113 ASTContext *Ctx = CallerCtx[Node];
114
115 return Node->getDecl(*Ctx);
116}
117
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +0000118void CallGraph::print(llvm::raw_ostream &os) {
119 for (iterator I = begin(), E = end(); I != E; ++I) {
Zhongxing Xu24ff0302009-07-17 05:49:16 +0000120 if (I->second->hasCallee()) {
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000121 os << "function: " << I->first.getPrintableName()
Zhongxing Xu56aac3f2009-07-17 07:49:44 +0000122 << " calls:\n";
Zhongxing Xu24ff0302009-07-17 05:49:16 +0000123 for (CallGraphNode::iterator CI = I->second->begin(),
124 CE = I->second->end(); CI != CE; ++CI) {
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000125 os << " " << CI->second->getName().c_str();
Zhongxing Xu24ff0302009-07-17 05:49:16 +0000126 }
127 os << '\n';
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +0000128 }
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +0000129 }
130}
131
132void CallGraph::dump() {
133 print(llvm::errs());
134}
Zhongxing Xu16a705f2009-07-23 09:04:23 +0000135
136void CallGraph::ViewCallGraph() const {
137 llvm::ViewGraph(*this, "CallGraph");
138}
139
140namespace llvm {
141
142template <>
143struct DOTGraphTraits<CallGraph> : public DefaultDOTGraphTraits {
144
145 static std::string getNodeLabel(const CallGraphNode *Node,
146 const CallGraph &CG, bool ShortNames) {
147 return Node->getName();
148
149 }
150
151};
152
153}