X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FUser.h;h=df303d0dd5f289e24accff8608da0dd1b486d868;hb=b02ed5b8eafd11500bbefb7206ecbf5bc3fc324a;hp=d3e4f1ede2a9389d6644b93ace1920891da17e88;hpb=34cd4a484e532cc463fd5a4bf59b88d13c5467c1;p=oota-llvm.git diff --git a/include/llvm/User.h b/include/llvm/User.h index d3e4f1ede2a..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,32 +19,71 @@ #ifndef LLVM_USER_H #define LLVM_USER_H +#include "llvm/Support/ErrorHandling.h" #include "llvm/Value.h" namespace llvm { +/// OperandTraits - Compile-time customization of +/// operand-related allocators and accessors +/// for use of the User class +template +struct OperandTraits; + 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 - /// embedded into the derived class. For nodes of variable arity - /// (e.g. ConstantArrays, CallInst, PHINodes, ReturnInst 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. /// unsigned NumOperands; - void *operator new(size_t s, size_t) { - return ::operator new(s); + void *operator new(size_t s, unsigned Us); + User(Type *ty, unsigned vty, Use *OpList, unsigned NumOps) + : Value(ty, vty), OperandList(OpList), NumOperands(NumOps) {} + Use *allocHungoffUses(unsigned) const; + void dropHungoffUses() { + Use::zap(OperandList, OperandList + NumOperands, true); + OperandList = 0; + // Reset NumOperands so User::operator delete() does the right thing. + NumOperands = 0; + } +public: + ~User() { + Use::zap(OperandList, OperandList + NumOperands); + } + /// operator delete - free memory allocated for User and Use objects + void operator delete(void *Usr); + /// placement delete - required by std, but never called. + void operator delete(void*, unsigned) { + llvm_unreachable("Constructor throws?"); + } + /// placement delete - required by std, but never called. + void operator delete(void*, unsigned, bool) { + llvm_unreachable("Constructor throws?"); + } +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); } - User(const Type *Ty, unsigned vty, Use *OpList, unsigned NumOps) - : Value(Ty, vty), OperandList(OpList), NumOperands(NumOps) {} - public: Value *getOperand(unsigned i) const { assert(i < NumOperands && "getOperand() out of range!"); @@ -52,8 +91,20 @@ public: } 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; } // --------------------------------------------------------------------------- @@ -67,18 +118,56 @@ 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 - // references... first all references are dropped, and all use counts go to - // zero. Then everything is delete'd for real. Note that no operations are + // references... First all references are dropped, and all use counts go to + // zero. Then everything is deleted for real. Note that no operations are // valid on an object that has "dropped all references", except operator // delete. // void dropAllReferences() { - Use *OL = OperandList; - for (unsigned i = 0, e = NumOperands; i != e; ++i) - OL[i].set(0); + for (op_iterator i = op_begin(), e = op_end(); i != e; ++i) + i->set(0); } /// replaceUsesOfWith - Replaces all references to the "From" definition with @@ -87,7 +176,6 @@ 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); }