blob: a21b52ae60272afc1723ba37d81a4c0e8bfa9417 [file] [log] [blame]
Anna Zaks190f6002012-03-02 22:54:36 +00001//== GlobalCallGraph.cpp - Call graph building ------------------*- C++ -*--==//
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +00002//
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
Anna Zaks190f6002012-03-02 22:54:36 +000014#include "clang/Index/GlobalCallGraph.h"
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000015
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
Anna Zaks190f6002012-03-02 22:54:36 +000021using namespace clang::idx;
22using clang::FunctionDecl;
23using clang::DeclContext;
24using clang::ASTContext;
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000025
26namespace {
27class CGBuilder : public StmtVisitor<CGBuilder> {
28
29 CallGraph &G;
30 FunctionDecl *FD;
31
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000032 Entity CallerEnt;
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000033
34 CallGraphNode *CallerNode;
35
36public:
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000037 CGBuilder(CallGraph &g, FunctionDecl *fd, Entity E, CallGraphNode *N)
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000038 : G(g), FD(fd), CallerEnt(E), CallerNode(N) {}
39
Zhongxing Xu93cbae32009-07-18 08:49:07 +000040 void VisitStmt(Stmt *S) { VisitChildren(S); }
Zhongxing Xu24ff0302009-07-17 05:49:16 +000041
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000042 void VisitCallExpr(CallExpr *CE);
43
44 void VisitChildren(Stmt *S) {
John McCall7502c1d2011-02-13 04:07:26 +000045 for (Stmt::child_range I = S->children(); I; ++I)
Mike Stump1eb44332009-09-09 15:08:12 +000046 if (*I)
47 static_cast<CGBuilder*>(this)->Visit(*I);
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000048 }
49};
50}
51
52void CGBuilder::VisitCallExpr(CallExpr *CE) {
Zhongxing Xua0042542009-07-17 07:29:51 +000053 if (FunctionDecl *CalleeDecl = CE->getDirectCallee()) {
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000054 Entity Ent = Entity::get(CalleeDecl, G.getProgram());
Zhongxing Xua0042542009-07-17 07:29:51 +000055 CallGraphNode *CalleeNode = G.getOrInsertFunction(Ent);
Argyrios Kyrtzidisf4526e32009-09-29 19:44:27 +000056 CallerNode->addCallee(ASTLocation(FD, CE), CalleeNode);
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000057 }
58}
59
Zhongxing Xu6d956df2010-07-02 06:39:46 +000060CallGraph::CallGraph(Program &P) : Prog(P), Root(0) {
Zhongxing Xu56a5d802009-07-23 13:39:38 +000061 ExternalCallingNode = getOrInsertFunction(Entity());
62}
63
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000064CallGraph::~CallGraph() {
65 if (!FunctionMap.empty()) {
66 for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
67 I != E; ++I)
68 delete I->second;
69 FunctionMap.clear();
70 }
71}
72
Zhongxing Xuf20288c2009-10-28 12:23:03 +000073void CallGraph::addTU(ASTContext& Ctx) {
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000074 DeclContext *DC = Ctx.getTranslationUnitDecl();
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000075 for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
76 I != E; ++I) {
77
78 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
Sean Hunt10620eb2011-05-06 20:44:56 +000079 if (FD->doesThisDeclarationHaveABody()) {
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000080 // Set caller's ASTContext.
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000081 Entity Ent = Entity::get(FD, Prog);
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000082 CallGraphNode *Node = getOrInsertFunction(Ent);
83 CallerCtx[Node] = &Ctx;
Zhongxing Xu56a5d802009-07-23 13:39:38 +000084
85 // If this function has external linkage, anything could call it.
86 if (FD->isGlobal())
87 ExternalCallingNode->addCallee(idx::ASTLocation(), Node);
88
89 // Set root node to 'main' function.
90 if (FD->getNameAsString() == "main")
91 Root = Node;
Mike Stump1eb44332009-09-09 15:08:12 +000092
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000093 CGBuilder builder(*this, FD, Ent, Node);
94 builder.Visit(FD->getBody());
95 }
96 }
97 }
98}
99
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000100CallGraphNode *CallGraph::getOrInsertFunction(Entity F) {
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +0000101 CallGraphNode *&Node = FunctionMap[F];
102 if (Node)
103 return Node;
104
105 return Node = new CallGraphNode(F);
106}
107
Zhongxing Xue3e643f2009-07-24 03:41:11 +0000108Decl *CallGraph::getDecl(CallGraphNode *Node) {
109 // Get the function's context.
110 ASTContext *Ctx = CallerCtx[Node];
111
112 return Node->getDecl(*Ctx);
113}
114
Chris Lattner5f9e2722011-07-23 10:55:15 +0000115void CallGraph::print(raw_ostream &os) {
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +0000116 for (iterator I = begin(), E = end(); I != E; ++I) {
Zhongxing Xu24ff0302009-07-17 05:49:16 +0000117 if (I->second->hasCallee()) {
Mike Stump1eb44332009-09-09 15:08:12 +0000118 os << "function: " << I->first.getPrintableName()
Zhongxing Xu56aac3f2009-07-17 07:49:44 +0000119 << " calls:\n";
Mike Stump1eb44332009-09-09 15:08:12 +0000120 for (CallGraphNode::iterator CI = I->second->begin(),
Zhongxing Xu24ff0302009-07-17 05:49:16 +0000121 CE = I->second->end(); CI != CE; ++CI) {
Benjamin Kramerd02e2322009-11-14 12:08:24 +0000122 os << " " << CI->second->getName();
Zhongxing Xu24ff0302009-07-17 05:49:16 +0000123 }
124 os << '\n';
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +0000125 }
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +0000126 }
127}
128
129void CallGraph::dump() {
130 print(llvm::errs());
131}
Zhongxing Xu16a705f2009-07-23 09:04:23 +0000132
133void CallGraph::ViewCallGraph() const {
134 llvm::ViewGraph(*this, "CallGraph");
135}
136
137namespace llvm {
138
Mike Stump1eb44332009-09-09 15:08:12 +0000139template <>
Zhongxing Xu16a705f2009-07-23 09:04:23 +0000140struct DOTGraphTraits<CallGraph> : public DefaultDOTGraphTraits {
141
Tobias Grosser006b0eb2009-11-30 14:16:05 +0000142 DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
143
Mike Stump1eb44332009-09-09 15:08:12 +0000144 static std::string getNodeLabel(const CallGraphNode *Node,
Tobias Grosser006b0eb2009-11-30 14:16:05 +0000145 const CallGraph &CG) {
Zhongxing Xu16a705f2009-07-23 09:04:23 +0000146 return Node->getName();
Mike Stump1eb44332009-09-09 15:08:12 +0000147
Zhongxing Xu16a705f2009-07-23 09:04:23 +0000148 }
149
150};
151
152}