| // RUN: %target-sil-opt -enable-objc-interop -enable-sil-verify-all=0 -module-name Swift -o /dev/null 2>&1 %s |
| // REQUIRES: asserts |
| |
| // This file is meant to contain tests that previously the verifier treated |
| // incorrectly. This is important to ensure that the verifier does not |
| // regress. It should only deal with use matching. |
| |
| sil_stage canonical |
| |
| import Builtin |
| |
| ////////////////// |
| // Declarations // |
| ////////////////// |
| |
| typealias AnyObject = Builtin.AnyObject |
| |
| public protocol Error {} |
| |
| struct SomeError: Error { |
| var ptr: Builtin.NativeObject |
| } |
| |
| enum Never {} |
| |
| enum Optional<T> { |
| case some(T) |
| case none |
| } |
| |
| enum ThreeDifferingPayloadEnum { |
| case nopayload |
| case trivial_payload(Builtin.Int32) |
| case nontrivial_payload(Builtin.NativeObject) |
| } |
| |
| struct TrivialStruct { |
| var f1: Builtin.Int32 |
| var f2: Builtin.Int32 |
| } |
| |
| struct NonTrivialStructWithTrivialField { |
| var owner: Builtin.NativeObject |
| var payload: Builtin.Int32 |
| } |
| |
| struct TupleContainingNonTrivialStruct { |
| var t: (Builtin.NativeObject, Builtin.NativeObject) |
| var opt: Optional<Builtin.NativeObject> |
| } |
| |
| class SuperKlass { |
| func d() {} |
| class func f() {} |
| } |
| class SubKlass : SuperKlass {} |
| class X { |
| @objc func f() { } |
| @objc class func g() {} |
| } |
| |
| protocol SwiftKlassP : class { |
| func foo() |
| } |
| |
| struct Val { |
| } |
| class Ref { |
| } |
| struct Aleph { |
| var a:Ref |
| var b:Val |
| } |
| |
| struct Int { |
| var value: Builtin.Int64 |
| } |
| |
| class RefWithInt { |
| var value: Builtin.Int32 |
| |
| init() |
| } |
| |
| struct EmptyStruct {} |
| |
| class RefWithRef { |
| var value: RefWithRef |
| |
| init() |
| } |
| |
| sil @no_arg_or_output_function : $@convention(thin) () -> () |
| |
| |
| sil @allocate_object : $@convention(thin) () -> @owned Builtin.NativeObject |
| |
| sil @three_differing_payload_enum_user : $@convention(thin) (@owned ThreeDifferingPayloadEnum, @guaranteed ThreeDifferingPayloadEnum, ThreeDifferingPayloadEnum) -> () |
| |
| sil @nontrivial_unowned_user : $@convention(thin) (Builtin.NativeObject) -> () |
| |
| sil @borrow_tuple_user : $@convention(thin) (@guaranteed (Builtin.Int32, Builtin.NativeObject, Builtin.Int32, Builtin.NativeObject)) -> () |
| sil @unowned_tuple_user : $@convention(thin) ((Builtin.Int32, Builtin.NativeObject, Builtin.Int32, Builtin.NativeObject)) -> () |
| |
| sil @produce_owned_optional : $@convention(thin) () -> @owned Optional<Builtin.NativeObject> |
| sil @guaranteed_nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| |
| //////////////// |
| // Test Cases // |
| //////////////// |
| |
| // Make sure that guaranteed args do not have a consuming use. |
| sil [ossa] @direct_guaranteed_arg_doesnt_have_consuming_use : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () { |
| bb0(%0 : @guaranteed $Builtin.NativeObject): |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @store_borrow_result : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () { |
| bb0(%0 : @guaranteed $Builtin.NativeObject): |
| %1 = alloc_stack $Builtin.NativeObject |
| store_borrow %0 to %1 : $*Builtin.NativeObject |
| dealloc_stack %1 : $*Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @load_borrow_from_class : $@convention(thin) (@guaranteed RefWithRef) -> () { |
| bb0(%0 : @guaranteed $RefWithRef): |
| %1 = ref_element_addr %0 : $RefWithRef, #RefWithRef.value |
| %2 = load_borrow %1 : $*RefWithRef |
| end_borrow %2 : $RefWithRef |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @trivial_struct_extract_from_non_trivial : $@convention(thin) (@guaranteed NonTrivialStructWithTrivialField) -> () { |
| bb0(%0 : @guaranteed $NonTrivialStructWithTrivialField): |
| %1 = struct_extract %0 : $NonTrivialStructWithTrivialField, #NonTrivialStructWithTrivialField.payload |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @trivial_struct_extract_from_trivial : $@convention(thin) (TrivialStruct) -> () { |
| bb0(%0 : $TrivialStruct): |
| %1 = struct_extract %0 : $TrivialStruct, #TrivialStruct.f1 |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @in_address_arg : $@convention(thin) (@in Builtin.NativeObject) -> () { |
| bb0(%0 : $*Builtin.NativeObject): |
| destroy_addr %0 : $*Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // We shouldn't assert given an unowned argument that is never used. |
| sil [ossa] @non_trivial_unowned_arg : $@convention(thin) (Builtin.NativeObject) -> () { |
| bb0(%0 : @unowned $Builtin.NativeObject): |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @builtin_unreachable_has_a_return_value : $@convention(thin) () -> () { |
| bb0: |
| %0 = builtin "unreachable"() : $Never |
| unreachable |
| } |
| |
| // Make sure that we can pass an owned, guaranteed, and unowned argument as |
| // unowned parameters such that the use is viewed as a non-lifetime ending use. |
| sil [ossa] @call_func_with_nontrivial_unowned_user_arg : $@convention(thin) (@owned Builtin.NativeObject, Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject, %1 : @unowned $Builtin.NativeObject): |
| %2 = function_ref @nontrivial_unowned_user : $@convention(thin) (Builtin.NativeObject) -> () |
| apply %2(%0) : $@convention(thin) (Builtin.NativeObject) -> () |
| %3 = begin_borrow %0 : $Builtin.NativeObject |
| apply %2(%3) : $@convention(thin) (Builtin.NativeObject) -> () |
| end_borrow %3 : $Builtin.NativeObject |
| destroy_value %0 : $Builtin.NativeObject |
| apply %2(%1) : $@convention(thin) (Builtin.NativeObject) -> () |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @forwarding_guaranteed_nonfunction_values_doesnt_end_lifetime : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %1 = begin_borrow %0 : $Builtin.NativeObject |
| %2 = unchecked_ref_cast %1 : $Builtin.NativeObject to $SuperKlass |
| end_borrow %1 : $Builtin.NativeObject |
| destroy_value %0 : $Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @alloc_value_buffer_dealloc_value_buffer : $@convention(thin) (@inout Builtin.UnsafeValueBuffer, Builtin.Int32) -> () { |
| bb0(%0 : $*Builtin.UnsafeValueBuffer, %1 : $Builtin.Int32): |
| %2 = alloc_value_buffer $Builtin.Int32 in %0 : $*Builtin.UnsafeValueBuffer |
| store %1 to [trivial] %2 : $*Builtin.Int32 |
| dealloc_value_buffer $Builtin.Int32 in %0 : $*Builtin.UnsafeValueBuffer |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @builtins_test : $@convention(thin) (@owned Error, Builtin.Int1, Builtin.RawPointer, Builtin.Word) -> ((), @error Error) { |
| bb0(%0 : @owned $Error, %1 : $Builtin.Int1, %2 : $Builtin.RawPointer, %3 : $Builtin.Word): |
| %4 = metatype $@thick Builtin.Int32.Type |
| builtin "willThrow"(%0 : $Error) : $() |
| builtin "onFastPath"() : $() |
| builtin "staticReport"(%1 : $Builtin.Int1, %1 : $Builtin.Int1, %2 : $Builtin.RawPointer) : $() |
| builtin "destroyArray"<Builtin.Int32>(%4 : $@thick Builtin.Int32.Type, %2 : $Builtin.RawPointer, %3 : $Builtin.Word) : $() |
| builtin "copyArray"<Builtin.Int32>(%4 : $@thick Builtin.Int32.Type, %2 : $Builtin.RawPointer, %2 : $Builtin.RawPointer, %3 : $Builtin.Word) : $() |
| builtin "takeArrayFrontToBack"<Builtin.Int32>(%4 : $@thick Builtin.Int32.Type, %2 : $Builtin.RawPointer, %2 : $Builtin.RawPointer, %3 : $Builtin.Word) : $() |
| builtin "takeArrayBackToFront"<Builtin.Int32>(%4 : $@thick Builtin.Int32.Type, %2 : $Builtin.RawPointer, %2 : $Builtin.RawPointer, %3 : $Builtin.Word) : $() |
| builtin "unexpectedError"(%0 : $Error) : $() |
| builtin "errorInMain"(%0 : $Error) : $() |
| %5 = integer_literal $Builtin.Int64, 0 |
| %6 = struct $Int(%5 : $Builtin.Int64) |
| builtin "deallocRaw"(%2 : $Builtin.RawPointer, %6 : $Int, %6 : $Int) : $() |
| builtin "fence_acquire"() : $() |
| %7 = integer_literal $Builtin.Int32, 0 |
| builtin "atomicstore_release_Int32"(%2 : $Builtin.RawPointer, %7 : $Builtin.Int32) : $() |
| %8 = function_ref @no_arg_or_output_function : $@convention(thin) () -> () |
| builtin "once"(%2 : $Builtin.RawPointer, %8 : $@convention(thin) () -> ()) : $() |
| throw %0 : $Error |
| } |
| |
| sil [ossa] @existential_box_test : $@convention(thin) (@owned SomeError) -> () { |
| bb0(%0 : @owned $SomeError): |
| %1 = alloc_existential_box $Error, $SomeError |
| %2 = project_existential_box $SomeError in %1 : $Error |
| store %0 to [init] %2 : $*SomeError |
| %4 = open_existential_box %1 : $Error to $*@opened("01234567-89AB-CDEF-0123-333333333333") Error |
| destroy_addr %4 : $*@opened("01234567-89AB-CDEF-0123-333333333333") Error |
| dealloc_existential_box %1 : $Error, $SomeError |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @tail_allocated_alloc_ref : $@convention(thin) (Builtin.Word, Builtin.Word, @thick SuperKlass.Type) -> () { |
| bb0(%0 : $Builtin.Word, %1 : $Builtin.Word, %2 : $@thick SuperKlass.Type): |
| %3 = alloc_ref [tail_elems $Val * %0 : $Builtin.Word] [tail_elems $Aleph * %1 : $Builtin.Word] $SuperKlass |
| dealloc_ref %3 : $SuperKlass |
| |
| %4 = alloc_ref_dynamic [tail_elems $Val * %0 : $Builtin.Word] [tail_elems $Aleph * %1 : $Builtin.Word] %2 : $@thick SuperKlass.Type, $SuperKlass |
| // CHECK: dealloc_ref %3 : $Class1 |
| dealloc_ref %4 : $SuperKlass |
| |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // All of these uses should not be consuming except for the destroy. |
| sil [ossa] @select_enum_test : $@convention(thin) (@owned ThreeDifferingPayloadEnum, @owned Builtin.NativeObject, Optional<Builtin.Int32>, @owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $ThreeDifferingPayloadEnum, %1 : @owned $Builtin.NativeObject, %2 : $Optional<Builtin.Int32>, %3 : @owned $Builtin.NativeObject): |
| %4 = integer_literal $Builtin.Int32, 2 |
| select_enum %0 : $ThreeDifferingPayloadEnum, case #ThreeDifferingPayloadEnum.nopayload!enumelt: %4, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt.1: %4, case #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt.1: %4 : $Builtin.Int32 |
| %5 = select_enum %2 : $Optional<Builtin.Int32>, case #Optional.none!enumelt: %1, case #Optional.some!enumelt.1: %3 : $Builtin.NativeObject |
| destroy_value %5 : $Builtin.NativeObject |
| destroy_value %0 : $ThreeDifferingPayloadEnum |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @cast_tests : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %2 = unchecked_trivial_bit_cast %0 : $Builtin.NativeObject to $Builtin.RawPointer |
| %3 = unchecked_trivial_bit_cast %2 : $Builtin.RawPointer to $Builtin.RawPointer |
| destroy_value %0 : $Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @existential_metatype_test : $@convention(thin) (@owned SwiftKlassP, @in SwiftKlassP) -> () { |
| bb0(%0 : @owned $SwiftKlassP, %1 : $*SwiftKlassP): |
| %2 = existential_metatype $@thick SwiftKlassP.Type, %0 : $SwiftKlassP |
| %3 = existential_metatype $@thick SwiftKlassP.Type, %1 : $*SwiftKlassP |
| destroy_value %0 : $SwiftKlassP |
| destroy_addr %1 : $*SwiftKlassP |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @value_metatype_test : $@convention(thin) (@owned Ref, @in Ref) -> () { |
| bb0(%0 : @owned $Ref, %1 : $*Ref): |
| %2 = value_metatype $@thick Ref.Type, %0 : $Ref |
| %3 = value_metatype $@thick Ref.Type, %1 : $*Ref |
| destroy_value %0 : $Ref |
| destroy_addr %1 : $*Ref |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @ref_element_addr_test : $@convention(thin) (@owned RefWithInt) -> () { |
| bb0(%0 : @owned $RefWithInt): |
| %1 = begin_borrow %0 : $RefWithInt |
| %2 = ref_element_addr %1 : $RefWithInt, #RefWithInt.value |
| end_borrow %1 : $RefWithInt |
| destroy_value %0 : $RefWithInt |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @trivial_payload_enum_pass_to_apply : $@convention(thin) () -> () { |
| bb0: |
| %0 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.nopayload!enumelt |
| %1 = function_ref @three_differing_payload_enum_user : $@convention(thin) (@owned ThreeDifferingPayloadEnum, @guaranteed ThreeDifferingPayloadEnum, ThreeDifferingPayloadEnum) -> () |
| apply %1(%0, %0, %0) : $@convention(thin) (@owned ThreeDifferingPayloadEnum, @guaranteed ThreeDifferingPayloadEnum, ThreeDifferingPayloadEnum) -> () |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @unsafeGuaranteedTest : $@convention(thin) (@owned Ref) -> () { |
| bb0(%0 : @owned $Ref): |
| %1 = builtin "unsafeGuaranteed"(%0 : $Ref) : $(Ref, Builtin.Int8) |
| %2 = begin_borrow %1 : $(Ref, Builtin.Int8) |
| %3 = tuple_extract %2 : $(Ref, Builtin.Int8), 1 |
| end_borrow %2 : $(Ref, Builtin.Int8) |
| builtin "unsafeGuaranteedEnd"(%3 : $Builtin.Int8) : $() |
| destroy_value %1 : $(Ref, Builtin.Int8) |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @unchecked_enum_data_propagates_ownership : $@convention(thin) (@owned Optional<Builtin.NativeObject>) -> @owned Builtin.NativeObject { |
| bb0(%0 : @owned $Optional<Builtin.NativeObject>): |
| %1 = begin_borrow %0 : $Optional<Builtin.NativeObject> |
| unchecked_enum_data %1 : $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1 |
| unchecked_enum_data %1 : $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1 |
| unchecked_enum_data %1 : $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1 |
| end_borrow %1 : $Optional<Builtin.NativeObject> |
| %2 = unchecked_enum_data %0 : $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1 |
| return %2 : $Builtin.NativeObject |
| } |
| |
| sil [ossa] @access_tests : $@convention(thin) () -> () { |
| bb0: |
| %0 = alloc_box ${ var Builtin.Int64 }, var, name "x" |
| %1 = project_box %0 : ${ var Builtin.Int64 }, 0 |
| %2 = begin_access [read] [static] %1 : $*Builtin.Int64 |
| %3 = load [trivial] %2 : $*Builtin.Int64 |
| end_access %2 : $*Builtin.Int64 |
| destroy_value %0 : ${ var Builtin.Int64 } |
| |
| %01 = alloc_ref $RefWithInt |
| %011 = begin_borrow %01 : $RefWithInt |
| %11 = alloc_stack $Builtin.UnsafeValueBuffer |
| %21 = ref_element_addr %011 : $RefWithInt, #RefWithInt.value |
| begin_unpaired_access [modify] [dynamic] %21 : $*Builtin.Int32, %11 : $*Builtin.UnsafeValueBuffer |
| end_unpaired_access [dynamic] %11 : $*Builtin.UnsafeValueBuffer |
| begin_unpaired_access [read] [dynamic] %21 : $*Builtin.Int32, %11 : $*Builtin.UnsafeValueBuffer |
| end_unpaired_access [dynamic] %11 : $*Builtin.UnsafeValueBuffer |
| end_borrow %011 : $RefWithInt |
| dealloc_stack %11 : $*Builtin.UnsafeValueBuffer |
| destroy_value %01 : $RefWithInt |
| |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @block_invoke_test : $@convention(thin) (@owned @convention(block) () -> ()) -> () { |
| bb0(%0 : @owned $@convention(block) () -> ()): |
| apply %0() : $@convention(block) () -> () |
| destroy_value %0 : $@convention(block) () -> () |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @class_method_metatype_test : $@convention(thin) (@thick SuperKlass.Type) -> () { |
| bb0(%0 : $@thick SuperKlass.Type): |
| %1 = class_method %0 : $@thick SuperKlass.Type, #SuperKlass.d!1 : (SuperKlass) -> () -> (), $@convention(method) (@guaranteed SuperKlass) -> () |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @trivial_enum_return_value : $@convention(thin) () -> @owned Optional<Builtin.NativeObject> { |
| bb0: |
| %0 = enum $Optional<Builtin.NativeObject>, #Optional.none!enumelt |
| return %0 : $Optional<Builtin.NativeObject> |
| } |
| |
| sil [ossa] @c_function : $@convention(c) (@inout_aliasable @block_storage @callee_owned () -> ()) -> () |
| |
| sil [ossa] @test_block_storage : $@convention(thin) () -> () { |
| bb0: |
| %0 = function_ref @c_function : $@convention(c) (@inout_aliasable @block_storage @callee_owned () -> ()) -> () |
| %1 = alloc_stack $@block_storage @callee_owned () -> () |
| %2 = project_block_storage %1 : $*@block_storage @callee_owned () -> () |
| %3 = init_block_storage_header %1 : $*@block_storage @callee_owned () -> (), invoke %0 : $@convention(c) (@inout_aliasable @block_storage @callee_owned () -> ()) -> (), type $@convention(block) () -> () |
| dealloc_stack %1 : $*@block_storage @callee_owned () -> () |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @test_store_weak : $@convention(thin) (@owned Optional<SuperKlass>, @in @sil_weak Optional<SuperKlass>, @guaranteed Optional<SuperKlass>) -> () { |
| bb0(%0 : @owned $Optional<SuperKlass>, %1 : $*@sil_weak Optional<SuperKlass>, %2 : @guaranteed $Optional<SuperKlass>): |
| store_weak %0 to %1 : $*@sil_weak Optional<SuperKlass> |
| store_weak %2 to %1 : $*@sil_weak Optional<SuperKlass> |
| destroy_value %0 : $Optional<SuperKlass> |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @test_dealloc_partial_ref : $@convention(thin) (@owned SuperKlass) -> () { |
| bb0(%0 : @owned $SuperKlass): |
| %1 = metatype $@thick SuperKlass.Type |
| dealloc_partial_ref %0 : $SuperKlass, %1 : $@thick SuperKlass.Type |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| ////////////////////// |
| // Terminator Tests // |
| ////////////////////// |
| |
| sil [ossa] @simple_branch : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| // Simple branch without an argument. |
| br bb1 |
| |
| bb1: |
| // Branch with multiple trivial arguments |
| %1 = integer_literal $Builtin.Int32, 0 |
| br bb2(%1 : $Builtin.Int32, %1 : $Builtin.Int32) |
| |
| bb2(%2 : $Builtin.Int32, %3 : $Builtin.Int32): |
| // Branch with mixed trivial and owned argument |
| br bb3(%1 : $Builtin.Int32, %0 : $Builtin.NativeObject, %2 : $Builtin.Int32) |
| |
| bb3(%4 : $Builtin.Int32, %5 : @owned $Builtin.NativeObject, %6 : $Builtin.Int32): |
| destroy_value %5 : $Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // Make sure that we can propagate through an argument through an enum that is |
| // switched upon and whose payload is then destroyed. |
| sil [ossa] @switch_enum_owned_payload_test : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %1 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %0 : $Builtin.NativeObject |
| switch_enum %1 : $Optional<Builtin.NativeObject>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb2 |
| |
| bb1(%2 : @owned $Builtin.NativeObject): |
| destroy_value %2 : $Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| br bb3 |
| |
| bb3: |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // Make sure that we can propagate through an argument through an enum that is |
| // switched upon and whose payload is then destroyed. |
| sil [ossa] @switch_enum_owned_payload_test2 : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %1 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %0 : $Builtin.NativeObject |
| switch_enum %1 : $Optional<Builtin.NativeObject>, case #Optional.none!enumelt: bb1, case #Optional.some!enumelt.1: bb2 |
| |
| bb1: |
| br bb3 |
| |
| bb2(%2 : @owned $Builtin.NativeObject): |
| destroy_value %2 : $Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @switch_enum_owned_payload_test3 : $@convention(thin) () -> () { |
| bb0: |
| %1 = enum $Optional<Builtin.NativeObject>, #Optional.none!enumelt |
| switch_enum %1 : $Optional<Builtin.NativeObject>, case #Optional.none!enumelt: bb1, case #Optional.some!enumelt.1: bb2 |
| |
| bb1: |
| br bb3 |
| |
| bb2(%2 : @owned $Builtin.NativeObject): |
| destroy_value %2 : $Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // Make sure that we can propagate through an argument through an enum that is |
| // switched upon and whose payload is then destroyed. |
| sil [ossa] @switch_enum_owned_payload_test4 : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %1 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %0 : $Builtin.NativeObject |
| switch_enum %1 : $Optional<Builtin.NativeObject>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb1 |
| |
| bb1: |
| br bb3 |
| |
| bb2(%2 : @owned $Builtin.NativeObject): |
| destroy_value %2 : $Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // Make sure that we can properly handle a guaranteed switch_enum. |
| sil [ossa] @switch_enum_guaranteed_arg_test : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () { |
| bb0(%0 : @guaranteed $Builtin.NativeObject): |
| %1 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %0 : $Builtin.NativeObject |
| switch_enum %1 : $Optional<Builtin.NativeObject>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb2 |
| |
| bb1(%2 : @guaranteed $Builtin.NativeObject): |
| end_borrow %2 : $Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| br bb3 |
| |
| bb3: |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @switch_enum_guaranteed_beginborrow_test_1a : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %1 = begin_borrow %0 : $Builtin.NativeObject |
| %2 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %1 : $Builtin.NativeObject |
| switch_enum %2 : $Optional<Builtin.NativeObject>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb2 |
| |
| bb1(%3 : @guaranteed $Builtin.NativeObject): |
| end_borrow %3 : $Builtin.NativeObject |
| end_borrow %1 : $Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| end_borrow %1 : $Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| destroy_value %0 : $Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @switch_enum_guaranteed_beginborrow_test_1b : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %1 = begin_borrow %0 : $Builtin.NativeObject |
| %2 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %1 : $Builtin.NativeObject |
| switch_enum %2 : $Optional<Builtin.NativeObject>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb2 |
| |
| bb1(%3 : @guaranteed $Builtin.NativeObject): |
| end_borrow %3 : $Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| br bb3 |
| |
| bb3: |
| end_borrow %1 : $Builtin.NativeObject |
| destroy_value %0 : $Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @switch_enum_guaranteed_beginborrow_test_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %1 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %0 : $Builtin.NativeObject |
| %2 = begin_borrow %1 : $Optional<Builtin.NativeObject> |
| switch_enum %2 : $Optional<Builtin.NativeObject>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb2 |
| |
| bb1(%3 : @guaranteed $Builtin.NativeObject): |
| end_borrow %3 : $Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| br bb3 |
| |
| bb3: |
| end_borrow %2 : $Optional<Builtin.NativeObject> |
| destroy_value %1 : $Optional<Builtin.NativeObject> |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // Make sure that we can properly handle a switch enum case where the input |
| // argument is an enum, but the final argument is trivial. |
| sil [ossa] @switch_enum_no_payload_test : $@convention(thin) () -> () { |
| bb0: |
| %0 = enum $Optional<Builtin.NativeObject>, #Optional.none!enumelt |
| switch_enum %0 : $Optional<Builtin.NativeObject>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb2 |
| |
| bb1(%1 : @owned $Builtin.NativeObject): |
| destroy_value %1 : $Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| br bb3 |
| |
| bb3: |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // Test various combinations of enum payload arguments to make sure that we |
| // handle the ordering in an invariant way. The specific interesting cases here are: |
| // |
| // 1. initial value, second value, and remaining values. |
| // 2. input enum is no payload, trivial payload, non-trivial payload |
| // |
| // The reason why this is interesting is that we do a loop over enum cases to |
| // determine if we have all trivial cases. If we do, then we only accept a |
| // ownership kind to the switch enum. Otherwise, we only accept an |
| // @owned trivial ownership kind. When we do the loop, we first skip over all |
| // trivial enums and then process only the non-trivial enums. That is why we |
| // need to make sure we handle all 3 cases. |
| sil [ossa] @three_different_payload_enum_ordering : $@convention(thin) () -> () { |
| bb0: |
| %0 = integer_literal $Builtin.Int32, 0 |
| %1 = function_ref @allocate_object : $@convention(thin) () -> @owned Builtin.NativeObject |
| br bb1 |
| |
| bb1: |
| %2 = apply %1() : $@convention(thin) () -> @owned Builtin.NativeObject |
| %e1a = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt.1, %2 : $Builtin.NativeObject |
| switch_enum %e1a : $ThreeDifferingPayloadEnum, case #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt.1: bb2, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt.1: bb3, case #ThreeDifferingPayloadEnum.nopayload!enumelt: bb4 |
| |
| bb2(%10 : @owned $Builtin.NativeObject): |
| destroy_value %10 : $Builtin.NativeObject |
| br bb5 |
| |
| bb3(%11 : $Builtin.Int32): |
| br bb5 |
| |
| bb4: |
| br bb5 |
| |
| bb5: |
| %3 = apply %1() : $@convention(thin) () -> @owned Builtin.NativeObject |
| %e1b = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt.1, %3 : $Builtin.NativeObject |
| switch_enum %e1b : $ThreeDifferingPayloadEnum, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt.1: bb7, case #ThreeDifferingPayloadEnum.nopayload!enumelt: bb8, case #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt.1: bb6 |
| |
| bb6(%12 : @owned $Builtin.NativeObject): |
| destroy_value %12 : $Builtin.NativeObject |
| br bb9 |
| |
| bb7(%13 : $Builtin.Int32): |
| br bb9 |
| |
| bb8: |
| br bb9 |
| |
| bb9: |
| %4 = apply %1() : $@convention(thin) () -> @owned Builtin.NativeObject |
| %e1c = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt.1, %4 : $Builtin.NativeObject |
| switch_enum %e1c : $ThreeDifferingPayloadEnum, case #ThreeDifferingPayloadEnum.nopayload!enumelt: bb12, case #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt.1: bb10, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt.1: bb11 |
| |
| bb10(%14 : @owned $Builtin.NativeObject): |
| destroy_value %14 : $Builtin.NativeObject |
| br bb13 |
| |
| bb11(%15 : $Builtin.Int32): |
| br bb13 |
| |
| bb12: |
| br bb13 |
| |
| bb13: |
| %e2 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.trivial_payload!enumelt.1, %0 : $Builtin.Int32 |
| switch_enum %e2 : $ThreeDifferingPayloadEnum, case #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt.1: bb16, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt.1: bb18, case #ThreeDifferingPayloadEnum.nopayload!enumelt: bb20 |
| |
| bb16(%17 : @owned $Builtin.NativeObject): |
| destroy_value %17 : $Builtin.NativeObject |
| br bb21 |
| |
| bb18(%19 : $Builtin.Int32): |
| br bb21 |
| |
| bb20: |
| br bb21 |
| |
| bb21: |
| switch_enum %e2 : $ThreeDifferingPayloadEnum, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt.1: bb24, case #ThreeDifferingPayloadEnum.nopayload!enumelt: bb26, case #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt.1: bb22 |
| |
| bb22(%23 : @owned $Builtin.NativeObject): |
| destroy_value %23 : $Builtin.NativeObject |
| br bb27 |
| |
| bb24(%25 : $Builtin.Int32): |
| br bb27 |
| |
| bb26: |
| br bb27 |
| |
| bb27: |
| switch_enum %e2 : $ThreeDifferingPayloadEnum, case #ThreeDifferingPayloadEnum.nopayload!enumelt: bb32, case #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt.1: bb28, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt.1: bb30 |
| |
| bb28(%29 : @owned $Builtin.NativeObject): |
| destroy_value %29 : $Builtin.NativeObject |
| br bb33 |
| |
| bb30(%31 : $Builtin.Int32): |
| br bb33 |
| |
| bb32: |
| br bb33 |
| |
| bb33: |
| %e3 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.nopayload!enumelt |
| switch_enum %e3 : $ThreeDifferingPayloadEnum, case #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt.1: bb34, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt.1: bb36, case #ThreeDifferingPayloadEnum.nopayload!enumelt: bb38 |
| |
| bb34(%35 : @owned $Builtin.NativeObject): |
| destroy_value %35 : $Builtin.NativeObject |
| br bb39 |
| |
| bb36(%37 : $Builtin.Int32): |
| br bb39 |
| |
| bb38: |
| br bb39 |
| |
| bb39: |
| switch_enum %e3 : $ThreeDifferingPayloadEnum, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt.1: bb42, case #ThreeDifferingPayloadEnum.nopayload!enumelt: bb44, case #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt.1: bb40 |
| |
| bb40(%41 : @owned $Builtin.NativeObject): |
| destroy_value %41 : $Builtin.NativeObject |
| br bb45 |
| |
| bb42(%43 : $Builtin.Int32): |
| br bb45 |
| |
| bb44: |
| br bb45 |
| |
| bb45: |
| switch_enum %e3 : $ThreeDifferingPayloadEnum, case #ThreeDifferingPayloadEnum.nopayload!enumelt: bb50, case #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt.1: bb46, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt.1: bb48 |
| |
| bb46(%47 : @owned $Builtin.NativeObject): |
| destroy_value %47 : $Builtin.NativeObject |
| br bb51 |
| |
| bb48(%49 : $Builtin.Int32): |
| br bb51 |
| |
| bb50: |
| br bb51 |
| |
| bb51: |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // We check first for objects, then for metatypes, then for guaranteed values |
| sil [ossa] @checked_cast_br_test : $@convention(thin) (@owned Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject, %6 : @guaranteed $Builtin.NativeObject): |
| checked_cast_br %0 : $Builtin.NativeObject to $SuperKlass, bb1, bb2 |
| |
| bb1(%1 : @owned $SuperKlass): |
| destroy_value %1 : $SuperKlass |
| br bb3 |
| |
| bb2(%2 : @owned $Builtin.NativeObject): |
| destroy_value %2 : $Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| %3 = metatype $@thick SuperKlass.Type |
| checked_cast_br %3 : $@thick SuperKlass.Type to $@thick SubKlass.Type, bb4, bb5 |
| |
| bb4(%4 : $@thick SubKlass.Type): |
| br bb6 |
| |
| bb5(%5 : $@thick SuperKlass.Type): |
| br bb6 |
| |
| bb6: |
| checked_cast_br %6 : $Builtin.NativeObject to $SuperKlass, bb7, bb8 |
| |
| bb7(%7 : @guaranteed $SuperKlass): |
| end_borrow %7 : $SuperKlass |
| br bb9 |
| |
| bb8(%8 : @guaranteed $Builtin.NativeObject): |
| end_borrow %8 : $Builtin.NativeObject |
| br bb9 |
| |
| bb9: |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @dynamic_method_br_test : $@convention(thin) (@owned AnyObject, @thick AnyObject.Type) -> () { |
| bb0(%0 : @owned $AnyObject, %1 : $@thick AnyObject.Type): |
| %2 = open_existential_ref %0 : $AnyObject to $@opened("01234567-89ab-cdef-0123-000000000000") AnyObject |
| %3 = unchecked_ref_cast %2 : $@opened("01234567-89ab-cdef-0123-000000000000") AnyObject to $Builtin.UnknownObject |
| dynamic_method_br %3 : $Builtin.UnknownObject, #X.f!1.foreign, bb1, bb2 |
| |
| bb1(%4 : $@convention(objc_method) (Builtin.UnknownObject) -> ()): |
| br bb3 |
| |
| bb2: |
| br bb3 |
| |
| bb3: |
| destroy_value %3 : $Builtin.UnknownObject |
| %5 = open_existential_metatype %1 : $@thick AnyObject.Type to $@thick (@opened("01234567-89ab-cdef-0123-000000000001") AnyObject).Type |
| dynamic_method_br %5 : $@thick (@opened("01234567-89ab-cdef-0123-000000000001") AnyObject).Type, #X.g!1.foreign, bb4, bb5 |
| |
| bb4(%6 : $@convention(objc_method) (@thick (@opened("01234567-89ab-cdef-0123-000000000001") AnyObject).Type) -> ()): |
| br bb6 |
| |
| bb5: |
| br bb6 |
| |
| bb6: |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @enum_cases_with_trivial_owned_cases_arg_into_phi : $@convention(thin) (@owned Builtin.NativeObject) -> @owned ThreeDifferingPayloadEnum { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| cond_br undef, bb3, bb4 |
| |
| bb2: |
| %1 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.nopayload!enumelt |
| destroy_value %0 : $Builtin.NativeObject |
| br bb5(%1 : $ThreeDifferingPayloadEnum) |
| |
| bb3: |
| %2 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt.1, %0 : $Builtin.NativeObject |
| br bb5(%2 : $ThreeDifferingPayloadEnum) |
| |
| bb4: |
| %3 = integer_literal $Builtin.Int32, 0 |
| %4 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.trivial_payload!enumelt.1, %3 : $Builtin.Int32 |
| destroy_value %0 : $Builtin.NativeObject |
| br bb5(%4 : $ThreeDifferingPayloadEnum) |
| |
| bb5(%5 : @owned $ThreeDifferingPayloadEnum): |
| return %5 : $ThreeDifferingPayloadEnum |
| } |
| |
| sil [ossa] @enum_cases_with_trivial_unowned_cases_arg_into_phi : $@convention(thin) (Builtin.NativeObject) -> ThreeDifferingPayloadEnum { |
| bb0(%0 : @unowned $Builtin.NativeObject): |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| cond_br undef, bb3, bb4 |
| |
| bb2: |
| %1 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.nopayload!enumelt |
| br bb5(%1 : $ThreeDifferingPayloadEnum) |
| |
| bb3: |
| %2 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt.1, %0 : $Builtin.NativeObject |
| br bb5(%2 : $ThreeDifferingPayloadEnum) |
| |
| bb4: |
| %3 = integer_literal $Builtin.Int32, 0 |
| %4 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.trivial_payload!enumelt.1, %3 : $Builtin.Int32 |
| br bb5(%4 : $ThreeDifferingPayloadEnum) |
| |
| bb5(%5 : @unowned $ThreeDifferingPayloadEnum): |
| return %5 : $ThreeDifferingPayloadEnum |
| } |
| |
| sil [ossa] @enum_cases_with_trivial_guaranteed_cases_arg_into_phi : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @owned ThreeDifferingPayloadEnum { |
| bb0(%0 : @guaranteed $Builtin.NativeObject): |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| cond_br undef, bb3, bb4 |
| |
| bb2: |
| %1 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.nopayload!enumelt |
| br bb5(%1 : $ThreeDifferingPayloadEnum) |
| |
| bb3: |
| %2 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt.1, %0 : $Builtin.NativeObject |
| br bb5(%2 : $ThreeDifferingPayloadEnum) |
| |
| bb4: |
| %3 = integer_literal $Builtin.Int32, 0 |
| %4 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.trivial_payload!enumelt.1, %3 : $Builtin.Int32 |
| br bb5(%4 : $ThreeDifferingPayloadEnum) |
| |
| bb5(%5 : @guaranteed $ThreeDifferingPayloadEnum): |
| %6 = copy_value %5 : $ThreeDifferingPayloadEnum |
| end_borrow %5 : $ThreeDifferingPayloadEnum |
| return %6 : $ThreeDifferingPayloadEnum |
| } |
| |
| sil [ossa] @enum_cases_with_trivial_guaranteed_cases_value_into_phi : $@convention(thin) (@owned Builtin.NativeObject) -> @owned ThreeDifferingPayloadEnum { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| %1 = begin_borrow %0 : $Builtin.NativeObject |
| cond_br undef, bb3, bb4 |
| |
| bb2: |
| %2 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.nopayload!enumelt |
| br bb6(%2 : $ThreeDifferingPayloadEnum) |
| |
| bb3: |
| %3 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt.1, %1 : $Builtin.NativeObject |
| br bb5(%3 : $ThreeDifferingPayloadEnum) |
| |
| bb4: |
| %4 = integer_literal $Builtin.Int32, 0 |
| %5 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.trivial_payload!enumelt.1, %4 : $Builtin.Int32 |
| br bb5(%5 : $ThreeDifferingPayloadEnum) |
| |
| bb5(%6 : @guaranteed $ThreeDifferingPayloadEnum): |
| %7 = copy_value %6 : $ThreeDifferingPayloadEnum |
| end_borrow %6 : $ThreeDifferingPayloadEnum |
| end_borrow %1 : $Builtin.NativeObject |
| br bb6(%7 : $ThreeDifferingPayloadEnum) |
| |
| bb6(%8 : @owned $ThreeDifferingPayloadEnum): |
| destroy_value %0 : $Builtin.NativeObject |
| return %8 : $ThreeDifferingPayloadEnum |
| } |
| |
| |
| ///////////////////// |
| // Aggregate Tests // |
| ///////////////////// |
| |
| // These tests make sure that we properly handle @owned forwarding of multiple |
| // levels of aggregate. |
| |
| sil [ossa] @owned_aggregates_simple : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> (@owned (Builtin.NativeObject, Builtin.NativeObject)) { |
| bb0(%0 : @owned $Builtin.NativeObject, %1 : @owned $Builtin.NativeObject): |
| %2 = tuple(%0 : $Builtin.NativeObject, %1 : $Builtin.NativeObject) |
| return %2 : $(Builtin.NativeObject, Builtin.NativeObject) |
| } |
| |
| sil [ossa] @multiple_level_owned_aggregates : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> (@owned TupleContainingNonTrivialStruct) { |
| bb0(%0 : @owned $Builtin.NativeObject, %1 : @owned $Builtin.NativeObject, %2 : @owned $Builtin.NativeObject): |
| %3 = tuple(%0 : $Builtin.NativeObject, %1 : $Builtin.NativeObject) |
| %4 = enum $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1, %2 : $Builtin.NativeObject |
| %5 = struct $TupleContainingNonTrivialStruct(%3 : $(Builtin.NativeObject, Builtin.NativeObject), %4 : $Optional<Builtin.NativeObject>) |
| return %5 : $TupleContainingNonTrivialStruct |
| } |
| |
| sil [ossa] @aggregates_with_mixed_trivial_nontrivial_types : $@convention(thin) (@owned Builtin.NativeObject, @guaranteed Builtin.NativeObject, Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject, %1 : @guaranteed $Builtin.NativeObject, %2 : @unowned $Builtin.NativeObject): |
| %3 = integer_literal $Builtin.Int32, 1 |
| %4 = copy_value %0 : $Builtin.NativeObject |
| %5 = copy_value %2 : $Builtin.NativeObject |
| %6 = tuple(%3 : $Builtin.Int32, %4 : $Builtin.NativeObject, %3 : $Builtin.Int32, %5 : $Builtin.NativeObject) |
| destroy_value %6 : $(Builtin.Int32, Builtin.NativeObject, Builtin.Int32, Builtin.NativeObject) |
| |
| %7 = tuple(%3 : $Builtin.Int32, %1 : $Builtin.NativeObject, %3 : $Builtin.Int32, %1 : $Builtin.NativeObject) |
| %8 = function_ref @borrow_tuple_user : $@convention(thin) (@guaranteed (Builtin.Int32, Builtin.NativeObject, Builtin.Int32, Builtin.NativeObject)) -> () |
| apply %8(%7) : $@convention(thin) (@guaranteed (Builtin.Int32, Builtin.NativeObject, Builtin.Int32, Builtin.NativeObject)) -> () |
| |
| %9 = tuple(%3 : $Builtin.Int32, %2 : $Builtin.NativeObject, %3 : $Builtin.Int32, %2 : $Builtin.NativeObject) |
| %10 = function_ref @unowned_tuple_user : $@convention(thin) ((Builtin.Int32, Builtin.NativeObject, Builtin.Int32, Builtin.NativeObject)) -> () |
| apply %10(%9) : $@convention(thin) ((Builtin.Int32, Builtin.NativeObject, Builtin.Int32, Builtin.NativeObject)) -> () |
| |
| destroy_value %0 : $Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // Make sure that we have a minimal verification as a non-lifetime ending use |
| // for mark_dependence. Eventually once we have a model of valid uses from the |
| // result of mark_dependence to move into the non-lifetime ending use set of the |
| // base object, this test should be extended with a negative use-after-free test |
| // in over-consume. |
| sil [ossa] @mark_dependence_test : $@convention(thin) (@owned Builtin.NativeObject, @guaranteed RefWithInt) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject, %1 : @guaranteed $RefWithInt): |
| %2 = alloc_stack $Builtin.Int32 |
| %3 = integer_literal $Builtin.Int32, 0 |
| %4 = integer_literal $Builtin.Int32, 1 |
| store %3 to [trivial] %2 : $*Builtin.Int32 |
| %5 = mark_dependence %2 : $*Builtin.Int32 on %0 : $Builtin.NativeObject |
| store %4 to [trivial] %5 : $*Builtin.Int32 |
| dealloc_stack %2 : $*Builtin.Int32 |
| %6 = alloc_stack $Builtin.Int32 |
| store %3 to [trivial] %6 : $*Builtin.Int32 |
| %7 = mark_dependence %6 : $*Builtin.Int32 on %1 : $RefWithInt |
| store %3 to [trivial] %7 : $*Builtin.Int32 |
| dealloc_stack %6 : $*Builtin.Int32 |
| destroy_value %0 : $Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @test_destructure_struct_tuple : $@convention(thin) (@owned (Builtin.NativeObject, Builtin.Int32), @owned NonTrivialStructWithTrivialField) -> @owned (Builtin.NativeObject, Builtin.Int32, Builtin.NativeObject, Builtin.Int32) { |
| bb0(%0 : @owned $(Builtin.NativeObject, Builtin.Int32), %1 : @owned $NonTrivialStructWithTrivialField): |
| // First test guaranteed |
| %2 = begin_borrow %0 : $(Builtin.NativeObject, Builtin.Int32) |
| (%3, %4) = destructure_tuple %2 : $(Builtin.NativeObject, Builtin.Int32) |
| end_borrow %2 : $(Builtin.NativeObject, Builtin.Int32) |
| |
| %5 = begin_borrow %1 : $NonTrivialStructWithTrivialField |
| (%6, %7) = destructure_struct %5 : $NonTrivialStructWithTrivialField |
| end_borrow %5 : $NonTrivialStructWithTrivialField |
| |
| // Then test destructive. |
| (%8, %9) = destructure_tuple %0 : $(Builtin.NativeObject, Builtin.Int32) |
| (%10, %11) = destructure_struct %1 : $NonTrivialStructWithTrivialField |
| %12 = tuple(%8 : $Builtin.NativeObject, %9 : $Builtin.Int32, %10 : $Builtin.NativeObject, %11 : $Builtin.Int32) |
| return %12 : $(Builtin.NativeObject, Builtin.Int32, Builtin.NativeObject, Builtin.Int32) |
| } |
| |
| sil [ossa] @test_empty_destructure : $@convention(thin) () -> () { |
| bb0: |
| %0 = struct $EmptyStruct() |
| () = destructure_struct %0 : $EmptyStruct |
| %1 = tuple() |
| () = destructure_tuple %1 : $() |
| return %1 : $() |
| } |
| |
| |
| ////////////////////////// |
| // Dependent Type Tests // |
| ////////////////////////// |
| |
| // Make sure that we are properly ignoring type dependent operands. These do not |
| // have parameter conventions. |
| sil [ossa] @dependent_type : $@convention(thin) (@owned SwiftKlassP) -> () { |
| bb0(%0 : @owned $SwiftKlassP): |
| %1 = begin_borrow %0 : $SwiftKlassP |
| %2 = open_existential_ref %1 : $SwiftKlassP to $@opened("3B64717A-E2B3-11E6-9646-985AEB89C610") SwiftKlassP |
| %cast = unchecked_ref_cast %2 : $@opened("3B64717A-E2B3-11E6-9646-985AEB89C610") SwiftKlassP to $Builtin.NativeObject |
| %3 = witness_method $@opened("3B64717A-E2B3-11E6-9646-985AEB89C610") SwiftKlassP, #SwiftKlassP.foo!1, %2 : $@opened("3B64717A-E2B3-11E6-9646-985AEB89C610") SwiftKlassP : $@convention(witness_method: SwiftKlassP) <τ_0_0 where τ_0_0 : SwiftKlassP> (@guaranteed τ_0_0) -> () |
| apply %3<@opened("3B64717A-E2B3-11E6-9646-985AEB89C610") SwiftKlassP>(%2) : $@convention(witness_method: SwiftKlassP) <τ_0_0 where τ_0_0 : SwiftKlassP> (@guaranteed τ_0_0) -> () |
| end_borrow %1 : $SwiftKlassP |
| destroy_value %0 : $SwiftKlassP |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| ///////////////// |
| // Undef Tests // |
| ///////////////// |
| |
| sil [ossa] @class_method_undef_test : $@convention(thin) () -> () { |
| bb0: |
| %0 = unchecked_ref_cast undef : $Builtin.NativeObject to $SuperKlass |
| %1 = class_method %0 : $SuperKlass, #SuperKlass.d!1 : (SuperKlass) -> () -> (), $@convention(method) (@guaranteed SuperKlass) -> () |
| destroy_value %0 : $SuperKlass |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @forwarding_instruction_undef_test : $@convention(thin) () -> () { |
| bb0: |
| %0 = unchecked_ref_cast undef : $Builtin.NativeObject to $SuperKlass |
| %1 = unchecked_ref_cast %0 : $SuperKlass to $Builtin.NativeObject |
| destroy_value %1 : $Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @transforming_terminator_undef_test : $@convention(thin) () -> () { |
| bb0: |
| %0 = unchecked_ref_cast undef : $Builtin.NativeObject to $Builtin.NativeObject |
| checked_cast_br %0 : $Builtin.NativeObject to $SuperKlass, bb1, bb2 |
| |
| bb1(%1 : @owned $SuperKlass): |
| destroy_value %1 : $SuperKlass |
| br bb3 |
| |
| bb2(%2 : @owned $Builtin.NativeObject): |
| destroy_value %2 : $Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @super_method_metatype_test : $@convention(thin) (@thick SubKlass.Type) -> () { |
| bb0(%0 : $@thick SubKlass.Type): |
| %1 = upcast %0 : $@thick SubKlass.Type to $@thick SuperKlass.Type |
| %2 = class_method %1 : $@thick SuperKlass.Type, #SuperKlass.f!1 : (SuperKlass.Type) -> () -> (), $@convention(method) (@thick SuperKlass.Type) -> () |
| apply %2(%1) : $@convention(method) (@thick SuperKlass.Type) -> () |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @switch_enum_apply_test : $@convention(thin) () -> @owned Builtin.NativeObject { |
| bb0: |
| %0 = function_ref @produce_owned_optional : $@convention(thin) () -> @owned Optional<Builtin.NativeObject> |
| %1 = apply %0() : $@convention(thin) () -> @owned Optional<Builtin.NativeObject> |
| switch_enum %1 : $Optional<Builtin.NativeObject>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb1 |
| |
| bb1: |
| unreachable |
| |
| bb2(%2 : @owned $Builtin.NativeObject): |
| return %2 : $Builtin.NativeObject |
| } |
| |
| // Make sure that we allow for @owned parameters to be passed as @guaranteed |
| // parameters since we are performing an "instantaneous" borrow. |
| sil [ossa] @owned_passed_to_guaranteed_apply_parameter : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0k(%0 : @owned $Builtin.NativeObject): |
| %1 = function_ref @guaranteed_nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| apply %1(%0) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| destroy_value %0 : $Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @owned_partial_apply_used_as_callee_guaranteed : $@convention(thin) () -> () { |
| bb0: |
| %0 = function_ref @allocate_object : $@convention(thin) () -> @owned Builtin.NativeObject |
| %1 = partial_apply %0() : $@convention(thin) () -> @owned Builtin.NativeObject |
| %2 = convert_function %1 : $@callee_owned () -> @owned Builtin.NativeObject to $@callee_guaranteed () -> @owned Builtin.NativeObject |
| %3 = apply %2() : $@callee_guaranteed () -> @owned Builtin.NativeObject |
| destroy_value %3 : $Builtin.NativeObject |
| destroy_value %2 : $@callee_guaranteed () -> @owned Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @mark_dependence_test_2 : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject, %1 : @owned $Builtin.NativeObject): |
| %2 = mark_dependence %0 : $Builtin.NativeObject on %1 : $Builtin.NativeObject |
| destroy_value %1 : $Builtin.NativeObject |
| destroy_value %2 : $Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| sil [ossa] @owned_partial_apply_is_escaping_closure : $@convention(thin) () -> () { |
| bb0: |
| %0 = function_ref @no_arg_or_output_function : $@convention(thin) () -> () |
| %1 = partial_apply %0() : $@convention(thin) () -> () |
| %2 = is_escaping_closure %1 : $@callee_owned () -> () |
| %3 = begin_borrow %1 : $@callee_owned () -> () |
| %4 = is_escaping_closure %3 : $@callee_owned () -> () |
| end_borrow %3 : $@callee_owned () -> () |
| destroy_value %1 : $@callee_owned () -> () |
| |
| %5 = partial_apply [callee_guaranteed] %0() : $@convention(thin) () -> () |
| %6 = is_escaping_closure %5 : $@callee_guaranteed () -> () |
| %7 = begin_borrow %5 : $@callee_guaranteed () -> () |
| %8 = is_escaping_closure %7 : $@callee_guaranteed () -> () |
| end_borrow %7 : $@callee_guaranteed () -> () |
| destroy_value %5 : $@callee_guaranteed () -> () |
| |
| %9999 = tuple() |
| return %9999 : $() |
| } |