xref: /freebsd/contrib/llvm-project/llvm/include/llvm/SandboxIR/User.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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