Skip to content

Commit

Permalink
[LLVM][DWARF] Add support for monolithic types in .debug_names (llvm#…
Browse files Browse the repository at this point in the history
…68131)

Added support for Type Units in monolithic DWARF in .debug_names.
  • Loading branch information
ayermolo authored Oct 5, 2023
1 parent f2aac19 commit 9bbd2bf
Show file tree
Hide file tree
Showing 19 changed files with 505 additions and 126 deletions.
35 changes: 28 additions & 7 deletions llvm/include/llvm/CodeGen/AccelTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ namespace llvm {
class AsmPrinter;
class DwarfCompileUnit;
class DwarfDebug;
class DwarfTypeUnit;
class MCSymbol;
class raw_ostream;

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

template <typename... Types>
void addName(DwarfStringPoolEntryRef Name, Types &&... Args);
void clear() { Entries.clear(); }
void addEntries(AccelTable<DataT> &Table);
const StringEntries getEntries() const { return Entries; }
};

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

template <typename AccelTableDataT>
void AccelTable<AccelTableDataT>::addEntries(
AccelTable<AccelTableDataT> &Table) {
for (auto &Entry : Table.getEntries()) {
for (AccelTableData *Value : Entry.second.Values)
addName(Entry.second.Name,
static_cast<AccelTableDataT *>(Value)->getDie());
}
}

/// A base class for different implementations of Data classes for Apple
/// Accelerator Tables. The columns in the table are defined by the static Atoms
/// variable defined on the subclasses.
Expand Down Expand Up @@ -250,6 +264,10 @@ class AppleAccelTableData : public AccelTableData {
/// 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) : Die(Die) {}
Expand Down Expand Up @@ -309,17 +327,20 @@ void emitAppleAccelTable(AsmPrinter *Asm, AccelTable<DataT> &Contents,
void emitDWARF5AccelTable(AsmPrinter *Asm,
AccelTable<DWARF5AccelTableData> &Contents,
const DwarfDebug &DD,
ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs);

ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs,
ArrayRef<std::unique_ptr<DwarfTypeUnit>> TUs);
using GetIndexForEntryReturnType =
std::optional<std::pair<unsigned, DWARF5AccelTableData::AttributeEncoding>>;
/// Emit a DWARFv5 Accelerator Table consisting of entries in the specified
/// AccelTable. The \p CUs contains either symbols keeping offsets to the
/// start of compilation unit, either offsets to the start of compilation
/// unit themselves.
void emitDWARF5AccelTable(
AsmPrinter *Asm, AccelTable<DWARF5AccelTableStaticData> &Contents,
ArrayRef<std::variant<MCSymbol *, uint64_t>> CUs,
llvm::function_ref<unsigned(const DWARF5AccelTableStaticData &)>
getCUIndexForEntry);
void emitDWARF5AccelTable(AsmPrinter *Asm,
AccelTable<DWARF5AccelTableStaticData> &Contents,
ArrayRef<std::variant<MCSymbol *, uint64_t>> CUs,
llvm::function_ref<GetIndexForEntryReturnType(
const DWARF5AccelTableStaticData &)>
getIndexForEntry);

/// Accelerator table data implementation for simple Apple accelerator tables
/// with just a DIE reference.
Expand Down
172 changes: 112 additions & 60 deletions llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#include "llvm/CodeGen/AccelTable.h"
#include "DwarfCompileUnit.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/AsmPrinter.h"
Expand Down Expand Up @@ -200,32 +199,30 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
uint32_t AugmentationStringSize = sizeof(AugmentationString);
char AugmentationString[8] = {'L', 'L', 'V', 'M', '0', '7', '0', '0'};

Header(uint32_t CompUnitCount, uint32_t BucketCount, uint32_t NameCount)
: CompUnitCount(CompUnitCount), BucketCount(BucketCount),
NameCount(NameCount) {}
Header(uint32_t CompUnitCount, uint32_t LocalTypeUnitCount,
uint32_t BucketCount, uint32_t NameCount)
: CompUnitCount(CompUnitCount), LocalTypeUnitCount(LocalTypeUnitCount),
BucketCount(BucketCount), NameCount(NameCount) {}

void emit(Dwarf5AccelTableWriter &Ctx);
};
struct AttributeEncoding {
dwarf::Index Index;
dwarf::Form Form;
};

