@@ -71,6 +71,96 @@ namespace sandboxir {
7171class Function ;
7272class Context ;
7373class 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+ };
74164
75165// / A SandboxIR Value has users. This is the base class.
76166class Value {
@@ -123,9 +213,77 @@ class Value {
123213 virtual ~Value () = default ;
124214 ClassID getSubclassID () const { return SubclassID; }
125215
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+
126284 Type *getType () const { return Val->getType (); }
127285
128- Context &getContext () const ;
286+ Context &getContext () const { return Ctx; }
129287#ifndef NDEBUG
130288 // / Should crash if there is something wrong with the instruction.
131289 virtual void verify () const = 0;
@@ -174,9 +332,61 @@ class User : public Value {
174332protected:
175333 User (ClassID ID, llvm::Value *V, Context &Ctx) : Value(ID, V, Ctx) {}
176334
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+
177352public:
178353 // / For isa/dyn_cast.
179354 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+
180390#ifndef NDEBUG
181391 void verify () const override {
182392 assert (isa<llvm::User>(Val) && " Expected User!" );
@@ -195,6 +405,9 @@ class Constant : public sandboxir::User {
195405 Constant (llvm::Constant *C, sandboxir::Context &SBCtx)
196406 : sandboxir::User(ClassID::Constant, C, SBCtx) {}
197407 friend class Context ; // For constructor.
408+ Use getOperandUseInternal (unsigned OpIdx, bool Verify) const final {
409+ return getOperandUseDefault (OpIdx, Verify);
410+ }
198411
199412public:
200413 // / For isa/dyn_cast.
@@ -203,6 +416,9 @@ class Constant : public sandboxir::User {
203416 From->getSubclassID () == ClassID::Function;
204417 }
205418 sandboxir::Context &getParent () const { return getContext (); }
419+ unsigned getUseOperandNo (const Use &Use) const final {
420+ return getUseOperandNoDefault (Use);
421+ }
206422#ifndef NDEBUG
207423 void verify () const final {
208424 assert (isa<llvm::Constant>(Val) && " Expected Constant!" );
@@ -309,11 +525,17 @@ class OpaqueInst : public sandboxir::Instruction {
309525 OpaqueInst (ClassID SubclassID, llvm::Instruction *I, sandboxir::Context &Ctx)
310526 : sandboxir::Instruction(SubclassID, Opcode::Opaque, I, Ctx) {}
311527 friend class Context ; // For constructor.
528+ Use getOperandUseInternal (unsigned OpIdx, bool Verify) const final {
529+ return getOperandUseDefault (OpIdx, Verify);
530+ }
312531
313532public:
314533 static bool classof (const sandboxir::Value *From) {
315534 return From->getSubclassID () == ClassID::Opaque;
316535 }
536+ unsigned getUseOperandNo (const Use &Use) const final {
537+ return getUseOperandNoDefault (Use);
538+ }
317539 unsigned getNumOfIRInstrs () const final { return 1u ; }
318540#ifndef NDEBUG
319541 void verify () const final {
0 commit comments