[Distributed] Move dist funcdecl getters to ASTContext

This commit is contained in:
Konrad `ktoso` Malawski
2022-01-28 10:57:39 +09:00
parent 6da455e0fa
commit e2c61d37ba
5 changed files with 95 additions and 136 deletions

View File

@@ -670,29 +670,30 @@ public:
NominalTypeDecl *actorOrSystem, NominalTypeDecl *actorOrSystem,
bool isVoidReturn) const; bool isVoidReturn) const;
/// Retrieve the declaration of DistributedActorSystem.make().
///
/// \param actorOrSystem distributed actor or actor system to get the
/// remoteCall function for. Since the method we're looking for is an ad-hoc
/// requirement, a specific type MUST be passed here as it is not possible
/// to obtain the decl from just the `DistributedActorSystem` protocol type.
FuncDecl *getMakeInvocationEncoderOnDistributedActorSystem(
NominalTypeDecl *actorOrSystem) const;
// Retrieve the declaration of DistributedInvocationEncoder.recordArgument(_:). // Retrieve the declaration of DistributedInvocationEncoder.recordArgument(_:).
// //
// \param nominal optionally provide a 'NominalTypeDecl' from which the // \param nominal optionally provide a 'NominalTypeDecl' from which the
// function decl shall be extracted. This is useful to avoid witness calls // function decl shall be extracted. This is useful to avoid witness calls
// through the protocol which is looked up when nominal is null. // through the protocol which is looked up when nominal is null.
FuncDecl *getRecordArgumentOnDistributedInvocationEncoder( FuncDecl *getRecordArgumentOnDistributedInvocationEncoder(
NominalTypeDecl *nominal = nullptr) const; NominalTypeDecl *nominal) const;
// Retrieve the declaration of DistributedInvocationEncoder.recordErrorType(). // Retrieve the declaration of DistributedInvocationEncoder.recordErrorType(_:).
//
// \param nominal optionally provide a 'NominalTypeDecl' from which the
// function decl shall be extracted. This is useful to avoid witness calls
// through the protocol which is looked up when nominal is null.
FuncDecl *getRecordErrorTypeOnDistributedInvocationEncoder( FuncDecl *getRecordErrorTypeOnDistributedInvocationEncoder(
NominalTypeDecl *nominal = nullptr) const; NominalTypeDecl *nominal) const;
// Retrieve the declaration of DistributedInvocationEncoder.recordReturnType(). // Retrieve the declaration of DistributedInvocationEncoder.recordReturnType(_:).
//
// \param nominal optionally provide a 'NominalTypeDecl' from which the
// function decl shall be extracted. This is useful to avoid witness calls
// through the protocol which is looked up when nominal is null.
FuncDecl *getRecordReturnTypeOnDistributedInvocationEncoder( FuncDecl *getRecordReturnTypeOnDistributedInvocationEncoder(
NominalTypeDecl *nominal = nullptr) const; NominalTypeDecl *nominal) const;
// Retrieve the declaration of DistributedInvocationEncoder.doneRecording(). // Retrieve the declaration of DistributedInvocationEncoder.doneRecording().
// //
@@ -700,8 +701,7 @@ public:
// function decl shall be extracted. This is useful to avoid witness calls // function decl shall be extracted. This is useful to avoid witness calls
// through the protocol which is looked up when nominal is null. // through the protocol which is looked up when nominal is null.
FuncDecl *getDoneRecordingOnDistributedInvocationEncoder( FuncDecl *getDoneRecordingOnDistributedInvocationEncoder(
NominalTypeDecl *nominal = nullptr) const; NominalTypeDecl *nominal) const;
/// Look for the declaration with the given name within the /// Look for the declaration with the given name within the
/// passed in module. /// passed in module.

View File

@@ -3370,9 +3370,6 @@ public:
/// Find, or potentially synthesize, the implicit 'id' property of this actor. /// Find, or potentially synthesize, the implicit 'id' property of this actor.
VarDecl *getDistributedActorIDProperty() const; VarDecl *getDistributedActorIDProperty() const;
/// Find the 'makeInvocation' function.
AbstractFunctionDecl* getDistributedActorSystemMakeInvocationEncoderFunction() const;
/// Find the 'RemoteCallTarget.init(_mangledName:)' initializer function /// Find the 'RemoteCallTarget.init(_mangledName:)' initializer function
ConstructorDecl* getDistributedRemoteCallTargetInitFunction() const; ConstructorDecl* getDistributedRemoteCallTargetInitFunction() const;

