diff --git a/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp b/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp index 6c77a631a92..940592ed26b 100644 --- a/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp @@ -42,16 +42,22 @@ DwarfAccelTable::DwarfAccelTable(DwarfAccelTable::Atom atom) : HeaderData(atom) { } +// The length of the header data is always going to be 4 + 4 + 4*NumAtoms. +DwarfAccelTable::DwarfAccelTable(std::vector &atomList) : + Header(8 + (atomList.size() * 4)), + HeaderData(atomList) { +} + DwarfAccelTable::~DwarfAccelTable() { - for (size_t i = 0, e = Data.size() ; i < e; ++i) + for (size_t i = 0, e = Data.size(); i < e; ++i) delete Data[i]; } -void DwarfAccelTable::AddName(StringRef Name, DIE* die) { +void DwarfAccelTable::AddName(StringRef Name, DIE* die, char Flags) { // If the string is in the list already then add this die to the list // otherwise add a new one. - DIEArray &DIEs = Entries[Name]; - DIEs.push_back(die); + DataArray &DIEs = Entries[Name]; + DIEs.push_back(new HashDataContents(die, Flags)); } void DwarfAccelTable::ComputeBucketCount(void) { @@ -76,15 +82,16 @@ void DwarfAccelTable::ComputeBucketCount(void) { namespace { // DIESorter - comparison predicate that sorts DIEs by their offset. struct DIESorter { - bool operator()(DIE *A, DIE *B) const { - return A->getOffset() < B->getOffset(); + bool operator()(const struct DwarfAccelTable::HashDataContents *A, + const struct DwarfAccelTable::HashDataContents *B) const { + return A->Die->getOffset() < B->Die->getOffset(); } }; } void DwarfAccelTable::FinalizeTable(AsmPrinter *Asm, const char *Prefix) { // Create the individual hash data outputs. - for (StringMap::iterator + for (StringMap::iterator EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) { struct HashData *Entry = new HashData((*EI).getKeyData()); @@ -93,10 +100,10 @@ void DwarfAccelTable::FinalizeTable(AsmPrinter *Asm, const char *Prefix) { (*EI).second.erase(std::unique((*EI).second.begin(), (*EI).second.end()), (*EI).second.end()); - for (DIEArray::const_iterator DI = (*EI).second.begin(), + for (DataArray::const_iterator DI = (*EI).second.begin(), DE = (*EI).second.end(); DI != DE; ++DI) - Entry->addOffset((*DI)->getOffset()); + Entry->addData((*DI)); Data.push_back(Entry); } @@ -202,11 +209,18 @@ void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfDebug *D) { Asm->EmitSectionOffset(D->getStringPoolEntry((*HI)->Str), D->getStringPool()); Asm->OutStreamer.AddComment("Num DIEs"); - Asm->EmitInt32((*HI)->DIEOffsets.size()); - for (std::vector::const_iterator - DI = (*HI)->DIEOffsets.begin(), DE = (*HI)->DIEOffsets.end(); + Asm->EmitInt32((*HI)->Data.size()); + for (std::vector::const_iterator + DI = (*HI)->Data.begin(), DE = (*HI)->Data.end(); DI != DE; ++DI) { - Asm->EmitInt32((*DI)); + // Emit the DIE offset + Asm->EmitInt32((*DI)->Die->getOffset()); + // 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((*DI)->Die->getTag()); + Asm->EmitInt8((*DI)->Flags); + } } // Emit a 0 to terminate the data unless we have a hash collision. if (PrevHash != (*HI)->HashValue) @@ -242,10 +256,10 @@ void DwarfAccelTable::print(raw_ostream &O) { HeaderData.print(O); O << "Entries: \n"; - for (StringMap::const_iterator + for (StringMap::const_iterator EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) { O << "Name: " << (*EI).getKeyData() << "\n"; - for (DIEArray::const_iterator DI = (*EI).second.begin(), + for (DataArray::const_iterator DI = (*EI).second.begin(), DE = (*EI).second.end(); DI != DE; ++DI) (*DI)->print(O); diff --git a/lib/CodeGen/AsmPrinter/DwarfAccelTable.h b/lib/CodeGen/AsmPrinter/DwarfAccelTable.h index 0c1e949c7f2..464ada48474 100644 --- a/lib/CodeGen/AsmPrinter/DwarfAccelTable.h +++ b/lib/CodeGen/AsmPrinter/DwarfAccelTable.h @@ -22,6 +22,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" +#include "DIE.h" #include #include @@ -134,6 +135,14 @@ public: eAtomTypeTypeFlags = 5u // Flags from enum TypeFlags }; + enum TypeFlags { + eTypeFlagClassMask = 0x0000000fu, + + // Always set for C++, only set for ObjC if this is the + // @implementation for a class. + eTypeFlagClassIsImplementation = ( 1u << 1 ) + }; + // Make these public so that they can be used as a general interface to // the class. struct Atom { @@ -144,7 +153,7 @@ public: static const char * AtomTypeString(enum AtomType); #ifndef NDEBUG void print(raw_ostream &O) { - O << "Type: " << dwarf::TagString(type) << "\n" + O << "Type: " << AtomTypeString(type) << "\n" << "Form: " << dwarf::FormEncodingString(form) << "\n"; } void dump() { @@ -159,6 +168,13 @@ public: uint32_t die_offset_base; std::vector Atoms; + TableHeaderData(std::vector &AtomList, + uint32_t offset = 0) : + die_offset_base(offset) { + for (size_t i = 0, e = AtomList.size(); i != e; ++i) + Atoms.push_back(AtomList[i]); + } + TableHeaderData(DwarfAccelTable::Atom Atom, uint32_t offset = 0) : die_offset_base(offset) { Atoms.push_back(Atom); @@ -184,15 +200,32 @@ public: // uint32_t str_offset // uint32_t hash_data_count // HashData[hash_data_count] +public: + struct HashDataContents { + DIE *Die; // Offsets + char Flags; // Specific flags to output + + HashDataContents(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 + }; +private: struct HashData { StringRef Str; uint32_t HashValue; MCSymbol *Sym; - std::vector DIEOffsets; // offsets + std::vector Data; // offsets HashData(StringRef S) : Str(S) { HashValue = DwarfAccelTable::HashDJB(S); } - void addOffset(uint32_t off) { DIEOffsets.push_back(off); } + void addData(struct HashDataContents *Datum) { Data.push_back(Datum); } #ifndef NDEBUG void print(raw_ostream &O) { O << "Name: " << Str << "\n"; @@ -201,8 +234,11 @@ public: if (Sym) Sym->print(O); else O << ""; O << "\n"; - for (size_t i = 0; i < DIEOffsets.size(); i++) - O << " Offset: " << DIEOffsets[i] << "\n"; + for (size_t i = 0; i < Data.size(); i++) { + O << " Offset: " << Data[i]->Die->getOffset() << "\n"; + O << " Tag: " << dwarf::TagString(Data[i]->Die->getTag()) << "\n"; + O << " Flags: " << Data[i]->Flags << "\n"; + } } void dump() { print(dbgs()); @@ -226,8 +262,8 @@ public: std::vector Data; // String Data - typedef std::vector DIEArray; - typedef StringMap StringEntries; + typedef std::vector DataArray; + typedef StringMap StringEntries; StringEntries Entries; // Buckets/Hashes/Offsets @@ -238,9 +274,10 @@ public: // Public Implementation public: - DwarfAccelTable(DwarfAccelTable::Atom Atom); + DwarfAccelTable(DwarfAccelTable::Atom); + DwarfAccelTable(std::vector &); ~DwarfAccelTable(); - void AddName(StringRef, DIE*); + void AddName(StringRef, DIE*, char = 0); void FinalizeTable(AsmPrinter *, const char *); void Emit(AsmPrinter *, MCSymbol *, DwarfDebug *); #ifndef NDEBUG diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index f43a5bf8421..e499d2c8bfe 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -13,6 +13,7 @@ #define DEBUG_TYPE "dwarfdebug" +#include "DwarfAccelTable.h" #include "DwarfCompileUnit.h" #include "DwarfDebug.h" #include "llvm/Constants.h" @@ -608,8 +609,20 @@ DIE *CompileUnit::getOrCreateTypeDIE(const MDNode *TyNode) { } // If this is a named finished type then include it in the list of types // for the accelerator tables. - if (!Ty.getName().empty() && !Ty.isForwardDecl()) - addAccelType(Ty.getName(), TyDIE); + if (!Ty.getName().empty() && !Ty.isForwardDecl()) { + bool IsImplementation = 0; + if (Ty.isCompositeType()) { + DICompositeType CT(Ty); + IsImplementation = (CT.getRunTimeLang() == 0) || + CT.isObjcClassComplete();; + } + + addAccelType(Ty.getName(), + std::make_pair(TyDIE, + (IsImplementation ? + DwarfAccelTable::eTypeFlagClassIsImplementation : + 0))); + } addToContextOwner(TyDIE, Ty.getContext()); return TyDIE; diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 07a772338ee..fe65927ff56 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -65,7 +65,7 @@ class CompileUnit { StringMap > AccelNames; StringMap > AccelObjC; StringMap > AccelNamespace; - StringMap > AccelTypes; + StringMap > > AccelTypes; /// DIEBlocks - A list of all the DIEBlocks in use. std::vector DIEBlocks; @@ -93,7 +93,8 @@ public: const StringMap > &getAccelNamespace() const { return AccelNamespace; } - const StringMap > &getAccelTypes() const { + const StringMap > > + &getAccelTypes() const { return AccelTypes; } @@ -119,8 +120,8 @@ public: std::vector &DIEs = AccelNamespace[Name]; DIEs.push_back(Die); } - void addAccelType(StringRef Name, DIE *Die) { - std::vector &DIEs = AccelTypes[Name]; + void addAccelType(StringRef Name, std::pair Die) { + std::vector > &DIEs = AccelTypes[Name]; DIEs.push_back(Die); } diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 94ce04a92d4..7e58c302730 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1844,19 +1844,26 @@ void DwarfDebug::emitAccelNamespaces() { /// emitAccelTypes() - Emit type dies into a hashed accelerator table. void DwarfDebug::emitAccelTypes() { - DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset, - dwarf::DW_FORM_data4)); + std::vector Atoms; + Atoms.push_back(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset, + dwarf::DW_FORM_data4)); + Atoms.push_back(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeTag, + dwarf::DW_FORM_data2)); + Atoms.push_back(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeTypeFlags, + dwarf::DW_FORM_data1)); + DwarfAccelTable AT(Atoms); for (DenseMap::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) { CompileUnit *TheCU = I->second; - const StringMap > &Names = TheCU->getAccelTypes(); - for (StringMap >::const_iterator + const StringMap > > &Names + = TheCU->getAccelTypes(); + for (StringMap > >::const_iterator GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { const char *Name = GI->getKeyData(); - std::vector Entities = GI->second; - for (std::vector::const_iterator DI = Entities.begin(), - DE= Entities.end(); DI !=DE; ++DI) - AT.AddName(Name, (*DI)); + std::vector > Entities = GI->second; + for (std::vector >::const_iterator DI + = Entities.begin(), DE = Entities.end(); DI !=DE; ++DI) + AT.AddName(Name, (*DI).first, (*DI).second); } }