Index: lib/CodeGen/AsmPrinter/DwarfAccelTable.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfAccelTable.h +++ lib/CodeGen/AsmPrinter/DwarfAccelTable.h @@ -165,20 +165,13 @@ // HashData[hash_data_count] public: struct HashDataContents { - const DIE *Die; // Offsets - char Flags; // Specific flags to output - - HashDataContents(const DIE *D, char Flags) : Die(D), Flags(Flags) {} -#ifndef NDEBUG - void print(raw_ostream &O) const { - O << " Offset: " << Die->getOffset() << "\n"; - O << " Tag: " << dwarf::TagString(Die->getTag()) << "\n"; - O << " Flags: " << Flags << "\n"; - } -#endif + virtual void emit(AsmPrinter *Asm, DwarfDebug *D) const = 0; + virtual bool less(const HashDataContents *Other) const = 0; + virtual void print(raw_ostream &OS) const = 0; + virtual ~HashDataContents(); }; -private: +protected: // String Data struct DataArray { DwarfStringPoolEntryRef Name; @@ -204,11 +197,8 @@ else O << ""; O << "\n"; - for (HashDataContents *C : Data.Values) { - O << " Offset: " << C->Die->getOffset() << "\n"; - O << " Tag: " << dwarf::TagString(C->Die->getTag()) << "\n"; - O << " Flags: " << C->Flags << "\n"; - } + for (auto *C : Data.Values) + C->print(O); } void dump() { print(dbgs()); } #endif @@ -224,6 +214,7 @@ void emitOffsets(AsmPrinter *, const MCSymbol *); void EmitData(AsmPrinter *, DwarfDebug *D); +protected: // Allocator for HashData and HashDataContents. BumpPtrAllocator Allocator; @@ -232,6 +223,7 @@ TableHeaderData HeaderData; std::vector Data; + // This map needs to be filled by subclasses. typedef StringMap StringEntries; StringEntries Entries; @@ -241,10 +233,9 @@ BucketList Buckets; HashList Hashes; - // Public Implementation -public: DwarfAccelTable(ArrayRef); - void AddName(DwarfStringPoolEntryRef Name, const DIE *Die, char Flags = 0); + +public: void FinalizeTable(AsmPrinter *, StringRef); void emit(AsmPrinter *, const MCSymbol *, DwarfDebug *); #ifndef NDEBUG @@ -252,5 +243,16 @@ void dump() { print(dbgs()); } #endif }; + +class DIEDwarfAccelTable : public DwarfAccelTable { + bool IsType; + +public: + /// Construct a DIE accelerator table. \p IsType is true if it will + /// be emitted as a type accelerator table. + DIEDwarfAccelTable(bool IsType = false); + + void AddName(DwarfStringPoolEntryRef Name, const DIE *Die); +}; } #endif Index: lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp +++ lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp @@ -25,22 +25,72 @@ using namespace llvm; -// The length of the header data is always going to be 4 + 4 + 4*NumAtoms. -DwarfAccelTable::DwarfAccelTable(ArrayRef atomList) - : Header(8 + (atomList.size() * 4)), HeaderData(atomList), - Entries(Allocator) {} +DwarfAccelTable::HashDataContents::~HashDataContents() {} -void DwarfAccelTable::AddName(DwarfStringPoolEntryRef Name, const DIE *die, - char Flags) { +template +class DIEHashDataContents : public DwarfAccelTable::HashDataContents { + const DIE *Die; + +public: + DIEHashDataContents(const DIE *Die) : Die(Die) {} + + void emit(AsmPrinter *Asm, DwarfDebug *D) const override { + // Emit the DIE offset + DwarfCompileUnit *CU = D->lookupUnit(Die->getUnit()); + assert(CU && "Accelerated DIE should belong to a CU."); + Asm->EmitInt32(Die->getOffset() + CU->getDebugInfoOffset()); + if (IsType) { + Asm->EmitInt16(Die->getTag()); + Asm->EmitInt8(0); // Flags + } + } + + bool less(const HashDataContents *Other) const override { + return Die->getOffset() < HD->Die->getOffset(); + } + + void print(raw_ostream &OS) const override { + OS << " Offset: " << Die->getOffset() << "\n"; + if (IsType) { + OS << " Tag: " << dwarf::TagString(Die->getTag()) << "\n"; + OS << " Flags: 0\n"; + } + } +}; + +static LLVM_CONSTEXPR DwarfAccelTable::Atom DieAtoms[] = { + DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)}; + +static LLVM_CONSTEXPR DwarfAccelTable::Atom TypeAtoms[] = { + DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), + DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), + DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)}; + +DIEDwarfAccelTable::DIEDwarfAccelTable(bool IsType) + : DwarfAccelTable(IsType ? makeArrayRef(TypeAtoms) + : makeArrayRef(DieAtoms)), + IsType(IsType) {} + +void DIEDwarfAccelTable::AddName(DwarfStringPoolEntryRef Name, const DIE *Die) { assert(Data.empty() && "Already finalized!"); // If the string is in the list already then add this die to the list // otherwise add a new one. DataArray &DIEs = Entries[Name.getString()]; assert(!DIEs.Name || DIEs.Name == Name); DIEs.Name = Name; - DIEs.Values.push_back(new (Allocator) HashDataContents(die, Flags)); + HashDataContents *HD; + if (IsType) + HD = new (Allocator) DIEHashDataContents(Die); + else + HD = new (Allocator) DIEHashDataContents(Die); + DIEs.Values.push_back(HD); } +// The length of the header data is always going to be 4 + 4 + 4*NumAtoms. +DwarfAccelTable::DwarfAccelTable(ArrayRef atomList) + : Header(8 + (atomList.size() * 4)), HeaderData(atomList), + Entries(Allocator) {} + void DwarfAccelTable::ComputeBucketCount(void) { // First get the number of unique hashes. std::vector uniques(Data.size()); @@ -62,12 +112,6 @@ Header.hashes_count = num; } -// compareDIEs - comparison predicate that sorts DIEs by their offset. -static bool compareDIEs(const DwarfAccelTable::HashDataContents *A, - const DwarfAccelTable::HashDataContents *B) { - return A->Die->getOffset() < B->Die->getOffset(); -} - void DwarfAccelTable::FinalizeTable(AsmPrinter *Asm, StringRef Prefix) { // Create the individual hash data outputs. Data.reserve(Entries.size()); @@ -75,7 +119,10 @@ EI != EE; ++EI) { // Unique the entries. - std::stable_sort(EI->second.Values.begin(), EI->second.Values.end(), compareDIEs); + std::stable_sort( + EI->second.Values.begin(), EI->second.Values.end(), + [](const DwarfAccelTable::HashDataContents *A, + const DwarfAccelTable::HashDataContents *B) { return A->less(B); }); EI->second.Values.erase( std::unique(EI->second.Values.begin(), EI->second.Values.end()), EI->second.Values.end()); @@ -219,18 +266,8 @@ Asm->emitDwarfStringOffset((*HI)->Data.Name); 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()); - // If we have multiple Atoms emit that info too. - // FIXME: A bit of a hack, we either emit only one atom or all info. - if (HeaderData.Atoms.size() > 1) { - Asm->EmitInt16(HD->Die->getTag()); - Asm->EmitInt8(HD->Flags); - } - } + for (HashDataContents *HD : (*HI)->Data.Values) + HD->emit(Asm, D); PrevHash = (*HI)->HashValue; } // Emit the final end marker for the bucket. Index: lib/CodeGen/AsmPrinter/DwarfDebug.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.h +++ lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -366,10 +366,10 @@ AddressPool AddrPool; - DwarfAccelTable AccelNames; - DwarfAccelTable AccelObjC; - DwarfAccelTable AccelNamespace; - DwarfAccelTable AccelTypes; + DIEDwarfAccelTable AccelNames; + DIEDwarfAccelTable AccelObjC; + DIEDwarfAccelTable AccelNamespace; + DIEDwarfAccelTable AccelTypes; DenseMap FunctionDIs; @@ -423,7 +423,7 @@ void emitAbbreviations(); /// Emit a specified accelerator table. - void emitAccel(DwarfAccelTable &Accel, MCSection *Section, + void emitAccel(DIEDwarfAccelTable &Accel, MCSection *Section, StringRef TableName); /// Emit visible names into a hashed accelerator table section. Index: lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -197,24 +197,14 @@ return Ty; } -static LLVM_CONSTEXPR DwarfAccelTable::Atom TypeAtoms[] = { - DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), - DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), - DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)}; - DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) : Asm(A), MMI(Asm->MMI), DebugLocs(A->OutStreamer->isVerboseAsm()), PrevLabel(nullptr), InfoHolder(A, "info_string", DIEValueAllocator), UsedNonDefaultText(false), SkeletonHolder(A, "skel_string", DIEValueAllocator), - IsDarwin(Triple(A->getTargetTriple()).isOSDarwin()), - AccelNames(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, - dwarf::DW_FORM_data4)), - AccelObjC(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, - dwarf::DW_FORM_data4)), - AccelNamespace(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, - dwarf::DW_FORM_data4)), - AccelTypes(TypeAtoms), DebuggerTuning(DebuggerKind::Default) { + IsDarwin(Triple(A->getTargetTriple()).isOSDarwin()), AccelNames(), + AccelObjC(), AccelNamespace(), AccelTypes(/* IsType =*/true), + DebuggerTuning(DebuggerKind::Default) { CurFn = nullptr; CurMI = nullptr; @@ -1314,7 +1304,7 @@ Holder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection()); } -void DwarfDebug::emitAccel(DwarfAccelTable &Accel, MCSection *Section, +void DwarfDebug::emitAccel(DIEDwarfAccelTable &Accel, MCSection *Section, StringRef TableName) { Accel.FinalizeTable(Asm, TableName); Asm->OutStreamer->SwitchSection(Section);