@@ -2156,12 +2156,25 @@ namespace {
21562156 if (value.getType ().isAddress () ||
21572157 !isReadAccessResultAddress (getAccessKind ()))
21582158 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+ }
21592170 }
21602171
21612172 // 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.
21622175 // 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 ()));
21652178 auto yieldsAsArray = llvm::makeArrayRef (yields);
21662179 copyBorrowedYieldsIntoTemporary (SGF, loc, yieldsAsArray,
21672180 getOrigFormalType (), getSubstFormalType (),
@@ -2882,6 +2895,118 @@ static ManagedValue visitRecNonInOutBase(SILGenLValue &SGL, Expr *e,
28822895 value);
28832896}
28842897
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+
28853010LValue SILGenLValue::visitRec (Expr *e, SGFAccessKind accessKind,
28863011 LValueOptions options, AbstractionPattern orig) {
28873012 // 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,
28943019 // a `borrow x` operator, the operator is used on the base here), we want to
28953020 // apply the lvalue within a formal access to the original value instead of
28963021 // 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);
29083028 }
2909-
3029+
29103030 // Otherwise we have a non-lvalue type (references, values, metatypes,
29113031 // etc). These act as the root of a logical lvalue. Compute the root value,
29123032 // wrap it in a ValueComponent, and return it for our caller.
@@ -3559,10 +3679,6 @@ static SGFAccessKind getBaseAccessKind(SILGenModule &SGM,
35593679 llvm_unreachable (" bad access strategy" );
35603680}
35613681
3562- static CanType getBaseFormalType (Expr *baseExpr) {
3563- return baseExpr->getType ()->getWithoutSpecifierType ()->getCanonicalType ();
3564- }
3565-
35663682bool isCallToReplacedInDynamicReplacement (SILGenFunction &SGF,
35673683 AbstractFunctionDecl *afd,
35683684 bool &isObjCReplacementSelfCall);
0 commit comments