diff --git a/llvm/include/llvm/ADT/iterator_range.h b/llvm/include/llvm/ADT/iterator_range.h index dd17d6c8f7b4..d004ead71f9d 100644 --- a/llvm/include/llvm/ADT/iterator_range.h +++ b/llvm/include/llvm/ADT/iterator_range.h @@ -48,6 +48,10 @@ public: template iterator_range make_range(T x, T y) { return iterator_range(std::move(x), std::move(y)); } + +template iterator_range make_range(std::pair p) { + return iterator_range(std::move(p.first), std::move(p.second)); +} } #endif diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index b48ecfaf27bf..bd33c265bef6 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -319,4 +319,63 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(DISubprogram SP) { return *SPDie; } +// Construct a DIE for this scope. +void DwarfCompileUnit::constructScopeDIE( + LexicalScope *Scope, SmallVectorImpl> &FinalChildren) { + if (!Scope || !Scope->getScopeNode()) + return; + + 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 = DD->constructInlinedScopeDIE(*this, Scope); + if (!ScopeDIE) + return; + // We create children when the scope DIE is not null. + DD->createScopeChildrenDIE(*this, Scope, Children); + } else { + // Early exit when we know the scope DIE is going to be null. + if (DD->isLexicalScopeDIENull(Scope)) + 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. + DD->createScopeChildrenDIE(*this, Scope, Children, &ChildScopeCount); + + // There is no need to emit empty lexical block DIE. + for (const auto &E : DD->findImportedEntitiesForScope(DS)) + Children.push_back( + constructImportedEntityDIE(DIImportedEntity(E.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 = DD->constructLexicalScopeDIE(*this, Scope); + assert(ScopeDIE && "Scope DIE should not be null."); + } + + // Add children + for (auto &I : Children) + ScopeDIE->addChild(std::move(I)); + + FinalChildren.push_back(std::move(ScopeDIE)); +} + } // end llvm namespace diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index a98ab26cc0f7..0c4ad4923f14 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -26,6 +26,7 @@ class DIE; class DwarfDebug; class DwarfFile; class MCSymbol; +class LexicalScope; class DwarfCompileUnit : public DwarfUnit { /// The attribute index of DW_AT_stmt_list in the compile unit DIE, avoiding @@ -68,6 +69,9 @@ public: /// variables in this scope then create and insert DIEs for these /// variables. DIE &updateSubprogramScopeDIE(DISubprogram SP); + + void constructScopeDIE(LexicalScope *Scope, + SmallVectorImpl> &FinalChildren); }; } // end llvm namespace diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h index 52cd9e7e4223..9deaa94ca068 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -349,25 +349,11 @@ class DwarfDebug : public AsmPrinterHandler { void ensureAbstractVariableIsCreatedIfScoped(const DIVariable &Var, const MDNode *Scope); - /// \brief A helper function to check whether the DIE for a given Scope is - /// going to be null. - bool isLexicalScopeDIENull(LexicalScope *Scope); - /// \brief A helper function to construct a RangeSpanList for a given /// lexical scope. void addScopeRangeList(DwarfCompileUnit &TheCU, DIE &ScopeDIE, const SmallVectorImpl &Range); - /// \brief Construct new DW_TAG_lexical_block for this scope and - /// attach DW_AT_low_pc/DW_AT_high_pc labels. - std::unique_ptr constructLexicalScopeDIE(DwarfCompileUnit &TheCU, - LexicalScope *Scope); - - /// \brief This scope represents inlined body of a function. Construct - /// DIE to represent this concrete inlined copy of the function. - std::unique_ptr constructInlinedScopeDIE(DwarfCompileUnit &TheCU, - LexicalScope *Scope); - /// \brief Construct a DIE for this scope. void constructScopeDIE(DwarfCompileUnit &TheCU, LexicalScope *Scope, SmallVectorImpl> &FinalChildren); @@ -379,10 +365,6 @@ class DwarfDebug : public AsmPrinterHandler { /// \brief Construct a DIE for this subprogram scope. void constructSubprogramScopeDIE(DwarfCompileUnit &TheCU, LexicalScope *Scope); - /// A helper function to create children of a Scope DIE. - DIE *createScopeChildrenDIE(DwarfCompileUnit &TheCU, LexicalScope *Scope, - SmallVectorImpl> &Children, - unsigned *ChildScopeCount = nullptr); /// \brief Emit initial Dwarf sections with a label at the start of each one. void emitSectionLabels(); @@ -680,6 +662,33 @@ public: const MachineFunction *getCurrentFunction() const { return CurFn; } const MCSymbol *getFunctionBeginSym() const { return FunctionBeginSym; } const MCSymbol *getFunctionEndSym() const { return FunctionEndSym; } + + iterator_range findImportedEntitiesForScope(const MDNode *Scope) const { + return make_range(std::equal_range( + ScopesWithImportedEntities.begin(), ScopesWithImportedEntities.end(), + std::pair(Scope, nullptr), less_first())); + } + + /// \brief A helper function to check whether the DIE for a given Scope is + /// going to be null. + bool isLexicalScopeDIENull(LexicalScope *Scope); + + // FIXME: Sink these functions down into DwarfFile/Dwarf*Unit. + + /// \brief Construct new DW_TAG_lexical_block for this scope and + /// attach DW_AT_low_pc/DW_AT_high_pc labels. + std::unique_ptr constructLexicalScopeDIE(DwarfCompileUnit &TheCU, + LexicalScope *Scope); + + /// \brief This scope represents inlined body of a function. Construct + /// DIE to represent this concrete inlined copy of the function. + std::unique_ptr constructInlinedScopeDIE(DwarfCompileUnit &TheCU, + LexicalScope *Scope); + + /// A helper function to create children of a Scope DIE. + DIE *createScopeChildrenDIE(DwarfCompileUnit &TheCU, LexicalScope *Scope, + SmallVectorImpl> &Children, + unsigned *ChildScopeCount = nullptr); }; } // End of namespace llvm