xref: /llvm-project/llvm/test/Transforms/Coroutines/coro-async-unreachable.ll (revision 2e29c91b96832504b9008be5e095f7dd640cdea0)
1; RUN: opt < %s -passes='default<O2>' -S | FileCheck --check-prefixes=CHECK %s
2
3target datalayout = "p:64:64:64"
4
5%async.task = type { i64 }
6%async.actor = type { i64 }
7%async.fp = type <{ i32, i32 }>
8
9%async.ctxt = type { ptr, ptr }
10
11; The async callee.
12@my_other_async_function_fp = external global <{ i32, i32 }>
13declare void @my_other_async_function(ptr %async.ctxt)
14
15; Function that implements the dispatch to the callee function.
16define 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)
18  ret void
19}
20
21declare void @some_user(i64)
22declare void @some_may_write(ptr)
23
24define ptr @resume_context_projection(ptr %ctxt) {
25entry:
26  %resume_ctxt = load ptr, ptr %ctxt, align 8
27  ret ptr %resume_ctxt
28}
29
30
31@unreachable_fp = constant <{ i32, i32 }>
32  <{ i32 trunc ( ; Relative pointer to async function
33       i64 sub (
34         i64 ptrtoint (ptr @unreachable to i64),
35         i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @unreachable_fp, i32 0, i32 1) to i64)
36       )
37     to i32),
38     i32 128    ; Initial async context size without space for frame
39}>
40
41define swiftcc void @unreachable(ptr %async.ctxt, ptr %task, ptr %actor)  {
42entry:
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
46
47  %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
48          ptr @unreachable_fp)
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)
53
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
62
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,
66                                                  ptr %resume.func_ptr,
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)
70
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)
77  unreachable
78}
79
80; CHECK: define swiftcc void @unreachable
81; CHECK-NOT: @llvm.coro.suspend.async
82; CHECK: return
83
84; CHECK: define internal swiftcc void @unreachable.resume.0
85; CHECK: unreachable
86
87declare ptr @llvm.coro.prepare.async(ptr)
88declare token @llvm.coro.id.async(i32, i32, i32, ptr)
89declare ptr @llvm.coro.begin(token, ptr)
90declare {ptr, ptr, ptr} @llvm.coro.suspend.async(i32, ptr, ptr, ...)
91declare ptr @llvm.coro.async.context.alloc(ptr, ptr)
92declare void @llvm.coro.async.context.dealloc(ptr)
93declare swiftcc void @asyncReturn(ptr, ptr, ptr)
94declare swiftcc void @asyncSuspend(ptr, ptr, ptr)
95declare ptr @llvm.coro.async.resume()
96