@@ -71,6 +71,69 @@ 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 *Usr;
84
+ Context *Ctx;
85
+
86
+ // / Don't allow the user to create a sandboxir::Use directly.
87
+ Use (llvm::Use *LLVMUse, User *Usr, Context &Ctx)
88
+ : LLVMUse(LLVMUse), Usr(Usr), 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 Usr; }
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 && Usr == Other.Usr ;
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_INSTR (ID, OPC, CLASS ) friend class CLASS ; // For constructor
118
+ #include " llvm/SandboxIR/SandboxIRValues.def"
119
+
120
+ public:
121
+ using difference_type = std::ptrdiff_t ;
122
+ using value_type = sandboxir::Use;
123
+ using pointer = value_type *;
124
+ using reference = value_type &;
125
+ using iterator_category = std::input_iterator_tag;
126
+
127
+ OperandUseIterator () = default ;
128
+ value_type operator *() const ;
129
+ OperandUseIterator &operator ++();
130
+ bool operator ==(const OperandUseIterator &Other) const {
131
+ return Use == Other.Use ;
132
+ }
133
+ bool operator !=(const OperandUseIterator &Other) const {
134
+ return !(*this == Other);
135
+ }
136
+ };
74
137
75
138
// / A SandboxIR Value has users. This is the base class.
76
139
class Value {
@@ -174,9 +237,61 @@ class User : public Value {
174
237
protected:
175
238
User (ClassID ID, llvm::Value *V, Context &Ctx) : Value(ID, V, Ctx) {}
176
239
240
+ // / \Returns the Use edge that corresponds to \p OpIdx.
241
+ // / Note: This is the default implementation that works for instructions that
242
+ // / match the underlying LLVM instruction. All others should use a different
243
+ // / implementation.
244
+ Use getOperandUseDefault (unsigned OpIdx, bool Verify) const ;
245
+ virtual Use getOperandUseInternal (unsigned OpIdx, bool Verify) const = 0;
246
+ friend class OperandUseIterator ; // for getOperandUseInternal()
247
+
248
+ // / The default implementation works only for single-LLVMIR-instruction
249
+ // / Users and only if they match exactly the LLVM instruction.
250
+ unsigned getUseOperandNoDefault (const Use &Use) const {
251
+ return Use.LLVMUse ->getOperandNo ();
252
+ }
253
+ // / \Returns the operand index of \p Use.
254
+ virtual unsigned getUseOperandNo (const Use &Use) const = 0;
255
+ friend unsigned Use::getOperandNo () const ; // For getUseOperandNo()
256
+
177
257
public:
178
258
// / For isa/dyn_cast.
179
259
static bool classof (const Value *From);
260
+ using op_iterator = OperandUseIterator;
261
+ using const_op_iterator = OperandUseIterator;
262
+ using op_range = iterator_range<op_iterator>;
263
+ using const_op_range = iterator_range<const_op_iterator>;
264
+
265
+ virtual op_iterator op_begin () {
266
+ assert (isa<llvm::User>(Val) && " Expect User value!" );
267
+ return op_iterator (getOperandUseInternal (0 , /* Verify=*/ false ));
268
+ }
269
+ virtual op_iterator op_end () {
270
+ assert (isa<llvm::User>(Val) && " Expect User value!" );
271
+ return op_iterator (
272
+ getOperandUseInternal (getNumOperands (), /* Verify=*/ false ));
273
+ }
274
+ virtual const_op_iterator op_begin () const {
275
+ return const_cast <User *>(this )->op_begin ();
276
+ }
277
+ virtual const_op_iterator op_end () const {
278
+ return const_cast <User *>(this )->op_end ();
279
+ }
280
+
281
+ op_range operands () { return make_range<op_iterator>(op_begin (), op_end ()); }
282
+ const_op_range operands () const {
283
+ return make_range<const_op_iterator>(op_begin (), op_end ());
284
+ }
285
+ Value *getOperand (unsigned OpIdx) const { return getOperandUse (OpIdx).get (); }
286
+ // / \Returns the operand edge for \p OpIdx. NOTE: This should also work for
287
+ // / OpIdx == getNumOperands(), which is used for op_end().
288
+ Use getOperandUse (unsigned OpIdx) const {
289
+ return getOperandUseInternal (OpIdx, /* Verify=*/ true );
290
+ }
291
+ virtual unsigned getNumOperands () const {
292
+ return isa<llvm::User>(Val) ? cast<llvm::User>(Val)->getNumOperands () : 0 ;
293
+ }
294
+
180
295
#ifndef NDEBUG
181
296
void verify () const override {
182
297
assert (isa<llvm::User>(Val) && " Expected User!" );
@@ -195,6 +310,9 @@ class Constant : public sandboxir::User {
195
310
Constant (llvm::Constant *C, sandboxir::Context &SBCtx)
196
311
: sandboxir::User(ClassID::Constant, C, SBCtx) {}
197
312
friend class Context ; // For constructor.
313
+ Use getOperandUseInternal (unsigned OpIdx, bool Verify) const final {
314
+ return getOperandUseDefault (OpIdx, Verify);
315
+ }
198
316
199
317
public:
200
318
// / For isa/dyn_cast.
@@ -203,6 +321,9 @@ class Constant : public sandboxir::User {
203
321
From->getSubclassID () == ClassID::Function;
204
322
}
205
323
sandboxir::Context &getParent () const { return getContext (); }
324
+ unsigned getUseOperandNo (const Use &Use) const final {
325
+ return getUseOperandNoDefault (Use);
326
+ }
206
327
#ifndef NDEBUG
207
328
void verify () const final {
208
329
assert (isa<llvm::Constant>(Val) && " Expected Constant!" );
@@ -309,11 +430,17 @@ class OpaqueInst : public sandboxir::Instruction {
309
430
OpaqueInst (ClassID SubclassID, llvm::Instruction *I, sandboxir::Context &Ctx)
310
431
: sandboxir::Instruction(SubclassID, Opcode::Opaque, I, Ctx) {}
311
432
friend class Context ; // For constructor.
433
+ Use getOperandUseInternal (unsigned OpIdx, bool Verify) const final {
434
+ return getOperandUseDefault (OpIdx, Verify);
435
+ }
312
436
313
437
public:
314
438
static bool classof (const sandboxir::Value *From) {
315
439
return From->getSubclassID () == ClassID::Opaque;
316
440
}
441
+ unsigned getUseOperandNo (const Use &Use) const final {
442
+ return getUseOperandNoDefault (Use);
443
+ }
317
444
unsigned getNumOfIRInstrs () const final { return 1u ; }
318
445
#ifndef NDEBUG
319
446
void verify () const final {
0 commit comments