Skip to content

Commit c4abccb

Browse files
authored
Merge pull request #34742 from atrick/fix-unchecked-ownership
Specify the unchecked_ownership_conversion instruction
2 parents dd6e796 + f529072 commit c4abccb

File tree

6 files changed

+57
-7
lines changed

6 files changed

+57
-7
lines changed

docs/SIL.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5894,6 +5894,25 @@ This instruction is assumed to forward a fixed ownership (set upon its
58945894
construction) and lowers to 'unchecked_bitwise_cast' in non-ossa code. This
58955895
causes the cast to lose its guarantee of layout-compatibility.
58965896

5897+
unchecked_ownership_conversion
5898+
``````````````````````````````
5899+
::
5900+
5901+
sil-instruction ::= 'unchecked_ownership_conversion' sil-operand ',' sil-value-ownership-kind 'to' sil-value-ownership-kind
5902+
5903+
%1 = unchecked_ownership_conversion %0 : $A, @guaranteed to @owned
5904+
5905+
Converts its operand to an identical value of the same type but with
5906+
different ownership without performing any semantic operations
5907+
normally required by for ownership conversion.
5908+
5909+
This is used in Objective-C compatible destructors to convert a
5910+
guaranteed parameter to an owned parameter without performing a
5911+
semantic copy.
5912+
5913+
The resulting value must meet the usual ownership requirements; for
5914+
example, a trivial type must have '.none' ownership.
5915+
58975916
ref_to_raw_pointer
58985917
``````````````````
58995918
::

include/swift/SIL/SILNodes.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
575575
SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
576576
#include "swift/AST/ReferenceStorage.def"
577577
SINGLE_VALUE_INST(UncheckedOwnershipConversionInst, unchecked_ownership_conversion,
578-
SingleValueInstruction, MayHaveSideEffects, MayRelease)
578+
SingleValueInstruction, None, MayRelease)
579579

580580
// IsUnique does not actually write to memory but should be modeled
581581
// as such. Its operand is a pointer to an object reference. The

lib/SIL/Utils/MemAccessUtils.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,9 @@ bool swift::isLetAddress(SILValue address) {
369369
// RC-identical would confuse ARC optimization, which might eliminate a retain
370370
// of such an object completely.
371371
//
372-
// The SILVerifier checks that none of these operations cast a nontrivial value
373-
// to a reference except unconditional_checked_cast[_value].
372+
// The SILVerifier checks that none of these operations cast a trivial value to
373+
// a reference except unconditional_checked_cast[_value], which is checked By
374+
// SILDynamicCastInst::isRCIdentityPreserving().
374375
bool swift::isRCIdentityPreservingCast(SingleValueInstruction *svi) {
375376
switch (svi->getKind()) {
376377
default:

lib/SIL/Verifier/LoadBorrowImmutabilityChecker.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,12 +268,11 @@ bool GatherWritesVisitor::visitUse(Operand *op, AccessUseType useTy) {
268268
if (!op->get()->getType().isAddress() && !user->mayWriteToMemory()) {
269269
return true;
270270
}
271-
// If we did not recognize the user, just return conservatively that it was
272-
// written to in a way we did not understand.
271+
// If we did not recognize the user, print additional error diagnostics and
272+
// return false to force SIL verification to fail.
273273
llvm::errs() << "Function: " << user->getFunction()->getName() << "\n";
274274
llvm::errs() << "Value: " << op->get();
275275
llvm::errs() << "Unknown instruction: " << *user;
276-
llvm::report_fatal_error("Unexpected instruction using borrowed address?!");
277276
return false;
278277
}
279278

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1958,6 +1958,17 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
19581958
"Inst with qualified ownership in a function that is not qualified");
19591959
}
19601960

1961+
void checkUncheckedOwnershipConversionInst(
1962+
UncheckedOwnershipConversionInst *uoci) {
1963+
require(
1964+
F.hasOwnership(),
1965+
"Inst with qualified ownership in a function that is not qualified");
1966+
require(!uoci->getType().isAddress(),
1967+
"cannot convert ownership of an address");
1968+
require(uoci->getType() == uoci->getOperand()->getType(),
1969+
"converting ownership does not affect the type");
1970+
}
1971+
19611972
template <class AI>
19621973
void checkAccessEnforcement(AI *AccessInst) {
19631974
if (AccessInst->getModule().getStage() != SILStage::Raw) {

test/SILOptimizer/load_borrow_verify.sil

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,24 @@ bb0(%0 : @owned $AnyObject):
7676
dealloc_stack %1 : $*Optional<AnyObject>
7777
%99 = tuple ()
7878
return %99 : $()
79-
}
79+
}
80+
81+
// unchecked_ownership_conversion should not be considered a write to memory.
82+
class ObjectWrapper {
83+
var object: AnyObject
84+
}
85+
86+
// CHECK-LABEL: sil [ossa] @unchecked_ownership_conversion_test : $@convention(thin) (@guaranteed ObjectWrapper) -> @owned ObjectWrapper {
87+
// CHECK: bb0(%0 : @guaranteed $ObjectWrapper):
88+
// CHECK: load_borrow
89+
// CHECK: unchecked_ownership_conversion %0 : $ObjectWrapper, @guaranteed to @owned
90+
// CHECK: end_borrow
91+
// CHECK-LABEL: } // end sil function 'unchecked_ownership_conversion_test'
92+
sil [ossa] @unchecked_ownership_conversion_test : $@convention(thin) (@guaranteed ObjectWrapper) -> @owned ObjectWrapper {
93+
bb0(%0 : @guaranteed $ObjectWrapper):
94+
%1 = ref_element_addr %0 : $ObjectWrapper, #ObjectWrapper.object
95+
%2 = load_borrow %1 : $*AnyObject
96+
%3 = unchecked_ownership_conversion %0 : $ObjectWrapper, @guaranteed to @owned
97+
end_borrow %2 : $AnyObject
98+
return %3 : $ObjectWrapper
99+
}

0 commit comments

Comments
 (0)