Skip to content

Commit 09c7a4e

Browse files
committed
[move-only] Also add support for enums as well.
1 parent b1738c6 commit 09c7a4e

File tree

2 files changed

+206
-20
lines changed

2 files changed

+206
-20
lines changed

lib/SILGen/SILGenDestructor.cpp

Lines changed: 81 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "swift/AST/Decl.h"
1919
#include "swift/AST/GenericSignature.h"
2020
#include "swift/AST/SubstitutionMap.h"
21+
#include "swift/SIL/SILBuilder.h"
2122
#include "swift/SIL/SILLinkage.h"
2223
#include "swift/SIL/SILMoveOnlyDeinit.h"
2324
#include "swift/SIL/SILValue.h"
@@ -490,24 +491,89 @@ void SILGenFunction::emitMoveOnlyMemberDestruction(SILValue selfValue,
490491
CleanupLocation cleanupLoc,
491492
SILBasicBlock *finishBB) {
492493
if (selfValue->getType().isAddress()) {
493-
for (VarDecl *vd : nom->getStoredProperties()) {
494-
const TypeLowering &ti = getTypeLowering(vd->getType());
495-
if (ti.isTrivial())
496-
continue;
494+
if (auto *structDecl = dyn_cast<StructDecl>(nom)) {
495+
for (VarDecl *vd : nom->getStoredProperties()) {
496+
const TypeLowering &ti = getTypeLowering(vd->getType());
497+
if (ti.isTrivial())
498+
continue;
499+
500+
SILValue addr = B.createStructElementAddr(
501+
cleanupLoc, selfValue, vd, ti.getLoweredType().getAddressType());
502+
addr = B.createBeginAccess(cleanupLoc, addr, SILAccessKind::Deinit,
503+
SILAccessEnforcement::Static,
504+
false /*noNestedConflict*/,
505+
false /*fromBuiltin*/);
506+
B.createDestroyAddr(cleanupLoc, addr);
507+
B.createEndAccess(cleanupLoc, addr, false /*is aborting*/);
508+
}
509+
} else {
510+
auto *origBlock = B.getInsertionBB();
511+
auto *enumDecl = cast<EnumDecl>(nom);
512+
SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 8>
513+
caseCleanups;
514+
auto *contBlock = createBasicBlock();
515+
516+
for (auto *enumElt : enumDecl->getAllElements()) {
517+
auto *enumBlock = createBasicBlock();
518+
SILBuilder builder(enumBlock, enumBlock->begin());
519+
520+
if (enumElt->hasAssociatedValues()) {
521+
auto *take = builder.createUncheckedTakeEnumDataAddr(
522+
cleanupLoc, selfValue, enumElt);
523+
builder.createDestroyAddr(cleanupLoc, take);
524+
}
525+
526+
// Branch to the continue trampoline block.
527+
builder.createBranch(cleanupLoc, contBlock);
528+
caseCleanups.emplace_back(enumElt, enumBlock);
529+
530+
// Set the insertion point to after this enum block so we insert the
531+
// next new block after this block.
532+
B.setInsertionPoint(enumBlock);
533+
}
497534

498-
SILValue addr = B.createStructElementAddr(
499-
cleanupLoc, selfValue, vd, ti.getLoweredType().getAddressType());
500-
addr = B.createBeginAccess(
501-
cleanupLoc, addr, SILAccessKind::Deinit, SILAccessEnforcement::Static,
502-
false /*noNestedConflict*/, false /*fromBuiltin*/);
503-
B.createDestroyAddr(cleanupLoc, addr);
504-
B.createEndAccess(cleanupLoc, addr, false /*is aborting*/);
535+
B.setInsertionPoint(origBlock);
536+
B.createSwitchEnumAddr(cleanupLoc, selfValue, nullptr, caseCleanups);
537+
B.setInsertionPoint(contBlock);
505538
}
506539
} else {
507-
auto *d =
508-
B.createDestructureStruct(cleanupLoc, selfValue, OwnershipKind::Owned);
509-
for (auto result : d->getResults()) {
510-
B.emitDestroyValueOperation(cleanupLoc, result);
540+
if (isa<StructDecl>(nom)) {
541+
auto *d = B.createDestructureStruct(cleanupLoc, selfValue,
542+
OwnershipKind::Owned);
543+
for (auto result : d->getResults()) {
544+
B.emitDestroyValueOperation(cleanupLoc, result);
545+
}
546+
} else {
547+
auto *origBlock = B.getInsertionBB();
548+
auto *enumDecl = dyn_cast<EnumDecl>(nom);
549+
SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 8>
550+
caseCleanups;
551+
auto *contBlock = createBasicBlock();
552+
553+
for (auto *enumElt : enumDecl->getAllElements()) {
554+
auto *enumBlock = createBasicBlock();
555+
SILBuilder builder(enumBlock, enumBlock->begin());
556+
557+
if (enumElt->hasAssociatedValues()) {
558+
auto caseType = selfValue->getType().getEnumElementType(
559+
enumElt, enumBlock->getParent());
560+
auto *phiArg =
561+
enumBlock->createPhiArgument(caseType, OwnershipKind::Owned);
562+
builder.emitDestroyValueOperation(cleanupLoc, phiArg);
563+
}
564+
565+
// Branch to the continue trampoline block.
566+
builder.createBranch(cleanupLoc, contBlock);
567+
caseCleanups.emplace_back(enumElt, enumBlock);
568+
569+
// Set the insertion point to after this enum block so we insert the
570+
// next new block after this block.
571+
B.setInsertionPoint(enumBlock);
572+
}
573+
574+
B.setInsertionPoint(origBlock);
575+
B.createSwitchEnum(cleanupLoc, selfValue, nullptr, caseCleanups);
576+
B.setInsertionPoint(contBlock);
511577
}
512578
}
513579

test/SILOptimizer/moveonly_deinit_insertion.sil

Lines changed: 125 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,26 @@ struct ThreeNonTrivialNoDeinit {
3737
var k2: Klass
3838
}
3939

40+
@_moveOnly enum TrivialMoveOnlyEnum {
41+
case first
42+
case second(Builtin.Int32)
43+
case third(Builtin.Int64, Builtin.Int64)
44+
deinit
45+
}
46+
47+
@_moveOnly enum NonTrivialMoveOnlyEnum {
48+
case first
49+
case second(Builtin.Int32)
50+
case third(Klass, Klass)
51+
case fourth(Builtin.Int64, Builtin.Int64)
52+
case fifth(TrivialMoveOnlyEnum)
53+
deinit
54+
}
55+
56+
//===----------------------------------------------------------------------===//
57+
// Object Tests
58+
//===----------------------------------------------------------------------===//
59+
4060
// CHECK-LABEL: sil [ossa] @klassTest : $@convention(thin) (@owned Klass) -> () {
4161
// CHECK: bb0([[ARG:%.*]] : @owned $Klass):
4262
// CHECK: [[FUNC:%.*]] = function_ref @$s4main5KlassCfD :
@@ -49,10 +69,6 @@ bb0(%0 : @owned $Klass):
4969
return %9999 : $()
5070
}
5171

52-
//===----------------------------------------------------------------------===//
53-
// Object Tests
54-
//===----------------------------------------------------------------------===//
55-
5672
// CHECK-LABEL: sil [ossa] @trivialStructTest : $@convention(thin) (@owned TrivialStruct) -> () {
5773
// CHECK: bb0([[ARG:%.*]] : @owned $TrivialStruct):
5874
// CHECK: [[FUNC:%.*]] = function_ref @$s4main13TrivialStructVfD :
@@ -87,6 +103,24 @@ bb0(%0 : @owned $ThreeNonTrivial):
87103
return %9999 : $()
88104
}
89105

106+
// CHECK-LABEL: sil [ossa] @trivialMoveOnlyEnum : $@convention(thin) (@owned TrivialMoveOnlyEnum) -> () {
107+
// CHECK: [[FUNC:%.*]] = function_ref @$s4main19TrivialMoveOnlyEnumOfD :
108+
// CHECK: apply [[FUNC]]([[ARG]])
109+
// CHECK: } // end sil function 'trivialMoveOnlyEnum'
110+
sil [ossa] @trivialMoveOnlyEnum : $@convention(thin) (@owned TrivialMoveOnlyEnum) -> () {
111+
bb0(%0 : @owned $TrivialMoveOnlyEnum):
112+
destroy_value %0 : $TrivialMoveOnlyEnum
113+
%9999 = tuple()
114+
return %9999 : $()
115+
}
116+
117+
sil [ossa] @nonTrivialMoveOnlyEnum : $@convention(thin) (@owned NonTrivialMoveOnlyEnum) -> () {
118+
bb0(%0 : @owned $NonTrivialMoveOnlyEnum):
119+
destroy_value %0 : $NonTrivialMoveOnlyEnum
120+
%9999 = tuple()
121+
return %9999 : $()
122+
}
123+
90124
//===----------------------------------------------------------------------===//
91125
// Var Tests
92126
//===----------------------------------------------------------------------===//
@@ -128,6 +162,32 @@ bb0(%0 : $*ThreeNonTrivial):
128162
return %9999 : $()
129163
}
130164

