Skip to content

Commit 9a8af70

Browse files
committed
[move-only] Teach SILGen how to emit deinits for nominal non-class move only types.
Even though with this change we emit the deinit, it isn't used yet since we still need to implement the move only deinit table/teach the checker how to call these/teach IRGen how to call this from the destroying value witness.
1 parent ffc6f20 commit 9a8af70

File tree

5 files changed

+145
-15
lines changed

5 files changed

+145
-15
lines changed

lib/SILGen/SILGen.cpp

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#define DEBUG_TYPE "silgen"
14+
1415
#include "ManagedValue.h"
1516
#include "RValue.h"
1617
#include "SILGenFunction.h"
1718
#include "SILGenFunctionBuilder.h"
1819
#include "Scope.h"
20+
#include "swift/AST/Decl.h"
1921
#include "swift/AST/DiagnosticsSIL.h"
2022
#include "swift/AST/Evaluator.h"
2123
#include "swift/AST/GenericEnvironment.h"
@@ -26,6 +28,7 @@
2628
#include "swift/AST/PropertyWrappers.h"
2729
#include "swift/AST/ProtocolConformance.h"
2830
#include "swift/AST/ResilienceExpansion.h"
31+
#include "swift/AST/SILGenRequests.h"
2932
#include "swift/AST/SourceFile.h"
3033
#include "swift/AST/TypeCheckRequests.h"
3134
#include "swift/Basic/Statistic.h"
@@ -34,7 +37,6 @@
3437
#include "swift/SIL/SILArgument.h"
3538
#include "swift/SIL/SILDebugScope.h"
3639
#include "swift/SIL/SILProfiler.h"
37-
#include "swift/AST/SILGenRequests.h"
3840
#include "swift/Serialization/SerializedModuleLoader.h"
3941
#include "swift/Serialization/SerializedSILLoader.h"
4042
#include "swift/Strings.h"
@@ -1085,15 +1087,17 @@ void SILGenModule::emitFunctionDefinition(SILDeclRef constant, SILFunction *f) {
10851087

10861088
case SILDeclRef::Kind::Deallocator: {
10871089
auto *dd = cast<DestructorDecl>(constant.getDecl());
1088-
auto *cd = cast<ClassDecl>(dd->getDeclContext());
1089-
1090-
if (usesObjCAllocator(cd)) {
1091-
preEmitFunction(constant, f, dd);
1092-
PrettyStackTraceSILFunction X("silgen emitDestructor -dealloc", f);
1093-
f->createProfiler(dd, constant);
1094-
SILGenFunction(*this, *f, dd).emitObjCDestructor(constant);
1095-
postEmitFunction(constant, f);
1096-
return;
1090+
auto *nom = dd->getDeclContext();
1091+
1092+
if (auto *cd = dyn_cast<ClassDecl>(nom)) {
1093+
if (usesObjCAllocator(cd)) {
1094+
preEmitFunction(constant, f, dd);
1095+
PrettyStackTraceSILFunction X("silgen emitDestructor -dealloc", f);
1096+
f->createProfiler(dd, constant);
1097+
SILGenFunction(*this, *f, dd).emitObjCDestructor(constant);
1098+
postEmitFunction(constant, f);
1099+
return;
1100+
}
10971101
}
10981102

10991103
auto loc = RegularLocation::getAutoGeneratedLocation(dd);
@@ -1605,6 +1609,17 @@ void SILGenModule::emitDestructor(ClassDecl *cd, DestructorDecl *dd) {
16051609
}
16061610
}
16071611

1612+
void SILGenModule::emitMoveOnlyDestructor(NominalTypeDecl *cd,
1613+
DestructorDecl *dd) {
1614+
assert(cd->isMoveOnly());
1615+
1616+
emitAbstractFuncDecl(dd);
1617+
1618+
// Emit the deallocating destructor.
1619+
SILDeclRef deallocator(dd, SILDeclRef::Kind::Deallocator);
1620+
emitFunctionDefinition(deallocator, getFunction(deallocator, ForDefinition));
1621+
}
1622+
16081623
void SILGenModule::emitDefaultArgGenerator(SILDeclRef constant,
16091624
ParamDecl *param) {
16101625
switch (param->getDefaultArgumentKind()) {

lib/SILGen/SILGen.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,8 +312,15 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
312312
/// Generates code for the given class's destructor and adds
313313
/// the SILFunction to the current SILModule under the name
314314
/// SILDeclRef(cd, Destructor).
315+
///
316+
/// TODO: Rename to emitClassDestructor.
315317
void emitDestructor(ClassDecl *cd, DestructorDecl *dd);
316318

319+
/// Generates code for the given move only nominal type's destructor and adds
320+
/// the SILFunction to the current SILModule under the name SILDeclRef(nd,
321+
/// dd).
322+
void emitMoveOnlyDestructor(NominalTypeDecl *nd, DestructorDecl *dd);
323+
317324
/// Emits the default argument generator with the given expression.
318325
void emitDefaultArgGenerator(SILDeclRef constant, ParamDecl *param);
319326

lib/SILGen/SILGenDestructor.cpp

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
#include "SILGenFunction.h"
1616
#include "SILGenFunctionBuilder.h"
1717
#include "SwitchEnumBuilder.h"
18+
#include "swift/AST/Decl.h"
1819
#include "swift/AST/GenericSignature.h"
1920
#include "swift/AST/SubstitutionMap.h"
21+
#include "swift/SIL/SILValue.h"
2022
#include "swift/SIL/TypeLowering.h"
2123
#include "llvm/ADT/SmallSet.h"
2224

@@ -30,7 +32,7 @@ void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) {
3032
if (dd->isImplicit())
3133
Loc.markAutoGenerated();
3234

33-
auto cd = cast<ClassDecl>(dd->getDeclContext());
35+
auto cd = cast<ClassDecl>(dd->getDeclContext()->getSelfNominalTypeDecl());
3436
auto &C = cd->getASTContext();
3537
SILValue selfValue = emitSelfDecl(dd->getImplicitSelfDecl());
3638

@@ -159,6 +161,14 @@ void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) {
159161
}
160162

161163
void SILGenFunction::emitDeallocatingDestructor(DestructorDecl *dd) {
164+
auto *nom = dd->getDeclContext()->getSelfNominalTypeDecl();
165+
if (isa<ClassDecl>(nom))
166+
return emitDeallocatingClassDestructor(dd);
167+
assert(nom->isMoveOnly());
168+
return emitDeallocatingMoveOnlyDestructor(dd);
169+
}
170+
171+
void SILGenFunction::emitDeallocatingClassDestructor(DestructorDecl *dd) {
162172
MagicFunctionName = DeclName(SGM.M.getASTContext().getIdentifier("deinit"));
163173

164174
// The deallocating destructor is always auto-generated.
@@ -212,6 +222,42 @@ void SILGenFunction::emitDeallocatingDestructor(DestructorDecl *dd) {
212222
B.createReturn(loc, emitEmptyTuple(loc));
213223
}
214224

225+
void SILGenFunction::emitDeallocatingMoveOnlyDestructor(DestructorDecl *dd) {
226+
MagicFunctionName = DeclName(SGM.M.getASTContext().getIdentifier("deinit"));
227+
228+
RegularLocation loc(dd);
229+
if (dd->isImplicit())
230+
loc.markAutoGenerated();
231+
232+
// Emit the prolog.
233+
auto selfValue = emitSelfDecl(dd->getImplicitSelfDecl());
234+
235+
// Create a basic block to jump to for the implicit destruction behavior
236+
// of releasing the elements and calling the superclass destructor.
237+
// We won't actually emit the block until we finish with the destructor body.
238+
prepareEpilog(None, false, CleanupLocation(loc));
239+
240+
auto cleanupLoc = CleanupLocation(loc);
241+
242+
emitProfilerIncrement(dd->getTypecheckedBody());
243+
emitStmt(dd->getTypecheckedBody());
244+
245+
Optional<SILValue> maybeReturnValue;
246+
SILLocation returnLoc(loc);
247+
std::tie(maybeReturnValue, returnLoc) = emitEpilogBB(loc);
248+
249+
if (!maybeReturnValue)
250+
return;
251+
252+
// Clean up our members, consuming our +1 self value as we do it.
253+
emitMoveOnlyMemberDestruction(selfValue,
254+
dd->getDeclContext()->getSelfNominalTypeDecl(),
255+
cleanupLoc, nullptr);
256+
257+
// Return.
258+
B.createReturn(loc, emitEmptyTuple(loc));
259+
}
260+
215261
void SILGenFunction::emitIVarDestroyer(SILDeclRef ivarDestroyer) {
216262
auto cd = cast<ClassDecl>(ivarDestroyer.getDecl());
217263
RegularLocation loc(cd);
@@ -440,6 +486,39 @@ void SILGenFunction::emitClassMemberDestruction(ManagedValue selfValue,
440486
}
441487
}
442488

489+
void SILGenFunction::emitMoveOnlyMemberDestruction(SILValue selfValue,
490+
NominalTypeDecl *nom,
491+
CleanupLocation cleanupLoc,
492+
SILBasicBlock *finishBB) {
493+
if (selfValue->getType().isAddress()) {
494+
for (VarDecl *vd : nom->getStoredProperties()) {
495+
const TypeLowering &ti = getTypeLowering(vd->getType());
496+
if (ti.isTrivial())
497+
continue;
498+
499+
SILValue addr = B.createStructElementAddr(
500+
cleanupLoc, selfValue, vd, ti.getLoweredType().getAddressType());
501+
addr = B.createBeginAccess(
502+
cleanupLoc, addr, SILAccessKind::Deinit, SILAccessEnforcement::Static,
503+
false /*noNestedConflict*/, false /*fromBuiltin*/);
504+
B.createDestroyAddr(cleanupLoc, addr);
505+
B.createEndAccess(cleanupLoc, addr, false /*is aborting*/);
506+
}
507+
} else {
508+
auto *d =
509+
B.createDestructureStruct(cleanupLoc, selfValue, OwnershipKind::Owned);
510+
for (auto result : d->getResults()) {
511+
B.emitDestroyValueOperation(cleanupLoc, result);
512+
}
513+
}
514+
515+
if (finishBB)
516+
B.createBranch(cleanupLoc, finishBB);
517+
518+
if (finishBB)
519+
B.emitBlock(finishBB);
520+
}
521+
443522
void SILGenFunction::emitObjCDestructor(SILDeclRef dtor) {
444523
auto dd = cast<DestructorDecl>(dtor.getDecl());
445524
auto cd = cast<ClassDecl>(dd->getDeclContext());

lib/SILGen/SILGenFunction.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
634634
void emitFunction(FuncDecl *fd);
635635
/// Emits code for a ClosureExpr.
636636
void emitClosure(AbstractClosureExpr *ce);
637+
637638
/// Generates code for a class destroying destructor. This
638639
/// emits the body code from the DestructorDecl, calls the base class
639640
/// destructor, then implicitly releases the elements of the class.
@@ -646,10 +647,18 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
646647
/// Generate code into @main for starting the async main on the main thread.
647648
void emitAsyncMainThreadStart(SILDeclRef entryPoint);
648649

650+
/// Generates code for class/move only deallocating destructor. This calls the
651+
/// destroying destructor and then deallocates 'self'.
652+
void emitDeallocatingDestructor(DestructorDecl *dd);
653+
649654
/// Generates code for a class deallocating destructor. This
650655
/// calls the destroying destructor and then deallocates 'self'.
651-
void emitDeallocatingDestructor(DestructorDecl *dd);
652-
656+
void emitDeallocatingClassDestructor(DestructorDecl *dd);
657+
658+
/// Generates code for the deinit of the move only type and destroys all of
659+
/// the fields.
660+
void emitDeallocatingMoveOnlyDestructor(DestructorDecl *dd);
661+
653662
/// Generates code for a struct constructor.
654663
/// This allocates the new 'self' value, emits the
655664
/// body code, then returns the final initialized 'self'.
@@ -692,6 +701,18 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
692701
CleanupLocation cleanupLoc,
693702
SILBasicBlock* finishBB);
694703

704+
/// Generates code to destroy the instance variables of a move only non-class
705+
/// nominal type.
706+
///
707+
/// \param selfValue The 'self' value.
708+
/// \param nd The nominal declaration whose members are being destroyed.
709+
/// \param finishBB If set, used as the basic block after members have been
710+
/// destroyed, and we're ready to perform final cleanups
711+
/// before returning.
712+
void emitMoveOnlyMemberDestruction(SILValue selfValue, NominalTypeDecl *nd,
713+
CleanupLocation cleanupLoc,
714+
SILBasicBlock *finishBB);
715+
695716
/// Generates code to destroy linearly recursive data structures, without
696717
/// building up the call stack.
697718
///

lib/SILGen/SILGenType.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,9 +1141,17 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {
11411141
!isa<ProtocolDecl>(cd->getDeclContext()))
11421142
SGM.emitObjCConstructorThunk(cd);
11431143
}
1144+
11441145
void visitDestructorDecl(DestructorDecl *dd) {
1145-
assert(isa<ClassDecl>(theType) && "destructor in a non-class type");
1146-
SGM.emitDestructor(cast<ClassDecl>(theType), dd);
1146+
if (auto *cd = dyn_cast<ClassDecl>(theType))
1147+
return SGM.emitDestructor(cast<ClassDecl>(theType), dd);
1148+
if (auto *nom = dyn_cast<NominalTypeDecl>(theType)) {
1149+
if (nom->isMoveOnly()) {
1150+
return SGM.emitMoveOnlyDestructor(nom, dd);
1151+
}
1152+
}
1153+
assert(isa<ClassDecl>(theType) &&
1154+
"destructor in a non-class, non-moveonly type");
11471155
}
11481156

11491157
void visitEnumCaseDecl(EnumCaseDecl *ecd) {}

0 commit comments

Comments
 (0)