diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index defae5d920b..2f0e8181ed5 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -455,15 +455,21 @@ static std::unique_ptr constructVariableDIE(DwarfCompileUnit &TheCU, DIE *DwarfDebug::createScopeChildrenDIE( DwarfCompileUnit &TheCU, LexicalScope *Scope, - SmallVectorImpl> &Children) { + SmallVectorImpl> &Children, + unsigned *ChildScopeCount) { DIE *ObjectPointer = nullptr; 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; } @@ -565,10 +571,11 @@ DIE &DwarfDebug::constructSubprogramScopeDIE(DwarfCompileUnit &TheCU, } // 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()); @@ -586,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, ++i) Children.push_back( constructImportedEntityDIE(TheCU, DIImportedEntity(i->second))); - if (Children.empty()) - return nullptr; + // 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."); } @@ -619,7 +634,7 @@ std::unique_ptr DwarfDebug::constructScopeDIE(DwarfCompileUnit &TheCU, 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 { diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 40385cf0b2c..5c33d34559b 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -377,8 +377,8 @@ class DwarfDebug : public AsmPrinterHandler { LexicalScope *Scope); /// \brief Construct a DIE for this scope. - std::unique_ptr constructScopeDIE(DwarfCompileUnit &TheCU, - LexicalScope *Scope); + void constructScopeDIE(DwarfCompileUnit &TheCU, LexicalScope *Scope, + SmallVectorImpl> &FinalChildren); DIE *createAndAddScopeChildren(DwarfCompileUnit &TheCU, LexicalScope *Scope, DIE &ScopeDIE); /// \brief Construct a DIE for this abstract scope. @@ -389,7 +389,8 @@ class DwarfDebug : public AsmPrinterHandler { LexicalScope *Scope); /// A helper function to create children of a Scope DIE. DIE *createScopeChildrenDIE(DwarfCompileUnit &TheCU, LexicalScope *Scope, - SmallVectorImpl> &Children); + SmallVectorImpl> &Children, + unsigned *ChildScopeCount = nullptr); /// \brief Emit initial Dwarf sections with a label at the start of each one. void emitSectionLabels(); diff --git a/test/DebugInfo/PR20038.ll b/test/DebugInfo/PR20038.ll index 61145e5c844..b8a80524fb9 100644 --- a/test/DebugInfo/PR20038.ll +++ b/test/DebugInfo/PR20038.ll @@ -30,22 +30,18 @@ ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "fun4" ; CHECK-NOT: {{DW_TAG|NULL}} -; CHECK: DW_TAG_lexical_block -; CHECK-NOT: {{DW_TAG|NULL}} -; CHECK: DW_TAG_inlined_subroutine +; CHECK: DW_TAG_inlined_subroutine ; CHECK-NOT: DW_TAG -; CHECK: DW_AT_abstract_origin {{.*}} {[[D1_ABS]]} +; CHECK: DW_AT_abstract_origin {{.*}} {[[D1_ABS]]} ; CHECK-NOT: {{DW_TAG|NULL}} -; CHECK: DW_TAG_formal_parameter +; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: DW_TAG -; CHECK: DW_AT_abstract_origin {{.*}} {[[D1_THIS_ABS]]} +; CHECK: DW_AT_abstract_origin {{.*}} {[[D1_THIS_ABS]]} ; FIXME: D2 is actually inlined into D1 but doesn't show up here, possibly due ; to there being no work in D2 (calling another member function from the dtor ; causes D2 to show up, calling a free function doesn't). -; CHECK-NOT: DW_TAG -; CHECK: NULL ; CHECK-NOT: DW_TAG ; CHECK: NULL ; CHECK-NOT: DW_TAG diff --git a/test/DebugInfo/X86/concrete_out_of_line.ll b/test/DebugInfo/X86/concrete_out_of_line.ll index ac038f353ad..32ebb068b68 100644 --- a/test/DebugInfo/X86/concrete_out_of_line.ll +++ b/test/DebugInfo/X86/concrete_out_of_line.ll @@ -32,9 +32,6 @@ ; CHECK: DW_TAG_formal_parameter ; CHECK-NOT: NULL ; CHECK-NOT: DW_TAG -; CHECK: DW_TAG_lexical_block -; CHECK-NOT: NULL -; CHECK-NOT: DW_TAG ; CHECK: DW_TAG_inlined_subroutine ; CHECK-NEXT: DW_AT_abstract_origin {{.*}} {[[ASSIGN:0x........]]} ; CHECK-NOT: NULL diff --git a/test/DebugInfo/X86/fission-ranges.ll b/test/DebugInfo/X86/fission-ranges.ll index 6e3bbfef75c..482ed8fa920 100644 --- a/test/DebugInfo/X86/fission-ranges.ll +++ b/test/DebugInfo/X86/fission-ranges.ll @@ -16,7 +16,7 @@ ; CHECK: DW_AT_location [DW_FORM_sec_offset] ([[E:0x[0-9a-z]*]]) ; CHECK: DW_AT_location [DW_FORM_sec_offset] ([[B:0x[0-9a-z]*]]) ; CHECK: DW_AT_location [DW_FORM_sec_offset] ([[D:0x[0-9a-z]*]]) -; CHECK: DW_AT_ranges [DW_FORM_sec_offset] (0x000000a0) +; CHECK: DW_AT_ranges [DW_FORM_sec_offset] (0x00000000) ; CHECK: .debug_loc contents: ; CHECK-NOT: Beginning address offset ; CHECK: .debug_loc.dwo contents: diff --git a/test/DebugInfo/missing-abstract-variable.ll b/test/DebugInfo/missing-abstract-variable.ll index 59a38cf39d5..2d4ba07843e 100644 --- a/test/DebugInfo/missing-abstract-variable.ll +++ b/test/DebugInfo/missing-abstract-variable.ll @@ -45,8 +45,6 @@ ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_name {{.*}} "b" ; CHECK-NOT: {{DW_TAG|NULL}} -; CHECK: DW_TAG_lexical_block -; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_lexical_block ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: [[ABS_S:.*]]: DW_TAG_variable @@ -89,19 +87,12 @@ ; CHECK-NOT: DW_TAG ; CHECK: DW_AT_abstract_origin {{.*}} {[[ABS_B]]} -; The two lexical blocks here are caused by the scope of the if that includes -; the condition variable, and the scope within the if's composite statement. I'm -; not sure we really need both of them since there's no variable declared in the -; outer of the two - ; CHECK-NOT: {{DW_TAG|NULL}} ; CHECK: DW_TAG_lexical_block ; CHECK-NOT: {{DW_TAG|NULL}} -; CHECK: DW_TAG_lexical_block -; CHECK-NOT: {{DW_TAG|NULL}} -; CHECK: DW_TAG_variable +; CHECK: DW_TAG_variable ; CHECK-NOT: DW_TAG -; CHECK: DW_AT_abstract_origin {{.*}} {[[ABS_S]]} +; CHECK: DW_AT_abstract_origin {{.*}} {[[ABS_S]]} @t = external global i32