aboutsummaryrefslogtreecommitdiffhomepage
path: root/lib/Module/InstructionInfoTable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Module/InstructionInfoTable.cpp')
-rw-r--r--lib/Module/InstructionInfoTable.cpp110
1 files changed, 79 insertions, 31 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)));
}
}