mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +00:00 
			
		
		
		
	git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28818 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			126 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			126 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //=- lib/Analysis/IPA/CallTargets.cpp - Resolve Call Targets --*- C++ -*-=====//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file was developed by the LLVM research group and is distributed under
 | |
| // the University of Illinois Open Source License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This pass uses DSA to map targets of all calls, and reports on if it
 | |
| // thinks it knows all targets of a given call.
 | |
| //
 | |
| // Loop over all callsites, and lookup the DSNode for that site.  Pull the
 | |
| // Functions from the node as callees.
 | |
| // This is essentially a utility pass to simplify later passes that only depend
 | |
| // on call sites and callees to operate (such as a devirtualizer).
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "llvm/Module.h"
 | |
| #include "llvm/Instructions.h"
 | |
| #include "llvm/Analysis/DataStructure/DataStructure.h"
 | |
| #include "llvm/Analysis/DataStructure/DSGraph.h"
 | |
| #include "llvm/Analysis/DataStructure/CallTargets.h"
 | |
| #include "llvm/ADT/Statistic.h"
 | |
| #include <iostream>
 | |
| #include "llvm/Constants.h"
 | |
| 
 | |
| using namespace llvm;
 | |
| 
 | |
| namespace {
 | |
|   Statistic<> DirCall("calltarget", "Number of direct calls");
 | |
|   Statistic<> IndCall("calltarget", "Number of indirect calls");
 | |
|   Statistic<> CompleteInd("calltarget", "Number of complete indirect calls");
 | |
|   Statistic<> CompleteEmpty("calltarget", "Number of complete empty calls");
 | |
| 
 | |
|   RegisterAnalysis<CallTargetFinder> X("calltarget", "Find Call Targets (uses DSA)");
 | |
| }
 | |
| 
 | |
| void CallTargetFinder::findIndTargets(Module &M)
 | |
| {
 | |
|   TDDataStructures* T = &getAnalysis<TDDataStructures>();
 | |
|   for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
 | |
|     if (!I->isExternal())
 | |
|       for (Function::iterator F = I->begin(), FE = I->end(); F != FE; ++F)
 | |
|         for (BasicBlock::iterator B = F->begin(), BE = F->end(); B != BE; ++B)
 | |
|           if (isa<CallInst>(B) || isa<InvokeInst>(B)) {
 | |
|             CallSite cs = CallSite::get(B);
 | |
|             AllSites.push_back(cs);
 | |
|             if (!cs.getCalledFunction()) {
 | |
|               IndCall++;
 | |
|               DSNode* N = T->getDSGraph(*cs.getCaller())
 | |
|                 .getNodeForValue(cs.getCalledValue()).getNode();
 | |
|               N->addFullFunctionList(IndMap[cs]);
 | |
|               if (N->isComplete() && IndMap[cs].size()) {
 | |
|                 CompleteSites.insert(cs);
 | |
|                 ++CompleteInd;
 | |
|               } 
 | |
|               if (N->isComplete() && !IndMap[cs].size()) {
 | |
|                 ++CompleteEmpty;
 | |
|                 std::cerr << "Call site empty: '" << cs.getInstruction()->getName() 
 | |
|                           << "' In '" << cs.getInstruction()->getParent()->getParent()->getName()
 | |
|                           << "'\n";
 | |
|               }
 | |
|             } else {
 | |
|               ++DirCall;
 | |
|               IndMap[cs].push_back(cs.getCalledFunction());
 | |
|               CompleteSites.insert(cs);
 | |
|             }
 | |
|           }
 | |
| }
 | |
| 
 | |
| void CallTargetFinder::print(std::ostream &O, const Module *M) const
 | |
| {
 | |
|   return;
 | |
|   O << "[* = incomplete] CS: func list\n";
 | |
|   for (std::map<CallSite, std::vector<Function*> >::const_iterator ii = IndMap.begin(),
 | |
|          ee = IndMap.end(); ii != ee; ++ii) {
 | |
|     if (!ii->first.getCalledFunction()) { //only print indirect
 | |
|       if (!isComplete(ii->first)) {
 | |
|         O << "* ";
 | |
|         CallSite cs = ii->first;
 | |
|         cs.getInstruction()->dump();
 | |
|         O << cs.getInstruction()->getParent()->getParent()->getName() << " "
 | |
|           << cs.getInstruction()->getName() << " ";
 | |
|       }
 | |
|       O << ii->first.getInstruction() << ":";
 | |
|       for (std::vector<Function*>::const_iterator i = ii->second.begin(),
 | |
|              e = ii->second.end(); i != e; ++i) {
 | |
|         O << " " << (*i)->getName();
 | |
|       }
 | |
|       O << "\n";
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool CallTargetFinder::runOnModule(Module &M) {
 | |
|   findIndTargets(M);
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| void CallTargetFinder::getAnalysisUsage(AnalysisUsage &AU) const {
 | |
|   AU.setPreservesAll();
 | |
|   AU.addRequired<TDDataStructures>();
 | |
| }
 | |
| 
 | |
| std::vector<Function*>::iterator CallTargetFinder::begin(CallSite cs) {
 | |
|   return IndMap[cs].begin();
 | |
| }
 | |
| 
 | |
| std::vector<Function*>::iterator CallTargetFinder::end(CallSite cs) {
 | |
|   return IndMap[cs].end();
 | |
| }
 | |
| 
 | |
| bool CallTargetFinder::isComplete(CallSite cs) const {
 | |
|   return CompleteSites.find(cs) != CompleteSites.end();
 | |
| }
 | |
| 
 | |
| std::list<CallSite>::iterator CallTargetFinder::cs_begin() {
 | |
|   return AllSites.begin();
 | |
| }
 | |
| 
 | |
| std::list<CallSite>::iterator CallTargetFinder::cs_end() {
 | |
|   return AllSites.end();
 | |
| }
 |