Skip to content

Commit a33812b

Browse files
authored
fix: Debug locations of CASE statement (#1315)
Fixes the debug locations line number, where previously the `switch ...` instruction would have a line number of the last case element.
1 parent 90e6e9c commit a33812b

File tree

3 files changed

+166
-11
lines changed

3 files changed

+166
-11
lines changed

src/codegen/generators/statement_generator.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,6 @@ impl<'a, 'b> StatementCodeGenerator<'a, 'b> {
484484

485485
let basic_block = builder.get_insert_block().expect(INTERNAL_LLVM_ERROR);
486486
let exp_gen = self.create_expr_generator();
487-
self.register_debug_location(selector);
488487
let selector_statement = exp_gen.generate_expression(selector)?;
489488

490489
let mut cases = Vec::new();
@@ -530,6 +529,8 @@ impl<'a, 'b> StatementCodeGenerator<'a, 'b> {
530529

531530
// now that we collected all cases, go back to the initial block and generate the switch-statement
532531
builder.position_at_end(basic_block);
532+
533+
self.register_debug_location(selector);
533534
builder.build_switch(selector_statement.into_int_value(), else_block, &cases);
534535

535536
builder.position_at_end(continue_block);

src/codegen/tests/debug_tests.rs

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,157 @@ fn test_dwarf_version_override() {
186186

187187
assert_snapshot!(codegen)
188188
}
189+
190+
#[test]
191+
fn switch_case_debug_info() {
192+
let codegen = codegen_with_debug_version(
193+
r#"
194+
FUNCTION main : DINT
195+
VAR
196+
x1 : INT;
197+
x2 : INT;
198+
x3 : INT;
199+
END_VAR
200+
201+
WHILE TRUE DO
202+
x1 := x1 + 1;
203+
204+
CASE x1 OF
205+
1: x2 := 1;
206+
2: x2 := 2;
207+
3: x2 := 3;
208+
ELSE
209+
x1 := 0;
210+
x2 := 1;
211+
x3 := 2;
212+
END_CASE
213+
214+
END_WHILE
215+
216+
END_FUNCTION
217+
"#,
218+
4,
219+
);
220+
221+
assert_snapshot!(codegen, @r###"
222+
; ModuleID = '<internal>'
223+
source_filename = "<internal>"
224+
225+
define i32 @main() section "fn-$RUSTY$main:i32" !dbg !4 {
226+
entry:
227+
%main = alloca i32, align 4, !dbg !9
228+
%x1 = alloca i16, align 2, !dbg !9
229+
%x2 = alloca i16, align 2, !dbg !9
230+
%x3 = alloca i16, align 2, !dbg !9
231+
call void @llvm.dbg.declare(metadata i16* %x1, metadata !10, metadata !DIExpression()), !dbg !12
232+
store i16 0, i16* %x1, align 2, !dbg !9
233+
call void @llvm.dbg.declare(metadata i16* %x2, metadata !13, metadata !DIExpression()), !dbg !14
234+
store i16 0, i16* %x2, align 2, !dbg !9
235+
call void @llvm.dbg.declare(metadata i16* %x3, metadata !15, metadata !DIExpression()), !dbg !16
236+
store i16 0, i16* %x3, align 2, !dbg !9
237+
call void @llvm.dbg.declare(metadata i32* %main, metadata !17, metadata !DIExpression()), !dbg !19
238+
store i32 0, i32* %main, align 4, !dbg !9
239+
br label %condition_check, !dbg !20
240+
241+
condition_check: ; preds = %entry, %continue1
242+
br i1 true, label %while_body, label %continue, !dbg !21
243+
244+
while_body: ; preds = %condition_check
245+
%load_x1 = load i16, i16* %x1, align 2, !dbg !22
246+
%0 = sext i16 %load_x1 to i32, !dbg !22
247+
%tmpVar = add i32 %0, 1, !dbg !22
248+
%1 = trunc i32 %tmpVar to i16, !dbg !22
249+
store i16 %1, i16* %x1, align 2, !dbg !22
250+
%load_x12 = load i16, i16* %x1, align 2, !dbg !22
251+
switch i16 %load_x12, label %else [
252+
i16 1, label %case
253+
i16 2, label %case3
254+
i16 3, label %case4
255+
], !dbg !20
256+
257+
continue: ; preds = %condition_check
258+
%main_ret = load i32, i32* %main, align 4, !dbg !20
259+
ret i32 %main_ret, !dbg !20
260+
261+
case: ; preds = %while_body
262+
store i16 1, i16* %x2, align 2, !dbg !23
263+
br label %continue1, !dbg !23
264+
265+
case3: ; preds = %while_body
266+
store i16 2, i16* %x2, align 2, !dbg !24
267+
br label %continue1, !dbg !24
268+
269+
case4: ; preds = %while_body
270+
store i16 3, i16* %x2, align 2, !dbg !25
271+
br label %continue1, !dbg !25
272+
273+
else: ; preds = %while_body
274+
store i16 0, i16* %x1, align 2, !dbg !26
275+
store i16 1, i16* %x2, align 2, !dbg !27
276+
store i16 2, i16* %x3, align 2, !dbg !28
277+
br label %continue1, !dbg !28
278+
279+
continue1: ; preds = %else, %case4, %case3, %case
280+
br label %condition_check, !dbg !20
281+
}
282+
283+
; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
284+
declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
285+
286+
attributes #0 = { nofree nosync nounwind readnone speculatable willreturn }
287+
288+
!llvm.module.flags = !{!0, !1}
289+
!llvm.dbg.cu = !{!2}
290+
291+
!0 = !{i32 2, !"Dwarf Version", i32 4}
292+
!1 = !{i32 2, !"Debug Info Version", i32 3}
293+
!2 = distinct !DICompileUnit(language: DW_LANG_C, file: !3, producer: "RuSTy Structured text Compiler", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false)
294+
!3 = !DIFile(filename: "<internal>", directory: "src")
295+
!4 = distinct !DISubprogram(name: "main", linkageName: "main", scope: !5, file: !5, line: 2, type: !6, scopeLine: 9, flags: DIFlagPublic, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !8)
296+
!5 = !DIFile(filename: "<internal>", directory: "")
297+
!6 = !DISubroutineType(flags: DIFlagPublic, types: !7)
298+
!7 = !{null}
299+
!8 = !{}
300+
!9 = !DILocation(line: 9, column: 12, scope: !4)
301+
!10 = !DILocalVariable(name: "x1", scope: !4, file: !5, line: 4, type: !11, align: 16)
302+
!11 = !DIBasicType(name: "INT", size: 16, encoding: DW_ATE_signed, flags: DIFlagPublic)
303+
!12 = !DILocation(line: 4, column: 16, scope: !4)
304+
!13 = !DILocalVariable(name: "x2", scope: !4, file: !5, line: 5, type: !11, align: 16)
305+
!14 = !DILocation(line: 5, column: 16, scope: !4)
306+
!15 = !DILocalVariable(name: "x3", scope: !4, file: !5, line: 6, type: !11, align: 16)
307+
!16 = !DILocation(line: 6, column: 16, scope: !4)
308+
!17 = !DILocalVariable(name: "main", scope: !4, file: !5, line: 2, type: !18, align: 32)
309+
!18 = !DIBasicType(name: "DINT", size: 32, encoding: DW_ATE_signed, flags: DIFlagPublic)
310+
!19 = !DILocation(line: 2, column: 17, scope: !4)
311+
!20 = !DILocation(line: 12, column: 17, scope: !4)
312+
!21 = !DILocation(line: 9, column: 18, scope: !4)
313+
!22 = !DILocation(line: 10, column: 12, scope: !4)
314+
!23 = !DILocation(line: 13, column: 19, scope: !4)
315+
!24 = !DILocation(line: 14, column: 19, scope: !4)
316+
!25 = !DILocation(line: 15, column: 19, scope: !4)
317+
!26 = !DILocation(line: 17, column: 20, scope: !4)
318+
!27 = !DILocation(line: 18, column: 20, scope: !4)
319+
!28 = !DILocation(line: 19, column: 20, scope: !4)
320+
; ModuleID = '__init___testproject'
321+
source_filename = "__init___testproject"
322+
323+
define void @__init___testproject() section "fn-$RUSTY$__init___testproject:v" !dbg !4 {
324+
entry:
325+
ret void, !dbg !9
326+
}
327+
328+
!llvm.module.flags = !{!0, !1}
329+
!llvm.dbg.cu = !{!2}
330+
331+
!0 = !{i32 2, !"Dwarf Version", i32 4}
332+
!1 = !{i32 2, !"Debug Info Version", i32 3}
333+
!2 = distinct !DICompileUnit(language: DW_LANG_C, file: !3, producer: "RuSTy Structured text Compiler", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false)
334+
!3 = !DIFile(filename: "__init___testproject", directory: "src")
335+
!4 = distinct !DISubprogram(name: "__init___testproject", linkageName: "__init___testproject", scope: !5, file: !5, type: !6, scopeLine: 1, flags: DIFlagPublic, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !8)
336+
!5 = !DIFile(filename: "<internal>", directory: "")
337+
!6 = !DISubroutineType(flags: DIFlagPublic, types: !7)
338+
!7 = !{null}
339+
!8 = !{}
340+
!9 = !DILocation(line: 0, scope: !4)
341+
"###);
342+
}

src/codegen/tests/debug_tests/snapshots/rusty__codegen__tests__debug_tests__expression_debugging__case_conditions_location_marked.snap

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,24 @@ entry:
1010
%myFunc = alloca i32, align 4, !dbg !9
1111
call void @llvm.dbg.declare(metadata i32* %myFunc, metadata !10, metadata !DIExpression()), !dbg !12
1212
store i32 0, i32* %myFunc, align 4, !dbg !9
13-
%load_myFunc = load i32, i32* %myFunc, align 4, !dbg !13
13+
%load_myFunc = load i32, i32* %myFunc, align 4, !dbg !9
1414
switch i32 %load_myFunc, label %else [
1515
i32 1, label %case
1616
i32 2, label %case1
17-
], !dbg !14
17+
], !dbg !13
1818

1919
case: ; preds = %entry
20+
store i32 1, i32* %myFunc, align 4, !dbg !14
21+
br label %continue, !dbg !14
22+
23+
case1: ; preds = %entry
2024
store i32 1, i32* %myFunc, align 4, !dbg !15
2125
br label %continue, !dbg !15
2226

23-
case1: ; preds = %entry
27+
else: ; preds = %entry
2428
store i32 1, i32* %myFunc, align 4, !dbg !16
2529
br label %continue, !dbg !16
2630

27-
else: ; preds = %entry
28-
store i32 1, i32* %myFunc, align 4, !dbg !14
29-
br label %continue, !dbg !14
30-
3131
continue: ; preds = %else, %case1, %case
3232
store i32 1, i32* %myFunc, align 4, !dbg !17
3333
%myFunc_ret = load i32, i32* %myFunc, align 4, !dbg !17
@@ -56,9 +56,9 @@ attributes #0 = { nofree nosync nounwind readnone speculatable willreturn }
5656
!11 = !DIBasicType(name: "DINT", size: 32, encoding: DW_ATE_signed, flags: DIFlagPublic)
5757
!12 = !DILocation(line: 2, column: 17, scope: !4)
5858
!13 = !DILocation(line: 3, column: 17, scope: !4)
59-
!14 = !DILocation(line: 9, column: 16, scope: !4)
60-
!15 = !DILocation(line: 5, column: 16, scope: !4)
61-
!16 = !DILocation(line: 7, column: 16, scope: !4)
59+
!14 = !DILocation(line: 5, column: 16, scope: !4)
60+
!15 = !DILocation(line: 7, column: 16, scope: !4)
61+
!16 = !DILocation(line: 9, column: 16, scope: !4)
6262
!17 = !DILocation(line: 11, column: 12, scope: !4)
6363
; ModuleID = '__init___testproject'
6464
source_filename = "__init___testproject"

0 commit comments

Comments
 (0)