DebugInfo: Move type units into the debug_types section with appropriate comdat group...
authorDavid Blaikie <dblaikie@gmail.com>
Fri, 13 Dec 2013 01:06:41 +0000 (01:06 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Fri, 13 Dec 2013 01:06:41 +0000 (01:06 +0000)
This commit does not complete the type units feature - there are issues
around fission support (skeletal type units, pubtypes/pubnames) and
hashing of some types including those containing references to types in
other type units.

Originally committed as r197073 and reverted in r197079.

This commit originally got jumbled up with another build-breaking commit
and I can't find the failures I thought this caused anymore.
Recommitting to hopefully get some clean buildbot results to work from.
I have a sneaking suspicion there's unstable output in the comdat group
output of MCStreamer...

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197197 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCObjectFileInfo.h
include/llvm/MC/MCSectionELF.h
lib/CodeGen/AsmPrinter/DwarfDebug.cpp
lib/CodeGen/AsmPrinter/DwarfUnit.cpp
lib/CodeGen/AsmPrinter/DwarfUnit.h
lib/MC/MCObjectFileInfo.cpp
test/DebugInfo/X86/c-type-units.ll
test/DebugInfo/X86/generate-odr-hash.ll

index 277ca579dae02f30582031ab5eff69776c85c7ec..7734a157f54f0461a4332512774c579fa00c8fcb 100644 (file)
@@ -262,6 +262,8 @@ public:
   const MCSection *getDwarfInfoDWOSection() const {
     return DwarfInfoDWOSection;
   }
+  const MCSection *getDwarfTypesSection(uint64_t Hash) const;
+  const MCSection *getDwarfTypesDWOSection(uint64_t Hash) const;
   const MCSection *getDwarfAbbrevDWOSection() const {
     return DwarfAbbrevDWOSection;
   }
index 59799158ad3c6d4a2b70ed649f8712a259e4b805..139adbf45c04765cbdda87f548ef3701bb54bc40 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "llvm/ADT/StringRef.h"
 #include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCSymbol.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ELF.h"
 #include "llvm/Support/raw_ostream.h"
@@ -60,8 +61,13 @@ public:
 
   StringRef getSectionName() const { return SectionName; }
   virtual std::string getLabelBeginName() const {
-    return SectionName.str() + "_begin"; }
+    if (Group)
+      return (SectionName.str() + '_' + Group->getName() + "_begin").str();
+    return SectionName.str() + "_begin";
+  }
   virtual std::string getLabelEndName() const {
+    if (Group)
+      return (SectionName.str() + '_' + Group->getName() + "_end").str();
     return SectionName.str() + "_end";
   }
   unsigned getType() const { return Type; }
index 27348a4b9b86c370e785dc0f72d21e58af36f5c9..7c61407e8732135eaa7e235ff3dbd814a2c42c59 100644 (file)
@@ -3056,19 +3056,17 @@ void DwarfDebug::addDwarfTypeUnitType(uint16_t Language, DIE *RefDie,
     // referenced type, or possibly walk the precomputed hashes of related types
     // at the end.
     uint64_t Signature = DIEHash().computeTypeSignature(*Die);
+    NewTU->setTypeSignature(Signature);
+    NewTU->setType(Die);
 
     // Remove the References vector and add the type hash.
     I->second.first = Signature;
     I->second.second = NULL;
 
     NewTU->initSection(
-        useSplitDwarf() ? Asm->getObjFileLowering().getDwarfInfoDWOSection()
-                        : Asm->getObjFileLowering().getDwarfInfoSection(),
-        // FIXME: This is subtle (using the info section even when
-        // this CU is in the dwo section) and necessary for the
-        // current arange code - ideally it should iterate
-        // skeleton units, not full units, if it's going to reference skeletons
-        useSplitDwarf() ? NULL : DwarfInfoSectionSym);
+        useSplitDwarf()
+            ? Asm->getObjFileLowering().getDwarfTypesDWOSection(Signature)
+            : Asm->getObjFileLowering().getDwarfTypesSection(Signature));
   }
 
   // Populate all the signatures.
index f87480d290b5455df549420e9247342fa36619ad..709f5bec031b6c32bedd7ea8a4f20c8bdaf8a168 100644 (file)
@@ -1997,3 +1997,27 @@ void DwarfUnit::emitHeader(const MCSection *ASection,
   Asm->OutStreamer.AddComment("Address Size (in bytes)");
   Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
 }
