X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FAsmPrinter%2FDwarfDebug.cpp;h=663ebef250bfab5a7269d070f80b5991e4894f05;hb=9e0dae166f9616e6b33b1bc7d8f493cb5b5e4f1b;hp=421cdbd95fa215dbe858ff7f4c1dc738cc753669;hpb=254d093f991287bea06e47c27ef2e14db36b1c59;p=oota-llvm.git diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 421cdbd95fa..663ebef250b 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -36,6 +36,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/LEB128.h" @@ -47,6 +48,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; #define DEBUG_TYPE "dwarfdebug" @@ -98,10 +100,6 @@ 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"; @@ -153,7 +151,7 @@ DIType DbgVariable::getType() const { if (tag == dwarf::DW_TAG_pointer_type) subType = resolve(DIDerivedType(Ty).getTypeDerivedFrom()); - DIArray Elements = DICompositeType(subType).getTypeArray(); + DIArray Elements = DICompositeType(subType).getElements(); for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDerivedType DT(Elements.getElement(i)); if (getName() == DT.getName()) @@ -209,9 +207,12 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) else HasDwarfPubSections = DwarfPubSections == Enable; + unsigned DwarfVersionNumber = Asm->TM.Options.MCOptions.DwarfVersion; DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber : MMI->getModule()->getDwarfVersion(); + Asm->OutStreamer.getContext().setDwarfVersion(DwarfVersion); + { NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); beginModule(); @@ -316,23 +317,9 @@ DIE &DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit &SPCU, DISubprogram SP) { DIE *SPDie = SPCU.getOrCreateSubprogramDIE(SP); - assert(SPDie && "Unable to find subprogram DIE!"); - - // 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. - if (DIE *AbsSPDIE = AbstractSPDies.lookup(SP)) { - assert(SPDie == AbsSPDIE); - // Pick up abstract subprogram DIE. - SPDie = &SPCU.createAndAddDIE( - dwarf::DW_TAG_subprogram, - *SPCU.getOrCreateContextDIE(resolve(SP.getContext()))); - SPCU.addDIEEntry(*SPDie, dwarf::DW_AT_abstract_origin, *AbsSPDIE); - } - attachLowHighPC(SPCU, *SPDie, FunctionBeginSym, FunctionEndSym); - const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + const TargetRegisterInfo *RI = Asm->TM.getSubtargetImpl()->getRegisterInfo(); MachineLocation Location(RI->getFrameRegister(*Asm->MF)); SPCU.addAddress(*SPDie, dwarf::DW_AT_frame_base, Location); @@ -359,9 +346,7 @@ bool DwarfDebug::isLexicalScopeDIENull(LexicalScope *Scope) { // We don't create a DIE if we have a single Range and the end label // is null. - SmallVectorImpl::const_iterator RI = Ranges.begin(); - MCSymbol *End = getLabelAfterInsn(RI->second); - return !End; + return !getLabelAfterInsn(Ranges.front().second); } static void addSectionLabel(AsmPrinter &Asm, DwarfUnit &U, DIE &D, @@ -435,7 +420,7 @@ DwarfDebug::constructInlinedScopeDIE(DwarfCompileUnit &TheCU, DISubprogram InlinedSP = getDISubprogram(DS); // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram // was inlined from another compile unit. - DIE *OriginDIE = SPMap[InlinedSP]->getDIE(InlinedSP); + DIE *OriginDIE = AbstractSPDies[InlinedSP]; assert(OriginDIE && "Unable to find original DIE for an inlined subprogram."); auto ScopeDIE = make_unique(dwarf::DW_TAG_inlined_subroutine); @@ -462,12 +447,7 @@ static std::unique_ptr constructVariableDIE(DwarfCompileUnit &TheCU, DbgVariable &DV, const LexicalScope &Scope, DIE *&ObjectPointer) { - AbstractOrInlined AOI = AOI_None; - if (Scope.isAbstractScope()) - AOI = AOI_Abstract; - else if (Scope.getInlinedAt()) - AOI = AOI_Inlined; - auto Var = TheCU.constructVariableDIE(DV, AOI); + auto Var = TheCU.constructVariableDIE(DV, Scope.isAbstractScope()); if (DV.isObjectPointer()) ObjectPointer = Var.get(); return Var; @@ -475,46 +455,35 @@ static std::unique_ptr constructVariableDIE(DwarfCompileUnit &TheCU, DIE *DwarfDebug::createScopeChildrenDIE( DwarfCompileUnit &TheCU, LexicalScope *Scope, - SmallVectorImpl> &Children) { + SmallVectorImpl> &Children, + unsigned *ChildScopeCount) { DIE *ObjectPointer = nullptr; - // Collect arguments for current function. - if (LScopes.isCurrentFunctionScope(Scope)) { - for (DbgVariable *ArgDV : CurrentFnArguments) - if (ArgDV) - Children.push_back( - constructVariableDIE(TheCU, *ArgDV, *Scope, ObjectPointer)); - - // If this is a variadic function, add an unspecified parameter. - DISubprogram SP(Scope->getScopeNode()); - DIArray FnArgs = SP.getType().getTypeArray(); - if (FnArgs.getElement(FnArgs.getNumElements() - 1) - .isUnspecifiedParameter()) { - Children.push_back( - make_unique(dwarf::DW_TAG_unspecified_parameters)); - } - } - - // Collect lexical scope children first. for (DbgVariable *DV : ScopeVariables.lookup(Scope)) Children.push_back(constructVariableDIE(TheCU, *DV, *Scope, ObjectPointer)); + unsigned ChildCountWithoutScopes = Children.size(); + for (LexicalScope *LS : Scope->getChildren()) - if (std::unique_ptr Nested = constructScopeDIE(TheCU, LS)) - Children.push_back(std::move(Nested)); + constructScopeDIE(TheCU, LS, Children); + + if (ChildScopeCount) + *ChildScopeCount = Children.size() - ChildCountWithoutScopes; + return ObjectPointer; } -void DwarfDebug::createAndAddScopeChildren(DwarfCompileUnit &TheCU, +DIE *DwarfDebug::createAndAddScopeChildren(DwarfCompileUnit &TheCU, LexicalScope *Scope, DIE &ScopeDIE) { // We create children when the scope DIE is not null. SmallVector, 8> Children; - if (DIE *ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children)) - TheCU.addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer); + DIE *ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children); // Add children for (auto &I : Children) ScopeDIE.addChild(std::move(I)); + + return ObjectPointer; } void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &TheCU, @@ -525,6 +494,8 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &TheCU, DISubprogram SP(Scope->getScopeNode()); + ProcessedSPNodes.insert(SP); + DIE *&AbsDef = AbstractSPDies[SP]; if (AbsDef) return; @@ -532,13 +503,27 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &TheCU, // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram // was inlined from another compile unit. DwarfCompileUnit &SPCU = *SPMap[SP]; - AbsDef = SPCU.getOrCreateSubprogramDIE(SP); + DIE *ContextDIE; + + // Some of this is duplicated from DwarfUnit::getOrCreateSubprogramDIE, with + // the important distinction that the DIDescriptor is not associated with the + // DIE (since the DIDescriptor will be associated with the concrete DIE, if + // any). It could be refactored to some common utility function. + if (DISubprogram SPDecl = SP.getFunctionDeclaration()) { + ContextDIE = &SPCU.getUnitDie(); + SPCU.getOrCreateSubprogramDIE(SPDecl); + } else + ContextDIE = SPCU.getOrCreateContextDIE(resolve(SP.getContext())); - if (!ProcessedSPNodes.insert(SP)) - return; + // Passing null as the associated DIDescriptor because the abstract definition + // shouldn't be found by lookup. + AbsDef = &SPCU.createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, + DIDescriptor()); + SPCU.applySubprogramAttributesToDefinition(SP, *AbsDef); SPCU.addUInt(*AbsDef, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined); - createAndAddScopeChildren(SPCU, Scope, *AbsDef); + if (DIE *ObjectPointer = createAndAddScopeChildren(SPCU, Scope, *AbsDef)) + SPCU.addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer); } DIE &DwarfDebug::constructSubprogramScopeDIE(DwarfCompileUnit &TheCU, @@ -554,16 +539,43 @@ DIE &DwarfDebug::constructSubprogramScopeDIE(DwarfCompileUnit &TheCU, DIE &ScopeDIE = updateSubprogramScopeDIE(TheCU, Sub); - createAndAddScopeChildren(TheCU, Scope, ScopeDIE); + // Collect arguments for current function. + assert(LScopes.isCurrentFunctionScope(Scope)); + DIE *ObjectPointer = nullptr; + for (DbgVariable *ArgDV : CurrentFnArguments) + if (ArgDV) + ScopeDIE.addChild( + constructVariableDIE(TheCU, *ArgDV, *Scope, ObjectPointer)); + + // If this is a variadic function, add an unspecified parameter. + DITypeArray FnArgs = Sub.getType().getTypeArray(); + // If we have a single element of null, it is a function that returns void. + // If we have more than one elements and the last one is null, it is a + // variadic function. + if (FnArgs.getNumElements() > 1 && + !FnArgs.getElement(FnArgs.getNumElements() - 1)) + ScopeDIE.addChild(make_unique(dwarf::DW_TAG_unspecified_parameters)); + + // Collect lexical scope children first. + // ObjectPointer might be a local (non-argument) local variable if it's a + // block's synthetic this pointer. + if (DIE *BlockObjPtr = createAndAddScopeChildren(TheCU, Scope, ScopeDIE)) { + assert(!ObjectPointer && "multiple object pointers can't be described"); + ObjectPointer = BlockObjPtr; + } + + if (ObjectPointer) + TheCU.addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer); return ScopeDIE; } // Construct a DIE for this scope. -std::unique_ptr DwarfDebug::constructScopeDIE(DwarfCompileUnit &TheCU, - LexicalScope *Scope) { +void DwarfDebug::constructScopeDIE( + DwarfCompileUnit &TheCU, LexicalScope *Scope, + SmallVectorImpl> &FinalChildren) { if (!Scope || !Scope->getScopeNode()) - return nullptr; + return; DIScope DS(Scope->getScopeNode()); @@ -581,17 +593,19 @@ std::unique_ptr DwarfDebug::constructScopeDIE(DwarfCompileUnit &TheCU, if (Scope->getParent() && DS.isSubprogram()) { ScopeDIE = constructInlinedScopeDIE(TheCU, Scope); if (!ScopeDIE) - return nullptr; + return; // We create children when the scope DIE is not null. createScopeChildrenDIE(TheCU, Scope, Children); } else { // Early exit when we know the scope DIE is going to be null. if (isLexicalScopeDIENull(Scope)) - return nullptr; + return; + + unsigned ChildScopeCount; // We create children here when we know the scope DIE is not going to be // null and the children will be added to the scope DIE. - createScopeChildrenDIE(TheCU, Scope, Children); + createScopeChildrenDIE(TheCU, Scope, Children, &ChildScopeCount); // There is no need to emit empty lexical block DIE. std::pair DwarfDebug::constructScopeDIE(DwarfCompileUnit &TheCU, ScopesWithImportedEntities.end(), std::pair(DS, nullptr), less_first()); - if (Children.empty() && Range.first == Range.second) - return nullptr; - ScopeDIE = constructLexicalScopeDIE(TheCU, Scope); - assert(ScopeDIE && "Scope DIE should not be null."); for (ImportedEntityMap::const_iterator i = Range.first; i != Range.second; ++i) - constructImportedEntityDIE(TheCU, i->second, *ScopeDIE); + Children.push_back( + constructImportedEntityDIE(TheCU, DIImportedEntity(i->second))); + // If there are only other scopes as children, put them directly in the + // parent instead, as this scope would serve no purpose. + if (Children.size() == ChildScopeCount) { + FinalChildren.insert(FinalChildren.end(), + std::make_move_iterator(Children.begin()), + std::make_move_iterator(Children.end())); + return; + } + ScopeDIE = constructLexicalScopeDIE(TheCU, Scope); + assert(ScopeDIE && "Scope DIE should not be null."); } // Add children for (auto &I : Children) ScopeDIE->addChild(std::move(I)); - return ScopeDIE; + FinalChildren.push_back(std::move(ScopeDIE)); } void DwarfDebug::addGnuPubAttributes(DwarfUnit &U, DIE &D) const { @@ -686,49 +707,21 @@ DwarfCompileUnit &DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { return NewCU; } -// Construct subprogram DIE. -void DwarfDebug::constructSubprogramDIE(DwarfCompileUnit &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. - - DwarfCompileUnit *&CURef = SPMap[N]; - if (CURef) - return; - CURef = &TheCU; - - DISubprogram SP(N); - assert(SP.isSubprogram()); - assert(SP.isDefinition()); - - DIE &SubprogramDie = *TheCU.getOrCreateSubprogramDIE(SP); - - // Expose as a global name. - TheCU.addGlobalName(SP.getName(), SubprogramDie, resolve(SP.getContext())); -} - -void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, - const MDNode *N) { +void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, + const MDNode *N) { DIImportedEntity Module(N); assert(Module.Verify()); if (DIE *D = TheCU.getOrCreateContextDIE(Module.getContext())) - constructImportedEntityDIE(TheCU, Module, *D); -} - -void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, - const MDNode *N, DIE &Context) { - DIImportedEntity Module(N); - assert(Module.Verify()); - return constructImportedEntityDIE(TheCU, Module, Context); + D->addChild(constructImportedEntityDIE(TheCU, Module)); } -void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, - const DIImportedEntity &Module, - DIE &Context) { +std::unique_ptr +DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, + const DIImportedEntity &Module) { assert(Module.Verify() && "Use one of the MDNode * overloads to handle invalid metadata"); - DIE &IMDie = TheCU.createAndAddDIE(Module.getTag(), Context, Module); + std::unique_ptr IMDie = make_unique((dwarf::Tag)Module.getTag()); + TheCU.insertDIE(Module, IMDie.get()); DIE *EntityDie; DIDescriptor Entity = resolve(Module.getEntity()); if (Entity.isNameSpace()) @@ -739,13 +732,16 @@ void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, EntityDie = TheCU.getOrCreateTypeDIE(DIType(Entity)); else EntityDie = TheCU.getDIE(Entity); - TheCU.addSourceLine(IMDie, Module.getLineNumber(), + assert(EntityDie); + TheCU.addSourceLine(*IMDie, Module.getLineNumber(), Module.getContext().getFilename(), Module.getContext().getDirectory()); - TheCU.addDIEEntry(IMDie, dwarf::DW_AT_import, *EntityDie); + TheCU.addDIEEntry(*IMDie, dwarf::DW_AT_import, *EntityDie); StringRef Name = Module.getName(); if (!Name.empty()) - TheCU.addString(IMDie, dwarf::DW_AT_name, Name); + TheCU.addString(*IMDie, dwarf::DW_AT_name, Name); + + return IMDie; } // Emit all Dwarf sections that should come prior to the content. Create @@ -757,6 +753,8 @@ void DwarfDebug::beginModule() { const Module *M = MMI->getModule(); + FunctionDIs = makeSubprogramMap(*M); + // If module has named metadata anchors then use them, otherwise scan the // module using debug info finder to collect debug info. NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); @@ -786,8 +784,13 @@ void DwarfDebug::beginModule() { for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) SPMap.insert(std::make_pair(SPs.getElement(i), &CU)); DIArray EnumTypes = CUNode.getEnumTypes(); - for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i) - CU.getOrCreateTypeDIE(EnumTypes.getElement(i)); + for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i) { + DIType Ty(EnumTypes.getElement(i)); + // The enum types array by design contains pointers to + // MDNodes rather than DIRefs. Unique them here. + DIType UniqueTy(resolve(Ty.getRef())); + CU.getOrCreateTypeDIE(UniqueTy); + } DIArray RetainedTypes = CUNode.getRetainedTypes(); for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i) { DIType Ty(RetainedTypes.getElement(i)); @@ -799,7 +802,7 @@ void DwarfDebug::beginModule() { // Emit imported_modules last so that the relevant context is already // available. for (unsigned i = 0, e = ImportedEntities.getNumElements(); i != e; ++i) - constructImportedEntityDIE(CU, ImportedEntities.getElement(i)); + constructAndAddImportedEntityDIE(CU, ImportedEntities.getElement(i)); } // Tell MMI that we have debug info. @@ -809,6 +812,24 @@ void DwarfDebug::beginModule() { SectionMap[Asm->getObjFileLowering().getTextSection()]; } +void DwarfDebug::finishVariableDefinitions() { + for (const auto &Var : ConcreteVariables) { + DIE *VariableDie = Var->getDIE(); + assert(VariableDie); + // FIXME: Consider the time-space tradeoff of just storing the unit pointer + // in the ConcreteVariables list, rather than looking it up again here. + // DIE::getUnit isn't simple - it walks parent pointers, etc. + DwarfCompileUnit *Unit = lookupUnit(VariableDie->getUnit()); + assert(Unit); + DbgVariable *AbsVar = getExistingAbstractVariable(Var->getVariable()); + if (AbsVar && AbsVar->getDIE()) { + Unit->addDIEEntry(*VariableDie, dwarf::DW_AT_abstract_origin, + *AbsVar->getDIE()); + } else + Unit->applyVariableAttributes(*Var, *VariableDie); + } +} + void DwarfDebug::finishSubprogramDefinitions() { const Module *M = MMI->getModule(); @@ -826,12 +847,18 @@ void DwarfDebug::finishSubprogramDefinitions() { if (SPMap[SP] != SPCU) continue; DIE *D = SPCU->getDIE(SP); - if (!D) - // Lazily construct the subprogram if we didn't see either concrete or - // inlined versions during codegen. - D = SPCU->getOrCreateSubprogramDIE(SP); - SPCU->applySubprogramAttributes(SP, *D); - SPCU->addGlobalName(SP.getName(), *D, resolve(SP.getContext())); + if (DIE *AbsSPDIE = AbstractSPDies.lookup(SP)) { + if (D) + // If this subprogram has an abstract definition, reference that + SPCU->addDIEEntry(*D, dwarf::DW_AT_abstract_origin, *AbsSPDIE); + } else { + if (!D) + // Lazily construct the subprogram if we didn't see either concrete or + // inlined versions during codegen. + D = SPCU->getOrCreateSubprogramDIE(SP); + // And attach the attributes + SPCU->applySubprogramAttributesToDefinition(SP, *D); + } } } } @@ -861,13 +888,17 @@ void DwarfDebug::collectDeadVariables() { if (Variables.getNumElements() == 0) continue; - DIE *SPDIE = SPCU->getDIE(SP); + DIE *SPDIE = AbstractSPDies.lookup(SP); + if (!SPDIE) + SPDIE = SPCU->getDIE(SP); assert(SPDIE); for (unsigned vi = 0, ve = Variables.getNumElements(); vi != ve; ++vi) { DIVariable DV(Variables.getElement(vi)); assert(DV.isVariable()); - DbgVariable NewVar(DV, nullptr, this); - SPDIE->addChild(SPCU->constructVariableDIE(NewVar)); + DbgVariable NewVar(DV, this); + auto VariableDie = SPCU->constructVariableDIE(NewVar); + SPCU->applyVariableAttributes(NewVar, *VariableDie); + SPDIE->addChild(std::move(VariableDie)); } } } @@ -877,6 +908,8 @@ void DwarfDebug::collectDeadVariables() { void DwarfDebug::finalizeModuleInfo() { finishSubprogramDefinitions(); + finishVariableDefinitions(); + // Collect info for variables that were optimized out. collectDeadVariables(); @@ -936,10 +969,7 @@ void DwarfDebug::finalizeModuleInfo() { 0); } else { RangeSpan &Range = TheU->getRanges().back(); - U.addLocalLabelAddress(U.getUnitDie(), dwarf::DW_AT_low_pc, - Range.getStart()); - U.addLabelDelta(U.getUnitDie(), dwarf::DW_AT_high_pc, Range.getEnd(), - Range.getStart()); + attachLowHighPC(U, U.getUnitDie(), Range.getStart(), Range.getEnd()); } } } @@ -1033,9 +1063,9 @@ void DwarfDebug::endModule() { emitDebugInfoDWO(); emitDebugAbbrevDWO(); emitDebugLineDWO(); + emitDebugLocDWO(); // Emit DWO addresses. AddrPool.emit(*Asm, Asm->getObjFileLowering().getDwarfAddrSection()); - emitDebugLocDWO(); } else // Emit info into a debug loc section. emitDebugLoc(); @@ -1063,27 +1093,51 @@ void DwarfDebug::endModule() { } // Find abstract variable, if any, associated with Var. -DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV, - DebugLoc ScopeLoc) { - return findAbstractVariable(DV, ScopeLoc.getScope(DV->getContext())); -} - -DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV, - const MDNode *ScopeNode) { +DbgVariable *DwarfDebug::getExistingAbstractVariable(const DIVariable &DV, + DIVariable &Cleansed) { LLVMContext &Ctx = DV->getContext(); // More then one inlined variable corresponds to one abstract variable. - DIVariable Var = cleanseInlinedVariable(DV, Ctx); - auto I = AbstractVariables.find(Var); + // FIXME: This duplication of variables when inlining should probably be + // removed. It's done to allow each DIVariable to describe its location + // because the DebugLoc on the dbg.value/declare isn't accurate. We should + // make it accurate then remove this duplication/cleansing stuff. + Cleansed = cleanseInlinedVariable(DV, Ctx); + auto I = AbstractVariables.find(Cleansed); if (I != AbstractVariables.end()) return I->second.get(); + return nullptr; +} - LexicalScope *Scope = LScopes.findAbstractScope(ScopeNode); - if (!Scope) - return nullptr; +DbgVariable *DwarfDebug::getExistingAbstractVariable(const DIVariable &DV) { + DIVariable Cleansed; + return getExistingAbstractVariable(DV, Cleansed); +} - auto AbsDbgVariable = make_unique(Var, nullptr, this); +void DwarfDebug::createAbstractVariable(const DIVariable &Var, + LexicalScope *Scope) { + auto AbsDbgVariable = make_unique(Var, this); addScopeVariable(Scope, AbsDbgVariable.get()); - return (AbstractVariables[Var] = std::move(AbsDbgVariable)).get(); + AbstractVariables[Var] = std::move(AbsDbgVariable); +} + +void DwarfDebug::ensureAbstractVariableIsCreated(const DIVariable &DV, + const MDNode *ScopeNode) { + DIVariable Cleansed = DV; + if (getExistingAbstractVariable(DV, Cleansed)) + return; + + createAbstractVariable(Cleansed, LScopes.getOrCreateAbstractScope(ScopeNode)); +} + +void +DwarfDebug::ensureAbstractVariableIsCreatedIfScoped(const DIVariable &DV, + const MDNode *ScopeNode) { + DIVariable Cleansed = DV; + if (getExistingAbstractVariable(DV, Cleansed)) + return; + + if (LexicalScope *Scope = LScopes.findAbstractScope(ScopeNode)) + createAbstractVariable(Cleansed, Scope); } // If Var is a current function argument then add it to CurrentFnArguments list. @@ -1104,13 +1158,14 @@ bool DwarfDebug::addCurrentFnArgument(DbgVariable *Var, LexicalScope *Scope) { // arguments does the function have at source level. if (ArgNo > Size) CurrentFnArguments.resize(ArgNo * 2); + assert(!CurrentFnArguments[ArgNo - 1]); CurrentFnArguments[ArgNo - 1] = Var; return true; } // Collect variable information from side table maintained by MMI. void DwarfDebug::collectVariableInfoFromMMITable( - SmallPtrSet &Processed) { + SmallPtrSetImpl &Processed) { for (const auto &VI : MMI->getVariableDbgInfo()) { if (!VI.Var) continue; @@ -1122,11 +1177,11 @@ void DwarfDebug::collectVariableInfoFromMMITable( if (!Scope) continue; - DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VI.Loc); - DbgVariable *RegVar = new DbgVariable(DV, AbsDbgVariable, this); + ensureAbstractVariableIsCreatedIfScoped(DV, Scope->getScopeNode()); + ConcreteVariables.push_back(make_unique(DV, this)); + DbgVariable *RegVar = ConcreteVariables.back().get(); RegVar->setFrameIndex(VI.Slot); - if (!addCurrentFnArgument(RegVar, Scope)) - addScopeVariable(Scope, RegVar); + addScopeVariable(Scope, RegVar); } } @@ -1155,9 +1210,121 @@ static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) { llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!"); } +/// Determine whether two variable pieces overlap. +static bool piecesOverlap(DIVariable P1, DIVariable P2) { + if (!P1.isVariablePiece() || !P2.isVariablePiece()) + return true; + unsigned l1 = P1.getPieceOffset(); + unsigned l2 = P2.getPieceOffset(); + unsigned r1 = l1 + P1.getPieceSize(); + unsigned r2 = l2 + P2.getPieceSize(); + // True where [l1,r1[ and [r1,r2[ overlap. + return (l1 < r2) && (l2 < r1); +} + +/// Build the location list for all DBG_VALUEs in the function that +/// describe the same variable. If the ranges of several independent +/// pieces of the same variable overlap partially, split them up and +/// combine the ranges. The resulting DebugLocEntries are will have +/// strict monotonically increasing begin addresses and will never +/// overlap. +// +// Input: +// +// Ranges History [var, loc, piece ofs size] +// 0 | [x, (reg0, piece 0, 32)] +// 1 | | [x, (reg1, piece 32, 32)] <- IsPieceOfPrevEntry +// 2 | | ... +// 3 | [clobber reg0] +// 4 [x, (mem, piece 0, 64)] <- overlapping with both previous pieces of x. +// +// Output: +// +// [0-1] [x, (reg0, piece 0, 32)] +// [1-3] [x, (reg0, piece 0, 32), (reg1, piece 32, 32)] +// [3-4] [x, (reg1, piece 32, 32)] +// [4- ] [x, (mem, piece 0, 64)] +void +DwarfDebug::buildLocationList(SmallVectorImpl &DebugLoc, + const DbgValueHistoryMap::InstrRanges &Ranges) { + SmallVector OpenRanges; + + for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { + const MachineInstr *Begin = I->first; + const MachineInstr *End = I->second; + assert(Begin->isDebugValue() && "Invalid History entry"); + + // Check if a variable is inaccessible in this range. + if (Begin->getNumOperands() > 1 && + Begin->getOperand(0).isReg() && !Begin->getOperand(0).getReg()) { + OpenRanges.clear(); + continue; + } + + // If this piece overlaps with any open ranges, truncate them. + DIVariable DIVar = Begin->getDebugVariable(); + auto Last = std::remove_if(OpenRanges.begin(), OpenRanges.end(), + [&](DebugLocEntry::Value R) { + return piecesOverlap(DIVar, R.getVariable()); + }); + OpenRanges.erase(Last, OpenRanges.end()); + + const MCSymbol *StartLabel = getLabelBeforeInsn(Begin); + assert(StartLabel && "Forgot label before DBG_VALUE starting a range!"); + + const MCSymbol *EndLabel; + if (End != nullptr) + EndLabel = getLabelAfterInsn(End); + else if (std::next(I) == Ranges.end()) + EndLabel = FunctionEndSym; + else + EndLabel = getLabelBeforeInsn(std::next(I)->first); + assert(EndLabel && "Forgot label after instruction ending a range!"); + + DEBUG(dbgs() << "DotDebugLoc: " << *Begin << "\n"); + + auto Value = getDebugLocValue(Begin); + DebugLocEntry Loc(StartLabel, EndLabel, Value); + bool couldMerge = false; + + // If this is a piece, it may belong to the current DebugLocEntry. + if (DIVar.isVariablePiece()) { + // Add this value to the list of open ranges. + OpenRanges.push_back(Value); + + // Attempt to add the piece to the last entry. + if (!DebugLoc.empty()) + if (DebugLoc.back().MergeValues(Loc)) + couldMerge = true; + } + + if (!couldMerge) { + // Need to add a new DebugLocEntry. Add all values from still + // valid non-overlapping pieces. + if (OpenRanges.size()) + Loc.addValues(OpenRanges); + + DebugLoc.push_back(std::move(Loc)); + } + + // Attempt to coalesce the ranges of two otherwise identical + // DebugLocEntries. + auto CurEntry = DebugLoc.rbegin(); + auto PrevEntry = std::next(CurEntry); + if (PrevEntry != DebugLoc.rend() && PrevEntry->MergeRanges(*CurEntry)) + DebugLoc.pop_back(); + + DEBUG(dbgs() << "Values:\n"; + for (auto Value : CurEntry->getValues()) + Value.getVariable()->dump(); + dbgs() << "-----\n"); + } +} + + // Find variables for each lexical scope. void -DwarfDebug::collectVariableInfo(SmallPtrSet &Processed) { +DwarfDebug::collectVariableInfo(SmallPtrSetImpl &Processed) { LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); @@ -1169,18 +1336,13 @@ DwarfDebug::collectVariableInfo(SmallPtrSet &Processed) { if (Processed.count(DV)) continue; - // History contains relevant DBG_VALUE instructions for DV and instructions - // clobbering it. - const SmallVectorImpl &History = I.second; - if (History.empty()) + // Instruction ranges, specifying where DV is accessible. + const auto &Ranges = I.second; + if (Ranges.empty()) continue; - const MachineInstr *MInsn = History.front(); LexicalScope *Scope = nullptr; - if (DV.getTag() == dwarf::DW_TAG_arg_variable && - DISubprogram(DV.getContext()).describes(CurFn->getFunction())) - Scope = LScopes.getCurrentFunctionScope(); - else if (MDNode *IA = DV.getInlinedAt()) { + if (MDNode *IA = DV.getInlinedAt()) { DebugLoc DL = DebugLoc::getFromDILocation(IA); Scope = LScopes.findInlinedScope(DebugLoc::get( DL.getLine(), DL.getCol(), DV.getContext(), IA)); @@ -1190,69 +1352,29 @@ DwarfDebug::collectVariableInfo(SmallPtrSet &Processed) { if (!Scope) continue; - Processed.insert(DV); + Processed.insert(getEntireVariable(DV)); + const MachineInstr *MInsn = Ranges.front().first; assert(MInsn->isDebugValue() && "History must begin with debug value"); - DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc()); - 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()))) { - RegVar->setMInsn(MInsn); + ensureAbstractVariableIsCreatedIfScoped(DV, Scope->getScopeNode()); + ConcreteVariables.push_back(make_unique(MInsn, this)); + DbgVariable *RegVar = ConcreteVariables.back().get(); + addScopeVariable(Scope, RegVar); + + // Check if the first DBG_VALUE is valid for the rest of the function. + if (Ranges.size() == 1 && Ranges.front().second == nullptr) continue; - } // Handle multiple DBG_VALUE instructions describing one variable. RegVar->setDotDebugLocOffset(DotDebugLocEntries.size()); DotDebugLocEntries.resize(DotDebugLocEntries.size() + 1); DebugLocList &LocList = DotDebugLocEntries.back(); + LocList.CU = TheCU; LocList.Label = Asm->GetTempSymbol("debug_loc", DotDebugLocEntries.size() - 1); - SmallVector &DebugLoc = LocList.List; - 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()) - continue; - // Compute the range for a register location. - const MCSymbol *FLabel = getLabelBeforeInsn(Begin); - const MCSymbol *SLabel = nullptr; - - if (HI + 1 == HE) - // If Begin is the last instruction in History then its value is valid - // until the end of the function. - SLabel = FunctionEndSym; - else { - const MachineInstr *End = HI[1]; - DEBUG(dbgs() << "DotDebugLoc Pair:\n" - << "\t" << *Begin << "\t" << *End << "\n"); - if (End->isDebugValue() && End->getDebugVariable() == DV) - SLabel = getLabelBeforeInsn(End); - else { - // End is clobbering the range. - SLabel = getLabelAfterInsn(End); - assert(SLabel && "Forgot label after clobber instruction"); - ++HI; - } - } - - // The value is valid until the next DBG_VALUE or clobber. - DebugLocEntry Loc(FLabel, SLabel, getDebugLocValue(Begin), TheCU); - if (DebugLoc.empty() || !DebugLoc.back().Merge(Loc)) - DebugLoc.push_back(std::move(Loc)); - } + // Build the location list for this variable. + buildLocationList(LocList.List, Ranges); } // Collect info for variables that were optimized out. @@ -1262,11 +1384,11 @@ DwarfDebug::collectVariableInfo(SmallPtrSet &Processed) { assert(DV.isVariable()); if (!Processed.insert(DV)) continue; - if (LexicalScope *Scope = LScopes.findLexicalScope(DV.getContext())) - addScopeVariable( - Scope, - new DbgVariable(DV, findAbstractVariable(DV, Scope->getScopeNode()), - this)); + if (LexicalScope *Scope = LScopes.findLexicalScope(DV.getContext())) { + ensureAbstractVariableIsCreatedIfScoped(DV, Scope->getScopeNode()); + ConcreteVariables.push_back(make_unique(DV, this)); + addScopeVariable(Scope, ConcreteVariables.back().get()); + } } } @@ -1380,6 +1502,17 @@ void DwarfDebug::identifyScopeMarkers() { } } +static DebugLoc findPrologueEndLoc(const MachineFunction *MF) { + // First known non-DBG_VALUE and non-frame setup location marks + // the beginning of the function body. + for (const auto &MBB : *MF) + for (const auto &MI : MBB) + if (!MI.isDebugValue() && !MI.getFlag(MachineInstr::FrameSetup) && + !MI.getDebugLoc().isUnknown()) + return MI.getDebugLoc(); + return DebugLoc(); +} + // Gather pre-function debug information. Assumes being called immediately // after the function entry point has been emitted. void DwarfDebug::beginFunction(const MachineFunction *MF) { @@ -1389,6 +1522,10 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { if (!MMI->hasDebugInfo()) return; + auto DI = FunctionDIs.find(MF->getFunction()); + if (DI == FunctionDIs.end()) + 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); @@ -1404,6 +1541,14 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // belongs to so that we add to the correct per-cu line table in the // non-asm case. LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); + // FnScope->getScopeNode() and DI->second should represent the same function, + // though they may not be the same MDNode due to inline functions merged in + // LTO where the debug info metadata still differs (either due to distinct + // written differences - two versions of a linkonce_odr function + // written/copied into two separate files, or some sub-optimal metadata that + // isn't structurally identical (see: file path/name info from clang, which + // includes the directory of the cpp file being built, even when the file name + // is absolute (such as an <> lookup header))) DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); assert(TheCU && "Unable to find compile unit!"); if (Asm->OutStreamer.hasRawTextSupport()) @@ -1417,48 +1562,42 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // Assumes in correct section after the entry point. Asm->OutStreamer.EmitLabel(FunctionBeginSym); - // Collect user variables, find the end of the prologue. - for (const auto &MBB : *MF) { - for (const auto &MI : MBB) { - if (MI.isDebugValue()) { - assert(MI.getNumOperands() > 1 && "Invalid machine instruction!"); - // Keep track of user variables in order of appearance. Create the - // empty history for each variable so that the order of keys in - // DbgValues is correct. Actual history will be populated in - // calculateDbgValueHistory() function. - const MDNode *Var = MI.getDebugVariable(); - DbgValues.insert( - std::make_pair(Var, SmallVector())); - } else if (!MI.getFlag(MachineInstr::FrameSetup) && - PrologEndLoc.isUnknown() && !MI.getDebugLoc().isUnknown()) { - // First known non-DBG_VALUE and non-frame setup location marks - // the beginning of the function body. - PrologEndLoc = MI.getDebugLoc(); - } - } - } - // Calculate history for local variables. - calculateDbgValueHistory(MF, Asm->TM.getRegisterInfo(), DbgValues); + calculateDbgValueHistory(MF, Asm->TM.getSubtargetImpl()->getRegisterInfo(), + DbgValues); // Request labels for the full history. - for (auto &I : DbgValues) { - const SmallVectorImpl &History = I.second; - if (History.empty()) + for (const auto &I : DbgValues) { + const auto &Ranges = I.second; + if (Ranges.empty()) continue; // The first mention of a function argument gets the FunctionBeginSym // label, so arguments are visible when breaking at function entry. - DIVariable DV(I.first); + DIVariable DV(Ranges.front().first->getDebugVariable()); if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable && - getDISubprogram(DV.getContext()).describes(MF->getFunction())) - LabelsBeforeInsn[History.front()] = FunctionBeginSym; - - for (const MachineInstr *MI : History) { - if (MI->isDebugValue() && MI->getDebugVariable() == DV) - requestLabelBeforeInsn(MI); - else - requestLabelAfterInsn(MI); + getDISubprogram(DV.getContext()).describes(MF->getFunction())) { + if (!DV.isVariablePiece()) + LabelsBeforeInsn[Ranges.front().first] = FunctionBeginSym; + else { + // Mark all non-overlapping initial pieces. + for (auto I = Ranges.begin(); I != Ranges.end(); ++I) { + DIVariable Piece = I->first->getDebugVariable(); + if (std::all_of(Ranges.begin(), I, + [&](DbgValueHistoryMap::InstrRange Pred){ + return !piecesOverlap(Piece, Pred.first->getDebugVariable()); + })) + LabelsBeforeInsn[I->first] = FunctionBeginSym; + else + break; + } + } + } + + for (const auto &Range : Ranges) { + requestLabelBeforeInsn(Range.first); + if (Range.second) + requestLabelAfterInsn(Range.second); } } @@ -1466,6 +1605,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { PrevLabel = FunctionBeginSym; // Record beginning of function. + PrologEndLoc = findPrologueEndLoc(MF); if (!PrologEndLoc.isUnknown()) { DebugLoc FnStartDL = PrologEndLoc.getFnDebugLoc(MF->getFunction()->getContext()); @@ -1479,6 +1619,8 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { } void DwarfDebug::addScopeVariable(LexicalScope *LS, DbgVariable *Var) { + if (addCurrentFnArgument(Var, LS)) + return; SmallVectorImpl &Vars = ScopeVariables[LS]; DIVariable DV = Var->getVariable(); // Variables with positive arg numbers are parameters. @@ -1520,11 +1662,11 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { assert(CurFn == MF); assert(CurFn != nullptr); - if (!MMI->hasDebugInfo() || LScopes.empty()) { + if (!MMI->hasDebugInfo() || LScopes.empty() || + !FunctionDIs.count(MF->getFunction())) { // If we don't have a lexical scope for this function then there will // be a hole in the range information. Keep note of this by setting the // previously used section to nullptr. - PrevSection = nullptr; PrevCU = nullptr; CurFn = nullptr; return; @@ -1547,8 +1689,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { // Construct abstract scopes. for (LexicalScope *AScope : LScopes.getAbstractScopesList()) { DISubprogram SP(AScope->getScopeNode()); - if (!SP.isSubprogram()) - continue; + assert(SP.isSubprogram()); // Collect info for variables that were optimized out. DIArray Variables = SP.getVariables(); for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) { @@ -1556,7 +1697,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { assert(DV && DV.isVariable()); if (!ProcessedVars.insert(DV)) continue; - findAbstractVariable(DV, DV.getContext()); + ensureAbstractVariableIsCreated(DV, DV.getContext()); } constructAbstractSubprogramScopeDIE(TheCU, AScope); } @@ -1568,19 +1709,14 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { // Add the range of this function to the list of ranges for the CU. RangeSpan Span(FunctionBeginSym, FunctionEndSym); TheCU.addRange(std::move(Span)); - PrevSection = Asm->getCurrentSection(); PrevCU = &TheCU; // Clear debug info // Ownership of DbgVariables is a bit subtle - ScopeVariables owns all the // DbgVariables except those that are also in AbstractVariables (since they // can be used cross-function) - for (const auto &I : ScopeVariables) - for (const auto *Var : I.second) - if (!AbstractVariables.count(Var->getVariable()) || Var->getAbstractVariable()) - delete Var; ScopeVariables.clear(); - DeleteContainerPointers(CurrentFnArguments); + CurrentFnArguments.clear(); DbgValues.clear(); LabelsBeforeInsn.clear(); LabelsAfterInsn.clear(); @@ -1600,8 +1736,8 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, assert(Scope.isScope()); Fn = Scope.getFilename(); Dir = Scope.getDirectory(); - if (Scope.isLexicalBlock()) - Discriminator = DILexicalBlock(S).getDiscriminator(); + if (Scope.isLexicalBlockFile()) + Discriminator = DILexicalBlockFile(S).getDiscriminator(); unsigned CUID = Asm->OutStreamer.getContext().getDwarfCompileUnitID(); Src = static_cast(*InfoHolder.getUnits()[CUID]) @@ -1622,9 +1758,12 @@ void DwarfDebug::emitSectionLabels() { // Dwarf sections base addresses. DwarfInfoSectionSym = emitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info"); - if (useSplitDwarf()) + if (useSplitDwarf()) { DwarfInfoDWOSectionSym = emitSectionSym(Asm, TLOF.getDwarfInfoDWOSection(), "section_info_dwo"); + DwarfTypesDWOSectionSym = + emitSectionSym(Asm, TLOF.getDwarfTypesDWOSection(), "section_types_dwo"); + } DwarfAbbrevSectionSym = emitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev"); if (useSplitDwarf()) @@ -1934,12 +2073,66 @@ void DwarfDebug::emitDebugStr() { Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection()); } +/// Emits an optimal (=sorted) sequence of DW_OP_pieces. +void DwarfDebug::emitLocPieces(ByteStreamer &Streamer, + const DITypeIdentifierMap &Map, + ArrayRef Values) { + assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value P) { + return P.isVariablePiece(); + }) && "all values are expected to be pieces"); + assert(std::is_sorted(Values.begin(), Values.end()) && + "pieces are expected to be sorted"); + + unsigned Offset = 0; + for (auto Piece : Values) { + DIVariable Var = Piece.getVariable(); + unsigned PieceOffset = Var.getPieceOffset(); + unsigned PieceSize = Var.getPieceSize(); + assert(Offset <= PieceOffset && "overlapping or duplicate pieces"); + if (Offset < PieceOffset) { + // The DWARF spec seriously mandates pieces with no locations for gaps. + Asm->EmitDwarfOpPiece(Streamer, (PieceOffset-Offset)*8); + Offset += PieceOffset-Offset; + } + + Offset += PieceSize; + + const unsigned SizeOfByte = 8; + assert(!Var.isIndirect() && "indirect address for piece"); +#ifndef NDEBUG + unsigned VarSize = Var.getSizeInBits(Map); + assert(PieceSize+PieceOffset <= VarSize/SizeOfByte + && "piece is larger than or outside of variable"); + assert(PieceSize*SizeOfByte != VarSize + && "piece covers entire variable"); +#endif + if (Piece.isLocation() && Piece.getLoc().isReg()) + Asm->EmitDwarfRegOpPiece(Streamer, + Piece.getLoc(), + PieceSize*SizeOfByte); + else { + emitDebugLocValue(Streamer, Piece); + Asm->EmitDwarfOpPiece(Streamer, PieceSize*SizeOfByte); + } + } +} + + void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, const DebugLocEntry &Entry) { - assert(Entry.getValues().size() == 1 && - "multi-value entries are not supported yet."); const DebugLocEntry::Value Value = Entry.getValues()[0]; - DIVariable DV(Value.getVariable()); + if (Value.isVariablePiece()) + // Emit all pieces that belong to the same variable and range. + return emitLocPieces(Streamer, TypeIdentifierMap, Entry.getValues()); + + assert(Entry.getValues().size() == 1 && "only pieces may have >1 value"); + emitDebugLocValue(Streamer, Value); +} + +void DwarfDebug::emitDebugLocValue(ByteStreamer &Streamer, + const DebugLocEntry::Value &Value) { + DIVariable DV = Value.getVariable(); + // Regular entry. if (Value.isInt()) { DIBasicType BTy(resolve(DV.getType())); if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed || @@ -1986,6 +2179,9 @@ void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, } else if (Element == DIBuilder::OpDeref) { if (!Loc.isReg()) Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref"); + } else if (Element == DIBuilder::OpPiece) { + i += 3; + // handled in emitDebugLocEntry. } else llvm_unreachable("unknown Opcode found in complex address"); } @@ -2017,11 +2213,12 @@ void DwarfDebug::emitDebugLoc() { unsigned char Size = Asm->getDataLayout().getPointerSize(); for (const auto &DebugLoc : DotDebugLocEntries) { Asm->OutStreamer.EmitLabel(DebugLoc.Label); + const DwarfCompileUnit *CU = DebugLoc.CU; + assert(!CU->getRanges().empty()); for (const auto &Entry : DebugLoc.List) { // Set up the range. This range is relative to the entry point of the // compile unit. This is a hard coded 0 for low_pc when we're emitting // ranges, or the DW_AT_low_pc on the compile unit otherwise. - const DwarfCompileUnit *CU = Entry.getCU(); if (CU->getRanges().size() == 1) { // Grab the begin symbol from the first range as our base. const MCSymbol *Base = CU->getRanges()[0].getStart(); @@ -2298,24 +2495,6 @@ DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) { return NewCU; } -// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_dwo_name, -// DW_AT_addr_base. -DwarfTypeUnit &DwarfDebug::constructSkeletonTU(DwarfTypeUnit &TU) { - DwarfCompileUnit &CU = static_cast( - *SkeletonHolder.getUnits()[TU.getCU().getUniqueID()]); - - auto OwnedUnit = make_unique(TU.getUniqueID(), CU, Asm, this, - &SkeletonHolder); - DwarfTypeUnit &NewTU = *OwnedUnit; - NewTU.setTypeSignature(TU.getTypeSignature()); - NewTU.setType(nullptr); - NewTU.initSection( - Asm->getObjFileLowering().getDwarfTypesSection(TU.getTypeSignature())); - - initSkeletonUnit(TU, NewTU.getUnitDie(), std::move(OwnedUnit)); - return NewTU; -} - // Emit the .debug_info.dwo section for separated dwarf. This contains the // compile units that would normally be in debug_info. void DwarfDebug::emitDebugInfoDWO() { @@ -2388,9 +2567,9 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, bool TopLevelType = TypeUnitsUnderConstruction.empty(); AddrPool.resetUsedFlag(); - auto OwnedUnit = - make_unique(InfoHolder.getUnits().size(), CU, Asm, this, - &InfoHolder, getDwoLineTable(CU)); + auto OwnedUnit = make_unique( + InfoHolder.getUnits().size() + TypeUnitsUnderConstruction.size(), CU, Asm, + this, &InfoHolder, getDwoLineTable(CU)); DwarfTypeUnit &NewTU = *OwnedUnit; DIE &UnitDie = NewTU.getUnitDie(); TU = &NewTU; @@ -2403,15 +2582,14 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, uint64_t Signature = makeTypeSignature(Identifier); NewTU.setTypeSignature(Signature); - if (!useSplitDwarf()) + if (useSplitDwarf()) + NewTU.initSection(Asm->getObjFileLowering().getDwarfTypesDWOSection(), + DwarfTypesDWOSectionSym); + else { CU.applyStmtList(UnitDie); - - // FIXME: Skip using COMDAT groups for type units in the .dwo file once tools - // such as DWP ( http://gcc.gnu.org/wiki/DebugFissionDWP ) can cope with it. - NewTU.initSection( - useSplitDwarf() - ? Asm->getObjFileLowering().getDwarfTypesDWOSection(Signature) - : Asm->getObjFileLowering().getDwarfTypesSection(Signature)); + NewTU.initSection( + Asm->getObjFileLowering().getDwarfTypesSection(Signature)); + } NewTU.setType(NewTU.createTypeDIE(CTy)); @@ -2439,17 +2617,14 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, // If the type wasn't dependent on fission addresses, finish adding the type // and all its dependent types. - for (auto &TU : TypeUnitsToAdd) { - if (useSplitDwarf()) - TU.first->setSkeleton(constructSkeletonTU(*TU.first)); + for (auto &TU : TypeUnitsToAdd) InfoHolder.addUnit(std::move(TU.first)); - } } CU.addDIETypeSignature(RefDie, NewTU); } void DwarfDebug::attachLowHighPC(DwarfCompileUnit &Unit, DIE &D, - MCSymbol *Begin, MCSymbol *End) { + const MCSymbol *Begin, const MCSymbol *End) { assert(Begin && "Begin label should not be null!"); assert(End && "End label should not be null!"); assert(Begin->isDefined() && "Invalid starting label");