@@ -26,7 +26,12 @@ struct Big<T: SomeClass> {
26
26
var h: T
27
27
}
28
28
29
+ struct BigWrapper<T : SomeClass> {
30
+ var big: Big<T>
31
+ }
32
+
29
33
sil @make_big : $<T: SomeClass> () -> (@owned Big<T>)
34
+ sil @use_some_class : $<T : SomeClass> (@guaranteed T) -> ()
30
35
31
36
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { i8*, %T14yield_once_big3BigV* } @test_simple
32
37
// CHECK-32-SAME: (i8* noalias dereferenceable([[BUFFER_SIZE:16]]) %0, %swift.type* %C)
@@ -171,3 +176,73 @@ cont:
171
176
%ret = tuple ()
172
177
return %ret : $()
173
178
}
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