LLVM API Documentation

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

EdgeCode.cpp

Go to the documentation of this file.
00001 //===-- EdgeCode.cpp - generate LLVM instrumentation code -----------------===//
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 //It implements the class EdgeCode: which provides 
00010 //support for inserting "appropriate" instrumentation at
00011 //designated points in the graph
00012 //
00013 //It also has methods to insert initialization code in 
00014 //top block of cfg
00015 //===----------------------------------------------------------------------===//
00016 
00017 #include "Graph.h"
00018 #include "llvm/Constants.h"
00019 #include "llvm/DerivedTypes.h"
00020 #include "llvm/Instructions.h"
00021 #include "llvm/Module.h"
00022 
00023 #define INSERT_LOAD_COUNT
00024 #define INSERT_STORE
00025 
00026 
00027 using std::vector;
00028 
00029 namespace llvm {
00030 
00031 static void getTriggerCode(Module *M, BasicBlock *BB, int MethNo, Value *pathNo,
00032                            Value *cnt, Instruction *rInst){ 
00033   
00034   vector<Value *> tmpVec;
00035   tmpVec.push_back(Constant::getNullValue(Type::LongTy));
00036   tmpVec.push_back(Constant::getNullValue(Type::LongTy));
00037   Instruction *Idx = new GetElementPtrInst(cnt, tmpVec, "");//,
00038   BB->getInstList().push_back(Idx);
00039 
00040   const Type *PIntTy = PointerType::get(Type::IntTy);
00041   Function *trigMeth = M->getOrInsertFunction("trigger", Type::VoidTy, 
00042                                               Type::IntTy, Type::IntTy,
00043                                               PIntTy, PIntTy, 0);
00044   assert(trigMeth && "trigger method could not be inserted!");
00045 
00046   vector<Value *> trargs;
00047 
00048   trargs.push_back(ConstantSInt::get(Type::IntTy,MethNo));
00049   trargs.push_back(pathNo);
00050   trargs.push_back(Idx);
00051   trargs.push_back(rInst);
00052 
00053   Instruction *callInst=new CallInst(trigMeth, trargs, "");//, BB->begin());
00054   BB->getInstList().push_back(callInst);
00055   //triggerInst = new CallInst(trigMeth, trargs, "");//, InsertPos);
00056 }
00057 
00058 
00059 //get the code to be inserted on the edge
00060 //This is determined from cond (1-6)
00061 void getEdgeCode::getCode(Instruction *rInst, Value *countInst, 
00062         Function *M, BasicBlock *BB, 
00063                           vector<Value *> &retVec){
00064   
00065   //Instruction *InsertPos = BB->getInstList().begin();
00066   
00067   //now check for cdIn and cdOut
00068   //first put cdOut
00069   if(cdOut!=NULL){
00070     cdOut->getCode(rInst, countInst, M, BB, retVec);
00071   }
00072   
00073   if(cdIn!=NULL){
00074     cdIn->getCode(rInst, countInst, M, BB, retVec);
00075   }
00076 
00077   //case: r=k code to be inserted
00078   switch(cond){
00079   case 1:{
00080     Value *val=ConstantSInt::get(Type::IntTy,inc);
00081 #ifdef INSERT_STORE
00082     Instruction *stInst=new StoreInst(val, rInst);//, InsertPos);
00083     BB->getInstList().push_back(stInst);
00084 #endif
00085     break;
00086     }
00087 
00088   //case: r=0 to be inserted
00089   case 2:{
00090 #ifdef INSERT_STORE
00091     Instruction *stInst = new StoreInst(ConstantSInt::getNullValue(Type::IntTy), rInst);//, InsertPos);
00092      BB->getInstList().push_back(stInst);
00093 #endif
00094     break;
00095   }
00096     
00097   //r+=k
00098   case 3:{
00099     Instruction *ldInst = new LoadInst(rInst, "ti1");//, InsertPos);
00100     BB->getInstList().push_back(ldInst);
00101     Value *val = ConstantSInt::get(Type::IntTy,inc);
00102     Instruction *addIn = BinaryOperator::create(Instruction::Add, ldInst, val,
00103                                           "ti2");//, InsertPos);
00104     BB->getInstList().push_back(addIn);
00105 #ifdef INSERT_STORE
00106     Instruction *stInst = new StoreInst(addIn, rInst);//, InsertPos);
00107     BB->getInstList().push_back(stInst);
00108 #endif
00109     break;
00110   }
00111 
00112   //count[inc]++
00113   case 4:{
00114     vector<Value *> tmpVec;
00115     tmpVec.push_back(Constant::getNullValue(Type::LongTy));
00116     tmpVec.push_back(ConstantSInt::get(Type::LongTy, inc));
00117     Instruction *Idx = new GetElementPtrInst(countInst, tmpVec, "");//,
00118 
00119     //Instruction *Idx = new GetElementPtrInst(countInst, 
00120     //           vector<Value*>(1,ConstantSInt::get(Type::LongTy, inc)),
00121     //                                       "");//, InsertPos);
00122     BB->getInstList().push_back(Idx);
00123 
00124     Instruction *ldInst=new LoadInst(Idx, "ti1");//, InsertPos);
00125     BB->getInstList().push_back(ldInst);
00126  
00127     Value *val = ConstantSInt::get(Type::IntTy, 1);
00128     //Instruction *addIn =
00129     Instruction *newCount =
00130       BinaryOperator::create(Instruction::Add, ldInst, val,"ti2");
00131     BB->getInstList().push_back(newCount);
00132     
00133 
00134 #ifdef INSERT_STORE
00135     //Instruction *stInst=new StoreInst(addIn, Idx, InsertPos);
00136     Instruction *stInst=new StoreInst(newCount, Idx);//, InsertPos);
00137     BB->getInstList().push_back(stInst);
00138 #endif
00139     
00140     Value *trAddIndex = ConstantSInt::get(Type::IntTy,inc);
00141 
00142     retVec.push_back(newCount);
00143     retVec.push_back(trAddIndex);
00144     //insert trigger
00145     //getTriggerCode(M->getParent(), BB, MethNo, 
00146     //     ConstantSInt::get(Type::IntTy,inc), newCount, triggerInst);
00147     //end trigger code
00148 
00149     assert(inc>=0 && "IT MUST BE POSITIVE NOW");
00150     break;
00151   }
00152 
00153   //case: count[r+inc]++
00154   case 5:{
00155    
00156     //ti1=inc+r
00157     Instruction *ldIndex=new LoadInst(rInst, "ti1");//, InsertPos);
00158     BB->getInstList().push_back(ldIndex);
00159 
00160     Value *val=ConstantSInt::get(Type::IntTy,inc);
00161     Instruction *addIndex=BinaryOperator::
00162       create(Instruction::Add, ldIndex, val,"ti2");//, InsertPos);
00163     BB->getInstList().push_back(addIndex);
00164     
00165     //now load count[addIndex]
00166     Instruction *castInst=new CastInst(addIndex, 
00167                Type::LongTy,"ctin");//, InsertPos);
00168     BB->getInstList().push_back(castInst);
00169 
00170     vector<Value *> tmpVec;
00171     tmpVec.push_back(Constant::getNullValue(Type::LongTy));
00172     tmpVec.push_back(castInst);
00173     Instruction *Idx = new GetElementPtrInst(countInst, tmpVec, "");//,
00174     //                                             InsertPos);
00175     BB->getInstList().push_back(Idx);
00176 
00177     Instruction *ldInst=new LoadInst(Idx, "ti3");//, InsertPos);
00178     BB->getInstList().push_back(ldInst);
00179 
00180     Value *cons=ConstantSInt::get(Type::IntTy,1);
00181     //count[addIndex]++
00182     //std::cerr<<"Type ldInst:"<<ldInst->getType()<<"\t cons:"<<cons->getType()<<"\n";
00183     Instruction *newCount = BinaryOperator::create(Instruction::Add, ldInst, 
00184                                                    cons,"");
00185     BB->getInstList().push_back(newCount);
00186     
00187 #ifdef INSERT_STORE
00188     Instruction *stInst = new StoreInst(newCount, Idx);//, InsertPos);
00189     BB->getInstList().push_back(stInst);
00190 #endif
00191 
00192     retVec.push_back(newCount);
00193     retVec.push_back(addIndex);
00194     //insert trigger
00195     //getTriggerCode(M->getParent(), BB, MethNo, addIndex, newCount, triggerInst);
00196     //end trigger code
00197 
00198     break;
00199   }
00200 
00201     //case: count[r]+
00202   case 6:{
00203     //ti1=inc+r
00204     Instruction *ldIndex=new LoadInst(rInst, "ti1");//, InsertPos);
00205     BB->getInstList().push_back(ldIndex);
00206 
00207     //now load count[addIndex]
00208     Instruction *castInst2=new CastInst(ldIndex, Type::LongTy,"ctin");
00209     BB->getInstList().push_back(castInst2);
00210 
00211     vector<Value *> tmpVec;
00212     tmpVec.push_back(Constant::getNullValue(Type::LongTy));
00213     tmpVec.push_back(castInst2);
00214     Instruction *Idx = new GetElementPtrInst(countInst, tmpVec, "");//,
00215 
00216     //Instruction *Idx = new GetElementPtrInst(countInst, 
00217     //                                       vector<Value*>(1,castInst2), "");
00218     
00219     BB->getInstList().push_back(Idx);
00220     
00221     Instruction *ldInst=new LoadInst(Idx, "ti2");//, InsertPos);
00222     BB->getInstList().push_back(ldInst);
00223 
00224     Value *cons=ConstantSInt::get(Type::IntTy,1);
00225 
00226     //count[addIndex]++
00227     Instruction *newCount = BinaryOperator::create(Instruction::Add, ldInst,
00228                                                    cons,"ti3");
00229     BB->getInstList().push_back(newCount);
00230 
00231 #ifdef INSERT_STORE
00232     Instruction *stInst = new StoreInst(newCount, Idx);//, InsertPos);
00233     BB->getInstList().push_back(stInst);
00234 #endif
00235 
00236     retVec.push_back(newCount);
00237     retVec.push_back(ldIndex);
00238     break;
00239   }
00240     
00241   }
00242 }
00243 
00244 
00245 
00246 //Insert the initialization code in the top BB
00247 //this includes initializing r, and count
00248 //r is like an accumulator, that 
00249 //keeps on adding increments as we traverse along a path
00250 //and at the end of the path, r contains the path
00251 //number of that path
00252 //Count is an array, where Count[k] represents
00253 //the number of executions of path k
00254 void insertInTopBB(BasicBlock *front, 
00255        int k, 
00256        Instruction *rVar, Value *threshold){
00257   //rVar is variable r, 
00258   //countVar is count[]
00259 
00260   Value *Int0 = ConstantInt::get(Type::IntTy, 0);
00261   
00262   //now push all instructions in front of the BB
00263   BasicBlock::iterator here=front->begin();
00264   front->getInstList().insert(here, rVar);
00265   //front->getInstList().insert(here,countVar);
00266   
00267   //Initialize Count[...] with 0
00268 
00269   //for (int i=0;i<k; i++){
00270   //Value *GEP2 = new GetElementPtrInst(countVar,
00271   //                      vector<Value *>(1,ConstantSInt::get(Type::LongTy, i)),
00272   //                                    "", here);
00273   //new StoreInst(Int0, GEP2, here);
00274   //}
00275 
00276   //store uint 0, uint *%R
00277   new StoreInst(Int0, rVar, here);
00278 }
00279 
00280 
00281 //insert a basic block with appropriate code
00282 //along a given edge
00283 void insertBB(Edge ed,
00284         getEdgeCode *edgeCode, 
00285         Instruction *rInst, 
00286         Value *countInst, 
00287         int numPaths, int Methno, Value *threshold){
00288 
00289   BasicBlock* BB1=ed.getFirst()->getElement();
00290   BasicBlock* BB2=ed.getSecond()->getElement();
00291   
00292 #ifdef DEBUG_PATH_PROFILES
00293   //debugging info
00294   cerr<<"Edges with codes ######################\n";
00295   cerr<<BB1->getName()<<"->"<<BB2->getName()<<"\n";
00296   cerr<<"########################\n";
00297 #endif
00298   
00299   //We need to insert a BB between BB1 and BB2 
00300   TerminatorInst *TI=BB1->getTerminator();
00301   BasicBlock *newBB=new BasicBlock("counter", BB1->getParent());
00302 
00303   //get code for the new BB
00304   vector<Value *> retVec;
00305 
00306   edgeCode->getCode(rInst, countInst, BB1->getParent(), newBB, retVec);
00307 
00308   BranchInst *BI =  cast<BranchInst>(TI);
00309 
00310   //Is terminator a branch instruction?
00311   //then we need to change branch destinations to include new BB
00312 
00313   if(BI->isUnconditional()){
00314     BI->setUnconditionalDest(newBB);
00315   }
00316   else{
00317       if(BI->getSuccessor(0)==BB2)
00318       BI->setSuccessor(0, newBB);
00319     
00320     if(BI->getSuccessor(1)==BB2)
00321       BI->setSuccessor(1, newBB);
00322   }
00323 
00324   BasicBlock *triggerBB = NULL;
00325   if(retVec.size()>0){
00326     triggerBB = new BasicBlock("trigger", BB1->getParent());
00327     getTriggerCode(BB1->getParent()->getParent(), triggerBB, Methno, 
00328                    retVec[1], countInst, rInst);//retVec[0]);
00329 
00330     //Instruction *castInst = new CastInst(retVec[0], Type::IntTy, "");
00331     Instruction *etr = new LoadInst(threshold, "threshold");
00332     
00333     //std::cerr<<"type1: "<<etr->getType()<<" type2: "<<retVec[0]->getType()<<"\n"; 
00334     Instruction *cmpInst = new SetCondInst(Instruction::SetLE, etr, 
00335                                            retVec[0], "");
00336     Instruction *newBI2 = new BranchInst(triggerBB, BB2, cmpInst);
00337     //newBB->getInstList().push_back(castInst);
00338     newBB->getInstList().push_back(etr);
00339     newBB->getInstList().push_back(cmpInst);
00340     newBB->getInstList().push_back(newBI2);
00341     
00342     //triggerBB->getInstList().push_back(triggerInst);
00343     new BranchInst(BB2, 0, 0, triggerBB);
00344   }
00345   else{
00346     new BranchInst(BB2, 0, 0, newBB);
00347   }
00348 
00349   //now iterate over BB2, and set its Phi nodes right
00350   for(BasicBlock::iterator BB2Inst = BB2->begin(), BBend = BB2->end(); 
00351       BB2Inst != BBend; ++BB2Inst){
00352    
00353     if(PHINode *phiInst=dyn_cast<PHINode>(BB2Inst)){
00354       int bbIndex=phiInst->getBasicBlockIndex(BB1);
00355       assert(bbIndex>=0);
00356       phiInst->setIncomingBlock(bbIndex, newBB);
00357 
00358       ///check if trigger!=null, then add value corresponding to it too!
00359       if(retVec.size()>0){
00360         assert(triggerBB && "BasicBlock with trigger should not be null!");
00361         Value *vl = phiInst->getIncomingValue((unsigned int)bbIndex);
00362         phiInst->addIncoming(vl, triggerBB);
00363       }
00364     }
00365   }
00366 }
00367 
00368 } // End llvm namespace