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 @@ -458,15 +458,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. @@ -500,9 +491,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) { SmallVector BB_List; + DIE *SPDie = getOrCreateSubprogramDIE(SP, includeMinimalInlineScopes()); // If basic block sections are on, ranges for each basic block section has // to be emitted separately. for (const auto &R : Asm->MBBSectionRanges) @@ -1055,7 +1049,6 @@ DIE &DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope) { DIE &ScopeDIE = updateSubprogramScopeDIE(Sub); - auto *ContextCU = static_cast(ScopeDIE.getUnit()); if (Scope) { assert(!Scope->getInlinedAt()); @@ -1063,10 +1056,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/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -1397,6 +1397,11 @@ CheckDI(N.isDistinct(), "subprogram definitions must be distinct", &N); CheckDI(Unit, "subprogram definitions must have a compile unit", &N); CheckDI(isa(Unit), "invalid unit type", &N, Unit); + if (isa_and_present(N.getRawScope())) + CheckDI(!M.getContext().isODRUniquingDebugTypes() || N.getDeclaration(), + "definition subprograms cannot be nested within DICompositeType " + "when enabling ODR", + &N); if (N.getFile()) verifySourceDebugInfo(*N.getUnit(), *N.getFile()); } else { 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 @@ -21,19 +21,22 @@ !2 = !{} !3 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !4, isOptimized: true, runtimeVersion: 5, emissionKind: FullDebug, imports: !2) !4 = !DIFile(filename: "B.swift", directory: "") +!5 = !DISubprogram(name: "foo", scope: !25, file: !1, line: 116, type: !27, scopeLine: 116, flags: DIFlagPrototyped, spFlags: 0) +!6 = !DISubprogram(name: "init", scope: !31, file: !30, type: !27, flags: DIFlagPrototyped, spFlags: 0) +!7 = !DISubprogram(name: "bar", scope: !31, file: !4, line: 21, type: !27, scopeLine: 21, flags: DIFlagPrototyped, spFlags: 0) !10 = !{i32 7, !"Dwarf Version", i32 4} !11 = !{i32 2, !"Debug Info Version", i32 3} -!24 = distinct !DISubprogram(name: "foo", scope: !25, file: !1, line: 116, type: !27, scopeLine: 116, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!24 = distinct !DISubprogram(name: "foo", scope: !25, file: !1, line: 116, type: !27, scopeLine: 116, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2, declaration: !5) !25 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "FooTy", scope: !26, file: !1, size: 64, elements: !2) !26 = !DIModule(scope: null, name: "Mod") !27 = !DISubroutineType(types: !2) !28 = !DILocation(line: 0, scope: !29, inlinedAt: !32) -!29 = distinct !DISubprogram(name: "init", scope: !31, file: !30, type: !27, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!29 = distinct !DISubprogram(name: "init", scope: !31, file: !30, type: !27, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2, declaration: !6) !30 = !DIFile(filename: "", directory: "") !31 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "ModController", scope: !26, file: !4, size: 64, elements: !2, runtimeLang: DW_LANG_Swift) !32 = !DILocation(line: 117, column: 29, scope: !33) !33 = distinct !DILexicalBlock(scope: !24, file: !1, line: 116, column: 68) -!34 = distinct !DISubprogram(name: "bar", scope: !31, file: !4, line: 21, type: !27, scopeLine: 21, unit: !3, retainedNodes: !2) +!34 = distinct !DISubprogram(name: "bar", scope: !31, file: !4, line: 21, type: !27, scopeLine: 21, unit: !3, retainedNodes: !2, declaration: !7) !35 = !DILocation(line: 0, scope: !36, inlinedAt: !37) !36 = distinct !DISubprogram(name: "goo", scope: !26, file: !30, type: !27, unit: !3, retainedNodes: !2) !37 = !DILocation(line: 21, column: 26, scope: !34) @@ -41,26 +44,39 @@ ; CHECK: DW_TAG_compile_unit ; CHECK: DW_TAG_module ; 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; DW_AT_name [DW_FORM_strp] ({{.*}} = "init") +; CHECK: DW_AT_declaration [DW_FORM_flag_present] (true) +; CHECK: 0x[[BAR_REF_ADDR:.*]]: DW_TAG_subprogram +; CHECK: DW_AT_name [DW_FORM_strp] ({{.*}} = "bar") +; CHECK: DW_AT_declaration [DW_FORM_flag_present] (true) ; CHECK: NULL ; CHECK: DW_TAG_structure_type ; CHECK: DW_TAG_subprogram ; CHECK; DW_AT_name [DW_FORM_strp] ({{.*}} = "foo") -; CHECK: DW_TAG_inlined_subroutine -; CHECK: DW_AT_abstract_origin [DW_FORM_ref4] ({{.*}} => {[[INIT]]} "init") -; CHECK: NULL +; CHECK: DW_AT_declaration [DW_FORM_flag_present] (true) ; CHECK: NULL ; CHECK: NULL +; 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] ({{.*}} = "foo") +; CHECK: DW_TAG_inlined_subroutine +; CHECK: DW_AT_abstract_origin [DW_FORM_ref4] ({{.*}} => {[[INIT]]} "init") +; CHECK: NULL ; CHECK: NULL ; CHECK: DW_TAG_compile_unit +; CHECK: DW_AT_low_pc [DW_FORM_addr] ([[LOW_PC:0x.*]] ".text") +; CHECK: DW_AT_high_pc [DW_FORM_data4] ([[HIGH_PC:0x.*]]) ; CHECK: DW_TAG_module -; CHECK: 0x[[GOO]]: DW_TAG_subprogram -; CHECK; DW_AT_name [DW_FORM_strp] ({{.*}} = "goo") +; CHECK: [[GOO:0x.*]]: DW_TAG_subprogram +; CHECK: DW_AT_name [DW_FORM_strp] ({{.*}} = "goo") +; CHECK: NULL +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_specification [DW_FORM_ref_addr] (0x00000000[[BAR_REF_ADDR]] "bar") +; CHECK: DW_TAG_inlined_subroutine +; CHECK: DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x{{.*}} => {[[GOO]]} "goo") +; CHECK: DW_AT_low_pc [DW_FORM_addr] ([[LOW_PC]] ".text") +; CHECK: DW_AT_high_pc [DW_FORM_data4] ([[HIGH_PC]]) ; CHECK: NULL ; CHECK: NULL diff --git a/llvm/test/DebugInfo/Generic/cross-cu-inlining-ranges.ll b/llvm/test/DebugInfo/Generic/cross-cu-inlining-ranges.ll --- a/llvm/test/DebugInfo/Generic/cross-cu-inlining-ranges.ll +++ b/llvm/test/DebugInfo/Generic/cross-cu-inlining-ranges.ll @@ -47,15 +47,18 @@ !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) +!10 = distinct !DISubprogram(name: "init", scope: !12, file: !11, type: !7, spFlags: DISPFlagDefinition, unit: !0, declaration: !22) !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) +!15 = distinct !DISubprogram(name: "bar", scope: !12, type: !7, spFlags: DISPFlagDefinition, unit: !2, declaration: !23) !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) +!18 = distinct !DISubprogram(name: "inlined_baz", scope: !12, file: !3, type: !7, spFlags: DISPFlagDefinition, unit: !2, declaration: !24) !19 = !DILocation(line: 0, scope: !20) !20 = distinct !DILexicalBlock(scope: !15, file: !3) !21 = !DILocation(line: 0, scope: !15) +!22 = !DISubprogram(name: "init", scope: !12, file: !11, type: !7, flags: DIFlagPrototyped, spFlags: 0) +!23 = !DISubprogram(name: "bar", scope: !12, type: !7, flags: DIFlagPrototyped, spFlags: 0) +!24 = !DISubprogram(name: "inlined_baz", scope: !12, file: !3, type: !7, flags: DIFlagPrototyped, spFlags: 0) diff --git a/llvm/test/Verifier/disubprogram-declaration-within-struct.ll b/llvm/test/Verifier/disubprogram-declaration-within-struct.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/disubprogram-declaration-within-struct.ll @@ -0,0 +1,47 @@ +; RUN: opt -passes=verify -disable-output < %s 2>&1 | FileCheck %s +; RUN: opt -passes=verify -S --disable-debug-info-type-map < %s | FileCheck --check-prefix=CHECK-NOT-ODR %s + +; The Rust source: +; pub struct Foo; +; impl Foo { +; pub fn bar() {} +; } + +; ModuleID = 'foo.7e668e4a-cgu.0' +source_filename = "foo.7e668e4a-cgu.0" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; foo::Foo::bar +; Function Attrs: nonlazybind uwtable +define void @_ZN3foo3Foo3bar17h32d65c44145019c8E() unnamed_addr #0 !dbg !6 { +start: + ret void, !dbg !14 +} + +attributes #0 = { nonlazybind uwtable "probe-stack"="__rust_probestack" "target-cpu"="x86-64" } + +!llvm.module.flags = !{!0, !1, !2, !3} +!llvm.dbg.cu = !{!4} + +!0 = !{i32 7, !"PIC Level", i32 2} +!1 = !{i32 2, !"RtLibUseGOT", i32 1} +!2 = !{i32 2, !"Dwarf Version", i32 4} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !5, producer: "clang LLVM (rustc version 1.69.0 (84c898d65 2023-04-16))", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false) +!5 = !DIFile(filename: "foo.rs/@/foo.7e668e4a-cgu.0", directory: "/tmp") +!6 = distinct !DISubprogram(name: "bar", linkageName: "_ZN3foo3Foo3bar17h32d65c44145019c8E", scope: !8, file: !7, line: 4, type: !12, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !4, templateParams: !11, retainedNodes: !11) +!7 = !DIFile(filename: "foo.rs", directory: "/tmp", checksumkind: CSK_MD5, checksum: "427d9b572596c2f310b6185a1781f222") +!8 = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", scope: !10, file: !9, align: 8, elements: !11, identifier: "a8fd67db4e906c9c4aceea39cb8b0f61") +!9 = !DIFile(filename: "", directory: "") +!10 = !DINamespace(name: "foo", scope: null) +!11 = !{} +!12 = !DISubroutineType(types: !13) +!13 = !{null} +!14 = !DILocation(line: 6, column: 6, scope: !6) + +; CHECK: definition subprograms cannot be nested within DICompositeType when enabling ODR +; CHECK: warning: ignoring invalid debug info + +; CHECK-NOT-ODR-NOT: definition subprograms cannot be nested within DICompositeType when enabling ODR +; CHECK-NOT-ODR-NOT: warning: ignoring invalid debug info