diff --git a/llvm/include/llvm/CodeGen/AccelTable.h b/llvm/include/llvm/CodeGen/AccelTable.h index e6a661696354b..6ee817a7124dc 100644 --- a/llvm/include/llvm/CodeGen/AccelTable.h +++ b/llvm/include/llvm/CodeGen/AccelTable.h @@ -275,11 +275,6 @@ struct DenseMapInfo : DenseMapInfo {}; /// 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 uint32_t UnitID, @@ -289,7 +284,7 @@ class DWARF5AccelTableData : public AccelTableData { const unsigned DieTag, const unsigned UnitID, const bool IsTU = false) : OffsetVal(DieOffset), ParentOffset(DefiningParentOffset), - DieTag(DieTag), UnitID(UnitID), IsTU(IsTU) {} + DieTag(DieTag), AbbrevNumber(0), IsTU(IsTU), UnitID(UnitID) {} #ifndef NDEBUG void print(raw_ostream &OS) const override; @@ -330,6 +325,12 @@ class DWARF5AccelTableData : public AccelTableData { return OffsetAndUnitID(*ParentOffset, getUnitID()); } + /// Sets AbbrevIndex for an Entry. + void setAbbrevNumber(uint16_t AbbrevNum) { AbbrevNumber = AbbrevNum; } + + /// Returns AbbrevIndex for an Entry. + uint16_t getAbbrevNumber() const { return AbbrevNumber; } + /// If `Die` has a non-null parent and the parent is not a declaration, /// return its offset. static std::optional getDefiningParentDieOffset(const DIE &Die); @@ -338,12 +339,42 @@ class DWARF5AccelTableData : public AccelTableData { std::variant OffsetVal; std::optional ParentOffset; uint32_t DieTag : 16; - uint32_t UnitID : 15; + uint32_t AbbrevNumber : 15; uint32_t IsTU : 1; - + uint32_t UnitID; uint64_t order() const override { return getDieOffset(); } }; +class DebugNamesAbbrev : public FoldingSetNode { +public: + uint32_t DieTag; + uint32_t Number; + struct AttributeEncoding { + dwarf::Index Index; + dwarf::Form Form; + }; + DebugNamesAbbrev(uint32_t DieTag) : DieTag(DieTag) {} + /// Add attribute encoding to an abbreviation. + void addAttribute(const DebugNamesAbbrev::AttributeEncoding &Attr) { + AttrVect.push_back(Attr); + } + /// Set abbreviation tag index. + void setNumber(uint32_t AbbrevNumber) { Number = AbbrevNumber; } + /// Get abbreviation tag index. + uint32_t getNumber() const { return Number; } + /// Get DIE Tag. + uint32_t getDieTag() const { return DieTag; } + /// Used to gather unique data for the abbreviation folding set. + void Profile(FoldingSetNodeID &ID) const; + /// Returns attributes for an abbreviation. + const SmallVector &getAttributes() const { + return AttrVect; + } + +private: + SmallVector AttrVect; +}; + struct TypeUnitMetaInfo { // Symbol for start of the TU section or signature if this is SplitDwarf. std::variant LabelOrSignature; @@ -358,7 +389,7 @@ class DWARF5AccelTable : public AccelTable { public: struct UnitIndexAndEncoding { unsigned Index; - DWARF5AccelTableData::AttributeEncoding Encoding; + DebugNamesAbbrev::AttributeEncoding Encoding; }; /// Returns type units that were constructed. const TUVectorTy &getTypeUnitsSymbols() { return TUSymbolsOrHashes; } diff --git a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp index 1024aabf2ab0f..230d7add6d37c 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp @@ -208,8 +208,13 @@ class Dwarf5AccelTableWriter : public AccelTableWriter { }; Header Header; - DenseMap> - Abbreviations; + /// FoldingSet that uniques the abbreviations. + FoldingSet AbbreviationsSet; + /// Vector containing DebugNames abbreviations for iteration in order. + SmallVector AbbreviationsVector; + /// The bump allocator to use when creating DIEAbbrev objects in the uniqued + /// storage container. + BumpPtrAllocator Alloc; ArrayRef> CompUnits; ArrayRef> TypeUnits; llvm::function_ref( @@ -234,7 +239,7 @@ class Dwarf5AccelTableWriter : public AccelTableWriter { void emitEntry( const DWARF5AccelTableData &Entry, const DenseMap &DIEOffsetToAccelEntryLabel, - DenseSet &EmittedAccelEntrySymbols) const; + DenseSet &EmittedAccelEntrySymbols); void emitData(); public: @@ -370,7 +375,7 @@ void AppleAccelTableWriter::emit() const { DWARF5AccelTableData::DWARF5AccelTableData(const DIE &Die, const uint32_t UnitID, const bool IsTU) - : OffsetVal(&Die), DieTag(Die.getTag()), UnitID(UnitID), IsTU(IsTU) {} + : OffsetVal(&Die), DieTag(Die.getTag()), IsTU(IsTU), UnitID(UnitID) {} void Dwarf5AccelTableWriter::Header::emit(Dwarf5AccelTableWriter &Ctx) { assert(CompUnitCount > 0 && "Index must have at least one CU."); @@ -409,51 +414,6 @@ DWARF5AccelTableData::getDefiningParentDieOffset(const DIE &Die) { return {}; } -enum IdxParentEncoding : uint8_t { - NoIndexedParent = 0, /// Parent information present but parent isn't indexed. - Ref4 = 1, /// Parent information present and parent is indexed. - NoParent = 2, /// Parent information missing. -}; - -static uint32_t constexpr NumBitsIdxParent = 2; - -uint8_t encodeIdxParent(const std::optional MaybeParentForm) { - if (!MaybeParentForm) - return NoParent; - switch (*MaybeParentForm) { - case dwarf::Form::DW_FORM_flag_present: - return NoIndexedParent; - case dwarf::Form::DW_FORM_ref4: - return Ref4; - default: - // This is not crashing on bad input: we should only reach this if the - // internal compiler logic is faulty; see getFormForIdxParent. - llvm_unreachable("Bad form for IDX_parent"); - } -} - -static uint32_t constexpr ParentBitOffset = dwarf::DW_IDX_type_hash; -static uint32_t constexpr TagBitOffset = ParentBitOffset + NumBitsIdxParent; -static uint32_t getTagFromAbbreviationTag(const uint32_t AbbrvTag) { - return AbbrvTag >> TagBitOffset; -} - -/// 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 &EntryRet, - std::optional MaybeParentForm) { - uint32_t AbbrvTag = 0; - if (EntryRet) - AbbrvTag |= 1 << EntryRet->Encoding.Index; - AbbrvTag |= 1 << dwarf::DW_IDX_die_offset; - AbbrvTag |= 1 << dwarf::DW_IDX_parent; - AbbrvTag |= encodeIdxParent(MaybeParentForm) << ParentBitOffset; - AbbrvTag |= Tag << TagBitOffset; - return AbbrvTag; -} - static std::optional getFormForIdxParent(const DenseSet &IndexedOffsets, std::optional ParentOffset) { @@ -467,26 +427,42 @@ getFormForIdxParent(const DenseSet &IndexedOffsets, return dwarf::Form::DW_FORM_flag_present; } +void DebugNamesAbbrev::Profile(FoldingSetNodeID &ID) const { + ID.AddInteger(DieTag); + for (const DebugNamesAbbrev::AttributeEncoding &Enc : AttrVect) { + ID.AddInteger(Enc.Index); + ID.AddInteger(Enc.Form); + } +} + void Dwarf5AccelTableWriter::populateAbbrevsMap() { for (auto &Bucket : Contents.getBuckets()) { for (auto *Hash : Bucket) { for (auto *Value : Hash->getValues()) { std::optional EntryRet = getIndexForEntry(*Value); - unsigned Tag = Value->getDieTag(); std::optional MaybeParentForm = getFormForIdxParent( IndexedOffsets, Value->getParentDieOffsetAndUnitID()); - uint32_t AbbrvTag = - constructAbbreviationTag(Tag, EntryRet, MaybeParentForm); - if (Abbreviations.count(AbbrvTag) == 0) { - SmallVector UA; - if (EntryRet) - UA.push_back(EntryRet->Encoding); - UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4}); - if (MaybeParentForm) - UA.push_back({dwarf::DW_IDX_parent, *MaybeParentForm}); - Abbreviations.try_emplace(AbbrvTag, UA); + DebugNamesAbbrev Abbrev(Value->getDieTag()); + if (EntryRet) + Abbrev.addAttribute(EntryRet->Encoding); + Abbrev.addAttribute({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4}); + if (MaybeParentForm) + Abbrev.addAttribute({dwarf::DW_IDX_parent, *MaybeParentForm}); + FoldingSetNodeID ID; + Abbrev.Profile(ID); + void *InsertPos; + if (DebugNamesAbbrev *Existing = + AbbreviationsSet.FindNodeOrInsertPos(ID, InsertPos)) { + Value->setAbbrevNumber(Existing->getNumber()); + continue; } + DebugNamesAbbrev *NewAbbrev = + new (Alloc) DebugNamesAbbrev(std::move(Abbrev)); + AbbreviationsVector.push_back(NewAbbrev); + NewAbbrev->setNumber(AbbreviationsVector.size()); + AbbreviationsSet.InsertNode(NewAbbrev, InsertPos); + Value->setAbbrevNumber(NewAbbrev->getNumber()); } } } @@ -536,14 +512,13 @@ void Dwarf5AccelTableWriter::emitStringOffsets() const { void Dwarf5AccelTableWriter::emitAbbrevs() const { Asm->OutStreamer->emitLabel(AbbrevStart); - for (const auto &Abbrev : Abbreviations) { + for (const DebugNamesAbbrev *Abbrev : AbbreviationsVector) { Asm->OutStreamer->AddComment("Abbrev code"); - 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(Abbrev->getNumber()); + Asm->OutStreamer->AddComment(dwarf::TagString(Abbrev->getDieTag())); + Asm->emitULEB128(Abbrev->getDieTag()); + for (const DebugNamesAbbrev::AttributeEncoding &AttrEnc : + Abbrev->getAttributes()) { Asm->emitULEB128(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data()); Asm->emitULEB128(AttrEnc.Form, dwarf::FormEncodingString(AttrEnc.Form).data()); @@ -558,21 +533,15 @@ void Dwarf5AccelTableWriter::emitAbbrevs() const { void Dwarf5AccelTableWriter::emitEntry( const DWARF5AccelTableData &Entry, const DenseMap &DIEOffsetToAccelEntryLabel, - DenseSet &EmittedAccelEntrySymbols) const { + DenseSet &EmittedAccelEntrySymbols) { + unsigned AbbrevIndex = Entry.getAbbrevNumber() - 1; + assert(AbbrevIndex < AbbreviationsVector.size() && + "Entry abbrev index is outside of abbreviations vector range."); + DebugNamesAbbrev *Abbrev = AbbreviationsVector[AbbrevIndex]; std::optional EntryRet = getIndexForEntry(Entry); std::optional MaybeParentOffset = Entry.getParentDieOffsetAndUnitID(); - std::optional MaybeParentForm = - getFormForIdxParent(IndexedOffsets, MaybeParentOffset); - uint32_t AbbrvTag = - constructAbbreviationTag(Entry.getDieTag(), EntryRet, MaybeParentForm); - auto AbbrevIt = Abbreviations.find(AbbrvTag); - assert(AbbrevIt != Abbreviations.end() && - "Why wasn't this abbrev generated?"); - assert(getTagFromAbbreviationTag(AbbrevIt->first) == Entry.getDieTag() && - "Invalid Tag"); - auto EntrySymbolIt = DIEOffsetToAccelEntryLabel.find(Entry.getDieOffsetAndUnitID()); assert(EntrySymbolIt != DIEOffsetToAccelEntryLabel.end()); @@ -584,9 +553,10 @@ void Dwarf5AccelTableWriter::emitEntry( if (EmittedAccelEntrySymbols.insert(EntrySymbol).second) Asm->OutStreamer->emitLabel(EntrySymbol); - Asm->emitULEB128(AbbrevIt->first, "Abbreviation code"); + Asm->emitULEB128(Entry.getAbbrevNumber(), "Abbreviation code"); - for (const auto &AttrEnc : AbbrevIt->second) { + for (const DebugNamesAbbrev::AttributeEncoding &AttrEnc : + Abbrev->getAttributes()) { Asm->OutStreamer->AddComment(dwarf::IndexString(AttrEnc.Index)); switch (AttrEnc.Index) { case dwarf::DW_IDX_compile_unit: diff --git a/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll b/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll index c15e2ad1d56b0..9a5fd07335873 100644 --- a/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll +++ b/llvm/test/DebugInfo/X86/debug-names-dwarf64.ll @@ -30,11 +30,6 @@ ; CHECK-NEXT: CU[0]: 0x00000000 ; CHECK-NEXT: ] ; CHECK-NEXT: Abbreviations [ -; CHECK-NEXT: Abbreviation [[ABBREV_LABEL:0x[0-9a-f]*]] { -; CHECK-NEXT: Tag: DW_TAG_label -; CHECK-NEXT: DW_IDX_die_offset: DW_FORM_ref4 -; CHECK-NEXT: DW_IDX_parent: 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 @@ -50,6 +45,11 @@ ; CHECK-NEXT: DW_IDX_die_offset: DW_FORM_ref4 ; CHECK-NEXT: DW_IDX_parent: DW_FORM_flag_present ; CHECK-NEXT: } +; CHECK-NEXT: Abbreviation [[ABBREV_LABEL:0x[0-9a-f]*]] { +; CHECK-NEXT: Tag: DW_TAG_label +; CHECK-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; CHECK-NEXT: DW_IDX_parent: 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 index f41bb5524b9c3..ff0d4d52c1f07 100644 --- a/llvm/test/DebugInfo/X86/debug-names-types.ll +++ b/llvm/test/DebugInfo/X86/debug-names-types.ll @@ -37,20 +37,14 @@ ; CHECK-NEXT: LocalTU[0]: 0x00000000 ; CHECK-NEXT: ] ; CHECK: Abbreviations [ -; 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: DW_IDX_parent: DW_FORM_flag_present -; CHECK-NEXT: } -; CHECK-NEXT: Abbreviation [[ABBREV4:0x[0-9a-f]*]] { +; CHECK-NEXT: Abbreviation [[ABBREV: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: DW_IDX_parent: DW_FORM_flag_present ; CHECK-NEXT: } -; CHECK-NEXT: Abbreviation [[ABBREV:0x[0-9a-f]*]] { -; CHECK-NEXT: Tag: DW_TAG_base_type +; 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: DW_IDX_parent: DW_FORM_flag_present ; CHECK-NEXT: } @@ -64,6 +58,12 @@ ; CHECK-NEXT: DW_IDX_die_offset: DW_FORM_ref4 ; CHECK-NEXT: DW_IDX_parent: DW_FORM_flag_present ; 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: DW_IDX_parent: DW_FORM_flag_present +; CHECK-NEXT: } ; CHECK-NEXT: ] ; CHECK-NEXT: Bucket 0 [ ; CHECK-NEXT: Name 1 { @@ -130,7 +130,7 @@ ; CHECK-SPLIT: Foreign TU count: 1 ; CHECK-SPLIT-NEXT: Bucket count: 4 ; CHECK-SPLIT-NEXT: Name count: 4 -; CHECK-SPLIT-NEXT: Abbreviations table size: 0x32 +; CHECK-SPLIT-NEXT: Abbreviations table size: 0x2D ; CHECK-SPLIT-NEXT: Augmentation: 'LLVM0700' ; CHECK-SPLIT-NEXT: } ; CHECK-SPLIT-NEXT: Compilation Unit offsets [ @@ -140,20 +140,14 @@ ; CHECK-SPLIT-NEXT: ForeignTU[0]: 0x675d23e4f33235f2 ; CHECK-SPLIT-NEXT: ] ; CHECK-SPLIT-NEXT: Abbreviations [ -; CHECK-SPLIT-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] { -; CHECK-SPLIT-NEXT: Tag: DW_TAG_structure_type -; CHECK-SPLIT-NEXT: DW_IDX_type_unit: DW_FORM_data1 -; CHECK-SPLIT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 -; CHECK-SPLIT-NEXT: DW_IDX_parent: DW_FORM_flag_present -; CHECK-SPLIT-NEXT: } -; CHECK-SPLIT-NEXT: Abbreviation [[ABBREV4:0x[0-9a-f]*]] { +; CHECK-SPLIT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] { ; CHECK-SPLIT-NEXT: Tag: DW_TAG_base_type -; CHECK-SPLIT-NEXT: DW_IDX_type_unit: DW_FORM_data1 ; CHECK-SPLIT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 ; CHECK-SPLIT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; CHECK-SPLIT-NEXT: } -; CHECK-SPLIT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] { -; CHECK-SPLIT-NEXT: Tag: DW_TAG_base_type +; CHECK-SPLIT-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] { +; CHECK-SPLIT-NEXT: Tag: DW_TAG_structure_type +; CHECK-SPLIT-NEXT: DW_IDX_type_unit: DW_FORM_data1 ; CHECK-SPLIT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 ; CHECK-SPLIT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; CHECK-SPLIT-NEXT: } @@ -167,6 +161,12 @@ ; CHECK-SPLIT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 ; CHECK-SPLIT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; CHECK-SPLIT-NEXT: } +; CHECK-SPLIT-NEXT: Abbreviation [[ABBREV4:0x[0-9a-f]*]] { +; CHECK-SPLIT-NEXT: Tag: DW_TAG_base_type +; CHECK-SPLIT-NEXT: DW_IDX_type_unit: DW_FORM_data1 +; CHECK-SPLIT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; CHECK-SPLIT-NEXT: DW_IDX_parent: DW_FORM_flag_present +; CHECK-SPLIT-NEXT: } ; CHECK-SPLIT-NEXT: ] ; CHECK-SPLIT-NEXT: Bucket 0 [ ; CHECK-SPLIT-NEXT: Name 1 { 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 5a37b4247b5bf..fb15f46ce0b24 100644 --- a/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test +++ b/llvm/test/tools/dsymutil/ARM/dwarf5-dwarf4-combination-macho.test @@ -221,8 +221,8 @@ CHECK-NEXT: Name Index @ 0x0 { CHECK-NEXT: Header { ; FIXME: when the parallel dwarf linker is able to generate DW_IDX_parent, ; these headers should be the same. -WITH-PARENTS-NEXT: Length: 0xC8 -NO-PARENTS-NEXT: Length: 0xC4 +WITH-PARENTS-NEXT: Length: 0xC0 +NO-PARENTS-NEXT: Length: 0xBC CHECK-NEXT: Format: DWARF32 CHECK-NEXT: Version: 5 CHECK-NEXT: CU count: 2 @@ -230,7 +230,7 @@ CHECK-NEXT: Local TU count: 0 CHECK-NEXT: Foreign TU count: 0 CHECK-NEXT: Bucket count: 5 CHECK-NEXT: Name count: 5 -WITH-PARENTS-NEXT: Abbreviations table size: 0x17 -NO-PARENTS-NEXT: Abbreviations table size: 0x13 +WITH-PARENTS-NEXT: Abbreviations table size: 0x15 +NO-PARENTS-NEXT: Abbreviations table size: 0x11 CHECK-NEXT: Augmentation: 'LLVM0700' CHECK-NEXT: }