+
+void DwarfTypeUnit::emitHeader(const MCSection *ASection,
+                               const MCSymbol *ASectionSym) const {
+  DwarfUnit::emitHeader(ASection, ASectionSym);
+  Asm->OutStreamer.AddComment("Type Signature");
+  Asm->OutStreamer.EmitIntValue(TypeSignature, sizeof(TypeSignature));
+  Asm->OutStreamer.AddComment("Type DIE Offset");
+  Asm->OutStreamer.EmitIntValue(Ty->getOffset(), sizeof(Ty->getOffset()));
+}
+
+void DwarfTypeUnit::initSection(const MCSection *Section) {
+  assert(!this->Section);
+  this->Section = Section;
+  // Since each type unit is contained in its own COMDAT section, the begin
+  // label and the section label are the same. Using the begin label emission in
+  // DwarfDebug to emit the section label as well is slightly subtle/sneaky, but
+  // the only other alternative of lazily constructing start-of-section labels
+  // and storing a mapping in DwarfDebug (or AsmPrinter).
+  this->SectionSym = this->LabelBegin =
+      Asm->GetTempSymbol(Section->getLabelBeginName(), getUniqueID());
+  this->LabelEnd =
+      Asm->GetTempSymbol(Section->getLabelEndName(), getUniqueID());
+  this->LabelRange = Asm->GetTempSymbol("gnu_ranges", getUniqueID());
+}
index 26b5f09004e1d5b0eddb9124fb91410f69c0db8f..6242a058cf8d0a272fcf37ef344767d7fb20ec4c 100644 (file)
@@ -413,14 +413,15 @@ public:
 
   /// Compute the size of a header for this unit, not including the initial
   /// length field.
-  unsigned getHeaderSize() const {
+  virtual unsigned getHeaderSize() const {
     return sizeof(int16_t) + // DWARF version number
            sizeof(int32_t) + // Offset Into Abbrev. Section
            sizeof(int8_t);   // Pointer Size (in bytes)
   }
 
   /// Emit the header for this unit, not including the initial length field.
-  void emitHeader(const MCSection *ASection, const MCSymbol *ASectionSym) const;
+  virtual void emitHeader(const MCSection *ASection,
+                          const MCSymbol *ASectionSym) const;
 
 protected:
   /// getOrCreateStaticMemberDIE - Create new static data member DIE.
@@ -513,12 +514,25 @@ public:
 class DwarfTypeUnit : public DwarfUnit {
 private:
   uint16_t Language;
+  uint64_t TypeSignature;
+  const DIE *Ty;
 
 public:
   DwarfTypeUnit(unsigned UID, DIE *D, uint16_t Language, AsmPrinter *A,
                 DwarfDebug *DW, DwarfFile *DWU);
 
+  void setTypeSignature(uint64_t Signature) { TypeSignature = Signature; }
+  void setType(const DIE *Ty) { this->Ty = Ty; }
+
   uint16_t getLanguage() const LLVM_OVERRIDE { return Language; }
+  /// Emit the header for this unit, not including the initial length field.
+  void emitHeader(const MCSection *ASection, const MCSymbol *ASectionSym) const
+      LLVM_OVERRIDE;
+  unsigned getHeaderSize() const LLVM_OVERRIDE {
+    return DwarfUnit::getHeaderSize() + sizeof(uint64_t) + // Type Signature
+           sizeof(uint32_t);                               // Type DIE Offset
+  }
+  void initSection(const MCSection *Section);
 };
 } // end llvm namespace
 #endif
index 8ef4a0a6d7b14351033fcabe281c9e1395638b60..da7072824792e2bc678098405943e7a55b7628ba 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "llvm/MC/MCObjectFileInfo.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCSection.h"
 #include "llvm/MC/MCSectionCOFF.h"
@@ -718,6 +719,17 @@ void MCObjectFileInfo::InitMCObjectFileInfo(StringRef TT, Reloc::Model relocm,
   }
 }
 
