<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Nov 19, 2013 at 3:08 PM, David Blaikie <span dir="ltr"><<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: dblaikie<br>
Date: Tue Nov 19 17:08:21 2013<br>
New Revision: 195166<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=195166&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=195166&view=rev</a><br>
Log:<br>
DebugInfo: Partial implementation of DWARF type units.<br>
<br>
Emit DW_TAG_type_units into the debug_info section using compile unit<br>
headers. This is bogus/unusable by debuggers, but testable and provides<br>
more isolated review.<br>
<br>
Subsequent patches will include support for type unit headers and<br>
emission into the debug_types section, as well as comdat grouping the<br>
types based on their hash. Also the CompileUnit type will be renamed<br>
'Unit' and relevant portions pulled out into respective CompileUnit and<br>
TypeUnit types.<br>
<br>
Modified:<br>
    llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp<br>
    llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h<br>
    llvm/trunk/lib/CodeGen/AsmPrinter/DIEHash.cpp<br>
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp<br>
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h<br>
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp<br>
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h<br>
    llvm/trunk/test/DebugInfo/X86/generate-odr-hash.ll<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp?rev=195166&r1=195165&r2=195166&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp?rev=195166&r1=195165&r2=195166&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp Tue Nov 19 17:08:21 2013<br>
