|
1 | 1 | // RUN: %target-swift-frontend -enable-experimental-concurrency -enable-objc-interop -primary-file %s -emit-ir -sil-verify-all -disable-llvm-optzns -disable-swift-specific-llvm-optzns | %FileCheck %s
|
| 2 | +// RUN: %target-swift-frontend -enable-experimental-concurrency -enable-objc-interop -primary-file %s -emit-ir -sil-verify-all |
2 | 3 |
|
3 | 4 | // REQUIRES: concurrency
|
4 | 5 |
|
|
13 | 14 | }
|
14 | 15 |
|
15 | 16 | // CHECK-LABEL: define{{.*}} @async_continuation(
|
| 17 | +// CHECK: [[cont_context:%.*]] = alloca %swift.async_continuation_context |
| 18 | +// CHECK: [[result_storage:%.*]] = alloca i32 |
| 19 | +// CHECK: call token @llvm.coro.id.async |
| 20 | +// CHECK: call i8* @llvm.coro.begin( |
| 21 | +// Create UnsafeContinuation<Int32>. |
| 22 | +// CHECK: [[tmp0:%.*]] = bitcast %swift.task* %0 to i8* |
| 23 | +// CHECK: [[tmp1:%.*]] = insertvalue %TSV undef, i8* [[tmp0]], 0 |
| 24 | +// CHECK: [[continuation:%.*]] = insertvalue %T12_Concurrency18UnsafeContinuationV undef, %TSV [[tmp1]], 0 |
| 25 | +// Initialize the async continuation context. |
| 26 | +// CHECK: [[context_addr:%.*]] = getelementptr inbounds %swift.async_continuation_context, %swift.async_continuation_context* [[cont_context]], i32 0, i32 0 |
| 27 | +// CHECK: store %swift.context* %2, %swift.context** [[context_addr]] |
| 28 | +// CHECK: [[error_addr:%.*]] = getelementptr inbounds %swift.async_continuation_context, %swift.async_continuation_context* [[cont_context]], i32 0, i32 2 |
| 29 | +// CHECK: store %swift.error* null, %swift.error** [[error_addr]] |
| 30 | +// CHECK: [[result_addr:%.*]] = getelementptr inbounds %swift.async_continuation_context, %swift.async_continuation_context* [[cont_context]], i32 0, i32 3 |
| 31 | +// CHECK: [[result_storage_as_opaque:%.*]] = bitcast i32* [[result_storage]] to %swift.opaque* |
| 32 | +// CHECK: store %swift.opaque* [[result_storage_as_opaque]], %swift.opaque** [[result_addr]] |
| 33 | +// Initialize the async task with the continuation function and async continuation context. |
| 34 | +// CHECK: [[task_continuation_fn_addr:%.*]] = getelementptr inbounds %swift.task, %swift.task* %0, i32 0, i32 3 |
| 35 | +// CHECK: [[continuation_fn:%.*]] = call i8* @llvm.coro.async.resume() |
| 36 | +// CHECK: store i8* [[continuation_fn]], i8** [[task_continuation_fn_addr]] |
| 37 | +// CHECK: [[task_resume_context_addr:%.*]] = getelementptr inbounds %swift.task, %swift.task* %0, i32 0, i32 4 |
| 38 | +// CHECK: [[cont_context2:%.*]] = bitcast %swift.async_continuation_context* [[cont_context]] to %swift.context* |
| 39 | +// CHECK: store %swift.context* [[cont_context2]], %swift.context** [[task_resume_context_addr]] |
| 40 | +// Initialize the synchronization variable. |
| 41 | +// CHECK: [[synchronization_addr:%.*]] = getelementptr inbounds %swift.async_continuation_context, %swift.async_continuation_context* %3, i32 0, i32 1 |
| 42 | +// CHECK: store atomic {{(i64|i32)}} 0, {{(i64|i32)}}* [[synchronization_addr]] release |
| 43 | +// Do some stuff. |
| 44 | +// CHECK: call swiftcc void @not_async_test() |
| 45 | +// Arrive at the await_async_continuation point. |
| 46 | +// CHECK: [[synchronization_addr_before_await:%.*]] = getelementptr inbounds %swift.async_continuation_context, %swift.async_continuation_context* %3, i32 0, i32 1 |
| 47 | +// CHECK: [[first_at_sync_pt:%.*]] = cmpxchg {{(i64|i32)}}* [[synchronization_addr_before_await]], {{(i64|i32)}} 0, {{(i64|i32)}} 1 release acquire |
| 48 | +// CHECK: [[first_at_sync_pt_bool:%.*]] = extractvalue { {{(i64|i32)}}, i1 } [[first_at_sync_pt]], 1 |
| 49 | +// CHECK: br i1 [[first_at_sync_pt_bool]], label %await.async.abort, label %await.async.maybe.resume |
| 50 | + |
| 51 | +// Abort if we are the first to arrive at the await/or continuation point -- |
| 52 | +// we must wait on the other to arrive. |
| 53 | +// CHECK: await.async.abort: |
| 54 | +// CHECK: br label %coro.end |
| 55 | + |
| 56 | +// CHECK: coro.end: |
| 57 | +// CHECK: call i1 @llvm.coro.end( |
| 58 | +// CHECK: unreachable |
| 59 | + |
| 60 | +// CHECK: await.async.maybe.resume: |
| 61 | +// CHECK: call { i8*, i8*, i8* } (i8*, i8*, ...) @llvm.coro.suspend.async({{.*}} @__swift_async_resume_project_context |
| 62 | +// Abort if we are the first to arrive at the continuation point we must wait |
| 63 | +// on the await to arrive. |
| 64 | +// CHECK: [[first_at_sync_pt:%.*]] = cmpxchg {{(i64|i32)}}* [[synchronization_addr_before_await]], {{(i64|i32)}} 0, {{(i64|i32)}} 1 release acquire |
| 65 | +// CHECK: [[first_at_sync_pt_bool:%.*]] = extractvalue { {{(i64|i32)}}, i1 } [[first_at_sync_pt]], 1 |
| 66 | +// CHECK: br i1 [[first_at_sync_pt_bool]], label %await.async.abort, label %await.async.resume |
| 67 | + |
| 68 | +// CHECK: await.async.resume: |
| 69 | +// CHECK: br label %await.async.normal |
| 70 | + |
| 71 | +// CHECK: await.async.normal: |
| 72 | +// CHECK: [[result_addr_addr:%.*]] = getelementptr inbounds %swift.async_continuation_context, %swift.async_continuation_context* [[cont_context]], i32 0, i32 3 |
| 73 | +// CHECK: [[result_addr:%.*]] = load %swift.opaque*, %swift.opaque** [[result_addr_addr]] |
| 74 | +// CHECK: [[typed_result_addr:%.*]] = bitcast %swift.opaque* [[result_addr]] to i32* |
| 75 | +// CHECK: [[result_value:%.*]] = load i32, i32* [[typed_result_addr]] |
| 76 | +// CHECK: br label [[result_bb:[0-9]+]] |
| 77 | + |
| 78 | +// CHECK: [[result_bb]]: |
| 79 | +// CHECK: phi i32 [ [[result_value]], %await.async.normal ] |
| 80 | + |
16 | 81 | sil @async_continuation : $@async () -> () {
|
17 | 82 | entry:
|
18 | 83 | %c = get_async_continuation $Builtin.Int32
|
|
0 commit comments