Skip to content

Commit

Permalink
[LLVM][DWARF] Change .debug_names abbrev to be an index (#81200)
Browse files Browse the repository at this point in the history
Based on the discussion in
#80229
changed implementation to align with how .debug_abbrev is handled. So
that
.debug_names abbrev tag is a monotonically increasing index. This allows
for
tools like LLDB to access it in constant time using array like data
structure.

clang-19 debug build
before change

[41] .debug_names PROGBITS 0000000000000000 8f9e0350 137fdbe0 00 0 0 4
after change
[41] .debug_names PROGBITS 0000000000000000 8f9e0350 125bfde 00 0 0 4

Reduction ~19.1MB
  • Loading branch information
ayermolo authored Feb 14, 2024
1 parent 5992b32 commit a78d13d
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 119 deletions.
49 changes: 40 additions & 9 deletions llvm/include/llvm/CodeGen/AccelTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,6 @@ struct DenseMapInfo<OffsetAndUnitID> : DenseMapInfo<OffsetAndUnitID::Base> {};
/// 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,
Expand All @@ -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;
Expand Down Expand Up @@ -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<uint64_t> getDefiningParentDieOffset(const DIE &Die);
Expand All @@ -338,12 +339,42 @@ class DWARF5AccelTableData : public AccelTableData {
std::variant<const DIE *, uint64_t> OffsetVal;
std::optional<uint64_t> 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<AttributeEncoding, 1> &getAttributes() const {
return AttrVect;
}

private:
SmallVector<AttributeEncoding, 1> AttrVect;
};

struct TypeUnitMetaInfo {
// Symbol for start of the TU section or signature if this is SplitDwarf.
std::variant<MCSymbol *, uint64_t> LabelOrSignature;
Expand All @@ -358,7 +389,7 @@ class DWARF5AccelTable : public AccelTable<DWARF5AccelTableData> {
public:
struct UnitIndexAndEncoding {
unsigned Index;
DWARF5AccelTableData::AttributeEncoding Encoding;
DebugNamesAbbrev::AttributeEncoding Encoding;
};
/// Returns type units that were constructed.
const TUVectorTy &getTypeUnitsSymbols() { return TUSymbolsOrHashes; }
Expand Down
130 changes: 50 additions & 80 deletions llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,13 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
};

Header Header;
DenseMap<uint32_t, SmallVector<DWARF5AccelTableData::AttributeEncoding, 3>>
Abbreviations;
/// FoldingSet that uniques the abbreviations.
FoldingSet<DebugNamesAbbrev> AbbreviationsSet;
/// Vector containing DebugNames abbreviations for iteration in order.
SmallVector<DebugNamesAbbrev *, 5> AbbreviationsVector;
/// The bump allocator to use when creating DIEAbbrev objects in the uniqued
/// storage container.
BumpPtrAllocator Alloc;
ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits;
ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits;
llvm::function_ref<std::optional<DWARF5AccelTable::UnitIndexAndEncoding>(
Expand All @@ -234,7 +239,7 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
void emitEntry(
const DWARF5AccelTableData &Entry,
const DenseMap<OffsetAndUnitID, MCSymbol *> &DIEOffsetToAccelEntryLabel,
DenseSet<MCSymbol *> &EmittedAccelEntrySymbols) const;
DenseSet<MCSymbol *> &EmittedAccelEntrySymbols);
void emitData();

public:
Expand Down Expand Up @@ -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.");
Expand Down Expand Up @@ -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<dwarf::Form> 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<DWARF5AccelTable::UnitIndexAndEncoding> &EntryRet,
std::optional<dwarf::Form> 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<dwarf::Form>
getFormForIdxParent(const DenseSet<OffsetAndUnitID> &IndexedOffsets,
std::optional<OffsetAndUnitID> ParentOffset) {
Expand All @@ -467,26 +427,42 @@ getFormForIdxParent(const DenseSet<OffsetAndUnitID> &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<DWARF5AccelTableData *>()) {
std::optional<DWARF5AccelTable::UnitIndexAndEncoding> EntryRet =
getIndexForEntry(*Value);
unsigned Tag = Value->getDieTag();
std::optional<dwarf::Form> MaybeParentForm = getFormForIdxParent(
IndexedOffsets, Value->getParentDieOffsetAndUnitID());
uint32_t AbbrvTag =
constructAbbreviationTag(Tag, EntryRet, MaybeParentForm);
if (Abbreviations.count(AbbrvTag) == 0) {
SmallVector<DWARF5AccelTableData::AttributeEncoding, 3> 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());
}
}
}
Expand Down Expand Up @@ -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());
Expand All @@ -558,21 +533,15 @@ void Dwarf5AccelTableWriter::emitAbbrevs() const {
void Dwarf5AccelTableWriter::emitEntry(
const DWARF5AccelTableData &Entry,
const DenseMap<OffsetAndUnitID, MCSymbol *> &DIEOffsetToAccelEntryLabel,
DenseSet<MCSymbol *> &EmittedAccelEntrySymbols) const {
DenseSet<MCSymbol *> &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<DWARF5AccelTable::UnitIndexAndEncoding> EntryRet =
getIndexForEntry(Entry);
std::optional<OffsetAndUnitID> MaybeParentOffset =
Entry.getParentDieOffsetAndUnitID();
std::optional<dwarf::Form> 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());
Expand All @@ -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:
Expand Down
10 changes: 5 additions & 5 deletions llvm/test/DebugInfo/X86/debug-names-dwarf64.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand Down
42 changes: 21 additions & 21 deletions llvm/test/DebugInfo/X86/debug-names-types.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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: }
Expand All @@ -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 {
Expand Down Expand Up @@ -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 [
Expand All @@ -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: }
Expand All @@ -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 {
Expand Down
Loading

0 comments on commit a78d13d

Please sign in to comment.