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 = DD->lookupCU(SPDie->getUnitDie()); + } 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,49 @@ +; RUN: %llc_dwarf %s -filetype=obj -o %t +; RUN: llvm-dwarfdump --verify %t + +; We want to check that when the CU attaches ranges use the correct ContextCU. + +declare void @f() + +define void @main() { + call void @f() + call void @f() + call void @f() + call void @f() + call void @f() + ret void +} + +define void @foo() !dbg !10 { + call void @f(), !dbg !13 + call void @f(), !dbg !18 + ret void, !dbg !13 +} + +define void @bar() !dbg !19 { + ret void +} + +!llvm.dbg.cu = !{!0, !2} +!llvm.module.flags = !{!8, !9} + +!0 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !1, producer: "foo", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +!1 = !DIFile(filename: "foo.swift", directory: "") +!2 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !3, producer: "bar", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4) +!3 = !DIFile(filename: "bar.swift", directory: "") +!4 = !{!5} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "global", linkageName: "global", scope: null, file: !3, line: 2, type: !7, isLocal: false, isDefinition: true) +!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "struct", file: !1, runtimeLang: DW_LANG_Swift, identifier: "struct") +!8 = !{i32 7, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = distinct !DISubprogram(name: "foo", linkageName: "_foo", scope: !7, type: !11, spFlags: DISPFlagDefinition, unit: !0) +!11 = !DISubroutineType(types: !12) +!12 = !{} +!13 = !DILocation(line: 0, scope: !14, inlinedAt: !16) +!14 = distinct !DILexicalBlock(scope: !15, file: !1) +!15 = distinct !DISubprogram(name: "inlined_baz", linkageName: "_inlined_baz", scope: !7, file: !1, line: 7, type: !11, scopeLine: 7, spFlags: DISPFlagDefinition, unit: !0) +!16 = !DILocation(line: 0, scope: !17) +!17 = distinct !DILexicalBlock(scope: !10, file: !1) +!18 = !DILocation(line: 0, scope: !10) +!19 = distinct !DISubprogram(name: "bar", linkageName: "bar", scope: !2, type: !11, spFlags: DISPFlagDefinition, unit: !2)