2009-07-16 08:54:12 +08:00
|
|
|
//== 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;
|
|
|
|
|
2009-07-21 08:07:06 +08:00
|
|
|
Entity CallerEnt;
|
2009-07-16 08:54:12 +08:00
|
|
|
|
|
|
|
CallGraphNode *CallerNode;
|
|
|
|
|
|
|
|
public:
|
2009-07-21 08:07:06 +08:00
|
|
|
CGBuilder(CallGraph &g, FunctionDecl *fd, Entity E, CallGraphNode *N)
|
2009-07-16 08:54:12 +08:00
|
|
|
: G(g), FD(fd), CallerEnt(E), CallerNode(N) {}
|
|
|
|
|
2009-07-18 16:49:07 +08:00
|
|
|
void VisitStmt(Stmt *S) { VisitChildren(S); }
|
2009-07-17 13:49:16 +08:00
|
|
|
|
2009-07-16 08:54:12 +08:00
|
|
|
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) {
|
2009-07-17 15:29:51 +08:00
|
|
|
if (FunctionDecl *CalleeDecl = CE->getDirectCallee()) {
|
2009-07-21 08:07:06 +08:00
|
|
|
Entity Ent = Entity::get(CalleeDecl, G.getProgram());
|
2009-07-17 15:29:51 +08:00
|
|
|
CallGraphNode *CalleeNode = G.getOrInsertFunction(Ent);
|
2009-07-17 15:36:20 +08:00
|
|
|
|
|
|
|
Decl *Parent = ASTLocation::FindImmediateParent(FD, CE);
|
|
|
|
|
|
|
|
CallerNode->addCallee(ASTLocation(Parent, CE), CalleeNode);
|
2009-07-16 08:54:12 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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.
|
2009-07-21 08:07:06 +08:00
|
|
|
Entity Ent = Entity::get(FD, Prog);
|
2009-07-16 08:54:12 +08:00
|
|
|
CallGraphNode *Node = getOrInsertFunction(Ent);
|
|
|
|
CallerCtx[Node] = &Ctx;
|
|
|
|
|
|
|
|
CGBuilder builder(*this, FD, Ent, Node);
|
|
|
|
builder.Visit(FD->getBody());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-21 08:07:06 +08:00
|
|
|
CallGraphNode *CallGraph::getOrInsertFunction(Entity F) {
|
2009-07-16 08:54:12 +08:00
|
|
|
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) {
|
2009-07-17 13:49:16 +08:00
|
|
|
if (I->second->hasCallee()) {
|
2009-07-21 15:52:21 +08:00
|
|
|
os << "function: " << I->first.getPrintableName()
|
2009-07-17 15:49:44 +08:00
|
|
|
<< " calls:\n";
|
2009-07-17 13:49:16 +08:00
|
|
|
for (CallGraphNode::iterator CI = I->second->begin(),
|
|
|
|
CE = I->second->end(); CI != CE; ++CI) {
|
2009-07-21 15:52:21 +08:00
|
|
|
os << " " << CI->second->getName().c_str();
|
2009-07-17 13:49:16 +08:00
|
|
|
}
|
|
|
|
os << '\n';
|
2009-07-16 08:54:12 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CallGraph::dump() {
|
|
|
|
print(llvm::errs());
|
|
|
|
}
|