Files
swift-mirror/test/SILGen/properties.swift
Slava Pestov 85b94a4300 SILGen: Refactor emitMemberInitializers() to use Initialization
Instead of constructing an LValue and storing the result of the
stored property initializer to the lvalue, let's emit the call
of the stored property initializer directly into an initialization
pointing at the stored properties named by the pattern.
2020-10-11 12:48:30 -04:00

899 lines
34 KiB
Swift

// RUN: %target-swift-emit-silgen -Xllvm -sil-full-demangle -parse-as-library -disable-objc-attr-requires-foundation-module -enable-objc-interop %s | %FileCheck %s
var zero: Int = 0
func use(_: Int) {}
func use(_: Double) {}
func getInt() -> Int { return zero }
// CHECK-LABEL: sil hidden [ossa] @{{.*}}physical_tuple_lvalue
// CHECK: bb0(%0 : $Int):
func physical_tuple_lvalue(_ c: Int) {
var x : (Int, Int)
// CHECK: [[BOX:%[0-9]+]] = alloc_box ${ var (Int, Int) }
// CHECK: [[MARKED_BOX:%[0-9]+]] = mark_uninitialized [var] [[BOX]]
// CHECK: [[XADDR:%.*]] = project_box [[MARKED_BOX]]
x.1 = c
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[XADDR]]
// CHECK: [[X_1:%[0-9]+]] = tuple_element_addr [[WRITE]] : {{.*}}, 1
// CHECK: assign %0 to [[X_1]]
}
func tuple_rvalue() -> (Int, Int) {}
// CHECK-LABEL: sil hidden [ossa] @{{.*}}physical_tuple_rvalue
func physical_tuple_rvalue() -> Int {
return tuple_rvalue().1
// CHECK: [[FUNC:%[0-9]+]] = function_ref @$s10properties12tuple_rvalue{{[_0-9a-zA-Z]*}}F
// CHECK: [[TUPLE:%[0-9]+]] = apply [[FUNC]]()
// CHECK: ({{%.*}}, [[RET:%[0-9]+]]) = destructure_tuple [[TUPLE]]
// CHECK: return [[RET]]
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties16tuple_assignment{{[_0-9a-zA-Z]*}}F
func tuple_assignment(_ a: inout Int, b: inout Int) {
// CHECK: bb0([[A_ADDR:%[0-9]+]] : $*Int, [[B_ADDR:%[0-9]+]] : $*Int):
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[B_ADDR]]
// CHECK: [[B:%[0-9]+]] = load [trivial] [[READ]]
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[A_ADDR]]
// CHECK: [[A:%[0-9]+]] = load [trivial] [[READ]]
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[A_ADDR]]
// CHECK: assign [[B]] to [[WRITE]]
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[B_ADDR]]
// CHECK: assign [[A]] to [[WRITE]]
(a, b) = (b, a)
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties18tuple_assignment_2{{[_0-9a-zA-Z]*}}F
func tuple_assignment_2(_ a: inout Int, b: inout Int, xy: (Int, Int)) {
// CHECK: bb0([[A_ADDR:%[0-9]+]] : $*Int, [[B_ADDR:%[0-9]+]] : $*Int, [[X:%[0-9]+]] : $Int, [[Y:%[0-9]+]] : $Int):
(a, b) = xy
// CHECK: [[XY2:%[0-9]+]] = tuple ([[X]] : $Int, [[Y]] : $Int)
// CHECK: ([[X:%[0-9]+]], [[Y:%[0-9]+]]) = destructure_tuple [[XY2]]
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[A_ADDR]]
// CHECK: assign [[X]] to [[WRITE]]
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[B_ADDR]]
// CHECK: assign [[Y]] to [[WRITE]]
}
class Ref {
var x, y : Int
var ref : Ref
var z: Int { get {} set {} }
var val_prop: Val { get {} set {} }
subscript(i: Int) -> Float { get {} set {} }
init(i: Int) {
x = i
y = i
ref = self
}
}
class RefSubclass : Ref {
var w : Int
override init (i: Int) {
w = i
super.init(i: i)
}
}
struct Val {
var x, y : Int
var ref : Ref
var z: Int { get {} set {} }
var z_tuple: (Int, Int) { get {} set {} }
subscript(i: Int) -> Float { get {} set {} }
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties22physical_struct_lvalue{{[_0-9a-zA-Z]*}}F
func physical_struct_lvalue(_ c: Int) {
var v : Val
// CHECK: [[VADDR:%[0-9]+]] = alloc_box ${ var Val }
v.y = c
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown]
// CHECK: [[YADDR:%.*]] = struct_element_addr [[WRITE]]
// CHECK: assign %0 to [[YADDR]]
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties21physical_class_lvalue{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@guaranteed Ref, Int) -> ()
// CHECK: bb0([[ARG0:%.*]] : @guaranteed $Ref,
func physical_class_lvalue(_ r: Ref, a: Int) {
r.y = a
// CHECK: [[FN:%[0-9]+]] = class_method [[ARG0]] : $Ref, #Ref.y!setter
// CHECK: apply [[FN]](%1, [[ARG0]]) : $@convention(method) (Int, @guaranteed Ref) -> ()
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties24physical_subclass_lvalue{{[_0-9a-zA-Z]*}}F
func physical_subclass_lvalue(_ r: RefSubclass, a: Int) {
// CHECK: bb0([[ARG1:%.*]] : @guaranteed $RefSubclass, [[ARG2:%.*]] : $Int):
r.y = a
// CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]] : $RefSubclass
// CHECK: [[R_SUP:%[0-9]+]] = upcast [[ARG1_COPY]] : $RefSubclass to $Ref
// CHECK: [[FN:%[0-9]+]] = class_method [[R_SUP]] : $Ref, #Ref.y!setter : (Ref) -> (Int) -> (), $@convention(method) (Int, @guaranteed Ref) -> ()
// CHECK: apply [[FN]]([[ARG2]], [[R_SUP]]) :
// CHECK: destroy_value [[R_SUP]]
r.w = a
// CHECK: [[FN:%[0-9]+]] = class_method [[ARG1]] : $RefSubclass, #RefSubclass.w!setter
// CHECK: apply [[FN]](%1, [[ARG1]]) : $@convention(method) (Int, @guaranteed RefSubclass) -> ()
// CHECK-NOT: destroy_value [[ARG1]]
// CHECK: } // end sil function '$s10properties24physical_subclass_lvalue{{[_0-9a-zA-Z]*}}F'
}
func struct_rvalue() -> Val {}
// CHECK-LABEL: sil hidden [ossa] @$s10properties22physical_struct_rvalue{{[_0-9a-zA-Z]*}}F
func physical_struct_rvalue() -> Int {
return struct_rvalue().y
// CHECK: [[FUNC:%[0-9]+]] = function_ref @$s10properties13struct_rvalueAA3ValVyF
// CHECK: [[STRUCT:%[0-9]+]] = apply [[FUNC]]()
// CHECK: [[BORROWED_STRUCT:%.*]] = begin_borrow [[STRUCT]]
// CHECK: [[RET:%[0-9]+]] = struct_extract [[BORROWED_STRUCT]] : $Val, #Val.y
// CHECK: end_borrow [[BORROWED_STRUCT]]
// CHECK: destroy_value [[STRUCT]]
// CHECK: return [[RET]]
}
func class_rvalue() -> Ref {}
// CHECK-LABEL: sil hidden [ossa] @$s10properties21physical_class_rvalue{{[_0-9a-zA-Z]*}}F
func physical_class_rvalue() -> Int {
return class_rvalue().y
// CHECK: [[FUNC:%[0-9]+]] = function_ref @$s10properties12class_rvalueAA3RefCyF
// CHECK: [[CLASS:%[0-9]+]] = apply [[FUNC]]()
// CHECK: [[BORROW:%.*]] = begin_borrow [[CLASS]]
// CHECK: [[FN:%[0-9]+]] = class_method [[BORROW]] : $Ref, #Ref.y!getter
// CHECK: [[RET:%[0-9]+]] = apply [[FN]]([[BORROW]])
// CHECK: return [[RET]]
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties18logical_struct_get{{[_0-9a-zA-Z]*}}F
func logical_struct_get() -> Int {
return struct_rvalue().z
// CHECK: [[GET_RVAL:%[0-9]+]] = function_ref @$s10properties13struct_rvalue{{[_0-9a-zA-Z]*}}F
// CHECK: [[STRUCT:%[0-9]+]] = apply [[GET_RVAL]]()
// CHECK: [[BORROW:%[0-9]+]] = begin_borrow [[STRUCT]]
// CHECK: [[GET_METHOD:%[0-9]+]] = function_ref @$s10properties3ValV1z{{[_0-9a-zA-Z]*}}vg
// CHECK: [[VALUE:%[0-9]+]] = apply [[GET_METHOD]]([[BORROW]])
// CHECK: return [[VALUE]]
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties18logical_struct_set{{[_0-9a-zA-Z]*}}F
func logical_struct_set(_ value: inout Val, z: Int) {
// CHECK: bb0([[VAL:%[0-9]+]] : $*Val, [[Z:%[0-9]+]] : $Int):
value.z = z
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[VAL]]
// CHECK: [[Z_SET_METHOD:%[0-9]+]] = function_ref @$s10properties3ValV1z{{[_0-9a-zA-Z]*}}vs
// CHECK: apply [[Z_SET_METHOD]]([[Z]], [[WRITE]])
// CHECK: return
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties27logical_struct_in_tuple_set{{[_0-9a-zA-Z]*}}F
func logical_struct_in_tuple_set(_ value: inout (Int, Val), z: Int) {
// CHECK: bb0([[VAL:%[0-9]+]] : $*(Int, Val), [[Z:%[0-9]+]] : $Int):
value.1.z = z
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[VAL]]
// CHECK: [[VAL_1:%[0-9]+]] = tuple_element_addr [[WRITE]] : {{.*}}, 1
// CHECK: [[Z_SET_METHOD:%[0-9]+]] = function_ref @$s10properties3ValV1z{{[_0-9a-zA-Z]*}}vs
// CHECK: apply [[Z_SET_METHOD]]([[Z]], [[VAL_1]])
// CHECK: return
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties29logical_struct_in_reftype_set{{[_0-9a-zA-Z]*}}F
func logical_struct_in_reftype_set(_ value: inout Val, z1: Int) {
// CHECK: bb0([[VAL:%[0-9]+]] : $*Val, [[Z1:%[0-9]+]] : $Int):
value.ref.val_prop.z_tuple.1 = z1
// -- val.ref
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[VAL]]
// CHECK: [[VAL_REF_ADDR:%[0-9]+]] = struct_element_addr [[READ]] : $*Val, #Val.ref
// CHECK: [[VAL_REF:%[0-9]+]] = load [copy] [[VAL_REF_ADDR]]
// -- getters and setters
// -- val.ref.val_prop
// CHECK: [[BORROW:%.*]] = begin_borrow [[VAL_REF]]
// CHECK: [[MAT_VAL_PROP_METHOD:%[0-9]+]] = class_method {{.*}} : $Ref, #Ref.val_prop!modify : (Ref) -> ()
// CHECK: ([[VAL_REF_VAL_PROP_MAT:%[0-9]+]], [[TOKEN:%.*]]) = begin_apply [[MAT_VAL_PROP_METHOD]]([[BORROW]])
// -- val.ref.val_prop.z_tuple
// CHECK: [[V_R_VP_Z_TUPLE_MAT:%[0-9]+]] = alloc_stack $(Int, Int)
// CHECK: [[LD:%[0-9]+]] = load_borrow [[VAL_REF_VAL_PROP_MAT]]
// CHECK: [[A0:%.*]] = tuple_element_addr [[V_R_VP_Z_TUPLE_MAT]] : {{.*}}, 0
// CHECK: [[A1:%.*]] = tuple_element_addr [[V_R_VP_Z_TUPLE_MAT]] : {{.*}}, 1
// CHECK: [[GET_Z_TUPLE_METHOD:%[0-9]+]] = function_ref @$s10properties3ValV7z_tupleSi_Sitvg
// CHECK: [[V_R_VP_Z_TUPLE:%[0-9]+]] = apply [[GET_Z_TUPLE_METHOD]]([[LD]])
// CHECK: ([[T0:%.*]], [[T1:%.*]]) = destructure_tuple [[V_R_VP_Z_TUPLE]]
// CHECK: store [[T0]] to [trivial] [[A0]]
// CHECK: store [[T1]] to [trivial] [[A1]]
// CHECK: end_borrow [[LD]]
// -- write to val.ref.val_prop.z_tuple.1
// CHECK: [[V_R_VP_Z_TUPLE_1:%[0-9]+]] = tuple_element_addr [[V_R_VP_Z_TUPLE_MAT]] : {{.*}}, 1
// CHECK: assign [[Z1]] to [[V_R_VP_Z_TUPLE_1]]
// -- writeback to val.ref.val_prop.z_tuple
// CHECK: [[WB_V_R_VP_Z_TUPLE:%[0-9]+]] = load [trivial] [[V_R_VP_Z_TUPLE_MAT]]
// CHECK: [[SET_Z_TUPLE_METHOD:%[0-9]+]] = function_ref @$s10properties3ValV7z_tupleSi_Sitvs
// CHECK: apply [[SET_Z_TUPLE_METHOD]]({{%[0-9]+, %[0-9]+}}, [[VAL_REF_VAL_PROP_MAT]])
// -- writeback to val.ref.val_prop
// CHECK: end_apply [[TOKEN]]
// -- cleanup
// CHECK: dealloc_stack [[V_R_VP_Z_TUPLE_MAT]]
// -- don't need to write back to val.ref because it's a ref type
}
func reftype_rvalue() -> Ref {}
// CHECK-LABEL: sil hidden [ossa] @$s10properties18reftype_rvalue_set{{[_0-9a-zA-Z]*}}F
func reftype_rvalue_set(_ value: Val) {
reftype_rvalue().val_prop = value
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties27tuple_in_logical_struct_set{{[_0-9a-zA-Z]*}}F
func tuple_in_logical_struct_set(_ value: inout Val, z1: Int) {
// CHECK: bb0([[VAL:%[0-9]+]] : $*Val, [[Z1:%[0-9]+]] : $Int):
value.z_tuple.1 = z1
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[VAL]]
// CHECK: [[Z_TUPLE_MATERIALIZED:%[0-9]+]] = alloc_stack $(Int, Int)
// CHECK: [[VAL1:%[0-9]+]] = load_borrow [[WRITE]]
// CHECK: [[A0:%.*]] = tuple_element_addr [[Z_TUPLE_MATERIALIZED]] : {{.*}}, 0
// CHECK: [[A1:%.*]] = tuple_element_addr [[Z_TUPLE_MATERIALIZED]] : {{.*}}, 1
// CHECK: [[Z_GET_METHOD:%[0-9]+]] = function_ref @$s10properties3ValV7z_tupleSi_Sitvg
// CHECK: [[Z_TUPLE:%[0-9]+]] = apply [[Z_GET_METHOD]]([[VAL1]])
// CHECK: ([[T0:%.*]], [[T1:%.*]]) = destructure_tuple [[Z_TUPLE]]
// CHECK: store [[T0]] to [trivial] [[A0]]
// CHECK: store [[T1]] to [trivial] [[A1]]
// CHECK: end_borrow [[VAL1]]
// CHECK: [[Z_TUPLE_1:%[0-9]+]] = tuple_element_addr [[Z_TUPLE_MATERIALIZED]] : {{.*}}, 1
// CHECK: assign [[Z1]] to [[Z_TUPLE_1]]
// CHECK: [[Z_TUPLE_MODIFIED:%[0-9]+]] = load [trivial] [[Z_TUPLE_MATERIALIZED]]
// CHECK: [[Z_SET_METHOD:%[0-9]+]] = function_ref @$s10properties3ValV7z_tupleSi_Sitvs
// CHECK: apply [[Z_SET_METHOD]]({{%[0-9]+, %[0-9]+}}, [[WRITE]])
// CHECK: dealloc_stack [[Z_TUPLE_MATERIALIZED]]
// CHECK: return
}
var global_prop : Int {
// CHECK-LABEL: sil hidden [ossa] @$s10properties11global_prop{{[_0-9a-zA-Z]*}}vg
get {
return zero
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties11global_prop{{[_0-9a-zA-Z]*}}vs
set {
use(newValue)
}
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties18logical_global_get{{[_0-9a-zA-Z]*}}F
func logical_global_get() -> Int {
return global_prop
// CHECK: [[GET:%[0-9]+]] = function_ref @$s10properties11global_prop{{[_0-9a-zA-Z]*}}vg
// CHECK: [[VALUE:%[0-9]+]] = apply [[GET]]()
// CHECK: return [[VALUE]]
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties18logical_global_set{{[_0-9a-zA-Z]*}}F
func logical_global_set(_ x: Int) {
global_prop = x
// CHECK: [[SET:%[0-9]+]] = function_ref @$s10properties11global_prop{{[_0-9a-zA-Z]*}}vs
// CHECK: apply [[SET]](%0)
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties17logical_local_get{{[_0-9a-zA-Z]*}}F
func logical_local_get(_ x: Int) -> Int {
var prop : Int {
get {
return x
}
}
// CHECK: [[GET_REF:%[0-9]+]] = function_ref [[PROP_GET_CLOSURE:@\$s10properties17logical_local_getyS2iF4propL_Sivg]]
// CHECK: apply [[GET_REF]](%0)
return prop
}
// CHECK-: sil private [[PROP_GET_CLOSURE]]
// CHECK: bb0(%{{[0-9]+}} : $Int):
func logical_generic_local_get<T>(_ x: Int, _: T) {
var prop1: Int {
get {
return x
}
}
_ = prop1
var prop2: Int {
get {
_ = T.self
return x
}
}
_ = prop2
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties26logical_local_captured_get{{[_0-9a-zA-Z]*}}F
func logical_local_captured_get(_ x: Int) -> Int {
var prop : Int {
get {
return x
}
}
func get_prop() -> Int {
return prop
}
return get_prop()
// CHECK: [[FUNC_REF:%[0-9]+]] = function_ref @$s10properties26logical_local_captured_getyS2iF0E5_propL_SiyF
// CHECK: apply [[FUNC_REF]](%0)
}
// CHECK: sil private [ossa] @$s10properties26logical_local_captured_get{{.*}}vg
// CHECK: bb0(%{{[0-9]+}} : $Int):
func inout_arg(_ x: inout Int) {}
// CHECK-LABEL: sil hidden [ossa] @$s10properties14physical_inout{{[_0-9a-zA-Z]*}}F
func physical_inout(_ x: Int) {
var x = x
// CHECK: [[XADDR:%[0-9]+]] = alloc_box ${ var Int }
// CHECK: [[PB:%.*]] = project_box [[XADDR]]
inout_arg(&x)
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
// CHECK: [[INOUT_ARG:%[0-9]+]] = function_ref @$s10properties9inout_arg{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[INOUT_ARG]]([[WRITE]])
}
/* TODO check writeback to more complex logical prop, check that writeback
* reuses temporaries */
// CHECK-LABEL: sil hidden [ossa] @$s10properties17val_subscript_get{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@guaranteed Val, Int) -> Float
// CHECK: bb0([[VVAL:%[0-9]+]] : @guaranteed $Val, [[I:%[0-9]+]] : $Int):
func val_subscript_get(_ v: Val, i: Int) -> Float {
return v[i]
// CHECK: [[SUBSCRIPT_GET_METHOD:%[0-9]+]] = function_ref @$s10properties3ValV{{[_0-9a-zA-Z]*}}ig
// CHECK: [[RET:%[0-9]+]] = apply [[SUBSCRIPT_GET_METHOD]]([[I]], [[VVAL]]) : $@convention(method) (Int, @guaranteed Val)
// CHECK: return [[RET]]
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties17val_subscript_set{{[_0-9a-zA-Z]*}}F
// CHECK: bb0(%0 : @guaranteed $Val, [[I:%[0-9]+]] : $Int, [[X:%[0-9]+]] : $Float):
func val_subscript_set(_ v: Val, i: Int, x: Float) {
var v = v
v[i] = x
// CHECK: [[VADDR:%[0-9]+]] = alloc_box ${ var Val }
// CHECK: [[PB:%.*]] = project_box [[VADDR]]
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
// CHECK: [[SUBSCRIPT_SET_METHOD:%[0-9]+]] = function_ref @$s10properties3ValV{{[_0-9a-zA-Z]*}}is
// CHECK: apply [[SUBSCRIPT_SET_METHOD]]([[X]], [[I]], [[WRITE]])
}
struct Generic<T> {
var mono_phys:Int
var mono_log: Int { get {} set {} }
var typevar_member:T
subscript(x: Int) -> Float { get {} set {} }
subscript(x: T) -> T { get {} set {} }
// CHECK-LABEL: sil hidden [ossa] @$s10properties7GenericV19copy_typevar_member{{[_0-9a-zA-Z]*}}F
mutating
func copy_typevar_member(_ x: Generic<T>) {
typevar_member = x.typevar_member
}
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties21generic_mono_phys_get{{[_0-9a-zA-Z]*}}F
func generic_mono_phys_get<T>(_ g: Generic<T>) -> Int {
return g.mono_phys
// CHECK: struct_element_addr %{{.*}}, #Generic.mono_phys
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties20generic_mono_log_get{{[_0-9a-zA-Z]*}}F
func generic_mono_log_get<T>(_ g: Generic<T>) -> Int {
return g.mono_log
// CHECK: [[GENERIC_GET_METHOD:%[0-9]+]] = function_ref @$s10properties7GenericV8mono_log{{[_0-9a-zA-Z]*}}vg
// CHECK: apply [[GENERIC_GET_METHOD]]<
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties20generic_mono_log_set{{[_0-9a-zA-Z]*}}F
func generic_mono_log_set<T>(_ g: Generic<T>, x: Int) {
var g = g
g.mono_log = x
// CHECK: [[GENERIC_SET_METHOD:%[0-9]+]] = function_ref @$s10properties7GenericV8mono_log{{[_0-9a-zA-Z]*}}vs
// CHECK: apply [[GENERIC_SET_METHOD]]<
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties26generic_mono_subscript_get{{[_0-9a-zA-Z]*}}F
func generic_mono_subscript_get<T>(_ g: Generic<T>, i: Int) -> Float {
return g[i]
// CHECK: [[GENERIC_GET_METHOD:%[0-9]+]] = function_ref @$s10properties7GenericV{{[_0-9a-zA-Z]*}}ig
// CHECK: apply [[GENERIC_GET_METHOD]]<
}
// CHECK-LABEL: sil hidden [ossa] @{{.*}}generic_mono_subscript_set
func generic_mono_subscript_set<T>(_ g: inout Generic<T>, i: Int, x: Float) {
g[i] = x
// CHECK: [[GENERIC_SET_METHOD:%[0-9]+]] = function_ref @$s10properties7GenericV{{[_0-9a-zA-Z]*}}is
// CHECK: apply [[GENERIC_SET_METHOD]]<
}
// CHECK-LABEL: sil hidden [ossa] @{{.*}}bound_generic_mono_phys_get
func bound_generic_mono_phys_get(_ g: inout Generic<UnicodeScalar>, x: Int) -> Int {
return g.mono_phys
// CHECK: struct_element_addr %{{.*}}, #Generic.mono_phys
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties26bound_generic_mono_log_get{{[_0-9a-zA-Z]*}}F
func bound_generic_mono_log_get(_ g: Generic<UnicodeScalar>, x: Int) -> Int {
return g.mono_log
// CHECK: [[GENERIC_GET_METHOD:%[0-9]+]] = function_ref @$s10properties7GenericV8mono_log{{[_0-9a-zA-Z]*}}vg
// CHECK: apply [[GENERIC_GET_METHOD]]<
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties22generic_subscript_type{{[_0-9a-zA-Z]*}}F
func generic_subscript_type<T>(_ g: Generic<T>, i: T, x: T) -> T {
var g = g
g[i] = x
return g[i]
}
/*TODO: archetype and existential properties and subscripts */
struct StaticProperty {
static var foo: Int {
get {
return zero
}
set {}
}
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties10static_get{{[_0-9a-zA-Z]*}}F
// CHECK: function_ref @$s10properties14StaticPropertyV3foo{{[_0-9a-zA-Z]*}}vgZ : $@convention(method) (@thin StaticProperty.Type) -> Int
func static_get() -> Int {
return StaticProperty.foo
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties10static_set{{[_0-9a-zA-Z]*}}F
// CHECK: function_ref @$s10properties14StaticPropertyV3foo{{[_0-9a-zA-Z]*}}vsZ : $@convention(method) (Int, @thin StaticProperty.Type) -> ()
func static_set(_ x: Int) {
StaticProperty.foo = x
}
// Superclass init methods should not get direct access to be class properties.
// rdar://16151899
class rdar16151899Base {
var x: Int = zero {
willSet {
use(x)
}
}
}
class rdar16151899Derived : rdar16151899Base {
// CHECK-LABEL: sil hidden [ossa] @$s10properties19rdar16151899DerivedC{{[_0-9a-zA-Z]*}}fc
override init() {
super.init()
// CHECK: upcast {{.*}} : $rdar16151899Derived to $rdar16151899Base
// CHECK: function_ref @$s10properties16rdar16151899BaseCACycfc : $@convention(method) (@owned rdar16151899Base) -> @owned rdar16151899Base
// This should not be a direct access, it should call the setter in the
// base.
x = zero
// CHECK: [[BASEPTR:%[0-9]+]] = upcast {{.*}} : $rdar16151899Derived to $rdar16151899Base
// CHECK: load{{.*}}Int
// CHECK-NEXT: end_access {{.*}} : $*Int
// CHECK-NEXT: [[SETTER:%[0-9]+]] = class_method {{.*}} : $rdar16151899Base, #rdar16151899Base.x!setter : (rdar16151899Base)
// CHECK-NEXT: apply [[SETTER]]({{.*}}, [[BASEPTR]])
}
}
class BaseProperty {
var x : Int { get {} set {} }
}
class DerivedProperty : BaseProperty {
override var x : Int { get {} set {} }
func super_property_reference() -> Int {
return super.x
}
}
// rdar://16381392 - Super property references in non-objc classes should be direct.
// CHECK-LABEL: sil hidden [ossa] @$s10properties15DerivedPropertyC24super_property_referenceSiyF : $@convention(method) (@guaranteed DerivedProperty) -> Int {
// CHECK: bb0([[SELF:%.*]] : @guaranteed $DerivedProperty):
// CHECK: [[SELF_COPY:%[0-9]+]] = copy_value [[SELF]]
// CHECK: [[BASEPTR:%[0-9]+]] = upcast [[SELF_COPY]] : $DerivedProperty to $BaseProperty
// CHECK: [[BORROW:%[0-9]+]] = begin_borrow [[BASEPTR]]
// CHECK: [[FN:%[0-9]+]] = function_ref @$s10properties12BasePropertyC1xSivg : $@convention(method) (@guaranteed BaseProperty) -> Int
// CHECK: [[RESULT:%.*]] = apply [[FN]]([[BORROW]]) : $@convention(method) (@guaranteed BaseProperty) -> Int
// CHECK: destroy_value [[BASEPTR]]
// CHECK: return [[RESULT]] : $Int
// CHECK: } // end sil function '$s10properties15DerivedPropertyC24super_property_referenceSiyF'
// <rdar://problem/16411449> ownership qualifiers don't work with non-mutating struct property
struct ReferenceStorageTypeRValues {
unowned var p1 : Ref
func testRValueUnowned() -> Ref {
return p1
}
// CHECK: sil hidden [ossa] @{{.*}}testRValueUnowned{{.*}} : $@convention(method) (@guaranteed ReferenceStorageTypeRValues) -> @owned Ref {
// CHECK: bb0([[ARG:%.*]] : @guaranteed $ReferenceStorageTypeRValues):
// CHECK-NEXT: debug_value [[ARG]] : $ReferenceStorageTypeRValues
// CHECK-NEXT: [[UNOWNED_ARG_FIELD:%.*]] = struct_extract [[ARG]] : $ReferenceStorageTypeRValues, #ReferenceStorageTypeRValues.p1
// CHECK-NEXT: [[COPIED_VALUE:%.*]] = strong_copy_unowned_value [[UNOWNED_ARG_FIELD]]
// CHECK-NEXT: return [[COPIED_VALUE]] : $Ref
init() {
}
}
// <rdar://problem/16554876> property accessor synthesization of weak variables doesn't work
protocol WeakPropertyProtocol {
var maybePresent : Ref? { get set }
}
struct WeakPropertyStruct : WeakPropertyProtocol {
weak var maybePresent : Ref?
init() {
maybePresent = nil
}
}
// <rdar://problem/16629598> direct property accesses to generic struct
// properties were being mischecked as computed property accesses.
struct SomeGenericStruct<T> {
var x: Int
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties4getX{{[_0-9a-zA-Z]*}}F
// CHECK: struct_extract {{%.*}} : $SomeGenericStruct<T>, #SomeGenericStruct.x
func getX<T>(_ g: SomeGenericStruct<T>) -> Int {
return g.x
}
/// <rdar://problem/16953517> Class properties should be allowed in protocols, even without stored class properties
protocol ProtoWithClassProp {
static var x: Int { get }
}
class ClassWithClassProp : ProtoWithClassProp {
class var x: Int {
return 42
}
}
struct StructWithClassProp : ProtoWithClassProp {
static var x: Int {
return 19
}
}
func getX<T : ProtoWithClassProp>(_ a : T) -> Int {
return T.x
}
func testClassPropertiesInProtocol() -> Int {
return getX(ClassWithClassProp())+getX(StructWithClassProp())
}
class GenericClass<T> {
var x: T
var y: Int
final let z: T
init() { fatalError("scaffold") }
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties12genericPropsyyAA12GenericClassCySSGF : $@convention(thin) (@guaranteed GenericClass<String>) -> () {
func genericProps(_ x: GenericClass<String>) {
// CHECK: bb0([[ARG:%.*]] : @guaranteed $GenericClass<String>):
// CHECK: class_method [[ARG]] : $GenericClass<String>, #GenericClass.x!getter
// CHECK: apply {{.*}}<String>({{.*}}, [[ARG]]) : $@convention(method) <τ_0_0> (@guaranteed GenericClass<τ_0_0>) -> @out τ_0_0
let _ = x.x
// CHECK: class_method [[ARG]] : $GenericClass<String>, #GenericClass.y!getter
// CHECK: apply {{.*}}<String>([[ARG]]) : $@convention(method) <τ_0_0> (@guaranteed GenericClass<τ_0_0>) -> Int
let _ = x.y
// CHECK: [[Z:%.*]] = ref_element_addr [[ARG]] : $GenericClass<String>, #GenericClass.z
// CHECK: [[LOADED_Z:%.*]] = load [copy] [[Z]] : $*String
// CHECK: destroy_value [[LOADED_Z]]
// CHECK-NOT: destroy_value [[ARG]]
let _ = x.z
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties28genericPropsInGenericContext{{[_0-9a-zA-Z]*}}F
func genericPropsInGenericContext<U>(_ x: GenericClass<U>) {
// CHECK: bb0([[ARG:%.*]] : @guaranteed $GenericClass<U>):
// CHECK: [[Z:%.*]] = ref_element_addr [[ARG]] : $GenericClass<U>, #GenericClass.z
// CHECK: copy_addr [[Z]] {{.*}} : $*U
let _ = x.z
}
// <rdar://problem/18275556> 'let' properties in a class should be implicitly final
class ClassWithLetProperty {
let p = 42
@objc dynamic let q = 97
// We shouldn't have any dynamic dispatch within this method, just load p.
func ReturnConstant() -> Int { return p }
// CHECK-LABEL: sil hidden [ossa] @$s10properties20ClassWithLetPropertyC14ReturnConstant{{[_0-9a-zA-Z]*}}F
// CHECK: bb0([[ARG:%.*]] : @guaranteed $ClassWithLetProperty):
// CHECK-NEXT: debug_value
// CHECK-NEXT: [[PTR:%[0-9]+]] = ref_element_addr [[ARG]] : $ClassWithLetProperty, #ClassWithLetProperty.p
// CHECK-NEXT: [[VAL:%[0-9]+]] = load [trivial] [[PTR]] : $*Int
// CHECK-NEXT: return [[VAL]] : $Int
// This property is marked dynamic, so go through the getter, always.
func ReturnDynamicConstant() -> Int { return q }
// CHECK-LABEL: sil hidden [ossa] @$s10properties20ClassWithLetPropertyC21ReturnDynamicConstant{{[_0-9a-zA-Z]*}}F
// CHECK: objc_method %0 : $ClassWithLetProperty, #ClassWithLetProperty.q!getter.foreign
}
// <rdar://problem/19254812> DI bug when referencing let member of a class
class r19254812Base {}
class r19254812Derived: r19254812Base{
let pi = 3.14159265359
init(x : ()) {
use(pi)
}
// Accessing the "pi" property should not copy_value/release self.
// CHECK-LABEL: sil hidden [ossa] @$s10properties16r19254812DerivedC{{[_0-9a-zA-Z]*}}fc
// CHECK: [[MARKED_SELF_BOX:%.*]] = mark_uninitialized [derivedself]
// CHECK: [[PB_BOX:%.*]] = project_box [[MARKED_SELF_BOX]]
// Initialization of the pi field: no copy_values/releases.
// CHECK: [[SELF:%[0-9]+]] = load_borrow [[PB_BOX]] : $*r19254812Derived
// CHECK-NEXT: [[PIPTR:%[0-9]+]] = ref_element_addr [[SELF]] : $r19254812Derived, #r19254812Derived.pi
// CHECK: [[FN:%[0-9]+]] = function_ref @$s10properties16r19254812DerivedC2piSdvpfi : $@convention(thin) () -> Double
// CHECK-NEXT: [[RESULT:%[0-9]+]] = apply [[FN]]() : $@convention(thin) () -> Double
// CHECK-NEXT: store [[RESULT]] to [trivial] [[PIPTR]] : $*Double
// CHECK-NOT: destroy_value
// CHECK-NOT: copy_value
// Load of the pi field: no copy_values/releases.
// CHECK: [[SELF:%[0-9]+]] = load_borrow [[PB_BOX]] : $*r19254812Derived
// CHECK-NEXT: [[PIPTR:%[0-9]+]] = ref_element_addr [[SELF]] : $r19254812Derived, #r19254812Derived.pi
// CHECK-NEXT: {{.*}} = load [trivial] [[PIPTR]] : $*Double
// CHECK: return
}
class RedundantSelfRetains {
final var f : RedundantSelfRetains
init() {
f = RedundantSelfRetains()
}
// <rdar://problem/19275047> Extraneous copy_values/releases of self are bad
func testMethod1() {
f = RedundantSelfRetains()
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties20RedundantSelfRetainsC11testMethod1{{[_0-9a-zA-Z]*}}F
// CHECK: bb0(%0 : @guaranteed $RedundantSelfRetains):
// CHECK-NOT: copy_value
// CHECK: [[FPTR:%[0-9]+]] = ref_element_addr %0 : $RedundantSelfRetains, #RedundantSelfRetains.f
// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[FPTR]] : $*RedundantSelfRetains
// CHECK-NEXT: assign {{.*}} to [[WRITE]] : $*RedundantSelfRetains
// CHECK: return
}
class RedundantRetains {
final var field = 0
}
func testRedundantRetains() {
let a = RedundantRetains()
a.field = 4 // no copy_value/release of a necessary here.
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties20testRedundantRetainsyyF : $@convention(thin) () -> () {
// CHECK: [[A:%[0-9]+]] = apply
// CHECK-NOT: copy_value
// CHECK: destroy_value [[A]] : $RedundantRetains
// CHECK-NOT: copy_value
// CHECK-NOT: destroy_value
// CHECK: return
struct AddressOnlyNonmutatingSet<T> {
var x: T
init(x: T) { self.x = x }
var prop: Int {
get { return 0 }
nonmutating set { }
}
}
func addressOnlyNonmutatingProperty<T>(_ x: AddressOnlyNonmutatingSet<T>)
-> Int {
x.prop = 0
return x.prop
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties30addressOnlyNonmutatingProperty{{[_0-9a-zA-Z]*}}F
// CHECK: [[SET:%.*]] = function_ref @$s10properties25AddressOnlyNonmutatingSetV4propSivs
// CHECK: apply [[SET]]<T>({{%.*}}, [[TMP:%[0-9]*]])
// CHECK: destroy_addr [[TMP]]
// CHECK: dealloc_stack [[TMP]]
// CHECK: [[GET:%.*]] = function_ref @$s10properties25AddressOnlyNonmutatingSetV4propSivg
// CHECK: apply [[GET]]<T>([[TMP:%[0-9]*]])
// CHECK: destroy_addr [[TMP]]
// CHECK: dealloc_stack [[TMP]]
protocol MakeAddressOnly {}
struct AddressOnlyReadOnlySubscript {
var x: MakeAddressOnly?
subscript(z: Int) -> Int { return z }
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties015addressOnlyReadC24SubscriptFromMutableBase
// CHECK: [[BASE:%.*]] = alloc_box ${ var AddressOnlyReadOnlySubscript }
// CHECK: copy_addr [[BASE:%.*]] to [initialization] [[COPY:%.*]] :
// CHECK: copy_addr [[COPY:%.*]] to [initialization] [[COPY2:%.*]] :
// CHECK: [[GETTER:%.*]] = function_ref @$s10properties015AddressOnlyReadC9SubscriptV{{[_0-9a-zA-Z]*}}ig
// CHECK: apply [[GETTER]]({{%.*}}, [[COPY2]])
func addressOnlyReadOnlySubscriptFromMutableBase(_ x: Int) {
var base = AddressOnlyReadOnlySubscript()
_ = base[x]
}
/// <rdar://problem/20912019> passing unmaterialized r-value as inout argument
struct MutatingGetterStruct {
var write: Int {
mutating get { }
}
// CHECK-LABEL: sil hidden [ossa] @$s10properties20MutatingGetterStructV4test
// CHECK: [[X:%.*]] = alloc_box ${ var MutatingGetterStruct }, var, name "x"
// CHECK-NEXT: [[PB:%.*]] = project_box [[X]]
// CHECK: store {{.*}} to [trivial] [[PB]] : $*MutatingGetterStruct
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
// CHECK: apply {{%.*}}([[WRITE]]) : $@convention(method) (@inout MutatingGetterStruct) -> Int
static func test() {
var x = MutatingGetterStruct()
_ = x.write
}
}
protocol ProtocolWithReadWriteSubscript {
subscript(i: Int) -> Int { get set }
}
struct CrashWithUnnamedSubscript : ProtocolWithReadWriteSubscript {
subscript(_: Int) -> Int { get { } set { } }
}
// Make sure that we can handle this AST:
// (load_expr
// (open_existential_expr
// (opaque_expr A)
// ...
// (load_expr
// (opaque_expr ))))
class ReferenceType {
var p: NonmutatingProtocol
init(p: NonmutatingProtocol) { self.p = p }
}
protocol NonmutatingProtocol {
var x: Int { get nonmutating set }
}
// sil hidden [ossa] @$s10properties19overlappingLoadExpr1cyAA13ReferenceTypeCz_tF : $@convention(thin) (@inout ReferenceType) -> () {
// CHECK: [[C_INOUT:%.*]] = begin_access [read] [unknown] %0 : $*ReferenceType
// CHECK-NEXT: [[C:%.*]] = load [copy] [[C_INOUT:%.*]] : $*ReferenceType
// CHECK-NEXT: end_access [[C_INOUT]] : $*ReferenceType
// CHECK-NEXT: [[C_BORROW:%.*]] = begin_borrow [[C]]
// CHECK-NEXT: [[C_FIELD_BOX:%.*]] = alloc_stack $NonmutatingProtocol
// CHECK-NEXT: [[GETTER:%.*]] = class_method [[C_BORROW]] : $ReferenceType, #ReferenceType.p!getter : (ReferenceType) -> () -> NonmutatingProtocol, $@convention(method) (@guaranteed ReferenceType) -> @out NonmutatingProtocol
// CHECK-NEXT: apply [[GETTER]]([[C_FIELD_BOX]], [[C_BORROW]]) : $@convention(method) (@guaranteed ReferenceType) -> @out NonmutatingProtocol
// CHECK-NEXT: end_borrow [[C_BORROW]]
// CHECK-NEXT: [[C_FIELD_PAYLOAD:%.*]] = open_existential_addr immutable_access [[C_FIELD_BOX]] : $*NonmutatingProtocol to $*@opened("{{.*}}") NonmutatingProtocol
// CHECK-NEXT: [[C_FIELD_COPY:%.*]] = alloc_stack $@opened("{{.*}}") NonmutatingProtocol
// CHECK-NEXT: copy_addr [[C_FIELD_PAYLOAD]] to [initialization] [[C_FIELD_COPY]] : $*@opened("{{.*}}") NonmutatingProtocol
// CHECK-NEXT: destroy_value [[C]] : $ReferenceType
// CHECK-NEXT: [[C_FIELD_BORROW:%.*]] = alloc_stack
// CHECK-NEXT: copy_addr [[C_FIELD_COPY]] to [initialization] [[C_FIELD_BORROW]]
// CHECK-NEXT: [[GETTER:%.*]] = witness_method $@opened("{{.*}}") NonmutatingProtocol, #NonmutatingProtocol.x!getter : <Self where Self : NonmutatingProtocol> (Self) -> () -> Int, [[C_FIELD_PAYLOAD]] : $*@opened("{{.*}}") NonmutatingProtocol : $@convention(witness_method: NonmutatingProtocol) <τ_0_0 where τ_0_0 : NonmutatingProtocol> (@in_guaranteed τ_0_0) -> Int
// CHECK-NEXT: [[RESULT_VALUE:%.*]] = apply [[GETTER]]<@opened("{{.*}}") NonmutatingProtocol>([[C_FIELD_BORROW]]) : $@convention(witness_method: NonmutatingProtocol) <τ_0_0 where τ_0_0 : NonmutatingProtocol> (@in_guaranteed τ_0_0) -> Int
// CHECK-NEXT: destroy_addr [[C_FIELD_BORROW]]
// CHECK-NEXT: destroy_addr [[C_FIELD_COPY]] : $*@opened("{{.*}}") NonmutatingProtocol
// CHECK-NEXT: dealloc_stack [[C_FIELD_BORROW]]
// CHECK-NEXT: dealloc_stack [[C_FIELD_COPY]] : $*@opened("{{.*}}") NonmutatingProtocol
// CHECK-NEXT: destroy_addr [[C_FIELD_BOX]] : $*NonmutatingProtocol
// CHECK-NEXT: dealloc_stack [[C_FIELD_BOX]] : $*NonmutatingProtocol
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
func overlappingLoadExpr(c: inout ReferenceType) {
_ = c.p.x
}
var globalOptionalComputed: Int? {
didSet { print("hello") }
}
func updateGlobalOptionalComputed() {
globalOptionalComputed? = 123
}
struct TupleStruct {
var v: (Int, Int) { get { } set { } }
var vv: (w: Int, h: Int) { get { } set { } }
}
func assign_to_tuple() {
var s = TupleStruct()
s.v = (1, 2)
let v = (3, 4)
s.vv = v
}
// CHECK-LABEL: sil private [ossa] @$s10properties8myglobalSivW
// CHECK-LABEL: sil [ossa] @$s10properties8myglobalSivg
// CHECK-LABEL: sil [ossa] @$s10properties8myglobalSivs
public var myglobal : Int = 1 {
didSet {
print("myglobal.didSet")
}
}
// CHECK-LABEL: sil private [ossa] @$s10properties9myglobal2Sivw
// CHECK-LABEL: sil [ossa] @$s10properties9myglobal2Sivg
// CHECK-LABEL: sil [ossa] @$s10properties9myglobal2Sivs
public var myglobal2 : Int = 1 {
willSet {
print("myglobal.willSet")
}
}
// CHECK-LABEL: sil private [ossa] @$s10properties9myglobal3Sivw
// CHECK-LABEL: sil private [ossa] @$s10properties9myglobal3SivW
// CHECK-LABEL: sil [ossa] @$s10properties9myglobal3Sivg
// CHECK-LABEL: sil [ossa] @$s10properties9myglobal3Sivs
public var myglobal3 : Int = 1 {
willSet {
print("myglobal.willSet")
}
didSet {
print("myglobal.didSet")
}
}