Skip to content

[LLVM][DWARF] Change .debug_names abbrev to be an index #81200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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