blob: 38fcd2e959537d1ebcdcb9cd7cf1119ff793f43e [file] [log] [blame]
//===--- ReborrowVerifierPrivate.h ----------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 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
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SIL_REBORROWVERIFIER_H
#define SWIFT_SIL_REBORROWVERIFIER_H
#include "LinearLifetimeCheckerPrivate.h"
#include "swift/SIL/OwnershipUtils.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILValue.h"
namespace swift {
class DeadEndBlocks;
/// A guaranteed phi arg ends the borrow scope of its incoming value and begins
/// a new borrow scope. ReborrowVerifier validates the lifetime of the reborrow
/// lies within the lifetime of its base value. It uses LinearLifetimeChecker
/// for this.
class ReborrowVerifier {
/// A cache of dead-end basic blocks that we use to determine if we can
/// ignore "leaks".
DeadEndBlocks &deadEndBlocks;
/// A cache map of borrow lifetime ending operands and their base value
llvm::SmallDenseMap<Operand *, SILValue> visitedOps;
/// A cache map of guaranteed phi args and their base value
llvm::SmallDenseMap<SILPhiArgument *, SILValue> visitedPhiArgs;
/// The builder that the checker uses to emit error messages, crash if asked
/// for, or supply back interesting info to the caller.
LinearLifetimeChecker::ErrorBuilder errorBuilder;
public:
ReborrowVerifier(const SILFunction *func, DeadEndBlocks &deadEndBlocks,
LinearLifetimeChecker::ErrorBuilder errorBuilder)
: deadEndBlocks(deadEndBlocks), errorBuilder(errorBuilder) {}
void verifyReborrows(BorrowingOperand initialScopedOperand, SILValue value);
private:
/// Verifies whether the reborrow's lifetime lies within its base value
bool verifyReborrowLifetime(SILPhiArgument *phiArg, SILValue baseVal);
/// Check if the operand is visited
bool isVisitedOp(Operand *op, SILValue baseVal) {
return visitedOps.find(op) != visitedOps.end();
}
/// Check if the phi arg and base value are visited
bool isVisitedPhiArg(SILPhiArgument *phiArg, SILValue baseVal) {
auto itPhiArg = visitedPhiArgs.find(phiArg);
return itPhiArg != visitedPhiArgs.end() && (*itPhiArg).second == baseVal;
}
/// Mark operand as visited
void addVisitedOp(Operand *op, SILValue baseVal) {
visitedOps.insert({op, baseVal});
}
/// Mark guaranteed phi arg as visited
void addVisitedPhiArg(SILPhiArgument *phiArg, SILValue baseVal) {
visitedPhiArgs.insert({phiArg, baseVal});
}
};
} // namespace swift
#endif