@@ -71,6 +71,96 @@ 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 Value ; // For constructor
92
+ friend class User ; // For constructor
93
+ friend class OperandUseIterator ; // For constructor
94
+ friend class UserUseIterator ; // For accessing members
95
+
96
+ public:
97
+ operator Value *() const { return get (); }
98
+ Value *get () const ;
99
+ class User *getUser () const { return Usr; }
100
+ unsigned getOperandNo () const ;
101
+ Context *getContext () const { return Ctx; }
102
+ bool operator ==(const Use &Other) const {
103
+ assert (Ctx == Other.Ctx && " Contexts differ!" );
104
+ return LLVMUse == Other.LLVMUse && Usr == Other.Usr ;
105
+ }
106
+ bool operator !=(const Use &Other) const { return !(*this == Other); }
107
+ #ifndef NDEBUG
108
+ void dump (raw_ostream &OS) const ;
109
+ void dump () const ;
110
+ #endif // NDEBUG
111
+ };
112
+
113
+ // / Returns the operand edge when dereferenced.
114
+ class OperandUseIterator {
115
+ sandboxir::Use Use;
116
+ // / Don't let the user create a non-empty OperandUseIterator.
117
+ OperandUseIterator (const class Use &Use) : Use(Use) {}
118
+ friend class User ; // For constructor
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
+ };
139
+
140
+ // / Returns user edge when dereferenced.
141
+ class UserUseIterator {
142
+ sandboxir::Use Use;
143
+ // / Don't let the user create a non-empty UserUseIterator.
144
+ UserUseIterator (const class Use &Use) : Use(Use) {}
145
+ friend class Value ; // For constructor
146
+
147
+ public:
148
+ using difference_type = std::ptrdiff_t ;
149
+ using value_type = sandboxir::Use;
150
+ using pointer = value_type *;
151
+ using reference = value_type &;
152
+ using iterator_category = std::input_iterator_tag;
153
+
154
+ UserUseIterator () = default ;
155
+ value_type operator *() const { return Use; }
156
+ UserUseIterator &operator ++();
157
+ bool operator ==(const UserUseIterator &Other) const {
158
+ return Use == Other.Use ;
159
+ }
160
+ bool operator !=(const UserUseIterator &Other) const {
161
+ return !(*this == Other);
162
+ }
163
+ };
74
164
75
165
// / A SandboxIR Value has users. This is the base class.
76
166
class Value {
@@ -123,9 +213,77 @@ class Value {
123
213
virtual ~Value () = default ;
124
214
ClassID getSubclassID () const { return SubclassID; }
125
215
216
+ using use_iterator = UserUseIterator;
217
+ using const_use_iterator = UserUseIterator;
218
+
219
+ use_iterator use_begin ();
220
+ const_use_iterator use_begin () const {
221
+ return const_cast <Value *>(this )->use_begin ();
222
+ }
223
+ use_iterator use_end () { return use_iterator (Use (nullptr , nullptr , Ctx)); }
224
+ const_use_iterator use_end () const {
225
+ return const_cast <Value *>(this )->use_end ();
226
+ }
227
+
228
+ iterator_range<use_iterator> uses () {
229
+ return make_range<use_iterator>(use_begin (), use_end ());
230
+ }
231
+ iterator_range<const_use_iterator> uses () const {
232
+ return make_range<const_use_iterator>(use_begin (), use_end ());
233
+ }
234
+
235
+ // / Helper for mapped_iterator.
236
+ struct UseToUser {
237
+ User *operator ()(const Use &Use) const { return &*Use.getUser (); }
238
+ };
239
+
240
+ using user_iterator = mapped_iterator<sandboxir::UserUseIterator, UseToUser>;
241
+ using const_user_iterator = user_iterator;
242
+
243
+ user_iterator user_begin ();
244
+ user_iterator user_end () {
245
+ return user_iterator (Use (nullptr , nullptr , Ctx), UseToUser ());
246
+ }
247
+ const_user_iterator user_begin () const {
248
+ return const_cast <Value *>(this )->user_begin ();
249
+ }
250
+ const_user_iterator user_end () const {
251
+ return const_cast <Value *>(this )->user_end ();
252
+ }
253
+
254
+ iterator_range<user_iterator> users () {
255
+ return make_range<user_iterator>(user_begin (), user_end ());
256
+ }
257
+ iterator_range<const_user_iterator> users () const {
258
+ return make_range<const_user_iterator>(user_begin (), user_end ());
259
+ }
260
+ // / \Returns the number of user edges (not necessarily to unique users).
261
+ // / WARNING: This is a linear-time operation.
262
+ unsigned getNumUses () const ;
263
+ // / Return true if this value has N uses or more.
264
+ // / This is logically equivalent to getNumUses() >= N.
265
+ // / WARNING: This can be expensive, as it is linear to the number of users.
266
+ bool hasNUsesOrMore (unsigned Num) const {
267
+ unsigned Cnt = 0 ;
268
+ for (auto It = use_begin (), ItE = use_end (); It != ItE; ++It) {
269
+ if (++Cnt >= Num)
270
+ return true ;
271
+ }
272
+ return false ;
273
+ }
274
+ // / Return true if this Value has exactly N uses.
275
+ bool hasNUses (unsigned Num) const {
276
+ unsigned Cnt = 0 ;
277
+ for (auto It = use_begin (), ItE = use_end (); It != ItE; ++It) {
278
+ if (++Cnt > Num)
279
+ return false ;
280
+ }
281
+ return Cnt == Num;
282
+ }
283
+
126
284
Type *getType () const { return Val->getType (); }
127
285
128
- Context &getContext () const ;
286
+ Context &getContext () const { return Ctx; }
129
287
#ifndef NDEBUG
130
288
// / Should crash if there is something wrong with the instruction.
131
289
virtual void verify () const = 0;
@@ -174,9 +332,61 @@ class User : public Value {
174
332
protected:
175
333
User (ClassID ID, llvm::Value *V, Context &Ctx) : Value(ID, V, Ctx) {}
176
334
335
+ // / \Returns the Use edge that corresponds to \p OpIdx.
336
+ // / Note: This is the default implementation that works for instructions that
337
+ // / match the underlying LLVM instruction. All others should use a different
338
+ // / implementation.
339
+ Use getOperandUseDefault (unsigned OpIdx, bool Verify) const ;
340
+ virtual Use getOperandUseInternal (unsigned OpIdx, bool Verify) const = 0;
341
+ friend class OperandUseIterator ; // for getOperandUseInternal()
342
+
343
+ // / The default implementation works only for single-LLVMIR-instruction
344
+ // / Users and only if they match exactly the LLVM instruction.
345
+ unsigned getUseOperandNoDefault (const Use &Use) const {
346
+ return Use.LLVMUse ->getOperandNo ();
347
+ }
348
+ // / \Returns the operand index of \p Use.
349
+ virtual unsigned getUseOperandNo (const Use &Use) const = 0;
350
+ friend unsigned Use::getOperandNo () const ; // For getUseOperandNo()
351
+
177
352
public:
178
353
// / For isa/dyn_cast.
179
354
static bool classof (const Value *From);
355
+ using op_iterator = OperandUseIterator;
356
+ using const_op_iterator = OperandUseIterator;
357
+ using op_range = iterator_range<op_iterator>;
358
+ using const_op_range = iterator_range<const_op_iterator>;
359
+
360
+ virtual op_iterator op_begin () {
361
+ assert (isa<llvm::User>(Val) && " Expect User value!" );
362
+ return op_iterator (getOperandUseInternal (0 , /* Verify=*/ false ));
363
+ }
364
+ virtual op_iterator op_end () {
365
+ assert (isa<llvm::User>(Val) && " Expect User value!" );
366
+ return op_iterator (
367
+ getOperandUseInternal (getNumOperands (), /* Verify=*/ false ));
368
+ }
369
+ virtual const_op_iterator op_begin () const {
370
+ return const_cast <User *>(this )->op_begin ();
371
+ }
372
+ virtual const_op_iterator op_end () const {
373
+ return const_cast <User *>(this )->op_end ();
374
+ }
375
+
376
+ op_range operands () { return make_range<op_iterator>(op_begin (), op_end ()); }
377
+ const_op_range operands () const {
378
+ return make_range<const_op_iterator>(op_begin (), op_end ());
379
+ }
380
+ Value *getOperand (unsigned OpIdx) const { return getOperandUse (OpIdx).get (); }
381
+ // / \Returns the operand edge for \p OpIdx. NOTE: This should also work for
382
+ // / OpIdx == getNumOperands(), which is used for op_end().
383
+ Use getOperandUse (unsigned OpIdx) const {
384
+ return getOperandUseInternal (OpIdx, /* Verify=*/ true );
385
+ }
386
+ virtual unsigned getNumOperands () const {
387
+ return isa<llvm::User>(Val) ? cast<llvm::User>(Val)->getNumOperands () : 0 ;
388
+ }
389
+
180
390
#ifndef NDEBUG
181
391
void verify () const override {
182
392
assert (isa<llvm::User>(Val) && " Expected User!" );
@@ -195,6 +405,9 @@ class Constant : public sandboxir::User {
195
405
Constant (llvm::Constant *C, sandboxir::Context &SBCtx)
196
406
: sandboxir::User(ClassID::Constant, C, SBCtx) {}
197
407
friend class Context ; // For constructor.
408
+ Use getOperandUseInternal (unsigned OpIdx, bool Verify) const final {
409
+ return getOperandUseDefault (OpIdx, Verify);
410
+ }
198
411
199
412
public:
200
413
// / For isa/dyn_cast.
@@ -203,6 +416,9 @@ class Constant : public sandboxir::User {
203
416
From->getSubclassID () == ClassID::Function;
204
417
}
205
418
sandboxir::Context &getParent () const { return getContext (); }
419
+ unsigned getUseOperandNo (const Use &Use) const final {
420
+ return getUseOperandNoDefault (Use);
421
+ }
206
422
#ifndef NDEBUG
207
423
void verify () const final {
208
424
assert (isa<llvm::Constant>(Val) && " Expected Constant!" );
@@ -309,11 +525,17 @@ class OpaqueInst : public sandboxir::Instruction {
309
525
OpaqueInst (ClassID SubclassID, llvm::Instruction *I, sandboxir::Context &Ctx)
310
526
: sandboxir::Instruction(SubclassID, Opcode::Opaque, I, Ctx) {}
311
527
friend class Context ; // For constructor.
528
+ Use getOperandUseInternal (unsigned OpIdx, bool Verify) const final {
529
+ return getOperandUseDefault (OpIdx, Verify);
530
+ }
312
531
313
532
public:
314
533
static bool classof (const sandboxir::Value *From) {
315
534
return From->getSubclassID () == ClassID::Opaque;
316
535
}
536
+ unsigned getUseOperandNo (const Use &Use) const final {
537
+ return getUseOperandNoDefault (Use);
538
+ }
317
539
unsigned getNumOfIRInstrs () const final { return 1u ; }
318
540
#ifndef NDEBUG
319
541
void verify () const final {
0 commit comments