+const MCSection *MCObjectFileInfo::getDwarfTypesSection(uint64_t Hash) const {
+  return Ctx->getELFSection(".debug_types", ELF::SHT_PROGBITS, ELF::SHF_GROUP,
+                            SectionKind::getMetadata(), 0, utostr(Hash));
+}
+
+const MCSection *
+MCObjectFileInfo::getDwarfTypesDWOSection(uint64_t Hash) const {
+  return Ctx->getELFSection(".debug_types.dwo", ELF::SHT_GROUP, 0,
+                            SectionKind::getMetadata(), 0, utostr(Hash));
+}
+
 void MCObjectFileInfo::InitEHFrameSection() {
   if (Env == IsMachO)
     EHFrameSection =
index 7fbbf7a3f025bb7432584706c43201b9cffbcf62..f931d5145647bda48fc217bb3ea9616356c166e8 100644 (file)
@@ -1,6 +1,6 @@
 ; REQUIRES: object-emission
 
-; RUN: llc -o - %s -filetype=obj -O0 -generate-type-units -mtriple=x86_64-unknown-linux-gnu | llvm-dwarfdump -debug-dump=info - | FileCheck %s
+; RUN: llc -o - %s -filetype=obj -O0 -generate-dwarf-pub-sections=Disable -generate-type-units -mtriple=x86_64-unknown-linux-gnu | llvm-dwarfdump -debug-dump=types - | FileCheck %s
 
 ; struct foo {
 ; } f;
index e76d6cc148e35085c2f6c4da36c6da56fe5a8937..8272cc04f4569f95ccb8db1db970a135b5aa2b1a 100644 (file)
 
 ; CHECK-LABEL: .debug_info contents:
 ; CHECK: Compile Unit: length = [[CU_SIZE:[0-9a-f]+]]
-; Check that we generate a hash for bar and the value.
-; CHECK-LABEL: DW_AT_GNU_odr_signature [DW_FORM_data8] (0x200520c0d5b90eff)
-; CHECK: DW_TAG_structure_type
-; CHECK-NEXT: debug_str{{.*}}"bar"
+
+; CHECK-LABEL: .debug_types contents:
 
 ; Check that we generate a hash for fluffy and the value.
-; CHECK-LABEL: DW_AT_GNU_odr_signature [DW_FORM_data8]   (0x9a0124d5a0c21c52)
+; CHECK-LABEL: type_signature = 0x139b2e1ea94afec7
+; CHECK: DW_AT_GNU_odr_signature [DW_FORM_data8]   (0x9a0124d5a0c21c52)
 ; CHECK: DW_TAG_namespace
 ; CHECK-NEXT: debug_str{{.*}}"echidna"
 ; CHECK: DW_TAG_namespace
 ; CHECK: DW_TAG_class_type
 ; CHECK-NEXT: debug_str{{.*}}"fluffy"
 
-; We emit no hash for walrus since the type is contained in an anonymous
+; Check that we generate a hash for wombat and the value, but not for the
+; anonymous type contained within.
+; CHECK-LABEL: type_signature = 0x73776f130648b986
+; CHECK: DW_AT_GNU_odr_signature [DW_FORM_data8] (0x685bcc220141e9d7)
+; CHECK: DW_TAG_structure_type
+; CHECK-NEXT: debug_str{{.*}}"wombat"
+
+; Check that we generate a hash for bar and the value.
+; CHECK-LABEL: type_signature = 0x6a7ee3d400662e88
+; CHECK: DW_AT_GNU_odr_signature [DW_FORM_data8] (0x200520c0d5b90eff)
+; CHECK: DW_TAG_structure_type
+; CHECK-NEXT: debug_str{{.*}}"bar"
+
 ; namespace and won't violate any ODR-ness.
+; CHECK-LABEL: type_signature = 0xc0d031d6449dbca7
 ; CHECK: DW_TAG_type_unit
 ; CHECK-NOT: NULL
+; We emit no hash for walrus since the type is contained in an anonymous
 ; CHECK-NOT: DW_AT_GNU_odr_signature
 ; CHECK: DW_TAG_structure_type
 ; CHECK-NEXT: debug_str{{.*}}"walrus"
 ; CHECK: DW_TAG_subprogram
 
 
-; Check that we generate a hash for wombat and the value, but not for the
-; anonymous type contained within.
-; CHECK-LABEL: DW_AT_GNU_odr_signature [DW_FORM_data8] (0x685bcc220141e9d7)
-; CHECK: DW_TAG_structure_type
-; CHECK-NEXT: debug_str{{.*}}"wombat"
-; CHECK: DW_TAG_type_unit
-; CHECK: DW_TAG_structure_type
+; Check that we generate no ODR hash for the anonymous type nested inside 'wombat'
+; CHECK-LABEL: type_signature = 0xbf6fc40e82583d7c
 ; The signature for the outer 'wombat' type - this can be FileChecked once the
 ; type units are moved to their own section with the full type unit header
 ; including the signature
 ; CHECK-NEXT: unit_size = [[CU_SIZE]]
 ; CHECK-NEXT: Offset Name
 ; Type unit for 'bar'
-; CHECK-NEXT: unit_size = 0x0000001f
+; CHECK-NEXT: unit_size = 0x0000002b
 ; CHECK-NEXT: Offset Name
 ; CHECK-NEXT: "bar"
-; CHECK-NEXT: unit_size = 0x00000059
+; CHECK-NEXT: unit_size = 0x00000065
 ; CHECK-NEXT: Offset Name
 ; CHECK-NEXT: "int"
 ; CHECK-NEXT: "echidna::capybara::mongoose::fluffy"
-; CHECK-NEXT: unit_size = 0x0000002f
+; CHECK-NEXT: unit_size = 0x0000003b
 ; CHECK-NEXT: Offset Name
 ; CHECK-NEXT: "walrus"
-; CHECK-NEXT: unit_size = 0x00000036
+; CHECK-NEXT: unit_size = 0x00000042
 ; CHECK-NEXT: Offset Name
 ; CHECK-NEXT: "wombat"
-; CHECK-NEXT: unit_size = 0x0000003f
+; CHECK-NEXT: unit_size = 0x0000004b
 ; CHECK-NEXT: Offset Name
 ; CHECK-NEXT: "int"