| // RUN: %target-sil-opt -enable-sil-verify-all %s -mandatory-inlining | %FileCheck %s |
| |
| sil_stage raw |
| |
| import Builtin |
| import Swift |
| |
| class C { |
| var i: Builtin.Int64 |
| init(i: Builtin.Int64) |
| } |
| |
| class Klass {} |
| |
| sil [transparent] [ossa] @calleeWithGuaranteed : $@convention(thin) (@guaranteed C) -> Builtin.Int64 { |
| bb(%0 : @guaranteed $C): |
| %1 = ref_element_addr %0 : $C, #C.i |
| %2 = load [trivial] %1 : $*Builtin.Int64 |
| return %2 : $Builtin.Int64 |
| } |
| |
| // CHECK-LABEL: sil [ossa] @callerWithOwned : $@convention(thin) (@owned C) -> Builtin.Int64 { |
| // CHECK: bb0(%0 : @owned $C): |
| // CHECK: [[BORROW:%.*]] = begin_borrow %0 : $C |
| // CHECK: [[ADDR:%.*]] = ref_element_addr [[BORROW]] : $C, #C.i |
| // CHECK: [[VAL:%.*]] = load [trivial] [[ADDR]] : $*Builtin.Int64 |
| // CHECK: end_borrow [[BORROW]] : $C |
| // CHECK: destroy_value %0 : $C |
| // CHECK: return [[VAL]] : $Builtin.Int64 |
| // CHECK-LABEL: } // end sil function 'callerWithOwned' |
| sil [ossa] @callerWithOwned : $@convention(thin) (@owned C) -> Builtin.Int64 { |
| bb(%0 : @owned $C): |
| %fn = function_ref @calleeWithGuaranteed : $@convention(thin) (@guaranteed C) -> Builtin.Int64 |
| %call = apply %fn(%0) : $@convention(thin) (@guaranteed C) -> Builtin.Int64 |
| destroy_value %0 : $C |
| return %call : $Builtin.Int64 |
| } |
| |
| struct MyError : Error {} |
| |
| sil [transparent] [ossa] @calleeWithGuaranteedThrows : $@convention(thin) (@guaranteed C) -> (Builtin.Int64, @error Error) { |
| bb(%0 : @guaranteed $C): |
| %1 = ref_element_addr %0 : $C, #C.i |
| %2 = load [trivial] %1 : $*Builtin.Int64 |
| %3 = integer_literal $Builtin.Int64, 0 |
| %5 = builtin "cmp_eq_Int64"(%2 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1 |
| cond_br %5, bb1, bb2 |
| |
| bb1: |
| %6 = alloc_existential_box $Error, $MyError |
| throw %6 : $Error |
| |
| bb2: |
| return %2 : $Builtin.Int64 |
| } |
| |
| // CHECK-LABEL: sil [ossa] @callerWithThrow : $@convention(thin) (@owned C) -> (Builtin.Int64, @error Error) { |
| // CHECK: bb0(%0 : @owned $C): |
| // CHECK: [[BORROW:%.*]] = begin_borrow %0 : $C |
| // CHECK: [[ADDR:%.*]] = ref_element_addr [[BORROW]] : $C, #C.i |
| // CHECK: [[VAL:%.*]] = load [trivial] [[ADDR]] : $*Builtin.Int64 |
| // CHECK: bb{{.*}}: |
| // CHECK: [[ERR:%.*]] = alloc_existential_box $Error, $MyError |
| // CHECK: end_borrow [[BORROW]] : $C |
| // CHECK: destroy_value %0 : $C |
| // CHECK: throw [[ERR]] : $Error |
| // CHECK: bb{{.*}}: |
| // CHECK: end_borrow [[BORROW]] : $C |
| // CHECK: destroy_value %0 : $C |
| // CHECK: return [[VAL]] : $Builtin.Int64 |
| // CHECK-LABEL: } // end sil function 'callerWithThrow' |
| sil [ossa] @callerWithThrow : $@convention(thin) (@owned C) -> (Builtin.Int64, @error Error) { |
| bb(%0 : @owned $C): |
| %fn = function_ref @calleeWithGuaranteedThrows : $@convention(thin) (@guaranteed C) -> (Builtin.Int64, @error Error) |
| try_apply %fn(%0) : $@convention(thin) (@guaranteed C) -> (Builtin.Int64, @error Error), normal bb1, error bb2 |
| |
| bb1(%4 : $Builtin.Int64): |
| destroy_value %0 : $C |
| return %4 : $Builtin.Int64 |
| |
| bb2(%5 : @owned $Error): |
| destroy_value %0 : $C |
| throw %5 : $Error |
| } |
| |
| // Partial Apply copy_value test. |
| |
| sil @nativeobject_plus : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject |
| sil @partial_apply_user : $@convention(thin) (@owned @callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject) -> () |
| |
| sil [ossa] [transparent] @test_partial_nativeobject_baz : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject { |
| bb0(%0 : @owned $Builtin.NativeObject, %1 : @owned $Builtin.NativeObject): |
| %6 = function_ref @nativeobject_plus : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject |
| %7 = apply %6(%0, %1) : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject |
| return %7 : $Builtin.NativeObject |
| } |
| |
| sil [ossa] [transparent] @test_partial_nativeobject_bar : $@convention(thin) (@owned @callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject { |
| bb0(%0 : @owned $@callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, %1 : @owned $Builtin.NativeObject): |
| %7 = apply %0(%1) : $@callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject |
| return %7 : $Builtin.NativeObject |
| } |
| |
| // CHECK-LABEL: sil [transparent] [ossa] @test_partial_nativeobject_foo : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject { |
| // CHECK: bb0([[ARG:%.*]] : @owned $Builtin.NativeObject): |
| // CHECK: [[FN:%.*]] = function_ref @test_partial_nativeobject_baz : |
| // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] |
| // CHECK: [[ARG_COPY_2:%.*]] = copy_value [[ARG_COPY]] |
| // CHECK: [[PAI:%.*]] = partial_apply [[FN]]([[ARG_COPY]]) |
| // CHECK: [[ARG_COPY_3:%.*]] = copy_value [[ARG]] |
| // CHECK: [[PAI_COPY:%.*]] = copy_value [[PAI]] |
| // CHECK: [[FN2:%.*]] = function_ref @nativeobject_plus : |
| // CHECK: [[RESULT:%.*]] = apply [[FN2]]([[ARG_COPY_3]], [[ARG_COPY_2]]) |
| // CHECK: destroy_value [[PAI_COPY]] |
| // CHECK: [[PAI_COPY_2:%.*]] = copy_value [[PAI]] |
| // CHECK: [[OPAQUE_FN:%.*]] = function_ref @partial_apply_user |
| // CHECK: apply [[OPAQUE_FN]]([[PAI_COPY_2]]) |
| // CHECK: destroy_value [[PAI]] |
| // CHECK: destroy_value [[ARG]] |
| // CHECK: return [[RESULT]] |
| // CHECK: } // end sil function 'test_partial_nativeobject_foo' |
| sil [transparent] [ossa] @test_partial_nativeobject_foo : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %2 = function_ref @test_partial_nativeobject_bar : $@convention(thin) (@owned @callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject |
| %3 = function_ref @test_partial_nativeobject_baz : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject |
| br bb1 |
| |
| bb1: |
| %0copy1 = copy_value %0 : $Builtin.NativeObject |
| %5 = partial_apply %3(%0copy1) : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject |
| br bb2 |
| |
| bb2: |
| %0copy2 = copy_value %0 : $Builtin.NativeObject |
| %5copy1 = copy_value %5 : $@callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject |
| %13 = apply %2(%5copy1, %0copy2) : $@convention(thin) (@owned @callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| %5copy2 = copy_value %5 : $@callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject |
| %15 = function_ref @partial_apply_user : $@convention(thin) (@owned @callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject) -> () |
| apply %15(%5copy2) : $@convention(thin) (@owned @callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject) -> () |
| destroy_value %5 : $@callee_owned (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject |
| destroy_value %0 : $Builtin.NativeObject |
| return %13 : $Builtin.NativeObject |
| } |
| |
| |
| sil [transparent] [ossa] @term_ossa_checked_cast_addr_br_takealways_callee : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %1 = alloc_stack $Builtin.NativeObject |
| %2 = alloc_stack $Klass |
| store %0 to [init] %1 : $*Builtin.NativeObject |
| checked_cast_addr_br take_always Builtin.NativeObject in %1 : $*Builtin.NativeObject to Klass in %2 : $*Klass, bb1, bb2 |
| |
| bb1: |
| destroy_addr %2 : $*Klass |
| br bb3 |
| |
| bb2: |
| br bb3 |
| |
| bb3: |
| dealloc_stack %2 : $*Klass |
| dealloc_stack %1 : $*Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| |
| // CHECK-LABEL: sil [ossa] @term_nonossa_checked_cast_addr_br_takealways_caller : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| // CHECK: bb0([[ARG:%.*]] : |
| // CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]] |
| // CHECK-NEXT: [[SRC_ADDR:%.*]] = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: [[DEST_ADDR:%.*]] = alloc_stack $Klass |
| // CHECK-NEXT: store [[ARG_COPY]] to [init] [[SRC_ADDR]] |
| // CHECK-NEXT: [[RELOADED_ARG:%.*]] = load [take] [[SRC_ADDR]] |
| // CHECK-NEXT: checked_cast_br [[RELOADED_ARG]] : $Builtin.NativeObject to $Klass, [[SUCCESS_BB:bb[0-9]+]], [[FAILURE_BB:bb[0-9]+]] |
| // |
| // ==> On success, we store the value into dest. The destroy is not from the |
| // ==> optimizer, but from the code. |
| // CHECK: [[SUCCESS_BB]]([[CAST_VALUE:%.*]] : |
| // CHECK-NEXT: store [[CAST_VALUE]] to [init] [[DEST_ADDR]] |
| // CHECK-NEXT: destroy_addr [[DEST_ADDR]] |
| // CHECK-NEXT: br [[CONT_BB:bb[0-9]+]] |
| // |
| // ==> take_always implies we destroy in failure |
| // CHECK: [[FAILURE_BB]]([[FAILURE_ARG:%.*]] : |
| // CHECK-NEXT: destroy_value [[FAILURE_ARG]] |
| // CHECK-NEXT: br [[CONT_BB]] |
| // |
| // CHECK: [[CONT_BB]]: |
| // CHECK: destroy_value [[ARG]] |
| // CHECK: } // end sil function 'term_nonossa_checked_cast_addr_br_takealways_caller' |
| sil [ossa] @term_nonossa_checked_cast_addr_br_takealways_caller : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %3 = function_ref @term_ossa_checked_cast_addr_br_takealways_callee : $@convention(thin) (@owned Builtin.NativeObject) -> () |
| %1 = copy_value %0 : $Builtin.NativeObject |
| apply %3(%1) : $@convention(thin) (@owned Builtin.NativeObject) -> () |
| destroy_value %0 : $Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [transparent] [ossa] @term_ossa_checked_cast_addr_br_takeonsuccess_callee : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %1 = alloc_stack $Builtin.NativeObject |
| %2 = alloc_stack $Klass |
| store %0 to [init] %1 : $*Builtin.NativeObject |
| checked_cast_addr_br take_on_success Builtin.NativeObject in %1 : $*Builtin.NativeObject to Klass in %2 : $*Klass, bb1, bb2 |
| |
| bb1: |
| destroy_addr %2 : $*Klass |
| br bb3 |
| |
| bb2: |
| destroy_addr %1 : $*Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| dealloc_stack %2 : $*Klass |
| dealloc_stack %1 : $*Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @checked_cast_addr_br_takeonsuccess_caller : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| // CHECK: bb0([[ARG:%.*]] : |
| // CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]] |
| // CHECK-NEXT: [[SRC_ADDR:%.*]] = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: [[DEST_ADDR:%.*]] = alloc_stack $Klass |
| // CHECK-NEXT: store [[ARG_COPY]] to [init] [[SRC_ADDR]] |
| // CHECK-NEXT: [[RELOADED_ARG:%.*]] = load [take] [[SRC_ADDR]] |
| // CHECK-NEXT: checked_cast_br [[RELOADED_ARG]] : $Builtin.NativeObject to $Klass, [[SUCCESS_BB:bb[0-9]+]], [[FAILURE_BB:bb[0-9]+]] |
| // |
| // CHECK: [[SUCCESS_BB]]([[CAST_VALUE:%.*]] : |
| // ==> On success, we store into dest and destroy dest. |
| // CHECK-NEXT: store [[CAST_VALUE]] to [init] [[DEST_ADDR]] |
| // CHECK-NEXT: destroy_addr [[DEST_ADDR]] |
| // CHECK-NEXT: br [[CONT_BB:bb[0-9]+]] |
| // |
| // ==> Since we are doing a take on success and we failed... store the original |
| // ==> value back into the memory slot. |
| // CHECK: [[FAILURE_BB]]([[FAIL_ARG:%.*]] : |
| // CHECK-NEXT: store [[FAIL_ARG]] to [init] [[SRC_ADDR]] |
| // CHECK-NEXT: destroy_addr [[SRC_ADDR]] |
| // CHECK-NEXT: br [[CONT_BB]] |
| // |
| // CHECK: } // end sil function 'checked_cast_addr_br_takeonsuccess_caller' |
| sil [ossa] @checked_cast_addr_br_takeonsuccess_caller : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %2 = function_ref @term_ossa_checked_cast_addr_br_takeonsuccess_callee : $@convention(thin) (@owned Builtin.NativeObject) -> () |
| %1 = copy_value %0 : $Builtin.NativeObject |
| apply %2(%1) : $@convention(thin) (@owned Builtin.NativeObject) -> () |
| destroy_value %0 : $Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [transparent] [ossa] @term_ossa_checked_cast_addr_br_copyonsuccess_callee : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %1 = alloc_stack $Builtin.NativeObject |
| %2 = alloc_stack $Klass |
| store %0 to [init] %1 : $*Builtin.NativeObject |
| checked_cast_addr_br copy_on_success Builtin.NativeObject in %1 : $*Builtin.NativeObject to Klass in %2 : $*Klass, bb1, bb2 |
| |
| bb1: |
| destroy_addr %2 : $*Klass |
| destroy_addr %1 : $*Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| destroy_addr %1 : $*Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| dealloc_stack %2 : $*Klass |
| dealloc_stack %1 : $*Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @checked_cast_addr_br_copyonsuccess_caller : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| // CHECK: bb0([[ARG:%.*]] : |
| // CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]] |
| // CHECK-NEXT: [[SRC_ADDR:%.*]] = alloc_stack $Builtin.NativeObject |
| // CHECK-NEXT: [[DEST_ADDR:%.*]] = alloc_stack $Klass |
| // CHECK-NEXT: store [[ARG_COPY]] to [init] [[SRC_ADDR]] |
| // CHECK-NEXT: [[RELOADED_ARG:%.*]] = load_borrow [[SRC_ADDR]] |
| // CHECK-NEXT: checked_cast_br [[RELOADED_ARG]] : $Builtin.NativeObject to $Klass, [[SUCCESS_BB:bb[0-9]+]], [[FAILURE_BB:bb[0-9]+]] |
| // |
| // CHECK: [[SUCCESS_BB]]([[CAST_VALUE:%.*]] : @guaranteed |
| // CHECK-NEXT: [[CAST_VALUE_COPY:%.*]] = copy_value [[CAST_VALUE]] |
| // CHECK-NEXT: end_borrow [[CAST_VALUE]] |
| // CHECK-NEXT: end_borrow [[RELOADED_ARG]] |
| // CHECK-NEXT: store [[CAST_VALUE_COPY]] to [init] [[DEST_ADDR]] |
| // CHECK-NEXT: destroy_addr [[DEST_ADDR]] |
| // CHECK-NEXT: destroy_addr [[SRC_ADDR]] |
| // CHECK-NEXT: br [[CONT_BB:bb[0-9]+]] |
| // |
| // CHECK: [[FAILURE_BB]]([[FAILURE_BORROWED_ARG:%.*]] : |
| // CHECK-NEXT: end_borrow [[FAILURE_BORROWED_ARG]] |
| // CHECK-NEXT: end_borrow [[RELOADED_ARG]] |
| // CHECK-NEXT: destroy_addr [[SRC_ADDR]] |
| // CHECK-NEXT: br [[CONT_BB]] |
| // |
| // CHECK: } // end sil function 'checked_cast_addr_br_copyonsuccess_caller' |
| sil [ossa] @checked_cast_addr_br_copyonsuccess_caller : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %1 = function_ref @term_ossa_checked_cast_addr_br_copyonsuccess_callee : $@convention(thin) (@owned Builtin.NativeObject) -> () |
| %2 = copy_value %0 : $Builtin.NativeObject |
| apply %1(%2) : $@convention(thin) (@owned Builtin.NativeObject) -> () |
| destroy_value %0 : $Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |