diff --git a/lib/Transforms/Instrumentation/TraceValues.cpp b/lib/Transforms/Instrumentation/TraceValues.cpp deleted file mode 100644 index c3fbef2aad5..00000000000 --- a/lib/Transforms/Instrumentation/TraceValues.cpp +++ /dev/null @@ -1,436 +0,0 @@ -//===- TraceValues.cpp - Value Tracing for debugging ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Support for inserting LLVM code to print values at basic block and function -// exits. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Transforms/Instrumentation.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instructions.h" -#include "llvm/Module.h" -#include "llvm/Pass.h" -#include "llvm/Assembly/Writer.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/ADT/StringExtras.h" -#include -#include -using namespace llvm; - -static cl::opt -DisablePtrHashing("tracedisablehashdisable", cl::Hidden, - cl::desc("Disable pointer hashing in the -trace or -tracem " - "passes")); - -static cl::list -TraceFuncNames("tracefunc", cl::desc("Only trace specific functions in the " - "-trace or -tracem passes"), - cl::value_desc("function"), cl::Hidden); - -static void TraceValuesAtBBExit(BasicBlock *BB, - Constant *Printf, Constant* HashPtrToSeqNum, - std::vector *valuesStoredInFunction); - -// We trace a particular function if no functions to trace were specified -// or if the function is in the specified list. -// -inline static bool -TraceThisFunction(Function &F) -{ - if (TraceFuncNames.empty()) return true; - - return std::find(TraceFuncNames.begin(), TraceFuncNames.end(), F.getName()) - != TraceFuncNames.end(); -} - - -namespace { - struct ExternalFuncs { - Constant *PrintfFunc, *HashPtrFunc, *ReleasePtrFunc; - Constant *RecordPtrFunc, *PushOnEntryFunc, *ReleaseOnReturnFunc; - void doInitialization(Module &M); // Add prototypes for external functions - }; - - class InsertTraceCode : public FunctionPass { - protected: - ExternalFuncs externalFuncs; - public: - - // Add a prototype for runtime functions not already in the program. - // - bool doInitialization(Module &M); - - //-------------------------------------------------------------------------- - // Function InsertCodeToTraceValues - // - // Inserts tracing code for all live values at basic block and/or function - // exits as specified by `traceBasicBlockExits' and `traceFunctionExits'. - // - bool doit(Function *M); - - virtual void handleBasicBlock(BasicBlock *BB, - std::vector &VI) = 0; - - // runOnFunction - This method does the work. - // - bool runOnFunction(Function &F); - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesCFG(); - } - }; - - struct FunctionTracer : public InsertTraceCode { - // Ignore basic blocks here... - virtual void handleBasicBlock(BasicBlock *BB, - std::vector &VI) {} - }; - - struct BasicBlockTracer : public InsertTraceCode { - // Trace basic blocks here... - virtual void handleBasicBlock(BasicBlock *BB, - std::vector &VI) { - TraceValuesAtBBExit(BB, externalFuncs.PrintfFunc, - externalFuncs.HashPtrFunc, &VI); - } - }; - - // Register the passes... - RegisterPass X("tracem","Insert Function trace code only"); - RegisterPass Y("trace","Insert BB and Function trace code"); -} // end anonymous namespace - -/// Just trace functions -FunctionPass *llvm::createTraceValuesPassForFunction() { - return new FunctionTracer(); -} - -/// Trace BB's and functions -FunctionPass *llvm::createTraceValuesPassForBasicBlocks() { - return new BasicBlockTracer(); -} - -// Add a prototype for external functions used by the tracing code and require -// the trace library for this module. -// -void ExternalFuncs::doInitialization(Module &M) { - M.addLibrary("trace"); - const Type *SBP = PointerType::get(Type::Int8Ty); - const FunctionType *MTy = - FunctionType::get(Type::Int32Ty, std::vector(1, SBP), true); - PrintfFunc = M.getOrInsertFunction("printf", MTy); - - // uint (sbyte*) - HashPtrFunc = M.getOrInsertFunction("HashPointerToSeqNum", Type::Int32Ty, SBP, - (Type *)0); - - // void (sbyte*) - ReleasePtrFunc = M.getOrInsertFunction("ReleasePointerSeqNum", - Type::VoidTy, SBP, (Type *)0); - RecordPtrFunc = M.getOrInsertFunction("RecordPointer", - Type::VoidTy, SBP, (Type *)0); - - PushOnEntryFunc = M.getOrInsertFunction("PushPointerSet", Type::VoidTy, - (Type *)0); - ReleaseOnReturnFunc = M.getOrInsertFunction("ReleasePointersPopSet", - Type::VoidTy, (Type *)0); -} - - -// Add a prototype for external functions used by the tracing code. -// -bool InsertTraceCode::doInitialization(Module &M) { - externalFuncs.doInitialization(M); - return false; -} - - -static inline GlobalVariable *getStringRef(Module *M, const std::string &str) { - // Create a constant internal string reference... - Constant *Init = ConstantArray::get(str); - - // Create the global variable and record it in the module - // The GV will be renamed to a unique name if needed. - GlobalVariable *GV = new GlobalVariable(Init->getType(), true, - GlobalValue::InternalLinkage, Init, - "trstr"); - M->getGlobalList().push_back(GV); - return GV; -} - - -// -// Check if this instruction has any uses outside its basic block, -// or if it used by either a Call or Return instruction (ditto). -// (Values stored to memory within this BB are live at end of BB but are -// traced at the store instruction, not where they are computed.) -// -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) - if (const Instruction *UI = dyn_cast(*U)) - if (UI->getParent() != BB || isa(UI)) - return true; - - return false; -} - - -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::OtherOpsBegin && - opCode != Instruction::Alloca && - opCode != Instruction::PHI && ! Instruction::isCast(opCode)); -} - - -// Trace a value computed by an instruction if it is non-void, it is computed -// by a real computation, not just a copy (see TraceThisOpCode), and -// -- it is a load instruction: we want to check values read from memory -// -- or it is live at exit from the basic block (i.e., ignore local temps) -// -static bool ShouldTraceValue(const Instruction *I) { - return - I->getType() != Type::VoidTy && - TraceThisOpCode(I->getOpcode()) && - (isa(I) || LiveAtBBExit(I)); -} - -static std::string getPrintfCodeFor(const Value *V) { - if (V == 0) return ""; - if (V->getType()->isFloatingPoint()) - return "%g"; - else if (V->getType() == Type::LabelTy) - return "0x%p"; - else if (isa(V->getType())) - return DisablePtrHashing ? "0x%p" : "%d"; - else if (V->getType()->isIntegral()) - return "%d"; - - assert(0 && "Illegal value to print out..."); - return ""; -} - - -static void InsertPrintInst(Value *V, BasicBlock *BB, Instruction *InsertBefore, - std::string Message, - Constant *Printf, Constant* HashPtrToSeqNum) { - // Escape Message by replacing all % characters with %% chars. - std::string Tmp; - std::swap(Tmp, Message); - std::string::iterator I = std::find(Tmp.begin(), Tmp.end(), '%'); - while (I != Tmp.end()) { - Message.append(Tmp.begin(), I); - Message += "%%"; - ++I; // Make sure to erase the % as well... - Tmp.erase(Tmp.begin(), I); - I = std::find(Tmp.begin(), Tmp.end(), '%'); - } - Message += Tmp; - Module *Mod = BB->getParent()->getParent(); - - // Turn the marker string into a global variable... - GlobalVariable *fmtVal = getStringRef(Mod, Message+getPrintfCodeFor(V)+"\n"); - - // Turn the format string into an sbyte * - Constant *GEP=ConstantExpr::getGetElementPtr(fmtVal, - std::vector(2,Constant::getNullValue(Type::Int64Ty))); - - // Insert a call to the hash function if this is a pointer value - if (V && isa(V->getType()) && !DisablePtrHashing) { - const Type *SBP = PointerType::get(Type::Int8Ty); - if (V->getType() != SBP) // Cast pointer to be sbyte* - V = new BitCastInst(V, SBP, "Hash_cast", InsertBefore); - - std::vector HashArgs(1, V); - V = new CallInst(HashPtrToSeqNum, HashArgs, "ptrSeqNum", InsertBefore); - } - - // Insert the first print instruction to print the string flag: - std::vector PrintArgs; - PrintArgs.push_back(GEP); - if (V) PrintArgs.push_back(V); - new CallInst(Printf, PrintArgs, "trace", InsertBefore); -} - - -static void InsertVerbosePrintInst(Value *V, BasicBlock *BB, - Instruction *InsertBefore, - const std::string &Message, Constant *Printf, - Constant * HashPtrToSeqNum) { - std::ostringstream OutStr; - if (V) WriteAsOperand(OutStr, V); - InsertPrintInst(V, BB, InsertBefore, Message+OutStr.str()+" = ", - Printf, HashPtrToSeqNum); -} - -static void -InsertReleaseInst(Value *V, BasicBlock *BB, - Instruction *InsertBefore, - Constant *ReleasePtrFunc) { - - const Type *SBP = PointerType::get(Type::Int8Ty); - if (V->getType() != SBP) // Cast pointer to be sbyte* - V = new BitCastInst(V, SBP, "RPSN_cast", InsertBefore); - - std::vector releaseArgs(1, V); - new CallInst(ReleasePtrFunc, releaseArgs, "", InsertBefore); -} - -static void -InsertRecordInst(Value *V, BasicBlock *BB, - Instruction *InsertBefore, - Constant *RecordPtrFunc) { - const Type *SBP = PointerType::get(Type::Int8Ty); - if (V->getType() != SBP) // Cast pointer to be sbyte* - V = new BitCastInst(V, SBP, "RP_cast", InsertBefore); - - std::vector releaseArgs(1, V); - new CallInst(RecordPtrFunc, releaseArgs, "", InsertBefore); -} - -// Look for alloca and free instructions. These are the ptrs to release. -// Release the free'd pointers immediately. Record the alloca'd pointers -// to be released on return from the current function. -// -static void -ReleasePtrSeqNumbers(BasicBlock *BB, - ExternalFuncs& externalFuncs) { - - for (BasicBlock::iterator II=BB->begin(), IE = BB->end(); II != IE; ++II) - if (FreeInst *FI = dyn_cast(II)) - InsertReleaseInst(FI->getOperand(0), BB, FI,externalFuncs.ReleasePtrFunc); - else if (AllocaInst *AI = dyn_cast(II)) - InsertRecordInst(AI, BB, AI->getNext(), externalFuncs.RecordPtrFunc); -} - - -// Insert print instructions at the end of basic block BB for each value -// computed in BB that is live at the end of BB, -// or that is stored to memory in BB. -// If the value is stored to memory, we load it back before printing it -// We also return all such loaded values in the vector valuesStoredInFunction -// for printing at the exit from the function. (Note that in each invocation -// of the function, this will only get the last value stored for each static -// store instruction). -// -static void TraceValuesAtBBExit(BasicBlock *BB, - Constant *Printf, Constant * HashPtrToSeqNum, - std::vector *valuesStoredInFunction) { - // Get an iterator to point to the insertion location, which is - // just before the terminator instruction. - // - TerminatorInst *InsertPos = BB->getTerminator(); - - std::ostringstream OutStr; - WriteAsOperand(OutStr, BB, false); - InsertPrintInst(0, BB, InsertPos, "LEAVING BB:" + OutStr.str(), - Printf, HashPtrToSeqNum); - - // Insert a print instruction for each instruction preceding InsertPos. - // The print instructions must go before InsertPos, so we use the - // instruction *preceding* InsertPos to check when to terminate the loop. - // - for (BasicBlock::iterator II = BB->begin(); &*II != InsertPos; ++II) { - if (StoreInst *SI = dyn_cast(II)) { - // Trace the stored value and address - InsertVerbosePrintInst(SI->getOperand(0), BB, InsertPos, - " (store value) ", Printf, HashPtrToSeqNum); - InsertVerbosePrintInst(SI->getOperand(1), BB, InsertPos, - " (store addr ) ", Printf, HashPtrToSeqNum); - } - else if (ShouldTraceValue(II)) - InsertVerbosePrintInst(II, BB, InsertPos, " ", Printf, HashPtrToSeqNum); - } -} - -static inline void InsertCodeToShowFunctionEntry(Function &F, Constant *Printf, - Constant * HashPtrToSeqNum){ - // Get an iterator to point to the insertion location - BasicBlock &BB = F.getEntryBlock(); - Instruction *InsertPos = BB.begin(); - - std::ostringstream OutStr; - WriteAsOperand(OutStr, &F); - InsertPrintInst(0, &BB, InsertPos, "ENTERING FUNCTION: " + OutStr.str(), - Printf, HashPtrToSeqNum); - - // Now print all the incoming arguments - unsigned ArgNo = 0; - for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I, ++ArgNo){ - InsertVerbosePrintInst(I, &BB, InsertPos, - " Arg #" + utostr(ArgNo) + ": ", Printf, - HashPtrToSeqNum); - } -} - - -static inline void InsertCodeToShowFunctionExit(BasicBlock *BB, - Constant *Printf, - Constant * HashPtrToSeqNum) { - // Get an iterator to point to the insertion location - ReturnInst *Ret = cast(BB->getTerminator()); - - std::ostringstream OutStr; - WriteAsOperand(OutStr, BB->getParent(), true); - InsertPrintInst(0, BB, Ret, "LEAVING FUNCTION: " + OutStr.str(), - Printf, HashPtrToSeqNum); - - // print the return value, if any - if (BB->getParent()->getReturnType() != Type::VoidTy) - InsertPrintInst(Ret->getReturnValue(), BB, Ret, " Returning: ", - Printf, HashPtrToSeqNum); -} - - -bool InsertTraceCode::runOnFunction(Function &F) { - if (!TraceThisFunction(F)) - return false; - - std::vector valuesStoredInFunction; - std::vector exitBlocks; - - // Insert code to trace values at function entry - InsertCodeToShowFunctionEntry(F, externalFuncs.PrintfFunc, - externalFuncs.HashPtrFunc); - - // Push a pointer set for recording alloca'd pointers at entry. - if (!DisablePtrHashing) - new CallInst(externalFuncs.PushOnEntryFunc, std::vector(), "", - F.getEntryBlock().begin()); - - for (Function::iterator BB = F.begin(); BB != F.end(); ++BB) { - if (isa(BB->getTerminator())) - exitBlocks.push_back(BB); // record this as an exit block - - // Insert trace code if this basic block is interesting... - handleBasicBlock(BB, valuesStoredInFunction); - - if (!DisablePtrHashing) // release seq. numbers on free/ret - ReleasePtrSeqNumbers(BB, externalFuncs); - } - - for (unsigned i=0; i != exitBlocks.size(); ++i) - { - // Insert code to trace values at function exit - InsertCodeToShowFunctionExit(exitBlocks[i], externalFuncs.PrintfFunc, - externalFuncs.HashPtrFunc); - - // Release all recorded pointers before RETURN. Do this LAST! - if (!DisablePtrHashing) - new CallInst(externalFuncs.ReleaseOnReturnFunc, std::vector(), - "", exitBlocks[i]->getTerminator()); - } - - return true; -}