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

Reply via email to