|
4 | 4 | // Declarations //
|
5 | 5 | //////////////////
|
6 | 6 |
|
| 7 | +@_moveOnly |
| 8 | +public class Klass2 {} |
| 9 | + |
7 | 10 | @_moveOnly
|
8 | 11 | public class Klass {
|
9 | 12 | var intField: Int
|
10 |
| - var klsField: Klass? |
| 13 | + var klsField: Klass2 |
11 | 14 |
|
12 | 15 | // CHECK-LABEL: sil hidden [ossa] @$s8moveonly5KlassCACycfc : $@convention(method) (@owned Klass) -> @owned Klass {
|
13 | 16 | // CHECK: bb0([[ARG:%.*]] : @owned $Klass):
|
14 | 17 | // CHECK: [[MARK_UNINIT:%.*]] = mark_uninitialized [rootself] [[ARG]]
|
15 | 18 | // CHECK: [[MARK_NO_IMP_COPY:%.*]] = mark_must_check [no_implicit_copy] [[MARK_UNINIT]]
|
16 | 19 | // CHECK: } // end sil function '$s8moveonly5KlassCACycfc'
|
17 | 20 | init() {
|
18 |
| - klsField = Klass() |
| 21 | + klsField = Klass2() |
19 | 22 | intField = 5
|
20 | 23 | }
|
21 | 24 | }
|
22 | 25 |
|
23 | 26 | public func nonConsumingUseKlass(_ k: Klass) {}
|
| 27 | +public func nonConsumingUseKlass2(_ k: Klass2) {} |
| 28 | + |
| 29 | +@_moveOnly |
| 30 | +public struct NonTrivialStruct2 { |
| 31 | + var k = Klass() |
| 32 | +} |
| 33 | + |
| 34 | +public func nonConsumingUseNonTrivialStruct2(_ s: NonTrivialStruct2) {} |
24 | 35 |
|
25 | 36 | @_moveOnly
|
26 | 37 | public struct NonTrivialStruct {
|
27 | 38 | var k = Klass()
|
| 39 | + var k2 = NonTrivialStruct2() |
28 | 40 | }
|
29 | 41 |
|
30 | 42 | public func nonConsumingUseNonTrivialStruct(_ s: NonTrivialStruct) {}
|
@@ -243,3 +255,143 @@ func blackHoleVarInitialization2() {
|
243 | 255 | x = Klass()
|
244 | 256 | var _ = x
|
245 | 257 | }
|
| 258 | + |
| 259 | +//////////////////////////////// |
| 260 | +// Borrow Function Call Tests // |
| 261 | +//////////////////////////////// |
| 262 | + |
| 263 | +// CHECK-LABEL: sil hidden [ossa] @$s8moveonly24borrowObjectFunctionCallyyF : $@convention(thin) () -> () { |
| 264 | +// CHECK: [[CLS:%.*]] = mark_must_check [no_implicit_copy] |
| 265 | +// CHECK: [[BORROW:%.*]] = begin_borrow [[CLS]] |
| 266 | +// CHECK: [[FN:%.*]] = function_ref @$s8moveonly20nonConsumingUseKlassyyAA0E0CF |
| 267 | +// CHECK: apply [[FN]]([[BORROW]]) |
| 268 | +// CHECK: end_borrow [[BORROW]] |
| 269 | +// CHECK: } // end sil function '$s8moveonly24borrowObjectFunctionCallyyF' |
| 270 | +func borrowObjectFunctionCall() { |
| 271 | + let k = Klass() |
| 272 | + nonConsumingUseKlass(k) |
| 273 | +} |
| 274 | + |
| 275 | +// CHECK-LABEL: sil hidden [ossa] @$s8moveonly25borrowAddressFunctionCallyyF : $@convention(thin) () -> () { |
| 276 | +// CHECK: [[BOX:%.*]] = mark_must_check [no_implicit_copy] |
| 277 | +// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[BOX]] |
| 278 | +// CHECK: [[BORROW:%.*]] = load_borrow [[ACCESS]] |
| 279 | +// CHECK: [[FN:%.*]] = function_ref @$s8moveonly20nonConsumingUseKlassyyAA0E0CF |
| 280 | +// CHECK: apply [[FN]]([[BORROW]]) |
| 281 | +// CHECK: end_borrow [[BORROW]] |
| 282 | +// CHECK: end_access [[ACCESS]] |
| 283 | +// CHECK: } // end sil function '$s8moveonly25borrowAddressFunctionCallyyF' |
| 284 | +func borrowAddressFunctionCall() { |
| 285 | + var k = Klass() |
| 286 | + k = Klass() |
| 287 | + nonConsumingUseKlass(k) |
| 288 | +} |
| 289 | + |
| 290 | +// We currently have the wrong behavior here since the class is treated by |
| 291 | +// LValue emission as a base. That being said, move only classes are not our |
| 292 | +// high order bit here, so I filed: ...; |
| 293 | +// |
| 294 | +// CHECK-LABEL: sil hidden [ossa] @$s8moveonly31klassBorrowAddressFunctionCall2yyF : $@convention(thin) () -> () { |
| 295 | +// CHECK: [[MARK:%.*]] = mark_must_check [no_implicit_copy] |
| 296 | +// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[MARK]] |
| 297 | +// CHECK: } // end sil function '$s8moveonly31klassBorrowAddressFunctionCall2yyF' |
| 298 | +func klassBorrowAddressFunctionCall2() { |
| 299 | + var k = Klass() |
| 300 | + k = Klass() |
| 301 | + nonConsumingUseKlass2(k.klsField) |
| 302 | +} |
| 303 | + |
| 304 | +// CHECK-LABEL: sil hidden [ossa] @$s8moveonly31structBorrowObjectFunctionCall1yyF : $@convention(thin) () -> () { |
| 305 | +// CHECK: [[VALUE:%.*]] = mark_must_check [no_implicit_copy] |
| 306 | +// CHECK: [[BORROW:%.*]] = begin_borrow [[VALUE]] |
| 307 | +// CHECK: [[FN:%.*]] = function_ref @$s8moveonly31nonConsumingUseNonTrivialStructyyAA0efG0VF : $@convention(thin) (@guaranteed NonTrivialStruct) -> () |
| 308 | +// CHECK: apply [[FN]]([[BORROW]]) |
| 309 | +// CHECK: end_borrow [[BORROW]] |
| 310 | +// CHECK: [[BORROW:%.*]] = begin_borrow [[VALUE]] |
| 311 | +// CHECK: [[STRUCT_EXT:%.*]] = struct_extract [[BORROW]] |
| 312 | +// CHECK: [[STRUCT_EXT_COPY:%.*]] = copy_value [[STRUCT_EXT]] |
| 313 | +// TODO: Should we insert a mark_must_check_here? |
| 314 | +// CHECK: [[FN:%.*]] = function_ref @$s8moveonly20nonConsumingUseKlassyyAA0E0CF |
| 315 | +// CHECK: apply [[FN]]([[STRUCT_EXT_COPY]]) |
| 316 | +// CHECK: destroy_value [[STRUCT_EXT_COPY]] |
| 317 | +// CHECK: end_borrow [[BORROW]] |
| 318 | +// CHECK: [[BORROW:%.*]] = begin_borrow [[VALUE]] |
| 319 | +// CHECK: [[STRUCT_EXT:%.*]] = struct_extract [[BORROW]] |
| 320 | +// CHECK: [[STRUCT_EXT_COPY:%.*]] = copy_value [[STRUCT_EXT]] |
| 321 | +// CHECK: [[STRUCT_EXT_COPY_BORROW:%.*]] = begin_borrow [[STRUCT_EXT_COPY]] |
| 322 | +// CHECK: [[METHOD:%.*]] = class_method [[STRUCT_EXT_COPY_BORROW]] |
| 323 | +// CHECK: [[KLS2:%.*]] = apply [[METHOD]]([[STRUCT_EXT_COPY_BORROW]]) |
| 324 | +// CHECK: end_borrow [[STRUCT_EXT_COPY_BORROW]] |
| 325 | +// CHECK: [[BORROWED_KLS2:%.*]] = begin_borrow [[KLS2]] |
| 326 | +// CHECK: [[FN:%.*]] = function_ref @$s8moveonly21nonConsumingUseKlass2yyAA0E0CF |
| 327 | +// CHECK: apply [[FN]]([[BORROWED_KLS2]]) |
| 328 | +// CHECK: destroy_value [[STRUCT_EXT_COPY]] |
| 329 | +// CHECK: destroy_value [[KLS2]] |
| 330 | +// CHECK: end_borrow [[BORROW]] |
| 331 | +// CHECK: destroy_value [[VALUE]] |
| 332 | +// CHECK: } // end sil function '$s8moveonly31structBorrowObjectFunctionCall1yyF' |
| 333 | +func structBorrowObjectFunctionCall1() { |
| 334 | + let k = NonTrivialStruct() |
| 335 | + nonConsumingUseNonTrivialStruct(k) |
| 336 | + nonConsumingUseKlass(k.k) |
| 337 | + nonConsumingUseKlass2(k.k.klsField) |
| 338 | +} |
| 339 | + |
| 340 | +// CHECK-LABEL: sil hidden [ossa] @$s8moveonly31structBorrowObjectFunctionCall2yyF : $@convention(thin) () -> () { |
| 341 | +// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [no_implicit_copy] |
| 342 | +// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[MARKED_ADDR]] |
| 343 | +// CHECK: [[BORROW:%.*]] = load_borrow [[ACCESS]] |
| 344 | +// CHECK: [[FN:%.*]] = function_ref @$s8moveonly31nonConsumingUseNonTrivialStructyyAA0efG0VF : |
| 345 | +// CHECK: apply [[FN]]([[BORROW]]) |
| 346 | +// CHECK: end_borrow [[BORROW]] |
| 347 | +// CHECK: end_access [[ACCESS]] |
| 348 | +// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[MARKED_ADDR]] |
| 349 | +// CHECK: [[STRUCT_EXT:%.*]] = struct_element_addr [[ACCESS]] |
| 350 | +// CHECK: [[BORROW:%.*]] = load_borrow [[STRUCT_EXT]] |
| 351 | +// CHECK: [[FN:%.*]] = function_ref @$s8moveonly20nonConsumingUseKlassyyAA0E0CF |
| 352 | +// CHECK: apply [[FN]]([[BORROW]]) |
| 353 | +// CHECK: end_borrow [[BORROW]] |
| 354 | +// CHECK: end_access [[ACCESS]] |
| 355 | +// |
| 356 | +// This case we fail due to the class being a base element. We need to use the |
| 357 | +// scope expansion approach to handle this. |
| 358 | +// |
| 359 | +// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[MARKED_ADDR]] |
| 360 | +// CHECK: [[STRUCT_EXT:%.*]] = struct_element_addr [[ACCESS]] |
| 361 | +// CHECK: [[STRUCT_EXT_COPY:%.*]] = load [copy] [[STRUCT_EXT]] |
| 362 | +// CHECK: end_access [[ACCESS]] |
| 363 | +// CHECK: [[STRUCT_EXT_COPY_BORROW:%.*]] = begin_borrow [[STRUCT_EXT_COPY]] |
| 364 | +// CHECK: [[METHOD:%.*]] = class_method [[STRUCT_EXT_COPY_BORROW]] |
| 365 | +// CHECK: [[KLS:%.*]] = apply [[METHOD]]([[STRUCT_EXT_COPY_BORROW]]) |
| 366 | +// CHECK: end_borrow [[STRUCT_EXT_COPY_BORROW]] |
| 367 | +// CHECK: [[BORROWED_KLS:%.*]] = begin_borrow [[KLS]] |
| 368 | +// CHECK: [[FN:%.*]] = function_ref @$s8moveonly21nonConsumingUseKlass2yyAA0E0CF |
| 369 | +// CHECK: apply [[FN]]([[BORROWED_KLS]]) |
| 370 | +// CHECK: end_borrow [[BORROWED_KLS]] |
| 371 | +// CHECK: destroy_value [[STRUCT_EXT_COPY]] |
| 372 | +// CHECK: destroy_value [[KLS]] |
| 373 | +// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[MARKED_ADDR]] |
| 374 | +// CHECK: [[GEP:%.*]] = struct_element_addr [[ACCESS]] : $*NonTrivialStruct, #NonTrivialStruct.k2 |
| 375 | +// CHECK: [[BORROW:%.*]] = load_borrow [[GEP]] |
| 376 | +// CHECK: [[FN:%.*]] = function_ref @$s8moveonly32nonConsumingUseNonTrivialStruct2yyAA0efG0VF : $@convention(thin) (@guaranteed NonTrivialStruct2) -> () |
| 377 | +// CHECK: apply [[FN]]([[BORROW]]) |
| 378 | +// CHECK: end_borrow [[BORROW]] |
| 379 | +// CHECK: end_access [[ACCESS]] |
| 380 | +// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[MARKED_ADDR]] |
| 381 | +// CHECK: [[GEP1:%.*]] = struct_element_addr [[ACCESS]] : $*NonTrivialStruct, #NonTrivialStruct.k2 |
| 382 | +// CHECK: [[GEP2:%.*]] = struct_element_addr [[GEP1]] : $*NonTrivialStruct2, #NonTrivialStruct2.k |
| 383 | +// CHECK: [[BORROW:%.*]] = load_borrow [[GEP2]] |
| 384 | +// CHECK: [[FN:%.*]] = function_ref @$s8moveonly20nonConsumingUseKlassyyAA0E0CF : $@convention(thin) (@guaranteed Klass) -> () |
| 385 | +// CHECK: apply [[FN]]([[BORROW]]) |
| 386 | +// CHECK: end_borrow [[BORROW]] |
| 387 | +// CHECK: end_access [[ACCESS]] |
| 388 | +// CHECK: } // end sil function '$s8moveonly31structBorrowObjectFunctionCall2yyF' |
| 389 | +func structBorrowObjectFunctionCall2() { |
| 390 | + var k = NonTrivialStruct() |
| 391 | + k = NonTrivialStruct() |
| 392 | + nonConsumingUseNonTrivialStruct(k) |
| 393 | + nonConsumingUseKlass(k.k) |
| 394 | + nonConsumingUseKlass2(k.k.klsField) |
| 395 | + nonConsumingUseNonTrivialStruct2(k.k2) |
| 396 | + nonConsumingUseKlass(k.k2.k) |
| 397 | +} |
0 commit comments