// RUN: %target-swift-emit-silgen -Xllvm -sil-print-types -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: [[XLIFETIME:%.*]] = begin_borrow [var_decl] [[MARKED_BOX]] // CHECK: [[XADDR:%.*]] = project_box [[XLIFETIME]] 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]+}} : @closureCapture $Int): func logical_generic_local_get(_ 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]+}} : @closureCapture $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: [[XL:%.*]] = begin_borrow [var_decl] [[XADDR]] // CHECK: [[PB:%.*]] = project_box [[XL]] 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: [[LIFETIME:%[0-9]+]] = begin_borrow [lexical] [var_decl] [[VADDR]] // CHECK: [[PB:%.*]] = project_box [[LIFETIME]] // 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 { 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) { typevar_member = x.typevar_member } } // CHECK-LABEL: sil hidden [ossa] @$s10properties21generic_mono_phys_get{{[_0-9a-zA-Z]*}}F func generic_mono_phys_get(_ g: Generic) -> 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(_ g: Generic) -> 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(_ g: Generic, 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(_ g: Generic, 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(_ g: inout Generic, 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, 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, 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(_ g: Generic, 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' // 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() { } } // 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 } } // direct property accesses to generic struct // properties were being mischecked as computed property accesses. struct SomeGenericStruct { var x: Int } // CHECK-LABEL: sil hidden [ossa] @$s10properties4getX{{[_0-9a-zA-Z]*}}F // CHECK: struct_extract {{%.*}} : $SomeGenericStruct, #SomeGenericStruct.x func getX(_ g: SomeGenericStruct) -> Int { return g.x } /// 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(_ a : T) -> Int { return T.x } func testClassPropertiesInProtocol() -> Int { return getX(ClassWithClassProp())+getX(StructWithClassProp()) } class GenericClass { var x: T var y: Int final let z: T init() { fatalError("scaffold") } } // CHECK-LABEL: sil hidden [ossa] @$s10properties12genericPropsyyAA12GenericClassCySSGF : $@convention(thin) (@guaranteed GenericClass) -> () { func genericProps(_ x: GenericClass) { // CHECK: bb0([[ARG:%.*]] : @guaranteed $GenericClass): // CHECK: class_method [[ARG]] : $GenericClass, #GenericClass.x!getter // CHECK: apply {{.*}}({{.*}}, [[ARG]]) : $@convention(method) <τ_0_0> (@guaranteed GenericClass<τ_0_0>) -> @out τ_0_0 let _ = x.x // CHECK: class_method [[ARG]] : $GenericClass, #GenericClass.y!getter // CHECK: apply {{.*}}([[ARG]]) : $@convention(method) <τ_0_0> (@guaranteed GenericClass<τ_0_0>) -> Int let _ = x.y // CHECK: [[Z:%.*]] = ref_element_addr [[ARG]] : $GenericClass, #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(_ x: GenericClass) { // CHECK: bb0([[ARG:%.*]] : @guaranteed $GenericClass): // CHECK: [[Z:%.*]] = ref_element_addr [[ARG]] : $GenericClass, #GenericClass.z // CHECK: copy_addr [[Z]] {{.*}} : $*U let _ = x.z } // '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 } // 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: [[LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[MARKED_SELF_BOX]] // CHECK: [[PB_BOX:%.*]] = project_box [[LIFETIME]] // 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() } // 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: [[MOVED_A:%[0-9]+]] = move_value [lexical] [var_decl] [[A]] // CHECK-NOT: copy_value // CHECK: destroy_value [[MOVED_A]] : $RedundantRetains // CHECK-NOT: copy_value // CHECK-NOT: destroy_value // CHECK: return struct AddressOnlyNonmutatingSet { var x: T init(x: T) { self.x = x } var prop: Int { get { return 0 } nonmutating set { } } } func addressOnlyNonmutatingProperty(_ x: AddressOnlyNonmutatingSet) -> 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]]({{%.*}}, %0) // CHECK: [[GET:%.*]] = function_ref @$s10properties25AddressOnlyNonmutatingSetV4propSivg // CHECK: apply [[GET]]([[TMP:%[0-9]*]]) 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 [init] [[COPY:%.*]] : // CHECK: [[GETTER:%.*]] = function_ref @$s10properties015AddressOnlyReadC9SubscriptV{{[_0-9a-zA-Z]*}}ig // CHECK: apply [[GETTER]]({{%.*}}, [[COPY]]) func addressOnlyReadOnlySubscriptFromMutableBase(_ x: Int) { var base = AddressOnlyReadOnlySubscript() _ = base[x] } /// 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: [[XL:%.*]] = begin_borrow [var_decl] [[X]] // CHECK-NEXT: [[PB:%.*]] = project_box [[XL]] // 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 $any NonmutatingProtocol // CHECK-NEXT: [[GETTER:%.*]] = class_method [[C_BORROW]] : $ReferenceType, #ReferenceType.p!getter : (ReferenceType) -> () -> any NonmutatingProtocol, $@convention(method) (@guaranteed ReferenceType) -> @out any NonmutatingProtocol // CHECK-NEXT: apply [[GETTER]]([[C_FIELD_BOX]], [[C_BORROW]]) : $@convention(method) (@guaranteed ReferenceType) -> @out any NonmutatingProtocol // CHECK-NEXT: end_borrow [[C_BORROW]] // CHECK-NEXT: [[C_FIELD_PAYLOAD:%.*]] = open_existential_addr immutable_access [[C_FIELD_BOX]] : $*any NonmutatingProtocol to $*@opened("{{.*}}", any NonmutatingProtocol) Self // CHECK-NEXT: [[C_FIELD_COPY:%.*]] = alloc_stack $@opened("{{.*}}", any NonmutatingProtocol) Self // CHECK-NEXT: copy_addr [[C_FIELD_PAYLOAD]] to [init] [[C_FIELD_COPY]] : $*@opened("{{.*}}", any NonmutatingProtocol) Self // CHECK-NEXT: destroy_value [[C]] : $ReferenceType // CHECK-NEXT: [[GETTER:%.*]] = witness_method $@opened("{{.*}}", any NonmutatingProtocol) Self, #NonmutatingProtocol.x!getter : (Self) -> () -> Int, [[C_FIELD_PAYLOAD]] : $*@opened("{{.*}}", any NonmutatingProtocol) Self : $@convention(witness_method: NonmutatingProtocol) <τ_0_0 where τ_0_0 : NonmutatingProtocol> (@in_guaranteed τ_0_0) -> Int // CHECK-NEXT: [[RESULT_VALUE:%.*]] = apply [[GETTER]]<@opened("{{.*}}", any NonmutatingProtocol) Self>([[C_FIELD_COPY]]) : $@convention(witness_method: NonmutatingProtocol) <τ_0_0 where τ_0_0 : NonmutatingProtocol> (@in_guaranteed τ_0_0) -> Int // CHECK-NEXT: ignored_use // CHECK-NEXT: destroy_addr [[C_FIELD_COPY]] : $*@opened("{{.*}}", any NonmutatingProtocol) Self // CHECK-NEXT: dealloc_stack [[C_FIELD_COPY]] : $*@opened("{{.*}}", any NonmutatingProtocol) Self // CHECK-NEXT: destroy_addr [[C_FIELD_BOX]] : $*any NonmutatingProtocol // CHECK-NEXT: dealloc_stack [[C_FIELD_BOX]] : $*any 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") } }