mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
Switch from using CallInst's to represent call sites to using the LLVM
CallSite class. Now we can represent function calls by invoke instructions too! llvm-svn: 8629
This commit is contained in:
parent
6a460d88d3
commit
b12a8a6177
@ -7,11 +7,9 @@
|
||||
#ifndef LLVM_ANALYSIS_DSSUPPORT_H
|
||||
#define LLVM_ANALYSIS_DSSUPPORT_H
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include "Support/hash_set"
|
||||
#include "llvm/Support/CallSite.h"
|
||||
|
||||
class Function;
|
||||
class CallInst;
|
||||
@ -127,7 +125,7 @@ namespace std {
|
||||
/// the DSNode handles for the function arguments.
|
||||
///
|
||||
class DSCallSite {
|
||||
CallInst *Inst; // Actual call site
|
||||
CallSite Site; // Actual call site
|
||||
Function *CalleeF; // The function called (direct call)
|
||||
DSNodeHandle CalleeN; // The function node called (indirect call)
|
||||
DSNodeHandle RetVal; // Returned value
|
||||
@ -160,21 +158,21 @@ public:
|
||||
/// Constructor. Note - This ctor destroys the argument vector passed in. On
|
||||
/// exit, the argument vector is empty.
|
||||
///
|
||||
DSCallSite(CallInst &inst, const DSNodeHandle &rv, DSNode *Callee,
|
||||
DSCallSite(CallSite CS, const DSNodeHandle &rv, DSNode *Callee,
|
||||
std::vector<DSNodeHandle> &Args)
|
||||
: Inst(&inst), CalleeF(0), CalleeN(Callee), RetVal(rv) {
|
||||
: Site(CS), CalleeF(0), CalleeN(Callee), RetVal(rv) {
|
||||
assert(Callee && "Null callee node specified for call site!");
|
||||
Args.swap(CallArgs);
|
||||
}
|
||||
DSCallSite(CallInst &inst, const DSNodeHandle &rv, Function *Callee,
|
||||
DSCallSite(CallSite CS, const DSNodeHandle &rv, Function *Callee,
|
||||
std::vector<DSNodeHandle> &Args)
|
||||
: Inst(&inst), CalleeF(Callee), RetVal(rv) {
|
||||
: Site(CS), CalleeF(Callee), RetVal(rv) {
|
||||
assert(Callee && "Null callee function specified for call site!");
|
||||
Args.swap(CallArgs);
|
||||
}
|
||||
|
||||
DSCallSite(const DSCallSite &DSCS) // Simple copy ctor
|
||||
: Inst(DSCS.Inst), CalleeF(DSCS.CalleeF), CalleeN(DSCS.CalleeN),
|
||||
: Site(DSCS.Site), CalleeF(DSCS.CalleeF), CalleeN(DSCS.CalleeN),
|
||||
RetVal(DSCS.RetVal), CallArgs(DSCS.CallArgs) {}
|
||||
|
||||
/// Mapping copy constructor - This constructor takes a preexisting call site
|
||||
@ -183,7 +181,7 @@ public:
|
||||
///
|
||||
template<typename MapTy>
|
||||
DSCallSite(const DSCallSite &FromCall, const MapTy &NodeMap) {
|
||||
Inst = FromCall.Inst;
|
||||
Site = FromCall.Site;
|
||||
InitNH(RetVal, FromCall.RetVal, NodeMap);
|
||||
InitNH(CalleeN, FromCall.CalleeN, NodeMap);
|
||||
CalleeF = FromCall.CalleeF;
|
||||
@ -194,7 +192,7 @@ public:
|
||||
}
|
||||
|
||||
const DSCallSite &operator=(const DSCallSite &RHS) {
|
||||
Inst = RHS.Inst;
|
||||
Site = RHS.Site;
|
||||
CalleeF = RHS.CalleeF;
|
||||
CalleeN = RHS.CalleeN;
|
||||
RetVal = RHS.RetVal;
|
||||
@ -212,7 +210,7 @@ public:
|
||||
|
||||
// Accessor functions...
|
||||
Function &getCaller() const;
|
||||
CallInst &getCallInst() const { return *Inst; }
|
||||
CallSite getCallSite() const { return Site; }
|
||||
DSNodeHandle &getRetVal() { return RetVal; }
|
||||
const DSNodeHandle &getRetVal() const { return RetVal; }
|
||||
|
||||
@ -236,7 +234,7 @@ public:
|
||||
|
||||
void swap(DSCallSite &CS) {
|
||||
if (this != &CS) {
|
||||
std::swap(Inst, CS.Inst);
|
||||
std::swap(Site, CS.Site);
|
||||
std::swap(RetVal, CS.RetVal);
|
||||
std::swap(CalleeN, CS.CalleeN);
|
||||
std::swap(CalleeF, CS.CalleeF);
|
||||
|
@ -11,10 +11,9 @@
|
||||
#include "Support/hash_set"
|
||||
|
||||
class Type;
|
||||
class CallInst;
|
||||
class Instruction;
|
||||
class DSGraph;
|
||||
class DSNode;
|
||||
class DSCallSite;
|
||||
|
||||
// FIXME: move this stuff to a private header
|
||||
namespace DataStructureAnalysis {
|
||||
@ -75,7 +74,7 @@ class BUDataStructures : public Pass {
|
||||
// DSInfo, one graph for each function
|
||||
hash_map<Function*, DSGraph*> DSInfo;
|
||||
DSGraph *GlobalsGraph;
|
||||
hash_multimap<CallInst*, Function*> ActualCallees;
|
||||
hash_multimap<Instruction*, Function*> ActualCallees;
|
||||
public:
|
||||
~BUDataStructures() { releaseMemory(); }
|
||||
|
||||
@ -106,7 +105,7 @@ public:
|
||||
AU.addRequired<LocalDataStructures>();
|
||||
}
|
||||
|
||||
typedef hash_multimap<CallInst*, Function*> ActualCalleesTy;
|
||||
typedef hash_multimap<Instruction*, Function*> ActualCalleesTy;
|
||||
const ActualCalleesTy &getActualCallees() const {
|
||||
return ActualCallees;
|
||||
}
|
||||
|
@ -45,7 +45,10 @@
|
||||
|
||||
class Module;
|
||||
class Function;
|
||||
class CallSite;
|
||||
class Instruction;
|
||||
class CallInst;
|
||||
class InvokeInst;
|
||||
class DSNode;
|
||||
class DSGraph;
|
||||
class DSNodeHandle;
|
||||
@ -117,15 +120,15 @@ class FunctionModRefInfo {
|
||||
IPModRef& IPModRefObj; // The IPModRef Object owning this
|
||||
DSGraph* funcTDGraph; // Top-down DS graph for function
|
||||
ModRefInfo funcModRefInfo; // ModRefInfo for the function body
|
||||
std::map<const CallInst*, ModRefInfo*>
|
||||
std::map<const Instruction*, ModRefInfo*>
|
||||
callSiteModRefInfo; // ModRefInfo for each callsite
|
||||
std::map<const DSNode*, unsigned> NodeIds;
|
||||
|
||||
friend class IPModRef;
|
||||
|
||||
void computeModRef (const Function &func);
|
||||
void computeModRef (const CallInst& callInst);
|
||||
DSGraph *ResolveCallSiteModRefInfo(CallInst &CI,
|
||||
void computeModRef (CallSite call);
|
||||
DSGraph *ResolveCallSiteModRefInfo(CallSite CS,
|
||||
hash_map<const DSNode*, DSNodeHandle> &NodeMap);
|
||||
|
||||
public:
|
||||
@ -145,9 +148,14 @@ public:
|
||||
return &funcModRefInfo;
|
||||
}
|
||||
const ModRefInfo* getModRefInfo (const CallInst& callInst) const {
|
||||
std::map<const CallInst*, ModRefInfo*>::const_iterator I =
|
||||
callSiteModRefInfo.find(&callInst);
|
||||
return (I == callSiteModRefInfo.end())? NULL : I->second;
|
||||
std::map<const Instruction*, ModRefInfo*>::const_iterator I =
|
||||
callSiteModRefInfo.find((Instruction*)&callInst);
|
||||
return (I == callSiteModRefInfo.end()) ? NULL : I->second;
|
||||
}
|
||||
const ModRefInfo* getModRefInfo (const InvokeInst& II) const {
|
||||
std::map<const Instruction*, ModRefInfo*>::const_iterator I =
|
||||
callSiteModRefInfo.find((Instruction*)&II);
|
||||
return (I == callSiteModRefInfo.end()) ? NULL : I->second;
|
||||
}
|
||||
|
||||
// Get the nodeIds used to index all Mod/Ref information for current function
|
||||
|
@ -253,7 +253,8 @@ void BUDataStructures::calculateGraph(DSGraph &Graph) {
|
||||
Graph.mergeInGraph(CS, *Callee, Graph, 0);
|
||||
|
||||
} else {
|
||||
ActualCallees.insert(std::make_pair(&CS.getCallInst(), Callee));
|
||||
ActualCallees.insert(std::make_pair(CS.getCallSite().getInstruction(),
|
||||
Callee));
|
||||
|
||||
// Get the data structure graph for the called function.
|
||||
//
|
||||
|
@ -709,7 +709,7 @@ void DSNode::mergeWith(const DSNodeHandle &NH, unsigned Offset) {
|
||||
|
||||
// Define here to avoid including iOther.h and BasicBlock.h in DSGraph.h
|
||||
Function &DSCallSite::getCaller() const {
|
||||
return *Inst->getParent()->getParent();
|
||||
return *Site.getInstruction()->getParent()->getParent();
|
||||
}
|
||||
|
||||
|
||||
@ -1044,7 +1044,7 @@ DSCallSite DSGraph::getCallSiteForArguments(Function &F) const {
|
||||
if (isPointerType(I->getType()))
|
||||
Args.push_back(getScalarMap().find(I)->second);
|
||||
|
||||
return DSCallSite(*(CallInst*)0, getReturnNodeFor(F), &F, Args);
|
||||
return DSCallSite(CallSite(), getReturnNodeFor(F), &F, Args);
|
||||
}
|
||||
|
||||
|
||||
|
@ -68,7 +68,7 @@ void DSGraphStats::countCallees(const Function& F) {
|
||||
|
||||
const std::vector<DSCallSite> &callSites = TDGraph->getFunctionCalls();
|
||||
for (unsigned i = 0, N = callSites.size(); i != N; ++i)
|
||||
if (isIndirectCallee(callSites[i].getCallInst().getCalledValue())) {
|
||||
if (isIndirectCallee(callSites[i].getCallSite().getCalledValue())) {
|
||||
// This is an indirect function call
|
||||
const std::vector<GlobalValue*> &Callees =
|
||||
callSites[i].getCalleeNode()->getGlobals();
|
||||
@ -76,8 +76,9 @@ void DSGraphStats::countCallees(const Function& F) {
|
||||
totalNumCallees += Callees.size();
|
||||
++numIndirectCalls;
|
||||
} else
|
||||
std::cerr << "WARNING: No callee in Function " << F.getName()
|
||||
<< "at call:\n" << callSites[i].getCallInst();
|
||||
std::cerr << "WARNING: No callee in Function '" << F.getName()
|
||||
<< "' at call: \n"
|
||||
<< *callSites[i].getCallSite().getInstruction();
|
||||
}
|
||||
|
||||
TotalNumCallees += totalNumCallees;
|
||||
|
@ -7,14 +7,11 @@
|
||||
|
||||
#include "llvm/Analysis/DataStructure.h"
|
||||
#include "llvm/Analysis/DSGraph.h"
|
||||
#include "llvm/iMemory.h"
|
||||
#include "llvm/iTerminators.h"
|
||||
#include "llvm/iPHINode.h"
|
||||
#include "llvm/iOther.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/GlobalVariable.h"
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/Support/InstVisitor.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "Support/CommandLine.h"
|
||||
@ -96,11 +93,13 @@ namespace {
|
||||
void visitLoadInst(LoadInst &LI);
|
||||
void visitStoreInst(StoreInst &SI);
|
||||
void visitCallInst(CallInst &CI);
|
||||
void visitInvokeInst(InvokeInst &II);
|
||||
void visitSetCondInst(SetCondInst &SCI) {} // SetEQ & friends are ignored
|
||||
void visitFreeInst(FreeInst &FI);
|
||||
void visitCastInst(CastInst &CI);
|
||||
void visitInstruction(Instruction &I);
|
||||
|
||||
void visitCallSite(CallSite CS);
|
||||
private:
|
||||
// Helper functions used to implement the visitation functions...
|
||||
|
||||
@ -405,29 +404,38 @@ void GraphBuilder::visitReturnInst(ReturnInst &RI) {
|
||||
}
|
||||
|
||||
void GraphBuilder::visitCallInst(CallInst &CI) {
|
||||
visitCallSite(&CI);
|
||||
}
|
||||
|
||||
void GraphBuilder::visitInvokeInst(InvokeInst &II) {
|
||||
visitCallSite(&II);
|
||||
}
|
||||
|
||||
void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
// Set up the return value...
|
||||
DSNodeHandle RetVal;
|
||||
if (isPointerType(CI.getType()))
|
||||
RetVal = getValueDest(CI);
|
||||
Instruction *I = CS.getInstruction();
|
||||
if (isPointerType(I->getType()))
|
||||
RetVal = getValueDest(*I);
|
||||
|
||||
DSNode *Callee = 0;
|
||||
if (DisableDirectCallOpt || !isa<Function>(CI.getOperand(0)))
|
||||
Callee = getValueDest(*CI.getOperand(0)).getNode();
|
||||
if (DisableDirectCallOpt || !isa<Function>(CS.getCalledValue()))
|
||||
Callee = getValueDest(*CS.getCalledValue()).getNode();
|
||||
|
||||
std::vector<DSNodeHandle> Args;
|
||||
Args.reserve(CI.getNumOperands()-1);
|
||||
Args.reserve(CS.arg_end()-CS.arg_begin());
|
||||
|
||||
// Calculate the arguments vector...
|
||||
for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i)
|
||||
if (isPointerType(CI.getOperand(i)->getType()))
|
||||
Args.push_back(getValueDest(*CI.getOperand(i)));
|
||||
for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); I != E; ++I)
|
||||
if (isPointerType((*I)->getType()))
|
||||
Args.push_back(getValueDest(**I));
|
||||
|
||||
// Add a new function call entry...
|
||||
if (Callee)
|
||||
FunctionCalls.push_back(DSCallSite(CI, RetVal, Callee, Args));
|
||||
FunctionCalls.push_back(DSCallSite(CS, RetVal, Callee, Args));
|
||||
else
|
||||
FunctionCalls.push_back(DSCallSite(CI, RetVal,
|
||||
cast<Function>(CI.getOperand(0)), Args));
|
||||
FunctionCalls.push_back(DSCallSite(CS, RetVal, CS.getCalledFunction(),
|
||||
Args));
|
||||
}
|
||||
|
||||
void GraphBuilder::visitFreeInst(FreeInst &FI) {
|
||||
|
@ -96,9 +96,10 @@ void TDDataStructures::ComputePostOrder(Function &F,hash_set<DSGraph*> &Visited,
|
||||
const std::vector<DSCallSite> &FunctionCalls = G.getFunctionCalls();
|
||||
|
||||
for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
|
||||
Instruction *CallI = FunctionCalls[i].getCallSite().getInstruction();
|
||||
std::pair<BUDataStructures::ActualCalleesTy::const_iterator,
|
||||
BUDataStructures::ActualCalleesTy::const_iterator>
|
||||
IP = ActualCallees.equal_range(&FunctionCalls[i].getCallInst());
|
||||
IP = ActualCallees.equal_range(CallI);
|
||||
|
||||
for (BUDataStructures::ActualCalleesTy::const_iterator I = IP.first;
|
||||
I != IP.second; ++I)
|
||||
@ -191,10 +192,11 @@ void TDDataStructures::inlineGraphIntoCallees(DSGraph &Graph) {
|
||||
// Clone and merge the reachable subgraph from the call into callee's graph.
|
||||
//
|
||||
for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
|
||||
Instruction *CallI = FunctionCalls[i].getCallSite().getInstruction();
|
||||
// For each function in the invoked function list at this call site...
|
||||
std::pair<BUDataStructures::ActualCalleesTy::const_iterator,
|
||||
BUDataStructures::ActualCalleesTy::const_iterator>
|
||||
IP = ActualCallees.equal_range(&FunctionCalls[i].getCallInst());
|
||||
IP = ActualCallees.equal_range(CallI);
|
||||
|
||||
// Multiple callees may have the same graph, so try to inline and merge
|
||||
// only once for each <callSite,calleeGraph> pair, not once for each
|
||||
|
@ -61,7 +61,7 @@ FunctionModRefInfo::FunctionModRefInfo(const Function& func,
|
||||
|
||||
FunctionModRefInfo::~FunctionModRefInfo()
|
||||
{
|
||||
for(std::map<const CallInst*, ModRefInfo*>::iterator
|
||||
for(std::map<const Instruction*, ModRefInfo*>::iterator
|
||||
I=callSiteModRefInfo.begin(), E=callSiteModRefInfo.end(); I != E; ++I)
|
||||
delete(I->second);
|
||||
|
||||
@ -98,7 +98,7 @@ void FunctionModRefInfo::computeModRef(const Function &func)
|
||||
// The call sites are recorded in the TD graph.
|
||||
const std::vector<DSCallSite>& callSites = funcTDGraph->getFunctionCalls();
|
||||
for (unsigned i = 0, N = callSites.size(); i < N; ++i)
|
||||
computeModRef(callSites[i].getCallInst());
|
||||
computeModRef(callSites[i].getCallSite());
|
||||
}
|
||||
|
||||
|
||||
@ -117,25 +117,22 @@ void FunctionModRefInfo::computeModRef(const Function &func)
|
||||
// requested information (because the call site calls an external
|
||||
// function or we cannot determine the complete set of functions invoked).
|
||||
//
|
||||
DSGraph* FunctionModRefInfo::ResolveCallSiteModRefInfo(CallInst &CI,
|
||||
DSGraph* FunctionModRefInfo::ResolveCallSiteModRefInfo(CallSite CS,
|
||||
hash_map<const DSNode*, DSNodeHandle> &NodeMap)
|
||||
{
|
||||
// Step #0: Quick check if we are going to fail anyway: avoid
|
||||
// all the graph cloning and map copying in steps #1 and #2.
|
||||
//
|
||||
if (const Function *F = CI.getCalledFunction())
|
||||
{
|
||||
if (F->isExternal())
|
||||
return 0; // We cannot compute Mod/Ref info for this callsite...
|
||||
}
|
||||
else
|
||||
{
|
||||
// Eventually, should check here if any callee is external.
|
||||
// For now we are not handling this case anyway.
|
||||
std::cerr << "IP Mod/Ref indirect call not implemented yet: "
|
||||
<< "Being conservative\n";
|
||||
if (const Function *F = CS.getCalledFunction()) {
|
||||
if (F->isExternal())
|
||||
return 0; // We cannot compute Mod/Ref info for this callsite...
|
||||
}
|
||||
} else {
|
||||
// Eventually, should check here if any callee is external.
|
||||
// For now we are not handling this case anyway.
|
||||
std::cerr << "IP Mod/Ref indirect call not implemented yet: "
|
||||
<< "Being conservative\n";
|
||||
return 0; // We cannot compute Mod/Ref info for this callsite...
|
||||
}
|
||||
|
||||
// Step #1: Clone the top-down graph...
|
||||
DSGraph *Result = new DSGraph(*funcTDGraph, NodeMap);
|
||||
@ -144,7 +141,7 @@ DSGraph* FunctionModRefInfo::ResolveCallSiteModRefInfo(CallInst &CI,
|
||||
Result->maskNodeTypes(~(DSNode::Modified | DSNode::Read));
|
||||
|
||||
// Step #3: clone the bottom up graphs for the callees into the caller graph
|
||||
if (Function *F = CI.getCalledFunction())
|
||||
if (Function *F = CS.getCalledFunction())
|
||||
{
|
||||
assert(!F->isExternal());
|
||||
|
||||
@ -152,17 +149,18 @@ DSGraph* FunctionModRefInfo::ResolveCallSiteModRefInfo(CallInst &CI,
|
||||
|
||||
// If the call returns a value, make sure to merge the nodes...
|
||||
DSNodeHandle RetVal;
|
||||
if (DS::isPointerType(CI.getType()))
|
||||
RetVal = Result->getNodeForValue(&CI);
|
||||
if (DS::isPointerType(CS.getInstruction()->getType()))
|
||||
RetVal = Result->getNodeForValue(CS.getInstruction());
|
||||
|
||||
// Populate the arguments list...
|
||||
std::vector<DSNodeHandle> Args;
|
||||
for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i)
|
||||
if (DS::isPointerType(CI.getOperand(i)->getType()))
|
||||
Args.push_back(Result->getNodeForValue(CI.getOperand(i)));
|
||||
for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
|
||||
I != E; ++I)
|
||||
if (DS::isPointerType((*I)->getType()))
|
||||
Args.push_back(Result->getNodeForValue(*I));
|
||||
|
||||
// Build the call site...
|
||||
DSCallSite CS(CI, RetVal, F, Args);
|
||||
DSCallSite CS(CS, RetVal, F, Args);
|
||||
|
||||
// Perform the merging now of the graph for the callee, which will
|
||||
// come with mod/ref bits set...
|
||||
@ -187,16 +185,15 @@ DSGraph* FunctionModRefInfo::ResolveCallSiteModRefInfo(CallInst &CI,
|
||||
// and then inlining the callee's BU graph into the caller's TD graph.
|
||||
//
|
||||
void
|
||||
FunctionModRefInfo::computeModRef(const CallInst& callInst)
|
||||
FunctionModRefInfo::computeModRef(CallSite CS)
|
||||
{
|
||||
// Allocate the mod/ref info for the call site. Bits automatically cleared.
|
||||
ModRefInfo* callModRefInfo = new ModRefInfo(funcTDGraph->getGraphSize());
|
||||
callSiteModRefInfo[&callInst] = callModRefInfo;
|
||||
callSiteModRefInfo[CS.getInstruction()] = callModRefInfo;
|
||||
|
||||
// Get a copy of the graph for the callee with the callee inlined
|
||||
hash_map<const DSNode*, DSNodeHandle> NodeMap;
|
||||
DSGraph* csgp = ResolveCallSiteModRefInfo(const_cast<CallInst&>(callInst),
|
||||
NodeMap);
|
||||
DSGraph* csgp = ResolveCallSiteModRefInfo(CS, NodeMap);
|
||||
if (!csgp)
|
||||
{ // Callee's side effects are unknown: mark all nodes Mod and Ref.
|
||||
// Eventually this should only mark nodes visible to the callee, i.e.,
|
||||
@ -323,7 +320,7 @@ void FunctionModRefInfo::print(std::ostream &O) const
|
||||
|
||||
// Second: Print Globals and Locals modified at each call site in function
|
||||
//
|
||||
for (std::map<const CallInst*, ModRefInfo*>::const_iterator
|
||||
for (std::map<const Instruction *, ModRefInfo*>::const_iterator
|
||||
CI = callSiteModRefInfo.begin(), CE = callSiteModRefInfo.end();
|
||||
CI != CE; ++CI)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user