ffd1746d03
This commit merges the latest LLVM sources from the vendor space. It also updates the build glue to match the new sources. Clang's version number is changed to match LLVM's, which means /usr/include/clang/2.0 has been renamed to /usr/include/clang/2.8. Obtained from: projects/clangbsd
151 lines
3.8 KiB
C++
151 lines
3.8 KiB
C++
//== 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/Index/CallGraph.h"
|
|
|
|
#include "clang/AST/ASTContext.h"
|
|
#include "clang/AST/StmtVisitor.h"
|
|
|
|
#include "llvm/Support/GraphWriter.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 VisitStmt(Stmt *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) {
|
|
if (FunctionDecl *CalleeDecl = CE->getDirectCallee()) {
|
|
Entity Ent = Entity::get(CalleeDecl, G.getProgram());
|
|
CallGraphNode *CalleeNode = G.getOrInsertFunction(Ent);
|
|
CallerNode->addCallee(ASTLocation(FD, CE), CalleeNode);
|
|
}
|
|
}
|
|
|
|
CallGraph::CallGraph(Program &P) : Prog(P), Root(0) {
|
|
ExternalCallingNode = getOrInsertFunction(Entity());
|
|
}
|
|
|
|
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(ASTContext& Ctx) {
|
|
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;
|
|
|
|
// If this function has external linkage, anything could call it.
|
|
if (FD->isGlobal())
|
|
ExternalCallingNode->addCallee(idx::ASTLocation(), Node);
|
|
|
|
// Set root node to 'main' function.
|
|
if (FD->getNameAsString() == "main")
|
|
Root = Node;
|
|
|
|
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);
|
|
}
|
|
|
|
Decl *CallGraph::getDecl(CallGraphNode *Node) {
|
|
// Get the function's context.
|
|
ASTContext *Ctx = CallerCtx[Node];
|
|
|
|
return Node->getDecl(*Ctx);
|
|
}
|
|
|
|
void CallGraph::print(llvm::raw_ostream &os) {
|
|
for (iterator I = begin(), E = end(); I != E; ++I) {
|
|
if (I->second->hasCallee()) {
|
|
os << "function: " << I->first.getPrintableName()
|
|
<< " calls:\n";
|
|
for (CallGraphNode::iterator CI = I->second->begin(),
|
|
CE = I->second->end(); CI != CE; ++CI) {
|
|
os << " " << CI->second->getName();
|
|
}
|
|
os << '\n';
|
|
}
|
|
}
|
|
}
|
|
|
|
void CallGraph::dump() {
|
|
print(llvm::errs());
|
|
}
|
|
|
|
void CallGraph::ViewCallGraph() const {
|
|
llvm::ViewGraph(*this, "CallGraph");
|
|
}
|
|
|
|
namespace llvm {
|
|
|
|
template <>
|
|
struct DOTGraphTraits<CallGraph> : public DefaultDOTGraphTraits {
|
|
|
|
DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
|
|
|
|
static std::string getNodeLabel(const CallGraphNode *Node,
|
|
const CallGraph &CG) {
|
|
return Node->getName();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|