Add some first skeleton work for the DWARF5 Fission proposal. Emit
authorEric Christopher <echristo@gmail.com>
Fri, 30 Nov 2012 23:59:06 +0000 (23:59 +0000)
committerEric Christopher <echristo@gmail.com>
Fri, 30 Nov 2012 23:59:06 +0000 (23:59 +0000)
part of the compile unit CU and start separating out information into
the various sections that will be pulled out later.

WIP.

llvm-svn: 169061

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
llvm/test/DebugInfo/X86/fission-cu.ll [new file with mode: 0644]

index 10061e1..c4c9d3f 100644 (file)
@@ -153,7 +153,7 @@ DIType DbgVariable::getType() const {
 } // end llvm namespace
 
 DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
-  : Asm(A), MMI(Asm->MMI), FirstCU(0),
+  : Asm(A), MMI(Asm->MMI), FirstCU(0), FissionCU(0),
     AbbreviationsSet(InitAbbreviationsSetSize),
     SourceIdMap(DIEValueAllocator), StringPool(DIEValueAllocator),
     PrevLabel(NULL) {
@@ -650,6 +650,9 @@ CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) {
 
   if (!FirstCU)
     FirstCU = NewCU;
+  if (useDwarfFission() && !FissionCU)
+    FissionCU = constructFissionCU(N);
+
   CUMap.insert(std::make_pair(N, NewCU));
   return NewCU;
 }
@@ -927,8 +930,9 @@ void DwarfDebug::endModule() {
     // TODO: Fill this in for Fission sections and separate
     // out information into new sections.
 
-    // Emit all the DIEs into a debug info section.
+    // Emit the debug info section and compile units.
     emitDebugInfo();
+    emitDebugInfoDWO();
 
     // Corresponding abbreviations into a abbrev section.
     emitAbbreviations();
@@ -975,7 +979,9 @@ void DwarfDebug::endModule() {
   for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
          E = CUMap.end(); I != E; ++I)
     delete I->second;
-  FirstCU = NULL;  // Reset for the next Module, if any.
+  // Reset these for the next Module if we have one.
+  FirstCU = NULL;
+  FissionCU = NULL;
 }
 
 // Find abstract variable, if any, associated with Var.
