diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -191,9 +191,11 @@ /// 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 &updateSubprogramScopeDIE(const DISubprogram *SP); + DIE &updateSubprogramScopeDIE(const DISubprogram *SP, + DwarfCompileUnit *&ContextCU); - void constructScopeDIE(LexicalScope *Scope, DIE &ParentScopeDIE); + void constructScopeDIE(LexicalScope *Scope, DIE &ParentScopeDIE, + DwarfCompileUnit *ContextCU); /// A helper function to construct a RangeSpanList for a given /// lexical scope. @@ -206,7 +208,8 @@ /// This scope represents an inlined body of a function. Construct a /// DIE to represent this concrete inlined copy of the function. - DIE *constructInlinedScopeDIE(LexicalScope *Scope, DIE &ParentScopeDIE); + DIE *constructInlinedScopeDIE(LexicalScope *Scope, DIE &ParentScopeDIE, + DwarfCompileUnit *ContextCU); /// Construct new DW_TAG_lexical_block for this scope and /// attach DW_AT_low_pc/DW_AT_high_pc labels. @@ -224,10 +227,11 @@ void createBaseTypeDIEs(); /// Construct a DIE for this subprogram scope. - DIE &constructSubprogramScopeDIE(const DISubprogram *Sub, - LexicalScope *Scope); + DIE &constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope, + DwarfCompileUnit *&ContextCU); - DIE *createAndAddScopeChildren(LexicalScope *Scope, DIE &ScopeDIE); + DIE *createAndAddScopeChildren(LexicalScope *Scope, DIE &ScopeDIE, + DwarfCompileUnit *ContextCU); void constructAbstractSubprogramScopeDIE(LexicalScope *Scope); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -443,8 +443,12 @@ // 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 &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) { +DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP, + DwarfCompileUnit *&ContextCU) { DIE *SPDie = getOrCreateSubprogramDIE(SP, includeMinimalInlineScopes()); + if (!ContextCU) { + ContextCU = static_cast(SPDie->getUnit()); + } SmallVector BB_List; // If basic block sections are on, ranges for each basic block section has @@ -452,7 +456,7 @@ for (const auto &R : Asm->MBBSectionRanges) BB_List.push_back({R.second.BeginLabel, R.second.EndLabel}); - attachRangesOrLowHighPC(*SPDie, BB_List); + ContextCU->attachRangesOrLowHighPC(*SPDie, BB_List); if (DD->useAppleExtensionAttributes() && !DD->getCurrentFunction()->getTarget().Options.DisableFramePointerElim( @@ -534,7 +538,8 @@ // Construct a DIE for this scope. void DwarfCompileUnit::constructScopeDIE(LexicalScope *Scope, - DIE &ParentScopeDIE) { + DIE &ParentScopeDIE, + DwarfCompileUnit *ContextCU) { if (!Scope || !Scope->getScopeNode()) return; @@ -547,9 +552,9 @@ // Emit inlined subprograms. if (Scope->getParent() && isa(DS)) { - DIE *ScopeDIE = constructInlinedScopeDIE(Scope, ParentScopeDIE); + DIE *ScopeDIE = constructInlinedScopeDIE(Scope, ParentScopeDIE, ContextCU); assert(ScopeDIE && "Scope DIE should not be null."); - createAndAddScopeChildren(Scope, *ScopeDIE); + createAndAddScopeChildren(Scope, *ScopeDIE, ContextCU); return; } @@ -562,7 +567,7 @@ assert(ScopeDIE && "Scope DIE should not be null."); ParentScopeDIE.addChild(ScopeDIE); - createAndAddScopeChildren(Scope, *ScopeDIE); + createAndAddScopeChildren(Scope, *ScopeDIE, ContextCU); } void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE, @@ -648,7 +653,8 @@ } DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope, - DIE &ParentScopeDIE) { + DIE &ParentScopeDIE, + DwarfCompileUnit *ContextCU) { assert(Scope->getScopeNode()); auto *DS = Scope->getScopeNode(); auto *InlinedSP = getDISubprogram(DS); @@ -661,7 +667,7 @@ ParentScopeDIE.addChild(ScopeDIE); addDIEEntry(*ScopeDIE, dwarf::DW_AT_abstract_origin, *OriginDIE); - attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges()); + ContextCU->attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges()); // Add the call site information to the DIE. const DILocation *IA = Scope->getInlinedAt(); @@ -1012,9 +1018,10 @@ return Result; } -DIE &DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub, - LexicalScope *Scope) { - DIE &ScopeDIE = updateSubprogramScopeDIE(Sub); +DIE &DwarfCompileUnit::constructSubprogramScopeDIE( + const DISubprogram *Sub, LexicalScope *Scope, + DwarfCompileUnit *&ContextCU) { + DIE &ScopeDIE = updateSubprogramScopeDIE(Sub, ContextCU); if (Scope) { assert(!Scope->getInlinedAt()); @@ -1022,7 +1029,8 @@ // 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 *ObjectPointer = createAndAddScopeChildren(Scope, ScopeDIE)) + if (DIE *ObjectPointer = + createAndAddScopeChildren(Scope, ScopeDIE, ContextCU)) addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer); } @@ -1041,7 +1049,8 @@ } DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope, - DIE &ScopeDIE) { + DIE &ScopeDIE, + DwarfCompileUnit *ContextCU) { DIE *ObjectPointer = nullptr; // Emit function arguments (order is significant). @@ -1080,9 +1089,9 @@ // If the lexical block doesn't have non-scope children, skip // its emission and put its children directly to the parent scope. if (needToEmitLexicalScope(LS)) - constructScopeDIE(LS, ScopeDIE); + constructScopeDIE(LS, ScopeDIE, ContextCU); else - createAndAddScopeChildren(LS, ScopeDIE); + createAndAddScopeChildren(LS, ScopeDIE, ContextCU); } return ObjectPointer; @@ -1124,8 +1133,10 @@ DD->getDwarfVersion() <= 4 ? Optional() : dwarf::DW_FORM_implicit_const, dwarf::DW_INL_inlined); - if (DIE *ObjectPointer = ContextCU->createAndAddScopeChildren(Scope, *AbsDef)) - ContextCU->addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer); + if (DIE *ObjectPointer = + ContextCU->createAndAddScopeChildren(Scope, *AbsDef, ContextCU)) + ContextCU->addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, + *ObjectPointer); } bool DwarfCompileUnit::useGNUAnalogForDwarf5Feature() const { diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -2257,11 +2257,14 @@ } ProcessedSPNodes.insert(SP); - DIE &ScopeDIE = TheCU.constructSubprogramScopeDIE(SP, FnScope); - if (auto *SkelCU = TheCU.getSkeleton()) + DwarfCompileUnit *ContextCU = nullptr; + DIE &ScopeDIE = TheCU.constructSubprogramScopeDIE(SP, FnScope, ContextCU); + if (auto *SkelCU = TheCU.getSkeleton()) { + DwarfCompileUnit *ContextSkelCU = ContextCU->getSkeleton(); if (!LScopes.getAbstractScopesList().empty() && TheCU.getCUNode()->getSplitDebugInlining()) - SkelCU->constructSubprogramScopeDIE(SP, FnScope); + SkelCU->constructSubprogramScopeDIE(SP, FnScope, ContextSkelCU); + } // Construct call site entries. constructCallSiteEntryDIEs(*SP, TheCU, ScopeDIE, *MF); diff --git a/llvm/test/DebugInfo/Generic/cross-cu-inlining-ranges.ll b/llvm/test/DebugInfo/Generic/cross-cu-inlining-ranges.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/Generic/cross-cu-inlining-ranges.ll @@ -0,0 +1,40 @@ +; RUN: %llc_dwarf %s -O0 -filetype=obj -o %t.o +; RUN: llvm-dwarfdump %t.o --debug-info --verify + +; We want to check that when the CU attaches ranges use the correct ContextCU. + +define void @foo() !dbg !6 { + ret void, !dbg !9 +} + +define void @bar(i32* %0) !dbg !15 { + store i32 1, i32* %0, align 4, !dbg !16 + store i32 1, i32* %0, align 4, !dbg !21 + ret void, !dbg !16 +} + +!llvm.dbg.cu = !{!0, !2} +!llvm.module.flags = !{!4, !5} + +!0 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !1, isOptimized: true, runtimeVersion: 5, emissionKind: FullDebug) +!1 = !DIFile(filename: "foo.swift", directory: "") +!2 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !3, isOptimized: true, runtimeVersion: 5, emissionKind: FullDebug) +!3 = !DIFile(filename: "bar.swift", directory: "") +!4 = !{i32 7, !"Dwarf Version", i32 4} +!5 = !{i32 2, !"Debug Info Version", i32 3} +!6 = distinct !DISubprogram(name: "foo", scope: !0, type: !7, spFlags: DISPFlagDefinition, unit: !0) +!7 = !DISubroutineType(types: !8) +!8 = !{} +!9 = !DILocation(line: 0, scope: !10, inlinedAt: !13) +!10 = distinct !DISubprogram(name: "init", scope: !12, file: !11, type: !7, spFlags: DISPFlagDefinition, unit: !0) +!11 = !DIFile(filename: "", directory: "") +!12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Type", file: !3, runtimeLang: DW_LANG_Swift, identifier: "Type") +!13 = !DILocation(line: 0, scope: !14) +!14 = distinct !DILexicalBlock(scope: !6, file: !1) +!15 = distinct !DISubprogram(name: "bar", scope: !12, type: !7, spFlags: DISPFlagDefinition, unit: !2) +!16 = !DILocation(line: 0, scope: !17, inlinedAt: !19) +!17 = distinct !DILexicalBlock(scope: !18, file: !3) +!18 = distinct !DISubprogram(name: "inlined_baz", scope: !12, file: !3, type: !7, spFlags: DISPFlagDefinition, unit: !2) +!19 = !DILocation(line: 0, scope: !20) +!20 = distinct !DILexicalBlock(scope: !15, file: !3) +!21 = !DILocation(line: 0, scope: !15)