aprantl created this revision. aprantl added reviewers: dblaikie, echristo, dexonsmith. aprantl added subscribers: davide, llvm-commits, cfe-commits. aprantl set the repository for this revision to rL LLVM.
As indicated in D18612, sample-based profiling and optimization remarks currently remove DICompileUnits from llvm.dbg.cu to suppress the emission of debug info from them. This is somewhat of a hack and only borderline legal IR. This patch uses the recently introduced NoDebug emission kind in DICompileUnit to achieve the same result without breaking the Verifier. A nice side-effect of this change is that it is now possible to combine NoDebug and regular compile units under LTO. For simplicity I combined the llvm and cfe patches into one review. Repository: rL LLVM http://reviews.llvm.org/D18808 Files: include/llvm/IR/DIBuilder.h lib/CodeGen/AsmPrinter/DwarfDebug.cpp lib/IR/DIBuilder.cpp test/DebugInfo/X86/mixed-nodebug-cu.ll tools/clang/lib/CodeGen/CGDebugInfo.cpp tools/clang/test/Frontend/optimization-remark.c tools/clang/test/Frontend/profile-sample-use-loc-tracking.c
Index: tools/clang/test/Frontend/profile-sample-use-loc-tracking.c =================================================================== --- tools/clang/test/Frontend/profile-sample-use-loc-tracking.c +++ tools/clang/test/Frontend/profile-sample-use-loc-tracking.c @@ -10,9 +10,10 @@ // CHECK: , !dbg ! // CHECK-NOT: DW_TAG_base_type -// But llvm.dbg.cu should be missing (to prevent writing debug info to +// The CU should be marked NoDebug (to prevent writing debug info to // the final output). -// CHECK-NOT: !llvm.dbg.cu = !{ +// CHECK: !llvm.dbg.cu = !{![[CU:.*]]} +// CHECK: ![[CU]] = distinct !DICompileUnit({{.*}}emissionKind: NoDebug int bar(int j) { return (j + j - 2) * (j - 2) * j; Index: tools/clang/test/Frontend/optimization-remark.c =================================================================== --- tools/clang/test/Frontend/optimization-remark.c +++ tools/clang/test/Frontend/optimization-remark.c @@ -27,9 +27,10 @@ // CHECK: , !dbg ! // CHECK-NOT: DW_TAG_base_type -// But llvm.dbg.cu should be missing (to prevent writing debug info to +// The CU should be marked NoDebug (to prevent writing debug info to // the final output). -// CHECK-NOT: !llvm.dbg.cu = !{ +// CHECK: !llvm.dbg.cu = !{![[CU:.*]]} +// CHECK: ![[CU]] = distinct !DICompileUnit({{.*}}emissionKind: NoDebug int foo(int x, int y) __attribute__((always_inline)); int foo(int x, int y) { return x + y; } Index: tools/clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- tools/clang/lib/CodeGen/CGDebugInfo.cpp +++ tools/clang/lib/CodeGen/CGDebugInfo.cpp @@ -396,16 +396,27 @@ if (LO.ObjC1) RuntimeVers = LO.ObjCRuntime.isNonFragile() ? 2 : 1; + llvm::DICompileUnit::DebugEmissionKind EmissionKind; + switch (DebugKind) { + case codegenoptions::NoDebugInfo: + case codegenoptions::LocTrackingOnly: + EmissionKind = llvm::DICompileUnit::NoDebug; + break; + case codegenoptions::DebugLineTablesOnly: + EmissionKind = llvm::DICompileUnit::LineTablesOnly; + break; + case codegenoptions::LimitedDebugInfo: + case codegenoptions::FullDebugInfo: + EmissionKind = llvm::DICompileUnit::FullDebug; + break; + } + // Create new compile unit. // FIXME - Eliminate TheCU. TheCU = DBuilder.createCompileUnit( LangTag, remapDIPath(MainFileName), remapDIPath(getCurrentDirname()), Producer, LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers, - CGM.getCodeGenOpts().SplitDwarfFile, - DebugKind <= codegenoptions::DebugLineTablesOnly - ? llvm::DICompileUnit::LineTablesOnly - : llvm::DICompileUnit::FullDebug, - 0 /* DWOid */, DebugKind != codegenoptions::LocTrackingOnly); + CGM.getCodeGenOpts().SplitDwarfFile, EmissionKind, 0 /* DWOid */); } llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) { Index: test/DebugInfo/X86/mixed-nodebug-cu.ll =================================================================== --- /dev/null +++ test/DebugInfo/X86/mixed-nodebug-cu.ll @@ -0,0 +1,50 @@ +; RUN: llc %s -o %t -filetype=obj +; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s +; CHECK: DW_TAG_compile_unit +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name{{.*}}"f" +; CHECK-NOT: DW_TAG_compile_unit +; +; created from +; void f() {} // compile with -g +; void g() {} // compile with -Rpass=inline +; and llvm-linking the result. + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.11.0" + +; Function Attrs: nounwind ssp uwtable +define void @f() #0 !dbg !4 { +entry: + ret void, !dbg !15 +} + +; Function Attrs: nounwind ssp uwtable +define void @g() #0 !dbg !9 { +entry: + ret void, !dbg !16 +} + +attributes #0 = { nounwind ssp uwtable } + +!llvm.dbg.cu = !{!0, !7} +!llvm.ident = !{!11, !11} +!llvm.module.flags = !{!12, !13, !14} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 265328) (llvm/trunk 265330)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, subprograms: !3) +!1 = !DIFile(filename: "test.c", directory: "/Volumes/Data/llvm") +!2 = !{} +!3 = !{!4} +!4 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, variables: !2) +!5 = !DISubroutineType(types: !6) +!6 = !{null} +!7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 265328) (llvm/trunk 265330)", isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug, enums: !2, subprograms: !8) +!8 = !{!9} +!9 = distinct !DISubprogram(name: "g", scope: !1, file: !1, line: 1, type: !10, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, variables: !2) +!10 = !DISubroutineType(types: !2) +!11 = !{!"clang version 3.9.0 (trunk 265328) (llvm/trunk 265330)"} +!12 = !{i32 2, !"Dwarf Version", i32 2} +!13 = !{i32 2, !"Debug Info Version", i32 3} +!14 = !{i32 1, !"PIC Level", i32 2} +!15 = !DILocation(line: 1, column: 12, scope: !4) +!16 = !DILocation(line: 1, column: 12, scope: !9) Index: lib/IR/DIBuilder.cpp =================================================================== --- lib/IR/DIBuilder.cpp +++ lib/IR/DIBuilder.cpp @@ -137,7 +137,7 @@ DICompileUnit *DIBuilder::createCompileUnit( unsigned Lang, StringRef Filename, StringRef Directory, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RunTimeVer, StringRef SplitName, - DICompileUnit::DebugEmissionKind Kind, uint64_t DWOId, bool EmitDebugInfo) { + DICompileUnit::DebugEmissionKind Kind, uint64_t DWOId) { assert(((Lang <= dwarf::DW_LANG_Fortran08 && Lang >= dwarf::DW_LANG_C89) || (Lang <= dwarf::DW_LANG_hi_user && Lang >= dwarf::DW_LANG_lo_user)) && @@ -152,15 +152,8 @@ nullptr, nullptr, nullptr, nullptr, nullptr, DWOId); // Create a named metadata so that it is easier to find cu in a module. - // Note that we only generate this when the caller wants to actually - // emit debug information. When we are only interested in tracking - // source line locations throughout the backend, we prevent codegen from - // emitting debug info in the final output by not generating llvm.dbg.cu. - if (EmitDebugInfo) { - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu"); - NMD->addOperand(CUNode); - } - + NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu"); + NMD->addOperand(CUNode); trackIfUnresolved(CUNode); return CUNode; } Index: lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -473,8 +473,13 @@ SingleCU = CU_Nodes->getNumOperands() == 1; + unsigned DebugCUs = 0; for (MDNode *N : CU_Nodes->operands()) { auto *CUNode = cast<DICompileUnit>(N); + if (CUNode->getEmissionKind() == DICompileUnit::NoDebug) + continue; + + DebugCUs++; DwarfCompileUnit &CU = constructDwarfCompileUnit(CUNode); for (auto *IE : CUNode->getImportedEntities()) CU.addImportedEntity(IE); @@ -502,7 +507,7 @@ } // Tell MMI that we have debug info. - MMI->setDebugInfoAvailability(true); + MMI->setDebugInfoAvailability(DebugCUs > 0); } void DwarfDebug::finishVariableDefinitions() { @@ -538,6 +543,9 @@ if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) { for (MDNode *N : CU_Nodes->operands()) { auto *TheCU = cast<DICompileUnit>(N); + if (TheCU->getEmissionKind() == DICompileUnit::NoDebug) + continue; + // Construct subprogram DIE and add variables DIEs. DwarfCompileUnit *SPCU = static_cast<DwarfCompileUnit *>(CUMap.lookup(TheCU)); @@ -1090,7 +1098,10 @@ // includes the directory of the cpp file being built, even when the file name // is absolute (such as an <> lookup header))) DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); - assert(TheCU && "Unable to find compile unit!"); + if (!TheCU) + // Once DISubprogram points to the owning CU, we can assert that the CU has + // a NoDebug EmissionKind here. + return; if (Asm->OutStreamer->hasRawTextSupport()) // Use a single line table if we are generating assembly. Asm->OutStreamer->getContext().setDwarfCompileUnitID(0); @@ -1113,7 +1124,8 @@ "endFunction should be called with the same function as beginFunction"); if (!MMI->hasDebugInfo() || LScopes.empty() || - !MF->getFunction()->getSubprogram()) { + !MF->getFunction()->getSubprogram() || + !SPMap.lookup(MF->getFunction()->getSubprogram())) { // If we don't have a lexical scope for this function then there will // be a hole in the range information. Keep note of this by setting the // previously used section to nullptr. Index: include/llvm/IR/DIBuilder.h =================================================================== --- include/llvm/IR/DIBuilder.h +++ include/llvm/IR/DIBuilder.h @@ -92,23 +92,13 @@ /// out into. /// \param Kind The kind of debug information to generate. /// \param DWOId The DWOId if this is a split skeleton compile unit. - /// \param EmitDebugInfo A boolean flag which indicates whether - /// debug information should be written to - /// the final output or not. When this is - /// false, debug information annotations will - /// be present in the IL but they are not - /// written to the final assembly or object - /// file. This supports tracking source - /// location information in the back end - /// without actually changing the output - /// (e.g., when using optimization remarks). DICompileUnit * createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RV, StringRef SplitName = StringRef(), DICompileUnit::DebugEmissionKind Kind = DICompileUnit::DebugEmissionKind::FullDebug, - uint64_t DWOId = 0, bool EmitDebugInfo = true); + uint64_t DWOId = 0); /// Create a file descriptor to hold debugging information /// for a file.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits