Skip to content

Commit f67c52e

Browse files
committed
[ownership] ref_to_* and *_to_ref produce values with OwnershipKind::Unowned so should be treated as PointerEscapes.
These instructions model a conversion in between ownership kinds without the result actually being owned by anything. As a result: 1. From an operand perspective, the instruction is treated like a pointer escape. 2. From a value perspective, the instruction returns a value with OwnershipKind::Unowned (to force the value to be copied before it can be used in an owned or guaranteed way) and Example: ``` sil @example : $@convention(thin) (@owned Klass) -> @owned @sil_unowned Klass { bb0(%0 : @owned $Klass): // Note that the ref_to_unowned does not consume %0 but instead converts %0 // from a "strong" value to a "safe unowned" value. A "safe unowned" value is // a value that corresponds to an 'unowned' value at the Swift level that use // unowned reference counting. At the SIL level these values can be recognized // by their types having the type attribute @sil_unowned. We have not // incremented the unowned ref count of %1 so we must treat %1 as unowned. %1 = ref_to_unowned %0 : $Klass // Then before we can use %2 in any way as a "safe unowned" value we need to // bump its unowned ref count by making a copy of the value. %2 will be a // "safe unowned" value with OwnershipKind::Owned ensuring that we decrement // the unowned ref count and do not leak said ref count. %2 = copy_value %1 : $@sil_unowned $Klass // Then since the original ref_to_unowned did not consume %0, we need to // destroy it here. destroy_value %0 : $Klass // And then return out OwnershipKind::Owned @sil_unowned Klass. return %2 : $@sil_unowned $Klass } ```
1 parent 650c1e6 commit f67c52e

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,8 @@ OPERAND_OWNERSHIP(InstantaneousUse, BridgeObjectToWord)
190190
OPERAND_OWNERSHIP(InstantaneousUse, ClassifyBridgeObject)
191191
OPERAND_OWNERSHIP(InstantaneousUse, SetDeallocating)
192192
#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
193-
OPERAND_OWNERSHIP(InstantaneousUse, RefTo##Name) \
194-
OPERAND_OWNERSHIP(InstantaneousUse, Name##ToRef) \
195193
OPERAND_OWNERSHIP(InstantaneousUse, StrongCopy##Name##Value)
196194
#define UNCHECKED_REF_STORAGE(Name, ...) \
197-
OPERAND_OWNERSHIP(InstantaneousUse, RefTo##Name) \
198195
OPERAND_OWNERSHIP(InstantaneousUse, StrongCopy##Name##Value)
199196
#include "swift/AST/ReferenceStorage.def"
200197

@@ -208,6 +205,16 @@ OPERAND_OWNERSHIP(UnownedInstantaneousUse, UnmanagedRetainValue)
208205
OPERAND_OWNERSHIP(UnownedInstantaneousUse, UnmanagedReleaseValue)
209206
OPERAND_OWNERSHIP(UnownedInstantaneousUse, UnmanagedAutoreleaseValue)
210207

208+
// These act as a form of conversion that does not imply ownership. Thus from an
209+
// operand perspective we treat them as a pointer escape and from a value
210+
// perspective, they return a value with OwnershipKind::Unowned.
211+
#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
212+
OPERAND_OWNERSHIP(PointerEscape, RefTo##Name) \
213+
OPERAND_OWNERSHIP(PointerEscape, Name##ToRef)
214+
#define UNCHECKED_REF_STORAGE(Name, ...) \
215+
OPERAND_OWNERSHIP(PointerEscape, RefTo##Name)
216+
#include "swift/AST/ReferenceStorage.def"
217+
211218
// Instructions that currently violate structural ownership requirements,
212219
// and therefore completely defeat canonicalization and optimization of any
213220
// OSSA value that they use.

test/SIL/ownership-verifier/use_verifier.sil

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,3 +1417,17 @@ bb3(%fUnknown : @owned $@callee_owned () -> ()):
14171417
%9999 = tuple()
14181418
return %9999 : $()
14191419
}
1420+
1421+
sil [ossa] @unowned_to_ref_is_unowned_instant_use : $@convention(thin) (@guaranteed Builtin.NativeObject) -> Builtin.NativeObject {
1422+
bb0(%0 : @guaranteed $Builtin.NativeObject):
1423+
%1 = ref_to_unowned %0 : $Builtin.NativeObject to $@sil_unowned Builtin.NativeObject
1424+
%2 = unowned_to_ref %1 : $@sil_unowned Builtin.NativeObject to $Builtin.NativeObject
1425+
return %2 : $Builtin.NativeObject
1426+
}
1427+
1428+
sil [ossa] @unmanaged_to_ref_is_unowned_instant_use : $@convention(thin) (@guaranteed Builtin.NativeObject) -> Builtin.NativeObject {
1429+
bb0(%0 : @guaranteed $Builtin.NativeObject):
1430+
%1 = ref_to_unmanaged %0 : $Builtin.NativeObject to $@sil_unmanaged Builtin.NativeObject
1431+
%2 = unmanaged_to_ref %1 : $@sil_unmanaged Builtin.NativeObject to $Builtin.NativeObject
1432+
return %2 : $Builtin.NativeObject
1433+
}

0 commit comments

Comments
 (0)