Index: lib/CodeGen/AsmPrinter/DwarfAccelTable.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfAccelTable.h +++ lib/CodeGen/AsmPrinter/DwarfAccelTable.h @@ -165,9 +165,12 @@ // HashData[hash_data_count] public: struct HashDataContents { - const DIE *Die; // Offsets - + union { + const DIE *Die; ///< The DIE. + uint32_t DieOffset; ///< Offset of the DIE in debug_info. + }; HashDataContents(const DIE *D) : Die(D) {} + HashDataContents(uint32_t Offset) : DieOffset(Offset) {} /// \brief Get the start of the Atom storage. /// Atoms are stored right after the HashDataContents object in memory. @@ -184,8 +187,7 @@ } #ifndef NDEBUG - void print(raw_ostream &O, - const DwarfAccelTable::TableHeaderData &Header) const; + void print(raw_ostream &O, const DwarfAccelTable &Table) const; #endif }; @@ -213,7 +215,10 @@ private: // String Data struct DataArray { - MCSymbol *StrSym; + union { + MCSymbol *StrSym; ///< Symbol of the string in debug_str. + uint32_t StrOffset; /// Values; DataArray() : StrSym(nullptr) {} }; @@ -228,7 +233,7 @@ HashValue = DwarfAccelTable::HashDJB(S); } #ifndef NDEBUG - void print(raw_ostream &O, TableHeaderData& Atoms) { + void print(raw_ostream &O, DwarfAccelTable& Table) { O << "Name: " << Str << "\n"; O << " Hash Value: " << format("0x%x", HashValue) << "\n"; O << " Symbol: "; @@ -238,9 +243,9 @@ O << ""; O << "\n"; for (HashDataContents *C : Data.Values) - C->print(O, Atoms); + C->print(O, Table); } - void dump(TableHeaderData& Atoms) { print(dbgs(), Atoms); } + void dump(DwarfAccelTable& Table) { print(dbgs(), Table); } #endif }; @@ -271,14 +276,22 @@ BucketList Buckets; HashList Hashes; unsigned AtomsSize; - + bool UseDieOffsets; + bool UseStringOffsets; + // Public Implementation public: - DwarfAccelTable(ArrayRef); + DwarfAccelTable(ArrayRef, bool UseDieOffset = false, + bool UseStringOffsets = false); HashDataContentsRef AddName(StringRef Name, MCSymbol *StrSym, const DIE *Die); + HashDataContentsRef AddName(StringRef Name, uint32_t StrOffset, + uint32_t DIeOffset); void FinalizeTable(AsmPrinter *, StringRef); void Emit(AsmPrinter *, MCSymbol *, DwarfDebug *, MCSymbol *StrSym); unsigned getAtomsSize() const { return AtomsSize; } + bool useDieOffssets() const { return UseDieOffsets; } + bool useStringOffssets() const { return UseStringOffsets; } + const TableHeaderData &getHeaderData() const { return HeaderData; } #ifndef NDEBUG bool checkAtomSize(unsigned Index, unsigned ByteSize) const; void print(raw_ostream &O); Index: lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp +++ lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp @@ -36,9 +36,11 @@ } // The length of the header data is always going to be 4 + 4 + 4*NumAtoms. -DwarfAccelTable::DwarfAccelTable(ArrayRef atomList) +DwarfAccelTable::DwarfAccelTable(ArrayRef atomList, + bool UseDieOffsets, bool UseStringOffsets) : Header(8 + (atomList.size() * 4)), HeaderData(atomList), - Entries(Allocator), AtomsSize(0) { + Entries(Allocator), AtomsSize(0), UseDieOffsets(UseDieOffsets), + UseStringOffsets(UseStringOffsets) { assert(atomList[0].type == dwarf::DW_ATOM_die_offset && atomList[0].form == dwarf::DW_FORM_data4); for (const auto &Atom : atomList.slice(1)) @@ -56,6 +58,8 @@ DwarfAccelTable::HashDataContentsRef DwarfAccelTable::AddName(StringRef Name, MCSymbol *StrSym, const DIE *die) { assert(Data.empty() && "Already finalized!"); + assert(!UseDieOffsets && "Mismatch between AddName and mode."); + assert(!UseStringOffsets && "Mismatch between AddName and mode."); // If the string is in the list already then add this die to the list // otherwise add a new one. DataArray &DIEs = Entries[Name]; @@ -68,6 +72,23 @@ return HashDataContentsRef(*HD, *this); } +DwarfAccelTable::HashDataContentsRef +DwarfAccelTable::AddName(StringRef Name, uint32_t StrOffset, uint32_t Offset) { + assert(Data.empty() && "Already finalized!"); + assert(UseDieOffsets && "Mismatch between AddName and mode."); + assert(UseStringOffsets && "Mismatch between AddName and mode."); + // If the string is in the list already then add this die to the list + // otherwise add a new one. + DataArray &DIEs = Entries[Name]; + assert(DIEs.Values.empty() || DIEs.StrOffset == StrOffset); + DIEs.StrOffset = StrOffset; + void *HashDataMem = Allocator.Allocate(sizeof(HashDataContents) + AtomsSize, + alignof(HashDataContents)); + auto *HD = new (HashDataMem) HashDataContents(Offset); + DIEs.Values.push_back(HD); + return HashDataContentsRef(*HD, *this); +} + void DwarfAccelTable::ComputeBucketCount(void) { // First get the number of unique hashes. std::vector uniques(Data.size()); @@ -95,6 +116,12 @@ return A->Die->getOffset() < B->Die->getOffset(); } +// \brief Compare DIE offsets. Table must be in useDieOffsets mode. +static bool compareOffsets(const DwarfAccelTable::HashDataContents *A, + const DwarfAccelTable::HashDataContents *B) { + return A->DieOffset < B->DieOffset; +} + void DwarfAccelTable::FinalizeTable(AsmPrinter *Asm, StringRef Prefix) { // Create the individual hash data outputs. Data.reserve(Entries.size()); @@ -102,7 +129,8 @@ EI != EE; ++EI) { // Unique the entries. - std::stable_sort(EI->second.Values.begin(), EI->second.Values.end(), compareDIEs); + auto *Comparator = UseDieOffsets ? compareOffsets : compareDIEs; + std::stable_sort(EI->second.Values.begin(), EI->second.Values.end(), Comparator); EI->second.Values.erase( std::unique(EI->second.Values.begin(), EI->second.Values.end()), EI->second.Values.end()); @@ -232,6 +260,8 @@ // Terminate each HashData bucket with 0. void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfDebug *D, MCSymbol *StrSym) { + assert(!(UseStringOffsets && StrSym)); + assert(!(UseDieOffsets && D)); for (size_t i = 0, e = Buckets.size(); i < e; ++i) { uint64_t PrevHash = UINT64_MAX; for (HashList::const_iterator HI = Buckets[i].begin(), @@ -244,14 +274,23 @@ // Remember to emit the label for our offset. Asm->OutStreamer.EmitLabel((*HI)->Sym); Asm->OutStreamer.AddComment((*HI)->Str); - Asm->EmitSectionOffset((*HI)->Data.StrSym, StrSym); + if (UseStringOffsets) + Asm->EmitInt32((*HI)->Data.StrOffset); + else + Asm->EmitSectionOffset((*HI)->Data.StrSym, StrSym); Asm->OutStreamer.AddComment("Num DIEs"); Asm->EmitInt32((*HI)->Data.Values.size()); for (HashDataContents *HD : (*HI)->Data.Values) { // Emit the DIE offset - DwarfCompileUnit *CU = D->lookupUnit(HD->Die->getUnit()); - assert(CU && "Accelerated DIE should belong to a CU."); - Asm->EmitInt32(HD->Die->getOffset() + CU->getDebugInfoOffset()); + uint32_t Offset; + if (UseDieOffsets) { + Offset = HD->DieOffset; + } else { + DwarfCompileUnit *CU = D->lookupUnit(HD->Die->getUnit()); + assert(CU && "Accelerated DIE should belong to a CU."); + Offset = HD->Die->getOffset() + CU->getDebugInfoOffset(); + } + Asm->EmitInt32(Offset); // If we have multiple Atoms emit that info too. unsigned AtomOffset = 0; for (const auto &Atom : makeArrayRef(HeaderData.Atoms.data() + 1, @@ -315,7 +354,7 @@ EI != EE; ++EI) { O << "Name: " << EI->getKeyData() << "\n"; for (HashDataContents *HD : EI->second.Values) - HD->print(O, HeaderData); + HD->print(O, *this); } O << "Buckets and Hashes: \n"; @@ -323,24 +362,24 @@ for (HashList::const_iterator HI = Buckets[i].begin(), HE = Buckets[i].end(); HI != HE; ++HI) - (*HI)->print(O, HeaderData); + (*HI)->print(O, *this); O << "Data: \n"; for (std::vector::const_iterator DI = Data.begin(), DE = Data.end(); DI != DE; ++DI) - (*DI)->print(O, HeaderData); + (*DI)->print(O, *this); } void DwarfAccelTable::HashDataContents::print( - raw_ostream &O, const DwarfAccelTable::TableHeaderData &Header) const { + raw_ostream &O, const DwarfAccelTable &Table) const { O << " Offset: " << Die->getOffset() << "\n"; O << " Tag: " << dwarf::TagString(Die->getTag()) << "\n"; unsigned Offset = 0; unsigned Idx = 0; - assert(!Header.Atoms.empty()); - for (const auto &Atom : make_range(Header.Atoms.begin()+1, - Header.Atoms.end())) { + assert(!Table.getHeaderData().Atoms.empty()); + for (const auto &Atom : make_range(Table.getHeaderData().Atoms.begin()+1, + Table.getHeaderData().Atoms.end())) { O << " Atom[" << Idx++ << "]: type " << Atom.type << " value: "; switch (getSizeForForm(Atom.form)) { case 1: