mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-01 00:25:01 +00:00
Make the call graph more precise despite the hated constantpointerrefs.
Do you detect the animosity I feel towards CPRs yet? llvm-svn: 9640
This commit is contained in:
parent
78b09155e1
commit
9c85e0b72c
@ -46,9 +46,11 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/Analysis/CallGraph.h"
|
#include "llvm/Analysis/CallGraph.h"
|
||||||
|
#include "llvm/Constants.h" // Remove when ConstantPointerRefs are gone
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/iOther.h"
|
#include "llvm/iOther.h"
|
||||||
#include "llvm/iTerminators.h"
|
#include "llvm/iTerminators.h"
|
||||||
|
#include "llvm/Support/CallSite.h"
|
||||||
#include "Support/STLExtras.h"
|
#include "Support/STLExtras.h"
|
||||||
|
|
||||||
static RegisterAnalysis<CallGraph> X("callgraph", "Call Graph Construction");
|
static RegisterAnalysis<CallGraph> X("callgraph", "Call Graph Construction");
|
||||||
@ -184,6 +186,13 @@ CallGraphNode *CallGraph::getNodeFor(Function *F) {
|
|||||||
return CGN = new CallGraphNode(F);
|
return CGN = new CallGraphNode(F);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isOnlyADirectCall(Function *F, CallSite CS) {
|
||||||
|
if (!CS.getInstruction()) return false;
|
||||||
|
for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); I != E; ++I)
|
||||||
|
if (*I == F) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// addToCallGraph - Add a function to the call graph, and link the node to all
|
// addToCallGraph - Add a function to the call graph, and link the node to all
|
||||||
// of the functions that it calls.
|
// of the functions that it calls.
|
||||||
//
|
//
|
||||||
@ -211,28 +220,39 @@ void CallGraph::addToCallGraph(Function *F) {
|
|||||||
|
|
||||||
// Loop over all of the users of the function... looking for callers...
|
// Loop over all of the users of the function... looking for callers...
|
||||||
//
|
//
|
||||||
|
bool isUsedExternally = false;
|
||||||
for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; ++I) {
|
for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; ++I) {
|
||||||
User *U = *I;
|
if (Instruction *Inst = dyn_cast<Instruction>(*I)) {
|
||||||
if (CallInst *CI = dyn_cast<CallInst>(U))
|
if (isOnlyADirectCall(F, CallSite::get(Inst)))
|
||||||
getNodeFor(CI->getParent()->getParent())->addCalledFunction(Node);
|
getNodeFor(Inst->getParent()->getParent())->addCalledFunction(Node);
|
||||||
else if (InvokeInst *II = dyn_cast<InvokeInst>(U))
|
else
|
||||||
getNodeFor(II->getParent()->getParent())->addCalledFunction(Node);
|
isUsedExternally = true;
|
||||||
else // Can't classify the user!
|
} else if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(*I)) {
|
||||||
ExternalNode->addCalledFunction(Node);
|
// THIS IS A DISGUSTING HACK. Brought to you by the power of
|
||||||
|
// ConstantPointerRefs!
|
||||||
|
for (Value::use_iterator I = CPR->use_begin(), E = CPR->use_end();
|
||||||
|
I != E; ++I)
|
||||||
|
if (Instruction *Inst = dyn_cast<Instruction>(*I)) {
|
||||||
|
if (isOnlyADirectCall(F, CallSite::get(Inst)))
|
||||||
|
getNodeFor(Inst->getParent()->getParent())->addCalledFunction(Node);
|
||||||
|
else
|
||||||
|
isUsedExternally = true;
|
||||||
|
} else {
|
||||||
|
isUsedExternally = true;
|
||||||
|
}
|
||||||
|
} else { // Can't classify the user!
|
||||||
|
isUsedExternally = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (isUsedExternally)
|
||||||
|
ExternalNode->addCalledFunction(Node);
|
||||||
|
|
||||||
// Look for an indirect function call...
|
// Look for an indirect function call...
|
||||||
for (Function::iterator BB = F->begin(), BBE = F->end(); BB != BBE; ++BB)
|
for (Function::iterator BB = F->begin(), BBE = F->end(); BB != BBE; ++BB)
|
||||||
for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); II != IE; ++II){
|
for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); II != IE; ++II){
|
||||||
Instruction &I = *II;
|
CallSite CS = CallSite::get(II);
|
||||||
|
if (CS.getInstruction() && !CS.getCalledFunction())
|
||||||
if (CallInst *CI = dyn_cast<CallInst>(&I)) {
|
Node->addCalledFunction(ExternalNode);
|
||||||
if (CI->getCalledFunction() == 0)
|
|
||||||
Node->addCalledFunction(ExternalNode);
|
|
||||||
} else if (InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
|
|
||||||
if (II->getCalledFunction() == 0)
|
|
||||||
Node->addCalledFunction(ExternalNode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user