@@ -1665,6 +1671,15 @@ DwarfDebug::computeSizeAndOffset(DIE *Die, unsigned Offset) {
 
 // Compute the size and offset of all the DIEs.
 void DwarfDebug::computeSizeAndOffsets() {
+  if (FissionCU) {
+    unsigned Offset =
+      sizeof(int32_t) + // Length of Compilation Unit Info
+      sizeof(int16_t) + // DWARF version number
+      sizeof(int32_t) + // Offset Into Abbrev. Section
+      sizeof(int8_t);   // Pointer Size (in bytes)
+
+    computeSizeAndOffset(FissionCU->getCUDie(), Offset);
+  }
   for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
          E = CUMap.end(); I != E; ++I) {
     // Compute size of compile unit header.
@@ -1795,11 +1810,8 @@ void DwarfDebug::emitDIE(DIE *Die) {
   }
 }
 
-// Emit the debug info section.
-void DwarfDebug::emitDebugInfo() {
-  // Start debug info section.
-  Asm->OutStreamer.SwitchSection(
-                            Asm->getObjFileLowering().getDwarfInfoSection());
+void DwarfDebug::emitCompileUnits(const MCSection *Section) {
+  Asm->OutStreamer.SwitchSection(Section);
   for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
          E = CUMap.end(); I != E; ++I) {
     CompileUnit *TheCU = I->second;
@@ -1830,6 +1842,14 @@ void DwarfDebug::emitDebugInfo() {
   }
 }
 
+// Emit the debug info section.
+void DwarfDebug::emitDebugInfo() {
+  if (!useDwarfFission())
+    emitCompileUnits(Asm->getObjFileLowering().getDwarfInfoSection());
+  else
+    emitFissionSkeletonCU(Asm->getObjFileLowering().getDwarfInfoSection());
+}
+
 // Emit the abbreviation section.
 void DwarfDebug::emitAbbreviations() {
   // Check to see if it is worth the effort.
@@ -2286,3 +2306,77 @@ void DwarfDebug::emitDebugInlineInfo() {
 
   Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_inlined_end", 1));
 }
+
+// DWARF5 Experimental Fission emitters.
+
+// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list,
+// DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id,
+// DW_AT_ranges_base, DW_AT_addr_base. If DW_AT_ranges is present,
+// DW_AT_low_pc and DW_AT_high_pc are not used, and vice versa.
+CompileUnit *DwarfDebug::constructFissionCU(const MDNode *N) {
+  DICompileUnit DIUnit(N);
+  StringRef FN = DIUnit.getFilename();
+  CompilationDir = DIUnit.getDirectory();
+  unsigned ID = getOrCreateSourceID(FN, CompilationDir);
+
+  DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
+  CompileUnit *NewCU = new CompileUnit(ID, DIUnit.getLanguage(), Die,
+                                       Asm, this);
+  // FIXME: This should be the .dwo file.
+  NewCU->addString(Die, dwarf::DW_AT_GNU_dwo_name, FN);
+
+  // FIXME: We also need DW_AT_addr_base and DW_AT_dwo_id.
+
+  // 2.17.1 requires that we use DW_AT_low_pc for a single entry point
+  // into an entity.
+  NewCU->addUInt(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0);
+  // DW_AT_stmt_list is a offset of line number information for this
+  // compile unit in debug_line section.
+  if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
+    NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
+                    Asm->GetTempSymbol("section_line"));
+  else
+    NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0);
+
+  if (!CompilationDir.empty())
+    NewCU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
+
+  return NewCU;
+}
+
+void DwarfDebug::emitFissionSkeletonCU(const MCSection *Section) {
+  Asm->OutStreamer.SwitchSection(Section);
+  DIE *Die = FissionCU->getCUDie();
+
+  // Emit the compile units header.
+  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("skel_info_begin",
+                                                FissionCU->getID()));
+
+  // Emit size of content not including length itself
+  unsigned ContentSize = Die->getSize() +
+    sizeof(int16_t) + // DWARF version number
+    sizeof(int32_t) + // Offset Into Abbrev. Section
+    sizeof(int8_t);   // Pointer Size (in bytes)
+
+  Asm->OutStreamer.AddComment("Length of Compilation Unit Info");
+  Asm->EmitInt32(ContentSize);
+  Asm->OutStreamer.AddComment("DWARF version number");
+  Asm->EmitInt16(dwarf::DWARF_VERSION);
+  Asm->OutStreamer.AddComment("Offset Into Abbrev. Section");
+  Asm->EmitSectionOffset(Asm->GetTempSymbol("abbrev_begin"),
+                         DwarfAbbrevSectionSym);
+  Asm->OutStreamer.AddComment("Address Size (in bytes)");
+  Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
+
+  emitDIE(Die);
+  Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("skel_info_end", FissionCU->getID()));
+
+
+}
+
+// Emit the .debug_info.dwo section for fission. This contains the compile
+// units that would normally be in debug_info.
+void DwarfDebug::emitDebugInfoDWO() {
+  assert(useDwarfFission() && "Got fission?");
+  emitCompileUnits(Asm->getObjFileLowering().getDwarfInfoDWOSection());
+}
index b6b28fa..35bddee 100644 (file)
@@ -205,6 +205,9 @@ class DwarfDebug {
 
   CompileUnit *FirstCU;
 
+  // The CU left in the original object file for Fission debug info.
+  CompileUnit *FissionCU;
+
   // Maps MDNode with its corresponding CompileUnit.
   DenseMap <const MDNode *, CompileUnit *> CUMap;
 
@@ -369,6 +372,9 @@ private:
   /// open.
   void endSections();
 
+  /// \brief Emit all of the compile units to the target section.
+  void emitCompileUnits(const MCSection *);
+
   /// \brief Emit the debug info section.
   void emitDebugInfo();
 
@@ -413,6 +419,17 @@ private:
   /// \brief Emit inline info using custom format.
   void emitDebugInlineInfo();
 
+  /// DWARF 5 Experimental Fission Emitters
+
+  /// \brief Construct the fission compile unit for the debug info section.
+  CompileUnit *constructFissionCU(const MDNode *);
+
+  /// \brief Emit the fission debug info section.
+  void emitFissionSkeletonCU(const MCSection *);
+
+  /// \brief Emit the debug info dwo section.
+  void emitDebugInfoDWO();
+
   /// \brief Create new CompileUnit for the given metadata node with tag
   /// DW_TAG_compile_unit.
   CompileUnit *constructCompileUnit(const MDNode *N);
diff --git a/llvm/test/DebugInfo/X86/fission-cu.ll b/llvm/test/DebugInfo/X86/fission-cu.ll
new file mode 100644 (file)
index 0000000..2c2c01a
--- /dev/null
@@ -0,0 +1,26 @@
+; RUN: llc -dwarf-fission=Enable -O0 %s -mtriple=x86_64-unknown-linux-gnu -filetype=obj -o %t
+; RUN: llvm-dwarfdump %t | FileCheck %s
+
+@a = common global i32 0, align 4
+
+!llvm.dbg.cu = !{!0}
+
+!0 = metadata !{i32 786449, i32 0, i32 12, metadata !"baz.c", metadata !"/usr/local/google/home/echristo/tmp", metadata !"clang version 3.3 (trunk 169021) (llvm/trunk 169020)", i1 true, i1 false, metadata !"", i32 0, metadata !1, metadata !1, metadata !1, metadata !3} ; [ DW_TAG_compile_unit ] [/usr/local/google/home/echristo/tmp/baz.c] [DW_LANG_C99]
+!1 = metadata !{metadata !2}
+!2 = metadata !{i32 0}
+!3 = metadata !{metadata !4}
+!4 = metadata !{metadata !5}
+!5 = metadata !{i32 786484, i32 0, null, metadata !"a", metadata !"a", metadata !"", metadata !6, i32 1, metadata !7, i32 0, i32 1, i32* @a} ; [ DW_TAG_variable ] [a] [line 1] [def]
+!6 = metadata !{i32 786473, metadata !"baz.c", metadata !"/usr/local/google/home/echristo/tmp", null} ; [ DW_TAG_file_type ]
+!7 = metadata !{i32 786468, null, metadata !"int", null, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
+
+; Check that the skeleton compile unit contains the proper attributes:
+; This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list,
+; DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id,
+; DW_AT_ranges_base, DW_AT_addr_base.
+
+; CHECK: DW_TAG_compile_unit [1]  
+; CHECK: DW_AT_GNU_dwo_name [DW_FORM_strp] ( .debug_str[0x00000035] = "baz.c")
+; CHECK: DW_AT_low_pc [DW_FORM_addr]       (0x0000000000000000)
+; CHECK: DW_AT_stmt_list [DW_FORM_data4]   (0x00000000)
+; CHECK: DW_AT_comp_dir [DW_FORM_strp]     ( .debug_str[0x0000003b] = "/usr/local/google/home/echristo/tmp")