#include <cstdarg>
using namespace llvm;
-static cl::opt<bool> VerifyDebugInfo("verify-debug-info", cl::init(false));
+static cl::opt<bool> VerifyDebugInfo("verify-debug-info", cl::init(true));
namespace {
struct VerifierSupport {
/// \brief Track the brokenness of the module while recursively visiting.
bool Broken;
+ bool EverBroken;
explicit VerifierSupport(raw_ostream &OS)
- : OS(OS), M(nullptr), Broken(false) {}
+ : OS(OS), M(nullptr), Broken(false), EverBroken(false) {}
private:
void Write(const Value *V) {
template <typename... Ts> void WriteTs() {}
public:
- // \brief A check failed, so printout out the condition and the message.
- //
- // This provides a nice place to put a breakpoint if you want to see why
- // something is not correct.
+ /// \brief A check failed, so printout out the condition and the message.
+ ///
+ /// This provides a nice place to put a breakpoint if you want to see why
+ /// something is not correct.
void CheckFailed(const Twine &Message) {
OS << Message << '\n';
- Broken = true;
+ EverBroken = Broken = true;
}
- // \brief A check failed (with values to print).
- //
- // This calls the Message-only version so that the above is easier to set a
- // breakpoint on.
+ /// \brief A check failed (with values to print).
+ ///
+ /// This calls the Message-only version so that the above is easier to set a
+ /// breakpoint on.
template <typename T1, typename... Ts>
void CheckFailed(const Twine &Message, const T1 &V1, const Ts &... Vs) {
CheckFailed(Message);
visitModuleFlags(M);
visitModuleIdents(M);
+ // Verify debug info last.
+ verifyDebugInfo();
+
return !Broken;
}
void VerifyConstantExprBitcastType(const ConstantExpr *CE);
void VerifyStatepoint(ImmutableCallSite CS);
void verifyFrameRecoverIndices();
-};
-class DebugInfoVerifier : public VerifierSupport {
-public:
- explicit DebugInfoVerifier(raw_ostream &OS = dbgs()) : VerifierSupport(OS) {}
- bool verify(const Module &M) {
- this->M = &M;
- verifyDebugInfo();
- return !Broken;
- }
-
-private:
+ // Module-level debug info verification...
void verifyDebugInfo();
void processInstructions(DebugInfoFinder &Finder);
void processCallInst(DebugInfoFinder &Finder, const CallInst &CI);
}
void Verifier::visitMDExpression(const MDExpression &N) {
- Assert(N.getTag() == dwarf::DW_TAG_expression, "invalid tag", &N);
Assert(N.isValid(), "invalid expression", &N);
}
Assert(isa<MDExpression>(DII.getRawExpression()),
"invalid llvm.dbg." + Kind + " intrinsic expression", &DII,
DII.getRawExpression());
-
- // Don't call visitMDNode(), since that will recurse through operands.
- visitMDLocalVariable(*DII.getVariable());
- visitMDExpression(*DII.getExpression());
}
-void DebugInfoVerifier::verifyDebugInfo() {
- if (!VerifyDebugInfo)
+void Verifier::verifyDebugInfo() {
+ // Run the debug info verifier only if the regular verifier succeeds, since
+ // sometimes checks that have already failed will cause crashes here.
+ if (EverBroken || !VerifyDebugInfo)
return;
DebugInfoFinder Finder;
}
}
-void DebugInfoVerifier::processInstructions(DebugInfoFinder &Finder) {
+void Verifier::processInstructions(DebugInfoFinder &Finder) {
for (const Function &F : *M)
for (auto I = inst_begin(&F), E = inst_end(&F); I != E; ++I) {
if (MDNode *MD = I->getMetadata(LLVMContext::MD_dbg))
}
}
-void DebugInfoVerifier::processCallInst(DebugInfoFinder &Finder,
- const CallInst &CI) {
+void Verifier::processCallInst(DebugInfoFinder &Finder, const CallInst &CI) {
if (Function *F = CI.getCalledFunction())
if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
switch (ID) {
- case Intrinsic::dbg_declare: {
- auto *DDI = cast<DbgDeclareInst>(&CI);
- Finder.processDeclare(*M, DDI);
- if (auto E = DDI->getExpression())
- Assert(DIExpression(E).Verify(), "DIExpression does not Verify!", E);
+ case Intrinsic::dbg_declare:
+ Finder.processDeclare(*M, cast<DbgDeclareInst>(&CI));
break;
- }
- case Intrinsic::dbg_value: {
- auto *DVI = cast<DbgValueInst>(&CI);
- Finder.processValue(*M, DVI);
- if (auto E = DVI->getExpression())
- Assert(DIExpression(E).Verify(), "DIExpression does not Verify!", E);
+ case Intrinsic::dbg_value:
+ Finder.processValue(*M, cast<DbgValueInst>(&CI));
break;
- }
default:
break;
}
// Note that this function's return value is inverted from what you would
// expect of a function called "verify".
- DebugInfoVerifier DIV(OS ? *OS : NullStr);
- return !V.verify(M) || !DIV.verify(M) || Broken;
+ return !V.verify(M) || Broken;
}
namespace {
AU.setPreservesAll();
}
};
-struct DebugInfoVerifierLegacyPass : public ModulePass {
- static char ID;
-
- DebugInfoVerifier V;
- bool FatalErrors;
-
- DebugInfoVerifierLegacyPass() : ModulePass(ID), FatalErrors(true) {
- initializeDebugInfoVerifierLegacyPassPass(*PassRegistry::getPassRegistry());
- }
- explicit DebugInfoVerifierLegacyPass(bool FatalErrors)
- : ModulePass(ID), V(dbgs()), FatalErrors(FatalErrors) {
- initializeDebugInfoVerifierLegacyPassPass(*PassRegistry::getPassRegistry());
- }
-
- bool runOnModule(Module &M) override {
- if (!V.verify(M) && FatalErrors)
- report_fatal_error("Broken debug info found, compilation aborted!");
-
- return false;
- }
-
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesAll();
- }
-};
}
char VerifierLegacyPass::ID = 0;
INITIALIZE_PASS(VerifierLegacyPass, "verify", "Module Verifier", false, false)
-char DebugInfoVerifierLegacyPass::ID = 0;
-INITIALIZE_PASS(DebugInfoVerifierLegacyPass, "verify-di", "Debug Info Verifier",
- false, false)
-
FunctionPass *llvm::createVerifierPass(bool FatalErrors) {
return new VerifierLegacyPass(FatalErrors);
}
-ModulePass *llvm::createDebugInfoVerifierPass(bool FatalErrors) {
- return new DebugInfoVerifierLegacyPass(FatalErrors);
-}
-
PreservedAnalyses VerifierPass::run(Module &M) {
if (verifyModule(M, &dbgs()) && FatalErrors)
report_fatal_error("Broken module found, compilation aborted!");