@@ -197,110 +197,64 @@ void SILGenFunction::emitIVarDestroyer(SILDeclRef ivarDestroyer) {
197197 emitEpilog (loc);
198198}
199199
200+ void SILGenFunction::destroyClassMember (SILLocation cleanupLoc,
201+ ManagedValue selfValue, VarDecl *D) {
202+ const TypeLowering &ti = getTypeLowering (D->getType ());
203+ if (!ti.isTrivial ()) {
204+ SILValue addr =
205+ B.createRefElementAddr (cleanupLoc, selfValue.getValue (), D,
206+ ti.getLoweredType ().getAddressType ());
207+ addr = B.createBeginAccess (
208+ cleanupLoc, addr, SILAccessKind::Deinit, SILAccessEnforcement::Static,
209+ false /* noNestedConflict*/ , false /* fromBuiltin*/ );
210+ B.createDestroyAddr (cleanupLoc, addr);
211+ B.createEndAccess (cleanupLoc, addr, false /* is aborting*/ );
212+ }
213+ }
214+
200215void SILGenFunction::emitClassMemberDestruction (ManagedValue selfValue,
201216 ClassDecl *cd,
202217 CleanupLocation cleanupLoc) {
203218 assert (selfValue.getOwnershipKind () == OwnershipKind::Guaranteed);
204- ASTContext &ctx = getASTContext ();
205-
206- auto loc = SILLocation (cd);
207- loc.markAutoGenerated ();
208219
220+ // / If this ClassDecl is a distributed actor, we must synthesise another code
221+ // / path for deallocating a 'remote' actor. In that case, these basic blocks
222+ // / are used to return to the "normal" (i.e. 'local' instance) destruction.
223+ // /
224+ // / For other cases, the basic blocks are not necessary and the destructor
225+ // / can just emit all the normal destruction code right into the current block.
226+ // If set, used as the basic block for the destroying of all members.
209227 SILBasicBlock* normalMemberDestroyBB = nullptr ;
210- SILBasicBlock* returnBB = nullptr ;
211-
212- auto destroyVar = [&](VarDecl *vd) {
213- const TypeLowering &ti = getTypeLowering (vd->getType ());
214- if (!ti.isTrivial ()) {
215- SILValue addr =
216- B.createRefElementAddr (cleanupLoc, selfValue.getValue (), vd,
217- ti.getLoweredType ().getAddressType ());
218- addr = B.createBeginAccess (
219- cleanupLoc, addr, SILAccessKind::Deinit, SILAccessEnforcement::Static,
220- false /* noNestedConflict*/ , false /* fromBuiltin*/ );
221- B.createDestroyAddr (cleanupLoc, addr);
222- B.createEndAccess (cleanupLoc, addr, false /* is aborting*/ );
223- }
224- };
228+ // If set, used as the basic block after members have been destroyed,
229+ // and we're ready to perform final cleanups before returning.
230+ SILBasicBlock* finishBB = nullptr ;
225231
232+ // / A distributed actor may be 'remote' in which case there is no need to
233+ // / destroy "all" members, because they never had storage to begin with.
226234 if (cd->isDistributedActor ()) {
227- auto selfTy = cd->getDeclaredInterfaceType ();
228-
229- Scope scope (Cleanups, CleanupLocation (loc));
230-
231- auto isLocalBB = createBasicBlock ();
235+ finishBB = createBasicBlock ();
232236 normalMemberDestroyBB = createBasicBlock ();
233- auto remoteMemberDestroyBB = createBasicBlock ();
234- returnBB = createBasicBlock ();
235-
236- // TODO(distributed): de-duplicate with the thunk logic in SILGenDistributed
237- // if __isRemoteActor(self) {
238- // ...
239- // } else {
240- // ...
241- // }
242- {
243- FuncDecl *isRemoteFn = ctx.getIsRemoteDistributedActor ();
244- assert (isRemoteFn && " Could not find 'is remote' function, is the "
245- " '_Distributed' module available?" );
246-
247- ManagedValue selfAnyObject =
248- B.createInitExistentialRef (loc, getLoweredType (ctx.getAnyObjectType ()),
249- CanType (selfTy), selfValue, {});
250- auto result = emitApplyOfLibraryIntrinsic (
251- loc, isRemoteFn, SubstitutionMap (), {selfAnyObject}, SGFContext ());
252-
253- SILValue isRemoteResult =
254- std::move (result).forwardAsSingleValue (*this , loc);
255- SILValue isRemoteResultUnwrapped =
256- emitUnwrapIntegerResult (loc, isRemoteResult);
257-
258- B.createCondBranch (loc, isRemoteResultUnwrapped, remoteMemberDestroyBB, isLocalBB);
259- }
260237
261- // // if __isRemoteActor(self)
262- // {
263- // // destroy only self.id and self.actorTransport
264- // }
265- {
266- B.emitBlock (remoteMemberDestroyBB);
267-
268- for (VarDecl *vd : cd->getStoredProperties ()) {
269- if (!vd->getAttrs ().hasAttribute <DistributedActorIndependentAttr>())
270- continue ;
271-
272- destroyVar (vd);
273- }
274-
275- B.createBranch (loc, returnBB);
276- }
277-
278- // // else (local distributed actor)
279- // {
280- // <continue normal deinit>
281- // }
282- {
283- B.emitBlock (isLocalBB);
284-
285- B.createBranch (loc, normalMemberDestroyBB);
286- }
238+ emitDistributedActorClassMemberDestruction (cleanupLoc, selfValue, cd,
239+ normalMemberDestroyBB,
240+ finishBB);
287241 }
288242
243+ // / Destroy all members.
289244 {
290245 if (normalMemberDestroyBB)
291246 B.emitBlock (normalMemberDestroyBB);
292247
293248 for (VarDecl *vd : cd->getStoredProperties ())
294- destroyVar ( vd);
249+ destroyClassMember (cleanupLoc, selfValue, vd);
295250
296- if (returnBB )
297- B.createBranch (loc, returnBB );
251+ if (finishBB )
252+ B.createBranch (cleanupLoc, finishBB );
298253 }
299254
300255 {
301- if (returnBB)
302- B.emitBlock (returnBB);
303-
256+ if (finishBB)
257+ B.emitBlock (finishBB);
304258
305259 if (cd->isRootDefaultActor ()) {
306260 // TODO(distributed): we may need to call the distributed destroy here instead?
0 commit comments