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 }
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
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)
27 i32 128 ; Initial async context size without space for frame
29 @my_async_function_pa_fp = constant <{ i32, i32 }>
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)
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)
45 declare void @some_user(i64)
46 declare void @some_may_write(ptr)
48 define ptr @__swift_async_resume_project_context(ptr %ctxt) {
50 %resume_ctxt = load ptr, ptr %ctxt, align 8
54 define ptr @resume_context_projection(ptr %ctxt) {
56 %resume_ctxt = load ptr, ptr %ctxt, align 8
61 define swiftcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine !dbg !1 {
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)
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,
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)
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)
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 initializes((152, 160)) %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 i8, ptr [[CALLEE_CTXT]], i64 8
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)
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]])
170 @my_async_function2_fp = constant <{ i32, i32 }>
171 <{ i32 trunc ( ; Relative pointer to async function
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)
177 i32 128 ; Initial async context size without space for frame
180 define swiftcc void @my_async_function2(ptr %task, ptr %actor, ptr %async.ctxt) presplitcoroutine "frame-pointer"="all" !dbg !6 {
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)
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)
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]]
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)
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)
252 ; CHECK-LABEL: define swiftcc void @top_level_caller(ptr initializes((152, 160)) %ctxt, ptr %task, ptr %actor)
253 ; CHECK: store ptr @my_async_functionTQ0_
254 ; CHECK: store ptr %ctxt
255 ; CHECK: tail call swiftcc void @asyncSuspend
258 @dont_crash_on_cf_fp = constant <{ i32, i32 }>
259 <{ i32 trunc ( ; Relative pointer to async function
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)
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
277 tail call swiftcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor)
281 define swiftcc void @dont_crash_on_cf(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine {
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)
304 @multiple_coro_end_async_fp = constant <{ i32, i32 }>
305 <{ i32 trunc ( ; Relative pointer to async function
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)
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)
319 define swiftcc void @multiple_coro_end_async(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine {
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
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)
346 call i1 (ptr, i1, ...) @llvm.coro.end.async(
348 ptr @must_tail_call_return,
349 ptr %async.ctxt, ptr %continuation_task_arg, ptr null)
353 ; CHECK-LABEL: define internal swiftcc void @multiple_coro_end_async.resume.0(
354 ; CHECK: musttail call swiftcc void @asyncReturn(
357 @polymorphic_suspend_return_fp = constant <{ i32, i32 }>
358 <{ i32 trunc ( ; Relative pointer to async function
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)
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 {
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 ...
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)
413 ; CHECK-LABEL: define swiftcc void @polymorphic_suspend_return(ptr swiftasync initializes((152, 160)) %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)
417 @no_coro_suspend_fp = constant <{ i32, i32 }>
418 <{ i32 trunc ( ; Relative pointer to async function
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)
424 i32 128 ; Initial async context size without space for frame
427 define swiftcc void @no_coro_suspend(ptr %async.ctx) presplitcoroutine {
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)
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
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)
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 {
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)
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 }>
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)
481 declare void @crash()
482 declare void @use(ptr)
484 define swiftcc void @undefined_coro_async_resume(ptr %async.ctx) presplitcoroutine {
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)
491 %unused = call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 false)
494 ; CHECK-LABEL: define swiftcc void @undefined_coro_async_resume
495 ; CHECK-NOT: @llvm.coro.async.resume
496 ; CHECK: call void @use(ptr null)
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)
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)