LLVM API Documentation
00001 //===- TraceValues.cpp - Value Tracing for debugging ----------------------===// 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 // 00010 // Support for inserting LLVM code to print values at basic block and function 00011 // exits. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "llvm/Transforms/Instrumentation.h" 00016 #include "llvm/Constants.h" 00017 #include "llvm/DerivedTypes.h" 00018 #include "llvm/Instructions.h" 00019 #include "llvm/Module.h" 00020 #include "llvm/Pass.h" 00021 #include "llvm/Assembly/Writer.h" 00022 #include "llvm/Support/CommandLine.h" 00023 #include "llvm/ADT/StringExtras.h" 00024 #include <algorithm> 00025 #include <sstream> 00026 using namespace llvm; 00027 00028 static cl::opt<bool> 00029 DisablePtrHashing("tracedisablehashdisable", cl::Hidden, 00030 cl::desc("Disable pointer hashing in the -trace or -tracem " 00031 "passes")); 00032 00033 static cl::list<std::string> 00034 TraceFuncNames("tracefunc", cl::desc("Only trace specific functions in the " 00035 "-trace or -tracem passes"), 00036 cl::value_desc("function"), cl::Hidden); 00037 00038 static void TraceValuesAtBBExit(BasicBlock *BB, 00039 Function *Printf, Function* HashPtrToSeqNum, 00040 std::vector<Instruction*> *valuesStoredInFunction); 00041 00042 // We trace a particular function if no functions to trace were specified 00043 // or if the function is in the specified list. 00044 // 00045 inline static bool 00046 TraceThisFunction(Function &F) 00047 { 00048 if (TraceFuncNames.empty()) return true; 00049 00050 return std::find(TraceFuncNames.begin(), TraceFuncNames.end(), F.getName()) 00051 != TraceFuncNames.end(); 00052 } 00053 00054 00055 namespace { 00056 struct ExternalFuncs { 00057 Function *PrintfFunc, *HashPtrFunc, *ReleasePtrFunc; 00058 Function *RecordPtrFunc, *PushOnEntryFunc, *ReleaseOnReturnFunc; 00059 void doInitialization(Module &M); // Add prototypes for external functions 00060 }; 00061 00062 class InsertTraceCode : public FunctionPass { 00063 protected: 00064 ExternalFuncs externalFuncs; 00065 public: 00066 00067 // Add a prototype for runtime functions not already in the program. 00068 // 00069 bool doInitialization(Module &M); 00070 00071 //-------------------------------------------------------------------------- 00072 // Function InsertCodeToTraceValues 00073 // 00074 // Inserts tracing code for all live values at basic block and/or function 00075 // exits as specified by `traceBasicBlockExits' and `traceFunctionExits'. 00076 // 00077 bool doit(Function *M); 00078 00079 virtual void handleBasicBlock(BasicBlock *BB, 00080 std::vector<Instruction*> &VI) = 0; 00081 00082 // runOnFunction - This method does the work. 00083 // 00084 bool runOnFunction(Function &F); 00085 00086 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 00087 AU.setPreservesCFG(); 00088 } 00089 }; 00090 00091 struct FunctionTracer : public InsertTraceCode { 00092 // Ignore basic blocks here... 00093 virtual void handleBasicBlock(BasicBlock *BB, 00094 std::vector<Instruction*> &VI) {} 00095 }; 00096 00097 struct BasicBlockTracer : public InsertTraceCode { 00098 // Trace basic blocks here... 00099 virtual void handleBasicBlock(BasicBlock *BB, 00100 std::vector<Instruction*> &VI) { 00101 TraceValuesAtBBExit(BB, externalFuncs.PrintfFunc, 00102 externalFuncs.HashPtrFunc, &VI); 00103 } 00104 }; 00105 00106 // Register the passes... 00107 RegisterOpt<FunctionTracer> X("tracem","Insert Function trace code only"); 00108 RegisterOpt<BasicBlockTracer> Y("trace","Insert BB and Function trace code"); 00109 } // end anonymous namespace 00110 00111 /// Just trace functions 00112 FunctionPass *llvm::createTraceValuesPassForFunction() { 00113 return new FunctionTracer(); 00114 } 00115 00116 /// Trace BB's and functions 00117 FunctionPass *llvm::createTraceValuesPassForBasicBlocks() { 00118 return new BasicBlockTracer(); 00119 } 00120 00121 // Add a prototype for external functions used by the tracing code. 00122 // 00123 void ExternalFuncs::doInitialization(Module &M) { 00124 const Type *SBP = PointerType::get(Type::SByteTy); 00125 const FunctionType *MTy = 00126 FunctionType::get(Type::IntTy, std::vector<const Type*>(1, SBP), true); 00127 PrintfFunc = M.getOrInsertFunction("printf", MTy); 00128 00129 // uint (sbyte*) 00130 HashPtrFunc = M.getOrInsertFunction("HashPointerToSeqNum", Type::UIntTy, SBP, 00131 0); 00132 00133 // void (sbyte*) 00134 ReleasePtrFunc = M.getOrInsertFunction("ReleasePointerSeqNum", 00135 Type::VoidTy, SBP, 0); 00136 RecordPtrFunc = M.getOrInsertFunction("RecordPointer", 00137 Type::VoidTy, SBP, 0); 00138 00139 PushOnEntryFunc = M.getOrInsertFunction("PushPointerSet", Type::VoidTy, 0); 00140 ReleaseOnReturnFunc = M.getOrInsertFunction("ReleasePointersPopSet", 00141 Type::VoidTy, 0); 00142 } 00143 00144 00145 // Add a prototype for external functions used by the tracing code. 00146 // 00147 bool InsertTraceCode::doInitialization(Module &M) { 00148 externalFuncs.doInitialization(M); 00149 return false; 00150 } 00151 00152 00153 static inline GlobalVariable *getStringRef(Module *M, const std::string &str) { 00154 // Create a constant internal string reference... 00155 Constant *Init = ConstantArray::get(str); 00156 00157 // Create the global variable and record it in the module 00158 // The GV will be renamed to a unique name if needed. 00159 GlobalVariable *GV = new GlobalVariable(Init->getType(), true, 00160 GlobalValue::InternalLinkage, Init, 00161 "trstr"); 00162 M->getGlobalList().push_back(GV); 00163 return GV; 00164 } 00165 00166 00167 // 00168 // Check if this instruction has any uses outside its basic block, 00169 // or if it used by either a Call or Return instruction (ditto). 00170 // (Values stored to memory within this BB are live at end of BB but are 00171 // traced at the store instruction, not where they are computed.) 00172 // 00173 static inline bool LiveAtBBExit(const Instruction* I) { 00174 const BasicBlock *BB = I->getParent(); 00175 for (Value::use_const_iterator U = I->use_begin(); U != I->use_end(); ++U) 00176 if (const Instruction *UI = dyn_cast<Instruction>(*U)) 00177 if (UI->getParent() != BB || isa<ReturnInst>(UI)) 00178 return true; 00179 00180 return false; 00181 } 00182 00183 00184 static inline bool TraceThisOpCode(unsigned opCode) { 00185 // Explicitly test for opCodes *not* to trace so that any new opcodes will 00186 // be traced by default (VoidTy's are already excluded) 00187 // 00188 return (opCode < Instruction::OtherOpsBegin && 00189 opCode != Instruction::Alloca && 00190 opCode != Instruction::PHI && 00191 opCode != Instruction::Cast); 00192 } 00193 00194 00195 // Trace a value computed by an instruction if it is non-void, it is computed 00196 // by a real computation, not just a copy (see TraceThisOpCode), and 00197 // -- it is a load instruction: we want to check values read from memory 00198 // -- or it is live at exit from the basic block (i.e., ignore local temps) 00199 // 00200 static bool ShouldTraceValue(const Instruction *I) { 00201 return 00202 I->getType() != Type::VoidTy && 00203 TraceThisOpCode(I->getOpcode()) && 00204 (isa<LoadInst>(I) || LiveAtBBExit(I)); 00205 } 00206 00207 static std::string getPrintfCodeFor(const Value *V) { 00208 if (V == 0) return ""; 00209 if (V->getType()->isFloatingPoint()) 00210 return "%g"; 00211 else if (V->getType() == Type::LabelTy) 00212 return "0x%p"; 00213 else if (isa<PointerType>(V->getType())) 00214 return DisablePtrHashing ? "0x%p" : "%d"; 00215 else if (V->getType()->isIntegral()) 00216 return "%d"; 00217 00218 assert(0 && "Illegal value to print out..."); 00219 return ""; 00220 } 00221 00222 00223 static void InsertPrintInst(Value *V, BasicBlock *BB, Instruction *InsertBefore, 00224 std::string Message, 00225 Function *Printf, Function* HashPtrToSeqNum) { 00226 // Escape Message by replacing all % characters with %% chars. 00227 std::string Tmp; 00228 std::swap(Tmp, Message); 00229 std::string::iterator I = std::find(Tmp.begin(), Tmp.end(), '%'); 00230 while (I != Tmp.end()) { 00231 Message.append(Tmp.begin(), I); 00232 Message += "%%"; 00233 ++I; // Make sure to erase the % as well... 00234 Tmp.erase(Tmp.begin(), I); 00235 I = std::find(Tmp.begin(), Tmp.end(), '%'); 00236 } 00237 Message += Tmp; 00238 Module *Mod = BB->getParent()->getParent(); 00239 00240 // Turn the marker string into a global variable... 00241 GlobalVariable *fmtVal = getStringRef(Mod, Message+getPrintfCodeFor(V)+"\n"); 00242 00243 // Turn the format string into an sbyte * 00244 Constant *GEP=ConstantExpr::getGetElementPtr(fmtVal, 00245 std::vector<Constant*>(2,Constant::getNullValue(Type::LongTy))); 00246 00247 // Insert a call to the hash function if this is a pointer value 00248 if (V && isa<PointerType>(V->getType()) && !DisablePtrHashing) { 00249 const Type *SBP = PointerType::get(Type::SByteTy); 00250 if (V->getType() != SBP) // Cast pointer to be sbyte* 00251 V = new CastInst(V, SBP, "Hash_cast", InsertBefore); 00252 00253 std::vector<Value*> HashArgs(1, V); 00254 V = new CallInst(HashPtrToSeqNum, HashArgs, "ptrSeqNum", InsertBefore); 00255 } 00256 00257 // Insert the first print instruction to print the string flag: 00258 std::vector<Value*> PrintArgs; 00259 PrintArgs.push_back(GEP); 00260 if (V) PrintArgs.push_back(V); 00261 new CallInst(Printf, PrintArgs, "trace", InsertBefore); 00262 } 00263 00264 00265 static void InsertVerbosePrintInst(Value *V, BasicBlock *BB, 00266 Instruction *InsertBefore, 00267 const std::string &Message, Function *Printf, 00268 Function* HashPtrToSeqNum) { 00269 std::ostringstream OutStr; 00270 if (V) WriteAsOperand(OutStr, V); 00271 InsertPrintInst(V, BB, InsertBefore, Message+OutStr.str()+" = ", 00272 Printf, HashPtrToSeqNum); 00273 } 00274 00275 static void 00276 InsertReleaseInst(Value *V, BasicBlock *BB, 00277 Instruction *InsertBefore, 00278 Function* ReleasePtrFunc) { 00279 00280 const Type *SBP = PointerType::get(Type::SByteTy); 00281 if (V->getType() != SBP) // Cast pointer to be sbyte* 00282 V = new CastInst(V, SBP, "RPSN_cast", InsertBefore); 00283 00284 std::vector<Value*> releaseArgs(1, V); 00285 new CallInst(ReleasePtrFunc, releaseArgs, "", InsertBefore); 00286 } 00287 00288 static void 00289 InsertRecordInst(Value *V, BasicBlock *BB, 00290 Instruction *InsertBefore, 00291 Function* RecordPtrFunc) { 00292 const Type *SBP = PointerType::get(Type::SByteTy); 00293 if (V->getType() != SBP) // Cast pointer to be sbyte* 00294 V = new CastInst(V, SBP, "RP_cast", InsertBefore); 00295 00296 std::vector<Value*> releaseArgs(1, V); 00297 new CallInst(RecordPtrFunc, releaseArgs, "", InsertBefore); 00298 } 00299 00300 // Look for alloca and free instructions. These are the ptrs to release. 00301 // Release the free'd pointers immediately. Record the alloca'd pointers 00302 // to be released on return from the current function. 00303 // 00304 static void 00305 ReleasePtrSeqNumbers(BasicBlock *BB, 00306 ExternalFuncs& externalFuncs) { 00307 00308 for (BasicBlock::iterator II=BB->begin(), IE = BB->end(); II != IE; ++II) 00309 if (FreeInst *FI = dyn_cast<FreeInst>(II)) 00310 InsertReleaseInst(FI->getOperand(0), BB, FI,externalFuncs.ReleasePtrFunc); 00311 else if (AllocaInst *AI = dyn_cast<AllocaInst>(II)) 00312 InsertRecordInst(AI, BB, AI->getNext(), externalFuncs.RecordPtrFunc); 00313 } 00314 00315 00316 // Insert print instructions at the end of basic block BB for each value 00317 // computed in BB that is live at the end of BB, 00318 // or that is stored to memory in BB. 00319 // If the value is stored to memory, we load it back before printing it 00320 // We also return all such loaded values in the vector valuesStoredInFunction 00321 // for printing at the exit from the function. (Note that in each invocation 00322 // of the function, this will only get the last value stored for each static 00323 // store instruction). 00324 // 00325 static void TraceValuesAtBBExit(BasicBlock *BB, 00326 Function *Printf, Function* HashPtrToSeqNum, 00327 std::vector<Instruction*> *valuesStoredInFunction) { 00328 // Get an iterator to point to the insertion location, which is 00329 // just before the terminator instruction. 00330 // 00331 TerminatorInst *InsertPos = BB->getTerminator(); 00332 00333 std::ostringstream OutStr; 00334 WriteAsOperand(OutStr, BB, false); 00335 InsertPrintInst(0, BB, InsertPos, "LEAVING BB:" + OutStr.str(), 00336 Printf, HashPtrToSeqNum); 00337 00338 // Insert a print instruction for each instruction preceding InsertPos. 00339 // The print instructions must go before InsertPos, so we use the 00340 // instruction *preceding* InsertPos to check when to terminate the loop. 00341 // 00342 for (BasicBlock::iterator II = BB->begin(); &*II != InsertPos; ++II) { 00343 if (StoreInst *SI = dyn_cast<StoreInst>(II)) { 00344 // Trace the stored value and address 00345 InsertVerbosePrintInst(SI->getOperand(0), BB, InsertPos, 00346 " (store value) ", Printf, HashPtrToSeqNum); 00347 InsertVerbosePrintInst(SI->getOperand(1), BB, InsertPos, 00348 " (store addr ) ", Printf, HashPtrToSeqNum); 00349 } 00350 else if (ShouldTraceValue(II)) 00351 InsertVerbosePrintInst(II, BB, InsertPos, " ", Printf, HashPtrToSeqNum); 00352 } 00353 } 00354 00355 static inline void InsertCodeToShowFunctionEntry(Function &F, Function *Printf, 00356 Function* HashPtrToSeqNum){ 00357 // Get an iterator to point to the insertion location 00358 BasicBlock &BB = F.getEntryBlock(); 00359 Instruction *InsertPos = BB.begin(); 00360 00361 std::ostringstream OutStr; 00362 WriteAsOperand(OutStr, &F); 00363 InsertPrintInst(0, &BB, InsertPos, "ENTERING FUNCTION: " + OutStr.str(), 00364 Printf, HashPtrToSeqNum); 00365 00366 // Now print all the incoming arguments 00367 unsigned ArgNo = 0; 00368 for (Function::aiterator I = F.abegin(), E = F.aend(); I != E; ++I, ++ArgNo){ 00369 InsertVerbosePrintInst(I, &BB, InsertPos, 00370 " Arg #" + utostr(ArgNo) + ": ", Printf, 00371 HashPtrToSeqNum); 00372 } 00373 } 00374 00375 00376 static inline void InsertCodeToShowFunctionExit(BasicBlock *BB, 00377 Function *Printf, 00378 Function* HashPtrToSeqNum) { 00379 // Get an iterator to point to the insertion location 00380 ReturnInst *Ret = cast<ReturnInst>(BB->getTerminator()); 00381 00382 std::ostringstream OutStr; 00383 WriteAsOperand(OutStr, BB->getParent(), true); 00384 InsertPrintInst(0, BB, Ret, "LEAVING FUNCTION: " + OutStr.str(), 00385 Printf, HashPtrToSeqNum); 00386 00387 // print the return value, if any 00388 if (BB->getParent()->getReturnType() != Type::VoidTy) 00389 InsertPrintInst(Ret->getReturnValue(), BB, Ret, " Returning: ", 00390 Printf, HashPtrToSeqNum); 00391 } 00392 00393 00394 bool InsertTraceCode::runOnFunction(Function &F) { 00395 if (!TraceThisFunction(F)) 00396 return false; 00397 00398 std::vector<Instruction*> valuesStoredInFunction; 00399 std::vector<BasicBlock*> exitBlocks; 00400 00401 // Insert code to trace values at function entry 00402 InsertCodeToShowFunctionEntry(F, externalFuncs.PrintfFunc, 00403 externalFuncs.HashPtrFunc); 00404 00405 // Push a pointer set for recording alloca'd pointers at entry. 00406 if (!DisablePtrHashing) 00407 new CallInst(externalFuncs.PushOnEntryFunc, std::vector<Value*>(), "", 00408 F.getEntryBlock().begin()); 00409 00410 for (Function::iterator BB = F.begin(); BB != F.end(); ++BB) { 00411 if (isa<ReturnInst>(BB->getTerminator())) 00412 exitBlocks.push_back(BB); // record this as an exit block 00413 00414 // Insert trace code if this basic block is interesting... 00415 handleBasicBlock(BB, valuesStoredInFunction); 00416 00417 if (!DisablePtrHashing) // release seq. numbers on free/ret 00418 ReleasePtrSeqNumbers(BB, externalFuncs); 00419 } 00420 00421 for (unsigned i=0; i != exitBlocks.size(); ++i) 00422 { 00423 // Insert code to trace values at function exit 00424 InsertCodeToShowFunctionExit(exitBlocks[i], externalFuncs.PrintfFunc, 00425 externalFuncs.HashPtrFunc); 00426 00427 // Release all recorded pointers before RETURN. Do this LAST! 00428 if (!DisablePtrHashing) 00429 new CallInst(externalFuncs.ReleaseOnReturnFunc, std::vector<Value*>(), 00430 "", exitBlocks[i]->getTerminator()); 00431 } 00432 00433 return true; 00434 }