mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-03 14:21:30 +00:00 
			
		
		
		
	git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@17482 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			309 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			309 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//===- RetracePath.cpp ----------------------------------------------------===//
 | 
						|
// 
 | 
						|
//                     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.
 | 
						|
// 
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// Retraces a path of BasicBlock, given a path number and a graph!
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "llvm/Module.h"
 | 
						|
#include "llvm/Instructions.h"
 | 
						|
#include "llvm/Support/CFG.h"
 | 
						|
#include "Graph.h"
 | 
						|
#include <iostream>
 | 
						|
 | 
						|
using std::vector;
 | 
						|
using std::map;
 | 
						|
using std::cerr;
 | 
						|
 | 
						|
namespace llvm {
 | 
						|
 | 
						|
//Routines to get the path trace!
 | 
						|
 | 
						|
void getPathFrmNode(Node *n, vector<BasicBlock*> &vBB, int pathNo, Graph &g, 
 | 
						|
		    vector<Edge> &stDummy, vector<Edge> &exDummy, 
 | 
						|
		    vector<Edge> &be,
 | 
						|
		    double strand){
 | 
						|
  Graph::nodeList &nlist = g.getNodeList(n);
 | 
						|
  
 | 
						|
  //printGraph(g);
 | 
						|
  //std::cerr<<"Path No: "<<pathNo<<"\n";
 | 
						|
  int maxCount=-9999999;
 | 
						|
  bool isStart=false;
 | 
						|
 | 
						|
  if(*n==*g.getRoot())//its root: so first node of path
 | 
						|
    isStart=true;
 | 
						|
 | 
						|
  double edgeRnd=0;
 | 
						|
  Node *nextRoot=n;
 | 
						|
  for(Graph::nodeList::iterator NLI = nlist.begin(), NLE=nlist.end(); NLI!=NLE;
 | 
						|
      ++NLI){
 | 
						|
    if(NLI->weight>maxCount && NLI->weight<=pathNo){
 | 
						|
      maxCount=NLI->weight;
 | 
						|
      nextRoot=NLI->element;
 | 
						|
      edgeRnd=NLI->randId;
 | 
						|
      if(isStart)
 | 
						|
	strand=NLI->randId;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if(!isStart)
 | 
						|
    assert(strand!=-1 && "strand not assigned!"); 
 | 
						|
 | 
						|
  assert(!(*nextRoot==*n && pathNo>0) && "No more BBs to go");
 | 
						|
  assert(!(*nextRoot==*g.getExit() && pathNo-maxCount!=0) && "Reached exit");
 | 
						|
 | 
						|
  vBB.push_back(n->getElement());
 | 
						|
 | 
						|
  if(pathNo-maxCount==0 && *nextRoot==*g.getExit()){
 | 
						|
 | 
						|
    //look for strnd and edgeRnd now:
 | 
						|
    bool has1=false, has2=false;
 | 
						|
    //check if exit has it
 | 
						|
    for(vector<Edge>::iterator VI=exDummy.begin(), VE=exDummy.end(); VI!=VE; 
 | 
						|
	++VI){
 | 
						|
      if(VI->getRandId()==edgeRnd){
 | 
						|
	has2=true;
 | 
						|
	break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    //check if start has it
 | 
						|
    for(vector<Edge>::iterator VI=stDummy.begin(), VE=stDummy.end(); VI!=VE; 
 | 
						|
	++VI){
 | 
						|
      if(VI->getRandId()==strand){
 | 
						|
	has1=true;
 | 
						|
	break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if(has1){
 | 
						|
      //find backedge with endpoint vBB[1]
 | 
						|
      for(vector<Edge>::iterator VI=be.begin(), VE=be.end(); VI!=VE; ++VI){
 | 
						|
	assert(vBB.size()>0 && "vector too small");
 | 
						|
	if( VI->getSecond()->getElement() == vBB[1] ){
 | 
						|
	  //vBB[0]=VI->getFirst()->getElement();
 | 
						|
          vBB.erase(vBB.begin());
 | 
						|
	  break;
 | 
						|
	}
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if(has2){
 | 
						|
      //find backedge with startpoint vBB[vBB.size()-1]
 | 
						|
      for(vector<Edge>::iterator VI=be.begin(), VE=be.end(); VI!=VE; ++VI){
 | 
						|
	assert(vBB.size()>0 && "vector too small");
 | 
						|
	if( VI->getFirst()->getElement() == vBB[vBB.size()-1] && 
 | 
						|
            VI->getSecond()->getElement() == vBB[0]){
 | 
						|
	  //vBB.push_back(VI->getSecond()->getElement());
 | 
						|
	  break;
 | 
						|
	}
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else 
 | 
						|
      vBB.push_back(nextRoot->getElement());
 | 
						|
   
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  assert(pathNo-maxCount>=0);
 | 
						|
 | 
						|
  return getPathFrmNode(nextRoot, vBB, pathNo-maxCount, g, stDummy, 
 | 
						|
			exDummy, be, strand);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static Node *findBB(std::vector<Node *> &st, BasicBlock *BB){
 | 
						|
  for(std::vector<Node *>::iterator si=st.begin(); si!=st.end(); ++si){
 | 
						|
    if(((*si)->getElement())==BB){
 | 
						|
      return *si;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
void getBBtrace(vector<BasicBlock *> &vBB, int pathNo, Function *M){//,
 | 
						|
  //                vector<Instruction *> &instToErase){
 | 
						|
  //step 1: create graph
 | 
						|
  //Transform the cfg s.t. we have just one exit node
 | 
						|
  
 | 
						|
  std::vector<Node *> nodes;
 | 
						|
  std::vector<Edge> edges;
 | 
						|
  Node *exitNode=0, *startNode=0;
 | 
						|
 | 
						|
  //Creat cfg just once for each function!
 | 
						|
  static std::map<Function *, Graph *> graphMap; 
 | 
						|
 | 
						|
  //get backedges, exit and start edges for the graphs and store them
 | 
						|
  static std::map<Function *, vector<Edge> > stMap, exMap, beMap; 
 | 
						|
  static std::map<Function *, Value *> pathReg; //path register
 | 
						|
 | 
						|
 | 
						|
  if(!graphMap[M]){
 | 
						|
    BasicBlock *ExitNode = 0;
 | 
						|
    for (Function::iterator I = M->begin(), E = M->end(); I != E; ++I){
 | 
						|
      if (isa<ReturnInst>(I->getTerminator())) {
 | 
						|
        ExitNode = I;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  
 | 
						|
    assert(ExitNode!=0 && "exitnode not found");
 | 
						|
 | 
						|
    //iterating over BBs and making graph 
 | 
						|
    //The nodes must be uniquely identified:
 | 
						|
    //That is, no two nodes must hav same BB*
 | 
						|
  
 | 
						|
    //keep a map for trigger basicblocks!
 | 
						|
    std::map<BasicBlock *, unsigned char> triggerBBs;
 | 
						|
    //First enter just nodes: later enter edges
 | 
						|
    for(Function::iterator BB = M->begin(), BE=M->end(); BB != BE; ++BB){
 | 
						|
      bool cont = false;
 | 
						|
      
 | 
						|
      if(BB->size()==3 || BB->size() ==2){
 | 
						|
        for(BasicBlock::iterator II = BB->begin(), IE = BB->end();
 | 
						|
            II != IE; ++II){
 | 
						|
          if(CallInst *callInst = dyn_cast<CallInst>(II)){
 | 
						|
            //std::cerr<<*callInst;
 | 
						|
            Function *calledFunction = callInst->getCalledFunction();
 | 
						|
            if(calledFunction && calledFunction->getName() == "trigger"){
 | 
						|
              triggerBBs[BB] = 9;
 | 
						|
              cont = true;
 | 
						|
              //std::cerr<<"Found trigger!\n";
 | 
						|
              break;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
      
 | 
						|
      if(cont)
 | 
						|
        continue;
 | 
						|
      
 | 
						|
      // const Instruction *inst = BB->getInstList().begin();
 | 
						|
      // if(isa<CallInst>(inst)){
 | 
						|
      // Instruction *ii1 = BB->getInstList().begin();
 | 
						|
      // CallInst *callInst = dyn_cast<CallInst>(ii1);
 | 
						|
      // if(callInst->getCalledFunction()->getName()=="trigger")
 | 
						|
      // continue;
 | 
						|
      // }
 | 
						|
      
 | 
						|
      Node *nd=new Node(BB);
 | 
						|
      nodes.push_back(nd); 
 | 
						|
      if(&*BB==ExitNode)
 | 
						|
        exitNode=nd;
 | 
						|
      if(&*BB==&M->front())
 | 
						|
        startNode=nd;
 | 
						|
    }
 | 
						|
 | 
						|
    assert(exitNode!=0 && startNode!=0 && "Start or exit not found!");
 | 
						|
 
 | 
						|
    for (Function::iterator BB = M->begin(), BE=M->end(); BB != BE; ++BB){
 | 
						|
      if(triggerBBs[BB] == 9) 
 | 
						|
        continue;
 | 
						|
      
 | 
						|
      //if(BB->size()==3)
 | 
						|
      //if(CallInst *callInst = dyn_cast<CallInst>(BB->getInstList().begin()))
 | 
						|
      //if(callInst->getCalledFunction()->getName() == "trigger")
 | 
						|
      //continue;
 | 
						|
      
 | 
						|
      // if(BB->size()==2){
 | 
						|
      //         const Instruction *inst = BB->getInstList().begin();
 | 
						|
      //         if(isa<CallInst>(inst)){
 | 
						|
      //           Instruction *ii1 = BB->getInstList().begin();
 | 
						|
      //           CallInst *callInst = dyn_cast<CallInst>(ii1);
 | 
						|
      //           if(callInst->getCalledFunction()->getName()=="trigger")
 | 
						|
      //             continue;
 | 
						|
      //         }
 | 
						|
      //       }
 | 
						|
      
 | 
						|
      Node *nd=findBB(nodes, BB);
 | 
						|
      assert(nd && "No node for this edge!");
 | 
						|
      
 | 
						|
      for(succ_iterator s=succ_begin(BB), se=succ_end(BB); s!=se; ++s){
 | 
						|
        
 | 
						|
        if(triggerBBs[*s] == 9){
 | 
						|
          //if(!pathReg[M]){ //Get the path register for this!
 | 
						|
          //if(BB->size()>8)
 | 
						|
          //  if(LoadInst *ldInst = dyn_cast<LoadInst>(BB->getInstList().begin()))
 | 
						|
          //    pathReg[M] = ldInst->getPointerOperand();
 | 
						|
          //}
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
        //if((*s)->size()==3)
 | 
						|
        //if(CallInst *callInst = 
 | 
						|
        //   dyn_cast<CallInst>((*s)->getInstList().begin()))
 | 
						|
        //  if(callInst->getCalledFunction()->getName() == "trigger")
 | 
						|
        //    continue;
 | 
						|
        
 | 
						|
        //  if((*s)->size()==2){
 | 
						|
        //           const Instruction *inst = (*s)->getInstList().begin();
 | 
						|
        //           if(isa<CallInst>(inst)){
 | 
						|
        //             Instruction *ii1 = (*s)->getInstList().begin();
 | 
						|
        //             CallInst *callInst = dyn_cast<CallInst>(ii1);
 | 
						|
        //             if(callInst->getCalledFunction()->getName()=="trigger")
 | 
						|
        //               continue;
 | 
						|
        //           }
 | 
						|
        //         }
 | 
						|
        
 | 
						|
        Node *nd2 = findBB(nodes,*s);
 | 
						|
        assert(nd2 && "No node for this edge!");
 | 
						|
        Edge ed(nd,nd2,0);
 | 
						|
        edges.push_back(ed);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  
 | 
						|
    graphMap[M]= new Graph(nodes,edges, startNode, exitNode);
 | 
						|
 
 | 
						|
    Graph *g = graphMap[M];
 | 
						|
 | 
						|
    if (M->size() <= 1) return; //uninstrumented 
 | 
						|
    
 | 
						|
    //step 2: getBackEdges
 | 
						|
    //vector<Edge> be;
 | 
						|
    std::map<Node *, int> nodePriority;
 | 
						|
    g->getBackEdges(beMap[M], nodePriority);
 | 
						|
    
 | 
						|
    //step 3: add dummy edges
 | 
						|
    //vector<Edge> stDummy;
 | 
						|
    //vector<Edge> exDummy;
 | 
						|
    addDummyEdges(stMap[M], exMap[M], *g, beMap[M]);
 | 
						|
    
 | 
						|
    //step 4: value assgn to edges
 | 
						|
    int numPaths = valueAssignmentToEdges(*g, nodePriority, beMap[M]);
 | 
						|
  }
 | 
						|
  
 | 
						|
  
 | 
						|
  //step 5: now travel from root, select max(edge) < pathNo, 
 | 
						|
  //and go on until reach the exit
 | 
						|
  getPathFrmNode(graphMap[M]->getRoot(), vBB, pathNo, *graphMap[M], 
 | 
						|
                 stMap[M], exMap[M], beMap[M], -1);
 | 
						|
  
 | 
						|
 | 
						|
  //post process vBB to locate instructions to be erased
 | 
						|
  /*
 | 
						|
  if(pathReg[M]){
 | 
						|
    for(vector<BasicBlock *>::iterator VBI = vBB.begin(), VBE = vBB.end();
 | 
						|
        VBI != VBE; ++VBI){
 | 
						|
      for(BasicBlock::iterator BBI = (*VBI)->begin(), BBE = (*VBI)->end();
 | 
						|
          BBI != BBE; ++BBI){
 | 
						|
        if(LoadInst *ldInst = dyn_cast<LoadInst>(BBI)){
 | 
						|
          if(pathReg[M] == ldInst->getPointerOperand())
 | 
						|
            instToErase.push_back(ldInst);
 | 
						|
        }
 | 
						|
        else if(StoreInst *stInst = dyn_cast<StoreInst>(BBI)){
 | 
						|
          if(pathReg[M] == stInst->getPointerOperand())
 | 
						|
            instToErase.push_back(stInst);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  */
 | 
						|
}
 | 
						|
 | 
						|
} // End llvm namespace
 |