diff options
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.h | 6 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 28 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 168 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h | 15 |
5 files changed, 224 insertions, 6 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.h b/llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.h index 242841a5095..2d3f4fd946d 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.h @@ -25,7 +25,7 @@ #include <vector> #include <map> -// The apple dwarf accelerator tables are an indirect hash table optimized +// The dwarf accelerator tables are an indirect hash table optimized // for null lookup rather than access to known data. They are output into // an on-disk format that looks like this: // @@ -176,9 +176,7 @@ public: #endif }; - // The data itself consists of a str_offset (to deal with collisions in - // some magical way? this looks like the KeyType from the spec, which - // should mean an integer compare on read), a count of the DIEs in the + // The data itself consists of a str_offset, a count of the DIEs in the // hash and the offsets to the DIEs themselves. // On disk each data section is ended with a 0 KeyType as the end of the // hash chain. diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 95f1f92fe3d..cb80bd810e3 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -904,8 +904,11 @@ DIE *CompileUnit::getOrCreateNameSpace(DINameSpace NS) { return NDie; NDie = new DIE(dwarf::DW_TAG_namespace); insertDIE(NS, NDie); - if (!NS.getName().empty()) + if (!NS.getName().empty()) { addString(NDie, dwarf::DW_AT_name, NS.getName()); + addAccelNamespace(NS.getName(), NDie); + } else + addAccelNamespace("(anonymous namespace)", NDie); addSourceLine(NDie, NS); addToContextOwner(NDie, NS.getContext()); return NDie; @@ -1078,7 +1081,9 @@ void CompileUnit::createGlobalVariableDIE(const MDNode *N) { DIDescriptor GVContext = GV.getContext(); addToContextOwner(VariableDIE, GVContext); // Add location. + bool addToAccelTable = false; if (isGlobalVariable) { + addToAccelTable = true; DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); addLabel(Block, 0, dwarf::DW_FORM_udata, @@ -1097,11 +1102,12 @@ void CompileUnit::createGlobalVariableDIE(const MDNode *N) { addDie(VariableSpecDIE); } else { addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); - } + } } else if (const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(GV.getConstant())) addConstantValue(VariableDIE, CI, GTy.isUnsignedDIType()); else if (const ConstantExpr *CE = getMergedGlobalExpr(N->getOperand(11))) { + addToAccelTable = true; // GV is a merged global. DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); Value *Ptr = CE->getOperand(0); @@ -1116,6 +1122,9 @@ void CompileUnit::createGlobalVariableDIE(const MDNode *N) { addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); } + if (addToAccelTable) + addAccelName(GV.getName(), VariableDIE); + return; } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index efab32efc17..b994ce37345 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -64,6 +64,13 @@ class CompileUnit { /// StringMap<DIE*> GlobalTypes; + /// AccelNames - A map of names for the name accelerator table. + /// + StringMap<DIE*> AccelNames; + StringMap<std::vector<DIE*> > AccelObjC; + StringMap<DIE*> AccelNamespace; + StringMap<DIE*> AccelTypes; + /// DIEBlocks - A list of all the DIEBlocks in use. std::vector<DIEBlock *> DIEBlocks; @@ -82,6 +89,13 @@ public: const StringMap<DIE*> &getGlobals() const { return Globals; } const StringMap<DIE*> &getGlobalTypes() const { return GlobalTypes; } + const StringMap<DIE*> &getAccelNames() const { return AccelNames; } + const StringMap<std::vector<DIE*> > &getAccelObjC() const { + return AccelObjC; + } + const StringMap<DIE*> &getAccelNamespace() const { return AccelNamespace; } + const StringMap<DIE*> &getAccelTypes() const { return AccelTypes; } + /// hasContent - Return true if this compile unit has something to write out. /// bool hasContent() const { return !CUDie->getChildren().empty(); } @@ -94,6 +108,20 @@ public: /// void addGlobalType(DIType Ty); + + /// addAccelName - Add a new name to the name accelerator table. + void addAccelName(StringRef Name, DIE *Die) { AccelNames[Name] = Die; } + void addAccelObjC(StringRef Name, DIE *Die) { + std::vector<DIE*> &DIEs = AccelObjC[Name]; + DIEs.push_back(Die); + } + void addAccelNamespace(StringRef Name, DIE *Die) { + AccelNamespace[Name] = Die; + } + void addAccelType(StringRef Name, DIE *Die) { + AccelTypes[Name] = Die; + } + /// getDIE - Returns the debug information entry map slot for the /// specified debug variable. DIE *getDIE(const MDNode *N) { return MDNodeToDieMap.lookup(N); } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 037b4ace026..8acc8571ddc 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -14,6 +14,7 @@ #define DEBUG_TYPE "dwarfdebug" #include "DwarfDebug.h" #include "DIE.h" +#include "DwarfAccelTable.h" #include "DwarfCompileUnit.h" #include "llvm/Constants.h" #include "llvm/Module.h" @@ -52,6 +53,10 @@ static cl::opt<bool> UnknownLocations("use-unknown-locations", cl::Hidden, cl::desc("Make an absence of debug location information explicit."), cl::init(false)); +static cl::opt<bool> DwarfAccelTables("dwarf-accel-tables", cl::Hidden, + cl::desc("Output prototype dwarf accelerator tables."), + cl::init(false)); + namespace { const char *DWARFGroupName = "DWARF Emission"; const char *DbgTimerName = "DWARF Debug Writer"; @@ -444,6 +449,9 @@ DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { if (DS.isSubprogram()) TheCU->addPubTypes(DISubprogram(DS)); + if (DS.isSubprogram() && !Scope->isAbstractScope()) + TheCU->addAccelName(DISubprogram(DS).getName(), ScopeDIE); + return ScopeDIE; } @@ -524,6 +532,36 @@ CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) { return NewCU; } +static bool isObjCClass(StringRef Name) { + return Name[0] == '+' || Name[0] == '-'; +} + +static bool hasObjCCategory(StringRef Name) { + if (Name[0] != '+' && Name[0] != '-') + return false; + + size_t pos = Name.find(')'); + if (pos != std::string::npos) { + if (Name[pos+1] != ' ') return false; + return true; + } + + return false; +} + +static void getObjCClassCategory(StringRef In, StringRef &Class, + StringRef &Category) { + if (!hasObjCCategory(In)) { + Class = In.slice(In.find('[') + 1, In.find(' ')); + Category = ""; + return; + } + + Class = In.slice(In.find('[') + 1, In.find('(')); + Category = In.slice(In.find('[') + 1, In.find(' ')); + return; +} + /// construct SubprogramDIE - Construct subprogram DIE. void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU, const MDNode *N) { @@ -561,6 +599,18 @@ void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU, // Expose as global. TheCU->addGlobal(SP.getName(), SubprogramDie); + // Add to Accel Names + TheCU->addAccelName(SP.getName(), SubprogramDie); + + // If this is an Objective-C selector name add it to the ObjC accelerator too. + if (isObjCClass(SP.getName())) { + StringRef Class, Category; + getObjCClassCategory(SP.getName(), Class, Category); + TheCU->addAccelObjC(Class, SubprogramDie); + if (Category != "") + TheCU->addAccelObjC(Category, SubprogramDie); + } + return; } @@ -757,6 +807,14 @@ void DwarfDebug::endModule() { // Corresponding abbreviations into a abbrev section. emitAbbreviations(); + // Emit info into a dwarf accelerator table sections. + if (DwarfAccelTables) { + emitAccelNames(); + emitAccelObjC(); + emitAccelNamespaces(); + emitAccelTypes(); + } + // Emit info into a debug pubnames section. emitDebugPubNames(); @@ -1696,6 +1754,116 @@ void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { Asm->EmitInt8(1); } +/// emitAccelNames - Emit visible names into a hashed accelerator table +/// section. +void DwarfDebug::emitAccelNames() { + DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset, + dwarf::DW_FORM_data4)); + for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(), + E = CUMap.end(); I != E; ++I) { + CompileUnit *TheCU = I->second; + const StringMap<DIE*> &Names = TheCU->getAccelNames(); + for (StringMap<DIE*>::const_iterator + GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { + const char *Name = GI->getKeyData(); + DIE *Entity = GI->second; + AT.AddName(Name, Entity); + } + } + + AT.FinalizeTable(Asm, "Names"); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfAccelNamesSection()); + MCSymbol *SectionBegin = Asm->GetTempSymbol("names_begin"); + Asm->OutStreamer.EmitLabel(SectionBegin); + + // Emit the full data. + AT.Emit(Asm, SectionBegin, this); +} + +/// emitAccelObjC - Emit objective C classes and categories into a hashed +/// accelerator table section. +void DwarfDebug::emitAccelObjC() { + DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset, + dwarf::DW_FORM_data4)); + for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(), + E = CUMap.end(); I != E; ++I) { + CompileUnit *TheCU = I->second; + const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelObjC(); + for (StringMap<std::vector<DIE*> >::const_iterator + GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { + const char *Name = GI->getKeyData(); + std::vector<DIE *> Entities = GI->second; + for (std::vector<DIE *>::const_iterator DI = Entities.begin(), + DE = Entities.end(); DI != DE; ++DI) + AT.AddName(Name, (*DI)); + } + } + + AT.FinalizeTable(Asm, "ObjC"); + Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering() + .getDwarfAccelObjCSection()); + MCSymbol *SectionBegin = Asm->GetTempSymbol("objc_begin"); + Asm->OutStreamer.EmitLabel(SectionBegin); + + // Emit the full data. + AT.Emit(Asm, SectionBegin, this); +} + +/// emitAccelNamespace - Emit namespace dies into a hashed accelerator +/// table. +void DwarfDebug::emitAccelNamespaces() { + DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset, + dwarf::DW_FORM_data4)); + for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(), + E = CUMap.end(); I != E; ++I) { + CompileUnit *TheCU = I->second; + const StringMap<DIE*> &Names = TheCU->getAccelNamespace(); + for (StringMap<DIE*>::const_iterator + GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { + const char *Name = GI->getKeyData(); + DIE *Entity = GI->second; + AT.AddName(Name, Entity); + } + } + + AT.FinalizeTable(Asm, "namespac"); + Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering() + .getDwarfAccelNamespaceSection()); + MCSymbol *SectionBegin = Asm->GetTempSymbol("namespac_begin"); + Asm->OutStreamer.EmitLabel(SectionBegin); + + // Emit the full data. + AT.Emit(Asm, SectionBegin, this); +} + +/// emitAccelTypes() - Emit type dies into a hashed accelerator table. +void DwarfDebug::emitAccelTypes() { + DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset, + dwarf::DW_FORM_data4)); + for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(), + E = CUMap.end(); I != E; ++I) { + CompileUnit *TheCU = I->second; + const StringMap<DIE*> &Names = TheCU->getGlobalTypes(); + //TODO: TheCU->getAccelTypes(); + for (StringMap<DIE*>::const_iterator + GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { + const char *Name = GI->getKeyData(); + DIE *Entity = GI->second; + AT.AddName(Name, Entity); + } + } + + AT.FinalizeTable(Asm, "types"); + Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering() + .getDwarfAccelTypesSection()); + MCSymbol *SectionBegin = Asm->GetTempSymbol("types_begin"); + Asm->OutStreamer.EmitLabel(SectionBegin); + + // Emit the full data. + AT.Emit(Asm, SectionBegin, this); +} + /// emitDebugPubNames - Emit visible names into a debug pubnames section. /// void DwarfDebug::emitDebugPubNames() { diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h index 7bcc5b42074..ce5e59ec286 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -367,6 +367,21 @@ private: /// void emitEndOfLineMatrix(unsigned SectionEnd); + /// emitAccelNames - Emit visible names into a hashed accelerator table + /// section. + void emitAccelNames(); + + /// emitAccelObjC - Emit objective C classes and categories into a hashed + /// accelerator table section. + void emitAccelObjC(); + + /// emitAccelNamespace - Emit namespace dies into a hashed accelerator + /// table. + void emitAccelNamespaces(); + + /// emitAccelTypes() - Emit type dies into a hashed accelerator table. + void emitAccelTypes(); + /// emitDebugPubNames - Emit visible names into a debug pubnames section. /// void emitDebugPubNames(); |