@@ -2156,12 +2156,25 @@ namespace {
2156
2156
if (value.getType ().isAddress () ||
2157
2157
!isReadAccessResultAddress (getAccessKind ()))
2158
2158
return value;
2159
+
2160
+ // If we have a guaranteed object and our read access result requires an
2161
+ // address, store it using a store_borrow.
2162
+ if (value.getType ().isObject () &&
2163
+ value.getOwnershipKind () == OwnershipKind::Guaranteed) {
2164
+ SILValue alloc = SGF.emitTemporaryAllocation (loc, getTypeOfRValue ());
2165
+ if (alloc->getType ().isMoveOnly ())
2166
+ alloc = SGF.B .createMarkMustCheckInst (
2167
+ loc, alloc, MarkMustCheckInst::CheckKind::NoConsumeOrAssign);
2168
+ return SGF.B .createFormalAccessStoreBorrow (loc, value, alloc);
2169
+ }
2159
2170
}
2160
2171
2161
2172
// Otherwise, we need to make a temporary.
2173
+ // TODO: This needs to be changed to use actual store_borrows. Noncopyable
2174
+ // types do not support tuples today, so we can avoid this for now.
2162
2175
// TODO: build a scalar tuple if possible.
2163
- auto temporary =
2164
- SGF. emitTemporary ( loc, SGF.getTypeLowering (getTypeOfRValue ()));
2176
+ auto temporary = SGF. emitFormalAccessTemporary (
2177
+ loc, SGF.getTypeLowering (getTypeOfRValue ()));
2165
2178
auto yieldsAsArray = llvm::makeArrayRef (yields);
2166
2179
copyBorrowedYieldsIntoTemporary (SGF, loc, yieldsAsArray,
2167
2180
getOrigFormalType (), getSubstFormalType (),
@@ -2882,6 +2895,118 @@ static ManagedValue visitRecNonInOutBase(SILGenLValue &SGL, Expr *e,
2882
2895
value);
2883
2896
}
2884
2897
2898
+ static CanType getBaseFormalType (Expr *baseExpr) {
2899
+ return baseExpr->getType ()->getWithoutSpecifierType ()->getCanonicalType ();
2900
+ }
2901
+
2902
+ class LLVM_LIBRARY_VISIBILITY SILGenBorrowedBaseVisitor
2903
+ : public Lowering::ExprVisitor<SILGenBorrowedBaseVisitor, LValue,
2904
+ SGFAccessKind, LValueOptions> {
2905
+ public:
2906
+ SILGenLValue &SGL;
2907
+ SILGenFunction &SGF;
2908
+
2909
+ SILGenBorrowedBaseVisitor (SILGenLValue &SGL, SILGenFunction &SGF)
2910
+ : SGL(SGL), SGF(SGF) {}
2911
+
2912
+ // / Returns the subexpr
2913
+ static bool isNonCopyableBaseBorrow (SILGenFunction &SGF, Expr *e) {
2914
+ if (auto *le = dyn_cast<LoadExpr>(e))
2915
+ return le->getType ()->isPureMoveOnly ();
2916
+ if (auto *m = dyn_cast<MemberRefExpr>(e)) {
2917
+ // If our m is a pure noncopyable type or our base is, we need to perform
2918
+ // a noncopyable base borrow.
2919
+ //
2920
+ // DISCUSSION: We can have a noncopyable member_ref_expr with a copyable
2921
+ // base if the noncopyable member_ref_expr is from a computed method. In
2922
+ // such a case, we want to ensure that we wrap things the right way.
2923
+ return m->getType ()->isPureMoveOnly () ||
2924
+ m->getBase ()->getType ()->isPureMoveOnly ();
2925
+ }
2926
+ if (auto *d = dyn_cast<DeclRefExpr>(e))
2927
+ return e->getType ()->isPureMoveOnly ();
2928
+ return false ;
2929
+ }
2930
+
2931
+ LValue visitExpr (Expr *e, SGFAccessKind accessKind, LValueOptions options) {
2932
+ e->dump (llvm::errs ());
2933
+ llvm::report_fatal_error (" Unimplemented node!" );
2934
+ }
2935
+
2936
+ LValue visitMemberRefExpr (MemberRefExpr *e, SGFAccessKind accessKind,
2937
+ LValueOptions options) {
2938
+ // If we have a member_ref_expr, we create a component that will when we
2939
+ // evaluate the lvalue,
2940
+ VarDecl *var = cast<VarDecl>(e->getMember ().getDecl ());
2941
+
2942
+ assert (!e->getType ()->is <LValueType>());
2943
+
2944
+ auto accessSemantics = e->getAccessSemantics ();
2945
+ AccessStrategy strategy = var->getAccessStrategy (
2946
+ accessSemantics, getFormalAccessKind (accessKind),
2947
+ SGF.SGM .M .getSwiftModule (), SGF.F .getResilienceExpansion ());
2948
+
2949
+ auto baseFormalType = getBaseFormalType (e->getBase ());
2950
+ LValue lv = visit (
2951
+ e->getBase (),
2952
+ getBaseAccessKind (SGF.SGM , var, accessKind, strategy, baseFormalType),
2953
+ getBaseOptions (options, strategy));
2954
+ llvm::Optional<ActorIsolation> actorIso;
2955
+ if (e->isImplicitlyAsync ())
2956
+ actorIso = getActorIsolation (var);
2957
+ lv.addMemberVarComponent (SGF, e, var, e->getMember ().getSubstitutions (),
2958
+ options, e->isSuper (), accessKind, strategy,
2959
+ getSubstFormalRValueType (e),
2960
+ false /* is on self parameter*/ , actorIso);
2961
+ return lv;
2962
+ }
2963
+
2964
+ ManagedValue emitImmediateBaseValue (Expr *e) {
2965
+ // We are going to immediately use this base value, so we want to borrow it.
2966
+ ManagedValue mv =
2967
+ SGF.emitRValueAsSingleValue (e, SGFContext::AllowImmediatePlusZero);
2968
+ if (mv.isPlusZeroRValueOrTrivial ())
2969
+ return mv;
2970
+
2971
+ // Any temporaries needed to materialize the lvalue must be destroyed when
2972
+ // at the end of the lvalue's formal evaluation scope.
2973
+ // e.g. for foo(self.bar)
2974
+ // %self = load [copy] %ptr_self
2975
+ // %rvalue = barGetter(%self)
2976
+ // destroy_value %self // self must be released before calling foo.
2977
+ // foo(%rvalue)
2978
+ SILValue value = mv.forward (SGF);
2979
+ return SGF.emitFormalAccessManagedRValueWithCleanup (CleanupLocation (e),
2980
+ value);
2981
+ }
2982
+
2983
+ LValue visitDeclRefExpr (DeclRefExpr *e, SGFAccessKind accessKind,
2984
+ LValueOptions options) {
2985
+ if (accessKind == SGFAccessKind::BorrowedObjectRead) {
2986
+ auto rv = emitImmediateBaseValue (e);
2987
+ CanType formalType = getSubstFormalRValueType (e);
2988
+ auto typeData = getValueTypeData (accessKind, formalType, rv.getValue ());
2989
+ LValue lv;
2990
+ lv.add <ValueComponent>(rv, llvm::None, typeData, /* isRValue=*/ true );
2991
+ return lv;
2992
+ }
2993
+
2994
+ return SGL.visitDeclRefExpr (e, accessKind, options);
2995
+ }
2996
+
2997
+ LValue visitLoadExpr (LoadExpr *e, SGFAccessKind accessKind,
2998
+ LValueOptions options) {
2999
+ // TODO: orig abstraction pattern.
3000
+ LValue lv = SGL.visitRec (e->getSubExpr (),
3001
+ SGFAccessKind::BorrowedAddressRead, options);
3002
+ CanType formalType = getSubstFormalRValueType (e);
3003
+ LValueTypeData typeData{accessKind, AbstractionPattern (formalType),
3004
+ formalType, lv.getTypeOfRValue ().getASTType ()};
3005
+ lv.add <BorrowValueComponent>(typeData);
3006
+ return lv;
3007
+ }
3008
+ };
3009
+
2885
3010
LValue SILGenLValue::visitRec (Expr *e, SGFAccessKind accessKind,
2886
3011
LValueOptions options, AbstractionPattern orig) {
2887
3012
// First see if we have an lvalue type. If we do, then quickly handle that and
@@ -2894,19 +3019,14 @@ LValue SILGenLValue::visitRec(Expr *e, SGFAccessKind accessKind,
2894
3019
// a `borrow x` operator, the operator is used on the base here), we want to
2895
3020
// apply the lvalue within a formal access to the original value instead of
2896
3021
// an actual loaded copy.
2897
-
2898
- if (e->getType ()->isPureMoveOnly ()) {
2899
- if (auto load = dyn_cast<LoadExpr>(e)) {
2900
- LValue lv = visitRec (load->getSubExpr (), SGFAccessKind::BorrowedAddressRead,
2901
- options, orig);
2902
- CanType formalType = getSubstFormalRValueType (e);
2903
- LValueTypeData typeData{accessKind, AbstractionPattern (formalType),
2904
- formalType, lv.getTypeOfRValue ().getASTType ()};
2905
- lv.add <BorrowValueComponent>(typeData);
2906
- return lv;
2907
- }
3022
+ if (SILGenBorrowedBaseVisitor::isNonCopyableBaseBorrow (SGF, e)) {
3023
+ SILGenBorrowedBaseVisitor visitor (*this , SGF);
3024
+ auto accessKind = SGFAccessKind::BorrowedObjectRead;
3025
+ if (e->getType ()->is <LValueType>())
3026
+ accessKind = SGFAccessKind::BorrowedAddressRead;
3027
+ return visitor.visit (e, accessKind, options);
2908
3028
}
2909
-
3029
+
2910
3030
// Otherwise we have a non-lvalue type (references, values, metatypes,
2911
3031
// etc). These act as the root of a logical lvalue. Compute the root value,
2912
3032
// wrap it in a ValueComponent, and return it for our caller.
@@ -3559,10 +3679,6 @@ static SGFAccessKind getBaseAccessKind(SILGenModule &SGM,
3559
3679
llvm_unreachable (" bad access strategy" );
3560
3680
}
3561
3681
3562
- static CanType getBaseFormalType (Expr *baseExpr) {
3563
- return baseExpr->getType ()->getWithoutSpecifierType ()->getCanonicalType ();
3564
- }
3565
-
3566
3682
bool isCallToReplacedInDynamicReplacement (SILGenFunction &SGF,
3567
3683
AbstractFunctionDecl *afd,
3568
3684
bool &isObjCReplacementSelfCall);
0 commit comments