@@ -114,18 +114,19 @@ DIE::~DIE() {<br>
<br>
 /// Climb up the parent chain to get the compile unit DIE to which this DIE<br>
 /// belongs.<br>
-const DIE *DIE::getCompileUnit() const {<br>
-  const DIE *Cu = getCompileUnitOrNull();<br>
+const DIE *DIE::getUnit() const {<br>
+  const DIE *Cu = getUnitOrNull();<br></blockquote><div><br></div><div>Hi David,</div><div><br></div><div>To help reviewing the changes, it is better to separate changes to getCompileUnit and getCompileUnitOrNull to a separate patch.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
   assert(Cu && "We should not have orphaned DIEs.");<br>
   return Cu;<br>
 }<br>
<br>
 /// Climb up the parent chain to get the compile unit DIE this DIE belongs<br>
 /// to. Return NULL if DIE is not added to an owner yet.<br>
-const DIE *DIE::getCompileUnitOrNull() const {<br>
+const DIE *DIE::getUnitOrNull() const {<br>
   const DIE *p = this;<br>
   while (p) {<br>
-    if (p->getTag() == dwarf::DW_TAG_compile_unit)<br>
+    if (p->getTag() == dwarf::DW_TAG_compile_unit ||<br>
+        p->getTag() == dwarf::DW_TAG_type_unit)<br></blockquote><div><br></div><div>Same here.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
       return p;<br>
     p = p->getParent();<br>
   }<br>
@@ -227,6 +228,7 @@ void DIEInteger::EmitValue(AsmPrinter *A<br>
   case dwarf::DW_FORM_ref4:  // Fall thru<br>
   case dwarf::DW_FORM_data4: Size = 4; break;<br>
   case dwarf::DW_FORM_ref8:  // Fall thru<br>
+  case dwarf::DW_FORM_ref_sig8:  // Fall thru<br>
   case dwarf::DW_FORM_data8: Size = 8; break;<br>
   case dwarf::DW_FORM_GNU_str_index: Asm->EmitULEB128(Integer); return;<br>
   case dwarf::DW_FORM_GNU_addr_index: Asm->EmitULEB128(Integer); return;<br>
@@ -253,6 +255,7 @@ unsigned DIEInteger::SizeOf(AsmPrinter *<br>
   case dwarf::DW_FORM_ref4:  // Fall thru<br>
   case dwarf::DW_FORM_data4: return sizeof(int32_t);<br>
   case dwarf::DW_FORM_ref8:  // Fall thru<br>
+  case dwarf::DW_FORM_ref_sig8:  // Fall thru<br>
   case dwarf::DW_FORM_data8: return sizeof(int64_t);<br>
   case dwarf::DW_FORM_GNU_str_index: return MCAsmInfo::getULEB128Size(Integer);<br>
   case dwarf::DW_FORM_GNU_addr_index: return MCAsmInfo::getULEB128Size(Integer);<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h?rev=195166&r1=195165&r2=195166&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h?rev=195166&r1=195165&r2=195166&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h Tue Nov 19 17:08:21 2013<br>
@@ -146,12 +146,12 @@ namespace llvm {<br>
     const std::vector<DIE *> &getChildren() const { return Children; }<br>
     const SmallVectorImpl<DIEValue*> &getValues() const { return Values; }<br>
     DIE *getParent() const { return Parent; }<br>
-    /// Climb up the parent chain to get the compile unit DIE this DIE belongs<br>
-    /// to.<br>
-    const DIE *getCompileUnit() const;<br>
-    /// Similar to getCompileUnit, returns null when DIE is not added to an<br>
+    /// Climb up the parent chain to get the compile or type unit DIE this DIE<br>
+    /// belongs to.<br>
+    const DIE *getUnit() const;<br>
+    /// Similar to getUnit, returns null when DIE is not added to an<br>
     /// owner yet.<br>
-    const DIE *getCompileUnitOrNull() const;<br>
+    const DIE *getUnitOrNull() const;<br></blockquote><div>Same here.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
     void setOffset(unsigned O) { Offset = O; }<br>
     void setSize(unsigned S) { Size = S; }<br>
<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DIEHash.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DIEHash.cpp?rev=195166&r1=195165&r2=195166&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DIEHash.cpp?rev=195166&r1=195165&r2=195166&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/DIEHash.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DIEHash.cpp Tue Nov 19 17:08:21 2013<br>
@@ -92,10 +92,12 @@ void DIEHash::addParentContext(const DIE<br>
   // outermost such construct...<br>
   SmallVector<const DIE *, 1> Parents;<br>
   const DIE *Cur = &Parent;<br>
-  while (Cur->getTag() != dwarf::DW_TAG_compile_unit) {<br>
+  while (Cur->getParent()) {<br>
     Parents.push_back(Cur);<br>
     Cur = Cur->getParent();<br>
   }<br>
+  assert(Cur->getTag() == dwarf::DW_TAG_compile_unit ||<br>
+         Cur->getTag() == dwarf::DW_TAG_type_unit);<br>
<br>
   // Reverse iterate over our list to go from the outermost construct to the<br>
   // innermost.<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp?rev=195166&r1=195165&r2=195166&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp?rev=195166&r1=195165&r2=195166&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp Tue Nov 19 17:08:21 2013<br>
@@ -29,18 +29,30 @@<br>
 #include "llvm/Target/TargetMachine.h"<br>
 #include "llvm/Target/TargetLoweringObjectFile.h"<br>
 #include "llvm/Target/TargetRegisterInfo.h"<br>
+#include "llvm/Support/CommandLine.h"<br>
<br>
 using namespace llvm;<br>
<br>
+static cl::opt<bool> GenerateTypeUnits("generate-type-units", cl::Hidden,<br>
+                                       cl::desc("Generate DWARF4 type units."),<br>
+                                       cl::init(false));<br>
+<br>
 /// CompileUnit - Compile unit constructor.<br>
 CompileUnit::CompileUnit(unsigned UID, DIE *D, DICompileUnit Node,<br>
                          AsmPrinter *A, DwarfDebug *DW, DwarfUnits *DWU)<br>
     : UniqueID(UID), Node(Node), CUDie(D), Asm(A), DD(DW), DU(DWU),<br>
-      IndexTyDie(0), DebugInfoOffset(0) {<br>
+      IndexTyDie(0), Language(Node.getLanguage()) {<br></blockquote><div>Is removing initialization to DebugInfoOffset intentional?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

   DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1);<br>
   insertDIE(Node, D);<br>
 }<br>
<br>
+CompileUnit::CompileUnit(unsigned UID, DIE *D, uint16_t Language, AsmPrinter *A,<br>
+                         DwarfDebug *DD, DwarfUnits *DU)<br>
+    : UniqueID(UID), Node(NULL), CUDie(D), Asm(A), DD(DD), DU(DU),<br>
+      IndexTyDie(0), Language(Language) {<br></blockquote><div>Should we initialize DebugInfoOffset here?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

+  DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1);<br>
+}<br>
+<br>
 /// ~CompileUnit - Destructor for compile unit.<br>
 CompileUnit::~CompileUnit() {<br>
   for (unsigned j = 0, M = DIEBlocks.size(); j < M; ++j)<br>
@@ -102,7 +114,9 @@ int64_t CompileUnit::getDefaultLowerBoun<br>
 static bool isShareableAcrossCUs(DIDescriptor D) {<br>
   // When the MDNode can be part of the type system, the DIE can be<br>
   // shared across CUs.<br>
-  return D.isType() || (D.isSubprogram() && !DISubprogram(D).isDefinition());<br>
+  return (D.isType() ||<br>
+          (D.isSubprogram() && !DISubprogram(D).isDefinition())) &&<br>
+         !GenerateTypeUnits;<br></blockquote><div><br></div><div>It is nice if we can have a comment explaining why when generating type units, we don't share MDNodes.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

 }<br>
<br>
 /// getDIE - Returns the debug information entry map slot for the<br>
@@ -281,8 +295,8 @@ void CompileUnit::addDIEEntry(DIE *Die,<br>
<br>
 void CompileUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute,<br>
                               DIEEntry *Entry) {<br>
-  const DIE *DieCU = Die->getCompileUnitOrNull();<br>
-  const DIE *EntryCU = Entry->getEntry()->getCompileUnitOrNull();<br>
+  const DIE *DieCU = Die->getUnitOrNull();<br>
+  const DIE *EntryCU = Entry->getEntry()->getUnitOrNull();<br>
   if (!DieCU)<br>
     // We assume that Die belongs to this CU, if it is not linked to any CU yet.<br>
     DieCU = getCUDie();<br>
@@ -871,6 +885,22 @@ DIE *CompileUnit::getOrCreateContextDIE(<br>
   return getDIE(Context);<br>
 }<br>
<br>
+DIE *CompileUnit::createTypeDIE(DICompositeType Ty) {<br>
+  DIE *ContextDIE = getOrCreateContextDIE(resolve(Ty.getContext()));<br>
+<br>
+  DIE *TyDIE = getDIE(Ty);<br>
+  if (TyDIE)<br>
+    return TyDIE;<br>
+<br>
+  // Create new type.<br>
+  TyDIE = createAndAddDIE(Ty.getTag(), *ContextDIE, Ty);<br>
+<br>
+  constructTypeDIEImpl(*TyDIE, Ty);<br>
+<br>
+  updateAcceleratorTables(Ty, TyDIE);<br>
+  return TyDIE;<br>
+}<br>
+<br>
 /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the<br>
 /// given DIType.<br>
 DIE *CompileUnit::getOrCreateTypeDIE(const MDNode *TyNode) {<br>
@@ -1112,6 +1142,9 @@ static bool isTypeUnitScoped(DIType Ty,<br>
<br>
 /// Return true if the type should be split out into a type unit.<br>
 static bool shouldCreateTypeUnit(DICompositeType CTy, const DwarfDebug *DD) {<br>
+  if (!GenerateTypeUnits)<br>
+    return false;<br>
+<br>
   uint16_t Tag = CTy.getTag();<br>
<br>
   switch (Tag) {<br>
@@ -1130,7 +1163,16 @@ static bool shouldCreateTypeUnit(DICompo<br>
<br>
 /// constructTypeDIE - Construct type DIE from DICompositeType.<br>
 void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {<br>
-  // Get core information.<br>
+  // If this is a type applicable to a type unit it then add it to the<br>
+  // list of types we'll compute a hash for later.<br>
+  if (shouldCreateTypeUnit(CTy, DD))<br>
+    DD->addTypeUnitType(&Buffer, CTy);<br>
+  else<br>
+    constructTypeDIEImpl(Buffer, CTy);<br>
+}<br>
+<br>
+void CompileUnit::constructTypeDIEImpl(DIE &Buffer, DICompositeType CTy) {<br>
+  // Add name if not anonymous or intermediate type.<br>
   StringRef Name = CTy.getName();<br>
<br>
   uint64_t Size = CTy.getSizeInBits() >> 3;<br>
@@ -1296,10 +1338,6 @@ void CompileUnit::constructTypeDIE(DIE &<br>
       addUInt(&Buffer, dwarf::DW_AT_APPLE_runtime_class, dwarf::DW_FORM_data1,<br>
               RLang);<br>
   }<br>
-  // If this is a type applicable to a type unit it then add it to the<br>
-  // list of types we'll compute a hash for later.<br>
-  if (shouldCreateTypeUnit(CTy, DD))<br>
-    DD->addTypeUnitType(&Buffer);<br>
 }<br>
<br>
 /// constructTemplateTypeParameterDIE - Construct new DIE for the given<br>
@@ -1510,7 +1548,6 @@ static const ConstantExpr *getMergedGlob<br>
<br>
 /// createGlobalVariableDIE - create global variable DIE.<br>
 void CompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) {<br>
-<br>
   // Check for pre-existence.<br>
   if (getDIE(GV))<br>
     return;<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h?rev=195166&r1=195165&r2=195166&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h?rev=195166&r1=195165&r2=195166&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h Tue Nov 19 17:08:21 2013<br>
@@ -93,14 +93,18 @@ class CompileUnit {<br>
   // DIEIntegerOne - A preallocated DIEValue because 1 is used frequently.<br>
   DIEInteger *DIEIntegerOne;<br>
<br>
+  uint16_t Language;<br>
+<br>
 public:<br>
   CompileUnit(unsigned UID, DIE *D, DICompileUnit CU, AsmPrinter *A,<br>
               DwarfDebug *DW, DwarfUnits *DWU);<br>
+  CompileUnit(unsigned UID, DIE *D, uint16_t Language, AsmPrinter *A,<br>
+              DwarfDebug *DW, DwarfUnits *DWU);<br>
   ~CompileUnit();<br>
<br>
   // Accessors.<br>
   unsigned getUniqueID() const { return UniqueID; }<br>
-  uint16_t getLanguage() const { return Node.getLanguage(); }<br>
+  uint16_t getLanguage() const { return Language; }<br>
   DICompileUnit getNode() const { return Node; }<br>
   DIE *getCUDie() const { return CUDie.get(); }<br>
   const StringMap<DIE *> &getGlobalNames() const { return GlobalNames; }<br>
@@ -311,6 +315,9 @@ public:<br>
   DIE *getOrCreateTypeDIE(const MDNode *N);<br>
<br>
   /// getOrCreateContextDIE - Get context owner's DIE.<br>
+  DIE *createTypeDIE(DICompositeType Ty);<br>
+<br>
+  /// getOrCreateContextDIE - Get context owner's DIE.<br>
   DIE *getOrCreateContextDIE(DIScope Context);<br>
<br>
   /// createGlobalVariableDIE - create global variable DIE.<br>
@@ -328,6 +335,10 @@ public:<br>
   DIE *createAndAddDIE(unsigned Tag, DIE &Parent,<br>
                        DIDescriptor N = DIDescriptor());<br>
<br>
+  /// constructTypeDIEImpl - Construct type DIE that is not a type unit<br>
+  /// reference from a DICompositeType.<br>
+  void constructTypeDIEImpl(DIE &Buffer, DICompositeType CTy);<br>
+<br>
   /// Compute the size of a header for this unit, not including the initial<br>
   /// length field.<br>
   unsigned getHeaderSize() const {<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=195166&r1=195165&r2=195166&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=195166&r1=195165&r2=195166&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Tue Nov 19 17:08:21 2013<br>
@@ -1051,22 +1051,6 @@ void DwarfDebug::finalizeModuleInfo() {<br>
   // Attach DW_AT_inline attribute with inlined subprogram DIEs.<br>
   computeInlinedDIEs();<br>
<br>
-  // Split out type units and conditionally add an ODR tag to the split<br>
-  // out type.<br>
-  // FIXME: Do type splitting.<br>
-  for (unsigned i = 0, e = TypeUnits.size(); i != e; ++i) {<br>
-    DIE *Die = TypeUnits[i];<br>
-    DIEHash Hash;<br>
-    // If we've requested ODR hashes and it's applicable for an ODR hash then<br>
-    // add the ODR signature now.<br>
-    // FIXME: This should be added onto the type unit, not the type, but this<br>
-    // works as an intermediate stage.<br>
-    if (GenerateODRHash && shouldAddODRHash(CUMap.begin()->second, Die))<br>
-      CUMap.begin()->second->addUInt(Die, dwarf::DW_AT_GNU_odr_signature,<br>
-                                     dwarf::DW_FORM_data8,<br>
-                                     Hash.computeDIEODRSignature(*Die));<br>
-  }<br>
-<br>
   // Handle anything that needs to be done on a per-cu basis.<br>
   for (DenseMap<const MDNode *, CompileUnit *>::iterator CUI = CUMap.begin(),<br>
                                                          CUE = CUMap.end();<br>
@@ -2071,7 +2055,7 @@ void DwarfDebug::emitDIE(DIE *Die, Array<br>
         // For DW_FORM_ref_addr, output the offset from beginning of debug info<br>
         // section. Origin->getOffset() returns the offset from start of the<br>
         // compile unit.<br>
-        CompileUnit *CU = CUDieMap.lookup(Origin->getCompileUnit());<br>
+        CompileUnit *CU = CUDieMap.lookup(Origin->getUnit());<br>
         assert(CU && "CUDie should belong to a CU.");<br>
         Addr += CU->getDebugInfoOffset();<br>
         if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())<br>
@@ -2083,7 +2067,7 @@ void DwarfDebug::emitDIE(DIE *Die, Array<br>
                                          DIEEntry::getRefAddrSize(Asm));<br>
       } else {<br>
         // Make sure Origin belong to the same CU.<br>
-        assert(Die->getCompileUnit() == Origin->getCompileUnit() &&<br>
+        assert(Die->getUnit() == Origin->getUnit() &&<br>
                "The referenced DIE should belong to the same CU in ref4");<br>
         Asm->EmitInt32(Addr);<br>
       }<br>
@@ -3063,3 +3047,57 @@ void DwarfDebug::emitDebugStrDWO() {<br>
   InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),<br>
                          OffSec, StrSym);<br>
 }<br>
+<br>
+void DwarfDebug::addTypeUnitType(DIE *RefDie, DICompositeType CTy) {<br>
+  DenseMap<const MDNode*, std::pair<uint64_t, SmallVectorImpl<DIE*>* > >::iterator I = TypeUnits.find(CTy);<br>
+  SmallVector<DIE *, 8> References;<br>
+  References.push_back(RefDie);<br>
+  if (I != TypeUnits.end()) {<br>
+    if (I->second.second) {<br>
+      I->second.second->push_back(RefDie);<br>
+      return;<br>
+    }<br>
+  } else {<br>
+    DIE *UnitDie = new DIE(dwarf::DW_TAG_type_unit);<br>
+    CompileUnit *NewCU =<br>
+        new CompileUnit(GlobalCUIndexCount++, UnitDie,<br>
+                        dwarf::DW_LANG_C_plus_plus, Asm, this, &InfoHolder);<br>
+    CUDieMap.insert(std::make_pair(UnitDie, NewCU));<br>
+    NewCU->addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2,<br>
+                   dwarf::DW_LANG_C_plus_plus);<br>
+<br>
+    // Register the type in the TypeUnits map with a vector of references to be<br>
+    // populated whenever a reference is required.<br>
+    I = TypeUnits.insert(std::make_pair(CTy, std::make_pair(0, &References)))<br>
+            .first;<br>
+<br>
+    // Construct the type, this may, recursively, require more type units that<br>
+    // may in turn require this type again - in which case they will add DIEs to<br>
+    // the References vector.<br>
+    DIE *Die = NewCU->createTypeDIE(CTy);<br>
+<br>
+    if (GenerateODRHash && shouldAddODRHash(NewCU, Die))<br>
+      NewCU->addUInt(UnitDie, dwarf::DW_AT_GNU_odr_signature,<br>
+                     dwarf::DW_FORM_data8,<br>
+                     DIEHash().computeDIEODRSignature(*Die));<br>
+    // FIXME: This won't handle circularly referential structures, as the DIE<br>
+    // may have references to other DIEs still under construction and missing<br>
+    // their signature. Hashing should walk through the signatures to their<br>
+    // referenced type, or possibly walk the precomputed hashes of related types<br>
+    // at the end.<br>
+    uint64_t Signature = DIEHash().computeTypeSignature(*Die);<br>
+<br>
+    // Remove the References vector and add the type hash.<br>
+    I->second.first = Signature;<br>
+    I->second.second = NULL;<br>
+<br>
+<br>
+    InfoHolder.addUnit(NewCU);<br>
+  }<br>
+<br>
+  // Populate all the signatures.<br>
+  for (unsigned i = 0, e = References.size(); i != e; ++i) {<br>
+    CUMap.begin()->second->addUInt(References[i], dwarf::DW_AT_signature,<br>
+                                   dwarf::DW_FORM_ref_sig8, I->second.first);<br>
+  }<br>
+}<br>
<br>
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h?rev=195166&r1=195165&r2=195166&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h?rev=195166&r1=195165&r2=195166&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h (original)<br>
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Tue Nov 19 17:08:21 2013<br>
@@ -37,6 +37,7 @@ class MachineFrameInfo;<br>
 class MachineModuleInfo;<br>
 class MachineOperand;<br>
 class MCAsmInfo;<br>
+class MCObjectFileInfo;<br>
 class DIEAbbrev;<br>
 class DIE;<br>
 class DIEBlock;<br>
@@ -443,7 +444,7 @@ class DwarfDebug {<br>
   ImportedEntityMap ScopesWithImportedEntities;<br>
<br>
   // Holder for types that are going to be extracted out into a type unit.<br>
-  std::vector<DIE *> TypeUnits;<br>
+  DenseMap<const MDNode *, std::pair<uint64_t, SmallVectorImpl<DIE*>* > > TypeUnits;<br></blockquote><div><br></div><div>Can you add a comment here explaining the pair?</div><div><br></div><div>Thanks,</div>
<div>Manman</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
   // Whether to emit the pubnames/pubtypes sections.<br>
   bool HasDwarfPubSections;<br>
@@ -695,7 +696,7 @@ public:<br>
<br>
   /// \brief Add a DIE to the set of types that we're going to pull into<br>
   /// type units.<br>
-  void addTypeUnitType(DIE *Die) { TypeUnits.push_back(Die); }<br>
+  void addTypeUnitType(DIE *Die, DICompositeType CTy);<br>
<br>
   /// \brief Add a label so that arange data can be generated for it.<br>
   void addArangeLabel(SymbolCU SCU) { ArangeLabels.push_back(SCU); }<br>
<br>
Modified: llvm/trunk/test/DebugInfo/X86/generate-odr-hash.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/generate-odr-hash.ll?rev=195166&r1=195165&r2=195166&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/generate-odr-hash.ll?rev=195166&r1=195165&r2=195166&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/test/DebugInfo/X86/generate-odr-hash.ll (original)<br>
+++ llvm/trunk/test/DebugInfo/X86/generate-odr-hash.ll Tue Nov 19 17:08:21 2013<br>
@@ -1,6 +1,6 @@<br>
 ; REQUIRES: object-emission<br>
<br>
-; RUN: llc %s -o %t -filetype=obj -O0 -generate-odr-hash -mtriple=x86_64-unknown-linux-gnu<br>
+; RUN: llc %s -o %t -filetype=obj -O0 -generate-type-units -generate-odr-hash -mtriple=x86_64-unknown-linux-gnu<br>
 ; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s<br>
 ;<br>
 ; Generated from:<br>
@@ -44,9 +44,12 @@<br>
 ; wombat wom;<br>
<br>
 ; Check that we generate a hash for bar and the value.<br>
+; CHECK-LABEL: DW_AT_GNU_odr_signature [DW_FORM_data8] (0x200520c0d5b90eff)<br>
 ; CHECK: DW_TAG_structure_type<br>
 ; CHECK-NEXT: debug_str{{.*}}"bar"<br>
-; CHECK: DW_AT_GNU_odr_signature [DW_FORM_data8] (0x200520c0d5b90eff)<br>
+<br>
+; Check that we generate a hash for fluffy and the value.<br>
+; CHECK-LABEL: DW_AT_GNU_odr_signature [DW_FORM_data8]   (0x9a0124d5a0c21c52)<br>
 ; CHECK: DW_TAG_namespace<br>
 ; CHECK-NEXT: debug_str{{.*}}"echidna"<br>
 ; CHECK: DW_TAG_namespace<br>
@@ -55,34 +58,36 @@<br>
 ; CHECK-NEXT: debug_str{{.*}}"mongoose"<br>
 ; CHECK: DW_TAG_class_type<br>
 ; CHECK-NEXT: debug_str{{.*}}"fluffy"<br>
-; CHECK: DW_AT_GNU_odr_signature [DW_FORM_data8]   (0x9a0124d5a0c21c52)<br>
<br>
 ; We emit no hash for walrus since the type is contained in an anonymous<br>
 ; namespace and won't violate any ODR-ness.<br>
+; CHECK: DW_TAG_type_unit<br>
+; CHECK-NOT: NULL<br>
+; CHECK-NOT: DW_AT_GNU_odr_signature<br>
 ; CHECK: DW_TAG_structure_type<br>
 ; CHECK-NEXT: debug_str{{.*}}"walrus"<br>
 ; CHECK-NEXT: DW_AT_byte_size<br>
 ; CHECK-NEXT: DW_AT_decl_file<br>
 ; CHECK-NEXT: DW_AT_decl_line<br>
-; CHECK-NOT: DW_AT_GNU_odr_signature<br>
 ; CHECK: DW_TAG_subprogram<br>
<br>
+<br>
 ; Check that we generate a hash for wombat and the value, but not for the<br>
 ; anonymous type contained within.<br>
+; CHECK: DW_TAG_type_unit<br>
 ; CHECK: DW_TAG_structure_type<br>
-; CHECK-NEXT: debug_str{{.*}}wombat<br>
-; CHECK: DW_AT_GNU_odr_signature [DW_FORM_data8] (0x685bcc220141e9d7)<br>
+; The signature for the outer 'wombat' type - this can be FileChecked once the<br>
+; type units are moved to their own section with the full type unit header<br>
+; including the signature<br>
+; CHECK: DW_AT_signature [DW_FORM_ref_sig8] (0x73776f130648b986)<br>
 ; CHECK: DW_TAG_structure_type<br>
-; CHECK-NEXT: DW_AT_byte_size<br>
-; CHECK-NEXT: DW_AT_decl_file<br>
-; CHECK-NEXT: DW_AT_decl_line<br>
+; CHECK-NOT: DW_AT_name<br>
+; CHECK-NOT: DW_AT_GNU_odr_signature<br>
 ; CHECK: DW_TAG_member<br>
 ; CHECK-NEXT: debug_str{{.*}}"a"<br>
-<br>
-; Check that we don't generate a hash for baz.<br>
+; CHECK-LABEL: DW_AT_GNU_odr_signature [DW_FORM_data8] (0x685bcc220141e9d7)<br>
 ; CHECK: DW_TAG_structure_type<br>
-; CHECK-NEXT: debug_str{{.*}}"baz"<br>
-; CHECK-NOT: DW_AT_GNU_odr_signature<br>
+; CHECK-NEXT: debug_str{{.*}}"wombat"<br>
<br>
 %struct.bar = type { i8 }<br>
 %"class.echidna::capybara::mongoose::fluffy" = type { i32, i32 }<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>