Follow up to d0858bffa11, add missing REQUIRES x86
[llvm-project.git] / llvm / test / Transforms / Coroutines / coro-async.ll
blobf796ce3dbb0d827c157913a1bb6ce02e870e1f0c
1 ; RUN: opt < %s -passes='default<O2>' -S | FileCheck --check-prefixes=CHECK %s
2 ; RUN: opt < %s -O0 -S | FileCheck --check-prefixes=CHECK-O0 %s
3 target datalayout = "p:64:64:64"
5 %async.task = type { i64 }
6 %async.actor = type { i64 }
7 %async.fp = type <{ i32, i32 }>
9 %async.ctxt = type { ptr, ptr }
11 ; The async callee.
12 @my_other_async_function_fp = external global <{ i32, i32 }>
13 declare void @my_other_async_function(ptr %async.ctxt)
15 ; The current async function (the caller).
16 ; This struct describes an async function. The first field is the
17 ; relative offset to the async function implementation, the second field is the
18 ; size needed for the async context of the current async function.
20 @my_async_function_fp = constant <{ i32, i32 }>
21   <{ i32 trunc ( ; Relative pointer to async function
22        i64 sub (
23          i64 ptrtoint (ptr @my_async_function to i64),
24          i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_fp, i32 0, i32 1) to i64)
25        )
26      to i32),
27      i32 128    ; Initial async context size without space for frame
29 @my_async_function_pa_fp = constant <{ i32, i32 }>
30   <{ i32 trunc (
31        i64 sub (
32          i64 ptrtoint (ptr @my_async_function_pa to i64),
33          i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_pa_fp, i32 0, i32 1) to i64)
34        )
35      to i32),
36      i32 8
39 ; Function that implements the dispatch to the callee function.
40 define swiftcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) {
41   tail call swiftcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor)
42   ret void
45 declare void @some_user(i64)
46 declare void @some_may_write(ptr)
48 define ptr @__swift_async_resume_project_context(ptr %ctxt) {
49 entry:
50   %resume_ctxt = load ptr, ptr %ctxt, align 8
51   ret ptr %resume_ctxt
54 define ptr @resume_context_projection(ptr %ctxt) {
55 entry:
56   %resume_ctxt = load ptr, ptr %ctxt, align 8
57   ret ptr %resume_ctxt
61 define swiftcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine !dbg !1 {
62 entry:
63   %tmp = alloca { i64, i64 }, align 8
64   %vector = alloca <4 x double>, align 16
65   %proj.1 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 0
66   %proj.2 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 1
68   %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
69           ptr @my_async_function_fp)
70   %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
71   store i64 0, ptr %proj.1, align 8
72   store i64 1, ptr %proj.2, align 8
73   call void @some_may_write(ptr %proj.1)
75         ; Begin lowering: apply %my_other_async_function(%args...)
77   ; setup callee context
78   %callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)
79   ; store arguments ...
80   ; ... (omitted)
82   ; store the return continuation
83   %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1
84   %resume.func_ptr = call ptr @llvm.coro.async.resume()
85   store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr
87   ; store caller context into callee context
88   store ptr %async.ctxt, ptr %callee_context
89   %vector_spill = load <4 x double>, ptr %vector, align 16
90   %res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,
91                                                   ptr %resume.func_ptr,
92                                                   ptr @__swift_async_resume_project_context,
93                                                   ptr @my_async_function.my_other_async_function_fp.apply,
94                                                   ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor), !dbg !5
96   call void @llvm.coro.async.context.dealloc(ptr %callee_context)
97   %continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 1
98   %val = load i64, ptr %proj.1
99   call void @some_user(i64 %val)
100   %val.2 = load i64, ptr %proj.2
101   call void @some_user(i64 %val.2)
102   store <4 x double> %vector_spill, ptr %vector, align 16
103   tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor)
104   call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0)
105   unreachable
108 define void @my_async_function_pa(ptr %ctxt, ptr %task, ptr %actor) {
109   call void @llvm.coro.async.size.replace(ptr @my_async_function_pa_fp, ptr @my_async_function_fp)
110   call swiftcc void @my_async_function(ptr %ctxt, ptr %task, ptr %actor)
111   ret void
114 ; Make sure we update the async function pointer
115 ; CHECK: @my_async_function_fp = constant <{ i32, i32 }> <{ {{.*}}, i32 176 }
116 ; CHECK: @my_async_function_pa_fp = constant <{ i32, i32 }> <{ {{.*}}, i32 176 }
117 ; CHECK: @my_async_function2_fp = constant <{ i32, i32 }> <{ {{.*}}, i32 176 }
119 ; CHECK-LABEL: define swiftcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor)
120 ; CHECK-O0-LABEL: define swiftcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor)
121 ; CHECK-SAME: !dbg ![[SP1:[0-9]+]] {
122 ; CHECK: coro.return:
123 ; CHECK:   [[FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr %async.ctxt, i64 128
124 ; CHECK:   [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr %async.ctxt, i64 152
125 ; CHECK:   store ptr %actor, ptr [[ACTOR_SPILL_ADDR]]
126 ; CHECK:   [[ADDR1:%.*]]  = getelementptr inbounds i8, ptr %async.ctxt, i64 144
127 ; CHECK:   store ptr %async.ctxt, ptr [[ADDR1]]
128 ; CHECK:   [[ALLOCA_PRJ2:%.*]] = getelementptr inbounds i8, ptr %async.ctxt, i64 136
129 ; CHECK:   store i64 0, ptr [[FRAMEPTR]]
130 ; CHECK:   store i64 1, ptr [[ALLOCA_PRJ2]]
131 ; CHECK:   tail call void @some_may_write(ptr nonnull [[FRAMEPTR]])
132 ; CHECK:   [[CALLEE_CTXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr %task, ptr nonnull @my_other_async_function_fp)
133 ; CHECK:   [[CALLEE_CTXT_SPILL:%.*]] = getelementptr inbounds i8, ptr %async.ctxt, i64 160
134 ; CHECK:   store ptr [[CALLEE_CTXT]], ptr [[CALLEE_CTXT_SPILL]]
135 ; CHECK:   [[TYPED_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds %async.ctxt, ptr [[CALLEE_CTXT]], i64 0, i32 1
136 ; CHECK:   store ptr @my_async_functionTQ0_, ptr [[TYPED_RETURN_TO_CALLER_ADDR]]
137 ; CHECK:   store ptr %async.ctxt, ptr [[CALLEE_CTXT]]
138 ; Make sure the spill is underaligned to the max context alignment (16).
139 ; CHECK-O0:   [[VECTOR_SPILL:%.*]] = load <4 x double>, ptr {{.*}}
140 ; CHECK-O0:   [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr {{.*}}, i32 0, i32 1
141 ; CHECK-O0:   store <4 x double> [[VECTOR_SPILL]], ptr [[VECTOR_SPILL_ADDR]], align 16
142 ; CHECK:   tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CTXT]], ptr %task, ptr %actor)
143 ; CHECK:   ret void
144 ; CHECK: }
146 ; CHECK-LABEL: define internal swiftcc void @my_async_functionTQ0_(ptr nocapture readonly swiftasync %0, ptr %1, ptr nocapture readnone %2)
147 ; CHECK-O0-LABEL: define internal swiftcc void @my_async_functionTQ0_(ptr swiftasync %0, ptr %1, ptr %2)
148 ; CHECK-SAME: !dbg ![[SP2:[0-9]+]] {
149 ; CHECK: entryresume.0:
150 ; CHECK:   [[CALLER_CONTEXT:%.*]] = load ptr, ptr %0
151 ; CHECK:   [[FRAME_PTR:%.*]] = getelementptr inbounds i8, ptr [[CALLER_CONTEXT]], i64 128
152 ; CHECK-O0:   [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr {{.*}}, i32 0, i32 1
153 ; CHECK-O0:   load <4 x double>, ptr [[VECTOR_SPILL_ADDR]], align 16
154 ; CHECK:   [[CALLEE_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[CALLER_CONTEXT]], i64 160
155 ; CHECK:   [[CALLEE_CTXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CTXT_SPILL_ADDR]]
156 ; CHECK:   [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[CALLER_CONTEXT]], i64 152
157 ; CHECK:   [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]]
158 ; CHECK:   [[ADDR1:%.*]] = getelementptr inbounds i8, ptr [[CALLER_CONTEXT]], i64 144
159 ; CHECK:   [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ADDR1]]
160 ; CHECK:   [[ALLOCA_PRJ2:%.*]] = getelementptr inbounds i8, ptr [[CALLER_CONTEXT]], i64 136
161 ; CHECK:   tail call void @llvm.coro.async.context.dealloc(ptr nonnull [[CALLEE_CTXT_RELOAD]])
162 ; CHECK:   [[VAL1:%.*]] = load i64, ptr [[FRAME_PTR]]
163 ; CHECK:   tail call void @some_user(i64 [[VAL1]])
164 ; CHECK:   [[VAL2:%.*]] = load i64, ptr [[ALLOCA_PRJ2]]
165 ; CHECK:   tail call void @some_user(i64 [[VAL2]])
166 ; CHECK:   tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr %1, ptr [[ACTOR_RELOAD]])
167 ; CHECK:   ret void
168 ; CHECK: }
170 @my_async_function2_fp = constant <{ i32, i32 }>
171   <{ i32 trunc ( ; Relative pointer to async function
172        i64 sub (
173          i64 ptrtoint (ptr @my_async_function2 to i64),
174          i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function2_fp, i32 0, i32 1) to i64)
175        )
176      to i32),
177      i32 128    ; Initial async context size without space for frame
178   }>
180 define swiftcc void @my_async_function2(ptr %task, ptr %actor, ptr %async.ctxt) presplitcoroutine "frame-pointer"="all" !dbg !6 {
181 entry:
183   %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 2, ptr @my_async_function2_fp)
184   %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
185   ; setup callee context
186   %callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)
188   %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1
189   %resume.func_ptr = call ptr @llvm.coro.async.resume()
190   store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr
191   store ptr %async.ctxt, ptr %callee_context
192   %res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 2,
193                                                   ptr %resume.func_ptr,
194                                                   ptr @resume_context_projection,
195                                                   ptr @my_async_function.my_other_async_function_fp.apply,
196                                                   ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor), !dbg !9
198   %continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 0
200   %callee_context.return_to_caller.addr.1 = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1
201   %resume.func_ptr.1 = call ptr @llvm.coro.async.resume()
202   store ptr %resume.func_ptr.1, ptr %callee_context.return_to_caller.addr.1
203   store ptr %async.ctxt, ptr %callee_context
204   %res.2 = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,
205                                                   ptr %resume.func_ptr.1,
206                                                   ptr @resume_context_projection,
207                                                   ptr @my_async_function.my_other_async_function_fp.apply,
208                                                   ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
210   call void @llvm.coro.async.context.dealloc(ptr %callee_context)
211   %continuation_actor_arg = extractvalue {ptr, ptr, ptr} %res.2, 1
213   tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %continuation_actor_arg)
214   call i1 @llvm.coro.end(ptr %hdl, i1 0, token none)
215   unreachable
218 ; CHECK-LABEL: define swiftcc void @my_async_function2(ptr %task, ptr %actor, ptr %async.ctxt)
219 ; CHECK-SAME: #[[FRAMEPOINTER:[0-9]+]]
220 ; CHECK-SAME: !dbg ![[SP3:[0-9]+]]
221 ; CHECK: store ptr %async.ctxt,
222 ; CHECK: store ptr %actor,
223 ; CHECK: store ptr %task,
224 ; CHECK: [[CALLEE_CTXT:%.*]] =  tail call ptr @llvm.coro.async.context.alloc(
225 ; CHECK: store ptr [[CALLEE_CTXT]],
226 ; CHECK: store ptr @my_async_function2.resume.0,
227 ; CHECK: store ptr %async.ctxt,
228 ; CHECK: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CTXT]], ptr %task, ptr %actor)
229 ; CHECK: ret void
231 ; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.0(ptr %0, ptr nocapture readnone %1, ptr nocapture readonly %2)
232 ; CHECK-SAME: #[[FRAMEPOINTER]]
233 ; CHECK-SAME: !dbg ![[SP4:[0-9]+]]
234 ; CHECK: [[CALLEE_CTXT:%.*]] = load ptr, ptr %2
235 ; CHECK: [[CALLEE_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[CALLEE_CTXT]], i64 152
236 ; CHECK: store ptr @my_async_function2.resume.1,
237 ; CHECK: [[CALLLE_CTXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CTXT_SPILL_ADDR]]
238 ; CHECK: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CTXT_RELOAD]]
239 ; CHECK: ret void
241 ; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.1(ptr nocapture readonly %0, ptr %1, ptr nocapture readnone %2)
242 ; CHECK-SAME: #[[FRAMEPOINTER]]
243 ; CHECK: tail call swiftcc void @asyncReturn({{.*}}%1)
244 ; CHECK: ret void
246 define swiftcc void @top_level_caller(ptr %ctxt, ptr %task, ptr %actor) {
247   %prepare = call ptr @llvm.coro.prepare.async(ptr @my_async_function)
248   call swiftcc void %prepare(ptr %ctxt, ptr %task, ptr %actor)
249   ret void
252 ; CHECK-LABEL: define swiftcc void @top_level_caller(ptr %ctxt, ptr %task, ptr %actor)
253 ; CHECK: store ptr @my_async_functionTQ0_
254 ; CHECK: store ptr %ctxt
255 ; CHECK: tail call swiftcc void @asyncSuspend
256 ; CHECK: ret void
258 @dont_crash_on_cf_fp = constant <{ i32, i32 }>
259   <{ i32 trunc ( ; Relative pointer to async function
260        i64 sub (
261          i64 ptrtoint (ptr @my_async_function to i64),
262          i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_fp, i32 0, i32 1) to i64)
263        )
264      to i32),
265      i32 128    ; Initial async context size without space for frame
269 define swiftcc void @dont_crash_on_cf_dispatch(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) {
270   %isNull = icmp eq ptr %task, null
271   br i1 %isNull, label %is_null, label %is_not_null
273 is_null:
274   ret void
276 is_not_null:
277   tail call swiftcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor)
278   ret void
281 define swiftcc void @dont_crash_on_cf(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine  {
282 entry:
283   %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
284           ptr @dont_crash_on_cf_fp)
285   %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
286   %callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)
287   %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1
288   %resume.func_ptr = call ptr @llvm.coro.async.resume()
289   store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr
290   store ptr %async.ctxt, ptr %callee_context
291   %res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,
292                                                   ptr %resume.func_ptr,
293                                                   ptr @resume_context_projection,
294                                                   ptr @dont_crash_on_cf_dispatch,
295                                                   ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
297   call void @llvm.coro.async.context.dealloc(ptr %callee_context)
298   %continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 1
299   tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor)
300   call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0)
301   unreachable
304 @multiple_coro_end_async_fp = constant <{ i32, i32 }>
305   <{ i32 trunc ( ; Relative pointer to async function
306        i64 sub (
307          i64 ptrtoint (ptr @multiple_coro_end_async to i64),
308          i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @multiple_coro_end_async_fp, i32 0, i32 1) to i64)
309        )
310      to i32),
311      i32 128    ; Initial async context size without space for frame
314 define swiftcc void @must_tail_call_return(ptr %async.ctxt, ptr %task, ptr %actor) {
315   musttail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %task, ptr %actor)
316   ret void
319 define swiftcc void @multiple_coro_end_async(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine {
320 entry:
321   %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
322           ptr @dont_crash_on_cf_fp)
323   %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
324   %callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)
325   %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1
326   %resume.func_ptr = call ptr @llvm.coro.async.resume()
327   store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr
328   store ptr %async.ctxt, ptr %callee_context
329   %res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,
330                                                   ptr %resume.func_ptr,
331                                                   ptr @resume_context_projection,
332                                                   ptr @dont_crash_on_cf_dispatch,
333                                                   ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
335   call void @llvm.coro.async.context.dealloc(ptr %callee_context)
336   %continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 1
337   %eq = icmp eq ptr %continuation_task_arg, null
338   br i1 %eq, label %is_equal, label %is_not_equal
340 is_equal:
341   tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor)
342   call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0)
343   unreachable
345 is_not_equal:
346   call i1 (ptr, i1, ...) @llvm.coro.end.async(
347                            ptr %hdl, i1 0,
348                            ptr @must_tail_call_return,
349                            ptr %async.ctxt, ptr %continuation_task_arg, ptr null)
350   unreachable
353 ; CHECK-LABEL: define internal swiftcc void @multiple_coro_end_async.resume.0(
354 ; CHECK: musttail call swiftcc void @asyncReturn(
355 ; CHECK: ret void
357 @polymorphic_suspend_return_fp = constant <{ i32, i32 }>
358   <{ i32 trunc ( ; Relative pointer to async function
359        i64 sub (
360          i64 ptrtoint (ptr @polymorphic_suspend_return to i64),
361          i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @polymorphic_suspend_return_fp, i32 0, i32 1) to i64)
362        )
363      to i32),
364      i32 64    ; Initial async context size without space for frame
367 define swiftcc void @polymorphic_suspend_return(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine {
368 entry:
369   %tmp = alloca { i64, i64 }, align 8
370   %proj.1 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 0
371   %proj.2 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 1
373   %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
374           ptr @polymorphic_suspend_return_fp)
375   %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
376   store i64 0, ptr %proj.1, align 8
377   store i64 1, ptr %proj.2, align 8
378   call void @some_may_write(ptr %proj.1)
380         ; Begin lowering: apply %my_other_async_function(%args...)
382   ; setup callee context
383   %callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)
384   ; store arguments ...
385   ; ... (omitted)
387   ; store the return continuation
388   %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1
389   %resume.func_ptr = call ptr @llvm.coro.async.resume()
390   store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr
392   ; store caller context into callee context
393   store ptr %async.ctxt, ptr %callee_context
394   %res = call {ptr, ptr, ptr, ptr} (i32, ptr, ptr, ...)
395          @llvm.coro.suspend.async.sl_p0i8p0i8p0i8p0i8s(i32 256, ;; swiftasync at 0 and swiftself at 1 in resume function
396                                                  ptr %resume.func_ptr,
397                                                  ptr @resume_context_projection,
398                                                  ptr @my_async_function.my_other_async_function_fp.apply,
399                                                  ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
401   call void @llvm.coro.async.context.dealloc(ptr %callee_context)
402   %continuation_task_arg = extractvalue {ptr, ptr, ptr, ptr} %res, 3
403   %val = load i64, ptr %proj.1
404   call void @some_user(i64 %val)
405   %val.2 = load i64, ptr %proj.2
406   call void @some_user(i64 %val.2)
408   tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor)
409   call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0)
410   unreachable
413 ; CHECK-LABEL: define swiftcc void @polymorphic_suspend_return(ptr swiftasync %async.ctxt, ptr %task, ptr %actor)
414 ; CHECK-LABEL: define internal swiftcc void @polymorphic_suspend_return.resume.0(ptr {{.*}}swiftasync{{.*}} %0, ptr {{.*}}swiftself{{.*}} %1, ptr {{.*}}%2, ptr {{.*}}%3)
415 ; CHECK: }
417 @no_coro_suspend_fp = constant <{ i32, i32 }>
418   <{ i32 trunc ( ; Relative pointer to async function
419        i64 sub (
420          i64 ptrtoint (ptr @no_coro_suspend to i64),
421          i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @no_coro_suspend_fp, i32 0, i32 1) to i64)
422        )
423      to i32),
424      i32 128    ; Initial async context size without space for frame
427 define swiftcc void @no_coro_suspend(ptr %async.ctx) presplitcoroutine {
428 entry:
429   %some_alloca = alloca i64
430   %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
431           ptr @no_coro_suspend_fp)
432   %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
433   call void @some_may_write(ptr %some_alloca)
434   call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0)
435   unreachable
438 ; CHECK-LABEL: define swiftcc void @no_coro_suspend
439 ; CHECK:   [[ALLOCA:%.*]] = alloca i64
440 ; CHECK:   call void @some_may_write(ptr {{.*}}[[ALLOCA]])
442 @no_coro_suspend_swifterror_fp = constant <{ i32, i32 }>
443   <{ i32 trunc ( ; Relative pointer to async function
444        i64 sub (
445          i64 ptrtoint (ptr @no_coro_suspend_swifterror to i64),
446          i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @no_coro_suspend_swifterror_fp, i32 0, i32 1) to i64)
447        )
448      to i32),
449      i32 128    ; Initial async context size without space for frame
452 declare void @do_with_swifterror(ptr swifterror)
454 define swiftcc void @no_coro_suspend_swifterror(ptr %async.ctx) presplitcoroutine {
455 entry:
456   %some_alloca = alloca swifterror ptr
457   %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
458           ptr @no_coro_suspend_swifterror_fp)
459   %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
460   store ptr null, ptr %some_alloca, align 8
461   call void @do_with_swifterror(ptr swifterror %some_alloca)
462   call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0)
463   unreachable
466  ; CHECK-LABEL: define swiftcc void @no_coro_suspend_swifterror
467  ; CHECK:  [[ALLOCA:%.*]] = alloca swifterror ptr
468  ; CHECK:   store ptr null, ptr [[ALLOCA]]
469  ; CHECK:   call void @do_with_swifterror(ptr {{.*}}swifterror{{.*}} [[ALLOCA]])
471 @undefined_coro_async_resume_fp = constant <{ i32, i32 }>
472   <{ i32 trunc (
473        i64 sub (
474          i64 ptrtoint (ptr @undefined_coro_async_resume to i64),
475          i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @undefined_coro_async_resume_fp, i32 0, i32 1) to i64)
476        )
477      to i32),
478      i32 24
481 declare void @crash()
482 declare void @use(ptr)
484 define swiftcc void @undefined_coro_async_resume(ptr %async.ctx) presplitcoroutine {
485 entry:
486   %id = call token @llvm.coro.id.async(i32 24, i32 16, i32 0, ptr @undefined_coro_async_resume_fp)
487   %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
488   %undefined_resume_pointer = call ptr @llvm.coro.async.resume()
489   call void @use(ptr %undefined_resume_pointer)
490   call void @crash()
491   %unused = call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 false)
492   unreachable
494 ; CHECK-LABEL: define swiftcc void @undefined_coro_async_resume
495 ; CHECK-NOT: @llvm.coro.async.resume
496 ; CHECK: call void @use(ptr null)
497 ; CHECK: ret
499 declare { ptr, ptr, ptr, ptr } @llvm.coro.suspend.async.sl_p0i8p0i8p0i8p0i8s(i32, ptr, ptr, ...)
500 declare ptr @llvm.coro.prepare.async(ptr)
501 declare token @llvm.coro.id.async(i32, i32, i32, ptr)
502 declare ptr @llvm.coro.begin(token, ptr)
503 declare i1 @llvm.coro.end.async(ptr, i1, ...)
504 declare i1 @llvm.coro.end(ptr, i1, token)
505 declare {ptr, ptr, ptr} @llvm.coro.suspend.async(i32, ptr, ptr, ...)
506 declare ptr @llvm.coro.async.context.alloc(ptr, ptr)
507 declare void @llvm.coro.async.context.dealloc(ptr)
508 declare swiftcc void @asyncReturn(ptr, ptr, ptr)
509 declare swiftcc void @asyncSuspend(ptr, ptr, ptr)
510 declare ptr @llvm.coro.async.resume()
511 declare void @llvm.coro.async.size.replace(ptr, ptr)
512 declare ptr @hide(ptr)
514 !llvm.dbg.cu = !{!2}
515 !llvm.module.flags = !{!0}
517 !0 = !{i32 2, !"Debug Info Version", i32 3}
518 ; CHECK: ![[SP1]] = distinct !DISubprogram(name: "my_async_function",
519 ; CHECK-SAME:                              linkageName: "my_async_function",
520 ; CHECK-SAME:                              scopeLine: 1
521 !1 = distinct !DISubprogram(name: "my_async_function",
522                             linkageName: "my_async_function",
523                             scope: !2, file: !3, line: 1, type: !4,
524                             scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
525 ; CHECK: ![[SP2]] = distinct !DISubprogram(name: "my_async_function",
526 ; CHECK-SAME:                              linkageName: "my_async_functionTQ0_",
527 ; CHECK-SAME:                              scopeLine: 2
528 !2 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !3, emissionKind: FullDebug)
529 !3 = !DIFile(filename: "/tmp/1.swift", directory: "/")
530 !4 = !DISubroutineType(types: !{})
531 !5 = !DILocation(line: 2, column: 0, scope: !1)
533 ; CHECK: ![[SP3]] = distinct !DISubprogram(name: "my_async_function2",
534 ; CHECK-SAME:                              linkageName: "my_async_function2",
535 ; CHECK-SAME:                              scopeLine: 1
536 !6 = distinct !DISubprogram(name: "my_async_function2",
537                             linkageName: "my_async_function2",
538                             scope: !2, file: !3, line: 1, type: !4,
539                             scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
540 ; CHECK: ![[SP4]] = distinct !DISubprogram(name: "my_async_function2",
541 ; CHECK-SAME:                              linkageName: "my_async_function2.resume.0",
542 ; CHECK-SAME:                              scopeLine: 1
543 !7 = !DILexicalBlockFile(scope: !6, file: !8, discriminator: 0)
544 !8 = !DIFile(filename: "/tmp/fake.cpp", directory: "/")
545 !9 = !DILocation(line: 2, column: 0, scope: !7)