@@ -3540,27 +3540,198 @@ Expr *ArgumentSource::findStorageReferenceExprForBorrow() && {
35403540ManagedValue
35413541SILGenFunction::tryEmitAddressableParameterAsAddress (ArgumentSource &&arg,
35423542 ValueOwnership ownership) {
3543+ if (!arg.isExpr ()) {
3544+ return ManagedValue ();
3545+ }
3546+
35433547 // If the function takes an addressable parameter, and its argument is
35443548 // a reference to an addressable declaration with compatible ownership,
35453549 // forward the address along in-place.
3546- if (arg.isExpr ()) {
3547- auto origExpr = std::move (arg).asKnownExpr ();
3548- auto expr = origExpr;
3550+ auto origExpr = std::move (arg).asKnownExpr ();
3551+ auto expr = origExpr;
3552+
3553+ // If the expression does not have a stable address to return, then restore
3554+ // the ArgumentSource and return a null value to the caller.
3555+ auto notAddressable = [&] {
3556+ arg = ArgumentSource (origExpr);
3557+ return ManagedValue ();
3558+ };
3559+
3560+ if (auto le = dyn_cast<LoadExpr>(expr)) {
3561+ expr = le->getSubExpr ();
3562+ }
3563+ if (auto dre = dyn_cast<DeclRefExpr>(expr)) {
3564+ if (auto param = dyn_cast<VarDecl>(dre->getDecl ())) {
3565+ if (auto addr = getLocalVariableAddressableBuffer (param, expr,
3566+ ownership)) {
3567+ return ManagedValue::forBorrowedAddressRValue (addr);
3568+ }
3569+ }
3570+ }
3571+
3572+ // Property or subscript member accesses may also be addressable.
3573+
3574+ AccessKind accessKind;
3575+ switch (ownership) {
3576+ case ValueOwnership::Shared:
3577+ case ValueOwnership::Default:
3578+ accessKind = AccessKind::Read;
3579+ break ;
3580+ case ValueOwnership::Owned:
3581+ case ValueOwnership::InOut:
3582+ accessKind = AccessKind::ReadWrite;
3583+ break ;
3584+ }
3585+
3586+ LookupExpr *lookupExpr;
3587+ AbstractStorageDecl *memberStorage;
3588+ SubstitutionMap subs;
3589+ AccessSemantics accessSemantics;
3590+ PreparedArguments indices;
3591+
3592+ if (auto mre = dyn_cast<MemberRefExpr>(expr)) {
3593+ lookupExpr = mre;
3594+ memberStorage = dyn_cast<VarDecl>(mre->getMember ().getDecl ());
3595+ subs = mre->getMember ().getSubstitutions ();
3596+ accessSemantics = mre->getAccessSemantics ();
3597+ } else if (auto se = dyn_cast<SubscriptExpr>(expr)) {
3598+ lookupExpr = se;
3599+ auto subscriptDecl = cast<SubscriptDecl>(se->getMember ().getDecl ());
3600+ memberStorage = subscriptDecl;
3601+ subs = se->getMember ().getSubstitutions ();
3602+ accessSemantics = se->getAccessSemantics ();
35493603
3550- if (auto le = dyn_cast<LoadExpr>(expr)) {
3551- expr = le->getSubExpr ();
3552- }
3553- if (auto dre = dyn_cast<DeclRefExpr>(expr)) {
3554- if (auto param = dyn_cast<VarDecl>(dre->getDecl ())) {
3555- if (auto addr = getLocalVariableAddressableBuffer (param, expr,
3556- ownership)) {
3557- return ManagedValue::forBorrowedAddressRValue (addr);
3558- }
3604+ indices = PreparedArguments (
3605+ subscriptDecl->getInterfaceType ()->castTo <AnyFunctionType>()
3606+ ->getParams (),
3607+ se->getArgs ());
3608+ } else {
3609+ return notAddressable ();
3610+ }
3611+
3612+ if (!memberStorage) {
3613+ return notAddressable ();
3614+ }
3615+
3616+ auto strategy = memberStorage->getAccessStrategy (accessSemantics, accessKind,
3617+ SGM.M .getSwiftModule (), F.getResilienceExpansion (),
3618+ std::make_pair<>(expr->getSourceRange (), FunctionDC),
3619+ /* old abi (doesn't matter here)*/ false );
3620+
3621+ switch (strategy.getKind ()) {
3622+ case AccessStrategy::Storage: {
3623+ auto vd = cast<VarDecl>(memberStorage);
3624+ // TODO: Is it possible and/or useful for class storage to be
3625+ // addressable?
3626+ if (!vd->getDeclContext ()->getInnermostTypeContext ()
3627+ ->getDeclaredTypeInContext ()->getStructOrBoundGenericStruct ()) {
3628+ return notAddressable ();
3629+ }
3630+
3631+ // If the storage holds the fully-abstracted representation of the
3632+ // type, then we can use its address.
3633+ auto absBaseTy = getLoweredType (AbstractionPattern::getOpaque (),
3634+ lookupExpr->getBase ()->getType ()->getWithoutSpecifierType ());
3635+ auto memberTy = absBaseTy.getFieldType (vd, &F);
3636+ auto absMemberTy = getLoweredType (AbstractionPattern::getOpaque (),
3637+ lookupExpr->getType ()->getWithoutSpecifierType ());
3638+
3639+ if (memberTy.getAddressType () != absMemberTy.getAddressType ()) {
3640+ // The storage is not fully abstracted, so it can't serve as a
3641+ // stable address.
3642+ return notAddressable ();
3643+ }
3644+
3645+ // Otherwise, we can project the field address from the stable address
3646+ // of the base, if it has one. Try to get the stable address for the
3647+ // base.
3648+ auto baseAddr = tryEmitAddressableParameterAsAddress (
3649+ ArgumentSource (lookupExpr->getBase ()), ownership);
3650+
3651+ if (!baseAddr) {
3652+ return notAddressable ();
3653+ }
3654+
3655+ // Project the field's address.
3656+ auto fieldAddr = B.createStructElementAddr (lookupExpr,
3657+ baseAddr.getValue (), vd);
3658+ return ManagedValue::forBorrowedAddressRValue (fieldAddr);
3659+ }
3660+
3661+ case AccessStrategy::DirectToAccessor:
3662+ case AccessStrategy::DispatchToAccessor: {
3663+ // Non-addressor accessors don't produce stable addresses.
3664+ if (strategy.getAccessor () != AccessorKind::Address
3665+ && strategy.getAccessor () != AccessorKind::MutableAddress) {
3666+ return notAddressable ();
3667+ }
3668+ // TODO: Non-yielding borrow/mutate accessors can also be considered
3669+ // addressable when we have those.
3670+
3671+ auto addressor = memberStorage->getAccessor (strategy.getAccessor ());
3672+ auto addressorRef = SILDeclRef (addressor, SILDeclRef::Kind::Func);
3673+ auto absMemberTy = getLoweredType (AbstractionPattern::getOpaque (),
3674+ lookupExpr->getType ()->getWithoutSpecifierType ())
3675+ .getAddressType ();
3676+
3677+ // Evaluate the base in the current formal access scope.
3678+ ManagedValue base;
3679+ // If the addressor wants the base addressable, try to honor that
3680+ // request.
3681+ auto addressorSelf = addressor->getImplicitSelfDecl ();
3682+ if (addressorSelf->isAddressable ()
3683+ || getTypeLowering (lookupExpr->getBase ()->getType ()
3684+ ->getWithoutSpecifierType ())
3685+ .getRecursiveProperties ().isAddressableForDependencies ()) {
3686+ ValueOwnership baseOwnership = addressorSelf->isInOut ()
3687+ ? ValueOwnership::InOut
3688+ : ValueOwnership::Shared;
3689+
3690+ base = tryEmitAddressableParameterAsAddress (
3691+ ArgumentSource (lookupExpr->getBase ()), baseOwnership);
3692+ }
3693+
3694+ // Otherwise, project the base as an lvalue.
3695+ if (!base) {
3696+ SGFAccessKind silAccess;
3697+ switch (accessKind) {
3698+ case AccessKind::Read:
3699+ silAccess = SGFAccessKind::BorrowedAddressRead;
3700+ break ;
3701+ case AccessKind::ReadWrite:
3702+ case AccessKind::Write:
3703+ silAccess = SGFAccessKind::ReadWrite;
3704+ break ;
35593705 }
3706+
3707+ LValue lv = emitLValue (lookupExpr, silAccess);
3708+
3709+ drillToLastComponent (lookupExpr->getBase (), std::move (lv), base);
35603710 }
3561- arg = ArgumentSource (origExpr);
3711+
3712+ // Materialize the base outside of the scope of the addressor call,
3713+ // since the returned address may depend on the materialized
3714+ // representation, even if it isn't transitively addressable.
3715+ auto baseTy = lookupExpr->getBase ()->getType ()->getCanonicalType ();
3716+ ArgumentSource baseArg = prepareAccessorBaseArgForFormalAccess (
3717+ lookupExpr->getBase (), base, baseTy, addressorRef);
3718+
3719+ // Invoke the addressor to directly produce the address.
3720+ return emitAddressorAccessor (lookupExpr,
3721+ addressorRef, subs,
3722+ std::move (baseArg),
3723+ /* super*/ false , /* direct accessor use*/ true ,
3724+ std::move (indices),
3725+ absMemberTy, /* on self*/ false );
35623726 }
3563- return ManagedValue ();
3727+
3728+ case AccessStrategy::MaterializeToTemporary:
3729+ case AccessStrategy::DispatchToDistributedThunk:
3730+ // These strategies never produce a value with a stable address.
3731+ return notAddressable ();
3732+ }
3733+
3734+ llvm_unreachable (" uncovered switch!" );
35643735}
35653736
35663737namespace {
@@ -7285,6 +7456,34 @@ ArgumentSource AccessorBaseArgPreparer::prepare() {
72857456 return prepareAccessorObjectBaseArg ();
72867457}
72877458
7459+ ArgumentSource SILGenFunction::prepareAccessorBaseArgForFormalAccess (
7460+ SILLocation loc,
7461+ ManagedValue base,
7462+ CanType baseFormalType,
7463+ SILDeclRef accessor) {
7464+ if (!base) {
7465+ return ArgumentSource ();
7466+ }
7467+
7468+ base = base.formalAccessBorrow (*this , loc);
7469+ // If the base needs to be materialized, do so in
7470+ // the outer formal evaluation scope, since an addressor or
7471+ // other dependent value may want to point into the materialization.
7472+ auto &baseInfo = getConstantInfo (getTypeExpansionContext (), accessor);
7473+
7474+ if (!baseInfo.FormalPattern .isForeign ()) {
7475+ auto baseFnTy = baseInfo.SILFnType ;
7476+
7477+ if (baseFnTy->getSelfParameter ().isFormalIndirect ()
7478+ && base.getType ().isObject ()
7479+ && silConv.useLoweredAddresses ()) {
7480+ base = base.formallyMaterialize (*this , loc);
7481+ }
7482+ }
7483+
7484+ return prepareAccessorBaseArg (loc, base, baseFormalType, accessor);
7485+ }
7486+
72887487ArgumentSource SILGenFunction::prepareAccessorBaseArg (SILLocation loc,
72897488 ManagedValue base,
72907489 CanType baseFormalType,
@@ -7604,10 +7803,7 @@ ManagedValue SILGenFunction::emitAddressorAccessor(
76047803
76057804 emission.addCallSite (loc, std::move (subscriptIndices));
76067805
7607- // Unsafe{Mutable}Pointer<T> or
7608- // (Unsafe{Mutable}Pointer<T>, Builtin.UnknownPointer) or
7609- // (Unsafe{Mutable}Pointer<T>, Builtin.NativePointer) or
7610- // (Unsafe{Mutable}Pointer<T>, Builtin.NativePointer?) or
7806+ // Result must be Unsafe{Mutable}Pointer<T>
76117807 SmallVector<ManagedValue, 2 > results;
76127808 emission.apply ().getAll (results);
76137809
0 commit comments