@@ -26,7 +26,12 @@ struct Big<T: SomeClass> {
2626 var h: T
2727}
2828
29+ struct BigWrapper<T : SomeClass> {
30+ var big: Big<T>
31+ }
32+
2933sil @make_big : $<T: SomeClass> () -> (@owned Big<T>)
34+ sil @use_some_class : $<T : SomeClass> (@guaranteed T) -> ()
3035
3136// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { i8*, %T14yield_once_big3BigV* } @test_simple
3237// CHECK-32-SAME: (i8* noalias dereferenceable([[BUFFER_SIZE:16]]) %0, %swift.type* %C)
@@ -171,3 +176,73 @@ cont:
171176 %ret = tuple ()
172177 return %ret : $()
173178}
179+
180+ // CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { i8*, %T14yield_once_big3BigV* } @test_simple_guaranteed
181+ // CHECK-32-SAME: (i8* noalias dereferenceable([[BUFFER_SIZE:16]]) %0, %T14yield_once_big10BigWrapperV* noalias nocapture dereferenceable(32) %1, %swift.type* %C)
182+ // CHECK-64-SAME: (i8* noalias dereferenceable([[BUFFER_SIZE:32]]) %0, %T14yield_once_big10BigWrapperV* noalias nocapture dereferenceable(64) %1, %swift.type* %C)
183+ sil [ossa] @test_simple_guaranteed : $@yield_once <C: SomeClass> (@in_guaranteed BigWrapper<C>) -> (@yields @guaranteed Big<C>) {
184+ entry(%arg : $*BigWrapper<C>):
185+ // Allocate space for the return value of make_big.
186+ // CHECK: [[TEMP:%.*]] = alloca [[BIG:%T14yield_once_big3BigV]]
187+ // CHECK-32-SAME: , align 4
188+ // CHECK-64-SAME: , align 8
189+
190+ // Coroutine setup.
191+ // CHECK-32-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], i8* %0, i8* bitcast (void (i8*, i1)* @"$s14yield_once_big10BigWrapperVyxGAA0D0VyxGAA9SomeClassCRbzlIetAnYn_TC" to i8*), i8* bitcast (i8* (i32)* @malloc to i8*), i8* bitcast (void (i8*)* @free to i8*))
192+ // CHECK-64-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], i8* %0, i8* bitcast (void (i8*, i1)* @"$s14yield_once_big10BigWrapperVyxGAA0D0VyxGAA9SomeClassCRbzlIetAnYn_TC" to i8*), i8* bitcast (i8* (i64)* @malloc to i8*), i8* bitcast (void (i8*)* @free to i8*))
193+ // CHECK-NEXT: [[BEGIN:%.*]] = call i8* @llvm.coro.begin(token [[ID]], i8* null)
194+ // CHECK-NEXT: store %swift.type*
195+
196+ // Create the return temporary. We could give this a tighter bound.
197+ // CHECK-NEXT: [[T0:%.*]] = bitcast [[BIG]]* [[TEMP]] to i8*
198+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 {{.*}}, i8* [[T0]])
199+
200+ // CHECK-NEXT: call swiftcc void @marker(i32 1000)
201+ %marker = function_ref @marker : $@convention(thin) (Builtin.Int32) -> ()
202+ %1000 = integer_literal $Builtin.Int32, 1000
203+ apply %marker(%1000) : $@convention(thin) (Builtin.Int32) -> ()
204+
205+ %value = load_borrow %arg : $*BigWrapper<C>
206+ %field = struct_extract %value : $BigWrapper<C>, #BigWrapper.big
207+
208+ // Make sure that we properly convert these struct_extract to
209+ // struct_element_addr while rewriting.
210+ //
211+ // CHECK: call swiftcc void @use_some_class(
212+ %field2 = struct_extract %value : $BigWrapper<C>, #BigWrapper.big
213+ %field3 = struct_extract %field2 : $Big<C>, #Big.a
214+ %f = function_ref @use_some_class : $@convention(thin) <T : SomeClass> (@guaranteed T) -> ()
215+ apply %f<C>(%field3) : $@convention(thin) <T : SomeClass>(@guaranteed T) -> ()
216+
217+ // Suspend.
218+ // CHECK-NEXT: [[IS_UNWIND:%.*]] = call i1 (...) @llvm.coro.suspend.retcon.i1([[BIG]]* [[TEMP]])
219+
220+ // CHECK-NEXT: br i1 [[IS_UNWIND]]
221+ yield %field : $Big<C>, resume resume, unwind unwind
222+
223+ resume:
224+ end_borrow %value : $BigWrapper<C>
225+
226+ // CHECK: call swiftcc void @marker(i32 2000)
227+ %2000 = integer_literal $Builtin.Int32, 2000
228+ apply %marker(%2000) : $@convention(thin) (Builtin.Int32) -> ()
229+ // CHECK-NEXT: [[T0:%.*]] = bitcast [[BIG]]* [[TEMP]] to i8*
230+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 {{.*}}, i8* [[T0]])
231+ // CHECK-NEXT: br label %coro.end
232+ %ret = tuple ()
233+ return %ret : $()
234+
235+ unwind:
236+ end_borrow %value : $BigWrapper<C>
237+ // CHECK: call swiftcc void @marker(i32 3000)
238+ %3000 = integer_literal $Builtin.Int32, 3000
239+ apply %marker(%3000) : $@convention(thin) (Builtin.Int32) -> ()
240+ // CHECK-NEXT: [[T0:%.*]] = bitcast [[BIG]]* [[TEMP]] to i8*
241+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 {{.*}}, i8* [[T0]])
242+ // CHECK-NEXT: br label %coro.end
243+ unwind
244+
245+ // CHECK: coro.end:
246+ // CHECK: call i1 @llvm.coro.end(i8* [[BEGIN]], i1 false)
247+ // CHECK-NEXT: unreachable
248+ }
0 commit comments