Skip to content

Commit b9c8e57

Browse files
committed
MemoryLifetimeVerifier: also verify locations with trivial types.
It helps to catch more problems
1 parent d7468b1 commit b9c8e57

14 files changed

+66
-27
lines changed

include/swift/SIL/MemoryLocations.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,13 @@ class MemoryLocations {
198198
/// init_existential_addr and open_existential_addr.
199199
bool handleNonTrivialProjections;
200200

201+
/// If true, also analyze trivial memory locations.
202+
bool handleTrivialLocations;
203+
201204
public:
202-
MemoryLocations(bool handleNonTrivialProjections) :
203-
handleNonTrivialProjections(handleNonTrivialProjections) {}
205+
MemoryLocations(bool handleNonTrivialProjections, bool handleTrivialLocations) :
206+
handleNonTrivialProjections(handleNonTrivialProjections),
207+
handleTrivialLocations(handleTrivialLocations) {}
204208

205209
MemoryLocations(const MemoryLocations &) = delete;
206210
MemoryLocations &operator=(const MemoryLocations &) = delete;
@@ -287,9 +291,6 @@ class MemoryLocations {
287291
/// Debug dump the MemoryLifetime internals.
288292
void dump() const;
289293

290-
/// Debug dump a bit set .
291-
static void dumpBits(const Bits &bits);
292-
293294
private:
294295
/// Clears all datastructures, except singleBlockLocations;
295296
void clear();

lib/SIL/Utils/MemoryLocations.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ void MemoryLocations::analyzeLocation(SILValue loc) {
212212
// Ignore trivial types to keep the number of locations small. Trivial types
213213
// are not interesting anyway, because such memory locations are not
214214
// destroyed.
215-
if (loc->getType().isTrivial(*function))
215+
if (!handleTrivialLocations && loc->getType().isTrivial(*function))
216216
return;
217217

218218
if (isEmptyType(loc->getType(), function))

lib/SIL/Verifier/MemoryLifetimeVerifier.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ class MemoryLifetimeVerifier {
133133

134134
public:
135135
MemoryLifetimeVerifier(SILFunction *function) :
136-
function(function), locations(/*handleNonTrivialProjections*/ true) {}
136+
function(function), locations(/*handleNonTrivialProjections*/ true,
137+
/*handleTrivialLocations*/ true) {}
137138

138139
/// The main entry point to verify the lifetime of all memory locations in
139140
/// the function.
@@ -593,7 +594,7 @@ void MemoryLifetimeVerifier::checkBlock(SILBasicBlock *block, Bits &bits) {
593594
case SILInstructionKind::InitExistentialAddrInst:
594595
case SILInstructionKind::InitEnumDataAddrInst: {
595596
SILValue addr = I.getOperand(0);
596-
requireBitsClear(bits, addr, &I);
597+
requireBitsClear(bits & nonTrivialLocations, addr, &I);
597598
requireNoStoreBorrowLocation(addr, &I);
598599
break;
599600
}
@@ -701,9 +702,17 @@ void MemoryLifetimeVerifier::checkFuncArgument(Bits &bits, Operand &argumentOp,
701702
break;
702703
case SILArgumentConvention::Indirect_In_Guaranteed:
703704
case SILArgumentConvention::Indirect_Inout:
704-
case SILArgumentConvention::Indirect_InoutAliasable:
705705
requireBitsSet(bits, argumentOp.get(), applyInst);
706706
break;
707+
case SILArgumentConvention::Indirect_InoutAliasable:
708+
// We don't require any locations to be initialized for a partial_apply
709+
// which takes an inout_aliasable argument. This is used for implicit
710+
// closures (e.g. for the Bool '||' and '&&' operator arguments). Such
711+
// closures capture the whole "self". When this is done in an initializer
712+
// it can happen that not all fields of "self" are initialized, yet.
713+
if (!isa<PartialApplyInst>(applyInst))
714+
requireBitsSet(bits, argumentOp.get(), applyInst);
715+
break;
707716
case SILArgumentConvention::Direct_Owned:
708717
case SILArgumentConvention::Direct_Unowned:
709718
case SILArgumentConvention::Direct_Guaranteed:

lib/SILOptimizer/Transforms/DestroyHoisting.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,9 @@ class DestroyHoisting {
127127
function(function),
128128
// We currently don't handle enum and existential projections, because they
129129
// cannot be re-created easily. We could support this in future.
130-
locations(/*handleNonTrivialProjections*/ false), DA(DA) {}
130+
locations(/*handleNonTrivialProjections*/ false,
131+
/*handleTrivialLocations*/ false),
132+
DA(DA) {}
131133

132134
bool hoistDestroys();
133135
};

test/Reflection/capture_descriptors.sil

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,11 @@ bb0(%i : $*T, %b : @owned $<τ_0_0> { var τ_0_0 } <U>):
7171
return %12 : $()
7272
}
7373

74-
sil [ossa] @concrete_caller2 : $@convention(thin) () -> @owned @callee_guaranteed () -> () {
75-
bb0:
74+
sil [ossa] @concrete_caller2 : $@convention(thin) (Int) -> @owned @callee_guaranteed () -> () {
75+
bb0(%0 : $Int):
7676
%f = function_ref @generic_callee2 : $@convention(thin) <T, U> (@in T, @owned <τ_0_0> { var τ_0_0 } <U>) -> ()
7777
%i = alloc_stack $Int
78+
store %0 to [trivial] %i : $*Int
7879
%b = alloc_box $<τ_0_0> { var τ_0_0 } <String>
7980
%c = partial_apply [callee_guaranteed] %f<Int, String>(%i, %b) : $@convention(thin) <T, U> (@in T, @owned <τ_0_0> { var τ_0_0 } <U>) -> ()
8081
dealloc_stack %i : $*Int

test/SIL/memory_lifetime_failures.sil

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,3 +525,16 @@ bb0:
525525
return %5 : $()
526526
}
527527

528+
sil @modify_bool : $@convention(thin) (@inout_aliasable Bool) -> ()
529+
530+
// CHECK: SIL memory lifetime failure in @test_trivial_alloc_stack: memory is not initialized, but should
531+
sil [ossa] @test_trivial_alloc_stack : $@convention(thin) (Bool) -> () {
532+
bb0(%0 : $Bool):
533+
%1 = alloc_stack $Bool
534+
store %0 to [trivial] %1 : $*Bool
535+
dealloc_stack %1 : $*Bool
536+
%8 = function_ref @modify_bool : $@convention(thin) (@inout_aliasable Bool) -> ()
537+
%9 = apply %8(%1) : $@convention(thin) (@inout_aliasable Bool) -> ()
538+
%10 = tuple ()
539+
return %10 : $()
540+
}

test/SILOptimizer/abcopts_ossa_guaranteed.sil

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ bb0(%0 : $*ArrayInt, %1 : $*ArrayInt):
137137
// Not redundant same index and array but append in between.
138138
%17 = function_ref @append : $@convention(method) (@in Int32, @inout ArrayInt) -> ()
139139
%18 = alloc_stack $Int32
140+
store %i2 to [trivial] %18 : $*Int32
140141
%19 = apply %17(%18, %0) : $@convention(method) (@in Int32, @inout ArrayInt) -> ()
141142
%20 = apply %func(%i1, %102, %2) : $@convention(method) (Int32, Bool, @guaranteed ArrayInt) -> _DependenceToken
142143
// CHECK: apply [[CHECKBOUNDS]]([[IDX1]], {{.*}}[[LD1]]
@@ -351,6 +352,7 @@ bb2:
351352
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
352353
%117 = function_ref @append : $@convention(method) (@in Int32, @inout ArrayInt) -> ()
353354
%118 = alloc_stack $Int32
355+
store %0 to [trivial] %118 : $*Int32
354356
%119 = apply %117(%118, %24) : $@convention(method) (@in Int32, @inout ArrayInt) -> ()
355357
%120 = apply %52(%37, %101, %3) : $@convention(method) (Int32, Bool, @guaranteed ArrayInt) -> _DependenceToken
356358
dealloc_stack %118 : $*Int32

test/SILOptimizer/abcopts_ossa_owned.sil

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ bb0(%0 : $*ArrayInt, %1 : $*ArrayInt):
143143
// Not redundant same index and array but append in between.
144144
%17 = function_ref @append : $@convention(method) (@in Int32, @inout ArrayInt) -> ()
145145
%18 = alloc_stack $Int32
146+
store %i2 to [trivial] %18 : $*Int32
146147
%19 = apply %17(%18, %0) : $@convention(method) (@in Int32, @inout ArrayInt) -> ()
147148
%copy2_10 = copy_value %2 : $ArrayInt
148149
%20 = apply %func(%i1, %102, %copy2_10) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken
@@ -377,6 +378,7 @@ bb2:
377378
%21 = tuple_extract %20 : $(Builtin.Int32, Builtin.Int1), 0
378379
%117 = function_ref @append : $@convention(method) (@in Int32, @inout ArrayInt) -> ()
379380
%118 = alloc_stack $Int32
381+
store %0 to [trivial] %118 : $*Int32
380382
%119 = apply %117(%118, %24) : $@convention(method) (@in Int32, @inout ArrayInt) -> ()
381383
%121 = load [copy] %24 : $*ArrayInt
382384
%120 = apply %52(%37, %101, %121) : $@convention(method) (Int32, Bool, @owned ArrayInt) -> _DependenceToken

test/SILOptimizer/capture_promotion_generic_context.sil

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ bb1(%f : $@callee_guaranteed @substituted <A, B> (@in_guaranteed A) -> @out B fo
9696

9797
bb2(%default : @guaranteed $E<(R<T>)->Int>):
9898
end_borrow %e : $E<(R<T>)->Int>
99+
copy_addr %1 to %result : $*Int
99100
br exit
100101

101102
exit:
@@ -113,7 +114,7 @@ exit:
113114
// CHECK-NEXT: retain_value %3
114115
// CHECK-NEXT: return [[CLOSURE]]
115116
// CHECK: } // end sil function 'call_generic_promotable_box_from_different_generic2'
116-
sil [ossa] @call_generic_promotable_box_from_different_generic2 : $@convention(thin) <T, U: P> (@in_guaranteed R<T>, @in_guaranteed E<(R<U>)->Int>, @in_guaranteed Int) -> @owned @callee_guaranteed (@in_guaranteed R<U>) -> @out Int {
117+
sil [ossa] @call_generic_promotable_box_from_different_generic2 : $@convention(thin) <T, U: P> (@in_guaranteed R<T>, @in_guaranteed E<(R<U>)->Int>, @in Int) -> @owned @callee_guaranteed (@in_guaranteed R<U>) -> @out Int {
117118
entry(%0 : $*R<T>, %1 : $*E<(R<U>)->Int>, %2 : $*Int):
118119
%f = function_ref @generic_promotable_box2 : $@convention(thin) <V> (@in_guaranteed R<V>, @in_guaranteed Int, @guaranteed <τ_0_0> { var E<(R<τ_0_0>)->Int> } <V>) -> @out Int
119120
%b = alloc_box $<τ_0_0> { var E<(R<τ_0_0>)->Int> } <U>

test/SILOptimizer/exclusivity_static_diagnostics.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ bb0(%0 : $*(Int, Int)):
527527
// This only happens when mandatory passes are applied repeatedly.
528528
//
529529
// CHECK-LABEL: sil hidden [ossa] @inlinedEnumValue
530-
sil hidden [ossa] @inlinedEnumValue : $@convention(thin) (Int) -> (@out Optional<Int>, Int) {
530+
sil hidden [ossa] @inlinedEnumValue : $@convention(thin) (@in Optional<Int>, Int) -> Int {
531531
bb0(%0 : $*Optional<Int>, %1 : $Int):
532532
%6 = unchecked_take_enum_data_addr %0 : $*Optional<Int>, #Optional.some!enumelt
533533
%7 = begin_access [read] [static] %6 : $*Int

0 commit comments

Comments
 (0)