Skip to content

Commit a179bd4

Browse files
dwblaikiedanakj
andauthored
Start plumbing through debug info type information with function parameters/return value (carbon-language#6410)
This adds just enough debug info for i32/int parameters and return values, with a path forward for adding DWARF type metadata for other types. As it happens, return type information is carried separately from parameter information: * Return type information is carried in the `type` of the `DISubprogram` (as a `DISubroutineType` - which does carry parameter type information as well, but that's unused when the DWARF is emitted by LLVM) * Parameter information is carried by `DILocalVariable`s with a non-zero `arg` value (representing the order of function parameters) In the absence of locations for the parameters (future work), nothing would usually keep the `DILocalVariable` live/reachable when emitting DWARF - so for cases where this can happen (for clang, this happens in optimized builds where all references to the parameter variable might be optimized away) the variables can be "retained" in a list on the `DISubprogram` - achieved by passing `AlwaysPreserve` parameter to `createParameterVariable` (adds them to a list, then that list gets attached to the `DISubprogram` when it's finalized later) For now, any unsupported types are emitted as `void*` (except void return, which is implemented as void) as a placeholder. Given this example: ``` import Core library "io"; class MyClass { } fn Unsupported(v: MyClass) { } fn Ret() -> i32 { return 42; } fn Arg(x: i32) { Core.Print(x); } fn Run() { } ``` this is the resulting DWARF: ``` DW_TAG_compile_unit DW_AT_name ("test.carbon") DW_TAG_subprogram DW_AT_name ("Unsupported") DW_TAG_formal_parameter DW_AT_type (0x00000066 "void *") DW_TAG_subprogram DW_AT_name ("Ret") DW_AT_type (0x00000062 "int") DW_TAG_subprogram DW_AT_name ("Arg") DW_TAG_formal_parameter DW_AT_type (0x00000062 "int") DW_TAG_subprogram DW_AT_name ("Run") DW_TAG_base_type DW_AT_name ("int") DW_TAG_pointer_type ``` And the debugger: ``` (gdb) p Ret() $1 = 42 (gdb) p Arg(4) 4 $2 = void ``` I'm not sure if there's a way this logic should be merged with the logic for making the `llvm::Function` type (which the `DISubroutineType` building code was inspired by/copied from) - since they're done at different times/places, I don't think there's an easy way to do it in one pass, but maybe the code can be shared (even if it's run twice) in some generic `SemIR::Function` type walker. --------- Co-authored-by: Dana Jansens <[email protected]>
1 parent 0baa74d commit a179bd4

File tree

184 files changed

+8027
-5978
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

184 files changed

+8027
-5978
lines changed

