1111// ===----------------------------------------------------------------------===//
1212
1313#include " SILGenFunction.h"
14+ #include " SILGenFunctionBuilder.h"
1415#include " RValue.h"
1516#include " ArgumentScope.h"
1617#include " swift/AST/GenericSignature.h"
@@ -75,6 +76,13 @@ void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) {
7576 resultSelfValue = selfValue;
7677 }
7778
79+
80+ if (cd->isDistributedActor ()) {
81+ SILBasicBlock *continueBB = createBasicBlock ();
82+ injectDistributedActorDestructorLifecycleCall (dd, selfValue, continueBB);
83+ B.emitBlock (continueBB);
84+ }
85+
7886 ArgumentScope S (*this , Loc);
7987 ManagedValue borrowedValue =
8088 ManagedValue::forUnmanaged (resultSelfValue).borrow (*this , cleanupLoc);
@@ -101,6 +109,113 @@ void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) {
101109 B.createReturn (returnLoc, resultSelfValue);
102110}
103111
112+ void SILGenFunction::injectDistributedActorDestructorLifecycleCall (
113+ DestructorDecl *dd, SILValue selfValue, SILBasicBlock *continueBB) {
114+ ASTContext &ctx = getASTContext ();
115+
116+ auto cd = cast<ClassDecl>(dd->getDeclContext ());
117+ assert (cd->isDistributedActor () &&
118+ " only distributed actors have transport lifecycle hooks in deinit" );
119+
120+ RegularLocation Loc (dd);
121+ if (dd->isImplicit ())
122+ Loc.markAutoGenerated ();
123+
124+ auto selfDecl = dd->getImplicitSelfDecl ();
125+ auto selfManagedValue = ManagedValue::forUnmanaged (selfValue);
126+ auto selfType = selfDecl->getType ();
127+
128+ // ==== locate: self.actorAddress
129+ auto addressVarDeclRefs = cd->lookupDirect (ctx.Id_actorAddress );
130+ assert (addressVarDeclRefs.size () == 1 );
131+ auto *addressVarDeclRef = dyn_cast<VarDecl>(addressVarDeclRefs.front ());
132+ assert (addressVarDeclRef);
133+ auto addressRef =
134+ B.createRefElementAddr (Loc, selfValue, addressVarDeclRef,
135+ getLoweredType (addressVarDeclRef->getType ()));
136+
137+ // ==== locate: self.actorTransport
138+ auto transportVarDeclRefs = cd->lookupDirect (ctx.Id_actorTransport );
139+ assert (transportVarDeclRefs.size () == 1 );
140+ auto *transportVarDeclRef = dyn_cast<VarDecl>(transportVarDeclRefs.front ());
141+ auto transportRef =
142+ B.createRefElementAddr (Loc, selfValue, transportVarDeclRef,
143+ getLoweredType (transportVarDeclRef->getType ()));
144+
145+ // locate: self.transport.resignAddress(...)
146+ auto *transportDecl = ctx.getActorTransportDecl ();
147+ auto resignFnDecls = transportDecl->lookupDirect (ctx.Id_resignAddress );
148+ assert (resignFnDecls.size () == 1 );
149+ auto *resignFnDecl = resignFnDecls.front ();
150+ auto resignFnRef = SILDeclRef (resignFnDecl);
151+
152+ // we only transport.resignAddress if we are a local actor,
153+ // and thus the address was created by transport.assignAddress.
154+ auto isRemoteBB = createBasicBlock ();
155+ auto isLocalBB = createBasicBlock ();
156+
157+ // if __isRemoteActor(self) {
158+ // ...
159+ // } else {
160+ // ...
161+ // }
162+ {
163+ FuncDecl *isRemoteFn = ctx.getIsRemoteDistributedActor ();
164+ assert (isRemoteFn && " Could not find 'is remote' function, is the "
165+ " '_Distributed' module available?" );
166+
167+ ManagedValue selfAnyObject =
168+ B.createInitExistentialRef (Loc, getLoweredType (ctx.getAnyObjectType ()),
169+ CanType (selfType), selfManagedValue, {});
170+ auto result = emitApplyOfLibraryIntrinsic (
171+ Loc, isRemoteFn, SubstitutionMap (), {selfAnyObject}, SGFContext ());
172+
173+ SILValue isRemoteResult =
174+ std::move (result).forwardAsSingleValue (*this , Loc);
175+ SILValue isRemoteResultUnwrapped =
176+ emitUnwrapIntegerResult (Loc, isRemoteResult);
177+
178+ B.createCondBranch (Loc, isRemoteResultUnwrapped, isRemoteBB, isLocalBB);
179+ }
180+
181+ // if remote
182+ // === <noop>
183+ {
184+ B.emitBlock (isRemoteBB);
185+ // noop, remote actors don't do anything in their deinit
186+ B.createBranch (Loc, continueBB);
187+ }
188+
189+ // if local
190+ // === self.transport.resignAddress(self.address)
191+ {
192+ B.emitBlock (isLocalBB);
193+
194+ auto openedTransport =
195+ OpenedArchetypeType::get (transportVarDeclRef->getType ());
196+ auto transportAddr = B.createOpenExistentialAddr (
197+ Loc, /* operand=*/ transportRef, getLoweredType (openedTransport),
198+ OpenedExistentialAccess::Immutable);
199+
200+ auto resignFnType = SGM.M .Types .getConstantFunctionType (
201+ TypeExpansionContext::minimal (), resignFnRef);
202+
203+ auto witness = B.createWitnessMethod (
204+ Loc, openedTransport, ProtocolConformanceRef (transportDecl),
205+ resignFnRef, SILType::getPrimitiveObjectType (resignFnType));
206+
207+ auto subs = SubstitutionMap::getProtocolSubstitutions (
208+ transportDecl, openedTransport, ProtocolConformanceRef (transportDecl));
209+
210+ SmallVector<SILValue, 2 > params;
211+ params.push_back (addressRef);
212+ params.push_back (transportAddr); // self for the call, as last param
213+
214+ B.createApply (Loc, witness, subs, params);
215+ B.createBranch (Loc, continueBB);
216+ }
217+ }
218+
104219void SILGenFunction::emitDeallocatingDestructor (DestructorDecl *dd) {
105220 MagicFunctionName = DeclName (SGM.M .getASTContext ().getIdentifier (" deinit" ));
106221
0 commit comments