blob: 7eee9bc6ce6ee1288c34110b74b68a7412dc6cd7 [file] [log] [blame]
// RUN: %target-sil-opt -enable-sil-ownership -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 //
//////////////////
sil @allocate_object : $@convention(thin) () -> @owned Builtin.NativeObject
public protocol AnyObject : class {}
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)
}
sil @three_differing_payload_enum_user : $@convention(thin) (@owned ThreeDifferingPayloadEnum, @guaranteed ThreeDifferingPayloadEnum, ThreeDifferingPayloadEnum) -> ()
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 SubKlass : SuperKlass {}
class X {
@objc func f() { }
@objc class func g() {}
}
protocol SwiftKlassP : class {
func foo()
}
sil @nontrivial_unowned_user : $@convention(thin) (Builtin.NativeObject) -> ()
struct Val {
}
class Ref {
}
struct Aleph {
var a:Ref
var b:Val
}
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)) -> ()
struct Int {
var value: Builtin.Int64
}
sil @no_arg_or_output_function : $@convention(thin) () -> ()
class RefWithInt {
var value: Builtin.Int32
init()
}
////////////////
// Test Cases //
////////////////
// Make sure that guaranteed args do not have a consuming use.
sil @direct_guaranteed_arg_doesnt_have_consuming_use : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%9999 = tuple()
return %9999 : $()
}
sil @store_borrow_result : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%1 = alloc_stack $Builtin.NativeObject
%2 = store_borrow %0 to %1 : $*Builtin.NativeObject
dealloc_stack %1 : $*Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
sil @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 @trivial_struct_extract_from_trivial : $@convention(thin) (TrivialStruct) -> () {
bb0(%0 : @trivial $TrivialStruct):
%1 = struct_extract %0 : $TrivialStruct, #TrivialStruct.f1
%9999 = tuple()
return %9999 : $()
}
sil @in_address_arg : $@convention(thin) (@in Builtin.NativeObject) -> () {
bb0(%0 : @trivial $*Builtin.NativeObject):
destroy_addr %0 : $*Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// We shouldn't assert given an unowned argument that is never used.
sil @non_trivial_unowned_arg : $@convention(thin) (Builtin.NativeObject) -> () {
bb0(%0 : @unowned $Builtin.NativeObject):
%9999 = tuple()
return %9999 : $()
}
sil @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 @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 from %0 : $Builtin.NativeObject, $Builtin.NativeObject
destroy_value %0 : $Builtin.NativeObject
apply %2(%1) : $@convention(thin) (Builtin.NativeObject) -> ()
%9999 = tuple()
return %9999 : $()
}
sil @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 from %0 : $Builtin.NativeObject, $Builtin.NativeObject
destroy_value %0 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
sil @alloc_value_buffer_dealloc_value_buffer : $@convention(thin) (@inout Builtin.UnsafeValueBuffer, Builtin.Int32) -> () {
bb0(%0 : @trivial $*Builtin.UnsafeValueBuffer, %1 : @trivial $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 @builtins_test : $@convention(thin) (@owned Error, Builtin.Int1, Builtin.RawPointer, Builtin.Word) -> ((), @error Error) {
bb0(%0 : @owned $Error, %1 : @trivial $Builtin.Int1, %2 : @trivial $Builtin.RawPointer, %3 : @trivial $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 @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 @tail_allocated_alloc_ref : $@convention(thin) (Builtin.Word, Builtin.Word, @thick SuperKlass.Type) -> () {
bb0(%0 : @trivial $Builtin.Word, %1 : @trivial $Builtin.Word, %2 : @trivial $@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 @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 : @trivial $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 @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 @existential_metatype_test : $@convention(thin) (@owned SwiftKlassP, @in SwiftKlassP) -> () {
bb0(%0 : @owned $SwiftKlassP, %1 : @trivial $*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 @value_metatype_test : $@convention(thin) (@owned Ref, @in Ref) -> () {
bb0(%0 : @owned $Ref, %1 : @trivial $*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 @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 from %0 : $RefWithInt, $RefWithInt
destroy_value %0 : $RefWithInt
%9999 = tuple()
return %9999 : $()
}
sil @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 @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 from %1 : $(Ref, Builtin.Int8), $(Ref, Builtin.Int8)
builtin "unsafeGuaranteedEnd"(%3 : $Builtin.Int8) : $()
destroy_value %1 : $(Ref, Builtin.Int8)
%9999 = tuple()
return %9999 : $()
}
sil @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 from %0 : $Optional<Builtin.NativeObject>, $Optional<Builtin.NativeObject>
%2 = unchecked_enum_data %0 : $Optional<Builtin.NativeObject>, #Optional.some!enumelt.1
return %2 : $Builtin.NativeObject
}
sil @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
%31 = begin_unpaired_access [modify] [dynamic] %21 : $*Builtin.Int32, %11 : $*Builtin.UnsafeValueBuffer
%41 = end_unpaired_access [dynamic] %11 : $*Builtin.UnsafeValueBuffer
%51 = begin_unpaired_access [read] [dynamic] %21 : $*Builtin.Int32, %11 : $*Builtin.UnsafeValueBuffer
%61 = end_unpaired_access [dynamic] %11 : $*Builtin.UnsafeValueBuffer
end_borrow %011 from %01 : $RefWithInt, $RefWithInt
dealloc_stack %11 : $*Builtin.UnsafeValueBuffer
destroy_value %01 : $RefWithInt
%9999 = tuple()
return %9999 : $()
}
sil @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 @class_method_metatype_test : $@convention(thin) (@thick SuperKlass.Type) -> () {
bb0(%0 : @trivial $@thick SuperKlass.Type):
%1 = class_method %0 : $@thick SuperKlass.Type, #SuperKlass.d!1 : (SuperKlass) -> () -> (), $@convention(method) (@guaranteed SuperKlass) -> ()
%9999 = tuple()
return %9999 : $()
}
sil @trivial_enum_return_value : $@convention(thin) () -> @owned Optional<Builtin.NativeObject> {
bb0:
%0 = enum $Optional<Builtin.NativeObject>, #Optional.none!enumelt
return %0 : $Optional<Builtin.NativeObject>
}
//////////////////////
// Terminator Tests //
//////////////////////
sil @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 : @trivial $Builtin.Int32, %3 : @trivial $Builtin.Int32):
// Branch with mixed trivial and owned argument
br bb3(%1 : $Builtin.Int32, %0 : $Builtin.NativeObject, %2 : $Builtin.Int32)
bb3(%4 : @trivial $Builtin.Int32, %5 : @owned $Builtin.NativeObject, %6 : @trivial $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 @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 properly handle a guaranteed switch_enum.
sil @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_argument %2 : $Builtin.NativeObject
br bb3
bb2:
br bb3
bb3:
%9999 = tuple()
return %9999 : $()
}
sil @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_argument %3 : $Builtin.NativeObject
end_borrow %1 from %0 : $Builtin.NativeObject, $Builtin.NativeObject
br bb3
bb2:
end_borrow %1 from %0 : $Builtin.NativeObject, $Builtin.NativeObject
br bb3
bb3:
destroy_value %0 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
sil @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_argument %3 : $Builtin.NativeObject
br bb3
bb2:
br bb3
bb3:
end_borrow %1 from %0 : $Builtin.NativeObject, $Builtin.NativeObject
destroy_value %0 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
sil @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_argument %3 : $Builtin.NativeObject
br bb3
bb2:
br bb3
bb3:
end_borrow %2 from %1 : $Optional<Builtin.NativeObject>, $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 @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
// @trivial 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 @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 : @trivial $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 : @trivial $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 : @trivial $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 : @trivial $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 : @trivial $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 : @trivial $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 : @trivial $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 : @trivial $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 : @trivial $Builtin.Int32):
br bb51
bb50:
br bb51
bb51:
%9999 = tuple()
return %9999 : $()
}
// We check first for objects and then for metatypes.
sil @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 : @trivial $@thick SubKlass.Type):
br bb6
bb5(%5 : @trivial $@thick SuperKlass.Type):
br bb6
bb6:
checked_cast_br %6 : $Builtin.NativeObject to $SuperKlass, bb7, bb8
bb7(%7 : @guaranteed $SuperKlass):
end_borrow_argument %7 : $SuperKlass
br bb9
bb8(%8 : @guaranteed $Builtin.NativeObject):
end_borrow_argument %8 : $Builtin.NativeObject
br bb9
bb9:
%9999 = tuple()
return %9999 : $()
}
sil @dynamic_method_br_test : $@convention(thin) (@owned AnyObject, @thick AnyObject.Type) -> () {
bb0(%0 : @owned $AnyObject, %1 : @trivial $@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 : @trivial $@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 : @trivial $@convention(objc_method) (@thick (@opened("01234567-89ab-cdef-0123-000000000001") AnyObject).Type) -> ()):
br bb6
bb5:
br bb6
bb6:
%9999 = tuple()
return %9999 : $()
}
sil @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 @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 @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_argument %5 : $ThreeDifferingPayloadEnum
return %6 : $ThreeDifferingPayloadEnum
}
sil @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_argument %6 : $ThreeDifferingPayloadEnum
end_borrow %1 from %0 : $Builtin.NativeObject, $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 @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 @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 @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 @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 : $()
}
//////////////////////////
// Dependent Type Tests //
//////////////////////////
// Make sure that we are properly ignoring type dependent operands. These do not
// have parameter conventions.
sil @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) <τ_0_0 where τ_0_0 : SwiftKlassP> (@guaranteed τ_0_0) -> ()
apply %3<@opened("3B64717A-E2B3-11E6-9646-985AEB89C610") SwiftKlassP>(%2) : $@convention(witness_method) _0_0 where τ_0_0 : SwiftKlassP> (@guaranteed τ_0_0) -> ()
end_borrow %1 from %0 : $SwiftKlassP, $SwiftKlassP
destroy_value %0 : $SwiftKlassP
%9999 = tuple()
return %9999 : $()
}