blob: 9550260540697b7d6afcf524c28d7a6c50b5c867 [file] [log] [blame]
//===--- OwnershipUtils.h ------------------------------------*- C++ -*----===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SIL_OWNERSHIPUTILS_H
#define SWIFT_SIL_OWNERSHIPUTILS_H
#include "swift/Basic/LLVM.h"
#include "swift/SIL/SILValue.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
namespace swift {
class SILBasicBlock;
class SILInstruction;
class SILModule;
class SILValue;
class DeadEndBlocks;
class BranchPropagatedUser;
namespace ownership {
struct ErrorBehaviorKind {
enum inner_t {
Invalid = 0,
ReturnFalse = 1,
PrintMessage = 2,
Assert = 4,
ReturnFalseOnLeak = 8,
PrintMessageAndReturnFalse = PrintMessage | ReturnFalse,
PrintMessageAndAssert = PrintMessage | Assert,
ReturnFalseOnLeakAssertOtherwise = ReturnFalseOnLeak | Assert,
} Value;
ErrorBehaviorKind() : Value(Invalid) {}
ErrorBehaviorKind(inner_t Inner) : Value(Inner) { assert(Value != Invalid); }
bool shouldAssert() const {
assert(Value != Invalid);
return Value & Assert;
}
bool shouldReturnFalseOnLeak() const {
assert(Value != Invalid);
return Value & ReturnFalseOnLeak;
}
bool shouldPrintMessage() const {
assert(Value != Invalid);
return Value & PrintMessage;
}
bool shouldReturnFalse() const {
assert(Value != Invalid);
return Value & ReturnFalse;
}
};
} // end namespace ownership
/// This class is a higher level interface to the ownership checker meant for
/// use with SILPasses. It uses the actual checker as an internal PImpl detail
/// so types/etc do not leak.
struct OwnershipChecker {
/// The list of regular users from the last run of the checker.
SmallVector<SILInstruction *, 16> regularUsers;
/// The list of regular users from the last run of the checker.
SmallVector<SILInstruction *, 16> lifetimeEndingUsers;
/// The live blocks for the SILValue we processed. This can be used to
/// determine if a block is in the "live" region of our SILInstruction.
SmallPtrSet<SILBasicBlock *, 32> liveBlocks;
/// The list of implicit regular users from the last run of the checker.
///
/// This is used to encode end of scope like instructions.
SmallVector<SILInstruction *, 4> endScopeRegularUsers;
/// The module that we are in.
SILModule &mod;
/// A cache of dead-end basic blocks that we use to determine if we can
/// ignore "leaks".
DeadEndBlocks &deadEndBlocks;
bool checkValue(SILValue Value);
};
/// Returns true if:
///
/// 1. No consuming uses are reachable from any other consuming use, from any
/// non-consuming uses, or from the producer instruction.
/// 2. The consuming use set jointly post dominates producers and all non
/// consuming uses.
///
/// \p value The value whose lifetime we are checking.
/// \p consumingUses the array of users that destroy or consume a value.
/// \p nonConsumingUses regular uses
/// \p deadEndBlocks a cache for the dead end block computation
/// \p errorBehavior If we detect an error, should we return false or hard
/// error.
/// \p leakingBlocks If non-null a list of blocks where the value was detected
/// to leak. Can be used to insert missing destroys.
bool valueHasLinearLifetime(
SILValue value, ArrayRef<BranchPropagatedUser> consumingUses,
ArrayRef<BranchPropagatedUser> nonConsumingUses,
SmallPtrSetImpl<SILBasicBlock *> &visitedBlocks,
DeadEndBlocks &deadEndBlocks, ownership::ErrorBehaviorKind errorBehavior,
SmallVectorImpl<SILBasicBlock *> *leakingBlocks = nullptr);
/// Returns true if v is an address or trivial.
bool isValueAddressOrTrivial(SILValue v, SILModule &m);
/// These operations forward both owned and guaranteed ownership.
bool isOwnershipForwardingValueKind(SILNodeKind kind);
/// These operations forward guaranteed ownership, but don't necessarily forward
/// owned values.
bool isGuaranteedForwardingValueKind(SILNodeKind kind);
bool isGuaranteedForwardingValue(SILValue value);
bool isOwnershipForwardingInst(SILInstruction *i);
bool isGuaranteedForwardingInst(SILInstruction *i);
bool getUnderlyingBorrowIntroducers(SILValue inputValue,
SmallVectorImpl<SILValue> &out);
} // namespace swift
#endif