Index: lib/CodeGen/AsmPrinter/DwarfAccelTable.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfAccelTable.h +++ lib/CodeGen/AsmPrinter/DwarfAccelTable.h @@ -166,17 +166,49 @@ 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"; + HashDataContents(const DIE *D) : Die(D) {} + + /// \brief Get the start of the Atom storage. + /// Atoms are stored right after the HashDataContents object in memory. + char *getAtomData() const { + return (char *)(void *)(this + 1); } + + /// \brief Get the atom of type AtomT at \p Offset in the Atom data. + template + AtomT getAtom(unsigned int Offset) const { + AtomT Atom; + memcpy(&Atom, getAtomData() + Offset, sizeof(AtomT)); + return Atom; + } + +#ifndef NDEBUG + void print(raw_ostream &O, + const DwarfAccelTable::TableHeaderData &Header) const; #endif }; + + class HashDataContentsRef { + const HashDataContents &Contents; ///< The entry we are populating + const DwarfAccelTable &Table; ///< The table that owns us + uint16_t AtomBytePos; ///< Byte position of the next Atom + uint8_t AtomPos; ///< Index of the next Atom + + public: + HashDataContentsRef(HashDataContents &Contents, DwarfAccelTable &Table) + : Contents(Contents), Table(Table), AtomBytePos(0), AtomPos(1) {} + + template + HashDataContentsRef addAtom(AtomT Atom) { + assert(AtomBytePos + sizeof(AtomT) <= Table.getAtomsSize()); + assert(Table.checkAtomSize(AtomPos, sizeof(AtomT))); + memcpy(Contents.getAtomData() + AtomBytePos, &Atom, sizeof(AtomT)); + ++AtomPos; + AtomBytePos += sizeof(AtomT); + return *this; + } + }; private: // String Data @@ -196,7 +228,7 @@ HashValue = DwarfAccelTable::HashDJB(S); } #ifndef NDEBUG - void print(raw_ostream &O) { + void print(raw_ostream &O, TableHeaderData& Atoms) { O << "Name: " << Str << "\n"; O << " Hash Value: " << format("0x%x", HashValue) << "\n"; O << " Symbol: "; @@ -205,13 +237,10 @@ 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 (HashDataContents *C : Data.Values) + C->print(O, Atoms); } - void dump() { print(dbgs()); } + void dump(TableHeaderData& Atoms) { print(dbgs(), Atoms); } #endif }; @@ -241,15 +270,17 @@ typedef std::vector BucketList; BucketList Buckets; HashList Hashes; + unsigned AtomsSize; // Public Implementation public: DwarfAccelTable(ArrayRef); - void AddName(StringRef Name, MCSymbol *StrSym, const DIE *Die, - char Flags = 0); + HashDataContentsRef AddName(StringRef Name, MCSymbol *StrSym, const DIE *Die); void FinalizeTable(AsmPrinter *, StringRef); void Emit(AsmPrinter *, MCSymbol *, DwarfDebug *, MCSymbol *StrSym); + unsigned getAtomsSize() const { return AtomsSize; } #ifndef NDEBUG + bool checkAtomSize(unsigned Index, unsigned ByteSize) const; void print(raw_ostream &O); void dump() { print(dbgs()); } #endif Index: lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp +++ lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp @@ -25,20 +25,47 @@ using namespace llvm; +static unsigned getSizeForForm(uint16_t Form) { + switch (Form) { + case dwarf::DW_FORM_data1: return 1; + case dwarf::DW_FORM_data2: return 2; + case dwarf::DW_FORM_data4: return 4; + case dwarf::DW_FORM_data8: return 8; + default: llvm_unreachable("Unsupported atom type"); + } +} + // 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) {} + Entries(Allocator), AtomsSize(0) { + assert(atomList[0].type == dwarf::DW_ATOM_die_offset && + atomList[0].form == dwarf::DW_FORM_data4); + for (const auto &Atom : atomList.slice(1)) + AtomsSize += getSizeForForm(Atom.form); +} -void DwarfAccelTable::AddName(StringRef Name, MCSymbol *StrSym, const DIE *die, - char Flags) { +#ifndef NDEBUG +bool DwarfAccelTable::checkAtomSize(unsigned Index, unsigned ByteSize) const { + if (Index >= HeaderData.Atoms.size()) + return false; + return getSizeForForm(HeaderData.Atoms[Index].form) == ByteSize; +} +#endif + +DwarfAccelTable::HashDataContentsRef +DwarfAccelTable::AddName(StringRef Name, MCSymbol *StrSym, 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]; assert(!DIEs.StrSym || DIEs.StrSym == StrSym); DIEs.StrSym = StrSym; - DIEs.Values.push_back(new (Allocator) HashDataContents(die, Flags)); + void *HashDataMem = Allocator.Allocate(sizeof(HashDataContents) + AtomsSize, + alignof(HashDataContents)); + auto *HD = new (HashDataMem) HashDataContents(die); + DIEs.Values.push_back(HD); + return HashDataContentsRef(*HD, *this); } void DwarfAccelTable::ComputeBucketCount(void) { @@ -226,10 +253,27 @@ 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); + unsigned AtomOffset = 0; + for (const auto &Atom : makeArrayRef(HeaderData.Atoms.data() + 1, + HeaderData.Atoms.size() - 1)) { + switch (Atom.form) { + case dwarf::DW_FORM_data1: + Asm->EmitInt8(HD->getAtom(AtomOffset)); + AtomOffset += 1; + break; + case dwarf::DW_FORM_data2: + Asm->EmitInt16(HD->getAtom(AtomOffset)); + AtomOffset += 2; + break; + case dwarf::DW_FORM_data4: + Asm->EmitInt32(HD->getAtom(AtomOffset)); + AtomOffset += 4; + break; + case dwarf::DW_FORM_data8: + Asm->OutStreamer.EmitIntValue(HD->getAtom(AtomOffset), 8); + AtomOffset += 8; + break; + } } } PrevHash = (*HI)->HashValue; @@ -271,7 +315,7 @@ EI != EE; ++EI) { O << "Name: " << EI->getKeyData() << "\n"; for (HashDataContents *HD : EI->second.Values) - HD->print(O); + HD->print(O, HeaderData); } O << "Buckets and Hashes: \n"; @@ -279,12 +323,43 @@ for (HashList::const_iterator HI = Buckets[i].begin(), HE = Buckets[i].end(); HI != HE; ++HI) - (*HI)->print(O); + (*HI)->print(O, HeaderData); O << "Data: \n"; for (std::vector::const_iterator DI = Data.begin(), DE = Data.end(); DI != DE; ++DI) - (*DI)->print(O); + (*DI)->print(O, HeaderData); +} + +void DwarfAccelTable::HashDataContents::print( + raw_ostream &O, const DwarfAccelTable::TableHeaderData &Header) 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())) { + O << " Atom[" << Idx++ << "]: type " << Atom.type << " value: "; + switch (getSizeForForm(Atom.form)) { + case 1: + format("0x%02x\n", (int)getAtom(Offset)); + Offset += 1; + break; + case 2: + format("0x%04x\n", getAtom(Offset)); + Offset += 2; + break; + case 4: + format("0x%08x\n", getAtom(Offset)); + Offset += 4; + break; + case 8: + format("0x%016" PRIx64 "\n", getAtom(Offset)); + Offset += 2; + break; + } + } } #endif Index: lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -2132,5 +2132,5 @@ if (!useDwarfAccelTables()) return; AccelTypes.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name), - &Die); + &Die).addAtom(Die.getTag()).addAtom(0); }