165+
// CHECK-LABEL: sil [ossa] @trivialMoveOnlyEnumArg : $@convention(thin) (@in TrivialMoveOnlyEnum) -> () {
166+
// CHECK: bb0([[ARG:%.*]] : $*TrivialMoveOnlyEnum):
167+
// CHECK: [[FUNC:%.*]] = function_ref @$s4main19TrivialMoveOnlyEnumOfD
168+
// CHECK: [[LOADED_VALUE:%.*]] = load [take] [[ARG]]
169+
// CHECK: apply [[FUNC]]([[LOADED_VALUE]])
170+
// CHECK: } // end sil function 'trivialMoveOnlyEnumArg'
171+
sil [ossa] @trivialMoveOnlyEnumArg : $@convention(thin) (@in TrivialMoveOnlyEnum) -> () {
172+
bb0(%0 : $*TrivialMoveOnlyEnum):
173+
destroy_addr %0 : $*TrivialMoveOnlyEnum
174+
%9999 = tuple()
175+
return %9999 : $()
176+
}
177+
178+
// CHECK-LABEL: sil [ossa] @nonTrivialMoveOnlyEnumAddrTest : $@convention(thin) (@in NonTrivialMoveOnlyEnum) -> () {
179+
// CHECK: bb0([[ARG:%.*]] : $*NonTrivialMoveOnlyEnum):
180+
// CHECK: [[FUNC:%.*]] = function_ref @$s4main22NonTrivialMoveOnlyEnumOfD :
181+
// CHECK: [[LOADED_VALUE:%.*]] = load [take] [[ARG]]
182+
// CHECK: apply [[FUNC]]([[LOADED_VALUE]])
183+
// CHECK: } // end sil function 'nonTrivialMoveOnlyEnumAddrTest'
184+
sil [ossa] @nonTrivialMoveOnlyEnumAddrTest : $@convention(thin) (@in NonTrivialMoveOnlyEnum) -> () {
185+
bb0(%0 : $*NonTrivialMoveOnlyEnum):
186+
destroy_addr %0 : $*NonTrivialMoveOnlyEnum
187+
%9999 = tuple()
188+
return %9999 : $()
189+
}
190+
131191
//===----------------------------------------------------------------------===//
132192
// Type Without Deinit
133193
//===----------------------------------------------------------------------===//
@@ -197,12 +257,64 @@ bb0(%0 : @owned $ThreeNonTrivial):
197257
return %7 : $()
198258
}
199259

