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