Header Header;
DenseMap<uint32_t, SmallVector<AttributeEncoding, 2>> Abbreviations;
DenseMap<uint32_t, SmallVector<DWARF5AccelTableData::AttributeEncoding, 2>>
Abbreviations;
ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits;
llvm::function_ref<unsigned(const DataT &)> getCUIndexForEntry;
ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits;
llvm::function_ref<GetIndexForEntryReturnType(const DataT &)>
getIndexForEntry;
MCSymbol *ContributionEnd = nullptr;
MCSymbol *AbbrevStart = Asm->createTempSymbol("names_abbrev_start");
MCSymbol *AbbrevEnd = Asm->createTempSymbol("names_abbrev_end");
MCSymbol *EntryPool = Asm->createTempSymbol("names_entries");

DenseSet<uint32_t> getUniqueTags() const;

// Right now, we emit uniform attributes for all tags.
SmallVector<AttributeEncoding, 2> getUniformAttributes() const;
void populateAbbrevsMap();

void emitCUList() const;
void emitTUList() const;
void emitBuckets() const;
void emitStringOffsets() const;
void emitAbbrevs() const;
Expand All @@ -236,7 +233,9 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
Dwarf5AccelTableWriter(
AsmPrinter *Asm, const AccelTableBase &Contents,
ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits,
llvm::function_ref<unsigned(const DataT &)> GetCUIndexForEntry);
ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits,
llvm::function_ref<GetIndexForEntryReturnType(const DataT &)>
getIndexForEntry);

void emit();
};
Expand Down Expand Up @@ -388,31 +387,39 @@ void Dwarf5AccelTableWriter<DataT>::Header::emit(Dwarf5AccelTableWriter &Ctx) {
Asm->OutStreamer->emitBytes({AugmentationString, AugmentationStringSize});
}

static uint32_t constexpr LowerBitSize = dwarf::DW_IDX_type_hash;
static uint32_t getTagFromAbbreviationTag(const uint32_t AbbrvTag) {
return AbbrvTag >> LowerBitSize;
}
static uint32_t
constructAbbreviationTag(const unsigned Tag,
const GetIndexForEntryReturnType &EntryRet) {
uint32_t AbbrvTag = 0;
if (EntryRet)
AbbrvTag |= 1 << EntryRet->second.Index;
AbbrvTag |= 1 << dwarf::DW_IDX_die_offset;
AbbrvTag |= Tag << LowerBitSize;
return AbbrvTag;
}
template <typename DataT>
DenseSet<uint32_t> Dwarf5AccelTableWriter<DataT>::getUniqueTags() const {
DenseSet<uint32_t> UniqueTags;
void Dwarf5AccelTableWriter<DataT>::populateAbbrevsMap() {
for (auto &Bucket : Contents.getBuckets()) {
for (auto *Hash : Bucket) {
for (auto *Value : Hash->Values) {
GetIndexForEntryReturnType EntryRet =
getIndexForEntry(*static_cast<const DataT *>(Value));
unsigned Tag = static_cast<const DataT *>(Value)->getDieTag();
UniqueTags.insert(Tag);
uint32_t AbbrvTag = constructAbbreviationTag(Tag, EntryRet);
if (Abbreviations.count(AbbrvTag) == 0) {
SmallVector<DWARF5AccelTableData::AttributeEncoding, 2> UA;
if (EntryRet)
UA.push_back(EntryRet->second);
UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
Abbreviations.try_emplace(AbbrvTag, UA);
}
}
}
}
return UniqueTags;
}

template <typename DataT>
SmallVector<typename Dwarf5AccelTableWriter<DataT>::AttributeEncoding, 2>
Dwarf5AccelTableWriter<DataT>::getUniformAttributes() const {
SmallVector<AttributeEncoding, 2> UA;
if (CompUnits.size() > 1) {
size_t LargestCUIndex = CompUnits.size() - 1;
dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false, LargestCUIndex);
UA.push_back({dwarf::DW_IDX_compile_unit, Form});
}
UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
return UA;
}

