Closed
Description
When the following IR is compiled with llc -O1 -trap-unreachable
, an incorrect line number is generated in the debuginfo for the call to panic_test2::do_panic
:
IR
source_filename = "panic_test2.6f3b49f66efc8fc7-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"
@alloc_14c43fe6be9850e9c6ac099b83b2e4e2 = private unnamed_addr constant <{ [7 x i8] }> <{ [7 x i8] c"unknown" }>, align 1
@alloc_1a2b9f3efbe1a8edd339fa75af2334ed = private unnamed_addr constant <{ [5 x i8] }> <{ [5 x i8] c"hello" }>, align 1
; Function Attrs: inlinehint noreturn nounwind nonlazybind
define fastcc void @bad_debug_info(ptr noalias nocapture noundef readonly align 8 dereferenceable(16) %_1) unnamed_addr #4 !dbg !85 {
start:
%_11 = alloca { ptr, i64 }, align 8
%_7 = alloca { ptr, i64 }, align 8
%0 = getelementptr inbounds { ptr, i64 }, ptr %_1, i64 0, i32 1, !dbg !87
%_13.1 = load i64, ptr %0, align 8, !dbg !87, !noundef !14
; call panic_test2::condition
%1 = tail call fastcc ptr @_ZN11panic_test29condition17haa518b986e55a3c9E(i64 noundef %_13.1) #9, !dbg !89
%.not = icmp eq ptr %1, null, !dbg !90
br i1 %.not, label %bb3, label %bb2, !dbg !90
bb2: ; preds = %start
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %_7), !dbg !91
store ptr %1, ptr %_7, align 8, !dbg !91
%2 = getelementptr inbounds { ptr, i64 }, ptr %_7, i64 0, i32 1, !dbg !91
store i64 5, ptr %2, align 8, !dbg !91
; call panic_test2::do_panic
call fastcc void @_ZN11panic_test28do_panic17h2c0ead66774c0583E(ptr noalias noundef nonnull readonly align 8 dereferenceable(16) %_7) #10, !dbg !92
unreachable, !dbg !92
bb3: ; preds = %start
call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %_11), !dbg !93
store ptr @alloc_14c43fe6be9850e9c6ac099b83b2e4e2, ptr %_11, align 8, !dbg !93
%3 = getelementptr inbounds { ptr, i64 }, ptr %_11, i64 0, i32 1, !dbg !93
store i64 7, ptr %3, align 8, !dbg !93
; call panic_test2::do_panic
call fastcc void @_ZN11panic_test28do_panic17h2c0ead66774c0583E(ptr noalias noundef nonnull readonly align 8 dereferenceable(16) %_11) #10, !dbg !94
unreachable, !dbg !94
}
; panic_test2::condition
; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind nonlazybind willreturn memory(none)
define internal fastcc ptr @_ZN11panic_test29condition17haa518b986e55a3c9E(i64 noundef %s.1) unnamed_addr #6 {
start:
%0 = icmp eq i64 %s.1, 0
%alloc_1a2b9f3efbe1a8edd339fa75af2334ed. = select i1 %0, ptr @alloc_1a2b9f3efbe1a8edd339fa75af2334ed, ptr null
ret ptr %alloc_1a2b9f3efbe1a8edd339fa75af2334ed.
}
; panic_test2::do_panic
; Function Attrs: noreturn nounwind nonlazybind
define internal fastcc void @_ZN11panic_test28do_panic17h2c0ead66774c0583E(ptr noalias noundef readonly align 8 dereferenceable(16) %h) unnamed_addr #5 {
start:
unreachable
}
; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #8
attributes #1 = { nounwind nonlazybind "probe-stack"="inline-asm" "target-cpu"="x86-64" }
attributes #5 = { noreturn nounwind nonlazybind "probe-stack"="inline-asm" "target-cpu"="x86-64" }
attributes #6 = { mustprogress nofree noinline norecurse nosync nounwind nonlazybind willreturn memory(none) "probe-stack"="inline-asm" "target-cpu"="x86-64" }
attributes #8 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
attributes #9 = { nounwind }
attributes #10 = { noreturn nounwind }
!llvm.module.flags = !{!3, !4}
!llvm.ident = !{!5}
!llvm.dbg.cu = !{!6}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{!"rustc version 1.73.0-beta.4 (9f37cd4f7 2023-09-01)"}
!6 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !7, producer: "clang LLVM (rustc version 1.73.0-beta.4 (9f37cd4f7 2023-09-01))", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false)
!7 = !DIFile(filename: "src/main.rs/@/panic_test2.6f3b49f66efc8fc7-cgu.0", directory: "/tmp/panic_test")
!13 = !DISubroutineType(types: !14)
!14 = !{}
!80 = !DIFile(filename: "src/main.rs", directory: "/tmp/panic_test", checksumkind: CSK_MD5, checksum: "7cd0751a66038391ee52be036e31f480")
!81 = !DINamespace(name: "panic_test2", scope: null)
!85 = distinct !DISubprogram(name: "bad_debug_info", linkageName: "bad_debug_info", scope: !86, file: !80, line: 14, type: !13, scopeLine: 14, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !6, templateParams: !14)
!86 = !DINamespace(name: "never_returns", scope: !81)
!87 = !DILocation(line: 15, column: 36, scope: !88)
!88 = distinct !DILexicalBlock(scope: !85, file: !80, line: 15, column: 39)
!89 = !DILocation(line: 15, column: 26, scope: !88)
!90 = !DILocation(line: 15, column: 16, scope: !88)
!91 = !DILocation(line: 16, column: 23, scope: !88)
!92 = !DILocation(line: 16, column: 13, scope: !88)
!93 = !DILocation(line: 18, column: 23, scope: !85)
!94 = !DILocation(line: 18, column: 13, scope: !85)
Notice that in the source IR, both calls to do_panic
have the correct line numbers:
...
bb2: ; preds = %start
...
; call panic_test2::do_panic
call fastcc void @_ZN11panic_test28do_panic17h2c0ead66774c0583E(ptr noalias noundef nonnull readonly align 8 dereferenceable(16) %_7) #10, !dbg !92
...
bb3: ; preds = %start
...
; call panic_test2::do_panic
call fastcc void @_ZN11panic_test28do_panic17h2c0ead66774c0583E(ptr noalias noundef nonnull readonly align 8 dereferenceable(16) %_11) #10, !dbg !94
...
!85 = distinct !DISubprogram(name: "bad_debug_info", linkageName: "bad_debug_info", scope: !86, file: !80, line: 14, type: !13, scopeLine: 14, flags: DIFlagPrototyped | DIFlagNoReturn, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !6, templateParams: !14)
!88 = distinct !DILexicalBlock(scope: !85, file: !80, line: 15, column: 39)
!92 = !DILocation(line: 16, column: 13, scope: !88)
!94 = !DILocation(line: 18, column: 13, scope: !85)
However, when lowering to machine code, these line numbers are erased and replaced with line 0:
...
.loc 1 0 23 is_stmt 0 # src/main.rs:0:23
leaq 8(%rsp), %rdi
callq panic_test2::do_panic::h2c0ead66774c0583
ud2
...
Looking at the optimization passes in godbolt, it seems that the "Control Flow Optimizer (branch-folder)" pass is responsible for merging the calls together and removing the correct line numbers.