LLVM API Documentation
00001 //=- lib/Analysis/IPA/CallTargets.cpp - Resolve Call Targets --*- C++ -*-=====// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by the LLVM research group and is distributed under 00006 // the University of Illinois Open Source License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This pass uses DSA to map targets of all calls, and reports on if it 00011 // thinks it knows all targets of a given call. 00012 // 00013 // Loop over all callsites, and lookup the DSNode for that site. Pull the 00014 // Functions from the node as callees. 00015 // This is essentially a utility pass to simplify later passes that only depend 00016 // on call sites and callees to operate (such as a devirtualizer). 00017 // 00018 //===----------------------------------------------------------------------===// 00019 00020 #include "llvm/Module.h" 00021 #include "llvm/Instructions.h" 00022 #include "llvm/Analysis/DataStructure/DataStructure.h" 00023 #include "llvm/Analysis/DataStructure/DSGraph.h" 00024 #include "llvm/Analysis/DataStructure/CallTargets.h" 00025 #include "llvm/ADT/Statistic.h" 00026 #include <iostream> 00027 #include "llvm/Constants.h" 00028 00029 using namespace llvm; 00030 00031 namespace { 00032 Statistic<> DirCall("calltarget", "Number of direct calls"); 00033 Statistic<> IndCall("calltarget", "Number of indirect calls"); 00034 Statistic<> CompleteInd("calltarget", "Number of complete indirect calls"); 00035 Statistic<> CompleteEmpty("calltarget", "Number of complete empty calls"); 00036 00037 RegisterAnalysis<CallTargetFinder> X("calltarget", "Find Call Targets (uses DSA)"); 00038 } 00039 00040 void CallTargetFinder::findIndTargets(Module &M) 00041 { 00042 TDDataStructures* T = &getAnalysis<TDDataStructures>(); 00043 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) 00044 if (!I->isExternal()) 00045 for (Function::iterator F = I->begin(), FE = I->end(); F != FE; ++F) 00046 for (BasicBlock::iterator B = F->begin(), BE = F->end(); B != BE; ++B) 00047 if (isa<CallInst>(B) || isa<InvokeInst>(B)) { 00048 CallSite cs = CallSite::get(B); 00049 AllSites.push_back(cs); 00050 if (!cs.getCalledFunction()) { 00051 IndCall++; 00052 DSNode* N = T->getDSGraph(*cs.getCaller()) 00053 .getNodeForValue(cs.getCalledValue()).getNode(); 00054 N->addFullFunctionList(IndMap[cs]); 00055 if (N->isComplete() && IndMap[cs].size()) { 00056 CompleteSites.insert(cs); 00057 ++CompleteInd; 00058 } 00059 if (N->isComplete() && !IndMap[cs].size()) { 00060 ++CompleteEmpty; 00061 std::cerr << "Call site empty: '" << cs.getInstruction()->getName() 00062 << "' In '" << cs.getInstruction()->getParent()->getParent()->getName() 00063 << "'\n"; 00064 } 00065 } else { 00066 ++DirCall; 00067 IndMap[cs].push_back(cs.getCalledFunction()); 00068 CompleteSites.insert(cs); 00069 } 00070 } 00071 } 00072 00073 void CallTargetFinder::print(std::ostream &O, const Module *M) const 00074 { 00075 return; 00076 O << "[* = incomplete] CS: func list\n"; 00077 for (std::map<CallSite, std::vector<Function*> >::const_iterator ii = IndMap.begin(), 00078 ee = IndMap.end(); ii != ee; ++ii) { 00079 if (!ii->first.getCalledFunction()) { //only print indirect 00080 if (!isComplete(ii->first)) { 00081 O << "* "; 00082 CallSite cs = ii->first; 00083 cs.getInstruction()->dump(); 00084 O << cs.getInstruction()->getParent()->getParent()->getName() << " " 00085 << cs.getInstruction()->getName() << " "; 00086 } 00087 O << ii->first.getInstruction() << ":"; 00088 for (std::vector<Function*>::const_iterator i = ii->second.begin(), 00089 e = ii->second.end(); i != e; ++i) { 00090 O << " " << (*i)->getName(); 00091 } 00092 O << "\n"; 00093 } 00094 } 00095 } 00096 00097 bool CallTargetFinder::runOnModule(Module &M) { 00098 findIndTargets(M); 00099 return false; 00100 } 00101 00102 void CallTargetFinder::getAnalysisUsage(AnalysisUsage &AU) const { 00103 AU.setPreservesAll(); 00104 AU.addRequired<TDDataStructures>(); 00105 } 00106 00107 std::vector<Function*>::iterator CallTargetFinder::begin(CallSite cs) { 00108 return IndMap[cs].begin(); 00109 } 00110 00111 std::vector<Function*>::iterator CallTargetFinder::end(CallSite cs) { 00112 return IndMap[cs].end(); 00113 } 00114 00115 bool CallTargetFinder::isComplete(CallSite cs) const { 00116 return CompleteSites.find(cs) != CompleteSites.end(); 00117 } 00118 00119 std::list<CallSite>::iterator CallTargetFinder::cs_begin() { 00120 return AllSites.begin(); 00121 } 00122 00123 std::list<CallSite>::iterator CallTargetFinder::cs_end() { 00124 return AllSites.end(); 00125 }