diff options
author | Martin Nowack <m.nowack@imperial.ac.uk> | 2019-03-16 14:06:56 +0000 |
---|---|---|
committer | Cristian Cadar <c.cadar@imperial.ac.uk> | 2019-03-19 15:37:46 +0000 |
commit | 51597914293ac0080f984efcca0e702cff35605f (patch) | |
tree | a287b279a8e06e365b228b77f2deeea436010af1 /lib/Module | |
parent | 2558d3e34b4e0a47a1fe224683604ddaec96f69c (diff) | |
download | klee-51597914293ac0080f984efcca0e702cff35605f.tar.gz |
Add support to assign debug instructions to optimised code
Diffstat (limited to 'lib/Module')
-rw-r--r-- | lib/Module/InstructionInfoTable.cpp | 110 | ||||
-rw-r--r-- | lib/Module/IntrinsicCleaner.cpp | 10 |
2 files changed, 79 insertions, 41 deletions
diff --git a/lib/Module/InstructionInfoTable.cpp b/lib/Module/InstructionInfoTable.cpp index a1896831..6ff49669 100644 --- a/lib/Module/InstructionInfoTable.cpp +++ b/lib/Module/InstructionInfoTable.cpp @@ -34,6 +34,13 @@ #else #include "llvm/DebugInfo.h" #endif +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 7) +#include "llvm/IR/DebugInfoMetadata.h" +#endif + +#if LLVM_VERSION_CODE == LLVM_VERSION(3, 6) +#include "llvm/Support/Debug.h" +#endif #include "llvm/Analysis/ValueTracking.h" #include "llvm/Support/ErrorHandling.h" @@ -105,7 +112,9 @@ static std::string getFullPath(llvm::StringRef Directory, class DebugInfoExtractor { std::vector<std::unique_ptr<std::string>> &internedStrings; std::map<uintptr_t, uint64_t> lineTable; +#if LLVM_VERSION_CODE < LLVM_VERSION(3, 8) llvm::DebugInfoFinder DIF; +#endif const llvm::Module &module; @@ -114,7 +123,9 @@ public: std::vector<std::unique_ptr<std::string>> &_internedStrings, const llvm::Module &_module) : internedStrings(_internedStrings), module(_module) { +#if LLVM_VERSION_CODE < LLVM_VERSION(3, 8) DIF.processModule(module); +#endif lineTable = buildInstructionToLineMap(module); } @@ -136,68 +147,105 @@ public: std::unique_ptr<FunctionInfo> getFunctionInfo(const llvm::Function &Func) { auto asmLine = lineTable.at(reinterpret_cast<std::uintptr_t>(&Func)); #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 8) -#if LLVM_VERSION_CODE >= LLVM_VERSION(6, 0) + +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 9) auto dsub = Func.getSubprogram(); #else auto dsub = llvm::getDISubprogram(&Func); #endif - if (dsub == nullptr) - return std::unique_ptr<FunctionInfo>( - new FunctionInfo(0, getInternedString(""), 0, asmLine)); - auto path = getFullPath(dsub->getDirectory(), dsub->getFilename()); - return std::unique_ptr<FunctionInfo>( - new FunctionInfo(0, getInternedString(path), dsub->getLine(), asmLine)); + if (dsub != nullptr) { + auto path = getFullPath(dsub->getDirectory(), dsub->getFilename()); + return std::unique_ptr<FunctionInfo>(new FunctionInfo( + 0, getInternedString(path), dsub->getLine(), asmLine)); + } -#else - // Acquire function debug information -#if LLVM_VERSION_CODE < LLVM_VERSION(3, 5) - for (auto subIt = DIF.subprogram_begin(), subItE = DIF.subprogram_end(); - subIt != subItE; ++subIt) { - llvm::DISubprogram SubProgram(*subIt); -#else - for (const auto &SubProgram : DIF.subprograms()) { -#endif +#elif LLVM_VERSION_CODE == LLVM_VERSION(3, 7) + for (const auto SP : DIF.subprograms()) { + auto &SubProgram = *SP; if (SubProgram.getFunction() != &Func) continue; - auto path = getFullPath(SubProgram.getDirectory(), SubProgram.getFilename()); + return std::unique_ptr<FunctionInfo>(new FunctionInfo( + 0, getInternedString(path), SubProgram.getLine(), asmLine)); + } +#endif +#if LLVM_VERSION_CODE <= LLVM_VERSION(3, 6) + // Workaround missing debug information for older LLVM versions + // Search for any instructions inside this function with debug information + // and assume it's part of this function in the source code as well. + for (auto it = llvm::inst_begin(&Func), ie = llvm::inst_end(&Func); + it != ie; ++it) { + auto iInfo = getInstructionInfo(*it, nullptr); + if (iInfo->file.empty()) + continue; + // Found an instruction return std::unique_ptr<FunctionInfo>(new FunctionInfo( - 0, getInternedString(path), SubProgram.getLineNumber(), asmLine)); + 0, getInternedString(iInfo->file), iInfo->line, asmLine)); } +#endif + // Fallback: Mark as unknown return std::unique_ptr<FunctionInfo>( new FunctionInfo(0, getInternedString(""), 0, asmLine)); -#endif } std::unique_ptr<InstructionInfo> - getInstructionInfo(const llvm::Instruction &Inst, const FunctionInfo &f) { + getInstructionInfo(const llvm::Instruction &Inst, const FunctionInfo *f) { auto asmLine = lineTable.at(reinterpret_cast<std::uintptr_t>(&Inst)); #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 8) + // Retrieve debug information associated with instruction auto dl = Inst.getDebugLoc(); - auto dil = dl.get(); - if (dil != nullptr) { - auto full_path = getFullPath(dil->getDirectory(), dil->getFilename()); + // Check if a valid debug location is assigned to the instruction. + if (dl.get() != nullptr) { + auto full_path = dl.get()->getFilename(); + auto line = dl.getLine(); + auto column = dl.getCol(); + + // Still, if the line is unknown, take the context of the instruction to + // narrow it down + if (line == 0) { + if (auto LexicalBlock = + llvm::dyn_cast<llvm::DILexicalBlock>(dl.getScope())) { + line = LexicalBlock->getLine(); + column = LexicalBlock->getColumn(); + } + } return std::unique_ptr<InstructionInfo>(new InstructionInfo( - 0, getInternedString(full_path), dl.getLine(), dl.getCol(), asmLine)); + 0, getInternedString(full_path), line, column, asmLine)); } -#else +#elif LLVM_VERSION_CODE == LLVM_VERSION(3, 7) + // Retrieve debug information llvm::DebugLoc Loc(Inst.getDebugLoc()); - if (!Loc.isUnknown()) { - llvm::DIScope Scope(Loc.getScope(module.getContext())); - auto full_path = getFullPath(Scope.getDirectory(), Scope.getFilename()); + // Check if valid + if (Loc.get() != nullptr) { + auto subProg = getDISubprogram(Loc.getScope()); + auto full_path = + getFullPath(subProg->getDirectory(), subProg->getFilename()); return std::unique_ptr<InstructionInfo>( new InstructionInfo(0, getInternedString(full_path), Loc.getLine(), Loc.getCol(), asmLine)); } +#elif LLVM_VERSION_CODE <= LLVM_VERSION(3, 6) + if (llvm::MDNode *N = Inst.getMetadata("dbg")) { + llvm::DILocation Loc(N); + auto path = getFullPath(Loc.getDirectory(), Loc.getFilename()); + auto Line = Loc.getLineNumber(); + return std::unique_ptr<InstructionInfo>( + new InstructionInfo(0, getInternedString(path), Line, 0, asmLine)); + } #endif + + if (f != nullptr) + // If nothing found, use the surrounding function + return std::unique_ptr<InstructionInfo>( + new InstructionInfo(0, f->file, f->line, 0, asmLine)); // If nothing found, use the surrounding function return std::unique_ptr<InstructionInfo>( - new InstructionInfo(0, f.file, f.line, 0, asmLine)); + new InstructionInfo(0, getInternedString(""), 0, 0, asmLine)); } }; @@ -206,13 +254,13 @@ InstructionInfoTable::InstructionInfoTable(const llvm::Module &m) { DebugInfoExtractor DI(internedStrings, m); for (const auto &Func : m) { auto F = DI.getFunctionInfo(Func); - auto FD = F.get(); + auto FR = F.get(); functionInfos.insert(std::make_pair(&Func, std::move(F))); for (auto it = llvm::inst_begin(Func), ie = llvm::inst_end(Func); it != ie; ++it) { auto instr = &*it; - infos.insert(std::make_pair(instr, DI.getInstructionInfo(*instr, *FD))); + infos.insert(std::make_pair(instr, DI.getInstructionInfo(*instr, FR))); } } diff --git a/lib/Module/IntrinsicCleaner.cpp b/lib/Module/IntrinsicCleaner.cpp index b757faa1..cb006799 100644 --- a/lib/Module/IntrinsicCleaner.cpp +++ b/lib/Module/IntrinsicCleaner.cpp @@ -199,16 +199,6 @@ bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b, Module &M) { break; } - case Intrinsic::dbg_value: - case Intrinsic::dbg_declare: { - // // Remove these regardless of lower intrinsics flag. This can - // // be removed once IntrinsicLowering is fixed to not have bad - // // caches. - // ii->eraseFromParent(); - // dirty = true; - break; - } - case Intrinsic::trap: { // Intrinsic instruction "llvm.trap" found. Directly lower it to // a call of the abort() function. |