mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
This originally trafficked in Instructions and for some reason the name was never changed. I also changed the result type to be a bool and added the ability for the passed in closure to signal failure (and iteration stop) by returning false. This also makes it possible to use visitLocalEndScopeUses in if statements which can be useful.
96 lines
3.6 KiB
C++
96 lines
3.6 KiB
C++
//===--- ReborrowVerifier.cpp ---------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#define DEBUG_TYPE "sil-reborrow-checker"
|
|
|
|
#include "ReborrowVerifierPrivate.h"
|
|
|
|
using namespace swift;
|
|
|
|
bool ReborrowVerifier::verifyReborrowLifetime(SILPhiArgument *phiArg,
|
|
SILValue baseVal) {
|
|
SmallPtrSet<SILBasicBlock *, 4> visitedBlocks;
|
|
bool result = false;
|
|
SmallVector<Operand *, 4> phiArgUses(phiArg->getUses());
|
|
|
|
// Verify whether the guaranteed phi arg lies within the lifetime of the base
|
|
// value.
|
|
LinearLifetimeChecker checker(visitedBlocks, deadEndBlocks);
|
|
// newErrorBuilder is consumed at the end of the checkValue function.
|
|
// Copy initial state from errorBuilder everytime
|
|
LinearLifetimeChecker::ErrorBuilder newErrorBuilder = errorBuilder;
|
|
SmallVector<Operand *, 4> baseValConsumingUses(baseVal->getConsumingUses());
|
|
// If the baseValue has no consuming uses, there is nothing more to verify
|
|
if (baseValConsumingUses.empty())
|
|
return false;
|
|
auto linearLifetimeResult = checker.checkValue(baseVal, baseValConsumingUses,
|
|
phiArgUses, newErrorBuilder);
|
|
result |= linearLifetimeResult.getFoundError();
|
|
return result;
|
|
}
|
|
|
|
void ReborrowVerifier::verifyReborrows(BorrowingOperand initialScopedOperand,
|
|
SILValue value) {
|
|
SmallVector<std::tuple<Operand *, SILValue>, 4> worklist;
|
|
// Initialize the worklist with borrow lifetime ending uses
|
|
initialScopedOperand.visitLocalEndScopeUses([&](Operand *op) {
|
|
worklist.emplace_back(op, value);
|
|
return true;
|
|
});
|
|
|
|
while (!worklist.empty()) {
|
|
Operand *borrowLifetimeEndOp;
|
|
SILValue baseVal;
|
|
std::tie(borrowLifetimeEndOp, baseVal) = worklist.pop_back_val();
|
|
auto *borrowLifetimeEndUser = borrowLifetimeEndOp->getUser();
|
|
|
|
auto borrowingOperand = BorrowingOperand::get(borrowLifetimeEndOp);
|
|
if (!borrowingOperand || !borrowingOperand->isReborrow())
|
|
continue;
|
|
|
|
if (isVisitedOp(borrowLifetimeEndOp, baseVal))
|
|
continue;
|
|
|
|
// Process reborrow
|
|
auto *branchInst = cast<BranchInst>(borrowLifetimeEndUser);
|
|
for (auto *succBlock : branchInst->getSuccessorBlocks()) {
|
|
auto *phiArg = cast<SILPhiArgument>(
|
|
succBlock->getArgument(borrowLifetimeEndOp->getOperandNumber()));
|
|
assert(phiArg->getOwnershipKind() == OwnershipKind::Guaranteed);
|
|
|
|
SILValue newBaseVal = baseVal;
|
|
// If the previous base value was also passed as a phi arg, that will be
|
|
// the new base value.
|
|
for (auto *arg : succBlock->getArguments()) {
|
|
if (arg->getIncomingPhiValue(branchInst->getParent()) == baseVal) {
|
|
newBaseVal = arg;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (isVisitedPhiArg(phiArg, newBaseVal))
|
|
continue;
|
|
addVisitedPhiArg(phiArg, newBaseVal);
|
|
verifyReborrowLifetime(phiArg, newBaseVal);
|
|
|
|
// Find the scope ending uses of the guaranteed phi arg and add it to the
|
|
// worklist.
|
|
auto scopedValue = BorrowedValue::get(phiArg);
|
|
assert(scopedValue.hasValue());
|
|
scopedValue->visitLocalScopeEndingUses([&](Operand *op) {
|
|
addVisitedOp(op, newBaseVal);
|
|
worklist.emplace_back(op, newBaseVal);
|
|
});
|
|
}
|
|
}
|
|
}
|