Skip to content

Commit ad45044

Browse files
committed
[LLVM][DWARF] Add support for monolithic types in .debug_names
Summary: Adding support for Type Units in monolithic DWARF in .debug_names.
1 parent cb7cf62 commit ad45044

19 files changed

+505
-126
lines changed

llvm/include/llvm/CodeGen/AccelTable.h

+28-7
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ namespace llvm {
106106
class AsmPrinter;
107107
class DwarfCompileUnit;
108108
class DwarfDebug;
109+
class DwarfTypeUnit;
109110
class MCSymbol;
110111
class raw_ostream;
111112

@@ -197,6 +198,9 @@ template <typename DataT> class AccelTable : public AccelTableBase {
197198

198199
template <typename... Types>
199200
void addName(DwarfStringPoolEntryRef Name, Types &&... Args);
201+
void clear() { Entries.clear(); }
202+
void addEntries(AccelTable<DataT> &Table);
203+
const StringEntries getEntries() const { return Entries; }
200204
};
201205

202206
template <typename AccelTableDataT>
@@ -215,6 +219,16 @@ void AccelTable<AccelTableDataT>::addName(DwarfStringPoolEntryRef Name,
215219
AccelTableDataT(std::forward<Types>(Args)...));
216220
}
217221

222+
template <typename AccelTableDataT>
223+
void AccelTable<AccelTableDataT>::addEntries(
224+
AccelTable<AccelTableDataT> &Table) {
225+
for (auto &Entry : Table.getEntries()) {
226+
for (AccelTableData *Value : Entry.second.Values)
227+
addName(Entry.second.Name,
228+
static_cast<AccelTableDataT *>(Value)->getDie());
229+
}
230+
}
231+
218232
/// A base class for different implementations of Data classes for Apple
219233
/// Accelerator Tables. The columns in the table are defined by the static Atoms
220234
/// variable defined on the subclasses.
@@ -250,6 +264,10 @@ class AppleAccelTableData : public AccelTableData {
250264
/// emitDWARF5AccelTable function.
251265
class DWARF5AccelTableData : public AccelTableData {
252266
public:
267+
struct AttributeEncoding {
268+
dwarf::Index Index;
269+
dwarf::Form Form;
270+
};
253271
static uint32_t hash(StringRef Name) { return caseFoldingDjbHash(Name); }
254272

255273
DWARF5AccelTableData(const DIE &Die) : Die(Die) {}
@@ -309,17 +327,20 @@ void emitAppleAccelTable(AsmPrinter *Asm, AccelTable<DataT> &Contents,
309327
void emitDWARF5AccelTable(AsmPrinter *Asm,
310328
AccelTable<DWARF5AccelTableData> &Contents,
311329
const DwarfDebug &DD,
312-
ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs);
313-
330+
ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs,
331+
ArrayRef<std::unique_ptr<DwarfTypeUnit>> TUs);
332+
using GetIndexForEntryReturnType =
333+
std::optional<std::pair<unsigned, DWARF5AccelTableData::AttributeEncoding>>;
314334
/// Emit a DWARFv5 Accelerator Table consisting of entries in the specified
315335
/// AccelTable. The \p CUs contains either symbols keeping offsets to the
316336
/// start of compilation unit, either offsets to the start of compilation
317337
/// unit themselves.
318-
void emitDWARF5AccelTable(
319-
AsmPrinter *Asm, AccelTable<DWARF5AccelTableStaticData> &Contents,
320-
ArrayRef<std::variant<MCSymbol *, uint64_t>> CUs,
321-
llvm::function_ref<unsigned(const DWARF5AccelTableStaticData &)>
322-
getCUIndexForEntry);
338+
void emitDWARF5AccelTable(AsmPrinter *Asm,
339+
AccelTable<DWARF5AccelTableStaticData> &Contents,
340+
ArrayRef<std::variant<MCSymbol *, uint64_t>> CUs,
341+
llvm::function_ref<GetIndexForEntryReturnType(
342+
const DWARF5AccelTableStaticData &)>
343+
getIndexForEntry);
323344

324345
/// Accelerator table data implementation for simple Apple accelerator tables
325346
/// with just a DIE reference.

llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp

+112-60
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#include "llvm/CodeGen/AccelTable.h"
1414
#include "DwarfCompileUnit.h"
1515
#include "llvm/ADT/STLExtras.h"
16-
#include "llvm/ADT/StringMap.h"
1716
#include "llvm/ADT/Twine.h"
1817
#include "llvm/BinaryFormat/Dwarf.h"
1918
#include "llvm/CodeGen/AsmPrinter.h"
@@ -200,32 +199,30 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
200199
uint32_t AugmentationStringSize = sizeof(AugmentationString);
201200
char AugmentationString[8] = {'L', 'L', 'V', 'M', '0', '7', '0', '0'};
202201

203-
Header(uint32_t CompUnitCount, uint32_t BucketCount, uint32_t NameCount)
204-
: CompUnitCount(CompUnitCount), BucketCount(BucketCount),
205-
NameCount(NameCount) {}
202+
Header(uint32_t CompUnitCount, uint32_t LocalTypeUnitCount,
203+
uint32_t BucketCount, uint32_t NameCount)
204+
: CompUnitCount(CompUnitCount), LocalTypeUnitCount(LocalTypeUnitCount),
205+
BucketCount(BucketCount), NameCount(NameCount) {}
206206

207207
void emit(Dwarf5AccelTableWriter &Ctx);
208208
};
209-
struct AttributeEncoding {
210-
dwarf::Index Index;
211-
dwarf::Form Form;
212-
};
213209

214210
Header Header;
215-
DenseMap<uint32_t, SmallVector<AttributeEncoding, 2>> Abbreviations;
211+
DenseMap<uint32_t, SmallVector<DWARF5AccelTableData::AttributeEncoding, 2>>
212+
Abbreviations;
216213
ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits;
217-
llvm::function_ref<unsigned(const DataT &)> getCUIndexForEntry;
214+
ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits;
215+
llvm::function_ref<GetIndexForEntryReturnType(const DataT &)>
216+
getIndexForEntry;
218217
MCSymbol *ContributionEnd = nullptr;
219218
MCSymbol *AbbrevStart = Asm->createTempSymbol("names_abbrev_start");
220219
MCSymbol *AbbrevEnd = Asm->createTempSymbol("names_abbrev_end");
221220
MCSymbol *EntryPool = Asm->createTempSymbol("names_entries");
222221

223-
DenseSet<uint32_t> getUniqueTags() const;
224-
225-
// Right now, we emit uniform attributes for all tags.
226-
SmallVector<AttributeEncoding, 2> getUniformAttributes() const;
222+
void populateAbbrevsMap();
227223

228224
void emitCUList() const;
225+
void emitTUList() const;
229226
void emitBuckets() const;
230227
void emitStringOffsets() const;
231228
void emitAbbrevs() const;
@@ -236,7 +233,9 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
236233
Dwarf5AccelTableWriter(
237234
AsmPrinter *Asm, const AccelTableBase &Contents,
238235
ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits,
239-
llvm::function_ref<unsigned(const DataT &)> GetCUIndexForEntry);
236+
ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits,
237+
llvm::function_ref<GetIndexForEntryReturnType(const DataT &)>
238+
getIndexForEntry);
240239

