@@ -88,8 +88,10 @@ class Use {
88
88
: LLVMUse(LLVMUse), Usr(Usr), Ctx(&Ctx) {}
89
89
Use () : LLVMUse(nullptr ), Ctx(nullptr ) {}
90
90
91
+ friend class Value ; // For constructor
91
92
friend class User ; // For constructor
92
93
friend class OperandUseIterator ; // For constructor
94
+ friend class UserUseIterator ; // For accessing members
93
95
94
96
public:
95
97
operator Value *() const { return get (); }
@@ -135,6 +137,31 @@ class OperandUseIterator {
135
137
}
136
138
};
137
139
140
+ // / Returns user edge when dereferenced.
141
+ class UserUseIterator {
142
+ 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
+ };
164
+
138
165
// / A SandboxIR Value has users. This is the base class.
139
166
class Value {
140
167
public:
@@ -186,9 +213,77 @@ class Value {
186
213
virtual ~Value () = default ;
187
214
ClassID getSubclassID () const { return SubclassID; }
188
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
+
189
284
Type *getType () const { return Val->getType (); }
190
285
191
- Context &getContext () const ;
286
+ Context &getContext () const { return Ctx; }
192
287
#ifndef NDEBUG
193
288
// / Should crash if there is something wrong with the instruction.
194
289
virtual void verify () const = 0;
0 commit comments