Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

/users/u3/mtikir/PMaCInstrumentor_v1601/src/Function.C

Go to the documentation of this file.
00001 #include <SectHeader.h>
00002 #include <Instruction.h>
00003 #include <RawSection.h>
00004 #include <SymbolTable.h>
00005 #include <DemangleWrapper.h>
00006 #include <Instruction.h>
00007 #include <Function.h>
00008 #include <Iterator.h>
00009 #include <XCoffFile.h>
00010 #include <BitSet.h>
00011 #include <BinaryFile.h>
00012 #include <Loop.h>
00013 #include <Stack.h>
00014 #include <LinkedList.h>
00015 #include <LengauerTarjan.h>
00016 
00017 TIMER(
00018     double cfg_s1=0.0;
00019     double cfg_s2=0.0;
00020     double cfg_s3=0.0;
00021     double cfg_s4=0.0;
00022     double cfg_s5=0.0;
00023 );
00024 
00025 void FlowGraph::printInnerLoops(){
00026     for (uint32_t i = 0; i < numberOfLoops; i++){
00027         for (uint32_t j = 0; j < numberOfLoops; j++){
00028             if (loops[i]->isInnerLoop(loops[j])){
00029                 PRINT_INFOR("Loop %d is inside loop %d", j, i);
00030             }
00031             if (i == j){
00032                 ASSERT(loops[i]->isIdenticalLoop(loops[j]));
00033             } else {
00034                 ASSERT(!loops[i]->isIdenticalLoop(loops[j]));
00035             }
00036         }
00037     }
00038 }
00039 
00040 int compareLoopHeaderVaddr(const void* arg1,const void* arg2){
00041     Loop* lp1 = *((Loop**)arg1);
00042     Loop* lp2 = *((Loop**)arg2);
00043     uint64_t vl1 = lp1->getHead()->getBaseAddress();
00044     uint64_t vl2 = lp2->getHead()->getBaseAddress();
00045 
00046     if(vl1 < vl2)
00047         return -1;
00048     if(vl1 > vl2)
00049         return 1;
00050     return 0;
00051 }
00052 
00053 void FlowGraph::buildLoops(){
00054     if(loops){
00055         return;
00056     }
00057 
00058     PRINT_DEBUG("Considering flowgraph for function %d -- has %d blocks", function->getIndex(),  numOfBasicBlocks);
00059 
00060     numberOfLoops = 0;
00061     loops = NULL;
00062 
00063     BasicBlock** allBlocks = getAllBlocks();
00064 
00065     LinkedList<BasicBlock*> backEdges;
00066     BitSet <BasicBlock*>* visitedBitSet = newBitSet();
00067     BitSet <BasicBlock*>* completedBitSet = newBitSet();
00068 
00069     depthFirstSearch(allBlocks[0],visitedBitSet,true,completedBitSet,&backEdges);
00070 
00071     delete visitedBitSet;
00072     delete completedBitSet;
00073 
00074     if(backEdges.empty()){
00075         PRINT_DEBUG("\t%d Contains %d loops (back edges) from %d", getIndex(),numberOfLoops,numOfBasicBlocks);
00076         return;
00077     }
00078 
00079     ASSERT(!(backEdges.size() % 2) && "Fatal: Back edge list should be multiple of 2, (from->to)");
00080     BitSet<BasicBlock*>* inLoop = newBitSet();
00081     Stack<BasicBlock*> loopStack(numOfBasicBlocks);
00082     LinkedList<Loop*> loopList;
00083 
00084     while(!backEdges.empty()){
00085 
00086         BasicBlock* from = backEdges.shift();
00087         BasicBlock* to = backEdges.shift();
00088         ASSERT(from && to && "Fatal: Backedge end points are invalid");
00089 
00090         if(from->isDominatedBy(to)){
00091             /* for each back edge found, perform natural loop finding algorithm 
00092                from pg. 604 of the Aho/Sethi/Ullman (Dragon) compiler book */
00093 
00094             numberOfLoops++;
00095 
00096             loopStack.clear();
00097             inLoop->clear();
00098 
00099             inLoop->insert(to->getIndex());
00100             if (!inLoop->contains(from->getIndex())){
00101                 inLoop->insert(from->getIndex());
00102                 loopStack.push(from);
00103             }
00104             while(!loopStack.empty()){
00105                 BasicBlock* top = loopStack.pop();
00106                 uint32_t numOfSources = top->getNumOfSources();
00107                 for (uint32_t m = 0; m < numOfSources; m++){
00108                     BasicBlock* pred = top->getSourceBlock(m);
00109                     if (!inLoop->contains(pred->getIndex())){
00110                         inLoop->insert(pred->getIndex());
00111                         loopStack.push(pred);
00112                     }
00113                 }
00114             }
00115 
00116             Loop* newLoop = new Loop(to, from, this, inLoop);
00117             loopList.insert(newLoop);
00118 
00119             DEBUG_MORE(
00120                 newLoop->print()
00121             );
00122         }
00123     }
00124 
00125     ASSERT((loopList.size() == numberOfLoops) && 
00126         "Fatal: Number of loops should match backedges defining them");
00127 
00128     delete inLoop;
00129 
00130     PRINT_DEBUG("\t%d Contains %d loops (back edges) from %d", getIndex(),numberOfLoops,numOfBasicBlocks);
00131 
00132     if(numberOfLoops){
00133         loops = new Loop*[numberOfLoops];
00134         uint32_t i = 0;
00135         while(!loopList.empty()){
00136             loops[i++] = loopList.shift();
00137         }
00138         ASSERT(numberOfLoops == i);
00139 
00140         qsort(loops,numberOfLoops,sizeof(Loop*),compareLoopHeaderVaddr);
00141         for(i=0;i<numberOfLoops;i++){
00142             loops[i]->setIndex(i);
00143         }
00144     } 
00145     ASSERT(!loopList.size());
00146 
00147     DEBUG_MORE(printInnerLoops());
00148 }
00149 
00150 BasicBlock* FlowGraph::getEntryBlock(){
00151     for (uint32_t i = 0; i < numOfBasicBlocks; i++){
00152         if (basicBlocks[i]->isEntry()){
00153             return basicBlocks[i];
00154         }
00155     }
00156     ASSERT(0 && "No entry block found");
00157     return NULL;
00158 }
00159 
00160 MemoryOperation::MemoryOperation(Instruction insn,uint64_t addr,BasicBlock* bb,uint32_t idx)
00161     : instruction(insn),basicBlock(bb),index(idx)
00162 {
00163     ASSERT(insn.isMemoryOperation() && 
00164            "FATAL : Only the memory instructions can form memory operation");
00165     offset = (uint32_t)(addr-basicBlock->getBaseAddress());
00166     hashCode = HashCode(basicBlock->getFlowGraph()->getRawSection()->getIndex(),
00167                        basicBlock->getFlowGraph()->getFunction()->getIndex(),
00168                        basicBlock->getIndex(),
00169                        index);
00170 }
00171 
00172 Operand MemoryOperation::getAddressOperand1(){
00173     uint32_t src1 = 0;
00174     if(isDForm() || isDsForm())
00175         src1 = instruction.getDFormSrc1();
00176     else if(isXForm())
00177         src1 = instruction.getXFormSrc1();
00178 
00179     if(src1)
00180         return Operand::GPRegisterOperands[src1];
00181 
00182     return Operand::IntegerOperand0;
00183 }
00184 
00185 Operand MemoryOperation::getAddressOperand2(){
00186     if(isDForm() || isDsForm()) {
00187         int32_t offset = instruction.getDFormImmediate();
00188         if(isDsForm())
00189             offset = instruction.getDsFormImmediate();
00190         return IntegerOperand(offset);
00191     } else if(isXForm()){
00192         uint32_t src2 = instruction.getXFormSrc2();
00193         if(instruction.isMemoryXFormButNoSrc2())
00194             return Operand::IntegerOperand0;
00195         else
00196             return Operand::GPRegisterOperands[src2];
00197     }
00198     return Operand::IntegerOperand0;
00199 }
00200 bool MemoryOperation::isDForm(){
00201     return instruction.isMemoryDForm();
00202 }
00203 bool MemoryOperation::isDsForm(){
00204     return instruction.isMemoryDsForm();
00205 }
00206 bool MemoryOperation::isXForm(){
00207     return instruction.isMemoryXForm();
00208 }
00209 void MemoryOperation::print(){
00210     PRINT_INFOR("\t(mem %#12llx) (idx %4d) (unq %#12llx)",
00211         offset+basicBlock->getBaseAddress(),index,getHashCode().getValue());
00212     getAddressOperand1().print();
00213     getAddressOperand2().print();
00214 }
00215 
00216 uint64_t MemoryOperation::getInsnAddr(){
00217     return (offset + basicBlock->getBaseAddress());
00218 }
00219 
00220 void BasicBlock::addEdge(BasicBlock* to)
00221 { 
00222     ASSERT(to && "FATAL : Invalid block is being added as an edge");
00223     if(isJumpTable() || to->isJumpTable() || isTrace() || to->isTrace()){
00224         PRINT_DEBUG("Inserting edge between JumpTable/TraceBack");
00225         return;
00226     }
00227 }
00228 
00229 AddressIterator BasicBlock::getInstructionIterator(){
00230     return AddressIterator::newAddressIteratorWord(baseAddress,sizeInBytes);
00231 }
00232 
00233 RawSection* BasicBlock::getRawSection(){
00234     return flowGraph->getRawSection();
00235 }
00236 
00237 void BasicBlock::findMemoryFloatOps(){
00238     if(isTrace() || isJumpTable())
00239         return;
00240 
00241     uint32_t insnCount = 0;
00242     numOfMemoryOps = 0;
00243 
00244     MemoryOperation** insnArr = new MemoryOperation*[getInstructionCount()];
00245 
00246     AddressIterator ait = getInstructionIterator();
00247     while(ait.hasMore()){
00248         insnCount++;
00249         Instruction insn = getRawSection()->readInstruction(&ait);
00250         if(insn.isMemoryOperation() && !insn.isUnhandledMemoryOp()){
00251             insnArr[numOfMemoryOps] = new MemoryOperation(insn,*ait,this,numOfMemoryOps);
00252             numOfMemoryOps++;
00253         } else if(insn.isFloatPOperation()){
00254             numOfFloatPOps++;
00255         } else if(insn.isUnhandledMemoryOp()){
00256             PRINT_INFOR("Unhandled memop bits of block %#llx, %dth instruction,\taddr %#llx\tvalue %x", 
00257                         getBaseAddress(), insnCount, *ait, insn.bits());
00258 //          ASSERT(0 && "FATAL : This is an unhandled memory operation");
00259         }
00260         ait++;
00261     }
00262 
00263     if(numOfMemoryOps){
00264         memoryOps = new MemoryOperation*[numOfMemoryOps];
00265         for(uint32_t i=0;i<numOfMemoryOps;i++){
00266             memoryOps[i] = insnArr[i];
00267         }
00268     }
00269 
00270     delete[] insnArr;
00271 }
00272 
00273 void BasicBlock::print(){
00274     PRINT_INFOR("[B(idx %5d) (adr %#12llx,%#12llx) (sz %4d) (unq %#12llx) (dom %d) (flgs %#8x)",
00275                 index,baseAddress,(baseAddress+sizeInBytes),sizeInBytes,
00276                 getHashCode().getValue(),immDominatedBy ? immDominatedBy->getIndex() : -1,
00277                 flags);
00278 
00279     for(uint32_t i=0;i<numOfTargets;i++){
00280         BasicBlock* bb = targets[i];
00281         PRINT_INFOR("\t(tgt %5d)",bb->getIndex());
00282     }
00283 
00284     for(uint32_t i=0;i<numOfSources;i++){
00285         BasicBlock* bb = sources[i];
00286         PRINT_INFOR("\t(src %5d)",bb->getIndex());
00287     }
00288 
00289 
00290     PRINT_INFOR("\t(inst %5d) (mops %3d) (fops %3d)",getInstructionCount(),numOfMemoryOps,numOfFloatPOps);
00291     for(uint32_t i=0;i<numOfMemoryOps;i++){
00292         memoryOps[i]->print();
00293     }
00294 
00295     AddressIterator ait = getInstructionIterator();
00296     while(ait.hasMore()){
00297         Instruction insn = getRawSection()->readInstruction(&ait);
00298         insn.print(*ait,getXCoffFile()->is64Bit());
00299         ait++;
00300     }
00301     PRINT_INFOR("]");
00302 }
00303 
00304 void BasicBlock::setIndex(uint32_t idx){
00305     index = idx;
00306     hashCode = HashCode(flowGraph->getRawSection()->getIndex(),
00307                         flowGraph->getFunction()->getIndex(),
00308                         index);
00309     
00310     ASSERT(hashCode.isBlock() && "FATAL : the has code for the block is not right");
00311 }
00312 
00313 RawSection* FlowGraph::getRawSection(){
00314     return function->getRawSection();
00315 }
00316 
00317 uint32_t FlowGraph::getIndex() { 
00318     return function->getIndex(); 
00319 }
00320 
00321 uint32_t FlowGraph::getAllBlocks(BasicBlock** arr){
00322     for(uint32_t i=0;i<numOfBasicBlocks;i++)
00323         arr[i] = basicBlocks[i];
00324     return numOfBasicBlocks;
00325 }
00326 
00327 uint32_t FlowGraph::initializeAllBlocks(BasicBlock** blockArray,BasicBlock* traceBlock,uint32_t arrCount){
00328 
00329     ASSERT("blockArray has to be sorted interms of block base addresses");
00330 
00331     uint32_t totalCount = (traceBlock ? 1 : 0);
00332 
00333     for(uint32_t i=0;i<arrCount;i++){
00334         if(blockArray[i]){
00335             totalCount++;
00336         }
00337     }
00338 
00339     if(totalCount){
00340 
00341         numOfBasicBlocks = totalCount;
00342         basicBlocks = new BasicBlock*[totalCount];
00343 
00344         if(traceBlock){
00345             totalCount--;
00346             traceBlock->setIndex(totalCount);
00347             basicBlocks[totalCount] = traceBlock;
00348         }
00349 
00350         uint32_t idx = 0;
00351         for(uint32_t i = 0;idx<totalCount;i++){
00352             BasicBlock* bb = blockArray[i];
00353             if(!bb)
00354                 continue;
00355             bb->setIndex(idx);
00356             basicBlocks[idx++] = bb;
00357         }
00358     }
00359 
00360     return numOfBasicBlocks;
00361 }
00362 
00363 void FlowGraph::findMemoryFloatOps(){
00364     if(!numOfBasicBlocks)
00365         return;
00366 
00367     for(uint32_t i=0;i<numOfBasicBlocks;i++){
00368         basicBlocks[i]->findMemoryFloatOps();
00369     }
00370 }
00371 
00372 
00373 void FlowGraph::print(){
00374     PRINT_INFOR("[G(idx %5d) (#bb %6d) (unq %#12llx)",
00375             getIndex(),numOfBasicBlocks,function->getHashCode().getValue());
00376 
00377     if(!numOfBasicBlocks){
00378         PRINT_INFOR("]");
00379         return;
00380     }
00381 
00382     for(uint32_t i=0;i<numOfBasicBlocks;i++){
00383         basicBlocks[i]->print();
00384     }
00385 
00386     PRINT_INFOR("]");
00387 
00388     for (uint32_t i = 0; i < numberOfLoops; i++){
00389         loops[i]->print();
00390     }
00391 }
00392 
00393 BitSet<BasicBlock*>* FlowGraph::newBitSet() { 
00394     if(numOfBasicBlocks)
00395         return new BitSet<BasicBlock*>(numOfBasicBlocks,basicBlocks); 
00396     return NULL;
00397 }
00398 
00399 Function::Function(uint32_t idx,uint32_t symCount,Symbol** symbols,RawSection* sect)
00400     : rawSection(sect),index(idx),numOfAllSymbols(symCount),insnSizeInBytes(0),
00401       flowGraph(NULL) {
00402 
00403     ASSERT(numOfAllSymbols && "FATAL : there should be at least one symbol for the function");
00404 
00405     allSymbols = new Symbol*[numOfAllSymbols];
00406 
00407     for(uint32_t i=0;i<numOfAllSymbols;i++){
00408         allSymbols[i] = symbols[i];
00409     }
00410     for(uint32_t i=0;i<numOfAllSymbols;i++){
00411         ASSERT(allSymbols[0]->GET(n_value) == allSymbols[i]->GET(n_value)); 
00412     }
00413 
00414     SymbolTable* symbolTable = rawSection->getSymbolTable();
00415     ASSERT(symbolTable && "FATAL : Every raw section should have the same symbol table not NULL");
00416 
00417     baseAddress = allSymbols[0]->GET(n_value);
00418     sizeInBytes = (uint32_t)(symbolTable->getSymbolLength(allSymbols[0]));
00419 
00420     hashCode = HashCode(rawSection->getIndex(),index);
00421     ASSERT(hashCode.isFunction() && "FATAL : the has code for the function is not right");
00422 
00423 }
00424 
00425 uint32_t Function::getAllSymbolNames(char* buffer,uint32_t len,bool onlyFirst){
00426     uint32_t ret = 0;
00427     uint32_t howMany = numOfAllSymbols;
00428     if(onlyFirst){
00429         howMany = 1;
00430     }
00431     SymbolTable* symbolTable = rawSection->getSymbolTable();
00432     if(buffer && len){
00433         char* ptr = buffer;
00434         for(uint32_t i=0;i<howMany;i++){
00435             char* name = symbolTable->getSymbolName(allSymbols[i]);
00436             uint32_t namelen = strlen(name);
00437 
00438             namelen = (len < namelen ? len : namelen);
00439             strncpy(ptr,name,namelen);
00440             ptr += namelen;
00441             len -= namelen;
00442             free(name);
00443 
00444             if(!len){
00445                 ptr--;
00446                 break;
00447             }
00448             if(i != (howMany-1)){
00449                 *ptr = ' ';
00450                 ptr++;
00451                 len--;
00452             }
00453         }
00454         *ptr = '\0';
00455         ret = (uint32_t)(ptr-buffer);
00456     }
00457     return ret;
00458 }
00459 
00460 void Function::print(){
00461     SymbolTable* symbolTable = rawSection->getSymbolTable();
00462 
00463     PRINT_INFOR("");
00464     PRINT_INFOR("[F(idx %5d) (bsz %#12llx,%5d) (trb %5d,%5d) (unq %#12llx)",
00465         index,baseAddress,sizeInBytes,insnSizeInBytes,sizeInBytes-insnSizeInBytes,
00466         getHashCode().getValue());
00467 
00468     for(uint32_t i=0;i<numOfAllSymbols;i++){
00469         char* name = symbolTable->getSymbolName(allSymbols[i]);
00470         uint64_t symSize = symbolTable->getSymbolLength(allSymbols[i]);
00471 
00472         DemangleWrapper wrapper;
00473         char* demangled = wrapper.demangle_combined(name);
00474 
00475         PRINT_INFOR("\t(sym %3lld,%3d,%s)",symSize,symbolTable->getStorageMapping(allSymbols[i]),demangled);
00476 
00477         free(name);
00478     }
00479 
00480     if(flowGraph)
00481         flowGraph->print();
00482 
00483     PRINT_INFOR("]");
00484     PRINT_INFOR("");
00485 }
00486 
00487 void Function::updateInstructionSize(){
00488 
00489     insnSizeInBytes = sizeInBytes;
00490 
00491     AddressIterator ait = getAddressIterator();
00492 
00493     while(ait.hasMore()){
00494         Instruction insn = rawSection->readInstruction(&ait);
00495         if(insn.isZero()){
00496             break;
00497         }
00498         ++ait;
00499     }
00500 
00501     if(ait.hasMore()){
00502         insnSizeInBytes = (uint32_t)(ait.getOffset());
00503     }
00504 }
00505 
00506 bool Function::getJumpTableInformation(uint64_t* jumpTableAddr,
00507                                        uint32_t* jumpTableEntryCount,
00508                                        AddressIterator ait)
00509 {
00510     *jumpTableAddr = 0;
00511     *jumpTableEntryCount = 0;
00512 
00513     ASSERT(ait.hasMore());
00514 
00515     if(!ait.hasPrev()){
00516         return false;
00517     }
00518 
00519     Instruction jumpInst = rawSection->readInstruction(&ait);
00520 
00521     ait--; ait--;
00522 
00523     int32_t additionalOffset = 0;
00524     bool jumpRequiresOneMoreIndir = false;
00525     uint32_t tocBaseRegister = INVALID_REGISTER;
00526 
00527     if(ait.hasMore()){
00528         Instruction prevInst = rawSection->readInstruction(&ait);
00529         if(jumpInst.isIndirectJumpCtr()){
00530             if(!prevInst.isAddBeforeJump()){
00531                 return false;
00532             }
00533         } else if(jumpInst.isIndirectJumpLnk()){
00534             if(!prevInst.isLoadBeforeJump()){
00535                 return false;
00536             } else {
00537                 tocBaseRegister = prevInst.getLoadBeforeJumpSrc1();
00538                 ait--;
00539                 if(ait.hasMore()){
00540                     prevInst = rawSection->readInstruction(&ait);
00541                     if(prevInst.definesJTBaseAddrIndir()){
00542                         additionalOffset = prevInst.getJTBaseAddrIndirOffset();
00543                         tocBaseRegister = prevInst.getJTBaseAddrIndirSrc();
00544                         jumpRequiresOneMoreIndir = true;
00545                     }
00546                 }
00547             }
00548 
00549         }
00550     }
00551 
00552     bool isCountSet = false;
00553     bool isAddrSet = false;
00554 
00555     while(ait.hasMore()){
00556         Instruction insn = rawSection->readInstruction(&ait);
00557 
00558         if(!*jumpTableEntryCount && insn.definesJTEntryCount()){
00559             *jumpTableEntryCount = insn.getJTEntryCount() + 1;
00560             isCountSet = true;
00561         }
00562         
00563         if(!*jumpTableAddr && insn.definesJTBaseAddress()){
00564             if((tocBaseRegister == INVALID_REGISTER) ||
00565                (insn.getJTBaseAddrTarget() == tocBaseRegister))
00566             {
00567                 int32_t TOCoffset = insn.getJTBaseOffsetTOC(); 
00568                 *jumpTableAddr = getXCoffFile()->readTOC(TOCoffset);
00569                 isAddrSet = true;
00570                 if(jumpRequiresOneMoreIndir){
00571                     PRINT_DEBUG("JMPINDIR one more indirection common to xlC");
00572                     *jumpTableAddr += additionalOffset;
00573                 }
00574             }
00575         }
00576 
00577         if(isAddrSet && isCountSet){
00578             return true;
00579         }
00580 
00581         ait--;
00582     }
00583 
00584     return false;
00585 }
00586 
00587 void Function::parseJumpTable(AddressIterator dait,
00588                               BasicBlock** allBlocks,
00589                               BasicBlock* currBlock,
00590                               LinkedList<uint32_t>* outgoingEdgeBags,
00591                               LinkedList<uint32_t>* incomingEdgeBags)
00592 {
00593     dait--;
00594 
00595     Instruction insn = rawSection->readInstruction(&dait);
00596 
00597     uint64_t jumpTableAddr = 0;
00598     uint32_t jumpTableEntryCount = 0;
00599 
00600     if(getJumpTableInformation(&jumpTableAddr,&jumpTableEntryCount,dait)){
00601 
00602         PRINT_DEBUG("JUMP TABLE : %#112llx %#12llx %d",*dait,jumpTableAddr,jumpTableEntryCount);
00603 
00604         RawSection* jumpTableSect = getXCoffFile()->findRawSection(jumpTableAddr);
00605 
00606         if(jumpTableSect && 
00607            (jumpTableSect->IS_SECT_TYPE(TEXT) || jumpTableSect->IS_SECT_TYPE(DATA))){
00608             AddressIterator jumpTableIt = jumpTableSect->getAddressIterator();
00609             jumpTableIt.skipTo(jumpTableAddr);
00610             for(uint32_t i=0;i<jumpTableEntryCount;i++){
00611                 uint64_t leaderAddr = jumpTableSect->readBytes(&jumpTableIt);
00612                 if(insn.isIndirectJumpCtr()){
00613                     leaderAddr += jumpTableAddr;
00614                 } 
00615                 if(instructionInRange(leaderAddr)){
00616                     uint32_t insnIndex = getInstructionIndex(leaderAddr);
00617                     if(!allBlocks[insnIndex]){
00618                         allBlocks[insnIndex] = new BasicBlock(flowGraph,leaderAddr);
00619                     }
00620                     if(currBlock){
00621                         BasicBlock* toBlock = allBlocks[insnIndex];
00622                         outgoingEdgeBags[currBlock->getIndex()].insert(toBlock->getIndex());
00623                         incomingEdgeBags[toBlock->getIndex()].insert(currBlock->getIndex());
00624                     }
00625 
00626                     PRINT_DEBUG("\tLeader : %#12llx JMP",leaderAddr);
00627                     jumpTableIt++;
00628                 }
00629             }
00630         }
00631 
00632         if(currBlock)
00633             return;
00634 
00635         if(instructionInRange(jumpTableAddr)){
00636             uint32_t insnIndex = getInstructionIndex(jumpTableAddr);
00637             BasicBlock* jumpTableBlock = allBlocks[insnIndex];
00638             if(!jumpTableBlock){
00639                 jumpTableBlock = new BasicBlock(flowGraph,jumpTableAddr);
00640                 allBlocks[insnIndex] = jumpTableBlock;
00641             }
00642             jumpTableBlock->setJumpTable();
00643             jumpTableBlock->setNoPath();
00644             jumpTableBlock->setSizeInBytes(jumpTableEntryCount*dait.unit());
00645         }
00646     }
00647 }
00648 
00649 FlowGraph* Function::getFlowGraph(){
00650     return flowGraph;
00651 }
00652 
00653 void Function::generateCFG(){
00654 
00655     TIMER(double t1 = timer());
00656 
00657     DEBUG_MORE(
00658         PRINT_INFOR("********************************\n");
00659         print();
00660     );
00661     
00662     flowGraph = new FlowGraph(this);
00663 
00664     uint32_t instructionCount = getInstructionCount();
00665     BasicBlock** allBlocks = new BasicBlock*[instructionCount];
00666     for(uint32_t i=0;i<instructionCount;i++){
00667         allBlocks[i] = NULL;
00668     }
00669 
00670     AddressIterator ait = getInstructionIterator();
00671 
00672     if (!ait.hasMore()){
00673         PRINT_INFOR("Function %d has no instructions", index);
00674         return;
00675     }
00676     ASSERT(ait.hasMore() && "FATAL : There is a Function with no instructions");
00677 
00678     allBlocks[0] = new BasicBlock(flowGraph,getBaseAddress());
00679     PRINT_DEBUG("\tLeader : %#12llx",getBaseAddress());
00680 
00681     while(ait.hasMore()){
00682 
00683         uint64_t insnAddr = *ait;
00684         Instruction insn = rawSection->readInstruction(&ait);
00685         uint32_t insnIndex = getInstructionIndex(insnAddr);
00686         BasicBlock* fromBlock = allBlocks[insnIndex];
00687 
00688         ASSERT(!insn.isZero() && "FATAL : Instructions should not have 0 word in them");
00689 
00690         if(fromBlock && fromBlock->isJumpTable()){
00691             ait.skip(fromBlock->getSizeInBytes());
00692             continue;
00693         }
00694 
00695         ait++;    
00696 
00697         if(insn.definesLeaders()){
00698             uint64_t leaderAddr = *ait;
00699             if(instructionInRange(leaderAddr)){
00700                 insnIndex = getInstructionIndex(leaderAddr);
00701                 if(!allBlocks[insnIndex]){
00702                     allBlocks[insnIndex] = new BasicBlock(flowGraph,leaderAddr);
00703                 }
00704                 PRINT_DEBUG("\tLeader : %#12llx",leaderAddr);
00705             }
00706         }
00707 
00708         if(insn.hasTargetAddress()){
00709             uint64_t leaderAddr = insn.getTargetAddress(insnAddr);
00710             if(instructionInRange(leaderAddr)){
00711                 insnIndex = getInstructionIndex(leaderAddr);
00712                 if(!allBlocks[insnIndex]){
00713                     allBlocks[insnIndex] = new BasicBlock(flowGraph,leaderAddr);
00714                 }
00715                 PRINT_DEBUG("\tLeader : %#12llx",leaderAddr);
00716             }
00717         } else if(insn.isIndirectJump()){
00718             uint64_t leaderAddr = *ait;
00719             if(instructionInRange(leaderAddr)){
00720                 parseJumpTable(ait,allBlocks);
00721             }
00722         } else if(insn.isOtherBranch()){
00723             PRINT_ERROR("\tConditional Return/Call");
00724             PRINT_ERROR("\tConditional Indirect Call");
00725             PRINT_ERROR("\tConditional Indirect Branch");
00726             ASSERT(0 && "FATAL : There is a type of branch does is not handled");
00727         }
00728     }
00729 
00730     BasicBlock* traceBackBlock = NULL;
00731     if(getSize() != getInstructionSize()){
00732         traceBackBlock = new BasicBlock(flowGraph,getBaseAddress()+getInstructionSize());
00733         traceBackBlock->setSizeInBytes(getSize()-getInstructionSize());
00734         traceBackBlock->setTrace();
00735         traceBackBlock->setNoPath();
00736     }
00737 
00738     TIMER(double t2 = timer();cfg_s1+=(t2-t1);t1=t2);
00739 
00740     uint32_t blockCount = flowGraph->initializeAllBlocks(allBlocks,traceBackBlock,instructionCount);
00741     if(!blockCount){
00742         delete[] allBlocks;
00743         return;
00744     }
00745 
00746     LinkedList<uint32_t>* outgoingEdgeBags = new LinkedList<uint32_t>[blockCount];
00747     LinkedList<uint32_t>* incomingEdgeBags = new LinkedList<uint32_t>[blockCount];
00748 
00749     BasicBlock* currBlock = NULL;
00750     bool prevInsnDefinesLeader = false;
00751 
00752     allBlocks[0]->setEntry();
00753     ait.reset();
00754     while(ait.hasMore()){
00755 
00756         uint64_t insnAddr = *ait;
00757         Instruction insn = rawSection->readInstruction(&ait);
00758         uint32_t insnIndex = getInstructionIndex(insnAddr);
00759         BasicBlock* nextBlock = allBlocks[insnIndex];
00760 
00761         if(nextBlock){
00762             if(currBlock && !currBlock->isJumpTable()){
00763                 currBlock->setSizeInBytes((uint32_t)(insnAddr-currBlock->getBaseAddress()));
00764                 if(!prevInsnDefinesLeader){
00765                     ASSERT(!nextBlock->isJumpTable() && "FATAL : Fallbacks to jump table???");
00766                     BasicBlock* toBlock = nextBlock;
00767                     outgoingEdgeBags[currBlock->getIndex()].insert(toBlock->getIndex());
00768                     incomingEdgeBags[toBlock->getIndex()].insert(currBlock->getIndex());
00769                 }
00770             }
00771 
00772             currBlock = nextBlock;
00773 
00774             if(currBlock->isJumpTable()){
00775                 ait.skip(currBlock->getSizeInBytes());
00776                 prevInsnDefinesLeader = false;
00777                 continue;
00778             }
00779         }
00780 
00781         ait++;    
00782 
00783         prevInsnDefinesLeader = false;
00784         if(insn.definesLeaders()){
00785             prevInsnDefinesLeader = true;
00786         }
00787 
00788         if(insn.isCondBranch() || insn.isCondReturn() || insn.isCall()){
00789             uint64_t leaderAddr = *ait;
00790             if(instructionInRange(leaderAddr)){
00791                 insnIndex = getInstructionIndex(leaderAddr);
00792                 BasicBlock* toBlock = allBlocks[insnIndex];
00793                 outgoingEdgeBags[currBlock->getIndex()].insert(toBlock->getIndex());
00794                 incomingEdgeBags[toBlock->getIndex()].insert(currBlock->getIndex());
00795             } else {
00796                 currBlock->setExit();
00797             }
00798         }
00799 
00800         if(insn.hasTargetAddress()){
00801             uint64_t leaderAddr = insn.getTargetAddress(insnAddr);
00802             if(instructionInRange(leaderAddr)){
00803                 insnIndex = getInstructionIndex(leaderAddr);
00804                 BasicBlock* toBlock = allBlocks[insnIndex];
00805                 outgoingEdgeBags[currBlock->getIndex()].insert(toBlock->getIndex());
00806                 incomingEdgeBags[toBlock->getIndex()].insert(currBlock->getIndex());
00807             } else {
00808                 currBlock->setExit();
00809             }
00810         } else if(insn.isIndirectJump()){
00811             uint64_t leaderAddr = *ait;
00812             if(instructionInRange(leaderAddr)){
00813                 parseJumpTable(ait,allBlocks,currBlock,outgoingEdgeBags,incomingEdgeBags);
00814             } else {
00815                 currBlock->setExit();
00816             }
00817         } 
00818 
00819         if(insn.isReturn()){
00820             currBlock->setExit();
00821         }
00822     }
00823 
00824     TIMER(t2 = timer();cfg_s2+=(t2-t1);t1=t2);
00825 
00826 
00827     if(currBlock){
00828         currBlock->setSizeInBytes((uint32_t)((*ait)-currBlock->getBaseAddress()));
00829     }
00830 
00831     PRINT_DEBUG("*** Found %d blocks for function %d\n",blockCount,getIndex());
00832 
00833     BitSet<BasicBlock*>* edgeSet = flowGraph->newBitSet();
00834 
00835     for(uint32_t i=0;i<blockCount;i++){
00836         BasicBlock* fromBlock = flowGraph->getBlock(i);
00837         LinkedList<uint32_t>* outgoingEdges = &(outgoingEdgeBags[fromBlock->getIndex()]);
00838         LinkedList<uint32_t>* incomingEdges = &(incomingEdgeBags[fromBlock->getIndex()]);
00839 
00840         ASSERT(fromBlock && "FATAL : Basic block and its outgoing edges can not be NULL");
00841 
00842         edgeSet->clear();
00843         while(!outgoingEdges->empty()){
00844             uint32_t bbidx = outgoingEdges->shift();
00845             edgeSet->insert(bbidx);
00846         }
00847         uint32_t numOfEdges = edgeSet->size();
00848         if(numOfEdges){
00849             fromBlock->setTargets(numOfEdges,edgeSet->duplicateMembers());
00850         }
00851 
00852 
00853         edgeSet->clear();
00854         while(!incomingEdges->empty()){
00855             uint32_t bbidx = incomingEdges->shift();
00856             edgeSet->insert(bbidx);
00857         }
00858         numOfEdges = edgeSet->size();
00859         if(numOfEdges){
00860             fromBlock->setSources(numOfEdges,edgeSet->duplicateMembers());
00861         }
00862     }
00863     delete[] outgoingEdgeBags;
00864     delete[] incomingEdgeBags;
00865 
00866     TIMER(t2 = timer();cfg_s3+=(t2-t1);t1=t2);
00867 
00868 
00869     PRINT_DEBUG("Finding unreachable blocks in %d block for %d\n",blockCount,getIndex());
00870 
00871     BasicBlock* root = allBlocks[0];
00872     edgeSet->setall(); /* 1 indicates not visited yet */
00873 
00874     flowGraph->depthFirstSearch(root,edgeSet,false);
00875 
00876     uint32_t unreachableCount = edgeSet->size(); /* all members with their bit set are unvisited ones **/
00877     if(unreachableCount){
00878         BasicBlock** unreachableBlocks = edgeSet->duplicateMembers();
00879         for(uint32_t i=0;i<unreachableCount;i++){
00880             unreachableBlocks[i]->setNoPath();
00881             PRINT_DEBUG("\tBlock %d is unreachable\n",unreachableBlocks[i]->getIndex());
00882         }
00883         delete[] unreachableBlocks;
00884     }
00885     PRINT_DEBUG("******** Found %d unreachable blocks for function %d with %d blocks\n",unreachableCount,getIndex(),blockCount);
00886 
00887     delete edgeSet;
00888 
00889     delete[] allBlocks;
00890 
00891     TIMER(t2 = timer();cfg_s4+=(t2-t1);t1=t2);
00892 
00893 
00894     flowGraph->setImmDominatorBlocks(root);
00895 
00896     DEBUG_MORE(
00897         print();
00898         PRINT_INFOR("********************************\n");
00899     );
00900 
00901     TIMER(t2 = timer();cfg_s5=(t2-t1);t1=t2);
00902 }
00903 
00904 void FlowGraph::setImmDominatorBlocks(BasicBlock* root){
00905 
00906     if(!root){
00908     }
00909     ASSERT(root && root->isEntry() && "Fatal: The root node should be valid and entry to cfg");
00910 
00911     LengauerTarjan dominatorAlg(getNumOfBasicBlocks(),root,getAllBlocks());
00912     dominatorAlg.immediateDominators();
00913 }
00914 
00915 void FlowGraph::depthFirstSearch(BasicBlock* root,BitSet<BasicBlock*>* visitedSet,bool visitedMarkOnSet,
00916                                  BitSet<BasicBlock*>* completedSet,LinkedList<BasicBlock*>* backEdges)
00917 {
00918 
00919     if(visitedMarkOnSet){
00920         visitedSet->insert(root->getIndex());
00921     } else {
00922         visitedSet->remove(root->getIndex());
00923     }
00924 
00925     uint32_t numOfTargets = root->getNumOfTargets();
00926     for(uint32_t i=0;i<numOfTargets;i++){
00927         BasicBlock* target = root->getTargetBlock(i);
00928 
00929         if(visitedMarkOnSet != visitedSet->contains(target->getIndex())){
00930             depthFirstSearch(target,visitedSet,visitedMarkOnSet,completedSet,backEdges);
00931         } else if(backEdges && completedSet && 
00932                   (visitedMarkOnSet != completedSet->contains(target->getIndex()))) 
00933         {
00934             backEdges->insert(target);
00935             backEdges->insert(root);
00936         }
00937     }
00938 
00939     if(completedSet){
00940         if(visitedMarkOnSet){
00941             completedSet->insert(root->getIndex());
00942         } else {
00943             completedSet->remove(root->getIndex());
00944         }
00945     }
00946 }
00947 
00948 void Function::findMemoryFloatOps(){
00949     if(flowGraph){
00950         flowGraph->findMemoryFloatOps();
00951     }
00952 }
00953 
00954 AddressIterator Function::getAddressIterator() {
00955     return AddressIterator::newAddressIteratorWord(baseAddress,sizeInBytes);
00956 }
00957 
00958 AddressIterator Function::getInstructionIterator() {
00959     return AddressIterator::newAddressIteratorWord(baseAddress,insnSizeInBytes);
00960 }
00961 
00962 XCoffFile* Function::getXCoffFile(){
00963     return rawSection->getXCoffFile();
00964 }
00965 
00966 bool Function::isAnySymbolA(char* name){
00967     if(!name)
00968         return false;
00969 
00970     SymbolTable* symbolTable = rawSection->getSymbolTable();
00971     for(uint32_t i=0;i<numOfAllSymbols;i++){
00972         char* symName = symbolTable->getSymbolName(allSymbols[i]);
00973         if(!strcmp(symName,name)){
00974             free(symName);
00975             return true;
00976         }
00977         free(symName);
00978     }
00979     return false;
00980 }
00981 
00982 XCoffFile* FlowGraph::getXCoffFile(){
00983     return function->getXCoffFile();
00984 }
00985 
00986 XCoffFile* BasicBlock::getXCoffFile(){
00987     return flowGraph->getXCoffFile();
00988 }
00989 
00990 uint32_t FlowGraph::getNumOfMemoryOps() {
00991     uint32_t ret = 0;
00992     for(uint32_t i=0;i<numOfBasicBlocks;i++){
00993         BasicBlock* bb = basicBlocks[i];
00994         ret += bb->getNumOfMemoryOps();
00995     }
00996     return ret;
00997 }
00998 
00999 uint32_t FlowGraph::getNumOfFloatPOps() {
01000     uint32_t ret = 0;
01001     for(uint32_t i=0;i<numOfBasicBlocks;i++){
01002         BasicBlock* bb = basicBlocks[i];
01003         ret += bb->getNumOfFloatPOps();
01004     }
01005     return ret;
01006 }
01007 
01008 bool BasicBlock::findFirstInstPoint(uint64_t* addr){ 
01009     *addr = 0x0;
01010     AddressIterator ait = getInstructionIterator();
01011     while(ait.hasMore()){
01012         Instruction insn = getRawSection()->readInstruction(&ait);
01013         if(!insn.definesLeaders()){
01014             *addr = *ait; 
01015             return true;
01016         }
01017         ait++;
01018     }
01019     return false; 
01020 }
01021 
01022 bool BasicBlock::isDominatedBy(BasicBlock* bb){
01023     if(!bb){
01024         return false;
01025     }
01026     BasicBlock* candidate = (BasicBlock*)this;
01027     while(candidate){
01028         if(candidate == bb){
01029             return true;
01030         }
01031         candidate = candidate->getImmDominator();
01032     }
01033     return false;
01034 }

Generated on Mon Jan 28 11:08:32 2008 for PMaCInstrumentor by doxygen 1.3.5