[llvm] [LLVM][DWARF] Add support for monolithic types in .debug_names (PR #70515)

Alexander Yermolovich via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 2 15:56:30 PDT 2023


https://github.com/ayermolo updated https://github.com/llvm/llvm-project/pull/70515

>From a039f332c420b9eef1d6541ee0d66fef813f447e Mon Sep 17 00:00:00 2001
From: Alexander Yermolovich <ayermolo at meta.com>
Date: Thu, 5 Oct 2023 12:39:02 -0700
Subject: [PATCH 1/6] [LLVM][DWARF] Add support for monolithic types in
 .debug_names

Enable Type Units with DWARF5 accelerator tables for monolithic DWARF.
Implementation relies on linker to tombstone offset in LocalTU list to -1 when
it deduplciates type units using COMDAT.
---
 llvm/include/llvm/CodeGen/AccelTable.h        |  64 +++++--
 llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp    | 173 ++++++++++++------
 .../lib/CodeGen/AsmPrinter/DwarfCompileUnit.h |   2 +-
 llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp    |  37 +++-
 llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h      |  12 +-
 llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp     |   4 +
 llvm/lib/CodeGen/AsmPrinter/DwarfFile.h       |  20 ++
 llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp     |   6 +
 llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h       |  15 ++
 llvm/lib/DWARFLinker/DWARFStreamer.cpp        |  18 +-
 .../DWARFLinkerParallel/DWARFEmitterImpl.cpp  |  13 +-
 .../test/DebugInfo/X86/accel-tables-dwarf5.ll |   1 -
 .../test/DebugInfo/X86/debug-names-dwarf64.ll |   8 +-
 .../X86/debug-names-types-monolithic.ll       | 163 +++++++++++++++++
 .../DebugInfo/X86/debug-names-types-split.ll  |  57 ++++++
 .../ARM/dwarf5-dwarf4-combination-macho.test  |  14 +-
 16 files changed, 503 insertions(+), 104 deletions(-)
 create mode 100644 llvm/test/DebugInfo/X86/debug-names-types-monolithic.ll
 create mode 100644 llvm/test/DebugInfo/X86/debug-names-types-split.ll

diff --git a/llvm/include/llvm/CodeGen/AccelTable.h b/llvm/include/llvm/CodeGen/AccelTable.h
index d4e21b2ac8e7ebc..d948b7d82b85979 100644
--- a/llvm/include/llvm/CodeGen/AccelTable.h
+++ b/llvm/include/llvm/CodeGen/AccelTable.h
@@ -16,7 +16,6 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
-#include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/CodeGen/DIE.h"
@@ -104,10 +103,13 @@
 namespace llvm {
 
 class AsmPrinter;
-class DwarfCompileUnit;
+class DwarfUnit;
 class DwarfDebug;
+class DwarfTypeUnit;
 class MCSymbol;
 class raw_ostream;
+struct TypeUnitMetaInfo;
+using TUVectorTy = SmallVector<TypeUnitMetaInfo, 1>;
 
 /// Interface which the different types of accelerator table data have to
 /// conform. It serves as a base class for different values of the template
@@ -197,6 +199,9 @@ template <typename DataT> class AccelTable : public AccelTableBase {
 
   template <typename... Types>
   void addName(DwarfStringPoolEntryRef Name, Types &&... Args);
+  void clear() { Entries.clear(); }
+  void addEntries(AccelTable<DataT> &Table);
+  const StringEntries getEntries() const { return Entries; }
 };
 
 template <typename AccelTableDataT>
@@ -250,11 +255,21 @@ class AppleAccelTableData : public AccelTableData {
 /// emitDWARF5AccelTable function.
 class DWARF5AccelTableData : public AccelTableData {
 public:
+  struct AttributeEncoding {
+    dwarf::Index Index;
+    dwarf::Form Form;
+  };
   static uint32_t hash(StringRef Name) { return caseFoldingDjbHash(Name); }
 
-  DWARF5AccelTableData(const DIE &Die, const DwarfCompileUnit &CU);
-  DWARF5AccelTableData(uint64_t DieOffset, unsigned DieTag, unsigned CUIndex)
-      : OffsetVal(DieOffset), DieTag(DieTag), UnitID(CUIndex) {}
+  DWARF5AccelTableData(const DIE &Die, const DwarfUnit &CU,
+                       const bool IsTU = false);
+  DWARF5AccelTableData(const uint64_t DieOffset, const unsigned DieTag,
+                       const unsigned Index, const bool IsTU = false)
+      : OffsetVal(DieOffset) {
+    Data.DieTag = DieTag;
+    Data.UnitID = Index;
+    Data.IsTU = IsTU;
+  }
 
 #ifndef NDEBUG
   void print(raw_ostream &OS) const override;
@@ -265,18 +280,25 @@ class DWARF5AccelTableData : public AccelTableData {
            "Accessing DIE Offset before normalizing.");
     return std::get<uint64_t>(OffsetVal);
   }
-  unsigned getDieTag() const { return DieTag; }
-  unsigned getUnitID() const { return UnitID; }
+  unsigned getDieTag() const { return Data.DieTag; }
+  unsigned getUnitID() const { return Data.UnitID; }
+  bool isTU() const { return Data.IsTU; }
   void normalizeDIEToOffset() {
     assert(std::holds_alternative<const DIE *>(OffsetVal) &&
            "Accessing offset after normalizing.");
     OffsetVal = std::get<const DIE *>(OffsetVal)->getOffset();
   }
+  bool isNormalized() const {
+    return std::holds_alternative<uint64_t>(OffsetVal);
+  }
 
 protected:
   std::variant<const DIE *, uint64_t> OffsetVal;
-  unsigned DieTag;
-  unsigned UnitID;
+  struct MetaData {
+    uint32_t DieTag : 16;
+    uint32_t UnitID : 15;
+    uint32_t IsTU : 1;
+  } Data;
 
   uint64_t order() const override { return getDieOffset(); }
 };
@@ -288,7 +310,19 @@ class DWARF5AccelTable : public AccelTable<DWARF5AccelTableData> {
   void convertDieToOffset() {
     for (auto &Entry : Entries) {
       for (AccelTableData *Value : Entry.second.Values) {
-        static_cast<DWARF5AccelTableData *>(Value)->normalizeDIEToOffset();
+        DWARF5AccelTableData *Data = static_cast<DWARF5AccelTableData *>(Value);
+        if (!Data->isNormalized())
+          Data->normalizeDIEToOffset();
+      }
+    }
+  }
+
+  void addTypeEntries(DWARF5AccelTable &Table) {
+    for (auto &Entry : Table.getEntries()) {
+      for (AccelTableData *Value : Entry.second.Values) {
+        DWARF5AccelTableData *Data = static_cast<DWARF5AccelTableData *>(Value);
+        addName(Entry.second.Name, Data->getDieOffset(), Data->getDieTag(),
+                Data->getUnitID(), true);
       }
     }
   }
@@ -310,8 +344,10 @@ void emitAppleAccelTable(AsmPrinter *Asm, AccelTable<DataT> &Contents,
 
 void emitDWARF5AccelTable(AsmPrinter *Asm, DWARF5AccelTable &Contents,
                           const DwarfDebug &DD,
-                          ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs);
-
+                          ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs,
+                          TUVectorTy TUSymbols);
+using GetIndexForEntryReturnType =
+    std::optional<std::pair<unsigned, DWARF5AccelTableData::AttributeEncoding>>;
 /// Emit a DWARFv5 Accelerator Table consisting of entries in the specified
 /// AccelTable. The \p CUs contains either symbols keeping offsets to the
 /// start of compilation unit, either offsets to the start of compilation
@@ -319,8 +355,8 @@ void emitDWARF5AccelTable(AsmPrinter *Asm, DWARF5AccelTable &Contents,
 void emitDWARF5AccelTable(
     AsmPrinter *Asm, DWARF5AccelTable &Contents,
     ArrayRef<std::variant<MCSymbol *, uint64_t>> CUs,
-    llvm::function_ref<unsigned(const DWARF5AccelTableData &)>
-        getCUIndexForEntry);
+    llvm::function_ref<GetIndexForEntryReturnType(const DWARF5AccelTableData &)>
+        getIndexForEntry);
 
 /// Accelerator table data implementation for simple Apple accelerator tables
 /// with just a DIE reference.
diff --git a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
index e393951744117eb..90715a805cc5e41 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
@@ -12,6 +12,7 @@
 
 #include "llvm/CodeGen/AccelTable.h"
 #include "DwarfCompileUnit.h"
+#include "DwarfUnit.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/BinaryFormat/Dwarf.h"
@@ -199,32 +200,30 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
     uint32_t AugmentationStringSize = sizeof(AugmentationString);
     char AugmentationString[8] = {'L', 'L', 'V', 'M', '0', '7', '0', '0'};
 
-    Header(uint32_t CompUnitCount, uint32_t BucketCount, uint32_t NameCount)
-        : CompUnitCount(CompUnitCount), BucketCount(BucketCount),
-          NameCount(NameCount) {}
+    Header(uint32_t CompUnitCount, uint32_t LocalTypeUnitCount,
+           uint32_t BucketCount, uint32_t NameCount)
+        : CompUnitCount(CompUnitCount), LocalTypeUnitCount(LocalTypeUnitCount),
+          BucketCount(BucketCount), NameCount(NameCount) {}
 
     void emit(Dwarf5AccelTableWriter &Ctx);
   };
-  struct AttributeEncoding {
-    dwarf::Index Index;
-    dwarf::Form Form;
-  };
 
   Header Header;
-  DenseMap<uint32_t, SmallVector<AttributeEncoding, 2>> Abbreviations;
+  DenseMap<uint32_t, SmallVector<DWARF5AccelTableData::AttributeEncoding, 2>>
+      Abbreviations;
   ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits;
-  llvm::function_ref<unsigned(const DataT &)> getCUIndexForEntry;
+  ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits;
+  llvm::function_ref<GetIndexForEntryReturnType(const DataT &)>
+      getIndexForEntry;
   MCSymbol *ContributionEnd = nullptr;
   MCSymbol *AbbrevStart = Asm->createTempSymbol("names_abbrev_start");
   MCSymbol *AbbrevEnd = Asm->createTempSymbol("names_abbrev_end");
   MCSymbol *EntryPool = Asm->createTempSymbol("names_entries");
 
-  DenseSet<uint32_t> getUniqueTags() const;
-
-  // Right now, we emit uniform attributes for all tags.
-  SmallVector<AttributeEncoding, 2> getUniformAttributes() const;
+  void populateAbbrevsMap();
 
   void emitCUList() const;
+  void emitTUList() const;
   void emitBuckets() const;
   void emitStringOffsets() const;
   void emitAbbrevs() const;
@@ -235,7 +234,9 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
   Dwarf5AccelTableWriter(
       AsmPrinter *Asm, const AccelTableBase &Contents,
       ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits,
-      llvm::function_ref<unsigned(const DataT &)> GetCUIndexForEntry);
+      ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits,
+      llvm::function_ref<GetIndexForEntryReturnType(const DataT &)>
+          getIndexForEntry);
 
   void emit();
 };
@@ -358,8 +359,13 @@ void AppleAccelTableWriter::emit() const {
 }
 
 DWARF5AccelTableData::DWARF5AccelTableData(const DIE &Die,
-                                           const DwarfCompileUnit &CU)
-    : OffsetVal(&Die), DieTag(Die.getTag()), UnitID(CU.getUniqueID()) {}
+                                           const DwarfUnit &Unit,
+                                           const bool IsTU)
+    : OffsetVal(&Die) {
+  Data.DieTag = Die.getTag();
+  Data.UnitID = Unit.getUniqueID();
+  Data.IsTU = IsTU;
+}
 
 template <typename DataT>
 void Dwarf5AccelTableWriter<DataT>::Header::emit(Dwarf5AccelTableWriter &Ctx) {
@@ -391,31 +397,39 @@ void Dwarf5AccelTableWriter<DataT>::Header::emit(Dwarf5AccelTableWriter &Ctx) {
   Asm->OutStreamer->emitBytes({AugmentationString, AugmentationStringSize});
 }
 
+static uint32_t constexpr LowerBitSize = dwarf::DW_IDX_type_hash;
+static uint32_t getTagFromAbbreviationTag(const uint32_t AbbrvTag) {
+  return AbbrvTag >> LowerBitSize;
+}
+static uint32_t
+constructAbbreviationTag(const unsigned Tag,
+                         const GetIndexForEntryReturnType &EntryRet) {
+  uint32_t AbbrvTag = 0;
+  if (EntryRet)
+    AbbrvTag |= 1 << EntryRet->second.Index;
+  AbbrvTag |= 1 << dwarf::DW_IDX_die_offset;
+  AbbrvTag |= Tag << LowerBitSize;
+  return AbbrvTag;
+}
 template <typename DataT>
-DenseSet<uint32_t> Dwarf5AccelTableWriter<DataT>::getUniqueTags() const {
-  DenseSet<uint32_t> UniqueTags;
+void Dwarf5AccelTableWriter<DataT>::populateAbbrevsMap() {
   for (auto &Bucket : Contents.getBuckets()) {
     for (auto *Hash : Bucket) {
       for (auto *Value : Hash->Values) {
+        GetIndexForEntryReturnType EntryRet =
+            getIndexForEntry(*static_cast<const DataT *>(Value));
         unsigned Tag = static_cast<const DataT *>(Value)->getDieTag();
-        UniqueTags.insert(Tag);
+        uint32_t AbbrvTag = constructAbbreviationTag(Tag, EntryRet);
+        if (Abbreviations.count(AbbrvTag) == 0) {
+          SmallVector<DWARF5AccelTableData::AttributeEncoding, 2> UA;
+          if (EntryRet)
+            UA.push_back(EntryRet->second);
+          UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
+          Abbreviations.try_emplace(AbbrvTag, UA);
+        }
       }
     }
   }
-  return UniqueTags;
-}
-
-template <typename DataT>
-SmallVector<typename Dwarf5AccelTableWriter<DataT>::AttributeEncoding, 2>
-Dwarf5AccelTableWriter<DataT>::getUniformAttributes() const {
-  SmallVector<AttributeEncoding, 2> UA;
-  if (CompUnits.size() > 1) {
-    size_t LargestCUIndex = CompUnits.size() - 1;
-    dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false, LargestCUIndex);
-    UA.push_back({dwarf::DW_IDX_compile_unit, Form});
-  }
-  UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
-  return UA;
 }
 
 template <typename DataT>
@@ -429,6 +443,17 @@ void Dwarf5AccelTableWriter<DataT>::emitCUList() const {
   }
 }
 
