Skip to content

Commit ef52542

Browse files
authored
Merge pull request #59700 from xedin/distributed-computed-properties-via-accessor-thunk
[Distributed] Implement distributed computed properties via special accessor
2 parents f542ca9 + 2480c99 commit ef52542

30 files changed

+473
-116
lines changed

include/swift/AST/ASTMangler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ class ASTMangler : public Mangler {
197197
Type GlobalActorBound,
198198
ModuleDecl *Module);
199199

200-
std::string mangleDistributedThunk(const FuncDecl *thunk);
200+
std::string mangleDistributedThunk(const AbstractFunctionDecl *thunk);
201201

202202
/// Mangle a completion handler block implementation function, used for importing ObjC
203203
/// APIs as async.

include/swift/AST/Attr.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ SIMPLE_DECL_ATTR(_inheritActorContext, InheritActorContext,
664664
// 117 was 'spawn' and is now unused
665665

666666
CONTEXTUAL_SIMPLE_DECL_ATTR(distributed, DistributedActor,
667-
DeclModifier | OnClass | OnFunc | OnVar |
667+
DeclModifier | OnClass | OnFunc | OnAccessor | OnVar |
668668
ABIBreakingToAdd | ABIBreakingToRemove |
669669
APIBreakingToAdd | APIBreakingToRemove,
670670
118)

include/swift/AST/Decl.h

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
412412
SWIFT_INLINE_BITFIELD(SubscriptDecl, VarDecl, 2,
413413
StaticSpelling : 2
414414
);
415-
SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+2+8+1+1+1+1+1+1,
415+
SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+2+8+1+1+1+1+1+1+1,
416416
/// \see AbstractFunctionDecl::BodyKind
417417
BodyKind : 3,
418418

@@ -439,7 +439,11 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
439439

440440
/// Whether peeking into this function detected nested type declarations.
441441
/// This is set when skipping over the decl at parsing.
442-
HasNestedTypeDeclarations : 1
442+
HasNestedTypeDeclarations : 1,
443+
444+
/// Whether this function is a distributed thunk for a distributed
445+
/// function or computed property.
446+
DistributedThunk: 1
443447
);
444448

