Skip to content

Commit

Permalink
[SILGen] Only use assign_by_wrapper for wrapped instance properties i…
Browse files Browse the repository at this point in the history
…nside an

initializer, and for wrapped local variables.
  • Loading branch information
hborla committed Sep 28, 2020
1 parent b33dbed commit 0842b42
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 16 deletions.
5 changes: 5 additions & 0 deletions lib/SILGen/SILGenLValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1314,6 +1314,11 @@ namespace {
IsOnSelfParameter &&
isa<ConstructorDecl>(SGF.FunctionDC->getAsDecl());

// Assignment to a wrapped property can only be re-written to initialization for
// members of `self` in an initializer, and for local variables.
if (!(isAssignmentToSelfParamInInit || VD->getDeclContext()->isLocalContext()))
return false;

// If we have a nonmutating setter on a value type, the call
// captures all of 'self' and we cannot rewrite an assignment
// into an initialization.
Expand Down
19 changes: 14 additions & 5 deletions test/SILGen/objc_properties.swift
Original file line number Diff line number Diff line change
Expand Up @@ -285,19 +285,28 @@ public struct SomeWrapper {

class SomeWrapperTests {
@objc @SomeWrapper dynamic var someWrapper: Int = 0
// CHECK-LABEL: sil hidden [ossa] @$s15objc_properties16SomeWrapperTestsC14testAssignmentyyF
@W @objc dynamic var s: String? = nil

// CHECK-LABEL: sil hidden [ossa] @$s15objc_properties16SomeWrapperTestsCyACSScfc : $@convention(method) (@owned String, @owned SomeWrapperTests) -> @owned SomeWrapperTests {
// CHECK: [[M:%.*]] = function_ref @$s15objc_properties16SomeWrapperTestsC04someD0SivsTD
// CHECK: [[C:%.*]] = partial_apply [callee_guaranteed] [[M]]({{.*}})
// CHECK: assign_by_wrapper {{%.*}}: $Int to {{%.*}} : $*SomeWrapper, init {{.*}} : $@callee_guaranteed (Int) -> SomeWrapper, set [[C]] : $@callee_guaranteed (Int) -> ()
// CHECK: [[M:%.*]] = function_ref @$s15objc_properties16SomeWrapperTestsC1sSSSgvsTD
// CHECK: [[C:%.*]] = partial_apply [callee_guaranteed] [[M]](
// CHECK: assign_by_wrapper {{.*}} : $Optional<String> to {{.*}} : $*W<Optional<String>>, init {{.*}} : $@callee_guaranteed (@owned Optional<String>) -> @owned W<Optional<String>>, set [[C]] : $@callee_guaranteed (@owned Optional<String>) -> ()
init(_ s: String) {
someWrapper = 1000
self.s = s
}

// CHECK-LABEL: sil hidden [ossa] @$s15objc_properties16SomeWrapperTestsC14testAssignmentyyF
// CHECK: objc_method %0 : $SomeWrapperTests, #SomeWrapperTests.someWrapper!setter.foreign : (SomeWrapperTests) -> (Int) -> (), $@convention(objc_method) (Int, SomeWrapperTests) -> ()
func testAssignment() {
someWrapper = 1000
}

@W @objc dynamic var s: String? = nil
// CHECK-LABEL: sil hidden [ossa] @$s15objc_properties16SomeWrapperTestsC16testBridgedValueyySSF
// CHECK: [[M:%.*]] = function_ref @$s15objc_properties16SomeWrapperTestsC1sSSSgvsTD
// CHECK: [[C:%.*]] = partial_apply [callee_guaranteed] [[M]](
// CHECK: assign_by_wrapper {{.*}} : $Optional<String> to {{.*}} : $*W<Optional<String>>, init {{.*}} : $@callee_guaranteed (@owned Optional<String>) -> @owned W<Optional<String>>, set [[C]] : $@callee_guaranteed (@owned Optional<String>) -> ()
// CHECK: objc_method %1 : $SomeWrapperTests, #SomeWrapperTests.s!setter.foreign : (SomeWrapperTests) -> (String?) -> (), $@convention(objc_method) (Optional<NSString>, SomeWrapperTests) -> ()
// Let's not crash.
func testBridgedValue(_ s: String) {
self.s = s
Expand Down
3 changes: 2 additions & 1 deletion test/SILGen/property_wrappers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,8 @@ struct WithTuples {
class TestResilientDI {
@MyPublished var data: Int? = nil

// CHECK: assign_by_wrapper {{%.*}} : $Optional<Int> to {{%.*}} : $*MyPublished<Optional<Int>>, init {{%.*}} : $@callee_guaranteed (Optional<Int>) -> @out MyPublished<Optional<Int>>, set {{%.*}} : $@callee_guaranteed (Optional<Int>) -> ()
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers15TestResilientDIC11doSomethingyyF : $@convention(method) (@guaranteed TestResilientDI) -> () {
// CHECK: class_method %0 : $TestResilientDI, #TestResilientDI.data!setter : (TestResilientDI) -> (Int?) -> (), $@convention(method) (Optional<Int>, @guaranteed TestResilientDI) -> ()

func doSomething() {
self.data = Int()
Expand Down
34 changes: 24 additions & 10 deletions test/SILGen/resilient_assign_by_wrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,27 @@ public enum AddressOnlyEnum {
public class AddressOnlySetter {
@WrapGod var value: AddressOnlyEnum = .value(nil)

init() {
// CHECK-LABEL: sil hidden [ossa] @$s27resilient_assign_by_wrapper17AddressOnlySetterCACycfc
// CHECK: [[E1:%.*]] = alloc_stack $AddressOnlyEnum
// CHECK: [[W:%.*]] = alloc_stack $WrapGod<AddressOnlyEnum>
// CHECK: [[I:%.*]] = function_ref @$s27resilient_assign_by_wrapper17AddressOnlySetterC5valueAA0eF4EnumOvpfP : $@convention(thin) (@in AddressOnlyEnum) -> @out WrapGod<AddressOnlyEnum>
// CHECK: apply [[I]]([[W]], [[E1]])

// CHECK: [[E2:%.*]] = alloc_stack $AddressOnlyEnum
// CHECK-NEXT: inject_enum_addr [[E2]] : $*AddressOnlyEnum, #AddressOnlyEnum.some!enumelt
// CHECK: [[S:%.*]] = partial_apply [callee_guaranteed] {{%.*}}({{%.*}}) : $@convention(method) (@in AddressOnlyEnum, @guaranteed AddressOnlySetter) -> ()
// CHECK: assign_by_wrapper [[E2]] : $*AddressOnlyEnum
// CHECK-SAME: set [[S]] : $@callee_guaranteed (@in AddressOnlyEnum) -> ()
self.value = .some
}

func testAssignment() {
// CHECK-LABEL: sil hidden [ossa] @$s27resilient_assign_by_wrapper17AddressOnlySetterC14testAssignmentyyF
// CHECK: [[E:%.*]] = alloc_stack $AddressOnlyEnum
// CHECK: inject_enum_addr [[E]] : $*AddressOnlyEnum, #AddressOnlyEnum.some!enumelt
// CHECK: [[S:%.*]] = partial_apply [callee_guaranteed] {{%.*}}({{%.*}}) : $@convention(method) (@in AddressOnlyEnum, @guaranteed AddressOnlySetter) -> ()
// CHECK: assign_by_wrapper [[E]] : $*AddressOnlyEnum
// CHECK-SAME: set [[S]] : $@callee_guaranteed (@in AddressOnlyEnum) -> ()
// CHECK: [[S:%.*]] = class_method %0 : $AddressOnlySetter, #AddressOnlySetter.value!setter : (AddressOnlySetter) -> (AddressOnlyEnum) -> (), $@convention(method) (@in AddressOnlyEnum, @guaranteed AddressOnlySetter) -> ()
// CHECK: apply [[S]]([[E]], %0) : $@convention(method) (@in AddressOnlyEnum, @guaranteed AddressOnlySetter) -> ()
self.value = .some
}
}
Expand All @@ -40,8 +54,8 @@ public struct SubstitutedSetter<T> {
}

extension SubstitutedSetter where T == Bool {
mutating func testAssignment() {
// CHECK-LABEL: sil hidden [ossa] @$s27resilient_assign_by_wrapper17SubstitutedSetterVAASbRszlE14testAssignmentyyF
init() {
// CHECK-LABEL: hidden [ossa] @$s27resilient_assign_by_wrapper17SubstitutedSetterVAASbRszlEACySbGycfC
// CHECK: [[W:%.*]] = struct_element_addr {{%.*}} : $*SubstitutedSetter<Bool>, #SubstitutedSetter._value
// CHECK: [[B:%.*]] = alloc_stack $Bool
// CHECK: assign_by_wrapper [[B]] : $*Bool to [[W]] : $*WrapGod<Bool>
Expand All @@ -56,9 +70,9 @@ public struct ReabstractedSetter<T> {
}

extension ReabstractedSetter where T == Int {
mutating func testAssignment() {
// CHECK-LABEL: sil hidden [ossa] @$s27resilient_assign_by_wrapper18ReabstractedSetterVAASiRszlE14testAssignmentyyF
// CHECK: [[F:%.*]] = function_ref @$s27resilient_assign_by_wrapper18ReabstractedSetterVAASiRszlE14testAssignmentyyFySicfU_ : $@convention(thin) (Int) -> ()
init() {
// CHECK-LABEL: hidden [ossa] @$s27resilient_assign_by_wrapper18ReabstractedSetterVAASiRszlEACySiGycfC
// CHECK: [[F:%.*]] = function_ref @$s27resilient_assign_by_wrapper18ReabstractedSetterVAASiRszlEACySiGycfcySicfU_ : $@convention(thin) (Int) -> ()
// CHECK: [[TH_F:%.*]] = thin_to_thick_function [[F]] : $@convention(thin) (Int) -> () to $@callee_guaranteed (Int) -> ()
// CHECK: [[THUNK_REF:%.*]] = function_ref @$sSiIegy_SiIegn_TR : $@convention(thin) (@in_guaranteed Int, @guaranteed @callee_guaranteed (Int) -> ()) -> ()
// CHECK: [[CF:%.*]] = partial_apply [callee_guaranteed] [[THUNK_REF]]([[TH_F]]) : $@convention(thin) (@in_guaranteed Int, @guaranteed @callee_guaranteed (Int) -> ()) -> ()
Expand All @@ -76,8 +90,8 @@ public struct ObjectifiedSetter<T: AnyObject> {
public class SomeObject {}

extension ObjectifiedSetter where T == SomeObject {
mutating func testAssignment() {
// CHECK-LABEL: sil hidden [ossa] @$s27resilient_assign_by_wrapper17ObjectifiedSetterVA2A10SomeObjectCRszrlE14testAssignmentyyF : $@convention(method) (@inout ObjectifiedSetter<SomeObject>) -> () {
init() {
// CHECK-LABEL: sil hidden [ossa] @$s27resilient_assign_by_wrapper17ObjectifiedSetterV5valuexvs : $@convention(method) <T where T : AnyObject> (@owned T, @inout ObjectifiedSetter<T>) -> () {
// CHECK: [[OBJ:%.*]] = apply {{%.*}}({{%.*}}) : $@convention(method) (@thick SomeObject.Type) -> @owned SomeObject
// CHECK: [[STORAGE:%.*]] = struct_element_addr {{%.*}} : $*ObjectifiedSetter<SomeObject>, #ObjectifiedSetter._value
// CHECK: assign_by_wrapper [[OBJ]] : $SomeObject to [[STORAGE]] : $*WrapGod<SomeObject>
Expand Down

0 comments on commit 0842b42

Please sign in to comment.