mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[SIL] Fix visitAccessedAddress @ end_borrow
`end_borrow` instructions may end the scopes introduced by `load_borrow` or `store_borrow` instructions, or those introduced by `begin_borrow` whose operand's guaranteed root includes a `load_borrow`. Previously, such scope ending instructions which end the scope associated with a borrowing load or store were not regarded as accessing the loaded-from or stored-to address. One consequence of this is that they were not regarded as accessing pointers and thus not as deinit barriers; that in turn resulted in `destroy_addr`s being hoisted into such borrow scopes. Here this is fixed by regarding such `end_borrow`s to access the loaded-from or stored-to address of the scope-introducing `load_borrow` or `store_borrow` respectively. rdar://157772187
This commit is contained in:
@@ -2796,6 +2796,23 @@ void swift::visitAccessedAddress(SILInstruction *I,
|
||||
visitor(singleOperand);
|
||||
return;
|
||||
}
|
||||
case SILInstructionKind::EndBorrowInst: {
|
||||
auto *ebi = cast<EndBorrowInst>(I);
|
||||
SmallVector<SILValue, 4> roots;
|
||||
findGuaranteedReferenceRoots(ebi->getOperand(),
|
||||
/*lookThroughNestedBorrows=*/true, roots);
|
||||
for (auto root : roots) {
|
||||
if (auto *lbi = dyn_cast<LoadBorrowInst>(root)) {
|
||||
visitor(&lbi->getOperandRef());
|
||||
return;
|
||||
}
|
||||
if (auto *sbi = dyn_cast<StoreBorrowInst>(root)) {
|
||||
visitor(&sbi->getOperandRef(StoreInst::Dest));
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Non-access cases: these are marked with memory side effects, but, by
|
||||
// themselves, do not access formal memory.
|
||||
#define UNCHECKED_REF_STORAGE(Name, ...) \
|
||||
@@ -2828,7 +2845,6 @@ void swift::visitAccessedAddress(SILInstruction *I,
|
||||
case SILInstructionKind::DropDeinitInst:
|
||||
case SILInstructionKind::EndAccessInst:
|
||||
case SILInstructionKind::EndApplyInst:
|
||||
case SILInstructionKind::EndBorrowInst:
|
||||
case SILInstructionKind::EndUnpairedAccessInst:
|
||||
case SILInstructionKind::EndLifetimeInst:
|
||||
case SILInstructionKind::ExistentialMetatypeInst:
|
||||
|
||||
@@ -84,6 +84,10 @@ struct STXXITXXII {
|
||||
struct MoS: ~Copyable {}
|
||||
struct MoE: ~Copyable {}
|
||||
|
||||
struct UnsafeMutablePointer<T> {
|
||||
var _rawValue: Builtin.RawPointer
|
||||
}
|
||||
|
||||
sil @unknown : $@convention(thin) () -> ()
|
||||
sil @use_S : $@convention(thin) (@in_guaranteed S) -> ()
|
||||
|
||||
@@ -1346,3 +1350,23 @@ entry(%c_addr : $*X):
|
||||
%retval = tuple ()
|
||||
return %retval
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil [ossa] @no_hoist_into_load_borrow_scope : {{.*}} {
|
||||
// CHECK: end_borrow
|
||||
// CHECK-NEXT: destroy_addr
|
||||
// CHECK-LABEL: } // end sil function 'no_hoist_into_load_borrow_scope'
|
||||
sil [ossa] @no_hoist_into_load_borrow_scope : $@convention(thin) (@in X) -> () {
|
||||
entry(%c_addr_in : $*X):
|
||||
%c_ptr = address_to_pointer [stack_protection] %c_addr_in to $Builtin.RawPointer
|
||||
%c_up = struct $UnsafeMutablePointer<X> (%c_ptr)
|
||||
%c_ptr_2 = struct_extract %c_up, #UnsafeMutablePointer._rawValue // user: %45
|
||||
%c_addr = pointer_to_address %c_ptr_2 to [strict] $*X
|
||||
%c_borrow = load_borrow %c_addr
|
||||
apply undef(%c_borrow) : $@convention(thin) (@guaranteed X) -> ()
|
||||
%c_copy = load [copy] %c_addr_in
|
||||
end_borrow %c_borrow
|
||||
%retval = tuple ()
|
||||
destroy_addr %c_addr_in
|
||||
destroy_value %c_copy
|
||||
return %retval
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user