-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[LLVM][DWARF] Add support for monolithic types in .debug_names #68131
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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" | ||
|
@@ -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; | ||
|
@@ -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(); | ||
}; | ||
|
@@ -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> | ||
|
@@ -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; | ||
|
@@ -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, | ||
|
@@ -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; | ||
} | ||
|
@@ -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(); | ||
|
@@ -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: | ||
|
@@ -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; | ||
} | ||
Comment on lines
+598
to
+603
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems a bit convoluted (unless there's an expectation to add more here) compared to:
|
||
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(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
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(); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this using
enumerate
if it's only using the values anyway? Perhaps this could iterate overTUs
directly instead?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was following the example of CUs iteration to try to keep coding style consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't a stylistic thing in this case - the CU iteration needed indexes, so it used
enumerate
, whereas the TU iteration doesn't need them, so it shouldn't useenumerate
, I think.(but, again, happy to wait on resolving a bunch of this stuff until we better understand the general approach/memory concerns, etc)