1 ; RUN: opt < %s -passes='default<O2>' -S | FileCheck --check-prefixes=CHECK %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 ; Function that implements the dispatch to the callee function.
16 define swiftcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) {
17 tail call swiftcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor)
21 declare void @some_user(i64)
22 declare void @some_may_write(ptr)
24 define ptr @resume_context_projection(ptr %ctxt) {
26 %resume_ctxt = load ptr, ptr %ctxt, align 8
31 @unreachable_fp = constant <{ i32, i32 }>
32 <{ i32 trunc ( ; Relative pointer to async function
34 i64 ptrtoint (ptr @unreachable to i64),
35 i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @unreachable_fp, i32 0, i32 1) to i64)
38 i32 128 ; Initial async context size without space for frame
41 define swiftcc void @unreachable(ptr %async.ctxt, ptr %task, ptr %actor) {
43 %tmp = alloca { i64, i64 }, align 8
44 %proj.1 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 0
45 %proj.2 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 1
47 %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
49 %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
50 store i64 0, ptr %proj.1, align 8
51 store i64 1, ptr %proj.2, align 8
52 call void @some_may_write(ptr %proj.1)
54 ; Begin lowering: apply %my_other_async_function(%args...)
55 ; setup callee context
56 %arg1 = bitcast ptr @my_other_async_function_fp to ptr
57 %callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr %arg1)
58 ; store the return continuation
59 %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1
60 %resume.func_ptr = call ptr @llvm.coro.async.resume()
61 store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr
63 ; store caller context into callee context
64 store ptr %async.ctxt, ptr %callee_context
65 %res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,
67 ptr @resume_context_projection,
68 ptr @my_async_function.my_other_async_function_fp.apply,
69 ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
71 call void @llvm.coro.async.context.dealloc(ptr %callee_context)
72 %continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 1
73 %val = load i64, ptr %proj.1
74 call void @some_user(i64 %val)
75 %val.2 = load i64, ptr %proj.2
76 call void @some_user(i64 %val.2)
80 ; CHECK: define swiftcc void @unreachable
81 ; CHECK-NOT: @llvm.coro.suspend.async
84 ; CHECK: define internal swiftcc void @unreachable.resume.0
87 declare ptr @llvm.coro.prepare.async(ptr)
88 declare token @llvm.coro.id.async(i32, i32, i32, ptr)
89 declare ptr @llvm.coro.begin(token, ptr)
90 declare {ptr, ptr, ptr} @llvm.coro.suspend.async(i32, ptr, ptr, ...)
91 declare ptr @llvm.coro.async.context.alloc(ptr, ptr)
92 declare void @llvm.coro.async.context.dealloc(ptr)
93 declare swiftcc void @asyncReturn(ptr, ptr, ptr)
94 declare swiftcc void @asyncSuspend(ptr, ptr, ptr)
95 declare ptr @llvm.coro.async.resume()