241240
void emit();
242241
};
@@ -388,31 +387,39 @@ void Dwarf5AccelTableWriter<DataT>::Header::emit(Dwarf5AccelTableWriter &Ctx) {
388387
Asm->OutStreamer->emitBytes({AugmentationString, AugmentationStringSize});
389388
}
390389

390+
static uint32_t constexpr LowerBitSize = dwarf::DW_IDX_type_hash;
391+
static uint32_t getTagFromAbbreviationTag(const uint32_t AbbrvTag) {
392+
return AbbrvTag >> LowerBitSize;
393+
}
394+
static uint32_t
395+
constructAbbreviationTag(const unsigned Tag,
396+
const GetIndexForEntryReturnType &EntryRet) {
397+
uint32_t AbbrvTag = 0;
398+
if (EntryRet)
399+
AbbrvTag |= 1 << EntryRet->second.Index;
400+
AbbrvTag |= 1 << dwarf::DW_IDX_die_offset;
401+
AbbrvTag |= Tag << LowerBitSize;
402+
return AbbrvTag;
403+
}
391404
template <typename DataT>
392-
DenseSet<uint32_t> Dwarf5AccelTableWriter<DataT>::getUniqueTags() const {
393-
DenseSet<uint32_t> UniqueTags;
405+
void Dwarf5AccelTableWriter<DataT>::populateAbbrevsMap() {
394406
for (auto &Bucket : Contents.getBuckets()) {
395407
for (auto *Hash : Bucket) {
396408
for (auto *Value : Hash->Values) {
409+
GetIndexForEntryReturnType EntryRet =
410+
getIndexForEntry(*static_cast<const DataT *>(Value));
397411
unsigned Tag = static_cast<const DataT *>(Value)->getDieTag();
398-
UniqueTags.insert(Tag);
412+
uint32_t AbbrvTag = constructAbbreviationTag(Tag, EntryRet);
413+
if (Abbreviations.count(AbbrvTag) == 0) {
414+
SmallVector<DWARF5AccelTableData::AttributeEncoding, 2> UA;
415+
if (EntryRet)
416+
UA.push_back(EntryRet->second);
417+
UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
418+
Abbreviations.try_emplace(AbbrvTag, UA);
419+
}
399420
}
400421
}
401422
}
402-
return UniqueTags;
403-
}
404-
405-
template <typename DataT>
406-
SmallVector<typename Dwarf5AccelTableWriter<DataT>::AttributeEncoding, 2>
407-
Dwarf5AccelTableWriter<DataT>::getUniformAttributes() const {
408-
SmallVector<AttributeEncoding, 2> UA;
409-
if (CompUnits.size() > 1) {
410-
size_t LargestCUIndex = CompUnits.size() - 1;
411-
dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false, LargestCUIndex);
412-
UA.push_back({dwarf::DW_IDX_compile_unit, Form});
413-
}
414-
UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
415-
return UA;
416423
}
417424

