X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FUser.h;h=df303d0dd5f289e24accff8608da0dd1b486d868;hb=553c42cefc9abe1f10ee33d34a12498b8ac12fe6;hp=a617f12b0a3d85602d1a57a625ed9d5cf34b1567;hpb=cbab0f7eddff0bee5ebb719b8628e706de016a40;p=oota-llvm.git diff --git a/include/llvm/User.h b/include/llvm/User.h index a617f12b0a3..df303d0dd5f 100644 --- a/include/llvm/User.h +++ b/include/llvm/User.h @@ -1,10 +1,17 @@ -//===-- llvm/User.h - User class definition ----------------------*- C++ -*--=// +//===-- llvm/User.h - User class definition ---------------------*- C++ -*-===// // -// This class defines the interface that one who 'use's a Value must implement. +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// 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) // //===----------------------------------------------------------------------===// @@ -12,68 +19,197 @@ #ifndef LLVM_USER_H #define LLVM_USER_H +#include "llvm/Support/ErrorHandling.h" #include "llvm/Value.h" -#include + +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 + User(const User &) LLVM_DELETED_FUNCTION; + void *operator new(size_t) LLVM_DELETED_FUNCTION; + template + friend struct HungoffOperandTraits; + virtual void anchor(); protected: - vector Operands; -public: - User(const Type *Ty, ValueTy vty, const string &name = ""); - virtual ~User() { dropAllReferences(); } + /// 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 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; - inline Value *getOperand(unsigned i) { - assert(i < Operands.size() && "getOperand() out of range!"); - return Operands[i]; + 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?"); } - inline const Value *getOperand(unsigned i) const { - assert(i < Operands.size() && "getOperand() const out of range!"); - return Operands[i]; + /// placement delete - required by std, but never called. + void operator delete(void*, unsigned, bool) { + llvm_unreachable("Constructor throws?"); } - inline void setOperand(unsigned i, Value *Val) { - assert(i < Operands.size() && "setOperand() out of range!"); - Operands[i] = Val; +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; } - inline unsigned getNumOperands() const { return Operands.size(); } + 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; } // --------------------------------------------------------------------------- // Operand Iterator interface... // - typedef vector::iterator op_iterator; - typedef vector::const_iterator op_const_iterator; + typedef Use* op_iterator; + typedef const Use* const_op_iterator; + + inline op_iterator op_begin() { return OperandList; } + inline const_op_iterator op_begin() const { return OperandList; } + 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) {} - inline op_iterator op_begin() { return Operands.begin(); } - inline op_const_iterator op_begin() const { return Operands.end(); } - inline op_iterator op_end() { return Operands.end(); } - inline op_const_iterator op_end() const { return Operands.end(); } + 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 - // valid on an object that has "dropped all references", except operator + // 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. // - inline void dropAllReferences() { - Operands.clear(); + void dropAllReferences() { + for (op_iterator i = op_begin(), e = op_end(); i != e; ++i) + i->set(0); } - // replaceUsesOfWith - Replaces all references to the "From" definition with - // references to the "To" definition. (defined in Value.cpp) - // + /// replaceUsesOfWith - Replaces all references to the "From" definition with + /// references to the "To" definition. + /// void replaceUsesOfWith(Value *From, Value *To); - // addOperand - This is a special purpose API that should not be used in most - // cases. It adds an empty (null) operand to the instruction specified. This - // is currently used by the back end as part of the "lowering" process... most - // optimizations will not handle instructions that are not in their normal - // form, so this method should be used with care. - // - void addOperand() { - Operands.push_back(Use(0, this)); + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *V) { + return isa(V) || isa(V); } }; +template<> struct simplify_type { + typedef Value* SimpleType; + + static SimpleType getSimplifiedValue(const User::op_iterator &Val) { + return static_cast(Val->get()); + } +}; + +template<> struct simplify_type + : public simplify_type {}; + +template<> struct simplify_type { + typedef Value* SimpleType; + + static SimpleType getSimplifiedValue(const User::const_op_iterator &Val) { + return static_cast(Val->get()); + } +}; + +template<> struct simplify_type + : public simplify_type {}; + + +// value_use_iterator::getOperandNo - Requires the definition of the User class. +template +unsigned value_use_iterator::getOperandNo() const { + return U - U->getUser()->op_begin(); +} + +} // End llvm namespace + #endif