@@ -38,3 +38,83 @@ public struct X {
3838 _ = Builtin . createAsyncTaskFuture ( 0 , nil , closure)
3939 }
4040}
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