1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
// RUN: %target-swift-frontend -g -enable-objc-interop -primary-file %s -emit-irgen -sil-verify-all | %IRGenFileCheck %s
// RUN: %target-swift-frontend -enable-objc-interop -primary-file %s -emit-ir -sil-verify-all
// REQUIRES: concurrency, objc_codegen
import Builtin
import Swift
import _Concurrency
sil @not_async_test : $@convention(thin) () -> () {
bb0:
%0 = tuple ()
return %0 : $()
}
// CHECK-LABEL: define{{.*}} @async_continuation(
// CHECK: [[ctxt_addr:%.*]] = alloca ptr
// CHECK: [[cont_context:%.*]] = alloca %swift.continuation_context
// CHECK: [[result_storage:%.*]] = alloca i32
// CHECK: call token @llvm.coro.id.async
// CHECK: call ptr @llvm.coro.begin(
// Initialize the async continuation context:
// Initialize Parent.
// CHECK: [[base_context:%.*]] = getelementptr inbounds %swift.continuation_context, ptr [[cont_context]], i32 0, i32 0
// CHECK: [[context_addr:%.*]] = getelementptr inbounds %swift.context, ptr [[base_context]], i32 0, i32 0
// CHECK: [[ctxt:%.*]] = load ptr, ptr [[ctxt_addr]]
// CHECK-arm64e: [[ctxt_addr_int:%[0-9]+]] = ptrtoint ptr [[context_addr]] to i64
// CHECK-arm64e: [[ptrauth_blend:%[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 [[ctxt_addr_int]], i64 48546)
// CHECK-arm64e: [[ctxt_int:%[0-9]+]] = ptrtoint ptr [[ctxt]] to i64
// CHECK-arm64e: [[signed_int:%[0-9]+]] = call i64 @llvm.ptrauth.sign(i64 [[ctxt_int]], i32 2, i64 [[ptrauth_blend]])
// CHECK-arm64e: [[signed_ctxt:%[0-9]+]] = inttoptr i64 [[signed_int]] to ptr
// CHECK-arm64e: store ptr [[signed_ctxt]], ptr [[context_addr]]
// CHECK-x86_64: store ptr [[ctxt]], ptr [[context_addr]]
// Initialize NormalResult.
// CHECK: [[result_addr:%.*]] = getelementptr inbounds %swift.continuation_context, ptr [[cont_context]], i32 0, i32 4
// CHECK: store ptr [[result_storage]], ptr [[result_addr]]
// Initialize ResumeParent.
// CHECK: [[resume_intrinsic:%.*]] = call ptr @llvm.coro.async.resume()
// CHECK: [[continuation_fn_addr:%.*]] = getelementptr inbounds %swift.context, ptr [[base_context]], i32 0, i32 1
// CHECK-arm64e: [[continuation_fn_addr_int:%[0-9]+]] = ptrtoint ptr [[continuation_fn_addr]] to i64
// CHECK-arm64e: [[ptrauth_blend:%[0-9]+]] = call i64 @llvm.ptrauth.blend(i64 [[continuation_fn_addr_int]], i64 55047)
// CHECK-arm64e: [[continuation_fn_int:%[0-9]+]] = ptrtoint ptr [[resume_intrinsic]] to i64
// CHECK-arm64e: [[signed_int:%[0-9]+]] = call i64 @llvm.ptrauth.sign(i64 [[continuation_fn_int]], i32 0, i64 [[ptrauth_blend]])
// CHECK-arm64e: [[signed_continuation_fn:%[0-9]+]] = inttoptr i64 [[signed_int]] to ptr
// CHECK-arm64e: store ptr [[signed_continuation_fn]], ptr [[continuation_fn_addr]]
// CHECK-x86_64: store ptr [[resume_intrinsic]], ptr [[continuation_fn_addr]]
// Call the runtime to retrieve and initialize the continuation.
// CHECK: call swiftcc ptr @swift_continuation_init(ptr [[cont_context]], [[INT]] 0)
// Do some stuff.
// CHECK: call swiftcc void @not_async_test()
// Arrive at the await_async_continuation point.
// CHECK: [[suspend:%.*]] = call { ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0s(i32 0, ptr [[resume_intrinsic]], ptr @__swift_async_resume_project_context, ptr @__swift_continuation_await_point, ptr [[cont_context]])
// CHECK: [[result_addr_addr:%.*]] = getelementptr inbounds %swift.continuation_context, ptr [[cont_context]], i32 0, i32 4
// CHECK: [[result_addr:%.*]] = load ptr, ptr [[result_addr_addr]]
// CHECK: [[result_value:%.*]] = load i32, ptr [[result_addr]]
// CHECK: br label %[[result_bb:[0-9]+]]
// CHECK: [[result_bb]]:
// CHECK: phi i32 [ [[result_value]], %entry ]
// CHECK: define {{.*}} void @__swift_continuation_await_point(ptr %0)
// CHECK: {{musttail call swifttailcc|tail call swiftcc}} void @swift_continuation_await(ptr %0)
// CHECK-NEXT: ret void
// CHECK: define {{.*}} void @async_continuation.0(ptr %0, ptr %1){{.*}}!dbg ![[DBG:[0-9]+]]
// CHECK-NOT: define
// CHECK: tail call swift{{(tail)?}}cc void %{{.*}}(ptr swiftasync %1)
// CHECK-NEXT: ret void
// CHECK: ![[DBG]] = distinct !DISubprogram(linkageName: "async_continuation"
sil @async_continuation : $@async () -> () {
entry:
%c = get_async_continuation Builtin.Int32
%f = function_ref @not_async_test : $@convention(thin) () -> ()
apply %f() : $@convention(thin) () -> ()
await_async_continuation %c : $Builtin.RawUnsafeContinuation, resume bb1
bb1(%r : $Builtin.Int32):
%t = tuple()
return %t : $()
}
sil @async_continuation_throws : $@async () -> () {
entry:
%c = get_async_continuation [throws] Builtin.Int32
%f = function_ref @not_async_test : $@convention(thin) () -> ()
apply %f() : $@convention(thin) () -> ()
await_async_continuation %c : $Builtin.RawUnsafeContinuation, resume bb1, error bb2
bb1(%r : $Builtin.Int32):
br bb3
bb2(%e : $Error):
br bb3
bb3:
%t = tuple()
return %t : $()
}
sil @async_continuation_addr : $@async () -> () {
entry:
%a = alloc_stack $Builtin.Int32
%c = get_async_continuation_addr Builtin.Int32, %a : $*Builtin.Int32
%f = function_ref @not_async_test : $@convention(thin) () -> ()
apply %f() : $@convention(thin) () -> ()
await_async_continuation %c : $Builtin.RawUnsafeContinuation, resume bb1
bb1:
dealloc_stack %a : $*Builtin.Int32
%t = tuple()
return %t : $()
}
sil @async_continuation_throws_addr : $@async () -> () {
entry:
%a = alloc_stack $Builtin.Int32
%c = get_async_continuation_addr [throws] Builtin.Int32, %a : $*Builtin.Int32
%f = function_ref @not_async_test : $@convention(thin) () -> ()
apply %f() : $@convention(thin) () -> ()
await_async_continuation %c : $Builtin.RawUnsafeContinuation, resume bb1, error bb2
bb1:
dealloc_stack %a : $*Builtin.Int32
br bb3
bb2(%e : $Error):
dealloc_stack %a : $*Builtin.Int32
br bb3
bb3:
%t = tuple()
return %t : $()
}
|