blob: 6c384fde3b0614391c7cd0dddd03f569249baf57 [file] [log] [blame]
// 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
}