Skip to content

Commit ac2f7b7

Browse files
committed
Add BorrowingOperand::hasEmptyRequiredEndingUses()
Temporary check for malformed borrow scopes. Def-use traversals expect at least one scope-ending use. Otherwise we can end up missing the borrow entirely and miscompiling. SIL should guarantee scope-ending uses on all paths, but that isn't fully enforced yet.
1 parent d361be9 commit ac2f7b7

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

include/swift/SIL/OwnershipUtils.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,15 @@ struct BorrowingOperand {
306306
/// visits the end of the introduced borrow scope.
307307
bool visitScopeEndingUses(function_ref<bool(Operand *)> func) const;
308308

309+
/// Returns true for borrows that create a local borrow scope but have no
310+
/// scope-ending uses (presumably all paths are dead-end blocks). This does
311+
/// not include instantaneous borrows, which don't require explicit scope
312+
/// ending uses.
313+
///
314+
/// FIXME: Borrow scopes should have scope-ending uses on all paths, even to
315+
/// dead end blocks. When the verifier enforces this, remove this check.
316+
bool hasEmptyRequiredEndingUses() const;
317+
309318
/// Visit the scope ending operands of the extended scope, after transitively
310319
/// searching through reborrows. These uses might not be dominated by this
311320
/// BorrowingOperand.

lib/SIL/Utils/OwnershipUtils.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,28 @@ llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &os,
356356
return os;
357357
}
358358

359+
bool BorrowingOperand::hasEmptyRequiredEndingUses() const {
360+
switch (kind) {
361+
case BorrowingOperandKind::Invalid:
362+
llvm_unreachable("Using invalid case");
363+
case BorrowingOperandKind::BeginBorrow:
364+
case BorrowingOperandKind::BeginApply: {
365+
return op->getUser()->hasUsesOfAnyResult();
366+
}
367+
case BorrowingOperandKind::Branch: {
368+
auto *br = cast<BranchInst>(op->getUser());
369+
return br->getArgForOperand(op)->use_empty();
370+
}
371+
// These are instantaneous borrow scopes so there aren't any special end
372+
// scope instructions.
373+
case BorrowingOperandKind::Apply:
374+
case BorrowingOperandKind::TryApply:
375+
case BorrowingOperandKind::Yield:
376+
return false;
377+
}
378+
llvm_unreachable("Covered switch isn't covered");
379+
}
380+
359381
bool BorrowingOperand::visitScopeEndingUses(
360382
function_ref<bool(Operand *)> func) const {
361383
switch (kind) {

0 commit comments

Comments
 (0)