// 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 // 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> // CHECK: strong_retain [[INPUT_VALUE]] // CHECK: apply {{%.*}}>([[CAST_TMP]], [[INPUT_VALUE]], // CHECK: strong_release [[INPUT_VALUE]] // CHECK: switch_enum_addr [[CAST_TMP]] : $*Optional>, case #Optional.some!enumelt: [[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 {{%.*}}([[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 checked_cast_addr_br copy_on_success NSArray in %4 : $*NSArray to Array in %7 : $*Array, bb2, bb3 bb2: %9 = load %7 : $*Array %10 = function_ref @guaranteed_swift_array_user : $@convention(thin) <τ_0_0> (@guaranteed Array<τ_0_0>) -> () apply %10(%9) : $@convention(thin) <τ_0_0> (@guaranteed Array<τ_0_0>) -> () release_value %9 : $Array dealloc_stack %7 : $*Array destroy_addr %4 : $*NSArray dealloc_stack %4 : $*NSArray br bb4 bb3: dealloc_stack %7 : $*Array 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 // 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> // CHECK: strong_retain [[INPUT_VALUE]] // CHECK: apply {{%.*}}>([[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>, case #Optional.some!enumelt: [[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 {{%.*}}([[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 checked_cast_addr_br take_on_success NSArray in %4 : $*NSArray to Array in %7 : $*Array, bb2, bb3 bb2: %9 = load %7 : $*Array %10 = function_ref @guaranteed_swift_array_user : $@convention(thin) <τ_0_0> (@guaranteed Array<τ_0_0>) -> () apply %10(%9) : $@convention(thin) <τ_0_0> (@guaranteed Array<τ_0_0>) -> () release_value %9 : $Array dealloc_stack %7 : $*Array dealloc_stack %4 : $*NSArray br bb4 bb3: dealloc_stack %7 : $*Array 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 // 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> // CHECK: strong_retain [[INPUT_VALUE]] // CHECK: apply {{%.*}}>([[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>, case #Optional.some!enumelt: [[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 {{%.*}}([[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 checked_cast_addr_br take_always NSArray in %4 : $*NSArray to Array in %7 : $*Array, bb2, bb3 bb2: %9 = load %7 : $*Array %10 = function_ref @guaranteed_swift_array_user : $@convention(thin) <τ_0_0> (@guaranteed Array<τ_0_0>) -> () apply %10(%9) : $@convention(thin) <τ_0_0> (@guaranteed Array<τ_0_0>) -> () release_value %9 : $Array dealloc_stack %7 : $*Array dealloc_stack %4 : $*NSArray br bb4 bb3: dealloc_stack %7 : $*Array 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 // CHECK: strong_retain [[CASTED_INPUT]] // CHECK: apply {{%.*}}([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) : // CHECK: strong_release [[CASTED_INPUT]] // CHECK: strong_release [[CASTED_INPUT]] // CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional, case #Optional.some!enumelt: [[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 // CHECK: strong_retain [[CASTED_INPUT]] // CHECK: apply {{%.*}}([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) : // CHECK: strong_release [[CASTED_INPUT]] // CHECK-NOT: strong_release [[CASTED_INPUT]] // CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional, case #Optional.some!enumelt: [[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 // CHECK: strong_retain [[CASTED_INPUT]] // CHECK: apply {{%.*}}([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) : // CHECK: strong_release [[CASTED_INPUT]] // CHECK-NOT: strong_release [[CASTED_INPUT]] // CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional, case #Optional.some!enumelt: [[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 // 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> // CHECK: strong_retain [[CASTED_INPUT]] // CHECK: apply {{%.*}}>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) : // CHECK: strong_release [[CASTED_INPUT]] // CHECK: strong_release [[CASTED_INPUT]] // CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional>, case #Optional.some!enumelt: [[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 br bb1 bb1: checked_cast_addr_br take_always NSObject in %nsSource : $*NSObject to Array in %stringDest : $*Array, bb2, bb3 bb2: destroy_addr %stringDest : $*Array br bb4 bb3: br bb4 bb4: dealloc_stack %stringDest : $*Array 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 // 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> // CHECK: strong_retain [[CASTED_INPUT]] // CHECK: apply {{%.*}}>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) : // CHECK: strong_release [[CASTED_INPUT]] // CHECK-NOT: strong_release [[CASTED_INPUT]] // CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional>, case #Optional.some!enumelt: [[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 br bb1 bb1: checked_cast_addr_br take_on_success NSObject in %nsSource : $*NSObject to Array in %stringDest : $*Array, bb2, bb3 bb2: destroy_addr %stringDest : $*Array br bb4 bb3: destroy_addr %nsSource : $*NSObject br bb4 bb4: dealloc_stack %stringDest : $*Array 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 // 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> // CHECK: strong_retain [[CASTED_INPUT]] // CHECK: apply {{%.*}}>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) : // CHECK: strong_release [[CASTED_INPUT]] // CHECK-NOT: strong_release [[CASTED_INPUT]] // CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional>, case #Optional.some!enumelt: [[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 br bb1 bb1: checked_cast_addr_br copy_on_success NSObject in %nsSource : $*NSObject to Array in %stringDest : $*Array, bb2, bb3 bb2: destroy_addr %stringDest : $*Array destroy_addr %nsSource : $*NSObject br bb4 bb3: destroy_addr %nsSource : $*NSObject br bb4 bb4: dealloc_stack %stringDest : $*Array 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 // 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> // CHECK: strong_retain [[CASTED_INPUT]] // CHECK: apply {{%.*}}>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) : // CHECK: strong_release [[CASTED_INPUT]] // CHECK: strong_release [[CASTED_INPUT]] // CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional>, case #Optional.some!enumelt: [[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 br bb1 bb1: checked_cast_addr_br take_always NSObject in %nsSource : $*NSObject to Dictionary in %stringDest : $*Dictionary, bb2, bb3 bb2: destroy_addr %stringDest : $*Dictionary br bb4 bb3: br bb4 bb4: dealloc_stack %stringDest : $*Dictionary 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 // 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> // CHECK: strong_retain [[CASTED_INPUT]] // CHECK: apply {{%.*}}>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) : // CHECK: strong_release [[CASTED_INPUT]] // CHECK-NOT: strong_release [[CASTED_INPUT]] // CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional>, case #Optional.some!enumelt: [[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 br bb1 bb1: checked_cast_addr_br take_on_success NSObject in %nsSource : $*NSObject to Dictionary in %stringDest : $*Dictionary, bb2, bb3 bb2: destroy_addr %stringDest : $*Dictionary br bb4 bb3: destroy_addr %nsSource : $*NSObject br bb4 bb4: dealloc_stack %stringDest : $*Dictionary 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 // 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> // CHECK: strong_retain [[CASTED_INPUT]] // CHECK: apply {{%.*}}>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) : // CHECK: strong_release [[CASTED_INPUT]] // CHECK-NOT: strong_release [[CASTED_INPUT]] // CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional>, case #Optional.some!enumelt: [[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 br bb1 bb1: checked_cast_addr_br copy_on_success NSObject in %nsSource : $*NSObject to Dictionary in %stringDest : $*Dictionary, bb2, bb3 bb2: destroy_addr %stringDest : $*Dictionary destroy_addr %nsSource : $*NSObject br bb4 bb3: destroy_addr %nsSource : $*NSObject br bb4 bb4: dealloc_stack %stringDest : $*Dictionary 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 // 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> // CHECK: strong_retain [[CASTED_INPUT]] // CHECK: apply {{%.*}}>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) : // CHECK: strong_release [[CASTED_INPUT]] // CHECK: strong_release [[CASTED_INPUT]] // CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional>, case #Optional.some!enumelt: [[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 br bb1 bb1: checked_cast_addr_br take_always NSObject in %nsSource : $*NSObject to Set in %stringDest : $*Set, bb2, bb3 bb2: destroy_addr %stringDest : $*Set br bb4 bb3: br bb4 bb4: dealloc_stack %stringDest : $*Set 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 // 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> // CHECK: strong_retain [[CASTED_INPUT]] // CHECK: apply {{%.*}}>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) : // CHECK: strong_release [[CASTED_INPUT]] // CHECK-NOT: strong_release [[CASTED_INPUT]] // CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional>, case #Optional.some!enumelt: [[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 br bb1 bb1: checked_cast_addr_br take_on_success NSObject in %nsSource : $*NSObject to Set in %stringDest : $*Set, bb2, bb3 bb2: destroy_addr %stringDest : $*Set br bb4 bb3: destroy_addr %nsSource : $*NSObject br bb4 bb4: dealloc_stack %stringDest : $*Set 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 // 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> // CHECK: strong_retain [[CASTED_INPUT]] // CHECK: apply {{%.*}}>([[CAST_RESULT]], [[CASTED_INPUT]], {{%.*}}) : // CHECK: strong_release [[CASTED_INPUT]] // CHECK-NOT: strong_release [[CASTED_INPUT]] // CHECK: switch_enum_addr [[CAST_RESULT]] : $*Optional>, case #Optional.some!enumelt: [[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 br bb1 bb1: checked_cast_addr_br copy_on_success NSObject in %nsSource : $*NSObject to Set in %stringDest : $*Set, bb2, bb3 bb2: destroy_addr %stringDest : $*Set destroy_addr %nsSource : $*NSObject br bb4 bb3: destroy_addr %nsSource : $*NSObject br bb4 bb4: dealloc_stack %stringDest : $*Set 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, #Optional.some!enumelt, [[RESULT]] // CHECK-NEXT: br bb3([[ENUM]] : // // CHECK: bb3([[RESULT:%.*]] : $Optional): // 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 { 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, #Optional.some!enumelt, %r1 : $ObjCClass br bb3(%r1Enum : $Optional) bb2: %none = enum $Optional, #Optional.none!enumelt br bb3(%none : $Optional) bb3(%result : $Optional): dealloc_stack %b : $*ObjCClass return %result : $Optional } // 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, #Optional.some!enumelt, [[RESULT]] // CHECK-NEXT: br bb3([[ENUM]] : // // CHECK: bb3([[RESULT:%.*]] : $Optional): // 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 { 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, #Optional.some!enumelt, %r1 : $ObjCClass br bb3(%r1Enum : $Optional) bb2: %none = enum $Optional, #Optional.none!enumelt destroy_addr %0 : $*Str br bb3(%none : $Optional) bb3(%result : $Optional): dealloc_stack %b : $*ObjCClass return %result : $Optional } // 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, #Optional.some!enumelt, [[RESULT]] // CHECK-NEXT: br bb3([[ENUM]] : // // CHECK: bb3([[RESULT:%.*]] : $Optional): // 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 { 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, #Optional.some!enumelt, %r1 : $ObjCClass br bb3(%r1Enum : $Optional) bb2: %none = enum $Optional, #Optional.none!enumelt br bb3(%none : $Optional) bb3(%result : $Optional): destroy_addr %0 : $*Str dealloc_stack %b : $*ObjCClass return %result : $Optional }