mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
144 lines
4.6 KiB
C++
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
|