aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/Debugify.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Utils/Debugify.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/Debugify.cpp540
1 files changed, 494 insertions, 46 deletions
diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp
index 3e4d53c10dc9..30c3fa521d52 100644
--- a/llvm/lib/Transforms/Utils/Debugify.cpp
+++ b/llvm/lib/Transforms/Utils/Debugify.cpp
@@ -1,4 +1,4 @@
-//===- Debugify.cpp - Attach synthetic debug info to everything -----------===//
+//===- Debugify.cpp - Check debug info preservation in optimizations ------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,8 +6,10 @@
//
//===----------------------------------------------------------------------===//
///
-/// \file This pass attaches synthetic debug info to everything. It can be used
-/// to create targeted tests for debug info preservation.
+/// \file In the `synthetic` mode, the `-debugify` attaches synthetic debug info
+/// to everything. It can be used to create targeted tests for debug info
+/// preservation. In addition, when using the `original` mode, it can check
+/// original debug info preservation. The `synthetic` mode is default one.
///
//===----------------------------------------------------------------------===//
@@ -23,6 +25,10 @@
#include "llvm/IR/PassInstrumentation.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/JSON.h"
+
+#define DEBUG_TYPE "debugify"
using namespace llvm;
@@ -35,6 +41,8 @@ enum class Level {
Locations,
LocationsAndVariables
};
+
+// Used for the synthetic mode only.
cl::opt<Level> DebugifyLevel(
"debugify-level", cl::desc("Kind of debug info to add"),
cl::values(clEnumValN(Level::Locations, "locations", "Locations only"),
@@ -199,16 +207,33 @@ bool llvm::applyDebugifyMetadata(
return true;
}
-static bool applyDebugify(Function &F) {
+static bool
+applyDebugify(Function &F,
+ enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
+ DebugInfoPerPassMap *DIPreservationMap = nullptr,
+ StringRef NameOfWrappedPass = "") {
Module &M = *F.getParent();
auto FuncIt = F.getIterator();
- return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
- "FunctionDebugify: ", /*ApplyToMF=*/nullptr);
+ if (Mode == DebugifyMode::SyntheticDebugInfo)
+ return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
+ "FunctionDebugify: ", /*ApplyToMF*/ nullptr);
+ assert(DIPreservationMap);
+ return collectDebugInfoMetadata(M, M.functions(), *DIPreservationMap,
+ "FunctionDebugify (original debuginfo)",
+ NameOfWrappedPass);
}
-static bool applyDebugify(Module &M) {
- return applyDebugifyMetadata(M, M.functions(),
- "ModuleDebugify: ", /*ApplyToMF=*/nullptr);
+static bool
+applyDebugify(Module &M,
+ enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
+ DebugInfoPerPassMap *DIPreservationMap = nullptr,
+ StringRef NameOfWrappedPass = "") {
+ if (Mode == DebugifyMode::SyntheticDebugInfo)
+ return applyDebugifyMetadata(M, M.functions(),
+ "ModuleDebugify: ", /*ApplyToMF*/ nullptr);
+ return collectDebugInfoMetadata(M, M.functions(), *DIPreservationMap,
+ "ModuleDebugify (original debuginfo)",
+ NameOfWrappedPass);
}
bool llvm::stripDebugifyMetadata(Module &M) {
@@ -256,6 +281,355 @@ bool llvm::stripDebugifyMetadata(Module &M) {
return Changed;
}
+bool llvm::collectDebugInfoMetadata(Module &M,
+ iterator_range<Module::iterator> Functions,
+ DebugInfoPerPassMap &DIPreservationMap,
+ StringRef Banner,
+ StringRef NameOfWrappedPass) {
+ LLVM_DEBUG(dbgs() << Banner << ": (before) " << NameOfWrappedPass << '\n');
+
+ // Clear the map with the debug info before every single pass.
+ DIPreservationMap.clear();
+
+ if (!M.getNamedMetadata("llvm.dbg.cu")) {
+ dbg() << Banner << ": Skipping module without debug info\n";
+ return false;
+ }
+
+ // Visit each instruction.
+ for (Function &F : Functions) {
+ if (isFunctionSkipped(F))
+ continue;
+
+ // Collect the DISubprogram.
+ auto *SP = F.getSubprogram();
+ DIPreservationMap[NameOfWrappedPass].DIFunctions.insert({F.getName(), SP});
+ if (SP) {
+ LLVM_DEBUG(dbgs() << " Collecting subprogram: " << *SP << '\n');
+ for (const DINode *DN : SP->getRetainedNodes()) {
+ if (const auto *DV = dyn_cast<DILocalVariable>(DN)) {
+ DIPreservationMap[NameOfWrappedPass].DIVariables[DV] = 0;
+ }
+ }
+ }
+
+ for (BasicBlock &BB : F) {
+ // Collect debug locations (!dbg) and debug variable intrinsics.
+ for (Instruction &I : BB) {
+ // Skip PHIs.
+ if (isa<PHINode>(I))
+ continue;
+
+ // Collect dbg.values and dbg.declares.
+ if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I)) {
+ if (!SP)
+ continue;
+ // Skip inlined variables.
+ if (I.getDebugLoc().getInlinedAt())
+ continue;
+ // Skip undef values.
+ if (DVI->isUndef())
+ continue;
+
+ auto *Var = DVI->getVariable();
+ DIPreservationMap[NameOfWrappedPass].DIVariables[Var]++;
+ continue;
+ }
+
+ // Skip debug instructions other than dbg.value and dbg.declare.
+ if (isa<DbgInfoIntrinsic>(&I))
+ continue;
+
+ LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I << '\n');
+ DIPreservationMap[NameOfWrappedPass].InstToDelete.insert({&I, &I});
+
+ const DILocation *Loc = I.getDebugLoc().get();
+ bool HasLoc = Loc != nullptr;
+ DIPreservationMap[NameOfWrappedPass].DILocations.insert({&I, HasLoc});
+ }
+ }
+ }
+
+ return true;
+}
+
+// This checks the preservation of original debug info attached to functions.
+static bool checkFunctions(const DebugFnMap &DIFunctionsBefore,
+ const DebugFnMap &DIFunctionsAfter,
+ StringRef NameOfWrappedPass,
+ 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()) {
+ 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;
+ if (!SP)
+ continue;
+ // If the function had the SP attached before the pass, consider it as
+ // a debug info bug.
+ 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;
+ }
+ }
+
+ return Preserved;
+}
+
+// This checks the preservation of the original debug info attached to
+// instructions.
+static bool checkInstructions(const DebugInstMap &DILocsBefore,
+ const DebugInstMap &DILocsAfter,
+ const WeakInstValueMap &InstToDelete,
+ StringRef NameOfWrappedPass,
+ StringRef FileNameFromCU,
+ bool ShouldWriteIntoJSON,
+ llvm::json::Array &Bugs) {
+ bool Preserved = true;
+ for (const auto &L : DILocsAfter) {
+ if (L.second)
+ continue;
+ auto Instr = L.first;
+
+ // In order to avoid pointer reuse/recycling, skip the values that might
+ // have been deleted during a pass.
+ auto WeakInstrPtr = InstToDelete.find(Instr);
+ if (WeakInstrPtr != InstToDelete.end() && !WeakInstrPtr->second)
+ continue;
+
+ 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()) {
+ 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.
+ 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;
+ }
+ }
+
+ return Preserved;
+}
+
+// This checks the preservation of original debug variable intrinsics.
+static bool checkVars(const DebugVarMap &DIFunctionsBefore,
+ const DebugVarMap &DIFunctionsAfter,
+ StringRef NameOfWrappedPass, StringRef FileNameFromCU,
+ bool ShouldWriteIntoJSON, llvm::json::Array &Bugs) {
+ bool Preserved = true;
+ for (const auto &V : DIFunctionsBefore) {
+ auto VarIt = DIFunctionsAfter.find(V.first);
+ if (VarIt == DIFunctionsAfter.end())
+ continue;
+
+ unsigned NumOfDbgValsAfter = VarIt->second;
+
+ if (V.second > NumOfDbgValsAfter) {
+ if (ShouldWriteIntoJSON)
+ Bugs.push_back(llvm::json::Object(
+ {{"metadata", "dbg-var-intrinsic"},
+ {"name", V.first->getName()},
+ {"fn-name", V.first->getScope()->getSubprogram()->getName()},
+ {"action", "drop"}}));
+ else
+ dbg() << "WARNING: " << NameOfWrappedPass
+ << " drops dbg.value()/dbg.declare() for " << V.first->getName()
+ << " from "
+ << "function " << V.first->getScope()->getSubprogram()->getName()
+ << " (file " << FileNameFromCU << ")\n";
+ Preserved = false;
+ }
+ }
+
+ 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_TextWithCRLF};
+ 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 OrigDIVerifyBugsReportFilePath) {
+ LLVM_DEBUG(dbgs() << Banner << ": (after) " << NameOfWrappedPass << '\n');
+
+ if (!M.getNamedMetadata("llvm.dbg.cu")) {
+ dbg() << Banner << ": Skipping module without debug info\n";
+ return false;
+ }
+
+ // Map the debug info holding DIs after a pass.
+ DebugInfoPerPassMap DIPreservationAfter;
+
+ // Visit each instruction.
+ for (Function &F : Functions) {
+ if (isFunctionSkipped(F))
+ continue;
+
+ // TODO: Collect metadata other than DISubprograms.
+ // Collect the DISubprogram.
+ auto *SP = F.getSubprogram();
+ DIPreservationAfter[NameOfWrappedPass].DIFunctions.insert(
+ {F.getName(), SP});
+
+ if (SP) {
+ LLVM_DEBUG(dbgs() << " Collecting subprogram: " << *SP << '\n');
+ for (const DINode *DN : SP->getRetainedNodes()) {
+ if (const auto *DV = dyn_cast<DILocalVariable>(DN)) {
+ DIPreservationAfter[NameOfWrappedPass].DIVariables[DV] = 0;
+ }
+ }
+ }
+
+ for (BasicBlock &BB : F) {
+ // Collect debug locations (!dbg) and debug variable intrinsics.
+ for (Instruction &I : BB) {
+ // Skip PHIs.
+ if (isa<PHINode>(I))
+ continue;
+
+ // Collect dbg.values and dbg.declares.
+ if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I)) {
+ if (!SP)
+ continue;
+ // Skip inlined variables.
+ if (I.getDebugLoc().getInlinedAt())
+ continue;
+ // Skip undef values.
+ if (DVI->isUndef())
+ continue;
+
+ auto *Var = DVI->getVariable();
+ DIPreservationAfter[NameOfWrappedPass].DIVariables[Var]++;
+ continue;
+ }
+
+ // Skip debug instructions other than dbg.value and dbg.declare.
+ if (isa<DbgInfoIntrinsic>(&I))
+ continue;
+
+ LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I << '\n');
+
+ const DILocation *Loc = I.getDebugLoc().get();
+ bool HasLoc = Loc != nullptr;
+
+ DIPreservationAfter[NameOfWrappedPass].DILocations.insert({&I, HasLoc});
+ }
+ }
+ }
+
+ // TODO: The name of the module could be read better?
+ StringRef FileNameFromCU =
+ (cast<DICompileUnit>(M.getNamedMetadata("llvm.dbg.cu")->getOperand(0)))
+ ->getFilename();
+
+ auto DIFunctionsBefore = DIPreservationMap[NameOfWrappedPass].DIFunctions;
+ auto DIFunctionsAfter = DIPreservationAfter[NameOfWrappedPass].DIFunctions;
+
+ auto DILocsBefore = DIPreservationMap[NameOfWrappedPass].DILocations;
+ auto DILocsAfter = DIPreservationAfter[NameOfWrappedPass].DILocations;
+
+ auto InstToDelete = DIPreservationAfter[NameOfWrappedPass].InstToDelete;
+
+ auto DIVarsBefore = DIPreservationMap[NameOfWrappedPass].DIVariables;
+ auto DIVarsAfter = DIPreservationAfter[NameOfWrappedPass].DIVariables;
+
+ 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 ResultForVars = checkVars(DIVarsBefore, DIVarsAfter, NameOfWrappedPass,
+ FileNameFromCU, ShouldWriteIntoJSON, Bugs);
+
+ bool Result = ResultForFunc && ResultForInsts && ResultForVars;
+
+ StringRef ResultBanner = NameOfWrappedPass != "" ? NameOfWrappedPass : Banner;
+ if (ShouldWriteIntoJSON && !Bugs.empty())
+ writeJSON(OrigDIVerifyBugsReportFilePath, FileNameFromCU, NameOfWrappedPass,
+ Bugs);
+
+ if (Result)
+ dbg() << ResultBanner << ": PASS\n";
+ else
+ dbg() << ResultBanner << ": FAIL\n";
+
+ LLVM_DEBUG(dbgs() << "\n\n");
+ return Result;
+}
+
namespace {
/// Return true if a mis-sized diagnostic is issued for \p DVI.
bool diagnoseMisSizedDbgValue(Module &M, DbgValueInst *DVI) {
@@ -264,15 +638,16 @@ bool diagnoseMisSizedDbgValue(Module &M, DbgValueInst *DVI) {
//
// TODO: This, along with a check for non-null value operands, should be
// promoted to verifier failures.
- Value *V = DVI->getValue();
- if (!V)
- return false;
// For now, don't try to interpret anything more complicated than an empty
// DIExpression. Eventually we should try to handle OP_deref and fragments.
if (DVI->getExpression()->getNumElements())
return false;
+ Value *V = DVI->getVariableLocationOp(0);
+ if (!V)
+ return false;
+
Type *Ty = V->getType();
uint64_t ValueOperandSize = getAllocSizeInBits(M, Ty);
Optional<uint64_t> DbgVarSize = DVI->getFragmentSizeInBits();
@@ -331,7 +706,7 @@ bool checkDebugifyMetadata(Module &M,
// Find missing lines.
for (Instruction &I : instructions(F)) {
- if (isa<DbgValueInst>(&I) || isa<PHINode>(&I))
+ if (isa<DbgValueInst>(&I))
continue;
auto DL = I.getDebugLoc();
@@ -340,7 +715,7 @@ bool checkDebugifyMetadata(Module &M,
continue;
}
- if (!DL) {
+ if (!isa<PHINode>(&I) && !DL) {
dbg() << "WARNING: Instruction with empty DebugLoc in function ";
dbg() << F.getName() << " --";
I.print(dbg());
@@ -394,43 +769,77 @@ bool checkDebugifyMetadata(Module &M,
/// ModulePass for attaching synthetic debug info to everything, used with the
/// legacy module pass manager.
struct DebugifyModulePass : public ModulePass {
- bool runOnModule(Module &M) override { return applyDebugify(M); }
+ bool runOnModule(Module &M) override {
+ return applyDebugify(M, Mode, DIPreservationMap, NameOfWrappedPass);
+ }
- DebugifyModulePass() : ModulePass(ID) {}
+ DebugifyModulePass(enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
+ StringRef NameOfWrappedPass = "",
+ DebugInfoPerPassMap *DIPreservationMap = nullptr)
+ : ModulePass(ID), NameOfWrappedPass(NameOfWrappedPass),
+ DIPreservationMap(DIPreservationMap), Mode(Mode) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
static char ID; // Pass identification.
+
+private:
+ StringRef NameOfWrappedPass;
+ DebugInfoPerPassMap *DIPreservationMap;
+ enum DebugifyMode Mode;
};
/// FunctionPass for attaching synthetic debug info to instructions within a
/// single function, used with the legacy module pass manager.
struct DebugifyFunctionPass : public FunctionPass {
- bool runOnFunction(Function &F) override { return applyDebugify(F); }
+ bool runOnFunction(Function &F) override {
+ return applyDebugify(F, Mode, DIPreservationMap, NameOfWrappedPass);
+ }
- DebugifyFunctionPass() : FunctionPass(ID) {}
+ DebugifyFunctionPass(
+ enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
+ StringRef NameOfWrappedPass = "",
+ DebugInfoPerPassMap *DIPreservationMap = nullptr)
+ : FunctionPass(ID), NameOfWrappedPass(NameOfWrappedPass),
+ DIPreservationMap(DIPreservationMap), Mode(Mode) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
static char ID; // Pass identification.
+
+private:
+ StringRef NameOfWrappedPass;
+ DebugInfoPerPassMap *DIPreservationMap;
+ enum DebugifyMode Mode;
};
/// ModulePass for checking debug info inserted by -debugify, used with the
/// legacy module pass manager.
struct CheckDebugifyModulePass : public ModulePass {
bool runOnModule(Module &M) override {
- return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
- "CheckModuleDebugify", Strip, StatsMap);
+ if (Mode == DebugifyMode::SyntheticDebugInfo)
+ return checkDebugifyMetadata(M, M.functions(), NameOfWrappedPass,
+ "CheckModuleDebugify", Strip, StatsMap);
+ return checkDebugInfoMetadata(
+ M, M.functions(), *DIPreservationMap,
+ "CheckModuleDebugify (original debuginfo)", NameOfWrappedPass,
+ OrigDIVerifyBugsReportFilePath);
}
- CheckDebugifyModulePass(bool Strip = false, StringRef NameOfWrappedPass = "",
- DebugifyStatsMap *StatsMap = nullptr)
- : ModulePass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
- StatsMap(StatsMap) {}
+ CheckDebugifyModulePass(
+ bool Strip = false, StringRef NameOfWrappedPass = "",
+ DebugifyStatsMap *StatsMap = nullptr,
+ enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
+ DebugInfoPerPassMap *DIPreservationMap = nullptr,
+ StringRef OrigDIVerifyBugsReportFilePath = "")
+ : ModulePass(ID), NameOfWrappedPass(NameOfWrappedPass),
+ OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),
+ StatsMap(StatsMap), DIPreservationMap(DIPreservationMap), Mode(Mode),
+ Strip(Strip) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
@@ -439,9 +848,12 @@ struct CheckDebugifyModulePass : public ModulePass {
static char ID; // Pass identification.
private:
- bool Strip;
StringRef NameOfWrappedPass;
+ StringRef OrigDIVerifyBugsReportFilePath;
DebugifyStatsMap *StatsMap;
+ DebugInfoPerPassMap *DIPreservationMap;
+ enum DebugifyMode Mode;
+ bool Strip;
};
/// FunctionPass for checking debug info inserted by -debugify-function, used
@@ -450,16 +862,26 @@ struct CheckDebugifyFunctionPass : public FunctionPass {
bool runOnFunction(Function &F) override {
Module &M = *F.getParent();
auto FuncIt = F.getIterator();
- return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
- NameOfWrappedPass, "CheckFunctionDebugify",
- Strip, StatsMap);
+ if (Mode == DebugifyMode::SyntheticDebugInfo)
+ return checkDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
+ NameOfWrappedPass, "CheckFunctionDebugify",
+ Strip, StatsMap);
+ return checkDebugInfoMetadata(
+ M, make_range(FuncIt, std::next(FuncIt)), *DIPreservationMap,
+ "CheckFunctionDebugify (original debuginfo)", NameOfWrappedPass,
+ OrigDIVerifyBugsReportFilePath);
}
- CheckDebugifyFunctionPass(bool Strip = false,
- StringRef NameOfWrappedPass = "",
- DebugifyStatsMap *StatsMap = nullptr)
- : FunctionPass(ID), Strip(Strip), NameOfWrappedPass(NameOfWrappedPass),
- StatsMap(StatsMap) {}
+ CheckDebugifyFunctionPass(
+ bool Strip = false, StringRef NameOfWrappedPass = "",
+ DebugifyStatsMap *StatsMap = nullptr,
+ enum DebugifyMode Mode = DebugifyMode::SyntheticDebugInfo,
+ DebugInfoPerPassMap *DIPreservationMap = nullptr,
+ StringRef OrigDIVerifyBugsReportFilePath = "")
+ : FunctionPass(ID), NameOfWrappedPass(NameOfWrappedPass),
+ OrigDIVerifyBugsReportFilePath(OrigDIVerifyBugsReportFilePath),
+ StatsMap(StatsMap), DIPreservationMap(DIPreservationMap), Mode(Mode),
+ Strip(Strip) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
@@ -468,9 +890,12 @@ struct CheckDebugifyFunctionPass : public FunctionPass {
static char ID; // Pass identification.
private:
- bool Strip;
StringRef NameOfWrappedPass;
+ StringRef OrigDIVerifyBugsReportFilePath;
DebugifyStatsMap *StatsMap;
+ DebugInfoPerPassMap *DIPreservationMap;
+ enum DebugifyMode Mode;
+ bool Strip;
};
} // end anonymous namespace
@@ -496,12 +921,23 @@ void llvm::exportDebugifyStats(StringRef Path, const DebugifyStatsMap &Map) {
}
}
-ModulePass *llvm::createDebugifyModulePass() {
- return new DebugifyModulePass();
+ModulePass *createDebugifyModulePass(enum DebugifyMode Mode,
+ llvm::StringRef NameOfWrappedPass,
+ DebugInfoPerPassMap *DIPreservationMap) {
+ if (Mode == DebugifyMode::SyntheticDebugInfo)
+ return new DebugifyModulePass();
+ assert(Mode == DebugifyMode::OriginalDebugInfo && "Must be original mode");
+ return new DebugifyModulePass(Mode, NameOfWrappedPass, DIPreservationMap);
}
-FunctionPass *llvm::createDebugifyFunctionPass() {
- return new DebugifyFunctionPass();
+FunctionPass *
+createDebugifyFunctionPass(enum DebugifyMode Mode,
+ llvm::StringRef NameOfWrappedPass,
+ DebugInfoPerPassMap *DIPreservationMap) {
+ if (Mode == DebugifyMode::SyntheticDebugInfo)
+ return new DebugifyFunctionPass();
+ assert(Mode == DebugifyMode::OriginalDebugInfo && "Must be original mode");
+ return new DebugifyFunctionPass(Mode, NameOfWrappedPass, DIPreservationMap);
}
PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {
@@ -510,16 +946,28 @@ PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {
return PreservedAnalyses::all();
}
-ModulePass *llvm::createCheckDebugifyModulePass(bool Strip,
- StringRef NameOfWrappedPass,
- DebugifyStatsMap *StatsMap) {
- return new CheckDebugifyModulePass(Strip, NameOfWrappedPass, StatsMap);
+ModulePass *createCheckDebugifyModulePass(
+ bool Strip, StringRef NameOfWrappedPass, DebugifyStatsMap *StatsMap,
+ 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,
+ OrigDIVerifyBugsReportFilePath);
}
-FunctionPass *
-llvm::createCheckDebugifyFunctionPass(bool Strip, StringRef NameOfWrappedPass,
- DebugifyStatsMap *StatsMap) {
- return new CheckDebugifyFunctionPass(Strip, NameOfWrappedPass, StatsMap);
+FunctionPass *createCheckDebugifyFunctionPass(
+ bool Strip, StringRef NameOfWrappedPass, DebugifyStatsMap *StatsMap,
+ 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,
+ OrigDIVerifyBugsReportFilePath);
}
PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,