summaryrefslogtreecommitdiffstats
path: root/llvm/tools/opt/Debugify.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/opt/Debugify.cpp')
-rw-r--r--llvm/tools/opt/Debugify.cpp164
1 files changed, 125 insertions, 39 deletions
diff --git a/llvm/tools/opt/Debugify.cpp b/llvm/tools/opt/Debugify.cpp
index 441fec36765..135a026da49 100644
--- a/llvm/tools/opt/Debugify.cpp
+++ b/llvm/tools/opt/Debugify.cpp
@@ -39,10 +39,12 @@ bool isFunctionSkipped(Function &F) {
return F.isDeclaration() || !F.hasExactDefinition();
}
-bool applyDebugifyMetadata(Module &M) {
+bool applyDebugifyMetadata(Module &M,
+ iterator_range<Module::iterator> Functions,
+ StringRef Banner) {
// Skip modules with debug info.
if (M.getNamedMetadata("llvm.dbg.cu")) {
- errs() << "Debugify: Skipping module with debug info\n";
+ errs() << Banner << "Skipping module with debug info\n";
return false;
}
@@ -65,12 +67,11 @@ bool applyDebugifyMetadata(Module &M) {
unsigned NextLine = 1;
unsigned NextVar = 1;
auto File = DIB.createFile(M.getName(), "/");
- auto CU =
- DIB.createCompileUnit(dwarf::DW_LANG_C, DIB.createFile(M.getName(), "/"),
+ auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, File,
"debugify", /*isOptimized=*/true, "", 0);
// Visit each instruction.
- for (Function &F : M) {
+ for (Function &F : Functions) {
if (isFunctionSkipped(F))
continue;
@@ -118,54 +119,57 @@ bool applyDebugifyMetadata(Module &M) {
};
addDebugifyOperand(NextLine - 1); // Original number of lines.
addDebugifyOperand(NextVar - 1); // Original number of variables.
+ assert(NMD->getNumOperands() == 2 &&
+ "llvm.debugify should have exactly 2 operands!");
return true;
}
-void checkDebugifyMetadata(Module &M) {
+bool checkDebugifyMetadata(Module &M,
+ iterator_range<Module::iterator> Functions,
+ StringRef Banner,
+ bool Strip) {
// Skip modules without debugify metadata.
NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
- if (!NMD)
- return;
+ if (!NMD) {
+ errs() << Banner << "Skipping module without debugify metadata\n";
+ return false;
+ }
auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
->getZExtValue();
};
+ assert(NMD->getNumOperands() == 2 &&
+ "llvm.debugify should have exactly 2 operands!");
unsigned OriginalNumLines = getDebugifyOperand(0);
unsigned OriginalNumVars = getDebugifyOperand(1);
bool HasErrors = false;
- // Find missing lines.
BitVector MissingLines{OriginalNumLines, true};
- for (Function &F : M) {
+ BitVector MissingVars{OriginalNumVars, true};
+ for (Function &F : Functions) {
if (isFunctionSkipped(F))
continue;
+ // Find missing lines.
for (Instruction &I : instructions(F)) {
if (isa<DbgValueInst>(&I))
continue;
auto DL = I.getDebugLoc();
- if (DL) {
+ if (DL && DL.getLine() != 0) {
MissingLines.reset(DL.getLine() - 1);
continue;
}
- outs() << "ERROR: Instruction with empty DebugLoc -- ";
+ outs() << "ERROR: Instruction with empty DebugLoc in function ";
+ outs() << F.getName() << " --";
I.print(outs());
outs() << "\n";
HasErrors = true;
}
- }
- for (unsigned Idx : MissingLines.set_bits())
- outs() << "WARNING: Missing line " << Idx + 1 << "\n";
-
- // Find missing variables.
- BitVector MissingVars{OriginalNumVars, true};
- for (Function &F : M) {
- if (isFunctionSkipped(F))
- continue;
+ // Find missing variables.
for (Instruction &I : instructions(F)) {
auto *DVI = dyn_cast<DbgValueInst>(&I);
if (!DVI)
@@ -177,18 +181,39 @@ void checkDebugifyMetadata(Module &M) {
MissingVars.reset(Var - 1);
}
}
+
+ // Print the results.
+ for (unsigned Idx : MissingLines.set_bits())
+ outs() << "WARNING: Missing line " << Idx + 1 << "\n";
+
for (unsigned Idx : MissingVars.set_bits())
outs() << "ERROR: Missing variable " << Idx + 1 << "\n";
HasErrors |= MissingVars.count() > 0;
- outs() << "CheckDebugify: " << (HasErrors ? "FAIL" : "PASS") << "\n";
+ outs() << Banner << (HasErrors ? "FAIL" : "PASS") << '\n';
+ if (HasErrors) {
+ outs() << "Module IR Dump\n";
+ M.print(outs(), nullptr, false);
+ }
+
+ // Strip the Debugify Metadata if required.
+ if (Strip) {
+ StripDebugInfo(M);
+ M.eraseNamedMetadata(NMD);
+ return true;
+ }
+
+ return false;
}
-/// Attach synthetic debug info to everything.
-struct DebugifyPass : public ModulePass {
- bool runOnModule(Module &M) override { return applyDebugifyMetadata(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 applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
+ }
- DebugifyPass() : ModulePass(ID) {}
+ DebugifyModulePass() : ModulePass(ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
@@ -197,43 +222,104 @@ struct DebugifyPass : public ModulePass {
static char ID; // Pass identification.
};
-/// Check debug info inserted by -debugify for completeness.
-struct CheckDebugifyPass : public ModulePass {
+/// 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 {
+ Module &M = *F.getParent();
+ auto FuncIt = F.getIterator();
+ return applyDebugifyMetadata(M, make_range(FuncIt, std::next(FuncIt)),
+ "FunctionDebugify: ");
+ }
+
+ DebugifyFunctionPass() : FunctionPass(ID) {}
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ }
+
+ static char ID; // Pass identification.
+};
+
+/// ModulePass for checking debug info inserted by -debugify, used with the
+/// legacy module pass manager.
+struct CheckDebugifyModulePass : public ModulePass {
bool runOnModule(Module &M) override {
- checkDebugifyMetadata(M);
- return false;
+ return checkDebugifyMetadata(M, M.functions(), "CheckModuleDebugify: ",
+ Strip);
}
- CheckDebugifyPass() : ModulePass(ID) {}
+ CheckDebugifyModulePass(bool Strip = false) : ModulePass(ID), Strip(Strip) {}
+
+ static char ID; // Pass identification.
+
+private:
+ bool Strip;
+};
+
+/// FunctionPass for checking debug info inserted by -debugify-function, used
+/// with the legacy module pass manager.
+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)),
+ "CheckFunctionDebugify: ", Strip);
+ }
+
+ CheckDebugifyFunctionPass(bool Strip = false) : FunctionPass(ID), Strip(Strip) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
static char ID; // Pass identification.
+
+private:
+ bool Strip;
};
} // end anonymous namespace
-ModulePass *createDebugifyPass() { return new DebugifyPass(); }
+ModulePass *createDebugifyModulePass() {
+ return new DebugifyModulePass();
+}
+
+FunctionPass *createDebugifyFunctionPass() {
+ return new DebugifyFunctionPass();
+}
PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) {
- applyDebugifyMetadata(M);
+ applyDebugifyMetadata(M, M.functions(), "ModuleDebugify: ");
return PreservedAnalyses::all();
}
-ModulePass *createCheckDebugifyPass() { return new CheckDebugifyPass(); }
+ModulePass *createCheckDebugifyModulePass(bool Strip) {
+ return new CheckDebugifyModulePass(Strip);
+}
+
+FunctionPass *createCheckDebugifyFunctionPass(bool Strip) {
+ return new CheckDebugifyFunctionPass(Strip);
+}
PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M,
ModuleAnalysisManager &) {
- checkDebugifyMetadata(M);
+ checkDebugifyMetadata(M, M.functions(), "CheckModuleDebugify: ", false);
return PreservedAnalyses::all();
}
-char DebugifyPass::ID = 0;
-static RegisterPass<DebugifyPass> X("debugify",
+char DebugifyModulePass::ID = 0;
+static RegisterPass<DebugifyModulePass> DM("debugify",
"Attach debug info to everything");
-char CheckDebugifyPass::ID = 0;
-static RegisterPass<CheckDebugifyPass> Y("check-debugify",
+char CheckDebugifyModulePass::ID = 0;
+static RegisterPass<CheckDebugifyModulePass> CDM("check-debugify",
"Check debug info from -debugify");
+
+char DebugifyFunctionPass::ID = 0;
+static RegisterPass<DebugifyFunctionPass> DF("debugify-function",
+ "Attach debug info to a function");
+
+char CheckDebugifyFunctionPass::ID = 0;
+static RegisterPass<CheckDebugifyFunctionPass> CDF("check-debugify-function",
+ "Check debug info from -debugify-function");
OpenPOWER on IntegriCloud