X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=include%2Fllvm%2FIR%2FUser.h;h=885ae197d2283439bd58f57081db81fa369064d2;hb=688b5df9e2910ecb5ec5c053b8b4365576d6a5aa;hp=3b72cfe1587b45630f269fe0cc31f791a47a893c;hpb=aaa3fa61d2d2107095f90648249ffb2f6f7099ca;p=oota-llvm.git diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index 3b72cfe1587..885ae197d22 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -19,9 +19,11 @@ #ifndef LLVM_IR_USER_H #define LLVM_IR_USER_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" #include "llvm/IR/Value.h" +#include "llvm/Support/AlignOf.h" #include "llvm/Support/ErrorHandling.h" namespace llvm { @@ -34,27 +36,43 @@ struct OperandTraits; class User : public Value { User(const User &) = delete; - void *operator new(size_t) = delete; template friend struct HungoffOperandTraits; virtual void anchor(); + + LLVM_ATTRIBUTE_ALWAYS_INLINE inline static void * + allocateFixedOperandUser(size_t, unsigned, unsigned); + protected: - /// \brief This is a pointer to the array of Uses for this User. + /// Allocate a User with an operand pointer co-allocated. /// - /// 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 *LegacyOperandList; + /// This is used for subclasses which need to allocate a variable number + /// of operands, ie, 'hung off uses'. + void *operator new(size_t Size); -protected: - void *operator new(size_t s, unsigned Us); + /// Allocate a User with the operands co-allocated. + /// + /// This is used for subclasses which have a fixed number of operands. + void *operator new(size_t Size, unsigned Us); + + /// Allocate a User with the operands co-allocated. If DescBytes is non-zero + /// then allocate an additional DescBytes bytes before the operands. These + /// bytes can be accessed by calling getDescriptor. + /// + /// DescBytes needs to be divisible by sizeof(void *). The allocated + /// descriptor, if any, is aligned to sizeof(void *) bytes. + /// + /// This is used for subclasses which have a fixed number of operands. + void *operator new(size_t Size, unsigned Us, unsigned DescBytes); - User(Type *ty, unsigned vty, Use *OpList, unsigned NumOps) + User(Type *ty, unsigned vty, Use *, unsigned NumOps) : Value(ty, vty) { - setOperandList(OpList); assert(NumOps < (1u << NumUserOperandsBits) && "Too many operands"); NumUserOperands = NumOps; + // If we have hung off uses, then the operand list should initially be + // null. + assert((!HasHungOffUses || !getOperandList()) && + "Error in initializing hung off uses for User"); } /// \brief Allocate the array of Uses, followed by a pointer @@ -69,14 +87,6 @@ protected: public: ~User() override { - // drop the hung off uses. - Use::zap(getOperandList(), getOperandList() + NumUserOperands, - HasHungOffUses); - if (HasHungOffUses) { - setOperandList(nullptr); - // Reset NumOperands so User::operator delete() does the right thing. - NumUserOperands = 0; - } } /// \brief Free memory allocated for User and Use objects. void operator delete(void *Usr); @@ -101,12 +111,23 @@ protected: return OpFrom(this); } private: + Use *&getHungOffOperands() { return *(reinterpret_cast(this) - 1); } + + Use *getIntrusiveOperands() { + return reinterpret_cast(this) - NumUserOperands; + } + void setOperandList(Use *NewList) { - LegacyOperandList = NewList; + assert(HasHungOffUses && + "Setting operand list only required for hung off uses"); + getHungOffOperands() = NewList; } public: - Use *getOperandList() const { - return LegacyOperandList; + Use *getOperandList() { + return HasHungOffUses ? getHungOffOperands() : getIntrusiveOperands(); + } + const Use *getOperandList() const { + return const_cast(this)->getOperandList(); } Value *getOperand(unsigned i) const { assert(i < NumUserOperands && "getOperand() out of range!"); @@ -130,6 +151,12 @@ public: unsigned getNumOperands() const { return NumUserOperands; } + /// Returns the descriptor co-allocated with this User instance. + ArrayRef getDescriptor() const; + + /// Returns the descriptor co-allocated with this User instance. + MutableArrayRef getDescriptor(); + /// Set the number of operands on a GlobalVariable. /// /// GlobalVariable always allocates space for a single operands, but @@ -160,18 +187,18 @@ public: typedef iterator_range op_range; typedef iterator_range const_op_range; - inline op_iterator op_begin() { return getOperandList(); } - inline const_op_iterator op_begin() const { return getOperandList(); } - inline op_iterator op_end() { + op_iterator op_begin() { return getOperandList(); } + const_op_iterator op_begin() const { return getOperandList(); } + op_iterator op_end() { return getOperandList() + NumUserOperands; } - inline const_op_iterator op_end() const { + const_op_iterator op_end() const { return getOperandList() + NumUserOperands; } - inline op_range operands() { + op_range operands() { return op_range(op_begin(), op_end()); } - inline const_op_range operands() const { + const_op_range operands() const { return const_op_range(op_begin(), op_end()); } @@ -186,14 +213,14 @@ public: Value *operator->() const { return operator*(); } }; - inline value_op_iterator value_op_begin() { + value_op_iterator value_op_begin() { return value_op_iterator(op_begin()); } - inline value_op_iterator value_op_end() { + value_op_iterator value_op_end() { return value_op_iterator(op_end()); } - inline iterator_range operand_values() { - return iterator_range(value_op_begin(), value_op_end()); + iterator_range operand_values() { + return make_range(value_op_begin(), value_op_end()); } /// \brief Drop all references to operands. @@ -220,6 +247,11 @@ public: return isa(V) || isa(V); } }; +// Either Use objects, or a Use pointer can be prepended to User. +static_assert(AlignOf::Alignment >= AlignOf::Alignment, + "Alignment is insufficient after objects prepended to User"); +static_assert(AlignOf::Alignment >= AlignOf::Alignment, + "Alignment is insufficient after objects prepended to User"); template<> struct simplify_type { typedef Value* SimpleType;