aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/Debugify.cpp
diff options
context:
space:
mode:
authorDjordje Todorovic <djtodoro@cisco.com>2021-02-22 06:01:54 -0800
committerDjordje Todorovic <djtodoro@cisco.com>2021-03-11 01:11:13 -0800
commit9f41c03f82874075c30b97b8ff71eff70f313fa0 (patch)
tree03cc3def5860163ce95884f7c4b19e4478d55d5b /llvm/lib/Transforms/Utils/Debugify.cpp
parentb975e3b5aa8c6c8b608302997a3bf0fda06bf8d8 (diff)
downloadllvm-9f41c03f82874075c30b97b8ff71eff70f313fa0.zip
llvm-9f41c03f82874075c30b97b8ff71eff70f313fa0.tar.gz
llvm-9f41c03f82874075c30b97b8ff71eff70f313fa0.tar.bz2
[Debugify][OriginalDIMode] Export the report into JSON file
By using the original-di check with debugify in the combination with the llvm/utils/llvm-original-di-preservation.py it becomes very user friendly tool. An example of the HTML page with the issues related to debug info can be found at [0]. [0] https://djolertrk.github.io/di-checker-html-report-example/ Differential Revision: https://reviews.llvm.org/D82546
Diffstat (limited to 'llvm/lib/Transforms/Utils/Debugify.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/Debugify.cpp134
1 files changed, 104 insertions, 30 deletions
diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp
index 7e6ce8c..73a3a40 100644
--- a/llvm/lib/Transforms/Utils/Debugify.cpp
+++ b/llvm/lib/Transforms/Utils/Debugify.cpp
@@ -25,6 +25,7 @@
#include "llvm/IR/PassInstrumentation.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/JSON.h"
#define DEBUG_TYPE "debugify"
@@ -334,16 +335,22 @@ bool llvm::collectDebugInfoMetadata(Module &M,
static bool checkFunctions(const DebugFnMap &DIFunctionsBefore,
const DebugFnMap &DIFunctionsAfter,
StringRef NameOfWrappedPass,
- StringRef FileNameFromCU) {
+ StringRef FileNameFromCU, bool ShouldWriteIntoJSON,
+ llvm::json::Array &Bugs) {
bool Preserved = true;
for (const auto &F : DIFunctionsAfter) {
if (F.second)
continue;
auto SPIt = DIFunctionsBefore.find(F.first);
if (SPIt == DIFunctionsBefore.end()) {
- dbg() << "ERROR: " << NameOfWrappedPass
- << " did not generate DISubprogram for " << F.first << " from "
- << FileNameFromCU << '\n';
+ if (ShouldWriteIntoJSON)
+ Bugs.push_back(llvm::json::Object({{"metadata", "DISubprogram"},
+ {"name", F.first},
+ {"action", "not-generate"}}));
+ else
+ dbg() << "ERROR: " << NameOfWrappedPass
+ << " did not generate DISubprogram for " << F.first << " from "
+ << FileNameFromCU << '\n';
Preserved = false;
} else {
auto SP = SPIt->second;
@@ -351,8 +358,13 @@ static bool checkFunctions(const DebugFnMap &DIFunctionsBefore,
continue;
// If the function had the SP attached before the pass, consider it as
// a debug info bug.
- dbg() << "ERROR: " << NameOfWrappedPass << " dropped DISubprogram of "
- << F.first << " from " << FileNameFromCU << '\n';
+ if (ShouldWriteIntoJSON)
+ Bugs.push_back(llvm::json::Object({{"metadata", "DISubprogram"},
+ {"name", F.first},
+ {"action", "drop"}}));
+ else
+ dbg() << "ERROR: " << NameOfWrappedPass << " dropped DISubprogram of "
+ << F.first << " from " << FileNameFromCU << '\n';
Preserved = false;
}
}
@@ -366,7 +378,9 @@ static bool checkInstructions(const DebugInstMap &DILocsBefore,
const DebugInstMap &DILocsAfter,
const WeakInstValueMap &InstToDelete,
StringRef NameOfWrappedPass,
- StringRef FileNameFromCU) {
+ StringRef FileNameFromCU,
+ bool ShouldWriteIntoJSON,
+ llvm::json::Array &Bugs) {
bool Preserved = true;
for (const auto &L : DILocsAfter) {
if (L.second)
@@ -382,22 +396,37 @@ static bool checkInstructions(const DebugInstMap &DILocsBefore,
auto FnName = Instr->getFunction()->getName();
auto BB = Instr->getParent();
auto BBName = BB->hasName() ? BB->getName() : "no-name";
+ auto InstName = Instruction::getOpcodeName(Instr->getOpcode());
auto InstrIt = DILocsBefore.find(Instr);
if (InstrIt == DILocsBefore.end()) {
- dbg() << "WARNING: " << NameOfWrappedPass
- << " did not generate DILocation for " << *Instr
- << " (BB: " << BBName << ", Fn: " << FnName
- << ", File: " << FileNameFromCU << ")\n";
+ if (ShouldWriteIntoJSON)
+ Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"},
+ {"fn-name", FnName.str()},
+ {"bb-name", BBName.str()},
+ {"instr", InstName},
+ {"action", "not-generate"}}));
+ else
+ dbg() << "WARNING: " << NameOfWrappedPass
+ << " did not generate DILocation for " << *Instr
+ << " (BB: " << BBName << ", Fn: " << FnName
+ << ", File: " << FileNameFromCU << ")\n";
Preserved = false;
} else {
if (!InstrIt->second)
continue;
// If the instr had the !dbg attached before the pass, consider it as
// a debug info issue.
- dbg() << "WARNING: " << NameOfWrappedPass << " dropped DILocation of "
- << *Instr << " (BB: " << BBName << ", Fn: " << FnName
- << ", File: " << FileNameFromCU << ")\n";
+ if (ShouldWriteIntoJSON)
+ Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"},
+ {"fn-name", FnName.str()},
+ {"bb-name", BBName.str()},
+ {"instr", InstName},
+ {"action", "drop"}}));
+ else
+ dbg() << "WARNING: " << NameOfWrappedPass << " dropped DILocation of "
+ << *Instr << " (BB: " << BBName << ", Fn: " << FnName
+ << ", File: " << FileNameFromCU << ")\n";
Preserved = false;
}
}
@@ -405,11 +434,35 @@ static bool checkInstructions(const DebugInstMap &DILocsBefore,
return Preserved;
}
+// Write the json data into the specifed file.
+static void writeJSON(StringRef OrigDIVerifyBugsReportFilePath,
+ StringRef FileNameFromCU, StringRef NameOfWrappedPass,
+ llvm::json::Array &Bugs) {
+ std::error_code EC;
+ raw_fd_ostream OS_FILE{OrigDIVerifyBugsReportFilePath, EC,
+ sys::fs::OF_Append | sys::fs::OF_Text};
+ if (EC) {
+ errs() << "Could not open file: " << EC.message() << ", "
+ << OrigDIVerifyBugsReportFilePath << '\n';
+ return;
+ }
+
+ OS_FILE << "{\"file\":\"" << FileNameFromCU << "\", ";
+
+ StringRef PassName = NameOfWrappedPass != "" ? NameOfWrappedPass : "no-name";
+ OS_FILE << "\"pass\":\"" << PassName << "\", ";
+
+ llvm::json::Value BugsToPrint{std::move(Bugs)};
+ OS_FILE << "\"bugs\": " << BugsToPrint;
+
+ OS_FILE << "}\n";
+}
+
bool llvm::checkDebugInfoMetadata(Module &M,
iterator_range<Module::iterator> Functions,
DebugInfoPerPassMap &DIPreservationMap,
- StringRef Banner,
- StringRef NameOfWrappedPass) {
+ StringRef Banner, StringRef NameOfWrappedPass,
+ StringRef OrigDIVerifyBugsReportFilePath) {
LLVM_DEBUG(dbgs() << Banner << ": (after) " << NameOfWrappedPass << '\n');
if (!M.getNamedMetadata("llvm.dbg.cu")) {
@@ -428,7 +481,8 @@ bool llvm::checkDebugInfoMetadata(Module &M,
// TODO: Collect metadata other than DISubprograms.
// Collect the DISubprogram.
auto *SP = F.getSubprogram();
- DIPreservationAfter[NameOfWrappedPass].DIFunctions.insert({F.getName(), SP});
+ DIPreservationAfter[NameOfWrappedPass].DIFunctions.insert(
+ {F.getName(), SP});
if (SP)
LLVM_DEBUG(dbgs() << " Collecting subprogram: " << *SP << '\n');
@@ -467,14 +521,22 @@ bool llvm::checkDebugInfoMetadata(Module &M,
auto InstToDelete = DIPreservationAfter[NameOfWrappedPass].InstToDelete;
- bool ResultForFunc = checkFunctions(DIFunctionsBefore, DIFunctionsAfter,
- NameOfWrappedPass, FileNameFromCU);
- bool ResultForInsts =
- checkInstructions(DILocsBefore, DILocsAfter, InstToDelete,
- NameOfWrappedPass, FileNameFromCU);
+ bool ShouldWriteIntoJSON = !OrigDIVerifyBugsReportFilePath.empty();
+ llvm::json::Array Bugs;
+
+ bool ResultForFunc =
+ checkFunctions(DIFunctionsBefore, DIFunctionsAfter, NameOfWrappedPass,
+ FileNameFromCU, ShouldWriteIntoJSON, Bugs);
+ bool ResultForInsts = checkInstructions(
+ DILocsBefore, DILocsAfter, InstToDelete, NameOfWrappedPass,
+ FileNameFromCU, ShouldWriteIntoJSON, Bugs);
bool Result = ResultForFunc && ResultForInsts;
StringRef ResultBanner = NameOfWrappedPass != "" ? NameOfWrappedPass : Banner;
+ if (ShouldWriteIntoJSON && !Bugs.empty())
+ writeJSON(OrigDIVerifyBugsReportFilePath, FileNameFromCU, NameOfWrappedPass,
+ Bugs);
+
if (Result)
dbg() << ResultBanner << ": PASS\n";
else
@@ -680,15 +742,18 @@ struct CheckDebugifyModulePass : public ModulePass {
"CheckModuleDebugify", Strip, StatsMap);
return checkDebugInfoMetadata(
M, M.functions(), *DIPreservationMap,
- "CheckModuleDebugify (original debuginfo)", NameOfWrappedPass);
+ "CheckModuleDebugify (original debuginfo)", NameOfWrappedPass,
+ OrigDIVerifyBugsReportFilePath);
}
CheckDebugifyModulePass(
bool Strip = false, StringRef NameOfWrappedPass = "",
DebugifyStatsMap *StatsMap = nullptr,
enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
- DebugInfoPerPassMap *DIPreservationMap = nullptr)
+ DebugInfoPerPassMap *DIPreservationMap = nullptr,
+ StringRef OrigDIVerifyBugsReportFilePath = "")
: ModulePass(ID), NameOfWrappedPass(NameOfWrappedPass),
+ OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),
StatsMap(StatsMap), DIPreservationMap(DIPreservationMap), Mode(Mode),
Strip(Strip) {}
@@ -700,6 +765,7 @@ struct CheckDebugifyModulePass : public ModulePass {
private:
StringRef NameOfWrappedPass;
+ StringRef OrigDIVerifyBugsReportFilePath;
DebugifyStatsMap *StatsMap;
DebugInfoPerPassMap *DIPreservationMap;
enum DebugifyMode Mode;
@@ -718,15 +784,18 @@ struct CheckDebugifyFunctionPass : public FunctionPass {
Strip, StatsMap);
return checkDebugInfoMetadata(
M, make_range(FuncIt, std::next(FuncIt)), *DIPreservationMap,
- "CheckFunctionDebugify (original debuginfo)", NameOfWrappedPass);
+ "CheckFunctionDebugify (original debuginfo)", NameOfWrappedPass,
+ OrigDIVerifyBugsReportFilePath);
}
CheckDebugifyFunctionPass(
bool Strip = false, StringRef NameOfWrappedPass = "",
DebugifyStatsMap *StatsMap = nullptr,
enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
- DebugInfoPerPassMap *DIPreservationMap = nullptr)
+ DebugInfoPerPassMap *DIPreservationMap = nullptr,
+ StringRef OrigDIVerifyBugsReportFilePath = "")
: FunctionPass(ID), NameOfWrappedPass(NameOfWrappedPass),
+ OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),
StatsMap(StatsMap), DIPreservationMap(DIPreservationMap), Mode(Mode),
Strip(Strip) {}
@@ -738,6 +807,7 @@ struct CheckDebugifyFunctionPass : public FunctionPass {
private:
StringRef NameOfWrappedPass;
+ StringRef OrigDIVerifyBugsReportFilePath;
DebugifyStatsMap *StatsMap;
DebugInfoPerPassMap *DIPreservationMap;
enum DebugifyMode Mode;
@@ -794,22 +864,26 @@ PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {
ModulePass *createCheckDebugifyModulePass(
bool Strip, StringRef NameOfWrappedPass, DebugifyStatsMap *StatsMap,
- enum DebugifyMode Mode, DebugInfoPerPassMap *DIPreservationMap) {
+ enum DebugifyMode Mode, DebugInfoPerPassMap *DIPreservationMap,
+ StringRef OrigDIVerifyBugsReportFilePath) {
if (Mode == DebugifyMode::SyntheticDebugInfo)
return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap);
assert(Mode == DebugifyMode::OriginalDebugInfo && "Must be original mode");
return new CheckDebugifyModulePass(false, NameOfWrappedPass, nullptr, Mode,
- DIPreservationMap);
+ DIPreservationMap,
+ OrigDIVerifyBugsReportFilePath);
}
FunctionPass *createCheckDebugifyFunctionPass(
bool Strip, StringRef NameOfWrappedPass, DebugifyStatsMap *StatsMap,
- enum DebugifyMode Mode, DebugInfoPerPassMap *DIPreservationMap) {
+ enum DebugifyMode Mode, DebugInfoPerPassMap *DIPreservationMap,
+ StringRef OrigDIVerifyBugsReportFilePath) {
if (Mode == DebugifyMode::SyntheticDebugInfo)
return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap);
assert(Mode == DebugifyMode::OriginalDebugInfo && "Must be original mode");
return new CheckDebugifyFunctionPass(false, NameOfWrappedPass, nullptr, Mode,
- DIPreservationMap);
+ DIPreservationMap,
+ OrigDIVerifyBugsReportFilePath);
}
PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,