@@ -31,11 +31,8 @@ namespace {
31
31
// / A utility for verifying memory lifetime.
32
32
// /
33
33
// / The MemoryLifetime utility checks the lifetime of memory locations.
34
- // / This is limited to memory locations which are guaranteed to be not aliased,
35
- // / like @in or @inout parameters. Also, alloc_stack locations are handled.
36
- // /
37
- // / In addition to verification, the MemoryLifetime class can be used as utility
38
- // / (e.g. base class) for optimizations, which need to compute memory lifetime.
34
+ // / This is limited to memory locations which can be handled by
35
+ // / `MemoryLocations`.
39
36
class MemoryLifetimeVerifier {
40
37
41
38
using Bits = MemoryLocations::Bits;
@@ -178,6 +175,22 @@ static bool isTrivialEnumElem(EnumElementDecl *elem, SILType enumType,
178
175
enumType.getEnumElementType (elem, function).isTrivial (*function);
179
176
}
180
177
178
+ static bool injectsNoPayloadCase (InjectEnumAddrInst *IEAI) {
179
+ if (!IEAI->getElement ()->hasAssociatedValues ())
180
+ return true ;
181
+ SILType enumType = IEAI->getOperand ()->getType ();
182
+ SILFunction *function = IEAI->getFunction ();
183
+ SILType elemType = enumType.getEnumElementType (IEAI->getElement (), function);
184
+ // Handle empty types (e.g. the empty tuple) as no-payload.
185
+ return elemType.isEmpty (*function);
186
+ }
187
+
188
+ static bool isOrHasEnum (SILType type) {
189
+ return type.getASTType ().findIf ([](Type ty) {
190
+ return ty->getEnumOrBoundGenericEnum () != nullptr ;
191
+ });
192
+ }
193
+
181
194
bool MemoryLifetimeVerifier::storesTrivialEnum (int locIdx,
182
195
SILBasicBlock::reverse_iterator start,
183
196
SILBasicBlock::reverse_iterator end) {
@@ -191,7 +204,7 @@ bool MemoryLifetimeVerifier::storesTrivialEnum(int locIdx,
191
204
if (auto *SI = dyn_cast<StoreInst>(&inst)) {
192
205
const Location *loc = locations.getLocation (SI->getDest ());
193
206
if (loc && loc->isSubLocation (locIdx) &&
194
- SI->getSrc ()->getType (). getEnumOrBoundGenericEnum ( )) {
207
+ isOrHasEnum ( SI->getSrc ()->getType ())) {
195
208
return SI->getOwnershipQualifier () == StoreOwnershipQualifier::Trivial;
196
209
}
197
210
}
@@ -343,7 +356,7 @@ void MemoryLifetimeVerifier::initDataflowInBlock(SILBasicBlock *block,
343
356
case SILInstructionKind::InjectEnumAddrInst: {
344
357
auto *IEAI = cast<InjectEnumAddrInst>(&I);
345
358
int enumIdx = locations.getLocationIdx (IEAI->getOperand ());
346
- if (enumIdx >= 0 && !IEAI-> getElement ()-> hasAssociatedValues ( )) {
359
+ if (enumIdx >= 0 && injectsNoPayloadCase (IEAI )) {
347
360
// This is a bit tricky: an injected no-payload case means that the
348
361
// "full" enum is initialized. So, for the purpose of dataflow, we
349
362
// treat it like a full initialization of the payload data.
@@ -582,7 +595,7 @@ void MemoryLifetimeVerifier::checkBlock(SILBasicBlock *block, Bits &bits) {
582
595
case SILInstructionKind::InjectEnumAddrInst: {
583
596
auto *IEAI = cast<InjectEnumAddrInst>(&I);
584
597
int enumIdx = locations.getLocationIdx (IEAI->getOperand ());
585
- if (enumIdx >= 0 && !IEAI-> getElement ()-> hasAssociatedValues ( )) {
598
+ if (enumIdx >= 0 && injectsNoPayloadCase (IEAI )) {
586
599
// Again, an injected no-payload case is treated like a "full"
587
600
// initialization. See initDataflowInBlock().
588
601
requireBitsClear (bits & nonTrivialLocations, IEAI->getOperand (), &I);
0 commit comments