Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -196,6 +196,9 @@ /// \brief Keep track of the metadata nodes that have been checked already. SmallPtrSet MDNodes; + /// Track all DICompileUnits visited. + SmallPtrSet CUVisited; + /// \brief Track unresolved string-based type references. SmallDenseMap UnresolvedTypeRefs; @@ -302,7 +305,9 @@ visitModuleFlags(M); visitModuleIdents(M); - // Verify type referneces last. + verifyCompileUnits(); + + // Verify type references last. verifyTypeRefs(); return !Broken; @@ -444,12 +449,15 @@ void verifyFrameRecoverIndices(); void verifySiblingFuncletUnwinds(); - // Module-level debug info verification... + /// @{ + /// Module-level debug info verification... void verifyTypeRefs(); + void verifyCompileUnits(); template void verifyBitPieceExpression(const DbgInfoIntrinsic &I, const MapTy &TypeRefs); void visitUnresolvedTypeRef(const MDString *S, const MDNode *N); + /// @} }; } // End anonymous namespace @@ -969,6 +977,7 @@ Assert(Op && isa(Op), "invalid macro ref", &N, Op); } } + CUVisited.insert(&N); } void Verifier::visitDISubprogram(const DISubprogram &N) { @@ -4251,6 +4260,18 @@ Assert(false, "unresolved type ref", S, N); } +void Verifier::verifyCompileUnits() { + auto *CUs = M->getNamedMetadata("llvm.dbg.cu"); + SmallPtrSet Listed; + if (CUs) + Listed.insert(CUs->op_begin(), CUs->op_end()); + Assert( + std::all_of(CUVisited.begin(), CUVisited.end(), + [&Listed](const Metadata *CU) { return Listed.count(CU); }), + "All DICompileUnits must be listed in llvm.dbg.cu"); + CUVisited.clear(); +} + void Verifier::verifyTypeRefs() { auto *CUs = M->getNamedMetadata("llvm.dbg.cu"); if (!CUs) Index: test/Assembler/dicompileunit.ll =================================================================== --- test/Assembler/dicompileunit.ll +++ test/Assembler/dicompileunit.ll @@ -1,8 +1,11 @@ ; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s ; RUN: verify-uselistorder %s +; Force a specific numbering. ; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9} !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9} +; CHECK: !llvm.dbg.cu = !{!8, !9} +!llvm.dbg.cu = !{!8, !9} !0 = distinct !{} !1 = !DIFile(filename: "path/to/file", directory: "/path/to/dir") @@ -24,3 +27,5 @@ !9 = distinct !DICompileUnit(language: 12, file: !1, producer: "", isOptimized: false, flags: "", runtimeVersion: 0, splitDebugFilename: "", emissionKind: 0) +!llvm.module.flags = !{!10} +!10 = !{i32 2, !"Debug Info Version", i32 3} Index: test/Transforms/LoopIdiom/debug-line.ll =================================================================== --- test/Transforms/LoopIdiom/debug-line.ll +++ test/Transforms/LoopIdiom/debug-line.ll @@ -28,11 +28,11 @@ declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnone !llvm.module.flags = !{!19} -!llvm.dbg.sp = !{!0} +!llvm.dbg.cu = !{!2} !0 = distinct !DISubprogram(name: "foo", line: 2, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, file: !18, scope: !1, type: !3) !1 = !DIFile(filename: "li.c", directory: "/private/tmp") -!2 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 2.9 (trunk 127165:127174)", isOptimized: true, emissionKind: 0, file: !18, enums: !9, retainedTypes: !9) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 2.9 (trunk 127165:127174)", isOptimized: true, emissionKind: 0, file: !18, enums: !9, subprograms: !{!0}, retainedTypes: !9) !3 = !DISubroutineType(types: !4) !4 = !{null} !5 = !DILocalVariable(name: "a", line: 2, arg: 1, scope: !0, file: !1, type: !6) Index: test/Verifier/dbg-orphaned-compileunit.ll =================================================================== --- /dev/null +++ test/Verifier/dbg-orphaned-compileunit.ll @@ -0,0 +1,10 @@ +; RUN: not llvm-as -disable-output <%s 2>&1 | FileCheck %s +; CHECK: assembly parsed, but does not verify +; CHECK-NEXT: All DICompileUnits must be listed in llvm.dbg.cu + +!named = !{!1} +!llvm.module.flags = !{!0} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!llvm.dbg.cu = !{} +!1 = distinct !DICompileUnit(file: !2, language: DW_LANG_Fortran77) +!2 = !DIFile(filename: "test.f", directory: "") Index: tools/bugpoint/CrashDebugger.cpp =================================================================== --- tools/bugpoint/CrashDebugger.cpp +++ tools/bugpoint/CrashDebugger.cpp @@ -552,7 +552,9 @@ std::vector ToDelete; ToDelete.reserve(M->named_metadata_size() - Names.size()); for (auto &NamedMD : M->named_metadata()) - if (!Names.count(NamedMD.getName())) + // Always keep a nonempty llvm.dbg.cu because the Verifier would complain. + if (!Names.count(NamedMD.getName()) && + (!(NamedMD.getName() == "llvm.dbg.cu" && NamedMD.getNumOperands() > 0))) ToDelete.push_back(&NamedMD); for (auto *NamedMD : ToDelete)