mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
decouple the emission of actorReady from SILGen
We need to be able to inject a call to a distributed actor's transport.actorReady, passing the actor instance to it, during definite initialization. This means that its dependence on SILGenFunction must be broken, hence this refactoring as a SILOptimizer utility.
This commit is contained in:
43
include/swift/SILOptimizer/Utils/DistributedActor.h
Normal file
43
include/swift/SILOptimizer/Utils/DistributedActor.h
Normal file
@@ -0,0 +1,43 @@
|
||||
//===---- DistributedActor.h - SIL utils for distributed actors -*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_SILOPTIMIZER_UTILS_DISTRIBUTED_ACTOR_H
|
||||
#define SWIFT_SILOPTIMIZER_UTILS_DISTRIBUTED_ACTOR_H
|
||||
|
||||
namespace swift {
|
||||
|
||||
class ASTContext;
|
||||
class ConstructorDecl;
|
||||
class ClassDecl;
|
||||
class SILBuilder;
|
||||
class SILArgument;
|
||||
class SILFunction;
|
||||
class SILLocation;
|
||||
class SILValue;
|
||||
|
||||
/// Perform a load of the given distributed actor's transport.
|
||||
/// \param actorSelf the value representing `self` for the distributed actor
|
||||
/// instance. \returns the transport value
|
||||
SILValue loadActorTransport(SILBuilder &B, SILLocation loc,
|
||||
ClassDecl *actorDecl, SILValue actorSelf);
|
||||
|
||||
/// Emits code that notifies the distributed actor's transport that the
|
||||
/// actor is ready for execution.
|
||||
/// \param B the builder to use when emitting the code.
|
||||
/// \param actor the distributed actor instance to pass to the transport as
|
||||
/// being "ready" \param transport a value representing the ActorTransport
|
||||
void emitActorReadyCall(SILBuilder &B, SILLocation loc, ClassDecl *actorDecl,
|
||||
SILValue actor, SILValue transport);
|
||||
|
||||
} // namespace swift
|
||||
|
||||
#endif
|
||||
@@ -785,7 +785,7 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
|
||||
|
||||
// Distributed actor initializers implicitly initialize their transport and id
|
||||
if (isDesignatedDistActorInit) {
|
||||
initializeDistributedActorImplicitStorageInit(ctor, selfArg);
|
||||
emitDistActorImplicitPropertyInits(ctor, selfArg);
|
||||
}
|
||||
|
||||
// Prepare the end of initializer location.
|
||||
|
||||
@@ -28,11 +28,12 @@
|
||||
#include "swift/SIL/SILArgument.h"
|
||||
#include "swift/SIL/SILUndef.h"
|
||||
#include "swift/SIL/TypeLowering.h"
|
||||
#include "swift/SILOptimizer/Utils/DistributedActor.h"
|
||||
|
||||
using namespace swift;
|
||||
using namespace Lowering;
|
||||
|
||||
// MARK: Local utility functions
|
||||
// MARK: utility functions
|
||||
|
||||
/// Obtain a nominal type's member by name, as a VarDecl.
|
||||
/// \returns nullptr if the name lookup doesn't resolve to exactly one member,
|
||||
@@ -44,6 +45,21 @@ static VarDecl* lookupProperty(NominalTypeDecl *ty, DeclName name) {
|
||||
return dyn_cast<VarDecl>(refs.front());
|
||||
}
|
||||
|
||||
/// Perform an initializing store to the given property using the value
|
||||
/// \param actorSelf the value representing `self` for the actor instance.
|
||||
/// \param prop the property to be initialized.
|
||||
/// \param value the value to use when initializing the property.
|
||||
static void initializeProperty(SILGenFunction &SGF, SILLocation loc,
|
||||
SILValue actorSelf,
|
||||
VarDecl* prop, SILValue value) {
|
||||
auto fieldAddr = SGF.B.createRefElementAddr(loc, actorSelf, prop,
|
||||
SGF.getLoweredType(prop->getInterfaceType()));
|
||||
SGF.B.createCopyAddr(loc,
|
||||
/*src*/value,
|
||||
/*dest*/fieldAddr,
|
||||
IsNotTake, IsInitialization);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************* COMMON (DISTRIBUTED) SIL PATTERNS ************************/
|
||||
/******************************************************************************/
|
||||
@@ -82,20 +98,15 @@ static void emitDistributedIfRemoteBranch(SILGenFunction &SGF,
|
||||
B.createCondBranch(Loc, isRemoteResultUnwrapped, isRemoteBB, isLocalBB);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/****************** DISTRIBUTED ACTOR STORAGE INITIALIZATION ******************/
|
||||
/******************************************************************************/
|
||||
// MARK: local instance initialization
|
||||
|
||||
/// Get the `ActorTransport` parameter of the constructor.
|
||||
/// Sema should have guaranteed that there is exactly one of them for any
|
||||
/// designated initializer of a distributed actor.
|
||||
static SILArgument*
|
||||
getActorTransportArgument(ASTContext& C, SILFunction& F, ConstructorDecl *ctor) {
|
||||
auto *DC = cast<DeclContext>(ctor);
|
||||
auto module = DC->getParentModule();
|
||||
/// Finds the first `ActorTransport`-compatible parameter of the given function.
|
||||
/// Crashes if the given function does not have such a parameter.
|
||||
static SILArgument *findFirstActorTransportArg(SILFunction &F) {
|
||||
auto *module = F.getModule().getSwiftModule();
|
||||
auto &C = F.getASTContext();
|
||||
|
||||
auto *transportProto =
|
||||
C.getProtocol(KnownProtocolKind::ActorTransport);
|
||||
auto *transportProto = C.getProtocol(KnownProtocolKind::ActorTransport);
|
||||
Type transportTy = transportProto->getDeclaredInterfaceType();
|
||||
|
||||
for (auto arg : F.getArguments()) {
|
||||
@@ -103,8 +114,8 @@ getActorTransportArgument(ASTContext& C, SILFunction& F, ConstructorDecl *ctor)
|
||||
Type argTy = arg->getType().getASTType();
|
||||
auto argDecl = arg->getDecl();
|
||||
|
||||
auto conformsToTransport = module->lookupConformance(
|
||||
argDecl->getInterfaceType(), transportProto);
|
||||
auto conformsToTransport =
|
||||
module->lookupConformance(argDecl->getInterfaceType(), transportProto);
|
||||
|
||||
// Is it a protocol that conforms to ActorTransport?
|
||||
if (argTy->isEqual(transportTy) || conformsToTransport) {
|
||||
@@ -122,42 +133,21 @@ getActorTransportArgument(ASTContext& C, SILFunction& F, ConstructorDecl *ctor)
|
||||
llvm_unreachable("Missing required ActorTransport argument!");
|
||||
}
|
||||
|
||||
/// Perform an initializing store to the given property using the value
|
||||
/// \param actorSelf the value representing `self` for the actor instance.
|
||||
/// \param prop the property to be initialized.
|
||||
/// \param value the value to use when initializing the property.
|
||||
static void initializeProperty(SILGenFunction &SGF, SILLocation loc,
|
||||
SILValue actorSelf,
|
||||
VarDecl* prop, SILArgument *value) {
|
||||
auto fieldAddr = SGF.B.createRefElementAddr(loc, actorSelf, prop,
|
||||
SGF.getLoweredType(prop->getInterfaceType()));
|
||||
SGF.B.createCopyAddr(loc,
|
||||
/*src*/value,
|
||||
/*dest*/fieldAddr,
|
||||
IsNotTake, IsInitialization);
|
||||
}
|
||||
|
||||
// TODO(distributed): remove this store impl and reuse Store_transport
|
||||
static void
|
||||
emitDistributedActor_init_transportStore(
|
||||
SILGenFunction &SGF,
|
||||
ManagedValue borrowedSelfArg, VarDecl *selfDecl,
|
||||
ConstructorDecl *ctor, VarDecl *var) {
|
||||
auto &C = selfDecl->getASTContext();
|
||||
auto &B = SGF.B;
|
||||
auto &F = SGF.F;
|
||||
|
||||
/// For the initialization of a local distributed actor instance, emits code to initialize the instance's
|
||||
/// stored property corresponding to the transport.
|
||||
static void emitTransportInit(SILGenFunction &SGF,
|
||||
ConstructorDecl *ctor,
|
||||
SILLocation loc,
|
||||
ManagedValue actorSelf) {
|
||||
auto *dc = ctor->getDeclContext();
|
||||
auto classDecl = dc->getSelfClassDecl();
|
||||
auto &C = ctor->getASTContext();
|
||||
|
||||
auto loc = SILLocation(ctor);
|
||||
loc.markAutoGenerated();
|
||||
|
||||
// ==== Prepare assignment: get the self.transport address
|
||||
SILValue transportArg = getActorTransportArgument(C, F, ctor);
|
||||
|
||||
auto fieldAddr = B.createRefElementAddr(
|
||||
loc, borrowedSelfArg.getValue(), var,
|
||||
SGF.getLoweredType(var->getInterfaceType()));
|
||||
// Sema has already guaranteed that there is exactly one ActorTransport
|
||||
// argument to the constructor, so we grab the first one from the params.
|
||||
SILValue transportArg = findFirstActorTransportArg(SGF.F);
|
||||
VarDecl *var = lookupProperty(classDecl, C.Id_actorTransport);
|
||||
assert(var);
|
||||
|
||||
// If the argument is not existential, it will be a concrete type
|
||||
// that can be erased to that existential.
|
||||
@@ -186,45 +176,35 @@ emitDistributedActor_init_transportStore(
|
||||
transportValue = mv.getValue();
|
||||
}
|
||||
|
||||
// ==== Store the transport
|
||||
B.createCopyAddr(loc,
|
||||
/*src*/transportValue,
|
||||
/*dest*/fieldAddr,
|
||||
IsNotTake, IsInitialization);
|
||||
initializeProperty(SGF, loc, actorSelf.getValue(), var, transportValue);
|
||||
}
|
||||
|
||||
/// Synthesize the distributed actor's identity (`id`) initialization:
|
||||
/// Emits the distributed actor's identity (`id`) initialization.
|
||||
///
|
||||
/// Specifically, it performs:
|
||||
/// \verbatim
|
||||
/// self.id = transport.assignIdentity(Self.self)
|
||||
/// \endverbatim
|
||||
static void emitDistributedActorStore_init_assignIdentity(
|
||||
SILGenFunction &SGF,
|
||||
ManagedValue borrowedSelfArg, VarDecl *selfVarDecl,
|
||||
ConstructorDecl *ctor, VarDecl *var) {
|
||||
auto &C = selfVarDecl->getASTContext();
|
||||
static void emitIdentityInit(SILGenFunction &SGF, ConstructorDecl *ctor,
|
||||
SILLocation loc, ManagedValue borrowedSelfArg) {
|
||||
auto &C = ctor->getASTContext();
|
||||
auto &B = SGF.B;
|
||||
auto &F = SGF.F;
|
||||
auto &SGM = SGF.SGM;
|
||||
SILGenFunctionBuilder builder(SGM);
|
||||
|
||||
auto loc = SILLocation(ctor);
|
||||
loc.markAutoGenerated();
|
||||
auto *dc = ctor->getDeclContext();
|
||||
auto classDecl = dc->getSelfClassDecl();
|
||||
|
||||
// ==== prepare the transport.assignIdentity(_:) function
|
||||
ProtocolDecl *transportProto = C.getProtocol(KnownProtocolKind::ActorTransport);
|
||||
|
||||
// --- Prepare the arguments
|
||||
SILValue transportArgValue = getActorTransportArgument(C, F, ctor);
|
||||
|
||||
ProtocolDecl *distributedActorProto = C.getProtocol(KnownProtocolKind::DistributedActor);
|
||||
|
||||
assert(distributedActorProto);
|
||||
assert(transportProto);
|
||||
|
||||
SILValue transportValue =
|
||||
loadActorTransport(B, loc, classDecl, borrowedSelfArg.getValue());
|
||||
|
||||
// --- Open the transport existential, if needed.
|
||||
SILValue transportValue = transportArgValue;
|
||||
auto transportASTType = transportArgValue->getType().getASTType();
|
||||
auto transportASTType = transportValue->getType().getASTType();
|
||||
if (transportASTType->isAnyExistentialType()) {
|
||||
OpenedArchetypeType *Opened;
|
||||
transportASTType =
|
||||
@@ -282,6 +262,8 @@ static void emitDistributedActorStore_init_assignIdentity(
|
||||
{transportASTType, selfTy},
|
||||
{transportConfRef, distributedActorConfRef});
|
||||
|
||||
VarDecl *var = lookupProperty(classDecl, C.Id_id);
|
||||
|
||||
// --- create a temporary storage for the result of the call
|
||||
// it will be deallocated automatically as we exit this scope
|
||||
auto resultTy = SGF.getLoweredType(var->getInterfaceType());
|
||||
@@ -292,133 +274,40 @@ static void emitDistributedActorStore_init_assignIdentity(
|
||||
loc, assignWitnessMethod, subs,
|
||||
{ temp, selfMetatypeValue, transportValue});
|
||||
|
||||
// ==== Assign the identity to stored property
|
||||
// TODO(distributed): reuse emitDistributedActorStore_id here, pass the SILValue
|
||||
// --- Prepare address of self.id
|
||||
auto idFieldAddr = B.createRefElementAddr(
|
||||
loc, borrowedSelfArg.getValue(), var,
|
||||
SGF.getLoweredType(var->getInterfaceType()));
|
||||
|
||||
// --- assign to the property
|
||||
B.createCopyAddr(loc, /*src*/temp, /*dest*/idFieldAddr,
|
||||
IsTake, IsInitialization);
|
||||
initializeProperty(SGF, loc, borrowedSelfArg.getValue(), var, temp);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************* DISTRIBUTED ACTOR LOCAL INIT *****************************/
|
||||
/******************************************************************************/
|
||||
|
||||
void SILGenFunction::initializeDistributedActorImplicitStorageInit(
|
||||
void SILGenFunction::emitDistActorImplicitPropertyInits(
|
||||
ConstructorDecl *ctor, ManagedValue selfArg) {
|
||||
VarDecl *selfVarDecl = ctor->getImplicitSelfDecl();
|
||||
auto *dc = ctor->getDeclContext();
|
||||
auto classDecl = dc->getSelfClassDecl();
|
||||
auto &C = classDecl->getASTContext();
|
||||
// Only designated initializers should perform this initialization.
|
||||
assert(ctor->isDesignatedInit());
|
||||
|
||||
// Only designated initializers get the lifecycle handling injected
|
||||
if (!ctor->isDesignatedInit())
|
||||
return;
|
||||
auto loc = SILLocation(ctor);
|
||||
loc.markAutoGenerated();
|
||||
|
||||
SILLocation prologueLoc = RegularLocation(ctor);
|
||||
prologueLoc.markAsPrologue(); // TODO: no idea if this is necessary or makes sense
|
||||
|
||||
// ==== Initialize Properties.
|
||||
auto borrowedSelfArg = selfArg.borrow(*this, prologueLoc);
|
||||
|
||||
VarDecl *transportVar = lookupProperty(classDecl, C.Id_actorTransport);
|
||||
emitDistributedActor_init_transportStore(*this, borrowedSelfArg, selfVarDecl,
|
||||
ctor, transportVar);
|
||||
|
||||
VarDecl *identityVar = lookupProperty(classDecl, C.Id_id);
|
||||
emitDistributedActorStore_init_assignIdentity(*this, borrowedSelfArg,
|
||||
selfVarDecl,
|
||||
ctor, identityVar);
|
||||
selfArg = selfArg.borrow(*this, loc);
|
||||
emitTransportInit(*this, ctor, loc, selfArg);
|
||||
emitIdentityInit(*this, ctor, loc, selfArg);
|
||||
}
|
||||
|
||||
void SILGenFunction::emitDistributedActorReady(
|
||||
SILLocation loc, ConstructorDecl *ctor, ManagedValue actorSelf) {
|
||||
|
||||
auto *dc = ctor->getDeclContext();
|
||||
auto classDecl = dc->getSelfClassDecl();
|
||||
auto &C = classDecl->getASTContext();
|
||||
|
||||
// Only designated initializers get the lifecycle handling injected
|
||||
assert(ctor->isDesignatedInit());
|
||||
|
||||
// setup scope for clean-ups
|
||||
auto *dc = ctor->getDeclContext();
|
||||
auto classDecl = dc->getSelfClassDecl();
|
||||
|
||||
SILValue transport = findFirstActorTransportArg(F);
|
||||
|
||||
FullExpr scope(Cleanups, CleanupLocation(loc));
|
||||
auto borrowedSelf = actorSelf.borrow(*this, loc);
|
||||
|
||||
// === Prepare the arguments
|
||||
SILValue transportArgValue = getActorTransportArgument(C, F, ctor);
|
||||
actorSelf = actorSelf.borrow(*this, loc);
|
||||
|
||||
ProtocolDecl *distributedActorProto = C.getProtocol(KnownProtocolKind::DistributedActor);
|
||||
ProtocolDecl *transportProto = C.getProtocol(KnownProtocolKind::ActorTransport);
|
||||
assert(distributedActorProto);
|
||||
assert(transportProto);
|
||||
|
||||
// --- Open the transport existential
|
||||
SILValue transportValue = transportArgValue;
|
||||
auto transportASTType = transportValue->getType().getASTType();
|
||||
if (transportASTType->isAnyExistentialType()) {
|
||||
OpenedArchetypeType *Opened;
|
||||
transportASTType =
|
||||
transportASTType->openAnyExistentialType(Opened)->getCanonicalType();
|
||||
transportValue = B.createOpenExistentialAddr(
|
||||
loc, transportValue, F.getLoweredType(transportASTType),
|
||||
OpenedExistentialAccess::Immutable);
|
||||
emitActorReadyCall(B, loc, classDecl, borrowedSelf.getValue(), transport);
|
||||
}
|
||||
|
||||
// === Make the transport.actorReady call
|
||||
// --- prepare the witness_method
|
||||
// Note: it does not matter on what module we perform the lookup,
|
||||
// it is currently ignored. So the Stdlib module is good enough.
|
||||
auto *module = getModule().getSwiftModule();
|
||||
|
||||
// the conformance here is just an abstract thing so we can simplify
|
||||
auto transportConfRef = ProtocolConformanceRef(transportProto);
|
||||
assert(!transportConfRef.isInvalid() && "Missing conformance to `ActorTransport`");
|
||||
|
||||
auto *selfTyDecl = ctor->getParent()->getSelfNominalTypeDecl();
|
||||
auto selfTy = F.mapTypeIntoContext(selfTyDecl->getDeclaredInterfaceType()); // TODO: thats just self var devl getType
|
||||
|
||||
auto distributedActorConfRef = module->lookupConformance(
|
||||
selfTy,
|
||||
distributedActorProto);
|
||||
assert(!distributedActorConfRef.isInvalid() && "Missing conformance to `DistributedActor`");
|
||||
|
||||
// === Prepare the actorReady function
|
||||
auto actorReadyMethod =
|
||||
cast<FuncDecl>(transportProto->getSingleRequirement(C.Id_actorReady));
|
||||
auto actorReadyRef = SILDeclRef(actorReadyMethod, SILDeclRef::Kind::Func);
|
||||
auto actorReadySILTy =
|
||||
getConstantInfo(getTypeExpansionContext(), actorReadyRef)
|
||||
.getSILType();
|
||||
|
||||
auto readyWitnessMethod = B.createWitnessMethod(
|
||||
loc,
|
||||
/*lookupTy*/transportASTType,
|
||||
/*Conformance*/transportConfRef,
|
||||
/*member*/actorReadyRef,
|
||||
/*methodTy*/actorReadySILTy);
|
||||
|
||||
// --- prepare conformance subs
|
||||
auto genericSig = actorReadyMethod->getGenericSignature();
|
||||
|
||||
SubstitutionMap subs =
|
||||
SubstitutionMap::get(genericSig,
|
||||
{transportASTType, selfTy},
|
||||
{transportConfRef, distributedActorConfRef});
|
||||
|
||||
// ---- actually call transport.actorReady(self)
|
||||
B.createApply(
|
||||
loc, readyWitnessMethod, subs,
|
||||
{ actorSelf.getValue(), transportValue});
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************* DISTRIBUTED ACTOR RESOLVE FUNCTION ***********************/
|
||||
/******************************************************************************/
|
||||
// MARK: remote instance initialization
|
||||
|
||||
/// Synthesize the distributed actor's identity (`id`) initialization:
|
||||
///
|
||||
|
||||
@@ -2006,8 +2006,9 @@ public:
|
||||
// Distributed Actors
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
/// Initialize the distributed actors transport and id.
|
||||
void initializeDistributedActorImplicitStorageInit(
|
||||
/// Initializes the implicit stored properties of a distributed actor that correspond to
|
||||
/// its transport and identity.
|
||||
void emitDistActorImplicitPropertyInits(
|
||||
ConstructorDecl *ctor, ManagedValue selfArg);
|
||||
|
||||
/// Given a function representing a distributed actor factory, emits the
|
||||
|
||||
@@ -10,6 +10,7 @@ target_sources(swiftSILOptimizer PRIVATE
|
||||
ConstExpr.cpp
|
||||
Devirtualize.cpp
|
||||
DifferentiationMangler.cpp
|
||||
DistributedActor.cpp
|
||||
Existential.cpp
|
||||
GenericCloner.cpp
|
||||
Generics.cpp
|
||||
|
||||
109
lib/SILOptimizer/Utils/DistributedActor.cpp
Normal file
109
lib/SILOptimizer/Utils/DistributedActor.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
//===-- DistributedActor.cpp - SIL utils for distributed actors -*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/SILOptimizer/Utils/DistributedActor.h"
|
||||
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/SIL/SILBuilder.h"
|
||||
#include "swift/SIL/SILLocation.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
// MARK: utilities
|
||||
|
||||
SILValue loadActorTransport(SILBuilder &B, SILLocation loc,
|
||||
ClassDecl *actorDecl, SILValue actorSelf) {
|
||||
assert(actorDecl->isDistributedActor());
|
||||
|
||||
// get the VarDecl corresponding to the transport
|
||||
auto &C = actorDecl->getASTContext();
|
||||
auto refs = actorDecl->lookupDirect(C.Id_actorTransport);
|
||||
assert(refs.size() == 1);
|
||||
VarDecl *prop = dyn_cast<VarDecl>(refs.front());
|
||||
|
||||
// form a reference and load it
|
||||
auto &F = B.getFunction();
|
||||
auto fieldAddr = B.createRefElementAddr(
|
||||
loc, actorSelf, prop, F.getLoweredType(prop->getInterfaceType()));
|
||||
return B.createLoad(loc, fieldAddr, LoadOwnershipQualifier::Copy);
|
||||
}
|
||||
|
||||
// MARK: exposed interface
|
||||
|
||||
void emitActorReadyCall(SILBuilder &B, SILLocation loc, ClassDecl *actorDecl,
|
||||
SILValue actor, SILValue transport) {
|
||||
|
||||
auto &F = B.getFunction();
|
||||
auto &M = B.getModule();
|
||||
auto &C = actorDecl->getASTContext();
|
||||
|
||||
ProtocolDecl *actorProto = C.getProtocol(KnownProtocolKind::DistributedActor);
|
||||
ProtocolDecl *transProto = C.getProtocol(KnownProtocolKind::ActorTransport);
|
||||
assert(actorProto);
|
||||
assert(transProto);
|
||||
|
||||
// Open the transport existential
|
||||
auto transportASTType = transport->getType().getASTType();
|
||||
if (transportASTType->isAnyExistentialType()) {
|
||||
OpenedArchetypeType *Opened;
|
||||
transportASTType =
|
||||
transportASTType->openAnyExistentialType(Opened)->getCanonicalType();
|
||||
transport = B.createOpenExistentialAddr(loc, transport,
|
||||
F.getLoweredType(transportASTType),
|
||||
OpenedExistentialAccess::Immutable);
|
||||
}
|
||||
|
||||
// Make the transport.actorReady call
|
||||
|
||||
// the conformance here is just an abstract thing so we can simplify
|
||||
auto transportConfRef = ProtocolConformanceRef(transProto);
|
||||
assert(!transportConfRef.isInvalid() &&
|
||||
"Missing conformance to `ActorTransport`");
|
||||
|
||||
auto *selfTyDecl = actorDecl->getSelfNominalTypeDecl();
|
||||
auto selfTy = F.mapTypeIntoContext(
|
||||
selfTyDecl->getDeclaredInterfaceType()); // TODO: thats just self var devl
|
||||
// getType
|
||||
|
||||
// Note: it does not matter on what module we perform the lookup,
|
||||
// it is currently ignored. So the Stdlib module is good enough.
|
||||
auto *module = M.getSwiftModule();
|
||||
auto distributedActorConfRef = module->lookupConformance(selfTy, actorProto);
|
||||
assert(!distributedActorConfRef.isInvalid() &&
|
||||
"Missing conformance to `DistributedActor`");
|
||||
|
||||
// Prepare the actorReady function
|
||||
auto actorReadyMethod =
|
||||
cast<FuncDecl>(transProto->getSingleRequirement(C.Id_actorReady));
|
||||
auto actorReadyRef = SILDeclRef(actorReadyMethod, SILDeclRef::Kind::Func);
|
||||
auto actorReadySILTy =
|
||||
M.Types.getConstantInfo(B.getTypeExpansionContext(), actorReadyRef)
|
||||
.getSILType();
|
||||
|
||||
auto readyWitnessMethod =
|
||||
B.createWitnessMethod(loc,
|
||||
/*lookupTy*/ transportASTType,
|
||||
/*Conformance*/ transportConfRef,
|
||||
/*member*/ actorReadyRef,
|
||||
/*methodTy*/ actorReadySILTy);
|
||||
|
||||
// prepare conformance substitutions
|
||||
auto genericSig = actorReadyMethod->getGenericSignature();
|
||||
|
||||
SubstitutionMap subs =
|
||||
SubstitutionMap::get(genericSig, {transportASTType, selfTy},
|
||||
{transportConfRef, distributedActorConfRef});
|
||||
|
||||
B.createApply(loc, readyWitnessMethod, subs, {actor, transport});
|
||||
}
|
||||
|
||||
} // namespace swift
|
||||
Reference in New Issue
Block a user