xref: /llvm-project/llvm/test/Transforms/Coroutines/swift-async-dbg.ll (revision ddcc601353db0464eb15a3e0258ec6789dd1602c)
1; RUN: opt -mtriple='arm64-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s
2; RUN: opt -mtriple='x86_64' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s
3; RUN: opt -mtriple='i386-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s --check-prefix=NOENTRY
4; RUN: opt -mtriple='armv7-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s --check-prefix=NOENTRY
5
6;; Replicate those tests with non-instruction debug markers.
7; RUN: opt --try-experimental-debuginfo-iterators -mtriple='arm64-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s
8; RUN: opt --try-experimental-debuginfo-iterators -mtriple='x86_64' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s
9; RUN: opt --try-experimental-debuginfo-iterators -mtriple='i386-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s --check-prefix=NOENTRY
10; RUN: opt --try-experimental-debuginfo-iterators -mtriple='armv7-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s --check-prefix=NOENTRY
11
12; NOENTRY-NOT: OP_llvm_entry_value
13
14target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
15
16; This coroutine has one split point and two variables defined by:
17;   %var_with_dbg_value,   which has multiple dbg.value intrinsics associated with
18;                          it, one per split point.
19;   %var_with_dbg_declare, which has a single dbg.declare intrinsic associated
20;                          with it at the coroutine entry.
21; We check that, for each funclet, the debug intrinsics are propagated properly AND that
22; an `entry_value` operation is created.
23define swifttailcc void @coroutineA(ptr swiftasync %arg) !dbg !48 {
24  %var_with_dbg_value = alloca ptr, align 8
25  %var_with_dbg_declare = alloca ptr, align 8
26  call void @llvm.dbg.declare(metadata ptr %var_with_dbg_declare, metadata !500, metadata !DIExpression()), !dbg !54
27  call void @llvm.dbg.value(metadata ptr %var_with_dbg_value, metadata !50, metadata !DIExpression(DW_OP_deref)), !dbg !54
28  %i2 = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr nonnull @coroutineATu)
29  %i3 = call ptr @llvm.coro.begin(token %i2, ptr null)
30; CHECK-LABEL: define {{.*}} @coroutineA(
31; CHECK-SAME:    ptr swiftasync %[[frame_ptr:.*]])
32; CHECK:      #dbg_declare(ptr %[[frame_ptr]], {{.*}} !DIExpression(
33; CHECK-SAME:                   DW_OP_plus_uconst, 24)
34; CHECK:      #dbg_value(ptr %[[frame_ptr]], {{.*}} !DIExpression(
35; CHECK-SAME:                 DW_OP_plus_uconst, 16, DW_OP_deref)
36; CHECK:      call {{.*}} @swift_task_switch
37
38  %i7 = call ptr @llvm.coro.async.resume(), !dbg !54
39  %i10 = call { ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0s(i32 0, ptr %i7, ptr nonnull @__swift_async_resume_get_context, ptr nonnull @coroutineA.1, ptr %i7, i64 0, i64 0, ptr %arg), !dbg !54
40  %i11 = extractvalue { ptr } %i10, 0, !dbg !55
41  %i12 = call ptr @__swift_async_resume_get_context(ptr %i11), !dbg !55
42  call void @dont_optimize(ptr %var_with_dbg_value, ptr %var_with_dbg_declare), !dbg !100
43  call void @llvm.dbg.value(metadata ptr %var_with_dbg_value, metadata !50, metadata !DIExpression(DW_OP_deref)), !dbg !54
44  %i17 = load i32, ptr getelementptr inbounds (<{i32, i32}>, ptr @coroutineBTu, i64 0, i32 1), align 8, !dbg !54
45  call void @llvm.dbg.value(metadata !DIArgList(ptr %var_with_dbg_value, i32 %i17), metadata !501, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_deref)), !dbg !54
46  %i18 = zext i32 %i17 to i64, !dbg !54
47  %i19 = call swiftcc ptr @swift_task_alloc(i64 %i18), !dbg !54
48; CHECK-NOT: define
49; CHECK-LABEL: define {{.*}} @coroutineATY0_(
50; CHECK-SAME:    ptr swiftasync %[[frame_ptr:.*]]) !dbg ![[ATY0:[0-9]*]]
51; CHECK:      #dbg_declare(ptr %[[frame_ptr]], {{.*}} !DIExpression(
52; CHECK-SAME:                   DW_OP_LLVM_entry_value, 1, DW_OP_plus_uconst, 24)
53; CHECK:      #dbg_value(ptr %[[frame_ptr]], {{.*}} !DIExpression(
54; CHECK-SAME:                 DW_OP_LLVM_entry_value, 1, DW_OP_plus_uconst, 16, DW_OP_deref)
55; CHECK:      #dbg_value(!DIArgList(ptr %[[frame_ptr]], i32 %{{.*}}), {{.*}} !DIExpression(
56; CHECK-SAME:                 DW_OP_LLVM_arg, 0, DW_OP_plus_uconst, 16, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_deref)
57; CHECK:      call {{.*}} @coroutineB
58
59  %i23 = call ptr @llvm.coro.async.resume(), !dbg !54
60  %i25 = getelementptr inbounds <{ ptr, ptr }>, ptr %i19, i64 0, i32 1, !dbg !54
61  store ptr %i23, ptr %i25, align 8, !dbg !54
62  %i27 = call { ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0s(i32 0, ptr %i23, ptr nonnull @__swift_async_resume_project_context, ptr nonnull @coroutineA.0, ptr nonnull @coroutineB, ptr nonnull %i19), !dbg !54
63  %i28 = extractvalue { ptr } %i27, 0, !dbg !54
64  %i29 = call ptr @__swift_async_resume_project_context(ptr %i28), !dbg !54
65  call swiftcc void @swift_task_dealloc(ptr nonnull %i19), !dbg !54
66  call void @dont_optimize(ptr %var_with_dbg_value, ptr %var_with_dbg_declare)
67  call void @llvm.dbg.value(metadata ptr %var_with_dbg_value, metadata !50, metadata !DIExpression(DW_OP_deref)), !dbg !54
68; CHECK-NOT: define
69; CHECK-LABEL: define {{.*}} @coroutineATQ1_(
70; CHECK-SAME:    ptr swiftasync %[[frame_ptr:.*]])
71; Note the extra level of indirection that shows up here!
72; CHECK:      #dbg_declare(ptr %[[frame_ptr]], {{.*}} !DIExpression(
73; CHECK-SAME:                   DW_OP_LLVM_entry_value, 1, DW_OP_deref, DW_OP_plus_uconst, 24)
74; CHECK:      #dbg_value(ptr %[[frame_ptr]], {{.*}} !DIExpression(
75; CHECK-SAME:                 DW_OP_LLVM_entry_value, 1, DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_deref)
76; CHECK:      call {{.*}} @swift_task_switch
77
78  %i31 = call ptr @llvm.coro.async.resume(), !dbg !54
79  %i33 = call { ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0s(i32 0, ptr %i31, ptr nonnull @__swift_async_resume_get_context, ptr nonnull @coroutineA.1, ptr %i31, i64 0, i64 0, ptr %i29), !dbg !54
80  %i34 = extractvalue { ptr } %i33, 0, !dbg !54
81  %i35 = call ptr @__swift_async_resume_get_context(ptr %i34), !dbg !54
82  %i45 = call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %i3, i1 false, ptr nonnull @coroutineA.0.1, ptr undef, ptr undef), !dbg !54
83  unreachable, !dbg !54
84; CHECK-NOT: define
85; CHECK-LABEL: define {{.*}} @coroutineATY2_(
86; CHECK-SAME:    ptr swiftasync %[[frame_ptr:.*]])
87; CHECK:      #dbg_declare(ptr %[[frame_ptr]], {{.*}} !DIExpression(
88; CHECK-SAME:                   DW_OP_LLVM_entry_value, 1, DW_OP_plus_uconst, 24)
89}
90
91; CHECK: ![[ATY0]] = {{.*}}DISubprogram(linkageName: "coroutineATY0_", {{.*}} scopeLine: 42
92
93; Everything from here on is just support code for the coroutines.
94
95@coroutineBTu = global <{i32, i32}> <{ i32 trunc (i64 sub (i64 ptrtoint (ptr @"coroutineB" to i64), i64 ptrtoint (ptr @"coroutineBTu" to i64)) to i32), i32 16 }>, align 8
96@coroutineATu = global <{i32, i32}> <{ i32 trunc (i64 sub (i64 ptrtoint (ptr @"coroutineA" to i64), i64 ptrtoint (ptr @"coroutineATu" to i64)) to i32), i32 16 }>, align 8
97
98define weak_odr hidden ptr @__swift_async_resume_get_context(ptr %arg) !dbg !64 {
99  ret ptr %arg, !dbg !65
100}
101define hidden swifttailcc void @coroutineA.1(ptr %arg, i64 %arg1, i64 %arg2, ptr %arg3) !dbg !66 {
102  musttail call swifttailcc void @swift_task_switch(ptr swiftasync %arg3, ptr %arg, i64 %arg1, i64 %arg2), !dbg !67
103  ret void, !dbg !67
104}
105
106define weak_odr hidden ptr @__swift_async_resume_project_context(ptr %arg) !dbg !68 {
107  %i1 = load ptr, ptr %arg, align 8, !dbg !69
108  %i2 = call ptr @llvm.swift.async.context.addr(), !dbg !69
109  store ptr %i1, ptr %i2, align 8, !dbg !69
110  ret ptr %i1, !dbg !69
111}
112define hidden swifttailcc void @coroutineA.0(ptr %arg, ptr %arg1) !dbg !70 {
113  musttail call swifttailcc void %arg(ptr swiftasync %arg1), !dbg !71
114  ret void, !dbg !71
115}
116define hidden swifttailcc void @coroutineA.0.1(ptr %arg, ptr %arg1) !dbg !72 {
117  musttail call swifttailcc void %arg(ptr swiftasync %arg1), !dbg !73
118  ret void, !dbg !73
119}
120define swifttailcc void @coroutineB(ptr swiftasync %arg) !dbg !37 {
121  %i2 = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr nonnull @coroutineBTu)
122  %i3 = call ptr @llvm.coro.begin(token %i2, ptr null)
123  %i6 = getelementptr inbounds <{ ptr, ptr }>, ptr %arg, i64 0, i32 1, !dbg !42
124  %i712 = load ptr, ptr %i6, align 8, !dbg !42
125  %i10 = call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %i3, i1 false, ptr nonnull @coroutineB.0, ptr %i712, ptr %arg), !dbg !42
126  unreachable, !dbg !42
127}
128define hidden swifttailcc void @coroutineB.0(ptr %arg, ptr %arg1) !dbg !44 {
129  musttail call swifttailcc void %arg(ptr swiftasync %arg1), !dbg !47
130  ret void, !dbg !47
131}
132
133declare i1 @llvm.coro.end.async(ptr, i1, ...)
134declare ptr @llvm.coro.async.resume()
135declare ptr @llvm.coro.begin(token, ptr writeonly)
136declare ptr @llvm.swift.async.context.addr()
137declare swiftcc ptr @swift_task_alloc(i64)
138declare swiftcc void @swift_task_dealloc(ptr)
139declare swifttailcc void @swift_task_switch(ptr, ptr, i64, i64)
140declare token @llvm.coro.id.async(i32, i32, i32, ptr)
141declare void @dont_optimize(ptr, ptr)
142declare void @llvm.dbg.declare(metadata, metadata, metadata)
143declare void @llvm.dbg.value(metadata, metadata, metadata)
144declare { ptr } @llvm.coro.suspend.async.sl_p0s(i32, ptr, ptr, ...)
145
146!llvm.module.flags = !{!6, !7}
147!llvm.dbg.cu = !{!16}
148
149!6 = !{i32 7, !"Dwarf Version", i32 4}
150!7 = !{i32 2, !"Debug Info Version", i32 3}
151
152!50 = !DILocalVariable(name: "k1", scope: !48, file: !17, line: 7, type: !53)
153!500 = !DILocalVariable(name: "k2", scope: !48, file: !17, line: 7, type: !53)
154!501 = !DILocalVariable(name: "k3", scope: !48, file: !17, line: 7, type: !53)
155!49 = !{!50, !500}
156
157!16 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !17, producer: "", emissionKind: FullDebug)
158!17 = !DIFile(filename: "blah", directory: "")
159
160!53 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Klass")
161!46 = !DISubroutineType(types: null)
162
163!64 = distinct !DISubprogram(linkageName: "blah", file: !17, type: !46, unit: !16)
164!68 = distinct !DISubprogram(linkageName: "blah", file: !17, type: !46, unit: !16)
165!66 = distinct !DISubprogram(linkageName: "coroutineA", file: !17, type: !46, unit: !16)
166!70 = distinct !DISubprogram(linkageName: "coroutineA", file: !17, type: !46, unit: !16)
167!72 = distinct !DISubprogram(linkageName: "coroutineA", file: !17, type: !46, unit: !16)
168!48 = distinct !DISubprogram(linkageName: "coroutineA", file: !17, type: !46, unit: !16, retainedNodes: !49)
169!37 = distinct !DISubprogram(linkageName: "coroutineB", file: !17, type: !46, unit: !16)
170!44 = distinct !DISubprogram(linkageName: "coroutineB", file: !17, type: !46, unit: !16)
171!65 = !DILocation(line: 0, scope: !64)
172!67 = !DILocation(line: 0, scope: !66)
173!69 = !DILocation(line: 0, scope: !68)
174!71 = !DILocation(line: 0, scope: !70)
175!73 = !DILocation(line: 0, scope: !72)
176!54 = !DILocation(line: 6, scope: !48)
177!55 = !DILocation(line: 0, scope: !48)
178!42 = !DILocation(line: 3, scope: !37)
179!47 = !DILocation(line: 0, scope: !44)
180!100 = !DILocation(line: 42, scope: !48)
181