Skip to content

Commit 9c978c9

Browse files
authored
[coroutines] Use DILocation from new storage for hoisted dbg.declare (#75402)
Make the hoisted dbg.declare inherent the DILocation scope from the new storage. After hoisting, the dbg.declare is moved into the block that defines the new storage. This could create an inconsistency in the debug location scope hierarchy where the scope of hoisted dbg.declare (i.e. DILexicalBlock) is enclosed with the scope of the block (i.e. DISubprogram). This confuses LiveDebugValues pass to think that the hoisted dbg.declare is killed in that block and does not generate DBG_VALUE in other blocks. Debugger won't be able to track its value anymore. We do this for unoptimized binary only.
1 parent bf684a9 commit 9c978c9

File tree

3 files changed

+84
-15
lines changed

3 files changed

+84
-15
lines changed

llvm/lib/Transforms/Coroutines/CoroFrame.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2951,9 +2951,11 @@ void coro::salvageDebugInfo(
29512951
// dbg.declare does.
29522952
if (isa<DbgDeclareInst>(DVI)) {
29532953
std::optional<BasicBlock::iterator> InsertPt;
2954-
if (auto *I = dyn_cast<Instruction>(Storage))
2954+
if (auto *I = dyn_cast<Instruction>(Storage)) {
29552955
InsertPt = I->getInsertionPointAfterDef();
2956-
else if (isa<Argument>(Storage))
2956+
if (!OptimizeFrame && I->getDebugLoc())
2957+
DVI.setDebugLoc(I->getDebugLoc());
2958+
} else if (isa<Argument>(Storage))
29572959
InsertPt = F->getEntryBlock().begin();
29582960
if (InsertPt)
29592961
DVI.moveBefore(*(*InsertPt)->getParent(), *InsertPt);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
; RUN: opt < %s -passes='module(coro-early),cgscc(inline,coro-split<reuse-storage>)' -S | FileCheck %s
2+
; RUN: opt --try-experimental-debuginfo-iterators < %s -passes='module(coro-early),cgscc(inline,coro-split<reuse-storage>)' -S | FileCheck %s
3+
4+
; Simplified version from pr#75104.
5+
; Make sure we do not update debug location for hosited dbg.declare intrinsics when optimizing coro frame.
6+
7+
; CHECK-NOT: mismatched subprogram between llvm.dbg.declare variable and !dbg attachment
8+
9+
%"struct.std::coroutine_handle" = type { i8 }
10+
11+
define void @_Z1fv() presplitcoroutine {
12+
entry:
13+
%0 = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
14+
%1 = call ptr @llvm.coro.begin(token %0, ptr null), !dbg !10
15+
br label %for.cond
16+
17+
for.cond: ; preds = %for.cond, %entry
18+
call void @_ZN1BD1Ev()
19+
%2 = call token @llvm.coro.save(ptr null)
20+
%3 = call i8 @llvm.coro.suspend(token none, i1 false)
21+
br label %for.cond
22+
}
23+
24+
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)
25+
declare ptr @llvm.coro.begin(token, ptr writeonly)
26+
declare void @llvm.dbg.declare(metadata, metadata, metadata)
27+
declare token @llvm.coro.save(ptr)
28+
declare i8 @llvm.coro.suspend(token, i1)
29+
30+
define void @_ZN1BD1Ev() {
31+
entry:
32+
%b11 = alloca [0 x [0 x %"struct.std::coroutine_handle"]], i32 0, align 1
33+
call void @llvm.dbg.declare(metadata ptr %b11, metadata !13, metadata !DIExpression()), !dbg !21
34+
%call = call i1 @_ZNSt16coroutine_handleIvEcvbEv(ptr %b11), !dbg !21
35+
ret void
36+
}
37+
38+
declare i1 @_ZNSt16coroutine_handleIvEcvbEv(ptr)
39+
40+
!llvm.dbg.cu = !{!0}
41+
!llvm.module.flags = !{!9}
42+
43+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 18.0.0git", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !2, splitDebugInlining: false, nameTableKind: None)
44+
!1 = !DIFile(filename: "<stdin>", directory: "")
45+
!2 = !{!3}
46+
!3 = !DIGlobalVariableExpression(var: !4, expr: !DIExpression())
47+
!4 = distinct !DIGlobalVariable(name: "a", scope: !0, file: !5, line: 17, type: !6, isLocal: false, isDefinition: true)
48+
!5 = !DIFile(filename: "bad.cpp", directory: "")
49+
!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "coroutine_handle<void>", scope: !7, file: !5, line: 2, size: 8, flags: DIFlagTypePassByValue, elements: !8, templateParams: !8, identifier: "_ZTSSt16coroutine_handleIvE")
50+
!7 = !DINamespace(name: "std", scope: null)
51+
!8 = !{}
52+
!9 = !{i32 2, !"Debug Info Version", i32 3}
53+
!10 = !DILocation(line: 31, column: 7, scope: !11)
54+
!11 = distinct !DISubprogram(name: "f", linkageName: "_Z1fv", scope: !5, file: !5, line: 31, type: !12, scopeLine: 31, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
55+
!12 = distinct !DISubroutineType(types: !8)
56+
!13 = !DILocalVariable(name: "b", scope: !14, file: !5, line: 27, type: !6)
57+
!14 = distinct !DILexicalBlock(scope: !15, file: !5, line: 27, column: 14)
58+
!15 = distinct !DILexicalBlock(scope: !16, file: !5, line: 26, column: 8)
59+
!16 = distinct !DISubprogram(name: "~B", linkageName: "_ZN1BD2Ev", scope: !17, file: !5, line: 26, type: !18, scopeLine: 26, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, declaration: !20, retainedNodes: !8)
60+
!17 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "B", file: !5, line: 18, size: 8, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !8, identifier: "_ZTS1B")
61+
!18 = !DISubroutineType(types: !19)
62+
!19 = !{null}
63+
!20 = !DISubprogram(name: "~B", scope: !17, file: !5, line: 26, type: !18, scopeLine: 26, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
64+
!21 = !DILocation(line: 27, column: 14, scope: !14)

llvm/test/Transforms/Coroutines/coro-debug-frame-variable.ll

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
; CHECK: entry:
3333
; CHECK: %j = alloca i32, align 4
3434
; CHECK: call void @llvm.dbg.declare(metadata ptr %j, metadata ![[JVAR:[0-9]+]], metadata !DIExpression()), !dbg ![[JDBGLOC:[0-9]+]]
35-
; CHECK: %[[MEMORY:.*]] = call ptr @new
36-
; CHECK: call void @llvm.dbg.declare(metadata ptr %[[MEMORY]], metadata ![[XVAR:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 32)), !dbg ![[IDBGLOC:[0-9]+]]
35+
; CHECK: %[[MEMORY:.*]] = call ptr @new({{.+}}), !dbg ![[IDBGLOC:[0-9]+]]
36+
; CHECK: call void @llvm.dbg.declare(metadata ptr %[[MEMORY]], metadata ![[XVAR:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 32)), !dbg ![[IDBGLOC]]
3737
; CHECK: call void @llvm.dbg.declare(metadata ptr %[[MEMORY]], metadata ![[IVAR:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 20)), !dbg ![[IDBGLOC]]
3838
; CHECK: await.ready:
3939
;
@@ -49,18 +49,20 @@
4949
; CHECK: await.ready:
5050
;
5151
; CHECK-DAG: ![[IVAR]] = !DILocalVariable(name: "i"
52-
; CHECK-DAG: ![[SCOPE:[0-9]+]] = distinct !DILexicalBlock(scope: !6, file: !1, line: 23, column: 12)
53-
; CHECK-DAG: ![[IDBGLOC]] = !DILocation(line: 24, column: 7, scope: ![[SCOPE]])
52+
; CHECK-DAG: ![[PROG_SCOPE:[0-9]+]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov"
53+
; CHECK-DAG: ![[BLK_SCOPE:[0-9]+]] = distinct !DILexicalBlock(scope: ![[PROG_SCOPE]], file: !1, line: 23, column: 12)
54+
; CHECK-DAG: ![[IDBGLOC]] = !DILocation(line: 23, column: 6, scope: ![[PROG_SCOPE]])
5455
; CHECK-DAG: ![[XVAR]] = !DILocalVariable(name: "x"
5556
; CHECK-DAG: ![[JVAR]] = !DILocalVariable(name: "j"
56-
; CHECK-DAG: ![[JDBGLOC]] = !DILocation(line: 32, column: 7, scope: ![[SCOPE]])
57+
; CHECK-DAG: ![[JDBGLOC]] = !DILocation(line: 32, column: 7, scope: ![[BLK_SCOPE]])
5758

5859
; CHECK-DAG: ![[XVAR_RESUME]] = !DILocalVariable(name: "x"
59-
; CHECK-DAG: ![[IDBGLOC_RESUME]] = !DILocation(line: 24, column: 7, scope: ![[RESUME_SCOPE:[0-9]+]])
60-
; CHECK-DAG: ![[RESUME_SCOPE]] = distinct !DILexicalBlock(scope: !22, file: !1, line: 23, column: 12)
60+
; CHECK-DAG: ![[RESUME_PROG_SCOPE:[0-9]+]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov"
61+
; CHECK-DAG: ![[IDBGLOC_RESUME]] = !DILocation(line: 24, column: 7, scope: ![[RESUME_BLK_SCOPE:[0-9]+]])
62+
; CHECK-DAG: ![[RESUME_BLK_SCOPE]] = distinct !DILexicalBlock(scope: ![[RESUME_PROG_SCOPE]], file: !1, line: 23, column: 12)
6163
; CHECK-DAG: ![[IVAR_RESUME]] = !DILocalVariable(name: "i"
6264
; CHECK-DAG: ![[JVAR_RESUME]] = !DILocalVariable(name: "j"
63-
; CHECK-DAG: ![[JDBGLOC_RESUME]] = !DILocation(line: 32, column: 7, scope: ![[RESUME_SCOPE]])
65+
; CHECK-DAG: ![[JDBGLOC_RESUME]] = !DILocation(line: 32, column: 7, scope: ![[RESUME_BLK_SCOPE]])
6466
define void @f() presplitcoroutine !dbg !8 {
6567
entry:
6668
%__promise = alloca i8, align 8
@@ -72,13 +74,13 @@ entry:
7274
br i1 %alloc, label %coro.alloc, label %coro.init
7375

7476
coro.alloc: ; preds = %entry
75-
%size = call i64 @llvm.coro.size.i64()
76-
%memory = call ptr @new(i64 %size)
77-
br label %coro.init
77+
%size = call i64 @llvm.coro.size.i64(), !dbg !23
78+
%memory = call ptr @new(i64 %size), !dbg !23
79+
br label %coro.init, !dbg !23
7880

7981
coro.init: ; preds = %coro.alloc, %entry
80-
%phi.entry.alloc = phi ptr [ null, %entry ], [ %memory, %coro.alloc ]
81-
%begin = call ptr @llvm.coro.begin(token %id, ptr %phi.entry.alloc)
82+
%phi.entry.alloc = phi ptr [ null, %entry ], [ %memory, %coro.alloc ], !dbg !23
83+
%begin = call ptr @llvm.coro.begin(token %id, ptr %phi.entry.alloc), !dbg !23
8284
%ready = call i1 @await_ready()
8385
br i1 %ready, label %init.ready, label %init.suspend
8486

@@ -240,3 +242,4 @@ declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg)
240242
!20 = !DILocation(line: 43, column: 3, scope: !7)
241243
!21 = !DILocation(line: 43, column: 8, scope: !7)
242244
!22 = distinct !DILexicalBlock(scope: !8, file: !1, line: 23, column: 12)
245+
!23 = !DILocation(line: 23, column: 6, scope: !8)

0 commit comments

Comments
 (0)