mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
This updates how we model reborrow's lifetimes for ownership verification. Today we follow and combine a borrow's lifetime through phi args as well. Owned values lifetimes end at a phi arg. This discrepency in modeling lifetimes leads to the OwnershipVerifier raising errors incorrectly for cases such as this, where the borrow and the base value do not dominate the end_borrow: bb0: cond_br undef, bb1, bb2 bb1: %copy0 = copy_value %0 %borrow0 = begin_borrow %copy0 br bb3(%borrow0, %copy0) bb2: %copy1 = copy_value %1 %borrow1 = begin_borrow %copy1 br bb3(%borrow1, %copy1) bb3(%borrow, %baseVal): end_borrow %borrow destroy_value %baseVal This PR adds a new ReborrowVerifier. The ownership verifier collects borrow's lifetime ending users and populates the worklist of the ReborrowVerifier with reborrows and the corresponding base value. ReborrowVerifier then verifies that the lifetime of the reborrow is within the lifetime of the base value.
78 lines
2.7 KiB
C++
78 lines
2.7 KiB
C++
//===--- 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
|