260+
sil hidden [ossa] @$s4main19TrivialMoveOnlyEnumOfD : $@convention(method) (@owned TrivialMoveOnlyEnum) -> () {
261+
bb0(%0 : @owned $TrivialMoveOnlyEnum):
262+
debug_value %0 : $TrivialMoveOnlyEnum, let, name "self", argno 1, implicit
263+
switch_enum %0 : $TrivialMoveOnlyEnum, case #TrivialMoveOnlyEnum.first!enumelt: bb1, case #TrivialMoveOnlyEnum.second!enumelt: bb2, case #TrivialMoveOnlyEnum.third!enumelt: bb3
264+
265+
bb1:
266+
br bb4
267+
268+
bb2(%4 : $Builtin.Int32):
269+
br bb4
270+
271+
bb3(%6 : $(Builtin.Int64, Builtin.Int64)):
272+
br bb4
273+
274+
bb4:
275+
%8 = tuple ()
276+
return %8 : $()
277+
}
278+
279+
// CHECK-LABEL: sil hidden [ossa] @$s4main22NonTrivialMoveOnlyEnumOfD : $@convention(method) (@owned NonTrivialMoveOnlyEnum) -> () {
280+
// CHECK: bb5([[ARG:%.*]] : @owned $TrivialMoveOnlyEnum):
281+
// CHECK: [[FUNC_REF:%.*]] = function_ref @$s4main19TrivialMoveOnlyEnumOfD : $@convention(method) (@owned TrivialMoveOnlyEnum) -> ()
282+
// CHECK: apply [[FUNC_REF]]([[ARG]])
283+
// CHECK: } // end sil function '$s4main22NonTrivialMoveOnlyEnumOfD'
284+
sil hidden [ossa] @$s4main22NonTrivialMoveOnlyEnumOfD : $@convention(method) (@owned NonTrivialMoveOnlyEnum) -> () {
285+
bb0(%0 : @owned $NonTrivialMoveOnlyEnum):
286+
debug_value %0 : $NonTrivialMoveOnlyEnum, let, name "self", argno 1, implicit
287+
switch_enum %0 : $NonTrivialMoveOnlyEnum, case #NonTrivialMoveOnlyEnum.first!enumelt: bb1, case #NonTrivialMoveOnlyEnum.second!enumelt: bb2, case #NonTrivialMoveOnlyEnum.third!enumelt: bb3, case #NonTrivialMoveOnlyEnum.fourth!enumelt: bb4, case #NonTrivialMoveOnlyEnum.fifth!enumelt: bb5
288+
289+
bb1:
290+
br bb6
291+
292+
bb2(%4 : $Builtin.Int32):
293+
br bb6
294+
295+
296+
bb3(%6 : @owned $(Klass, Klass)):
297+
destroy_value %6 : $(Klass, Klass)
298+
br bb6
299+
300+
bb4(%9 : $(Builtin.Int64, Builtin.Int64)):
301+
br bb6
302+
303+
bb5(%11 : @owned $TrivialMoveOnlyEnum):
304+
destroy_value %11 : $TrivialMoveOnlyEnum
305+
br bb6
306+
307+
bb6:
308+
%14 = tuple ()
309+
return %14 : $()
310+
}
311+
200312
sil @$s4main5KlassCfD : $@convention(method) (@owned Klass) -> ()
201313
sil @$s4main5KlassCACycfc : $@convention(method) (@owned Klass) -> @owned Klass
202314
sil @$s4main5KlassCfd : $@convention(method) (@guaranteed Klass) -> @owned Builtin.NativeObject
203315

204316
sil_moveonlydeinit Klass {
205-
@$s4main5KlassCfD // Klass.__deallocating_deinit
317+
@$s4main5KlassCfD
206318
}
207319

208320
sil_moveonlydeinit TrivialStruct {
@@ -220,3 +332,11 @@ sil_moveonlydeinit ThreeNonTrivial {
220332
sil_vtable Klass {
221333
#Klass.deinit!deallocator: @$s4main5KlassCfD // Klass.__deallocating_deinit
222334
}
335+
336+
sil_moveonlydeinit TrivialMoveOnlyEnum {
337+
@$s4main19TrivialMoveOnlyEnumOfD
338+
}
339+
340+
sil_moveonlydeinit NonTrivialMoveOnlyEnum {
341+
@$s4main22NonTrivialMoveOnlyEnumOfD
342+
}

0 commit comments

Comments
 (0)