Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DW_TAG_formal_parameter always has DW_AT_decl_line == 1 #45010

Open
cuviper opened this issue Oct 3, 2017 · 3 comments
Open

DW_TAG_formal_parameter always has DW_AT_decl_line == 1 #45010

cuviper opened this issue Oct 3, 2017 · 3 comments
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) C-bug Category: This is a bug. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@cuviper
Copy link
Member

cuviper commented Oct 3, 2017

It seems that Rust debuginfo always writes decl_line of 1 for formal parameters.

With this line.rs:

#![crate_type = "dylib"] // line 1
pub fn foo( // 2
    x: i32, // 3
    y: i32) // 4
    -> i32  // 5
{ x + y }   // 6

With:

$ rustc +nightly -Vv
rustc 1.22.0-nightly (185cc5f26 2017-10-02)
binary: rustc
commit-hash: 185cc5f26d2c8a794189b028b43f6a3b8fc586db
commit-date: 2017-10-02
host: x86_64-unknown-linux-gnu
release: 1.22.0-nightly
LLVM version: 4.0

I get this output:

$ rustc +nightly -g line.rs
$ dwgrep 'entry ?(@AT_name == "foo") child*' libline.so
[2f]    subprogram
        low_pc  0x42100
        high_pc 66
        frame_base      0..0xffffffffffffffff:0 reg6
        linkage_name    "_ZN4line3fooE"
        name    "foo"
        decl_file       "/tmp/line.rs"
        decl_line       2
        type    [8c] base_type
        external        true
[4c]    formal_parameter
        location        0..0xffffffffffffffff:0 fbreg <-16>
        name    "x"
        decl_file       "/tmp/line.rs"
        decl_line       1
        type    [8c] base_type
[5a]    formal_parameter
        location        0..0xffffffffffffffff:0 fbreg <-12>
        name    "y"
        decl_file       "/tmp/line.rs"
        decl_line       1
        type    [8c] base_type
[68]    lexical_block
        ranges  0x4210e..0x4212a, 0x4213a..0x42142
[6d]    variable
        location        0..0xffffffffffffffff:0 fbreg <-8>
        name    "x"
        decl_file       "/tmp/line.rs"
        decl_line       3
        type    [8c] base_type
[7b]    variable
        location        0..0xffffffffffffffff:0 fbreg <-4>
        name    "y"
        decl_file       "/tmp/line.rs"
        decl_line       4
        type    [8c] base_type

So it describes the formal parameters of x and y both with line 1, but also describes local variables with the correct lines 3 and 4.

In LLVM IR it looks like this, with the wrong lines in !10 and !13:

$ rustc +nightly -g line.rs --emit=llvm-ir
$ sed -n '/DIComp/,$p' line.ll
!0 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !1, producer: "clang LLVM (rustc version 1.22.0-nightly (185cc5f26 2017-10-02))", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "line.rs", directory: "/tmp")
!2 = !{}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = distinct !DISubprogram(name: "foo", linkageName: "_ZN4line3fooE", scope: !5, file: !1, line: 2, type: !7, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, templateParams: !2, variables: !2)
!5 = !DINamespace(name: "line", scope: null, file: !6)
!6 = !DIFile(filename: "<unknown>", directory: "")
!7 = !DISubroutineType(types: !8)
!8 = !{!9, !9, !9}
!9 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed)
!10 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !1, line: 1, type: !9)
!11 = !DIExpression()
!12 = !DILocation(line: 1, scope: !4)
!13 = !DILocalVariable(name: "y", arg: 2, scope: !4, file: !1, line: 1, type: !9)
!14 = !DILocalVariable(name: "x", scope: !15, file: !1, line: 3, type: !9, align: 4)
!15 = distinct !DILexicalBlock(scope: !4, file: !1, line: 6)
!16 = !DILocation(line: 3, scope: !15)
!17 = !DILocalVariable(name: "y", scope: !15, file: !1, line: 4, type: !9, align: 4)
!18 = !DILocation(line: 4, scope: !15)
!19 = !DILocation(line: 6, scope: !15)
!20 = !DILocation(line: 6, scope: !4)
@cuviper
Copy link
Member Author

