Skip to content

Commit a4f3f2f

Browse files
authoredAug 20, 2021
Merge pull request #38938 from drexin/wip-dist-resolve
[Distributed] Generate SIL for DistributedActor.resolve
2 parents 8cf6c2e + 3161d8f commit a4f3f2f

15 files changed

+231
-51
lines changed
 

‎lib/IRGen/GenBuiltin.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
390390

391391
if (Builtin.ID == BuiltinValueKind::InitializeDistributedRemoteActor) {
392392
auto actorMetatype = args.claimNext();
393-
emitDistributedActorInitializeRemote(IGF, actorMetatype, out);
393+
emitDistributedActorInitializeRemote(IGF, resultType, actorMetatype, out);
394394
return;
395395
}
396396

‎lib/IRGen/GenDistributed.cpp

+11-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "GenDistributed.h"
1818

1919
#include "BitPatternBuilder.h"
20+
#include "ClassTypeInfo.h"
2021
#include "ExtraInhabitants.h"
2122
#include "GenProto.h"
2223
#include "GenType.h"
@@ -32,7 +33,12 @@ using namespace swift;
3233
using namespace irgen;
3334

3435
llvm::Value *irgen::emitDistributedActorInitializeRemote(
35-
IRGenFunction &IGF, llvm::Value *actorMetatype, Explosion &out) {
36+
IRGenFunction &IGF, SILType selfType, llvm::Value *actorMetatype, Explosion &out) {
37+
auto &classTI = IGF.getTypeInfo(selfType).as<ClassTypeInfo>();
38+
auto &classLayout = classTI.getClassLayout(IGF.IGM, selfType,
39+
/*forBackwardDeployment=*/false);
40+
llvm::Type *destType = classLayout.getType()->getPointerTo();
41+
3642
auto fn = IGF.IGM.getDistributedActorInitializeRemoteFn();
3743
actorMetatype =
3844
IGF.Builder.CreateBitCast(actorMetatype, IGF.IGM.TypeMetadataPtrTy);
@@ -41,9 +47,11 @@ llvm::Value *irgen::emitDistributedActorInitializeRemote(
4147
call->setCallingConv(IGF.IGM.SwiftCC);
4248
call->setDoesNotThrow();
4349

44-
out.add(call);
50+
auto result = IGF.Builder.CreateBitCast(call, destType);
51+
52+
out.add(result);
4553

46-
return call;
54+
return result;
4755
}
4856

4957
void irgen::emitDistributedActorDestroy(IRGenFunction &IGF,

‎lib/IRGen/GenDistributed.h

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class IRGenFunction;
4343
/// Emit the '_distributedActorRemoteInitialize' call.
4444
llvm::Value *emitDistributedActorInitializeRemote(
4545
IRGenFunction &IGF,
46+
SILType selfType,
4647
llvm::Value *actorMetatype,
4748
Explosion &out);
4849

‎lib/SILGen/SILGenDistributed.cpp

+196-20
Original file line numberDiff line numberDiff line change
@@ -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

383417
void 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()));

‎lib/SILGen/SILGenFunction.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -514,17 +514,18 @@ void SILGenFunction::emitFunction(FuncDecl *fd) {
514514
emitProfilerIncrement(fd->getTypecheckedBody());
515515
emitProlog(captureInfo, fd->getParameters(), fd->getImplicitSelfDecl(), fd,
516516
fd->getResultInterfaceType(), fd->hasThrows(), fd->getThrowsLoc());
517-
prepareEpilog(true, fd->hasThrows(), CleanupLocation(fd));
518517

519518
if (fd->isDistributedActorFactory()) {
520519
// Synthesize the factory function body
521520
emitDistributedActorFactory(fd);
522521
} else {
522+
prepareEpilog(true, fd->hasThrows(), CleanupLocation(fd));
523+
523524
// Emit the actual function body as usual
524525
emitStmt(fd->getTypecheckedBody());
525-
}
526526

527-
emitEpilog(fd);
527+
emitEpilog(fd);
528+
}
528529

529530
mergeCleanupBlocks();
530531
}

‎stdlib/public/Distributed/ActorTransport.swift

+1-7
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public protocol ActorTransport: Sendable {
4848
///
4949
/// Detecting liveness of such remote actors shall be offered / by transport libraries
5050
/// by other means, such as "watching an actor for termination" or similar.
51-
func resolve<Act>(_ identity: AnyActorIdentity, as actorType: Act.Type) throws -> ActorResolved<Act> // TODO(distributed): make just optional
51+
func resolve<Act>(_ identity: AnyActorIdentity, as actorType: Act.Type) throws -> Act? // TODO(distributed): make just optional
5252
where Act: DistributedActor
5353

5454
// ==== ---------------------------------------------------------------------
@@ -73,9 +73,3 @@ public protocol ActorTransport: Sendable {
7373
func resignIdentity(_ id: AnyActorIdentity)
7474

7575
}
76-
77-
@available(SwiftStdlib 5.5, *)
78-
public enum ActorResolved<Act: DistributedActor> {
79-
case resolved(Act)
80-
case makeProxy
81-
}

0 commit comments

Comments
 (0)