Files
swift-mirror/include/swift/SIL/ScopedAddressUtils.h
2024-12-06 16:22:24 -08:00

144 lines
4.6 KiB
C++

//===--- ScopedAddressUtils.h ---------------------------------------------===//
//
// 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_SCOPEDADDRESSUTILS_H
#define SWIFT_SIL_SCOPEDADDRESSUTILS_H
#include "swift/Basic/Debug.h"
#include "swift/Basic/LLVM.h"
#include "swift/SIL/OwnershipUtils.h"
#include "swift/SIL/PrunedLiveness.h"
#include "swift/SIL/SILBasicBlock.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILValue.h"
#include "swift/SILOptimizer/Utils/InstModCallbacks.h"
namespace swift {
class ScopedAddressValueKind {
public:
enum Kind : uint8_t {
Invalid = 0,
StoreBorrow,
BeginAccess,
};
private:
Kind value;
public:
static ScopedAddressValueKind get(SILValue value) {
switch (value->getKind()) {
default:
return Kind::Invalid;
case ValueKind::StoreBorrowInst:
return Kind::StoreBorrow;
case ValueKind::BeginAccessInst:
return Kind::BeginAccess;
}
}
ScopedAddressValueKind(Kind newValue) : value(newValue) {}
operator Kind() const { return value; }
void print(llvm::raw_ostream &os) const;
SWIFT_DEBUG_DUMP { print(llvm::dbgs()); }
};
llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
ScopedAddressValueKind kind);
struct ScopedAddressValue {
SILValue value;
ScopedAddressValueKind kind = ScopedAddressValueKind::Invalid;
ScopedAddressValue() = default;
explicit ScopedAddressValue(SILValue value) {
kind = ScopedAddressValueKind::get(value);
if (kind)
this->value = value;
}
operator bool() const {
return kind != ScopedAddressValueKind::Invalid && value;
}
// Both the store_borrow source and address operands are effectively used for
// the duration of the address scope.
static ScopedAddressValue forUse(Operand *use) {
if (auto svi = dyn_cast<SingleValueInstruction>(use->getUser()))
return ScopedAddressValue(svi);
return ScopedAddressValue();
}
void print(llvm::raw_ostream &os) const;
SWIFT_DEBUG_DUMP { print(llvm::dbgs()); }
// Helpers to allow a ScopedAddressValue to easily be used as a SILValue
// programatically.
SILValue operator->() { return value; }
SILValue operator->() const { return value; }
SILValue operator*() { return value; }
SILValue operator*() const { return value; }
/// Returns true if \p op is a scope ending use of the scoped address value.
bool isScopeEndingUse(Operand *op) const;
/// Pass all scope ending instructions to the visitor.
bool visitScopeEndingUses(function_ref<bool(Operand *)> visitor) const;
/// Optimistically computes liveness for all transitive uses, and adds this
/// scope's live blocks into the SSA PrunedLiveness result. Returns
/// AddressUseKind indicated whether a PointerEscape or Unknown use was
/// encountered.
///
/// This transitively finds uses within nested borrow scopes to handle
/// incomplete nested lifetimes. Here, liveness will consider the apply to be
/// a live use of the store_borrow:
/// %a = store_borrow
/// %v = load_borrow
/// apply (%v)
/// unreachable
///
/// FIXME: with complete OSSA lifetimes, store borrow liveness is simply
/// computed by visiting the end_borrow users.
AddressUseKind computeTransitiveLiveness(SSAPrunedLiveness &liveness) const;
/// Update \p liveness for all the transitive address uses.
///
/// Valid for any type of liveness, SSA or MultiDef, that may be used by a
/// scoped address.
AddressUseKind updateTransitiveLiveness(SSAPrunedLiveness &liveness) const;
/// Create appropriate scope ending instruction at \p insertPt.
SILInstruction *createScopeEnd(SILBasicBlock::iterator insertPt,
SILLocation loc) const;
/// Create scope ending instructions at \p liveness boundary.
void endScopeAtLivenessBoundary(SSAPrunedLiveness *liveness) const;
};
llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
const ScopedAddressValue &value);
/// Returns true if there are other store_borrows enclosed within a store_borrow
/// \p sbi's scope
bool hasOtherStoreBorrowsInLifetime(StoreBorrowInst *sbi,
SSAPrunedLiveness *liveness,
DeadEndBlocks *deadEndBlocks);
} // namespace swift
#endif