+template <typename DataT>
+void Dwarf5AccelTableWriter<DataT>::emitTUList() const {
+  for (const auto &TU : enumerate(TypeUnits)) {
+    Asm->OutStreamer->AddComment("Type unit " + Twine(TU.index()));
+    if (std::holds_alternative<MCSymbol *>(TU.value()))
+      Asm->emitDwarfSymbolReference(std::get<MCSymbol *>(TU.value()));
+    else
+      Asm->emitDwarfLengthOrOffset(std::get<uint64_t>(TU.value()));
+  }
+}
+
 template <typename DataT>
 void Dwarf5AccelTableWriter<DataT>::emitBuckets() const {
   uint32_t Index = 1;
@@ -456,10 +481,11 @@ void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const {
   Asm->OutStreamer->emitLabel(AbbrevStart);
   for (const auto &Abbrev : Abbreviations) {
     Asm->OutStreamer->AddComment("Abbrev code");
-    assert(Abbrev.first != 0);
-    Asm->emitULEB128(Abbrev.first);
-    Asm->OutStreamer->AddComment(dwarf::TagString(Abbrev.first));
+    uint32_t Tag = getTagFromAbbreviationTag(Abbrev.first);
+    assert(Tag != 0);
     Asm->emitULEB128(Abbrev.first);
+    Asm->OutStreamer->AddComment(dwarf::TagString(Tag));
+    Asm->emitULEB128(Tag);
     for (const auto &AttrEnc : Abbrev.second) {
       Asm->emitULEB128(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data());
       Asm->emitULEB128(AttrEnc.Form,
@@ -474,16 +500,21 @@ void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const {
 
 template <typename DataT>
 void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const {
-  auto AbbrevIt = Abbreviations.find(Entry.getDieTag());
+  GetIndexForEntryReturnType EntryRet = getIndexForEntry(Entry);
+  uint32_t AbbrvTag = constructAbbreviationTag(Entry.getDieTag(), EntryRet);
+  auto AbbrevIt = Abbreviations.find(AbbrvTag);
   assert(AbbrevIt != Abbreviations.end() &&
          "Why wasn't this abbrev generated?");
-
+  assert(getTagFromAbbreviationTag(AbbrevIt->first) == Entry.getDieTag() &&
+         "Invalid Tag");
   Asm->emitULEB128(AbbrevIt->first, "Abbreviation code");
+
   for (const auto &AttrEnc : AbbrevIt->second) {
     Asm->OutStreamer->AddComment(dwarf::IndexString(AttrEnc.Index));
     switch (AttrEnc.Index) {
-    case dwarf::DW_IDX_compile_unit: {
-      DIEInteger ID(getCUIndexForEntry(Entry));
+    case dwarf::DW_IDX_compile_unit:
+    case dwarf::DW_IDX_type_unit: {
+      DIEInteger ID(EntryRet->first);
       ID.emitValue(Asm, AttrEnc.Form);
       break;
     }
@@ -515,22 +546,21 @@ template <typename DataT>
 Dwarf5AccelTableWriter<DataT>::Dwarf5AccelTableWriter(
     AsmPrinter *Asm, const AccelTableBase &Contents,
     ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits,
-    llvm::function_ref<unsigned(const DataT &)> getCUIndexForEntry)
+    ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits,
+    llvm::function_ref<GetIndexForEntryReturnType(const DataT &)>
+        getIndexForEntry)
     : AccelTableWriter(Asm, Contents, false),
-      Header(CompUnits.size(), Contents.getBucketCount(),
+      Header(CompUnits.size(), TypeUnits.size(), Contents.getBucketCount(),
              Contents.getUniqueNameCount()),
-      CompUnits(CompUnits), getCUIndexForEntry(std::move(getCUIndexForEntry)) {
-  DenseSet<uint32_t> UniqueTags = getUniqueTags();
-  SmallVector<AttributeEncoding, 2> UniformAttributes = getUniformAttributes();
-
-  Abbreviations.reserve(UniqueTags.size());
-  for (uint32_t Tag : UniqueTags)
-    Abbreviations.try_emplace(Tag, UniformAttributes);
+      CompUnits(CompUnits), TypeUnits(TypeUnits),
+      getIndexForEntry(std::move(getIndexForEntry)) {
+  populateAbbrevsMap();
 }
 
 template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emit() {
   Header.emit(*this);
   emitCUList();
+  emitTUList();
   emitBuckets();
   emitHashes();
   emitStringOffsets();
@@ -548,12 +578,16 @@ void llvm::emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents,
   AppleAccelTableWriter(Asm, Contents, Atoms, SecBegin).emit();
 }
 
-void llvm::emitDWARF5AccelTable(
-    AsmPrinter *Asm, DWARF5AccelTable &Contents, const DwarfDebug &DD,
-    ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) {
+void llvm::emitDWARF5AccelTable(AsmPrinter *Asm, DWARF5AccelTable &Contents,
+                                const DwarfDebug &DD,
+                                ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs,
+                                TUVectorTy TUSymbols) {
   std::vector<std::variant<MCSymbol *, uint64_t>> CompUnits;
+  std::vector<std::variant<MCSymbol *, uint64_t>> TypeUnits;
   SmallVector<unsigned, 1> CUIndex(CUs.size());
-  int Count = 0;
+  DenseMap<unsigned, unsigned> TUIndex(TUSymbols.size());
+  int CUCount = 0;
+  int TUCount = 0;
   for (const auto &CU : enumerate(CUs)) {
     switch (CU.value()->getCUNode()->getNameTableKind()) {
     case DICompileUnit::DebugNameTableKind::Default:
@@ -562,13 +596,18 @@ void llvm::emitDWARF5AccelTable(
     default:
       continue;
     }
-    CUIndex[CU.index()] = Count++;
+    CUIndex[CU.index()] = CUCount++;
     assert(CU.index() == CU.value()->getUniqueID());
     const DwarfCompileUnit *MainCU =
         DD.useSplitDwarf() ? CU.value()->getSkeleton() : CU.value().get();
     CompUnits.push_back(MainCU->getLabelBegin());
   }
 
+  for (const auto &TU : TUSymbols) {
+    TUIndex[TU.UniqueID] = TUCount++;
+    TypeUnits.push_back(TU.Label);
+  }
+
   if (CompUnits.empty())
     return;
 
@@ -576,10 +615,21 @@ void llvm::emitDWARF5AccelTable(
       Asm->getObjFileLowering().getDwarfDebugNamesSection());
 
   Contents.finalize(Asm, "names");
+  dwarf::Form CUIndexForm =
+      DIEInteger::BestForm(/*IsSigned*/ false, CompUnits.size() - 1);
+  dwarf::Form TUIndexForm =
+      DIEInteger::BestForm(/*IsSigned*/ false, TypeUnits.size() - 1);
   Dwarf5AccelTableWriter<DWARF5AccelTableData>(
-      Asm, Contents, CompUnits,
-      [&](const DWARF5AccelTableData &Entry) {
-        return CUIndex[Entry.getUnitID()];
+      Asm, Contents, CompUnits, TypeUnits,
+      [&](const DWARF5AccelTableData &Entry) -> GetIndexForEntryReturnType {
+        GetIndexForEntryReturnType Index = std::nullopt;
+        if (Entry.isTU())
+          Index = {TUIndex[Entry.getUnitID()],
+                   {dwarf::DW_IDX_type_unit, TUIndexForm}};
+        else if (CUIndex.size() > 1)
+          Index = {CUIndex[Entry.getUnitID()],
+                   {dwarf::DW_IDX_compile_unit, CUIndexForm}};
+        return Index;
       })
       .emit();
 }
@@ -587,11 +637,12 @@ void llvm::emitDWARF5AccelTable(
 void llvm::emitDWARF5AccelTable(
     AsmPrinter *Asm, DWARF5AccelTable &Contents,
     ArrayRef<std::variant<MCSymbol *, uint64_t>> CUs,
-    llvm::function_ref<unsigned(const DWARF5AccelTableData &)>
-        getCUIndexForEntry) {
+    llvm::function_ref<GetIndexForEntryReturnType(const DWARF5AccelTableData &)>
+        getIndexForEntry) {
+  std::vector<std::variant<MCSymbol *, uint64_t>> TypeUnits;
   Contents.finalize(Asm, "names");
-  Dwarf5AccelTableWriter<DWARF5AccelTableData>(Asm, Contents, CUs,
-                                               getCUIndexForEntry)
+  Dwarf5AccelTableWriter<DWARF5AccelTableData>(Asm, Contents, CUs, TypeUnits,
+                                               getIndexForEntry)
       .emit();
 }
 
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
index 453dcc1c90bbf49..70dbd8e17c933ed 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
@@ -151,7 +151,7 @@ class DwarfCompileUnit final : public DwarfUnit {
                    UnitKind Kind = UnitKind::Full);
 
   bool hasRangeLists() const { return HasRangeLists; }
-  unsigned getUniqueID() const { return UniqueID; }
+  unsigned getUniqueID() const override { return UniqueID; }
 
   DwarfCompileUnit *getSkeleton() const {
     return Skeleton;
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 61ac492a9097063..3923ad61d825c8b 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -305,6 +305,7 @@ void Loc::MMI::addFrameIndexExpr(const DIExpression *Expr, int FI) {
 
 static AccelTableKind computeAccelTableKind(unsigned DwarfVersion,
                                             bool GenerateTypeUnits,
+                                            bool HasSplitDwarf,
                                             DebuggerKind Tuning,
                                             const Triple &TT) {
   // Honor an explicit request.
@@ -312,7 +313,8 @@ static AccelTableKind computeAccelTableKind(unsigned DwarfVersion,
     return AccelTables;
 
   // Accelerator tables with type units are currently not supported.
-  if (GenerateTypeUnits)
+  if (GenerateTypeUnits &&
+      (DwarfVersion < 5 || HasSplitDwarf || !TT.isOSBinFormatELF()))
     return AccelTableKind::None;
 
   // Accelerator tables get emitted if targetting DWARF v5 or LLDB.  DWARF v5
@@ -325,6 +327,9 @@ static AccelTableKind computeAccelTableKind(unsigned DwarfVersion,
                                    : AccelTableKind::Dwarf;
   return AccelTableKind::None;
 }
+void DwarfDebug::addTypeUnitSymbol(DwarfTypeUnit &U) {
+  InfoHolder.addTypeUnitSymbol(U);
+}
 
 DwarfDebug::DwarfDebug(AsmPrinter *A)
     : DebugHandlerBase(A), DebugLocs(A->OutStreamer->isVerboseAsm()),
@@ -400,8 +405,9 @@ DwarfDebug::DwarfDebug(AsmPrinter *A)
                        A->TM.getTargetTriple().isOSBinFormatWasm()) &&
                       GenerateDwarfTypeUnits;
 
-  TheAccelTableKind = computeAccelTableKind(
-      DwarfVersion, GenerateTypeUnits, DebuggerTuning, A->TM.getTargetTriple());
+  TheAccelTableKind =
+      computeAccelTableKind(DwarfVersion, GenerateTypeUnits, HasSplitDwarf,
+                            DebuggerTuning, A->TM.getTargetTriple());
 
   // Work around a GDB bug. GDB doesn't support the standard opcode;
   // SCE doesn't support GNU's; LLDB prefers the standard opcode, which
@@ -2398,7 +2404,8 @@ void DwarfDebug::emitAccelDebugNames() {
   if (getUnits().empty())
     return;
 
-  emitDWARF5AccelTable(Asm, AccelDebugNames, *this, getUnits());
+  emitDWARF5AccelTable(Asm, AccelDebugNames, *this, getUnits(),
+                       getTypeUnitsSymbols());
 }
 
 // Emit visible names into a hashed accelerator table section.
@@ -3503,7 +3510,7 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
     // Types referencing entries in the address table cannot be placed in type
     // units.
     if (AddrPool.hasBeenUsed()) {
-
+      AccelTypeUntsDebugNames.clear();
       // Remove all the types built while building this type.
       // This is pessimistic as some of these types might not be dependent on
       // the type that used an address.
@@ -3518,11 +3525,16 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
       return;
     }
 
-    // If the type wasn't dependent on fission addresses, finish adding the type
-    // and all its dependent types.
     for (auto &TU : TypeUnitsToAdd) {
       InfoHolder.computeSizeAndOffsetsForUnit(TU.first.get());
       InfoHolder.emitUnit(TU.first.get(), useSplitDwarf());
+      if (getDwarfVersion() >= 5 &&
+          getAccelTableKind() == AccelTableKind::Dwarf) {
+        addTypeUnitSymbol(*TU.first);
+        AccelTypeUntsDebugNames.convertDieToOffset();
+        AccelDebugNames.addTypeEntries(AccelTypeUntsDebugNames);
+        AccelTypeUntsDebugNames.clear();
+      }
     }
   }
   CU.addDIETypeSignature(RefDie, Signature);
@@ -3552,8 +3564,15 @@ void DwarfDebug::addAccelNameImpl(const DICompileUnit &CU,
     AppleAccel.addName(Ref, Die);
     break;
   case AccelTableKind::Dwarf: {
-    DwarfCompileUnit *DCU = CUMap.lookup(&CU);
-    AccelDebugNames.addName(Ref, Die, *DCU);
+    // The type unit can be discarded, so need to add references to final
+    // acceleration table once we know it's complete and we emit it.
+    if (TypeUnitsUnderConstruction.empty()) {
+      DwarfCompileUnit *Unit = CUMap.lookup(&CU);
+      AccelDebugNames.addName(Ref, Die, *Unit);
+    } else {
+      DwarfTypeUnit *Unit = TypeUnitsUnderConstruction.back().first.get();
+      AccelTypeUntsDebugNames.addName(Ref, Die, *Unit);
+    }
     break;
   }
   case AccelTableKind::Default:
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
index b41d2be5eb9b8c9..66c87a68fa342ae 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -17,7 +17,6 @@
 #include "DebugLocEntry.h"
 #include "DebugLocStream.h"
 #include "DwarfFile.h"
-#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/MapVector.h"
@@ -497,6 +496,7 @@ class DwarfDebug : public DebugHandlerBase {
 
   /// Accelerator tables.
   DWARF5AccelTable AccelDebugNames;
+  DWARF5AccelTable AccelTypeUntsDebugNames;
   AccelTable<AppleAccelTableOffsetData> AccelNames;
   AccelTable<AppleAccelTableOffsetData> AccelObjC;
   AccelTable<AppleAccelTableOffsetData> AccelNamespace;
@@ -515,6 +515,13 @@ class DwarfDebug : public DebugHandlerBase {
     return InfoHolder.getUnits();
   }
 
+  /// Returns Type Units constructed for this module.
+  const TUVectorTy &getTypeUnitsSymbols() {
+    return InfoHolder.getTypeUnitsSymbols();
+  }
+
+  void addTypeUnitSymbol(DwarfTypeUnit &U);
+
   using InlinedEntity = DbgValueHistoryMap::InlinedEntity;
 
   void ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU,
@@ -780,6 +787,9 @@ class DwarfDebug : public DebugHandlerBase {
   /// Returns what kind (if any) of accelerator tables to emit.
   AccelTableKind getAccelTableKind() const { return TheAccelTableKind; }
 
+  /// Seet TheAccelTableKind
+  void setTheAccelTableKind(AccelTableKind K) { TheAccelTableKind = K; };
+
   bool useAppleExtensionAttributes() const {
     return HasAppleExtensionAttributes;
   }
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp
index eab798c0da78438..dd946426e8860f4 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp
@@ -24,6 +24,10 @@ void DwarfFile::addUnit(std::unique_ptr<DwarfCompileUnit> U) {
   CUs.push_back(std::move(U));
 }
 
+void DwarfFile::addTypeUnitSymbol(DwarfTypeUnit &U) {
+  TUSymbols.emplace_back(U.getLabelBegin(), U.getUniqueID());
+}
+
 // Emit the various dwarf units to the unit section USection with
 // the abbreviations going into ASection.
 void DwarfFile::emitUnits(bool UseOffsets) {
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
index f76858fc2f36a02..6b48984b818c3d0 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
@@ -28,6 +28,7 @@ class DbgLabel;
 class DINode;
 class DILocalScope;
 class DwarfCompileUnit;
+class DwarfTypeUnit;
 class DwarfUnit;
 class LexicalScope;
 class MCSection;
@@ -47,6 +48,14 @@ struct RangeSpanList {
   SmallVector<RangeSpan, 2> Ranges;
 };
 
+struct TypeUnitMetaInfo {
+  TypeUnitMetaInfo(MCSymbol *L, unsigned ID) : Label(L), UniqueID(ID) {}
+  // Symbol for start of the TU section.
+  MCSymbol *Label;
+  unsigned UniqueID;
+};
+using TUVectorTy = SmallVector<TypeUnitMetaInfo, 1>;
+
 class DwarfFile {
   // Target of Dwarf emission, used for sizing of abbreviations.
   AsmPrinter *Asm;
@@ -59,6 +68,9 @@ class DwarfFile {
   // A pointer to all units in the section.
   SmallVector<std::unique_ptr<DwarfCompileUnit>, 1> CUs;
 
+  // Symbols to start of all the TU sections that were generated.
+  TUVectorTy TUSymbols;
+
   DwarfStringPool StrPool;
 
   // List of range lists for a given compile unit, separate from the ranges for
@@ -103,6 +115,9 @@ class DwarfFile {
     return CUs;
   }
 
+  /// Returns type units that were constructed.
+  const TUVectorTy &getTypeUnitsSymbols() { return TUSymbols; }
+
   std::pair<uint32_t, RangeSpanList *> addRange(const DwarfCompileUnit &CU,
                                                 SmallVector<RangeSpan, 2> R);
 
@@ -124,6 +139,11 @@ class DwarfFile {
   /// Add a unit to the list of CUs.
   void addUnit(std::unique_ptr<DwarfCompileUnit> U);
 
+  /// Add a unit to the list of TUs.
+  /// Preserves type unit so that memory is not released before DWARF5
+  /// accelerator table is created.
+  void addTypeUnitSymbol(DwarfTypeUnit &U);
+
   /// Emit all of the units to the section listed with the given
   /// abbreviation section.
   void emitUnits(bool UseOffsets);
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index a5960a5d4a09a17..d095594655a05ea 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -83,11 +83,13 @@ DwarfUnit::DwarfUnit(dwarf::Tag UnitTag, const DICompileUnit *Node,
                      AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU)
     : DIEUnit(UnitTag), CUNode(Node), Asm(A), DD(DW), DU(DWU) {}
 
+unsigned DwarfTypeUnit::UniqueID = 0;
 DwarfTypeUnit::DwarfTypeUnit(DwarfCompileUnit &CU, AsmPrinter *A,
                              DwarfDebug *DW, DwarfFile *DWU,
                              MCDwarfDwoLineTable *SplitLineTable)
     : DwarfUnit(dwarf::DW_TAG_type_unit, CU.getCUNode(), A, DW, DWU), CU(CU),
       SplitLineTable(SplitLineTable) {
+  ++DwarfTypeUnit::UniqueID;
 }
 
 DwarfUnit::~DwarfUnit() {
@@ -1777,6 +1779,10 @@ void DwarfUnit::emitCommonHeader(bool UseOffsets, dwarf::UnitType UT) {
 }
 
 void DwarfTypeUnit::emitHeader(bool UseOffsets) {
+  if (!DD->useSplitDwarf()) {
+    LabelBegin = Asm->createTempSymbol("tu_begin");
+    Asm->OutStreamer->emitLabel(LabelBegin);
+  }
   DwarfUnit::emitCommonHeader(UseOffsets,
                               DD->useSplitDwarf() ? dwarf::DW_UT_split_type
                                                   : dwarf::DW_UT_type);
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
index 8f17e94c2d1c331..29c560a1cee0ff1 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
@@ -301,6 +301,9 @@ class DwarfUnit : public DIEUnit {
   /// Get context owner's DIE.
   DIE *createTypeDIE(const DICompositeType *Ty);
 
+  /// Returns a unique ID.
+  virtual unsigned getUniqueID() const = 0;
+
 protected:
   ~DwarfUnit();
 
@@ -358,10 +361,13 @@ class DwarfUnit : public DIEUnit {
 
 class DwarfTypeUnit final : public DwarfUnit {
   uint64_t TypeSignature;
+  static unsigned UniqueID;
   const DIE *Ty;
   DwarfCompileUnit &CU;
   MCDwarfDwoLineTable *SplitLineTable;
   bool UsedLineTable = false;
+  /// The start of the type unit within .debug_nfo section.
+  MCSymbol *LabelBegin = nullptr;
 
   unsigned getOrCreateSourceID(const DIFile *File) override;
   void finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) override;
@@ -372,6 +378,8 @@ class DwarfTypeUnit final : public DwarfUnit {
                 DwarfFile *DWU, MCDwarfDwoLineTable *SplitLineTable = nullptr);
 
   void setTypeSignature(uint64_t Signature) { TypeSignature = Signature; }
+  /// Returns Type Signature.
+  uint64_t getTypeSignature() const { return TypeSignature; }
   void setType(const DIE *Ty) { this->Ty = Ty; }
 
   /// Emit the header for this unit, not including the initial length field.
@@ -385,6 +393,13 @@ class DwarfTypeUnit final : public DwarfUnit {
   void addGlobalType(const DIType *Ty, const DIE &Die,
                      const DIScope *Context) override;
   DwarfCompileUnit &getCU() override { return CU; }
+  /// Get the the symbol for start of the section for this type unit.
+  MCSymbol *getLabelBegin() const {
+    assert(LabelBegin && "LabelBegin is not initialized");
+    return LabelBegin;
+  }
+
+  unsigned getUniqueID() const override { return UniqueID; }
 };
 } // end llvm namespace
 #endif
diff --git a/llvm/lib/DWARFLinker/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
index 2c6aba7225adcce..53a75f429880118 100644
--- a/llvm/lib/DWARFLinker/DWARFStreamer.cpp
+++ b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
@@ -306,10 +306,20 @@ void DwarfStreamer::emitDebugNames(DWARF5AccelTable &Table) {
   }
 
   Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());
-  emitDWARF5AccelTable(Asm.get(), Table, CompUnits,
-                       [&UniqueIdToCuMap](const DWARF5AccelTableData &Entry) {
-                         return UniqueIdToCuMap[Entry.getUnitID()];
-                       });
+  dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false,
+                                          (uint64_t)UniqueIdToCuMap.size() - 1);
+  /// llvm-dwarfutil doesn't support type units + .debug_names right now anyway,
+  /// so just keeping current behavior.
+  emitDWARF5AccelTable(
+      Asm.get(), Table, CompUnits,
+      [&UniqueIdToCuMap,
+       &Form](const DWARF5AccelTableData &Entry) -> GetIndexForEntryReturnType {
+        GetIndexForEntryReturnType Index = std::nullopt;
+        if (UniqueIdToCuMap.size() > 1)
+          Index = {UniqueIdToCuMap[Entry.getUnitID()],
+                   {dwarf::DW_IDX_compile_unit, Form}};
+        return Index;
+      });
 }
 
 void DwarfStreamer::emitAppleNamespaces(
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp b/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp
index 88038824c9dcb4d..00b2437efdf9073 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp
+++ b/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp
@@ -230,9 +230,18 @@ void DwarfEmitterImpl::emitDebugNames(DWARF5AccelTable &Table,
     return;
 
   Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());
+  dwarf::Form Form =
+      DIEInteger::BestForm(/*IsSigned*/ false, (uint64_t)CUidToIdx.size() - 1);
+  /// DWARFLinker doesn't support type units + .debug_names right now anyway,
+  /// so just keeping current behavior.
   emitDWARF5AccelTable(Asm.get(), Table, CUOffsets,
-                       [&CUidToIdx](const DWARF5AccelTableData &Entry) {
-                         return CUidToIdx[Entry.getUnitID()];
+                       [&CUidToIdx, &Form](const DWARF5AccelTableData &Entry)
+                           -> GetIndexForEntryReturnType {
+                         GetIndexForEntryReturnType Index = std::nullopt;
+                         if (CUidToIdx.size() > 1)
+                           Index = {CUidToIdx[Entry.getUnitID()],
+                                    {dwarf::DW_IDX_compile_unit, Form}};
+                         return Index;
                        });
 }
 
diff --git a/llvm/test/DebugInfo/X86/accel-tables-dwarf5.ll b/llvm/test/DebugInfo/X86/accel-tables-dwarf5.ll
index e7cf7968003d9a6..243dea608a2d7f7 100644
--- a/llvm/test/DebugInfo/X86/accel-tables-dwarf5.ll
+++ b/llvm/test/DebugInfo/X86/accel-tables-dwarf5.ll
@@ -22,7 +22,6 @@
 ; RUN:   | llvm-readobj --sections - | FileCheck --check-prefix=DEBUG_NAMES %s
 
 ; NONE-NOT: apple_names
-; NONE-NOT: debug_names
 
 ; DEBUG_NAMES-NOT: apple_names
 ; DEBUG_NAMES: debug_names
diff --git a/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll b/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll
index 8cd1f0c18292093..c6edd794607c201 100644
--- a/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll
+++ b/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll
@@ -26,14 +26,14 @@
 ; CHECK-NEXT:     CU[0]: 0x00000000
 ; CHECK-NEXT:   ]
 ; CHECK-NEXT:   Abbreviations [
-; CHECK-NEXT:     Abbreviation [[ABBREV1:0x[0-9a-f]*]] {
-; CHECK-NEXT:       Tag: DW_TAG_variable
-; CHECK-NEXT:       DW_IDX_die_offset: DW_FORM_ref4
-; CHECK-NEXT:     }
 ; CHECK-NEXT:     Abbreviation [[ABBREV:0x[0-9a-f]*]] {
 ; CHECK-NEXT:       Tag: DW_TAG_base_type
 ; CHECK-NEXT:       DW_IDX_die_offset: DW_FORM_ref4
 ; CHECK-NEXT:     }
+; CHECK-NEXT:     Abbreviation [[ABBREV1:0x[0-9a-f]*]] {
+; CHECK-NEXT:       Tag: DW_TAG_variable
+; CHECK-NEXT:       DW_IDX_die_offset: DW_FORM_ref4
+; CHECK-NEXT:     }
 ; CHECK-NEXT:   ]
 ; CHECK-NEXT:   Bucket 0 [
 ; CHECK-NEXT:     Name 1 {
diff --git a/llvm/test/DebugInfo/X86/debug-names-types-monolithic.ll b/llvm/test/DebugInfo/X86/debug-names-types-monolithic.ll
new file mode 100644
index 000000000000000..84f8ff0d4d9050a
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/debug-names-types-monolithic.ll
@@ -0,0 +1,163 @@
+; This checks that .debug_names can be generated with monolithic -fdebug-type-sections.
+
+; RUN: llc -mtriple=x86_64 -generate-type-units -dwarf-version=5 -filetype=obj %s -o %t
+; RUN: llvm-dwarfdump -debug-info -debug-names %t | FileCheck %s
+
+; CHECK:     .debug_info contents:
+; CHECK:      DW_TAG_type_unit
+; CHECK-NEXT:   DW_AT_language  (DW_LANG_C_plus_plus_14)
+; CHECK-NEXT:   DW_AT_stmt_list (0x00000000)
+; CHECK-NEXT:   DW_AT_str_offsets_base  (0x00000008)
+; CHECK:      DW_TAG_structure_type
+; CHECK-NEXT:     DW_AT_calling_convention  (DW_CC_pass_by_value)
+; CHECK-NEXT:     DW_AT_name  ("Foo")
+; CHECK-NEXT:     DW_AT_byte_size (0x08)
+; CHECK-NEXT:     DW_AT_decl_file ("/typeSmall/main.cpp")
+; CHECK-NEXT:     DW_AT_decl_line (1)
+; CHECK:       DW_TAG_member
+; CHECK-NEXT:       DW_AT_name  ("c1")
+; CHECK-NEXT:       DW_AT_type  (0x00000033 "char *")
+; CHECK-NEXT:       DW_AT_decl_file ("/typeSmall/main.cpp")
+; CHECK-NEXT:       DW_AT_decl_line (2)
+; CHECK-NEXT:       DW_AT_data_member_location  (0x00)
+; CHECK:       DW_TAG_pointer_type
+; CHECK-NEXT:     DW_AT_type  (0x00000038 "char")
+; CHECK:       DW_TAG_base_type
+; CHECK-NEXT:     DW_AT_name  ("char")
+; CHECK-NEXT:     DW_AT_encoding  (DW_ATE_signed_char)
+; CHECK-NEXT:     DW_AT_byte_size (0x01)
+; CHECK:        .debug_names contents:
+; CHECK:         Compilation Unit offsets [
+; CHECK-NEXT:        CU[0]: 0x00000000
+; CHECK-NEXT:      ]
+; CHECK-NEXT:      Local Type Unit offsets [
+; CHECK-NEXT:        LocalTU[0]: 0x00000000
+; CHECK-NEXT:      ]
+; CHECK:        Abbreviations [
+; CHECK-NEXT:     Abbreviation [[ABBREV1:0x[0-9a-f]*]] {
+; CHECK-NEXT:       Tag: DW_TAG_structure_type
+; CHECK-NEXT:       DW_IDX_die_offset: DW_FORM_ref4
+; CHECK-NEXT:     }
+; CHECK-NEXT:     Abbreviation [[ABBREV3:0x[0-9a-f]*]] {
+; CHECK-NEXT:       Tag: DW_TAG_structure_type
+; CHECK-NEXT:       DW_IDX_type_unit: DW_FORM_data1
+; CHECK-NEXT:       DW_IDX_die_offset: DW_FORM_ref4
+; CHECK-NEXT:     }
+; CHECK-NEXT:     Abbreviation [[ABBREV:0x[0-9a-f]*]] {
+; CHECK-NEXT:       Tag: DW_TAG_base_type
+; CHECK-NEXT:       DW_IDX_die_offset: DW_FORM_ref4
+; CHECK-NEXT:     }
+; CHECK-NEXT:     Abbreviation [[ABBREV2:0x[0-9a-f]*]] {
+; CHECK-NEXT:       Tag: DW_TAG_subprogram
+; CHECK-NEXT:       DW_IDX_die_offset: DW_FORM_ref4
+; CHECK-NEXT:     }
+; CHECK-NEXT:     Abbreviation [[ABBREV4:0x[0-9a-f]*]] {
+; CHECK-NEXT:       Tag: DW_TAG_base_type
+; CHECK-NEXT:       DW_IDX_type_unit: DW_FORM_data1
+; CHECK-NEXT:       DW_IDX_die_offset: DW_FORM_ref4
+; CHECK-NEXT:     }
+; CHECK-NEXT:   ]
+; CHECK-NEXT:   Bucket 0 [
+; CHECK-NEXT:     Name 1 {
+; CHECK-NEXT:       Hash: 0xB888030
+; CHECK-NEXT:       String: {{.+}} "int"
+; CHECK-NEXT:       Entry @ {{.+}} {
+; CHECK-NEXT:         Abbrev: [[ABBREV]]
+; CHECK-NEXT:         Tag: DW_TAG_base_type
+; CHECK-NEXT:         DW_IDX_die_offset: 0x0000003e
+; CHECK-NEXT:       }
+; CHECK-NEXT:     }
+; CHECK-NEXT:   ]
+; CHECK-NEXT:   Bucket 1 [
+; CHECK-NEXT:     Name 2 {
+; CHECK-NEXT:       Hash: 0xB887389
+; CHECK-NEXT:       String: {{.+}} "Foo"
+; CHECK-NEXT:       Entry @ {{.+}} {
+; CHECK-NEXT:         Abbrev: [[ABBREV3]]
+; CHECK-NEXT:           Tag: DW_TAG_structure_type
+; CHECK-NEXT:           DW_IDX_type_unit: 0x00
+; CHECK-NEXT:           DW_IDX_die_offset: 0x00000023
+; CHECK-NEXT:       }
+; CHECK-NEXT:       Entry @ 0xaa {
+; CHECK-NEXT:         Abbrev: [[ABBREV1]]
+; CHECK-NEXT:         Tag: DW_TAG_structure_type
+; CHECK-NEXT:         DW_IDX_die_offset: 0x00000042
+; CHECK-NEXT:       }
+; CHECK-NEXT:     }
+; CHECK-NEXT:   ]
+; CHECK-NEXT:   Bucket 2 [
+; CHECK-NEXT:     Name 3 {
+; CHECK-NEXT:       Hash: 0x7C9A7F6A
+; CHECK-NEXT:       String: {{.+}} "main"
+; CHECK-NEXT:       Entry @ {{.+}} {
+; CHECK-NEXT:         Abbrev: [[ABBREV2]]
+; CHECK-NEXT:         Tag: DW_TAG_subprogram
+; CHECK-NEXT:         DW_IDX_die_offset: 0x00000023
+; CHECK-NEXT:       }
+; CHECK-NEXT:     }
+; CHECK-NEXT:   ]
+; CHECK-NEXT:   Bucket 3 [
+; CHECK-NEXT:     Name 4 {
+; CHECK-NEXT:       Hash: 0x7C952063
+; CHECK-NEXT:       String: {{.+}} "char"
+; CHECK-NEXT:       Entry @ {{.+}} {
+; CHECK-NEXT:         Abbrev: [[ABBREV4]]
+; CHECK-NEXT:           Tag: DW_TAG_base_type
+; CHECK-NEXT:           DW_IDX_type_unit: 0x00
+; CHECK-NEXT:           DW_IDX_die_offset: 0x00000038
+; CHECK-NEXT:       }
+; CHECK-NEXT:     }
+; CHECK-NEXT:   ]
+; CHECK-NEXT: }
+
+
+; ModuleID = 'main.cpp'
+source_filename = "main.cpp"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.Foo = type { ptr }
+
+; Function Attrs: mustprogress noinline norecurse nounwind optnone uwtable
+define dso_local noundef i32 @main() #0 !dbg !10 {
+entry:
+  %retval = alloca i32, align 4
+  %f = alloca %struct.Foo, align 8
+  store i32 0, ptr %retval, align 4
+  call void @llvm.dbg.declare(metadata ptr %f, metadata !15, metadata !DIExpression()), !dbg !21
+  ret i32 0, !dbg !22
+}
+
+; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+attributes #0 = { mustprogress noinline norecurse nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}
+!llvm.ident = !{!9}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 18.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false)
+!1 = !DIFile(filename: "main.cpp", directory: "/typeSmall", checksumkind: CSK_MD5, checksum: "e5b402e9dbafe24c7adbb087d1f03549")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 8, !"PIC Level", i32 2}
+!6 = !{i32 7, !"PIE Level", i32 2}
+!7 = !{i32 7, !"uwtable", i32 2}
+!8 = !{i32 7, !"frame-pointer", i32 2}
+!9 = !{!"clang version 18.0.0"}
+!10 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 4, type: !11, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14)
+!11 = !DISubroutineType(types: !12)
+!12 = !{!13}
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !{}
+!15 = !DILocalVariable(name: "f", scope: !10, file: !1, line: 5, type: !16)
+!16 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !1, line: 1, size: 64, flags: DIFlagTypePassByValue, elements: !17, identifier: "_ZTS3Foo")
+!17 = !{!18}
+!18 = !DIDerivedType(tag: DW_TAG_member, name: "c1", scope: !16, file: !1, line: 2, baseType: !19, size: 64)
+!19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !20, size: 64)
+!20 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!21 = !DILocation(line: 5, column: 6, scope: !10)
+!22 = !DILocation(line: 6, column: 2, scope: !10)
diff --git a/llvm/test/DebugInfo/X86/debug-names-types-split.ll b/llvm/test/DebugInfo/X86/debug-names-types-split.ll
new file mode 100644
index 000000000000000..d5908aeaf114a20
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/debug-names-types-split.ll
@@ -0,0 +1,57 @@
+; This checks that .debug_names is not generated with split-dwarf + -fdebug-type-sections.
+
+; RUN: llc -mtriple=x86_64 -generate-type-units -dwarf-version=5 -filetype=obj -split-dwarf-file=mainTypes.dwo --split-dwarf-output=mainTypes.dwo %s -o %t
+; RUN: llvm-readelf --sections %t | FileCheck %s
+
+; CHECK-NOT: .debug_names
+
+; ModuleID = 'main.cpp'
+source_filename = "main.cpp"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.Foo = type { ptr }
+
+; Function Attrs: mustprogress noinline norecurse nounwind optnone uwtable
+define dso_local noundef i32 @main() #0 !dbg !10 {
+entry:
+  %retval = alloca i32, align 4
+  %f = alloca %struct.Foo, align 8
+  store i32 0, ptr %retval, align 4
+  call void @llvm.dbg.declare(metadata ptr %f, metadata !15, metadata !DIExpression()), !dbg !21
+  ret i32 0, !dbg !22
+}
+
+; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+attributes #0 = { mustprogress noinline norecurse nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}
+!llvm.ident = !{!9}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 18.0.0 (ssh://git.vip.facebook.com/data/gitrepos/osmeta/external/llvm-project 680deb27e25976d9b74ad7b48ec5cb96be0e44b6)", isOptimized: false, runtimeVersion: 0, splitDebugFilename: "main.dwo", emissionKind: FullDebug, splitDebugInlining: false)
+!1 = !DIFile(filename: "main.cpp", directory: "/home/ayermolo/local/tasks/T138552329/typeSmallSplit", checksumkind: CSK_MD5, checksum: "e5b402e9dbafe24c7adbb087d1f03549")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 8, !"PIC Level", i32 2}
+!6 = !{i32 7, !"PIE Level", i32 2}
+!7 = !{i32 7, !"uwtable", i32 2}
+!8 = !{i32 7, !"frame-pointer", i32 2}
+!9 = !{!"clang version 18.0.0 (ssh://git.vip.facebook.com/data/gitrepos/osmeta/external/llvm-project 680deb27e25976d9b74ad7b48ec5cb96be0e44b6)"}
+!10 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 4, type: !11, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14)
+!11 = !DISubroutineType(types: !12)
+!12 = !{!13}
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !{}
+!15 = !DILocalVariable(name: "f", scope: !10, file: !1, line: 5, type: !16)
+!16 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !1, line: 1, size: 64, flags: DIFlagTypePassByValue, elements: !17, identifier: "_ZTS3Foo")
+!17 = !{!18}
+!18 = !DIDerivedType(tag: DW_TAG_member, name: "c1", scope: !16, file: !1, line: 2, baseType: !19, size: 64)
+!19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !20, size: 64)
+!20 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!21 = !DILocation(line: 5, column: 6, scope: !10)
+!22 = !DILocation(line: 6, column: 2, scope: !10)
diff --git a/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test b/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test
index 90f6818b8c8e5b0..3e4d90490931666 100644
--- a/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test
+++ b/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test
@@ -44,7 +44,7 @@ CHECK:.debug_abbrev contents:
 CHECK-NEXT: Abbrev table for offset: 0x00000000
 
 CHECK: .debug_info contents:
-CHECK: 0x00000000: Compile Unit: length = 0x0000004a, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = 0x0000, addr_size = 0x08 
+CHECK: 0x00000000: Compile Unit: length = 0x0000004a, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = 0x0000, addr_size = 0x08
 CHECK: DW_AT_producer [DW_FORM_strx]     (indexed (00000000) string = "Apple clang version 14.0.3 (clang-1403.0.22.14.1)")
 CHECK: DW_AT_name [DW_FORM_strx] (indexed (00000001) string = "a.cpp")
 CHECK: DW_AT_LLVM_sysroot [DW_FORM_strx] (indexed (00000002) string = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk")
@@ -59,12 +59,12 @@ CHECK-NEXT:  DW_AT_low_pc [DW_FORM_addrx]     (indexed (00000000) address = 0x[[
 CHECK: DW_AT_linkage_name [DW_FORM_strx]       (indexed (00000005) string = "_Z4foo2i")
 CHECK: DW_AT_name [DW_FORM_strx]       (indexed (00000006) string = "foo2")
 CHECK: 0x0000003c:     DW_TAG_formal_parameter [3]   (0x0000002c)
-CHECK-NEXT:                   DW_AT_location [DW_FORM_sec_offset]   (0x[[LOCLIST_OFFSET:[0-9a-f]+]]: 
+CHECK-NEXT:                   DW_AT_location [DW_FORM_sec_offset]   (0x[[LOCLIST_OFFSET:[0-9a-f]+]]:
 CHECK-NEXT:                      [0x[[#%.16x,LOCLIST_PAIR_START:]], 0x[[#%.16x,LOCLIST_PAIR_END:]]): [[LOCLIST_EXPR:.*]]
 CHECK-NEXT:                      [0x[[#%.16x,LOCLIST_PAIR_START2:]], 0x[[#%.16x,LOCLIST_PAIR_END2:]]): [[LOCLIST_EXPR2:.*]])
 CHECK: DW_AT_name [DW_FORM_strx]     (indexed (00000007) string = "a")
 
-CHECK: 0x0000004e: Compile Unit: length = 0x00000072, format = DWARF32, version = 0x0004, abbr_offset = 0x00{{00|5a}}, addr_size = 0x08 
+CHECK: 0x0000004e: Compile Unit: length = 0x00000072, format = DWARF32, version = 0x0004, abbr_offset = 0x00{{00|5a}}, addr_size = 0x08
 CHECK: DW_AT_producer [DW_FORM_strp]     ( .debug_str[0x00000001] = "Apple clang version 14.0.3 (clang-1403.0.22.14.1)")
 CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x000000e0] = "b.cpp")
 CHECK: DW_AT_LLVM_sysroot [DW_FORM_strp] ( .debug_str[0x00000039] = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk")
@@ -79,7 +79,7 @@ CHECK-NEXT:                DW_AT_low_pc [DW_FORM_addr]     (0x[[#%.16x,LOC_LOWPC
 CHECK: DW_AT_linkage_name [DW_FORM_strp]       ( .debug_str[0x000000e6] = "_Z3bari")
 CHECK: DW_AT_name [DW_FORM_strp]       ( .debug_str[0x000000ee] = "bar")
 CHECK: 0x0000009d:     DW_TAG_formal_parameter {{.*}}   (0x00000080)
-CHECK-NEXT:                  DW_AT_location [DW_FORM_sec_offset]   (0x[[LOC_OFFSET:[0-9a-f]+]]: 
+CHECK-NEXT:                  DW_AT_location [DW_FORM_sec_offset]   (0x[[LOC_OFFSET:[0-9a-f]+]]:
 CHECK-NEXT:                     [0x[[#%.16x,LOC_PAIR_START:]], 0x[[#%.16x,LOC_PAIR_END:]]): [[LOC_EXPR:.*]]
 CHECK-NEXT:                     [0x[[#%.16x,LOC_PAIR_START2:]], 0x[[#%.16x,LOC_PAIR_END2:]]): [[LOC_EXPR2:.*]])
 CHECK: DW_AT_name [DW_FORM_strp]     ( .debug_str[0x000000f2] = "x")
@@ -91,7 +91,7 @@ CHECK-NEXT:            (0x[[#sub(LOC_PAIR_START2,LOC_LOWPC)]], 0x[[#sub(LOC_PAIR
 
 CHECK: .debug_loclists contents:
 CHECK-NEXT: 0x00000000: locations list header: length = 0x00000018, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
-CHECK-NEXT: 0x[[LOCLIST_OFFSET]]: 
+CHECK-NEXT: 0x[[LOCLIST_OFFSET]]:
 CHECK-NEXT:            DW_LLE_base_addressx   (0x0000000000000000)
 CHECK-NEXT:            DW_LLE_offset_pair     (0x[[#sub(LOCLIST_PAIR_START,LOCLIST_LOWPC)]], 0x[[#sub(LOCLIST_PAIR_END,LOCLIST_LOWPC)]])
 CHECK-NEXT:            DW_LLE_offset_pair     (0x[[#sub(LOCLIST_PAIR_START2,LOCLIST_LOWPC)]], 0x[[#sub(LOCLIST_PAIR_END2,LOCLIST_LOWPC)]])
@@ -205,7 +205,7 @@ CHECK-NEXT: 0x00000028: 000000dc "int"
 CHECK: .debug_names contents:
 CHECK-NEXT: Name Index @ 0x0 {
 CHECK-NEXT:   Header {
-CHECK-NEXT:     Length: 0xBC
+CHECK-NEXT:     Length: 0xC4
 CHECK-NEXT:     Format: DWARF32
 CHECK-NEXT:     Version: 5
 CHECK-NEXT:     CU count: 2
@@ -213,6 +213,6 @@ CHECK-NEXT:     Local TU count: 0
 CHECK-NEXT:     Foreign TU count: 0
 CHECK-NEXT:     Bucket count: 5
 CHECK-NEXT:     Name count: 5
-CHECK-NEXT:     Abbreviations table size: 0x11
+CHECK-NEXT:     Abbreviations table size: 0x13
 CHECK-NEXT:     Augmentation: 'LLVM0700'
 CHECK-NEXT:   }

>From 2de7bd4a41bcc811c4314852e753ea7314bf9ade Mon Sep 17 00:00:00 2001
From: Alexander Yermolovich <ayermolo at meta.com>
Date: Fri, 27 Oct 2023 16:01:43 -0700
Subject: [PATCH 2/6] fixup! [LLVM][DWARF] Add support for monolithic types in
 .debug_names

---
 llvm/test/MC/WebAssembly/comdat-sections.ll | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/test/MC/WebAssembly/comdat-sections.ll b/llvm/test/MC/WebAssembly/comdat-sections.ll
index 8dc63e3c3f6fccd..05e66dfc89a12e6 100644
--- a/llvm/test/MC/WebAssembly/comdat-sections.ll
+++ b/llvm/test/MC/WebAssembly/comdat-sections.ll
@@ -17,6 +17,7 @@
 ; ASM: .section .debug_types,"G",@,4721183873463917179,comdat
 ; Here we are not trying to verify all of the debug info; just enough  to ensure
 ; that the section contains a type unit for a type with matching signature
+; ASM-NEXT: .Ltu_begin0:
 ; ASM-NEXT:	.int32	.Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
 ; ASM-NEXT: .Ldebug_info_start0:
 ; ASM-NEXT:	.int16	4                               # DWARF version number

>From 87d8c848e662035d543b3edcc3116c19877c004b Mon Sep 17 00:00:00 2001
From: Alexander Yermolovich <ayermolo at meta.com>
Date: Mon, 30 Oct 2023 13:48:18 -0700
Subject: [PATCH 3/6] fixup! fixup! [LLVM][DWARF] Add support for monolithic
 types in .debug_names

---
 llvm/lib/DWARFLinker/DWARFStreamer.cpp          | 2 +-
 llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/DWARFLinker/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
index 53a75f429880118..e088a0ec1f66ba1 100644
--- a/llvm/lib/DWARFLinker/DWARFStreamer.cpp
+++ b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
@@ -297,7 +297,7 @@ void DwarfStreamer::emitDebugNames(DWARF5AccelTable &Table) {
 
   // Build up data structures needed to emit this section.
   std::vector<std::variant<MCSymbol *, uint64_t>> CompUnits;
-  DenseMap<unsigned, size_t> UniqueIdToCuMap;
+  DenseMap<unsigned, unsigned> UniqueIdToCuMap;
   unsigned Id = 0;
   for (auto &CU : EmittedUnits) {
     CompUnits.push_back(CU.LabelBegin);
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.h b/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.h
index 1849442678d320b..d03336c1c11a364 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.h
+++ b/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.h
@@ -39,7 +39,7 @@ class MCCodeEmitter;
 namespace dwarflinker_parallel {
 
 using DebugNamesUnitsOffsets = std::vector<std::variant<MCSymbol *, uint64_t>>;
-using CompUnitIDToIdx = DenseMap<unsigned, size_t>;
+using CompUnitIDToIdx = DenseMap<unsigned, unsigned>;
 
 /// This class emits DWARF data to the output stream. It emits already
 /// generated section data and specific data, which could not be generated

>From c1ebc0fd70109bbd9945c250de258308a6ba6440 Mon Sep 17 00:00:00 2001
From: Alexander Yermolovich <ayermolo at meta.com>
Date: Mon, 30 Oct 2023 17:17:57 -0700
Subject: [PATCH 4/6] fixup! fixup! fixup! [LLVM][DWARF] Add support for
 monolithic types in .debug_names

---
 llvm/include/llvm/CodeGen/AccelTable.h        | 60 ++++++++++--------
 llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp    | 61 +++++++++++--------
 llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp    | 38 ++++++------
 llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h      | 39 +++++++++---
 llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp     |  4 --
 llvm/lib/CodeGen/AsmPrinter/DwarfFile.h       | 19 ------
 llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp     |  9 +--
 llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h       |  5 +-
 llvm/lib/DWARFLinker/DWARFStreamer.cpp        | 19 +++---
 .../DWARFLinkerParallel/DWARFEmitterImpl.cpp  |  6 +-
 10 files changed, 139 insertions(+), 121 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/AccelTable.h b/llvm/include/llvm/CodeGen/AccelTable.h
index d948b7d82b85979..02c1050b11274db 100644
--- a/llvm/include/llvm/CodeGen/AccelTable.h
+++ b/llvm/include/llvm/CodeGen/AccelTable.h
@@ -108,8 +108,6 @@ class DwarfDebug;
 class DwarfTypeUnit;
 class MCSymbol;
 class raw_ostream;
-struct TypeUnitMetaInfo;
-using TUVectorTy = SmallVector<TypeUnitMetaInfo, 1>;
 
 /// Interface which the different types of accelerator table data have to
 /// conform. It serves as a base class for different values of the template
@@ -265,11 +263,7 @@ class DWARF5AccelTableData : public AccelTableData {
                        const bool IsTU = false);
   DWARF5AccelTableData(const uint64_t DieOffset, const unsigned DieTag,
                        const unsigned Index, const bool IsTU = false)
-      : OffsetVal(DieOffset) {
-    Data.DieTag = DieTag;
-    Data.UnitID = Index;
-    Data.IsTU = IsTU;
-  }
+      : OffsetVal(DieOffset), DieTag(DieTag), UnitID(Index), IsTU(IsTU) {}
 
 #ifndef NDEBUG
   void print(raw_ostream &OS) const override;
@@ -280,9 +274,9 @@ class DWARF5AccelTableData : public AccelTableData {
            "Accessing DIE Offset before normalizing.");
     return std::get<uint64_t>(OffsetVal);
   }
-  unsigned getDieTag() const { return Data.DieTag; }
-  unsigned getUnitID() const { return Data.UnitID; }
-  bool isTU() const { return Data.IsTU; }
+  unsigned getDieTag() const { return DieTag; }
+  unsigned getUnitID() const { return UnitID; }
+  bool isTU() const { return IsTU; }
   void normalizeDIEToOffset() {
     assert(std::holds_alternative<const DIE *>(OffsetVal) &&
            "Accessing offset after normalizing.");
@@ -294,23 +288,38 @@ class DWARF5AccelTableData : public AccelTableData {
 
 protected:
   std::variant<const DIE *, uint64_t> OffsetVal;
-  struct MetaData {
-    uint32_t DieTag : 16;
-    uint32_t UnitID : 15;
-    uint32_t IsTU : 1;
-  } Data;
+  uint32_t DieTag : 16;
+  uint32_t UnitID : 15;
+  uint32_t IsTU : 1;
 
   uint64_t order() const override { return getDieOffset(); }
 };
 
+struct TypeUnitMetaInfo {
+  // Symbol for start of the TU section.
+  MCSymbol *Label;
+  // Unique ID of Type Unit.
+  unsigned UniqueID;
+};
+using TUVectorTy = SmallVector<TypeUnitMetaInfo, 1>;
 class DWARF5AccelTable : public AccelTable<DWARF5AccelTableData> {
+  // Symbols to start of all the TU sections that were generated.
+  TUVectorTy TUSymbols;
+
 public:
+  /// Returns type units that were constructed.
+  const TUVectorTy &getTypeUnitsSymbols() { return TUSymbols; }
+  /// Add a type unit start symbol.
+  void addTypeUnitSymbol(DwarfTypeUnit &U);
   /// Convert DIE entries to explicit offset.
   /// Needs to be called after DIE offsets are computed.
   void convertDieToOffset() {
     for (auto &Entry : Entries) {
       for (AccelTableData *Value : Entry.second.Values) {
         DWARF5AccelTableData *Data = static_cast<DWARF5AccelTableData *>(Value);
+        // For TU we normalize as each Unit is emitted.
+        // So when this is invoked after CU construction we will be in mixed
+        // state.
         if (!Data->isNormalized())
           Data->normalizeDIEToOffset();
       }
@@ -344,19 +353,22 @@ void emitAppleAccelTable(AsmPrinter *Asm, AccelTable<DataT> &Contents,
 
 void emitDWARF5AccelTable(AsmPrinter *Asm, DWARF5AccelTable &Contents,
                           const DwarfDebug &DD,
-                          ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs,
-                          TUVectorTy TUSymbols);
-using GetIndexForEntryReturnType =
-    std::optional<std::pair<unsigned, DWARF5AccelTableData::AttributeEncoding>>;
+                          ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs);
+
+struct DWARF5AccelTableEntry {
+  unsigned Index;
+  DWARF5AccelTableData::AttributeEncoding Endoding;
+};
+using DWARF5AccelTableEntryReturnType = std::optional<DWARF5AccelTableEntry>;
 /// Emit a DWARFv5 Accelerator Table consisting of entries in the specified
 /// AccelTable. The \p CUs contains either symbols keeping offsets to the
 /// start of compilation unit, either offsets to the start of compilation
 /// unit themselves.
-void emitDWARF5AccelTable(
-    AsmPrinter *Asm, DWARF5AccelTable &Contents,
-    ArrayRef<std::variant<MCSymbol *, uint64_t>> CUs,
-    llvm::function_ref<GetIndexForEntryReturnType(const DWARF5AccelTableData &)>
-        getIndexForEntry);
+void emitDWARF5AccelTable(AsmPrinter *Asm, DWARF5AccelTable &Contents,
+                          ArrayRef<std::variant<MCSymbol *, uint64_t>> CUs,
+                          llvm::function_ref<DWARF5AccelTableEntryReturnType(
+                              const DWARF5AccelTableData &)>
+                              getIndexForEntry);
 
 /// Accelerator table data implementation for simple Apple accelerator tables
 /// with just a DIE reference.
diff --git a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
index 90715a805cc5e41..441f9f356dd7f42 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
@@ -213,7 +213,7 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
       Abbreviations;
   ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits;
   ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits;
-  llvm::function_ref<GetIndexForEntryReturnType(const DataT &)>
+  llvm::function_ref<DWARF5AccelTableEntryReturnType(const DataT &)>
       getIndexForEntry;
   MCSymbol *ContributionEnd = nullptr;
   MCSymbol *AbbrevStart = Asm->createTempSymbol("names_abbrev_start");
@@ -235,7 +235,7 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
       AsmPrinter *Asm, const AccelTableBase &Contents,
       ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits,
       ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits,
-      llvm::function_ref<GetIndexForEntryReturnType(const DataT &)>
+      llvm::function_ref<DWARF5AccelTableEntryReturnType(const DataT &)>
           getIndexForEntry);
 
   void emit();
@@ -361,11 +361,8 @@ void AppleAccelTableWriter::emit() const {
 DWARF5AccelTableData::DWARF5AccelTableData(const DIE &Die,
                                            const DwarfUnit &Unit,
                                            const bool IsTU)
-    : OffsetVal(&Die) {
-  Data.DieTag = Die.getTag();
-  Data.UnitID = Unit.getUniqueID();
-  Data.IsTU = IsTU;
-}
+    : OffsetVal(&Die), DieTag(Die.getTag()), UnitID(Unit.getUniqueID()),
+      IsTU(IsTU) {}
 
 template <typename DataT>
 void Dwarf5AccelTableWriter<DataT>::Header::emit(Dwarf5AccelTableWriter &Ctx) {
@@ -401,12 +398,15 @@ static uint32_t constexpr LowerBitSize = dwarf::DW_IDX_type_hash;
 static uint32_t getTagFromAbbreviationTag(const uint32_t AbbrvTag) {
   return AbbrvTag >> LowerBitSize;
 }
+
+/// Constructs a unique AbbrevTag that captures what a DIE accesses.
+/// Using this tag we can emit a unique abbreviation for each DIE.
 static uint32_t
 constructAbbreviationTag(const unsigned Tag,
-                         const GetIndexForEntryReturnType &EntryRet) {
+                         const DWARF5AccelTableEntryReturnType &EntryRet) {
   uint32_t AbbrvTag = 0;
   if (EntryRet)
-    AbbrvTag |= 1 << EntryRet->second.Index;
+    AbbrvTag |= 1 << EntryRet->Endoding.Index;
   AbbrvTag |= 1 << dwarf::DW_IDX_die_offset;
   AbbrvTag |= Tag << LowerBitSize;
   return AbbrvTag;
@@ -416,14 +416,14 @@ void Dwarf5AccelTableWriter<DataT>::populateAbbrevsMap() {
   for (auto &Bucket : Contents.getBuckets()) {
     for (auto *Hash : Bucket) {
       for (auto *Value : Hash->Values) {
-        GetIndexForEntryReturnType EntryRet =
+        DWARF5AccelTableEntryReturnType EntryRet =
             getIndexForEntry(*static_cast<const DataT *>(Value));
         unsigned Tag = static_cast<const DataT *>(Value)->getDieTag();
         uint32_t AbbrvTag = constructAbbreviationTag(Tag, EntryRet);
         if (Abbreviations.count(AbbrvTag) == 0) {
           SmallVector<DWARF5AccelTableData::AttributeEncoding, 2> UA;
           if (EntryRet)
-            UA.push_back(EntryRet->second);
+            UA.push_back(EntryRet->Endoding);
           UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
           Abbreviations.try_emplace(AbbrvTag, UA);
         }
@@ -500,7 +500,7 @@ void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const {
 
 template <typename DataT>
 void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const {
-  GetIndexForEntryReturnType EntryRet = getIndexForEntry(Entry);
+  DWARF5AccelTableEntryReturnType EntryRet = getIndexForEntry(Entry);
   uint32_t AbbrvTag = constructAbbreviationTag(Entry.getDieTag(), EntryRet);
   auto AbbrevIt = Abbreviations.find(AbbrvTag);
   assert(AbbrevIt != Abbreviations.end() &&
@@ -514,7 +514,7 @@ void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const {
     switch (AttrEnc.Index) {
     case dwarf::DW_IDX_compile_unit:
     case dwarf::DW_IDX_type_unit: {
-      DIEInteger ID(EntryRet->first);
+      DIEInteger ID(EntryRet->Index);
       ID.emitValue(Asm, AttrEnc.Form);
       break;
     }
@@ -547,7 +547,7 @@ Dwarf5AccelTableWriter<DataT>::Dwarf5AccelTableWriter(
     AsmPrinter *Asm, const AccelTableBase &Contents,
     ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits,
     ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits,
-    llvm::function_ref<GetIndexForEntryReturnType(const DataT &)>
+    llvm::function_ref<DWARF5AccelTableEntryReturnType(const DataT &)>
         getIndexForEntry)
     : AccelTableWriter(Asm, Contents, false),
       Header(CompUnits.size(), TypeUnits.size(), Contents.getBucketCount(),
@@ -578,10 +578,10 @@ void llvm::emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents,
   AppleAccelTableWriter(Asm, Contents, Atoms, SecBegin).emit();
 }
 
-void llvm::emitDWARF5AccelTable(AsmPrinter *Asm, DWARF5AccelTable &Contents,
-                                const DwarfDebug &DD,
-                                ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs,
-                                TUVectorTy TUSymbols) {
+void llvm::emitDWARF5AccelTable(
+    AsmPrinter *Asm, DWARF5AccelTable &Contents, const DwarfDebug &DD,
+    ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) {
+  TUVectorTy TUSymbols = Contents.getTypeUnitsSymbols();
   std::vector<std::variant<MCSymbol *, uint64_t>> CompUnits;
   std::vector<std::variant<MCSymbol *, uint64_t>> TypeUnits;
   SmallVector<unsigned, 1> CUIndex(CUs.size());
@@ -621,23 +621,30 @@ void llvm::emitDWARF5AccelTable(AsmPrinter *Asm, DWARF5AccelTable &Contents,
       DIEInteger::BestForm(/*IsSigned*/ false, TypeUnits.size() - 1);
   Dwarf5AccelTableWriter<DWARF5AccelTableData>(
       Asm, Contents, CompUnits, TypeUnits,
-      [&](const DWARF5AccelTableData &Entry) -> GetIndexForEntryReturnType {
-        GetIndexForEntryReturnType Index = std::nullopt;
+      [&](const DWARF5AccelTableData &Entry)
+          -> DWARF5AccelTableEntryReturnType {
         if (Entry.isTU())
-          Index = {TUIndex[Entry.getUnitID()],
-                   {dwarf::DW_IDX_type_unit, TUIndexForm}};
-        else if (CUIndex.size() > 1)
-          Index = {CUIndex[Entry.getUnitID()],
-                   {dwarf::DW_IDX_compile_unit, CUIndexForm}};
-        return Index;
+          return std::optional<DWARF5AccelTableEntry>(
+              {TUIndex[Entry.getUnitID()],
+               {dwarf::DW_IDX_type_unit, TUIndexForm}});
+        if (CUIndex.size() > 1)
+          return std::optional<DWARF5AccelTableEntry>(
+              {CUIndex[Entry.getUnitID()],
+               {dwarf::DW_IDX_compile_unit, CUIndexForm}});
+        return std::nullopt;
       })
       .emit();
 }
 
+void DWARF5AccelTable::addTypeUnitSymbol(DwarfTypeUnit &U) {
+  TUSymbols.push_back({U.getLabelBegin(), U.getUniqueID()});
+}
+
 void llvm::emitDWARF5AccelTable(
     AsmPrinter *Asm, DWARF5AccelTable &Contents,
     ArrayRef<std::variant<MCSymbol *, uint64_t>> CUs,
-    llvm::function_ref<GetIndexForEntryReturnType(const DWARF5AccelTableData &)>
+    llvm::function_ref<
+        DWARF5AccelTableEntryReturnType(const DWARF5AccelTableData &)>
         getIndexForEntry) {
   std::vector<std::variant<MCSymbol *, uint64_t>> TypeUnits;
   Contents.finalize(Asm, "names");
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 3923ad61d825c8b..9321fdd512e59c8 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -312,7 +312,8 @@ static AccelTableKind computeAccelTableKind(unsigned DwarfVersion,
   if (AccelTables != AccelTableKind::Default)
     return AccelTables;
 
-  // Accelerator tables with type units are currently not supported.
+  // Generating DWARF5 acceleration table.
+  // Currently Split dwarf and non ELF format is not supported.
   if (GenerateTypeUnits &&
       (DwarfVersion < 5 || HasSplitDwarf || !TT.isOSBinFormatELF()))
     return AccelTableKind::None;
@@ -327,9 +328,6 @@ static AccelTableKind computeAccelTableKind(unsigned DwarfVersion,
                                    : AccelTableKind::Dwarf;
   return AccelTableKind::None;
 }
-void DwarfDebug::addTypeUnitSymbol(DwarfTypeUnit &U) {
-  InfoHolder.addTypeUnitSymbol(U);
-}
 
 DwarfDebug::DwarfDebug(AsmPrinter *A)
     : DebugHandlerBase(A), DebugLocs(A->OutStreamer->isVerboseAsm()),
@@ -2404,8 +2402,7 @@ void DwarfDebug::emitAccelDebugNames() {
   if (getUnits().empty())
     return;
 
-  emitDWARF5AccelTable(Asm, AccelDebugNames, *this, getUnits(),
-                       getTypeUnitsSymbols());
+  emitDWARF5AccelTable(Asm, AccelDebugNames, *this, getUnits());
 }
 
 // Emit visible names into a hashed accelerator table section.
@@ -3452,6 +3449,7 @@ uint64_t DwarfDebug::makeTypeSignature(StringRef Identifier) {
 void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
                                       StringRef Identifier, DIE &RefDie,
                                       const DICompositeType *CTy) {
+  setCurrentDWARF5AccelTable(DWARF5AccelTableKind::TU);
   // Fast path if we're building some type units and one has already used the
   // address pool we know we're going to throw away all this work anyway, so
   // don't bother building dependent types.
@@ -3467,8 +3465,8 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
   bool TopLevelType = TypeUnitsUnderConstruction.empty();
   AddrPool.resetUsedFlag();
 
-  auto OwnedUnit = std::make_unique<DwarfTypeUnit>(CU, Asm, this, &InfoHolder,
-                                                    getDwoLineTable(CU));
+  auto OwnedUnit = std::make_unique<DwarfTypeUnit>(
+      CU, Asm, this, &InfoHolder, NumTypeUnitsCreated++, getDwoLineTable(CU));
   DwarfTypeUnit &NewTU = *OwnedUnit;
   DIE &UnitDie = NewTU.getUnitDie();
   TypeUnitsUnderConstruction.emplace_back(std::move(OwnedUnit), CTy);
@@ -3510,7 +3508,7 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
     // Types referencing entries in the address table cannot be placed in type
     // units.
     if (AddrPool.hasBeenUsed()) {
-      AccelTypeUntsDebugNames.clear();
+      AccelTypeUnitsDebugNames.clear();
       // Remove all the types built while building this type.
       // This is pessimistic as some of these types might not be dependent on
       // the type that used an address.
@@ -3521,23 +3519,26 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
       // This is inefficient because all the dependent types will be rebuilt
       // from scratch, including building them in type units, discovering that
       // they depend on addresses, throwing them out and rebuilding them.
+      setCurrentDWARF5AccelTable(DWARF5AccelTableKind::CU);
       CU.constructTypeDIE(RefDie, cast<DICompositeType>(CTy));
       return;
     }
 
+    // If the type wasn't dependent on fission addresses, finish adding the type
+    // and all its dependent types.
     for (auto &TU : TypeUnitsToAdd) {
       InfoHolder.computeSizeAndOffsetsForUnit(TU.first.get());
       InfoHolder.emitUnit(TU.first.get(), useSplitDwarf());
       if (getDwarfVersion() >= 5 &&
-          getAccelTableKind() == AccelTableKind::Dwarf) {
-        addTypeUnitSymbol(*TU.first);
-        AccelTypeUntsDebugNames.convertDieToOffset();
-        AccelDebugNames.addTypeEntries(AccelTypeUntsDebugNames);
-        AccelTypeUntsDebugNames.clear();
-      }
+          getAccelTableKind() == AccelTableKind::Dwarf)
+        AccelDebugNames.addTypeUnitSymbol(*TU.first);
     }
+    AccelTypeUnitsDebugNames.convertDieToOffset();
+    AccelDebugNames.addTypeEntries(AccelTypeUnitsDebugNames);
+    AccelTypeUnitsDebugNames.clear();
   }
   CU.addDIETypeSignature(RefDie, Signature);
+  setCurrentDWARF5AccelTable(DWARF5AccelTableKind::CU);
 }
 
 // Add the Name along with its companion DIE to the appropriate accelerator
@@ -3564,14 +3565,15 @@ void DwarfDebug::addAccelNameImpl(const DICompileUnit &CU,
     AppleAccel.addName(Ref, Die);
     break;
   case AccelTableKind::Dwarf: {
+    DWARF5AccelTable &Current = getCurrentDWARF5AccelTable();
     // The type unit can be discarded, so need to add references to final
     // acceleration table once we know it's complete and we emit it.
-    if (TypeUnitsUnderConstruction.empty()) {
+    if (getCurrentAccelTableKind() == DWARF5AccelTableKind::CU) {
       DwarfCompileUnit *Unit = CUMap.lookup(&CU);
-      AccelDebugNames.addName(Ref, Die, *Unit);
+      Current.addName(Ref, Die, *Unit);
     } else {
       DwarfTypeUnit *Unit = TypeUnitsUnderConstruction.back().first.get();
-      AccelTypeUntsDebugNames.addName(Ref, Die, *Unit);
+      Current.addName(Ref, Die, *Unit);
     }
     break;
   }
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 66c87a68fa342ae..0a16365360edf48 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -408,6 +408,11 @@ class DwarfDebug : public DebugHandlerBase {
       std::pair<std::unique_ptr<DwarfTypeUnit>, const DICompositeType *>, 1>
       TypeUnitsUnderConstruction;
 
+  /// Used to set a uniqe ID for a Type Unit.
+  /// This counter represents number of DwarfTypeUnits created, not necessarily
+  /// number of type units that will be emitted.
+  unsigned NumTypeUnitsCreated = 0;
+
   /// Whether to use the GNU TLS opcode (instead of the standard opcode).
   bool UseGNUTLSOpcode;
 
@@ -448,6 +453,11 @@ class DwarfDebug : public DebugHandlerBase {
     Form,
   };
 
+  enum class DWARF5AccelTableKind {
+    CU = 0,
+    TU = 1,
+  };
+
 private:
   /// Force the use of DW_AT_ranges even for single-entry range lists.
   MinimizeAddrInV5 MinimizeAddr = MinimizeAddrInV5::Disabled;
@@ -496,11 +506,15 @@ class DwarfDebug : public DebugHandlerBase {
 
   /// Accelerator tables.
   DWARF5AccelTable AccelDebugNames;
-  DWARF5AccelTable AccelTypeUntsDebugNames;
+  DWARF5AccelTable AccelTypeUnitsDebugNames;
+  /// Used to hide which DWARF5AccelTable we are using now.
+  DWARF5AccelTable *CurrentDebugNames = &AccelDebugNames;
   AccelTable<AppleAccelTableOffsetData> AccelNames;
   AccelTable<AppleAccelTableOffsetData> AccelObjC;
   AccelTable<AppleAccelTableOffsetData> AccelNamespace;
   AccelTable<AppleAccelTableTypeData> AccelTypes;
+  /// The current DWARF5AccelTable being used.
+  DWARF5AccelTableKind CurrentAccelTableKind = DWARF5AccelTableKind::CU;
 
   /// Identify a debugger for "tuning" the debug info.
   ///
@@ -515,13 +529,6 @@ class DwarfDebug : public DebugHandlerBase {
     return InfoHolder.getUnits();
   }
 
-  /// Returns Type Units constructed for this module.
-  const TUVectorTy &getTypeUnitsSymbols() {
-    return InfoHolder.getTypeUnitsSymbols();
-  }
-
-  void addTypeUnitSymbol(DwarfTypeUnit &U);
-
   using InlinedEntity = DbgValueHistoryMap::InlinedEntity;
 
   void ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU,
@@ -908,6 +915,22 @@ class DwarfDebug : public DebugHandlerBase {
   MDNodeSet &getLocalDeclsForScope(const DILocalScope *S) {
     return LocalDeclsPerLS[S];
   }
+
+  /// Sets the current DWARF5AccelTable to use.
+  void setCurrentDWARF5AccelTable(const DWARF5AccelTableKind Kind) {
+    switch (Kind) {
+    case DWARF5AccelTableKind::CU:
+      CurrentDebugNames = &AccelDebugNames;
+      break;
+    case DWARF5AccelTableKind::TU:
+      CurrentDebugNames = &AccelTypeUnitsDebugNames;
+    }
+  }
+  /// Returns either CU or TU DWARF5AccelTable.
+  DWARF5AccelTable &getCurrentDWARF5AccelTable() { return *CurrentDebugNames; }
+  DWARF5AccelTableKind getCurrentAccelTableKind() const {
+    return CurrentAccelTableKind;
+  }
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp
index dd946426e8860f4..eab798c0da78438 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp
@@ -24,10 +24,6 @@ void DwarfFile::addUnit(std::unique_ptr<DwarfCompileUnit> U) {
   CUs.push_back(std::move(U));
 }
 
-void DwarfFile::addTypeUnitSymbol(DwarfTypeUnit &U) {
-  TUSymbols.emplace_back(U.getLabelBegin(), U.getUniqueID());
-}
-
 // Emit the various dwarf units to the unit section USection with
 // the abbreviations going into ASection.
 void DwarfFile::emitUnits(bool UseOffsets) {
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
index 6b48984b818c3d0..e10fd2b2642ac91 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
@@ -48,14 +48,6 @@ struct RangeSpanList {
   SmallVector<RangeSpan, 2> Ranges;
 };
 
-struct TypeUnitMetaInfo {
-  TypeUnitMetaInfo(MCSymbol *L, unsigned ID) : Label(L), UniqueID(ID) {}
-  // Symbol for start of the TU section.
-  MCSymbol *Label;
-  unsigned UniqueID;
-};
-using TUVectorTy = SmallVector<TypeUnitMetaInfo, 1>;
-
 class DwarfFile {
   // Target of Dwarf emission, used for sizing of abbreviations.
   AsmPrinter *Asm;
@@ -68,9 +60,6 @@ class DwarfFile {
   // A pointer to all units in the section.
   SmallVector<std::unique_ptr<DwarfCompileUnit>, 1> CUs;
 
-  // Symbols to start of all the TU sections that were generated.
-  TUVectorTy TUSymbols;
-
   DwarfStringPool StrPool;
 
   // List of range lists for a given compile unit, separate from the ranges for
@@ -115,9 +104,6 @@ class DwarfFile {
     return CUs;
   }
 
-  /// Returns type units that were constructed.
-  const TUVectorTy &getTypeUnitsSymbols() { return TUSymbols; }
-
   std::pair<uint32_t, RangeSpanList *> addRange(const DwarfCompileUnit &CU,
                                                 SmallVector<RangeSpan, 2> R);
 
@@ -139,11 +125,6 @@ class DwarfFile {
   /// Add a unit to the list of CUs.
   void addUnit(std::unique_ptr<DwarfCompileUnit> U);
 
-  /// Add a unit to the list of TUs.
-  /// Preserves type unit so that memory is not released before DWARF5
-  /// accelerator table is created.
-  void addTypeUnitSymbol(DwarfTypeUnit &U);
-
   /// Emit all of the units to the section listed with the given
   /// abbreviation section.
   void emitUnits(bool UseOffsets);
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index d095594655a05ea..0420bc442b0005c 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -83,14 +83,11 @@ DwarfUnit::DwarfUnit(dwarf::Tag UnitTag, const DICompileUnit *Node,
                      AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU)
     : DIEUnit(UnitTag), CUNode(Node), Asm(A), DD(DW), DU(DWU) {}
 
-unsigned DwarfTypeUnit::UniqueID = 0;
 DwarfTypeUnit::DwarfTypeUnit(DwarfCompileUnit &CU, AsmPrinter *A,
-                             DwarfDebug *DW, DwarfFile *DWU,
+                             DwarfDebug *DW, DwarfFile *DWU, unsigned UniqueID,
                              MCDwarfDwoLineTable *SplitLineTable)
-    : DwarfUnit(dwarf::DW_TAG_type_unit, CU.getCUNode(), A, DW, DWU), CU(CU),
-      SplitLineTable(SplitLineTable) {
-  ++DwarfTypeUnit::UniqueID;
-}
+    : DwarfUnit(dwarf::DW_TAG_type_unit, CU.getCUNode(), A, DW, DWU),
+      UniqueID(UniqueID), CU(CU), SplitLineTable(SplitLineTable) {}
 
 DwarfUnit::~DwarfUnit() {
   for (DIEBlock *B : DIEBlocks)
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
index 29c560a1cee0ff1..1ce0217c4bdd77a 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
@@ -361,7 +361,7 @@ class DwarfUnit : public DIEUnit {
 
 class DwarfTypeUnit final : public DwarfUnit {
   uint64_t TypeSignature;
-  static unsigned UniqueID;
+  unsigned UniqueID;
   const DIE *Ty;
   DwarfCompileUnit &CU;
   MCDwarfDwoLineTable *SplitLineTable;
@@ -375,7 +375,8 @@ class DwarfTypeUnit final : public DwarfUnit {
 
 public:
   DwarfTypeUnit(DwarfCompileUnit &CU, AsmPrinter *A, DwarfDebug *DW,
-                DwarfFile *DWU, MCDwarfDwoLineTable *SplitLineTable = nullptr);
+                DwarfFile *DWU, unsigned UniqueID,
+                MCDwarfDwoLineTable *SplitLineTable = nullptr);
 
   void setTypeSignature(uint64_t Signature) { TypeSignature = Signature; }
   /// Returns Type Signature.
diff --git a/llvm/lib/DWARFLinker/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
index e088a0ec1f66ba1..64639e8158a9661 100644
--- a/llvm/lib/DWARFLinker/DWARFStreamer.cpp
+++ b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
@@ -310,16 +310,15 @@ void DwarfStreamer::emitDebugNames(DWARF5AccelTable &Table) {
                                           (uint64_t)UniqueIdToCuMap.size() - 1);
   /// llvm-dwarfutil doesn't support type units + .debug_names right now anyway,
   /// so just keeping current behavior.
-  emitDWARF5AccelTable(
-      Asm.get(), Table, CompUnits,
-      [&UniqueIdToCuMap,
-       &Form](const DWARF5AccelTableData &Entry) -> GetIndexForEntryReturnType {
-        GetIndexForEntryReturnType Index = std::nullopt;
-        if (UniqueIdToCuMap.size() > 1)
-          Index = {UniqueIdToCuMap[Entry.getUnitID()],
-                   {dwarf::DW_IDX_compile_unit, Form}};
-        return Index;
-      });
+  emitDWARF5AccelTable(Asm.get(), Table, CompUnits,
+                       [&](const DWARF5AccelTableData &Entry)
+                           -> DWARF5AccelTableEntryReturnType {
+                         if (UniqueIdToCuMap.size() > 1)
+                           return std::optional<DWARF5AccelTableEntry>(
+                               {UniqueIdToCuMap[Entry.getUnitID()],
+                                {dwarf::DW_IDX_compile_unit, Form}});
+                         return std::nullopt;
+                       });
 }
 
 void DwarfStreamer::emitAppleNamespaces(
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp b/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp
index 00b2437efdf9073..22dd67971fce05e 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp
+++ b/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp
@@ -235,9 +235,9 @@ void DwarfEmitterImpl::emitDebugNames(DWARF5AccelTable &Table,
   /// DWARFLinker doesn't support type units + .debug_names right now anyway,
   /// so just keeping current behavior.
   emitDWARF5AccelTable(Asm.get(), Table, CUOffsets,
-                       [&CUidToIdx, &Form](const DWARF5AccelTableData &Entry)
-                           -> GetIndexForEntryReturnType {
-                         GetIndexForEntryReturnType Index = std::nullopt;
+                       [&](const DWARF5AccelTableData &Entry)
+                           -> DWARF5AccelTableEntryReturnType {
+                         DWARF5AccelTableEntryReturnType Index = std::nullopt;
                          if (CUidToIdx.size() > 1)
                            Index = {CUidToIdx[Entry.getUnitID()],
                                     {dwarf::DW_IDX_compile_unit, Form}};

>From 3d9485759330c36d03d2f8334a2e83977e4e4ab9 Mon Sep 17 00:00:00 2001
From: Alexander Yermolovich <ayermolo at meta.com>
Date: Tue, 31 Oct 2023 10:07:31 -0700
Subject: [PATCH 5/6] fixup! fixup! fixup! fixup! [LLVM][DWARF] Add support for
 monolithic types in .debug_names

---
 llvm/test/DebugInfo/X86/debug-names-types-monolithic.ll | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/test/DebugInfo/X86/debug-names-types-monolithic.ll b/llvm/test/DebugInfo/X86/debug-names-types-monolithic.ll
index 84f8ff0d4d9050a..af7a9a0663bb8a8 100644
--- a/llvm/test/DebugInfo/X86/debug-names-types-monolithic.ll
+++ b/llvm/test/DebugInfo/X86/debug-names-types-monolithic.ll
@@ -1,3 +1,4 @@
+; UNSUPPORTED: system-windows
 ; This checks that .debug_names can be generated with monolithic -fdebug-type-sections.
 
 ; RUN: llc -mtriple=x86_64 -generate-type-units -dwarf-version=5 -filetype=obj %s -o %t

>From b6a1bdfee88f4e7ad4e487118af8485ddf47d29f Mon Sep 17 00:00:00 2001
From: Alexander Yermolovich <ayermolo at meta.com>
Date: Thu, 2 Nov 2023 15:55:47 -0700
Subject: [PATCH 6/6] fixup! fixup! fixup! fixup! fixup! [LLVM][DWARF] Add
 support for monolithic types in .debug_names

---
 llvm/include/llvm/CodeGen/AccelTable.h        | 18 +++---
 llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp    | 15 ++---
 .../CodeGen/AsmPrinter/DwarfCompileUnit.cpp   |  2 +-
 .../lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 11 ----
 llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp    |  4 +-
 llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp     | 10 ++--
 llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h       | 29 +++++-----
 llvm/lib/DWARFLinker/DWARFStreamer.cpp        | 10 ++--
 .../DWARFLinkerParallel/DWARFEmitterImpl.cpp  |  7 +--
 .../DebugInfo/X86/debug-names-types-split.ll  | 57 -------------------
 ...pes-monolithic.ll => debug-names-types.ll} |  7 ++-
 .../ARM/dwarf5-dwarf4-combination-macho.test  | 10 ++--
 12 files changed, 58 insertions(+), 122 deletions(-)
 delete mode 100644 llvm/test/DebugInfo/X86/debug-names-types-split.ll
 rename llvm/test/DebugInfo/X86/{debug-names-types-monolithic.ll => debug-names-types.ll} (95%)

diff --git a/llvm/include/llvm/CodeGen/AccelTable.h b/llvm/include/llvm/CodeGen/AccelTable.h
index 02c1050b11274db..100bb8e89be7a39 100644
--- a/llvm/include/llvm/CodeGen/AccelTable.h
+++ b/llvm/include/llvm/CodeGen/AccelTable.h
@@ -257,13 +257,14 @@ class DWARF5AccelTableData : public AccelTableData {
     dwarf::Index Index;
     dwarf::Form Form;
   };
+
   static uint32_t hash(StringRef Name) { return caseFoldingDjbHash(Name); }
 
-  DWARF5AccelTableData(const DIE &Die, const DwarfUnit &CU,
+  DWARF5AccelTableData(const DIE &Die, const uint32_t UnitID,
                        const bool IsTU = false);
   DWARF5AccelTableData(const uint64_t DieOffset, const unsigned DieTag,
-                       const unsigned Index, const bool IsTU = false)
-      : OffsetVal(DieOffset), DieTag(DieTag), UnitID(Index), IsTU(IsTU) {}
+                       const unsigned UnitID, const bool IsTU = false)
+      : OffsetVal(DieOffset), DieTag(DieTag), UnitID(UnitID), IsTU(IsTU) {}
 
 #ifndef NDEBUG
   void print(raw_ostream &OS) const override;
@@ -307,6 +308,10 @@ class DWARF5AccelTable : public AccelTable<DWARF5AccelTableData> {
   TUVectorTy TUSymbols;
 
 public:
+  struct UnitIndexAndEncoding {
+    unsigned Index;
+    DWARF5AccelTableData::AttributeEncoding Endoding;
+  };
   /// Returns type units that were constructed.
   const TUVectorTy &getTypeUnitsSymbols() { return TUSymbols; }
   /// Add a type unit start symbol.
@@ -355,11 +360,8 @@ void emitDWARF5AccelTable(AsmPrinter *Asm, DWARF5AccelTable &Contents,
                           const DwarfDebug &DD,
                           ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs);
 
-struct DWARF5AccelTableEntry {
-  unsigned Index;
-  DWARF5AccelTableData::AttributeEncoding Endoding;
-};
-using DWARF5AccelTableEntryReturnType = std::optional<DWARF5AccelTableEntry>;
+using DWARF5AccelTableEntryReturnType =
+    std::optional<DWARF5AccelTable::UnitIndexAndEncoding>;
 /// Emit a DWARFv5 Accelerator Table consisting of entries in the specified
 /// AccelTable. The \p CUs contains either symbols keeping offsets to the
 /// start of compilation unit, either offsets to the start of compilation
diff --git a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
index 441f9f356dd7f42..94793d1f9884d7c 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
@@ -359,10 +359,9 @@ void AppleAccelTableWriter::emit() const {
 }
 
 DWARF5AccelTableData::DWARF5AccelTableData(const DIE &Die,
-                                           const DwarfUnit &Unit,
+                                           const uint32_t UnitID,
                                            const bool IsTU)
-    : OffsetVal(&Die), DieTag(Die.getTag()), UnitID(Unit.getUniqueID()),
-      IsTU(IsTU) {}
+    : OffsetVal(&Die), DieTag(Die.getTag()), UnitID(UnitID), IsTU(IsTU) {}
 
 template <typename DataT>
 void Dwarf5AccelTableWriter<DataT>::Header::emit(Dwarf5AccelTableWriter &Ctx) {
@@ -624,13 +623,11 @@ void llvm::emitDWARF5AccelTable(
       [&](const DWARF5AccelTableData &Entry)
           -> DWARF5AccelTableEntryReturnType {
         if (Entry.isTU())
-          return std::optional<DWARF5AccelTableEntry>(
-              {TUIndex[Entry.getUnitID()],
-               {dwarf::DW_IDX_type_unit, TUIndexForm}});
+          return {{TUIndex[Entry.getUnitID()],
+                   {dwarf::DW_IDX_type_unit, TUIndexForm}}};
         if (CUIndex.size() > 1)
-          return std::optional<DWARF5AccelTableEntry>(
-              {CUIndex[Entry.getUnitID()],
-               {dwarf::DW_IDX_compile_unit, CUIndexForm}});
+          return {{CUIndex[Entry.getUnitID()],
+                   {dwarf::DW_IDX_compile_unit, CUIndexForm}}};
         return std::nullopt;
       })
       .emit();
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 42bf755737506b4..9c538e781b45ef7 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -58,7 +58,7 @@ static dwarf::Tag GetCompileUnitType(UnitKind Kind, DwarfDebug *DW) {
 DwarfCompileUnit::DwarfCompileUnit(unsigned UID, const DICompileUnit *Node,
                                    AsmPrinter *A, DwarfDebug *DW,
                                    DwarfFile *DWU, UnitKind Kind)
-    : DwarfUnit(GetCompileUnitType(Kind, DW), Node, A, DW, DWU), UniqueID(UID) {
+    : DwarfUnit(GetCompileUnitType(Kind, DW), Node, A, DW, DWU, UID) {
   insertDIE(Node, &getUnitDie());
   MacroLabelBegin = Asm->createTempSymbol("cu_macro_begin");
 }
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
index 70dbd8e17c933ed..2faa057f46073c1 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
@@ -44,8 +44,6 @@ class MDNode;
 enum class UnitKind { Skeleton, Full };
 
 class DwarfCompileUnit final : public DwarfUnit {
-  /// A numeric ID unique among all CUs in the module
-  unsigned UniqueID;
   bool HasRangeLists = false;
 
   /// The start of the unit line section, this is also
@@ -55,9 +53,6 @@ class DwarfCompileUnit final : public DwarfUnit {
   /// Skeleton unit associated with this unit.
   DwarfCompileUnit *Skeleton = nullptr;
 
-  /// The start of the unit within its section.
-  MCSymbol *LabelBegin = nullptr;
-
   /// The start of the unit macro info within macro section.
   MCSymbol *MacroLabelBegin;
 
@@ -151,7 +146,6 @@ class DwarfCompileUnit final : public DwarfUnit {
                    UnitKind Kind = UnitKind::Full);
 
   bool hasRangeLists() const { return HasRangeLists; }
-  unsigned getUniqueID() const override { return UniqueID; }
 
   DwarfCompileUnit *getSkeleton() const {
     return Skeleton;
@@ -330,11 +324,6 @@ class DwarfCompileUnit final : public DwarfUnit {
   /// Add the DW_AT_addr_base attribute to the unit DIE.
   void addAddrTableBase();
 
-  MCSymbol *getLabelBegin() const {
-    assert(LabelBegin && "LabelBegin is not initialized");
-    return LabelBegin;
-  }
-
   MCSymbol *getMacroLabelBegin() const {
     return MacroLabelBegin;
   }
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 9321fdd512e59c8..887d9faca64f04d 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -3570,10 +3570,10 @@ void DwarfDebug::addAccelNameImpl(const DICompileUnit &CU,
     // acceleration table once we know it's complete and we emit it.
     if (getCurrentAccelTableKind() == DWARF5AccelTableKind::CU) {
       DwarfCompileUnit *Unit = CUMap.lookup(&CU);
-      Current.addName(Ref, Die, *Unit);
+      Current.addName(Ref, Die, Unit->getUniqueID());
     } else {
       DwarfTypeUnit *Unit = TypeUnitsUnderConstruction.back().first.get();
-      Current.addName(Ref, Die, *Unit);
+      Current.addName(Ref, Die, Unit->getUniqueID());
     }
     break;
   }
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 0420bc442b0005c..9b042c89696f5b5 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -80,14 +80,16 @@ bool DIEDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI,
 }
 
 DwarfUnit::DwarfUnit(dwarf::Tag UnitTag, const DICompileUnit *Node,
-                     AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU)
-    : DIEUnit(UnitTag), CUNode(Node), Asm(A), DD(DW), DU(DWU) {}
+                     AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU,
+                     unsigned UniqueID)
+    : DIEUnit(UnitTag), UniqueID(UniqueID), CUNode(Node), Asm(A), DD(DW),
+      DU(DWU) {}
 
 DwarfTypeUnit::DwarfTypeUnit(DwarfCompileUnit &CU, AsmPrinter *A,
                              DwarfDebug *DW, DwarfFile *DWU, unsigned UniqueID,
                              MCDwarfDwoLineTable *SplitLineTable)
-    : DwarfUnit(dwarf::DW_TAG_type_unit, CU.getCUNode(), A, DW, DWU),
-      UniqueID(UniqueID), CU(CU), SplitLineTable(SplitLineTable) {}
+    : DwarfUnit(dwarf::DW_TAG_type_unit, CU.getCUNode(), A, DW, DWU, UniqueID),
+      CU(CU), SplitLineTable(SplitLineTable) {}
 
 DwarfUnit::~DwarfUnit() {
   for (DIEBlock *B : DIEBlocks)
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
index 1ce0217c4bdd77a..18f50f86ec87a1a 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
@@ -34,6 +34,8 @@ class MCSymbol;
 /// source file.
 class DwarfUnit : public DIEUnit {
 protected:
+  /// A numeric ID unique among all CUs in the module
+  unsigned UniqueID;
   /// MDNode for the compile unit.
   const DICompileUnit *CUNode;
 
@@ -43,6 +45,9 @@ class DwarfUnit : public DIEUnit {
   /// Target of Dwarf emission.
   AsmPrinter *Asm;
 
+  /// The start of the unit within its section.
+  MCSymbol *LabelBegin = nullptr;
+
   /// Emitted at the end of the CU and used to compute the CU Length field.
   MCSymbol *EndLabel = nullptr;
 
@@ -68,8 +73,8 @@ class DwarfUnit : public DIEUnit {
   /// corresponds to the MDNode mapped with the subprogram DIE.
   DenseMap<DIE *, const DINode *> ContainingTypeMap;
 
-  DwarfUnit(dwarf::Tag, const DICompileUnit *Node, AsmPrinter *A, DwarfDebug *DW,
-            DwarfFile *DWU);
+  DwarfUnit(dwarf::Tag, const DICompileUnit *Node, AsmPrinter *A,
+            DwarfDebug *DW, DwarfFile *DWU, unsigned UniqueID = 0);
 
   bool applySubprogramDefinitionAttributes(const DISubprogram *SP, DIE &SPDie, bool Minimal);
 
@@ -92,8 +97,15 @@ class DwarfUnit : public DIEUnit {
   }
 
 public:
+  /// Gets Unique ID for this unit.
+  unsigned getUniqueID() const { return UniqueID; }
   // Accessors.
   AsmPrinter* getAsmPrinter() const { return Asm; }
+  /// Get the the symbol for start of the section for this unit.
+  MCSymbol *getLabelBegin() const {
+    assert(LabelBegin && "LabelBegin is not initialized");
+    return LabelBegin;
+  }
   MCSymbol *getEndLabel() const { return EndLabel; }
   uint16_t getLanguage() const { return CUNode->getSourceLanguage(); }
   const DICompileUnit *getCUNode() const { return CUNode; }
@@ -301,9 +313,6 @@ class DwarfUnit : public DIEUnit {
   /// Get context owner's DIE.
   DIE *createTypeDIE(const DICompositeType *Ty);
 
-  /// Returns a unique ID.
-  virtual unsigned getUniqueID() const = 0;
-
 protected:
   ~DwarfUnit();
 
@@ -361,13 +370,10 @@ class DwarfUnit : public DIEUnit {
 
 class DwarfTypeUnit final : public DwarfUnit {
   uint64_t TypeSignature;
-  unsigned UniqueID;
   const DIE *Ty;
   DwarfCompileUnit &CU;
   MCDwarfDwoLineTable *SplitLineTable;
   bool UsedLineTable = false;
-  /// The start of the type unit within .debug_nfo section.
-  MCSymbol *LabelBegin = nullptr;
 
   unsigned getOrCreateSourceID(const DIFile *File) override;
   void finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) override;
@@ -394,13 +400,6 @@ class DwarfTypeUnit final : public DwarfUnit {
   void addGlobalType(const DIType *Ty, const DIE &Die,
                      const DIScope *Context) override;
   DwarfCompileUnit &getCU() override { return CU; }
-  /// Get the the symbol for start of the section for this type unit.
-  MCSymbol *getLabelBegin() const {
-    assert(LabelBegin && "LabelBegin is not initialized");
-    return LabelBegin;
-  }
-
-  unsigned getUniqueID() const override { return UniqueID; }
 };
 } // end llvm namespace
 #endif
diff --git a/llvm/lib/DWARFLinker/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
index 64639e8158a9661..d756a4fba7a7460 100644
--- a/llvm/lib/DWARFLinker/DWARFStreamer.cpp
+++ b/llvm/lib/DWARFLinker/DWARFStreamer.cpp
@@ -308,15 +308,15 @@ void DwarfStreamer::emitDebugNames(DWARF5AccelTable &Table) {
   Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());
   dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false,
                                           (uint64_t)UniqueIdToCuMap.size() - 1);
-  /// llvm-dwarfutil doesn't support type units + .debug_names right now anyway,
-  /// so just keeping current behavior.
+  /// llvm-dwarfutil doesn't support type units + .debug_names right now.
+  // FIXME: add support for type units + .debug_names. For now the behavior is
+  // unsuported.
   emitDWARF5AccelTable(Asm.get(), Table, CompUnits,
                        [&](const DWARF5AccelTableData &Entry)
                            -> DWARF5AccelTableEntryReturnType {
                          if (UniqueIdToCuMap.size() > 1)
-                           return std::optional<DWARF5AccelTableEntry>(
-                               {UniqueIdToCuMap[Entry.getUnitID()],
-                                {dwarf::DW_IDX_compile_unit, Form}});
+                           return {{UniqueIdToCuMap[Entry.getUnitID()],
+                                    {dwarf::DW_IDX_compile_unit, Form}}};
                          return std::nullopt;
                        });
 }
diff --git a/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp b/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp
index 22dd67971fce05e..056a546f560ebd8 100644
--- a/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp
+++ b/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp
@@ -237,11 +237,10 @@ void DwarfEmitterImpl::emitDebugNames(DWARF5AccelTable &Table,
   emitDWARF5AccelTable(Asm.get(), Table, CUOffsets,
                        [&](const DWARF5AccelTableData &Entry)
                            -> DWARF5AccelTableEntryReturnType {
-                         DWARF5AccelTableEntryReturnType Index = std::nullopt;
                          if (CUidToIdx.size() > 1)
-                           Index = {CUidToIdx[Entry.getUnitID()],
-                                    {dwarf::DW_IDX_compile_unit, Form}};
-                         return Index;
+                           return {{CUidToIdx[Entry.getUnitID()],
+                                    {dwarf::DW_IDX_compile_unit, Form}}};
+                         return std::nullopt;
                        });
 }
 
diff --git a/llvm/test/DebugInfo/X86/debug-names-types-split.ll b/llvm/test/DebugInfo/X86/debug-names-types-split.ll
deleted file mode 100644
index d5908aeaf114a20..000000000000000
--- a/llvm/test/DebugInfo/X86/debug-names-types-split.ll
+++ /dev/null
@@ -1,57 +0,0 @@
-; This checks that .debug_names is not generated with split-dwarf + -fdebug-type-sections.
-
-; RUN: llc -mtriple=x86_64 -generate-type-units -dwarf-version=5 -filetype=obj -split-dwarf-file=mainTypes.dwo --split-dwarf-output=mainTypes.dwo %s -o %t
-; RUN: llvm-readelf --sections %t | FileCheck %s
-
-; CHECK-NOT: .debug_names
-
-; ModuleID = 'main.cpp'
-source_filename = "main.cpp"
-target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-linux-gnu"
-
-%struct.Foo = type { ptr }
-
-; Function Attrs: mustprogress noinline norecurse nounwind optnone uwtable
-define dso_local noundef i32 @main() #0 !dbg !10 {
-entry:
-  %retval = alloca i32, align 4
-  %f = alloca %struct.Foo, align 8
-  store i32 0, ptr %retval, align 4
-  call void @llvm.dbg.declare(metadata ptr %f, metadata !15, metadata !DIExpression()), !dbg !21
-  ret i32 0, !dbg !22
-}
-
-; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
-declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
-
-attributes #0 = { mustprogress noinline norecurse nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
-attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}
-!llvm.ident = !{!9}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 18.0.0 (ssh://git.vip.facebook.com/data/gitrepos/osmeta/external/llvm-project 680deb27e25976d9b74ad7b48ec5cb96be0e44b6)", isOptimized: false, runtimeVersion: 0, splitDebugFilename: "main.dwo", emissionKind: FullDebug, splitDebugInlining: false)
-!1 = !DIFile(filename: "main.cpp", directory: "/home/ayermolo/local/tasks/T138552329/typeSmallSplit", checksumkind: CSK_MD5, checksum: "e5b402e9dbafe24c7adbb087d1f03549")
-!2 = !{i32 7, !"Dwarf Version", i32 5}
-!3 = !{i32 2, !"Debug Info Version", i32 3}
-!4 = !{i32 1, !"wchar_size", i32 4}
-!5 = !{i32 8, !"PIC Level", i32 2}
-!6 = !{i32 7, !"PIE Level", i32 2}
-!7 = !{i32 7, !"uwtable", i32 2}
-!8 = !{i32 7, !"frame-pointer", i32 2}
-!9 = !{!"clang version 18.0.0 (ssh://git.vip.facebook.com/data/gitrepos/osmeta/external/llvm-project 680deb27e25976d9b74ad7b48ec5cb96be0e44b6)"}
-!10 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 4, type: !11, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14)
-!11 = !DISubroutineType(types: !12)
-!12 = !{!13}
-!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!14 = !{}
-!15 = !DILocalVariable(name: "f", scope: !10, file: !1, line: 5, type: !16)
-!16 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !1, line: 1, size: 64, flags: DIFlagTypePassByValue, elements: !17, identifier: "_ZTS3Foo")
-!17 = !{!18}
-!18 = !DIDerivedType(tag: DW_TAG_member, name: "c1", scope: !16, file: !1, line: 2, baseType: !19, size: 64)
-!19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !20, size: 64)
-!20 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
-!21 = !DILocation(line: 5, column: 6, scope: !10)
-!22 = !DILocation(line: 6, column: 2, scope: !10)
diff --git a/llvm/test/DebugInfo/X86/debug-names-types-monolithic.ll b/llvm/test/DebugInfo/X86/debug-names-types.ll
similarity index 95%
rename from llvm/test/DebugInfo/X86/debug-names-types-monolithic.ll
rename to llvm/test/DebugInfo/X86/debug-names-types.ll
index af7a9a0663bb8a8..ba4e4a5d7c15c80 100644
--- a/llvm/test/DebugInfo/X86/debug-names-types-monolithic.ll
+++ b/llvm/test/DebugInfo/X86/debug-names-types.ll
@@ -1,9 +1,14 @@
 ; UNSUPPORTED: system-windows
-; This checks that .debug_names can be generated with monolithic -fdebug-type-sections.
+; This checks that .debug_names can be generated with monolithic -fdebug-type-sections, and does not generate when split-dwarf is enabled.
 
 ; RUN: llc -mtriple=x86_64 -generate-type-units -dwarf-version=5 -filetype=obj %s -o %t
 ; RUN: llvm-dwarfdump -debug-info -debug-names %t | FileCheck %s
 
+; RUN: llc -mtriple=x86_64 -generate-type-units -dwarf-version=5 -filetype=obj -split-dwarf-file=mainTypes.dwo --split-dwarf-output=mainTypes.dwo %s -o %t
+; RUN: llvm-readelf --sections %t | FileCheck %s --check-prefixes=CHECK-SPLIT
+
+; CHECK-SPLIT-NOT: .debug_names
+
 ; CHECK:     .debug_info contents:
 ; CHECK:      DW_TAG_type_unit
 ; CHECK-NEXT:   DW_AT_language  (DW_LANG_C_plus_plus_14)
diff --git a/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test b/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test
index 3e4d90490931666..2f1f026dfe288f2 100644
--- a/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test
+++ b/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test
@@ -44,7 +44,7 @@ CHECK:.debug_abbrev contents:
 CHECK-NEXT: Abbrev table for offset: 0x00000000
 
 CHECK: .debug_info contents:
-CHECK: 0x00000000: Compile Unit: length = 0x0000004a, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = 0x0000, addr_size = 0x08
+CHECK: 0x00000000: Compile Unit: length = 0x0000004a, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = 0x0000, addr_size = 0x08 
 CHECK: DW_AT_producer [DW_FORM_strx]     (indexed (00000000) string = "Apple clang version 14.0.3 (clang-1403.0.22.14.1)")
 CHECK: DW_AT_name [DW_FORM_strx] (indexed (00000001) string = "a.cpp")
 CHECK: DW_AT_LLVM_sysroot [DW_FORM_strx] (indexed (00000002) string = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk")
@@ -59,12 +59,12 @@ CHECK-NEXT:  DW_AT_low_pc [DW_FORM_addrx]     (indexed (00000000) address = 0x[[
 CHECK: DW_AT_linkage_name [DW_FORM_strx]       (indexed (00000005) string = "_Z4foo2i")
 CHECK: DW_AT_name [DW_FORM_strx]       (indexed (00000006) string = "foo2")
 CHECK: 0x0000003c:     DW_TAG_formal_parameter [3]   (0x0000002c)
-CHECK-NEXT:                   DW_AT_location [DW_FORM_sec_offset]   (0x[[LOCLIST_OFFSET:[0-9a-f]+]]:
+CHECK-NEXT:                   DW_AT_location [DW_FORM_sec_offset]   (0x[[LOCLIST_OFFSET:[0-9a-f]+]]: 
 CHECK-NEXT:                      [0x[[#%.16x,LOCLIST_PAIR_START:]], 0x[[#%.16x,LOCLIST_PAIR_END:]]): [[LOCLIST_EXPR:.*]]
 CHECK-NEXT:                      [0x[[#%.16x,LOCLIST_PAIR_START2:]], 0x[[#%.16x,LOCLIST_PAIR_END2:]]): [[LOCLIST_EXPR2:.*]])
 CHECK: DW_AT_name [DW_FORM_strx]     (indexed (00000007) string = "a")
 
-CHECK: 0x0000004e: Compile Unit: length = 0x00000072, format = DWARF32, version = 0x0004, abbr_offset = 0x00{{00|5a}}, addr_size = 0x08
+CHECK: 0x0000004e: Compile Unit: length = 0x00000072, format = DWARF32, version = 0x0004, abbr_offset = 0x00{{00|5a}}, addr_size = 0x08 
 CHECK: DW_AT_producer [DW_FORM_strp]     ( .debug_str[0x00000001] = "Apple clang version 14.0.3 (clang-1403.0.22.14.1)")
 CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x000000e0] = "b.cpp")
 CHECK: DW_AT_LLVM_sysroot [DW_FORM_strp] ( .debug_str[0x00000039] = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk")
@@ -79,7 +79,7 @@ CHECK-NEXT:                DW_AT_low_pc [DW_FORM_addr]     (0x[[#%.16x,LOC_LOWPC
 CHECK: DW_AT_linkage_name [DW_FORM_strp]       ( .debug_str[0x000000e6] = "_Z3bari")
 CHECK: DW_AT_name [DW_FORM_strp]       ( .debug_str[0x000000ee] = "bar")
 CHECK: 0x0000009d:     DW_TAG_formal_parameter {{.*}}   (0x00000080)
-CHECK-NEXT:                  DW_AT_location [DW_FORM_sec_offset]   (0x[[LOC_OFFSET:[0-9a-f]+]]:
+CHECK-NEXT:                  DW_AT_location [DW_FORM_sec_offset]   (0x[[LOC_OFFSET:[0-9a-f]+]]:  
 CHECK-NEXT:                     [0x[[#%.16x,LOC_PAIR_START:]], 0x[[#%.16x,LOC_PAIR_END:]]): [[LOC_EXPR:.*]]
 CHECK-NEXT:                     [0x[[#%.16x,LOC_PAIR_START2:]], 0x[[#%.16x,LOC_PAIR_END2:]]): [[LOC_EXPR2:.*]])
 CHECK: DW_AT_name [DW_FORM_strp]     ( .debug_str[0x000000f2] = "x")
@@ -91,7 +91,7 @@ CHECK-NEXT:            (0x[[#sub(LOC_PAIR_START2,LOC_LOWPC)]], 0x[[#sub(LOC_PAIR
 
 CHECK: .debug_loclists contents:
 CHECK-NEXT: 0x00000000: locations list header: length = 0x00000018, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
-CHECK-NEXT: 0x[[LOCLIST_OFFSET]]:
+CHECK-NEXT: 0x[[LOCLIST_OFFSET]]: 
 CHECK-NEXT:            DW_LLE_base_addressx   (0x0000000000000000)
 CHECK-NEXT:            DW_LLE_offset_pair     (0x[[#sub(LOCLIST_PAIR_START,LOCLIST_LOWPC)]], 0x[[#sub(LOCLIST_PAIR_END,LOCLIST_LOWPC)]])
 CHECK-NEXT:            DW_LLE_offset_pair     (0x[[#sub(LOCLIST_PAIR_START2,LOCLIST_LOWPC)]], 0x[[#sub(LOCLIST_PAIR_END2,LOCLIST_LOWPC)]])



More information about the llvm-commits mailing list