418425
template <typename DataT>
@@ -426,6 +433,17 @@ void Dwarf5AccelTableWriter<DataT>::emitCUList() const {
426433
}
427434
}
428435

436+
template <typename DataT>
437+
void Dwarf5AccelTableWriter<DataT>::emitTUList() const {
438+
for (const auto &TU : enumerate(TypeUnits)) {
439+
Asm->OutStreamer->AddComment("Type unit " + Twine(TU.index()));
440+
if (std::holds_alternative<MCSymbol *>(TU.value()))
441+
Asm->emitDwarfSymbolReference(std::get<MCSymbol *>(TU.value()));
442+
else
443+
Asm->emitDwarfLengthOrOffset(std::get<uint64_t>(TU.value()));
444+
}
445+
}
446+
429447
template <typename DataT>
430448
void Dwarf5AccelTableWriter<DataT>::emitBuckets() const {
431449
uint32_t Index = 1;
@@ -453,10 +471,11 @@ void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const {
453471
Asm->OutStreamer->emitLabel(AbbrevStart);
454472
for (const auto &Abbrev : Abbreviations) {
455473
Asm->OutStreamer->AddComment("Abbrev code");
456-
assert(Abbrev.first != 0);
457-
Asm->emitULEB128(Abbrev.first);
458-
Asm->OutStreamer->AddComment(dwarf::TagString(Abbrev.first));
474+
uint32_t Tag = getTagFromAbbreviationTag(Abbrev.first);
475+
assert(Tag != 0);
459476
Asm->emitULEB128(Abbrev.first);
477+
Asm->OutStreamer->AddComment(dwarf::TagString(Tag));
478+
Asm->emitULEB128(Tag);
460479
for (const auto &AttrEnc : Abbrev.second) {
461480
Asm->emitULEB128(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data());
462481
Asm->emitULEB128(AttrEnc.Form,
@@ -471,16 +490,21 @@ void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const {
471490

472491
template <typename DataT>
473492
void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const {
474-
auto AbbrevIt = Abbreviations.find(Entry.getDieTag());
493+
GetIndexForEntryReturnType EntryRet = getIndexForEntry(Entry);
494+
uint32_t AbbrvTag = constructAbbreviationTag(Entry.getDieTag(), EntryRet);
495+
auto AbbrevIt = Abbreviations.find(AbbrvTag);
475496
assert(AbbrevIt != Abbreviations.end() &&
476497
"Why wasn't this abbrev generated?");
477-
498+
assert(getTagFromAbbreviationTag(AbbrevIt->first) == Entry.getDieTag() &&
499+
"Invalid Tag");
478500
Asm->emitULEB128(AbbrevIt->first, "Abbreviation code");
501+
479502
for (const auto &AttrEnc : AbbrevIt->second) {
480503
Asm->OutStreamer->AddComment(dwarf::IndexString(AttrEnc.Index));
481504
switch (AttrEnc.Index) {
482-
case dwarf::DW_IDX_compile_unit: {
483-
DIEInteger ID(getCUIndexForEntry(Entry));
505+
case dwarf::DW_IDX_compile_unit:
506+
case dwarf::DW_IDX_type_unit: {
507+
DIEInteger ID(EntryRet->first);
484508
ID.emitValue(Asm, AttrEnc.Form);
485509
break;
486510
}
@@ -512,22 +536,21 @@ template <typename DataT>
512536
Dwarf5AccelTableWriter<DataT>::Dwarf5AccelTableWriter(
513537
AsmPrinter *Asm, const AccelTableBase &Contents,
514538
ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits,
515-
llvm::function_ref<unsigned(const DataT &)> getCUIndexForEntry)
539+
ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits,
540+
llvm::function_ref<GetIndexForEntryReturnType(const DataT &)>
541+
getIndexForEntry)
516542
: AccelTableWriter(Asm, Contents, false),
517-
Header(CompUnits.size(), Contents.getBucketCount(),
543+
Header(CompUnits.size(), TypeUnits.size(), Contents.getBucketCount(),
518544
Contents.getUniqueNameCount()),
519-
CompUnits(CompUnits), getCUIndexForEntry(std::move(getCUIndexForEntry)) {
520-
DenseSet<uint32_t> UniqueTags = getUniqueTags();
521-
SmallVector<AttributeEncoding, 2> UniformAttributes = getUniformAttributes();
522-
523-
Abbreviations.reserve(UniqueTags.size());
524-
for (uint32_t Tag : UniqueTags)
525-
Abbreviations.try_emplace(Tag, UniformAttributes);
545+
CompUnits(CompUnits), TypeUnits(TypeUnits),
546+
getIndexForEntry(std::move(getIndexForEntry)) {
547+
populateAbbrevsMap();
526548
}
527549

528550
template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emit() {
529551
Header.emit(*this);
530552
emitCUList();
553+
emitTUList();
531554
emitBuckets();
532555
emitHashes();
533556
emitStringOffsets();
@@ -545,12 +568,17 @@ void llvm::emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents,
545568
AppleAccelTableWriter(Asm, Contents, Atoms, SecBegin).emit();
546569
}
547570

548-
void llvm::emitDWARF5AccelTable(
549-
AsmPrinter *Asm, AccelTable<DWARF5AccelTableData> &Contents,
550-
const DwarfDebug &DD, ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) {
571+
void llvm::emitDWARF5AccelTable(AsmPrinter *Asm,
572+
AccelTable<DWARF5AccelTableData> &Contents,
573+
const DwarfDebug &DD,
574+
ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs,
575+
ArrayRef<std::unique_ptr<DwarfTypeUnit>> TUs) {
551576
std::vector<std::variant<MCSymbol *, uint64_t>> CompUnits;
577+
std::vector<std::variant<MCSymbol *, uint64_t>> TypeUnits;
552578
SmallVector<unsigned, 1> CUIndex(CUs.size());
553-
int Count = 0;
579+
DenseMap<const DIE *, unsigned> TUIndex(TUs.size());
580+
int CUCount = 0;
581+
int TUCount = 0;
554582
for (const auto &CU : enumerate(CUs)) {
555583
switch (CU.value()->getCUNode()->getNameTableKind()) {
556584
case DICompileUnit::DebugNameTableKind::Default:
@@ -559,37 +587,61 @@ void llvm::emitDWARF5AccelTable(
559587
default:
560588
continue;
561589
}
562-
CUIndex[CU.index()] = Count++;
590+
CUIndex[CU.index()] = CUCount++;
563591
assert(CU.index() == CU.value()->getUniqueID());
564592
const DwarfCompileUnit *MainCU =
565593
DD.useSplitDwarf() ? CU.value()->getSkeleton() : CU.value().get();
566594
CompUnits.push_back(MainCU->getLabelBegin());
567595
}
568596

597+
for (const auto &TU : enumerate(TUs)) {
598+
switch (TU.value()->getCUNode()->getNameTableKind()) {
599+
case DICompileUnit::DebugNameTableKind::Default:
600+
break;
601+
default:
602+
continue;
603+
}
604+
TUIndex[&TU.value()->getUnitDie()] = TUCount++;
605+
const DwarfTypeUnit *MainTU = TU.value().get();
606+
TypeUnits.push_back(MainTU->getLabelBegin());
607+
}
608+
569609
if (CompUnits.empty())
570610
return;
571611

572612
Asm->OutStreamer->switchSection(
573613
Asm->getObjFileLowering().getDwarfDebugNamesSection());
574614

575615
Contents.finalize(Asm, "names");
616+
dwarf::Form CUIndexForm =
617+
DIEInteger::BestForm(/*IsSigned*/ false, CompUnits.size() - 1);
618+
dwarf::Form TUIndexForm =
619+
DIEInteger::BestForm(/*IsSigned*/ false, TypeUnits.size() - 1);
576620
Dwarf5AccelTableWriter<DWARF5AccelTableData>(
577-
Asm, Contents, CompUnits,
578-
[&](const DWARF5AccelTableData &Entry) {
621+
Asm, Contents, CompUnits, TypeUnits,
622+
[&](const DWARF5AccelTableData &Entry) -> GetIndexForEntryReturnType {
579623
const DIE *CUDie = Entry.getDie().getUnitDie();
580-
return CUIndex[DD.lookupCU(CUDie)->getUniqueID()];
624+
GetIndexForEntryReturnType Index = std::nullopt;
625+
if (CUDie->getTag() == dwarf::DW_TAG_type_unit)
626+
Index = {TUIndex[CUDie], {dwarf::DW_IDX_type_unit, TUIndexForm}};
627+
else if (CUIndex.size() > 1)
628+
Index = {CUIndex[DD.lookupCU(CUDie)->getUniqueID()],
629+
{dwarf::DW_IDX_compile_unit, CUIndexForm}};
630+
return Index;
581631
})
582632
.emit();
583633
}
584634

585635
void llvm::emitDWARF5AccelTable(
586636
AsmPrinter *Asm, AccelTable<DWARF5AccelTableStaticData> &Contents,
587637
ArrayRef<std::variant<MCSymbol *, uint64_t>> CUs,
588-
llvm::function_ref<unsigned(const DWARF5AccelTableStaticData &)>
589-
getCUIndexForEntry) {
638+
llvm::function_ref<
639+
GetIndexForEntryReturnType(const DWARF5AccelTableStaticData &)>
640+
getIndexForEntry) {
641+
std::vector<std::variant<MCSymbol *, uint64_t>> TypeUnits;
590642
Contents.finalize(Asm, "names");
591-
Dwarf5AccelTableWriter<DWARF5AccelTableStaticData>(Asm, Contents, CUs,
592-
getCUIndexForEntry)
643+
Dwarf5AccelTableWriter<DWARF5AccelTableStaticData>(
644+
Asm, Contents, CUs, TypeUnits, getIndexForEntry)
593645
.emit();
594646
}
595647

0 commit comments

Comments
 (0)