blob: 9eab992c7a7185f6d8d223fb61f0752d99a03838 [file] [log] [blame]
// RUN: %target-sil-opt -enable-sil-verify-all %s -diagnostic-constant-propagation | %FileCheck %s
// RUN: %target-sil-opt -enable-sil-verify-all %s -performance-constant-propagation | %FileCheck %s
// REQUIRES: objc_interop
sil_stage canonical
import Swift
import Foundation
import Builtin
sil @$ss11AnyHashableVyABxcSHRzlufC : $@convention(method) _0_0 where τ_0_0 : Hashable> (@in τ_0_0, @thin AnyHashable.Type) -> @out AnyHashable
sil @guaranteed_swift_array_user : $@convention(thin) _0_0> (@guaranteed Array_0_0>) -> ()
// CHECK-LABEL: sil @array_downcast_copyonsuccess : $@convention(thin) (@guaranteed NSArray) -> () {
// CHECK: bb0([[ARG:%.*]] : $NSArray):
// CHECK: [[INPUT:%.*]] = alloc_stack $NSArray
// CHECK: retain_value [[ARG]]
// CHECK: store [[ARG]] to [[INPUT]]
// CHECK: [[OUTPUT:%.*]] = alloc_stack $Array<String>
// CHECK: [[INPUT_VALUE:%.*]] = load [[INPUT]]
// CHECK: br [[BRIDGE_BB:bb[0-9]+]]([[INPUT_VALUE]] :
//
// CHECK: [[BRIDGE_BB]]([[INPUT_VALUE:%.*]] : $NSArray):
// CHECK: [[CAST_TMP:%.*]] = alloc_stack $Optional<Array<String>>
// CHECK: strong_retain [[INPUT_VALUE]]
// CHECK: apply {{%.*}}<Array<String>>([[CAST_TMP]], [[INPUT_VALUE]],
// CHECK: strong_release [[INPUT_VALUE]]
// CHECK: switch_enum_addr [[CAST_TMP]] : $*Optional<Array<String>>, case #Optional.some!enumelt.1: [[SUCCESS_TRAMPOLINE_BB:bb[0-9]+]], case #Optional.none!enumelt: [[FAIL_BB:bb[0-9]+]]
//
// CHECK: [[SUCCESS_TRAMPOLINE_BB]]:
// CHECK: [[PROJ_ENUM:%.*]] = unchecked_take_enum_data_addr [[CAST_TMP]]
// CHECK: copy_addr [take] [[PROJ_ENUM]] to [initialization] [[OUTPUT]]
// CHECK: dealloc_stack [[CAST_TMP]]
// CHECK: br [[SUCCESS_BB:bb[0-9]+]]
//
// CHECK: [[SUCCESS_BB]]:
// CHECK: [[SUCCESS_VAL:%.*]] = load [[OUTPUT]]
// CHECK: [[CAST_RESULT:%.*]] = apply {{%.*}}<String>([[SUCCESS_VAL]])
// CHECK-NEXT: release_value [[SUCCESS_VAL]]
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: destroy_addr [[INPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: br [[EXIT_BB:bb[0-9]+]]
//
// CHECK: [[FAIL_BB]]:
// CHECK-NEXT: dealloc_stack [[CAST_TMP:%.*]]
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: destroy_addr [[INPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: br [[EXIT_BB]]
//
// CHECK: [[EXIT_BB]]:
// CHECK: return
//
// CHECK: } // end sil function 'array_downcast_copyonsuccess'
sil @array_downcast_copyonsuccess : $@convention(thin) (@guaranteed NSArray) -> () {
bb0(%0 : $NSArray):
%4 = alloc_stack $NSArray
retain_value %0 : $NSArray
store %0 to %4 : $*NSArray
%7 = alloc_stack $Array<String>
checked_cast_addr_br copy_on_success NSArray in %4 : $*NSArray to Array<String> in %7 : $*Array<String>, bb2, bb3
bb2:
%9 = load %7 : $*Array<String>
%10 = function_ref @guaranteed_swift_array_user : $@convention(thin) _0_0> (@guaranteed Array_0_0>) -> ()
apply %10<String>(%9) : $@convention(thin) _0_0> (@guaranteed Array_0_0>) -> ()
release_value %9 : $Array<String>
dealloc_stack %7 : $*Array<String>
destroy_addr %4 : $*NSArray
dealloc_stack %4 : $*NSArray
br bb4
bb3:
dealloc_stack %7 : $*Array<String>
destroy_addr %4 : $*NSArray
dealloc_stack %4 : $*NSArray
br bb4
bb4:
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @array_downcast_takeonsuccess : $@convention(thin) (@guaranteed NSArray) -> () {
// CHECK: bb0([[ARG:%.*]] : $NSArray):
// CHECK: [[INPUT:%.*]] = alloc_stack $NSArray
// CHECK: retain_value [[ARG]]
// CHECK: store [[ARG]] to [[INPUT]]
// CHECK: [[OUTPUT:%.*]] = alloc_stack $Array<String>
// CHECK: [[INPUT_VALUE:%.*]] = load [[INPUT]]
// CHECK: br [[BRIDGE_BB:bb[0-9]+]]([[INPUT_VALUE]] :
//
// CHECK: [[BRIDGE_BB]]([[INPUT_VALUE:%.*]] : $NSArray):
// CHECK: [[CAST_TMP:%.*]] = alloc_stack $Optional<Array<String>>
// CHECK: strong_retain [[INPUT_VALUE]]
// CHECK: apply {{%.*}}<Array<String>>([[CAST_TMP]], [[INPUT_VALUE]],
// CHECK: strong_release [[INPUT_VALUE]]
// NOTE: In contrast to with take_always, the release_value is above in SUCCESS_BLOCK
// CHECK: switch_enum_addr [[CAST_TMP]] : $*Optional<Array<String>>, case #Optional.some!enumelt.1: [[SUCCESS_TRAMPOLINE_BB:bb[0-9]+]], case #Optional.none!enumelt: [[FAIL_BB:bb[0-9]+]]
//
// CHECK: [[SUCCESS_TRAMPOLINE_BB]]:
// CHECK: [[PROJ_ENUM:%.*]] = unchecked_take_enum_data_addr [[CAST_TMP]]
// CHECK: copy_addr [take] [[PROJ_ENUM]] to [initialization] [[OUTPUT]]
// CHECK: dealloc_stack [[CAST_TMP]]
// CHECK: br [[SUCCESS_BB:bb[0-9]+]]
//
// CHECK: [[SUCCESS_BB]]:
// CHECK: strong_release [[INPUT_VALUE:%.*]] :
// CHECK: [[SUCCESS_VAL:%.*]] = load [[OUTPUT]]
// CHECK: [[CAST_RESULT:%.*]] = apply {{%.*}}<String>([[SUCCESS_VAL]])
// CHECK-NEXT: release_value [[SUCCESS_VAL]]
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: br [[EXIT_BB:bb[0-9]+]]
//
// CHECK: [[FAIL_BB]]:
// CHECK-NEXT: dealloc_stack [[CAST_TMP:%.*]]
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: destroy_addr [[INPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: br [[EXIT_BB]]
//
// CHECK: [[EXIT_BB]]:
// CHECK: return
// CHECK: } // end sil function 'array_downcast_takeonsuccess'
sil @array_downcast_takeonsuccess : $@convention(thin) (@guaranteed NSArray) -> () {
bb0(%0 : $NSArray):
%4 = alloc_stack $NSArray
retain_value %0 : $NSArray
store %0 to %4 : $*NSArray
%7 = alloc_stack $Array<String>
checked_cast_addr_br take_on_success NSArray in %4 : $*NSArray to Array<String> in %7 : $*Array<String>, bb2, bb3
bb2:
%9 = load %7 : $*Array<String>
%10 = function_ref @guaranteed_swift_array_user : $@convention(thin) _0_0> (@guaranteed Array_0_0>) -> ()
apply %10<String>(%9) : $@convention(thin) _0_0> (@guaranteed Array_0_0>) -> ()
release_value %9 : $Array<String>
dealloc_stack %7 : $*Array<String>
dealloc_stack %4 : $*NSArray
br bb4
bb3:
dealloc_stack %7 : $*Array<String>
destroy_addr %4 : $*NSArray
dealloc_stack %4 : $*NSArray
br bb4
bb4:
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @array_downcast_takealways : $@convention(thin) (@guaranteed NSArray) -> () {
// CHECK: bb0([[ARG:%.*]] : $NSArray):
// CHECK: [[INPUT:%.*]] = alloc_stack $NSArray
// CHECK: retain_value [[ARG]]
// CHECK: store [[ARG]] to [[INPUT]]
// CHECK: [[OUTPUT:%.*]] = alloc_stack $Array<String>
// CHECK: [[INPUT_VALUE:%.*]] = load [[INPUT]]
// CHECK: br [[BRIDGE_BB:bb[0-9]+]]([[INPUT_VALUE]] :
//
// CHECK: [[BRIDGE_BB]]([[INPUT_VALUE:%.*]] : $NSArray):
// CHECK: [[CAST_TMP:%.*]] = alloc_stack $Optional<Array<String>>
// CHECK: strong_retain [[INPUT_VALUE]]
// CHECK: apply {{%.*}}<Array<String>>([[CAST_TMP]], [[INPUT_VALUE]],
// CHECK: strong_release [[INPUT_VALUE]]
// NOTE: When we perform take_always, this is the take of the cast.
// CHECK: strong_release [[INPUT_VALUE]]
// CHECK: switch_enum_addr [[CAST_TMP]] : $*Optional<Array<String>>, case #Optional.some!enumelt.1: [[SUCCESS_TRAMPOLINE_BB:bb[0-9]+]], case #Optional.none!enumelt: [[FAIL_BB]]
//
// CHECK: [[SUCCESS_TRAMPOLINE_BB]]:
// CHECK: [[PROJ_ENUM:%.*]] = unchecked_take_enum_data_addr [[CAST_TMP]]
// CHECK: copy_addr [take] [[PROJ_ENUM]] to [initialization] [[OUTPUT]]
// CHECK: dealloc_stack [[CAST_TMP]]
// CHECK: br [[SUCCESS_BB]]
//
//
// CHECK: [[SUCCESS_BB:bb[0-9]+]]:
// CHECK: [[SUCCESS_VAL:%.*]] = load [[OUTPUT]]
// CHECK: [[CAST_RESULT:%.*]] = apply {{%.*}}<String>([[SUCCESS_VAL]])
// CHECK-NEXT: release_value [[SUCCESS_VAL]]
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: br [[EXIT_BB:bb[0-9]+]]
//
// CHECK: [[FAIL_BB:bb[0-9]+]]:
// CHECK-NEXT: dealloc_stack [[CAST_TMP:%.*]]
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: br [[EXIT_BB]]
//
// CHECK: [[EXIT_BB]]:
// CHECK: return
//
// CHECK: } // end sil function 'array_downcast_takealways'
sil @array_downcast_takealways : $@convention(thin) (@guaranteed NSArray) -> () {
bb0(%0 : $NSArray):
%4 = alloc_stack $NSArray
retain_value %0 : $NSArray
store %0 to %4 : $*NSArray
%7 = alloc_stack $Array<String>
checked_cast_addr_br take_always NSArray in %4 : $*NSArray to Array<String> in %7 : $*Array<String>, bb2, bb3
bb2:
%9 = load %7 : $*Array<String>
%10 = function_ref @guaranteed_swift_array_user : $@convention(thin) _0_0> (@guaranteed Array_0_0>) -> ()
apply %10<String>(%9) : $@convention(thin) _0_0> (@guaranteed Array_0_0>) -> ()
release_value %9 : $Array<String>
dealloc_stack %7 : $*Array<String>
dealloc_stack %4 : $*NSArray
br bb4
bb3:
dealloc_stack %7 : $*Array<String>
dealloc_stack %4 : $*NSArray
br bb4
bb4:
%9999 = tuple()
return %9999 : $()
}
// Make sure we handle correctly various sorts of NSObject casts without
// breaking ownership invariants when compiling in ossa.
// CHECK-LABEL: sil @nsobject_test_take_always_string : $@convention(thin) (@owned NSObject) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[INPUT:%.*]] = alloc_stack $NSObject
// CHECK: store [[ARG]] to [[INPUT]] :
// CHECK: [[OUTPUT:%.*]] = alloc_stack $String
// CHECK: br bb1
//
// CHECK: bb1:
// CHECK: [[LOADED_INPUT:%.*]] = load [[INPUT]]
// CHECK: checked_cast_br [[LOADED_INPUT]] : $NSObject to $NSString, [[YES_BB:bb[0-9]+]], [[NO_BB:bb[0-9]+]]
//
// CHECK: [[NO_BB]]:
// CHECK-NEXT: strong_release [[LOADED_INPUT]]
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE:bb[0-9]+]]
//
// CHECK: [[YES_BB]]([[CASTED_INPUT:%.*]] :
// CHECK: [[CAST_RESULT:%.*]] = alloc_stack $Optional<String>
// CHECK: strong_retain [[CASTED_INPUT]]
// CHECK: apply {{%.*}}<String>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) :
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional<String>, case #Optional.some!enumelt.1: [[COND_CAST_SUCC:bb[0-9]+]], case #Optional.none!enumelt: [[COND_CAST_FAIL:bb[0-9]+]]
//
// CHECK: [[COND_CAST_SUCC]]:
// CHECK: [[UNWRAPPED_CAST_RESULT:%.*]] = unchecked_take_enum_data_addr [[CAST_RESULT]]
// CHECK: copy_addr [take] [[UNWRAPPED_CAST_RESULT]] to [initialization] [[OUTPUT]]
// CHECK: dealloc_stack [[CAST_RESULT]]
// CHECK: destroy_addr [[OUTPUT]]
// CHECK: br [[EXIT_BB:bb[0-9]+]]
//
// CHECK: [[COND_CAST_FAIL]]:
// CHECK-NEXT: dealloc_stack
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE]]
//
// CHECK: [[FAIL_EXIT_TRAMPOLINE]]:
// CHECK-NEXT: br [[EXIT_BB]]
//
// CHECK: [[EXIT_BB]]:
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
// CHECK: } // end sil function 'nsobject_test_take_always_string'
sil @nsobject_test_take_always_string : $@convention(thin) (@owned NSObject) -> () {
bb0(%0 : $NSObject):
%nsSource = alloc_stack $NSObject
store %0 to %nsSource : $*NSObject
%stringDest = alloc_stack $String
br bb1
bb1:
checked_cast_addr_br take_always NSObject in %nsSource : $*NSObject to String in %stringDest : $*String, bb2, bb3
bb2:
destroy_addr %stringDest : $*String
br bb4
bb3:
br bb4
bb4:
dealloc_stack %stringDest : $*String
dealloc_stack %nsSource : $*NSObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @nsobject_test_take_on_success_string : $@convention(thin) (@owned NSObject) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[INPUT:%.*]] = alloc_stack $NSObject
// CHECK: store [[ARG]] to [[INPUT]] :
// CHECK: [[OUTPUT:%.*]] = alloc_stack $String
// CHECK: br bb1
//
// CHECK: bb1:
// CHECK: [[LOADED_INPUT:%.*]] = load [[INPUT]]
// CHECK: checked_cast_br [[LOADED_INPUT]] : $NSObject to $NSString, [[YES_BB:bb[0-9]+]], [[NO_BB:bb[0-9]+]]
//
// CHECK: [[NO_BB]]:
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE:bb[0-9]+]]
//
// CHECK: [[YES_BB]]([[CASTED_INPUT:%.*]] :
// CHECK: [[CAST_RESULT:%.*]] = alloc_stack $Optional<String>
// CHECK: strong_retain [[CASTED_INPUT]]
// CHECK: apply {{%.*}}<String>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) :
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK-NOT: strong_release [[CASTED_INPUT]]
// CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional<String>, case #Optional.some!enumelt.1: [[COND_CAST_SUCC:bb[0-9]+]], case #Optional.none!enumelt: [[COND_CAST_FAIL:bb[0-9]+]]
//
// CHECK: [[COND_CAST_SUCC]]:
// CHECK: [[UNWRAPPED_CAST_RESULT:%.*]] = unchecked_take_enum_data_addr [[CAST_RESULT]]
// CHECK: copy_addr [take] [[UNWRAPPED_CAST_RESULT]] to [initialization] [[OUTPUT]]
// CHECK: dealloc_stack [[CAST_RESULT]]
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK: destroy_addr [[OUTPUT]]
// CHECK: br [[EXIT_BB:bb[0-9]+]]
//
// CHECK: [[COND_CAST_FAIL]]:
// CHECK-NEXT: dealloc_stack
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE]]
//
// CHECK: [[FAIL_EXIT_TRAMPOLINE]]:
// CHECK-NEXT: destroy_addr [[INPUT]]
// CHECK-NEXT: br [[EXIT_BB]]
//
// CHECK: [[EXIT_BB]]:
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
// CHECK: } // end sil function 'nsobject_test_take_on_success_string'
sil @nsobject_test_take_on_success_string : $@convention(thin) (@owned NSObject) -> () {
bb0(%0 : $NSObject):
%nsSource = alloc_stack $NSObject
store %0 to %nsSource : $*NSObject
%stringDest = alloc_stack $String
br bb1
bb1:
checked_cast_addr_br take_on_success NSObject in %nsSource : $*NSObject to String in %stringDest : $*String, bb2, bb3
bb2:
destroy_addr %stringDest : $*String
br bb4
bb3:
destroy_addr %nsSource : $*NSObject
br bb4
bb4:
dealloc_stack %stringDest : $*String
dealloc_stack %nsSource : $*NSObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @nsobject_test_copy_on_success_string : $@convention(thin) (@owned NSObject) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[INPUT:%.*]] = alloc_stack $NSObject
// CHECK: store [[ARG]] to [[INPUT]] :
// CHECK: [[OUTPUT:%.*]] = alloc_stack $String
// CHECK: br bb1
//
// CHECK: bb1:
// CHECK: [[LOADED_INPUT:%.*]] = load [[INPUT]]
// CHECK: checked_cast_br [[LOADED_INPUT]] : $NSObject to $NSString, [[YES_BB:bb[0-9]+]], [[NO_BB:bb[0-9]+]]
//
// CHECK: [[NO_BB]]:
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE:bb[0-9]+]]
//
// CHECK: [[YES_BB]]([[CASTED_INPUT:%.*]] :
// CHECK: [[CAST_RESULT:%.*]] = alloc_stack $Optional<String>
// CHECK: strong_retain [[CASTED_INPUT]]
// CHECK: apply {{%.*}}<String>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) :
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK-NOT: strong_release [[CASTED_INPUT]]
// CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional<String>, case #Optional.some!enumelt.1: [[COND_CAST_SUCC:bb[0-9]+]], case #Optional.none!enumelt: [[COND_CAST_FAIL:bb[0-9]+]]
//
// CHECK: [[COND_CAST_SUCC]]:
// CHECK: [[UNWRAPPED_CAST_RESULT:%.*]] = unchecked_take_enum_data_addr [[CAST_RESULT]]
// CHECK: copy_addr [take] [[UNWRAPPED_CAST_RESULT]] to [initialization] [[OUTPUT]]
// CHECK: dealloc_stack [[CAST_RESULT]]
// CHECK: destroy_addr [[OUTPUT]]
// CHECK: destroy_addr [[INPUT]]
// CHECK: br [[EXIT_BB:bb[0-9]+]]
//
// CHECK: [[COND_CAST_FAIL]]:
// CHECK-NEXT: dealloc_stack
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE]]
//
// CHECK: [[FAIL_EXIT_TRAMPOLINE]]:
// CHECK-NEXT: destroy_addr [[INPUT]]
// CHECK-NEXT: br [[EXIT_BB]]
//
// CHECK: [[EXIT_BB]]:
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
// CHECK: } // end sil function 'nsobject_test_copy_on_success_string'
sil @nsobject_test_copy_on_success_string : $@convention(thin) (@owned NSObject) -> () {
bb0(%0 : $NSObject):
%nsSource = alloc_stack $NSObject
store %0 to %nsSource : $*NSObject
%stringDest = alloc_stack $String
br bb1
bb1:
checked_cast_addr_br copy_on_success NSObject in %nsSource : $*NSObject to String in %stringDest : $*String, bb2, bb3
bb2:
destroy_addr %stringDest : $*String
destroy_addr %nsSource : $*NSObject
br bb4
bb3:
destroy_addr %nsSource : $*NSObject
br bb4
bb4:
dealloc_stack %stringDest : $*String
dealloc_stack %nsSource : $*NSObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @nsobject_test_take_always_array_of_any : $@convention(thin) (@owned NSObject) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[INPUT:%.*]] = alloc_stack $NSObject
// CHECK: store [[ARG]] to [[INPUT]] :
// CHECK: [[OUTPUT:%.*]] = alloc_stack $Array<Any>
// CHECK: br bb1
//
// CHECK: bb1:
// CHECK: [[LOADED_INPUT:%.*]] = load [[INPUT]]
// CHECK: checked_cast_br [[LOADED_INPUT]] : $NSObject to $NSArray, [[YES_BB:bb[0-9]+]], [[NO_BB:bb[0-9]+]]
//
// CHECK: [[NO_BB]]:
// CHECK-NEXT: strong_release [[LOADED_INPUT]]
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE:bb[0-9]+]]
//
// CHECK: [[YES_BB]]([[CASTED_INPUT:%.*]] :
// CHECK: [[CAST_RESULT:%.*]] = alloc_stack $Optional<Array<Any>>
// CHECK: strong_retain [[CASTED_INPUT]]
// CHECK: apply {{%.*}}<Array<Any>>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) :
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional<Array<Any>>, case #Optional.some!enumelt.1: [[COND_CAST_SUCC:bb[0-9]+]], case #Optional.none!enumelt: [[COND_CAST_FAIL:bb[0-9]+]]
//
// CHECK: [[COND_CAST_SUCC]]:
// CHECK: [[UNWRAPPED_CAST_RESULT:%.*]] = unchecked_take_enum_data_addr [[CAST_RESULT]]
// CHECK: copy_addr [take] [[UNWRAPPED_CAST_RESULT]] to [initialization] [[OUTPUT]]
// CHECK: dealloc_stack [[CAST_RESULT]]
// CHECK: destroy_addr [[OUTPUT]]
// CHECK: br [[EXIT_BB:bb[0-9]+]]
//
// CHECK: [[COND_CAST_FAIL]]:
// CHECK-NEXT: dealloc_stack
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE]]
//
// CHECK: [[FAIL_EXIT_TRAMPOLINE]]:
// CHECK-NEXT: br [[EXIT_BB]]
//
// CHECK: [[EXIT_BB]]:
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
// CHECK: } // end sil function 'nsobject_test_take_always_array_of_any'
sil @nsobject_test_take_always_array_of_any : $@convention(thin) (@owned NSObject) -> () {
bb0(%0 : $NSObject):
%nsSource = alloc_stack $NSObject
store %0 to %nsSource : $*NSObject
%stringDest = alloc_stack $Array<Any>
br bb1
bb1:
checked_cast_addr_br take_always NSObject in %nsSource : $*NSObject to Array<Any> in %stringDest : $*Array<Any>, bb2, bb3
bb2:
destroy_addr %stringDest : $*Array<Any>
br bb4
bb3:
br bb4
bb4:
dealloc_stack %stringDest : $*Array<Any>
dealloc_stack %nsSource : $*NSObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @nsobject_test_take_on_success_array_of_any : $@convention(thin) (@owned NSObject) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[INPUT:%.*]] = alloc_stack $NSObject
// CHECK: store [[ARG]] to [[INPUT]] :
// CHECK: [[OUTPUT:%.*]] = alloc_stack $Array<Any>
// CHECK: br bb1
//
// CHECK: bb1:
// CHECK: [[LOADED_INPUT:%.*]] = load [[INPUT]]
// CHECK: checked_cast_br [[LOADED_INPUT]] : $NSObject to $NSArray, [[YES_BB:bb[0-9]+]], [[NO_BB:bb[0-9]+]]
//
// CHECK: [[NO_BB]]:
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE:bb[0-9]+]]
//
// CHECK: [[YES_BB]]([[CASTED_INPUT:%.*]] :
// CHECK: [[CAST_RESULT:%.*]] = alloc_stack $Optional<Array<Any>>
// CHECK: strong_retain [[CASTED_INPUT]]
// CHECK: apply {{%.*}}<Array<Any>>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) :
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK-NOT: strong_release [[CASTED_INPUT]]
// CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional<Array<Any>>, case #Optional.some!enumelt.1: [[COND_CAST_SUCC:bb[0-9]+]], case #Optional.none!enumelt: [[COND_CAST_FAIL:bb[0-9]+]]
//
// CHECK: [[COND_CAST_SUCC]]:
// CHECK: [[UNWRAPPED_CAST_RESULT:%.*]] = unchecked_take_enum_data_addr [[CAST_RESULT]]
// CHECK: copy_addr [take] [[UNWRAPPED_CAST_RESULT]] to [initialization] [[OUTPUT]]
// CHECK: dealloc_stack [[CAST_RESULT]]
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK: destroy_addr [[OUTPUT]]
// CHECK: br [[EXIT_BB:bb[0-9]+]]
//
// CHECK: [[COND_CAST_FAIL]]:
// CHECK-NEXT: dealloc_stack
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE]]
//
// CHECK: [[FAIL_EXIT_TRAMPOLINE]]:
// CHECK-NEXT: destroy_addr [[INPUT]]
// CHECK-NEXT: br [[EXIT_BB]]
//
// CHECK: [[EXIT_BB]]:
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
// CHECK: } // end sil function 'nsobject_test_take_on_success_array_of_any'
sil @nsobject_test_take_on_success_array_of_any : $@convention(thin) (@owned NSObject) -> () {
bb0(%0 : $NSObject):
%nsSource = alloc_stack $NSObject
store %0 to %nsSource : $*NSObject
%stringDest = alloc_stack $Array<Any>
br bb1
bb1:
checked_cast_addr_br take_on_success NSObject in %nsSource : $*NSObject to Array<Any> in %stringDest : $*Array<Any>, bb2, bb3
bb2:
destroy_addr %stringDest : $*Array<Any>
br bb4
bb3:
destroy_addr %nsSource : $*NSObject
br bb4
bb4:
dealloc_stack %stringDest : $*Array<Any>
dealloc_stack %nsSource : $*NSObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @nsobject_test_copy_on_success_array_of_any : $@convention(thin) (@owned NSObject) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[INPUT:%.*]] = alloc_stack $NSObject
// CHECK: store [[ARG]] to [[INPUT]] :
// CHECK: [[OUTPUT:%.*]] = alloc_stack $Array<Any>
// CHECK: br bb1
//
// CHECK: bb1:
// CHECK: [[LOADED_INPUT:%.*]] = load [[INPUT]]
// CHECK: checked_cast_br [[LOADED_INPUT]] : $NSObject to $NSArray, [[YES_BB:bb[0-9]+]], [[NO_BB:bb[0-9]+]]
//
// CHECK: [[NO_BB]]:
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE:bb[0-9]+]]
//
// CHECK: [[YES_BB]]([[CASTED_INPUT:%.*]] :
// CHECK: [[CAST_RESULT:%.*]] = alloc_stack $Optional<Array<Any>>
// CHECK: strong_retain [[CASTED_INPUT]]
// CHECK: apply {{%.*}}<Array<Any>>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) :
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK-NOT: strong_release [[CASTED_INPUT]]
// CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional<Array<Any>>, case #Optional.some!enumelt.1: [[COND_CAST_SUCC:bb[0-9]+]], case #Optional.none!enumelt: [[COND_CAST_FAIL:bb[0-9]+]]
//
// CHECK: [[COND_CAST_SUCC]]:
// CHECK: [[UNWRAPPED_CAST_RESULT:%.*]] = unchecked_take_enum_data_addr [[CAST_RESULT]]
// CHECK: copy_addr [take] [[UNWRAPPED_CAST_RESULT]] to [initialization] [[OUTPUT]]
// CHECK: dealloc_stack [[CAST_RESULT]]
// CHECK: destroy_addr [[OUTPUT]]
// CHECK: destroy_addr [[INPUT]]
// CHECK: br [[EXIT_BB:bb[0-9]+]]
//
// CHECK: [[COND_CAST_FAIL]]:
// CHECK-NEXT: dealloc_stack
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE]]
//
// CHECK: [[FAIL_EXIT_TRAMPOLINE]]:
// CHECK-NEXT: destroy_addr [[INPUT]]
// CHECK-NEXT: br [[EXIT_BB]]
//
// CHECK: [[EXIT_BB]]:
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
// CHECK: } // end sil function 'nsobject_test_copy_on_success_array_of_any'
sil @nsobject_test_copy_on_success_array_of_any : $@convention(thin) (@owned NSObject) -> () {
bb0(%0 : $NSObject):
%nsSource = alloc_stack $NSObject
store %0 to %nsSource : $*NSObject
%stringDest = alloc_stack $Array<Any>
br bb1
bb1:
checked_cast_addr_br copy_on_success NSObject in %nsSource : $*NSObject to Array<Any> in %stringDest : $*Array<Any>, bb2, bb3
bb2:
destroy_addr %stringDest : $*Array<Any>
destroy_addr %nsSource : $*NSObject
br bb4
bb3:
destroy_addr %nsSource : $*NSObject
br bb4
bb4:
dealloc_stack %stringDest : $*Array<Any>
dealloc_stack %nsSource : $*NSObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @nsobject_test_take_always_dictionary_anyhashable_to_any : $@convention(thin) (@owned NSObject) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[INPUT:%.*]] = alloc_stack $NSObject
// CHECK: store [[ARG]] to [[INPUT]] :
// CHECK: [[OUTPUT:%.*]] = alloc_stack $Dictionary<AnyHashable, Any>
// CHECK: br bb1
//
// CHECK: bb1:
// CHECK: [[LOADED_INPUT:%.*]] = load [[INPUT]]
// CHECK: checked_cast_br [[LOADED_INPUT]] : $NSObject to $NSDictionary, [[YES_BB:bb[0-9]+]], [[NO_BB:bb[0-9]+]]
//
// CHECK: [[NO_BB]]:
// CHECK-NEXT: strong_release [[LOADED_INPUT]]
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE:bb[0-9]+]]
//
// CHECK: [[YES_BB]]([[CASTED_INPUT:%.*]] :
// CHECK: [[CAST_RESULT:%.*]] = alloc_stack $Optional<Dictionary<AnyHashable, Any>>
// CHECK: strong_retain [[CASTED_INPUT]]
// CHECK: apply {{%.*}}<Dictionary<AnyHashable, Any>>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) :
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional<Dictionary<AnyHashable, Any>>, case #Optional.some!enumelt.1: [[COND_CAST_SUCC:bb[0-9]+]], case #Optional.none!enumelt: [[COND_CAST_FAIL:bb[0-9]+]]
//
// CHECK: [[COND_CAST_SUCC]]:
// CHECK: [[UNWRAPPED_CAST_RESULT:%.*]] = unchecked_take_enum_data_addr [[CAST_RESULT]]
// CHECK: copy_addr [take] [[UNWRAPPED_CAST_RESULT]] to [initialization] [[OUTPUT]]
// CHECK: dealloc_stack [[CAST_RESULT]]
// CHECK: destroy_addr [[OUTPUT]]
// CHECK: br [[EXIT_BB:bb[0-9]+]]
//
// CHECK: [[COND_CAST_FAIL]]:
// CHECK-NEXT: dealloc_stack
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE]]
//
// CHECK: [[FAIL_EXIT_TRAMPOLINE]]:
// CHECK-NEXT: br [[EXIT_BB]]
//
// CHECK: [[EXIT_BB]]:
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
// CHECK: } // end sil function 'nsobject_test_take_always_dictionary_anyhashable_to_any'
sil @nsobject_test_take_always_dictionary_anyhashable_to_any : $@convention(thin) (@owned NSObject) -> () {
bb0(%0 : $NSObject):
%nsSource = alloc_stack $NSObject
store %0 to %nsSource : $*NSObject
%stringDest = alloc_stack $Dictionary<AnyHashable, Any>
br bb1
bb1:
checked_cast_addr_br take_always NSObject in %nsSource : $*NSObject to Dictionary<AnyHashable, Any> in %stringDest : $*Dictionary<AnyHashable, Any>, bb2, bb3
bb2:
destroy_addr %stringDest : $*Dictionary<AnyHashable, Any>
br bb4
bb3:
br bb4
bb4:
dealloc_stack %stringDest : $*Dictionary<AnyHashable, Any>
dealloc_stack %nsSource : $*NSObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @nsobject_test_take_on_success_dictionary_anyhashable_to_any : $@convention(thin) (@owned NSObject) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[INPUT:%.*]] = alloc_stack $NSObject
// CHECK: store [[ARG]] to [[INPUT]] :
// CHECK: [[OUTPUT:%.*]] = alloc_stack $Dictionary<AnyHashable, Any>
// CHECK: br bb1
//
// CHECK: bb1:
// CHECK: [[LOADED_INPUT:%.*]] = load [[INPUT]]
// CHECK: checked_cast_br [[LOADED_INPUT]] : $NSObject to $NSDictionary, [[YES_BB:bb[0-9]+]], [[NO_BB:bb[0-9]+]]
//
// CHECK: [[NO_BB]]:
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE:bb[0-9]+]]
//
// CHECK: [[YES_BB]]([[CASTED_INPUT:%.*]] :
// CHECK: [[CAST_RESULT:%.*]] = alloc_stack $Optional<Dictionary<AnyHashable, Any>>
// CHECK: strong_retain [[CASTED_INPUT]]
// CHECK: apply {{%.*}}<Dictionary<AnyHashable, Any>>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) :
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK-NOT: strong_release [[CASTED_INPUT]]
// CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional<Dictionary<AnyHashable, Any>>, case #Optional.some!enumelt.1: [[COND_CAST_SUCC:bb[0-9]+]], case #Optional.none!enumelt: [[COND_CAST_FAIL:bb[0-9]+]]
//
// CHECK: [[COND_CAST_SUCC]]:
// CHECK: [[UNWRAPPED_CAST_RESULT:%.*]] = unchecked_take_enum_data_addr [[CAST_RESULT]]
// CHECK: copy_addr [take] [[UNWRAPPED_CAST_RESULT]] to [initialization] [[OUTPUT]]
// CHECK: dealloc_stack [[CAST_RESULT]]
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK: destroy_addr [[OUTPUT]]
// CHECK: br [[EXIT_BB:bb[0-9]+]]
//
// CHECK: [[COND_CAST_FAIL]]:
// CHECK-NEXT: dealloc_stack
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE]]
//
// CHECK: [[FAIL_EXIT_TRAMPOLINE]]:
// CHECK-NEXT: destroy_addr [[INPUT]]
// CHECK-NEXT: br [[EXIT_BB]]
//
// CHECK: [[EXIT_BB]]:
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
// CHECK: } // end sil function 'nsobject_test_take_on_success_dictionary_anyhashable_to_any'
sil @nsobject_test_take_on_success_dictionary_anyhashable_to_any : $@convention(thin) (@owned NSObject) -> () {
bb0(%0 : $NSObject):
%nsSource = alloc_stack $NSObject
store %0 to %nsSource : $*NSObject
%stringDest = alloc_stack $Dictionary<AnyHashable, Any>
br bb1
bb1:
checked_cast_addr_br take_on_success NSObject in %nsSource : $*NSObject to Dictionary<AnyHashable, Any> in %stringDest : $*Dictionary<AnyHashable, Any>, bb2, bb3
bb2:
destroy_addr %stringDest : $*Dictionary<AnyHashable, Any>
br bb4
bb3:
destroy_addr %nsSource : $*NSObject
br bb4
bb4:
dealloc_stack %stringDest : $*Dictionary<AnyHashable, Any>
dealloc_stack %nsSource : $*NSObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @nsobject_test_copy_on_success_dictionary_anyhashable_to_any : $@convention(thin) (@owned NSObject) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[INPUT:%.*]] = alloc_stack $NSObject
// CHECK: store [[ARG]] to [[INPUT]] :
// CHECK: [[OUTPUT:%.*]] = alloc_stack $Dictionary<AnyHashable, Any>
// CHECK: br bb1
//
// CHECK: bb1:
// CHECK: [[LOADED_INPUT:%.*]] = load [[INPUT]]
// CHECK: checked_cast_br [[LOADED_INPUT]] : $NSObject to $NSDictionary, [[YES_BB:bb[0-9]+]], [[NO_BB:bb[0-9]+]]
//
// CHECK: [[NO_BB]]:
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE:bb[0-9]+]]
//
// CHECK: [[YES_BB]]([[CASTED_INPUT:%.*]] :
// CHECK: [[CAST_RESULT:%.*]] = alloc_stack $Optional<Dictionary<AnyHashable, Any>>
// CHECK: strong_retain [[CASTED_INPUT]]
// CHECK: apply {{%.*}}<Dictionary<AnyHashable, Any>>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) :
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK-NOT: strong_release [[CASTED_INPUT]]
// CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional<Dictionary<AnyHashable, Any>>, case #Optional.some!enumelt.1: [[COND_CAST_SUCC:bb[0-9]+]], case #Optional.none!enumelt: [[COND_CAST_FAIL:bb[0-9]+]]
//
// CHECK: [[COND_CAST_SUCC]]:
// CHECK: [[UNWRAPPED_CAST_RESULT:%.*]] = unchecked_take_enum_data_addr [[CAST_RESULT]]
// CHECK: copy_addr [take] [[UNWRAPPED_CAST_RESULT]] to [initialization] [[OUTPUT]]
// CHECK: dealloc_stack [[CAST_RESULT]]
// CHECK: destroy_addr [[OUTPUT]]
// CHECK: destroy_addr [[INPUT]]
// CHECK: br [[EXIT_BB:bb[0-9]+]]
//
// CHECK: [[COND_CAST_FAIL]]:
// CHECK-NEXT: dealloc_stack
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE]]
//
// CHECK: [[FAIL_EXIT_TRAMPOLINE]]:
// CHECK-NEXT: destroy_addr [[INPUT]]
// CHECK-NEXT: br [[EXIT_BB]]
//
// CHECK: [[EXIT_BB]]:
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
// CHECK: } // end sil function 'nsobject_test_copy_on_success_dictionary_anyhashable_to_any'
sil @nsobject_test_copy_on_success_dictionary_anyhashable_to_any : $@convention(thin) (@owned NSObject) -> () {
bb0(%0 : $NSObject):
%nsSource = alloc_stack $NSObject
store %0 to %nsSource : $*NSObject
%stringDest = alloc_stack $Dictionary<AnyHashable, Any>
br bb1
bb1:
checked_cast_addr_br copy_on_success NSObject in %nsSource : $*NSObject to Dictionary<AnyHashable, Any> in %stringDest : $*Dictionary<AnyHashable, Any>, bb2, bb3
bb2:
destroy_addr %stringDest : $*Dictionary<AnyHashable, Any>
destroy_addr %nsSource : $*NSObject
br bb4
bb3:
destroy_addr %nsSource : $*NSObject
br bb4
bb4:
dealloc_stack %stringDest : $*Dictionary<AnyHashable, Any>
dealloc_stack %nsSource : $*NSObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @nsobject_test_take_always_set_anyhashable : $@convention(thin) (@owned NSObject) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[INPUT:%.*]] = alloc_stack $NSObject
// CHECK: store [[ARG]] to [[INPUT]] :
// CHECK: [[OUTPUT:%.*]] = alloc_stack $Set<AnyHashable>
// CHECK: br bb1
//
// CHECK: bb1:
// CHECK: [[LOADED_INPUT:%.*]] = load [[INPUT]]
// CHECK: checked_cast_br [[LOADED_INPUT]] : $NSObject to $NSSet, [[YES_BB:bb[0-9]+]], [[NO_BB:bb[0-9]+]]
//
// CHECK: [[NO_BB]]:
// CHECK-NEXT: strong_release [[LOADED_INPUT]]
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE:bb[0-9]+]]
//
// CHECK: [[YES_BB]]([[CASTED_INPUT:%.*]] :
// CHECK: [[CAST_RESULT:%.*]] = alloc_stack $Optional<Set<AnyHashable>>
// CHECK: strong_retain [[CASTED_INPUT]]
// CHECK: apply {{%.*}}<Set<AnyHashable>>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) :
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional<Set<AnyHashable>>, case #Optional.some!enumelt.1: [[COND_CAST_SUCC:bb[0-9]+]], case #Optional.none!enumelt: [[COND_CAST_FAIL:bb[0-9]+]]
//
// CHECK: [[COND_CAST_SUCC]]:
// CHECK: [[UNWRAPPED_CAST_RESULT:%.*]] = unchecked_take_enum_data_addr [[CAST_RESULT]]
// CHECK: copy_addr [take] [[UNWRAPPED_CAST_RESULT]] to [initialization] [[OUTPUT]]
// CHECK: dealloc_stack [[CAST_RESULT]]
// CHECK: destroy_addr [[OUTPUT]]
// CHECK: br [[EXIT_BB:bb[0-9]+]]
//
// CHECK: [[COND_CAST_FAIL]]:
// CHECK-NEXT: dealloc_stack
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE]]
//
// CHECK: [[FAIL_EXIT_TRAMPOLINE]]:
// CHECK-NEXT: br [[EXIT_BB]]
//
// CHECK: [[EXIT_BB]]:
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
// CHECK: } // end sil function 'nsobject_test_take_always_set_anyhashable'
sil @nsobject_test_take_always_set_anyhashable : $@convention(thin) (@owned NSObject) -> () {
bb0(%0 : $NSObject):
%nsSource = alloc_stack $NSObject
store %0 to %nsSource : $*NSObject
%stringDest = alloc_stack $Set<AnyHashable>
br bb1
bb1:
checked_cast_addr_br take_always NSObject in %nsSource : $*NSObject to Set<AnyHashable> in %stringDest : $*Set<AnyHashable>, bb2, bb3
bb2:
destroy_addr %stringDest : $*Set<AnyHashable>
br bb4
bb3:
br bb4
bb4:
dealloc_stack %stringDest : $*Set<AnyHashable>
dealloc_stack %nsSource : $*NSObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @nsobject_test_take_on_success_set_anyhashable : $@convention(thin) (@owned NSObject) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[INPUT:%.*]] = alloc_stack $NSObject
// CHECK: store [[ARG]] to [[INPUT]] :
// CHECK: [[OUTPUT:%.*]] = alloc_stack $Set<AnyHashable>
// CHECK: br bb1
//
// CHECK: bb1:
// CHECK: [[LOADED_INPUT:%.*]] = load [[INPUT]]
// CHECK: checked_cast_br [[LOADED_INPUT]] : $NSObject to $NSSet, [[YES_BB:bb[0-9]+]], [[NO_BB:bb[0-9]+]]
//
// CHECK: [[NO_BB]]:
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE:bb[0-9]+]]
//
// CHECK: [[YES_BB]]([[CASTED_INPUT:%.*]] :
// CHECK: [[CAST_RESULT:%.*]] = alloc_stack $Optional<Set<AnyHashable>>
// CHECK: strong_retain [[CASTED_INPUT]]
// CHECK: apply {{%.*}}<Set<AnyHashable>>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) :
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK-NOT: strong_release [[CASTED_INPUT]]
// CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional<Set<AnyHashable>>, case #Optional.some!enumelt.1: [[COND_CAST_SUCC:bb[0-9]+]], case #Optional.none!enumelt: [[COND_CAST_FAIL:bb[0-9]+]]
//
// CHECK: [[COND_CAST_SUCC]]:
// CHECK: [[UNWRAPPED_CAST_RESULT:%.*]] = unchecked_take_enum_data_addr [[CAST_RESULT]]
// CHECK: copy_addr [take] [[UNWRAPPED_CAST_RESULT]] to [initialization] [[OUTPUT]]
// CHECK: dealloc_stack [[CAST_RESULT]]
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK: destroy_addr [[OUTPUT]]
// CHECK: br [[EXIT_BB:bb[0-9]+]]
//
// CHECK: [[COND_CAST_FAIL]]:
// CHECK-NEXT: dealloc_stack
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE]]
//
// CHECK: [[FAIL_EXIT_TRAMPOLINE]]:
// CHECK-NEXT: destroy_addr [[INPUT]]
// CHECK-NEXT: br [[EXIT_BB]]
//
// CHECK: [[EXIT_BB]]:
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
// CHECK: } // end sil function 'nsobject_test_take_on_success_set_anyhashable'
sil @nsobject_test_take_on_success_set_anyhashable : $@convention(thin) (@owned NSObject) -> () {
bb0(%0 : $NSObject):
%nsSource = alloc_stack $NSObject
store %0 to %nsSource : $*NSObject
%stringDest = alloc_stack $Set<AnyHashable>
br bb1
bb1:
checked_cast_addr_br take_on_success NSObject in %nsSource : $*NSObject to Set<AnyHashable> in %stringDest : $*Set<AnyHashable>, bb2, bb3
bb2:
destroy_addr %stringDest : $*Set<AnyHashable>
br bb4
bb3:
destroy_addr %nsSource : $*NSObject
br bb4
bb4:
dealloc_stack %stringDest : $*Set<AnyHashable>
dealloc_stack %nsSource : $*NSObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @nsobject_test_copy_on_success_set_anyhashable : $@convention(thin) (@owned NSObject) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[INPUT:%.*]] = alloc_stack $NSObject
// CHECK: store [[ARG]] to [[INPUT]] :
// CHECK: [[OUTPUT:%.*]] = alloc_stack $Set<AnyHashable>
// CHECK: br bb1
//
// CHECK: bb1:
// CHECK: [[LOADED_INPUT:%.*]] = load [[INPUT]]
// CHECK: checked_cast_br [[LOADED_INPUT]] : $NSObject to $NSSet, [[YES_BB:bb[0-9]+]], [[NO_BB:bb[0-9]+]]
//
// CHECK: [[NO_BB]]:
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE:bb[0-9]+]]
//
// CHECK: [[YES_BB]]([[CASTED_INPUT:%.*]] :
// CHECK: [[CAST_RESULT:%.*]] = alloc_stack $Optional<Set<AnyHashable>>
// CHECK: strong_retain [[CASTED_INPUT]]
// CHECK: apply {{%.*}}<Set<AnyHashable>>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) :
// CHECK: strong_release [[CASTED_INPUT]]
// CHECK-NOT: strong_release [[CASTED_INPUT]]
// CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional<Set<AnyHashable>>, case #Optional.some!enumelt.1: [[COND_CAST_SUCC:bb[0-9]+]], case #Optional.none!enumelt: [[COND_CAST_FAIL:bb[0-9]+]]
//
// CHECK: [[COND_CAST_SUCC]]:
// CHECK: [[UNWRAPPED_CAST_RESULT:%.*]] = unchecked_take_enum_data_addr [[CAST_RESULT]]
// CHECK: copy_addr [take] [[UNWRAPPED_CAST_RESULT]] to [initialization] [[OUTPUT]]
// CHECK: dealloc_stack [[CAST_RESULT]]
// CHECK: destroy_addr [[OUTPUT]]
// CHECK: destroy_addr [[INPUT]]
// CHECK: br [[EXIT_BB:bb[0-9]+]]
//
// CHECK: [[COND_CAST_FAIL]]:
// CHECK-NEXT: dealloc_stack
// CHECK-NEXT: br [[FAIL_EXIT_TRAMPOLINE]]
//
// CHECK: [[FAIL_EXIT_TRAMPOLINE]]:
// CHECK-NEXT: destroy_addr [[INPUT]]
// CHECK-NEXT: br [[EXIT_BB]]
//
// CHECK: [[EXIT_BB]]:
// CHECK-NEXT: dealloc_stack [[OUTPUT]]
// CHECK-NEXT: dealloc_stack [[INPUT]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
// CHECK: } // end sil function 'nsobject_test_copy_on_success_set_anyhashable'
sil @nsobject_test_copy_on_success_set_anyhashable : $@convention(thin) (@owned NSObject) -> () {
bb0(%0 : $NSObject):
%nsSource = alloc_stack $NSObject
store %0 to %nsSource : $*NSObject
%stringDest = alloc_stack $Set<AnyHashable>
br bb1
bb1:
checked_cast_addr_br copy_on_success NSObject in %nsSource : $*NSObject to Set<AnyHashable> in %stringDest : $*Set<AnyHashable>, bb2, bb3
bb2:
destroy_addr %stringDest : $*Set<AnyHashable>
destroy_addr %nsSource : $*NSObject
br bb4
bb3:
destroy_addr %nsSource : $*NSObject
br bb4
bb4:
dealloc_stack %stringDest : $*Set<AnyHashable>
dealloc_stack %nsSource : $*NSObject
%9999 = tuple()
return %9999 : $()
}
@objc class ObjCClass {}
struct Str: _ObjectiveCBridgeable {
func _bridgeToObjectiveC() -> ObjCClass
static func _forceBridgeFromObjectiveC(_ source: ObjCClass,
result: inout Str?)
static func _conditionallyBridgeFromObjectiveC(_ source: ObjCClass,
result: inout Str?) -> Bool
static func _unconditionallyBridgeFromObjectiveC(_ source: ObjCClass?) -> Str
// Make it a non-trivial type
var x: AnyObject?
}
// CHECK-LABEL: sil @checked_cast_with_take_always :
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[TEMP_MEM:%[0-9]+]] = alloc_stack
// CHECK: [[LOADED_VALUE:%[0-9]+]] = load [[ARG]]
// CHECK-NEXT: [[RESULT:%[0-9]+]] = apply %{{[0-9]+}}([[LOADED_VALUE]])
// CHECK-NEXT: release_value [[LOADED_VALUE]]
// CHECK-NEXT: store [[RESULT]] to [[TEMP_MEM]]
// CHECK-NEXT: br bb1
//
// CHECK: bb1:
// CHECK-NEXT: [[RESULT:%.*]] = load [[TEMP_MEM]]
// CHECK-NEXT: [[ENUM:%.*]] = enum $Optional<ObjCClass>, #Optional.some!enumelt.1, [[RESULT]]
// CHECK-NEXT: br bb3([[ENUM]] :
//
// CHECK: bb3([[RESULT:%.*]] : $Optional<ObjCClass>):
// CHECK-NEXT: dealloc_stack [[TEMP_MEM]]
// CHECK-NEXT: return [[RESULT]]
// CHECK: } // end sil function 'checked_cast_with_take_always'
sil @checked_cast_with_take_always : $@convention(thin) (@in Str) -> @owned Optional<ObjCClass> {
bb0(%0 : $*Str):
%b = alloc_stack $ObjCClass
checked_cast_addr_br take_always Str in %0 : $*Str to ObjCClass in %b : $*ObjCClass, bb1, bb2
bb1:
%r1 = load %b : $*ObjCClass
%r1Enum = enum $Optional<ObjCClass>, #Optional.some!enumelt.1, %r1 : $ObjCClass
br bb3(%r1Enum : $Optional<ObjCClass>)
bb2:
%none = enum $Optional<ObjCClass>, #Optional.none!enumelt
br bb3(%none : $Optional<ObjCClass>)
bb3(%result : $Optional<ObjCClass>):
dealloc_stack %b : $*ObjCClass
return %result : $Optional<ObjCClass>
}
// CHECK-LABEL: sil @checked_cast_with_take_on_success :
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[TEMP_MEM:%[0-9]+]] = alloc_stack
// CHECK: [[LOADED_VALUE:%[0-9]+]] = load [[ARG]]
// CHECK-NEXT: [[RESULT:%[0-9]+]] = apply %{{[0-9]+}}([[LOADED_VALUE]])
// CHECK-NEXT: store [[RESULT]] to [[TEMP_MEM]]
// CHECK-NEXT: br bb1
//
// CHECK: bb1:
// CHECK-NEXT: release_value [[LOADED_VALUE]]
// CHECK-NEXT: [[RESULT:%.*]] = load [[TEMP_MEM]]
// CHECK-NEXT: [[ENUM:%.*]] = enum $Optional<ObjCClass>, #Optional.some!enumelt.1, [[RESULT]]
// CHECK-NEXT: br bb3([[ENUM]] :
//
// CHECK: bb3([[RESULT:%.*]] : $Optional<ObjCClass>):
// CHECK-NEXT: dealloc_stack [[TEMP_MEM]]
// CHECK-NEXT: return [[RESULT]]
// CHECK: } // end sil function 'checked_cast_with_take_on_success'
sil @checked_cast_with_take_on_success : $@convention(thin) (@in Str) -> @owned Optional<ObjCClass> {
bb0(%0 : $*Str):
%b = alloc_stack $ObjCClass
checked_cast_addr_br take_on_success Str in %0 : $*Str to ObjCClass in %b : $*ObjCClass, bb1, bb2
bb1:
%r1 = load %b : $*ObjCClass
%r1Enum = enum $Optional<ObjCClass>, #Optional.some!enumelt.1, %r1 : $ObjCClass
br bb3(%r1Enum : $Optional<ObjCClass>)
bb2:
%none = enum $Optional<ObjCClass>, #Optional.none!enumelt
destroy_addr %0 : $*Str
br bb3(%none : $Optional<ObjCClass>)
bb3(%result : $Optional<ObjCClass>):
dealloc_stack %b : $*ObjCClass
return %result : $Optional<ObjCClass>
}
// CHECK-LABEL: sil @checked_cast_with_copy_on_success :
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[TEMP_MEM:%[0-9]+]] = alloc_stack
// CHECK: [[LOADED_VALUE:%[0-9]+]] = load [[ARG]]
// CHECK-NEXT: [[RESULT:%[0-9]+]] = apply %{{[0-9]+}}([[LOADED_VALUE]])
// CHECK-NEXT: store [[RESULT]] to [[TEMP_MEM]]
// CHECK-NEXT: br bb1
//
// CHECK: bb1:
// CHECK-NEXT: store [[LOADED_VALUE]] to [[ARG]]
// CHECK-NEXT: [[RESULT:%.*]] = load [[TEMP_MEM]]
// CHECK-NEXT: [[ENUM:%.*]] = enum $Optional<ObjCClass>, #Optional.some!enumelt.1, [[RESULT]]
// CHECK-NEXT: br bb3([[ENUM]] :
//
// CHECK: bb3([[RESULT:%.*]] : $Optional<ObjCClass>):
// CHECK-NEXT: destroy_addr [[ARG]]
// CHECK-NEXT: dealloc_stack [[TEMP_MEM]]
// CHECK-NEXT: return [[RESULT]]
// CHECK: } // end sil function 'checked_cast_with_copy_on_success'
sil @checked_cast_with_copy_on_success : $@convention(thin) (@in Str) -> @owned Optional<ObjCClass> {
bb0(%0 : $*Str):
%b = alloc_stack $ObjCClass
checked_cast_addr_br copy_on_success Str in %0 : $*Str to ObjCClass in %b : $*ObjCClass, bb1, bb2
bb1:
%r1 = load %b : $*ObjCClass
%r1Enum = enum $Optional<ObjCClass>, #Optional.some!enumelt.1, %r1 : $ObjCClass
br bb3(%r1Enum : $Optional<ObjCClass>)
bb2:
%none = enum $Optional<ObjCClass>, #Optional.none!enumelt
br bb3(%none : $Optional<ObjCClass>)
bb3(%result : $Optional<ObjCClass>):
destroy_addr %0 : $*Str
dealloc_stack %b : $*ObjCClass
return %result : $Optional<ObjCClass>
}