toolchain/driver/testdata/compile/optimize/clang_no_optimize_twice.carbon

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ fn Call() -> i32 {
3636
// CHECK:STDOUT: ; Function Attrs: noinline nounwind optnone
3737
// CHECK:STDOUT: define i32 @_CCall.Main() #0 !dbg !7 {
3838
// CHECK:STDOUT: entry:
39-
// CHECK:STDOUT: %g.call = call i32 @_Z1gv(), !dbg !10
40-
// CHECK:STDOUT: ret i32 %g.call, !dbg !11
39+
// CHECK:STDOUT: %g.call = call i32 @_Z1gv(), !dbg !11
40+
// CHECK:STDOUT: ret i32 %g.call, !dbg !12
4141
// CHECK:STDOUT: }
4242
// CHECK:STDOUT:
4343
// CHECK:STDOUT: ; Function Attrs: mustprogress noinline optnone
@@ -69,6 +69,7 @@ fn Call() -> i32 {
6969
// CHECK:STDOUT: !6 = !DIFile(filename: "foo.carbon", directory: "")
7070
// CHECK:STDOUT: !7 = distinct !DISubprogram(name: "Call", linkageName: "_CCall.Main", scope: null, file: !6, line: 12, type: !8, spFlags: DISPFlagDefinition, unit: !5)
7171
// CHECK:STDOUT: !8 = !DISubroutineType(types: !9)
72-
// CHECK:STDOUT: !9 = !{}
73-
// CHECK:STDOUT: !10 = !DILocation(line: 13, column: 10, scope: !7)
74-
// CHECK:STDOUT: !11 = !DILocation(line: 13, column: 3, scope: !7)
72+
// CHECK:STDOUT: !9 = !{!10}
73+
// CHECK:STDOUT: !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
74+
// CHECK:STDOUT: !11 = !DILocation(line: 13, column: 10, scope: !7)
75+
// CHECK:STDOUT: !12 = !DILocation(line: 13, column: 3, scope: !7)

toolchain/driver/testdata/compile/optimize/optimize_debug.carbon

Lines changed: 55 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -43,39 +43,39 @@ fn VectorizedWithOptSpeed(a: array(i32, 65536)*) {
4343
// CHECK:STDOUT: ; Function Attrs: nounwind
4444
// CHECK:STDOUT: define i32 @_CNoInlineWithOz.Main() local_unnamed_addr #0 !dbg !4 {
4545
// CHECK:STDOUT: entry:
46-
// CHECK:STDOUT: %Rand.call.loc7_15 = tail call i32 @_CRand.Main() #0, !dbg !7
47-
// CHECK:STDOUT: %Rand.call.loc7_24 = tail call i32 @_CRand.Main() #0, !dbg !8
48-
// CHECK:STDOUT: %Int.as.AddWith.impl.Op.call = add i32 %Rand.call.loc7_24, %Rand.call.loc7_15, !dbg !7
49-
// CHECK:STDOUT: ret i32 %Int.as.AddWith.impl.Op.call, !dbg !9
46+
// CHECK:STDOUT: %Rand.call.loc7_15 = tail call i32 @_CRand.Main() #0, !dbg !8
47+
// CHECK:STDOUT: %Rand.call.loc7_24 = tail call i32 @_CRand.Main() #0, !dbg !9
48+
// CHECK:STDOUT: %Int.as.AddWith.impl.Op.call = add i32 %Rand.call.loc7_24, %Rand.call.loc7_15, !dbg !8
49+
// CHECK:STDOUT: ret i32 %Int.as.AddWith.impl.Op.call, !dbg !10
5050
// CHECK:STDOUT: }
5151
// CHECK:STDOUT:
5252
// CHECK:STDOUT: ; Function Attrs: nounwind
53-
// CHECK:STDOUT: define i32 @_CCallNoInlineWithOptSize.Main() local_unnamed_addr #0 !dbg !10 {
53+
// CHECK:STDOUT: define i32 @_CCallNoInlineWithOptSize.Main() local_unnamed_addr #0 !dbg !11 {
5454
// CHECK:STDOUT: entry:
55-
// CHECK:STDOUT: %Rand.call.loc7_15.i = tail call i32 @_CRand.Main() #0, !dbg !11
56-
// CHECK:STDOUT: %Rand.call.loc7_24.i = tail call i32 @_CRand.Main() #0, !dbg !13
57-
// CHECK:STDOUT: %Int.as.AddWith.impl.Op.call.i = add i32 %Rand.call.loc7_24.i, %Rand.call.loc7_15.i, !dbg !11
58-
// CHECK:STDOUT: ret i32 %Int.as.AddWith.impl.Op.call.i, !dbg !14
55+
// CHECK:STDOUT: %Rand.call.loc7_15.i = tail call i32 @_CRand.Main() #0, !dbg !12
56+
// CHECK:STDOUT: %Rand.call.loc7_24.i = tail call i32 @_CRand.Main() #0, !dbg !14
57+
// CHECK:STDOUT: %Int.as.AddWith.impl.Op.call.i = add i32 %Rand.call.loc7_24.i, %Rand.call.loc7_15.i, !dbg !12
58+
// CHECK:STDOUT: ret i32 %Int.as.AddWith.impl.Op.call.i, !dbg !15
5959
// CHECK:STDOUT: }
6060
// CHECK:STDOUT:
6161
// CHECK:STDOUT: ; Function Attrs: nofree norecurse nosync nounwind memory(argmem: readwrite)
62-
// CHECK:STDOUT: define void @_CVectorizedWithOptSpeed.Main(ptr captures(none) %a) local_unnamed_addr #1 !dbg !15 {
62+
// CHECK:STDOUT: define void @_CVectorizedWithOptSpeed.Main(ptr captures(none) %a) local_unnamed_addr #1 !dbg !16 {
6363
// CHECK:STDOUT: entry:
64-
// CHECK:STDOUT: br label %while.body, !dbg !16
64+
// CHECK:STDOUT: br label %while.body, !dbg !22
6565
// CHECK:STDOUT:
6666
// CHECK:STDOUT: while.body: ; preds = %entry, %while.body
6767
// CHECK:STDOUT: %n.var.03 = phi i32 [ 0, %entry ], [ %1, %while.body ]
68-
// CHECK:STDOUT: %0 = zext nneg i32 %n.var.03 to i64, !dbg !17
69-
// CHECK:STDOUT: %.loc19_11.array.index = getelementptr inbounds nuw i32, ptr %a, i64 %0, !dbg !17
70-
// CHECK:STDOUT: %Int.as.MulAssignWith.impl.Op.call = load i32, ptr %.loc19_11.array.index, align 4, !dbg !17
71-
// CHECK:STDOUT: %Int.as.MulAssignWith.impl.Op.call1 = shl i32 %Int.as.MulAssignWith.impl.Op.call, 1, !dbg !17
72-
// CHECK:STDOUT: store i32 %Int.as.MulAssignWith.impl.Op.call1, ptr %.loc19_11.array.index, align 4, !dbg !17
73-
// CHECK:STDOUT: %1 = add nuw nsw i32 %n.var.03, 1, !dbg !18
74-
// CHECK:STDOUT: %Int.as.OrderedWith.impl.Less.call = icmp samesign ult i32 %n.var.03, 65535, !dbg !24
75-
// CHECK:STDOUT: br i1 %Int.as.OrderedWith.impl.Less.call, label %while.body, label %while.done, !dbg !16
68+
// CHECK:STDOUT: %0 = zext nneg i32 %n.var.03 to i64, !dbg !23
69+
// CHECK:STDOUT: %.loc19_11.array.index = getelementptr inbounds nuw i32, ptr %a, i64 %0, !dbg !23
70+
// CHECK:STDOUT: %Int.as.MulAssignWith.impl.Op.call = load i32, ptr %.loc19_11.array.index, align 4, !dbg !23
71+
// CHECK:STDOUT: %Int.as.MulAssignWith.impl.Op.call1 = shl i32 %Int.as.MulAssignWith.impl.Op.call, 1, !dbg !23
72+
// CHECK:STDOUT: store i32 %Int.as.MulAssignWith.impl.Op.call1, ptr %.loc19_11.array.index, align 4, !dbg !23
73+
// CHECK:STDOUT: %1 = add nuw nsw i32 %n.var.03, 1, !dbg !24
74+
// CHECK:STDOUT: %Int.as.OrderedWith.impl.Less.call = icmp samesign ult i32 %n.var.03, 65535, !dbg !39
75+
// CHECK:STDOUT: br i1 %Int.as.OrderedWith.impl.Less.call, label %while.body, label %while.done, !dbg !22
7676
// CHECK:STDOUT:
7777
// CHECK:STDOUT: while.done: ; preds = %while.body
78-
// CHECK:STDOUT: ret void, !dbg !25
78+
// CHECK:STDOUT: ret void, !dbg !40
7979
// CHECK:STDOUT:
8080
// CHECK:STDOUT: ; uselistorder directives
8181
// CHECK:STDOUT: uselistorder label %while.body, { 1, 0 }
@@ -95,23 +95,38 @@ fn VectorizedWithOptSpeed(a: array(i32, 65536)*) {
9595
// CHECK:STDOUT: !3 = !DIFile(filename: "foo.carbon", directory: "")
9696
// CHECK:STDOUT: !4 = distinct !DISubprogram(name: "NoInlineWithOz", linkageName: "_CNoInlineWithOz.Main", scope: null, file: !3, line: 6, type: !5, spFlags: DISPFlagDefinition, unit: !2)
9797
// CHECK:STDOUT: !5 = !DISubroutineType(types: !6)
98-
// CHECK:STDOUT: !6 = !{}
99-
// CHECK:STDOUT: !7 = !DILocation(line: 7, column: 10, scope: !4)
100-
// CHECK:STDOUT: !8 = !DILocation(line: 7, column: 19, scope: !4)
101-
// CHECK:STDOUT: !9 = !DILocation(line: 7, column: 3, scope: !4)
102-
// CHECK:STDOUT: !10 = distinct !DISubprogram(name: "CallNoInlineWithOptSize", linkageName: "_CCallNoInlineWithOptSize.Main", scope: null, file: !3, line: 10, type: !5, spFlags: DISPFlagDefinition, unit: !2)
103-
// CHECK:STDOUT: !11 = !DILocation(line: 7, column: 10, scope: !4, inlinedAt: !12)
104-
// CHECK:STDOUT: !12 = distinct !DILocation(line: 12, column: 10, scope: !10)
105-
// CHECK:STDOUT: !13 = !DILocation(line: 7, column: 19, scope: !4, inlinedAt: !12)
106-
// CHECK:STDOUT: !14 = !DILocation(line: 12, column: 3, scope: !10)
107-
// CHECK:STDOUT: !15 = distinct !DISubprogram(name: "VectorizedWithOptSpeed", linkageName: "_CVectorizedWithOptSpeed.Main", scope: null, file: !3, line: 15, type: !5, spFlags: DISPFlagDefinition, unit: !2)
108-
// CHECK:STDOUT: !16 = !DILocation(line: 18, column: 9, scope: !15)
109-
// CHECK:STDOUT: !17 = !DILocation(line: 19, column: 5, scope: !15)
110-
// CHECK:STDOUT: !18 = !DILocation(line: 275, column: 3, scope: !19, inlinedAt: !21)
111-
// CHECK:STDOUT: !19 = distinct !DISubprogram(name: "Op", linkageName: "_COp:thunk.Int.Core:AddAssignWith.Core.5dfb78ae56583d8e", scope: null, file: !20, line: 275, type: !5, spFlags: DISPFlagDefinition, unit: !2)
112-
// CHECK:STDOUT: !20 = !DIFile(filename: "{{.*}}/prelude/types/int.carbon", directory: "")
113-
// CHECK:STDOUT: !21 = distinct !DILocation(line: 341, column: 5, scope: !22, inlinedAt: !23)
114-
// CHECK:STDOUT: !22 = distinct !DISubprogram(name: "Op", linkageName: "_COp.Int.Core:Inc.Core.be1e879c1ad406d8", scope: null, file: !20, line: 339, type: !5, spFlags: DISPFlagDefinition, unit: !2)
115-
// CHECK:STDOUT: !23 = distinct !DILocation(line: 20, column: 5, scope: !15)
116-
// CHECK:STDOUT: !24 = !DILocation(line: 18, column: 10, scope: !15)
117-
// CHECK:STDOUT: !25 = !DILocation(line: 15, column: 1, scope: !15)
98+
// CHECK:STDOUT: !6 = !{!7}
99+
// CHECK:STDOUT: !7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
100+
// CHECK:STDOUT: !8 = !DILocation(line: 7, column: 10, scope: !4)
101+
// CHECK:STDOUT: !9 = !DILocation(line: 7, column: 19, scope: !4)
102+
// CHECK:STDOUT: !10 = !DILocation(line: 7, column: 3, scope: !4)
103+
// CHECK:STDOUT: !11 = distinct !DISubprogram(name: "CallNoInlineWithOptSize", linkageName: "_CCallNoInlineWithOptSize.Main", scope: null, file: !3, line: 10, type: !5, spFlags: DISPFlagDefinition, unit: !2)
104+
// CHECK:STDOUT: !12 = !DILocation(line: 7, column: 10, scope: !4, inlinedAt: !13)
105+
// CHECK:STDOUT: !13 = distinct !DILocation(line: 12, column: 10, scope: !11)
106+
// CHECK:STDOUT: !14 = !DILocation(line: 7, column: 19, scope: !4, inlinedAt: !13)
107+
// CHECK:STDOUT: !15 = !DILocation(line: 12, column: 3, scope: !11)
108+
// CHECK:STDOUT: !16 = distinct !DISubprogram(name: "VectorizedWithOptSpeed", linkageName: "_CVectorizedWithOptSpeed.Main", scope: null, file: !3, line: 15, type: !17, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !20)
109+
// CHECK:STDOUT: !17 = !DISubroutineType(types: !18)
110+
// CHECK:STDOUT: !18 = !{null, !19}
111+
// CHECK:STDOUT: !19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 8)
112+
// CHECK:STDOUT: !20 = !{!21}
113+
// CHECK:STDOUT: !21 = !DILocalVariable(arg: 1, scope: !16, type: !19)
114+
// CHECK:STDOUT: !22 = !DILocation(line: 18, column: 9, scope: !16)
115+
// CHECK:STDOUT: !23 = !DILocation(line: 19, column: 5, scope: !16)
116+
// CHECK:STDOUT: !24 = !DILocation(line: 275, column: 3, scope: !25, inlinedAt: !32)
117+
// CHECK:STDOUT: !25 = distinct !DISubprogram(name: "Op", linkageName: "_COp:thunk.Int.Core:AddAssignWith.Core.5dfb78ae56583d8e", scope: null, file: !26, line: 275, type: !27, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !29)
118+
// CHECK:STDOUT: !26 = !DIFile(filename: "{{.*}}/prelude/types/int.carbon", directory: "")
119+
// CHECK:STDOUT: !27 = !DISubroutineType(types: !28)
120+
// CHECK:STDOUT: !28 = !{null, !7, !7}
121+
// CHECK:STDOUT: !29 = !{!30, !31}
122+
// CHECK:STDOUT: !30 = !DILocalVariable(arg: 1, scope: !25, type: !7)
123+
// CHECK:STDOUT: !31 = !DILocalVariable(arg: 2, scope: !25, type: !7)
124+
// CHECK:STDOUT: !32 = distinct !DILocation(line: 341, column: 5, scope: !33, inlinedAt: !38)
125+
// CHECK:STDOUT: !33 = distinct !DISubprogram(name: "Op", linkageName: "_COp.Int.Core:Inc.Core.be1e879c1ad406d8", scope: null, file: !26, line: 339, type: !34, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !36)
126+
// CHECK:STDOUT: !34 = !DISubroutineType(types: !35)
127+
// CHECK:STDOUT: !35 = !{null, !7}
128+
// CHECK:STDOUT: !36 = !{!37}
129+
// CHECK:STDOUT: !37 = !DILocalVariable(arg: 1, scope: !33, type: !7)
130+
// CHECK:STDOUT: !38 = distinct !DILocation(line: 20, column: 5, scope: !16)
131+
// CHECK:STDOUT: !39 = !DILocation(line: 18, column: 10, scope: !16)
132+
// CHECK:STDOUT: !40 = !DILocation(line: 15, column: 1, scope: !16)

0 commit comments

Comments
 (0)