X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FUser.h;h=df303d0dd5f289e24accff8608da0dd1b486d868;hb=b09c146b116359616f6cbd4c8b3328607e00ff42;hp=570f381d1a8c4eb168e16f21305cfc3d0b0be78f;hpb=e98fc279e28de4817831a9d11ec99b83a3f49d02;p=oota-llvm.git diff --git a/include/llvm/User.h b/include/llvm/User.h index 570f381d1a8..df303d0dd5f 100644 --- a/include/llvm/User.h +++ b/include/llvm/User.h @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// // -// This class defines the interface that one who 'use's a Value must implement. +// This class defines the interface that one who uses a Value must implement. // Each instance of the Value class keeps track of what User's have handles // to it. // -// * Instructions are the largest class of User's. +// * Instructions are the largest class of Users. // * Constants may be users of other constants (think arrays and stuff) // //===----------------------------------------------------------------------===// @@ -19,6 +19,7 @@ #ifndef LLVM_USER_H #define LLVM_USER_H +#include "llvm/Support/ErrorHandling.h" #include "llvm/Value.h" namespace llvm { @@ -29,33 +30,18 @@ namespace llvm { template struct OperandTraits; -class User; - -/// OperandTraits - specialization to User -template <> -struct OperandTraits { - static inline Use *op_begin(User*); - static inline Use *op_end(User*); - static inline unsigned operands(const User*); - template - struct Layout { - typedef U overlay; - }; - static inline void *allocate(unsigned); -}; - class User : public Value { - User(const User &); // Do not implement - void *operator new(size_t); // Do not implement + User(const User &) LLVM_DELETED_FUNCTION; + void *operator new(size_t) LLVM_DELETED_FUNCTION; template friend struct HungoffOperandTraits; + virtual void anchor(); protected: - /// OperandList - This is a pointer to the array of Users for this operand. + /// OperandList - This is a pointer to the array of Uses for this User. /// For nodes of fixed arity (e.g. a binary operator) this array will live - /// prefixed to the derived class. For nodes of resizable variable arity - /// (e.g. PHINodes, SwitchInst etc.), this memory will be dynamically - /// allocated and should be destroyed by the classes' - /// virtual dtor. + /// prefixed to some derived class instance. For nodes of resizable variable + /// arity (e.g. PHINodes, SwitchInst etc.), this memory will be dynamically + /// allocated and should be destroyed by the classes' virtual dtor. Use *OperandList; /// NumOperands - The number of values used by this User. @@ -63,15 +49,14 @@ protected: unsigned NumOperands; void *operator new(size_t s, unsigned Us); - User(const Type *ty, unsigned vty, Use *OpList, unsigned NumOps) + User(Type *ty, unsigned vty, Use *OpList, unsigned NumOps) : Value(ty, vty), OperandList(OpList), NumOperands(NumOps) {} Use *allocHungoffUses(unsigned) const; - void dropHungoffUses(Use *U) { - if (OperandList == U) { - OperandList = 0; - NumOperands = 0; - } - Use::zap(U, U->getImpliedUser(), true); + void dropHungoffUses() { + Use::zap(OperandList, OperandList + NumOperands, true); + OperandList = 0; + // Reset NumOperands so User::operator delete() does the right thing. + NumOperands = 0; } public: ~User() { @@ -81,22 +66,45 @@ public: void operator delete(void *Usr); /// placement delete - required by std, but never called. void operator delete(void*, unsigned) { - assert(0 && "Constructor throws?"); + llvm_unreachable("Constructor throws?"); } - template Use &Op() { - return OperandTraits::op_begin(this)[Idx]; + /// placement delete - required by std, but never called. + void operator delete(void*, unsigned, bool) { + llvm_unreachable("Constructor throws?"); } - template const Use &Op() const { - return OperandTraits::op_begin(const_cast(this))[Idx]; +protected: + template static Use &OpFrom(const U *that) { + return Idx < 0 + ? OperandTraits::op_end(const_cast(that))[Idx] + : OperandTraits::op_begin(const_cast(that))[Idx]; + } + template Use &Op() { + return OpFrom(this); } + template const Use &Op() const { + return OpFrom(this); + } +public: Value *getOperand(unsigned i) const { assert(i < NumOperands && "getOperand() out of range!"); return OperandList[i]; } void setOperand(unsigned i, Value *Val) { assert(i < NumOperands && "setOperand() out of range!"); + assert((!isa((const Value*)this) || + isa((const Value*)this)) && + "Cannot mutate a constant with setOperand!"); OperandList[i] = Val; } + const Use &getOperandUse(unsigned i) const { + assert(i < NumOperands && "getOperandUse() out of range!"); + return OperandList[i]; + } + Use &getOperandUse(unsigned i) { + assert(i < NumOperands && "getOperandUse() out of range!"); + return OperandList[i]; + } + unsigned getNumOperands() const { return NumOperands; } // --------------------------------------------------------------------------- @@ -110,6 +118,45 @@ public: inline op_iterator op_end() { return OperandList+NumOperands; } inline const_op_iterator op_end() const { return OperandList+NumOperands; } + /// Convenience iterator for directly iterating over the Values in the + /// OperandList + class value_op_iterator : public std::iterator { + op_iterator OI; + public: + explicit value_op_iterator(Use *U) : OI(U) {} + + bool operator==(const value_op_iterator &x) const { + return OI == x.OI; + } + bool operator!=(const value_op_iterator &x) const { + return !operator==(x); + } + + /// Iterator traversal: forward iteration only + value_op_iterator &operator++() { // Preincrement + ++OI; + return *this; + } + value_op_iterator operator++(int) { // Postincrement + value_op_iterator tmp = *this; ++*this; return tmp; + } + + /// Retrieve a pointer to the current Value. + Value *operator*() const { + return *OI; + } + + Value *operator->() const { return operator*(); } + }; + + inline value_op_iterator value_op_begin() { + return value_op_iterator(op_begin()); + } + inline value_op_iterator value_op_end() { + return value_op_iterator(op_end()); + } + // dropAllReferences() - This function is in charge of "letting go" of all // objects that this User refers to. This allows one to // 'delete' a whole class at a time, even though there may be circular @@ -129,24 +176,11 @@ public: void replaceUsesOfWith(Value *From, Value *To); // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const User *) { return true; } static inline bool classof(const Value *V) { return isa(V) || isa(V); } }; -inline Use *OperandTraits::op_begin(User *U) { - return U->op_begin(); -} - -inline Use *OperandTraits::op_end(User *U) { - return U->op_end(); -} - -inline unsigned OperandTraits::operands(const User *U) { - return U->getNumOperands(); -} - template<> struct simplify_type { typedef Value* SimpleType;