@@ -38,3 +38,83 @@ public struct X {
38
38
_ = Builtin . createAsyncTaskFuture ( 0 , nil , closure)
39
39
}
40
40
}
41
+
42
+ // CHECK-LABEL: sil [ossa] @$s4test26usesWithUnsafeContinuationyyYF : $@convention(thin) @async () -> () {
43
+ public func usesWithUnsafeContinuation( ) async {
44
+ // trivial resume type
45
+ let _: Int = await Builtin . withUnsafeContinuation { c in }
46
+
47
+ // CHECK: [[FN:%.*]] = function_ref @$s4test26usesWithUnsafeContinuationyyYFyBcXEfU_ : $@convention(thin) (Builtin.RawUnsafeContinuation) -> ()
48
+ // CHECK: [[TMP:%.*]] = convert_function [[FN]] : $@convention(thin) (Builtin.RawUnsafeContinuation) -> () to $@convention(thin) @noescape (Builtin.RawUnsafeContinuation) -> ()
49
+ // CHECK: [[CLOSURE:%.*]] = thin_to_thick_function [[TMP]]
50
+ // CHECK: [[BOX:%.*]] = alloc_stack $Int
51
+ // CHECK: [[CC:%.*]] = get_async_continuation_addr Int, [[BOX]] : $*Int
52
+ // CHECK: apply [[CLOSURE]]([[CC]]) : $@noescape @callee_guaranteed (Builtin.RawUnsafeContinuation) -> ()
53
+ // CHECK: await_async_continuation [[CC]] : $Builtin.RawUnsafeContinuation, resume bb1
54
+
55
+ // CHECK: bb1:
56
+ // CHECK: [[RESULT:%.*]] = load [trivial] [[BOX]] : $*Int
57
+ // CHECK: dealloc_stack [[BOX]]
58
+
59
+ // loadable resume type
60
+ let _: String = await Builtin . withUnsafeContinuation { c in }
61
+
62
+ // CHECK: [[FN:%.*]] = function_ref @$s4test26usesWithUnsafeContinuationyyYFyBcXEfU0_ : $@convention(thin) (Builtin.RawUnsafeContinuation) -> ()
63
+ // CHECK: [[TMP:%.*]] = convert_function [[FN]] : $@convention(thin) (Builtin.RawUnsafeContinuation) -> () to $@convention(thin) @noescape (Builtin.RawUnsafeContinuation) -> ()
64
+ // CHECK: [[CLOSURE:%.*]] = thin_to_thick_function [[TMP]]
65
+ // CHECK: [[BOX:%.*]] = alloc_stack $String
66
+ // CHECK: [[CC:%.*]] = get_async_continuation_addr String, [[BOX]] : $*String
67
+ // CHECK: apply [[CLOSURE]]([[CC]]) : $@noescape @callee_guaranteed (Builtin.RawUnsafeContinuation) -> ()
68
+ // CHECK: await_async_continuation [[CC]] : $Builtin.RawUnsafeContinuation, resume bb2
69
+
70
+ // CHECK: bb2:
71
+ // CHECK: [[RESULT:%.*]] = load [take] [[BOX]] : $*String
72
+ // CHECK: destroy_value [[RESULT]]
73
+ // CHECK: dealloc_stack [[BOX]]
74
+
75
+ // address-only resume type
76
+ let _: Any = await Builtin . withUnsafeContinuation { c in }
77
+
78
+ // CHECK: [[FN:%.*]] = function_ref @$s4test26usesWithUnsafeContinuationyyYFyBcXEfU1_ : $@convention(thin) (Builtin.RawUnsafeContinuation) -> ()
79
+ // CHECK: [[TMP:%.*]] = convert_function [[FN]] : $@convention(thin) (Builtin.RawUnsafeContinuation) -> () to $@convention(thin) @noescape (Builtin.RawUnsafeContinuation) -> ()
80
+ // CHECK: [[CLOSURE:%.*]] = thin_to_thick_function [[TMP]]
81
+ // CHECK: [[BOX:%.*]] = alloc_stack $Any
82
+ // CHECK: [[CC:%.*]] = get_async_continuation_addr Any, [[BOX]] : $*Any
83
+ // CHECK: apply [[CLOSURE]]([[CC]]) : $@noescape @callee_guaranteed (Builtin.RawUnsafeContinuation) -> ()
84
+ // CHECK: await_async_continuation [[CC]] : $Builtin.RawUnsafeContinuation, resume bb3
85
+
86
+ // CHECK: bb3:
87
+ // CHECK: [[COPY:%.*]] = alloc_stack $Any
88
+ // CHECK: copy_addr [take] [[BOX]] to [initialization] [[COPY]]
89
+ // CHECK: destroy_addr [[COPY]]
90
+ // CHECK: dealloc_stack [[COPY]]
91
+ // CHECK: dealloc_stack [[BOX]]
92
+ }
93
+
94
+ // CHECK-LABEL: sil [ossa] @$s4test34usesWithUnsafeThrowingContinuationyyYKF : $@convention(thin) @async () -> @error Error {
95
+ public func usesWithUnsafeThrowingContinuation( ) async throws {
96
+ let _: Int = try await Builtin . withUnsafeThrowingContinuation { c in }
97
+
98
+ // CHECK: [[FN:%.*]] = function_ref @$s4test34usesWithUnsafeThrowingContinuationyyYKFyBcXEfU_ : $@convention(thin) (Builtin.RawUnsafeContinuation) -> ()
99
+ // CHECK: [[TMP:%.*]] = convert_function [[FN]] : $@convention(thin) (Builtin.RawUnsafeContinuation) -> () to $@convention(thin) @noescape (Builtin.RawUnsafeContinuation) -> ()
100
+ // CHECK: [[CLOSURE:%.*]] = thin_to_thick_function [[TMP]]
101
+ // CHECK: [[BOX:%.*]] = alloc_stack $Int
102
+ // CHECK: [[CC:%.*]] = get_async_continuation_addr [throws] Int, [[BOX]] : $*Int
103
+ // CHECK: apply [[CLOSURE]]([[CC]]) : $@noescape @callee_guaranteed (Builtin.RawUnsafeContinuation) -> ()
104
+ // CHECK: await_async_continuation [[CC]] : $Builtin.RawUnsafeContinuation, resume bb1, error bb2
105
+
106
+ // CHECK: bb1:
107
+ // CHECK: [[RESULT:%.*]] = load [trivial] [[BOX]] : $*Int
108
+ // CHECK: dealloc_stack [[BOX]]
109
+
110
+ // CHECK: bb2([[ERROR:%.*]] : @owned $Error):
111
+ // CHECK: builtin "willThrow"([[ERROR]] : $Error) : $()
112
+ // CHECK: dealloc_stack [[BOX]]
113
+ // CHECK: throw [[ERROR]]
114
+ }
115
+
116
+ // Make sure we do the right thing when the closure value is non-trivial,
117
+ // because it has captures and was formed by a partial_apply.
118
+ public func usesWithUnsafeContinuationCaptures( fn: ( Builtin . RawUnsafeContinuation ) -> ( ) ) async throws {
119
+ let _: Int = await Builtin . withUnsafeContinuation { c in fn ( c) }
120
+ }
0 commit comments