blob: 7afbf78d6f3d93e4d876c99c74cb60a75bac830b [file] [log] [blame]
// RUN: %target-sil-opt -enable-sil-verify-all %s -inout-deshadow | FileCheck %s
sil_stage canonical
import Builtin
import Swift
protocol P {
func foo()
}
sil @takeInt : $@convention(method) (@inout Int64) -> ()
sil @TrivialTest : $@convention(thin) (@inout Int64) -> () {
bb0(%0 : $*Int64):
%1 = alloc_stack $Int64, var, name "a" // users: %6, %2, %4, %5
copy_addr %0 to [initialization] %1 : $*Int64
%3 = function_ref @takeInt : $@convention(method) (@inout Int64) -> () // user: %4
%4 = apply %3(%1) : $@convention(method) (@inout Int64) -> ()
copy_addr %1 to %0 : $*Int64
dealloc_stack %1 : $*Int64
%7 = tuple () // user: %8
return %7 : $()
}
// CHECK-LABEL: sil @AddressOnlyTest
sil @AddressOnlyTest : $@convention(thin) (@inout P) -> () {
bb0(%0 : $*P): // CHECK: bb0(%0 : $*P):
%1 = alloc_stack $P
copy_addr %0 to [initialization] %1 : $*P
// CHECK-NEXT: debug_value_addr %0
// CHECK-NEXT: open_existential_addr %0 : $*P
%3 = open_existential_addr %1 : $*P to $*@opened("01234567-89ab-cdef-0123-000000000000") P
%4 = witness_method $@opened("01234567-89ab-cdef-0123-000000000000") P, #P.foo!1, %3 : $*@opened("01234567-89ab-cdef-0123-000000000000") P : $@convention(witness_method) @callee_owned <T: P> (@inout T) -> ()
// CHECK: apply
%5 = apply %4<@opened("01234567-89ab-cdef-0123-000000000000") P>(%3) : $@convention(witness_method) @callee_owned <T: P> (@inout T) -> ()
copy_addr [take] %1 to %0 : $*P
dealloc_stack %1 : $*P
// CHECK-NEXT: tuple ()
%9 = tuple ()
// CHECK-NEXT: return
return %9 : $()
}
class C {
}
struct NontrivialStruct {
var a: Int
var b: C
func foo()
}
sil @takeNontrivial : $@convention(method) (@inout NontrivialStruct) -> ()
// CHECK-LABEL: sil @NontrivialTest
sil @NontrivialTest : $@convention(thin) (@inout NontrivialStruct) -> () {
bb0(%0 : $*NontrivialStruct):
// CHECK: bb0(%0 : $*NontrivialStruct):
%1 = alloc_stack $NontrivialStruct
copy_addr %0 to [initialization] %1 : $*NontrivialStruct
// CHECK-NEXT: debug_value_addr %0
// CHECK-NEXT: // function_ref takeNontrivial
// CHECK-NEXT: function_ref @takeNontrivial
%3 = function_ref @takeNontrivial : $@convention(method) (@inout NontrivialStruct) -> () // user: %4
// CHECK-NEXT: apply
%4 = apply %3(%1) : $@convention(method) (@inout NontrivialStruct) -> ()
copy_addr [take] %1 to %0 : $*NontrivialStruct
dealloc_stack %1 : $*NontrivialStruct
// CHECK-NEXT: tuple
%9 = tuple ()
// CHECK-NEXT: return
return %9 : $()
}
// Inout deshadowing should *not* deshadow inouts that are copied to temporaries for use by
// @in arguments. <rdar://problem/16105449>
sil @in_argument : $@convention(thin) (@in Any) -> ()
// CHECK-LABEL: sil @inout_argument_passed_to_in_argument
sil @inout_argument_passed_to_in_argument : $@convention(thin) (@inout Any) -> () {
// CHECK: bb0([[INOUT:%.*]] : $*Any):
entry(%0 : $*Any):
%f = function_ref @in_argument : $@convention(thin) (@in Any) -> ()
%x = alloc_stack $Any
// CHECK: copy_addr [[INOUT]] to [initialization]
copy_addr %0 to [initialization] %x : $*Any
%z = apply %f(%x) : $@convention(thin) (@in Any) -> ()
dealloc_stack %x : $*Any
return %z : $()
}
sil @makeError : $@convention(thin) () -> @owned Error
struct MyStruct<T> {
@sil_stored var placeholder: T
@sil_stored var value: Bool
mutating func throwing(value: Bool) throws
init(placeholder: T, value: Bool)
}
// Verify that we deshadow in functions that throw.
// CHECK-LABEL: throwing
sil hidden @throwing : $@convention(method) <T> (Bool, @inout MyStruct<T>) -> @error Error {
// CHECK: bb0
bb0(%0 : $Bool, %1 : $*MyStruct<T>):
%2 = alloc_stack $MyStruct<T>
debug_value %0 : $Bool
// CHECK-NOT: copy_addr
copy_addr %1 to [initialization] %2 : $*MyStruct<T>
%5 = struct_extract %0 : $Bool, #Bool._value
cond_br %5, bb1, bb2
// CHECK: bb1
bb1:
%7 = function_ref @makeError : $@convention(thin) () -> @owned Error
%8 = apply %7() : $@convention(thin) () -> @owned Error
%9 = builtin "willThrow"(%8 : $Error) : $()
// CHECK-NOT: copy_addr
copy_addr [take] %2 to %1 : $*MyStruct<T>
dealloc_stack %2 : $*MyStruct<T>
throw %8 : $Error
// CHECK: bb2
bb2:
%12 = struct_element_addr %2 : $*MyStruct<T>, #MyStruct.value
store %0 to %12 : $*Bool
// CHECK-NOT: copy_addr
copy_addr [take] %2 to %1 : $*MyStruct<T>
%15 = tuple ()
dealloc_stack %2 : $*MyStruct<T>
return %15 : $()
}