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 @@ -196,7 +196,6 @@ /// variables in this scope then create and insert DIEs for these /// variables. DIE &updateSubprogramScopeDIE(const DISubprogram *SP); - DIE &updateSubprogramScopeDIEImpl(const DISubprogram *SP, DIE *SPDie); void constructScopeDIE(LexicalScope *Scope, DIE &ParentScopeDIE); 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 @@ -457,15 +457,6 @@ addLabelDelta(D, dwarf::DW_AT_high_pc, End, Begin); } -// 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 *SPDie = getOrCreateSubprogramDIE(SP, includeMinimalInlineScopes()); - auto *ContextCU = static_cast(SPDie->getUnit()); - return ContextCU->updateSubprogramScopeDIEImpl(SP, SPDie); -} - // Add info for Wasm-global-based relocation. // 'GlobalIndex' is used for split dwarf, which currently relies on a few // assumptions that are not guaranteed in a formal way but work in practice. @@ -499,8 +490,12 @@ } } -DIE &DwarfCompileUnit::updateSubprogramScopeDIEImpl(const DISubprogram *SP, - DIE *SPDie) { +// 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 *SPDie = getOrCreateSubprogramDIE(SP, includeMinimalInlineScopes()); + SmallVector BB_List; // If basic block sections are on, ranges for each basic block section has // to be emitted separately. @@ -1049,7 +1044,6 @@ DIE &DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope) { DIE &ScopeDIE = updateSubprogramScopeDIE(Sub); - auto *ContextCU = static_cast(ScopeDIE.getUnit()); if (Scope) { assert(!Scope->getInlinedAt()); @@ -1057,10 +1051,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 = - ContextCU->createAndAddScopeChildren(Scope, ScopeDIE)) - ContextCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, - *ObjectPointer); + if (DIE *ObjectPointer = createAndAddScopeChildren(Scope, ScopeDIE)) + addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer); } // If this is a variadic function, add an unspecified parameter. diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1160,6 +1160,11 @@ if (DIE *SPDie = getDIE(SP)) return SPDie; + // If the scope and SP are not in the same CU after LTO, we prefer the DIE + // of SP's CU as ParentDIE. + if (this != static_cast(ContextDIE->getUnit())) + ContextDIE = &getUnitDie(); + if (auto *SPDecl = SP->getDeclaration()) { if (!Minimal) { // Add subprogram definitions to the CU die directly. @@ -1177,8 +1182,8 @@ if (SP->isDefinition()) return &SPDie; - static_cast(SPDie.getUnit()) - ->applySubprogramAttributes(SP, SPDie); + applySubprogramAttributes(SP, SPDie); + return &SPDie; } diff --git a/llvm/test/DebugInfo/Generic/cross-cu-inlining-2.ll b/llvm/test/DebugInfo/Generic/cross-cu-inlining-2.ll --- a/llvm/test/DebugInfo/Generic/cross-cu-inlining-2.ll +++ b/llvm/test/DebugInfo/Generic/cross-cu-inlining-2.ll @@ -43,12 +43,7 @@ ; CHECK: DW_TAG_structure_type ; CHECK: [[INIT:0x.*]]: DW_TAG_subprogram ; CHECK; DW_AT_name [DW_FORM_strp] ({{.*}} = "init") -; CHECK: DW_TAG_subprogram -; CHECK; DW_AT_name [DW_FORM_strp] ({{.*}} = "bar") -; CHECK: DW_TAG_inlined_subroutine -; CHECK: DW_AT_abstract_origin [DW_FORM_ref_addr] (0x00000000[[GOO:.*]] "goo") ; CHECK: NULL -; CHECK: NULL ; CHECK: DW_TAG_structure_type ; CHECK: DW_TAG_subprogram ; CHECK; DW_AT_name [DW_FORM_strp] ({{.*}} = "foo") @@ -60,7 +55,12 @@ ; CHECK: NULL ; CHECK: DW_TAG_compile_unit ; CHECK: DW_TAG_module -; CHECK: 0x[[GOO]]: DW_TAG_subprogram +; CHECK: [[GOO:0x.*]]: DW_TAG_subprogram ; CHECK; DW_AT_name [DW_FORM_strp] ({{.*}} = "goo") ; CHECK: NULL +; CHECK: DW_TAG_subprogram +; CHECK; DW_AT_name [DW_FORM_strp] ({{.*}} = "bar") +; CHECK: DW_TAG_inlined_subroutine +; CHECK: DW_AT_abstract_origin [DW_FORM_ref4] ({{.*}} => {[[GOO]]} "goo") +; CHECK: NULL ; CHECK: NULL diff --git a/llvm/test/DebugInfo/Generic/cross-cu.ll b/llvm/test/DebugInfo/Generic/cross-cu.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/Generic/cross-cu.ll @@ -0,0 +1,100 @@ +; RUN: %llc_dwarf %s -O1 -mtriple=x86_64-unknown-unknown -filetype=obj -o %t.o +; RUN: %llc_dwarf %s -O0 -filetype=obj -o %t.o +; RUN: llvm-dwarfdump %t.o --debug-info --verbose | FileCheck %s +; RUN: llvm-dwarfdump %t.o --debug-info --verify + +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +define { ptr, i64 } @test(i1 %0, ptr %1) !dbg !23 { + %3 = alloca i64, i32 0, align 8 + call void @llvm.dbg.declare(metadata ptr %3, metadata !26, metadata !DIExpression()), !dbg !29 + %4 = icmp eq i64 0, 0 + br i1 %4, label %5, label %6 + +5: ; preds = %2 + store ptr null, ptr null, align 8, !dbg !30 + store i64 0, ptr %1, align 8 + ret { ptr, i64 } zeroinitializer + +6: ; preds = %2 + br i1 %0, label %9, label %7, !dbg !31 + +7: ; preds = %6 + %8 = load i64, ptr null, align 8, !dbg !32 + store i64 %8, ptr %1, align 8 + ret { ptr, i64 } zeroinitializer + +9: ; preds = %6 + store i64 0, ptr null, align 8 + ret { ptr, i64 } zeroinitializer +} + +define void @test2() cold !dbg !33 { + unreachable +} + +!llvm.module.flags = !{!0} +!llvm.dbg.cu = !{!1, !4} + +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !2, producer: "clang LLVM (rustc version 1.70.0-nightly (ec2f40c6b 2023-03-30))", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, splitDebugInlining: false) +!2 = !DIFile(filename: "src/lib.rs/@/3jkrl8oz9knrf4o4", directory: "/home/npopov/repos/test") +!3 = !{} +!4 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !5, producer: "clang LLVM (rustc version 1.70.0-nightly (ec2f40c6b 2023-03-30))", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !6, splitDebugInlining: false) +!5 = !DIFile(filename: "src/lib.rs/@/4r9uiw0o66d13q4b", directory: "/home/npopov/repos/test") +!6 = !{!7} +!7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression()) +!8 = distinct !DIGlobalVariable(name: "<&alloc::vec::Vec as core::fmt::Debug>::{vtable}", scope: null, file: !9, type: !10, isLocal: true, isDefinition: true) +!9 = !DIFile(filename: "", directory: "") +!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "<&alloc::vec::Vec as core::fmt::Debug>::{vtable_type}", file: !9, size: 256, align: 64, flags: DIFlagArtificial, elements: !3, vtableHolder: !11, templateParams: !3, identifier: "8b5b18a5b595fd2726a060be925b88b2") +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&alloc::vec::Vec", baseType: !12, size: 64, align: 64, dwarfAddressSpace: 0) +!12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Vec", scope: !13, file: !9, size: 192, align: 64, elements: !15, templateParams: !3, identifier: "528a0d32ae6e19b7d83105274ce701fc") +!13 = !DINamespace(name: "vec", scope: !14) +!14 = !DINamespace(name: "alloc", scope: null) +!15 = !{!16} +!16 = !DIDerivedType(tag: DW_TAG_member, name: "buf", scope: !12, file: !9, baseType: !17, size: 128, align: 64) +!17 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "RawVec", scope: !18, file: !9, size: 128, align: 64, elements: !3, templateParams: !19, identifier: "67d483d3bf48782733e92e6e5b9d5f14") +!18 = !DINamespace(name: "raw_vec", scope: !14) +!19 = !{!20} +!20 = !DITemplateTypeParameter(name: "A", type: !21) +!21 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Global", scope: !22, file: !9, align: 8, elements: !3, identifier: "8b09da5419eb6d204173b283709c5949") +!22 = !DINamespace(name: "alloc", scope: !14) +!23 = distinct !DISubprogram(name: "alloc_impl", linkageName: "_ZN5alloc5alloc6Global10alloc_impl17h238d0844851c71a5E", scope: !21, file: !24, line: 170, type: !25, scopeLine: 170, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !1, templateParams: !3, retainedNodes: !3) +!24 = !DIFile(filename: "/rustc/ec2f40c6b04f0e9850dd1f454e8639d319f4ed9b/library/alloc/src/alloc.rs", directory: "", checksumkind: CSK_MD5, checksum: "4972b0b4c31877237f60deae5d06e8ce") +!25 = distinct !DISubroutineType(types: !3) +!26 = !DILocalVariable(name: "size", scope: !27, file: !24, line: 174, type: !28, align: 8) +!27 = distinct !DILexicalBlock(scope: !23, file: !24, line: 174, column: 13) +!28 = !DIBasicType(name: "usize", size: 64, encoding: DW_ATE_unsigned) +!29 = !DILocation(line: 174, column: 13, scope: !27) +!30 = !DILocation(line: 172, column: 51, scope: !23) +!31 = !DILocation(line: 175, column: 34, scope: !27) +!32 = !DILocation(line: 175, column: 79, scope: !27) +!33 = distinct !DISubprogram(name: "assert_failed, alloc::vec::Vec>", linkageName: "_ZN4core9panicking13assert_failed17h49f83a394aded8c4E", scope: !35, file: !34, line: 204, type: !37, scopeLine: 204, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !4, templateParams: !3, retainedNodes: !3) +!34 = !DIFile(filename: "/rustc/ec2f40c6b04f0e9850dd1f454e8639d319f4ed9b/library/core/src/panicking.rs", directory: "", checksumkind: CSK_MD5, checksum: "83265ee8d3fb756102ca03de7bd05933") +!35 = !DINamespace(name: "panicking", scope: !36) +!36 = !DINamespace(name: "core", scope: null) +!37 = distinct !DISubroutineType(types: !38) +!38 = !{null} + +; CHECK: DW_TAG_compile_unit +; CHECK: DW_AT_name [DW_FORM_strp] ({{.*}} = "src/lib.rs/@/4r9uiw0o66d13q4b") +; CHECK: DW_AT_low_pc [DW_FORM_addr] ([[LOW_PC_1:0x.*]] ".text") +; CHECK: DW_AT_high_pc [DW_FORM_data4] +; CHECK: DW_TAG_namespace +; CHECK: DW_TAG_namespace +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_low_pc [DW_FORM_addr] ([[LOW_PC_1]] ".text") +; CHECK: NULL +; CHECK: NULL +; CHECK: NULL +; CHECK: DW_TAG_compile_unit +; CHECK: DW_AT_name [DW_FORM_strp] ({{.*}} = "src/lib.rs/@/3jkrl8oz9knrf4o4") +; CHECK: DW_AT_low_pc [DW_FORM_addr] ([[LOW_PC_2:0x.*]] ".text") +; CHECK: DW_AT_high_pc [DW_FORM_data4] +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_low_pc [DW_FORM_addr] ([[LOW_PC_2]] ".text") +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_variable +; CHECK: NULL +; CHECK: NULL +; CHECK: NULL