445449
SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl, 1+1+2+1+1+2+1,
@@ -5119,6 +5123,13 @@ class AbstractStorageDecl : public ValueDecl {
51195123

51205124
bool hasAnyNativeDynamicAccessors() const;
51215125

5126+
/// Does this have a 'distributed' modifier?
5127+
bool isDistributed() const;
5128+
5129+
/// Return a distributed thunk if this computed property is marked as
5130+
/// 'distributed' and and nullptr otherwise.
5131+
FuncDecl *getDistributedThunk() const;
5132+
51225133
// Implement isa/cast/dyncast/etc.
51235134
static bool classof(const Decl *D) {
51245135
return D->getKind() >= DeclKind::First_AbstractStorageDecl &&
@@ -5352,9 +5363,6 @@ class VarDecl : public AbstractStorageDecl {
53525363
/// Is this an "async let" property?
53535364
bool isAsyncLet() const;
53545365

5355-
/// Does this have a 'distributed' modifier?
5356-
bool isDistributed() const;
5357-
53585366
/// Is this var known to be a "local" distributed actor,
53595367
/// if so the implicit throwing ans some isolation checks can be skipped.
53605368
bool isKnownToBeLocal() const;
@@ -6331,6 +6339,7 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
63316339
Bits.AbstractFunctionDecl.Throws = Throws;
63326340
Bits.AbstractFunctionDecl.HasSingleExpressionBody = false;
63336341
Bits.AbstractFunctionDecl.HasNestedTypeDeclarations = false;
6342+
Bits.AbstractFunctionDecl.DistributedThunk = false;
63346343
}
63356344

63366345
void setBodyKind(BodyKind K) {
@@ -6429,6 +6438,16 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
64296438
/// Returns 'true' if the function is distributed.
64306439
bool isDistributed() const;
64316440

6441+
/// Is this a thunk function used to access a distributed method
6442+
/// or computed property outside of its actor isolation context?
6443+
bool isDistributedThunk() const {
6444+
return Bits.AbstractFunctionDecl.DistributedThunk;
6445+
}
6446+
6447+
void setDistributedThunk(bool isThunk) {
6448+
Bits.AbstractFunctionDecl.DistributedThunk = isThunk;
6449+
}
6450+
64326451
/// For a 'distributed' target (func or computed property),
64336452
/// get the 'thunk' responsible for performing the 'remoteCall'.
64346453
///

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4807,6 +4807,9 @@ ERROR(distributed_property_cannot_be_static,none,
48074807
ERROR(distributed_property_can_only_be_computed,none,
48084808
"%0 %1 cannot be 'distributed', only computed properties can",
48094809
(DescriptiveDeclKind, DeclName))
4810+
ERROR(distributed_property_accessor_only_get_can_be_distributed,none,
4811+
"only 'get' accessors may be 'distributed'",
4812+
())
48104813
NOTE(distributed_actor_isolated_property,none,
48114814
"access to %0 %1 is only permitted within distributed actor %2",
48124815
(DescriptiveDeclKind, DeclName, DeclName))

include/swift/AST/Expr.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,12 @@ enum class AccessSemantics : uint8_t {
124124
/// This is an ordinary access to a declaration, using whatever
125125
/// polymorphism is expected.
126126
Ordinary,
127+
128+
/// This is an access to the underlying storage through a distributed thunk.
129+
///
130+
/// The declaration must be a 'distributed' computed property used outside
131+
/// of its actor isolation context.
132+
DistributedThunk,
127133
};
128134

129135
/// Expr - Base class for all expressions in swift.
@@ -1684,6 +1690,14 @@ class MemberRefExpr : public LookupExpr {
16841690
return (AccessSemantics) Bits.MemberRefExpr.Semantics;
16851691
}
16861692

1693+
/// Informs IRGen to that this member should be applied via its distributed
1694+
/// thunk, rather than invoking it directly.
1695+
///
1696+
/// Only intended to be set on distributed get-only computed properties.
1697+
void setAccessViaDistributedThunk() {
1698+
Bits.MemberRefExpr.Semantics = (unsigned)AccessSemantics::DistributedThunk;
1699+
}
1700+
16871701
SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }
16881702
SourceLoc getStartLoc() const {
16891703
SourceLoc BaseStartLoc = getBase()->getStartLoc();

include/swift/AST/StorageImpl.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ class AccessStrategy {
110110
/// separately performing a Read into a temporary variable followed by
111111
/// a Write access back into the storage.
112112
MaterializeToTemporary,
113+
114+
/// The access is to a computed distributed property, and thus the
115+
/// get-accessor is a distributed thunk which may perform a remote call.
116+
DispatchToDistributedThunk,
113117
};
114118

115119
private:
@@ -149,6 +153,10 @@ class AccessStrategy {
149153
return { dispatched ? DispatchToAccessor : DirectToAccessor, accessor };
150154
}
151155

156+
static AccessStrategy getDistributedThunkDispatchStrategy() {
157+
return {DispatchToDistributedThunk, AccessorKind::Get};
158+
}
159+
152160
static AccessStrategy getMaterializeToTemporary(AccessStrategy read,
153161
AccessStrategy write) {
154162
return { read, write };
@@ -157,7 +165,8 @@ class AccessStrategy {
157165
Kind getKind() const { return TheKind; }
158166

159167
bool hasAccessor() const {
160-
return TheKind == DirectToAccessor || TheKind == DispatchToAccessor;
168+
return TheKind == DirectToAccessor || TheKind == DispatchToAccessor ||
169+
TheKind == DispatchToDistributedThunk;
161170
}
162171

163172
AccessorKind getAccessor() const {

include/swift/AST/TypeCheckRequests.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,17 +1237,22 @@ class GetDistributedRemoteCallArgumentInitFunctionRequest :
12371237
///
12381238
/// The thunk is responsible for invoking 'remoteCall' when invoked on a remote
12391239
/// 'distributed actor'.
1240-
class GetDistributedThunkRequest :
1241-
public SimpleRequest<GetDistributedThunkRequest,
1242-
FuncDecl *(AbstractFunctionDecl *),
1243-
RequestFlags::Cached> {
1240+
class GetDistributedThunkRequest
1241+
: public SimpleRequest<GetDistributedThunkRequest,
1242+
FuncDecl *(
1243+
llvm::PointerUnion<AbstractStorageDecl *,
1244+
AbstractFunctionDecl *>),
1245+
RequestFlags::Cached> {
1246+
using Originator =
1247+
llvm::PointerUnion<AbstractStorageDecl *, AbstractFunctionDecl *>;
1248+
12441249
public:
12451250
using SimpleRequest::SimpleRequest;
12461251

12471252
private:
12481253
friend SimpleRequest;
12491254

1250-
FuncDecl *evaluate(Evaluator &evaluator, AbstractFunctionDecl *distributedFunc) const;
1255+
FuncDecl *evaluate(Evaluator &evaluator, Originator originator) const;
12511256

12521257
public:
12531258
// Caching

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ SWIFT_REQUEST(TypeChecker, GetDistributedTargetInvocationResultHandlerOnReturnFu
127127
AbstractFunctionDecl *(NominalTypeDecl *),
128128
Cached, NoLocationInfo)
129129
SWIFT_REQUEST(TypeChecker, GetDistributedThunkRequest,
130-
FuncDecl *(AbstractFunctionDecl *),
130+
FuncDecl *(llvm::PointerUnion<AbstractStorageDecl *, AbstractFunctionDecl *>),
131131
Cached, NoLocationInfo)
132132
SWIFT_REQUEST(TypeChecker, GetDistributedActorIDPropertyRequest,
133133
VarDecl *(NominalTypeDecl *),

lib/AST/ASTDumper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ static StringRef getAccessSemanticsString(AccessSemantics value) {
255255
case AccessSemantics::Ordinary: return "ordinary";
256256
case AccessSemantics::DirectToStorage: return "direct_to_storage";
257257
case AccessSemantics::DirectToImplementation: return "direct_to_impl";
258+
case AccessSemantics::DistributedThunk: return "distributed_thunk";
258259
}
259260

260261
llvm_unreachable("Unhandled AccessSemantics in switch.");
@@ -745,6 +746,8 @@ namespace {
745746

746747
void visitVarDecl(VarDecl *VD) {
747748
printCommon(VD, "var_decl");
749+
if (VD->isDistributed())
750+
PrintWithColorRAII(OS, DeclModifierColor) << " distributed";
748751
if (VD->isLet())
749752
PrintWithColorRAII(OS, DeclModifierColor) << " let";
750753
if (VD->getAttrs().hasAttribute<LazyAttr>())
@@ -875,6 +878,9 @@ namespace {
875878
if (D->isDistributed()) {
876879
PrintWithColorRAII(OS, ExprModifierColor) << " distributed";
877880
}
881+
if (D->isDistributedThunk()) {
882+
PrintWithColorRAII(OS, ExprModifierColor) << " distributed-thunk";
883+
}
878884

879885
if (auto fac = D->getForeignAsyncConvention()) {
880886
OS << " foreign_async=";

lib/AST/ASTMangler.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3486,10 +3486,33 @@ ASTMangler::mangleOpaqueTypeDescriptorRecord(const OpaqueTypeDecl *decl) {
34863486
return finalize();
34873487
}
34883488

3489-
std::string ASTMangler::mangleDistributedThunk(const FuncDecl *thunk) {
3489+
std::string ASTMangler::mangleDistributedThunk(const AbstractFunctionDecl *thunk) {
34903490
// Marker protocols cannot be checked at runtime, so there is no point
34913491
// in recording them for distributed thunks.
34923492
llvm::SaveAndRestore<bool> savedAllowMarkerProtocols(AllowMarkerProtocols,
34933493
false);
3494+
3495+
// Since computed property SILDeclRef's refer to the "originator"
3496+
// of the thunk, we need to mangle distributed thunks of accessors
3497+
// specially.
3498+
if (auto *accessor = dyn_cast<AccessorDecl>(thunk)) {
3499+
// TODO: This needs to use accessor type instead of
3500+
// distributed thunk after all SILDeclRefs are switched
3501+
// to use "originator" instead of the thunk itself.
3502+
//
3503+
// ```
3504+
// beginMangling();
3505+
// appendContextOf(thunk);
3506+
// appendDeclName(accessor->getStorage());
3507+
// appendDeclType(accessor, FunctionMangling);
3508+
// appendOperator("F");
3509+
// appendSymbolKind(SymbolKind::DistributedThunk);
3510+
// return finalize();
3511+
// ```
3512+
auto *storage = accessor->getStorage();
3513+
thunk = storage->getDistributedThunk();
3514+
assert(thunk);
3515+
}
3516+
34943517
return mangleEntity(thunk, SymbolKind::DistributedThunk);
34953518
}

0 commit comments

Comments
 (0)