@@ -70,6 +70,34 @@ static void emitDistributedIfRemoteBranch(SILGenFunction &SGF,
7070 B.createCondBranch (Loc, isRemoteResultUnwrapped, isRemoteBB, isLocalBB);
7171}
7272
73+ static AbstractFunctionDecl *lookupActorTransportResolveFunc (ASTContext &C) {
74+ auto transportDecl = C.getActorTransportDecl ();
75+
76+ for (auto decl : transportDecl->lookupDirect (DeclName (C.Id_resolve )))
77+ if (auto funcDecl = dyn_cast<AbstractFunctionDecl>(decl))
78+ return funcDecl;
79+
80+ llvm_unreachable (" Missing ActorTransport.resolve function" );
81+ }
82+
83+ static VarDecl *lookupActorTransportProperty (ASTContext &C, ClassDecl *cd,
84+ SILValue selfValue) {
85+ auto transportVarDeclRefs = cd->lookupDirect (C.Id_actorTransport );
86+ assert (transportVarDeclRefs.size () == 1 );
87+ return dyn_cast<VarDecl>(transportVarDeclRefs.front ());
88+ }
89+
90+ static EnumElementDecl *lookupEnumCase (ASTContext &C, EnumDecl *target,
91+ Identifier identifier) {
92+ auto elementDecls = target->lookupDirect (DeclName (identifier));
93+ if (elementDecls.empty ())
94+ return nullptr ;
95+
96+ auto *elementDecl = elementDecls.front ();
97+
98+ return dyn_cast<EnumElementDecl>(elementDecl);
99+ }
100+
73101/* *****************************************************************************/
74102/* ***************** DISTRIBUTED ACTOR STORAGE INITIALIZATION ******************/
75103/* *****************************************************************************/
@@ -120,6 +148,7 @@ static void emitDistributedActorStore_transport(
120148 SILValue actorSelf, AbstractFunctionDecl *func,
121149 SILArgument *transportArg) {
122150 auto &B = SGF.B ;
151+
123152 auto &SGM = SGF.SGM ;
124153 SILGenFunctionBuilder builder (SGM);
125154
@@ -135,6 +164,7 @@ static void emitDistributedActorStore_transport(
135164 auto *var = dyn_cast<VarDecl>(vars.front ());
136165
137166 // ----
167+
138168 auto fieldAddr = B.createRefElementAddr (
139169 loc, actorSelf, var,
140170 SGF.getLoweredType (var->getInterfaceType ()));
@@ -166,6 +196,7 @@ emitDistributedActor_init_transportStore(
166196 SILValue transportArgValue = getActorTransportArgument (C, F, ctor);
167197
168198 // ----
199+
169200 auto transportFieldAddr = B.createRefElementAddr (
170201 loc, borrowedSelfArg.getValue (), var,
171202 SGF.getLoweredType (var->getInterfaceType ()));
@@ -187,6 +218,7 @@ static void emitDistributedActorStore_id(
187218 SILValue actorSelf, AbstractFunctionDecl *func,
188219 SILArgument *identityArg) {
189220 auto &B = SGF.B ;
221+
190222 auto &SGM = SGF.SGM ;
191223 SILGenFunctionBuilder builder (SGM);
192224
@@ -237,7 +269,9 @@ static void emitDistributedActorStore_init_assignIdentity(
237269
238270 // --- Prepare the arguments
239271 SILValue transportArgValue = getActorTransportArgument (C, F, ctor);
272+
240273 ProtocolDecl *distributedActorProto = C.getProtocol (KnownProtocolKind::DistributedActor);
274+
241275 assert (distributedActorProto);
242276 assert (transportProto);
243277
@@ -382,6 +416,7 @@ void SILGenFunction::initializeDistributedActorImplicitStorageInit(
382416
383417void SILGenFunction::emitDistributedActorReady (
384418 ConstructorDecl *ctor, ManagedValue selfArg) {
419+
385420 auto *dc = ctor->getDeclContext ();
386421 auto classDecl = dc->getSelfClassDecl ();
387422 auto &C = classDecl->getASTContext ();
@@ -462,6 +497,86 @@ void SILGenFunction::emitDistributedActorReady(
462497/* ****************** DISTRIBUTED ACTOR RESOLVE FUNCTION ***********************/
463498/* *****************************************************************************/
464499
500+ // / Synthesize the distributed actor's identity (`id`) initialization:
501+ // /
502+ // / \verbatim
503+ // / transport.resolve(_, as:)
504+ // / \endverbatim
505+ static void createDistributedActorFactory_resolve (
506+ SILGenFunction &SGF, ASTContext &C, FuncDecl *fd, SILValue identityValue,
507+ SILValue transportValue, Type selfTy, SILValue selfMetatypeValue,
508+ SILType resultTy, SILBasicBlock *normalBB, SILBasicBlock *errorBB) {
509+ auto &B = SGF.B ;
510+ auto &SGM = SGF.SGM ;
511+ auto &F = SGF.F ;
512+ SILGenFunctionBuilder builder (SGM);
513+
514+ auto loc = SILLocation (fd);
515+ loc.markAutoGenerated ();
516+
517+ ProtocolDecl *distributedActorProto =
518+ C.getProtocol (KnownProtocolKind::DistributedActor);
519+ ProtocolDecl *transportProto =
520+ C.getProtocol (KnownProtocolKind::ActorTransport);
521+ assert (distributedActorProto);
522+ assert (transportProto);
523+
524+ // // --- Open the transport existential
525+ OpenedArchetypeType *Opened;
526+ auto transportASTType = transportValue->getType ().getASTType ();
527+ auto openedTransportType =
528+ transportASTType->openAnyExistentialType (Opened)->getCanonicalType ();
529+ auto openedTransportSILType = F.getLoweredType (openedTransportType);
530+ auto transportArchetypeValue =
531+ B.createOpenExistentialAddr (loc, transportValue, openedTransportSILType,
532+ OpenedExistentialAccess::Immutable);
533+
534+ // --- prepare the witness_method
535+ // Note: it does not matter on what module we perform the lookup,
536+ // it is currently ignored. So the Stdlib module is good enough.
537+ auto *module = SGF.getModule ().getSwiftModule ();
538+
539+ // the conformance here is just an abstract thing so we can simplify
540+ auto transportConfRef = ProtocolConformanceRef (transportProto);
541+ assert (!transportConfRef.isInvalid () &&
542+ " Missing conformance to `ActorTransport`" );
543+
544+ auto distributedActorConfRef =
545+ module ->lookupConformance (selfTy, distributedActorProto);
546+ assert (!distributedActorConfRef.isInvalid () &&
547+ " Missing conformance to `DistributedActor`" );
548+
549+ auto resolveMethod =
550+ cast<FuncDecl>(transportProto->getSingleRequirement (C.Id_resolve ));
551+ auto resolveRef = SILDeclRef (resolveMethod, SILDeclRef::Kind::Func);
552+ auto constantInfo =
553+ SGF.getConstantInfo (SGF.getTypeExpansionContext (), resolveRef);
554+ auto resolveSILTy = constantInfo.getSILType ();
555+
556+ auto resolveWitnessMethod =
557+ B.createWitnessMethod (loc,
558+ /* lookupTy*/ openedTransportType,
559+ /* Conformance*/ transportConfRef,
560+ /* member*/ resolveRef,
561+ /* methodTy*/ resolveSILTy);
562+
563+ // // --- prepare conformance subs
564+ auto genericSig = resolveMethod->getGenericSignature ();
565+
566+ SubstitutionMap subs =
567+ SubstitutionMap::get (genericSig, {openedTransportType, selfTy},
568+ {transportConfRef, distributedActorConfRef});
569+
570+ // // ---- actually call transport.resolve(id, as: Self.self)
571+
572+ SmallVector<SILValue, 3 > params;
573+ params.push_back (identityValue);
574+ params.push_back (selfMetatypeValue);
575+ params.push_back (transportArchetypeValue); // self for the call, as last param
576+
577+ B.createTryApply (loc, resolveWitnessMethod, subs, params, normalBB, errorBB);
578+ }
579+
465580// / Function body of:
466581// / \verbatim
467582// / DistributedActor.resolve(
@@ -487,28 +602,66 @@ void SILGenFunction::emitDistributedActorFactory(FuncDecl *fd) {
487602 assert (
488603 transportArg->getType ().getASTType ()->isEqual (C.getActorTransportType ()));
489604
490- // --- Parameter: self
605+ SILValue selfArgValue = F.getSelfArgument ();
606+ ManagedValue selfArg = ManagedValue::forUnmanaged (selfArgValue);
607+
608+ // type: SpecificDistributedActor.Type
609+ auto selfArgType = F.mapTypeIntoContext (selfArg.getType ().getASTType ());
610+ auto selfMetatype = getLoweredType (selfArgType);
611+ SILValue selfMetatypeValue = B.createMetatype (loc, selfMetatype);
612+
613+ // type: SpecificDistributedActor
491614 auto *selfTyDecl = fd->getParent ()->getSelfNominalTypeDecl ();
492615 assert (selfTyDecl->isDistributedActor ());
616+ auto selfTy = F.mapTypeIntoContext (selfTyDecl->getDeclaredInterfaceType ());
617+ auto returnTy = getLoweredType (selfTy);
493618
494- SILValue selfArgValue = F.getSelfArgument ();
495- ManagedValue selfArg = ManagedValue::forUnmanaged (selfArgValue);
619+ // ==== Prepare all the basic blocks
620+ auto returnBB = createBasicBlock ();
621+ auto resolvedBB = createBasicBlock ();
622+ auto makeProxyBB = createBasicBlock ();
623+ auto switchBB = createBasicBlock ();
624+ auto errorBB = createBasicBlock ();
625+
626+ SILFunctionConventions fnConv = F.getConventions (); // TODO: no idea?
627+
628+ // --- get the uninitialized allocation from the runtime system.
629+ FullExpr scope (Cleanups, CleanupLocation (fd));
630+
631+ auto optionalReturnTy = SILType::getOptionalType (returnTy);
496632
497- // ==== Case 'remote') Create the remote instance
633+ // ==== Call `try transport.resolve(id, as: Self.self)`
498634 {
499- // ==== Create 'remote' distributed actor instance
500- // --- Prepare param: Self.self
501- // type: SpecificDistributedActor
502- auto returnTy = getLoweredType (
503- F.mapTypeIntoContext (selfTyDecl->getDeclaredInterfaceType ()));
635+ createDistributedActorFactory_resolve (
636+ *this , C, fd, identityArg, transportArg, selfTy, selfMetatypeValue,
637+ optionalReturnTy, switchBB, errorBB);
638+ }
639+
640+ // ==== switch resolved { ... }
641+ {
642+ B.emitBlock (switchBB);
643+ auto resolve =
644+ switchBB->createPhiArgument (optionalReturnTy, OwnershipKind::Owned);
645+
646+ B.createSwitchEnum (
647+ loc, resolve, nullptr ,
648+ {{C.getOptionalSomeDecl (), resolvedBB},
649+ {std::make_pair (C.getOptionalNoneDecl (), makeProxyBB)}});
650+ }
504651
505- // type: SpecificDistributedActor.Type
506- auto selfMetatype =
507- getLoweredType (F.mapTypeIntoContext (selfArg.getType ().getASTType ()));
508- SILValue selfMetatypeValue = B.createMetatype (loc, selfMetatype);
652+ // ==== Case 'some') return the resolved instance
653+ {
654+ B.emitBlock (resolvedBB);
655+
656+ auto local = resolvedBB->createPhiArgument (returnTy, OwnershipKind::Owned);
657+
658+ B.createBranch (loc, returnBB, {local});
659+ }
509660
510- // --- get the uninitialized allocation from the runtime system.
511- FullExpr scope (Cleanups, CleanupLocation (fd));
661+ // ==== Case 'none') Create the remote instance
662+ {
663+ B.emitBlock (makeProxyBB);
664+ // ==== Create 'remote' distributed actor instance
512665
513666 // --- Call: _distributedActorRemoteInitialize(Self.self)
514667 auto builtinName = C.getIdentifier (
@@ -528,8 +681,32 @@ void SILGenFunction::emitDistributedActorFactory(FuncDecl *fd) {
528681 emitDistributedActorStore_transport (
529682 C, *this , /* actorSelf*/ remote, fd, transportArg);
530683
531- // ==== Return the fully initialized remote instance
532- B.createReturn (loc, remote);
684+ // ==== Branch to return the fully initialized remote instance
685+ B.createBranch (loc, returnBB, {remote});
686+ }
687+
688+ // --- Emit return logic
689+ // return <remote>
690+ {
691+ B.emitBlock (returnBB);
692+
693+ auto local = returnBB->createPhiArgument (returnTy, OwnershipKind::Owned);
694+
695+ Cleanups.emitCleanupsForReturn (CleanupLocation (loc), NotForUnwind);
696+ B.createReturn (loc, local);
697+ }
698+
699+ // --- Emit rethrow logic
700+ // throw error
701+ {
702+ B.emitBlock (errorBB);
703+
704+ auto error = errorBB->createPhiArgument (
705+ fnConv.getSILErrorType (F.getTypeExpansionContext ()),
706+ OwnershipKind::Owned);
707+
708+ Cleanups.emitCleanupsForReturn (CleanupLocation (loc), IsForUnwind);
709+ B.createThrow (loc, error);
533710 }
534711}
535712
@@ -563,9 +740,8 @@ void SILGenFunction::emitDistributedActor_resignAddress(
563740 getLoweredType (idVarDeclRef->getType ()));
564741
565742 // ==== locate: self.actorTransport
566- auto transportVarDeclRefs = cd->lookupDirect (ctx.Id_actorTransport );
567- assert (transportVarDeclRefs.size () == 1 );
568- auto *transportVarDeclRef = dyn_cast<VarDecl>(transportVarDeclRefs.front ());
743+ auto transportVarDeclRef = lookupActorTransportProperty (ctx, cd, selfValue);
744+
569745 auto transportRef =
570746 B.createRefElementAddr (Loc, selfValue, transportVarDeclRef,
571747 getLoweredType (transportVarDeclRef->getType ()));
0 commit comments