// 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) // CHECK-NOT: define // CHECK: tail call swift{{(tail)?}}cc void %{{.*}}(ptr swiftasync %1) // CHECK-NEXT: ret void 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 : $() }