//===--- 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 visitedOps; /// A cache map of guaranteed phi args and their base value llvm::SmallDenseMap 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