diff options
author | Chris Lattner <sabre@nondot.org> | 2001-12-14 16:26:05 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2001-12-14 16:26:05 +0000 |
commit | 29c147302f2681516fdc74ab9eaa03ce953dfef3 (patch) | |
tree | 26045a8c831bff77a0a19ccb5224a2867f899ecd | |
parent | 7ae9b93a7d8f52dd01682b7c2e6df89f91a0cd29 (diff) | |
download | external_llvm-29c147302f2681516fdc74ab9eaa03ce953dfef3.zip external_llvm-29c147302f2681516fdc74ab9eaa03ce953dfef3.tar.gz external_llvm-29c147302f2681516fdc74ab9eaa03ce953dfef3.tar.bz2 |
* Refactor trace values to work as a proper pass. Before it used to add
methods while the pass was running which was a no no. Now it adds the
printf method at pass initialization
* Revamp code to use printf calls instead of the old style print_<type>
calls.
* Simplify code
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1457 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/Instrumentation/TraceValues.cpp | 597 |
1 files changed, 177 insertions, 420 deletions
diff --git a/lib/Transforms/Instrumentation/TraceValues.cpp b/lib/Transforms/Instrumentation/TraceValues.cpp index d6f5a57..7948266 100644 --- a/lib/Transforms/Instrumentation/TraceValues.cpp +++ b/lib/Transforms/Instrumentation/TraceValues.cpp @@ -1,337 +1,151 @@ -// $Id$ -//*************************************************************************** -// File: -// TraceValues.cpp -// -// Purpose: -// Support for inserting LLVM code to print values at basic block -// and method exits. Also exports functions to create a call -// "printf" instruction with one of the signatures listed below. -// -// History: -// 10/11/01 - Vikram Adve - Created -//**************************************************************************/ - +//===- TraceValues.cpp - Value Tracing for debugging -------------*- C++ -*--=// +// +// Support for inserting LLVM code to print values at basic block and method +// exits. +// +//===----------------------------------------------------------------------===// #include "llvm/Transforms/Instrumentation/TraceValues.h" #include "llvm/GlobalVariable.h" #include "llvm/ConstantVals.h" -#include "llvm/Type.h" #include "llvm/DerivedTypes.h" -#include "llvm/Instruction.h" #include "llvm/iMemory.h" #include "llvm/iTerminators.h" #include "llvm/iOther.h" -#include "llvm/BasicBlock.h" #include "llvm/Method.h" #include "llvm/Module.h" #include "llvm/SymbolTable.h" #include "llvm/Assembly/Writer.h" #include "Support/StringExtras.h" -#include "Support/HashExtras.h" -#include <hash_set> #include <sstream> -static const char* -PrintMethodNameForType(const Type* type) -{ - if (PointerType* pty = dyn_cast<PointerType>(type)) - { - const Type* elemTy; - if (ArrayType* aty = dyn_cast<ArrayType>(pty->getElementType())) - elemTy = aty->getElementType(); - else - elemTy = pty->getElementType(); - if (elemTy == Type::SByteTy || elemTy == Type::UByteTy) - return "printString"; - } +// Add a prototype for printf if it is not already in the program. +// +bool InsertTraceCode::doPassInitialization(Module *M) { + SymbolTable *ST = M->getSymbolTable(); + const Type *SBP = PointerType::get(Type::SByteTy); + const MethodType *MTy = + MethodType::get(Type::IntTy, vector<const Type*>(1, SBP), true); - switch (type->getPrimitiveID()) - { - case Type::BoolTyID: return "printBool"; - case Type::UByteTyID: return "printUByte"; - case Type::SByteTyID: return "printSByte"; - case Type::UShortTyID: return "printUShort"; - case Type::ShortTyID: return "printShort"; - case Type::UIntTyID: return "printUInt"; - case Type::IntTyID: return "printInt"; - case Type::ULongTyID: return "printULong"; - case Type::LongTyID: return "printLong"; - case Type::FloatTyID: return "printFloat"; - case Type::DoubleTyID: return "printDouble"; - case Type::PointerTyID: return "printPointer"; - default: - assert(0 && "Unsupported type for printing"); - return NULL; - } + if (Value *Meth = ST->lookup(PointerType::get(MTy), "printf")) { + PrintfMeth = cast<Method>(Meth); + return false; + } + + // Create a new method and add it to the module + PrintfMeth = new Method(MTy, false, "printf"); + M->getMethodList().push_back(PrintfMeth); + return true; } -static inline GlobalVariable *GetStringRef(Module *M, const string &str) { - ConstantArray *Init = ConstantArray::get(str); - GlobalVariable *GV = new GlobalVariable(Init->getType(), /*Const*/true, - /*intern*/true, Init); + +static inline GlobalVariable *getStringRef(Module *M, const string &str) { + // Create a constant internal string reference... + Constant *Init = ConstantArray::get(str); + GlobalVariable *GV = new GlobalVariable(Init->getType(), true, true, Init, + "trstr"); M->getGlobalList().push_back(GV); return GV; } -static inline bool -TraceThisOpCode(unsigned opCode) -{ - // Explicitly test for opCodes *not* to trace so that any new opcodes will - // be traced by default (VoidTy's are already excluded) - // - return (opCode < Instruction::FirstOtherOp && - opCode != Instruction::Alloca && - opCode != Instruction::PHINode && - opCode != Instruction::Cast); -} - // // Check if this instruction has any uses outside its basic block, // or if it used by either a Call or Return instruction. // -static inline bool -LiveAtBBExit(Instruction* I) -{ - BasicBlock* bb = I->getParent(); - bool isLive = false; +static inline bool LiveAtBBExit(const Instruction* I) { + const BasicBlock *BB = I->getParent(); for (Value::use_const_iterator U = I->use_begin(); U != I->use_end(); ++U) - { - const Instruction* userI = dyn_cast<Instruction>(*U); - if (userI == NULL - || userI->getParent() != bb - || userI->getOpcode() == Instruction::Call - || userI->getOpcode() == Instruction::Ret) - isLive = true; - } - return isLive; + if (const Instruction *UI = dyn_cast<Instruction>(*U)) + if (UI->getParent() != BB || isa<ReturnInst>(UI)) + return true; + + return false; } -static void -FindValuesToTraceInBB(BasicBlock* bb, vector<Instruction*>& valuesToTraceInBB) -{ - for (BasicBlock::iterator II = bb->begin(); II != bb->end(); ++II) - if ((*II)->getOpcode() == Instruction::Store - || (LiveAtBBExit(*II) && - (*II)->getType()->isPrimitiveType() && - (*II)->getType() != Type::VoidTy && - TraceThisOpCode((*II)->getOpcode()))) - { - valuesToTraceInBB.push_back(*II); - } +static inline bool TraceThisOpCode(unsigned opCode) { + // Explicitly test for opCodes *not* to trace so that any new opcodes will + // be traced by default (VoidTy's are already excluded) + // + return (opCode < Instruction::FirstOtherOp && + opCode != Instruction::Alloca && + opCode != Instruction::PHINode && + opCode != Instruction::Cast); } -// -// Let's save this code for future use; it has been tested and works: -// -// The signatures of the printf methods supported are: -// int printf(ubyte*, ubyte*, ubyte*, ubyte*, int intValue) -// int printf(ubyte*, ubyte*, ubyte*, ubyte*, unsigned uintValue) -// int printf(ubyte*, ubyte*, ubyte*, ubyte*, float floatValue) -// int printf(ubyte*, ubyte*, ubyte*, ubyte*, double doubleValue) -// int printf(ubyte*, ubyte*, ubyte*, ubyte*, char* stringValue) -// int printf(ubyte*, ubyte*, ubyte*, ubyte*, void* ptrValue) -// -// The invocation should be: -// call "printf"(fmt, bbName, valueName, valueTypeName, value). -// -Value *GetPrintfMethodForType(Module* module, const Type* valueType) -{ - PointerType *ubytePtrTy = PointerType::get(ArrayType::get(Type::UByteTy)); - vector<const Type*> argTypesVec(4, ubytePtrTy); - argTypesVec.push_back(valueType); - - MethodType *printMethodTy = MethodType::get(Type::IntTy, argTypesVec, - /*isVarArg*/ false); - - SymbolTable *ST = module->getSymbolTable(); - if (Value *Meth = ST->lookup(PointerType::get(printMethodTy), "printf")) - return Meth; - // Create a new method and add it to the module - Method *printMethod = new Method(printMethodTy, "printf"); - module->getMethodList().push_back(printMethod); - - return printMethod; +static bool ShouldTraceValue(const Instruction *I) { + return + I->getType() != Type::VoidTy && LiveAtBBExit(I) && + TraceThisOpCode(I->getOpcode()); } +static string getPrintfCodeFor(const Value *V) { + if (V == 0) return ""; + switch (V->getType()->getPrimitiveID()) { + case Type::BoolTyID: + case Type::UByteTyID: case Type::UShortTyID: + case Type::UIntTyID: case Type::ULongTyID: + case Type::SByteTyID: case Type::ShortTyID: + case Type::IntTyID: case Type::LongTyID: + return "%d"; + + case Type::FloatTyID: case Type::DoubleTyID: + return "%g"; -Instruction* -CreatePrintfInstr(Value* val, - const BasicBlock* bb, - Module* module, - unsigned int indent, - bool isMethodExit) -{ - ostringstream fmtString, scopeNameString, valNameString; - vector<Value*> paramList; - const Type* valueType = val->getType(); - Method* printMethod = cast<Method>(GetPrintfMethodForType(module,valueType)); - - if (! valueType->isPrimitiveType() || - valueType->getPrimitiveID() == Type::VoidTyID || - valueType->getPrimitiveID() == Type::TypeTyID || - valueType->getPrimitiveID() == Type::LabelTyID) - { - assert(0 && "Unsupported type for printing"); - return NULL; - } - - const Value* scopeToUse = (isMethodExit)? (const Value*) bb->getParent() - : (const Value*) bb; - if (scopeToUse->hasName()) - scopeNameString << scopeToUse->getName() << ends; - else - scopeNameString << scopeToUse << ends; - - if (val->hasName()) - valNameString << val->getName() << ends; - else - valNameString << val << ends; + case Type::LabelTyID: case Type::PointerTyID: + return "%p"; - for (unsigned i=0; i < indent; i++) - fmtString << " "; - - fmtString << " AT EXIT OF " - << ((isMethodExit)? "METHOD " : "BB ") - << "%s : val %s = %s "; - - GlobalVariable* scopeNameVal = GetStringRef(module, scopeNameString.str()); - GlobalVariable* valNameVal = GetStringRef(module,valNameString.str()); - GlobalVariable* typeNameVal = GetStringRef(module, - val->getType()->getDescription().c_str()); - - switch(valueType->getPrimitiveID()) - { - case Type::BoolTyID: - case Type::UByteTyID: case Type::UShortTyID: - case Type::UIntTyID: case Type::ULongTyID: - case Type::SByteTyID: case Type::ShortTyID: - case Type::IntTyID: case Type::LongTyID: - fmtString << " %d\n"; - break; - - case Type::FloatTyID: case Type::DoubleTyID: - fmtString << " %g\n"; - break; - - case Type::PointerTyID: - fmtString << " %p\n"; - break; - - default: - assert(0 && "Should not get here. Check the IF expression above"); - return NULL; - } - - fmtString << ends; - GlobalVariable* fmtVal = GetStringRef(module, fmtString.str()); - - paramList.push_back(fmtVal); - paramList.push_back(scopeNameVal); - paramList.push_back(valNameVal); - paramList.push_back(typeNameVal); - paramList.push_back(val); - - return new CallInst(printMethod, paramList); + default: + assert(0 && "Illegal value to print out..."); + return ""; + } } -// The invocation should be: -// call "printString"([ubyte*] or [sbyte*] or ubyte* or sbyte*). -// call "printLong"(long) -// call "printInt"(int) ... -// -static Value *GetPrintMethodForType(Module *Mod, const Type *VTy) { - MethodType *MTy = MethodType::get(Type::VoidTy, vector<const Type*>(1, VTy), - /*isVarArg*/ false); - - const char* printMethodName = PrintMethodNameForType(VTy); - SymbolTable *ST = Mod->getSymbolTableSure(); - if (Value *V = ST->lookup(PointerType::get(MTy), printMethodName)) - return V; - - // Create a new method and add it to the module - Method *M = new Method(MTy, printMethodName); - Mod->getMethodList().push_back(M); - return M; -} +static void InsertPrintInst(Value *V, BasicBlock *BB, BasicBlock::iterator &BBI, + string Message, Method *Printf) { + // Escape Message by replacing all % characters with %% chars. + unsigned Offset = 0; + while ((Offset = Message.find('%', Offset)) != string::npos) { + string::iterator Offs = Message.begin()+Offset; + //Message.replace(Offs, Offs+1, "%%"); + Message.replace(Offset, 2, "%%"); + Offset += 2; // Skip over the new %'s + } + Module *Mod = BB->getParent()->getParent(); -static void -InsertPrintInsts(Value *Val, - BasicBlock* BB, - BasicBlock::iterator &BBI, - Module *Mod, - unsigned int indent, - bool isMethodExit, - bool isMethodEntry = false) -{ - const Type* ValTy = Val->getType(); - - assert((ValTy->isPrimitiveType() || isa<PointerType>(ValTy)) && - ValTy != Type::VoidTy && ValTy != Type::TypeTy && - ValTy != Type::LabelTy && "Unsupported type for printing"); - - const Value* scopeToUse = - (isMethodExit || isMethodEntry)? (const Value*)BB->getParent() : (const Value*)BB; - - // Create the marker string... - ostringstream scopeNameString; - if (isMethodExit || isMethodEntry) - scopeNameString << " METHOD "; - else - scopeNameString << " BASIC BLOCK "; - - scopeNameString << ((scopeToUse->hasName()) - ? scopeToUse->getName().c_str() - : itostr((int) scopeToUse).c_str()) - << " : "; - - WriteAsOperand(scopeNameString, Val) << " = "; - - string fmtString(indent, ' '); - if (isMethodEntry) - fmtString += string(" AT ENTRY OF") + scopeNameString.str(); - else - fmtString += string(" AT EXIT OF") + scopeNameString.str(); - // Turn the marker string into a global variable... - GlobalVariable *fmtVal = GetStringRef(Mod, fmtString); + GlobalVariable *fmtVal = getStringRef(Mod, Message+getPrintfCodeFor(V)+"\n"); + + // Turn the format string into an sbyte * + Instruction *GEP = + new GetElementPtrInst(fmtVal, + vector<Value*>(2,ConstantUInt::get(Type::UIntTy, 0)), + "trstr"); + BBI = BB->getInstList().insert(BBI, GEP)+1; // Insert the first print instruction to print the string flag: - Instruction *I = new CallInst(GetPrintMethodForType(Mod, fmtVal->getType()), - vector<Value*>(1, fmtVal)); - BBI = BB->getInstList().insert(BBI, I)+1; - - // Insert the next print instruction to print the value: - I = new CallInst(GetPrintMethodForType(Mod, ValTy), - vector<Value*>(1, Val)); - BBI = BB->getInstList().insert(BBI, I)+1; - - // Print out a newline - fmtVal = GetStringRef(Mod, "\n"); - I = new CallInst(GetPrintMethodForType(Mod, fmtVal->getType()), - vector<Value*>(1, fmtVal)); + vector<Value*> PrintArgs; + PrintArgs.push_back(GEP); + if (V) PrintArgs.push_back(V); + Instruction *I = new CallInst(Printf, PrintArgs, "trace"); BBI = BB->getInstList().insert(BBI, I)+1; } - - -static LoadInst* -InsertLoadInst(StoreInst *SI, - BasicBlock *bb, - BasicBlock::iterator &BBI) -{ - LoadInst* loadInst = new LoadInst(SI->getPointerOperand(), SI->copyIndices()); - BBI = bb->getInstList().insert(BBI, loadInst) + 1; - return loadInst; + + +static void InsertVerbosePrintInst(Value *V, BasicBlock *BB, + BasicBlock::iterator &BBI, + const string &Message, Method *Printf) { + ostringstream OutStr; + if (V) WriteAsOperand(OutStr, V); + InsertPrintInst(V, BB, BBI, Message+OutStr.str()+" = ", Printf); } -// // Insert print instructions at the end of the basic block *bb // for each value in valueVec[] that is live at the end of that basic block, // or that is stored to memory in this basic block. @@ -343,20 +157,13 @@ InsertLoadInst(StoreInst *SI, // *bb must be the block in which the value is computed; // this is not checked here. // -static void -TraceValuesAtBBExit(const vector<Instruction*>& valueVec, - BasicBlock* bb, - Module* module, - unsigned int indent, - bool isMethodExit, - vector<Instruction*>* valuesStoredInMethod) -{ +static void TraceValuesAtBBExit(BasicBlock *BB, Method *Printf, + vector<Instruction*> *valuesStoredInMethod) { // Get an iterator to point to the insertion location, which is // just before the terminator instruction. // - BasicBlock::InstListType& instList = bb->getInstList(); - BasicBlock::iterator here = instList.end()-1; - assert((*here)->isTerminator()); + BasicBlock::iterator InsertPos = BB->end()-1; + assert((*InsertPos)->isTerminator()); // If the terminator is a conditional branch, insert the trace code just // before the instruction that computes the branch condition (just to @@ -364,157 +171,107 @@ TraceValuesAtBBExit(const vector<Instruction*>& valueVec, // Use laterInstrSet to mark instructions that come after the setCC instr // because those cannot be traced at the location we choose. // - hash_set<Instruction*> laterInstrSet; - if (BranchInst* brInst = dyn_cast<BranchInst>(*here)) - if (! brInst->isUnconditional()) - if (Instruction* setCC = dyn_cast<Instruction>(brInst->getCondition())) - if (setCC->getParent() == bb) - { - while ((*here) != setCC && here != instList.begin()) - { - --here; - laterInstrSet.insert(*here); - } - assert((*here) == setCC && "Missed the setCC instruction?"); - laterInstrSet.insert(*here); - } - - // Insert a print instruction for each value. - // - for (unsigned i=0, N=valueVec.size(); i < N; i++) - { - Instruction* I = valueVec[i]; - if (I->getOpcode() == Instruction::Store) - { - assert(valuesStoredInMethod != NULL && - "Should not be printing a store instruction at method exit"); - I = InsertLoadInst((StoreInst*) I, bb, here); - valuesStoredInMethod->push_back(I); + Instruction *SetCC = 0; + if (BranchInst *Branch = dyn_cast<BranchInst>(BB->getTerminator())) + if (!Branch->isUnconditional()) + if (Instruction *I = dyn_cast<Instruction>(Branch->getCondition())) + if (I->getParent() == BB) { + SetCC = I; + while (*InsertPos != SetCC) + --InsertPos; // Back up until we can insert before the setcc } - if (laterInstrSet.find(I) == laterInstrSet.end()) - InsertPrintInsts(I, bb, here, module, indent, isMethodExit); - } -} - + // Copy all of the instructions into a vector to avoid problems with Setcc + const vector<Instruction*> Insts(BB->begin(), InsertPos); -static Instruction* -CreateMethodTraceInst(Method* method, - unsigned int indent, - const string& msg) -{ - string fmtString(indent, ' '); - // ostringstream methodNameString; - // WriteAsOperand(methodNameString, method); - // fmtString += msg + methodNameString.str() + '\n'; - if (method->hasName()) - fmtString += msg + method->getName().c_str() + '\n'; - else - fmtString += msg + itostr((int) method) + '\n'; - - GlobalVariable *fmtVal = GetStringRef(method->getParent(), fmtString); - Instruction *printInst = - new CallInst(GetPrintMethodForType(method->getParent(), fmtVal->getType()), - vector<Value*>(1, fmtVal)); + ostringstream OutStr; + WriteAsOperand(OutStr, BB, false); + InsertPrintInst(0, BB, InsertPos, "LEAVING BB:" + OutStr.str(), Printf); - return printInst; + // Insert a print instruction for each value. + // + for (vector<Instruction*>::const_iterator II = Insts.begin(), + IE = Insts.end(); II != IE; ++II) { + Instruction *I = *II; + if (StoreInst *SI = dyn_cast<StoreInst>(I)) { + assert(valuesStoredInMethod && + "Should not be printing a store instruction at method exit"); + LoadInst *LI = new LoadInst(SI->getPointerOperand(), SI->copyIndices(), + "reload"); + InsertPos = BB->getInstList().insert(InsertPos, LI) + 1; + valuesStoredInMethod->push_back(LI); + } + if (ShouldTraceValue(I)) + InsertVerbosePrintInst(I, BB, InsertPos, " ", Printf); + } } - -static inline void -InsertCodeToShowMethodEntry(Method* method, - BasicBlock* entryBB, - unsigned int indent) -{ +static inline void InsertCodeToShowMethodEntry(Method *M, Method *Printf) { // Get an iterator to point to the insertion location - BasicBlock::InstListType& instList = entryBB->getInstList(); - BasicBlock::iterator here = instList.begin(); - - Instruction *printInst = CreateMethodTraceInst(method, indent, - "ENTERING METHOD "); - here = entryBB->getInstList().insert(here, printInst) + 1; - + BasicBlock *BB = M->getEntryNode(); + BasicBlock::iterator BBI = BB->begin(); + + ostringstream OutStr; + WriteAsOperand(OutStr, M, true); + InsertPrintInst(0, BB, BBI, "ENTERING METHOD: " + OutStr.str(), Printf); + // Now print all the incoming arguments - const Method::ArgumentListType& argList = method->getArgumentList(); + const Method::ArgumentListType &argList = M->getArgumentList(); + unsigned ArgNo = 0; for (Method::ArgumentListType::const_iterator - I=argList.begin(), E=argList.end(); I != E; ++I) - { - InsertPrintInsts((*I), entryBB, here, method->getParent(), - indent, /*isMethodExit*/false, /*isMethodEntry*/true); - } + I = argList.begin(), E = argList.end(); I != E; ++I, ++ArgNo) { + InsertVerbosePrintInst(*I, BB, BBI, + " Arg #" + utostr(ArgNo), Printf); + } } -static inline void -InsertCodeToShowMethodExit(Method* method, - BasicBlock* exitBB, - unsigned int indent) -{ +static inline void InsertCodeToShowMethodExit(BasicBlock *BB, Method *Printf) { // Get an iterator to point to the insertion location - BasicBlock::InstListType& instList = exitBB->getInstList(); - BasicBlock::iterator here = instList.end()-1; - assert((*here)->isTerminator()); - assert(isa<ReturnInst>(*here)); + BasicBlock::iterator BBI = BB->end()-1; + ReturnInst *Ret = cast<ReturnInst>(*BBI); - Instruction *printInst = CreateMethodTraceInst(method, indent, - "LEAVING METHOD "); - here = exitBB->getInstList().insert(here, printInst) + 1; + ostringstream OutStr; + WriteAsOperand(OutStr, BB->getParent(), true); + InsertPrintInst(0, BB, BBI, "LEAVING METHOD: " + OutStr.str(), Printf); // print the return value, if any - if (method->getReturnType() != Type::VoidTy) - InsertPrintInsts(cast<ReturnInst>(exitBB->getTerminator())->getReturnValue(), - exitBB, here, method->getParent(), - indent, /*isMethodExit*/true, /*isMethodEntry*/false); + if (BB->getParent()->getReturnType() != Type::VoidTy) + InsertPrintInst(Ret->getReturnValue(), BB, BBI, " Returning: ", Printf); } -//************************** External Functions ****************************/ - +bool InsertTraceCode::doit(Method *M, bool traceBasicBlockExits, + bool traceMethodEvents, Method *Printf) { + if (M->isExternal() || (!traceBasicBlockExits && !traceMethodEvents)) + return false; -bool -InsertTraceCode::doInsertTraceCode(Method *M, - bool traceBasicBlockExits, - bool traceMethodExits) -{ vector<Instruction*> valuesStoredInMethod; - Module* module = M->getParent(); - vector<BasicBlock*> exitBlocks; + vector<BasicBlock*> exitBlocks; - if (M->isExternal() || - (! traceBasicBlockExits && ! traceMethodExits)) - return false; - - if (traceMethodExits) - InsertCodeToShowMethodEntry(M, M->getEntryNode(), /*indent*/ 0); + Module *module = M->getParent(); + + if (traceMethodEvents) + InsertCodeToShowMethodEntry(M, Printf); - for (Method::iterator BI = M->begin(); BI != M->end(); ++BI) - { - BasicBlock* bb = *BI; - bool isExitBlock = false; - vector<Instruction*> valuesToTraceInBB; - - FindValuesToTraceInBB(bb, valuesToTraceInBB); - - if (bb->succ_begin() == bb->succ_end()) - { // record this as an exit block - exitBlocks.push_back(bb); - isExitBlock = true; - } - - if (traceBasicBlockExits) - TraceValuesAtBBExit(valuesToTraceInBB, bb, module, - /*indent*/ 4, /*isMethodExit*/ false, - &valuesStoredInMethod); + for (Method::iterator BI = M->begin(); BI != M->end(); ++BI) { + BasicBlock *BB = *BI; + if (isa<ReturnInst>(BB->getTerminator())) + exitBlocks.push_back(BB); // record this as an exit block + + if (traceBasicBlockExits) + TraceValuesAtBBExit(BB, Printf, &valuesStoredInMethod); + } + + if (traceMethodEvents) + for (unsigned i=0; i < exitBlocks.size(); ++i) { +#if 0 + TraceValuesAtBBExit(valuesStoredInMethod, exitBlocks[i], module, + /*indent*/ 0, /*isMethodExit*/ true, + /*valuesStoredInMethod*/ NULL); +#endif + InsertCodeToShowMethodExit(exitBlocks[i], Printf); } - if (traceMethodExits) - for (unsigned i=0; i < exitBlocks.size(); ++i) - { - TraceValuesAtBBExit(valuesStoredInMethod, exitBlocks[i], module, - /*indent*/ 0, /*isMethodExit*/ true, - /*valuesStoredInMethod*/ NULL); - InsertCodeToShowMethodExit(M, exitBlocks[i], /*indent*/ 0); - } - return true; } |