Index: include/llvm/LTO/LTOCodeGenerator.h =================================================================== --- include/llvm/LTO/LTOCodeGenerator.h +++ include/llvm/LTO/LTOCodeGenerator.h @@ -198,6 +198,7 @@ void DiagnosticHandler2(const DiagnosticInfo &DI); void emitError(const std::string &ErrMsg); + void emitWarning(const std::string &WarnMsg); LLVMContext &Context; std::unique_ptr MergedModule; Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -4430,6 +4430,21 @@ return !V.verify(M) || Broken; } +bool llvm::verifyModule(bool &BrokenDebugInfo, const Module &M, + raw_ostream *OS) { + // Don't use a raw_null_ostream. Printing IR is expensive. + Verifier V(OS, /*treatBrokenDebugInfoAsError=*/false); + bool Broken = false; + for (const Function &F : M) + if (!F.isDeclaration() && !F.isMaterializable()) + Broken |= !V.verify(F); + + Broken = !V.verify(M); + BrokenDebugInfo = V.hasBrokenDebugInfo(); + return Broken; +} + + namespace { struct VerifierLegacyPass : public FunctionPass { static char ID; Index: lib/LTO/LTOCodeGenerator.cpp =================================================================== --- lib/LTO/LTOCodeGenerator.cpp +++ lib/LTO/LTOCodeGenerator.cpp @@ -26,6 +26,7 @@ #include "llvm/Config/config.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" @@ -78,6 +79,16 @@ cl::init(false), #endif cl::Hidden); + +cl::opt LTOStripInvalidDebugInfo( + "lto-strip-invalid-debug-info", + cl::desc("Strip invalid debug info metadata during LTO."), +#ifdef NDEBUG + cl::init(true), +#else + cl::init(false), +#endif + cl::Hidden); } LTOCodeGenerator::LTOCodeGenerator(LLVMContext &Context) @@ -478,6 +489,15 @@ return; HasVerifiedInput = true; + if (LTOStripInvalidDebugInfo) { + bool BrokenDebugInfo = false; + if (verifyModule(BrokenDebugInfo, *MergedModule, &dbgs())) + report_fatal_error("Broken module found, compilation aborted!"); + if (BrokenDebugInfo) { + emitWarning("Invalid debug info found, debug info will be stripped"); + StripDebugInfo(*MergedModule); + } + } if (verifyModule(*MergedModule, &dbgs())) report_fatal_error("Broken module found, compilation aborted!"); } @@ -643,3 +663,10 @@ else Context.diagnose(LTODiagnosticInfo(ErrMsg)); } + +void LTOCodeGenerator::emitWarning(const std::string &WarnMsg) { + if (DiagHandler) + (*DiagHandler)(LTO_DS_WARNING, WarnMsg.c_str(), DiagContext); + else + Context.diagnose(LTODiagnosticInfo(WarnMsg, DS_Warning)); +} Index: test/LTO/X86/strip-debug-info.ll =================================================================== --- /dev/null +++ test/LTO/X86/strip-debug-info.ll @@ -0,0 +1,20 @@ +; RUN: not llvm-lto -lto-strip-invalid-debug-info=false \ +; RUN: -o %t.o %S/Inputs/strip-debug-info.bc 2>&1 | \ +; RUN: FileCheck %s -allow-empty -check-prefix=CHECK-ERR +; RUN: llvm-lto -lto-strip-invalid-debug-info=true -exported-symbol _foo \ +; RUN: -o %t.o %S/Inputs/strip-debug-info.bc 2>&1 | \ +; RUN: FileCheck %s -allow-empty -check-prefix=CHECK-WARN +; RUN: llvm-nm %t.o | FileCheck %s + +; CHECK-ERR: Broken module found, compilation aborted +; CHECK-WARN: Invalid debug info found, debug info will be stripped +; CHECK: foo +define void @foo() { + ret void +} + +!llvm.module.flags = !{!0} +!llvm.dbg.cu = !{!1} + +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = !DIFile(filename: "broken", directory: "")