cuviper commented Oct 3, 2017

Historically, 1.11.0 looked more like I would expect, with the right line numbers on the formal parameters and no extra local variables.

$ rustc +1.11.0 -g line.rs --emit=llvm-ir && sed -n '/DIComp/,$p' line.ll
!0 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !1, producer: "rustc version 1.11.0 (9b21dcd6a 2016-08-15)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, subprograms: !3)
!1 = !DIFile(filename: "./line.rs", directory: "/tmp")
!2 = !{}
!3 = !{!4}
!4 = distinct !DISubprogram(name: "foo", linkageName: "_ZN4line3fooE", scope: !6, file: !5, line: 2, type: !7, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, templateParams: !2, variables: !2)
!5 = !DIFile(filename: "/tmp/line.rs", directory: "/tmp")
!6 = !DINamespace(name: "line", scope: null)
!7 = !DISubroutineType(types: !8)
!8 = !{!9, !9, !9}
!9 = !DIBasicType(name: "i32", size: 32, align: 32, encoding: DW_ATE_signed)
!10 = !{i32 2, !"Debug Info Version", i32 3}
!11 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !5, line: 3, type: !9)
!12 = !DIExpression()
!13 = !DILocation(line: 3, scope: !4)
!14 = !DILocalVariable(name: "y", arg: 2, scope: !4, file: !5, line: 4, type: !9)
!15 = !DILocation(line: 4, scope: !4)
!16 = !DILocation(line: 6, scope: !17)
!17 = distinct !DILexicalBlock(scope: !4, file: !5, line: 6)
!18 = !DILocation(line: 6, scope: !4)

In 1.12.0, it added the extra locals, and the formal parameters took on line 2 like the subprogram.

$ rustc +1.12.0 -g line.rs --emit=llvm-ir && sed -n '/DIComp/,$p' line.ll
!0 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !1, producer: "rustc version 1.12.0 (3191fbae9 2016-09-23)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "./line.rs", directory: "/tmp")
!2 = !{}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = distinct !DISubprogram(name: "foo", linkageName: "_ZN4line3fooE", scope: !6, file: !5, line: 2, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, templateParams: !2, variables: !2)
!5 = !DIFile(filename: "/tmp/line.rs", directory: "/tmp")
!6 = !DINamespace(name: "line", scope: null, file: !7)
!7 = !DIFile(filename: "<unknown>", directory: "")
!8 = !DISubroutineType(types: !9)
!9 = !{!10, !10, !10}
!10 = !DIBasicType(name: "i32", size: 32, align: 32, encoding: DW_ATE_signed)
!11 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !5, line: 2, type: !10)
!12 = !DIExpression()
!13 = !DILocation(line: 2, scope: !4)
!14 = !DILocalVariable(name: "y", arg: 2, scope: !4, file: !5, line: 2, type: !10)
!15 = !DILocalVariable(name: "x", scope: !16, file: !5, line: 3, type: !10)
!16 = distinct !DILexicalBlock(scope: !4, file: !5, line: 6)
!17 = !DILocation(line: 3, scope: !16)
!18 = !DILocalVariable(name: "y", scope: !16, file: !5, line: 4, type: !10)
!19 = !DILocation(line: 4, scope: !16)
!20 = !DILocation(line: 3, scope: !4)
!21 = !DILocation(line: 4, scope: !4)
!22 = !DILocation(line: 6, scope: !16)
!23 = !DILocation(line: 2, scope: !16)

Then 1.13.0 shows the line 1 behavior like the current nightly.

