LLVM API Documentation

TraceValues.cpp

Go to the documentation of this file.
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 and require
00122 // the trace library for this module.
00123 //
00124 void ExternalFuncs::doInitialization(Module &M) {
00125   M.addLibrary("trace");
00126   const Type *SBP = PointerType::get(Type::SByteTy);
00127   const FunctionType *MTy =
00128     FunctionType::get(Type::IntTy, std::vector<const Type*>(1, SBP), true);
00129   PrintfFunc = M.getOrInsertFunction("printf", MTy);
00130 
00131   // uint (sbyte*)
00132   HashPtrFunc = M.getOrInsertFunction("HashPointerToSeqNum", Type::UIntTy, SBP,
00133                                       (Type *)0);
00134 
00135   // void (sbyte*)
00136   ReleasePtrFunc = M.getOrInsertFunction("ReleasePointerSeqNum",
00137                                          Type::VoidTy, SBP, (Type *)0);
00138   RecordPtrFunc  = M.getOrInsertFunction("RecordPointer",
00139                                          Type::VoidTy, SBP, (Type *)0);
00140 
00141   PushOnEntryFunc = M.getOrInsertFunction("PushPointerSet", Type::VoidTy,
00142                                           (Type *)0);
00143   ReleaseOnReturnFunc = M.getOrInsertFunction("ReleasePointersPopSet",
00144                                               Type::VoidTy, (Type *)0);
00145 }
00146 
00147 
00148 // Add a prototype for external functions used by the tracing code.
00149 //
00150 bool InsertTraceCode::doInitialization(Module &M) {
00151   externalFuncs.doInitialization(M);
00152   return false;
00153 }
00154 
00155 
00156 static inline GlobalVariable *getStringRef(Module *M, const std::string &str) {
00157   // Create a constant internal string reference...
00158   Constant *Init = ConstantArray::get(str);
00159 
00160   // Create the global variable and record it in the module
00161   // The GV will be renamed to a unique name if needed.
00162   GlobalVariable *GV = new GlobalVariable(Init->getType(), true,
00163                                           GlobalValue::InternalLinkage, Init,
00164                                           "trstr");
00165   M->getGlobalList().push_back(GV);
00166   return GV;
00167 }
00168 
00169 
00170 //
00171 // Check if this instruction has any uses outside its basic block,
00172 // or if it used by either a Call or Return instruction (ditto).
00173 // (Values stored to memory within this BB are live at end of BB but are
00174 // traced at the store instruction, not where they are computed.)
00175 //
00176 static inline bool LiveAtBBExit(const Instruction* I) {
00177   const BasicBlock *BB = I->getParent();
00178   for (Value::use_const_iterator U = I->use_begin(); U != I->use_end(); ++U)
00179     if (const Instruction *UI = dyn_cast<Instruction>(*U))
00180       if (UI->getParent() != BB || isa<ReturnInst>(UI))
00181         return true;
00182 
00183   return false;
00184 }
00185 
00186 
00187 static inline bool TraceThisOpCode(unsigned opCode) {
00188   // Explicitly test for opCodes *not* to trace so that any new opcodes will
00189   // be traced by default (VoidTy's are already excluded)
00190   //
00191   return (opCode  < Instruction::OtherOpsBegin &&
00192           opCode != Instruction::Alloca &&
00193           opCode != Instruction::PHI &&
00194           opCode != Instruction::Cast);
00195 }
00196 
00197 
00198 // Trace a value computed by an instruction if it is non-void, it is computed
00199 // by a real computation, not just a copy (see TraceThisOpCode), and
00200 // -- it is a load instruction: we want to check values read from memory
00201 // -- or it is live at exit from the basic block (i.e., ignore local temps)
00202 //
00203 static bool ShouldTraceValue(const Instruction *I) {
00204   return
00205     I->getType() != Type::VoidTy &&
00206     TraceThisOpCode(I->getOpcode()) &&
00207     (isa<LoadInst>(I) || LiveAtBBExit(I));
00208 }
00209 
00210 static std::string getPrintfCodeFor(const Value *V) {
00211   if (V == 0) return "";
00212   if (V->getType()->isFloatingPoint())
00213     return "%g";
00214   else if (V->getType() == Type::LabelTy)
00215     return "0x%p";
00216   else if (isa<PointerType>(V->getType()))
00217     return DisablePtrHashing ? "0x%p" : "%d";
00218   else if (V->getType()->isIntegral())
00219     return "%d";
00220 
00221   assert(0 && "Illegal value to print out...");
00222   return "";
00223 }
00224 
00225 
00226 static void InsertPrintInst(Value *V, BasicBlock *BB, Instruction *InsertBefore,
00227                             std::string Message,
00228                             Function *Printf, Function* HashPtrToSeqNum) {
00229   // Escape Message by replacing all % characters with %% chars.
00230   std::string Tmp;
00231   std::swap(Tmp, Message);
00232   std::string::iterator I = std::find(Tmp.begin(), Tmp.end(), '%');
00233   while (I != Tmp.end()) {
00234     Message.append(Tmp.begin(), I);
00235     Message += "%%";
00236     ++I; // Make sure to erase the % as well...
00237     Tmp.erase(Tmp.begin(), I);
00238     I = std::find(Tmp.begin(), Tmp.end(), '%');
00239   }
00240   Message += Tmp;
00241   Module *Mod = BB->getParent()->getParent();
00242 
00243   // Turn the marker string into a global variable...
00244   GlobalVariable *fmtVal = getStringRef(Mod, Message+getPrintfCodeFor(V)+"\n");
00245 
00246   // Turn the format string into an sbyte *
00247   Constant *GEP=ConstantExpr::getGetElementPtr(fmtVal,
00248                 std::vector<Constant*>(2,Constant::getNullValue(Type::LongTy)));
00249 
00250   // Insert a call to the hash function if this is a pointer value
00251   if (V && isa<PointerType>(V->getType()) && !DisablePtrHashing) {
00252     const Type *SBP = PointerType::get(Type::SByteTy);
00253     if (V->getType() != SBP)     // Cast pointer to be sbyte*
00254       V = new CastInst(V, SBP, "Hash_cast", InsertBefore);
00255 
00256     std::vector<Value*> HashArgs(1, V);
00257     V = new CallInst(HashPtrToSeqNum, HashArgs, "ptrSeqNum", InsertBefore);
00258   }
00259 
00260   // Insert the first print instruction to print the string flag:
00261   std::vector<Value*> PrintArgs;
00262   PrintArgs.push_back(GEP);
00263   if (V) PrintArgs.push_back(V);
00264   new CallInst(Printf, PrintArgs, "trace", InsertBefore);
00265 }
00266 
00267 
00268 static void InsertVerbosePrintInst(Value *V, BasicBlock *BB,
00269                                    Instruction *InsertBefore,
00270                                    const std::string &Message, Function *Printf,
00271                                    Function* HashPtrToSeqNum) {
00272   std::ostringstream OutStr;
00273   if (V) WriteAsOperand(OutStr, V);
00274   InsertPrintInst(V, BB, InsertBefore, Message+OutStr.str()+" = ",
00275                   Printf, HashPtrToSeqNum);
00276 }
00277 
00278 static void
00279 InsertReleaseInst(Value *V, BasicBlock *BB,
00280                   Instruction *InsertBefore,
00281                   Function* ReleasePtrFunc) {
00282 
00283   const Type *SBP = PointerType::get(Type::SByteTy);
00284   if (V->getType() != SBP)    // Cast pointer to be sbyte*
00285     V = new CastInst(V, SBP, "RPSN_cast", InsertBefore);
00286 
00287   std::vector<Value*> releaseArgs(1, V);
00288   new CallInst(ReleasePtrFunc, releaseArgs, "", InsertBefore);
00289 }
00290 
00291 static void
00292 InsertRecordInst(Value *V, BasicBlock *BB,
00293                  Instruction *InsertBefore,
00294                  Function* RecordPtrFunc) {
00295     const Type *SBP = PointerType::get(Type::SByteTy);
00296   if (V->getType() != SBP)     // Cast pointer to be sbyte*
00297     V = new CastInst(V, SBP, "RP_cast", InsertBefore);
00298 
00299   std::vector<Value*> releaseArgs(1, V);
00300   new CallInst(RecordPtrFunc, releaseArgs, "", InsertBefore);
00301 }
00302 
00303 // Look for alloca and free instructions. These are the ptrs to release.
00304 // Release the free'd pointers immediately.  Record the alloca'd pointers
00305 // to be released on return from the current function.
00306 //
00307 static void
00308 ReleasePtrSeqNumbers(BasicBlock *BB,
00309                      ExternalFuncs& externalFuncs) {
00310 
00311   for (BasicBlock::iterator II=BB->begin(), IE = BB->end(); II != IE; ++II)
00312     if (FreeInst *FI = dyn_cast<FreeInst>(II))
00313       InsertReleaseInst(FI->getOperand(0), BB, FI,externalFuncs.ReleasePtrFunc);
00314     else if (AllocaInst *AI = dyn_cast<AllocaInst>(II))
00315       InsertRecordInst(AI, BB, AI->getNext(), externalFuncs.RecordPtrFunc);
00316 }
00317 
00318 
00319 // Insert print instructions at the end of basic block BB for each value
00320 // computed in BB that is live at the end of BB,
00321 // or that is stored to memory in BB.
00322 // If the value is stored to memory, we load it back before printing it
00323 // We also return all such loaded values in the vector valuesStoredInFunction
00324 // for printing at the exit from the function.  (Note that in each invocation
00325 // of the function, this will only get the last value stored for each static
00326 // store instruction).
00327 //
00328 static void TraceValuesAtBBExit(BasicBlock *BB,
00329                                 Function *Printf, Function* HashPtrToSeqNum,
00330                             std::vector<Instruction*> *valuesStoredInFunction) {
00331   // Get an iterator to point to the insertion location, which is
00332   // just before the terminator instruction.
00333   //
00334   TerminatorInst *InsertPos = BB->getTerminator();
00335 
00336   std::ostringstream OutStr;
00337   WriteAsOperand(OutStr, BB, false);
00338   InsertPrintInst(0, BB, InsertPos, "LEAVING BB:" + OutStr.str(),
00339                   Printf, HashPtrToSeqNum);
00340 
00341   // Insert a print instruction for each instruction preceding InsertPos.
00342   // The print instructions must go before InsertPos, so we use the
00343   // instruction *preceding* InsertPos to check when to terminate the loop.
00344   //
00345   for (BasicBlock::iterator II = BB->begin(); &*II != InsertPos; ++II) {
00346     if (StoreInst *SI = dyn_cast<StoreInst>(II)) {
00347       // Trace the stored value and address
00348       InsertVerbosePrintInst(SI->getOperand(0), BB, InsertPos,
00349                              "  (store value) ", Printf, HashPtrToSeqNum);
00350       InsertVerbosePrintInst(SI->getOperand(1), BB, InsertPos,
00351                              "  (store addr ) ", Printf, HashPtrToSeqNum);
00352     }
00353     else if (ShouldTraceValue(II))
00354       InsertVerbosePrintInst(II, BB, InsertPos, "  ", Printf, HashPtrToSeqNum);
00355   }
00356 }
00357 
00358 static inline void InsertCodeToShowFunctionEntry(Function &F, Function *Printf,
00359                                                  Function* HashPtrToSeqNum){
00360   // Get an iterator to point to the insertion location
00361   BasicBlock &BB = F.getEntryBlock();
00362   Instruction *InsertPos = BB.begin();
00363 
00364   std::ostringstream OutStr;
00365   WriteAsOperand(OutStr, &F);
00366   InsertPrintInst(0, &BB, InsertPos, "ENTERING FUNCTION: " + OutStr.str(),
00367                   Printf, HashPtrToSeqNum);
00368 
00369   // Now print all the incoming arguments
00370   unsigned ArgNo = 0;
00371   for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I, ++ArgNo){
00372     InsertVerbosePrintInst(I, &BB, InsertPos,
00373                            "  Arg #" + utostr(ArgNo) + ": ", Printf,
00374                            HashPtrToSeqNum);
00375   }
00376 }
00377 
00378 
00379 static inline void InsertCodeToShowFunctionExit(BasicBlock *BB,
00380                                                 Function *Printf,
00381                                                 Function* HashPtrToSeqNum) {
00382   // Get an iterator to point to the insertion location
00383   ReturnInst *Ret = cast<ReturnInst>(BB->getTerminator());
00384 
00385   std::ostringstream OutStr;
00386   WriteAsOperand(OutStr, BB->getParent(), true);
00387   InsertPrintInst(0, BB, Ret, "LEAVING  FUNCTION: " + OutStr.str(),
00388                   Printf, HashPtrToSeqNum);
00389 
00390   // print the return value, if any
00391   if (BB->getParent()->getReturnType() != Type::VoidTy)
00392     InsertPrintInst(Ret->getReturnValue(), BB, Ret, "  Returning: ",
00393                     Printf, HashPtrToSeqNum);
00394 }
00395 
00396 
00397 bool InsertTraceCode::runOnFunction(Function &F) {
00398   if (!TraceThisFunction(F))
00399     return false;
00400 
00401   std::vector<Instruction*> valuesStoredInFunction;
00402   std::vector<BasicBlock*>  exitBlocks;
00403 
00404   // Insert code to trace values at function entry
00405   InsertCodeToShowFunctionEntry(F, externalFuncs.PrintfFunc,
00406                                 externalFuncs.HashPtrFunc);
00407 
00408   // Push a pointer set for recording alloca'd pointers at entry.
00409   if (!DisablePtrHashing)
00410     new CallInst(externalFuncs.PushOnEntryFunc, std::vector<Value*>(), "",
00411                  F.getEntryBlock().begin());
00412 
00413   for (Function::iterator BB = F.begin(); BB != F.end(); ++BB) {
00414     if (isa<ReturnInst>(BB->getTerminator()))
00415       exitBlocks.push_back(BB); // record this as an exit block
00416 
00417     // Insert trace code if this basic block is interesting...
00418     handleBasicBlock(BB, valuesStoredInFunction);
00419 
00420     if (!DisablePtrHashing)          // release seq. numbers on free/ret
00421       ReleasePtrSeqNumbers(BB, externalFuncs);
00422   }
00423 
00424   for (unsigned i=0; i != exitBlocks.size(); ++i)
00425     {
00426       // Insert code to trace values at function exit
00427       InsertCodeToShowFunctionExit(exitBlocks[i], externalFuncs.PrintfFunc,
00428                                    externalFuncs.HashPtrFunc);
00429 
00430       // Release all recorded pointers before RETURN.  Do this LAST!
00431       if (!DisablePtrHashing)
00432         new CallInst(externalFuncs.ReleaseOnReturnFunc, std::vector<Value*>(),
00433                      "", exitBlocks[i]->getTerminator());
00434     }
00435 
00436   return true;
00437 }