| //===-- PoolAccessTrace.cpp - Build trace of loads ------------------------===// |
| // |
| // 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. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements the -poolaccesstrace pass. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #define DEBUG_TYPE "pointercompress" |
| |
| #include "dsa/DataStructure.h" |
| #include "dsa/DSGraph.h" |
| #include "poolalloc/PoolAllocate.h" |
| #include "llvm/Instructions.h" |
| #include "llvm/Module.h" |
| using namespace llvm; |
| |
| namespace { |
| |
| /// PoolAccessTrace - This transformation adds instrumentation to the program |
| /// to print a trace of pairs containing the address of each load and the pool |
| /// descriptor loaded from. |
| class PoolAccessTrace : public ModulePass { |
| PoolAllocate *PoolAlloc; |
| DataStructures *G; |
| Constant *AccessTraceInitFn, *PoolAccessTraceFn; |
| const PointerType *VoidPtrTy; |
| public: |
| |
| PoolAccessTrace() : ModulePass((intptr_t)&ID) {} |
| |
| bool runOnModule(Module &M); |
| |
| void getAnalysisUsage(AnalysisUsage &AU) const; |
| |
| const DSGraph* getGraphForFunc(PA::FuncInfo *FI) const { |
| return G->getDSGraph(FI->F); |
| } |
| static char ID; |
| |
| private: |
| void InitializeLibraryFunctions(Module &M); |
| void InstrumentAccess(Instruction *I, Value *Ptr, |
| PA::FuncInfo *FI, DSGraph* DSG); |
| }; |
| |
| char PoolAccessTrace::ID = 0; |
| RegisterPass<PoolAccessTrace> |
| X("poolaccesstrace", "Instrument program to print trace of accesses"); |
| } |
| |
| void PoolAccessTrace::getAnalysisUsage(AnalysisUsage &AU) const { |
| // Need information about how pool allocation happened. |
| AU.addRequired<PoolAllocatePassAllPools>(); |
| |
| // Need information from DSA. |
| AU.addRequired<CompleteBUDataStructures>(); |
| } |
| |
| void PoolAccessTrace::InitializeLibraryFunctions(Module &M) { |
| const IntegerType * IT = IntegerType::getInt8Ty(getGlobalContext()); |
| const Type * VoidType = Type::getVoidTy(getGlobalContext()); |
| VoidPtrTy = PointerType::getUnqual(IT); |
| |
| AccessTraceInitFn = M.getOrInsertFunction("poolaccesstraceinit", |
| VoidType, NULL); |
| PoolAccessTraceFn = M.getOrInsertFunction("poolaccesstrace", VoidType, |
| VoidPtrTy, VoidPtrTy, NULL); |
| } |
| |
| void PoolAccessTrace::InstrumentAccess(Instruction *I, Value *Ptr, |
| PA::FuncInfo *FI, DSGraph* DSG) { |
| // Don't trace loads of globals or the stack. |
| if (isa<Constant>(Ptr) || isa<AllocaInst>(Ptr)) return; |
| |
| Value *MappedPtr = Ptr; |
| if (!FI->NewToOldValueMap.empty()) |
| if ((MappedPtr = FI->MapValueToOriginal(MappedPtr)) == 0) { |
| // Value didn't exist in the orig program (pool desc?). |
| return; |
| } |
| DSNode *Node = DSG->getNodeForValue(MappedPtr).getNode(); |
| if (Node == 0) return; |
| |
| Value *PD = FI->PoolDescriptors[Node]; |
| Ptr = CastInst::CreatePointerCast (Ptr, VoidPtrTy, Ptr->getName(), I); |
| |
| if (PD) |
| PD = CastInst::CreatePointerCast (PD, VoidPtrTy, PD->getName(), I); |
| else |
| PD = ConstantPointerNull::get(VoidPtrTy); |
| |
| // Insert the trace call. |
| Value *Opts[2] = {Ptr, PD}; |
| CallInst::Create (PoolAccessTraceFn, Opts, Opts + 2, "", I); |
| } |
| |
| bool PoolAccessTrace::runOnModule(Module &M) { |
| PoolAlloc = &getAnalysis<PoolAllocatePassAllPools>(); |
| G = &getAnalysis<CompleteBUDataStructures>(); |
| |
| // Create the function prototypes for runtime library. |
| InitializeLibraryFunctions(M); |
| |
| Function *MainFunc = M.getFunction("main"); |
| if (MainFunc && !MainFunc->isDeclaration()) |
| // Insert a call to the library init function into the beginning of main. |
| CallInst::Create (AccessTraceInitFn, "", MainFunc->begin()->begin()); |
| |
| // Look at all of the loads in the program. |
| for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { |
| if (F->isDeclaration()) continue; |
| |
| PA::FuncInfo *FI = PoolAlloc->getFuncInfoOrClone(*F); |
| assert(FI && "DIDN'T FIND POOL INFO!"); |
| |
| // If this function was cloned, and this is the original function, ignore it |
| // (it's dead). We'll deal with the cloned version later when we run into |
| // it again. |
| if (FI->Clone && &FI->F == F) |
| continue; |
| |
| // Get the DSGraph for this function. |
| DSGraph* DSG = G->getDSGraph(FI->F); |
| |
| for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) |
| for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) |
| if (LoadInst *LI = dyn_cast<LoadInst>(I)) |
| InstrumentAccess(LI, LI->getOperand(0), FI, DSG); |
| } |
| return true; |
| } |