Skip to content

Commit d7468b1

Browse files
committed
MemoryLifetimeVerifier: fix the check for "empty" types.
The MemoryLifetimeVerifier has to ignore locations with empty types, e.g. and empty tuple. So far, the check for empty types didn't check recursively, so it missed e.g. "((), ())"
1 parent 1baf009 commit d7468b1

File tree

2 files changed

+35
-9
lines changed

2 files changed

+35
-9
lines changed

lib/SIL/Utils/MemoryLocations.cpp

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,32 @@ static bool allUsesInSameBlock(AllocStackInst *ASI) {
6767
return numDeallocStacks == 1;
6868
}
6969

70-
static bool shouldTrackLocation(SILType ty, SILFunction *function) {
71-
// Ignore empty tuples and empty structs.
70+
/// We don't handle empty tuples and empty structs.
71+
///
72+
/// Locations with empty types don't even need a store to count as
73+
/// "initialized". We don't handle such cases.
74+
static bool isEmptyType(SILType ty, SILFunction *function) {
7275
if (auto tupleTy = ty.getAs<TupleType>()) {
73-
return tupleTy->getNumElements() != 0;
76+
// A tuple is empty if it either has no elements or if all elements are
77+
// empty.
78+
for (unsigned idx = 0, num = tupleTy->getNumElements(); idx < num; ++idx) {
79+
if (!isEmptyType(ty.getTupleElementType(idx), function))
80+
return false;
81+
}
82+
return true;
7483
}
75-
if (StructDecl *decl = ty.getStructOrBoundGenericStruct()) {
76-
return decl->getStoredProperties().size() != 0;
84+
if (StructDecl *structDecl = ty.getStructOrBoundGenericStruct()) {
85+
// Also, a struct is empty if it either has no fields or if all fields are
86+
// empty.
87+
SILModule &module = function->getModule();
88+
TypeExpansionContext typeEx = function->getTypeExpansionContext();
89+
for (VarDecl *field : structDecl->getStoredProperties()) {
90+
if (!isEmptyType(ty.getFieldType(field, module, typeEx), function))
91+
return false;
92+
}
93+
return true;
7794
}
78-
return true;
95+
return false;
7996
}
8097

8198
} // anonymous namespace
@@ -100,7 +117,7 @@ MemoryLocations::Location::Location(SILValue val, unsigned index, int parentIdx)
100117

101118
void MemoryLocations::Location::updateFieldCounters(SILType ty, int increment) {
102119
SILFunction *function = representativeValue->getFunction();
103-
if (shouldTrackLocation(ty, function)) {
120+
if (!isEmptyType(ty, function)) {
104121
numFieldsNotCoveredBySubfields += increment;
105122
if (!ty.isTrivial(*function))
106123
numNonTrivialFieldsNotCovered += increment;
@@ -198,7 +215,7 @@ void MemoryLocations::analyzeLocation(SILValue loc) {
198215
if (loc->getType().isTrivial(*function))
199216
return;
200217

201-
if (!shouldTrackLocation(loc->getType(), function))
218+
if (isEmptyType(loc->getType(), function))
202219
return;
203220

204221
unsigned currentLocIdx = locations.size();
@@ -376,7 +393,7 @@ bool MemoryLocations::analyzeAddrProjection(
376393
SingleValueInstruction *projection, unsigned parentLocIdx,unsigned fieldNr,
377394
SmallVectorImpl<SILValue> &collectedVals, SubLocationMap &subLocationMap) {
378395

379-
if (!shouldTrackLocation(projection->getType(), projection->getFunction()))
396+
if (isEmptyType(projection->getType(), projection->getFunction()))
380397
return false;
381398

382399
unsigned &subLocIdx = subLocationMap[std::make_pair(parentLocIdx, fieldNr)];

test/SIL/memory_lifetime.sil

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,3 +630,12 @@ bb0(%0 : $*T):
630630
return %5 : $()
631631
}
632632

633+
sil [ossa] @test_ignore_empty_types : $@convention(thin) (Int, @guaranteed @callee_guaranteed (@in_guaranteed (Int, ((), ()))) -> Int) -> Int {
634+
bb0(%0 : $Int, %1 : @guaranteed $@callee_guaranteed (@in_guaranteed (Int, ((), ()))) -> Int):
635+
%2 = alloc_stack $(Int, ((), ()))
636+
%3 = tuple_element_addr %2 : $*(Int, ((), ())), 0
637+
store %0 to [trivial] %3 : $*Int
638+
%5 = apply %1(%2) : $@callee_guaranteed (@in_guaranteed (Int, ((), ()))) -> Int
639+
dealloc_stack %2 : $*(Int, ((), ()))
640+
return %5 : $Int
641+
}

0 commit comments

Comments
 (0)