template <typename DataT>
Expand All @@ -426,6 +433,17 @@ void Dwarf5AccelTableWriter<DataT>::emitCUList() const {
}
}

template <typename DataT>
void Dwarf5AccelTableWriter<DataT>::emitTUList() const {
for (const auto &TU : enumerate(TypeUnits)) {
Asm->OutStreamer->AddComment("Type unit " + Twine(TU.index()));
if (std::holds_alternative<MCSymbol *>(TU.value()))
Asm->emitDwarfSymbolReference(std::get<MCSymbol *>(TU.value()));
else
Asm->emitDwarfLengthOrOffset(std::get<uint64_t>(TU.value()));
}
}

template <typename DataT>
void Dwarf5AccelTableWriter<DataT>::emitBuckets() const {
uint32_t Index = 1;
Expand Down Expand Up @@ -453,10 +471,11 @@ void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const {
Asm->OutStreamer->emitLabel(AbbrevStart);
for (const auto &Abbrev : Abbreviations) {
Asm->OutStreamer->AddComment("Abbrev code");
assert(Abbrev.first != 0);
Asm->emitULEB128(Abbrev.first);
Asm->OutStreamer->AddComment(dwarf::TagString(Abbrev.first));
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(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data());
Asm->emitULEB128(AttrEnc.Form,
Expand All @@ -471,16 +490,21 @@ void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const {

template <typename DataT>
void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const {
auto AbbrevIt = Abbreviations.find(Entry.getDieTag());
GetIndexForEntryReturnType EntryRet = getIndexForEntry(Entry);
uint32_t AbbrvTag = constructAbbreviationTag(Entry.getDieTag(), EntryRet);
auto AbbrevIt = Abbreviations.find(AbbrvTag);
assert(AbbrevIt != Abbreviations.end() &&
"Why wasn't this abbrev generated?");

assert(getTagFromAbbreviationTag(AbbrevIt->first) == Entry.getDieTag() &&
"Invalid Tag");
Asm->emitULEB128(AbbrevIt->first, "Abbreviation code");

for (const auto &AttrEnc : AbbrevIt->second) {
Asm->OutStreamer->AddComment(dwarf::IndexString(AttrEnc.Index));
switch (AttrEnc.Index) {
case dwarf::DW_IDX_compile_unit: {
DIEInteger ID(getCUIndexForEntry(Entry));
case dwarf::DW_IDX_compile_unit:
case dwarf::DW_IDX_type_unit: {
DIEInteger ID(EntryRet->first);
ID.emitValue(Asm, AttrEnc.Form);
break;
}
Expand Down Expand Up @@ -512,22 +536,21 @@ template <typename DataT>
Dwarf5AccelTableWriter<DataT>::Dwarf5AccelTableWriter(
AsmPrinter *Asm, const AccelTableBase &Contents,
ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits,
llvm::function_ref<unsigned(const DataT &)> getCUIndexForEntry)
ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits,
llvm::function_ref<GetIndexForEntryReturnType(const DataT &)>
getIndexForEntry)
: AccelTableWriter(Asm, Contents, false),
Header(CompUnits.size(), Contents.getBucketCount(),
Header(CompUnits.size(), TypeUnits.size(), Contents.getBucketCount(),
Contents.getUniqueNameCount()),
CompUnits(CompUnits), getCUIndexForEntry(std::move(getCUIndexForEntry)) {
DenseSet<uint32_t> UniqueTags = getUniqueTags();
SmallVector<AttributeEncoding, 2> UniformAttributes = getUniformAttributes();

Abbreviations.reserve(UniqueTags.size());
for (uint32_t Tag : UniqueTags)
Abbreviations.try_emplace(Tag, UniformAttributes);
CompUnits(CompUnits), TypeUnits(TypeUnits),
getIndexForEntry(std::move(getIndexForEntry)) {
populateAbbrevsMap();
}

template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emit() {
Header.emit(*this);
emitCUList();
emitTUList();
emitBuckets();
emitHashes();
emitStringOffsets();
Expand All @@ -545,12 +568,17 @@ void llvm::emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents,
AppleAccelTableWriter(Asm, Contents, Atoms, SecBegin).emit();
}

void llvm::emitDWARF5AccelTable(
AsmPrinter *Asm, AccelTable<DWARF5AccelTableData> &Contents,
const DwarfDebug &DD, ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) {
void llvm::emitDWARF5AccelTable(AsmPrinter *Asm,
AccelTable<DWARF5AccelTableData> &Contents,
const DwarfDebug &DD,
ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs,
ArrayRef<std::unique_ptr<DwarfTypeUnit>> TUs) {
std::vector<std::variant<MCSymbol *, uint64_t>> CompUnits;
std::vector<std::variant<MCSymbol *, uint64_t>> TypeUnits;
SmallVector<unsigned, 1> CUIndex(CUs.size());
int Count = 0;
DenseMap<const DIE *, unsigned> TUIndex(TUs.size());
int CUCount = 0;
int TUCount = 0;
for (const auto &CU : enumerate(CUs)) {
switch (CU.value()->getCUNode()->getNameTableKind()) {
case DICompileUnit::DebugNameTableKind::Default:
Expand All @@ -559,37 +587,61 @@ void llvm::emitDWARF5AccelTable(
default:
continue;
}
CUIndex[CU.index()] = Count++;
CUIndex[CU.index()] = CUCount++;
assert(CU.index() == CU.value()->getUniqueID());
const DwarfCompileUnit *MainCU =
DD.useSplitDwarf() ? CU.value()->getSkeleton() : CU.value().get();
CompUnits.push_back(MainCU->getLabelBegin());
}

for (const auto &TU : enumerate(TUs)) {
switch (TU.value()->getCUNode()->getNameTableKind()) {
case DICompileUnit::DebugNameTableKind::Default:
break;
default:
continue;
}
TUIndex[&TU.value()->getUnitDie()] = TUCount++;
const DwarfTypeUnit *MainTU = TU.value().get();
TypeUnits.push_back(MainTU->getLabelBegin());
}

if (CompUnits.empty())
return;

Asm->OutStreamer->switchSection(
Asm->getObjFileLowering().getDwarfDebugNamesSection());

Contents.finalize(Asm, "names");
dwarf::Form CUIndexForm =
DIEInteger::BestForm(/*IsSigned*/ false, CompUnits.size() - 1);
dwarf::Form TUIndexForm =
DIEInteger::BestForm(/*IsSigned*/ false, TypeUnits.size() - 1);
Dwarf5AccelTableWriter<DWARF5AccelTableData>(
Asm, Contents, CompUnits,
[&](const DWARF5AccelTableData &Entry) {
Asm, Contents, CompUnits, TypeUnits,
[&](const DWARF5AccelTableData &Entry) -> GetIndexForEntryReturnType {
const DIE *CUDie = Entry.getDie().getUnitDie();
return CUIndex[DD.lookupCU(CUDie)->getUniqueID()];
GetIndexForEntryReturnType Index = std::nullopt;
if (CUDie->getTag() == dwarf::DW_TAG_type_unit)
Index = {TUIndex[CUDie], {dwarf::DW_IDX_type_unit, TUIndexForm}};
else if (CUIndex.size() > 1)
Index = {CUIndex[DD.lookupCU(CUDie)->getUniqueID()],
{dwarf::DW_IDX_compile_unit, CUIndexForm}};
return Index;
})
.emit();
}

void llvm::emitDWARF5AccelTable(
AsmPrinter *Asm, AccelTable<DWARF5AccelTableStaticData> &Contents,
ArrayRef<std::variant<MCSymbol *, uint64_t>> CUs,
llvm::function_ref<unsigned(const DWARF5AccelTableStaticData &)>
getCUIndexForEntry) {
llvm::function_ref<
GetIndexForEntryReturnType(const DWARF5AccelTableStaticData &)>
getIndexForEntry) {
std::vector<std::variant<MCSymbol *, uint64_t>> TypeUnits;
Contents.finalize(Asm, "names");
Dwarf5AccelTableWriter<DWARF5AccelTableStaticData>(Asm, Contents, CUs,
getCUIndexForEntry)
Dwarf5AccelTableWriter<DWARF5AccelTableStaticData>(
Asm, Contents, CUs, TypeUnits, getIndexForEntry)
.emit();
}

Expand Down
Loading

0 comments on commit 9bbd2bf

Please sign in to comment.