@@ -71,6 +71,71 @@ namespace sandboxir {
71
71
class Function ;
72
72
class Context ;
73
73
class Instruction ;
74
+ class User ;
75
+ class Value ;
76
+
77
+ // / Represents a Def-use/Use-def edge in SandboxIR.
78
+ // / NOTE: Unlike llvm::Use, this is not an integral part of the use-def chains.
79
+ // / It is also not uniqued and is currently passed by value, so you can have
80
+ // / more than one sandboxir::Use objects for the same use-def edge.
81
+ class Use {
82
+ llvm::Use *LLVMUse;
83
+ User *User;
84
+ Context *Ctx;
85
+
86
+ // / Don't allow the user to create a sandboxir::Use directly.
87
+ Use (llvm::Use *LLVMUse, class User *User, Context &Ctx)
88
+ : LLVMUse(LLVMUse), User(User), Ctx(&Ctx) {}
89
+ Use () : LLVMUse(nullptr ), Ctx(nullptr ) {}
90
+
91
+ friend class User ; // For constructor
92
+ friend class OperandUseIterator ; // For constructor
93
+
94
+ public:
95
+ operator Value *() const { return get (); }
96
+ Value *get () const ;
97
+ class User *getUser () const { return User; }
98
+ unsigned getOperandNo () const ;
99
+ Context *getContext () const { return Ctx; }
100
+ bool operator ==(const Use &Other) const {
101
+ assert (Ctx == Other.Ctx && " Contexts differ!" );
102
+ return LLVMUse == Other.LLVMUse && User == Other.User ;
103
+ }
104
+ bool operator !=(const Use &Other) const { return !(*this == Other); }
105
+ #ifndef NDEBUG
106
+ void dump (raw_ostream &OS) const ;
107
+ void dump () const ;
108
+ #endif // NDEBUG
109
+ };
110
+
111
+ // / Returns the operand edge when dereferenced.
112
+ class OperandUseIterator {
113
+ Use Use;
114
+ // / Don't let the user create a non-empty OperandUseIterator.
115
+ OperandUseIterator (const class Use &Use) : Use(Use) {}
116
+ friend class User ; // For constructor
117
+ #define DEF_VALUE (ID, CLASS )
118
+ #define DEF_USER (ID, CLASS )
119
+ #define DEF_INSTR (ID, OPC, CLASS ) friend class CLASS ; // For constructor
120
+ #include " llvm/SandboxIR/SandboxIRValues.def"
121
+
122
+ public:
123
+ using difference_type = std::ptrdiff_t ;
124
+ using value_type = sandboxir::Use;
125
+ using pointer = value_type *;
126
+ using reference = value_type &;
127
+ using iterator_category = std::input_iterator_tag;
128
+
129
+ OperandUseIterator () = default ;
130
+ value_type operator *() const ;
131
+ OperandUseIterator &operator ++();
132
+ bool operator ==(const OperandUseIterator &Other) const {
133
+ return Use == Other.Use ;
134
+ }
135
+ bool operator !=(const OperandUseIterator &Other) const {
136
+ return !(*this == Other);
137
+ }
138
+ };
74
139
75
140
// / A SandboxIR Value has users. This is the base class.
76
141
class Value {
@@ -174,9 +239,61 @@ class User : public Value {
174
239
protected:
175
240
User (ClassID ID, llvm::Value *V, Context &Ctx) : Value(ID, V, Ctx) {}
176
241
242
+ // / \Returns the Use edge that corresponds to \p OpIdx.
243
+ // / Note: This is the default implementation that works for instructions that
244
+ // / match the underlying LLVM instruction. All others should use a different
245
+ // / implementation.
246
+ Use getOperandUseDefault (unsigned OpIdx, bool Verify) const ;
247
+ virtual Use getOperandUseInternal (unsigned OpIdx, bool Verify) const = 0;
248
+ friend class OperandUseIterator ; // for getOperandUseInternal()
249
+
250
+ // / The default implementation works only for single-LLVMIR-instruction
251
+ // / Users and only if they match exactly the LLVM instruction.
252
+ unsigned getUseOperandNoDefault (const Use &Use) const {
253
+ return Use.LLVMUse ->getOperandNo ();
254
+ }
255
+ // / \Returns the operand index of \p Use.
256
+ virtual unsigned getUseOperandNo (const Use &Use) const = 0;
257
+ friend unsigned Use::getOperandNo () const ; // For getUseOperandNo()
258
+
177
259
public:
178
260
// / For isa/dyn_cast.
179
261
static bool classof (const Value *From);
262
+ using op_iterator = OperandUseIterator;
263
+ using const_op_iterator = OperandUseIterator;
264
+ using op_range = iterator_range<op_iterator>;
265
+ using const_op_range = iterator_range<const_op_iterator>;
266
+
267
+ virtual op_iterator op_begin () {
268
+ assert (isa<llvm::User>(Val) && " Expect User value!" );
269
+ return op_iterator (getOperandUseInternal (0 , /* Verify=*/ false ));
270
+ }
271
+ virtual op_iterator op_end () {
272
+ assert (isa<llvm::User>(Val) && " Expect User value!" );
273
+ return op_iterator (
274
+ getOperandUseInternal (getNumOperands (), /* Verify=*/ false ));
275
+ }
276
+ virtual const_op_iterator op_begin () const {
277
+ return const_cast <User *>(this )->op_begin ();
278
+ }
279
+ virtual const_op_iterator op_end () const {
280
+ return const_cast <User *>(this )->op_end ();
281
+ }
282
+
283
+ op_range operands () { return make_range<op_iterator>(op_begin (), op_end ()); }
284
+ const_op_range operands () const {
285
+ return make_range<const_op_iterator>(op_begin (), op_end ());
286
+ }
287
+ Value *getOperand (unsigned OpIdx) const { return getOperandUse (OpIdx).get (); }
288
+ // / \Returns the operand edge for \p OpIdx. NOTE: This should also work for
289
+ // / OpIdx == getNumOperands(), which is used for op_end().
290
+ Use getOperandUse (unsigned OpIdx) const {
291
+ return getOperandUseInternal (OpIdx, /* Verify=*/ true );
292
+ }
293
+ virtual unsigned getNumOperands () const {
294
+ return isa<llvm::User>(Val) ? cast<llvm::User>(Val)->getNumOperands () : 0 ;
295
+ }
296
+
180
297
#ifndef NDEBUG
181
298
void verify () const override {
182
299
assert (isa<llvm::User>(Val) && " Expected User!" );
@@ -195,6 +312,9 @@ class Constant : public sandboxir::User {
195
312
Constant (llvm::Constant *C, sandboxir::Context &SBCtx)
196
313
: sandboxir::User(ClassID::Constant, C, SBCtx) {}
197
314
friend class Context ; // For constructor.
315
+ Use getOperandUseInternal (unsigned OpIdx, bool Verify) const final {
316
+ return getOperandUseDefault (OpIdx, Verify);
317
+ }
198
318
199
319
public:
200
320
// / For isa/dyn_cast.
@@ -203,6 +323,9 @@ class Constant : public sandboxir::User {
203
323
From->getSubclassID () == ClassID::Function;
204
324
}
205
325
sandboxir::Context &getParent () const { return getContext (); }
326
+ unsigned getUseOperandNo (const Use &Use) const final {
327
+ return getUseOperandNoDefault (Use);
328
+ }
206
329
#ifndef NDEBUG
207
330
void verify () const final {
208
331
assert (isa<llvm::Constant>(Val) && " Expected Constant!" );
@@ -309,11 +432,17 @@ class OpaqueInst : public sandboxir::Instruction {
309
432
OpaqueInst (ClassID SubclassID, llvm::Instruction *I, sandboxir::Context &Ctx)
310
433
: sandboxir::Instruction(SubclassID, Opcode::Opaque, I, Ctx) {}
311
434
friend class Context ; // For constructor.
435
+ Use getOperandUseInternal (unsigned OpIdx, bool Verify) const final {
436
+ return getOperandUseDefault (OpIdx, Verify);
437
+ }
312
438
313
439
public:
314
440
static bool classof (const sandboxir::Value *From) {
315
441
return From->getSubclassID () == ClassID::Opaque;
316
442
}
443
+ unsigned getUseOperandNo (const Use &Use) const final {
444
+ return getUseOperandNoDefault (Use);
445
+ }
317
446
unsigned getNumOfIRInstrs () const final { return 1u ; }
318
447
#ifndef NDEBUG
319
448
void verify () const final {
0 commit comments