X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FAsmPrinter%2FDwarfDebug.cpp;h=a7056d6a0116901f239a4ee508415d821542e98b;hb=3ddd790df11cb1df6d2c81882b24f8c187c09033;hp=48a7c185ec2b5fbe1b9155cf5ee7ec577b38c465;hpb=eb46def978a60fd705cca3037feff5573122b404;p=oota-llvm.git diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 48a7c185ec2..a7056d6a011 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -16,7 +16,7 @@ #include "DIE.h" #include "DIEHash.h" #include "DwarfAccelTable.h" -#include "DwarfCompileUnit.h" +#include "DwarfUnit.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" @@ -63,10 +63,9 @@ GenerateODRHash("generate-odr-hash", cl::Hidden, cl::desc("Add an ODR hash to external type DIEs."), cl::init(false)); -static cl::opt -GenerateCUHash("generate-cu-hash", cl::Hidden, - cl::desc("Add the CU hash as the dwo_id."), - cl::init(false)); +static cl::opt GenerateCUHash("generate-cu-hash", cl::Hidden, + cl::desc("Add the CU hash as the dwo_id."), + cl::init(false)); static cl::opt GenerateGnuPubSections("generate-gnu-dwarf-pub-sections", cl::Hidden, @@ -105,6 +104,11 @@ DwarfPubSections("generate-dwarf-pub-sections", cl::Hidden, clEnumVal(Disable, "Disabled"), clEnumValEnd), cl::init(Default)); +static cl::opt +DwarfVersionNumber("dwarf-version", cl::Hidden, + cl::desc("Generate DWARF for dwarf version."), + cl::init(0)); + static const char *const DWARFGroupName = "DWARF Emission"; static const char *const DbgTimerName = "DWARF Debug Writer"; @@ -116,6 +120,12 @@ static const unsigned InitAbbreviationsSetSize = 9; // log2(512) namespace llvm { +/// resolve - Look in the DwarfDebug map for the MDNode that +/// corresponds to the reference. +template T DbgVariable::resolve(DIRef Ref) const { + return DD->resolve(Ref); +} + DIType DbgVariable::getType() const { DIType Ty = Var.getType(); // FIXME: isBlockByrefVariable should be reformulated in terms of complex @@ -149,13 +159,13 @@ DIType DbgVariable::getType() const { uint16_t tag = Ty.getTag(); if (tag == dwarf::DW_TAG_pointer_type) - subType = DIDerivedType(Ty).getTypeDerivedFrom(); + subType = resolve(DIDerivedType(Ty).getTypeDerivedFrom()); DIArray Elements = DICompositeType(subType).getTypeArray(); for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { - DIDerivedType DT = DIDerivedType(Elements.getElement(i)); + DIDerivedType DT(Elements.getElement(i)); if (getName() == DT.getName()) - return (DT.getTypeDerivedFrom()); + return (resolve(DT.getTypeDerivedFrom())); } } return Ty; @@ -172,15 +182,14 @@ static unsigned getDwarfVersionFromModule(const Module *M) { } DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) - : Asm(A), MMI(Asm->MMI), FirstCU(0), - AbbreviationsSet(InitAbbreviationsSetSize), - SourceIdMap(DIEValueAllocator), - PrevLabel(NULL), GlobalCUIndexCount(0), - InfoHolder(A, &AbbreviationsSet, &Abbreviations, "info_string", - DIEValueAllocator), - SkeletonAbbrevSet(InitAbbreviationsSetSize), - SkeletonHolder(A, &SkeletonAbbrevSet, &SkeletonAbbrevs, "skel_string", - DIEValueAllocator) { + : Asm(A), MMI(Asm->MMI), FirstCU(0), + AbbreviationsSet(InitAbbreviationsSetSize), + SourceIdMap(DIEValueAllocator), PrevLabel(NULL), GlobalCUIndexCount(0), + GlobalRangeCount(0), InfoHolder(A, &AbbreviationsSet, Abbreviations, + "info_string", DIEValueAllocator), + SkeletonAbbrevSet(InitAbbreviationsSetSize), + SkeletonHolder(A, &SkeletonAbbrevSet, SkeletonAbbrevs, "skel_string", + DIEValueAllocator) { DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0; DwarfStrSectionSym = TextSectionSym = 0; @@ -188,10 +197,10 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) DwarfAddrSectionSym = 0; DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = 0; FunctionBeginSym = FunctionEndSym = 0; + CurFn = 0; CurMI = 0; - // Turn on accelerator tables and older gdb compatibility - // for Darwin by default, pubnames by default for non-Darwin, - // and handle split dwarf. + // Turn on accelerator tables for Darwin by default, pubnames by + // default for non-Darwin, and handle split dwarf. bool IsDarwin = Triple(A->getTargetTriple()).isOSDarwin(); if (DwarfAccelTables == Default) @@ -209,45 +218,54 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) else HasDwarfPubSections = DwarfPubSections == Enable; - DwarfVersion = getDwarfVersionFromModule(MMI->getModule()); + DwarfVersion = DwarfVersionNumber + ? DwarfVersionNumber + : getDwarfVersionFromModule(MMI->getModule()); { NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); beginModule(); } } -DwarfDebug::~DwarfDebug() { -} // Switch to the specified MCSection and emit an assembler // temporary label to it if SymbolStem is specified. static MCSymbol *emitSectionSym(AsmPrinter *Asm, const MCSection *Section, const char *SymbolStem = 0) { Asm->OutStreamer.SwitchSection(Section); - if (!SymbolStem) return 0; + if (!SymbolStem) + return 0; MCSymbol *TmpSym = Asm->GetTempSymbol(SymbolStem); Asm->OutStreamer.EmitLabel(TmpSym); return TmpSym; } +DwarfUnits::~DwarfUnits() { + for (SmallVectorImpl::iterator I = CUs.begin(), E = CUs.end(); I != E; + ++I) + delete *I; +} + MCSymbol *DwarfUnits::getStringPoolSym() { return Asm->GetTempSymbol(StringPref); } MCSymbol *DwarfUnits::getStringPoolEntry(StringRef Str) { - std::pair &Entry = - StringPool.GetOrCreateValue(Str).getValue(); - if (Entry.first) return Entry.first; + std::pair &Entry = + StringPool.GetOrCreateValue(Str).getValue(); + if (Entry.first) + return Entry.first; Entry.second = NextStringPoolNumber++; return Entry.first = Asm->GetTempSymbol(StringPref, Entry.second); } unsigned DwarfUnits::getStringPoolIndex(StringRef Str) { - std::pair &Entry = - StringPool.GetOrCreateValue(Str).getValue(); - if (Entry.first) return Entry.second; + std::pair &Entry = + StringPool.GetOrCreateValue(Str).getValue(); + if (Entry.first) + return Entry.second; Entry.second = NextStringPoolNumber++; Entry.first = Asm->GetTempSymbol(StringPref, Entry.second); @@ -275,10 +293,10 @@ void DwarfUnits::assignAbbrevNumber(DIEAbbrev &Abbrev) { // If it's newly added. if (InSet == &Abbrev) { // Add to abbreviation list. - Abbreviations->push_back(&Abbrev); + Abbreviations.push_back(&Abbrev); // Assign the vector position + 1 as its number. - Abbrev.setNumber(Abbreviations->size()); + Abbrev.setNumber(Abbreviations.size()); } else { // Assign existing abbreviation number. Abbrev.setNumber(InSet->getNumber()); @@ -290,7 +308,8 @@ static bool isObjCClass(StringRef Name) { } static bool hasObjCCategory(StringRef Name) { - if (!isObjCClass(Name)) return false; + if (!isObjCClass(Name)) + return false; return Name.find(") ") != StringRef::npos; } @@ -312,30 +331,37 @@ static StringRef getObjCMethodName(StringRef In) { return In.slice(In.find(' ') + 1, In.find(']')); } +// Helper for sorting sections into a stable output order. +static bool SectionSort(const MCSection *A, const MCSection *B) { + std::string LA = (A ? A->getLabelBeginName() : ""); + std::string LB = (B ? B->getLabelBeginName() : ""); + return LA < LB; +} + // Add the various names to the Dwarf accelerator table names. // TODO: Determine whether or not we should add names for programs // that do not have a DW_AT_name or DW_AT_linkage_name field - this // is only slightly different than the lookup of non-standard ObjC names. -static void addSubprogramNames(CompileUnit *TheCU, DISubprogram SP, - DIE* Die) { - if (!SP.isDefinition()) return; - TheCU->addAccelName(SP.getName(), Die); +static void addSubprogramNames(Unit *TheU, DISubprogram SP, DIE *Die) { + if (!SP.isDefinition()) + return; + TheU->addAccelName(SP.getName(), Die); // If the linkage name is different than the name, go ahead and output // that as well into the name table. if (SP.getLinkageName() != "" && SP.getName() != SP.getLinkageName()) - TheCU->addAccelName(SP.getLinkageName(), Die); + TheU->addAccelName(SP.getLinkageName(), Die); // 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, Die); + TheU->addAccelObjC(Class, Die); if (Category != "") - TheCU->addAccelObjC(Category, Die); + TheU->addAccelObjC(Category, Die); // Also add the base method name to the name table. - TheCU->addAccelName(getObjCMethodName(SP.getName()), Die); + TheU->addAccelName(getObjCMethodName(SP.getName()), Die); } } @@ -355,27 +381,19 @@ bool DwarfDebug::isSubprogramContext(const MDNode *Context) { // Find DIE for the given subprogram and attach appropriate DW_AT_low_pc // and DW_AT_high_pc attributes. If there are global variables in this // scope then create and insert DIEs for these variables. -DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU, - const MDNode *SPNode) { - DIE *SPDie = SPCU->getDIE(SPNode); +DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU, DISubprogram SP) { + DIE *SPDie = SPCU->getDIE(SP); assert(SPDie && "Unable to find subprogram DIE!"); - DISubprogram SP(SPNode); // If we're updating an abstract DIE, then we will be adding the children and // object pointer later on. But what we don't want to do is process the // concrete DIE twice. - DIE *AbsSPDIE = AbstractSPDies.lookup(SPNode); - if (AbsSPDIE) { - bool InSameCU = (AbsSPDIE->getCompileUnit() == SPCU->getCUDie()); + if (DIE *AbsSPDIE = AbstractSPDies.lookup(SP)) { // Pick up abstract subprogram DIE. - SPDie = new DIE(dwarf::DW_TAG_subprogram); - // If AbsSPDIE belongs to a different CU, use DW_FORM_ref_addr instead of - // DW_FORM_ref4. - SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin, - InSameCU ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr, - AbsSPDIE); - SPCU->addDie(SPDie); + SPDie = + SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *SPCU->getUnitDie()); + SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin, AbsSPDIE); } else { DISubprogram SPDecl = SP.getFunctionDeclaration(); if (!SPDecl.isSubprogram()) { @@ -384,9 +402,9 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU, // function then gdb prefers the definition at top level and but does not // expect specification DIE in parent function. So avoid creating // specification DIE for a function defined inside a function. - if (SP.isDefinition() && !SP.getContext().isCompileUnit() && - !SP.getContext().isFile() && - !isSubprogramContext(SP.getContext())) { + DIScope SPContext = resolve(SP.getContext()); + if (SP.isDefinition() && !SPContext.isCompileUnit() && + !SPContext.isFile() && !isSubprogramContext(SPContext)) { SPCU->addFlag(SPDie, dwarf::DW_AT_declaration); // Add arguments. @@ -395,31 +413,26 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU, uint16_t SPTag = SPTy.getTag(); if (SPTag == dwarf::DW_TAG_subroutine_type) for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { - DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); - DIType ATy = DIType(Args.getElement(i)); + DIE *Arg = + SPCU->createAndAddDIE(dwarf::DW_TAG_formal_parameter, *SPDie); + DIType ATy(Args.getElement(i)); SPCU->addType(Arg, ATy); if (ATy.isArtificial()) SPCU->addFlag(Arg, dwarf::DW_AT_artificial); if (ATy.isObjectPointer()) - SPCU->addDIEEntry(SPDie, dwarf::DW_AT_object_pointer, - dwarf::DW_FORM_ref4, Arg); - SPDie->addChild(Arg); + SPCU->addDIEEntry(SPDie, dwarf::DW_AT_object_pointer, Arg); } DIE *SPDeclDie = SPDie; - SPDie = new DIE(dwarf::DW_TAG_subprogram); - SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, - dwarf::DW_FORM_ref4, SPDeclDie); - SPCU->addDie(SPDie); + SPDie = SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, + *SPCU->getUnitDie()); + SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, SPDeclDie); } } } - SPCU->addLabelAddress(SPDie, dwarf::DW_AT_low_pc, - Asm->GetTempSymbol("func_begin", - Asm->getFunctionNumber())); - SPCU->addLabelAddress(SPDie, dwarf::DW_AT_high_pc, - Asm->GetTempSymbol("func_end", - Asm->getFunctionNumber())); + SPCU->addLabelAddress(SPDie, dwarf::DW_AT_low_pc, FunctionBeginSym); + SPCU->addLabelAddress(SPDie, dwarf::DW_AT_high_pc, FunctionEndSym); + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); MachineLocation Location(RI->getFrameRegister(*Asm->MF)); SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location); @@ -452,6 +465,25 @@ bool DwarfDebug::isLexicalScopeDIENull(LexicalScope *Scope) { return !End; } +void DwarfDebug::addScopeRangeList(CompileUnit *TheCU, DIE *ScopeDIE, + const SmallVectorImpl &Range) { + // Emit offset in .debug_range as a relocatable label. emitDIE will handle + // emitting it appropriately. + TheCU->addSectionLabel(ScopeDIE, dwarf::DW_AT_ranges, + Asm->GetTempSymbol("debug_ranges", GlobalRangeCount)); + RangeSpanList *List = new RangeSpanList(GlobalRangeCount++); + for (SmallVectorImpl::const_iterator RI = Range.begin(), + RE = Range.end(); + RI != RE; ++RI) { + RangeSpan Span(getLabelBeforeInsn(RI->first), + getLabelAfterInsn(RI->second)); + List->addRange(Span); + } + + // Add the range list to the set of ranges to be emitted. + TheCU->addRangeList(List); +} + // Construct new DW_TAG_lexical_block for this scope and attach // DW_AT_low_pc/DW_AT_high_pc labels. DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU, @@ -463,29 +495,16 @@ DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU, if (Scope->isAbstractScope()) return ScopeDIE; - const SmallVectorImpl &Ranges = Scope->getRanges(); - // If we have multiple ranges, emit them into the range section. - if (Ranges.size() > 1) { - // .debug_range section has not been laid out yet. Emit offset in - // .debug_range as a uint, size 4, for now. emitDIE will handle - // DW_AT_ranges appropriately. - TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4, - DebugRangeSymbols.size() - * Asm->getDataLayout().getPointerSize()); - for (SmallVectorImpl::const_iterator RI = Ranges.begin(), - RE = Ranges.end(); RI != RE; ++RI) { - DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first)); - DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second)); - } + const SmallVectorImpl &ScopeRanges = Scope->getRanges(); - // Terminate the range list. - DebugRangeSymbols.push_back(NULL); - DebugRangeSymbols.push_back(NULL); + // If we have multiple ranges, emit them into the range section. + if (ScopeRanges.size() > 1) { + addScopeRangeList(TheCU, ScopeDIE, ScopeRanges); return ScopeDIE; } // Construct the address range for this DIE. - SmallVectorImpl::const_iterator RI = Ranges.begin(); + SmallVectorImpl::const_iterator RI = ScopeRanges.begin(); MCSymbol *Start = getLabelBeforeInsn(RI->first); MCSymbol *End = getLabelAfterInsn(RI->second); assert(End && "End label should not be null!"); @@ -503,8 +522,8 @@ DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU, // represent this concrete inlined copy of the function. DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { - const SmallVectorImpl &Ranges = Scope->getRanges(); - assert(Ranges.empty() == false && + const SmallVectorImpl &ScopeRanges = Scope->getRanges(); + assert(ScopeRanges.empty() == false && "LexicalScope does not have instruction markers!"); if (!Scope->getScopeNode()) @@ -518,25 +537,13 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, } DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine); - TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, - dwarf::DW_FORM_ref4, OriginDIE); - - if (Ranges.size() > 1) { - // .debug_range section has not been laid out yet. Emit offset in - // .debug_range as a uint, size 4, for now. emitDIE will handle - // DW_AT_ranges appropriately. - TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4, - DebugRangeSymbols.size() - * Asm->getDataLayout().getPointerSize()); - for (SmallVectorImpl::const_iterator RI = Ranges.begin(), - RE = Ranges.end(); RI != RE; ++RI) { - DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first)); - DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second)); - } - DebugRangeSymbols.push_back(NULL); - DebugRangeSymbols.push_back(NULL); - } else { - SmallVectorImpl::const_iterator RI = Ranges.begin(); + TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, OriginDIE); + + // If we have multiple ranges, emit them into the range section. + if (ScopeRanges.size() > 1) + addScopeRangeList(TheCU, ScopeDIE, ScopeRanges); + else { + SmallVectorImpl::const_iterator RI = ScopeRanges.begin(); MCSymbol *StartLabel = getLabelBeforeInsn(RI->first); MCSymbol *EndLabel = getLabelAfterInsn(RI->second); @@ -555,10 +562,10 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, // Add the call site information to the DIE. DILocation DL(Scope->getInlinedAt()); - TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_file, 0, + TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_file, None, getOrCreateSourceID(DL.getFilename(), DL.getDirectory(), TheCU->getUniqueID())); - TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_line, 0, DL.getLineNumber()); + TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_line, None, DL.getLineNumber()); // Add name to the name table, we do this here because we're guaranteed // to have concrete versions of our DW_TAG_inlined_subprogram nodes. @@ -568,26 +575,29 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, } DIE *DwarfDebug::createScopeChildrenDIE(CompileUnit *TheCU, LexicalScope *Scope, - SmallVectorImpl &Children) { - DIE *ObjectPointer = NULL; + SmallVectorImpl &Children) { + DIE *ObjectPointer = NULL; // Collect arguments for current function. if (LScopes.isCurrentFunctionScope(Scope)) for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i) if (DbgVariable *ArgDV = CurrentFnArguments[i]) if (DIE *Arg = - TheCU->constructVariableDIE(ArgDV, Scope->isAbstractScope())) { + TheCU->constructVariableDIE(*ArgDV, Scope->isAbstractScope())) { Children.push_back(Arg); - if (ArgDV->isObjectPointer()) ObjectPointer = Arg; + if (ArgDV->isObjectPointer()) + ObjectPointer = Arg; } // Collect lexical scope children first. - const SmallVectorImpl &Variables =ScopeVariables.lookup(Scope); + const SmallVectorImpl &Variables = + ScopeVariables.lookup(Scope); for (unsigned i = 0, N = Variables.size(); i < N; ++i) - if (DIE *Variable = - TheCU->constructVariableDIE(Variables[i], Scope->isAbstractScope())) { + if (DIE *Variable = TheCU->constructVariableDIE(*Variables[i], + Scope->isAbstractScope())) { Children.push_back(Variable); - if (Variables[i]->isObjectPointer()) ObjectPointer = Variable; + if (Variables[i]->isObjectPointer()) + ObjectPointer = Variable; } const SmallVectorImpl &Scopes = Scope->getChildren(); for (unsigned j = 0, M = Scopes.size(); j < M; ++j) @@ -620,11 +630,9 @@ DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { // Note down abstract DIE. if (ScopeDIE) AbstractSPDies.insert(std::make_pair(DS, ScopeDIE)); - } - else - ScopeDIE = updateSubprogramScopeDIE(TheCU, DS); - } - else { + } else + ScopeDIE = updateSubprogramScopeDIE(TheCU, DISubprogram(DS)); + } else { // Early exit when we know the scope DIE is going to be null. if (isLexicalScopeDIENull(Scope)) return NULL; @@ -636,10 +644,12 @@ DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { // There is no need to emit empty lexical block DIE. std::pair Range = std::equal_range( - ScopesWithImportedEntities.begin(), ScopesWithImportedEntities.end(), - std::pair(DS, (const MDNode*)0), - less_first()); + ImportedEntityMap::const_iterator> Range = + std::equal_range( + ScopesWithImportedEntities.begin(), + ScopesWithImportedEntities.end(), + std::pair(DS, (const MDNode *)0), + less_first()); if (Children.empty() && Range.first == Range.second) return NULL; ScopeDIE = constructLexicalScopeDIE(TheCU, Scope); @@ -660,15 +670,12 @@ DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { // Add children for (SmallVectorImpl::iterator I = Children.begin(), - E = Children.end(); I != E; ++I) + E = Children.end(); + I != E; ++I) ScopeDIE->addChild(*I); if (DS.isSubprogram() && ObjectPointer != NULL) - TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, - dwarf::DW_FORM_ref4, ObjectPointer); - - if (DS.isSubprogram()) - TheCU->addPubTypes(DISubprogram(DS)); + TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, ObjectPointer); return ScopeDIE; } @@ -677,12 +684,14 @@ DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { // If none currently exists, create a new id and insert it in the // SourceIds map. This can update DirectoryNames and SourceFileNames maps // as well. -unsigned DwarfDebug::getOrCreateSourceID(StringRef FileName, - StringRef DirName, unsigned CUID) { +unsigned DwarfDebug::getOrCreateSourceID(StringRef FileName, StringRef DirName, + unsigned CUID) { // If we use .loc in assembly, we can't separate .file entries according to // compile units. Thus all files will belong to the default compile unit. - if (Asm->TM.hasMCUseLoc() && - Asm->OutStreamer.getKind() == MCStreamer::SK_AsmStreamer) + + // FIXME: add a better feature test than hasRawTextSupport. Even better, + // extend .file to support this. + if (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport()) CUID = 0; // If FE did not provide a file name, then assume stdin. @@ -717,14 +726,13 @@ unsigned DwarfDebug::getOrCreateSourceID(StringRef FileName, // Create new CompileUnit for the given metadata node with tag // DW_TAG_compile_unit. -CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) { - DICompileUnit DIUnit(N); +CompileUnit *DwarfDebug::constructCompileUnit(DICompileUnit DIUnit) { StringRef FN = DIUnit.getFilename(); CompilationDir = DIUnit.getDirectory(); DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); - CompileUnit *NewCU = - new CompileUnit(GlobalCUIndexCount++, Die, N, Asm, this, &InfoHolder); + CompileUnit *NewCU = new CompileUnit(GlobalCUIndexCount++, Die, DIUnit, Asm, + this, &InfoHolder); FileIDCUMap[NewCU->getUniqueID()] = 0; // Call this to emit a .file directive if it wasn't emitted for the source @@ -743,44 +751,63 @@ CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) { NewCU->addLabelAddress(Die, dwarf::DW_AT_low_pc, NULL); // Define start line table label for each Compile Unit. - MCSymbol *LineTableStartSym = Asm->GetTempSymbol("line_table_start", - NewCU->getUniqueID()); + MCSymbol *LineTableStartSym = + Asm->GetTempSymbol("line_table_start", NewCU->getUniqueID()); Asm->OutStreamer.getContext().setMCLineTableSymbol(LineTableStartSym, NewCU->getUniqueID()); // Use a single line table if we are using .loc and generating assembly. bool UseTheFirstCU = - (Asm->TM.hasMCUseLoc() && - Asm->OutStreamer.getKind() == MCStreamer::SK_AsmStreamer) || - (NewCU->getUniqueID() == 0); + (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport()) || + (NewCU->getUniqueID() == 0); - // DW_AT_stmt_list is a offset of line number information for this - // compile unit in debug_line section. For split dwarf this is - // left in the skeleton CU and so not included. - // The line table entries are not always emitted in assembly, so it - // is not okay to use line_table_start here. if (!useSplitDwarf()) { + // DW_AT_stmt_list is a offset of line number information for this + // compile unit in debug_line section. For split dwarf this is + // left in the skeleton CU and so not included. + // The line table entries are not always emitted in assembly, so it + // is not okay to use line_table_start here. if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset, - UseTheFirstCU ? - Asm->GetTempSymbol("section_line") : LineTableStartSym); + NewCU->addSectionLabel( + Die, dwarf::DW_AT_stmt_list, + UseTheFirstCU ? Asm->GetTempSymbol("section_line") + : LineTableStartSym); else if (UseTheFirstCU) - NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0); + NewCU->addSectionOffset(Die, dwarf::DW_AT_stmt_list, 0); else - NewCU->addDelta(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, - LineTableStartSym, DwarfLineSectionSym); + NewCU->addSectionDelta(Die, dwarf::DW_AT_stmt_list, + LineTableStartSym, DwarfLineSectionSym); + + // If we're using split dwarf the compilation dir is going to be in the + // skeleton CU and so we don't need to duplicate it here. + if (!CompilationDir.empty()) + NewCU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); + + // Flags to let the linker know we have emitted new style pubnames. Only + // emit it here if we don't have a skeleton CU for split dwarf. + if (GenerateGnuPubSections) { + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) + NewCU->addSectionLabel( + Die, dwarf::DW_AT_GNU_pubnames, + Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID())); + else + NewCU->addSectionDelta( + Die, dwarf::DW_AT_GNU_pubnames, + Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()), + DwarfGnuPubNamesSectionSym); + + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) + NewCU->addSectionLabel( + Die, dwarf::DW_AT_GNU_pubtypes, + Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID())); + else + NewCU->addSectionDelta( + Die, dwarf::DW_AT_GNU_pubtypes, + Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()), + DwarfGnuPubTypesSectionSym); + } } - // If we're using split dwarf the compilation dir is going to be in the - // skeleton CU and so we don't need to duplicate it here. - if (!useSplitDwarf() && !CompilationDir.empty()) - NewCU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); - - // Flag to let the linker know we have emitted new style pubnames. Only - // emit it here if we don't have a skeleton CU for split dwarf. - if (!useSplitDwarf() && GenerateGnuPubSections) - NewCU->addFlag(Die, dwarf::DW_AT_GNU_pubnames); - if (DIUnit.isOptimized()) NewCU->addFlag(Die, dwarf::DW_AT_APPLE_optimized); @@ -790,20 +817,24 @@ CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) { if (unsigned RVer = DIUnit.getRunTimeVersion()) NewCU->addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, - dwarf::DW_FORM_data1, RVer); + dwarf::DW_FORM_data1, RVer); if (!FirstCU) FirstCU = NewCU; InfoHolder.addUnit(NewCU); - CUMap.insert(std::make_pair(N, NewCU)); + CUMap.insert(std::make_pair(DIUnit, NewCU)); + CUDieMap.insert(std::make_pair(Die, NewCU)); return NewCU; } // Construct subprogram DIE. -void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU, - const MDNode *N) { +void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU, const MDNode *N) { + // FIXME: We should only call this routine once, however, during LTO if a + // program is defined in multiple CUs we could end up calling it out of + // beginModule as we walk the CUs. + CompileUnit *&CURef = SPMap[N]; if (CURef) return; @@ -817,14 +848,8 @@ void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU, DIE *SubprogramDie = TheCU->getOrCreateSubprogramDIE(SP); - // Add to map. - TheCU->insertDIE(N, SubprogramDie); - - // Add to context owner. - TheCU->addToContextOwner(SubprogramDie, SP.getContext()); - // Expose as a global name. - TheCU->addGlobalName(SP.getName(), SubprogramDie); + TheCU->addGlobalName(SP.getName(), SubprogramDie, resolve(SP.getContext())); } void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU, @@ -865,10 +890,9 @@ void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU, unsigned FileID = getOrCreateSourceID(Module.getContext().getFilename(), Module.getContext().getDirectory(), TheCU->getUniqueID()); - TheCU->addUInt(IMDie, dwarf::DW_AT_decl_file, 0, FileID); - TheCU->addUInt(IMDie, dwarf::DW_AT_decl_line, 0, Module.getLineNumber()); - TheCU->addDIEEntry(IMDie, dwarf::DW_AT_import, dwarf::DW_FORM_ref4, - EntityDie); + TheCU->addUInt(IMDie, dwarf::DW_AT_decl_file, None, FileID); + TheCU->addUInt(IMDie, dwarf::DW_AT_decl_line, None, Module.getLineNumber()); + TheCU->addDIEEntry(IMDie, dwarf::DW_AT_import, EntityDie); StringRef Name = Module.getName(); if (!Name.empty()) TheCU->addString(IMDie, dwarf::DW_AT_name, Name); @@ -906,7 +930,7 @@ void DwarfDebug::beginModule() { ScopesWithImportedEntities.end(), less_first()); DIArray GVs = CUNode.getGlobalVariables(); for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) - CU->createGlobalVariableDIE(GVs.getElement(i)); + CU->createGlobalVariableDIE(DIGlobalVariable(GVs.getElement(i))); DIArray SPs = CUNode.getSubprograms(); for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) constructSubprogramDIE(CU, SPs.getElement(i)); @@ -933,23 +957,24 @@ void DwarfDebug::beginModule() { void DwarfDebug::computeInlinedDIEs() { // Attach DW_AT_inline attribute with inlined subprogram DIEs. for (SmallPtrSet::iterator AI = InlinedSubprogramDIEs.begin(), - AE = InlinedSubprogramDIEs.end(); AI != AE; ++AI) { + AE = InlinedSubprogramDIEs.end(); + AI != AE; ++AI) { DIE *ISP = *AI; - FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined); + FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined); } for (DenseMap::iterator AI = AbstractSPDies.begin(), - AE = AbstractSPDies.end(); AI != AE; ++AI) { + AE = AbstractSPDies.end(); + AI != AE; ++AI) { DIE *ISP = AI->second; if (InlinedSubprogramDIEs.count(ISP)) continue; - FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined); + FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined); } } // Collect info for variables that were optimized out. void DwarfDebug::collectDeadVariables() { const Module *M = MMI->getModule(); - DenseMap DeadFnScopeMap; if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) { for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { @@ -957,33 +982,34 @@ void DwarfDebug::collectDeadVariables() { DIArray Subprograms = TheCU.getSubprograms(); for (unsigned i = 0, e = Subprograms.getNumElements(); i != e; ++i) { DISubprogram SP(Subprograms.getElement(i)); - if (ProcessedSPNodes.count(SP) != 0) continue; - if (!SP.isSubprogram()) continue; - if (!SP.isDefinition()) continue; + if (ProcessedSPNodes.count(SP) != 0) + continue; + if (!SP.isSubprogram()) + continue; + if (!SP.isDefinition()) + continue; DIArray Variables = SP.getVariables(); - if (Variables.getNumElements() == 0) continue; - - LexicalScope *Scope = - new LexicalScope(NULL, DIDescriptor(SP), NULL, false); - DeadFnScopeMap[SP] = Scope; + if (Variables.getNumElements() == 0) + continue; // Construct subprogram DIE and add variables DIEs. - CompileUnit *SPCU = CUMap.lookup(TheCU); + CompileUnit *SPCU = static_cast(CUMap.lookup(TheCU)); assert(SPCU && "Unable to find Compile Unit!"); + // FIXME: See the comment in constructSubprogramDIE about duplicate + // subprogram DIEs. constructSubprogramDIE(SPCU, SP); - DIE *ScopeDIE = SPCU->getDIE(SP); + DIE *SPDIE = SPCU->getDIE(SP); for (unsigned vi = 0, ve = Variables.getNumElements(); vi != ve; ++vi) { DIVariable DV(Variables.getElement(vi)); - if (!DV.isVariable()) continue; - DbgVariable NewVar(DV, NULL); - if (DIE *VariableDIE = - SPCU->constructVariableDIE(&NewVar, Scope->isAbstractScope())) - ScopeDIE->addChild(VariableDIE); + if (!DV.isVariable()) + continue; + DbgVariable NewVar(DV, NULL, this); + if (DIE *VariableDIE = SPCU->constructVariableDIE(NewVar, false)) + SPDIE->addChild(VariableDIE); } } } } - DeleteContainerSeconds(DeadFnScopeMap); } // Type Signature [7.27] and ODR Hash code. @@ -1015,7 +1041,7 @@ static bool isContainedInAnonNamespace(DIE *Die) { /// Test if the current CU language is C++ and that we have /// a named type that is not contained in an anonymous namespace. -static bool shouldAddODRHash(CompileUnit *CU, DIE *Die) { +static bool shouldAddODRHash(TypeUnit *CU, DIE *Die) { return CU->getLanguage() == dwarf::DW_LANG_C_plus_plus && getDIEStringAttr(Die, dwarf::DW_AT_name) != "" && !isContainedInAnonNamespace(Die); @@ -1028,46 +1054,31 @@ void DwarfDebug::finalizeModuleInfo() { // Attach DW_AT_inline attribute with inlined subprogram DIEs. computeInlinedDIEs(); - // Split out type units and conditionally add an ODR tag to the split - // out type. - // FIXME: Do type splitting. - for (unsigned i = 0, e = TypeUnits.size(); i != e; ++i) { - DIE *Die = TypeUnits[i]; - DIEHash Hash; - // If we've requested ODR hashes and it's applicable for an ODR hash then - // add the ODR signature now. - // FIXME: This should be added onto the type unit, not the type, but this - // works as an intermediate stage. - if (GenerateODRHash && shouldAddODRHash(CUMap.begin()->second, Die)) - CUMap.begin()->second->addUInt(Die, dwarf::DW_AT_GNU_odr_signature, - dwarf::DW_FORM_data8, - Hash.computeDIEODRSignature(Die)); - } - // Handle anything that needs to be done on a per-cu basis. - for (DenseMap::iterator CUI = CUMap.begin(), - CUE = CUMap.end(); - CUI != CUE; ++CUI) { - CompileUnit *TheCU = CUI->second; + for (SmallVectorImpl::const_iterator I = getUnits().begin(), + E = getUnits().end(); + I != E; ++I) { + Unit *TheU = *I; // Emit DW_AT_containing_type attribute to connect types with their // vtable holding type. - TheCU->constructContainingTypeDIEs(); + TheU->constructContainingTypeDIEs(); // If we're splitting the dwarf out now that we've got the entire // CU then construct a skeleton CU based upon it. - if (useSplitDwarf()) { + if (useSplitDwarf() && + TheU->getUnitDie()->getTag() == dwarf::DW_TAG_compile_unit) { uint64_t ID = 0; if (GenerateCUHash) { DIEHash CUHash; - ID = CUHash.computeCUSignature(TheCU->getCUDie()); + ID = CUHash.computeCUSignature(*TheU->getUnitDie()); } // This should be a unique identifier when we want to build .dwp files. - TheCU->addUInt(TheCU->getCUDie(), dwarf::DW_AT_GNU_dwo_id, - dwarf::DW_FORM_data8, ID); + TheU->addUInt(TheU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id, + dwarf::DW_FORM_data8, ID); // Now construct the skeleton CU associated. - CompileUnit *SkCU = constructSkeletonCU(TheCU); + CompileUnit *SkCU = constructSkeletonCU(static_cast(TheU)); // This should be a unique identifier when we want to build .dwp files. - SkCU->addUInt(SkCU->getCUDie(), dwarf::DW_AT_GNU_dwo_id, + SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8, ID); } } @@ -1079,9 +1090,9 @@ void DwarfDebug::finalizeModuleInfo() { } void DwarfDebug::endSections() { - // Filter labels by section. - for (size_t n = 0; n < Labels.size(); n++) { - const SymbolCU &SCU = Labels[n]; + // Filter labels by section. + for (size_t n = 0; n < ArangeLabels.size(); n++) { + const SymbolCU &SCU = ArangeLabels[n]; if (SCU.Sym->isInSection()) { // Make a note of this symbol and it's section. const MCSection *Section = &SCU.Sym->getSection(); @@ -1095,30 +1106,47 @@ void DwarfDebug::endSections() { } } - // Add terminating symbols for each section. + // Build a list of sections used. + std::vector Sections; for (SectionMapType::iterator it = SectionMap.begin(); it != SectionMap.end(); it++) { const MCSection *Section = it->first; + Sections.push_back(Section); + } + + // Sort the sections into order. + // This is only done to ensure consistent output order across different runs. + std::sort(Sections.begin(), Sections.end(), SectionSort); + + // Add terminating symbols for each section. + for (unsigned ID = 0; ID < Sections.size(); ID++) { + const MCSection *Section = Sections[ID]; MCSymbol *Sym = NULL; if (Section) { - Sym = Asm->GetTempSymbol(Section->getLabelEndName()); + // We can't call MCSection::getLabelEndName, as it's only safe to do so + // if we know the section name up-front. For user-created sections, the + // resulting + // label may not be valid to use as a label. (section names can use a + // greater + // set of characters on some systems) + Sym = Asm->GetTempSymbol("debug_end", ID); Asm->OutStreamer.SwitchSection(Section); Asm->OutStreamer.EmitLabel(Sym); } // Insert a final terminator. - SymbolCU Entry; - Entry.CU = NULL; - Entry.Sym = Sym; - SectionMap[Section].push_back(Entry); + SectionMap[Section].push_back(SymbolCU(NULL, Sym)); } } // Emit all Dwarf sections that should come after the content. void DwarfDebug::endModule() { + assert(CurFn == 0); + assert(CurMI == 0); - if (!FirstCU) return; + if (!FirstCU) + return; // End any existing sections. // TODO: Does this need to happen? @@ -1127,57 +1155,32 @@ void DwarfDebug::endModule() { // Finalize the debug info for the module. finalizeModuleInfo(); - if (!useSplitDwarf()) { - emitDebugStr(); + emitDebugStr(); - // Emit all the DIEs into a debug info section. - emitDebugInfo(); + // Emit all the DIEs into a debug info section. + emitDebugInfo(); - // Corresponding abbreviations into a abbrev section. - emitAbbreviations(); + // Corresponding abbreviations into a abbrev section. + emitAbbreviations(); - // Emit info into a debug loc section. - emitDebugLoc(); + // Emit info into a debug loc section. + emitDebugLoc(); - // Emit info into a debug aranges section. - emitDebugARanges(); + // Emit info into a debug aranges section. + emitDebugARanges(); - // Emit info into a debug ranges section. - emitDebugRanges(); + // Emit info into a debug ranges section. + emitDebugRanges(); - // Emit info into a debug macinfo section. - emitDebugMacInfo(); + // Emit info into a debug macinfo section. + emitDebugMacInfo(); - } else { - // TODO: Fill this in for separated debug sections and separate - // out information into new sections. - emitDebugStr(); - if (useSplitDwarf()) - emitDebugStrDWO(); - - // Emit the debug info section and compile units. - emitDebugInfo(); + if (useSplitDwarf()) { + emitDebugStrDWO(); emitDebugInfoDWO(); - - // Corresponding abbreviations into a abbrev section. - emitAbbreviations(); emitDebugAbbrevDWO(); - - // Emit info into a debug loc section. - emitDebugLoc(); - - // Emit info into a debug aranges section. - emitDebugARanges(); - - // Emit info into a debug ranges section. - emitDebugRanges(); - - // Emit info into a debug macinfo section. - emitDebugMacInfo(); - // Emit DWO addresses. InfoHolder.emitAddresses(Asm->getObjFileLowering().getDwarfAddrSection()); - } // Emit info into the dwarf accelerator table sections. @@ -1196,13 +1199,6 @@ void DwarfDebug::endModule() { // clean up. SPMap.clear(); - for (DenseMap::iterator I = CUMap.begin(), - E = CUMap.end(); I != E; ++I) - delete I->second; - - for (SmallVectorImpl::iterator I = SkeletonCUs.begin(), - E = SkeletonCUs.end(); I != E; ++I) - delete *I; // Reset these for the next Module if we have one. FirstCU = NULL; @@ -1222,15 +1218,14 @@ DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV, if (!Scope) return NULL; - AbsDbgVariable = new DbgVariable(Var, NULL); + AbsDbgVariable = new DbgVariable(Var, NULL, this); addScopeVariable(Scope, AbsDbgVariable); AbstractVariables[Var] = AbsDbgVariable; return AbsDbgVariable; } // If Var is a current function argument then add it to CurrentFnArguments list. -bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF, - DbgVariable *Var, LexicalScope *Scope) { +bool DwarfDebug::addCurrentFnArgument(DbgVariable *Var, LexicalScope *Scope) { if (!LScopes.isCurrentFunctionScope(Scope)) return false; DIVariable DV = Var->getVariable(); @@ -1242,7 +1237,7 @@ bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF, size_t Size = CurrentFnArguments.size(); if (Size == 0) - CurrentFnArguments.resize(MF->getFunction()->arg_size()); + CurrentFnArguments.resize(CurFn->getFunction()->arg_size()); // llvm::Function argument size is not good indicator of how many // arguments does the function have at source level. if (ArgNo > Size) @@ -1252,14 +1247,15 @@ bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF, } // Collect variable information from side table maintained by MMI. -void -DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction *MF, - SmallPtrSet &Processed) { +void DwarfDebug::collectVariableInfoFromMMITable( + SmallPtrSet &Processed) { MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo(); for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(), - VE = VMap.end(); VI != VE; ++VI) { + VE = VMap.end(); + VI != VE; ++VI) { const MDNode *Var = VI->first; - if (!Var) continue; + if (!Var) + continue; Processed.insert(Var); DIVariable DV(Var); const std::pair &VP = VI->second; @@ -1271,9 +1267,9 @@ DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction *MF, continue; DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.second); - DbgVariable *RegVar = new DbgVariable(DV, AbsDbgVariable); + DbgVariable *RegVar = new DbgVariable(DV, AbsDbgVariable, this); RegVar->setFrameIndex(VP.first); - if (!addCurrentFnArgument(MF, RegVar, Scope)) + if (!addCurrentFnArgument(RegVar, Scope)) addScopeVariable(Scope, RegVar); if (AbsDbgVariable) AbsDbgVariable->setFrameIndex(VP.first); @@ -1284,8 +1280,8 @@ DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction *MF, // defined reg. static bool isDbgValueInDefinedReg(const MachineInstr *MI) { assert(MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!"); - return MI->getNumOperands() == 3 && - MI->getOperand(0).isReg() && MI->getOperand(0).getReg() && + return MI->getNumOperands() == 3 && MI->getOperand(0).isReg() && + MI->getOperand(0).getReg() && (MI->getOperand(1).isImm() || (MI->getOperand(1).isReg() && MI->getOperand(1).getReg() == 0U)); } @@ -1295,7 +1291,7 @@ static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm, const MCSymbol *FLabel, const MCSymbol *SLabel, const MachineInstr *MI) { - const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata(); + const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata(); assert(MI->getNumOperands() == 3); if (MI->getOperand(0).isReg()) { @@ -1320,22 +1316,22 @@ static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm, // Find variables for each lexical scope. void -DwarfDebug::collectVariableInfo(const MachineFunction *MF, - SmallPtrSet &Processed) { +DwarfDebug::collectVariableInfo(SmallPtrSet &Processed) { // Grab the variable info that was squirreled away in the MMI side-table. - collectVariableInfoFromMMITable(MF, Processed); + collectVariableInfoFromMMITable(Processed); - for (SmallVectorImpl::const_iterator - UVI = UserVariables.begin(), UVE = UserVariables.end(); UVI != UVE; - ++UVI) { + for (SmallVectorImpl::const_iterator + UVI = UserVariables.begin(), + UVE = UserVariables.end(); + UVI != UVE; ++UVI) { const MDNode *Var = *UVI; if (Processed.count(Var)) continue; // History contains relevant DBG_VALUE instructions for Var and instructions // clobbering it. - SmallVectorImpl &History = DbgValues[Var]; + SmallVectorImpl &History = DbgValues[Var]; if (History.empty()) continue; const MachineInstr *MInsn = History.front(); @@ -1343,7 +1339,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, DIVariable DV(Var); LexicalScope *Scope = NULL; if (DV.getTag() == dwarf::DW_TAG_arg_variable && - DISubprogram(DV.getContext()).describes(MF->getFunction())) + DISubprogram(DV.getContext()).describes(CurFn->getFunction())) Scope = LScopes.getCurrentFunctionScope(); else if (MDNode *IA = DV.getInlinedAt()) Scope = LScopes.findInlinedScope(DebugLoc::getFromDILocation(IA)); @@ -1356,15 +1352,15 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, Processed.insert(DV); assert(MInsn->isDebugValue() && "History must begin with debug value"); DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc()); - DbgVariable *RegVar = new DbgVariable(DV, AbsVar); - if (!addCurrentFnArgument(MF, RegVar, Scope)) + DbgVariable *RegVar = new DbgVariable(DV, AbsVar, this); + if (!addCurrentFnArgument(RegVar, Scope)) addScopeVariable(Scope, RegVar); if (AbsVar) AbsVar->setMInsn(MInsn); // Simplify ranges that are fully coalesced. - if (History.size() <= 1 || (History.size() == 2 && - MInsn->isIdenticalTo(History.back()))) { + if (History.size() <= 1 || + (History.size() == 2 && MInsn->isIdenticalTo(History.back()))) { RegVar->setMInsn(MInsn); continue; } @@ -1372,14 +1368,16 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, // Handle multiple DBG_VALUE instructions describing one variable. RegVar->setDotDebugLocOffset(DotDebugLocEntries.size()); - for (SmallVectorImpl::const_iterator - HI = History.begin(), HE = History.end(); HI != HE; ++HI) { + for (SmallVectorImpl::const_iterator + HI = History.begin(), + HE = History.end(); + HI != HE; ++HI) { const MachineInstr *Begin = *HI; assert(Begin->isDebugValue() && "Invalid History entry"); // Check if DBG_VALUE is truncating a range. - if (Begin->getNumOperands() > 1 && Begin->getOperand(0).isReg() - && !Begin->getOperand(0).getReg()) + if (Begin->getNumOperands() > 1 && Begin->getOperand(0).isReg() && + !Begin->getOperand(0).getReg()) continue; // Compute the range for a register location. @@ -1393,7 +1391,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, else { const MachineInstr *End = HI[1]; DEBUG(dbgs() << "DotDebugLoc Pair:\n" - << "\t" << *Begin << "\t" << *End << "\n"); + << "\t" << *Begin << "\t" << *End << "\n"); if (End->isDebugValue()) SLabel = getLabelBeforeInsn(End); else { @@ -1405,8 +1403,8 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, } // The value is valid until the next DBG_VALUE or clobber. - DotDebugLocEntries.push_back(getDebugLocEntry(Asm, FLabel, SLabel, - Begin)); + DotDebugLocEntries.push_back( + getDebugLocEntry(Asm, FLabel, SLabel, Begin)); } DotDebugLocEntries.push_back(DotDebugLocEntry()); } @@ -1419,7 +1417,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, if (!DV || !DV.isVariable() || !Processed.insert(DV)) continue; if (LexicalScope *Scope = LScopes.findLexicalScope(DV.getContext())) - addScopeVariable(Scope, new DbgVariable(DV, NULL)); + addScopeVariable(Scope, new DbgVariable(DV, NULL, this)); } } @@ -1437,6 +1435,8 @@ MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) { // Process beginning of an instruction. void DwarfDebug::beginInstruction(const MachineInstr *MI) { + assert(CurMI == 0); + CurMI = MI; // Check if source location changes, but ignore DBG_VALUE locations. if (!MI->isDebugValue()) { DebugLoc DL = MI->getDebugLoc(); @@ -1459,8 +1459,8 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { } // Insert labels where requested. - DenseMap::iterator I = - LabelsBeforeInsn.find(MI); + DenseMap::iterator I = + LabelsBeforeInsn.find(MI); // No label needed. if (I == LabelsBeforeInsn.end()) @@ -1478,14 +1478,16 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { } // Process end of an instruction. -void DwarfDebug::endInstruction(const MachineInstr *MI) { +void DwarfDebug::endInstruction() { + assert(CurMI != 0); // Don't create a new label after DBG_VALUE instructions. // They don't generate code. - if (!MI->isDebugValue()) + if (!CurMI->isDebugValue()) PrevLabel = 0; - DenseMap::iterator I = - LabelsAfterInsn.find(MI); + DenseMap::iterator I = + LabelsAfterInsn.find(CurMI); + CurMI = 0; // No label needed. if (I == LabelsAfterInsn.end()) @@ -1515,8 +1517,10 @@ void DwarfDebug::identifyScopeMarkers() { const SmallVectorImpl &Children = S->getChildren(); if (!Children.empty()) - for (SmallVectorImpl::const_iterator SI = Children.begin(), - SE = Children.end(); SI != SE; ++SI) + for (SmallVectorImpl::const_iterator + SI = Children.begin(), + SE = Children.end(); + SI != SE; ++SI) WorkList.push_back(*SI); if (S->isAbstractScope()) @@ -1526,7 +1530,8 @@ void DwarfDebug::identifyScopeMarkers() { if (Ranges.empty()) continue; for (SmallVectorImpl::const_iterator RI = Ranges.begin(), - RE = Ranges.end(); RI != RE; ++RI) { + RE = Ranges.end(); + RI != RE; ++RI) { assert(RI->first && "InsnRange does not have first instruction!"); assert(RI->second && "InsnRange does not have second instruction!"); requestLabelBeforeInsn(RI->first); @@ -1562,36 +1567,46 @@ static DebugLoc getFnDebugLoc(DebugLoc DL, const LLVMContext &Ctx) { // Gather pre-function debug information. Assumes being called immediately // after the function entry point has been emitted. void DwarfDebug::beginFunction(const MachineFunction *MF) { - if (!MMI->hasDebugInfo()) return; + CurFn = MF; + + // If there's no debug info for the function we're not going to do anything. + if (!MMI->hasDebugInfo()) + return; + + // Grab the lexical scopes for the function, if we don't have any of those + // then we're not going to be able to do anything. LScopes.initialize(*MF); - if (LScopes.empty()) return; + if (LScopes.empty()) + return; + + assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't cleaned"); + + // Make sure that each lexical scope will have a begin/end label. identifyScopeMarkers(); // Set DwarfCompileUnitID in MCContext to the Compile Unit this function - // belongs to. + // belongs to so that we add to the correct per-cu line table in the + // non-asm case. LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); CompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); assert(TheCU && "Unable to find compile unit!"); - if (Asm->TM.hasMCUseLoc() && - Asm->OutStreamer.getKind() == MCStreamer::SK_AsmStreamer) + if (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport()) // Use a single line table if we are using .loc and generating assembly. Asm->OutStreamer.getContext().setDwarfCompileUnitID(0); else Asm->OutStreamer.getContext().setDwarfCompileUnitID(TheCU->getUniqueID()); - FunctionBeginSym = Asm->GetTempSymbol("func_begin", - Asm->getFunctionNumber()); + // Emit a label for the function so that we have a beginning address. + FunctionBeginSym = Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber()); // Assumes in correct section after the entry point. Asm->OutStreamer.EmitLabel(FunctionBeginSym); - assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't cleaned"); - const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo(); // LiveUserVar - Map physreg numbers to the MDNode they contain. - std::vector LiveUserVar(TRI->getNumRegs()); + std::vector LiveUserVar(TRI->getNumRegs()); - for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); - I != E; ++I) { + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E; + ++I) { bool AtBlockEntry = true; for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); II != IE; ++II) { @@ -1602,22 +1617,21 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // Keep track of user variables. const MDNode *Var = - MI->getOperand(MI->getNumOperands() - 1).getMetadata(); + MI->getOperand(MI->getNumOperands() - 1).getMetadata(); // Variable is in a register, we need to check for clobbers. if (isDbgValueInDefinedReg(MI)) LiveUserVar[MI->getOperand(0).getReg()] = Var; // Check the history of this variable. - SmallVectorImpl &History = DbgValues[Var]; + SmallVectorImpl &History = DbgValues[Var]; if (History.empty()) { UserVariables.push_back(Var); // The first mention of a function argument gets the FunctionBeginSym // label, so arguments are visible when breaking at function entry. DIVariable DV(Var); if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable && - DISubprogram(getDISubprogram(DV.getContext())) - .describes(MF->getFunction())) + getDISubprogram(DV.getContext()).describes(MF->getFunction())) LabelsBeforeInsn[MI] = FunctionBeginSym; } else { // We have seen this variable before. Try to coalesce DBG_VALUEs. @@ -1627,8 +1641,8 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { if (History.size() >= 2 && Prev->isIdenticalTo(History[History.size() - 2])) { DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n" - << "\t" << *Prev - << "\t" << *History[History.size() - 2] << "\n"); + << "\t" << *Prev << "\t" + << *History[History.size() - 2] << "\n"); History.pop_back(); } @@ -1639,11 +1653,11 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // Previous register assignment needs to terminate at the end of // its basic block. MachineBasicBlock::const_iterator LastMI = - PrevMBB->getLastNonDebugInstr(); + PrevMBB->getLastNonDebugInstr(); if (LastMI == PrevMBB->end()) { // Drop DBG_VALUE for empty range. DEBUG(dbgs() << "Dropping DBG_VALUE for empty range:\n" - << "\t" << *Prev << "\n"); + << "\t" << *Prev << "\n"); History.pop_back(); } else if (llvm::next(PrevMBB) != PrevMBB->getParent()->end()) // Terminate after LastMI. @@ -1665,11 +1679,12 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // Check if the instruction clobbers any registers with debug vars. for (MachineInstr::const_mop_iterator MOI = MI->operands_begin(), - MOE = MI->operands_end(); MOI != MOE; ++MOI) { + MOE = MI->operands_end(); + MOI != MOE; ++MOI) { if (!MOI->isReg() || !MOI->isDef() || !MOI->getReg()) continue; - for (MCRegAliasIterator AI(MOI->getReg(), TRI, true); - AI.isValid(); ++AI) { + for (MCRegAliasIterator AI(MOI->getReg(), TRI, true); AI.isValid(); + ++AI) { unsigned Reg = *AI; const MDNode *Var = LiveUserVar[Reg]; if (!Var) @@ -1681,7 +1696,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { DbgValueHistoryMap::iterator HistI = DbgValues.find(Var); if (HistI == DbgValues.end()) continue; - SmallVectorImpl &History = HistI->second; + SmallVectorImpl &History = HistI->second; if (History.empty()) continue; const MachineInstr *Prev = History.back(); @@ -1703,7 +1718,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { for (DbgValueHistoryMap::iterator I = DbgValues.begin(), E = DbgValues.end(); I != E; ++I) { - SmallVectorImpl &History = I->second; + SmallVectorImpl &History = I->second; if (History.empty()) continue; @@ -1712,7 +1727,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) { const MachineBasicBlock *PrevMBB = Prev->getParent(); MachineBasicBlock::const_iterator LastMI = - PrevMBB->getLastNonDebugInstr(); + PrevMBB->getLastNonDebugInstr(); if (LastMI == PrevMBB->end()) // Drop DBG_VALUE for empty range. History.pop_back(); @@ -1736,13 +1751,14 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // Record beginning of function. if (!PrologEndLoc.isUnknown()) { - DebugLoc FnStartDL = getFnDebugLoc(PrologEndLoc, - MF->getFunction()->getContext()); - recordSourceLine(FnStartDL.getLine(), FnStartDL.getCol(), - FnStartDL.getScope(MF->getFunction()->getContext()), - // We'd like to list the prologue as "not statements" but GDB behaves - // poorly if we do that. Revisit this with caution/GDB (7.5+) testing. - DWARF2_FLAG_IS_STMT); + DebugLoc FnStartDL = + getFnDebugLoc(PrologEndLoc, MF->getFunction()->getContext()); + recordSourceLine( + FnStartDL.getLine(), FnStartDL.getCol(), + FnStartDL.getScope(MF->getFunction()->getContext()), + // We'd like to list the prologue as "not statements" but GDB behaves + // poorly if we do that. Revisit this with caution/GDB (7.5+) testing. + DWARF2_FLAG_IS_STMT); } } @@ -1779,18 +1795,29 @@ void DwarfDebug::addScopeVariable(LexicalScope *LS, DbgVariable *Var) { // Gather and emit post-function debug information. void DwarfDebug::endFunction(const MachineFunction *MF) { - if (!MMI->hasDebugInfo() || LScopes.empty()) return; + // Every beginFunction(MF) call should be followed by an endFunction(MF) call, + // though the beginFunction may not be called at all. + // We should handle both cases. + if (CurFn == 0) + CurFn = MF; + else + assert(CurFn == MF); + assert(CurFn != 0); + + if (!MMI->hasDebugInfo() || LScopes.empty()) { + CurFn = 0; + return; + } // Define end label for subprogram. - FunctionEndSym = Asm->GetTempSymbol("func_end", - Asm->getFunctionNumber()); + FunctionEndSym = Asm->GetTempSymbol("func_end", Asm->getFunctionNumber()); // Assumes in correct section after the entry point. Asm->OutStreamer.EmitLabel(FunctionEndSym); // Set DwarfCompileUnitID in MCContext to default value. Asm->OutStreamer.getContext().setDwarfCompileUnitID(0); SmallPtrSet ProcessedVars; - collectVariableInfo(MF, ProcessedVars); + collectVariableInfo(ProcessedVars); LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); CompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); @@ -1815,7 +1842,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { if (AbstractVariables.lookup(CleanDV)) continue; if (LexicalScope *Scope = LScopes.findAbstractScope(DV.getContext())) - addScopeVariable(Scope, new DbgVariable(DV, NULL)); + addScopeVariable(Scope, new DbgVariable(DV, NULL, this)); } } if (ProcessedSPNodes.count(AScope->getScopeNode()) == 0) @@ -1824,12 +1851,13 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { DIE *CurFnDIE = constructScopeDIE(TheCU, FnScope); - if (!MF->getTarget().Options.DisableFramePointerElim(*MF)) + if (!CurFn->getTarget().Options.DisableFramePointerElim(*CurFn)) TheCU->addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr); // Clear debug info - for (ScopeVariablesMap::iterator - I = ScopeVariables.begin(), E = ScopeVariables.end(); I != E; ++I) + for (ScopeVariablesMap::iterator I = ScopeVariables.begin(), + E = ScopeVariables.end(); + I != E; ++I) DeleteContainerPointers(I->second); ScopeVariables.clear(); DeleteContainerPointers(CurrentFnArguments); @@ -1839,6 +1867,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { LabelsBeforeInsn.clear(); LabelsAfterInsn.clear(); PrevLabel = NULL; + CurFn = 0; } // Register a source line with debug info. Returns the unique label that was @@ -1874,8 +1903,8 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, } else llvm_unreachable("Unexpected scope info"); - Src = getOrCreateSourceID(Fn, Dir, - Asm->OutStreamer.getContext().getDwarfCompileUnitID()); + Src = getOrCreateSourceID( + Fn, Dir, Asm->OutStreamer.getContext().getDwarfCompileUnitID()); } Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, Flags, 0, 0, Fn); } @@ -1884,9 +1913,9 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, // Emit Methods //===----------------------------------------------------------------------===// -// Compute the size and offset of a DIE. -unsigned -DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) { +// Compute the size and offset of a DIE. The offset is relative to start of the +// CU. It returns the offset after laying out the DIE. +unsigned DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) { // Get the children. const std::vector &Children = Die->getChildren(); @@ -1895,7 +1924,7 @@ DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) { // Get the abbreviation for this DIE. unsigned AbbrevNumber = Die->getAbbrevNumber(); - const DIEAbbrev *Abbrev = Abbreviations->at(AbbrevNumber - 1); + const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1]; // Set DIE offset Die->setOffset(Offset); @@ -1903,7 +1932,7 @@ DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) { // Start the size with the size of abbreviation code. Offset += MCAsmInfo::getULEB128Size(AbbrevNumber); - const SmallVectorImpl &Values = Die->getValues(); + const SmallVectorImpl &Values = Die->getValues(); const SmallVectorImpl &AbbrevData = Abbrev->getData(); // Size the DIE attribute values. @@ -1927,20 +1956,24 @@ DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) { return Offset; } -// Compute the size and offset of all the DIEs. +// Compute the size and offset for each DIE. void DwarfUnits::computeSizeAndOffsets() { - // Offset from the beginning of debug info section. + // Offset from the first CU in the debug info section is 0 initially. unsigned SecOffset = 0; - for (SmallVectorImpl::iterator I = CUs.begin(), - E = CUs.end(); I != E; ++I) { + + // Iterate over each compile unit and set the size and offsets for each + // DIE within each compile unit. All offsets are CU relative. + for (SmallVectorImpl::const_iterator I = CUs.begin(), E = CUs.end(); + I != E; ++I) { (*I)->setDebugInfoOffset(SecOffset); - unsigned Offset = - sizeof(int32_t) + // Length of Compilation Unit Info - sizeof(int16_t) + // DWARF version number - sizeof(int32_t) + // Offset Into Abbrev. Section - sizeof(int8_t); // Pointer Size (in bytes) - unsigned EndOffset = computeSizeAndOffset((*I)->getCUDie(), Offset); + // CU-relative offset is reset to 0 here. + unsigned Offset = sizeof(int32_t) + // Length of Unit Info + (*I)->getHeaderSize(); // Unit-specific headers + + // EndOffset here is CU-relative, after laying out + // all of the CU DIE. + unsigned EndOffset = computeSizeAndOffset((*I)->getUnitDie(), Offset); SecOffset += EndOffset; } } @@ -1951,52 +1984,53 @@ void DwarfDebug::emitSectionLabels() { // Dwarf sections base addresses. DwarfInfoSectionSym = - emitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info"); + emitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info"); DwarfAbbrevSectionSym = - emitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev"); + emitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev"); if (useSplitDwarf()) - DwarfAbbrevDWOSectionSym = - emitSectionSym(Asm, TLOF.getDwarfAbbrevDWOSection(), - "section_abbrev_dwo"); + DwarfAbbrevDWOSectionSym = emitSectionSym( + Asm, TLOF.getDwarfAbbrevDWOSection(), "section_abbrev_dwo"); emitSectionSym(Asm, TLOF.getDwarfARangesSection()); if (const MCSection *MacroInfo = TLOF.getDwarfMacroInfoSection()) emitSectionSym(Asm, MacroInfo); DwarfLineSectionSym = - emitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line"); + emitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line"); emitSectionSym(Asm, TLOF.getDwarfLocSection()); - if (HasDwarfPubSections) { + if (GenerateGnuPubSections) { + DwarfGnuPubNamesSectionSym = + emitSectionSym(Asm, TLOF.getDwarfGnuPubNamesSection()); + DwarfGnuPubTypesSectionSym = + emitSectionSym(Asm, TLOF.getDwarfGnuPubTypesSection()); + } else if (HasDwarfPubSections) { emitSectionSym(Asm, TLOF.getDwarfPubNamesSection()); emitSectionSym(Asm, TLOF.getDwarfPubTypesSection()); - } else if (GenerateGnuPubSections) { - emitSectionSym(Asm, TLOF.getDwarfGnuPubNamesSection()); - emitSectionSym(Asm, TLOF.getDwarfGnuPubTypesSection()); } DwarfStrSectionSym = - emitSectionSym(Asm, TLOF.getDwarfStrSection(), "info_string"); + emitSectionSym(Asm, TLOF.getDwarfStrSection(), "info_string"); if (useSplitDwarf()) { DwarfStrDWOSectionSym = - emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string"); + emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string"); DwarfAddrSectionSym = - emitSectionSym(Asm, TLOF.getDwarfAddrSection(), "addr_sec"); + emitSectionSym(Asm, TLOF.getDwarfAddrSection(), "addr_sec"); } - DwarfDebugRangeSectionSym = emitSectionSym(Asm, TLOF.getDwarfRangesSection(), - "debug_range"); + DwarfDebugRangeSectionSym = + emitSectionSym(Asm, TLOF.getDwarfRangesSection(), "debug_range"); - DwarfDebugLocSectionSym = emitSectionSym(Asm, TLOF.getDwarfLocSection(), - "section_debug_loc"); + DwarfDebugLocSectionSym = + emitSectionSym(Asm, TLOF.getDwarfLocSection(), "section_debug_loc"); TextSectionSym = emitSectionSym(Asm, TLOF.getTextSection(), "text_begin"); emitSectionSym(Asm, TLOF.getDataSection()); } // Recursively emits a debug information entry. -void DwarfDebug::emitDIE(DIE *Die, std::vector *Abbrevs) { +void DwarfDebug::emitDIE(DIE *Die, ArrayRef Abbrevs) { // Get the abbreviation for this DIE. unsigned AbbrevNumber = Die->getAbbrevNumber(); - const DIEAbbrev *Abbrev = Abbrevs->at(AbbrevNumber - 1); + const DIEAbbrev *Abbrev = Abbrevs[AbbrevNumber - 1]; // Emit the code (index) for the abbreviation. if (Asm->isVerbose()) @@ -2006,54 +2040,65 @@ void DwarfDebug::emitDIE(DIE *Die, std::vector *Abbrevs) { dwarf::TagString(Abbrev->getTag())); Asm->EmitULEB128(AbbrevNumber); - const SmallVectorImpl &Values = Die->getValues(); + const SmallVectorImpl &Values = Die->getValues(); const SmallVectorImpl &AbbrevData = Abbrev->getData(); // Emit the DIE attribute values. for (unsigned i = 0, N = Values.size(); i < N; ++i) { - unsigned Attr = AbbrevData[i].getAttribute(); - unsigned Form = AbbrevData[i].getForm(); + dwarf::Attribute Attr = AbbrevData[i].getAttribute(); + dwarf::Form Form = AbbrevData[i].getForm(); assert(Form && "Too many attributes for DIE (check abbreviation)"); if (Asm->isVerbose()) Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr)); switch (Attr) { - case dwarf::DW_AT_abstract_origin: { + case dwarf::DW_AT_abstract_origin: + case dwarf::DW_AT_type: + case dwarf::DW_AT_friend: + case dwarf::DW_AT_specification: + case dwarf::DW_AT_import: + case dwarf::DW_AT_containing_type: { DIEEntry *E = cast(Values[i]); DIE *Origin = E->getEntry(); unsigned Addr = Origin->getOffset(); if (Form == dwarf::DW_FORM_ref_addr) { + assert(!useSplitDwarf() && "TODO: dwo files can't have relocations."); // For DW_FORM_ref_addr, output the offset from beginning of debug info // section. Origin->getOffset() returns the offset from start of the // compile unit. - DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; - Addr += Holder.getCUOffset(Origin->getCompileUnit()); + CompileUnit *CU = CUDieMap.lookup(Origin->getUnit()); + assert(CU && "CUDie should belong to a CU."); + Addr += CU->getDebugInfoOffset(); + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) + Asm->EmitLabelPlusOffset(DwarfInfoSectionSym, Addr, + DIEEntry::getRefAddrSize(Asm)); + else + Asm->EmitLabelOffsetDifference(DwarfInfoSectionSym, Addr, + DwarfInfoSectionSym, + DIEEntry::getRefAddrSize(Asm)); + } else { + // Make sure Origin belong to the same CU. + assert(Die->getUnit() == Origin->getUnit() && + "The referenced DIE should belong to the same CU in ref4"); + Asm->EmitInt32(Addr); } - Asm->OutStreamer.EmitIntValue(Addr, - Form == dwarf::DW_FORM_ref_addr ? DIEEntry::getRefAddrSize(Asm) : 4); break; } case dwarf::DW_AT_ranges: { // DW_AT_range Value encodes offset in debug_range section. - DIEInteger *V = cast(Values[i]); + DIELabel *V = cast(Values[i]); - if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) { - Asm->EmitLabelPlusOffset(DwarfDebugRangeSectionSym, - V->getValue(), - 4); - } else { - Asm->EmitLabelOffsetDifference(DwarfDebugRangeSectionSym, - V->getValue(), - DwarfDebugRangeSectionSym, - 4); - } + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) + Asm->EmitSectionOffset(V->getValue(), DwarfDebugRangeSectionSym); + else + Asm->EmitLabelDifference(V->getValue(), DwarfDebugRangeSectionSym, 4); break; } case dwarf::DW_AT_location: { if (DIELabel *L = dyn_cast(Values[i])) { if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - Asm->EmitLabelReference(L->getValue(), 4); + Asm->EmitSectionOffset(L->getValue(), DwarfDebugLocSectionSym); else Asm->EmitLabelDifference(L->getValue(), DwarfDebugLocSectionSym, 4); } else { @@ -2091,54 +2136,29 @@ void DwarfDebug::emitDIE(DIE *Die, std::vector *Abbrevs) { // Emit the various dwarf units to the unit section USection with // the abbreviations going into ASection. -void DwarfUnits::emitUnits(DwarfDebug *DD, - const MCSection *USection, +void DwarfUnits::emitUnits(DwarfDebug *DD, const MCSection *USection, const MCSection *ASection, const MCSymbol *ASectionSym) { Asm->OutStreamer.SwitchSection(USection); - for (SmallVectorImpl::iterator I = CUs.begin(), - E = CUs.end(); I != E; ++I) { - CompileUnit *TheCU = *I; - DIE *Die = TheCU->getCUDie(); + for (SmallVectorImpl::iterator I = CUs.begin(), E = CUs.end(); I != E; + ++I) { + Unit *TheU = *I; + DIE *Die = TheU->getUnitDie(); // Emit the compile units header. - Asm->OutStreamer - .EmitLabel(Asm->GetTempSymbol(USection->getLabelBeginName(), - TheCU->getUniqueID())); + Asm->OutStreamer.EmitLabel( + Asm->GetTempSymbol(USection->getLabelBeginName(), TheU->getUniqueID())); // Emit size of content not including length itself - unsigned ContentSize = Die->getSize() + - sizeof(int16_t) + // DWARF version number - sizeof(int32_t) + // Offset Into Abbrev. Section - sizeof(int8_t); // Pointer Size (in bytes) + Asm->OutStreamer.AddComment("Length of Unit"); + Asm->EmitInt32(TheU->getHeaderSize() + Die->getSize()); - Asm->OutStreamer.AddComment("Length of Compilation Unit Info"); - Asm->EmitInt32(ContentSize); - Asm->OutStreamer.AddComment("DWARF version number"); - Asm->EmitInt16(DD->getDwarfVersion()); - Asm->OutStreamer.AddComment("Offset Into Abbrev. Section"); - Asm->EmitSectionOffset(Asm->GetTempSymbol(ASection->getLabelBeginName()), - ASectionSym); - Asm->OutStreamer.AddComment("Address Size (in bytes)"); - Asm->EmitInt8(Asm->getDataLayout().getPointerSize()); + TheU->emitHeader(ASection, ASectionSym); DD->emitDIE(Die, Abbreviations); - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol(USection->getLabelEndName(), - TheCU->getUniqueID())); - } -} - -/// For a given compile unit DIE, returns offset from beginning of debug info. -unsigned DwarfUnits::getCUOffset(DIE *Die) { - assert(Die->getTag() == dwarf::DW_TAG_compile_unit && - "Input DIE should be compile unit in getCUOffset."); - for (SmallVectorImpl::iterator I = CUs.begin(), E = CUs.end(); - I != E; ++I) { - CompileUnit *TheCU = *I; - if (TheCU->getCUDie() == Die) - return TheCU->getDebugInfoOffset(); + Asm->OutStreamer.EmitLabel( + Asm->GetTempSymbol(USection->getLabelEndName(), TheU->getUniqueID())); } - llvm_unreachable("The compile unit DIE should belong to CUs in DwarfUnits."); } // Emit the debug info section. @@ -2202,8 +2222,9 @@ void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { Asm->OutStreamer.AddComment("Section end label"); - Asm->OutStreamer.EmitSymbolValue(Asm->GetTempSymbol("section_end",SectionEnd), - Asm->getDataLayout().getPointerSize()); + Asm->OutStreamer.EmitSymbolValue( + Asm->GetTempSymbol("section_end", SectionEnd), + Asm->getDataLayout().getPointerSize()); // Mark end of matrix. Asm->OutStreamer.AddComment("DW_LNE_end_sequence"); @@ -2214,25 +2235,29 @@ void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { // Emit visible names into a hashed accelerator table section. void DwarfDebug::emitAccelNames() { - DwarfAccelTable AT(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, - dwarf::DW_FORM_data4)); - for (DenseMap::iterator I = CUMap.begin(), - E = CUMap.end(); I != E; ++I) { - CompileUnit *TheCU = I->second; - const StringMap > &Names = TheCU->getAccelNames(); - for (StringMap >::const_iterator - GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { + DwarfAccelTable AT( + DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)); + for (SmallVectorImpl::const_iterator I = getUnits().begin(), + E = getUnits().end(); + I != E; ++I) { + Unit *TheU = *I; + const StringMap > &Names = TheU->getAccelNames(); + for (StringMap >::const_iterator + GI = Names.begin(), + GE = Names.end(); + GI != GE; ++GI) { StringRef Name = GI->getKey(); - const std::vector &Entities = GI->second; - for (std::vector::const_iterator DI = Entities.begin(), - DE = Entities.end(); DI != DE; ++DI) - AT.AddName(Name, (*DI)); + const std::vector &Entities = GI->second; + for (std::vector::const_iterator DI = Entities.begin(), + DE = Entities.end(); + DI != DE; ++DI) + AT.AddName(Name, *DI); } } AT.FinalizeTable(Asm, "Names"); Asm->OutStreamer.SwitchSection( - Asm->getObjFileLowering().getDwarfAccelNamesSection()); + Asm->getObjFileLowering().getDwarfAccelNamesSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("names_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); @@ -2243,25 +2268,29 @@ void DwarfDebug::emitAccelNames() { // Emit objective C classes and categories into a hashed accelerator table // section. void DwarfDebug::emitAccelObjC() { - DwarfAccelTable AT(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, - dwarf::DW_FORM_data4)); - for (DenseMap::iterator I = CUMap.begin(), - E = CUMap.end(); I != E; ++I) { - CompileUnit *TheCU = I->second; - const StringMap > &Names = TheCU->getAccelObjC(); - for (StringMap >::const_iterator - GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { + DwarfAccelTable AT( + DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)); + for (SmallVectorImpl::const_iterator I = getUnits().begin(), + E = getUnits().end(); + I != E; ++I) { + Unit *TheU = *I; + const StringMap > &Names = TheU->getAccelObjC(); + for (StringMap >::const_iterator + GI = Names.begin(), + GE = Names.end(); + GI != GE; ++GI) { StringRef Name = GI->getKey(); - const std::vector &Entities = GI->second; - for (std::vector::const_iterator DI = Entities.begin(), - DE = Entities.end(); DI != DE; ++DI) - AT.AddName(Name, (*DI)); + const std::vector &Entities = GI->second; + for (std::vector::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()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfAccelObjCSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("objc_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); @@ -2271,25 +2300,30 @@ void DwarfDebug::emitAccelObjC() { // Emit namespace dies into a hashed accelerator table. void DwarfDebug::emitAccelNamespaces() { - DwarfAccelTable AT(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, - dwarf::DW_FORM_data4)); - for (DenseMap::iterator I = CUMap.begin(), - E = CUMap.end(); I != E; ++I) { - CompileUnit *TheCU = I->second; - const StringMap > &Names = TheCU->getAccelNamespace(); - for (StringMap >::const_iterator - GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { + DwarfAccelTable AT( + DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)); + for (SmallVectorImpl::const_iterator I = getUnits().begin(), + E = getUnits().end(); + I != E; ++I) { + Unit *TheU = *I; + const StringMap > &Names = + TheU->getAccelNamespace(); + for (StringMap >::const_iterator + GI = Names.begin(), + GE = Names.end(); + GI != GE; ++GI) { StringRef Name = GI->getKey(); - const std::vector &Entities = GI->second; - for (std::vector::const_iterator DI = Entities.begin(), - DE = Entities.end(); DI != DE; ++DI) - AT.AddName(Name, (*DI)); + const std::vector &Entities = GI->second; + for (std::vector::const_iterator DI = Entities.begin(), + DE = Entities.end(); + DI != DE; ++DI) + AT.AddName(Name, *DI); } } AT.FinalizeTable(Asm, "namespac"); - Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering() - .getDwarfAccelNamespaceSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfAccelNamespaceSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("namespac_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); @@ -2300,31 +2334,38 @@ void DwarfDebug::emitAccelNamespaces() { // Emit type dies into a hashed accelerator table. void DwarfDebug::emitAccelTypes() { std::vector Atoms; - Atoms.push_back(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, - dwarf::DW_FORM_data4)); - Atoms.push_back(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, - dwarf::DW_FORM_data2)); - Atoms.push_back(DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, - dwarf::DW_FORM_data1)); + Atoms.push_back( + DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)); + Atoms.push_back( + DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2)); + Atoms.push_back( + DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, 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 - GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { + for (SmallVectorImpl::const_iterator I = getUnits().begin(), + E = getUnits().end(); + I != E; ++I) { + Unit *TheU = *I; + const StringMap > > &Names = + TheU->getAccelTypes(); + for (StringMap< + std::vector > >::const_iterator + GI = Names.begin(), + GE = Names.end(); + GI != GE; ++GI) { StringRef Name = GI->getKey(); - const 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); + const 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); } } AT.FinalizeTable(Asm, "types"); - Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering() - .getDwarfAccelTypesSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfAccelTypesSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("types_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); @@ -2347,17 +2388,29 @@ void DwarfDebug::emitAccelTypes() { // reference in the pubname header doesn't change. /// computeIndexValue - Compute the gdb index value for the DIE and CU. -static dwarf::PubIndexEntryDescriptor computeIndexValue(CompileUnit *CU, - DIE *Die) { - dwarf::GDBIndexEntryLinkage IsStatic = - Die->findAttribute(dwarf::DW_AT_external) ? dwarf::GIEL_EXTERNAL - : dwarf::GIEL_STATIC; +static dwarf::PubIndexEntryDescriptor computeIndexValue(Unit *CU, + const DIE *Die) { + dwarf::GDBIndexEntryLinkage Linkage = dwarf::GIEL_STATIC; + + // We could have a specification DIE that has our most of our knowledge, + // look for that now. + DIEValue *SpecVal = Die->findAttribute(dwarf::DW_AT_specification); + if (SpecVal) { + DIE *SpecDIE = cast(SpecVal)->getEntry(); + if (SpecDIE->findAttribute(dwarf::DW_AT_external)) + Linkage = dwarf::GIEL_EXTERNAL; + } else if (Die->findAttribute(dwarf::DW_AT_external)) + Linkage = dwarf::GIEL_EXTERNAL; switch (Die->getTag()) { case dwarf::DW_TAG_class_type: case dwarf::DW_TAG_structure_type: case dwarf::DW_TAG_union_type: case dwarf::DW_TAG_enumeration_type: + return dwarf::PubIndexEntryDescriptor( + dwarf::GIEK_TYPE, CU->getLanguage() != dwarf::DW_LANG_C_plus_plus + ? dwarf::GIEL_STATIC + : dwarf::GIEL_EXTERNAL); case dwarf::DW_TAG_typedef: case dwarf::DW_TAG_base_type: case dwarf::DW_TAG_subrange_type: @@ -2365,10 +2418,10 @@ static dwarf::PubIndexEntryDescriptor computeIndexValue(CompileUnit *CU, case dwarf::DW_TAG_namespace: return dwarf::GIEK_TYPE; case dwarf::DW_TAG_subprogram: - return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_FUNCTION, IsStatic); + return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_FUNCTION, Linkage); case dwarf::DW_TAG_constant: case dwarf::DW_TAG_variable: - return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_VARIABLE, IsStatic); + return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_VARIABLE, Linkage); case dwarf::DW_TAG_enumerator: return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_VARIABLE, dwarf::GIEL_STATIC); @@ -2385,23 +2438,26 @@ void DwarfDebug::emitDebugPubNames(bool GnuStyle) { GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubNamesSection() : Asm->getObjFileLowering().getDwarfPubNamesSection(); - typedef DenseMap CUMapType; - for (CUMapType::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) { - CompileUnit *TheCU = I->second; - unsigned ID = TheCU->getUniqueID(); - - if (TheCU->getGlobalNames().empty()) - continue; + for (SmallVectorImpl::const_iterator I = getUnits().begin(), + E = getUnits().end(); + I != E; ++I) { + Unit *TheU = *I; + unsigned ID = TheU->getUniqueID(); // Start the dwarf pubnames section. Asm->OutStreamer.SwitchSection(PSec); + // Emit a label so we can reference the beginning of this pubname section. + if (GnuStyle) + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("gnu_pubnames", ID)); + // Emit the header. Asm->OutStreamer.AddComment("Length of Public Names Info"); - Asm->EmitLabelDifference(Asm->GetTempSymbol("pubnames_end", ID), - Asm->GetTempSymbol("pubnames_begin", ID), 4); + MCSymbol *BeginLabel = Asm->GetTempSymbol("pubnames_begin", ID); + MCSymbol *EndLabel = Asm->GetTempSymbol("pubnames_end", ID); + Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_begin", ID)); + Asm->OutStreamer.EmitLabel(BeginLabel); Asm->OutStreamer.AddComment("DWARF Version"); Asm->EmitInt16(dwarf::DW_PUBNAMES_VERSION); @@ -2416,17 +2472,18 @@ void DwarfDebug::emitDebugPubNames(bool GnuStyle) { 4); // Emit the pubnames for this compilation unit. - const StringMap &Globals = TheCU->getGlobalNames(); - for (StringMap::const_iterator - GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) { + const StringMap &Globals = TheU->getGlobalNames(); + for (StringMap::const_iterator GI = Globals.begin(), + GE = Globals.end(); + GI != GE; ++GI) { const char *Name = GI->getKeyData(); - DIE *Entity = GI->second; + const DIE *Entity = GI->second; Asm->OutStreamer.AddComment("DIE offset"); Asm->EmitInt32(Entity->getOffset()); if (GnuStyle) { - dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheCU, Entity); + dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheU, Entity); Asm->OutStreamer.AddComment( Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " + dwarf::GDBIndexEntryLinkageString(Desc.Linkage)); @@ -2435,32 +2492,41 @@ void DwarfDebug::emitDebugPubNames(bool GnuStyle) { if (Asm->isVerbose()) Asm->OutStreamer.AddComment("External Name"); - Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1)); + Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength() + 1)); } Asm->OutStreamer.AddComment("End Mark"); Asm->EmitInt32(0); - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_end", ID)); + Asm->OutStreamer.EmitLabel(EndLabel); } } void DwarfDebug::emitDebugPubTypes(bool GnuStyle) { const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection(); - const MCSection *PSec = Asm->getObjFileLowering().getDwarfPubTypesSection(); + const MCSection *PSec = + GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubTypesSection() + : Asm->getObjFileLowering().getDwarfPubTypesSection(); - for (DenseMap::iterator I = CUMap.begin(), - E = CUMap.end(); + for (SmallVectorImpl::const_iterator I = getUnits().begin(), + E = getUnits().end(); I != E; ++I) { - CompileUnit *TheCU = I->second; + Unit *TheU = *I; + unsigned ID = TheU->getUniqueID(); + // Start the dwarf pubtypes section. Asm->OutStreamer.SwitchSection(PSec); + + // Emit a label so we can reference the beginning of this pubtype section. + if (GnuStyle) + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("gnu_pubtypes", ID)); + + // Emit the header. Asm->OutStreamer.AddComment("Length of Public Types Info"); - Asm->EmitLabelDifference( - Asm->GetTempSymbol("pubtypes_end", TheCU->getUniqueID()), - Asm->GetTempSymbol("pubtypes_begin", TheCU->getUniqueID()), 4); + MCSymbol *BeginLabel = Asm->GetTempSymbol("pubtypes_begin", ID); + MCSymbol *EndLabel = Asm->GetTempSymbol("pubtypes_end", ID); + Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); - Asm->OutStreamer.EmitLabel( - Asm->GetTempSymbol("pubtypes_begin", TheCU->getUniqueID())); + Asm->OutStreamer.EmitLabel(BeginLabel); if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DWARF Version"); @@ -2468,27 +2534,28 @@ void DwarfDebug::emitDebugPubTypes(bool GnuStyle) { Asm->OutStreamer.AddComment("Offset of Compilation Unit Info"); Asm->EmitSectionOffset( - Asm->GetTempSymbol(ISec->getLabelBeginName(), TheCU->getUniqueID()), + Asm->GetTempSymbol(ISec->getLabelBeginName(), TheU->getUniqueID()), DwarfInfoSectionSym); Asm->OutStreamer.AddComment("Compilation Unit Length"); Asm->EmitLabelDifference( - Asm->GetTempSymbol(ISec->getLabelEndName(), TheCU->getUniqueID()), - Asm->GetTempSymbol(ISec->getLabelBeginName(), TheCU->getUniqueID()), 4); + Asm->GetTempSymbol(ISec->getLabelEndName(), TheU->getUniqueID()), + Asm->GetTempSymbol(ISec->getLabelBeginName(), TheU->getUniqueID()), 4); - const StringMap &Globals = TheCU->getGlobalTypes(); - for (StringMap::const_iterator GI = Globals.begin(), - GE = Globals.end(); + // Emit the pubtypes. + const StringMap &Globals = TheU->getGlobalTypes(); + for (StringMap::const_iterator GI = Globals.begin(), + GE = Globals.end(); GI != GE; ++GI) { const char *Name = GI->getKeyData(); - DIE *Entity = GI->second; + const DIE *Entity = GI->second; if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DIE offset"); Asm->EmitInt32(Entity->getOffset()); if (GnuStyle) { - dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheCU, Entity); + dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheU, Entity); Asm->OutStreamer.AddComment( Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " + dwarf::GDBIndexEntryLinkageString(Desc.Linkage)); @@ -2504,8 +2571,7 @@ void DwarfDebug::emitDebugPubTypes(bool GnuStyle) { Asm->OutStreamer.AddComment("End Mark"); Asm->EmitInt32(0); - Asm->OutStreamer.EmitLabel( - Asm->GetTempSymbol("pubtypes_end", TheCU->getUniqueID())); + Asm->OutStreamer.EmitLabel(EndLabel); } } @@ -2514,18 +2580,21 @@ void DwarfUnits::emitStrings(const MCSection *StrSection, const MCSection *OffsetSection = NULL, const MCSymbol *StrSecSym = NULL) { - if (StringPool.empty()) return; + if (StringPool.empty()) + return; // Start the dwarf str section. Asm->OutStreamer.SwitchSection(StrSection); // Get all of the string pool entries and put them in an array by their ID so // we can sort them. - SmallVector >*>, 64> Entries; + SmallVector< + std::pair > *>, + 64> Entries; - for (StringMap >::iterator - I = StringPool.begin(), E = StringPool.end(); + for (StringMap >::iterator + I = StringPool.begin(), + E = StringPool.end(); I != E; ++I) Entries.push_back(std::make_pair(I->second.second, &*I)); @@ -2536,8 +2605,9 @@ void DwarfUnits::emitStrings(const MCSection *StrSection, Asm->OutStreamer.EmitLabel(Entries[i].second->getValue().first); // Emit the string itself with a terminating null byte. - Asm->OutStreamer.EmitBytes(StringRef(Entries[i].second->getKeyData(), - Entries[i].second->getKeyLength()+1)); + Asm->OutStreamer.EmitBytes( + StringRef(Entries[i].second->getKeyData(), + Entries[i].second->getKeyLength() + 1)); } // If we've got an offset section go ahead and emit that now as well. @@ -2552,10 +2622,12 @@ void DwarfUnits::emitStrings(const MCSection *StrSection, } } -// Emit strings into a string section. + +// Emit addresses into the section given. void DwarfUnits::emitAddresses(const MCSection *AddrSection) { - if (AddressPool.empty()) return; + if (AddressPool.empty()) + return; // Start the dwarf addr section. Asm->OutStreamer.SwitchSection(AddrSection); @@ -2575,7 +2647,6 @@ void DwarfUnits::emitAddresses(const MCSection *AddrSection) { else Asm->OutStreamer.EmitIntValue(0, Asm->getDataLayout().getPointerSize()); } - } // Emit visible names into a debug str section. @@ -2590,24 +2661,27 @@ void DwarfDebug::emitDebugLoc() { return; for (SmallVectorImpl::iterator - I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end(); + I = DotDebugLocEntries.begin(), + E = DotDebugLocEntries.end(); I != E; ++I) { DotDebugLocEntry &Entry = *I; if (I + 1 != DotDebugLocEntries.end()) - Entry.Merge(I+1); + Entry.Merge(I + 1); } // Start the dwarf loc section. Asm->OutStreamer.SwitchSection( - Asm->getObjFileLowering().getDwarfLocSection()); + Asm->getObjFileLowering().getDwarfLocSection()); unsigned char Size = Asm->getDataLayout().getPointerSize(); Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", 0)); unsigned index = 1; for (SmallVectorImpl::iterator - I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end(); + I = DotDebugLocEntries.begin(), + E = DotDebugLocEntries.end(); I != E; ++I, ++index) { DotDebugLocEntry &Entry = *I; - if (Entry.isMerged()) continue; + if (Entry.isMerged()) + continue; if (Entry.isEmpty()) { Asm->OutStreamer.EmitIntValue(0, Size); Asm->OutStreamer.EmitIntValue(0, Size); @@ -2623,9 +2697,8 @@ void DwarfDebug::emitDebugLoc() { Asm->OutStreamer.EmitLabel(begin); if (Entry.isInt()) { DIBasicType BTy(DV.getType()); - if (BTy.Verify() && - (BTy.getEncoding() == dwarf::DW_ATE_signed - || BTy.getEncoding() == dwarf::DW_ATE_signed_char)) { + if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed || + BTy.getEncoding() == dwarf::DW_ATE_signed_char)) { Asm->OutStreamer.AddComment("DW_OP_consts"); Asm->EmitInt8(dwarf::DW_OP_consts); Asm->EmitSLEB128(Entry.getInt()); @@ -2688,7 +2761,7 @@ struct SymbolCUSorter { SymbolCUSorter(const MCStreamer &s) : Streamer(s) {} const MCStreamer &Streamer; - bool operator() (const SymbolCU &A, const SymbolCU &B) { + bool operator()(const SymbolCU &A, const SymbolCU &B) { unsigned IA = A.Sym ? Streamer.GetSymbolOrder(A.Sym) : 0; unsigned IB = B.Sym ? Streamer.GetSymbolOrder(B.Sym) : 0; @@ -2702,14 +2775,8 @@ struct SymbolCUSorter { } }; -static bool SectionSort(const MCSection *A, const MCSection *B) { - std::string LA = (A ? A->getLabelBeginName() : ""); - std::string LB = (B ? B->getLabelBeginName() : ""); - return LA < LB; -} - -static bool CUSort(const CompileUnit *A, const CompileUnit *B) { - return (A->getUniqueID() < B->getUniqueID()); +static bool CUSort(const Unit *A, const Unit *B) { + return (A->getUniqueID() < B->getUniqueID()); } struct ArangeSpan { @@ -2720,8 +2787,8 @@ struct ArangeSpan { // address we can tie back to a CU. void DwarfDebug::emitDebugARanges() { // Start the dwarf aranges section. - Asm->OutStreamer - .SwitchSection(Asm->getObjFileLowering().getDwarfARangesSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfARangesSection()); typedef DenseMap > SpansType; @@ -2740,7 +2807,7 @@ void DwarfDebug::emitDebugARanges() { std::sort(Sections.begin(), Sections.end(), SectionSort); // Build a set of address spans, sorted by CU. - for (size_t SecIdx=0;SecIdx &List = SectionMap[Section]; if (List.size() < 2) @@ -2795,16 +2862,16 @@ void DwarfDebug::emitDebugARanges() { std::sort(CUs.begin(), CUs.end(), CUSort); // Emit an arange table for each CU we used. - for (size_t CUIdx=0;CUIdx &List = Spans[CU]; // Emit size of content not including length itself. - unsigned ContentSize - = sizeof(int16_t) // DWARF ARange version number - + sizeof(int32_t) // Offset of CU in the .debug_info section - + sizeof(int8_t) // Pointer Size (in bytes) - + sizeof(int8_t); // Segment Size (in bytes) + unsigned ContentSize = + sizeof(int16_t) + // DWARF ARange version number + sizeof(int32_t) + // Offset of CU in the .debug_info section + sizeof(int8_t) + // Pointer Size (in bytes) + sizeof(int8_t); // Segment Size (in bytes) unsigned TupleSize = PtrSize * 2; @@ -2860,23 +2927,60 @@ void DwarfDebug::emitDebugARanges() { // Emit visible names into a debug ranges section. void DwarfDebug::emitDebugRanges() { // Start the dwarf ranges section. - Asm->OutStreamer - .SwitchSection(Asm->getObjFileLowering().getDwarfRangesSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfRangesSection()); + + // Size for our labels. unsigned char Size = Asm->getDataLayout().getPointerSize(); - for (SmallVectorImpl::iterator - I = DebugRangeSymbols.begin(), E = DebugRangeSymbols.end(); + + // Grab the specific ranges for the compile units in the module. + for (DenseMap::iterator I = CUMap.begin(), + E = CUMap.end(); I != E; ++I) { - if (*I) - Asm->OutStreamer.EmitSymbolValue(const_cast(*I), Size); - else + CompileUnit *TheCU = I->second; + unsigned ID = TheCU->getUniqueID(); + + // Emit a symbol so we can find the beginning of our ranges. + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("gnu_ranges", ID)); + + // Iterate over the misc ranges for the compile units in the module. + const SmallVectorImpl &RangeLists = TheCU->getRangeLists(); + for (SmallVectorImpl::const_iterator + I = RangeLists.begin(), + E = RangeLists.end(); + I != E; ++I) { + RangeSpanList *List = *I; + + // Emit a symbol so we can find the beginning of the range. + Asm->OutStreamer.EmitLabel( + Asm->GetTempSymbol("debug_ranges", List->getIndex())); + + for (SmallVectorImpl::const_iterator + I = List->getRanges().begin(), + E = List->getRanges().end(); + I != E; ++I) { + RangeSpan Range = *I; + // We occasionally have ranges without begin/end labels. + // FIXME: Verify and fix. + const MCSymbol *Begin = Range.getStart(); + const MCSymbol *End = Range.getEnd(); + Begin ? Asm->OutStreamer.EmitSymbolValue(Begin, Size) + : Asm->OutStreamer.EmitIntValue(0, Size); + End ? Asm->OutStreamer.EmitSymbolValue(End, Size) + : Asm->OutStreamer.EmitIntValue(0, Size); + } + + // And terminate the list with two 0 values. + Asm->OutStreamer.EmitIntValue(0, Size); Asm->OutStreamer.EmitIntValue(0, Size); + } } } // Emit visible names into a debug macinfo section. void DwarfDebug::emitDebugMacInfo() { if (const MCSection *LineInfo = - Asm->getObjFileLowering().getDwarfMacroInfoSection()) { + Asm->getObjFileLowering().getDwarfMacroInfoSection()) { // Start the dwarf macinfo section. Asm->OutStreamer.SwitchSection(LineInfo); } @@ -2886,8 +2990,7 @@ void DwarfDebug::emitDebugMacInfo() { // This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list, // DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id, -// DW_AT_ranges_base, DW_AT_addr_base. If DW_AT_ranges is present, -// DW_AT_low_pc and DW_AT_high_pc are not used, and vice versa. +// DW_AT_ranges_base, DW_AT_addr_base. CompileUnit *DwarfDebug::constructSkeletonCU(const CompileUnit *CU) { DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); @@ -2895,16 +2998,15 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const CompileUnit *CU) { Asm, this, &SkeletonHolder); NewCU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name, - DICompileUnit(CU->getNode()).getSplitDebugFilename()); + CU->getNode().getSplitDebugFilename()); // Relocate to the beginning of the addr_base section, else 0 for the // beginning of the one for this compile unit. if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - NewCU->addLabel(Die, dwarf::DW_AT_GNU_addr_base, dwarf::DW_FORM_sec_offset, - DwarfAddrSectionSym); + NewCU->addSectionLabel(Die, dwarf::DW_AT_GNU_addr_base, + DwarfAddrSectionSym); else - NewCU->addUInt(Die, dwarf::DW_AT_GNU_addr_base, - dwarf::DW_FORM_sec_offset, 0); + NewCU->addSectionOffset(Die, dwarf::DW_AT_GNU_addr_base, 0); // 2.17.1 requires that we use DW_AT_low_pc for a single entry point // into an entity. We're using 0, or a NULL label for this. @@ -2914,20 +3016,51 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const CompileUnit *CU) { // compile unit in debug_line section. // FIXME: Should handle multiple compile units. if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset, - DwarfLineSectionSym); + NewCU->addSectionLabel(Die, dwarf::DW_AT_stmt_list, + DwarfLineSectionSym); else - NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset, 0); + NewCU->addSectionOffset(Die, dwarf::DW_AT_stmt_list, 0); if (!CompilationDir.empty()) NewCU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir); - // Flag to let the linker know we have emitted new style pubnames. - if (GenerateGnuPubSections) - NewCU->addFlag(Die, dwarf::DW_AT_GNU_pubnames); + // Flags to let the linker know we have emitted new style pubnames. + if (GenerateGnuPubSections) { + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) + NewCU->addSectionLabel( + Die, dwarf::DW_AT_GNU_pubnames, + Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID())); + else + NewCU->addSectionDelta( + Die, dwarf::DW_AT_GNU_pubnames, + Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()), + DwarfGnuPubNamesSectionSym); + + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) + NewCU->addSectionLabel( + Die, dwarf::DW_AT_GNU_pubtypes, + Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID())); + else + NewCU->addSectionDelta( + Die, dwarf::DW_AT_GNU_pubtypes, + Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()), + DwarfGnuPubTypesSectionSym); + } + + // Attribute if we've emitted any ranges and their location for the compile unit. + if (CU->getRangeLists().size()) { + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) + NewCU->addSectionLabel( + Die, dwarf::DW_AT_GNU_ranges_base, + Asm->GetTempSymbol("gnu_ranges", NewCU->getUniqueID())); + else + NewCU->addSectionDelta( + Die, dwarf::DW_AT_GNU_ranges_base, + Asm->GetTempSymbol("gnu_ranges", NewCU->getUniqueID()), + DwarfDebugRangeSectionSym); + } SkeletonHolder.addUnit(NewCU); - SkeletonCUs.push_back(NewCU); return NewCU; } @@ -2959,9 +3092,63 @@ void DwarfDebug::emitDebugAbbrevDWO() { // sections. void DwarfDebug::emitDebugStrDWO() { assert(useSplitDwarf() && "No split dwarf?"); - const MCSection *OffSec = Asm->getObjFileLowering() - .getDwarfStrOffDWOSection(); + const MCSection *OffSec = + Asm->getObjFileLowering().getDwarfStrOffDWOSection(); const MCSymbol *StrSym = DwarfStrSectionSym; InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(), OffSec, StrSym); } + +void DwarfDebug::addTypeUnitType(uint16_t Language, DIE *RefDie, + DICompositeType CTy) { + DenseMap *> >::iterator I = + TypeUnits.find(CTy); + SmallVector References; + References.push_back(RefDie); + if (I != TypeUnits.end()) { + if (I->second.second) { + I->second.second->push_back(RefDie); + return; + } + } else { + DIE *UnitDie = new DIE(dwarf::DW_TAG_type_unit); + TypeUnit *NewTU = new TypeUnit(GlobalCUIndexCount++, UnitDie, Language, Asm, + this, &InfoHolder); + NewTU->addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2, + Language); + + // Register the type in the TypeUnits map with a vector of references to be + // populated whenever a reference is required. + I = TypeUnits.insert(std::make_pair(CTy, std::make_pair(0, &References))) + .first; + + // Construct the type, this may, recursively, require more type units that + // may in turn require this type again - in which case they will add DIEs to + // the References vector. + DIE *Die = NewTU->createTypeDIE(CTy); + + if (GenerateODRHash && shouldAddODRHash(NewTU, Die)) + NewTU->addUInt(UnitDie, dwarf::DW_AT_GNU_odr_signature, + dwarf::DW_FORM_data8, + DIEHash().computeDIEODRSignature(*Die)); + // FIXME: This won't handle circularly referential structures, as the DIE + // may have references to other DIEs still under construction and missing + // their signature. Hashing should walk through the signatures to their + // referenced type, or possibly walk the precomputed hashes of related types + // at the end. + uint64_t Signature = DIEHash().computeTypeSignature(*Die); + + // Remove the References vector and add the type hash. + I->second.first = Signature; + I->second.second = NULL; + + InfoHolder.addUnit(NewTU); + } + + // Populate all the signatures. + for (unsigned i = 0, e = References.size(); i != e; ++i) { + CUMap.begin()->second->addUInt(References[i], dwarf::DW_AT_signature, + dwarf::DW_FORM_ref_sig8, I->second.first); + } +}