@@ -1338,7 +1338,8 @@ static SGFAccessKind getBaseAccessKind(SILGenModule &SGM,
1338
1338
AbstractStorageDecl *member,
1339
1339
SGFAccessKind accessKind,
1340
1340
AccessStrategy strategy,
1341
- CanType baseFormalType);
1341
+ CanType baseFormalType,
1342
+ bool forBorrowExpr);
1342
1343
1343
1344
namespace {
1344
1345
// / A helper class for implementing components that involve accessing
@@ -1977,7 +1978,8 @@ namespace {
1977
1978
if (!base) return LValue ();
1978
1979
auto baseAccessKind =
1979
1980
getBaseAccessKind (SGF.SGM , Storage, accessKind, strategy,
1980
- BaseFormalType);
1981
+ BaseFormalType,
1982
+ /* for borrow*/ false );
1981
1983
return LValue::forValue (baseAccessKind, base, BaseFormalType);
1982
1984
}();
1983
1985
@@ -3055,7 +3057,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenBorrowedBaseVisitor
3055
3057
auto baseFormalType = getBaseFormalType (e->getBase ());
3056
3058
LValue lv = visit (
3057
3059
e->getBase (),
3058
- getBaseAccessKind (SGF.SGM , var, accessKind, strategy, baseFormalType),
3060
+ getBaseAccessKind (SGF.SGM , var, accessKind, strategy, baseFormalType,
3061
+ /* for borrow*/ true ),
3059
3062
getBaseOptions (options, strategy));
3060
3063
llvm::Optional<ActorIsolation> actorIso;
3061
3064
if (e->isImplicitlyAsync ())
@@ -3724,14 +3727,50 @@ LValue SILGenLValue::visitDotSyntaxBaseIgnoredExpr(DotSyntaxBaseIgnoredExpr *e,
3724
3727
return visitRec (e->getRHS (), accessKind, options);
3725
3728
}
3726
3729
3730
+ // / Should the self argument of the given method always be emitted as
3731
+ // / an r-value (meaning that it can be borrowed only if that is not
3732
+ // / semantically detectable), or it acceptable to emit it as a borrowed
3733
+ // / storage reference?
3734
+ static bool shouldEmitSelfAsRValue (AccessorDecl *fn, CanType selfType,
3735
+ bool forBorrowExpr) {
3736
+ if (fn->isStatic ())
3737
+ return true ;
3738
+
3739
+ switch (fn->getSelfAccessKind ()) {
3740
+ case SelfAccessKind::Mutating:
3741
+ return false ;
3742
+ case SelfAccessKind::Borrowing:
3743
+ case SelfAccessKind::NonMutating:
3744
+ // If the accessor is a coroutine, we may want to access the projected
3745
+ // value through a borrow of the base. But if it's a regular get/set then
3746
+ // there isn't any real benefit to doing so.
3747
+ if (!fn->isCoroutine ()) {
3748
+ return true ;
3749
+ }
3750
+ // Normally we'll copy the base to minimize accesses. But if the base
3751
+ // is noncopyable, or we're accessing it in a `borrow` expression, then
3752
+ // we want to keep the access nested on the original base.
3753
+ if (forBorrowExpr || selfType->isNoncopyable ()) {
3754
+ return false ;
3755
+ }
3756
+ return true ;
3757
+
3758
+ case SelfAccessKind::LegacyConsuming:
3759
+ case SelfAccessKind::Consuming:
3760
+ return true ;
3761
+ }
3762
+ llvm_unreachable (" bad self-access kind" );
3763
+ }
3764
+
3727
3765
static SGFAccessKind getBaseAccessKindForAccessor (SILGenModule &SGM,
3728
3766
AccessorDecl *accessor,
3729
- CanType baseFormalType) {
3767
+ CanType baseFormalType,
3768
+ bool forBorrowExpr) {
3730
3769
if (accessor->isMutating ())
3731
3770
return SGFAccessKind::ReadWrite;
3732
3771
3733
3772
auto declRef = SGM.getAccessorDeclRef (accessor, ResilienceExpansion::Minimal);
3734
- if (SGM. shouldEmitSelfAsRValue (accessor, baseFormalType)) {
3773
+ if (shouldEmitSelfAsRValue (accessor, baseFormalType, forBorrowExpr )) {
3735
3774
return SGM.isNonMutatingSelfIndirect (declRef)
3736
3775
? SGFAccessKind::OwnedAddressRead
3737
3776
: SGFAccessKind::OwnedObjectRead;
@@ -3755,7 +3794,8 @@ static SGFAccessKind getBaseAccessKind(SILGenModule &SGM,
3755
3794
AbstractStorageDecl *member,
3756
3795
SGFAccessKind accessKind,
3757
3796
AccessStrategy strategy,
3758
- CanType baseFormalType) {
3797
+ CanType baseFormalType,
3798
+ bool forBorrowExpr) {
3759
3799
switch (strategy.getKind ()) {
3760
3800
case AccessStrategy::Storage:
3761
3801
return getBaseAccessKindForStorage (accessKind);
@@ -3764,7 +3804,8 @@ static SGFAccessKind getBaseAccessKind(SILGenModule &SGM,
3764
3804
assert (accessKind == SGFAccessKind::ReadWrite);
3765
3805
auto writeBaseKind = getBaseAccessKind (SGM, member, SGFAccessKind::Write,
3766
3806
strategy.getWriteStrategy (),
3767
- baseFormalType);
3807
+ baseFormalType,
3808
+ /* for borrow*/ false );
3768
3809
3769
3810
// Fast path for the common case that the write will need to mutate
3770
3811
// the base.
@@ -3774,7 +3815,8 @@ static SGFAccessKind getBaseAccessKind(SILGenModule &SGM,
3774
3815
auto readBaseKind = getBaseAccessKind (SGM, member,
3775
3816
SGFAccessKind::OwnedAddressRead,
3776
3817
strategy.getReadStrategy (),
3777
- baseFormalType);
3818
+ baseFormalType,
3819
+ /* for borrow*/ false );
3778
3820
3779
3821
// If they're the same kind, just use that.
3780
3822
if (readBaseKind == writeBaseKind)
@@ -3793,7 +3835,8 @@ static SGFAccessKind getBaseAccessKind(SILGenModule &SGM,
3793
3835
case AccessStrategy::DispatchToAccessor:
3794
3836
case AccessStrategy::DispatchToDistributedThunk: {
3795
3837
auto accessor = member->getOpaqueAccessor (strategy.getAccessor ());
3796
- return getBaseAccessKindForAccessor (SGM, accessor, baseFormalType);
3838
+ return getBaseAccessKindForAccessor (SGM, accessor, baseFormalType,
3839
+ forBorrowExpr);
3797
3840
}
3798
3841
}
3799
3842
llvm_unreachable (" bad access strategy" );
@@ -3870,7 +3913,8 @@ LValue SILGenLValue::visitMemberRefExpr(MemberRefExpr *e,
3870
3913
3871
3914
LValue lv = visitRec (e->getBase (),
3872
3915
getBaseAccessKind (SGF.SGM , var, accessKind, strategy,
3873
- getBaseFormalType (e->getBase ())),
3916
+ getBaseFormalType (e->getBase ()),
3917
+ /* for borrow */ false ),
3874
3918
getBaseOptions (options, strategy));
3875
3919
assert (lv.isValid ());
3876
3920
@@ -4075,7 +4119,8 @@ LValue SILGenLValue::visitSubscriptExpr(SubscriptExpr *e,
4075
4119
4076
4120
LValue lv = visitRec (e->getBase (),
4077
4121
getBaseAccessKind (SGF.SGM , decl, accessKind, strategy,
4078
- getBaseFormalType (e->getBase ())),
4122
+ getBaseFormalType (e->getBase ()),
4123
+ /* for borrow*/ false ),
4079
4124
getBaseOptions (options, strategy));
4080
4125
assert (lv.isValid ());
4081
4126
@@ -4432,7 +4477,8 @@ LValue SILGenFunction::emitPropertyLValue(SILLocation loc, ManagedValue base,
4432
4477
F.getResilienceExpansion ());
4433
4478
4434
4479
auto baseAccessKind =
4435
- getBaseAccessKind (SGM, ivar, accessKind, strategy, baseFormalType);
4480
+ getBaseAccessKind (SGM, ivar, accessKind, strategy, baseFormalType,
4481
+ /* for borrow*/ false );
4436
4482
4437
4483
LValueTypeData baseTypeData =
4438
4484
getValueTypeData (baseAccessKind, baseFormalType, base.getValue ());
@@ -5155,7 +5201,8 @@ RValue SILGenFunction::emitRValueForStorageLoad(
5155
5201
if (!base) return LValue ();
5156
5202
5157
5203
auto baseAccess = getBaseAccessKind (SGM, storage, accessKind,
5158
- strategy, baseFormalType);
5204
+ strategy, baseFormalType,
5205
+ /* for borrow*/ false );
5159
5206
return LValue::forValue (baseAccess, base, baseFormalType);
5160
5207
}();
5161
5208
0 commit comments