DebugInfo: Rename DwarfCompileUnit.* to DwarfUnit.* to match their contents.
[oota-llvm.git] / lib / CodeGen / AsmPrinter / DwarfDebug.cpp
index 35f76047dba6e80fdf40231db09086f1ef4404d8..3e71735d61cf7f24b7d903a1e17e0c277b5c5e4e 100644 (file)
@@ -16,7 +16,7 @@
 #include "DIE.h"
 #include "DIEHash.h"
 #include "DwarfAccelTable.h"
-#include "DwarfCompileUnit.h"
+#include "DwarfUnit.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
@@ -104,6 +104,11 @@ DwarfPubSections("generate-dwarf-pub-sections", cl::Hidden,
                             clEnumVal(Disable, "Disabled"), clEnumValEnd),
                  cl::init(Default));
 
+static cl::opt<unsigned>
+DwarfVersionNumber("dwarf-version", cl::Hidden,
+                   cl::desc("Generate DWARF for dwarf version."),
+                   cl::init(0));
+
 static const char *const DWARFGroupName = "DWARF Emission";
 static const char *const DbgTimerName = "DWARF Debug Writer";
 
@@ -212,7 +217,9 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
   else
     HasDwarfPubSections = DwarfPubSections == Enable;
 
-  DwarfVersion = getDwarfVersionFromModule(MMI->getModule());
+  DwarfVersion = DwarfVersionNumber
+                     ? DwarfVersionNumber
+                     : getDwarfVersionFromModule(MMI->getModule());
 
   {
     NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
@@ -233,6 +240,12 @@ static MCSymbol *emitSectionSym(AsmPrinter *Asm, const MCSection *Section,
   return TmpSym;
 }
 
+DwarfUnits::~DwarfUnits() {
+  for (SmallVectorImpl<Unit *>::iterator I = CUs.begin(), E = CUs.end(); I != E;
+       ++I)
+    delete *I;
+}
+
 MCSymbol *DwarfUnits::getStringPoolSym() {
   return Asm->GetTempSymbol(StringPref);
 }
@@ -328,7 +341,7 @@ static bool SectionSort(const MCSection *A, const MCSection *B) {
 // TODO: Determine whether or not we should add names for programs
 // that do not have a DW_AT_name or DW_AT_linkage_name field - this
 // is only slightly different than the lookup of non-standard ObjC names.
-static void addSubprogramNames(CompileUnit *TheCU, DISubprogram SP, DIE *Die) {
+static void addSubprogramNames(Unit *TheCU, DISubprogram SP, DIE *Die) {
   if (!SP.isDefinition())
     return;
   TheCU->addAccelName(SP.getName(), Die);
@@ -468,11 +481,11 @@ DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU,
   // If we have multiple ranges, emit them into the range section.
   if (Ranges.size() > 1) {
     // .debug_range section has not been laid out yet. Emit offset in
-    // .debug_range as a uint, size 4, for now. emitDIE will handle
-    // DW_AT_ranges appropriately.
-    TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
-                   DebugRangeSymbols.size() *
-                       Asm->getDataLayout().getPointerSize());
+    // .debug_range as a relocatable label. emitDIE will handle
+    // emitting it appropriately.
+    unsigned Offset = DebugRangeSymbols.size();
+    TheCU->addSectionLabel(ScopeDIE, dwarf::DW_AT_ranges,
+                           Asm->GetTempSymbol("debug_ranges", Offset));
     for (SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin(),
                                                     RE = Ranges.end();
          RI != RE; ++RI) {
@@ -524,11 +537,11 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU,
 
   if (Ranges.size() > 1) {
     // .debug_range section has not been laid out yet. Emit offset in
-    // .debug_range as a uint, size 4, for now. emitDIE will handle
-    // DW_AT_ranges appropriately.
-    TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
-                   DebugRangeSymbols.size() *
-                       Asm->getDataLayout().getPointerSize());
+    // .debug_range as a relocatable label. emitDIE will handle
+    // emitting it appropriately.
+    unsigned Offset = DebugRangeSymbols.size();
+    TheCU->addSectionLabel(ScopeDIE, dwarf::DW_AT_ranges,
+                           Asm->GetTempSymbol("debug_ranges", Offset));
     for (SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin(),
                                                     RE = Ranges.end();
          RI != RE; ++RI) {
@@ -672,9 +685,6 @@ DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) {
   if (DS.isSubprogram() && ObjectPointer != NULL)
     TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, ObjectPointer);
 
-  if (DS.isSubprogram())
-    TheCU->addPubTypes(DISubprogram(DS));
-
   return ScopeDIE;
 }
 
@@ -766,14 +776,15 @@ CompileUnit *DwarfDebug::constructCompileUnit(DICompileUnit DIUnit) {
     // The line table entries are not always emitted in assembly, so it
     // is not okay to use line_table_start here.
     if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
-      NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset,
-                      UseTheFirstCU ? Asm->GetTempSymbol("section_line")
-                                    : LineTableStartSym);
+      NewCU->addSectionLabel(
+          Die, dwarf::DW_AT_stmt_list,
+          UseTheFirstCU ? Asm->GetTempSymbol("section_line")
+                        : LineTableStartSym);
     else if (UseTheFirstCU)
-      NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0);
+      NewCU->addSectionOffset(Die, dwarf::DW_AT_stmt_list, 0);
     else
-      NewCU->addDelta(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
-                      LineTableStartSym, DwarfLineSectionSym);
+      NewCU->addSectionDelta(Die, dwarf::DW_AT_stmt_list,
+                             LineTableStartSym, DwarfLineSectionSym);
 
     // If we're using split dwarf the compilation dir is going to be in the
     // skeleton CU and so we don't need to duplicate it here.
@@ -784,22 +795,22 @@ CompileUnit *DwarfDebug::constructCompileUnit(DICompileUnit DIUnit) {
     // emit it here if we don't have a skeleton CU for split dwarf.
     if (GenerateGnuPubSections) {
       if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
-        NewCU->addLabel(
-            Die, dwarf::DW_AT_GNU_pubnames, dwarf::DW_FORM_sec_offset,
+        NewCU->addSectionLabel(
+            Die, dwarf::DW_AT_GNU_pubnames,
             Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()));
       else
-        NewCU->addDelta(
-            Die, dwarf::DW_AT_GNU_pubnames, dwarf::DW_FORM_data4,
+        NewCU->addSectionDelta(
+            Die, dwarf::DW_AT_GNU_pubnames,
             Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()),
             DwarfGnuPubNamesSectionSym);
 
       if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
-        NewCU->addLabel(
-            Die, dwarf::DW_AT_GNU_pubtypes, dwarf::DW_FORM_sec_offset,
+        NewCU->addSectionLabel(
+            Die, dwarf::DW_AT_GNU_pubtypes,
             Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()));
       else
-        NewCU->addDelta(
-            Die, dwarf::DW_AT_GNU_pubtypes, dwarf::DW_FORM_data4,
+        NewCU->addSectionDelta(
+            Die, dwarf::DW_AT_GNU_pubtypes,
             Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()),
             DwarfGnuPubTypesSectionSym);
     }
@@ -990,7 +1001,7 @@ void DwarfDebug::collectDeadVariables() {
           continue;
 
         // Construct subprogram DIE and add variables DIEs.
-        CompileUnit *SPCU = CUMap.lookup(TheCU);
+        CompileUnit *SPCU = static_cast<CompileUnit *>(CUMap.lookup(TheCU));
         assert(SPCU && "Unable to find Compile Unit!");
         // FIXME: See the comment in constructSubprogramDIE about duplicate
         // subprogram DIEs.
@@ -1038,7 +1049,7 @@ static bool isContainedInAnonNamespace(DIE *Die) {
 
 /// Test if the current CU language is C++ and that we have
 /// a named type that is not contained in an anonymous namespace.
-static bool shouldAddODRHash(CompileUnit *CU, DIE *Die) {
+static bool shouldAddODRHash(TypeUnit *CU, DIE *Die) {
   return CU->getLanguage() == dwarf::DW_LANG_C_plus_plus &&
          getDIEStringAttr(Die, dwarf::DW_AT_name) != "" &&
          !isContainedInAnonNamespace(Die);
@@ -1051,34 +1062,19 @@ void DwarfDebug::finalizeModuleInfo() {
   // Attach DW_AT_inline attribute with inlined subprogram DIEs.
   computeInlinedDIEs();
 
-  // Split out type units and conditionally add an ODR tag to the split
-  // out type.
-  // FIXME: Do type splitting.
-  for (unsigned i = 0, e = TypeUnits.size(); i != e; ++i) {
-    DIE *Die = TypeUnits[i];
-    DIEHash Hash;
-    // If we've requested ODR hashes and it's applicable for an ODR hash then
-    // add the ODR signature now.
-    // FIXME: This should be added onto the type unit, not the type, but this
-    // works as an intermediate stage.
-    if (GenerateODRHash && shouldAddODRHash(CUMap.begin()->second, Die))
-      CUMap.begin()->second->addUInt(Die, dwarf::DW_AT_GNU_odr_signature,
-                                     dwarf::DW_FORM_data8,
-                                     Hash.computeDIEODRSignature(*Die));
-  }
-
   // Handle anything that needs to be done on a per-cu basis.
-  for (DenseMap<const MDNode *, CompileUnit *>::iterator CUI = CUMap.begin(),
-                                                         CUE = CUMap.end();
-       CUI != CUE; ++CUI) {
-    CompileUnit *TheCU = CUI->second;
+  for (SmallVectorImpl<Unit *>::const_iterator I = getUnits().begin(),
+                                               E = getUnits().end();
+       I != E; ++I) {
+    Unit *TheCU = *I;
     // Emit DW_AT_containing_type attribute to connect types with their
     // vtable holding type.
     TheCU->constructContainingTypeDIEs();
 
     // If we're splitting the dwarf out now that we've got the entire
     // CU then construct a skeleton CU based upon it.
-    if (useSplitDwarf()) {
+    if (useSplitDwarf() &&
+        TheCU->getCUDie()->getTag() == dwarf::DW_TAG_compile_unit) {
       uint64_t ID = 0;
       if (GenerateCUHash) {
         DIEHash CUHash;
@@ -1088,7 +1084,8 @@ void DwarfDebug::finalizeModuleInfo() {
       TheCU->addUInt(TheCU->getCUDie(), dwarf::DW_AT_GNU_dwo_id,
                      dwarf::DW_FORM_data8, ID);
       // Now construct the skeleton CU associated.
-      CompileUnit *SkCU = constructSkeletonCU(TheCU);
+      CompileUnit *SkCU =
+          constructSkeletonCU(static_cast<CompileUnit *>(TheCU));
       // This should be a unique identifier when we want to build .dwp files.
       SkCU->addUInt(SkCU->getCUDie(), dwarf::DW_AT_GNU_dwo_id,
                     dwarf::DW_FORM_data8, ID);
@@ -1209,15 +1206,6 @@ void DwarfDebug::endModule() {
 
   // clean up.
   SPMap.clear();
-  for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
-                                                         E = CUMap.end();
-       I != E; ++I)
-    delete I->second;
-
-  for (SmallVectorImpl<CompileUnit *>::iterator I = SkeletonCUs.begin(),
-                                                E = SkeletonCUs.end();
-       I != E; ++I)
-    delete *I;
 
   // Reset these for the next Module if we have one.
   FirstCU = NULL;
@@ -1967,7 +1955,7 @@ void DwarfUnits::computeSizeAndOffsets() {
 
   // Iterate over each compile unit and set the size and offsets for each
   // DIE within each compile unit. All offsets are CU relative.
-  for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(), E = CUs.end();
+  for (SmallVectorImpl<Unit *>::const_iterator I = CUs.begin(), E = CUs.end();
        I != E; ++I) {
     (*I)->setDebugInfoOffset(SecOffset);
 
@@ -2071,7 +2059,7 @@ void DwarfDebug::emitDIE(DIE *Die, ArrayRef<DIEAbbrev *> Abbrevs) {
         // For DW_FORM_ref_addr, output the offset from beginning of debug info
         // section. Origin->getOffset() returns the offset from start of the
         // compile unit.
-        CompileUnit *CU = CUDieMap.lookup(Origin->getCompileUnit());
+        CompileUnit *CU = CUDieMap.lookup(Origin->getUnit());
         assert(CU && "CUDie should belong to a CU.");
         Addr += CU->getDebugInfoOffset();
         if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
@@ -2083,7 +2071,7 @@ void DwarfDebug::emitDIE(DIE *Die, ArrayRef<DIEAbbrev *> Abbrevs) {
                                          DIEEntry::getRefAddrSize(Asm));
       } else {
         // Make sure Origin belong to the same CU.
-        assert(Die->getCompileUnit() == Origin->getCompileUnit() &&
+        assert(Die->getUnit() == Origin->getUnit() &&
                "The referenced DIE should belong to the same CU in ref4");
         Asm->EmitInt32(Addr);
       }
@@ -2091,14 +2079,12 @@ void DwarfDebug::emitDIE(DIE *Die, ArrayRef<DIEAbbrev *> Abbrevs) {
     }
     case dwarf::DW_AT_ranges: {
       // DW_AT_range Value encodes offset in debug_range section.
-      DIEInteger *V = cast<DIEInteger>(Values[i]);
+      DIELabel *V = cast<DIELabel>(Values[i]);
 
-      if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) {
-        Asm->EmitLabelPlusOffset(DwarfDebugRangeSectionSym, V->getValue(), 4);
-      } else {
-        Asm->EmitLabelOffsetDifference(DwarfDebugRangeSectionSym, V->getValue(),
-                                       DwarfDebugRangeSectionSym, 4);
-      }
+      if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
+        Asm->EmitSectionOffset(V->getValue(), DwarfDebugRangeSectionSym);
+      else
+        Asm->EmitLabelDifference(V->getValue(), DwarfDebugRangeSectionSym, 4);
       break;
     }
     case dwarf::DW_AT_location: {
@@ -2146,9 +2132,9 @@ void DwarfUnits::emitUnits(DwarfDebug *DD, const MCSection *USection,
                            const MCSection *ASection,
                            const MCSymbol *ASectionSym) {
   Asm->OutStreamer.SwitchSection(USection);
-  for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(), E = CUs.end();
-       I != E; ++I) {
-    CompileUnit *TheCU = *I;
+  for (SmallVectorImpl<Unit *>::iterator I = CUs.begin(), E = CUs.end(); I != E;
+       ++I) {
+    Unit *TheCU = *I;
     DIE *Die = TheCU->getCUDie();
 
     // Emit the compile units header.
@@ -2243,10 +2229,10 @@ void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) {
 void DwarfDebug::emitAccelNames() {
   DwarfAccelTable AT(
       DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4));
-  for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
-                                                         E = CUMap.end();
+  for (SmallVectorImpl<Unit *>::const_iterator I = getUnits().begin(),
+                                               E = getUnits().end();
        I != E; ++I) {
-    CompileUnit *TheCU = I->second;
+    Unit *TheCU = *I;
     const StringMap<std::vector<const DIE *> > &Names = TheCU->getAccelNames();
     for (StringMap<std::vector<const DIE *> >::const_iterator
              GI = Names.begin(),
@@ -2276,10 +2262,10 @@ void DwarfDebug::emitAccelNames() {
 void DwarfDebug::emitAccelObjC() {
   DwarfAccelTable AT(
       DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4));
-  for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
-                                                         E = CUMap.end();
+  for (SmallVectorImpl<Unit *>::const_iterator I = getUnits().begin(),
+                                               E = getUnits().end();
        I != E; ++I) {
-    CompileUnit *TheCU = I->second;
+    Unit *TheCU = *I;
     const StringMap<std::vector<const DIE *> > &Names = TheCU->getAccelObjC();
     for (StringMap<std::vector<const DIE *> >::const_iterator
              GI = Names.begin(),
@@ -2308,10 +2294,10 @@ void DwarfDebug::emitAccelObjC() {
 void DwarfDebug::emitAccelNamespaces() {
   DwarfAccelTable AT(
       DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4));
-  for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
-                                                         E = CUMap.end();
+  for (SmallVectorImpl<Unit *>::const_iterator I = getUnits().begin(),
+                                               E = getUnits().end();
        I != E; ++I) {
-    CompileUnit *TheCU = I->second;
+    Unit *TheCU = *I;
     const StringMap<std::vector<const DIE *> > &Names =
         TheCU->getAccelNamespace();
     for (StringMap<std::vector<const DIE *> >::const_iterator
@@ -2347,10 +2333,10 @@ void DwarfDebug::emitAccelTypes() {
   Atoms.push_back(
       DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1));
   DwarfAccelTable AT(Atoms);
-  for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
-                                                         E = CUMap.end();
+  for (SmallVectorImpl<Unit *>::const_iterator I = getUnits().begin(),
+                                               E = getUnits().end();
        I != E; ++I) {
-    CompileUnit *TheCU = I->second;
+    Unit *TheCU = *I;
     const StringMap<std::vector<std::pair<const DIE *, unsigned> > > &Names =
         TheCU->getAccelTypes();
     for (StringMap<
@@ -2394,8 +2380,8 @@ void DwarfDebug::emitAccelTypes() {
 // reference in the pubname header doesn't change.
 
 /// computeIndexValue - Compute the gdb index value for the DIE and CU.
-static dwarf::PubIndexEntryDescriptor computeIndexValue(CompileUnit *CU,
-                                                        DIE *Die) {
+static dwarf::PubIndexEntryDescriptor computeIndexValue(Unit *CU,
+                                                        const DIE *Die) {
   dwarf::GDBIndexEntryLinkage Linkage = dwarf::GIEL_STATIC;
 
   // We could have a specification DIE that has our most of our knowledge,
@@ -2444,9 +2430,10 @@ void DwarfDebug::emitDebugPubNames(bool GnuStyle) {
       GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubNamesSection()
                : Asm->getObjFileLowering().getDwarfPubNamesSection();
 
-  typedef DenseMap<const MDNode *, CompileUnit *> CUMapType;
-  for (CUMapType::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) {
-    CompileUnit *TheCU = I->second;
+  for (SmallVectorImpl<Unit *>::const_iterator I = getUnits().begin(),
+                                               E = getUnits().end();
+       I != E; ++I) {
+    Unit *TheCU = *I;
     unsigned ID = TheCU->getUniqueID();
 
     // Start the dwarf pubnames section.
@@ -2477,12 +2464,12 @@ void DwarfDebug::emitDebugPubNames(bool GnuStyle) {
                              4);
 
     // Emit the pubnames for this compilation unit.
-    const StringMap<DIE *> &Globals = TheCU->getGlobalNames();
-    for (StringMap<DIE *>::const_iterator GI = Globals.begin(),
-                                          GE = Globals.end();
+    const StringMap<const DIE *> &Globals = TheCU->getGlobalNames();
+    for (StringMap<const DIE *>::const_iterator GI = Globals.begin(),
+                                                GE = Globals.end();
          GI != GE; ++GI) {
       const char *Name = GI->getKeyData();
-      DIE *Entity = GI->second;
+      const DIE *Entity = GI->second;
 
       Asm->OutStreamer.AddComment("DIE offset");
       Asm->EmitInt32(Entity->getOffset());
@@ -2512,10 +2499,10 @@ void DwarfDebug::emitDebugPubTypes(bool GnuStyle) {
       GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubTypesSection()
                : Asm->getObjFileLowering().getDwarfPubTypesSection();
 
-  for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
-                                                         E = CUMap.end();
+  for (SmallVectorImpl<Unit *>::const_iterator I = getUnits().begin(),
+                                               E = getUnits().end();
        I != E; ++I) {
-    CompileUnit *TheCU = I->second;
+    Unit *TheCU = *I;
     // Start the dwarf pubtypes section.
     Asm->OutStreamer.SwitchSection(PSec);
 
@@ -2548,12 +2535,12 @@ void DwarfDebug::emitDebugPubTypes(bool GnuStyle) {
         Asm->GetTempSymbol(ISec->getLabelBeginName(), TheCU->getUniqueID()), 4);
 
     // Emit the pubtypes.
-    const StringMap<DIE *> &Globals = TheCU->getGlobalTypes();
-    for (StringMap<DIE *>::const_iterator GI = Globals.begin(),
-                                          GE = Globals.end();
+    const StringMap<const DIE *> &Globals = TheCU->getGlobalTypes();
+    for (StringMap<const DIE *>::const_iterator GI = Globals.begin(),
+                                                GE = Globals.end();
          GI != GE; ++GI) {
       const char *Name = GI->getKeyData();
-      DIE *Entity = GI->second;
+      const DIE *Entity = GI->second;
 
       if (Asm->isVerbose())
         Asm->OutStreamer.AddComment("DIE offset");
@@ -2781,7 +2768,7 @@ struct SymbolCUSorter {
   }
 };
 
-static bool CUSort(const CompileUnit *A, const CompileUnit *B) {
+static bool CUSort(const Unit *A, const Unit *B) {
   return (A->getUniqueID() < B->getUniqueID());
 }
 
@@ -2936,12 +2923,15 @@ void DwarfDebug::emitDebugRanges() {
   Asm->OutStreamer.SwitchSection(
       Asm->getObjFileLowering().getDwarfRangesSection());
   unsigned char Size = Asm->getDataLayout().getPointerSize();
-  for (SmallVectorImpl<const MCSymbol *>::iterator
-           I = DebugRangeSymbols.begin(),
-           E = DebugRangeSymbols.end();
-       I != E; ++I) {
-    if (*I)
-      Asm->OutStreamer.EmitSymbolValue(const_cast<MCSymbol *>(*I), Size);
+  for (uint32_t i = 0, e = DebugRangeSymbols.size(); i < e; ++i) {
+    // Only emit a symbol for every range pair for now.
+    // FIXME: Make this per range list.
+    if ((i % 2) == 0)
+      Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_ranges", i));
+
+    const MCSymbol *I = DebugRangeSymbols[i];
+    if (I)
+      Asm->OutStreamer.EmitSymbolValue(I, Size);
     else
       Asm->OutStreamer.EmitIntValue(0, Size);
   }
@@ -2973,11 +2963,10 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const CompileUnit *CU) {
   // Relocate to the beginning of the addr_base section, else 0 for the
   // beginning of the one for this compile unit.
   if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
-    NewCU->addLabel(Die, dwarf::DW_AT_GNU_addr_base, dwarf::DW_FORM_sec_offset,
-                    DwarfAddrSectionSym);
+    NewCU->addSectionLabel(Die, dwarf::DW_AT_GNU_addr_base,
+                           DwarfAddrSectionSym);
   else
-    NewCU->addUInt(Die, dwarf::DW_AT_GNU_addr_base, dwarf::DW_FORM_sec_offset,
-                   0);
+    NewCU->addSectionOffset(Die, dwarf::DW_AT_GNU_addr_base, 0);
 
   // 2.17.1 requires that we use DW_AT_low_pc for a single entry point
   // into an entity. We're using 0, or a NULL label for this.
@@ -2987,10 +2976,10 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const CompileUnit *CU) {
   // compile unit in debug_line section.
   // FIXME: Should handle multiple compile units.
   if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
-    NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset,
-                    DwarfLineSectionSym);
+    NewCU->addSectionLabel(Die, dwarf::DW_AT_stmt_list,
+                           DwarfLineSectionSym);
   else
-    NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset, 0);
+    NewCU->addSectionOffset(Die, dwarf::DW_AT_stmt_list, 0);
 
   if (!CompilationDir.empty())
     NewCU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
@@ -2998,34 +2987,37 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const CompileUnit *CU) {
   // Flags to let the linker know we have emitted new style pubnames.
   if (GenerateGnuPubSections) {
     if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
-      NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubnames, dwarf::DW_FORM_sec_offset,
-                      Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()));
+      NewCU->addSectionLabel(
+          Die, dwarf::DW_AT_GNU_pubnames,
+          Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()));
     else
-      NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubnames, dwarf::DW_FORM_data4,
-                      Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()),
-                      DwarfGnuPubNamesSectionSym);
+      NewCU->addSectionDelta(
+          Die, dwarf::DW_AT_GNU_pubnames,
+          Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()),
+          DwarfGnuPubNamesSectionSym);
 
     if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
-      NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubtypes, dwarf::DW_FORM_sec_offset,
-                      Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()));
+      NewCU->addSectionLabel(
+          Die, dwarf::DW_AT_GNU_pubtypes,
+          Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()));
     else
-      NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubtypes, dwarf::DW_FORM_data4,
-                      Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()),
-                      DwarfGnuPubTypesSectionSym);
+      NewCU->addSectionDelta(
+          Die, dwarf::DW_AT_GNU_pubtypes,
+          Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()),
+          DwarfGnuPubTypesSectionSym);
   }
 
   // Flag if we've emitted any ranges and their location for the compile unit.
   if (DebugRangeSymbols.size()) {
     if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
-      NewCU->addLabel(Die, dwarf::DW_AT_GNU_ranges_base,
-                      dwarf::DW_FORM_sec_offset, DwarfDebugRangeSectionSym);
+      NewCU->addSectionLabel(Die, dwarf::DW_AT_GNU_ranges_base,
+                             DwarfDebugRangeSectionSym);
     else
       NewCU->addUInt(Die, dwarf::DW_AT_GNU_ranges_base, dwarf::DW_FORM_data4,
                      0);
   }
 
   SkeletonHolder.addUnit(NewCU);
-  SkeletonCUs.push_back(NewCU);
 
   return NewCU;
 }
@@ -3063,3 +3055,57 @@ void DwarfDebug::emitDebugStrDWO() {
   InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),
                          OffSec, StrSym);
 }
+
+void DwarfDebug::addTypeUnitType(uint16_t Language, DIE *RefDie,
+                                 DICompositeType CTy) {
+  DenseMap<const MDNode *,
+           std::pair<uint64_t, SmallVectorImpl<DIE *> *> >::iterator I =
+      TypeUnits.find(CTy);
+  SmallVector<DIE *, 8> References;
+  References.push_back(RefDie);
+  if (I != TypeUnits.end()) {
+    if (I->second.second) {
+      I->second.second->push_back(RefDie);
+      return;
+    }
+  } else {
+    DIE *UnitDie = new DIE(dwarf::DW_TAG_type_unit);
+    TypeUnit *NewTU = new TypeUnit(GlobalCUIndexCount++, UnitDie, Language, Asm,
+                                   this, &InfoHolder);
+    NewTU->addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
+                   Language);
+
+    // Register the type in the TypeUnits map with a vector of references to be
+    // populated whenever a reference is required.
+    I = TypeUnits.insert(std::make_pair(CTy, std::make_pair(0, &References)))
+            .first;
+
+    // Construct the type, this may, recursively, require more type units that
+    // may in turn require this type again - in which case they will add DIEs to
+    // the References vector.
+    DIE *Die = NewTU->createTypeDIE(CTy);
+
+    if (GenerateODRHash && shouldAddODRHash(NewTU, Die))
+      NewTU->addUInt(UnitDie, dwarf::DW_AT_GNU_odr_signature,
+                     dwarf::DW_FORM_data8,
+                     DIEHash().computeDIEODRSignature(*Die));
+    // FIXME: This won't handle circularly referential structures, as the DIE
+    // may have references to other DIEs still under construction and missing
+    // their signature. Hashing should walk through the signatures to their
+    // referenced type, or possibly walk the precomputed hashes of related types
+    // at the end.
+    uint64_t Signature = DIEHash().computeTypeSignature(*Die);
+
+    // Remove the References vector and add the type hash.
+    I->second.first = Signature;
+    I->second.second = NULL;
+
+    InfoHolder.addUnit(NewTU);
+  }
+
+  // Populate all the signatures.
+  for (unsigned i = 0, e = References.size(); i != e; ++i) {
+    CUMap.begin()->second->addUInt(References[i], dwarf::DW_AT_signature,
+                                   dwarf::DW_FORM_ref_sig8, I->second.first);
+  }
+}