1 //===- User.h ---------------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_SANDBOXIR_USER_H 10 #define LLVM_SANDBOXIR_USER_H 11 12 #include "llvm/IR/User.h" 13 #include "llvm/IR/Value.h" 14 #include "llvm/SandboxIR/Use.h" 15 #include "llvm/SandboxIR/Value.h" 16 #include "llvm/Support/Compiler.h" 17 18 namespace llvm::sandboxir { 19 20 class Context; 21 22 /// Iterator for the `Use` edges of a User's operands. 23 /// \Returns the operand `Use` when dereferenced. 24 class OperandUseIterator { 25 sandboxir::Use Use; 26 /// Don't let the user create a non-empty OperandUseIterator. OperandUseIterator(const class Use & Use)27 OperandUseIterator(const class Use &Use) : Use(Use) {} 28 friend class User; // For constructor 29 #define DEF_INSTR(ID, OPC, CLASS) friend class CLASS; // For constructor 30 #include "llvm/SandboxIR/Values.def" 31 32 public: 33 using difference_type = std::ptrdiff_t; 34 using value_type = sandboxir::Use; 35 using pointer = value_type *; 36 using reference = value_type &; 37 using iterator_category = std::input_iterator_tag; 38 39 OperandUseIterator() = default; 40 LLVM_ABI value_type operator*() const; 41 LLVM_ABI OperandUseIterator &operator++(); 42 OperandUseIterator operator++(int) { 43 auto Copy = *this; 44 this->operator++(); 45 return Copy; 46 } 47 bool operator==(const OperandUseIterator &Other) const { 48 return Use == Other.Use; 49 } 50 bool operator!=(const OperandUseIterator &Other) const { 51 return !(*this == Other); 52 } 53 LLVM_ABI OperandUseIterator operator+(unsigned Num) const; 54 LLVM_ABI OperandUseIterator operator-(unsigned Num) const; 55 LLVM_ABI int operator-(const OperandUseIterator &Other) const; 56 }; 57 58 /// A sandboxir::User has operands. 59 class LLVM_ABI User : public Value { 60 protected: User(ClassID ID,llvm::Value * V,Context & Ctx)61 User(ClassID ID, llvm::Value *V, Context &Ctx) : Value(ID, V, Ctx) {} 62 63 /// \Returns the Use edge that corresponds to \p OpIdx. 64 /// Note: This is the default implementation that works for instructions that 65 /// match the underlying LLVM instruction. All others should use a different 66 /// implementation. 67 Use getOperandUseDefault(unsigned OpIdx, bool Verify) const; 68 /// \Returns the Use for the \p OpIdx'th operand. This is virtual to allow 69 /// instructions to deviate from the LLVM IR operands, which is a requirement 70 /// for sandboxir Instructions that consist of more than one LLVM Instruction. 71 virtual Use getOperandUseInternal(unsigned OpIdx, bool Verify) const = 0; 72 friend class OperandUseIterator; // for getOperandUseInternal() 73 74 /// The default implementation works only for single-LLVMIR-instruction 75 /// Users and only if they match exactly the LLVM instruction. getUseOperandNoDefault(const Use & Use)76 unsigned getUseOperandNoDefault(const Use &Use) const { 77 return Use.LLVMUse->getOperandNo(); 78 } 79 /// \Returns the operand index of \p Use. 80 virtual unsigned getUseOperandNo(const Use &Use) const = 0; 81 friend unsigned Use::getOperandNo() const; // For getUseOperandNo() 82 swapOperandsInternal(unsigned OpIdxA,unsigned OpIdxB)83 void swapOperandsInternal(unsigned OpIdxA, unsigned OpIdxB) { 84 assert(OpIdxA < getNumOperands() && "OpIdxA out of bounds!"); 85 assert(OpIdxB < getNumOperands() && "OpIdxB out of bounds!"); 86 auto UseA = getOperandUse(OpIdxA); 87 auto UseB = getOperandUse(OpIdxB); 88 UseA.swap(UseB); 89 } 90 91 #ifndef NDEBUG 92 void verifyUserOfLLVMUse(const llvm::Use &Use) const; 93 #endif // NDEBUG 94 95 public: 96 /// For isa/dyn_cast. 97 static bool classof(const Value *From); 98 using op_iterator = OperandUseIterator; 99 using const_op_iterator = OperandUseIterator; 100 using op_range = iterator_range<op_iterator>; 101 using const_op_range = iterator_range<const_op_iterator>; 102 op_begin()103 virtual op_iterator op_begin() { 104 assert(isa<llvm::User>(Val) && "Expect User value!"); 105 return op_iterator(getOperandUseInternal(0, /*Verify=*/false)); 106 } op_end()107 virtual op_iterator op_end() { 108 assert(isa<llvm::User>(Val) && "Expect User value!"); 109 return op_iterator( 110 getOperandUseInternal(getNumOperands(), /*Verify=*/false)); 111 } op_begin()112 virtual const_op_iterator op_begin() const { 113 return const_cast<User *>(this)->op_begin(); 114 } op_end()115 virtual const_op_iterator op_end() const { 116 return const_cast<User *>(this)->op_end(); 117 } 118 operands()119 op_range operands() { return make_range<op_iterator>(op_begin(), op_end()); } operands()120 const_op_range operands() const { 121 return make_range<const_op_iterator>(op_begin(), op_end()); 122 } getOperand(unsigned OpIdx)123 Value *getOperand(unsigned OpIdx) const { return getOperandUse(OpIdx).get(); } 124 /// \Returns the operand edge for \p OpIdx. NOTE: This should also work for 125 /// OpIdx == getNumOperands(), which is used for op_end(). getOperandUse(unsigned OpIdx)126 Use getOperandUse(unsigned OpIdx) const { 127 return getOperandUseInternal(OpIdx, /*Verify=*/true); 128 } getNumOperands()129 virtual unsigned getNumOperands() const { 130 return isa<llvm::User>(Val) ? cast<llvm::User>(Val)->getNumOperands() : 0; 131 } 132 133 virtual void setOperand(unsigned OperandIdx, Value *Operand); 134 /// Replaces any operands that match \p FromV with \p ToV. Returns whether any 135 /// operands were replaced. 136 bool replaceUsesOfWith(Value *FromV, Value *ToV); 137 138 #ifndef NDEBUG verify()139 void verify() const override { 140 assert(isa<llvm::User>(Val) && "Expected User!"); 141 } 142 void dumpCommonHeader(raw_ostream &OS) const final; dumpOS(raw_ostream & OS)143 void dumpOS(raw_ostream &OS) const override { 144 // TODO: Remove this tmp implementation once we get the Instruction classes. 145 } 146 #endif 147 }; 148 149 } // namespace llvm::sandboxir 150 151 #endif // LLVM_SANDBOXIR_USER_H 152