Skip to content

Commit 7a382cd

Browse files
[llvm][DebugNames] Implement DW_IDX_parent entries
1 parent 1fafdee commit 7a382cd

File tree

5 files changed

+70
-11
lines changed

5 files changed

+70
-11
lines changed

llvm/include/llvm/CodeGen/AccelTable.h

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,12 @@ class DWARF5AccelTableData : public AccelTableData {
261261

262262
DWARF5AccelTableData(const DIE &Die, const uint32_t UnitID,
263263
const bool IsTU = false);
264-
DWARF5AccelTableData(const uint64_t DieOffset, const unsigned DieTag,
265-
const unsigned UnitID, const bool IsTU = false)
266-
: OffsetVal(DieOffset), DieTag(DieTag), UnitID(UnitID), IsTU(IsTU) {}
264+
DWARF5AccelTableData(const uint64_t DieOffset,
265+
const std::optional<uint64_t> ParentOffset,
266+
const unsigned DieTag, const unsigned UnitID,
267+
const bool IsTU = false)
268+
: OffsetVal(DieOffset), ParentOffset(ParentOffset), DieTag(DieTag),
269+
UnitID(UnitID), IsTU(IsTU) {}
267270

268271
#ifndef NDEBUG
269272
void print(raw_ostream &OS) const override;
@@ -278,14 +281,24 @@ class DWARF5AccelTableData : public AccelTableData {
278281
bool isTU() const { return IsTU; }
279282
void normalizeDIEToOffset() {
280283
assert(!isNormalized() && "Accessing offset after normalizing.");
281-
OffsetVal = std::get<const DIE *>(OffsetVal)->getOffset();
284+
const DIE *Entry = std::get<const DIE *>(OffsetVal);
285+
ParentOffset = Entry->getParent() ? Entry->getParent()->getOffset()
286+
: std::optional<uint64_t>();
287+
OffsetVal = Entry->getOffset();
282288
}
283289
bool isNormalized() const {
284290
return std::holds_alternative<uint64_t>(OffsetVal);
285291
}
286292

293+
std::optional<uint64_t> getParentDieOffset() const {
294+
assert(std::holds_alternative<uint64_t>(OffsetVal) &&
295+
"Accessing DIE Offset before normalizing.");
296+
return ParentOffset;
297+
}
298+
287299
protected:
288300
std::variant<const DIE *, uint64_t> OffsetVal;
301+
std::optional<uint64_t> ParentOffset;
289302
uint32_t DieTag : 16;
290303
uint32_t UnitID : 15;
291304
uint32_t IsTU : 1;
@@ -334,7 +347,8 @@ class DWARF5AccelTable : public AccelTable<DWARF5AccelTableData> {
334347
for (auto &Entry : Table.getEntries()) {
335348
for (AccelTableData *Value : Entry.second.Values) {
336349
DWARF5AccelTableData *Data = static_cast<DWARF5AccelTableData *>(Value);
337-
addName(Entry.second.Name, Data->getDieOffset(), Data->getDieTag(),
350+
addName(Entry.second.Name, Data->getDieOffset(),
351+
Data->getParentDieOffset(), Data->getDieTag(),
338352
Data->getUnitID(), true);
339353
}
340354
}

llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
224224
MCSymbol *EntryPool = Asm->createTempSymbol("names_entries");
225225
// Indicates if this module is built with Split Dwarf enabled.
226226
bool IsSplitDwarf = false;
227+
DenseMap<uint64_t, MCSymbol *> DieOffsetToAccelEntrySymbol;
228+
llvm::DenseSet<MCSymbol *> EmittedAccelEntrySymbols;
227229

228230
void populateAbbrevsMap();
229231

@@ -232,8 +234,8 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
232234
void emitBuckets() const;
233235
void emitStringOffsets() const;
234236
void emitAbbrevs() const;
235-
void emitEntry(const DataT &Entry) const;
236-
void emitData() const;
237+
void emitEntry(const DataT &Entry);
238+
void emitData();
237239

238240
public:
239241
Dwarf5AccelTableWriter(
@@ -414,6 +416,7 @@ static uint32_t constructAbbreviationTag(
414416
if (EntryRet)
415417
AbbrvTag |= 1 << EntryRet->Encoding.Index;
416418
AbbrvTag |= 1 << dwarf::DW_IDX_die_offset;
419+
AbbrvTag |= 1 << dwarf::DW_IDX_parent;
417420
AbbrvTag |= Tag << LowerBitSize;
418421
return AbbrvTag;
419422
}
@@ -427,10 +430,11 @@ void Dwarf5AccelTableWriter<DataT>::populateAbbrevsMap() {
427430
unsigned Tag = static_cast<const DataT *>(Value)->getDieTag();
428431
uint32_t AbbrvTag = constructAbbreviationTag(Tag, EntryRet);
429432
if (Abbreviations.count(AbbrvTag) == 0) {
430-
SmallVector<DWARF5AccelTableData::AttributeEncoding, 2> UA;
433+
SmallVector<DWARF5AccelTableData::AttributeEncoding, 3> UA;
431434
if (EntryRet)
432435
UA.push_back(EntryRet->Encoding);
433436
UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
437+
UA.push_back({dwarf::DW_IDX_parent, dwarf::DW_FORM_ref4});
434438
Abbreviations.try_emplace(AbbrvTag, UA);
435439
}
436440
}
@@ -507,7 +511,7 @@ void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const {
507511
}
508512

509513
template <typename DataT>
510-
void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const {
514+
void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) {
511515
std::optional<DWARF5AccelTable::UnitIndexAndEncoding> EntryRet =
512516
getIndexForEntry(Entry);
513517
uint32_t AbbrvTag = constructAbbreviationTag(Entry.getDieTag(), EntryRet);
@@ -516,6 +520,18 @@ void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const {
516520
"Why wasn't this abbrev generated?");
517521
assert(getTagFromAbbreviationTag(AbbrevIt->first) == Entry.getDieTag() &&
518522
"Invalid Tag");
523+
524+
// Create a label for this Entry, if not yet created by a IDX_parent
525+
// reference to the same underlying DIE.
526+
MCSymbol *&EntrySymbol = DieOffsetToAccelEntrySymbol[Entry.getDieOffset()];
527+
if (EntrySymbol == nullptr)
528+
EntrySymbol = Asm->createTempSymbol("symbol");
529+
530+
// Emit the label for this Entry, if a label hasn't yet been emitted for some
531+
// other Entry of the same underlying DIE (a DIE may have multiple Entries).
532+
if (EmittedAccelEntrySymbols.insert(EntrySymbol).second)
533+
Asm->OutStreamer->emitLabel(EntrySymbol);
534+
519535
Asm->emitULEB128(AbbrevIt->first, "Abbreviation code");
520536

521537
for (const auto &AttrEnc : AbbrevIt->second) {
@@ -531,13 +547,25 @@ void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const {
531547
assert(AttrEnc.Form == dwarf::DW_FORM_ref4);
532548
Asm->emitInt32(Entry.getDieOffset());
533549
break;
550+
case dwarf::DW_IDX_parent: {
551+
// If a DIE is being placed on the table, its parent is always non-null
552+
// (top-level DIEs are not placed in the table), though the parent may not
553+
// be indexed. Bad input is handled like a parent that is not indexed,
554+
// i.e., with an offset that is not in the table.
555+
uint64_t ParentOffset = Entry.getParentDieOffset().value_or(-1);
556+
MCSymbol *&ParentSymbol = DieOffsetToAccelEntrySymbol[ParentOffset];
557+
if (ParentSymbol == nullptr)
558+
ParentSymbol = Asm->createTempSymbol("symbol");
559+
Asm->emitLabelDifference(ParentSymbol, EntryPool, 4);
560+
break;
561+
}
534562
default:
535563
llvm_unreachable("Unexpected index attribute!");
536564
}
537565
}
538566
}
539567

540-
template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emitData() const {
568+
template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emitData() {
541569
Asm->OutStreamer->emitLabel(EntryPool);
542570
for (auto &Bucket : Contents.getBuckets()) {
543571
for (auto *Hash : Bucket) {
@@ -549,6 +577,11 @@ template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emitData() const {
549577
Asm->emitInt8(0);
550578
}
551579
}
580+
// Any labels not yet emitted refer to DIEs that are not present in the
581+
// accelerator table. Point them to end of the table.
582+
for (MCSymbol *Symbol : make_second_range(DieOffsetToAccelEntrySymbol))
583+
if (EmittedAccelEntrySymbols.insert(Symbol).second)
584+
Asm->OutStreamer->emitLabel(Symbol);
552585
}
553586

554587
template <typename DataT>

llvm/lib/DWARFLinker/DWARFLinker.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2253,14 +2253,22 @@ void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
22532253
TheDwarfEmitter->emitPubTypesForUnit(Unit);
22542254
} break;
22552255
case AccelTableKind::DebugNames: {
2256+
auto ParentOffsetOrNull = [](const DIE *Die) -> std::optional<uint64_t> {
2257+
if (const DIE *Parent = Die->getParent())
2258+
return Die->getParent()->getOffset();
2259+
return std::nullopt;
2260+
};
22562261
for (const auto &Namespace : Unit.getNamespaces())
22572262
DebugNames.addName(Namespace.Name, Namespace.Die->getOffset(),
2263+
ParentOffsetOrNull(Namespace.Die),
22582264
Namespace.Die->getTag(), Unit.getUniqueID());
22592265
for (const auto &Pubname : Unit.getPubnames())
22602266
DebugNames.addName(Pubname.Name, Pubname.Die->getOffset(),
2267+
ParentOffsetOrNull(Pubname.Die),
22612268
Pubname.Die->getTag(), Unit.getUniqueID());
22622269
for (const auto &Pubtype : Unit.getPubtypes())
22632270
DebugNames.addName(Pubtype.Name, Pubtype.Die->getOffset(),
2271+
ParentOffsetOrNull(Pubtype.Die),
22642272
Pubtype.Die->getTag(), Unit.getUniqueID());
22652273
} break;
22662274
}

llvm/lib/DWARFLinkerParallel/DWARFLinkerImpl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1376,7 +1376,8 @@ void DWARFLinkerImpl::emitDWARFv5DebugNamesSection(const Triple &TargetTriple) {
13761376
case DwarfUnit::AccelType::Namespace:
13771377
case DwarfUnit::AccelType::Type: {
13781378
DebugNames->addName(*DebugStrStrings.getExistingEntry(Info.String),
1379-
Info.OutOffset, Info.Tag, CU->getUniqueID());
1379+
Info.OutOffset, Info.ParentOutOffset, Info.Tag,
1380+
CU->getUniqueID());
13801381
} break;
13811382

13821383
default:

llvm/lib/DWARFLinkerParallel/DWARFLinkerUnit.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ class DwarfUnit : public OutputSections {
125125
/// Output offset of the DIE this entry describes.
126126
uint64_t OutOffset;
127127

128+
/// Output offset of the parent of the DIE this entry describes.
129+
std::optional<uint64_t> ParentOutOffset;
130+
128131
/// Hash of the fully qualified name.
129132
uint32_t QualifiedNameHash = 0;
130133

0 commit comments

Comments
 (0)