Skip to content

Commit dc95b11

Browse files
committed
Fix ManagedValue::isPlusOne for addresses
In-memory values cannot be reused after deinitialization. Add ManagedValue::isPlusOneOrTrivial() for situations where we want to forward a value without destroying the original memory. Fixes rdar://108001491 (SIL verification failed: Found mutating or consuming use of an in_guaranteed parameter?!: !ImmutableAddressUseVerifier().isMutatingOrConsuming(fArg))
1 parent 3368e71 commit dc95b11

File tree

4 files changed

+43
-24
lines changed

4 files changed

+43
-24
lines changed

lib/SILGen/ManagedValue.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -293,19 +293,20 @@ bool ManagedValue::isPlusOne(SILGenFunction &SGF) const {
293293
if (isa<SILUndef>(getValue()))
294294
return true;
295295

296-
// Ignore trivial values since for our purposes they are always at +1 since
297-
// they can always be passed to +1 APIs.
298-
if (getType().isTrivial(SGF.F))
299-
return true;
300-
301-
// If we have an object and the object has any ownership, the same
302-
// property applies.
296+
// A value without ownership can always be passed to +1 APIs.
297+
//
298+
// This is not true for address types because deinitializing an in-memory
299+
// value invalidates the storage.
303300
if (getType().isObject() && getOwnershipKind() == OwnershipKind::None)
304301
return true;
305302

306303
return hasCleanup();
307304
}
308305

306+
bool ManagedValue::isPlusOneOrTrivial(SILGenFunction &SGF) const {
307+
return getType().isTrivial(SGF.F) || isPlusOne(SGF);
308+
}
309+
309310
bool ManagedValue::isPlusZero() const {
310311
// SILUndef can always be passed to +0 APIs.
311312
if (isa<SILUndef>(getValue()))

lib/SILGen/ManagedValue.h

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -217,19 +217,24 @@ class ManagedValue {
217217
return !hasCleanup();
218218
}
219219

220-
/// Returns true if this is an managed value that can be used safely as a +1
221-
/// managed value.
220+
/// Returns true if this managed value can be consumed.
222221
///
223-
/// This returns true iff:
222+
/// This is true if either this value has a cleanup or if it is an
223+
/// SSA value without ownership.
224224
///
225-
/// 1. All sub-values are trivially typed.
226-
/// 2. There exists at least one non-trivial typed sub-value and all such
227-
/// sub-values all have cleanups.
228-
///
229-
/// *NOTE* Due to 1. isPlusOne and isPlusZero both return true for managed
230-
/// values consisting of only trivial values.
225+
/// When an SSA value does not have ownership, it can be used by a consuming
226+
/// operation without destroying it. Consuming a value by address, however,
227+
/// deinitializes the memory regardless of whether the value has ownership.
231228
bool isPlusOne(SILGenFunction &SGF) const;
232229

230+
/// Returns true if this managed value can be forwarded without necessarilly
231+
/// destroying the original.
232+
///
233+
/// This is true if either isPlusOne is true or the value is trivial. A
234+
/// trivial value in memory can be forwarded as a +1 value without
235+
/// deinitializing the memory.
236+
bool isPlusOneOrTrivial(SILGenFunction &SGF) const;
237+
233238
/// Returns true if this is an ManagedValue that can be used safely as a +0
234239
/// ManagedValue.
235240
///

lib/SILGen/RValue.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,13 @@ bool RValue::isPlusOne(SILGenFunction &SGF) const & {
823823
values, [&SGF](ManagedValue mv) -> bool { return mv.isPlusOne(SGF); });
824824
}
825825

826+
bool RValue::isPlusOneOrTrivial(SILGenFunction &SGF) const & {
827+
return llvm::all_of(
828+
values, [&SGF](ManagedValue mv) -> bool {
829+
return mv.isPlusOneOrTrivial(SGF);
830+
});
831+
}
832+
826833
bool RValue::isPlusZero(SILGenFunction &SGF) const & {
827834
return llvm::none_of(values,
828835
[](ManagedValue mv) -> bool { return mv.isPlusZero(); });

lib/SILGen/RValue.h

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -242,18 +242,24 @@ class RValue {
242242
return value;
243243
}
244244

245-
/// Returns true if this is an rvalue that can be used safely as a +1 rvalue.
245+
/// Returns true if this rvalue can be consumed.
246246
///
247-
/// This returns true iff:
247+
/// This is true if each element either has a cleanup or is an SSA value
248+
/// without ownership.
248249
///
249-
/// 1. All sub-values are trivially typed.
250-
/// 2. There exists at least one non-trivial typed sub-value and all such
251-
/// sub-values all have cleanups.
252-
///
253-
/// *NOTE* Due to 1. isPlusOne and isPlusZero both return true for rvalues
254-
/// consisting of only trivial values.
250+
/// When an SSA value does not have ownership, it can be used by a consuming
251+
/// operation without destroying it. Consuming a value by address, however,
252+
/// deinitializes the memory regardless of whether the value has ownership.
255253
bool isPlusOne(SILGenFunction &SGF) const &;
256254

255+
/// Returns true if this rvalue can be forwarded without necessarilly
256+
/// destroying the original.
257+
///
258+
/// This is true if either isPlusOne is true or the value is trivial. A
259+
/// trivial value in memory can be forwarded as a +1 value without
260+
/// deinitializing the memory.
261+
bool isPlusOneOrTrivial(SILGenFunction &SGF) const &;
262+
257263
/// Returns true if this is an rvalue that can be used safely as a +0 rvalue.
258264
///
259265
/// Specifically, we return true if:

0 commit comments

Comments
 (0)