X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FCodeGen%2FAsmPrinter%2FDwarfDebug.cpp;h=29685abab48a3d3db980963a6a0db16a84240715;hp=defae5d920b7faf0ce6958173a8bf55f52a3b30a;hb=48ba51a8cddd823f1c6823218b982b87b0018c0d;hpb=363d0d273896d5e0ae595547b99fefadc5790819 diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index defae5d920b..29685abab48 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -11,8 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "ByteStreamer.h" #include "DwarfDebug.h" + +#include "ByteStreamer.h" +#include "DwarfCompileUnit.h" #include "DIE.h" #include "DIEHash.h" #include "DwarfUnit.h" @@ -168,9 +170,11 @@ static LLVM_CONSTEXPR DwarfAccelTable::Atom TypeAtoms[] = { DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) : Asm(A), MMI(Asm->MMI), FirstCU(nullptr), PrevLabel(nullptr), - GlobalRangeCount(0), InfoHolder(A, "info_string", DIEValueAllocator), + GlobalRangeCount(0), + InfoHolder(A, *this, "info_string", DIEValueAllocator), UsedNonDefaultText(false), - SkeletonHolder(A, "skel_string", DIEValueAllocator), + SkeletonHolder(A, *this, "skel_string", DIEValueAllocator), + IsDarwin(Triple(A->getTargetTriple()).isOSDarwin()), AccelNames(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)), AccelObjC(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, @@ -190,8 +194,6 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) // 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) HasDwarfAccelTables = IsDarwin; else @@ -310,26 +312,6 @@ bool DwarfDebug::isSubprogramContext(const MDNode *Context) { return false; } -// 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(DwarfCompileUnit &SPCU, - DISubprogram SP) { - DIE *SPDie = SPCU.getOrCreateSubprogramDIE(SP); - - attachLowHighPC(SPCU, *SPDie, FunctionBeginSym, FunctionEndSym); - - const TargetRegisterInfo *RI = Asm->TM.getSubtargetImpl()->getRegisterInfo(); - MachineLocation Location(RI->getFrameRegister(*Asm->MF)); - SPCU.addAddress(*SPDie, dwarf::DW_AT_frame_base, Location); - - // Add name to the name table, we do this here because we're guaranteed - // to have concrete versions of our DW_TAG_subprogram nodes. - addSubprogramNames(SP, *SPDie); - - return *SPDie; -} - /// Check whether we should create a DIE for the given Scope, return true /// if we don't create a DIE (the corresponding DIE is null). bool DwarfDebug::isLexicalScopeDIENull(LexicalScope *Scope) { @@ -349,277 +331,22 @@ bool DwarfDebug::isLexicalScopeDIENull(LexicalScope *Scope) { return !getLabelAfterInsn(Ranges.front().second); } -static void addSectionLabel(AsmPrinter &Asm, DwarfUnit &U, DIE &D, - dwarf::Attribute A, const MCSymbol *L, - const MCSymbol *Sec) { - if (Asm.MAI->doesDwarfUseRelocationsAcrossSections()) - U.addSectionLabel(D, A, L); - else - U.addSectionDelta(D, A, L, Sec); -} - -void DwarfDebug::addScopeRangeList(DwarfCompileUnit &TheCU, DIE &ScopeDIE, - const SmallVectorImpl &Range) { - // Emit offset in .debug_range as a relocatable label. emitDIE will handle - // emitting it appropriately. - MCSymbol *RangeSym = Asm->GetTempSymbol("debug_ranges", GlobalRangeCount++); - - // Under fission, ranges are specified by constant offsets relative to the - // CU's DW_AT_GNU_ranges_base. - if (useSplitDwarf()) - TheCU.addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, RangeSym, - DwarfDebugRangeSectionSym); - else - addSectionLabel(*Asm, TheCU, ScopeDIE, dwarf::DW_AT_ranges, RangeSym, - DwarfDebugRangeSectionSym); - - RangeSpanList List(RangeSym); - for (const InsnRange &R : Range) { - RangeSpan Span(getLabelBeforeInsn(R.first), getLabelAfterInsn(R.second)); - List.addRange(std::move(Span)); - } - - // Add the range list to the set of ranges to be emitted. - TheCU.addRangeList(std::move(List)); -} - -void DwarfDebug::attachRangesOrLowHighPC(DwarfCompileUnit &TheCU, DIE &Die, - const SmallVectorImpl &Ranges) { - assert(!Ranges.empty()); - if (Ranges.size() == 1) - attachLowHighPC(TheCU, Die, getLabelBeforeInsn(Ranges.front().first), - getLabelAfterInsn(Ranges.front().second)); - else - addScopeRangeList(TheCU, Die, Ranges); -} - -// Construct new DW_TAG_lexical_block for this scope and attach -// DW_AT_low_pc/DW_AT_high_pc labels. -std::unique_ptr -DwarfDebug::constructLexicalScopeDIE(DwarfCompileUnit &TheCU, - LexicalScope *Scope) { - if (isLexicalScopeDIENull(Scope)) - return nullptr; - - auto ScopeDIE = make_unique(dwarf::DW_TAG_lexical_block); - if (Scope->isAbstractScope()) - return ScopeDIE; - - attachRangesOrLowHighPC(TheCU, *ScopeDIE, Scope->getRanges()); - - return ScopeDIE; -} - -// This scope represents inlined body of a function. Construct DIE to -// represent this concrete inlined copy of the function. -std::unique_ptr -DwarfDebug::constructInlinedScopeDIE(DwarfCompileUnit &TheCU, - LexicalScope *Scope) { - assert(Scope->getScopeNode()); - DIScope DS(Scope->getScopeNode()); - DISubprogram InlinedSP = getDISubprogram(DS); - // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram - // was inlined from another compile unit. - DIE *OriginDIE = AbstractSPDies[InlinedSP]; - assert(OriginDIE && "Unable to find original DIE for an inlined subprogram."); - - auto ScopeDIE = make_unique(dwarf::DW_TAG_inlined_subroutine); - TheCU.addDIEEntry(*ScopeDIE, dwarf::DW_AT_abstract_origin, *OriginDIE); - - attachRangesOrLowHighPC(TheCU, *ScopeDIE, Scope->getRanges()); - - InlinedSubprogramDIEs.insert(OriginDIE); - - // Add the call site information to the DIE. - DILocation DL(Scope->getInlinedAt()); - TheCU.addUInt(*ScopeDIE, dwarf::DW_AT_call_file, None, - TheCU.getOrCreateSourceID(DL.getFilename(), DL.getDirectory())); - 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. - addSubprogramNames(InlinedSP, *ScopeDIE); - - return ScopeDIE; -} - -static std::unique_ptr constructVariableDIE(DwarfCompileUnit &TheCU, - DbgVariable &DV, - const LexicalScope &Scope, - DIE *&ObjectPointer) { - auto Var = TheCU.constructVariableDIE(DV, Scope.isAbstractScope()); - if (DV.isObjectPointer()) - ObjectPointer = Var.get(); - return Var; -} - -DIE *DwarfDebug::createScopeChildrenDIE( - DwarfCompileUnit &TheCU, LexicalScope *Scope, - SmallVectorImpl> &Children) { - DIE *ObjectPointer = nullptr; - - for (DbgVariable *DV : ScopeVariables.lookup(Scope)) - Children.push_back(constructVariableDIE(TheCU, *DV, *Scope, ObjectPointer)); - - for (LexicalScope *LS : Scope->getChildren()) - if (std::unique_ptr Nested = constructScopeDIE(TheCU, LS)) - Children.push_back(std::move(Nested)); - return ObjectPointer; -} - -DIE *DwarfDebug::createAndAddScopeChildren(DwarfCompileUnit &TheCU, - LexicalScope *Scope, DIE &ScopeDIE) { - // We create children when the scope DIE is not null. - SmallVector, 8> Children; - DIE *ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children); - - // Add children - for (auto &I : Children) - ScopeDIE.addChild(std::move(I)); - - return ObjectPointer; -} - -void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &TheCU, - LexicalScope *Scope) { +void DwarfDebug::constructAbstractSubprogramScopeDIE(LexicalScope *Scope) { assert(Scope && Scope->getScopeNode()); assert(Scope->isAbstractScope()); assert(!Scope->getInlinedAt()); - DISubprogram SP(Scope->getScopeNode()); - - ProcessedSPNodes.insert(SP); + const MDNode *SP = Scope->getScopeNode(); DIE *&AbsDef = AbstractSPDies[SP]; if (AbsDef) return; + ProcessedSPNodes.insert(SP); + // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram // was inlined from another compile unit. - DwarfCompileUnit &SPCU = *SPMap[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())); - - // 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); - if (DIE *ObjectPointer = createAndAddScopeChildren(SPCU, Scope, *AbsDef)) - SPCU.addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer); -} - -DIE &DwarfDebug::constructSubprogramScopeDIE(DwarfCompileUnit &TheCU, - LexicalScope *Scope) { - assert(Scope && Scope->getScopeNode()); - assert(!Scope->getInlinedAt()); - assert(!Scope->isAbstractScope()); - DISubprogram Sub(Scope->getScopeNode()); - - assert(Sub.isSubprogram()); - - ProcessedSPNodes.insert(Sub); - - DIE &ScopeDIE = updateSubprogramScopeDIE(TheCU, Sub); - - // 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) { - if (!Scope || !Scope->getScopeNode()) - return nullptr; - - DIScope DS(Scope->getScopeNode()); - - assert((Scope->getInlinedAt() || !DS.isSubprogram()) && - "Only handle inlined subprograms here, use " - "constructSubprogramScopeDIE for non-inlined " - "subprograms"); - - SmallVector, 8> Children; - - // We try to create the scope DIE first, then the children DIEs. This will - // avoid creating un-used children then removing them later when we find out - // the scope DIE is null. - std::unique_ptr ScopeDIE; - if (Scope->getParent() && DS.isSubprogram()) { - ScopeDIE = constructInlinedScopeDIE(TheCU, Scope); - if (!ScopeDIE) - return nullptr; - // 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; - - // 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); - - // There is no need to emit empty lexical block DIE. - std::pair Range = - std::equal_range(ScopesWithImportedEntities.begin(), - ScopesWithImportedEntities.end(), - std::pair(DS, nullptr), - less_first()); - for (ImportedEntityMap::const_iterator i = Range.first; i != Range.second; - ++i) - Children.push_back( - constructImportedEntityDIE(TheCU, DIImportedEntity(i->second))); - if (Children.empty()) - return nullptr; - 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; + AbsDef = &SPMap[SP]->constructAbstractSubprogramScopeDIE(Scope); } void DwarfDebug::addGnuPubAttributes(DwarfUnit &U, DIE &D) const { @@ -697,36 +424,7 @@ void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, DIImportedEntity Module(N); assert(Module.Verify()); if (DIE *D = TheCU.getOrCreateContextDIE(Module.getContext())) - D->addChild(constructImportedEntityDIE(TheCU, Module)); -} - -std::unique_ptr -DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, - const DIImportedEntity &Module) { - assert(Module.Verify() && - "Use one of the MDNode * overloads to handle invalid metadata"); - 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()) - EntityDie = TheCU.getOrCreateNameSpace(DINameSpace(Entity)); - else if (Entity.isSubprogram()) - EntityDie = TheCU.getOrCreateSubprogramDIE(DISubprogram(Entity)); - else if (Entity.isType()) - EntityDie = TheCU.getOrCreateTypeDIE(DIType(Entity)); - else - EntityDie = TheCU.getDIE(Entity); - assert(EntityDie); - TheCU.addSourceLine(*IMDie, Module.getLineNumber(), - Module.getContext().getFilename(), - Module.getContext().getDirectory()); - TheCU.addDIEEntry(*IMDie, dwarf::DW_AT_import, *EntityDie); - StringRef Name = Module.getName(); - if (!Name.empty()) - TheCU.addString(*IMDie, dwarf::DW_AT_name, Name); - - return IMDie; + D->addChild(TheCU.constructImportedEntityDIE(Module)); } // Emit all Dwarf sections that should come prior to the content. Create @@ -764,7 +462,7 @@ void DwarfDebug::beginModule() { ScopesWithImportedEntities.end(), less_first()); DIArray GVs = CUNode.getGlobalVariables(); for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) - CU.createGlobalVariableDIE(DIGlobalVariable(GVs.getElement(i))); + CU.getOrCreateGlobalVariableDIE(DIGlobalVariable(GVs.getElement(i))); DIArray SPs = CUNode.getSubprograms(); for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) SPMap.insert(std::make_pair(SPs.getElement(i), &CU)); @@ -816,36 +514,8 @@ void DwarfDebug::finishVariableDefinitions() { } void DwarfDebug::finishSubprogramDefinitions() { - const Module *M = MMI->getModule(); - - NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); - for (MDNode *N : CU_Nodes->operands()) { - DICompileUnit TheCU(N); - // Construct subprogram DIE and add variables DIEs. - DwarfCompileUnit *SPCU = - static_cast(CUMap.lookup(TheCU)); - DIArray Subprograms = TheCU.getSubprograms(); - for (unsigned i = 0, e = Subprograms.getNumElements(); i != e; ++i) { - DISubprogram SP(Subprograms.getElement(i)); - // Perhaps the subprogram is in another CU (such as due to comdat - // folding, etc), in which case ignore it here. - if (SPMap[SP] != SPCU) - continue; - DIE *D = SPCU->getDIE(SP); - 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); - } - } - } + for (const auto &P : SPMap) + P.second->finishSubprogramDefinition(DISubprogram(P.first)); } @@ -880,7 +550,7 @@ void DwarfDebug::collectDeadVariables() { for (unsigned vi = 0, ve = Variables.getNumElements(); vi != ve; ++vi) { DIVariable DV(Variables.getElement(vi)); assert(DV.isVariable()); - DbgVariable NewVar(DV, this); + DbgVariable NewVar(DV, DIExpression(nullptr), this); auto VariableDie = SPCU->constructVariableDIE(NewVar); SPCU->applyVariableAttributes(NewVar, *VariableDie); SPDIE->addChild(std::move(VariableDie)); @@ -922,13 +592,12 @@ void DwarfDebug::finalizeModuleInfo() { // We don't keep track of which addresses are used in which CU so this // is a bit pessimistic under LTO. if (!AddrPool.isEmpty()) - addSectionLabel(*Asm, *SkCU, SkCU->getUnitDie(), - dwarf::DW_AT_GNU_addr_base, DwarfAddrSectionSym, - DwarfAddrSectionSym); + SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_addr_base, + DwarfAddrSectionSym, DwarfAddrSectionSym); if (!TheU->getRangeLists().empty()) - addSectionLabel(*Asm, *SkCU, SkCU->getUnitDie(), - dwarf::DW_AT_GNU_ranges_base, - DwarfDebugRangeSectionSym, DwarfDebugRangeSectionSym); + SkCU->addSectionLabel( + SkCU->getUnitDie(), dwarf::DW_AT_GNU_ranges_base, + DwarfDebugRangeSectionSym, DwarfDebugRangeSectionSym); } // If we have code split among multiple sections or non-contiguous @@ -942,9 +611,9 @@ void DwarfDebug::finalizeModuleInfo() { unsigned NumRanges = TheU->getRanges().size(); if (NumRanges) { if (NumRanges > 1) { - addSectionLabel(*Asm, U, U.getUnitDie(), dwarf::DW_AT_ranges, - Asm->GetTempSymbol("cu_ranges", U.getUniqueID()), - DwarfDebugRangeSectionSym); + U.addSectionLabel(U.getUnitDie(), dwarf::DW_AT_ranges, + Asm->GetTempSymbol("cu_ranges", U.getUniqueID()), + DwarfDebugRangeSectionSym); // A DW_AT_low_pc attribute may also be specified in combination with // DW_AT_ranges to specify the default base address for use in @@ -954,7 +623,7 @@ void DwarfDebug::finalizeModuleInfo() { 0); } else { RangeSpan &Range = TheU->getRanges().back(); - attachLowHighPC(U, U.getUnitDie(), Range.getStart(), Range.getEnd()); + U.attachLowHighPC(U.getUnitDie(), Range.getStart(), Range.getEnd()); } } } @@ -1100,8 +769,8 @@ DbgVariable *DwarfDebug::getExistingAbstractVariable(const DIVariable &DV) { void DwarfDebug::createAbstractVariable(const DIVariable &Var, LexicalScope *Scope) { - auto AbsDbgVariable = make_unique(Var, this); - addScopeVariable(Scope, AbsDbgVariable.get()); + auto AbsDbgVariable = make_unique(Var, DIExpression(), this); + InfoHolder.addNonArgumentScopeVariable(Scope, AbsDbgVariable.get()); AbstractVariables[Var] = std::move(AbsDbgVariable); } @@ -1125,29 +794,6 @@ DwarfDebug::ensureAbstractVariableIsCreatedIfScoped(const DIVariable &DV, createAbstractVariable(Cleansed, Scope); } -// If Var is a current function argument then add it to CurrentFnArguments list. -bool DwarfDebug::addCurrentFnArgument(DbgVariable *Var, LexicalScope *Scope) { - if (!LScopes.isCurrentFunctionScope(Scope)) - return false; - DIVariable DV = Var->getVariable(); - if (DV.getTag() != dwarf::DW_TAG_arg_variable) - return false; - unsigned ArgNo = DV.getArgNumber(); - if (ArgNo == 0) - return false; - - size_t Size = CurrentFnArguments.size(); - if (Size == 0) - 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) - 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( SmallPtrSetImpl &Processed) { @@ -1156,6 +802,7 @@ void DwarfDebug::collectVariableInfoFromMMITable( continue; Processed.insert(VI.Var); DIVariable DV(VI.Var); + DIExpression Expr(VI.Expr); LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc); // If variable scope is not found then skip this variable. @@ -1163,7 +810,7 @@ void DwarfDebug::collectVariableInfoFromMMITable( continue; ensureAbstractVariableIsCreatedIfScoped(DV, Scope->getScopeNode()); - ConcreteVariables.push_back(make_unique(DV, this)); + ConcreteVariables.push_back(make_unique(DV, Expr, this)); DbgVariable *RegVar = ConcreteVariables.back().get(); RegVar->setFrameIndex(VI.Slot); addScopeVariable(Scope, RegVar); @@ -1172,9 +819,10 @@ void DwarfDebug::collectVariableInfoFromMMITable( // Get .debug_loc entry for the instruction range starting at MI. static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) { + const MDNode *Expr = MI->getDebugExpression(); const MDNode *Var = MI->getDebugVariable(); - assert(MI->getNumOperands() == 3); + assert(MI->getNumOperands() == 4); if (MI->getOperand(0).isReg()) { MachineLocation MLoc; // If the second operand is an immediate, this is a @@ -1183,20 +831,20 @@ static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) { MLoc.set(MI->getOperand(0).getReg()); else MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm()); - return DebugLocEntry::Value(Var, MLoc); + return DebugLocEntry::Value(Var, Expr, MLoc); } if (MI->getOperand(0).isImm()) - return DebugLocEntry::Value(Var, MI->getOperand(0).getImm()); + return DebugLocEntry::Value(Var, Expr, MI->getOperand(0).getImm()); if (MI->getOperand(0).isFPImm()) - return DebugLocEntry::Value(Var, MI->getOperand(0).getFPImm()); + return DebugLocEntry::Value(Var, Expr, MI->getOperand(0).getFPImm()); if (MI->getOperand(0).isCImm()) - return DebugLocEntry::Value(Var, MI->getOperand(0).getCImm()); + return DebugLocEntry::Value(Var, Expr, MI->getOperand(0).getCImm()); - llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!"); + llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!"); } /// Determine whether two variable pieces overlap. -static bool piecesOverlap(DIVariable P1, DIVariable P2) { +static bool piecesOverlap(DIExpression P1, DIExpression P2) { if (!P1.isVariablePiece() || !P2.isVariablePiece()) return true; unsigned l1 = P1.getPieceOffset(); @@ -1247,11 +895,11 @@ DwarfDebug::buildLocationList(SmallVectorImpl &DebugLoc, } // If this piece overlaps with any open ranges, truncate them. - DIVariable DIVar = Begin->getDebugVariable(); + DIExpression DIExpr = Begin->getDebugExpression(); auto Last = std::remove_if(OpenRanges.begin(), OpenRanges.end(), [&](DebugLocEntry::Value R) { - return piecesOverlap(DIVar, R.getVariable()); - }); + return piecesOverlap(DIExpr, R.getExpression()); + }); OpenRanges.erase(Last, OpenRanges.end()); const MCSymbol *StartLabel = getLabelBeforeInsn(Begin); @@ -1273,7 +921,7 @@ DwarfDebug::buildLocationList(SmallVectorImpl &DebugLoc, bool couldMerge = false; // If this is a piece, it may belong to the current DebugLocEntry. - if (DIVar.isVariablePiece()) { + if (DIExpr.isVariablePiece()) { // Add this value to the list of open ranges. OpenRanges.push_back(Value); @@ -1299,20 +947,22 @@ DwarfDebug::buildLocationList(SmallVectorImpl &DebugLoc, if (PrevEntry != DebugLoc.rend() && PrevEntry->MergeRanges(*CurEntry)) DebugLoc.pop_back(); - DEBUG(dbgs() << "Values:\n"; - for (auto Value : CurEntry->getValues()) - Value.getVariable()->dump(); - dbgs() << "-----\n"); + DEBUG({ + dbgs() << CurEntry->getValues().size() << " Values:\n"; + for (auto Value : CurEntry->getValues()) { + Value.getVariable()->dump(); + Value.getExpression()->dump(); + } + dbgs() << "-----\n"; + }); } } // Find variables for each lexical scope. void -DwarfDebug::collectVariableInfo(SmallPtrSetImpl &Processed) { - LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); - DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); - +DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, DISubprogram SP, + SmallPtrSetImpl &Processed) { // Grab the variable info that was squirreled away in the MMI side-table. collectVariableInfoFromMMITable(Processed); @@ -1337,7 +987,7 @@ DwarfDebug::collectVariableInfo(SmallPtrSetImpl &Processed) { if (!Scope) continue; - Processed.insert(getEntireVariable(DV)); + Processed.insert(DV); const MachineInstr *MInsn = Ranges.front().first; assert(MInsn->isDebugValue() && "History must begin with debug value"); ensureAbstractVariableIsCreatedIfScoped(DV, Scope->getScopeNode()); @@ -1354,7 +1004,7 @@ DwarfDebug::collectVariableInfo(SmallPtrSetImpl &Processed) { DotDebugLocEntries.resize(DotDebugLocEntries.size() + 1); DebugLocList &LocList = DotDebugLocEntries.back(); - LocList.CU = TheCU; + LocList.CU = &TheCU; LocList.Label = Asm->GetTempSymbol("debug_loc", DotDebugLocEntries.size() - 1); @@ -1363,7 +1013,7 @@ DwarfDebug::collectVariableInfo(SmallPtrSetImpl &Processed) { } // Collect info for variables that were optimized out. - DIArray Variables = DISubprogram(FnScope->getScopeNode()).getVariables(); + DIArray Variables = SP.getVariables(); for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) { DIVariable DV(Variables.getElement(i)); assert(DV.isVariable()); @@ -1371,7 +1021,8 @@ DwarfDebug::collectVariableInfo(SmallPtrSetImpl &Processed) { continue; if (LexicalScope *Scope = LScopes.findLexicalScope(DV.getContext())) { ensureAbstractVariableIsCreatedIfScoped(DV, Scope->getScopeNode()); - ConcreteVariables.push_back(make_unique(DV, this)); + DIExpression NoExpr; + ConcreteVariables.push_back(make_unique(DV, NoExpr, this)); addScopeVariable(Scope, ConcreteVariables.back().get()); } } @@ -1559,18 +1210,17 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // The first mention of a function argument gets the FunctionBeginSym // label, so arguments are visible when breaking at function entry. - DIVariable DV(Ranges.front().first->getDebugVariable()); - if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable && - getDISubprogram(DV.getContext()).describes(MF->getFunction())) { - if (!DV.isVariablePiece()) - LabelsBeforeInsn[Ranges.front().first] = FunctionBeginSym; - else { + DIVariable DIVar(Ranges.front().first->getDebugVariable()); + if (DIVar.isVariable() && DIVar.getTag() == dwarf::DW_TAG_arg_variable && + getDISubprogram(DIVar.getContext()).describes(MF->getFunction())) { + LabelsBeforeInsn[Ranges.front().first] = FunctionBeginSym; + if (Ranges.front().first->getDebugExpression().isVariablePiece()) { // Mark all non-overlapping initial pieces. for (auto I = Ranges.begin(); I != Ranges.end(); ++I) { - DIVariable Piece = I->first->getDebugVariable(); + DIExpression Piece = I->first->getDebugExpression(); if (std::all_of(Ranges.begin(), I, - [&](DbgValueHistoryMap::InstrRange Pred){ - return !piecesOverlap(Piece, Pred.first->getDebugVariable()); + [&](DbgValueHistoryMap::InstrRange Pred) { + return !piecesOverlap(Piece, Pred.first->getDebugExpression()); })) LabelsBeforeInsn[I->first] = FunctionBeginSym; else @@ -1604,55 +1254,21 @@ 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. - if (unsigned ArgNum = DV.getArgNumber()) { - // Keep all parameters in order at the start of the variable list to ensure - // function types are correct (no out-of-order parameters) - // - // This could be improved by only doing it for optimized builds (unoptimized - // builds have the right order to begin with), searching from the back (this - // would catch the unoptimized case quickly), or doing a binary search - // rather than linear search. - SmallVectorImpl::iterator I = Vars.begin(); - while (I != Vars.end()) { - unsigned CurNum = (*I)->getVariable().getArgNumber(); - // A local (non-parameter) variable has been found, insert immediately - // before it. - if (CurNum == 0) - break; - // A later indexed parameter has been found, insert immediately before it. - if (CurNum > ArgNum) - break; - ++I; - } - Vars.insert(I, Var); + if (InfoHolder.addCurrentFnArgument(Var, LS)) return; - } - - Vars.push_back(Var); + InfoHolder.addNonArgumentScopeVariable(LS, Var); } // Gather and emit post-function debug information. void DwarfDebug::endFunction(const MachineFunction *MF) { - // 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) - CurFn = MF; - else - assert(CurFn == MF); - assert(CurFn != nullptr); + assert(CurFn == MF && + "endFunction should be called with the same function as beginFunction"); 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; @@ -1666,12 +1282,36 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { // Set DwarfDwarfCompileUnitID in MCContext to default value. Asm->OutStreamer.getContext().setDwarfCompileUnitID(0); + LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); + DISubprogram SP(FnScope->getScopeNode()); + DwarfCompileUnit &TheCU = *SPMap.lookup(SP); + SmallPtrSet ProcessedVars; - collectVariableInfo(ProcessedVars); + collectVariableInfo(TheCU, SP, ProcessedVars); - LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); - DwarfCompileUnit &TheCU = *SPMap.lookup(FnScope->getScopeNode()); + // Add the range of this function to the list of ranges for the CU. + TheCU.addRange(RangeSpan(FunctionBeginSym, FunctionEndSym)); + + // Under -gmlt, skip building the subprogram if there are no inlined + // subroutines inside it. + if (TheCU.getCUNode().getEmissionKind() == DIBuilder::LineTablesOnly && + LScopes.getAbstractScopesList().empty() && !IsDarwin) { + assert(ScopeVariables.empty()); + assert(CurrentFnArguments.empty()); + assert(DbgValues.empty()); + // FIXME: This wouldn't be true in LTO with a -g (with inlining) CU followed + // by a -gmlt CU. Add a test and remove this assertion. + assert(AbstractVariables.empty()); + LabelsBeforeInsn.clear(); + LabelsAfterInsn.clear(); + PrevLabel = nullptr; + CurFn = nullptr; + return; + } +#ifndef NDEBUG + size_t NumAbstractScopes = LScopes.getAbstractScopesList().size(); +#endif // Construct abstract scopes. for (LexicalScope *AScope : LScopes.getAbstractScopesList()) { DISubprogram SP(AScope->getScopeNode()); @@ -1684,19 +1324,13 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { if (!ProcessedVars.insert(DV)) continue; ensureAbstractVariableIsCreated(DV, DV.getContext()); + assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes + && "ensureAbstractVariableIsCreated inserted abstract scopes"); } - constructAbstractSubprogramScopeDIE(TheCU, AScope); + constructAbstractSubprogramScopeDIE(AScope); } - DIE &CurFnDIE = constructSubprogramScopeDIE(TheCU, FnScope); - if (!CurFn->getTarget().Options.DisableFramePointerElim(*CurFn)) - TheCU.addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr); - - // 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; + TheCU.constructSubprogramScopeDIE(FnScope); // Clear debug info // Ownership of DbgVariables is a bit subtle - ScopeVariables owns all the @@ -1834,7 +1468,7 @@ void DwarfDebug::emitDIE(DIE &Die) { void DwarfDebug::emitDebugInfo() { DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; - Holder.emitUnits(this, DwarfAbbrevSectionSym); + Holder.emitUnits(DwarfAbbrevSectionSym); } // Emit the abbreviation section. @@ -1868,54 +1502,41 @@ void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { Asm->EmitInt8(1); } -// Emit visible names into a hashed accelerator table section. -void DwarfDebug::emitAccelNames() { - AccelNames.FinalizeTable(Asm, "Names"); - Asm->OutStreamer.SwitchSection( - Asm->getObjFileLowering().getDwarfAccelNamesSection()); - MCSymbol *SectionBegin = Asm->GetTempSymbol("names_begin"); +void DwarfDebug::emitAccel(DwarfAccelTable &Accel, const MCSection *Section, + StringRef TableName, StringRef SymName) { + Accel.FinalizeTable(Asm, TableName); + Asm->OutStreamer.SwitchSection(Section); + auto *SectionBegin = Asm->GetTempSymbol(SymName); Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. - AccelNames.Emit(Asm, SectionBegin, &InfoHolder); + Accel.Emit(Asm, SectionBegin, &InfoHolder, DwarfStrSectionSym); +} + +// Emit visible names into a hashed accelerator table section. +void DwarfDebug::emitAccelNames() { + emitAccel(AccelNames, Asm->getObjFileLowering().getDwarfAccelNamesSection(), + "Names", "names_begin"); } // Emit objective C classes and categories into a hashed accelerator table // section. void DwarfDebug::emitAccelObjC() { - AccelObjC.FinalizeTable(Asm, "ObjC"); - Asm->OutStreamer.SwitchSection( - Asm->getObjFileLowering().getDwarfAccelObjCSection()); - MCSymbol *SectionBegin = Asm->GetTempSymbol("objc_begin"); - Asm->OutStreamer.EmitLabel(SectionBegin); - - // Emit the full data. - AccelObjC.Emit(Asm, SectionBegin, &InfoHolder); + emitAccel(AccelObjC, Asm->getObjFileLowering().getDwarfAccelObjCSection(), + "ObjC", "objc_begin"); } // Emit namespace dies into a hashed accelerator table. void DwarfDebug::emitAccelNamespaces() { - AccelNamespace.FinalizeTable(Asm, "namespac"); - Asm->OutStreamer.SwitchSection( - Asm->getObjFileLowering().getDwarfAccelNamespaceSection()); - MCSymbol *SectionBegin = Asm->GetTempSymbol("namespac_begin"); - Asm->OutStreamer.EmitLabel(SectionBegin); - - // Emit the full data. - AccelNamespace.Emit(Asm, SectionBegin, &InfoHolder); + emitAccel(AccelNamespace, + Asm->getObjFileLowering().getDwarfAccelNamespaceSection(), + "namespac", "namespac_begin"); } // Emit type dies into a hashed accelerator table. void DwarfDebug::emitAccelTypes() { - - AccelTypes.FinalizeTable(Asm, "types"); - Asm->OutStreamer.SwitchSection( - Asm->getObjFileLowering().getDwarfAccelTypesSection()); - MCSymbol *SectionBegin = Asm->GetTempSymbol("types_begin"); - Asm->OutStreamer.EmitLabel(SectionBegin); - - // Emit the full data. - AccelTypes.Emit(Asm, SectionBegin, &InfoHolder); + emitAccel(AccelTypes, Asm->getObjFileLowering().getDwarfAccelTypesSection(), + "types", "types_begin"); } // Public name handling. @@ -2072,9 +1693,9 @@ void DwarfDebug::emitLocPieces(ByteStreamer &Streamer, unsigned Offset = 0; for (auto Piece : Values) { - DIVariable Var = Piece.getVariable(); - unsigned PieceOffset = Var.getPieceOffset(); - unsigned PieceSize = Var.getPieceSize(); + DIExpression Expr = Piece.getExpression(); + unsigned PieceOffset = Expr.getPieceOffset(); + unsigned PieceSize = Expr.getPieceSize(); assert(Offset <= PieceOffset && "overlapping or duplicate pieces"); if (Offset < PieceOffset) { // The DWARF spec seriously mandates pieces with no locations for gaps. @@ -2085,8 +1706,9 @@ void DwarfDebug::emitLocPieces(ByteStreamer &Streamer, Offset += PieceSize; const unsigned SizeOfByte = 8; - assert(!Var.isIndirect() && "indirect address for piece"); #ifndef NDEBUG + DIVariable Var = Piece.getVariable(); + assert(!Var.isIndirect() && "indirect address for piece"); unsigned VarSize = Var.getSizeInBits(Map); assert(PieceSize+PieceOffset <= VarSize/SizeOfByte && "piece is larger than or outside of variable"); @@ -2132,24 +1754,25 @@ void DwarfDebug::emitDebugLocValue(ByteStreamer &Streamer, } } else if (Value.isLocation()) { MachineLocation Loc = Value.getLoc(); - if (!DV.hasComplexAddress()) + DIExpression Expr = Value.getExpression(); + if (!Expr) // Regular entry. Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect()); else { // Complex address entry. - unsigned N = DV.getNumAddrElements(); + unsigned N = Expr.getNumElements(); unsigned i = 0; - if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) { + if (N >= 2 && Expr.getElement(0) == dwarf::DW_OP_plus) { if (Loc.getOffset()) { i = 2; Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect()); Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref"); Streamer.EmitInt8(dwarf::DW_OP_plus_uconst, "DW_OP_plus_uconst"); - Streamer.EmitSLEB128(DV.getAddrElement(1)); + Streamer.EmitSLEB128(Expr.getElement(1)); } else { // If first address element is OpPlus then emit // DW_OP_breg + Offset instead of DW_OP_reg + Offset. - MachineLocation TLoc(Loc.getReg(), DV.getAddrElement(1)); + MachineLocation TLoc(Loc.getReg(), Expr.getElement(1)); Asm->EmitDwarfRegOp(Streamer, TLoc, DV.isIndirect()); i = 2; } @@ -2159,14 +1782,14 @@ void DwarfDebug::emitDebugLocValue(ByteStreamer &Streamer, // Emit remaining complex address elements. for (; i < N; ++i) { - uint64_t Element = DV.getAddrElement(i); - if (Element == DIBuilder::OpPlus) { + uint64_t Element = Expr.getElement(i); + if (Element == dwarf::DW_OP_plus) { Streamer.EmitInt8(dwarf::DW_OP_plus_uconst, "DW_OP_plus_uconst"); - Streamer.EmitULEB128(DV.getAddrElement(++i)); - } else if (Element == DIBuilder::OpDeref) { + Streamer.EmitULEB128(Expr.getElement(++i)); + } else if (Element == dwarf::DW_OP_deref) { if (!Loc.isReg()) Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref"); - } else if (Element == DIBuilder::OpPiece) { + } else if (Element == dwarf::DW_OP_piece) { i += 3; // handled in emitDebugLocEntry. } else @@ -2488,7 +2111,7 @@ void DwarfDebug::emitDebugInfoDWO() { assert(useSplitDwarf() && "No split dwarf debug info?"); // Don't pass an abbrev symbol, using a constant zero instead so as not to // emit relocations into the dwo file. - InfoHolder.emitUnits(this, /* AbbrevSymbol */ nullptr); + InfoHolder.emitUnits(/* AbbrevSymbol */ nullptr); } // Emit the .debug_abbrev.dwo section for separated dwarf. This contains the @@ -2512,9 +2135,8 @@ void DwarfDebug::emitDebugStrDWO() { assert(useSplitDwarf() && "No split dwarf?"); const MCSection *OffSec = Asm->getObjFileLowering().getDwarfStrOffDWOSection(); - const MCSymbol *StrSym = DwarfStrSectionSym; InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(), - OffSec, StrSym); + OffSec); } MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) { @@ -2610,20 +2232,6 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, CU.addDIETypeSignature(RefDie, NewTU); } -void DwarfDebug::attachLowHighPC(DwarfCompileUnit &Unit, DIE &D, - 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"); - assert(End->isDefined() && "Invalid end label"); - - Unit.addLabelAddress(D, dwarf::DW_AT_low_pc, Begin); - if (DwarfVersion < 4) - Unit.addLabelAddress(D, dwarf::DW_AT_high_pc, End); - else - Unit.addLabelDelta(D, dwarf::DW_AT_high_pc, End, Begin); -} - // Accelerator table mutators - add each name along with its companion // DIE to the proper table while ensuring that the name that we're going // to reference is in the string table. We do this since the names we