@@ -2877,6 +2877,116 @@ static ManagedValue visitRecNonInOutBase(SILGenLValue &SGL, Expr *e,
2877
2877
value);
2878
2878
}
2879
2879
2880
+ static CanType getBaseFormalType (Expr *baseExpr) {
2881
+ return baseExpr->getType ()->getWithoutSpecifierType ()->getCanonicalType ();
2882
+ }
2883
+
2884
+ class LLVM_LIBRARY_VISIBILITY SILGenBorrowedBaseVisitor
2885
+ : public Lowering::ExprVisitor<SILGenBorrowedBaseVisitor, LValue,
2886
+ SGFAccessKind, LValueOptions> {
2887
+ public:
2888
+ SILGenLValue &SGL;
2889
+ SILGenFunction &SGF;
2890
+
2891
+ SILGenBorrowedBaseVisitor (SILGenLValue &SGL, SILGenFunction &SGF)
2892
+ : SGL(SGL), SGF(SGF) {}
2893
+
2894
+ // / Returns the subexpr
2895
+ static bool isNonCopyableBaseBorrow (SILGenFunction &SGF, Expr *e) {
2896
+ if (auto *le = dyn_cast<LoadExpr>(e))
2897
+ return le->getType ()->isPureMoveOnly ();
2898
+ if (auto *m = dyn_cast<MemberRefExpr>(e)) {
2899
+ // If our m is a pure noncopyable type or our base is, we need to perform
2900
+ // a noncopyable base borrow.
2901
+ //
2902
+ // DISCUSSION: We can have a noncopyable member_ref_expr with a copyable
2903
+ // base if the noncopyable member_ref_expr is from a computed method. In
2904
+ // such a case, we want to ensure that we wrap things the right way.
2905
+ return m->getType ()->isPureMoveOnly () ||
2906
+ m->getBase ()->getType ()->isPureMoveOnly ();
2907
+ }
2908
+ return false ;
2909
+ }
2910
+
2911
+ LValue visitExpr (Expr *e, SGFAccessKind accessKind, LValueOptions options) {
2912
+ e->dump (llvm::errs ());
2913
+ llvm::report_fatal_error (" Unimplemented node!" );
2914
+ }
2915
+
2916
+ LValue visitMemberRefExpr (MemberRefExpr *e, SGFAccessKind accessKind,
2917
+ LValueOptions options) {
2918
+ // If we have a member_ref_expr, we create a component that will when we
2919
+ // evaluate the lvalue,
2920
+ VarDecl *var = cast<VarDecl>(e->getMember ().getDecl ());
2921
+
2922
+ assert (!e->getType ()->is <LValueType>());
2923
+
2924
+ auto accessSemantics = e->getAccessSemantics ();
2925
+ AccessStrategy strategy = var->getAccessStrategy (
2926
+ accessSemantics, getFormalAccessKind (accessKind),
2927
+ SGF.SGM .M .getSwiftModule (), SGF.F .getResilienceExpansion ());
2928
+
2929
+ auto baseFormalType = getBaseFormalType (e->getBase ());
2930
+ LValue lv = visit (
2931
+ e->getBase (),
2932
+ getBaseAccessKind (SGF.SGM , var, accessKind, strategy, baseFormalType),
2933
+ getBaseOptions (options, strategy));
2934
+ llvm::Optional<ActorIsolation> actorIso;
2935
+ if (e->isImplicitlyAsync ())
2936
+ actorIso = getActorIsolation (var);
2937
+ lv.addMemberVarComponent (SGF, e, var, e->getMember ().getSubstitutions (),
2938
+ options, e->isSuper (), accessKind, strategy,
2939
+ getSubstFormalRValueType (e),
2940
+ false /* is on self parameter*/ , actorIso);
2941
+ return lv;
2942
+ }
2943
+
2944
+ ManagedValue emitImmediateBaseValue (Expr *e) {
2945
+ // We are going to immediately use this base value, so we want to borrow it.
2946
+ ManagedValue mv =
2947
+ SGF.emitRValueAsSingleValue (e, SGFContext::AllowImmediatePlusZero);
2948
+ if (mv.isPlusZeroRValueOrTrivial ())
2949
+ return mv;
2950
+
2951
+ // Any temporaries needed to materialize the lvalue must be destroyed when
2952
+ // at the end of the lvalue's formal evaluation scope.
2953
+ // e.g. for foo(self.bar)
2954
+ // %self = load [copy] %ptr_self
2955
+ // %rvalue = barGetter(%self)
2956
+ // destroy_value %self // self must be released before calling foo.
2957
+ // foo(%rvalue)
2958
+ SILValue value = mv.forward (SGF);
2959
+ return SGF.emitFormalAccessManagedRValueWithCleanup (CleanupLocation (e),
2960
+ value);
2961
+ }
2962
+
2963
+ LValue visitDeclRefExpr (DeclRefExpr *e, SGFAccessKind accessKind,
2964
+ LValueOptions options) {
2965
+ if (accessKind == SGFAccessKind::BorrowedObjectRead) {
2966
+ auto rv = emitImmediateBaseValue (e);
2967
+ CanType formalType = getSubstFormalRValueType (e);
2968
+ auto typeData = getValueTypeData (accessKind, formalType, rv.getValue ());
2969
+ LValue lv;
2970
+ lv.add <ValueComponent>(rv, llvm::None, typeData, /* isRValue=*/ true );
2971
+ return lv;
2972
+ }
2973
+
2974
+ return SGL.visitDeclRefExpr (e, accessKind, options);
2975
+ }
2976
+
2977
+ LValue visitLoadExpr (LoadExpr *e, SGFAccessKind accessKind,
2978
+ LValueOptions options) {
2979
+ // TODO: orig abstraction pattern.
2980
+ LValue lv = SGL.visitRec (e->getSubExpr (),
2981
+ SGFAccessKind::BorrowedAddressRead, options);
2982
+ CanType formalType = getSubstFormalRValueType (e);
2983
+ LValueTypeData typeData{accessKind, AbstractionPattern (formalType),
2984
+ formalType, lv.getTypeOfRValue ().getASTType ()};
2985
+ lv.add <BorrowValueComponent>(typeData);
2986
+ return lv;
2987
+ }
2988
+ };
2989
+
2880
2990
LValue SILGenLValue::visitRec (Expr *e, SGFAccessKind accessKind,
2881
2991
LValueOptions options, AbstractionPattern orig) {
2882
2992
// First see if we have an lvalue type. If we do, then quickly handle that and
@@ -2889,19 +2999,14 @@ LValue SILGenLValue::visitRec(Expr *e, SGFAccessKind accessKind,
2889
2999
// a `borrow x` operator, the operator is used on the base here), we want to
2890
3000
// apply the lvalue within a formal access to the original value instead of
2891
3001
// an actual loaded copy.
2892
-
2893
- if (e->getType ()->isPureMoveOnly ()) {
2894
- if (auto load = dyn_cast<LoadExpr>(e)) {
2895
- LValue lv = visitRec (load->getSubExpr (), SGFAccessKind::BorrowedAddressRead,
2896
- options, orig);
2897
- CanType formalType = getSubstFormalRValueType (e);
2898
- LValueTypeData typeData{accessKind, AbstractionPattern (formalType),
2899
- formalType, lv.getTypeOfRValue ().getASTType ()};
2900
- lv.add <BorrowValueComponent>(typeData);
2901
- return lv;
2902
- }
3002
+ if (SILGenBorrowedBaseVisitor::isNonCopyableBaseBorrow (SGF, e)) {
3003
+ SILGenBorrowedBaseVisitor visitor (*this , SGF);
3004
+ auto accessKind = SGFAccessKind::BorrowedObjectRead;
3005
+ if (e->getType ()->is <LValueType>())
3006
+ accessKind = SGFAccessKind::BorrowedAddressRead;
3007
+ return visitor.visit (e, accessKind, options);
2903
3008
}
2904
-
3009
+
2905
3010
// Otherwise we have a non-lvalue type (references, values, metatypes,
2906
3011
// etc). These act as the root of a logical lvalue. Compute the root value,
2907
3012
// wrap it in a ValueComponent, and return it for our caller.
@@ -3554,10 +3659,6 @@ static SGFAccessKind getBaseAccessKind(SILGenModule &SGM,
3554
3659
llvm_unreachable (" bad access strategy" );
3555
3660
}
3556
3661
3557
- static CanType getBaseFormalType (Expr *baseExpr) {
3558
- return baseExpr->getType ()->getWithoutSpecifierType ()->getCanonicalType ();
3559
- }
3560
-
3561
3662
bool isCallToReplacedInDynamicReplacement (SILGenFunction &SGF,
3562
3663
AbstractFunctionDecl *afd,
3563
3664
bool &isObjCReplacementSelfCall);
0 commit comments