diff options
author | Alexander Yermolovich <43973793+ayermolo@users.noreply.github.com> | 2023-11-18 06:36:33 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-18 06:36:33 -0800 |
commit | b00e2f2a5f3e48fbbe2324b0b371e5657ccd969c (patch) | |
tree | ac51444f85b2da96cc6285b7c1059820ccac7561 | |
parent | f9974f7fe15a9e97ceb7514d437bef6ee46ccc38 (diff) | |
download | llvm-b00e2f2a5f3e48fbbe2324b0b371e5657ccd969c.zip llvm-b00e2f2a5f3e48fbbe2324b0b371e5657ccd969c.tar.gz llvm-b00e2f2a5f3e48fbbe2324b0b371e5657ccd969c.tar.bz2 |
[LLVM][DWARF] Add support for monolithic types in .debug_names (#70515)
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.
-rw-r--r-- | llvm/include/llvm/CodeGen/AccelTable.h | 69 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp | 175 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 17 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 11 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 96 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h | 59 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfFile.h | 1 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 25 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h | 21 | ||||
-rw-r--r-- | llvm/lib/DWARFLinker/DWARFStreamer.cpp | 20 | ||||
-rw-r--r-- | llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp | 17 | ||||
-rw-r--r-- | llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.h | 2 | ||||
-rw-r--r-- | llvm/test/DebugInfo/X86/accel-tables-dwarf5.ll | 1 | ||||
-rw-r--r-- | llvm/test/DebugInfo/X86/debug-names-dwarf64.ll | 8 | ||||
-rw-r--r-- | llvm/test/DebugInfo/X86/debug-names-types.ll | 170 | ||||
-rw-r--r-- | llvm/test/MC/WebAssembly/comdat-sections.ll | 1 | ||||
-rw-r--r-- | llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test | 4 |
17 files changed, 536 insertions, 161 deletions
diff --git a/llvm/include/llvm/CodeGen/AccelTable.h b/llvm/include/llvm/CodeGen/AccelTable.h index d4e21b2..6a69a01 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,8 +103,9 @@ namespace llvm { class AsmPrinter; -class DwarfCompileUnit; +class DwarfUnit; class DwarfDebug; +class DwarfTypeUnit; class MCSymbol; class raw_ostream; @@ -197,6 +197,9 @@ public: 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 +253,18 @@ public: /// 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 uint32_t UnitID, + const bool IsTU = false); + DWARF5AccelTableData(const uint64_t DieOffset, const unsigned DieTag, + const unsigned UnitID, const bool IsTU = false) + : OffsetVal(DieOffset), DieTag(DieTag), UnitID(UnitID), IsTU(IsTU) {} #ifndef NDEBUG void print(raw_ostream &OS) const override; @@ -267,28 +277,66 @@ public: } 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."); 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; + 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: + struct UnitIndexAndEncoding { + unsigned Index; + DWARF5AccelTableData::AttributeEncoding Endoding; + }; + /// 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) { - static_cast<DWARF5AccelTableData *>(Value)->normalizeDIEToOffset(); + 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(); + } + } + } + + 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); } } } @@ -319,8 +367,9 @@ 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<std::optional<DWARF5AccelTable::UnitIndexAndEncoding>( + 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 e393951..60c5468 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,31 @@ 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<std::optional<DWARF5AccelTable::UnitIndexAndEncoding>( + 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 +235,10 @@ public: 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< + std::optional<DWARF5AccelTable::UnitIndexAndEncoding>(const DataT &)> + getIndexForEntry); void emit(); }; @@ -358,8 +361,9 @@ void AppleAccelTableWriter::emit() const { } DWARF5AccelTableData::DWARF5AccelTableData(const DIE &Die, - const DwarfCompileUnit &CU) - : OffsetVal(&Die), DieTag(Die.getTag()), UnitID(CU.getUniqueID()) {} + const uint32_t UnitID, + const bool IsTU) + : OffsetVal(&Die), DieTag(Die.getTag()), UnitID(UnitID), IsTU(IsTU) {} template <typename DataT> void Dwarf5AccelTableWriter<DataT>::Header::emit(Dwarf5AccelTableWriter &Ctx) { @@ -391,31 +395,42 @@ 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; +} + +/// 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 std::optional<DWARF5AccelTable::UnitIndexAndEncoding> &EntryRet) { + uint32_t AbbrvTag = 0; + if (EntryRet) + AbbrvTag |= 1 << EntryRet->Endoding.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) { + std::optional<DWARF5AccelTable::UnitIndexAndEncoding> 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->Endoding); + 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> @@ -430,6 +445,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; for (const auto &Bucket : enumerate(Contents.getBuckets())) { @@ -456,10 +482,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 +501,22 @@ void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const { template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const { - auto AbbrevIt = Abbreviations.find(Entry.getDieTag()); + std::optional<DWARF5AccelTable::UnitIndexAndEncoding> 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->Index); ID.emitValue(Asm, AttrEnc.Form); break; } @@ -515,22 +548,22 @@ 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< + std::optional<DWARF5AccelTable::UnitIndexAndEncoding>(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(); @@ -551,9 +584,13 @@ void llvm::emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents, 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()); - 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 +599,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,22 +618,39 @@ 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) + -> std::optional<DWARF5AccelTable::UnitIndexAndEncoding> { + if (Entry.isTU()) + return {{TUIndex[Entry.getUnitID()], + {dwarf::DW_IDX_type_unit, TUIndexForm}}}; + if (CUIndex.size() > 1) + return {{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<unsigned(const DWARF5AccelTableData &)> - getCUIndexForEntry) { + llvm::function_ref<std::optional<DWARF5AccelTable::UnitIndexAndEncoding>( + 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.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index feb5ab6..14f2a36 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"); } @@ -367,13 +367,15 @@ void DwarfCompileUnit::addLocationAttribute( addLinkageName(*VariableDIE, GV->getLinkageName()); if (addToAccelTable) { - DD->addAccelName(*CUNode, GV->getName(), *VariableDIE); + DD->addAccelName(*this, CUNode->getNameTableKind(), GV->getName(), + *VariableDIE); // If the linkage name is different than the name, go ahead and output // that as well into the name table. if (GV->getLinkageName() != "" && GV->getName() != GV->getLinkageName() && DD->useAllLinkageNames()) - DD->addAccelName(*CUNode, GV->getLinkageName(), *VariableDIE); + DD->addAccelName(*this, CUNode->getNameTableKind(), GV->getLinkageName(), + *VariableDIE); } } @@ -561,7 +563,7 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) { // Add name to the name table, we do this here because we're guaranteed // to have concrete versions of our DW_TAG_subprogram nodes. - DD->addSubprogramNames(*CUNode, SP, *SPDie); + DD->addSubprogramNames(*this, CUNode->getNameTableKind(), SP, *SPDie); return *SPDie; } @@ -710,7 +712,8 @@ DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope, // Add name to the name table, we do this here because we're guaranteed // to have concrete versions of our DW_TAG_inlined_subprogram nodes. - DD->addSubprogramNames(*CUNode, InlinedSP, *ScopeDIE); + DD->addSubprogramNames(*this, CUNode->getNameTableKind(), InlinedSP, + *ScopeDIE); return ScopeDIE; } @@ -1358,7 +1361,7 @@ DIE *DwarfCompileUnit::constructImportedEntityDIE( // or `using namespace std::ranges`, we could add the // import declaration into the accelerator table with the // name being the one of the entity being imported. - DD->addAccelNamespace(*CUNode, Name, *IMDie); + DD->addAccelNamespace(*this, CUNode->getNameTableKind(), Name, *IMDie); } // This is for imported module with renamed entities (such as variables and @@ -1433,7 +1436,7 @@ void DwarfCompileUnit::finishEntityDefinition(const DbgEntity *Entity) { // A TAG_label with a name and an AT_low_pc must be placed in debug_names. if (StringRef Name = Label->getName(); !Name.empty()) - getDwarfDebug().addAccelName(*CUNode, Name, *Die); + getDwarfDebug().addAccelName(*this, CUNode->getNameTableKind(), Name, *Die); } DbgEntity *DwarfCompileUnit::getExistingAbstractEntity(const DINode *Node) { diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 453dcc1..2faa057 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 @@ public: UnitKind Kind = UnitKind::Full); bool hasRangeLists() const { return HasRangeLists; } - unsigned getUniqueID() const { return UniqueID; } DwarfCompileUnit *getSkeleton() const { return Skeleton; @@ -330,11 +324,6 @@ public: /// 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 cc19c1a..f311931 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -305,14 +305,17 @@ 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. if (AccelTables != AccelTableKind::Default) return AccelTables; - // Accelerator tables with type units are currently not supported. - if (GenerateTypeUnits) + // Generating DWARF5 acceleration table. + // Currently Split dwarf and non ELF format is not supported. + if (GenerateTypeUnits && + (DwarfVersion < 5 || HasSplitDwarf || !TT.isOSBinFormatELF())) return AccelTableKind::None; // Accelerator tables get emitted if targetting DWARF v5 or LLDB. DWARF v5 @@ -400,8 +403,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 @@ -472,36 +476,38 @@ static StringRef getObjCMethodName(StringRef In) { } // Add the various names to the Dwarf accelerator table names. -void DwarfDebug::addSubprogramNames(const DICompileUnit &CU, - const DISubprogram *SP, DIE &Die) { +void DwarfDebug::addSubprogramNames( + const DwarfUnit &Unit, + const DICompileUnit::DebugNameTableKind NameTableKind, + const DISubprogram *SP, DIE &Die) { if (getAccelTableKind() != AccelTableKind::Apple && - CU.getNameTableKind() != DICompileUnit::DebugNameTableKind::Apple && - CU.getNameTableKind() == DICompileUnit::DebugNameTableKind::None) + NameTableKind != DICompileUnit::DebugNameTableKind::Apple && + NameTableKind == DICompileUnit::DebugNameTableKind::None) return; if (!SP->isDefinition()) return; if (SP->getName() != "") - addAccelName(CU, SP->getName(), Die); + addAccelName(Unit, NameTableKind, SP->getName(), Die); // If the linkage name is different than the name, go ahead and output that as // well into the name table. Only do that if we are going to actually emit // that name. if (SP->getLinkageName() != "" && SP->getName() != SP->getLinkageName() && (useAllLinkageNames() || InfoHolder.getAbstractScopeDIEs().lookup(SP))) - addAccelName(CU, SP->getLinkageName(), Die); + addAccelName(Unit, NameTableKind, SP->getLinkageName(), Die); // If this is an Objective-C selector name add it to the ObjC accelerator // too. if (isObjCClass(SP->getName())) { StringRef Class, Category; getObjCClassCategory(SP->getName(), Class, Category); - addAccelObjC(CU, Class, Die); + addAccelObjC(Unit, NameTableKind, Class, Die); if (Category != "") - addAccelObjC(CU, Category, Die); + addAccelObjC(Unit, NameTableKind, Category, Die); // Also add the base method name to the name table. - addAccelName(CU, getObjCMethodName(SP->getName()), Die); + addAccelName(Unit, NameTableKind, getObjCMethodName(SP->getName()), Die); } } @@ -3445,6 +3451,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. @@ -3460,8 +3467,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); @@ -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()) { - + 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. @@ -3514,6 +3521,7 @@ 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; } @@ -3523,9 +3531,16 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, for (auto &TU : TypeUnitsToAdd) { InfoHolder.computeSizeAndOffsetsForUnit(TU.first.get()); InfoHolder.emitUnit(TU.first.get(), useSplitDwarf()); + if (getDwarfVersion() >= 5 && + 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 @@ -3533,15 +3548,16 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, // AccelTableKind::Apple, we use the table we got as an argument). If // accelerator tables are disabled, this function does nothing. template <typename DataT> -void DwarfDebug::addAccelNameImpl(const DICompileUnit &CU, - AccelTable<DataT> &AppleAccel, StringRef Name, - const DIE &Die) { +void DwarfDebug::addAccelNameImpl( + const DwarfUnit &Unit, + const DICompileUnit::DebugNameTableKind NameTableKind, + AccelTable<DataT> &AppleAccel, StringRef Name, const DIE &Die) { if (getAccelTableKind() == AccelTableKind::None || Name.empty()) return; if (getAccelTableKind() != AccelTableKind::Apple && - CU.getNameTableKind() != DICompileUnit::DebugNameTableKind::Apple && - CU.getNameTableKind() != DICompileUnit::DebugNameTableKind::Default) + NameTableKind != DICompileUnit::DebugNameTableKind::Apple && + NameTableKind != DICompileUnit::DebugNameTableKind::Default) return; DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; @@ -3552,8 +3568,10 @@ void DwarfDebug::addAccelNameImpl(const DICompileUnit &CU, AppleAccel.addName(Ref, Die); break; case AccelTableKind::Dwarf: { - DwarfCompileUnit *DCU = CUMap.lookup(&CU); - AccelDebugNames.addName(Ref, Die, *DCU); + 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. + Current.addName(Ref, Die, Unit.getUniqueID()); break; } case AccelTableKind::Default: @@ -3563,26 +3581,34 @@ void DwarfDebug::addAccelNameImpl(const DICompileUnit &CU, } } -void DwarfDebug::addAccelName(const DICompileUnit &CU, StringRef Name, - const DIE &Die) { - addAccelNameImpl(CU, AccelNames, Name, Die); +void DwarfDebug::addAccelName( + const DwarfUnit &Unit, + const DICompileUnit::DebugNameTableKind NameTableKind, StringRef Name, + const DIE &Die) { + addAccelNameImpl(Unit, NameTableKind, AccelNames, Name, Die); } -void DwarfDebug::addAccelObjC(const DICompileUnit &CU, StringRef Name, - const DIE &Die) { +void DwarfDebug::addAccelObjC( + const DwarfUnit &Unit, + const DICompileUnit::DebugNameTableKind NameTableKind, StringRef Name, + const DIE &Die) { // ObjC names go only into the Apple accelerator tables. if (getAccelTableKind() == AccelTableKind::Apple) - addAccelNameImpl(CU, AccelObjC, Name, Die); + addAccelNameImpl(Unit, NameTableKind, AccelObjC, Name, Die); } -void DwarfDebug::addAccelNamespace(const DICompileUnit &CU, StringRef Name, - const DIE &Die) { - addAccelNameImpl(CU, AccelNamespace, Name, Die); +void DwarfDebug::addAccelNamespace( + const DwarfUnit &Unit, + const DICompileUnit::DebugNameTableKind NameTableKind, StringRef Name, + const DIE &Die) { + addAccelNameImpl(Unit, NameTableKind, AccelNamespace, Name, Die); } -void DwarfDebug::addAccelType(const DICompileUnit &CU, StringRef Name, - const DIE &Die, char Flags) { - addAccelNameImpl(CU, AccelTypes, Name, Die); +void DwarfDebug::addAccelType( + const DwarfUnit &Unit, + const DICompileUnit::DebugNameTableKind NameTableKind, StringRef Name, + const DIE &Die, char Flags) { + addAccelNameImpl(Unit, NameTableKind, AccelTypes, Name, Die); } uint16_t DwarfDebug::getDwarfVersion() const { diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h index b41d2be..452485b 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" @@ -409,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; @@ -449,6 +453,11 @@ public: 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; @@ -497,6 +506,9 @@ private: /// Accelerator tables. DWARF5AccelTable AccelDebugNames; + DWARF5AccelTable AccelTypeUnitsDebugNames; + /// Used to hide which DWARF5AccelTable we are using now. + DWARF5AccelTable *CurrentDebugNames = &AccelDebugNames; AccelTable<AppleAccelTableOffsetData> AccelNames; AccelTable<AppleAccelTableOffsetData> AccelObjC; AccelTable<AppleAccelTableOffsetData> AccelNamespace; @@ -535,8 +547,10 @@ private: DIE &ScopeDIE, const MachineFunction &MF); template <typename DataT> - void addAccelNameImpl(const DICompileUnit &CU, AccelTable<DataT> &AppleAccel, - StringRef Name, const DIE &Die); + void addAccelNameImpl(const DwarfUnit &Unit, + const DICompileUnit::DebugNameTableKind NameTableKind, + AccelTable<DataT> &AppleAccel, StringRef Name, + const DIE &Die); void finishEntityDefinitions(); @@ -780,6 +794,9 @@ public: /// 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; } @@ -837,20 +854,27 @@ public: void emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry, const DwarfCompileUnit *CU); - void addSubprogramNames(const DICompileUnit &CU, const DISubprogram *SP, - DIE &Die); + void addSubprogramNames(const DwarfUnit &Unit, + const DICompileUnit::DebugNameTableKind NameTableKind, + const DISubprogram *SP, DIE &Die); AddressPool &getAddressPool() { return AddrPool; } - void addAccelName(const DICompileUnit &CU, StringRef Name, const DIE &Die); + void addAccelName(const DwarfUnit &Unit, + const DICompileUnit::DebugNameTableKind NameTableKind, + StringRef Name, const DIE &Die); - void addAccelObjC(const DICompileUnit &CU, StringRef Name, const DIE &Die); + void addAccelObjC(const DwarfUnit &Unit, + const DICompileUnit::DebugNameTableKind NameTableKind, + StringRef Name, const DIE &Die); - void addAccelNamespace(const DICompileUnit &CU, StringRef Name, - const DIE &Die); + void addAccelNamespace(const DwarfUnit &Unit, + const DICompileUnit::DebugNameTableKind NameTableKind, + StringRef Name, const DIE &Die); - void addAccelType(const DICompileUnit &CU, StringRef Name, const DIE &Die, - char Flags); + void addAccelType(const DwarfUnit &Unit, + const DICompileUnit::DebugNameTableKind NameTableKind, + StringRef Name, const DIE &Die, char Flags); const MachineFunction *getCurrentFunction() const { return CurFn; } @@ -898,6 +922,19 @@ public: 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; } }; } // end namespace llvm diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h index f76858f..e10fd2b 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; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index a5960a5..d462859 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -80,15 +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, + DwarfDebug *DW, DwarfFile *DWU, unsigned UniqueID, MCDwarfDwoLineTable *SplitLineTable) - : DwarfUnit(dwarf::DW_TAG_type_unit, CU.getCUNode(), A, DW, DWU), 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) @@ -639,7 +640,8 @@ void DwarfUnit::updateAcceleratorTables(const DIScope *Context, IsImplementation = CT->getRuntimeLang() == 0 || CT->isObjcClassComplete(); } unsigned Flags = IsImplementation ? dwarf::DW_FLAG_type_implementation : 0; - DD->addAccelType(*CUNode, Ty->getName(), TyDIE, Flags); + DD->addAccelType(*this, CUNode->getNameTableKind(), Ty->getName(), TyDIE, + Flags); if (!Context || isa<DICompileUnit>(Context) || isa<DIFile>(Context) || isa<DINamespace>(Context) || isa<DICommonBlock>(Context)) @@ -1111,7 +1113,7 @@ DIE *DwarfUnit::getOrCreateNameSpace(const DINamespace *NS) { addString(NDie, dwarf::DW_AT_name, NS->getName()); else Name = "(anonymous namespace)"; - DD->addAccelNamespace(*CUNode, Name, NDie); + DD->addAccelNamespace(*this, CUNode->getNameTableKind(), Name, NDie); addGlobalName(Name, NDie, NS->getScope()); if (NS->getExportSymbols()) addFlag(NDie, dwarf::DW_AT_export_symbols); @@ -1438,7 +1440,8 @@ DIE *DwarfUnit::getIndexTyDie() { addUInt(*IndexTyDie, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, dwarf::getArrayIndexTypeEncoding( (dwarf::SourceLanguage)getLanguage())); - DD->addAccelType(*CUNode, Name, *IndexTyDie, /*Flags*/ 0); + DD->addAccelType(*this, CUNode->getNameTableKind(), Name, *IndexTyDie, + /*Flags*/ 0); return IndexTyDie; } @@ -1777,6 +1780,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 8f17e94..18f50f8 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 @@ protected: /// 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 @@ protected: /// 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 @@ protected: } 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; } @@ -369,9 +381,12 @@ 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. + 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. diff --git a/llvm/lib/DWARFLinker/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/DWARFStreamer.cpp index 2c6aba7..cd649c3 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); @@ -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. + // FIXME: add support for type units + .debug_names. For now the behavior is + // unsuported. + emitDWARF5AccelTable( + Asm.get(), Table, CompUnits, + [&](const DWARF5AccelTableData &Entry) + -> std::optional<DWARF5AccelTable::UnitIndexAndEncoding> { + if (UniqueIdToCuMap.size() > 1) + return {{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 88038824..355cfae 100644 --- a/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp +++ b/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp @@ -230,10 +230,19 @@ void DwarfEmitterImpl::emitDebugNames(DWARF5AccelTable &Table, return; Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection()); - emitDWARF5AccelTable(Asm.get(), Table, CUOffsets, - [&CUidToIdx](const DWARF5AccelTableData &Entry) { - return CUidToIdx[Entry.getUnitID()]; - }); + dwarf::Form Form = + DIEInteger::BestForm(/*IsSigned*/ false, (uint64_t)CUidToIdx.size() - 1); + // FIXME: add support for type units + .debug_names. For now the behavior is + // unsuported. + emitDWARF5AccelTable( + Asm.get(), Table, CUOffsets, + [&](const DWARF5AccelTableData &Entry) + -> std::optional<DWARF5AccelTable::UnitIndexAndEncoding> { + if (CUidToIdx.size() > 1) + return {{CUidToIdx[Entry.getUnitID()], + {dwarf::DW_IDX_compile_unit, Form}}}; + return std::nullopt; + }); } void DwarfEmitterImpl::emitAppleNamespaces( diff --git a/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.h b/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.h index 1849442..d03336c 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 diff --git a/llvm/test/DebugInfo/X86/accel-tables-dwarf5.ll b/llvm/test/DebugInfo/X86/accel-tables-dwarf5.ll index e7cf796..243dea6 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 e5fd6be..b94bdbc 100644 --- a/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll +++ b/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll @@ -30,6 +30,10 @@ ; CHECK-NEXT: CU[0]: 0x00000000 ; CHECK-NEXT: ] ; CHECK-NEXT: Abbreviations [ +; 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 @@ -42,10 +46,6 @@ ; CHECK-NEXT: Tag: DW_TAG_label ; 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: ] ; CHECK-NEXT: Bucket 0 [ ; CHECK-NEXT: Name 1 { diff --git a/llvm/test/DebugInfo/X86/debug-names-types.ll b/llvm/test/DebugInfo/X86/debug-names-types.ll new file mode 100644 index 0000000..59d18f1 --- /dev/null +++ b/llvm/test/DebugInfo/X86/debug-names-types.ll @@ -0,0 +1,170 @@ +; UNSUPPORTED: system-windows +; This checks that .debug_names can be generated with monolithic -fdebug-type-sections, and does not generate when split-dwarf is enabled. +; Generated with: clang++ main.cpp -g2 -gdwarf-5 -gpubnames -fdebug-types-section + +; 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) +; 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/MC/WebAssembly/comdat-sections.ll b/llvm/test/MC/WebAssembly/comdat-sections.ll index 8dc63e3..05e66df 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 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 90f6818..324a156 100644 --- a/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test +++ b/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test @@ -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: } |