Files
swift-mirror/test/SILOptimizer/ownership_model_eliminator.sil
Nate Chandler e5d87f75a8 [SIL] Add source formal type to checked_cast_br.
It is necessary for opaque values where for casts that will newly start
out as checked_cast_brs and be lowered to checked_cast_addr_brs, since
the latter has the source formal type, IRGen relies on being able to
access it, and there's no way in general to obtain the source formal
type from the source lowered type.
2023-07-27 15:04:15 -07:00

414 lines
20 KiB
Plaintext

// RUN: %target-sil-opt -ownership-model-eliminator %s | %FileCheck %s
sil_stage raw
import Builtin
sil @use_native_object : $@convention(thin) (@owned Builtin.NativeObject) -> ()
sil @use_native_object_inguaranteed : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> ()
sil @use_int32 : $@convention(thin) (Builtin.Int32) -> ()
enum Either<T, R> {
case left(T)
case some(R)
}
class C {}
struct PairOfInt {
var lhs : Builtin.Int32
var rhs : Builtin.Int32
}
// CHECK-LABEL: sil @load : $@convention(thin) (@in Builtin.NativeObject, @in Builtin.Int32) -> () {
// CHECK: bb0([[ARG1:%[0-9]+]] : $*Builtin.NativeObject, [[ARG2:%[0-9]+]] : $*Builtin.Int32):
// CHECK: [[LOAD2:%[0-9]+]] = load [[ARG1]] : $*Builtin.NativeObject
// CHECK: strong_retain [[LOAD2]]
// CHECK: apply {{%[0-9]+}}([[LOAD2]])
// CHECK: [[LOAD3:%[0-9]+]] = load [[ARG1]] : $*Builtin.NativeObject
// CHECK: apply {{%[0-9]+}}([[LOAD3]])
// CHECK: [[LOAD4:%[0-9]+]] = load [[ARG2]] : $*Builtin.Int32
// CHECK: apply {{%[0-9]+}}([[LOAD4]])
sil [ossa] @load : $@convention(thin) (@in Builtin.NativeObject, @in Builtin.Int32) -> () {
bb0(%0 : $*Builtin.NativeObject, %1 : $*Builtin.Int32):
%use_native_object_func = function_ref @use_native_object : $@convention(thin) (@owned Builtin.NativeObject) -> ()
%use_int32_func = function_ref @use_int32 : $@convention(thin) (Builtin.Int32) -> ()
%3 = load [copy] %0 : $*Builtin.NativeObject
apply %use_native_object_func(%3) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
%4 = load [take] %0 : $*Builtin.NativeObject
apply %use_native_object_func(%4) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
%5 = load [trivial] %1 : $*Builtin.Int32
apply %use_int32_func(%5) : $@convention(thin) (Builtin.Int32) -> ()
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @store : $@convention(thin) (Builtin.NativeObject, @in Builtin.Int32, Builtin.Int32) -> @out Builtin.NativeObject {
// CHECK: bb0([[ARG1:%[0-9]+]] : $*Builtin.NativeObject, [[ARG2:%[0-9]+]] : $Builtin.NativeObject, [[ARG3:%[0-9]+]] : $*Builtin.Int32, [[ARG4:%[0-9]+]] : $Builtin.Int32):
// CHECK: strong_retain [[ARG2]]
// CHECK: strong_retain [[ARG2]]
// CHECK: store [[ARG2]] to [[ARG1]] : $*Builtin.NativeObject
// CHECK: [[OLDVAL:%[0-9]+]] = load [[ARG1]] : $*Builtin.NativeObject
// CHECK: store [[ARG2]] to [[ARG1]] : $*Builtin.NativeObject
// CHECK: strong_release [[OLDVAL]]
// CHECK: store [[ARG4]] to [[ARG3]] : $*Builtin.Int32
sil [ossa] @store : $@convention(thin) (Builtin.NativeObject, @in Builtin.Int32, Builtin.Int32) -> @out Builtin.NativeObject {
bb0(%0 : $*Builtin.NativeObject, %1 : @unowned $Builtin.NativeObject, %2 : $*Builtin.Int32, %3 : $Builtin.Int32):
%4 = copy_value %1 : $Builtin.NativeObject
%5 = copy_value %1 : $Builtin.NativeObject
store %4 to [init] %0 : $*Builtin.NativeObject
store %5 to [assign] %0 : $*Builtin.NativeObject
store %3 to [trivial] %2 : $*Builtin.Int32
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @borrow : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> () {
// CHECK: bb0([[ARG:%[0-9]+]] : $*Builtin.NativeObject):
// CHECK: [[BORROWED_VALUE:%[0-9]+]] = load [[ARG]] : $*Builtin.NativeObject
// CHECK: unchecked_ref_cast [[BORROWED_VALUE]]
// CHECK-NOT: end_borrow
sil [ossa] @borrow : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> () {
bb0(%0 : $*Builtin.NativeObject):
%1 = load_borrow %0 : $*Builtin.NativeObject
%2 = unchecked_ref_cast %1 : $Builtin.NativeObject to $Builtin.NativeObject
end_borrow %1 : $Builtin.NativeObject
%3 = tuple()
return %3 : $()
}
sil @opaque_function : $@convention(thin) () -> ()
// CHECK-LABEL: sil @copy_value_destroy_value : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
// CHECK: bb0([[ARG1:%.*]] : $Builtin.NativeObject):
// CHECK: strong_retain [[ARG1]]
// CHECK: strong_release [[ARG1]]
// CHECK: return [[ARG1]]
sil [ossa] @copy_value_destroy_value : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
bb0(%0 : @owned $Builtin.NativeObject):
%1 = function_ref @opaque_function : $@convention(thin) () -> ()
%2 = copy_value %0 : $Builtin.NativeObject
apply %1() : $@convention(thin) () -> ()
destroy_value %0 : $Builtin.NativeObject
return %2 : $Builtin.NativeObject
}
// CHECK-LABEL: sil @begin_borrow_store_borrow : $@convention(thin) (@owned Builtin.NativeObject) -> () {
// CHECK: bb0([[ARG:%.*]] : $Builtin.NativeObject):
// CHECK-NEXT: [[MEM:%.*]] = alloc_stack $Builtin.NativeObject
// CHECK-NEXT: store [[ARG]] to [[MEM]] : $*Builtin.NativeObject
// CHECK-NEXT: dealloc_stack [[MEM]] : $*Builtin.NativeObject
// CHECK-NEXT: strong_release [[ARG]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
// CHECK: } // end sil function 'begin_borrow_store_borrow'
sil [ossa] @begin_borrow_store_borrow : $@convention(thin) (@owned Builtin.NativeObject) -> () {
bb0(%0 : @owned $Builtin.NativeObject):
%1 = begin_borrow %0 : $Builtin.NativeObject
end_borrow %1 : $Builtin.NativeObject
%2 = alloc_stack $Builtin.NativeObject
%3 = begin_borrow %0 : $Builtin.NativeObject
%4 = store_borrow %3 to %2 : $*Builtin.NativeObject
end_borrow %4 : $*Builtin.NativeObject
end_borrow %3 : $Builtin.NativeObject
dealloc_stack %2 : $*Builtin.NativeObject
destroy_value %0 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// We no longer lower strong_copy_unowned_value. So make sure that we actually don't.
//
// CHECK-LABEL: sil @strong_copy_unowned_value_test : $@convention(thin) (@owned @sil_unowned Builtin.NativeObject) -> () {
// CHECK: bb0([[ARG:%.*]] : $@sil_unowned Builtin.NativeObject):
// CHECK-NEXT: [[STRONG:%.*]] = strong_copy_unowned_value [[ARG]] : $@sil_unowned Builtin.NativeObject
// CHECK-NEXT: strong_release [[STRONG]] : $Builtin.NativeObject
// CHECK-NEXT: unowned_release [[ARG]] : $@sil_unowned Builtin.NativeObject
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
sil [ossa] @strong_copy_unowned_value_test : $@convention(thin) (@owned @sil_unowned Builtin.NativeObject) -> () {
bb0(%0 : @owned $@sil_unowned Builtin.NativeObject):
%1 = strong_copy_unowned_value %0 : $@sil_unowned Builtin.NativeObject
destroy_value %1 : $Builtin.NativeObject
destroy_value %0 : $@sil_unowned Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @unmanaged_retain_release_test : $@convention(thin) (@owned Builtin.NativeObject, @owned C) -> () {
// CHECK: bb0([[ARG1:%.*]] : $Builtin.NativeObject, [[ARG2:%.*]] : $C):
// CHECK: strong_retain [[ARG1]] : $Builtin.NativeObject
// CHECK: autorelease_value [[ARG2]] : $C
// CHECK: strong_release [[ARG1]] : $Builtin.NativeObject
// CHECK: strong_release [[ARG1]] : $Builtin.NativeObject
// CHECK: } // end sil function 'unmanaged_retain_release_test'
sil [ossa] @unmanaged_retain_release_test : $@convention(thin) (@owned Builtin.NativeObject, @owned C) -> () {
bb0(%0 : @owned $Builtin.NativeObject, %1 : @owned $C):
unmanaged_retain_value %0 : $Builtin.NativeObject
unmanaged_autorelease_value %1 : $C
br bb1
bb1:
unmanaged_release_value %0 : $Builtin.NativeObject
destroy_value %0 : $Builtin.NativeObject
destroy_value %1 : $C
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @checked_cast_br_lowered : $@convention(thin) (@owned Builtin.NativeObject) -> () {
// CHECK: bb0([[ARG:%.*]] : $Builtin.NativeObject):
// CHECK: checked_cast_br Builtin.NativeObject in [[ARG]] : $Builtin.NativeObject to C, [[SUCCBB:bb[0-9]+]], [[FAILBB:bb[0-9]+]]
//
// CHECK: [[SUCCBB]]([[CASTED_VALUE:%.*]] : $C):
// CHECK-NEXT: strong_release [[CASTED_VALUE]]
// CHECK-NEXT: br bb3
//
// CHECK: [[FAILBB]]:
// CHECK-NEXT: strong_release [[ARG]]
// CHECK-NEXT: br bb3
sil [ossa] @checked_cast_br_lowered : $@convention(thin) (@owned Builtin.NativeObject) -> () {
bb0(%0 : @owned $Builtin.NativeObject):
checked_cast_br Builtin.NativeObject in %0 : $Builtin.NativeObject to C, bb1, bb2
bb1(%1 : @owned $C):
destroy_value %1 : $C
br bb3
bb2(%2 : @owned $Builtin.NativeObject):
destroy_value %2 : $Builtin.NativeObject
br bb3
bb3:
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @end_lifetime_test : $@convention(thin) (@owned Builtin.NativeObject) -> () {
// CHECK-NOT: end_lifetime {{%.*}} : $Builtin.NativeObject
sil [ossa] @end_lifetime_test : $@convention(thin) (@owned Builtin.NativeObject) -> () {
bb0(%0 : @owned $Builtin.NativeObject):
end_lifetime %0 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @unchecked_ownership_conversion_test : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @owned Builtin.NativeObject {
// CHECK: bb0([[ARG:%.*]] : $Builtin.NativeObject):
// CHECK: return [[ARG]] : $Builtin.NativeObject
sil [ossa] @unchecked_ownership_conversion_test : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @owned Builtin.NativeObject {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%1 = unchecked_ownership_conversion %0 : $Builtin.NativeObject, @guaranteed to @owned
return %1 : $Builtin.NativeObject
}
// CHECK-LABEL: sil @switch_enum_default_case : $@convention(thin) (@owned Either<Builtin.NativeObject, AnyObject>) -> () {
// CHECK: bb0([[ARG:%.*]] : $Either<Builtin.NativeObject, AnyObject>):
// CHECK: switch_enum [[ARG]] : $Either<Builtin.NativeObject, AnyObject>, case #Either.left!enumelt: [[SUCC_BB:bb[0-9]+]], default [[DEFAULT_BB:bb[0-9]+]]
//
// CHECK: [[SUCC_BB]]([[LHS:%.*]] : $Builtin.NativeObject
// CHECK: strong_release [[LHS]]
// CHECK: br [[EPILOG_BB:bb[0-9]+]]
//
// CHECK: [[DEFAULT_BB]]:
// CHECK: release_value [[ARG]]
// CHECK: br [[EPILOG_BB]]
//
// CHECK: [[EPILOG_BB]]:
// CHECK: return
// CHECK: } // end sil function 'switch_enum_default_case'
sil [ossa] @switch_enum_default_case : $@convention(thin) (@owned Either<Builtin.NativeObject, Builtin.AnyObject>) -> () {
bb0(%0 : @owned $Either<Builtin.NativeObject, Builtin.AnyObject>):
switch_enum %0 : $Either<Builtin.NativeObject, Builtin.AnyObject>, case #Either.left!enumelt: bb1, default bb2
bb1(%1 : @owned $Builtin.NativeObject):
destroy_value %1 : $Builtin.NativeObject
br bb3
bb2(%2 : @owned $Builtin.AnyObject):
destroy_value %2 : $Builtin.AnyObject
br bb3
bb3:
%9999 = tuple()
return %9999 : $()
}
class TestArrayStorage {
@_hasStorage var count: Builtin.Int32
init()
}
struct TestArray {
var storage : TestArrayStorage
}
struct TestArray2 {
var storage : TestArrayStorage
var someValue : Builtin.Int32
var storage2 : TestArrayStorage
}
// CHECK-LABEL: sil @test_destructure_struct_tuple : $@convention(thin) (@owned (Builtin.NativeObject, Builtin.Int32), @owned TestArray2) -> @owned (Builtin.NativeObject, Builtin.Int32, TestArrayStorage, Builtin.Int32, TestArrayStorage) {
// CHECK: bb0([[TUPLE:%.*]] : $(Builtin.NativeObject, Builtin.Int32), [[STRUCT:%.*]] : $TestArray2):
// CHECK: [[TUP_ELT_0:%.*]] = tuple_extract [[TUPLE]] : $(Builtin.NativeObject, Builtin.Int32), 0
// CHECK: [[TUP_ELT_1:%.*]] = tuple_extract [[TUPLE]] : $(Builtin.NativeObject, Builtin.Int32), 1
// CHECK: [[STRUCT_FIELD_0:%.*]] = struct_extract [[STRUCT]] : $TestArray2, #TestArray2.storage
// CHECK: [[STRUCT_FIELD_1:%.*]] = struct_extract [[STRUCT]] : $TestArray2, #TestArray2.someValue
// CHECK: [[STRUCT_FIELD_2:%.*]] = struct_extract [[STRUCT]] : $TestArray2, #TestArray2.storage2
// CHECK: [[RESULT:%.*]] = tuple ([[TUP_ELT_0]] : {{.*}}, [[TUP_ELT_1]] : {{.*}}, [[STRUCT_FIELD_0]] : {{.*}}, [[STRUCT_FIELD_1]] : {{.*}}, [[STRUCT_FIELD_2]] : {{.*}})
// CHECK: return [[RESULT]]
// CHECK: } // end sil function 'test_destructure_struct_tuple'
sil [ossa] @test_destructure_struct_tuple : $@convention(thin) (@owned (Builtin.NativeObject, Builtin.Int32), @owned TestArray2) -> @owned (Builtin.NativeObject, Builtin.Int32, TestArrayStorage, Builtin.Int32, TestArrayStorage) {
bb0(%0 : @owned $(Builtin.NativeObject, Builtin.Int32), %1 : @owned $TestArray2):
(%2, %3) = destructure_tuple %0 : $(Builtin.NativeObject, Builtin.Int32)
(%4, %5, %6) = destructure_struct %1 : $TestArray2
%7 = tuple(%2 : $Builtin.NativeObject, %3 : $Builtin.Int32, %4 : $TestArrayStorage, %5 : $Builtin.Int32, %6 : $TestArrayStorage)
return %7 : $(Builtin.NativeObject, Builtin.Int32, TestArrayStorage, Builtin.Int32, TestArrayStorage)
}
struct EmptyStruct {}
// We should completely eliminate the destructures here since the relevant
// aggregates are empty.
//
// CHECK-LABEL: sil @test_empty_destructure : $@convention(thin) () -> () {
// CHECK-NOT: destructure_struct
// CHECK-NOT: destructure_tuple
// CHECK: } // end sil function 'test_empty_destructure'
sil [ossa] @test_empty_destructure : $@convention(thin) () -> () {
bb0:
%0 = struct $EmptyStruct()
() = destructure_struct %0 : $EmptyStruct
%1 = tuple()
() = destructure_tuple %1 : $()
return %1 : $()
}
// CHECK-LABEL: sil [canonical] @test_destructure_struct_tuple_canonical : $@convention(thin) (@owned (Builtin.NativeObject, Builtin.Int32), @owned TestArray2) -> @owned (Builtin.NativeObject, Builtin.Int32, TestArrayStorage, Builtin.Int32, TestArrayStorage) {
// CHECK: bb0([[TUPLE:%.*]] : $(Builtin.NativeObject, Builtin.Int32), [[STRUCT:%.*]] : $TestArray2):
// CHECK: [[TUP_ELT_0:%.*]] = tuple_extract [[TUPLE]] : $(Builtin.NativeObject, Builtin.Int32), 0
// CHECK: [[TUP_ELT_1:%.*]] = tuple_extract [[TUPLE]] : $(Builtin.NativeObject, Builtin.Int32), 1
// CHECK: [[STRUCT_FIELD_0:%.*]] = struct_extract [[STRUCT]] : $TestArray2, #TestArray2.storage
// CHECK: [[STRUCT_FIELD_1:%.*]] = struct_extract [[STRUCT]] : $TestArray2, #TestArray2.someValue
// CHECK: [[STRUCT_FIELD_2:%.*]] = struct_extract [[STRUCT]] : $TestArray2, #TestArray2.storage2
// CHECK: [[RESULT:%.*]] = tuple ([[TUP_ELT_0]] : {{.*}}, [[TUP_ELT_1]] : {{.*}}, [[STRUCT_FIELD_0]] : {{.*}}, [[STRUCT_FIELD_1]] : {{.*}}, [[STRUCT_FIELD_2]] : {{.*}})
// CHECK: return [[RESULT]]
// CHECK: } // end sil function 'test_destructure_struct_tuple_canonical'
sil [canonical] [ossa] @test_destructure_struct_tuple_canonical : $@convention(thin) (@owned (Builtin.NativeObject, Builtin.Int32), @owned TestArray2) -> @owned (Builtin.NativeObject, Builtin.Int32, TestArrayStorage, Builtin.Int32, TestArrayStorage) {
bb0(%0 : @owned $(Builtin.NativeObject, Builtin.Int32), %1 : @owned $TestArray2):
(%2, %3) = destructure_tuple %0 : $(Builtin.NativeObject, Builtin.Int32)
(%4, %5, %6) = destructure_struct %1 : $TestArray2
%7 = tuple(%2 : $Builtin.NativeObject, %3 : $Builtin.Int32, %4 : $TestArrayStorage, %5 : $Builtin.Int32, %6 : $TestArrayStorage)
return %7 : $(Builtin.NativeObject, Builtin.Int32, TestArrayStorage, Builtin.Int32, TestArrayStorage)
}
// In the following test, the trivial parts do not have any actual uses... do
// not emit any value projections for them!
//
// CHECK-LABEL: sil [canonical] @test_destructure_with_only_some_uses : $@convention(thin) (@owned (Builtin.NativeObject, Builtin.Int32), @owned TestArray2) -> @owned (Builtin.NativeObject, TestArrayStorage, TestArrayStorage) {
// CHECK: bb0([[ARG0:%.*]] : $(Builtin.NativeObject, Builtin.Int32), [[ARG1:%.*]] : $TestArray2):
// CHECK-NEXT: [[ARG0_0:%.*]] = tuple_extract [[ARG0]]
// CHECK-NEXT: [[STORAGE:%.*]] = struct_extract [[ARG1]] : $TestArray2, #TestArray2.storage
// CHECK-NEXT: [[STORAGE2:%.*]] = struct_extract [[ARG1]] : $TestArray2, #TestArray2.storage2
// CHECK-NEXT: [[RESULT:%.*]] = tuple ([[ARG0_0]] : ${{.*}}, [[STORAGE]] : ${{.*}}, [[STORAGE2]] : ${{.*}})
// CHECK-NEXT: return [[RESULT]]
// CHECK: } // end sil function 'test_destructure_with_only_some_uses'
sil [canonical] [ossa] @test_destructure_with_only_some_uses : $@convention(thin) (@owned (Builtin.NativeObject, Builtin.Int32), @owned TestArray2) -> @owned (Builtin.NativeObject, TestArrayStorage, TestArrayStorage) {
bb0(%0 : @owned $(Builtin.NativeObject, Builtin.Int32), %1 : @owned $TestArray2):
(%2, %3) = destructure_tuple %0 : $(Builtin.NativeObject, Builtin.Int32)
(%4, %5, %6) = destructure_struct %1 : $TestArray2
%7 = tuple (%2 : $Builtin.NativeObject, %4 : $TestArrayStorage, %6 : $TestArrayStorage)
return %7 : $(Builtin.NativeObject, TestArrayStorage, TestArrayStorage)
}
// CHECK-LABEL: sil [canonical] @test_simplify_instruction : $@convention(thin) (@owned Builtin.NativeObject, Builtin.Int32) -> @owned Builtin.NativeObject {
// CHECK: bb0([[ARG:%.*]] : $Builtin.NativeObject,
// CHECK: return [[ARG]]
// CHECK: } // end sil function 'test_simplify_instruction'
sil [canonical] [ossa] @test_simplify_instruction : $@convention(thin) (@owned Builtin.NativeObject, Builtin.Int32) -> @owned Builtin.NativeObject {
bb0(%0 : @owned $Builtin.NativeObject, %1 : $Builtin.Int32):
%2 = tuple(%0 : $Builtin.NativeObject, %1 : $Builtin.Int32)
(%3, %4) = destructure_tuple %2 : $(Builtin.NativeObject, Builtin.Int32)
return %3 : $Builtin.NativeObject
}
// Just make sure that we do not crash on this function.
//
// CHECK-LABEL: sil @do_not_crash_due_to_debug_value_use : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> () {
// CHECK: } // end sil function 'do_not_crash_due_to_debug_value_use'
sil [ossa] @do_not_crash_due_to_debug_value_use : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> () {
bb0(%0a : $Builtin.Int32, %0b : $Builtin.Int32):
%0 = tuple(%0a : $Builtin.Int32, %0b : $Builtin.Int32)
(%1, %2) = destructure_tuple %0 : $(Builtin.Int32, Builtin.Int32)
debug_value %0 : $(Builtin.Int32, Builtin.Int32), let, name "myName2"
%9999 = tuple()
return %9999 : $()
}
// Just make sure that we do not crash on this function.
//
// CHECK-LABEL: sil @lower_unchecked_value_cast_to_unchecked_bitwise_cast : $@convention(thin) (PairOfInt) -> Builtin.Int64 {
// CHECK: unchecked_bitwise_cast
// CHECK: } // end sil function 'lower_unchecked_value_cast_to_unchecked_bitwise_cast'
sil [ossa] @lower_unchecked_value_cast_to_unchecked_bitwise_cast : $@convention(thin) (PairOfInt) -> Builtin.Int64 {
bb0(%0a : $PairOfInt):
%0b = unchecked_value_cast %0a : $PairOfInt to $Builtin.Int64
return %0b : $Builtin.Int64
}
// Make sure we RAUW the store_borrow's result with its dest while lowering.
//
// CHECK-LABEL: sil @lower_store_borrow_result_correctly : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[STACK:%.*]] = alloc_stack
// CHECK: store [[ARG]] to [[STACK]]
// CHECK: apply {{%.*}}([[STACK]])
// CHECK: } // end sil function 'lower_store_borrow_result_correctly'
sil [ossa] @lower_store_borrow_result_correctly : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
// This is materializing %0 into memory to be passed as an in_guaranteed arg.
%1 = alloc_stack $Builtin.NativeObject
%result = store_borrow %0 to %1 : $*Builtin.NativeObject
%f = function_ref @use_native_object_inguaranteed : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> ()
apply %f(%result) : $@convention(thin) (@in_guaranteed Builtin.NativeObject) -> ()
end_borrow %result : $*Builtin.NativeObject
dealloc_stack %1 : $*Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @lower_explicit_copy_addr : $@convention(thin) (@in_guaranteed C) -> () {
// CHECK: {{[^_]copy_addr}}
// CHECK: } // end sil function 'lower_explicit_copy_addr'
sil [ossa] @lower_explicit_copy_addr : $@convention(thin) (@in_guaranteed C) -> () {
bb0(%0 : $*C):
%1 = alloc_stack $C
explicit_copy_addr %0 to [init] %1 : $*C
destroy_addr %1 : $*C
dealloc_stack %1 : $*C
%9999 = tuple()
return %9999 : $()
}
sil @closure1: $@convention(thin) (@guaranteed C, @inout_aliasable C) -> ()
sil @closure2 : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> ()
// Ensure no assertion about missing dealloc_stack for partial_apply [on_stack] after OME
sil [ossa] @test_partial_apply_on_stack: $@convention(thin) (@guaranteed C, @inout C) -> () {
bb0(%0 : @guaranteed $C, %1 : $*C):
%f1 = function_ref @closure1: $@convention(thin) (@guaranteed C, @inout_aliasable C) -> ()
%pa1 = partial_apply [callee_guaranteed] [on_stack] %f1(%0, %1) : $@convention(thin) (@guaranteed C, @inout_aliasable C) -> ()
%md = mark_dependence %pa1 : $@noescape @callee_guaranteed () -> () on %1 : $*C
%f2 = function_ref @closure2 : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> ()
%pa2 = partial_apply [callee_guaranteed] %f2(%md) : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> ()
destroy_value %pa2 : $@callee_guaranteed () -> ()
%t = tuple ()
return %t : $()
}