mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
The problem with `is_escaping_closure` was that it didn't consume its operand and therefore reference count checks were unreliable. For example, copy-propagation could break it. As this instruction was always used together with an immediately following `destroy_value` of the closure, it makes sense to combine both into a `destroy_not_escaped_closure`. It 1. checks the reference count and returns true if it is 1 2. consumes and destroys the operand
1427 lines
54 KiB
Plaintext
1427 lines
54 KiB
Plaintext
// RUN: %target-sil-opt -update-borrowed-from -enable-objc-interop -enable-sil-verify-all=0 -module-name Swift -o /dev/null %s 2>&1
|
|
// 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 : AnyObject {
|
|
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) -> ()
|
|
|
|
class UnsafeUnownedFieldKlass {
|
|
unowned(safe) var x: @sil_unowned Builtin.NativeObject
|
|
}
|
|
|
|
class ClassProtConformingRef {}
|
|
protocol ClassProt : AnyObject {}
|
|
extension ClassProtConformingRef : ClassProt {}
|
|
|
|
////////////////
|
|
// 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
|
|
%sb = store_borrow %0 to %1 : $*Builtin.NativeObject
|
|
end_borrow %sb : $*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] @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
|
|
%1a = begin_borrow %1 : $Error
|
|
%4 = open_existential_box %1a : $Error to $*@opened("01234567-89AB-CDEF-0123-333333333333", Error) Self
|
|
destroy_addr %4 : $*@opened("01234567-89AB-CDEF-0123-333333333333", Error) Self
|
|
end_borrow %1a : $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, Builtin.Int1, Optional<Builtin.Int32>, Builtin.Int1) -> () {
|
|
bb0(%0 : @owned $ThreeDifferingPayloadEnum, %1 : $Builtin.Int1, %2 : $Optional<Builtin.Int32>, %3 : $Builtin.Int1):
|
|
%4 = integer_literal $Builtin.Int32, 2
|
|
select_enum %0 : $ThreeDifferingPayloadEnum, case #ThreeDifferingPayloadEnum.nopayload!enumelt: %4, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt: %4, case #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt: %4 : $Builtin.Int32
|
|
%5 = select_enum %2 : $Optional<Builtin.Int32>, case #Optional.none!enumelt: %1, case #Optional.some!enumelt: %3 : $Builtin.Int1
|
|
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] @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
|
|
unchecked_enum_data %1 : $Optional<Builtin.NativeObject>, #Optional.some!enumelt
|
|
unchecked_enum_data %1 : $Optional<Builtin.NativeObject>, #Optional.some!enumelt
|
|
end_borrow %1 : $Optional<Builtin.NativeObject>
|
|
%2 = unchecked_enum_data %0 : $Optional<Builtin.NativeObject>, #Optional.some!enumelt
|
|
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 : (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, %0 : $Builtin.NativeObject
|
|
switch_enum %1 : $Optional<Builtin.NativeObject>, case #Optional.some!enumelt: 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, %0 : $Builtin.NativeObject
|
|
switch_enum %1 : $Optional<Builtin.NativeObject>, case #Optional.none!enumelt: bb1, case #Optional.some!enumelt: 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: bb2, forwarding: @owned
|
|
|
|
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, %0 : $Builtin.NativeObject
|
|
switch_enum %1 : $Optional<Builtin.NativeObject>, case #Optional.some!enumelt: 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, %0 : $Builtin.NativeObject
|
|
switch_enum %1 : $Optional<Builtin.NativeObject>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
|
|
|
|
bb1(%2 : @guaranteed $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 : $Builtin.NativeObject
|
|
switch_enum %2 : $Optional<Builtin.NativeObject>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
|
|
|
|
bb1(%3 : @guaranteed $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 : $Builtin.NativeObject
|
|
switch_enum %2 : $Optional<Builtin.NativeObject>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
|
|
|
|
bb1(%3 : @guaranteed $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, %0 : $Builtin.NativeObject
|
|
%2 = begin_borrow %1 : $Optional<Builtin.NativeObject>
|
|
switch_enum %2 : $Optional<Builtin.NativeObject>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
|
|
|
|
bb1(%3 : @guaranteed $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: bb1, case #Optional.none!enumelt: bb2, forwarding: @owned
|
|
|
|
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, %2 : $Builtin.NativeObject
|
|
switch_enum %e1a : $ThreeDifferingPayloadEnum, case #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt: bb2, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt: 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, %3 : $Builtin.NativeObject
|
|
switch_enum %e1b : $ThreeDifferingPayloadEnum, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt: bb7, case #ThreeDifferingPayloadEnum.nopayload!enumelt: bb8, case #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt: 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, %4 : $Builtin.NativeObject
|
|
switch_enum %e1c : $ThreeDifferingPayloadEnum, case #ThreeDifferingPayloadEnum.nopayload!enumelt: bb12, case #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt: bb10, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt: 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, %0 : $Builtin.Int32
|
|
switch_enum %e2 : $ThreeDifferingPayloadEnum, case #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt: bb16, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt: bb18, case #ThreeDifferingPayloadEnum.nopayload!enumelt: bb20, forwarding: @owned
|
|
|
|
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: bb24, case #ThreeDifferingPayloadEnum.nopayload!enumelt: bb26, case #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt: bb22, forwarding: @owned
|
|
|
|
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: bb28, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt: bb30, forwarding: @owned
|
|
|
|
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: bb34, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt: bb36, case #ThreeDifferingPayloadEnum.nopayload!enumelt: bb38, forwarding: @owned
|
|
|
|
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: bb42, case #ThreeDifferingPayloadEnum.nopayload!enumelt: bb44, case #ThreeDifferingPayloadEnum.nontrivial_payload!enumelt: bb40, forwarding: @owned
|
|
|
|
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: bb46, case #ThreeDifferingPayloadEnum.trivial_payload!enumelt: bb48, forwarding: @owned
|
|
|
|
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 Builtin.NativeObject in %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 SuperKlass.Type in %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 Builtin.NativeObject in %6 : $Builtin.NativeObject to SuperKlass, bb7, bb8
|
|
|
|
bb7(%7 : @guaranteed $SuperKlass):
|
|
br bb9
|
|
|
|
bb8(%8 : @guaranteed $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) Self
|
|
dynamic_method_br %2 : $@opened("01234567-89ab-cdef-0123-000000000000", AnyObject) Self, #X.f!foreign, bb1, bb2
|
|
|
|
bb1(%4 : $@convention(objc_method) (@opened("01234567-89ab-cdef-0123-000000000000", AnyObject) Self) -> ()):
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
destroy_value %2 : $@opened("01234567-89ab-cdef-0123-000000000000", AnyObject) Self
|
|
%5 = open_existential_metatype %1 : $@thick AnyObject.Type to $@thick (@opened("01234567-89ab-cdef-0123-000000000001", AnyObject) Self).Type
|
|
dynamic_method_br %5 : $@thick (@opened("01234567-89ab-cdef-0123-000000000001", AnyObject) Self).Type, #X.g!foreign, bb4, bb5
|
|
|
|
bb4(%6 : $@convention(objc_method) (@thick (@opened("01234567-89ab-cdef-0123-000000000001", AnyObject) Self).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, %0 : $Builtin.NativeObject
|
|
br bb5(%2 : $ThreeDifferingPayloadEnum)
|
|
|
|
bb4:
|
|
%3 = integer_literal $Builtin.Int32, 0
|
|
%4 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.trivial_payload!enumelt, %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, %0 : $Builtin.NativeObject
|
|
br bb5(%2 : $ThreeDifferingPayloadEnum)
|
|
|
|
bb4:
|
|
%3 = integer_literal $Builtin.Int32, 0
|
|
%4 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.trivial_payload!enumelt, %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, %0 : $Builtin.NativeObject
|
|
br bb5(%2 : $ThreeDifferingPayloadEnum)
|
|
|
|
bb4:
|
|
%3 = integer_literal $Builtin.Int32, 0
|
|
%4 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.trivial_payload!enumelt, %3 : $Builtin.Int32
|
|
br bb5(%4 : $ThreeDifferingPayloadEnum)
|
|
|
|
bb5(%5 : @guaranteed $ThreeDifferingPayloadEnum):
|
|
%6 = copy_value %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 : $Builtin.NativeObject
|
|
br bb5(%3 : $ThreeDifferingPayloadEnum)
|
|
|
|
bb4:
|
|
%4 = integer_literal $Builtin.Int32, 0
|
|
%5 = enum $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.trivial_payload!enumelt, %4 : $Builtin.Int32
|
|
br bb5(%5 : $ThreeDifferingPayloadEnum)
|
|
|
|
bb5(%6 : @guaranteed $ThreeDifferingPayloadEnum):
|
|
%7 = copy_value %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, %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) Self
|
|
%cast = unchecked_ref_cast %2 : $@opened("3B64717A-E2B3-11E6-9646-985AEB89C610", SwiftKlassP) Self to $Builtin.NativeObject
|
|
%3 = witness_method $@opened("3B64717A-E2B3-11E6-9646-985AEB89C610", SwiftKlassP) Self, #SwiftKlassP.foo, %2 : $@opened("3B64717A-E2B3-11E6-9646-985AEB89C610", SwiftKlassP) Self : $@convention(witness_method: SwiftKlassP) <τ_0_0 where τ_0_0 : SwiftKlassP> (@guaranteed τ_0_0) -> ()
|
|
apply %3<@opened("3B64717A-E2B3-11E6-9646-985AEB89C610", SwiftKlassP) Self>(%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 : (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 Builtin.NativeObject in %0 : $Builtin.NativeObject to SuperKlass, bb1, bb2, forwarding: @owned
|
|
|
|
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 : (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: 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_destroy_not_escaped_closure : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @no_arg_or_output_function : $@convention(thin) () -> ()
|
|
%1 = partial_apply %0() : $@convention(thin) () -> ()
|
|
destroy_not_escaped_closure %1 : $@callee_owned () -> ()
|
|
|
|
%5 = partial_apply [callee_guaranteed] %0() : $@convention(thin) () -> ()
|
|
destroy_not_escaped_closure %5 : $@callee_guaranteed () -> ()
|
|
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// Make sure that we do not false positive due to borrow users of %12 in an
|
|
// unreachable block.
|
|
sil [ossa] @test_unreachable_users : $@convention(method) (@guaranteed UnsafeUnownedFieldKlass) -> () {
|
|
bb0(%0 : @guaranteed $UnsafeUnownedFieldKlass):
|
|
%3 = ref_element_addr %0 : $UnsafeUnownedFieldKlass, #UnsafeUnownedFieldKlass.x
|
|
%4 = load_borrow %3 : $*@sil_unowned Builtin.NativeObject
|
|
%5 = strong_copy_unowned_value %4 : $@sil_unowned Builtin.NativeObject
|
|
end_borrow %4 : $@sil_unowned Builtin.NativeObject
|
|
%12 = begin_borrow %5 : $Builtin.NativeObject
|
|
%func = function_ref @guaranteed_nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %func(%12) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
end_borrow %12 : $Builtin.NativeObject
|
|
destroy_value %5 : $Builtin.NativeObject
|
|
%36 = tuple ()
|
|
return %36 : $()
|
|
|
|
bb1:
|
|
%func2 = function_ref @guaranteed_nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
apply %func2(%12) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
|
|
unreachable
|
|
}
|
|
|
|
sil [ossa] @strong_copy_unmanaged_value_test : $@convention(thin) (@sil_unmanaged Builtin.NativeObject) -> @owned Builtin.NativeObject {
|
|
bb0(%0 : $@sil_unmanaged Builtin.NativeObject):
|
|
%1 = strong_copy_unmanaged_value %0 : $@sil_unmanaged Builtin.NativeObject
|
|
return %1 : $Builtin.NativeObject
|
|
}
|
|
|
|
sil [ossa] @mark_dependence_test_guaranteed : $@convention(thin) (@guaranteed Builtin.NativeObject, @owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : @guaranteed $Builtin.NativeObject, %1 : @owned $Builtin.NativeObject):
|
|
%2 = mark_dependence %0 : $Builtin.NativeObject on %1 : $Builtin.NativeObject
|
|
destroy_value %1 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
/////////////////////////////////////////
|
|
// Movable Guaranteed Scope Test Cases //
|
|
/////////////////////////////////////////
|
|
|
|
sil [ossa] @simple_non_postdominating_diamond : $@convention(thin) (@in_guaranteed Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*Builtin.NativeObject, %1 : @guaranteed $Builtin.NativeObject):
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%3 = load_borrow %0 : $*Builtin.NativeObject
|
|
br bb3(%3 : $Builtin.NativeObject)
|
|
|
|
bb2:
|
|
%5 = begin_borrow %1 : $Builtin.NativeObject
|
|
br bb3(%5 : $Builtin.NativeObject)
|
|
|
|
bb3(%7 : @guaranteed $Builtin.NativeObject):
|
|
end_borrow %7 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
sil [ossa] @simple_non_postdominating_diamond_with_forwarding_uses : $@convention(thin) (@in_guaranteed Builtin.NativeObject, @guaranteed NonTrivialStructWithTrivialField) -> () {
|
|
bb0(%0 : $*Builtin.NativeObject, %1 : @guaranteed $NonTrivialStructWithTrivialField):
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%3 = load_borrow %0 : $*Builtin.NativeObject
|
|
br bb3(%3 : $Builtin.NativeObject)
|
|
|
|
bb2:
|
|
%5 = struct_extract %1 : $NonTrivialStructWithTrivialField, #NonTrivialStructWithTrivialField.owner
|
|
%6 = begin_borrow %5 : $Builtin.NativeObject
|
|
br bb3(%6 : $Builtin.NativeObject)
|
|
|
|
bb3(%7 : @guaranteed $Builtin.NativeObject):
|
|
end_borrow %7 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// Make sure that we can express a borrow loop carry.
|
|
sil [ossa] @simple_loop_carry : $@convention(thin) (@in_guaranteed Builtin.NativeObject, @owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*Builtin.NativeObject, %1 : @owned $Builtin.NativeObject):
|
|
br bb1
|
|
|
|
bb1:
|
|
%2 = begin_borrow %1 : $Builtin.NativeObject
|
|
br bb2(%2 : $Builtin.NativeObject)
|
|
|
|
bb2(%3 : @guaranteed $Builtin.NativeObject):
|
|
cond_br undef, bb3, bb4
|
|
|
|
bb3:
|
|
%4 = load_borrow %0 : $*Builtin.NativeObject
|
|
end_borrow %3 : $Builtin.NativeObject
|
|
br bb2(%4 : $Builtin.NativeObject)
|
|
|
|
bb4:
|
|
end_borrow %3 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
destroy_value %1 : $Builtin.NativeObject
|
|
return %9999 : $()
|
|
}
|
|
|
|
// Make sure that we accept a borrow loop carry over a two backedge loop.
|
|
sil [ossa] @simple_loop_carry_two_backedge : $@convention(thin) (@in_guaranteed Builtin.NativeObject, @owned Builtin.NativeObject) -> () {
|
|
bb0(%0 : $*Builtin.NativeObject, %1 : @owned $Builtin.NativeObject):
|
|
br bb1
|
|
|
|
bb1:
|
|
%2 = begin_borrow %1 : $Builtin.NativeObject
|
|
br bb2(%2 : $Builtin.NativeObject)
|
|
|
|
bb2(%3 : @guaranteed $Builtin.NativeObject):
|
|
br bb2a
|
|
|
|
bb2a:
|
|
cond_br undef, bb3, bb4
|
|
|
|
bb3:
|
|
cond_br undef, bb3a, bb3b
|
|
|
|
bb3a:
|
|
%4 = load_borrow %0 : $*Builtin.NativeObject
|
|
end_borrow %3 : $Builtin.NativeObject
|
|
br bb2(%4 : $Builtin.NativeObject)
|
|
|
|
bb3b:
|
|
%5 = load_borrow %0 : $*Builtin.NativeObject
|
|
end_borrow %3 : $Builtin.NativeObject
|
|
br bb2(%5 : $Builtin.NativeObject)
|
|
|
|
bb4:
|
|
end_borrow %3 : $Builtin.NativeObject
|
|
%9999 = tuple()
|
|
destroy_value %1 : $Builtin.NativeObject
|
|
return %9999 : $()
|
|
}
|
|
|
|
sil [ossa] @init_existential_ref_forwarding : $@convention(thin) (@guaranteed ClassProtConformingRef, @owned ClassProtConformingRef) -> @owned (ClassProt, ClassProt) {
|
|
bb0(%0 : @guaranteed $ClassProtConformingRef, %1 : @owned $ClassProtConformingRef):
|
|
%2 = init_existential_ref %0 : $ClassProtConformingRef : $ClassProtConformingRef, $ClassProt
|
|
%3 = copy_value %2 : $ClassProt
|
|
%4 = init_existential_ref %1 : $ClassProtConformingRef : $ClassProtConformingRef, $ClassProt
|
|
%5 = tuple(%3 : $ClassProt, %4 : $ClassProt)
|
|
return %5 : $(ClassProt, ClassProt)
|
|
}
|
|
|
|
// Make sure that a generic struct that has an AnyObject constraint can be cased
|
|
// successfully.
|
|
|
|
struct GenericS<T> {
|
|
var t1: T
|
|
var t2: T
|
|
}
|
|
|
|
sil [ossa] @unchecked_value_cast_forwarding : $@convention(thin) <T : AnyObject> (@owned GenericS<T>) -> @owned GenericS<AnyObject> {
|
|
bb0(%0 : @owned $GenericS<T>):
|
|
%1 = unchecked_value_cast %0 : $GenericS<T> to $GenericS<AnyObject>
|
|
return %1 : $GenericS<AnyObject>
|
|
}
|
|
|
|
sil [ossa] @unchecked_value_cast_forwarding_2 : $@convention(thin) <T : AnyObject> (@guaranteed GenericS<T>) -> @owned GenericS<AnyObject> {
|
|
bb0(%0 : @guaranteed $GenericS<T>):
|
|
%1 = unchecked_value_cast %0 : $GenericS<T> to $GenericS<AnyObject>
|
|
%2 = copy_value %1 : $GenericS<AnyObject>
|
|
return %2 : $GenericS<AnyObject>
|
|
}
|
|
|
|
/////////////////////////////
|
|
// Thin To Thick Ownership //
|
|
/////////////////////////////
|
|
|
|
// Make sure that we always have thin_to_thick_function produce any ownership
|
|
// and that ownership phis propagate things correctly.
|
|
|
|
sil @thin_to_thick_function_callee : $@convention(thin) () -> ()
|
|
|
|
sil [ossa] @thin_to_thick_function_noneownership_test_1 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%f1 = function_ref @thin_to_thick_function_callee : $@convention(thin) () -> ()
|
|
%f2 = function_ref @thin_to_thick_function_callee : $@convention(thin) () -> ()
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%f1thick = thin_to_thick_function %f1 : $@convention(thin) () -> () to $@callee_owned () -> ()
|
|
br bb3(%f1thick : $@callee_owned () -> ())
|
|
|
|
bb2:
|
|
%f2thick = thin_to_thick_function %f2 : $@convention(thin) () -> () to $@callee_owned () -> ()
|
|
br bb3(%f2thick : $@callee_owned () -> ())
|
|
|
|
bb3(%fUnknown : @owned $@callee_owned () -> ()):
|
|
destroy_value %fUnknown : $@callee_owned () -> ()
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
sil [ossa] @thin_to_thick_function_noneownership_test_2 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%f1 = function_ref @thin_to_thick_function_callee : $@convention(thin) () -> ()
|
|
%f2 = function_ref @thin_to_thick_function_callee : $@convention(thin) () -> ()
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%f1thick = thin_to_thick_function %f1 : $@convention(thin) () -> () to $@callee_owned () -> ()
|
|
br bb3(%f1thick : $@callee_owned () -> ())
|
|
|
|
bb2:
|
|
%f2thick = thin_to_thick_function %f2 : $@convention(thin) () -> () to $@callee_owned () -> ()
|
|
br bb3(%f2thick : $@callee_owned () -> ())
|
|
|
|
bb3(%fUnknown : $@callee_owned () -> ()):
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
sil [ossa] @thin_to_thick_function_noneownership_test_3 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%f1 = function_ref @thin_to_thick_function_callee : $@convention(thin) () -> ()
|
|
%f2 = function_ref @thin_to_thick_function_callee : $@convention(thin) () -> ()
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%f1thick = thin_to_thick_function %f1 : $@convention(thin) () -> () to $@callee_owned () -> ()
|
|
br bb3(%f1thick : $@callee_owned () -> ())
|
|
|
|
bb2:
|
|
%f2thick = thin_to_thick_function %f2 : $@convention(thin) () -> () to $@callee_owned () -> ()
|
|
br bb3(%f2thick : $@callee_owned () -> ())
|
|
|
|
bb3(%fUnknown : @guaranteed $@callee_owned () -> ()):
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
sil [ossa] @thin_to_thick_function_noneownership_test_4 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%f1 = function_ref @thin_to_thick_function_callee : $@convention(thin) () -> ()
|
|
%f2 = function_ref @thin_to_thick_function_callee : $@convention(thin) () -> ()
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%f1thick = thin_to_thick_function %f1 : $@convention(thin) () -> () to $@callee_owned () -> ()
|
|
br bb3(%f1thick : $@callee_owned () -> ())
|
|
|
|
bb2:
|
|
%f2thick = partial_apply %f2() : $@convention(thin) () -> ()
|
|
br bb3(%f2thick : $@callee_owned () -> ())
|
|
|
|
// This case we can only pass owned b/c of the partial apply.
|
|
bb3(%fUnknown : @owned $@callee_owned () -> ()):
|
|
destroy_value %fUnknown : $@callee_owned () -> ()
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
sil [ossa] @unowned_to_ref_is_unowned_instant_use : $@convention(thin) (@guaranteed Builtin.NativeObject) -> Builtin.NativeObject {
|
|
bb0(%0 : @guaranteed $Builtin.NativeObject):
|
|
%1 = ref_to_unowned %0 : $Builtin.NativeObject to $@sil_unowned Builtin.NativeObject
|
|
%2 = unowned_to_ref %1 : $@sil_unowned Builtin.NativeObject to $Builtin.NativeObject
|
|
return %2 : $Builtin.NativeObject
|
|
}
|
|
|
|
sil [ossa] @unmanaged_to_ref_is_unowned_instant_use : $@convention(thin) (@guaranteed Builtin.NativeObject) -> Builtin.NativeObject {
|
|
bb0(%0 : @guaranteed $Builtin.NativeObject):
|
|
%1 = ref_to_unmanaged %0 : $Builtin.NativeObject to $@sil_unmanaged Builtin.NativeObject
|
|
%2 = unmanaged_to_ref %1 : $@sil_unmanaged Builtin.NativeObject to $Builtin.NativeObject
|
|
return %2 : $Builtin.NativeObject
|
|
}
|
|
|
|
sil [ossa] @nontrivial_enum_unchecked_enum_data_trivial_payload_owned : $@convention(thin) (@owned ThreeDifferingPayloadEnum) -> Builtin.Int32 {
|
|
bb0(%0 : @owned $ThreeDifferingPayloadEnum):
|
|
// NOTE: It may be surprising that %0 is consumed by this unchecked_enum_data
|
|
// despite the result of the instruction being trivial... after all... aren't
|
|
// we leaking something?! If one takes a step back, one will realize that even
|
|
// though %0 is statically owned, it dynamically is known to be a value with
|
|
// OwnershipKind::None and thus there is nothing to clean up. So in a certain
|
|
// sense by converting its non-trivial input type to a trivial output type,
|
|
// the instruction is stating that it knows that %0 is really dynamically
|
|
// OwnershipKind::None and thus it is safe to not propagate a value with
|
|
// non-OwnershipKind::None to be cleaned up to cleanup %0.
|
|
%1 = unchecked_enum_data %0 : $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.trivial_payload!enumelt
|
|
return %1 : $Builtin.Int32
|
|
}
|
|
|
|
sil [ossa] @nontrivial_enum_unchecked_enum_data_trivial_payload_guaranteed : $@convention(thin) (@guaranteed ThreeDifferingPayloadEnum) -> Builtin.Int32 {
|
|
bb0(%0 : @guaranteed $ThreeDifferingPayloadEnum):
|
|
%1 = unchecked_enum_data %0 : $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.trivial_payload!enumelt
|
|
return %1 : $Builtin.Int32
|
|
}
|
|
|
|
sil [ossa] @nontrivial_enum_unchecked_enum_data_trivial_payload_unowned : $@convention(thin) (ThreeDifferingPayloadEnum) -> Builtin.Int32 {
|
|
bb0(%0 : @unowned $ThreeDifferingPayloadEnum):
|
|
%1 = unchecked_enum_data %0 : $ThreeDifferingPayloadEnum, #ThreeDifferingPayloadEnum.trivial_payload!enumelt
|
|
return %1 : $Builtin.Int32
|
|
}
|
|
|