View File

@@ -267,18 +267,6 @@ struct ASTContext::Implementation {
/// -> Builtin.Int1 /// -> Builtin.Int1
FuncDecl *IsOSVersionAtLeastDecl = nullptr; FuncDecl *IsOSVersionAtLeastDecl = nullptr;
/// func recordArgument(_:) throws
FuncDecl *RecordArgumentDistributedInvocationEncoderDecl = nullptr;
/// func recordErrorType(_:) throws
FuncDecl *RecordErrorTypeDistributedInvocationEncoderDecl = nullptr;
/// func recordReturnType(_:) throws
FuncDecl *RecordReturnTypeDistributedInvocationEncoderDecl = nullptr;
/// func doneRecording() throws
FuncDecl *DoneRecordingDistributedInvocationEncoderDecl = nullptr;
/// The set of known protocols, lazily populated as needed. /// The set of known protocols, lazily populated as needed.
ProtocolDecl *KnownProtocols[NumKnownProtocols] = { }; ProtocolDecl *KnownProtocols[NumKnownProtocols] = { };
@@ -1295,7 +1283,7 @@ AbstractFunctionDecl *ASTContext::getRemoteCallOnDistributedActorSystem(
NominalTypeDecl *actorOrSystem, bool isVoidReturn) const { NominalTypeDecl *actorOrSystem, bool isVoidReturn) const {
assert(actorOrSystem && "distributed actor (or system) decl must be provided"); assert(actorOrSystem && "distributed actor (or system) decl must be provided");
const NominalTypeDecl *system = actorOrSystem; const NominalTypeDecl *system = actorOrSystem;
if (actorOrSystem && actorOrSystem->isDistributedActor()) { if (actorOrSystem->isDistributedActor()) {
auto var = actorOrSystem->getDistributedActorSystemProperty(); auto var = actorOrSystem->getDistributedActorSystemProperty();
system = var->getInterfaceType()->getAnyNominal(); system = var->getInterfaceType()->getAnyNominal();
} }
@@ -1310,32 +1298,49 @@ AbstractFunctionDecl *ASTContext::getRemoteCallOnDistributedActorSystem(
nullptr); nullptr);
} }
FuncDecl *ASTContext::getRecordArgumentOnDistributedInvocationEncoder( FuncDecl *ASTContext::getMakeInvocationEncoderOnDistributedActorSystem(
NominalTypeDecl *nominal) const { NominalTypeDecl *actorOrSystem) const {
if (getImpl().RecordArgumentDistributedInvocationEncoderDecl) { NominalTypeDecl *system = actorOrSystem;
return getImpl().RecordArgumentDistributedInvocationEncoderDecl; assert(actorOrSystem && "distributed actor (or system) decl must be provided");
if (actorOrSystem->isDistributedActor()) {
auto var = actorOrSystem->getDistributedActorSystemProperty();
system = var->getInterfaceType()->getAnyNominal();
} }
NominalTypeDecl *encoderProto = nominal ? for (auto result : system->lookupDirect(Id_makeInvocationEncoder)) {
nominal :
getProtocol(KnownProtocolKind::DistributedTargetInvocationEncoder);
assert(encoderProto && "Missing DistributedTargetInvocationEncoder protocol");
for (auto result : encoderProto->lookupDirect(Id_recordArgument)) {
auto *fd = dyn_cast<FuncDecl>(result); auto *fd = dyn_cast<FuncDecl>(result);
if (!fd) if (!fd)
continue; continue;
if (fd->getParameters()->size() != 0)
continue;
if (fd->hasAsync())
continue;
if (fd->hasThrows())
continue;
// TODO(distributed): more checks, return type etc
return fd;
}
return nullptr;
}
FuncDecl *ASTContext::getRecordArgumentOnDistributedInvocationEncoder(
NominalTypeDecl *nominal) const {
for (auto result : nominal->lookupDirect(Id_recordArgument)) {
auto *fd = dyn_cast<FuncDecl>(result);
if (!fd)
continue;
if (fd->getParameters()->size() != 1) if (fd->getParameters()->size() != 1)
continue; continue;
if (fd->hasAsync())
continue;
if (!fd->hasThrows())
continue;
// TODO(distributed): more checks // TODO(distributed): more checks
if (fd->getResultInterfaceType()->isVoid() && if (fd->getResultInterfaceType()->isVoid())
fd->hasThrows() &&
!fd->hasAsync()) {
getImpl().RecordArgumentDistributedInvocationEncoderDecl = fd;
return fd; return fd;
}
} }
return nullptr; return nullptr;
@@ -1343,31 +1348,20 @@ FuncDecl *ASTContext::getRecordArgumentOnDistributedInvocationEncoder(
FuncDecl *ASTContext::getRecordErrorTypeOnDistributedInvocationEncoder( FuncDecl *ASTContext::getRecordErrorTypeOnDistributedInvocationEncoder(
NominalTypeDecl *nominal) const { NominalTypeDecl *nominal) const {
if (getImpl().RecordErrorTypeDistributedInvocationEncoderDecl) { for (auto result : nominal->lookupDirect(Id_recordErrorType)) {
return getImpl().RecordErrorTypeDistributedInvocationEncoderDecl;
}
NominalTypeDecl *encoderProto =
nominal
? nominal
: getProtocol(KnownProtocolKind::DistributedTargetInvocationEncoder);
assert(encoderProto && "Missing DistributedTargetInvocationEncoder protocol");
for (auto result : encoderProto->lookupDirect(Id_recordErrorType)) {
auto *fd = dyn_cast<FuncDecl>(result); auto *fd = dyn_cast<FuncDecl>(result);
if (!fd) if (!fd)
continue; continue;
if (fd->getParameters()->size() != 1) if (fd->getParameters()->size() != 1)
continue; continue;
if (fd->hasAsync())
continue;
if (!fd->hasThrows())
continue;
// TODO(distributed): more checks
// TODO(distributed): more checks that the arg type matches (!!!) if (fd->getResultInterfaceType()->isVoid())
if (fd->getResultInterfaceType()->isVoid() &&
fd->hasThrows() &&
!fd->hasAsync()) {
getImpl().RecordErrorTypeDistributedInvocationEncoderDecl = fd;
return fd; return fd;
}
} }
return nullptr; return nullptr;
@@ -1375,31 +1369,20 @@ FuncDecl *ASTContext::getRecordErrorTypeOnDistributedInvocationEncoder(
FuncDecl *ASTContext::getRecordReturnTypeOnDistributedInvocationEncoder( FuncDecl *ASTContext::getRecordReturnTypeOnDistributedInvocationEncoder(
NominalTypeDecl *nominal) const { NominalTypeDecl *nominal) const {
if (getImpl().RecordReturnTypeDistributedInvocationEncoderDecl) { for (auto result : nominal->lookupDirect(Id_recordReturnType)) {
return getImpl().RecordReturnTypeDistributedInvocationEncoderDecl;
}
NominalTypeDecl *encoderProto =
nominal
? nominal
: getProtocol(KnownProtocolKind::DistributedTargetInvocationEncoder);
assert(encoderProto && "Missing DistributedTargetInvocationEncoder protocol");
for (auto result : encoderProto->lookupDirect(Id_recordReturnType)) {
auto *fd = dyn_cast<FuncDecl>(result); auto *fd = dyn_cast<FuncDecl>(result);
if (!fd) if (!fd)
continue; continue;
if (fd->getParameters()->size() != 1) if (fd->getParameters()->size() != 1)
continue; continue;
if (fd->hasAsync())
continue;
if (!fd->hasThrows())
continue;
// TODO(distributed): more checks
// TODO(distributed): more checks that the arg type matches (!!!) if (fd->getResultInterfaceType()->isVoid())
if (fd->getResultInterfaceType()->isVoid() &&
fd->hasThrows() &&
!fd->hasAsync()) {
getImpl().RecordReturnTypeDistributedInvocationEncoderDecl = fd;
return fd; return fd;
}
} }
return nullptr; return nullptr;
@@ -1407,16 +1390,7 @@ FuncDecl *ASTContext::getRecordReturnTypeOnDistributedInvocationEncoder(
FuncDecl *ASTContext::getDoneRecordingOnDistributedInvocationEncoder( FuncDecl *ASTContext::getDoneRecordingOnDistributedInvocationEncoder(
NominalTypeDecl *nominal) const { NominalTypeDecl *nominal) const {
if (getImpl().DoneRecordingDistributedInvocationEncoderDecl) { for (auto result : nominal->lookupDirect(Id_doneRecording)) {
return getImpl().DoneRecordingDistributedInvocationEncoderDecl;
}
NominalTypeDecl *encoderProto =
nominal
? nominal
: getProtocol(KnownProtocolKind::DistributedTargetInvocationEncoder);
assert(encoderProto && "Missing DistributedTargetInvocationEncoder protocol");
for (auto result : encoderProto->lookupDirect(Id_doneRecording)) {
auto *fd = dyn_cast<FuncDecl>(result); auto *fd = dyn_cast<FuncDecl>(result);
if (!fd) if (!fd)
continue; continue;
@@ -1426,10 +1400,8 @@ FuncDecl *ASTContext::getDoneRecordingOnDistributedInvocationEncoder(
if (fd->getResultInterfaceType()->isVoid() && if (fd->getResultInterfaceType()->isVoid() &&
fd->hasThrows() && fd->hasThrows() &&
!fd->hasAsync()) { !fd->hasAsync())
getImpl().DoneRecordingDistributedInvocationEncoderDecl = fd;
return fd; return fd;
}
} }
return nullptr; return nullptr;

View File

@@ -7402,17 +7402,14 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
auto callId = isVoidReturn ? C.Id_remoteCallVoid : C.Id_remoteCall; auto callId = isVoidReturn ? C.Id_remoteCallVoid : C.Id_remoteCall;
// Check the name // Check the name
if (this->getBaseName() != callId) if (getBaseName() != callId)
return false; return false;
auto params = this->getParameters(); auto params = getParameters();
unsigned int expectedParamNum = isVoidReturn ? 4 : 5;
// Check the expected argument count // Check the expected argument count:
// - for value returning remoteCall: if (!params || params->size() != expectedParamNum)
if (!params || (!isVoidReturn && params->size() != 5))
return false;
// - for void returning remoteCallVoid:
if (!params || (isVoidReturn && params->size() != 4))
return false; return false;
// Check API names of the arguments // Check API names of the arguments
@@ -7422,7 +7419,7 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
auto thrownTypeParam = params->get(3); auto thrownTypeParam = params->get(3);
if (actorParam->getArgumentName() != C.Id_on || if (actorParam->getArgumentName() != C.Id_on ||
targetParam->getArgumentName() != C.Id_target || targetParam->getArgumentName() != C.Id_target ||
invocationParam->getArgumentName() != C.Id_invocationDecoder || invocationParam->getArgumentName() != C.Id_invocation ||
thrownTypeParam->getArgumentName() != C.Id_throwing) thrownTypeParam->getArgumentName() != C.Id_throwing)
return false; return false;
@@ -7432,6 +7429,26 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
return false; return false;
} }
if (!isGeneric())
return false;
auto genericParams = getGenericParams();
unsigned int expectedGenericParamNum = isVoidReturn ? 2 : 3;
// We expect: Act, Err, Res?
if (genericParams->size() != expectedGenericParamNum) {
return false;
}
// FIXME(distributed): check the exact generic requirements
// === check the return type
if (isVoidReturn) {
if (auto func = dyn_cast<FuncDecl>(this))
if (!func->getResultInterfaceType()->isVoid())
return false;
}
// FIXME(distributed): check the right types of the args and generics... // FIXME(distributed): check the right types of the args and generics...
// FIXME(distributed): check access level actually is ok, i.e. not private etc // FIXME(distributed): check access level actually is ok, i.e. not private etc
@@ -7439,34 +7456,7 @@ bool AbstractFunctionDecl::isDistributedActorSystemRemoteCall(bool isVoidReturn)
} }
bool AbstractFunctionDecl::isDistributed() const { bool AbstractFunctionDecl::isDistributed() const {
return this->getAttrs().hasAttribute<DistributedActorAttr>(); return getAttrs().hasAttribute<DistributedActorAttr>();
}
AbstractFunctionDecl*
NominalTypeDecl::getDistributedActorSystemMakeInvocationEncoderFunction() const {
auto &C = this->getASTContext();
NominalTypeDecl *system = const_cast<NominalTypeDecl *>(this);
if (this->isDistributedActor()) {
auto var = this->getDistributedActorSystemProperty();
system = var->getInterfaceType()->getAnyNominal();
}
// FIXME(distributed): implement more properly...
for (auto value : system->lookupDirect(C.Id_makeInvocationEncoder)) {
auto func = dyn_cast<AbstractFunctionDecl>(value);
if (!func)
continue;
if (func->getParameters()->size() != 0)
continue;
// TODO(distriuted): return type must conform to our expected protocol
return func;
}
// TODO(distributed): make a Request for it?
return nullptr;
} }
ConstructorDecl* ConstructorDecl*

View File

@@ -724,8 +724,8 @@ void SILGenFunction::emitDistributedThunk(SILDeclRef thunk) {
// === `InvocationEncoder` types // === `InvocationEncoder` types
AbstractFunctionDecl *makeInvocationEncoderFnDecl = AbstractFunctionDecl *makeInvocationEncoderFnDecl =
selfTyDecl->getDistributedActorSystemMakeInvocationEncoderFunction(); ctx.getMakeInvocationEncoderOnDistributedActorSystem(selfTyDecl);
assert(makeInvocationEncoderFnDecl && "no remoteCall func found!"); assert(makeInvocationEncoderFnDecl && "no 'makeInvocationEncoder' func found!");
auto makeInvocationEncoderFnRef = SILDeclRef(makeInvocationEncoderFnDecl); auto makeInvocationEncoderFnRef = SILDeclRef(makeInvocationEncoderFnDecl);
ProtocolDecl *invocationEncoderProto = ProtocolDecl *invocationEncoderProto =
@@ -882,7 +882,7 @@ void SILGenFunction::emitDistributedThunk(SILDeclRef thunk) {
// function_ref FakeActorSystem.makeInvocationEncoder() // function_ref FakeActorSystem.makeInvocationEncoder()
// %19 = function_ref @$s27FakeDistributedActorSystems0aC6SystemV21makeInvocationEncoderAA0aG0VyF : $@convention(method) (@guaranteed FakeActorSystem) -> FakeInvocation // user: %20 // %19 = function_ref @$s27FakeDistributedActorSystems0aC6SystemV21makeInvocationEncoderAA0aG0VyF : $@convention(method) (@guaranteed FakeActorSystem) -> FakeInvocation // user: %20
auto makeInvocationEncoderFnSIL = SILFunction *makeInvocationEncoderFnSIL =
builder.getOrCreateFunction(loc, makeInvocationEncoderFnRef, NotForDefinition); builder.getOrCreateFunction(loc, makeInvocationEncoderFnRef, NotForDefinition);
SILValue makeInvocationEncoderFn = SILValue makeInvocationEncoderFn =
B.createFunctionRefFor(loc, makeInvocationEncoderFnSIL); B.createFunctionRefFor(loc, makeInvocationEncoderFnSIL);
@@ -1395,7 +1395,7 @@ void SILGenFunction::emitDistributedThunk(SILDeclRef thunk) {
} }
assert(returnMetatypeValue); assert(returnMetatypeValue);
// function_ref FakeActorSystem.remoteCall<A, B, C>(on:target:invocationDecoder:throwing:returning:) // function_ref FakeActorSystem.remoteCall<A, B, C>(on:target:invocation:throwing:returning:)
// %49 = function_ref @$s27FakeDistributedActorSystems0aC6SystemV10remoteCall2on6target17invocationDecoder8throwing9returningq0_x_01_B006RemoteG6TargetVAA0A10InvocationVzq_mq0_mSgtYaKAJ0bC0RzSeR0_SER0_AA0C7AddressV2IDRtzr1_lF : $@convention(method) @async <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : DistributedActor, τ_0_2 : Decodable, τ_0_2 : Encodable, τ_0_0.ID == ActorAddress> (@guaranteed τ_0_0, @in_guaranteed RemoteCallTarget, @inout FakeInvocation, @thick τ_0_1.Type, Optional<@thick τ_0_2.Type>, @guaranteed FakeActorSystem) -> (@out τ_0_2, @error Error) // user: %50 // %49 = function_ref @$s27FakeDistributedActorSystems0aC6SystemV10remoteCall2on6target17invocationDecoder8throwing9returningq0_x_01_B006RemoteG6TargetVAA0A10InvocationVzq_mq0_mSgtYaKAJ0bC0RzSeR0_SER0_AA0C7AddressV2IDRtzr1_lF : $@convention(method) @async <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : DistributedActor, τ_0_2 : Decodable, τ_0_2 : Encodable, τ_0_0.ID == ActorAddress> (@guaranteed τ_0_0, @in_guaranteed RemoteCallTarget, @inout FakeInvocation, @thick τ_0_1.Type, Optional<@thick τ_0_2.Type>, @guaranteed FakeActorSystem) -> (@out τ_0_2, @error Error) // user: %50
auto remoteCallFnDecl = auto remoteCallFnDecl =
ctx.getRemoteCallOnDistributedActorSystem(selfTyDecl, /*isVoid=*/resultType.isVoid()); ctx.getRemoteCallOnDistributedActorSystem(selfTyDecl, /*isVoid=*/resultType.isVoid());