|
| 1 | +//===--- ScopedAddressUtils.h ---------------------------------------------===// |
| 2 | +// |
| 3 | +// This source file is part of the Swift.org open source project |
| 4 | +// |
| 5 | +// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors |
| 6 | +// Licensed under Apache License v2.0 with Runtime Library Exception |
| 7 | +// |
| 8 | +// See https://swift.org/LICENSE.txt for license information |
| 9 | +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| 10 | +// |
| 11 | +//===----------------------------------------------------------------------===// |
| 12 | + |
| 13 | +#ifndef SWIFT_SIL_SCOPEDADDRESSUTILS_H |
| 14 | +#define SWIFT_SIL_SCOPEDADDRESSUTILS_H |
| 15 | + |
| 16 | +#include "swift/Basic/Debug.h" |
| 17 | +#include "swift/Basic/LLVM.h" |
| 18 | +#include "swift/SIL/PrunedLiveness.h" |
| 19 | +#include "swift/SIL/SILBasicBlock.h" |
| 20 | +#include "swift/SIL/SILInstruction.h" |
| 21 | +#include "swift/SIL/SILValue.h" |
| 22 | +#include "swift/SILOptimizer/Utils/InstModCallbacks.h" |
| 23 | + |
| 24 | +namespace swift { |
| 25 | + |
| 26 | +class ScopedAddressValueKind { |
| 27 | +public: |
| 28 | + enum Kind : uint8_t { |
| 29 | + Invalid = 0, |
| 30 | + StoreBorrow, |
| 31 | + BeginAccess, |
| 32 | + }; |
| 33 | + |
| 34 | +private: |
| 35 | + Kind value; |
| 36 | + |
| 37 | +public: |
| 38 | + static ScopedAddressValueKind get(SILValue value) { |
| 39 | + switch (value->getKind()) { |
| 40 | + default: |
| 41 | + return Kind::Invalid; |
| 42 | + case ValueKind::StoreBorrowInst: |
| 43 | + return Kind::StoreBorrow; |
| 44 | + case ValueKind::BeginAccessInst: |
| 45 | + return Kind::BeginAccess; |
| 46 | + } |
| 47 | + } |
| 48 | + |
| 49 | + ScopedAddressValueKind(Kind newValue) : value(newValue) {} |
| 50 | + |
| 51 | + operator Kind() const { return value; } |
| 52 | + |
| 53 | + void print(llvm::raw_ostream &os) const; |
| 54 | + SWIFT_DEBUG_DUMP { print(llvm::dbgs()); } |
| 55 | +}; |
| 56 | + |
| 57 | +llvm::raw_ostream &operator<<(llvm::raw_ostream &os, |
| 58 | + ScopedAddressValueKind kind); |
| 59 | + |
| 60 | +struct ScopedAddressValue { |
| 61 | + SILValue value; |
| 62 | + ScopedAddressValueKind kind = ScopedAddressValueKind::Invalid; |
| 63 | + |
| 64 | + ScopedAddressValue() = default; |
| 65 | + |
| 66 | + explicit ScopedAddressValue(SILValue value) { |
| 67 | + kind = ScopedAddressValueKind::get(value); |
| 68 | + if (kind) |
| 69 | + this->value = value; |
| 70 | + } |
| 71 | + |
| 72 | + operator bool() const { |
| 73 | + return kind != ScopedAddressValueKind::Invalid && value; |
| 74 | + } |
| 75 | + |
| 76 | + void print(llvm::raw_ostream &os) const; |
| 77 | + SWIFT_DEBUG_DUMP { print(llvm::dbgs()); } |
| 78 | + |
| 79 | + // Helpers to allow a ScopedAddressValue to easily be used as a SILValue |
| 80 | + // programatically. |
| 81 | + SILValue operator->() { return value; } |
| 82 | + SILValue operator->() const { return value; } |
| 83 | + SILValue operator*() { return value; } |
| 84 | + SILValue operator*() const { return value; } |
| 85 | + |
| 86 | + /// Returns true if \p op is a scope edning use of the scoped address value. |
| 87 | + bool isScopeEndingUse(Operand *op) const; |
| 88 | + /// Pass all scope ending instructions to the visitor. |
| 89 | + bool visitScopeEndingUses(function_ref<bool(Operand *)> visitor) const; |
| 90 | + /// Returns false, if liveness cannot be computed due to pointer escape or |
| 91 | + /// unkown address use. Add this scope's live blocks into the PrunedLiveness |
| 92 | + /// result. |
| 93 | + bool computeLiveness(PrunedLiveness &liveness) const; |
| 94 | + |
| 95 | + /// Create appropriate scope ending instruction at \p insertPt. |
| 96 | + void createScopeEnd(SILBasicBlock::iterator insertPt, SILLocation loc) const; |
| 97 | + |
| 98 | + /// Create scope ending instructions at \p liveness boundary. |
| 99 | + void endScopeAtLivenessBoundary(PrunedLiveness *liveness) const; |
| 100 | +}; |
| 101 | + |
| 102 | +llvm::raw_ostream &operator<<(llvm::raw_ostream &os, |
| 103 | + const ScopedAddressValue &value); |
| 104 | + |
| 105 | +/// Returns true if there are other store_borrows enclosed within a store_borrow |
| 106 | +/// \p sbi's scope |
| 107 | +bool hasOtherStoreBorrowsInLifetime(StoreBorrowInst *sbi, |
| 108 | + PrunedLiveness *liveness, |
| 109 | + DeadEndBlocks *deadEndBlocks); |
| 110 | + |
| 111 | +/// Extend the store_borrow \p sbi's scope such that it encloses \p newUsers. |
| 112 | +bool extendStoreBorrow(StoreBorrowInst *sbi, |
| 113 | + SmallVectorImpl<Operand *> &newUses, |
| 114 | + DeadEndBlocks *deadEndBlocks, |
| 115 | + InstModCallbacks callbacks = InstModCallbacks()); |
| 116 | +} // namespace swift |
| 117 | + |
| 118 | +#endif |
0 commit comments