// RUN: %target-sil-opt -enable-sil-verify-all %s -sil-combine | %FileCheck %s // REQUIRES: objc_interop // TODO: Update optimizer for id-as-Any changes. sil_stage canonical import Builtin import Swift import Foundation // FIXME: Should go into the standard library. public extension _ObjectiveCBridgeable { static func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectiveCType?) -> Self } class AnNSArray { } struct AnArray : _ObjectiveCBridgeable { @_hasStorage var Buffer : Builtin.NativeObject func _bridgeToObjectiveC() -> AnNSArray { return AnNSArray() } static func _forceBridgeFromObjectiveC( _ x: AnNSArray, result: inout AnArray? ) { preconditionFailure("implement") } static func _conditionallyBridgeFromObjectiveC( _ x: AnNSArray, result: inout AnArray? ) -> Bool { preconditionFailure("implement") } } sil [_semantics "convertFromObjectiveC"] @bridgeFromObjectiveC : $@convention(thin) <τ_0_0> (@owned AnNSArray) -> @owned AnArray<τ_0_0> sil [_semantics "convertToObjectiveC"] @bridgeToObjectiveC: $@convention(method) <τ_0_0> (@owned AnArray<τ_0_0>) -> @owned AnNSArray // CHECK-LABEL: sil @bridge_from_to_owned // CHECK-NOT: apply // CHECK: strong_retain // CHECK-NOT: apply // CHECK: strong_release // CHECK-NOT: apply // CHECK: return sil @bridge_from_to_owned : $@convention(thin) (@owned AnNSArray) -> @owned AnNSArray { bb0(%0 : $AnNSArray): %1 = function_ref @bridgeFromObjectiveC : $@convention(thin) (@owned AnNSArray) -> @owned AnArray %2 = apply %1(%0) : $@convention(thin) (@owned AnNSArray) -> @owned AnArray retain_value %2 : $AnArray release_value %2 : $AnArray %3 = function_ref @bridgeToObjectiveC : $@convention(method) (@owned AnArray) -> @owned AnNSArray %4 = apply %3(%2) : $@convention(method) (@owned AnArray) -> @owned AnNSArray return %4 : $AnNSArray } sil [_semantics "convertFromObjectiveC"] [dynamically_replacable] @bridgeFromObjectiveC2 : $@convention(thin) <τ_0_0> (@owned AnNSArray) -> @owned AnArray<τ_0_0> sil [_semantics "convertToObjectiveC"] [dynamically_replacable] @bridgeToObjectiveC2: $@convention(method) <τ_0_0> (@owned AnArray<τ_0_0>) -> @owned AnNSArray // This should not crash. sil @bridge_from_to_owned_dynamic : $@convention(thin) (@owned AnNSArray) -> @owned AnNSArray { bb0(%0 : $AnNSArray): %1 = dynamic_function_ref @bridgeFromObjectiveC2 : $@convention(thin) (@owned AnNSArray) -> @owned AnArray %2 = apply %1(%0) : $@convention(thin) (@owned AnNSArray) -> @owned AnArray retain_value %2 : $AnArray release_value %2 : $AnArray %3 = dynamic_function_ref @bridgeToObjectiveC2 : $@convention(method) (@owned AnArray) -> @owned AnNSArray %4 = apply %3(%2) : $@convention(method) (@owned AnArray) -> @owned AnNSArray return %4 : $AnNSArray } // CHECK-LABEL: sil @bridge_to_from_owned // CHECK-NOT: apply // CHECK: retain_value // CHECK-NOT: apply // CHECK: release_value // CHECK-NOT: apply // CHECK: return sil @bridge_to_from_owned : $@convention(thin) (@owned AnArray) -> @owned AnArray{ bb0(%0 : $AnArray): %1 = function_ref @bridgeToObjectiveC : $@convention(method) (@owned AnArray) -> @owned AnNSArray %2 = apply %1(%0) : $@convention(method) (@owned AnArray) -> @owned AnNSArray debug_value %2 : $AnNSArray // should not prevent the optimization strong_retain %2 : $AnNSArray strong_release %2 : $AnNSArray %3 = function_ref @bridgeFromObjectiveC : $@convention(thin) (@owned AnNSArray) -> @owned AnArray %4 = apply %3(%2) : $@convention(thin) (@owned AnNSArray) -> @owned AnArray return %4 : $AnArray } sil [_semantics "convertFromObjectiveC"] @bridgeFromObjectiveCGuaranteed : $@convention(thin) <τ_0_0> (@guaranteed AnNSArray) -> @owned AnArray<τ_0_0> sil [_semantics "convertToObjectiveC"] @bridgeToObjectiveCGuaranteed: $@convention(method) <τ_0_0> (@guaranteed AnArray<τ_0_0>) -> @owned AnNSArray // CHECK-LABEL: sil @bridge_from_to_guaranteed // CHECK-NOT: apply // CHECK: strong_retain // CHECK-NOT: apply // CHECK: strong_release // CHECK-NOT: apply // CHECK: return sil @bridge_from_to_guaranteed : $@convention(thin) (@owned AnNSArray) -> @owned AnNSArray { bb0(%0 : $AnNSArray): %1 = function_ref @bridgeFromObjectiveCGuaranteed : $@convention(thin) (@guaranteed AnNSArray) -> @owned AnArray %2 = apply %1(%0) : $@convention(thin) (@guaranteed AnNSArray) -> @owned AnArray release_value %0 : $AnNSArray %3 = function_ref @bridgeToObjectiveCGuaranteed : $@convention(method) (@guaranteed AnArray) -> @owned AnNSArray %4 = apply %3(%2) : $@convention(method) (@guaranteed AnArray) -> @owned AnNSArray release_value %2 : $AnArray return %4 : $AnNSArray } // CHECK-LABEL: sil @bridge_to_from_guaranteed // CHECK-NOT: apply // CHECK: retain_value // CHECK-NOT: apply // CHECK: release_value // CHECK-NOT: apply // CHECK: return sil @bridge_to_from_guaranteed : $@convention(thin) (@owned AnArray) -> @owned AnArray{ bb0(%0 : $AnArray): %1 = function_ref @bridgeToObjectiveCGuaranteed : $@convention(method) (@guaranteed AnArray) -> @owned AnNSArray %2 = apply %1(%0) : $@convention(method) (@guaranteed AnArray) -> @owned AnNSArray release_value %0 : $AnArray %3 = function_ref @bridgeFromObjectiveCGuaranteed : $@convention(thin) (@guaranteed AnNSArray) -> @owned AnArray %4 = apply %3(%2) : $@convention(thin) (@guaranteed AnNSArray) -> @owned AnArray release_value %2 : $AnNSArray return %4 : $AnArray } struct PlainStruct { } // CHECK-LABEL: sil @plain_struct_bridge_from_to_owned // CHECK-NOT: apply // CHECK-NOT: apply // CHECK: return sil @plain_struct_bridge_from_to_owned : $@convention(thin) (@owned AnNSArray) -> @owned AnNSArray { bb0(%0 : $AnNSArray): %1 = function_ref @bridgeFromObjectiveC : $@convention(thin) (@owned AnNSArray) -> @owned AnArray %2 = apply %1(%0) : $@convention(thin) (@owned AnNSArray) -> @owned AnArray retain_value %2 : $AnArray release_value %2 : $AnArray %3 = function_ref @bridgeToObjectiveC : $@convention(method) (@owned AnArray) -> @owned AnNSArray %4 = apply %3(%2) : $@convention(method) (@owned AnArray) -> @owned AnNSArray return %4 : $AnNSArray } // CHECK-LABEL: sil @plain_struct_bridge_from_to_owned_generic // CHECK-NOT: apply // CHECK-NOT: apply // CHECK: return sil @plain_struct_bridge_from_to_owned_generic : $@convention(thin) (@owned AnNSArray) -> @owned AnNSArray { bb0(%0 : $AnNSArray): %1 = function_ref @bridgeFromObjectiveC : $@convention(thin) (@owned AnNSArray) -> @owned AnArray %2 = apply %1(%0) : $@convention(thin) (@owned AnNSArray) -> @owned AnArray retain_value %2 : $AnArray release_value %2 : $AnArray %3 = function_ref @bridgeToObjectiveC : $@convention(method) (@owned AnArray) -> @owned AnNSArray %4 = apply %3(%2) : $@convention(method) (@owned AnArray) -> @owned AnNSArray return %4 : $AnNSArray } // CHECK-LABEL: sil @plain_struct_from_to_owned_recursive_type // CHECK-NOT: apply // CHECK-NOT: apply // CHECK: return sil @plain_struct_from_to_owned_recursive_type : $@convention(thin) (@owned AnNSArray) -> @owned AnNSArray { bb0(%0 : $AnNSArray): %1 = function_ref @bridgeFromObjectiveC : $@convention(thin) (@owned AnNSArray) -> @owned AnArray %2 = apply %1>(%0) : $@convention(thin) (@owned AnNSArray) -> @owned AnArray retain_value %2 : $AnArray> release_value %2 : $AnArray> %3 = function_ref @bridgeToObjectiveC : $@convention(method) (@owned AnArray) -> @owned AnNSArray %4 = apply %3>(%2) : $@convention(method) (@owned AnArray) -> @owned AnNSArray return %4 : $AnNSArray } // CHECK-LABEL: sil shared @bridge_from_swift_array_to_NSObject_cast // CHECK: function_ref @$sSa10FoundationE19_bridgeToObjectiveC{{[_0-9a-zA-Z]*}}F // CHECK-NOT: retain // CHECK: apply // CHECK: release_value // CHECK: upcast %{{.*}} : $NSArray to $NSObject // CHECK: store // CHECK: return sil shared @bridge_from_swift_array_to_NSObject_cast: $@convention(thin) (@in Array) -> @out NSObject { bb0(%0 : $*NSObject, %1 : $*Array): %2 = alloc_stack $Array copy_addr %1 to [initialization] %2 : $*Array unconditional_checked_cast_addr Array in %2 : $*Array to NSObject in %0 : $*NSObject dealloc_stack %2 : $*Array destroy_addr %1 : $*Array %7 = tuple () return %7 : $() } enum AddressOnlyError : Error { case data(Data) case none } // Test that we emit a copy_addr for the address-only value initialization. // CHECK-LABEL: sil @unconditional_checked_cast_addr_address_only_type // CHECK: alloc_stack $Error // CHECK: alloc_stack $AddressOnlyError // CHECK: copy_addr // CHECK: alloc_existential_box // CHECK: project_existential_box // CHECK: copy_addr // CHECK: store sil @unconditional_checked_cast_addr_address_only_type: $@convention(thin) (@in_guaranteed AddressOnlyError) -> @owned Error { bb0(%0 : $*AddressOnlyError): %1 = alloc_stack $Error %2 = alloc_stack $AddressOnlyError copy_addr %0 to [initialization] %2 : $*AddressOnlyError unconditional_checked_cast_addr AddressOnlyError in %2 : $*AddressOnlyError to Error in %1 : $*Error dealloc_stack %2 : $*AddressOnlyError %8 = tuple () %9 = load %1 : $*Error dealloc_stack %1 : $*Error return %9 : $Error }