| // RUN: %target-sil-opt -enable-objc-interop -enforce-exclusivity=none -enable-sil-verify-all %s -simplify-cfg | %FileCheck %s |
| |
| // REQUIRES: objc_interop |
| |
| import Swift |
| import Foundation |
| |
| class Test : NSObject { |
| @objc var other : Test? { get set } |
| } |
| |
| |
| // CHECK-LABEL: sil hidden @one_call : $@convention(thin) (@guaranteed Optional<Test>, @guaranteed Optional<Test>) -> () { |
| // CHECK: bb0([[ARG0:%.*]] : $Optional<Test>, [[ARG1:%.*]] : $Optional<Test>): |
| // CHECK: switch_enum [[ARG0]] : $Optional<Test>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb3 |
| // CHECK: bb1([[ARG0_PAYLOAD:%.*]] : $Test): |
| // CHECK: [[ARG1_PAYLOAD:%.*]] = unchecked_ref_cast [[ARG1]] : $Optional<Test> to $Test |
| // CHECK: [[GETTER:%.*]] = objc_method [[ARG1_PAYLOAD]] : $Test, #Test.other!getter.1.foreign |
| // CHECK: [[RESULT:%.*]] = apply [[GETTER]]([[ARG1_PAYLOAD]]) |
| // CHECK: [[SETTER:%.*]] = objc_method [[ARG0_PAYLOAD]] : $Test, #Test.other!setter.1.foreign : (Test) -> (Test?) -> (), $@convention(objc_method) (Optional<Test>, Test) -> () |
| // CHECK: apply [[SETTER]]([[RESULT]], [[ARG0_PAYLOAD]]) |
| // CHECK: br bb2 |
| // CHECK: bb2: |
| // CHECK: return |
| // CHECK: bb3: |
| // CHECK: br bb2 |
| // CHECK: } |
| |
| sil hidden @one_call : $@convention(thin) (@guaranteed Optional<Test>, @guaranteed Optional<Test>) -> () { |
| bb0(%0 : $Optional<Test>, %1 : $Optional<Test>): |
| retain_value %0 : $Optional<Test> |
| switch_enum %0 : $Optional<Test>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb6 |
| |
| bb1(%6 : $Test): |
| retain_value %1 : $Optional<Test> |
| switch_enum %1 : $Optional<Test>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb5 |
| |
| bb2(%9 : $Test): |
| %10 = objc_method %9 : $Test, #Test.other!getter.1.foreign : (Test) -> () -> Test?, $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| %11 = apply %10(%9) : $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| strong_release %9 : $Test |
| br bb3(%11 : $Optional<Test>) |
| |
| bb3(%14 : $Optional<Test>): |
| %15 = objc_method %6 : $Test, #Test.other!setter.1.foreign : (Test) -> (Test?) -> (), $@convention(objc_method) (Optional<Test>, Test) -> () |
| %16 = apply %15(%14, %6) : $@convention(objc_method) (Optional<Test>, Test) -> () |
| release_value %14 : $Optional<Test> |
| strong_release %6 : $Test |
| %19 = tuple () |
| br bb4 |
| |
| bb4: |
| %23 = tuple () |
| return %23 : $() |
| |
| bb5: |
| %25 = enum $Optional<Test>, #Optional.none!enumelt |
| br bb3(%25 : $Optional<Test>) |
| |
| bb6: |
| br bb4 |
| } |
| |
| // CHECK-LABEL: sil hidden @one_call2 : $@convention(thin) (@guaranteed Optional<Test>, @guaranteed Optional<Test>) -> () { |
| // CHECK: bb0([[ARG0:%.*]] : $Optional<Test>, [[ARG1:%.*]] : $Optional<Test>): |
| // CHECK: switch_enum [[ARG0]] : $Optional<Test>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb3 |
| // CHECK: bb1([[ARG0_PAYLOAD:%.*]] : $Test): |
| // CHECK: [[ARG1_PAYLOAD:%.*]] = unchecked_ref_cast [[ARG1]] : $Optional<Test> to $Test |
| // CHECK: [[GETTER:%.*]] = objc_method [[ARG1_PAYLOAD]] : $Test, #Test.other!getter.1.foreign |
| // CHECK: [[RESULT:%.*]] = apply [[GETTER]]([[ARG1_PAYLOAD]]) |
| // CHECK: [[SETTER:%.*]] = objc_method [[ARG0_PAYLOAD]] : $Test, #Test.other!setter.1.foreign : (Test) -> (Test?) -> (), $@convention(objc_method) (Optional<Test>, Test) -> () |
| // CHECK: apply [[SETTER]]([[RESULT]], [[ARG0_PAYLOAD]]) |
| // CHECK: br bb2 |
| // CHECK: bb2: |
| // CHECK: return |
| // CHECK: bb3: |
| // CHECK: br bb2 |
| // CHECK: } |
| |
| sil hidden @one_call2 : $@convention(thin) (@guaranteed Optional<Test>, @guaranteed Optional<Test>) -> () { |
| bb0(%0 : $Optional<Test>, %1 : $Optional<Test>): |
| retain_value %0 : $Optional<Test> |
| switch_enum %0 : $Optional<Test>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb6 |
| |
| bb1(%6 : $Test): |
| retain_value %1 : $Optional<Test> |
| switch_enum %1 : $Optional<Test>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb5 |
| |
| bb2: |
| %9 = unchecked_enum_data %1 : $Optional<Test>, #Optional.some!enumelt.1 |
| %10 = objc_method %9 : $Test, #Test.other!getter.1.foreign : (Test) -> () -> Test?, $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| %11 = apply %10(%9) : $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| strong_release %9 : $Test |
| br bb3(%11 : $Optional<Test>) |
| |
| bb3(%14 : $Optional<Test>): |
| %15 = objc_method %6 : $Test, #Test.other!setter.1.foreign : (Test) -> (Test?) -> (), $@convention(objc_method) (Optional<Test>, Test) -> () |
| %16 = apply %15(%14, %6) : $@convention(objc_method) (Optional<Test>, Test) -> () |
| release_value %14 : $Optional<Test> |
| strong_release %6 : $Test |
| %19 = tuple () |
| br bb4 |
| |
| bb4: |
| %23 = tuple () |
| return %23 : $() |
| |
| bb5: |
| %25 = enum $Optional<Test>, #Optional.none!enumelt |
| br bb3(%25 : $Optional<Test>) |
| |
| bb6: |
| br bb4 |
| } |
| sil @some_sideeffect : $@convention(thin) () -> () |
| |
| // CHECK-LABEL: sil hidden @sideeffect |
| // CHECK: switch_enum |
| // CHECK: switch_enum |
| // CHECK: } |
| sil hidden @sideeffect : $@convention(thin) (@guaranteed Optional<Test>, @guaranteed Optional<Test>) -> () { |
| bb0(%0 : $Optional<Test>, %1 : $Optional<Test>): |
| retain_value %0 : $Optional<Test> |
| switch_enum %0 : $Optional<Test>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb6 |
| |
| bb1(%6 : $Test): |
| retain_value %1 : $Optional<Test> |
| switch_enum %1 : $Optional<Test>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb5 |
| |
| bb2(%9 : $Test): |
| %10 = objc_method %9 : $Test, #Test.other!getter.1.foreign : (Test) -> () -> Test?, $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| %11 = apply %10(%9) : $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| strong_release %9 : $Test |
| %12 = function_ref @some_sideeffect : $@convention(thin) () -> () |
| apply %12() : $@convention(thin) () -> () |
| br bb3(%11 : $Optional<Test>) |
| |
| bb3(%14 : $Optional<Test>): |
| %15 = objc_method %6 : $Test, #Test.other!setter.1.foreign : (Test) -> (Test?) -> (), $@convention(objc_method) (Optional<Test>, Test) -> () |
| %16 = apply %15(%14, %6) : $@convention(objc_method) (Optional<Test>, Test) -> () |
| release_value %14 : $Optional<Test> |
| strong_release %6 : $Test |
| %19 = tuple () |
| br bb4 |
| |
| bb4: |
| %23 = tuple () |
| return %23 : $() |
| |
| bb5: |
| %25 = enum $Optional<Test>, #Optional.none!enumelt |
| br bb3(%25 : $Optional<Test>) |
| |
| bb6: |
| br bb4 |
| } |
| |
| // CHECK-LABEL: sil hidden @sideeffect2 |
| // CHECK: switch_enum |
| // CHECK: switch_enum |
| // CHECK: } |
| sil hidden @sideeffect2 : $@convention(thin) (@guaranteed Optional<Test>, @guaranteed Optional<Test>) -> () { |
| bb0(%0 : $Optional<Test>, %1 : $Optional<Test>): |
| retain_value %0 : $Optional<Test> |
| switch_enum %0 : $Optional<Test>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb6 |
| |
| bb1(%6 : $Test): |
| retain_value %1 : $Optional<Test> |
| switch_enum %1 : $Optional<Test>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb5 |
| |
| bb2(%9 : $Test): |
| %10 = objc_method %9 : $Test, #Test.other!getter.1.foreign : (Test) -> () -> Test?, $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| %11 = apply %10(%9) : $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| strong_release %9 : $Test |
| br bb3(%11 : $Optional<Test>) |
| |
| bb3(%14 : $Optional<Test>): |
| %15 = objc_method %6 : $Test, #Test.other!setter.1.foreign : (Test) -> (Test?) -> (), $@convention(objc_method) (Optional<Test>, Test) -> () |
| %16 = apply %15(%14, %6) : $@convention(objc_method) (Optional<Test>, Test) -> () |
| release_value %14 : $Optional<Test> |
| strong_release %6 : $Test |
| %19 = tuple () |
| br bb4 |
| |
| bb4: |
| %23 = tuple () |
| return %23 : $() |
| |
| bb5: |
| %12 = function_ref @some_sideeffect : $@convention(thin) () -> () |
| apply %12() : $@convention(thin) () -> () |
| %25 = enum $Optional<Test>, #Optional.none!enumelt |
| br bb3(%25 : $Optional<Test>) |
| |
| bb6: |
| br bb4 |
| } |
| |
| // CHECK-LABEL: sil hidden @not_on_optional |
| // CHECK: switch_enum |
| // CHECK: switch_enum |
| // CHECK: } |
| sil hidden @not_on_optional : $@convention(thin) (@guaranteed Optional<Test>, @guaranteed Optional<Test>) -> () { |
| bb0(%0 : $Optional<Test>, %1 : $Optional<Test>): |
| retain_value %0 : $Optional<Test> |
| switch_enum %0 : $Optional<Test>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb6 |
| |
| bb1(%6 : $Test): |
| retain_value %1 : $Optional<Test> |
| switch_enum %1 : $Optional<Test>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb5 |
| |
| bb2(%9 : $Test): |
| %10 = objc_method %9 : $Test, #Test.other!getter.1.foreign : (Test) -> () -> Test?, $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| %11 = apply %10(%6) : $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| strong_release %9 : $Test |
| br bb3(%11 : $Optional<Test>) |
| |
| bb3(%14 : $Optional<Test>): |
| %15 = objc_method %6 : $Test, #Test.other!setter.1.foreign : (Test) -> (Test?) -> (), $@convention(objc_method) (Optional<Test>, Test) -> () |
| %16 = apply %15(%14, %6) : $@convention(objc_method) (Optional<Test>, Test) -> () |
| release_value %14 : $Optional<Test> |
| strong_release %6 : $Test |
| %19 = tuple () |
| br bb4 |
| |
| bb4: |
| %23 = tuple () |
| return %23 : $() |
| |
| bb5: |
| %25 = enum $Optional<Test>, #Optional.none!enumelt |
| br bb3(%25 : $Optional<Test>) |
| |
| bb6: |
| br bb4 |
| } |
| |
| // CHECK-LABEL: sil hidden @forwards_wrong_value |
| // CHECK: switch_enum |
| // CHECK: switch_enum |
| // CHECK: } |
| sil hidden @forwards_wrong_value : $@convention(thin) (@guaranteed Optional<Test>, @guaranteed Optional<Test>) -> () { |
| bb0(%0 : $Optional<Test>, %1 : $Optional<Test>): |
| retain_value %0 : $Optional<Test> |
| switch_enum %0 : $Optional<Test>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb6 |
| |
| bb1(%6 : $Test): |
| retain_value %1 : $Optional<Test> |
| switch_enum %1 : $Optional<Test>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb5 |
| |
| bb2(%9 : $Test): |
| %10 = objc_method %9 : $Test, #Test.other!getter.1.foreign : (Test) -> () -> Test?, $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| %11 = apply %10(%9) : $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| strong_release %9 : $Test |
| br bb3(%0 : $Optional<Test>) |
| |
| bb3(%14 : $Optional<Test>): |
| %15 = objc_method %6 : $Test, #Test.other!setter.1.foreign : (Test) -> (Test?) -> (), $@convention(objc_method) (Optional<Test>, Test) -> () |
| %16 = apply %15(%14, %6) : $@convention(objc_method) (Optional<Test>, Test) -> () |
| release_value %14 : $Optional<Test> |
| strong_release %6 : $Test |
| %19 = tuple () |
| br bb4 |
| |
| bb4: |
| %23 = tuple () |
| return %23 : $() |
| |
| bb5: |
| %25 = enum $Optional<Test>, #Optional.none!enumelt |
| br bb3(%25 : $Optional<Test>) |
| |
| bb6: |
| br bb4 |
| } |
| |
| // CHECK-LABEL: sil hidden @forwards_wrong_value2 |
| // CHECK: switch_enum |
| // CHECK: switch_enum |
| // CHECK: } |
| sil hidden @forwards_wrong_value2 : $@convention(thin) (@guaranteed Optional<Test>, @guaranteed Optional<Test>) -> () { |
| bb0(%0 : $Optional<Test>, %1 : $Optional<Test>): |
| retain_value %0 : $Optional<Test> |
| switch_enum %0 : $Optional<Test>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb6 |
| |
| bb1(%6 : $Test): |
| retain_value %1 : $Optional<Test> |
| switch_enum %1 : $Optional<Test>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb5 |
| |
| bb2(%9 : $Test): |
| %10 = objc_method %9 : $Test, #Test.other!getter.1.foreign : (Test) -> () -> Test?, $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| %11 = apply %10(%9) : $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| strong_release %9 : $Test |
| br bb3(%11 : $Optional<Test>) |
| |
| bb3(%14 : $Optional<Test>): |
| %15 = objc_method %6 : $Test, #Test.other!setter.1.foreign : (Test) -> (Test?) -> (), $@convention(objc_method) (Optional<Test>, Test) -> () |
| %16 = apply %15(%14, %6) : $@convention(objc_method) (Optional<Test>, Test) -> () |
| release_value %14 : $Optional<Test> |
| strong_release %6 : $Test |
| %19 = tuple () |
| br bb4 |
| |
| bb4: |
| %23 = tuple () |
| return %23 : $() |
| |
| bb5: |
| br bb3(%0 : $Optional<Test>) |
| |
| bb6: |
| br bb4 |
| } |
| |
| // CHECK-LABEL: sil hidden @two_chained_calls |
| // CHECK: bb0([[ARG0:%.*]] : $Optional<Test>, [[ARG1:%.*]] : $Optional<Test>): |
| // CHECK: switch_enum [[ARG0]] |
| // CHECK: bb1([[ARG0_PAYLOAD:%.*]] : $Test): |
| // CHECK: [[PAYLOAD:%.*]] = unchecked_ref_cast [[ARG1]] |
| // CHECK: [[METH:%.*]] = objc_method [[PAYLOAD]] : $Test, #Test.other!getter.1.foreign |
| // CHECK: [[RESULT:%.*]] = apply [[METH]]([[PAYLOAD]]) |
| // CHECK: [[PAYLOAD2:%.*]] = unchecked_ref_cast [[RESULT]] |
| // CHECK: [[METH2:%.*]] = objc_method [[PAYLOAD2]] : $Test, #Test.other!getter.1.foreign |
| // CHECK: [[RESULT2:%.*]] = apply [[METH2]]([[PAYLOAD2]]) |
| // CHECK: [[SETTER:%.*]] = objc_method [[ARG0_PAYLOAD]] : $Test, #Test.other!setter.1.foreign |
| // CHECK: apply [[SETTER]]([[RESULT2]], [[ARG0_PAYLOAD]]) : $@convention(objc_method) (Optional<Test>, Test) -> () |
| // CHECK: br bb2 |
| // CHECK: bb2: |
| // CHECK: return |
| // CHECK: bb3: |
| // CHECK: br bb2 |
| // CHECK: } |
| |
| sil hidden @two_chained_calls : $@convention(thin) (@guaranteed Optional<Test>, @guaranteed Optional<Test>) -> () { |
| bb0(%0 : $Optional<Test>, %1 : $Optional<Test>): |
| retain_value %0 : $Optional<Test> |
| switch_enum %0 : $Optional<Test>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb9 |
| |
| bb1(%6 : $Test): |
| retain_value %1 : $Optional<Test> |
| switch_enum %1 : $Optional<Test>, case #Optional.some!enumelt.1: bb3, case #Optional.none!enumelt: bb2 |
| |
| bb2: |
| br bb8 |
| |
| bb3(%10 : $Test): |
| %11 = objc_method %10 : $Test, #Test.other!getter.1.foreign : (Test) -> () -> Test?, $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| %12 = apply %11(%10) : $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| switch_enum %12 : $Optional<Test>, case #Optional.none!enumelt: bb4, case #Optional.some!enumelt.1: bb5 |
| |
| bb4: |
| release_value %12 : $Optional<Test> |
| strong_release %10 : $Test |
| br bb8 |
| |
| bb5: |
| %17 = unchecked_enum_data %12 : $Optional<Test>, #Optional.some!enumelt.1 |
| strong_retain %17 : $Test |
| release_value %12 : $Optional<Test> |
| strong_release %10 : $Test |
| %21 = objc_method %17 : $Test, #Test.other!getter.1.foreign : (Test) -> () -> Test?, $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| %22 = apply %21(%17) : $@convention(objc_method) (Test) -> @autoreleased Optional<Test> |
| strong_release %17 : $Test |
| br bb6(%22 : $Optional<Test>) |
| |
| bb6(%25 : $Optional<Test>): |
| %26 = objc_method %6 : $Test, #Test.other!setter.1.foreign : (Test) -> (Test?) -> (), $@convention(objc_method) (Optional<Test>, Test) -> () |
| %27 = apply %26(%25, %6) : $@convention(objc_method) (Optional<Test>, Test) -> () |
| release_value %25 : $Optional<Test> |
| strong_release %6 : $Test |
| br bb7 |
| |
| bb7: |
| %31 = tuple () |
| return %31 : $() |
| |
| bb8: |
| %33 = enum $Optional<Test>, #Optional.none!enumelt |
| br bb6(%33 : $Optional<Test>) |
| |
| bb9: |
| br bb7 |
| } |