$ rustc +1.13.0 -g line.rs --emit=llvm-ir && sed -n '/DIComp/,$p' line.ll
!0 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !1, producer: "rustc version 1.13.0 (2c6933acc 2016-11-07)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "./line.rs", directory: "/tmp")
!2 = !{}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = distinct !DISubprogram(name: "foo", linkageName: "_ZN4line3fooE", scope: !6, file: !5, line: 2, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, templateParams: !2, variables: !2)
!5 = !DIFile(filename: "/tmp/line.rs", directory: "/tmp")
!6 = !DINamespace(name: "line", scope: null, file: !7)
!7 = !DIFile(filename: "<unknown>", directory: "")
!8 = !DISubroutineType(types: !9)
!9 = !{!10, !10, !10}
!10 = !DIBasicType(name: "i32", size: 32, align: 32, encoding: DW_ATE_signed)
!11 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !5, line: 1, type: !10)
!12 = !DIExpression()
!13 = !DILocation(line: 1, scope: !4)
!14 = !DILocalVariable(name: "y", arg: 2, scope: !4, file: !5, line: 1, type: !10)
!15 = !DILocalVariable(name: "x", scope: !16, file: !5, line: 3, type: !10)
!16 = distinct !DILexicalBlock(scope: !4, file: !5, line: 6)
!17 = !DILocation(line: 3, scope: !16)
!18 = !DILocalVariable(name: "y", scope: !16, file: !5, line: 4, type: !10)
!19 = !DILocation(line: 4, scope: !16)
!20 = !DILocation(line: 3, scope: !4)
!21 = !DILocation(line: 4, scope: !4)
!22 = !DILocation(line: 6, scope: !16)
!23 = !DILocation(line: 2, scope: !16)

@cuviper
Copy link
Member Author

cuviper commented Nov 8, 2017

With the latest nightly, it no longer has the extra local declarations (perhaps thanks to #44573), but the formal-parameter line numbers are still just 1.

$ rustc +nightly -Vv
rustc 1.23.0-nightly (ee2286149 2017-11-07)
binary: rustc
commit-hash: ee2286149a5f0b148334841d4f067dc819dcca3b
commit-date: 2017-11-07
host: x86_64-unknown-linux-gnu
release: 1.23.0-nightly
LLVM version: 4.0
$ rustc +nightly -g line.rs --emit=llvm-ir
$ sed -n '/DIComp/,$p' line.ll
!0 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !1, producer: "clang LLVM (rustc version 1.23.0-nightly (ee2286149 2017-11-07))", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "line.rs", directory: "/tmp")
!2 = !{}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = distinct !DISubprogram(name: "foo", linkageName: "_ZN4line3fooE", scope: !5, file: !1, line: 2, type: !7, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, templateParams: !2, variables: !2)
!5 = !DINamespace(name: "line", scope: null, file: !6)
!6 = !DIFile(filename: "<unknown>", directory: "")
!7 = !DISubroutineType(types: !8)
!8 = !{!9, !9, !9}
!9 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed)
!10 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !1, line: 1, type: !9)
!11 = !DIExpression()
!12 = !DILocation(line: 1, scope: !4)
!13 = !DILocalVariable(name: "y", arg: 2, scope: !4, file: !1, line: 1, type: !9)
!14 = !DILocation(line: 6, scope: !4)
$ rustc +nightly -g line.rs
$ dwgrep 'entry ?(@AT_name == "foo") child*' libline.so
[2f]    subprogram
        low_pc  0x42570
        high_pc 54
        frame_base      0..0xffffffffffffffff:0 reg6
        linkage_name    "_ZN4line3fooE"
        name    "foo"
        decl_file       "/tmp/line.rs"
        decl_line       2
        type    [6a] base_type
        external        true
[4c]    formal_parameter
        location        0..0xffffffffffffffff:0 fbreg <-8>
        name    "x"
        decl_file       "/tmp/line.rs"
        decl_line       1
        type    [6a] base_type
[5a]    formal_parameter
        location        0..0xffffffffffffffff:0 fbreg <-4>
        name    "y"
        decl_file       "/tmp/line.rs"
        decl_line       1
        type    [6a] base_type

@XAMPPRocky XAMPPRocky added A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-bug Category: This is a bug. labels Jan 22, 2018
@wesleywiser
Copy link
Member

This was fixed in Rust 1.40 (godbolt). wg-debugging would like to see a codegen test added to prevent regressions and then this can be closed.

@wesleywiser wesleywiser added the E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. label Jul 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) C-bug Category: This is a bug. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants