Port the strip-invalid-debuginfo logic to the legacy verifier pass, too.

Since r268966 the modern Verifier pass defaults to stripping invalid debug info
in nonasserts builds.  This patch ports this behavior back to the legacy
Verifier pass as well.  The primary motivation is that the clang frontend
accepts bitcode files as input but is still using the legacy pass pipeline.

Background: The problem I'm trying to solve with this sequence of patches is
that historically we've done a really bad job at verifying debug info. We want
to be able to make the verifier stricter without having to worry about breaking
bitcode compatibility with existing producers. For example, we don't necessarily
want IR produced by an older version of clang to be rejected by an LTO link just
because of malformed debug info, and rather provide an option to strip it. Note
that merely outdated (but well-formed) debug info would continue to be
auto-upgraded in this scenario.

http://reviews.llvm.org/D20629
<rdar://problem/26448800>

llvm-svn: 270768
This commit is contained in:
Adrian Prantl 2016-05-25 21:33:20 +00:00
parent d6469e3467
commit 94a903eefc
2 changed files with 39 additions and 7 deletions

View File

@ -4460,17 +4460,16 @@ struct VerifierLegacyPass : public FunctionPass {
static char ID;
Verifier V;
bool FatalErrors;
bool FatalErrors = true;
VerifierLegacyPass()
: FunctionPass(ID),
V(&dbgs(), /*ShouldTreatBrokenDebugInfoAsError=*/true),
FatalErrors(true) {
V(&dbgs(), /*ShouldTreatBrokenDebugInfoAsError=*/false) {
initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry());
}
explicit VerifierLegacyPass(bool FatalErrors)
: FunctionPass(ID),
V(&dbgs(), /*ShouldTreatBrokenDebugInfoAsError=*/true),
V(&dbgs(), /*ShouldTreatBrokenDebugInfoAsError=*/false),
FatalErrors(FatalErrors) {
initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry());
}
@ -4483,9 +4482,20 @@ struct VerifierLegacyPass : public FunctionPass {
}
bool doFinalization(Module &M) override {
if (!V.verify(M) && FatalErrors)
report_fatal_error("Broken module found, compilation aborted!");
bool HasErrors = !V.verify(M);
if (FatalErrors) {
if (HasErrors)
report_fatal_error("Broken module found, compilation aborted!");
assert(!V.hasBrokenDebugInfo() && "Module contains invalid debug info");
}
// Strip broken debug info.
if (V.hasBrokenDebugInfo()) {
DiagnosticInfoIgnoringInvalidDebugMetadata DiagInvalid(M);
M.getContext().diagnose(DiagInvalid);
if (!StripDebugInfo(M))
report_fatal_error("Failed to strip malformed debug info");
}
return false;
}

View File

@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/Verifier.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DerivedTypes.h"
@ -16,7 +15,9 @@
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "gtest/gtest.h"
namespace llvm {
@ -198,5 +199,26 @@ TEST(VerifierTest, StripInvalidDebugInfo) {
}
#endif
TEST(VerifierTest, StripInvalidDebugInfoLegacy) {
LLVMContext C;
Module M("M", C);
DIBuilder DIB(M);
DIB.createCompileUnit(dwarf::DW_LANG_C89, "broken.c", "/",
"unittest", false, "", 0);
DIB.finalize();
EXPECT_FALSE(verifyModule(M));
// Now break it.
auto *File = DIB.createFile("not-a-CU.f", ".");
NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu");
NMD->addOperand(File);
EXPECT_TRUE(verifyModule(M));
legacy::PassManager Passes;
Passes.add(createVerifierPass(false));
Passes.run(M);
EXPECT_FALSE(verifyModule(M));
}
} // end anonymous namespace
} // end namespace llvm