mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
2005 lines
72 KiB
Plaintext
2005 lines
72 KiB
Plaintext
// RUN: %target-sil-opt %s -dump-mem-behavior -o /dev/null | %FileCheck %s
|
|
|
|
// REQUIRES: asserts
|
|
// REQUIRES: swift_in_compiler
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
class X {
|
|
@_hasStorage var a: Int32
|
|
@_hasStorage var x: X
|
|
|
|
init()
|
|
}
|
|
|
|
class Derived : X { }
|
|
|
|
class C {
|
|
@_hasStorage @_hasInitialValue final var prop: Builtin.Int32 { get }
|
|
}
|
|
|
|
class CL {
|
|
@_hasStorage let x: String
|
|
}
|
|
|
|
|
|
class Parent {
|
|
@_hasStorage var child: C { get set }
|
|
}
|
|
|
|
sil @unknown_func : $@convention(thin) (Int32, @in_guaranteed Int32) -> ()
|
|
sil @single_indirect_arg : $@convention(thin) (@in_guaranteed Int32) -> Int32
|
|
sil @single_indirect_arg_and_error : $@convention(thin) (@in Int32) -> (Int32, @error Error)
|
|
sil @single_indirect_arg_coroutine : $@yield_once @convention(thin) (@in Int32) -> @yields Int32
|
|
sil [readnone] @read_none_coroutine : $@yield_once @convention(thin) () -> @yields @inout Int32
|
|
sil @indirect_arg_and_ptr : $@convention(thin) (@in_guaranteed Int32, Builtin.RawPointer) -> Int32
|
|
sil @single_reference : $@convention(thin) (@guaranteed X) -> Int32
|
|
sil @indirect_yield_coroutine : $@yield_once @convention(thin) (@inout Int32) -> @yields @inout Int32
|
|
sil @nouser_func : $@convention(thin) () -> ()
|
|
sil @in_ptr : $@convention(thin) (@in Builtin.RawPointer) -> ()
|
|
sil @init_C : $@convention(thin) () -> @out C
|
|
sil @read_C : $@convention(thin) (@in_guaranteed C) -> ()
|
|
sil @consume : $@convention(thin) (@owned CL) -> ()
|
|
|
|
sil @store_to_int : $@convention(thin) (Int32, @inout Int32) -> () {
|
|
[%1: write v**]
|
|
[global: ]
|
|
bb0(%0 : $Int32, %1 : $*Int32):
|
|
store %0 to %1 : $*Int32
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
sil @store_to_x_a : $@convention(thin) (Int32, @guaranteed X) -> () {
|
|
[%1: noescape **, write **]
|
|
[global: ]
|
|
bb0(%0 : $Int32, %1 : $X):
|
|
%2 = ref_element_addr %1 : $X, #X.a
|
|
store %0 to %2 : $*Int32
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
sil @only_retain : $@convention(thin) (@guaranteed X) -> () {
|
|
bb0(%0 : $X):
|
|
strong_retain %0 : $X
|
|
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
sil @read_from_raw_pointer : $@convention(thin) (Builtin.RawPointer) -> UInt8 {
|
|
[%0: read v**]
|
|
[global: ]
|
|
bb0(%0 : $Builtin.RawPointer):
|
|
%1 = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*UInt8
|
|
%2 = load %1 : $*UInt8
|
|
return %2 : $UInt8
|
|
}
|
|
|
|
// CHECK-LABEL: @call_unknown_func
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %4 = apply %3(%0, %1) : $@convention(thin) (Int32, @in_guaranteed Int32) -> ()
|
|
// CHECK-NEXT: %1 = argument of bb0 : $*Int32{{.*}}
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %4 = apply %3(%0, %1) : $@convention(thin) (Int32, @in_guaranteed Int32) -> ()
|
|
// CHECK-NEXT: %2 = argument of bb0 : $*Int32
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @call_unknown_func : $@convention(thin) (Int32, @in Int32, @in Int32) -> () {
|
|
bb0(%0 : $Int32, %1 : $*Int32, %2 : $*Int32):
|
|
%3 = function_ref @unknown_func : $@convention(thin) (Int32, @in_guaranteed Int32) -> ()
|
|
%4 = apply %3(%0, %1) : $@convention(thin) (Int32, @in_guaranteed Int32) -> ()
|
|
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @call_store_to_int_not_aliased
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %4 = apply %3(%0, %1) : $@convention(thin) (Int32, @inout Int32) -> ()
|
|
// CHECK-NEXT: %1 = argument of bb0 : $*Int32{{.*}}
|
|
// CHECK-NEXT: r=0,w=1
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %4 = apply %3(%0, %1) : $@convention(thin) (Int32, @inout Int32) -> ()
|
|
// CHECK-NEXT: %2 = argument of bb0 : $*Int32
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @call_store_to_int_not_aliased : $@convention(thin) (Int32, @inout Int32, @in Int32) -> () {
|
|
bb0(%0 : $Int32, %1 : $*Int32, %2 : $*Int32):
|
|
%3 = function_ref @store_to_int : $@convention(thin) (Int32, @inout Int32) -> ()
|
|
%4 = apply %3(%0, %1) : $@convention(thin) (Int32, @inout Int32) -> ()
|
|
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @call_store_to_int_aliased
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %6 = apply %5(%0, %3) : $@convention(thin) (Int32, @inout Int32) -> ()
|
|
// CHECK-NEXT: %3 = ref_element_addr %1 : $X, #X.a{{.*}}
|
|
// CHECK-NEXT: r=0,w=1
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %6 = apply %5(%0, %3) : $@convention(thin) (Int32, @inout Int32) -> ()
|
|
// CHECK-NEXT: %4 = ref_element_addr %2 : $X, #X.a
|
|
// CHECK-NEXT: r=0,w=1
|
|
sil @call_store_to_int_aliased : $@convention(thin) (Int32, @guaranteed X, @guaranteed X) -> () {
|
|
bb0(%0 : $Int32, %1 : $X, %2 : $X):
|
|
%3 = ref_element_addr %1 : $X, #X.a
|
|
%4 = ref_element_addr %2 : $X, #X.a
|
|
%5 = function_ref @store_to_int : $@convention(thin) (Int32, @inout Int32) -> ()
|
|
%6 = apply %5(%0, %3) : $@convention(thin) (Int32, @inout Int32) -> ()
|
|
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @alias_class_member
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %5 = apply %4(%0, %1) : $@convention(thin) (Int32, @guaranteed X) -> ()
|
|
// CHECK-NEXT: %2 = ref_element_addr %1 : $X, #X.a
|
|
// CHECK-NEXT: r=0,w=1
|
|
|
|
sil @alias_class_member : $@convention(thin) (Int32) -> () {
|
|
bb0(%0 : $Int32):
|
|
%1 = alloc_ref $X
|
|
%2 = ref_element_addr %1 : $X, #X.a
|
|
fix_lifetime %2 : $*Int32
|
|
%4 = function_ref @store_to_x_a : $@convention(thin) (Int32, @guaranteed X) -> ()
|
|
%5 = apply %4(%0, %1) : $@convention(thin) (Int32, @guaranteed X) -> ()
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @alias_unknown_class_member
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %6 = apply %5(%0, %2) : $@convention(thin) (Int32, @guaranteed X) -> ()
|
|
// CHECK-NEXT: %3 = ref_element_addr %1 : $X, #X.a
|
|
// CHECK-NEXT: r=0,w=1
|
|
sil @alias_unknown_class_member : $@convention(thin) (Int32, @guaranteed X, @guaranteed X) -> () {
|
|
bb0(%0 : $Int32, %1 : $X, %2 : $X):
|
|
%3 = ref_element_addr %1 : $X, #X.a
|
|
fix_lifetime %3 : $*Int32
|
|
%5 = function_ref @store_to_x_a : $@convention(thin) (Int32, @guaranteed X) -> ()
|
|
%6 = apply %5(%0, %2) : $@convention(thin) (Int32, @guaranteed X) -> ()
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @no_alias_to_unknown_class
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %6 = apply %5(%0, %1) : $@convention(thin) (Int32, @guaranteed X) -> ()
|
|
// CHECK-NEXT: %3 = ref_element_addr %2 : $X, #X.a
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @no_alias_to_unknown_class : $@convention(thin) (Int32, @guaranteed X) -> () {
|
|
bb0(%0 : $Int32, %1 : $X):
|
|
%2 = alloc_ref $X
|
|
%3 = ref_element_addr %2 : $X, #X.a
|
|
fix_lifetime %3 : $*Int32
|
|
%5 = function_ref @store_to_x_a : $@convention(thin) (Int32, @guaranteed X) -> ()
|
|
%6 = apply %5(%0, %1) : $@convention(thin) (Int32, @guaranteed X) -> ()
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
sil @call_only_retain : $@convention(thin) (@guaranteed X, @guaranteed X) -> () {
|
|
bb0(%0 : $X, %1 : $X):
|
|
%2 = function_ref @only_retain : $@convention(thin) (@guaranteed X) -> ()
|
|
%3 = apply %2(%0) : $@convention(thin) (@guaranteed X) -> ()
|
|
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @allocstack_apply_no_side_effect
|
|
// CHECK: PAIR #0
|
|
// CHECK-NEXT: %3 = apply %2() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %1 = alloc_stack $Int32{{.*}}
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @allocstack_apply_no_side_effect : $@convention(thin) (Int32) -> () {
|
|
bb0(%0 : $Int32):
|
|
%1 = alloc_stack $Int32
|
|
%2 = function_ref @nouser_func : $@convention(thin) () -> ()
|
|
%3 = apply %2() : $@convention(thin) () -> ()
|
|
%4 = tuple ()
|
|
dealloc_stack %1 : $*Int32
|
|
return %4 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @allocstack_apply_side_effect
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %3 = apply %2(%0, %1) : $@convention(thin) (Int32, @inout Int32) -> ()
|
|
// CHECK-NEXT: %1 = alloc_stack $Int32
|
|
// CHECK-NEXT: r=0,w=1
|
|
sil @allocstack_apply_side_effect : $@convention(thin) (Int32) -> () {
|
|
bb0(%0 : $Int32):
|
|
%1 = alloc_stack $Int32
|
|
// function_ref store_to_int
|
|
%2 = function_ref @store_to_int : $@convention(thin) (Int32, @inout Int32) -> ()
|
|
%3 = apply %2(%0, %1) : $@convention(thin) (Int32, @inout Int32) -> ()
|
|
%4 = tuple ()
|
|
dealloc_stack %1 : $*Int32
|
|
return %4 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @allocstack_apply_no_escaping
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %3 = apply %2() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %1 = alloc_stack $Int32{{.*}}
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @allocstack_apply_no_escaping : $@convention(thin) (Int32) -> () {
|
|
bb0(%0 : $Int32):
|
|
%1 = alloc_stack $Int32
|
|
%2 = function_ref @nouser_func : $@convention(thin) () -> ()
|
|
%3 = apply %2() : $@convention(thin) () -> ()
|
|
%4 = function_ref @store_to_int: $@convention(thin) (Int32, @inout Int32) -> ()
|
|
%5 = apply %4(%0, %1) : $@convention(thin) (Int32, @inout Int32) -> ()
|
|
%6 = tuple ()
|
|
dealloc_stack %1 : $*Int32
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @allocstack_apply_read_only
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %4 = apply %3(%1) : $@convention(thin) (@in_guaranteed X) -> ()
|
|
// CHECK-NEXT: %1 = alloc_stack $X{{.*}}
|
|
// CHECK-NEXT: r=1,w=0
|
|
sil @allocstack_apply_read_only : $@convention(thin) (X) -> () {
|
|
bb0(%0 : $X):
|
|
%1 = alloc_stack $X
|
|
store %0 to %1 : $*X
|
|
%3 = function_ref @load_from_in : $@convention(thin) (@in_guaranteed X) -> ()
|
|
%4 = apply %3(%1) : $@convention(thin) (@in_guaranteed X) -> ()
|
|
dealloc_stack %1 : $*X
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @allocstack_and_copyaddr
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: %4 = apply %3(%0) : $@convention(thin) (@in_guaranteed Int32) -> Int32
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int32
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: %4 = apply %3(%0) : $@convention(thin) (@in_guaranteed Int32) -> Int32
|
|
// CHECK-NEXT: %1 = alloc_stack $Int32
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @allocstack_and_copyaddr : $@convention(thin) (@in Int32) -> Int32 {
|
|
bb0(%0 : $*Int32):
|
|
%1 = alloc_stack $Int32
|
|
copy_addr %0 to %1 : $*Int32
|
|
%3 = function_ref @single_indirect_arg : $@convention(thin) (@in_guaranteed Int32) -> Int32
|
|
%4 = apply %3(%0) : $@convention(thin) (@in_guaranteed Int32) -> Int32
|
|
dealloc_stack %1 : $*Int32
|
|
return %4 : $Int32
|
|
}
|
|
|
|
// CHECK-LABEL: @inout_and_copyaddr
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: %4 = apply %3(%0) : $@convention(thin) (@in_guaranteed Int32) -> Int32
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int32
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: %4 = apply %3(%0) : $@convention(thin) (@in_guaranteed Int32) -> Int32
|
|
// CHECK-NEXT: %1 = argument of bb0 : $*Int32
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @inout_and_copyaddr : $@convention(thin) (@in Int32, @inout Int32) -> Int32 {
|
|
bb0(%0 : $*Int32, %1 : $*Int32):
|
|
copy_addr %0 to %1 : $*Int32
|
|
%3 = function_ref @single_indirect_arg : $@convention(thin) (@in_guaranteed Int32) -> Int32
|
|
%4 = apply %3(%0) : $@convention(thin) (@in_guaranteed Int32) -> Int32
|
|
return %4 : $Int32
|
|
}
|
|
|
|
// CHECK-LABEL: @escaping_allocstack_and_copyaddr
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: %5 = apply %4(%0, %3) : $@convention(thin) (@in_guaranteed Int32, Builtin.RawPointer) -> Int32
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int32
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: %5 = apply %4(%0, %3) : $@convention(thin) (@in_guaranteed Int32, Builtin.RawPointer) -> Int32
|
|
// CHECK-NEXT: %1 = alloc_stack $Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil @escaping_allocstack_and_copyaddr : $@convention(thin) (@in Int32) -> Int32 {
|
|
bb0(%0 : $*Int32):
|
|
%1 = alloc_stack $Int32
|
|
copy_addr %0 to %1 : $*Int32
|
|
%3 = address_to_pointer %1 : $*Int32 to $Builtin.RawPointer
|
|
%4 = function_ref @indirect_arg_and_ptr : $@convention(thin) (@in_guaranteed Int32, Builtin.RawPointer) -> Int32
|
|
%5 = apply %4(%0, %3) : $@convention(thin) (@in_guaranteed Int32, Builtin.RawPointer) -> Int32
|
|
dealloc_stack %1 : $*Int32
|
|
return %5 : $Int32
|
|
}
|
|
|
|
// CHECK-LABEL: @escaping_allocstack_to_known_function
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %5 = apply %4(%3) : $@convention(thin) (Builtin.RawPointer) -> UInt8
|
|
// CHECK-NEXT: %1 = alloc_stack $UInt8
|
|
// CHECK-NEXT: r=1,w=0
|
|
sil @escaping_allocstack_to_known_function : $@convention(thin) (UInt8) -> UInt8 {
|
|
bb0(%0 : $UInt8):
|
|
%1 = alloc_stack $UInt8
|
|
store %0 to %1 : $*UInt8
|
|
%3 = address_to_pointer %1 : $*UInt8 to $Builtin.RawPointer
|
|
%4 = function_ref @read_from_raw_pointer : $@convention(thin) (Builtin.RawPointer) -> UInt8
|
|
%5 = apply %4(%3) : $@convention(thin) (Builtin.RawPointer) -> UInt8
|
|
dealloc_stack %1 : $*UInt8
|
|
return %5 : $UInt8
|
|
}
|
|
|
|
// CHECK-LABEL: @tryapply_allocstack_and_copyaddr
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: try_apply %3(%0) : $@convention(thin) (@in Int32) -> (Int32, @error any Error), normal bb1, error bb2
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: try_apply %3(%0) : $@convention(thin) (@in Int32) -> (Int32, @error any Error), normal bb1, error bb2
|
|
// CHECK-NEXT: %1 = alloc_stack $Int32
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @tryapply_allocstack_and_copyaddr : $@convention(thin) (@in Int32) -> Int32 {
|
|
bb0(%0 : $*Int32):
|
|
%1 = alloc_stack $Int32
|
|
copy_addr %0 to %1 : $*Int32
|
|
%3 = function_ref @single_indirect_arg_and_error : $@convention(thin) (@in Int32) -> (Int32, @error Error)
|
|
try_apply %3(%0) : $@convention(thin) (@in Int32) -> (Int32, @error Error), normal bb1, error bb2
|
|
bb1(%5 : $Int32):
|
|
dealloc_stack %1 : $*Int32
|
|
return %5 : $Int32
|
|
bb2(%8 : $Error):
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: @beginapply_allocstack_and_copyaddr
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: (%4, %5) = begin_apply %3(%0) : $@yield_once @convention(thin) (@in Int32) -> @yields Int32
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: (%4, %5) = begin_apply %3(%0) : $@yield_once @convention(thin) (@in Int32) -> @yields Int32
|
|
// CHECK-NEXT: %1 = alloc_stack $Int32
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #4.
|
|
// CHECK-NEXT: end_apply %5
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #5.
|
|
// CHECK-NEXT: end_apply %5
|
|
// CHECK-NEXT: %1 = alloc_stack $Int32
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #6.
|
|
// CHECK-NEXT: abort_apply %5
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #7.
|
|
// CHECK-NEXT: abort_apply %5
|
|
// CHECK-NEXT: %1 = alloc_stack $Int32
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @beginapply_allocstack_and_copyaddr : $@convention(thin) (@in Int32) -> Int32 {
|
|
bb0(%0 : $*Int32):
|
|
%1 = alloc_stack $Int32
|
|
copy_addr %0 to %1 : $*Int32
|
|
%3 = function_ref @single_indirect_arg_coroutine : $@yield_once @convention(thin) (@in Int32) -> @yields Int32
|
|
(%4, %5) = begin_apply %3(%0) : $@yield_once @convention(thin) (@in Int32) -> @yields Int32
|
|
cond_br undef, bb1, bb2
|
|
bb1:
|
|
end_apply %5 as $()
|
|
dealloc_stack %1 : $*Int32
|
|
return %4 : $Int32
|
|
bb2:
|
|
abort_apply %5
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: @test_indirect_yield
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: store %0 to %4 : $*Int32
|
|
// CHECK-NEXT: %1 = alloc_stack $Int32
|
|
// CHECK-NEXT: r=0,w=1
|
|
sil @test_indirect_yield : $@convention(thin) (Int32) -> () {
|
|
bb0(%0 : $Int32):
|
|
%1 = alloc_stack $Int32
|
|
store %0 to %1 : $*Int32
|
|
%3 = function_ref @indirect_yield_coroutine : $@yield_once @convention(thin) (@inout Int32) -> @yields @inout Int32
|
|
(%4, %5) = begin_apply %3(%1) : $@yield_once @convention(thin) (@inout Int32) -> @yields @inout Int32
|
|
store %0 to %4 : $*Int32
|
|
end_apply %5 as $()
|
|
dealloc_stack %1 : $*Int32
|
|
%9 = tuple ()
|
|
return %9 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @read_none_end_apply
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: (%2, %3) = begin_apply %1() : $@yield_once @convention(thin) () -> @yields @inout Int32 // users: %8, %5
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int32
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %5 = end_apply %3 as $()
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int32
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: %5 = end_apply %3 as $()
|
|
// CHECK-NEXT: (**%2**, %3) = begin_apply %1() : $@yield_once @convention(thin) () -> @yields @inout Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: abort_apply %3
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int32
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #4.
|
|
// CHECK-NEXT: abort_apply %3
|
|
// CHECK-NEXT: (**%2**, %3) = begin_apply %1() : $@yield_once @convention(thin) () -> @yields @inout Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @read_none_end_apply : $@convention(thin) (@in Int32) -> () {
|
|
bb0(%0 : $*Int32):
|
|
%3 = function_ref @read_none_coroutine : $@yield_once @convention(thin) () -> @yields @inout Int32
|
|
(%4, %5) = begin_apply %3() : $@yield_once @convention(thin) () -> @yields @inout Int32
|
|
cond_br undef, bb1, bb2
|
|
bb1:
|
|
end_apply %5 as $()
|
|
%r = tuple ()
|
|
return %r
|
|
bb2:
|
|
abort_apply %5
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: @refelementaddr_and_reference
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %3 = apply %2(%0) : $@convention(thin) (@guaranteed X) -> Int32
|
|
// CHECK-NEXT: %1 = ref_element_addr %0 : $X, #X.a
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil @refelementaddr_and_reference : $@convention(thin) (@guaranteed X) -> Int32 {
|
|
bb0(%0 : $X):
|
|
%1 = ref_element_addr %0 : $X, #X.a
|
|
%2 = function_ref @single_reference : $@convention(thin) (@guaranteed X) -> Int32
|
|
%3 = apply %2(%0) : $@convention(thin) (@guaranteed X) -> Int32
|
|
return %3 : $Int32
|
|
}
|
|
|
|
// CHECK-LABEL: @apply_and_begin_access
|
|
// CHECK: PAIR #8.
|
|
// CHECK-NEXT: %6 = apply %5(%1) : $@convention(thin) (@in_guaranteed Int32) -> Int32
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int32
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @apply_and_begin_access : $@convention(thin) (@in Int32) -> Int32 {
|
|
bb0(%0 : $*Int32):
|
|
%1 = alloc_stack $Int32
|
|
%2 = begin_access [read] [static] %0 : $*Int32
|
|
copy_addr %2 to %1 : $*Int32
|
|
end_access %2 : $*Int32
|
|
%5 = function_ref @single_indirect_arg : $@convention(thin) (@in_guaranteed Int32) -> Int32
|
|
%6 = apply %5(%1) : $@convention(thin) (@in_guaranteed Int32) -> Int32
|
|
dealloc_stack %1 : $*Int32
|
|
return %6 : $Int32
|
|
}
|
|
|
|
sil @load_from_in : $@convention(thin) (@in_guaranteed X) -> () {
|
|
bb0(%0 : $*X):
|
|
%1 = load %0 : $*X
|
|
%2 = tuple ()
|
|
return %2 : $()
|
|
}
|
|
|
|
struct TwoInts {
|
|
var i1 : Int32
|
|
var i2 : Int32
|
|
}
|
|
|
|
// CHECK-LABEL: @combination_of_read_and_write_effects
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %4 = apply %3(%1, %2) : $@convention(thin) (@inout Int32, @inout Int32) -> ()
|
|
// CHECK-NEXT: %0 = alloc_stack $TwoInts
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %4 = apply %3(%1, %2) : $@convention(thin) (@inout Int32, @inout Int32) -> ()
|
|
// CHECK-NEXT: %1 = struct_element_addr %0 : $*TwoInts, #TwoInts.i1
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: %4 = apply %3(%1, %2) : $@convention(thin) (@inout Int32, @inout Int32) -> ()
|
|
// CHECK-NEXT: %2 = struct_element_addr %0 : $*TwoInts, #TwoInts.i2
|
|
// CHECK-NEXT: r=0,w=1
|
|
sil @combination_of_read_and_write_effects : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = alloc_stack $TwoInts
|
|
%1 = struct_element_addr %0 : $*TwoInts, #TwoInts.i1
|
|
%2 = struct_element_addr %0 : $*TwoInts, #TwoInts.i2
|
|
%3 = function_ref @copy_ints : $@convention(thin) (@inout Int32, @inout Int32) -> ()
|
|
apply %3 (%1, %2) : $@convention(thin) (@inout Int32, @inout Int32) -> ()
|
|
dealloc_stack %0 : $*TwoInts
|
|
%r = tuple()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @non_overlapping_struct_fields
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %4 = apply %3(%1) : $@convention(thin) (@in_guaranteed Int32) -> Int32
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*TwoInts
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %4 = apply %3(%1) : $@convention(thin) (@in_guaranteed Int32) -> Int32
|
|
// CHECK-NEXT: %1 = struct_element_addr %0 : $*TwoInts, #TwoInts.i1
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: %4 = apply %3(%1) : $@convention(thin) (@in_guaranteed Int32) -> Int32
|
|
// CHECK-NEXT: %2 = struct_element_addr %0 : $*TwoInts, #TwoInts.i2
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @non_overlapping_struct_fields : $@convention(thin) (@in TwoInts) -> Int32 {
|
|
bb0(%0 : $*TwoInts):
|
|
%1 = struct_element_addr %0 : $*TwoInts, #TwoInts.i1
|
|
%2 = struct_element_addr %0 : $*TwoInts, #TwoInts.i2
|
|
%3 = function_ref @single_indirect_arg : $@convention(thin) (@in_guaranteed Int32) -> Int32
|
|
%4 = apply %3(%1) : $@convention(thin) (@in_guaranteed Int32) -> Int32
|
|
return %4 : $Int32
|
|
}
|
|
|
|
sil @copy_ints : $@convention(thin) (@inout Int32, @inout Int32) -> () {
|
|
[%0: read v**]
|
|
[%1: write v**]
|
|
[global: ]
|
|
bb0(%0 : $*Int32, %1 : $*Int32):
|
|
%2 = load %0 : $*Int32
|
|
store %2 to %1 : $*Int32
|
|
%r = tuple()
|
|
return %r : $()
|
|
}
|
|
|
|
sil @test_in_guaranteed_only_fun_is_ro_callee : $@convention(thin) (@in_guaranteed Int) -> ()
|
|
|
|
// CHECK-LABEL: @test_in_guaranteed_only_fun_is_ro_entry
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = apply %1(%0) : $@convention(thin) (@in_guaranteed Int) -> ()
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int
|
|
// CHECK-NEXT: r=1,w=0
|
|
sil @test_in_guaranteed_only_fun_is_ro_entry : $@convention(thin) (@in Int) -> () {
|
|
bb0(%0 : $*Int):
|
|
%f_callee = function_ref @test_in_guaranteed_only_fun_is_ro_callee : $@convention(thin) (@in_guaranteed Int) -> ()
|
|
%r1 = apply %f_callee(%0) : $@convention(thin) (@in_guaranteed Int) -> ()
|
|
|
|
%3 = tuple()
|
|
return %3 : $()
|
|
}
|
|
|
|
// Check the memory behavior of a read-only load relative to an
|
|
// unknown instruction with side effects.
|
|
//
|
|
// CHECK-LABEL: @testLetSideEffects
|
|
//
|
|
// The store does not affect the let-load (ref_element_addr).
|
|
// CHECK: PAIR #6.
|
|
// CHECK-NEXT: %6 = begin_access [modify] [static] %1 : $*Builtin.Int32
|
|
// CHECK-NEXT: %10 = ref_element_addr %9 : $C, #C.prop
|
|
// CHECK-NEXT: r=0,w=0
|
|
//
|
|
// Any unknown instructions with side effects does affect the let-load.
|
|
// CHECK: PAIR #22.
|
|
// CHECK-NEXT: end_borrow %{{.*}} : $C
|
|
// CHECK-NEXT: ref_element_addr %{{.*}} : $C, #C.prop
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #34.
|
|
// CHECK-NEXT: destroy_value %0 : $Parent
|
|
// CHECK-NEXT: ref_element_addr %{{.*}} : $C, #C.prop
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @testLetSideEffects : $@convention(thin) (@owned Parent, @inout Builtin.Int32) -> Builtin.Int32 {
|
|
bb0(%0 : @owned $Parent, %1 : $*Builtin.Int32):
|
|
%borrow1 = begin_borrow %0 : $Parent
|
|
%childAdr = ref_element_addr %borrow1 : $Parent, #Parent.child
|
|
%child = load_borrow %childAdr : $*C
|
|
|
|
%three = integer_literal $Builtin.Int32, 3
|
|
%access = begin_access [modify] [static] %1 : $*Builtin.Int32
|
|
store %three to [trivial] %access : $*Builtin.Int32
|
|
end_access %access : $*Builtin.Int32
|
|
|
|
%borrow2 = begin_borrow %child : $C
|
|
%propAdr = ref_element_addr %borrow2 : $C, #C.prop
|
|
%val = load [trivial] %propAdr : $*Builtin.Int32
|
|
end_borrow %borrow2 : $C
|
|
end_borrow %child : $C
|
|
end_borrow %borrow1 : $Parent
|
|
destroy_value %0 : $Parent
|
|
return %val : $Builtin.Int32
|
|
}
|
|
|
|
// Check the memory behavior of access markers.
|
|
//
|
|
// CHECK-LABEL: @testReadWriteAccess
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %{{.*}} = begin_access [read] [static] %0 : $*Builtin.Int32
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Builtin.Int32
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %{{.*}} = begin_access [read] [static] %0 : $*Builtin.Int32
|
|
// CHECK-NEXT: %{{.*}} = begin_access [modify] [static] %0 : $*Builtin.Int32
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #5.
|
|
// CHECK-NEXT: end_access %{{.*}} : $*Builtin.Int32
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Builtin.Int32
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #6.
|
|
// CHECK-NEXT: end_access %{{.*}} : $*Builtin.Int32
|
|
// CHECK-NEXT: %{{.*}} = begin_access [read] [static] %0 : $*Builtin.Int32
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #7.
|
|
// CHECK-NEXT: end_access %{{.*}} : $*Builtin.Int32
|
|
// CHECK-NEXT: %{{.*}} = begin_access [modify] [static] %0 : $*Builtin.Int32
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #8.
|
|
// CHECK-NEXT: %{{.*}} = begin_access [modify] [static] %0 : $*Builtin.Int32
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Builtin.Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #9.
|
|
// CHECK-NEXT: %{{.*}} = begin_access [modify] [static] %0 : $*Builtin.Int32
|
|
// CHECK-NEXT: %{{.*}} = begin_access [read] [static] %0 : $*Builtin.Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #13.
|
|
// CHECK-NEXT: end_access %{{.*}} : $*Builtin.Int32
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Builtin.Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #14.
|
|
// CHECK-NEXT: end_access %{{.*}} : $*Builtin.Int32
|
|
// CHECK-NEXT: %{{.*}} = begin_access [read] [static] %0 : $*Builtin.Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #15.
|
|
// CHECK-NEXT: end_access %{{.*}} : $*Builtin.Int32
|
|
// CHECK-NEXT: %{{.*}} = begin_access [modify] [static] %0 : $*Builtin.Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @testReadWriteAccess : $@convention(thin) (@inout Builtin.Int32) -> Builtin.Int32 {
|
|
bb0(%0 : $*Builtin.Int32):
|
|
%read = begin_access [read] [static] %0 : $*Builtin.Int32
|
|
%val = load [trivial] %read : $*Builtin.Int32
|
|
end_access %read : $*Builtin.Int32
|
|
%three = integer_literal $Builtin.Int32, 3
|
|
%write = begin_access [modify] [static] %0 : $*Builtin.Int32
|
|
store %three to [trivial] %write : $*Builtin.Int32
|
|
end_access %write : $*Builtin.Int32
|
|
return %val : $Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: @testDeinitAccess
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %1 = begin_access [deinit] [static] %0 : $*Builtin.Int32
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Builtin.Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: end_access %1 : $*Builtin.Int32
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Builtin.Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @testDeinitAccess : $@convention(thin) (@in Builtin.Int32) -> () {
|
|
bb0(%0 : $*Builtin.Int32):
|
|
%1 = begin_access [deinit] [static] %0 : $*Builtin.Int32
|
|
end_access %1 : $*Builtin.Int32
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @testInitAccess
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %{{.*}} = begin_access [init] [static] %0 : $*Builtin.Int32
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Builtin.Int32
|
|
// CHECK-NEXT: r=0,w=1
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: end_access %{{.*}} : $*Builtin.Int32
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Builtin.Int32
|
|
// CHECK-NEXT: r=0,w=1
|
|
sil [ossa] @testInitAccess : $@convention(thin) (Builtin.Int32) -> @out Builtin.Int32 {
|
|
bb0(%0 : $*Builtin.Int32, %1 : $Builtin.Int32):
|
|
%init = begin_access [init] [static] %0 : $*Builtin.Int32
|
|
store %1 to [trivial] %init : $*Builtin.Int32
|
|
end_access %init : $*Builtin.Int32
|
|
%val = load [trivial] %0 : $*Builtin.Int32
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @testReadAccessOfClassProperty
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: %5 = apply %4() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %1 = ref_element_addr %0 : $X, #X.a
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #4.
|
|
// CHECK-NEXT: %5 = apply %4() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %2 = begin_access [read] [dynamic] %1 : $*Int32
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #8.
|
|
// CHECK-NEXT: %7 = apply %4() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %2 = begin_access [read] [dynamic] %1 : $*Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @testReadAccessOfClassProperty : $@convention(thin) (@guaranteed X) -> Int32 {
|
|
bb0(%0 : @guaranteed $X):
|
|
%1 = ref_element_addr %0 : $X, #X.a
|
|
%2 = begin_access [read] [dynamic] %1 : $*Int32
|
|
%3 = load [trivial] %2 : $*Int32
|
|
%4 = function_ref @nouser_func : $@convention(thin) () -> ()
|
|
%5 = apply %4() : $@convention(thin) () -> ()
|
|
end_access %2 : $*Int32
|
|
%7 = apply %4() : $@convention(thin) () -> ()
|
|
return %3 : $Int32
|
|
}
|
|
|
|
// CHECK-LABEL: @testModifyAccessOfClassProperty
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: %6 = apply %5() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %2 = ref_element_addr %0 : $X, #X.a
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #4.
|
|
// CHECK-NEXT: %6 = apply %5() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %3 = begin_access [modify] [dynamic] %2 : $*Int32
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #8.
|
|
// CHECK-NEXT: %8 = apply %5() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %3 = begin_access [modify] [dynamic] %2 : $*Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @testModifyAccessOfClassProperty : $@convention(thin) (@guaranteed X, Int32) -> () {
|
|
bb0(%0 : @guaranteed $X, %1 : $Int32):
|
|
%2 = ref_element_addr %0 : $X, #X.a
|
|
%3 = begin_access [modify] [dynamic] %2 : $*Int32
|
|
store %1 to [trivial] %3 : $*Int32
|
|
%5 = function_ref @nouser_func : $@convention(thin) () -> ()
|
|
%6 = apply %5() : $@convention(thin) () -> ()
|
|
end_access %3 : $*Int32
|
|
%8 = apply %5() : $@convention(thin) () -> ()
|
|
%9 = tuple ()
|
|
return %9 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @testImmutableRefWithGuaranteedParam
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %4 = apply %3() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %1 = ref_element_addr [immutable] %0 : $X, #X.a
|
|
// CHECK-NEXT: r=1,w=0
|
|
sil [ossa] @testImmutableRefWithGuaranteedParam : $@convention(thin) (@guaranteed X) -> Int32 {
|
|
bb0(%0 : @guaranteed $X):
|
|
%1 = ref_element_addr [immutable] %0 : $X, #X.a
|
|
%3 = load [trivial] %1 : $*Int32
|
|
%5 = function_ref @nouser_func : $@convention(thin) () -> ()
|
|
%6 = apply %5() : $@convention(thin) () -> ()
|
|
return %3 : $Int32
|
|
}
|
|
|
|
// CHECK-LABEL: @testNonOSSAImmutableRefWithGuaranteedParam
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %4 = apply %3() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %1 = ref_element_addr [immutable] %0 : $X, #X.a
|
|
// CHECK-NEXT: r=1,w=0
|
|
sil @testNonOSSAImmutableRefWithGuaranteedParam : $@convention(thin) (@guaranteed X) -> Int32 {
|
|
bb0(%0 : $X):
|
|
%1 = ref_element_addr [immutable] %0 : $X, #X.a
|
|
%3 = load %1 : $*Int32
|
|
%5 = function_ref @nouser_func : $@convention(thin) () -> ()
|
|
%6 = apply %5() : $@convention(thin) () -> ()
|
|
return %3 : $Int32
|
|
}
|
|
// CHECK-LABEL: @testImmutableRefWithBorrow
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %5 = apply %4() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %2 = ref_element_addr [immutable] %1 : $X, #X.a
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: %7 = apply %4() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %2 = ref_element_addr [immutable] %1 : $X, #X.a
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @testImmutableRefWithBorrow : $@convention(thin) (@owned X) -> Int32 {
|
|
bb0(%0 : @owned $X):
|
|
%1 = begin_borrow %0 : $X
|
|
%2 = ref_element_addr [immutable] %1 : $X, #X.a
|
|
%3 = load [trivial] %2 : $*Int32
|
|
%4 = function_ref @nouser_func : $@convention(thin) () -> ()
|
|
%5 = apply %4() : $@convention(thin) () -> ()
|
|
end_borrow %1 : $X
|
|
%7 = apply %4() : $@convention(thin) () -> ()
|
|
destroy_value %0 : $X
|
|
return %3 : $Int32
|
|
}
|
|
|
|
// CHECK-LABEL: @testImmutableRefWithControlFlow
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = apply %1() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %4 = ref_element_addr [immutable] %3 : $X, #X.a
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: %6 = apply %1() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %4 = ref_element_addr [immutable] %3 : $X, #X.a
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #4.
|
|
// CHECK-NEXT: %9 = apply %1() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %4 = ref_element_addr [immutable] %3 : $X, #X.a
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #5.
|
|
// CHECK-NEXT: %11 = apply %1() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %4 = ref_element_addr [immutable] %3 : $X, #X.a
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #7.
|
|
// CHECK-NEXT: %14 = apply %1() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %4 = ref_element_addr [immutable] %3 : $X, #X.a
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @testImmutableRefWithControlFlow : $@convention(thin) (@owned X) -> Int32 {
|
|
bb0(%0 : @owned $X):
|
|
%1 = function_ref @nouser_func : $@convention(thin) () -> ()
|
|
%2 = apply %1() : $@convention(thin) () -> ()
|
|
%3 = begin_borrow %0 : $X
|
|
%4 = ref_element_addr [immutable] %3 : $X, #X.a
|
|
%5 = load [trivial] %4 : $*Int32
|
|
%6 = apply %1() : $@convention(thin) () -> ()
|
|
cond_br undef, bb1, bb2
|
|
bb1:
|
|
end_borrow %3 : $X
|
|
%9 = apply %1() : $@convention(thin) () -> ()
|
|
br bb4
|
|
bb2:
|
|
%11 = apply %1() : $@convention(thin) () -> ()
|
|
br bb3
|
|
bb3:
|
|
end_borrow %3 : $X
|
|
%14 = apply %1() : $@convention(thin) () -> ()
|
|
br bb4
|
|
bb4:
|
|
destroy_value %0 : $X
|
|
return %5 : $Int32
|
|
}
|
|
|
|
// CHECK-LABEL: @dontCrashWithOptionalNone
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %6 = apply %5() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %4 = ref_element_addr [immutable] %3 : $X, #X.a
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @dontCrashWithOptionalNone : $@convention(thin) () -> () {
|
|
bb0:
|
|
%26 = enum $Optional<X>, #Optional.none!enumelt
|
|
switch_enum %26 : $Optional<X>, case #Optional.none!enumelt: bb1, case #Optional.some!enumelt: bb2
|
|
bb1:
|
|
br bb3
|
|
bb2:
|
|
%68 = unchecked_enum_data %26 : $Optional<X>, #Optional.some!enumelt
|
|
%1 = ref_element_addr [immutable] %68 : $X, #X.a
|
|
%5 = function_ref @nouser_func : $@convention(thin) () -> ()
|
|
%6 = apply %5() : $@convention(thin) () -> ()
|
|
br bb3
|
|
bb3:
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @testLoadTake
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = load [take] %0 : $*C
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %2 = load [take] %0 : $*C
|
|
// CHECK-NEXT: %1 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil [ossa] @testLoadTake : $@convention(thin) (@in C, @in_guaranteed C) -> @owned C {
|
|
bb0(%0 : $*C, %1 : $*C):
|
|
%2 = load [take] %0 : $*C
|
|
return %2 : $C
|
|
}
|
|
|
|
sil_global hidden [let] @globalC : $C
|
|
sil_global hidden @globalCVar : $C
|
|
|
|
// CHECK-LABEL: @testGlobalLet
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %3 = apply %2() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %0 = global_addr @globalC : $*C
|
|
// CHECK-NEXT: r=1,w=0
|
|
sil hidden @testGlobalLet : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = global_addr @globalC : $*C
|
|
%1 = load %0 : $*C
|
|
%2 = function_ref @nouser_func : $@convention(thin) () -> ()
|
|
%3 = apply %2() : $@convention(thin) () -> ()
|
|
%4 = function_ref @read_C : $@convention(thin) (@in_guaranteed C) -> ()
|
|
%5 = apply %4(%0) : $@convention(thin) (@in_guaranteed C) -> ()
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @testInitGlobalLet
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = apply %1(%0) : $@convention(thin) () -> @out C
|
|
// CHECK-NEXT: %0 = global_addr @globalC : $*C
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil hidden [global_init_once_fn] @testInitGlobalLet : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = global_addr @globalC : $*C
|
|
%1 = function_ref @init_C : $@convention(thin) () -> @out C
|
|
%2 = apply %1(%0) : $@convention(thin) () -> @out C
|
|
%3 = load %0 : $*C
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @main
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = apply %1(%0) : $@convention(thin) () -> @out C
|
|
// CHECK-NEXT: %0 = global_addr @globalC : $*C
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [global_init_once_fn] @main : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = global_addr @globalC : $*C
|
|
%1 = function_ref @init_C : $@convention(thin) () -> @out C
|
|
%2 = apply %1(%0) : $@convention(thin) () -> @out C
|
|
%3 = load %0 : $*C
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @testGlobalVar
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %3 = apply %2() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %0 = global_addr @globalCVar : $*C
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil hidden @testGlobalVar : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = global_addr @globalCVar : $*C
|
|
%1 = load %0 : $*C
|
|
%2 = function_ref @nouser_func : $@convention(thin) () -> ()
|
|
%3 = apply %2() : $@convention(thin) () -> ()
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
sil [global_init] @addressor_of_globalC : $@convention(thin) () -> Builtin.RawPointer {
|
|
bb0:
|
|
%0 = global_addr @globalC : $*C
|
|
%1 = address_to_pointer %0 : $*C to $Builtin.RawPointer
|
|
return %1 : $Builtin.RawPointer
|
|
}
|
|
|
|
sil [global_init] @addressor_of_globalCVar : $@convention(thin) () -> Builtin.RawPointer {
|
|
bb0:
|
|
%0 = global_addr @globalCVar : $*C
|
|
%1 = address_to_pointer %0 : $*C to $Builtin.RawPointer
|
|
return %1 : $Builtin.RawPointer
|
|
}
|
|
|
|
// CHECK-LABEL: @testGlobalViaAddressorLet
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: %5 = apply %4() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*C
|
|
// CHECK-NEXT: r=1,w=0
|
|
sil @testGlobalViaAddressorLet : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @addressor_of_globalC : $@convention(thin) () -> Builtin.RawPointer
|
|
%1 = apply %0() : $@convention(thin) () -> Builtin.RawPointer
|
|
%2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*C
|
|
%3 = load %2 : $*C
|
|
%4 = function_ref @nouser_func : $@convention(thin) () -> ()
|
|
%5 = apply %4() : $@convention(thin) () -> ()
|
|
%6 = function_ref @read_C : $@convention(thin) (@in_guaranteed C) -> ()
|
|
%7 = apply %6(%2) : $@convention(thin) (@in_guaranteed C) -> ()
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @testGlobalViaAddressorVar
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: %5 = apply %4() : $@convention(thin) () -> ()
|
|
// CHECK-NEXT: %2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*C
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil @testGlobalViaAddressorVar : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @addressor_of_globalCVar : $@convention(thin) () -> Builtin.RawPointer
|
|
%1 = apply %0() : $@convention(thin) () -> Builtin.RawPointer
|
|
%2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*C
|
|
%3 = load %2 : $*C
|
|
%4 = function_ref @nouser_func : $@convention(thin) () -> ()
|
|
%5 = apply %4() : $@convention(thin) () -> ()
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @testGlobalAliasing
|
|
// CHECK: PAIR #6.
|
|
// CHECK-NEXT: store %0 to %3 : $*C
|
|
// CHECK-NEXT: %3 = pointer_to_address %2 : $Builtin.RawPointer to [strict] $*C
|
|
// CHECK-NEXT: r=0,w=1
|
|
// CHECK: PAIR #7.
|
|
// CHECK-NEXT: store %0 to %3 : $*C
|
|
// CHECK-NEXT: %6 = pointer_to_address %5 : $Builtin.RawPointer to [strict] $*C
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @testGlobalAliasing : $@convention(thin) (@guaranteed C) -> () {
|
|
bb0(%0 : $C):
|
|
%1 = function_ref @addressor_of_globalCVar : $@convention(thin) () -> Builtin.RawPointer
|
|
%2 = apply %1() : $@convention(thin) () -> Builtin.RawPointer
|
|
%3 = pointer_to_address %2 : $Builtin.RawPointer to [strict] $*C
|
|
%4 = function_ref @addressor_of_globalC : $@convention(thin) () -> Builtin.RawPointer
|
|
%5 = apply %4() : $@convention(thin) () -> Builtin.RawPointer
|
|
%6 = pointer_to_address %5 : $Builtin.RawPointer to [strict] $*C
|
|
%7 = global_addr @globalCVar : $*C
|
|
store %0 to %3 : $*C
|
|
fix_lifetime %3 : $*C
|
|
fix_lifetime %6 : $*C
|
|
%9 = tuple ()
|
|
return %9 : $()
|
|
}
|
|
|
|
// ===-----------------------------------------------------------------------===
|
|
// Test the effect of a [deinit] access on a global 'let'
|
|
//
|
|
// Test <rdar://60046018> Assert: (v->getType().isAddress()), getAccessedAddress
|
|
|
|
// CHECK-LABEL: @testDeinitInstVsNonAddressValue
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: load %{{.*}} : $*C
|
|
// CHECK-NEXT: begin_access [deinit] [static] %{{.*}} : $*Builtin.Int32
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil hidden @testDeinitInstVsNonAddressValue : $@convention(thin) (@guaranteed C) -> () {
|
|
bb0(%0 : $C):
|
|
%1 = global_addr @globalC : $*C
|
|
%2 = load %1 : $*C
|
|
%3 = ref_element_addr %2 : $C, #C.prop
|
|
%4 = load %3 : $*Builtin.Int32
|
|
%5 = ref_element_addr %0 : $C, #C.prop
|
|
%6 = begin_access [deinit] [static] %5 : $*Builtin.Int32
|
|
end_access %6 : $*Builtin.Int32
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
// ===-----------------------------------------------------------------------===
|
|
// Test that isLetAccess does not assert on nested access markers with
|
|
// interprosed projections.
|
|
|
|
struct Int64Wrapper {
|
|
var val : Int64
|
|
}
|
|
|
|
// CHECK-LABEL: @testNestedAccessWithInterposedProjection
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: %1 = begin_access [modify] [static] %0 : $*Int64Wrapper
|
|
// CHECK-NEXT: %3 = begin_access [read] [static] %2 : $*Int64
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil @testNestedAccessWithInterposedProjection : $@convention(thin) (@inout Int64Wrapper) -> () {
|
|
bb0(%0 : $*Int64Wrapper):
|
|
%1 = begin_access [modify] [static] %0 : $*Int64Wrapper
|
|
%2 = struct_element_addr %1 : $*Int64Wrapper, #Int64Wrapper.val
|
|
%3 = begin_access [read] [static] %2 : $*Int64
|
|
%4 = struct_element_addr %3 : $*Int64, #Int64._value
|
|
%5 = load %4 : $*Builtin.Int64
|
|
end_access %3 : $*Int64
|
|
end_access %1 : $*Int64Wrapper
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @test_copy_addr_initialize
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: copy_addr %1 to [init] %0 : $*C
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=0,w=1
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: copy_addr %1 to [init] %0 : $*C
|
|
// CHECK-NEXT: %1 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: copy_addr %1 to [init] %0 : $*C
|
|
// CHECK-NEXT: %2 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @test_copy_addr_initialize : $@convention(thin) (@inout C, @inout C) -> @out C {
|
|
bb0(%0 : $*C, %1 : $*C, %2: $*C):
|
|
copy_addr %1 to [init] %0 : $*C
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @test_copy_addr_assign
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: copy_addr %1 to %0 : $*C
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: copy_addr %1 to %0 : $*C
|
|
// CHECK-NEXT: %1 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: copy_addr %1 to %0 : $*C
|
|
// CHECK-NEXT: %2 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @test_copy_addr_assign : $@convention(thin) (@inout C, @inout C, @inout C) -> () {
|
|
bb0(%0 : $*C, %1 : $*C, %2: $*C):
|
|
copy_addr %1 to %0 : $*C
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @test_copy_addr_take
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: copy_addr [take] %1 to [init] %0 : $*C
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=0,w=1
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: copy_addr [take] %1 to [init] %0 : $*C
|
|
// CHECK-NEXT: %1 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: copy_addr [take] %1 to [init] %0 : $*C
|
|
// CHECK-NEXT: %2 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @test_copy_addr_take : $@convention(thin) (@in C, @inout C) -> @out C {
|
|
bb0(%0 : $*C, %1 : $*C, %2: $*C):
|
|
copy_addr [take] %1 to [init] %0 : $*C
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @test_destroy_value
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %1 = load [copy] %0 : $*C
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: destroy_value %1 : $C
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil [ossa] @test_destroy_value : $@convention(thin) (@in C) -> () {
|
|
bb0 (%0 : $*C):
|
|
%1 = load [copy] %0 : $*C
|
|
destroy_value %1 : $C
|
|
destroy_addr %0 : $*C
|
|
%2 = tuple()
|
|
return %2 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @test_destroy_value_with_effects
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: destroy_value %0 : $X
|
|
// CHECK-NEXT: %2 = ref_element_addr %1 : $X, #X.x
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @test_destroy_value_with_effects : $@convention(thin) (@owned X) -> () {
|
|
bb0 (%0 : @owned $X):
|
|
%1 = begin_borrow %0 : $X
|
|
%2 = ref_element_addr %1 : $X, #X.x
|
|
fix_lifetime %2 : $*X
|
|
end_borrow %1 : $X
|
|
destroy_value %0 : $X
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: @test_deadend_destroy_value
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: destroy_value [dead_end] %0 : $X
|
|
// CHECK-NEXT: %2 = ref_element_addr %1 : $X, #X.x
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil [ossa] @test_deadend_destroy_value : $@convention(thin) (@owned X) -> () {
|
|
bb0 (%0 : @owned $X):
|
|
%1 = begin_borrow %0 : $X
|
|
%2 = ref_element_addr %1 : $X, #X.x
|
|
fix_lifetime %2 : $*X
|
|
end_borrow %1 : $X
|
|
destroy_value [dead_end] %0 : $X
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: @test_copy_value
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %2 = copy_value %1 : $C
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil [ossa] @test_copy_value : $@convention(thin) (@in C) -> () {
|
|
bb0 (%0 : $*C):
|
|
%1 = load [copy] %0 : $*C
|
|
%2 = copy_value %1 : $C
|
|
destroy_value %1 : $C
|
|
destroy_value %2 : $C
|
|
destroy_addr %0 : $*C
|
|
%3 = tuple()
|
|
return %3 : $()
|
|
}
|
|
|
|
sil @do_store : $@convention(thin) (@guaranteed Parent) -> () {
|
|
[%0: noescape **, read c0.v**]
|
|
[global: write]
|
|
}
|
|
|
|
// CHECK-LABEL: @test_double_class_indirection
|
|
// CHECK: PAIR #4.
|
|
// CHECK-NEXT: %8 = apply %7(%1) : $@convention(thin) (@guaranteed Parent) -> ()
|
|
// CHECK-NEXT: %3 = ref_element_addr %1 : $Parent, #Parent.child
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK-NEXT: PAIR #5.
|
|
// CHECK-NEXT: %8 = apply %7(%1) : $@convention(thin) (@guaranteed Parent) -> ()
|
|
// CHECK-NEXT: %5 = ref_element_addr %2 : $C, #C.prop
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil @test_double_class_indirection : $@convention(thin) (Builtin.Int32) -> () {
|
|
bb0(%0 : $Builtin.Int32):
|
|
%1 = alloc_ref $Parent
|
|
%2 = alloc_ref $C
|
|
%3 = ref_element_addr %1 : $Parent, #Parent.child
|
|
store %2 to %3 : $*C
|
|
%5 = ref_element_addr %2 : $C, #C.prop
|
|
store %0 to %5 : $*Builtin.Int32
|
|
|
|
%f = function_ref @do_store : $@convention(thin) (@guaranteed Parent) -> ()
|
|
%a = apply %f(%1) : $@convention(thin) (@guaranteed Parent) -> ()
|
|
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
sil_global @gi : $Int
|
|
sil @g_init : $@convention(c) () -> ()
|
|
|
|
// CHECK-LABEL: @test_builtin_once
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %4 = builtin "once"(%0 : $Builtin.RawPointer, %3 : $@convention(c) () -> ()) : $()
|
|
// CHECK-NEXT: %1 = global_addr @gi : $*Int
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %4 = builtin "once"(%0 : $Builtin.RawPointer, %3 : $@convention(c) () -> ()) : $()
|
|
// CHECK-NEXT: %2 = alloc_stack $Int
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @test_builtin_once : $@convention(thin) (Builtin.RawPointer) -> () {
|
|
bb0(%0 : $Builtin.RawPointer):
|
|
%1 = global_addr @gi : $*Int
|
|
%2 = alloc_stack $Int
|
|
%3 = function_ref @g_init : $@convention(c) () -> ()
|
|
%4 = builtin "once"(%0 : $Builtin.RawPointer, %3 : $@convention(c) () -> ()) : $()
|
|
dealloc_stack %2 : $*Int
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: @test_debug_value
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: debug_value %0 : $*Int, let, name "x"
|
|
// CHECK-NEXT: %0 = alloc_stack $Int
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: debug_value %0 : $*Int, let, name "x"
|
|
// CHECK-NEXT: %1 = alloc_stack $Int
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: debug_value undef : $*Int, let, name "y"
|
|
// CHECK-NEXT: %0 = alloc_stack $Int
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil @test_debug_value : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = alloc_stack $Int
|
|
%1 = alloc_stack $Int
|
|
debug_value %0 : $*Int, let, name "x"
|
|
debug_value undef : $*Int, let, name "y"
|
|
dealloc_stack %1 : $*Int
|
|
dealloc_stack %0 : $*Int
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @test_debug_step
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: debug_step
|
|
// CHECK-NEXT: %0 = argument of bb0
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil [ossa] @test_debug_step : $@convention(thin) (@inout_aliasable Int) -> () {
|
|
bb0(%0 : $*Int):
|
|
debug_step
|
|
%99 = tuple ()
|
|
return %99 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @test_store_assign
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: store %2 to [assign] %0 : $*C
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: store %2 to [assign] %0 : $*C
|
|
// CHECK-NEXT: %1 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: store %2 to [assign] %0 : $*C
|
|
// CHECK-NEXT: %3 = global_addr @globalC : $*C
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: store %2 to [assign] %0 : $*C
|
|
// CHECK-NEXT: %4 = global_addr @globalCVar : $*C
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @test_store_assign : $@convention(thin) (@inout C, @inout C, @owned C) -> () {
|
|
bb0(%0 : $*C, %1 : $*C, %2 : @owned $C):
|
|
%3 = global_addr @globalC : $*C
|
|
%4 = global_addr @globalCVar : $*C
|
|
store %2 to [assign] %0 : $*C
|
|
%r = tuple ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @test_builtin_zeroInitializer
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = builtin "zeroInitializer"(%1 : $*C)
|
|
// CHECK-NEXT: %0 = alloc_stack
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %2 = builtin "zeroInitializer"(%1 : $*C)
|
|
// CHECK-NEXT: %1 = alloc_stack
|
|
// CHECK-NEXT: r=0,w=1
|
|
sil @test_builtin_zeroInitializer : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = alloc_stack $C
|
|
%1 = alloc_stack $C
|
|
%2 = builtin "zeroInitializer"(%1 : $*C) : $()
|
|
%3 = apply undef<C>(%1) : $@convention(thin) <C> () -> @out C
|
|
copy_addr [take] %1 to [init] %0 : $*C
|
|
dealloc_stack %1 : $*C
|
|
destroy_addr %0 : $*C
|
|
dealloc_stack %0 : $*C
|
|
%4 = tuple ()
|
|
return %4 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @test_builtin_zeroInitializer_atomicload
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = builtin "zeroInitializer"(%1 : $*C)
|
|
// CHECK-NEXT: %0 = alloc_stack
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %2 = builtin "zeroInitializer"(%1 : $*C)
|
|
// CHECK-NEXT: %1 = alloc_stack
|
|
// CHECK-NEXT: r=0,w=1
|
|
sil @test_builtin_zeroInitializer_atomicload : $@convention(thin) () -> Builtin.Int64 {
|
|
bb0:
|
|
%0 = alloc_stack $C
|
|
%1 = alloc_stack $C
|
|
%2 = builtin "zeroInitializer"(%1 : $*C) : $()
|
|
%3 = apply undef<C>(%1) : $@convention(thin) <C> () -> @out C
|
|
copy_addr [take] %1 to [init] %0 : $*C
|
|
dealloc_stack %1 : $*C
|
|
%4 = address_to_pointer %0 : $*C to $Builtin.RawPointer
|
|
%5 = builtin "atomicload_monotonic_Int64"(%4 : $Builtin.RawPointer) : $Builtin.Int64
|
|
destroy_addr %0 : $*C
|
|
dealloc_stack %0 : $*C
|
|
return %5 : $Builtin.Int64
|
|
}
|
|
|
|
// CHECK-LABEL: @test_builtin_zeroInitializer_atomicstore
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = builtin "zeroInitializer"(%1 : $*C)
|
|
// CHECK-NEXT: %0 = alloc_stack
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %2 = builtin "zeroInitializer"(%1 : $*C)
|
|
// CHECK-NEXT: %1 = alloc_stack
|
|
// CHECK-NEXT: r=0,w=1
|
|
sil @test_builtin_zeroInitializer_atomicstore : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = alloc_stack $C
|
|
%1 = alloc_stack $C
|
|
%2 = builtin "zeroInitializer"(%1 : $*C) : $()
|
|
%3 = apply undef<C>(%1) : $@convention(thin) <C> () -> @out C
|
|
copy_addr [take] %1 to [init] %0 : $*C
|
|
dealloc_stack %1 : $*C
|
|
%4 = address_to_pointer %0 : $*C to $Builtin.RawPointer
|
|
%5 = integer_literal $Builtin.Int64, 1
|
|
%6 = builtin "atomicstore_monotonic_Int64"(%4 : $Builtin.RawPointer, %5 : $Builtin.Int64) : $()
|
|
destroy_addr %0 : $*C
|
|
dealloc_stack %0 : $*C
|
|
%7 = tuple ()
|
|
return %7 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @test_builtin_zeroInitializer_atomicrmw
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = builtin "zeroInitializer"(%1 : $*C)
|
|
// CHECK-NEXT: %0 = alloc_stack
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %2 = builtin "zeroInitializer"(%1 : $*C)
|
|
// CHECK-NEXT: %1 = alloc_stack
|
|
// CHECK-NEXT: r=0,w=1
|
|
sil @test_builtin_zeroInitializer_atomicrmw : $@convention(thin) () -> (Builtin.Int64, Builtin.Int64) {
|
|
bb0:
|
|
%0 = alloc_stack $C
|
|
%1 = alloc_stack $C
|
|
%2 = builtin "zeroInitializer"(%1 : $*C) : $()
|
|
%3 = apply undef<C>(%1) : $@convention(thin) <C> () -> @out C
|
|
copy_addr [take] %1 to [init] %0 : $*C
|
|
dealloc_stack %1 : $*C
|
|
%4 = address_to_pointer %0 : $*C to $Builtin.RawPointer
|
|
%5 = integer_literal $Builtin.Int64, 1
|
|
%6 = builtin "atomicrmw_xchg_monotonic_Int64"(%4 : $Builtin.RawPointer, %5 : $Builtin.Int64) : $Builtin.Int64
|
|
%7 = builtin "atomicrmw_add_monotonic_Int64"(%4 : $Builtin.RawPointer, %5 : $Builtin.Int64) : $Builtin.Int64
|
|
destroy_addr %0 : $*C
|
|
dealloc_stack %0 : $*C
|
|
%8 = tuple (%6 : $Builtin.Int64, %7 : $Builtin.Int64)
|
|
return %8 : $(Builtin.Int64, Builtin.Int64)
|
|
}
|
|
|
|
// CHECK-LABEL: @test_builtin_zeroInitializer_cmpxchg
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = builtin "zeroInitializer"(%1 : $*C)
|
|
// CHECK-NEXT: %0 = alloc_stack
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %2 = builtin "zeroInitializer"(%1 : $*C)
|
|
// CHECK-NEXT: %1 = alloc_stack
|
|
// CHECK-NEXT: r=0,w=1
|
|
sil @test_builtin_zeroInitializer_cmpxchg : $@convention(thin) () -> (Builtin.Int64, Builtin.Int1) {
|
|
bb0:
|
|
%0 = alloc_stack $C
|
|
%1 = alloc_stack $C
|
|
%2 = builtin "zeroInitializer"(%1 : $*C) : $()
|
|
%3 = apply undef<C>(%1) : $@convention(thin) <C> () -> @out C
|
|
copy_addr [take] %1 to [init] %0 : $*C
|
|
dealloc_stack %1 : $*C
|
|
%4 = address_to_pointer %0 : $*C to $Builtin.RawPointer
|
|
%5 = integer_literal $Builtin.Int64, 1
|
|
%6 = builtin "cmpxchg_monotonic_monotonic_Int64"(%4 : $Builtin.RawPointer, %5 : $Builtin.Int64) : $(Builtin.Int64, Builtin.Int1)
|
|
destroy_addr %0 : $*C
|
|
dealloc_stack %0 : $*C
|
|
return %6 : $(Builtin.Int64, Builtin.Int1)
|
|
}
|
|
|
|
// CHECK-LABEL: @test_builtin_zeroInitializer_fence
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = builtin "zeroInitializer"(%1 : $*C)
|
|
// CHECK-NEXT: %0 = alloc_stack
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %2 = builtin "zeroInitializer"(%1 : $*C)
|
|
// CHECK-NEXT: %1 = alloc_stack
|
|
// CHECK-NEXT: r=0,w=1
|
|
sil @test_builtin_zeroInitializer_fence : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = alloc_stack $C
|
|
%1 = alloc_stack $C
|
|
%2 = builtin "zeroInitializer"(%1 : $*C) : $()
|
|
%3 = apply undef<C>(%1) : $@convention(thin) <C> () -> @out C
|
|
copy_addr [take] %1 to [init] %0 : $*C
|
|
dealloc_stack %1 : $*C
|
|
%5 = builtin "fence_release"() : $()
|
|
destroy_addr %0 : $*C
|
|
dealloc_stack %0 : $*C
|
|
return %5 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @builtin_initializer_and_class
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %3 = builtin "zeroInitializer"(%2 : $*Int32) : $()
|
|
// CHECK-NEXT: %1 = ref_element_addr %0 : $C, #C.prop
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %3 = builtin "zeroInitializer"(%2 : $*Int32) : $()
|
|
// CHECK-NEXT: %2 = alloc_stack $Int32
|
|
// CHECK-NEXT: r=0,w=1
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: %4 = builtin "prepareInitialization"(%2 : $*Int32) : $()
|
|
// CHECK-NEXT: %1 = ref_element_addr %0 : $C, #C.prop
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: %4 = builtin "prepareInitialization"(%2 : $*Int32) : $()
|
|
// CHECK-NEXT: %2 = alloc_stack $Int32
|
|
// CHECK-NEXT: r=0,w=1
|
|
sil @builtin_initializer_and_class : $@convention(thin) (@guaranteed C) -> () {
|
|
bb0(%0 : $C):
|
|
%1 = ref_element_addr %0, #C.prop
|
|
%2 = alloc_stack $Int32
|
|
%3 = builtin "zeroInitializer"(%2 : $*Int32) : $()
|
|
%4 = builtin "prepareInitialization"(%2 : $*Int32) : $()
|
|
dealloc_stack %2
|
|
%6 = tuple ()
|
|
return %6
|
|
}
|
|
|
|
// CHECK-LABEL: @test_stored_pointer
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: %5 = apply %4(%2) : $@convention(thin) (@in Builtin.RawPointer) -> ()
|
|
// CHECK-NEXT: %0 = alloc_stack $Int
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil @test_stored_pointer : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = alloc_stack $Int
|
|
%1 = address_to_pointer %0 : $*Int to $Builtin.RawPointer
|
|
%2 = alloc_stack $Builtin.RawPointer
|
|
store %1 to %2 : $*Builtin.RawPointer
|
|
%4 = function_ref @in_ptr : $@convention(thin) (@in Builtin.RawPointer) -> ()
|
|
%5 = apply %4(%2) : $@convention(thin) (@in Builtin.RawPointer) -> ()
|
|
dealloc_stack %2 : $*Builtin.RawPointer
|
|
dealloc_stack %0 : $*Int
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @test_store_borrow
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = store_borrow %0 to %1 : $*X
|
|
// CHECK-NEXT: %1 = alloc_stack $X
|
|
// CHECK-NEXT: r=0,w=1
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: end_borrow %2 : $*X
|
|
// CHECK-NEXT: %1 = alloc_stack $X
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: end_borrow %2 : $*X
|
|
// CHECK-NEXT: %2 = store_borrow %0 to %1 : $*X
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @test_store_borrow : $@convention(thin) (@guaranteed X) -> () {
|
|
bb0(%0 : @guaranteed $X):
|
|
%1 = alloc_stack $X
|
|
%2 = store_borrow %0 to %1 : $*X
|
|
end_borrow %2 : $*X
|
|
dealloc_stack %1 : $*X
|
|
%7 = tuple ()
|
|
return %7 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @test_end_borrow1
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: end_borrow %1 : $X
|
|
// CHECK-NEXT: %2 = alloc_stack $X
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: end_borrow %1 : $X
|
|
// CHECK-NEXT: %4 = ref_element_addr %1 : $X, #X.a
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: end_borrow %1 : $X
|
|
// CHECK-NEXT: %6 = pointer_to_address %5 : $Builtin.RawPointer to $*Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @test_end_borrow1 : $@convention(thin) (@owned X) -> @owned X {
|
|
bb0(%0 : @owned $X):
|
|
%1 = begin_borrow %0 : $X
|
|
%2 = alloc_stack $X
|
|
dealloc_stack %2 : $*X
|
|
%4 = ref_element_addr %1 : $X, #X.a
|
|
%5 = address_to_pointer %4 : $*Int32 to $Builtin.RawPointer
|
|
%6 = pointer_to_address %5 : $Builtin.RawPointer to $*Int32
|
|
end_borrow %1 : $X
|
|
return %0 : $X
|
|
}
|
|
|
|
// CHECK-LABEL: @test_end_borrow2
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: end_borrow %3 : $X
|
|
// CHECK-NEXT: %1 = ref_element_addr %0 : $X, #X.x
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil [ossa] @test_end_borrow2 : $@convention(thin) (@guaranteed X) -> Int32 {
|
|
bb0(%0 : @guaranteed $X):
|
|
%1 = ref_element_addr %0 : $X, #X.x
|
|
%2 = load [copy] %1 : $*X
|
|
%3 = begin_borrow %2 : $X
|
|
%4 = function_ref @single_reference : $@convention(thin) (@guaranteed X) -> Int32
|
|
%5 = apply %4(%3) : $@convention(thin) (@guaranteed X) -> Int32
|
|
end_borrow %3 : $X
|
|
destroy_value %2 : $X
|
|
return %5 : $Int32
|
|
}
|
|
|
|
// CHECK-LABEL: @test_end_borrow3
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: end_borrow %6 : $X
|
|
// CHECK-NEXT: %3 = ref_element_addr %2 : $X, #X.x
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #4.
|
|
// CHECK-NEXT: end_borrow %6 : $X
|
|
// CHECK-NEXT: %4 = ref_element_addr %0 : $X, #X.x
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #5.
|
|
// CHECK-NEXT: end_borrow %6 : $X
|
|
// CHECK-NEXT: %7 = ref_element_addr %6 : $X, #X.x
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #6.
|
|
// CHECK-NEXT: end_borrow %2 : $X
|
|
// CHECK-NEXT: %3 = ref_element_addr %2 : $X, #X.x
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #7.
|
|
// CHECK-NEXT: end_borrow %2 : $X
|
|
// CHECK-NEXT: %4 = ref_element_addr %0 : $X, #X.x
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #8.
|
|
// CHECK-NEXT: end_borrow %2 : $X
|
|
// CHECK-NEXT: %7 = ref_element_addr %6 : $X, #X.x
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil [ossa] @test_end_borrow3 : $@convention(thin) (@guaranteed X, @owned X) -> @owned (X, X) {
|
|
bb0(%0 : @guaranteed $X, %1 : @owned $X):
|
|
%2 = begin_borrow %1 : $X
|
|
%3 = ref_element_addr %2 : $X, #X.x
|
|
%4 = ref_element_addr %0 : $X, #X.x
|
|
%5 = copy_value %2 : $X
|
|
%6 = begin_borrow %5 : $X
|
|
%7 = ref_element_addr %6 : $X, #X.x
|
|
end_borrow %6 : $X
|
|
end_borrow %2 : $X
|
|
%r = tuple (%5 : $X, %1 : $X)
|
|
return %r : $(X, X)
|
|
}
|
|
|
|
// CHECK-LABEL: @test_end_borrow4
|
|
// CHECK: PAIR #4.
|
|
// CHECK-NEXT: end_borrow %3 : $X
|
|
// CHECK-NEXT: %4 = ref_element_addr %3 : $X, #X.x
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #5.
|
|
// CHECK-NEXT: end_borrow %3 : $X
|
|
// CHECK-NEXT: %8 = ref_element_addr %7 : $X, #X.x
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #10.
|
|
// CHECK-NEXT: end_borrow %7 : $X
|
|
// CHECK-NEXT: %4 = ref_element_addr %3 : $X, #X.x
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #11.
|
|
// CHECK-NEXT: end_borrow %7 : $X
|
|
// CHECK-NEXT: %8 = ref_element_addr %7 : $X, #X.x
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #13.
|
|
// CHECK-NEXT: end_borrow %2 : $X
|
|
// CHECK-NEXT: %4 = ref_element_addr %3 : $X, #X.x
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #14.
|
|
// CHECK-NEXT: end_borrow %2 : $X
|
|
// CHECK-NEXT: %8 = ref_element_addr %7 : $X, #X.x
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil [ossa] @test_end_borrow4 : $@convention(thin) (@guaranteed X, @in_guaranteed X) -> @owned X {
|
|
bb0(%0 : @guaranteed $X, %1 : $*X):
|
|
%2 = begin_borrow %0 : $X
|
|
%3 = load_borrow %1 : $*X
|
|
%4 = ref_element_addr %3 : $X, #X.x
|
|
end_borrow %3 : $X
|
|
%6 = load [copy] %1 : $*X
|
|
%7 = begin_borrow %6 : $X
|
|
%8 = ref_element_addr %7 : $X, #X.x
|
|
end_borrow %7 : $X
|
|
end_borrow %2 : $X
|
|
return %6 : $X
|
|
}
|
|
|
|
// CHECK-LABEL: @test_end_borrow5
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: end_borrow %2 : $X
|
|
// CHECK-NEXT: %5 = ref_element_addr [immutable] %4 : $X, #X.x
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @test_end_borrow5 : $@convention(thin) (@guaranteed X) -> () {
|
|
bb0(%0 : @guaranteed $X):
|
|
%1 = ref_element_addr [immutable] %0 : $X, #X.x
|
|
%2 = load_borrow %1 : $*X
|
|
%3 = unconditional_checked_cast %2 : $X to Derived
|
|
%4 = upcast %3 : $Derived to $X
|
|
%5 = ref_element_addr [immutable] %4 : $X, #X.x
|
|
end_borrow %2 : $X
|
|
%7 = tuple ()
|
|
return %7 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @test_load_borrow
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %1 = load_borrow %0 : $*X
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*X
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %1 = load_borrow %0 : $*X
|
|
// CHECK-NEXT: %2 = alloc_stack $X
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #4.
|
|
// CHECK-NEXT: end_borrow %1 : $X
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*X
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #5.
|
|
// CHECK-NEXT: end_borrow %1 : $X
|
|
// CHECK-NEXT: %2 = alloc_stack $X
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #6.
|
|
// CHECK-NEXT: end_borrow %1 : $X
|
|
// CHECK-NEXT: %4 = ref_element_addr %1 : $X, #X.a
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #7.
|
|
// CHECK-NEXT: end_borrow %1 : $X
|
|
// CHECK-NEXT: %6 = pointer_to_address %5 : $Builtin.RawPointer to $*Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @test_load_borrow : $@convention(thin) (@inout X) -> () {
|
|
bb0(%0 : $*X):
|
|
%1 = load_borrow %0 : $*X
|
|
%2 = alloc_stack $X
|
|
dealloc_stack %2 : $*X
|
|
%4 = ref_element_addr %1 : $X, #X.a
|
|
%5 = address_to_pointer %4 : $*Int32 to $Builtin.RawPointer
|
|
%6 = pointer_to_address %5 : $Builtin.RawPointer to $*Int32
|
|
end_borrow %1 : $X
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @test_immutable_end_borrow
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: end_borrow %1 : $X
|
|
// CHECK-NEXT: %2 = alloc_stack $X
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: end_borrow %1 : $X
|
|
// CHECK-NEXT: %4 = ref_element_addr [immutable] %1 : $X, #X.a
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: end_borrow %1 : $X
|
|
// CHECK-NEXT: %6 = pointer_to_address %5 : $Builtin.RawPointer to $*Int32
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @test_immutable_end_borrow : $@convention(thin) (@owned X) -> @owned X {
|
|
bb0(%0 : @owned $X):
|
|
%1 = begin_borrow %0 : $X
|
|
%2 = alloc_stack $X
|
|
dealloc_stack %2 : $*X
|
|
%4 = ref_element_addr [immutable] %1 : $X, #X.a
|
|
%5 = address_to_pointer %4 : $*Int32 to $Builtin.RawPointer
|
|
%6 = pointer_to_address %5 : $Builtin.RawPointer to $*Int32
|
|
end_borrow %1 : $X
|
|
%8 = tuple ()
|
|
return %0 : $X
|
|
}
|
|
|
|
sil @indirect_X : $@convention(thin) (@in_guaranteed X) -> ()
|
|
|
|
// CHECK-LABEL: @test_escaping_partial_apply
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = partial_apply %1(%0) : $@convention(thin) (@in_guaranteed X) -> ()
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*X
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @test_escaping_partial_apply : $@convention(thin) (@in X) -> () {
|
|
bb0(%0 : $*X):
|
|
%1 = function_ref @indirect_X : $@convention(thin) (@in_guaranteed X) -> ()
|
|
%2 = partial_apply %1(%0) : $@convention(thin) (@in_guaranteed X) -> ()
|
|
destroy_value %2 : $@callee_owned () -> ()
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @test_non_escaping_partial_apply
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = partial_apply [on_stack] %1(%0) : $@convention(thin) (@in_guaranteed X) -> ()
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*X
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: destroy_value %2 : $@noescape @callee_owned () -> ()
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*X
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil [ossa] @test_non_escaping_partial_apply : $@convention(thin) (@in X) -> () {
|
|
bb0(%0 : $*X):
|
|
%1 = function_ref @indirect_X : $@convention(thin) (@in_guaranteed X) -> ()
|
|
%2 = partial_apply [on_stack] %1(%0) : $@convention(thin) (@in_guaranteed X) -> ()
|
|
destroy_value %2 : $@noescape @callee_owned () -> ()
|
|
destroy_addr %0 : $*X
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @test_non_escaping_applied
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = partial_apply [on_stack] %1(%0) : $@convention(thin) (@in_guaranteed X) -> ()
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*X
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %3 = apply %2() : $@noescape @callee_owned () -> ()
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*X
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil [ossa] @test_non_escaping_applied : $@convention(thin) (@in X) -> () {
|
|
bb0(%0 : $*X):
|
|
%1 = function_ref @indirect_X : $@convention(thin) (@in_guaranteed X) -> ()
|
|
%2 = partial_apply [on_stack] %1(%0) : $@convention(thin) (@in_guaranteed X) -> ()
|
|
%3 = apply %2() : $@noescape @callee_owned () -> ()
|
|
destroy_addr %0
|
|
%6 = tuple ()
|
|
return %6 : $()
|
|
}
|
|
|
|
sil @closure : $@convention(thin) (@inout_aliasable Int) -> ()
|
|
sil @closure2 : $@convention(thin) (Int, @inout_aliasable Int) -> ()
|
|
|
|
// CHECK-LABEL: @closure_with_inout
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = partial_apply [callee_guaranteed] [on_stack] %1(%0) : $@convention(thin) (@inout_aliasable Int) -> ()
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %3 = apply %2() : $@noescape @callee_guaranteed () -> ()
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil @closure_with_inout : $@convention(thin) (@inout Int) -> () {
|
|
bb0(%0 : $*Int):
|
|
%1 = function_ref @closure : $@convention(thin) (@inout_aliasable Int) -> ()
|
|
%2 = partial_apply [callee_guaranteed] [on_stack] %1(%0) : $@convention(thin) (@inout_aliasable Int) -> ()
|
|
%3 = apply %2() : $@noescape @callee_guaranteed () -> ()
|
|
dealloc_stack %2
|
|
%r = tuple ()
|
|
return %r
|
|
}
|
|
|
|
// CHECK-LABEL: @two_closures_with_inout
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %3 = partial_apply [callee_guaranteed] [on_stack] %2(%0) : $@convention(thin) (Int, @inout_aliasable Int) -> ()
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %4 = partial_apply [callee_guaranteed] [on_stack] %3(%1) : $@noescape @callee_guaranteed (Int) -> ()
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: %5 = apply %4() : $@noescape @callee_guaranteed () -> ()
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil @two_closures_with_inout : $@convention(thin) (@inout Int, Int) -> () {
|
|
bb0(%0 : $*Int, %1 : $Int):
|
|
%2 = function_ref @closure2 : $@convention(thin) (Int, @inout_aliasable Int) -> ()
|
|
%3 = partial_apply [callee_guaranteed] [on_stack] %2(%0) : $@convention(thin) (Int, @inout_aliasable Int) -> ()
|
|
%4 = partial_apply [callee_guaranteed] [on_stack] %3(%1) : $@noescape @callee_guaranteed (Int) -> ()
|
|
%5 = apply %4() : $@noescape @callee_guaranteed () -> ()
|
|
dealloc_stack %4
|
|
dealloc_stack %3
|
|
%r = tuple ()
|
|
return %r
|
|
}
|
|
|
|
sil @call_closure : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> () {
|
|
[%0: read v**.c*.v**, write v**.c*.v**]
|
|
[global: read,write]
|
|
}
|
|
|
|
// CHECK-LABEL: @pass_closure_to_function
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = partial_apply [callee_guaranteed] [on_stack] %1(%0) : $@convention(thin) (@inout_aliasable Int) -> ()
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %4 = apply %3(%2) : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> ()
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*Int
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil @pass_closure_to_function : $@convention(thin) (@inout Int) -> () {
|
|
bb0(%0 : $*Int):
|
|
%4 = function_ref @closure : $@convention(thin) (@inout_aliasable Int) -> ()
|
|
%5 = partial_apply [callee_guaranteed] [on_stack] %4(%0) : $@convention(thin) (@inout_aliasable Int) -> ()
|
|
%6 = function_ref @call_closure : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> ()
|
|
%7 = apply %6(%5) : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> ()
|
|
dealloc_stack %5
|
|
%r = tuple ()
|
|
return %r
|
|
}
|
|
|
|
// CHECK-LABEL: @test_is_unique
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = is_unique %0 : $*X
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*X
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %2 = is_unique %0 : $*X
|
|
// CHECK-NEXT: %1 = argument of bb0 : $*X
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil [ossa] @test_is_unique : $@convention(thin) (@in X, @in X) -> () {
|
|
bb0(%0 : $*X, %1 : $*X):
|
|
%2 = is_unique %0 : $*X
|
|
destroy_addr %0 : $*X
|
|
destroy_addr %1 : $*X
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: @test_unchecked_addr_cast
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = load [copy] %1 : $*C
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*X
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: %3 = is_unique %1 : $*C
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*X
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #4.
|
|
// CHECK-NEXT: %4 = load_borrow %1 : $*C
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*X
|
|
// CHECK-NEXT: r=1,w=0
|
|
sil [ossa] @test_unchecked_addr_cast : $@convention(thin) (@in_guaranteed X) -> @owned C {
|
|
bb0(%0 : $*X):
|
|
%1 = unchecked_addr_cast %0 : $*X to $*C
|
|
%2 = load [copy] %1 : $*C
|
|
%3 = is_unique %1 : $*C
|
|
%4 = load_borrow %1 : $*C
|
|
end_borrow %4 : $C
|
|
return %2 : $C
|
|
}
|
|
|
|
// CHECK-LABEL: @test_release_of_class_with_let
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: strong_release %0 : $CL
|
|
// CHECK-NEXT: %1 = ref_element_addr [immutable] %0 : $CL, #CL.x
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil @test_release_of_class_with_let : $@convention(thin) (@owned CL) -> () {
|
|
bb0(%0 : $CL):
|
|
%1 = ref_element_addr [immutable] %0, #CL.x
|
|
strong_release %0
|
|
%3 = tuple ()
|
|
return %3
|
|
}
|
|
|
|
// CHECK-LABEL: @test_consume_of_class_with_let
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %3 = apply %2(%0) : $@convention(thin) (@owned CL) -> ()
|
|
// CHECK-NEXT: %1 = ref_element_addr [immutable] %0 : $CL, #CL.x
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil @test_consume_of_class_with_let : $@convention(thin) (@owned CL) -> () {
|
|
bb0(%0 : $CL):
|
|
%1 = ref_element_addr [immutable] %0, #CL.x
|
|
%4 = function_ref @consume : $@convention(thin) (@owned CL) -> ()
|
|
apply %4(%0) : $@convention(thin) (@owned CL) -> ()
|
|
%3 = tuple ()
|
|
return %3
|
|
}
|
|
|
|
// CHECK-LABEL: @test_ossa_consume_of_class_with_let
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: %5 = apply %4(%0) : $@convention(thin) (@owned CL) -> ()
|
|
// CHECK-NEXT: %2 = ref_element_addr [immutable] %1 : $CL, #CL.x
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @test_ossa_consume_of_class_with_let : $@convention(thin) (@owned CL) -> () {
|
|
bb0(%0 : @owned $CL):
|
|
%1 = begin_borrow %0
|
|
%2 = ref_element_addr [immutable] %1, #CL.x
|
|
end_borrow %1
|
|
%4 = function_ref @consume : $@convention(thin) (@owned CL) -> ()
|
|
apply %4(%0) : $@convention(thin) (@owned CL) -> ()
|
|
%3 = tuple ()
|
|
return %3
|
|
}
|
|
|
|
// CHECK-LABEL: @test_mark_dependence
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %3 = mark_dependence %1 : $*C on %2 : $C
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: %4 = mark_dependence %2 : $C on %0 : $*C
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #4.
|
|
// CHECK-NEXT: %4 = mark_dependence %2 : $C on %0 : $*C
|
|
// CHECK-NEXT: %1 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #7.
|
|
// CHECK-NEXT: %5 = mark_dependence %1 : $*C on %0 : $*C
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #8.
|
|
// CHECK-NEXT: %5 = mark_dependence %1 : $*C on %0 : $*C
|
|
// CHECK-NEXT: %1 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=0,w=0
|
|
sil [ossa] @test_mark_dependence : $@convention(thin) (@in_guaranteed C, @in_guaranteed C, @owned C) -> @owned C {
|
|
bb0(%0 : $*C, %1 : $*C, %2 : @owned $C):
|
|
%3 = mark_dependence %1 on %2
|
|
%4 = mark_dependence %2 on %0
|
|
%5 = mark_dependence %1 on %0
|
|
return %4
|
|
}
|
|
|
|
// CHECK-LABEL: @test_mark_dependence_addr
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: mark_dependence_addr %1 : $*C on %2 : $C
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=0,w=0
|
|
// CHECK: PAIR #1.
|
|
// CHECK-NEXT: mark_dependence_addr %1 : $*C on %2 : $C
|
|
// CHECK-NEXT: %1 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=1,w=1
|
|
// CHECK: PAIR #2.
|
|
// CHECK-NEXT: mark_dependence_addr %1 : $*C on %0 : $*C
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=1,w=0
|
|
// CHECK: PAIR #3.
|
|
// CHECK-NEXT: mark_dependence_addr %1 : $*C on %0 : $*C
|
|
// CHECK-NEXT: %1 = argument of bb0 : $*C
|
|
// CHECK-NEXT: r=1,w=1
|
|
sil [ossa] @test_mark_dependence_addr : $@convention(thin) (@in_guaranteed C, @inout C, @guaranteed C) -> () {
|
|
bb0(%0 : $*C, %1 : $*C, %2 : @guaranteed $C):
|
|
mark_dependence_addr %1 on %2
|
|
mark_dependence_addr %1 on %0
|
|
%99 = tuple ()
|
|
return %99 : $()
|
|
}
|
|
|
|
sil @returns_tuple : $@convention(thin) () -> (Int64, @out UInt64)
|
|
|
|
// CHECK-LABEL: @aliasing_apply_with_direct_and_indirect_result
|
|
// CHECK: PAIR #0.
|
|
// CHECK-NEXT: %2 = apply %1(%0) : $@convention(thin) () -> (Int64, @out UInt64)
|
|
// CHECK-NEXT: %0 = argument of bb0 : $*UInt64
|
|
// CHECK-NEXT: r=0,w=1
|
|
sil [ossa] @aliasing_apply_with_direct_and_indirect_result : $@convention(thin) () -> @out UInt64 {
|
|
bb0(%0 : $*UInt64):
|
|
%1 = function_ref @returns_tuple : $@convention(thin) () -> (Int64, @out UInt64)
|
|
%2 = apply %1(%0) : $@convention(thin) () -> (Int64, @out UInt64)
|
|
%99 = tuple ()
|
|
return %99 : $()
|
|
}
|
|
|