merge of use-diet branch to trunk

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50943 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Gabor Greif 2008-05-10 08:32:32 +00:00
parent 4982babf4a
commit efe65369a7
18 changed files with 1528 additions and 584 deletions

View File

@ -110,6 +110,10 @@ E: greened@obbligato.org
D: Miscellaneous bug fixes
D: Register allocation refactoring
N: Gabor Greif
E: ggreif@gmail.com
D: Improvements for space efficiency
N: Gordon Henriksen
E: gordonhenriksen@mac.com
D: Pluggable GC support

View File

@ -22,6 +22,7 @@
#include "llvm/Constant.h"
#include "llvm/Type.h"
#include "llvm/OperandTraits.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APFloat.h"
@ -318,7 +319,6 @@ class ConstantArray : public Constant {
ConstantArray(const ConstantArray &); // DO NOT IMPLEMENT
protected:
ConstantArray(const ArrayType *T, const std::vector<Constant*> &Val);
~ConstantArray();
public:
/// get() - Static factory methods - Return objects of the specified value
static Constant *get(const ArrayType *T, const std::vector<Constant*> &);
@ -336,6 +336,9 @@ public:
/// null termination.
static Constant *get(const std::string &Initializer, bool AddNull = true);
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
/// getType - Specialize the getType() method to always return an ArrayType,
/// which reduces the amount of casting needed in parts of the compiler.
///
@ -374,6 +377,11 @@ public:
}
};
template <>
struct OperandTraits<ConstantArray> : VariadicOperandTraits<> {
};
DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantArray, Constant)
//===----------------------------------------------------------------------===//
// ConstantStruct - Constant Struct Declarations
@ -384,7 +392,6 @@ class ConstantStruct : public Constant {
ConstantStruct(const ConstantStruct &); // DO NOT IMPLEMENT
protected:
ConstantStruct(const StructType *T, const std::vector<Constant*> &Val);
~ConstantStruct();
public:
/// get() - Static factory methods - Return objects of the specified value
///
@ -396,6 +403,9 @@ public:
return get(std::vector<Constant*>(Vals, Vals+NumVals), Packed);
}
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
/// getType() specialization - Reduce amount of casting...
///
inline const StructType *getType() const {
@ -419,6 +429,12 @@ public:
}
};
template <>
struct OperandTraits<ConstantStruct> : VariadicOperandTraits<> {
};
DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantStruct, Constant)
//===----------------------------------------------------------------------===//
/// ConstantVector - Constant Vector Declarations
///
@ -428,7 +444,6 @@ class ConstantVector : public Constant {
ConstantVector(const ConstantVector &); // DO NOT IMPLEMENT
protected:
ConstantVector(const VectorType *T, const std::vector<Constant*> &Val);
~ConstantVector();
public:
/// get() - Static factory methods - Return objects of the specified value
static Constant *get(const VectorType *T, const std::vector<Constant*> &);
@ -438,6 +453,9 @@ public:
return get(std::vector<Constant*>(Vals, Vals+NumVals));
}
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
/// getType - Specialize the getType() method to always return a VectorType,
/// which reduces the amount of casting needed in parts of the compiler.
///
@ -475,6 +493,12 @@ public:
}
};
template <>
struct OperandTraits<ConstantVector> : VariadicOperandTraits<> {
};
DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantVector, Constant)
//===----------------------------------------------------------------------===//
/// ConstantPointerNull - a constant pointer value that points to null
///
@ -573,6 +597,9 @@ public:
static Constant *getIntToPtr(Constant *C, const Type *Ty);
static Constant *getBitCast (Constant *C, const Type *Ty);
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
// @brief Convenience function for getting one of the casting operations
// using a CastOps opcode.
static Constant *getCast(
@ -709,13 +736,13 @@ public:
virtual void destroyConstant();
virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U);
/// Override methods to provide more type information...
/* /// Override methods to provide more type information...
inline Constant *getOperand(unsigned i) {
return cast<Constant>(User::getOperand(i));
}
inline Constant *getOperand(unsigned i) const {
return const_cast<Constant*>(cast<Constant>(User::getOperand(i)));
}
}*/
/// Methods for support type inquiry through isa, cast, and dyn_cast:
@ -725,6 +752,11 @@ public:
}
};
template <>
struct OperandTraits<ConstantExpr> : VariadicOperandTraits<1> {
};
DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantExpr, Constant)
//===----------------------------------------------------------------------===//
/// UndefValue - 'undef' values are things that do not have specified contents.

View File

@ -16,6 +16,7 @@
#define LLVM_GLOBAL_ALIAS_H
#include "llvm/GlobalValue.h"
#include "llvm/OperandTraits.h"
namespace llvm {
@ -42,17 +43,19 @@ class GlobalAlias : public GlobalValue {
GlobalAlias *getPrev() { return Prev; }
const GlobalAlias *getPrev() const { return Prev; }
Use Aliasee;
public:
// allocate space for exactly zero operands
// allocate space for exactly one operand
void *operator new(size_t s) {
return User::operator new(s, 0);
return User::operator new(s, 1);
}
/// GlobalAlias ctor - If a parent module is specified, the alias is
/// automatically inserted into the end of the specified module's alias list.
GlobalAlias(const Type *Ty, LinkageTypes Linkage, const std::string &Name = "",
Constant* Aliasee = 0, Module *Parent = 0);
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
/// isDeclaration - Is this global variable lacking an initializer? If so,
/// the global variable is defined in some other translation unit, and is thus
/// only a declaration here.
@ -95,6 +98,12 @@ public:
}
};
template <>
struct OperandTraits<GlobalAlias> : FixedNumOperandTraits<1> {
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalAlias, Value)
} // End llvm namespace
#endif

View File

@ -21,6 +21,7 @@
#define LLVM_GLOBAL_VARIABLE_H
#include "llvm/GlobalValue.h"
#include "llvm/OperandTraits.h"
namespace llvm {
@ -44,26 +45,32 @@ class GlobalVariable : public GlobalValue {
bool isConstantGlobal : 1; // Is this a global constant?
bool isThreadLocalSymbol : 1; // Is this symbol "Thread Local"?
Use Initializer;
public:
// allocate space for exactly zero operands
// allocate space for exactly one operand
void *operator new(size_t s) {
return User::operator new(s, 0);
return User::operator new(s, 1);
}
/// GlobalVariable ctor - If a parent module is specified, the global is
/// automatically inserted into the end of the specified modules global list.
GlobalVariable(const Type *Ty, bool isConstant, LinkageTypes Linkage,
Constant *Initializer = 0, const std::string &Name = "",
Module *Parent = 0, bool ThreadLocal = false,
Module *Parent = 0, bool ThreadLocal = false,
unsigned AddressSpace = 0);
/// GlobalVariable ctor - This creates a global and inserts it before the
/// specified other global.
GlobalVariable(const Type *Ty, bool isConstant, LinkageTypes Linkage,
Constant *Initializer, const std::string &Name,
GlobalVariable *InsertBefore, bool ThreadLocal = false,
GlobalVariable *InsertBefore, bool ThreadLocal = false,
unsigned AddressSpace = 0);
~GlobalVariable() {
NumOperands = 1; // FIXME: needed by operator delete
}
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
/// isDeclaration - Is this global variable lacking an initializer? If so,
/// the global variable is defined in some other translation unit, and is thus
/// only a declaration here.
@ -79,24 +86,24 @@ public:
/// illegal to call this method if the global is external, because we cannot
/// tell what the value is initialized to!
///
inline Constant *getInitializer() const {
inline /*const FIXME*/ Constant *getInitializer() const {
assert(hasInitializer() && "GV doesn't have initializer!");
return reinterpret_cast<Constant*>(Initializer.get());
return static_cast<Constant*>(Op<0>().get());
}
inline Constant *getInitializer() {
assert(hasInitializer() && "GV doesn't have initializer!");
return reinterpret_cast<Constant*>(Initializer.get());
return static_cast<Constant*>(Op<0>().get());
}
inline void setInitializer(Constant *CPV) {
if (CPV == 0) {
if (hasInitializer()) {
Initializer.set(0);
Op<0>().set(0);
NumOperands = 0;
}
} else {
if (!hasInitializer())
NumOperands = 1;
Initializer.set(CPV);
Op<0>().set(CPV);
}
}
@ -141,6 +148,12 @@ private:
const GlobalVariable *getPrev() const { return Prev; }
};
template <>
struct OperandTraits<GlobalVariable> : OptionalOperandTraits<> {
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalVariable, Value)
} // End llvm namespace
#endif

View File

@ -17,6 +17,7 @@
#define LLVM_INSTRUCTION_TYPES_H
#include "llvm/Instruction.h"
#include "llvm/OperandTraits.h"
namespace llvm {
@ -78,22 +79,22 @@ public:
}
};
//===----------------------------------------------------------------------===//
// UnaryInstruction Class
//===----------------------------------------------------------------------===//
class UnaryInstruction : public Instruction {
void *operator new(size_t, unsigned); // Do not implement
Use Op;
// avoiding warning: 'this' : used in base member initializer list
UnaryInstruction* this_() { return this; }
protected:
UnaryInstruction(const Type *Ty, unsigned iType, Value *V, Instruction *IB =0)
: Instruction(Ty, iType, &Op, 1, IB), Op(V, this_()) {
UnaryInstruction(const Type *Ty, unsigned iType, Value *V, Instruction *IB = 0)
: Instruction(Ty, iType, &Op<0>(), 1, IB) {
Op<0>() = V;
}
UnaryInstruction(const Type *Ty, unsigned iType, Value *V, BasicBlock *IAE)
: Instruction(Ty, iType, &Op, 1, IAE), Op(V, this_()) {
: Instruction(Ty, iType, &Op<0>(), 1, IAE) {
Op<0>() = V;
}
public:
// allocate space for exactly one operand
@ -104,16 +105,8 @@ public:
// Out of line virtual method, so the vtable, etc has a home.
~UnaryInstruction();
// Transparently provide more efficient getOperand methods.
Value *getOperand(unsigned i) const {
assert(i == 0 && "getOperand() out of range!");
return Op;
}
void setOperand(unsigned i, Value *Val) {
assert(i == 0 && "setOperand() out of range!");
Op = Val;
}
unsigned getNumOperands() const { return 1; }
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const UnaryInstruction *) { return true; }
@ -130,13 +123,18 @@ public:
}
};
template <>
struct OperandTraits<UnaryInstruction> : FixedNumOperandTraits<1> {
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value)
//===----------------------------------------------------------------------===//
// BinaryOperator Class
//===----------------------------------------------------------------------===//
class BinaryOperator : public Instruction {
void *operator new(size_t, unsigned); // Do not implement
Use Ops[2];
protected:
void init(BinaryOps iType);
BinaryOperator(BinaryOps iType, Value *S1, Value *S2, const Type *Ty,
@ -150,15 +148,7 @@ public:
}
/// Transparently provide more efficient getOperand methods.
Value *getOperand(unsigned i) const {
assert(i < 2 && "getOperand() out of range!");
return Ops[i];
}
void setOperand(unsigned i, Value *Val) {
assert(i < 2 && "setOperand() out of range!");
Ops[i] = Val;
}
unsigned getNumOperands() const { return 2; }
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
/// create() - Construct a binary instruction, given the opcode and the two
/// operands. Optionally (if InstBefore is specified) insert the instruction
@ -251,6 +241,12 @@ public:
}
};
template <>
struct OperandTraits<BinaryOperator> : FixedNumOperandTraits<2> {
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value)
//===----------------------------------------------------------------------===//
// CastInst Class
//===----------------------------------------------------------------------===//
@ -497,6 +493,7 @@ public:
/// This class is the base class for the comparison instructions.
/// @brief Abstract base class of comparison instructions.
// FIXME: why not derive from BinaryOperator?
class CmpInst: public Instruction {
void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
CmpInst(); // do not implement
@ -507,8 +504,6 @@ protected:
CmpInst(Instruction::OtherOps op, unsigned short pred, Value *LHS, Value *RHS,
const std::string &Name, BasicBlock *InsertAtEnd);
Use Ops[2]; // CmpInst instructions always have 2 operands, optimize
public:
// allocate space for exactly two operands
void *operator new(size_t s) {
@ -548,17 +543,7 @@ public:
}
/// @brief Provide more efficient getOperand methods.
Value *getOperand(unsigned i) const {
assert(i < 2 && "getOperand() out of range!");
return Ops[i];
}
void setOperand(unsigned i, Value *Val) {
assert(i < 2 && "setOperand() out of range!");
Ops[i] = Val;
}
/// @brief CmpInst instructions always have 2 operands.
unsigned getNumOperands() const { return 2; }
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
/// This is just a convenience that dispatches to the subclasses.
/// @brief Swap the operands and adjust predicate accordingly to retain
@ -598,6 +583,14 @@ public:
}
};
// FIXME: these are redundant if CmpInst < BinaryOperator
template <>
struct OperandTraits<CmpInst> : FixedNumOperandTraits<2> {
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CmpInst, Value)
} // End llvm namespace
#endif

View File

@ -20,7 +20,6 @@
namespace llvm {
struct AssemblyAnnotationWriter;
class BinaryOperator;
template<typename ValueSubClass, typename ItemParentClass>
class SymbolTableListTraits;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,163 @@
//===-- llvm/OperandTraits.h - OperandTraits class definition ---------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the traits classes that are handy for enforcing the correct
// layout of various User subclasses. It also provides the means for accessing
// the operands in the most efficient manner.
//
#ifndef LLVM_OPERAND_TRAITS_H
#define LLVM_OPERAND_TRAITS_H
#include "llvm/User.h"
namespace llvm {
//===----------------------------------------------------------------------===//
// FixedNumOperands Trait Class
//===----------------------------------------------------------------------===//
template <unsigned ARITY>
struct FixedNumOperandTraits {
static Use *op_begin(User* U) {
return reinterpret_cast<Use*>(U) - ARITY;
}
static Use *op_end(User* U) {
return reinterpret_cast<Use*>(U);
}
static unsigned operands(const User*) {
return ARITY;
}
struct prefix {
Use Ops[ARITY];
prefix(); // DO NOT IMPLEMENT
};
template <class U>
struct Layout {
struct overlay : prefix, U {
overlay(); // DO NOT IMPLEMENT
};
};
static inline void *allocate(unsigned); // FIXME
};
//===----------------------------------------------------------------------===//
// OptionalOperands Trait Class
//===----------------------------------------------------------------------===//
template <unsigned ARITY = 1>
struct OptionalOperandTraits : FixedNumOperandTraits<ARITY> {
static unsigned operands(const User *U) {
return U->getNumOperands();
}
};
//===----------------------------------------------------------------------===//
// VariadicOperand Trait Class
//===----------------------------------------------------------------------===//
template <unsigned MINARITY = 0>
struct VariadicOperandTraits {
static Use *op_begin(User* U) {
return reinterpret_cast<Use*>(U) - U->getNumOperands();
}
static Use *op_end(User* U) {
return reinterpret_cast<Use*>(U);
}
static unsigned operands(const User *U) {
return U->getNumOperands();
}
static inline void *allocate(unsigned); // FIXME
};
//===----------------------------------------------------------------------===//
// HungoffOperand Trait Class
//===----------------------------------------------------------------------===//
template <unsigned MINARITY = 1>
struct HungoffOperandTraits {
static Use *op_begin(User* U) {
return U->OperandList;
}
static Use *op_end(User* U) {
return U->OperandList + U->getNumOperands();
}
static unsigned operands(const User *U) {
return U->getNumOperands();
}
static inline void *allocate(unsigned); // FIXME
};
/// Macro for generating in-class operand accessor declarations.
/// It should only be called in the public section of the interface.
///
#define DECLARE_TRANSPARENT_OPERAND_ACCESSORS(VALUECLASS) \
public: \
inline VALUECLASS *getOperand(unsigned) const; \
inline void setOperand(unsigned, VALUECLASS*); \
protected: \
template <unsigned> inline Use &Op(); \
template <unsigned> inline const Use &Op() const; \
public: \
inline unsigned getNumOperands() const
/// Macro for generating out-of-class operand accessor definitions
#define DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CLASS, VALUECLASS) \
VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \
assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
&& "getOperand() out of range!"); \
return static_cast<VALUECLASS*>( \
OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture]); \
} \
void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \
assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
&& "setOperand() out of range!"); \
OperandTraits<CLASS>::op_begin(this)[i_nocapture] = Val_nocapture; \
} \
unsigned CLASS::getNumOperands() const { \
return OperandTraits<CLASS>::operands(this); \
} \
template <unsigned Idx_nocapture> Use &CLASS::Op() { \
return OperandTraits<CLASS>::op_begin(this)[Idx_nocapture]; \
} \
template <unsigned Idx_nocapture> const Use &CLASS::Op() const { \
return OperandTraits<CLASS>::op_begin( \
const_cast<CLASS*>(this))[Idx_nocapture]; \
}
/// Macro for generating out-of-class operand accessor
/// definitions with casted result
#define DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(CLASS, VALUECLASS) \
VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \
assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
&& "getOperand() out of range!"); \
return cast<VALUECLASS>( \
OperandTraits<CLASS>::op_begin(const_cast<CLASS*>(this))[i_nocapture]); \
} \
void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \
assert(i_nocapture < OperandTraits<CLASS>::operands(this) \
&& "setOperand() out of range!"); \
OperandTraits<CLASS>::op_begin(this)[i_nocapture] = Val_nocapture; \
} \
unsigned CLASS::getNumOperands() const { \
return OperandTraits<CLASS>::operands(this); \
} \
template <unsigned Idx_nocapture> Use &CLASS::Op() { \
return OperandTraits<CLASS>::op_begin(this)[Idx_nocapture]; \
} \
template <unsigned Idx_nocapture> const Use &CLASS::Op() const { \
return OperandTraits<CLASS>::op_begin( \
const_cast<CLASS*>(this))[Idx_nocapture]; \
}
} // End llvm namespace
#endif

View File

@ -25,6 +25,40 @@ class Value;
class User;
//===----------------------------------------------------------------------===//
// Generic Tagging Functions
//===----------------------------------------------------------------------===//
/// Tag - generic tag type for (at least 32 bit) pointers
enum Tag { noTag, tagOne, tagTwo, tagThree };
/// addTag - insert tag bits into an (untagged) pointer
template <typename T, typename TAG>
inline T *addTag(const T *P, TAG Tag) {
return reinterpret_cast<T*>(ptrdiff_t(P) | Tag);
}
/// stripTag - remove tag bits from a pointer,
/// making it dereferencable
template <ptrdiff_t MASK, typename T>
inline T *stripTag(const T *P) {
return reinterpret_cast<T*>(ptrdiff_t(P) & ~MASK);
}
/// extractTag - extract tag bits from a pointer
template <typename TAG, TAG MASK, typename T>
inline TAG extractTag(const T *P) {
return TAG(ptrdiff_t(P) & MASK);
}
/// transferTag - transfer tag bits from a pointer,
/// to an untagged pointer
template <ptrdiff_t MASK, typename T>
inline T *transferTag(const T *From, const T *To) {
return reinterpret_cast<T*>((ptrdiff_t(From) & MASK) | ptrdiff_t(To));
}
//===----------------------------------------------------------------------===//
// Use Class
//===----------------------------------------------------------------------===//
@ -35,20 +69,36 @@ class Use {
public:
inline void init(Value *V, User *U);
Use(Value *V, User *U) { init(V, U); }
Use(const Use &U) { init(U.Val, U.U); }
private:
/// Allow std::swap some intimacy
template <typename U> friend void std::swap(U&, U&);
/// Copy ctor - Only for std::swap
Use(const Use &U) { init(U.get(), 0); }
/// Destructor - Only for zap() and std::swap
inline ~Use() {
if (Val) removeFromList();
if (get()) removeFromList();
}
/// Default ctor - This leaves the Use completely unitialized. The only thing
/// Default ctor - This leaves the Use completely uninitialized. The only thing
/// that is valid to do with this use is to call the "init" method.
inline Use() : Val(0) {}
inline Use() {}
enum PrevPtrTag { zeroDigitTag = noTag
, oneDigitTag = tagOne
, stopTag = tagTwo
, fullStopTag = tagThree };
public:
operator Value*() const { return Val; }
Value *get() const { return Val; }
User *getUser() const { return U; }
User *getUser() const;
const Use* getImpliedUser() const;
static Use *initTags(Use *Start, Use *Stop, ptrdiff_t Done = 0);
static void zap(Use *Start, const Use *Stop, bool del = false);
inline void set(Value *Val);
@ -57,7 +107,7 @@ public:
return RHS;
}
const Use &operator=(const Use &RHS) {
set(RHS.Val);
set(RHS.get());
return *this;
}
@ -66,19 +116,22 @@ public:
Use *getNext() const { return Next; }
private:
Use *Next, **Prev;
Value *Val;
User *U;
Use *Next, **Prev;
void setPrev(Use **NewPrev) {
Prev = transferTag<fullStopTag>(Prev, NewPrev);
}
void addToList(Use **List) {
Next = *List;
if (Next) Next->Prev = &Next;
Prev = List;
if (Next) Next->setPrev(&Next);
setPrev(List);
*List = this;
}
void removeFromList() {
*Prev = Next;
if (Next) Next->Prev = Prev;
Use **StrippedPrev = stripTag<fullStopTag>(Prev);
*StrippedPrev = Next;
if (Next) Next->setPrev(StrippedPrev);
}
friend class Value;
@ -138,7 +191,7 @@ public:
// Retrieve a reference to the current User
UserTy *operator*() const {
assert(U && "Cannot increment end iterator!");
assert(U && "Cannot dereference end iterator!");
return U->getUser();
}

View File

@ -23,15 +23,203 @@
namespace llvm {
/*==============================================================================
-----------------------------------------------------------------
--- Interaction and relationship between User and Use objects ---
-----------------------------------------------------------------
A subclass of User can choose between incorporating its Use objects
or refer to them out-of-line by means of a pointer. A mixed variant
(some Uses inline others hung off) is impractical and breaks the invariant
that the Use objects belonging to the same User form a contiguous array.
We have 2 different layouts in the User (sub)classes:
Layout a)
The Use object(s) are inside (resp. at fixed offset) of the User
object and there are a fixed number of them.
Layout b)
The Use object(s) are referenced by a pointer to an
array from the User object and there may be a variable
number of them.
Initially each layout will possess a direct pointer to the
start of the array of Uses. Though not mandatory for layout a),
we stick to this redundancy for the sake of simplicity.
The User object will also store the number of Use objects it
has. (Theoretically this information can also be calculated
given the scheme presented below.)
Special forms of allocation operators (operator new)
will enforce the following memory layouts:
# Layout a) will be modelled by prepending the User object
# by the Use[] array.
#
# ...---.---.---.---.-------...
# | P | P | P | P | User
# '''---'---'---'---'-------'''
# Layout b) will be modelled by pointing at the Use[] array.
#
# .-------...
# | User
# '-------'''
# |
# v
# .---.---.---.---...
# | P | P | P | P |
# '---'---'---'---'''
(In the above figures 'P' stands for the Use** that
is stored in each Use object in the member Use::Prev)
Since the Use objects will be deprived of the direct pointer to
their User objects, there must be a fast and exact method to
recover it. This is accomplished by the following scheme:
A bit-encoding in the 2 LSBits of the Use::Prev will allow to find the
start of the User object:
00 --> binary digit 0
01 --> binary digit 1
10 --> stop and calc (s)
11 --> full stop (S)
Given a Use*, all we have to do is to walk till we get
a stop and we either have a User immediately behind or
we have to walk to the next stop picking up digits
and calculating the offset:
.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.----------------
| 1 | s | 1 | 0 | 1 | 0 | s | 1 | 1 | 0 | s | 1 | 1 | s | 1 | S | User (or User*)
'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'----------------
|+15 |+10 |+6 |+3 |+1
| | | | |__>
| | | |__________>
| | |______________________>
| |______________________________________>
|__________________________________________________________>
Only the significant number of bits need to be stored between the
stops, so that the worst case is 20 memory accesses when there are
1000 Use objects.
The following literate Haskell fragment demonstrates the concept:
> import Test.QuickCheck
>
> digits :: Int -> [Char] -> [Char]
> digits 0 acc = '0' : acc
> digits 1 acc = '1' : acc
> digits n acc = digits (n `div` 2) $ digits (n `mod` 2) acc
>
> dist :: Int -> [Char] -> [Char]
> dist 0 [] = ['S']
> dist 0 acc = acc
> dist 1 acc = let r = dist 0 acc in 's' : digits (length r) r
> dist n acc = dist (n - 1) $ dist 1 acc
>
> takeLast n ss = reverse $ take n $ reverse ss
>
> test = takeLast 40 $ dist 20 []
>
Printing <test> gives: "1s100000s11010s10100s1111s1010s110s11s1S"
The reverse algorithm computes the
length of the string just by examining
a certain prefix:
> pref :: [Char] -> Int
> pref "S" = 1
> pref ('s':'1':rest) = decode 2 1 rest
> pref (_:rest) = 1 + pref rest
>
> decode walk acc ('0':rest) = decode (walk + 1) (acc * 2) rest
> decode walk acc ('1':rest) = decode (walk + 1) (acc * 2 + 1) rest
> decode walk acc _ = walk + acc
>
Now, as expected, printing <pref test> gives 40.
We can quickCheck this with following property:
> testcase = dist 2000 []
> testcaseLength = length testcase
>
> identityProp n = n > 0 && n <= testcaseLength ==> length arr == pref arr
> where arr = takeLast n testcase
As expected <quickCheck identityProp> gives:
*Main> quickCheck identityProp
OK, passed 100 tests.
Let's be a bit more exhaustive:
>
> deepCheck p = check (defaultConfig { configMaxTest = 500 }) p
>
And here is the result of <deepCheck identityProp>:
*Main> deepCheck identityProp
OK, passed 500 tests.
To maintain the invariant that the 2 LSBits of each Use** in Use
never change after being set up, setters of Use::Prev must re-tag the
new Use** on every modification. Accordingly getters must strip the
tag bits.
For layout b) instead of the User we will find a pointer (User* with LSBit set).
Following this pointer brings us to the User. A portable trick will ensure
that the first bytes of User (if interpreted as a pointer) will never have
the LSBit set.
==============================================================================*/
/// OperandTraits - Compile-time customization of
/// operand-related allocators and accessors
/// for use of the User class
template <class>
struct OperandTraits;
class User;
/// OperandTraits<User> - specialization to User
template <>
struct OperandTraits<User> {
static inline Use *op_begin(User*);
static inline Use *op_end(User*);
static inline unsigned operands(const User*);
template <class U>
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
template <unsigned>
friend struct HungoffOperandTraits;
protected:
/// OperandList - This is a pointer to the array of Users for this operand.
/// 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
/// 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.
Use *OperandList;
@ -39,13 +227,43 @@ protected:
///
unsigned NumOperands;
void *operator new(size_t s, size_t) {
return ::operator new(s);
void *operator new(size_t s, unsigned Us) {
void *Storage = ::operator new(s + sizeof(Use) * Us);
Use *Start = static_cast<Use*>(Storage);
Use *End = Start + Us;
User *Obj = reinterpret_cast<User*>(End);
Obj->OperandList = Start;
Obj->NumOperands = Us;
Use::initTags(Start, End);
return Obj;
}
User(const 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);
}
public:
~User() {
Use::zap(OperandList, OperandList + NumOperands);
}
void operator delete(void *Usr) {
User *Start = static_cast<User*>(Usr);
Use *Storage = static_cast<Use*>(Usr) - Start->NumOperands;
::operator delete(Storage == Start->OperandList
? Storage
: Usr);
}
template <unsigned Idx> Use &Op() {
return OperandTraits<User>::op_begin(this)[Idx];
}
template <unsigned Idx> const Use &Op() const {
return OperandTraits<User>::op_begin(const_cast<User*>(this))[Idx];
}
Value *getOperand(unsigned i) const {
assert(i < NumOperands && "getOperand() out of range!");
return OperandList[i];
@ -93,6 +311,18 @@ public:
}
};
inline Use *OperandTraits<User>::op_begin(User *U) {
return U->op_begin();
}
inline Use *OperandTraits<User>::op_end(User *U) {
return U->op_end();
}
inline unsigned OperandTraits<User>::operands(const User *U) {
return U->getNumOperands();
}
template<> struct simplify_type<User::op_iterator> {
typedef Value* SimpleType;

View File

@ -232,10 +232,9 @@ inline std::ostream &operator<<(std::ostream &OS, const Value &V) {
return OS;
}
void Use::init(Value *v, User *user) {
Val = v;
U = user;
if (Val) Val->addUse(*this);
void Use::init(Value *V, User *user) {
Val = V;
if (V) V->addUse(*this);
}
void Use::set(Value *V) {

View File

@ -23,6 +23,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/OperandTraits.h"
using namespace llvm;
void BitcodeReader::FreeState() {
@ -115,55 +116,81 @@ static int GetDecodedBinaryOpcode(unsigned Val, const Type *Ty) {
}
}
namespace llvm {
namespace {
/// @brief A class for maintaining the slot number definition
/// as a placeholder for the actual definition for forward constants defs.
class ConstantPlaceHolder : public ConstantExpr {
ConstantPlaceHolder(); // DO NOT IMPLEMENT
void operator=(const ConstantPlaceHolder &); // DO NOT IMPLEMENT
Use Op;
public:
// allocate space for exactly one operand
void *operator new(size_t s) {
return User::operator new(s, 1);
}
explicit ConstantPlaceHolder(const Type *Ty)
: ConstantExpr(Ty, Instruction::UserOp1, &Op, 1),
Op(UndefValue::get(Type::Int32Ty), this) {
: ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) {
Op<0>() = UndefValue::get(Type::Int32Ty);
}
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
}
// FIXME: can we inherit this from ConstantExpr?
template <>
struct OperandTraits<ConstantPlaceHolder> : FixedNumOperandTraits<1> {
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantPlaceHolder, Value)
}
void BitcodeReaderValueList::resize(unsigned Desired) {
if (Desired > Capacity) {
// Since we expect many values to come from the bitcode file we better
// allocate the double amount, so that the array size grows exponentially
// at each reallocation. Also, add a small amount of 100 extra elements
// each time, to reallocate less frequently when the array is still small.
//
Capacity = Desired * 2 + 100;
Use *New = allocHungoffUses(Capacity);
Use *Old = OperandList;
unsigned Ops = getNumOperands();
for (int i(Ops - 1); i >= 0; --i)
New[i] = Old[i].get();
OperandList = New;
if (Old) Use::zap(Old, Old + Ops, true);
}
}
Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx,
const Type *Ty) {
if (Idx >= size()) {
// Insert a bunch of null values.
Uses.resize(Idx+1);
OperandList = &Uses[0];
resize(Idx + 1);
NumOperands = Idx+1;
}
if (Value *V = Uses[Idx]) {
if (Value *V = OperandList[Idx]) {
assert(Ty == V->getType() && "Type mismatch in constant table!");
return cast<Constant>(V);
}
// Create and return a placeholder, which will later be RAUW'd.
Constant *C = new ConstantPlaceHolder(Ty);
Uses[Idx].init(C, this);
OperandList[Idx].init(C, this);
return C;
}
Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, const Type *Ty) {
if (Idx >= size()) {
// Insert a bunch of null values.
Uses.resize(Idx+1);
OperandList = &Uses[0];
resize(Idx + 1);
NumOperands = Idx+1;
}
if (Value *V = Uses[Idx]) {
if (Value *V = OperandList[Idx]) {
assert((Ty == 0 || Ty == V->getType()) && "Type mismatch in value table!");
return V;
}
@ -173,7 +200,7 @@ Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, const Type *Ty) {
// Create and return a placeholder, which will later be RAUW'd.
Value *V = new Argument(Ty);
Uses[Idx].init(V, this);
OperandList[Idx].init(V, this);
return V;
}

View File

@ -17,7 +17,7 @@
#include "llvm/ModuleProvider.h"
#include "llvm/ParameterAttributes.h"
#include "llvm/Type.h"
#include "llvm/User.h"
#include "llvm/OperandTraits.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Bitcode/LLVMBitCodes.h"
#include "llvm/ADT/DenseMap.h"
@ -26,32 +26,43 @@
namespace llvm {
class MemoryBuffer;
//===----------------------------------------------------------------------===//
// BitcodeReaderValueList Class
//===----------------------------------------------------------------------===//
class BitcodeReaderValueList : public User {
std::vector<Use> Uses;
unsigned Capacity;
public:
BitcodeReaderValueList() : User(Type::VoidTy, Value::ArgumentVal, 0, 0) {}
BitcodeReaderValueList() : User(Type::VoidTy, Value::ArgumentVal, 0, 0)
, Capacity(0) {}
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
// vector compatibility methods
unsigned size() const { return getNumOperands(); }
void resize(unsigned);
void push_back(Value *V) {
Uses.push_back(Use(V, this));
OperandList = &Uses[0];
++NumOperands;
unsigned OldOps(NumOperands), NewOps(NumOperands + 1);
resize(NewOps);
NumOperands = NewOps;
OperandList[OldOps] = V;
}
void clear() {
std::vector<Use>().swap(Uses);
if (OperandList) dropHungoffUses(OperandList);
Capacity = 0;
}
Value *operator[](unsigned i) const { return getOperand(i); }
Value *back() const { return Uses.back(); }
void pop_back() { Uses.pop_back(); --NumOperands; }
Value *back() const { return getOperand(size() - 1); }
void pop_back() { setOperand(size() - 1, 0); --NumOperands; }
bool empty() const { return NumOperands == 0; }
void shrinkTo(unsigned N) {
assert(N <= NumOperands && "Invalid shrinkTo request!");
Uses.resize(N);
NumOperands = N;
while (NumOperands > N)
pop_back();
}
virtual void print(std::ostream&) const {}
@ -73,11 +84,20 @@ public:
private:
void initVal(unsigned Idx, Value *V) {
assert(Uses[Idx] == 0 && "Cannot init an already init'd Use!");
Uses[Idx].init(V, this);
if (Idx >= size()) {
// Insert a bunch of null values.
resize(Idx * 2 + 1);
}
assert(getOperand(Idx) == 0 && "Cannot init an already init'd Use!");
OperandList[Idx].init(V, this);
}
};
template <>
struct OperandTraits<BitcodeReaderValueList> : HungoffOperandTraits</*16 FIXME*/> {
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BitcodeReaderValueList, Value)
class BitcodeReader : public ModuleProvider {
MemoryBuffer *Buffer;

View File

@ -332,10 +332,10 @@ Constant *llvm::ConstantFoldExtractElementInstruction(const Constant *Val,
if (const ConstantVector *CVal = dyn_cast<ConstantVector>(Val)) {
if (const ConstantInt *CIdx = dyn_cast<ConstantInt>(Idx)) {
return const_cast<Constant*>(CVal->getOperand(CIdx->getZExtValue()));
return CVal->getOperand(CIdx->getZExtValue());
} else if (isa<UndefValue>(Idx)) {
// ee({w,x,y,z}, undef) -> w (an arbitrary value).
return const_cast<Constant*>(CVal->getOperand(0));
return CVal->getOperand(0);
}
}
return 0;
@ -401,7 +401,7 @@ Constant *llvm::ConstantFoldInsertElementInstruction(const Constant *Val,
/// return the specified element value. Otherwise return null.
static Constant *GetVectorElement(const Constant *C, unsigned EltNo) {
if (const ConstantVector *CV = dyn_cast<ConstantVector>(C))
return const_cast<Constant*>(CV->getOperand(EltNo));
return CV->getOperand(EltNo);
const Type *EltTy = cast<VectorType>(C->getType())->getElementType();
if (isa<ConstantAggregateZero>(C))
@ -1222,9 +1222,9 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred,
if (const ConstantVector *CP2 = dyn_cast<ConstantVector>(C2)) {
if (pred == FCmpInst::FCMP_OEQ || pred == FCmpInst::FCMP_UEQ) {
for (unsigned i = 0, e = CP1->getNumOperands(); i != e; ++i) {
Constant *C= ConstantExpr::getFCmp(FCmpInst::FCMP_OEQ,
const_cast<Constant*>(CP1->getOperand(i)),
const_cast<Constant*>(CP2->getOperand(i)));
Constant *C = ConstantExpr::getFCmp(FCmpInst::FCMP_OEQ,
CP1->getOperand(i),
CP2->getOperand(i));
if (ConstantInt *CB = dyn_cast<ConstantInt>(C))
return CB;
}
@ -1233,8 +1233,8 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred,
} else if (pred == ICmpInst::ICMP_EQ) {
for (unsigned i = 0, e = CP1->getNumOperands(); i != e; ++i) {
Constant *C = ConstantExpr::getICmp(ICmpInst::ICMP_EQ,
const_cast<Constant*>(CP1->getOperand(i)),
const_cast<Constant*>(CP2->getOperand(i)));
CP1->getOperand(i),
CP2->getOperand(i));
if (ConstantInt *CB = dyn_cast<ConstantInt>(C))
return CB;
}

View File

@ -354,7 +354,9 @@ ConstantFP *ConstantFP::get(const Type *Ty, double V) {
ConstantArray::ConstantArray(const ArrayType *T,
const std::vector<Constant*> &V)
: Constant(T, ConstantArrayVal, new Use[V.size()], V.size()) {
: Constant(T, ConstantArrayVal,
OperandTraits<ConstantArray>::op_end(this) - V.size(),
V.size()) {
assert(V.size() == T->getNumElements() &&
"Invalid initializer vector for constant array");
Use *OL = OperandList;
@ -369,13 +371,12 @@ ConstantArray::ConstantArray(const ArrayType *T,
}
}
ConstantArray::~ConstantArray() {
delete [] OperandList;
}
ConstantStruct::ConstantStruct(const StructType *T,
const std::vector<Constant*> &V)
: Constant(T, ConstantStructVal, new Use[V.size()], V.size()) {
: Constant(T, ConstantStructVal,
OperandTraits<ConstantStruct>::op_end(this) - V.size(),
V.size()) {
assert(V.size() == T->getNumElements() &&
"Invalid initializer vector for constant structure");
Use *OL = OperandList;
@ -392,14 +393,12 @@ ConstantStruct::ConstantStruct(const StructType *T,
}
}
ConstantStruct::~ConstantStruct() {
delete [] OperandList;
}
ConstantVector::ConstantVector(const VectorType *T,
const std::vector<Constant*> &V)
: Constant(T, ConstantVectorVal, new Use[V.size()], V.size()) {
: Constant(T, ConstantVectorVal,
OperandTraits<ConstantVector>::op_end(this) - V.size(),
V.size()) {
Use *OL = OperandList;
for (std::vector<Constant*>::const_iterator I = V.begin(), E = V.end();
I != E; ++I, ++OL) {
@ -412,10 +411,8 @@ ConstantVector::ConstantVector(const VectorType *T,
}
}
ConstantVector::~ConstantVector() {
delete [] OperandList;
}
namespace llvm {
// We declare several classes private to this file, so use an anonymous
// namespace
namespace {
@ -424,49 +421,54 @@ namespace {
/// behind the scenes to implement unary constant exprs.
class VISIBILITY_HIDDEN UnaryConstantExpr : public ConstantExpr {
void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
Use Op;
public:
// allocate space for exactly one operand
void *operator new(size_t s) {
return User::operator new(s, 1);
}
UnaryConstantExpr(unsigned Opcode, Constant *C, const Type *Ty)
: ConstantExpr(Ty, Opcode, &Op, 1), Op(C, this) {}
: ConstantExpr(Ty, Opcode, &Op<0>(), 1) {
Op<0>() = C;
}
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
/// BinaryConstantExpr - This class is private to Constants.cpp, and is used
/// behind the scenes to implement binary constant exprs.
class VISIBILITY_HIDDEN BinaryConstantExpr : public ConstantExpr {
void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
Use Ops[2];
public:
// allocate space for exactly two operands
void *operator new(size_t s) {
return User::operator new(s, 2);
}
BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2)
: ConstantExpr(C1->getType(), Opcode, Ops, 2) {
Ops[0].init(C1, this);
Ops[1].init(C2, this);
: ConstantExpr(C1->getType(), Opcode, &Op<0>(), 2) {
Op<0>().init(C1, this);
Op<1>().init(C2, this);
}
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
/// SelectConstantExpr - This class is private to Constants.cpp, and is used
/// behind the scenes to implement select constant exprs.
class VISIBILITY_HIDDEN SelectConstantExpr : public ConstantExpr {
void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
Use Ops[3];
public:
// allocate space for exactly three operands
void *operator new(size_t s) {
return User::operator new(s, 3);
}
SelectConstantExpr(Constant *C1, Constant *C2, Constant *C3)
: ConstantExpr(C2->getType(), Instruction::Select, Ops, 3) {
Ops[0].init(C1, this);
Ops[1].init(C2, this);
Ops[2].init(C3, this);
: ConstantExpr(C2->getType(), Instruction::Select, &Op<0>(), 3) {
Op<0>().init(C1, this);
Op<1>().init(C2, this);
Op<2>().init(C3, this);
}
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
/// ExtractElementConstantExpr - This class is private to
@ -474,7 +476,6 @@ public:
/// extractelement constant exprs.
class VISIBILITY_HIDDEN ExtractElementConstantExpr : public ConstantExpr {
void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
Use Ops[2];
public:
// allocate space for exactly two operands
void *operator new(size_t s) {
@ -482,10 +483,12 @@ public:
}
ExtractElementConstantExpr(Constant *C1, Constant *C2)
: ConstantExpr(cast<VectorType>(C1->getType())->getElementType(),
Instruction::ExtractElement, Ops, 2) {
Ops[0].init(C1, this);
Ops[1].init(C2, this);
Instruction::ExtractElement, &Op<0>(), 2) {
Op<0>().init(C1, this);
Op<1>().init(C2, this);
}
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
/// InsertElementConstantExpr - This class is private to
@ -493,7 +496,6 @@ public:
/// insertelement constant exprs.
class VISIBILITY_HIDDEN InsertElementConstantExpr : public ConstantExpr {
void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
Use Ops[3];
public:
// allocate space for exactly three operands
void *operator new(size_t s) {
@ -501,11 +503,13 @@ public:
}
InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3)
: ConstantExpr(C1->getType(), Instruction::InsertElement,
Ops, 3) {
Ops[0].init(C1, this);
Ops[1].init(C2, this);
Ops[2].init(C3, this);
&Op<0>(), 3) {
Op<0>().init(C1, this);
Op<1>().init(C2, this);
Op<2>().init(C3, this);
}
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
/// ShuffleVectorConstantExpr - This class is private to
@ -513,7 +517,6 @@ public:
/// shufflevector constant exprs.
class VISIBILITY_HIDDEN ShuffleVectorConstantExpr : public ConstantExpr {
void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
Use Ops[3];
public:
// allocate space for exactly three operands
void *operator new(size_t s) {
@ -521,32 +524,27 @@ public:
}
ShuffleVectorConstantExpr(Constant *C1, Constant *C2, Constant *C3)
: ConstantExpr(C1->getType(), Instruction::ShuffleVector,
Ops, 3) {
Ops[0].init(C1, this);
Ops[1].init(C2, this);
Ops[2].init(C3, this);
&Op<0>(), 3) {
Op<0>().init(C1, this);
Op<1>().init(C2, this);
Op<2>().init(C3, this);
}
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
/// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
/// used behind the scenes to implement getelementpr constant exprs.
class VISIBILITY_HIDDEN GetElementPtrConstantExpr : public ConstantExpr {
GetElementPtrConstantExpr(Constant *C, const std::vector<Constant*> &IdxList,
const Type *DestTy)
: ConstantExpr(DestTy, Instruction::GetElementPtr,
new Use[IdxList.size()+1], IdxList.size()+1) {
OperandList[0].init(C, this);
for (unsigned i = 0, E = IdxList.size(); i != E; ++i)
OperandList[i+1].init(IdxList[i], this);
}
const Type *DestTy);
public:
static GetElementPtrConstantExpr *Create(Constant *C, const std::vector<Constant*> &IdxList,
const Type *DestTy) {
return new(IdxList.size() + 1/*FIXME*/) GetElementPtrConstantExpr(C, IdxList, DestTy);
}
~GetElementPtrConstantExpr() {
delete [] OperandList;
const Type *DestTy) {
return new(IdxList.size() + 1) GetElementPtrConstantExpr(C, IdxList, DestTy);
}
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
// CompareConstantExpr - This class is private to Constants.cpp, and is used
@ -559,17 +557,77 @@ struct VISIBILITY_HIDDEN CompareConstantExpr : public ConstantExpr {
return User::operator new(s, 2);
}
unsigned short predicate;
Use Ops[2];
CompareConstantExpr(Instruction::OtherOps opc, unsigned short pred,
Constant* LHS, Constant* RHS)
: ConstantExpr(Type::Int1Ty, opc, Ops, 2), predicate(pred) {
OperandList[0].init(LHS, this);
OperandList[1].init(RHS, this);
: ConstantExpr(Type::Int1Ty, opc, &Op<0>(), 2), predicate(pred) {
Op<0>().init(LHS, this);
Op<1>().init(RHS, this);
}
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
} // end anonymous namespace
template <>
struct OperandTraits<UnaryConstantExpr> : FixedNumOperandTraits<1> {
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryConstantExpr, Value)
template <>
struct OperandTraits<BinaryConstantExpr> : FixedNumOperandTraits<2> {
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryConstantExpr, Value)
template <>
struct OperandTraits<SelectConstantExpr> : FixedNumOperandTraits<3> {
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectConstantExpr, Value)
template <>
struct OperandTraits<ExtractElementConstantExpr> : FixedNumOperandTraits<2> {
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementConstantExpr, Value)
template <>
struct OperandTraits<InsertElementConstantExpr> : FixedNumOperandTraits<3> {
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementConstantExpr, Value)
template <>
struct OperandTraits<ShuffleVectorConstantExpr> : FixedNumOperandTraits<3> {
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr, Value)
template <>
struct OperandTraits<GetElementPtrConstantExpr> : VariadicOperandTraits<1> {
};
GetElementPtrConstantExpr::GetElementPtrConstantExpr
(Constant *C,
const std::vector<Constant*> &IdxList,
const Type *DestTy)
: ConstantExpr(DestTy, Instruction::GetElementPtr,
OperandTraits<GetElementPtrConstantExpr>::op_end(this)
- (IdxList.size()+1),
IdxList.size()+1) {
OperandList[0].init(C, this);
for (unsigned i = 0, E = IdxList.size(); i != E; ++i)
OperandList[i+1].init(IdxList[i], this);
}
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrConstantExpr, Value)
template <>
struct OperandTraits<CompareConstantExpr> : FixedNumOperandTraits<2> {
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr, Value)
} // End llvm namespace
// Utility function for determining if a ConstantExpr is a CastOp or not. This
// can't be inline because we don't want to #include Instruction.h into
@ -815,17 +873,29 @@ bool ConstantFP::isValueValidForType(const Type *Ty, const APFloat& Val) {
//===----------------------------------------------------------------------===//
// Factory Function Implementation
// The number of operands for each ConstantCreator::create method is
// determined by the ConstantTraits template.
// ConstantCreator - A class that is used to create constants by
// ValueMap*. This class should be partially specialized if there is
// something strange that needs to be done to interface to the ctor for the
// constant.
//
namespace llvm {
template<class ValType>
struct ConstantTraits;
template<typename T, typename Alloc>
struct VISIBILITY_HIDDEN ConstantTraits< std::vector<T, Alloc> > {
static unsigned uses(const std::vector<T, Alloc>& v) {
return v.size();
}
};
template<class ConstantClass, class TypeClass, class ValType>
struct VISIBILITY_HIDDEN ConstantCreator {
static ConstantClass *create(const TypeClass *Ty, const ValType &V) {
unsigned FIXME = 0; // = traits<ValType>::uses(V)
return new(FIXME) ConstantClass(Ty, V);
return new(ConstantTraits<ValType>::uses(V)) ConstantClass(Ty, V);
}
};

View File

@ -89,14 +89,13 @@ GlobalVariable::GlobalVariable(const Type *Ty, bool constant, LinkageTypes Link,
Module *ParentModule, bool ThreadLocal,
unsigned AddressSpace)
: GlobalValue(PointerType::get(Ty, AddressSpace), Value::GlobalVariableVal,
&Initializer, InitVal != 0, Link, Name),
OperandTraits<GlobalVariable>::op_begin(this),
InitVal != 0, Link, Name),
isConstantGlobal(constant), isThreadLocalSymbol(ThreadLocal) {
if (InitVal) {
assert(InitVal->getType() == Ty &&
"Initializer should be the same type as the GlobalVariable!");
Initializer.init(InitVal, this);
} else {
Initializer.init(0, this);
Op<0>().init(InitVal, this);
}
LeakDetector::addGarbageObject(this);
@ -110,14 +109,13 @@ GlobalVariable::GlobalVariable(const Type *Ty, bool constant, LinkageTypes Link,
GlobalVariable *Before, bool ThreadLocal,
unsigned AddressSpace)
: GlobalValue(PointerType::get(Ty, AddressSpace), Value::GlobalVariableVal,
&Initializer, InitVal != 0, Link, Name),
OperandTraits<GlobalVariable>::op_begin(this),
InitVal != 0, Link, Name),
isConstantGlobal(constant), isThreadLocalSymbol(ThreadLocal) {
if (InitVal) {
assert(InitVal->getType() == Ty &&
"Initializer should be the same type as the GlobalVariable!");
Initializer.init(InitVal, this);
} else {
Initializer.init(0, this);
Op<0>().init(InitVal, this);
}
LeakDetector::addGarbageObject(this);
@ -169,12 +167,12 @@ void GlobalVariable::replaceUsesOfWithOnConstant(Value *From, Value *To,
GlobalAlias::GlobalAlias(const Type *Ty, LinkageTypes Link,
const std::string &Name, Constant* aliasee,
Module *ParentModule)
: GlobalValue(Ty, Value::GlobalAliasVal, &Aliasee, 1, Link, Name) {
: GlobalValue(Ty, Value::GlobalAliasVal, &Op<0>(), 1, Link, Name) {
LeakDetector::addGarbageObject(this);
if (aliasee)
assert(aliasee->getType() == Ty && "Alias and aliasee types should match!");
Aliasee.init(aliasee, this);
Op<0>().init(aliasee, this);
if (ParentModule)
ParentModule->getAliasList().push_back(this);

View File

@ -100,18 +100,21 @@ void CallSite::setDoesNotThrow(bool doesNotThrow) {
TerminatorInst::~TerminatorInst() {
}
//===----------------------------------------------------------------------===//
// UnaryInstruction Class
//===----------------------------------------------------------------------===//
// Out of line virtual method, so the vtable, etc has a home.
UnaryInstruction::~UnaryInstruction() {
}
//===----------------------------------------------------------------------===//
// PHINode Class
//===----------------------------------------------------------------------===//
PHINode::PHINode(const PHINode &PN)
: Instruction(PN.getType(), Instruction::PHI,
new Use[PN.getNumOperands()], PN.getNumOperands()),
allocHungoffUses(PN.getNumOperands()), PN.getNumOperands()),
ReservedSpace(PN.getNumOperands()) {
Use *OL = OperandList;
for (unsigned i = 0, e = PN.getNumOperands(); i != e; i+=2) {
@ -121,7 +124,7 @@ PHINode::PHINode(const PHINode &PN)
}
PHINode::~PHINode() {
delete [] OperandList;
dropHungoffUses(OperandList);
}
// removeIncomingValue - Remove an incoming value. This is useful if a
@ -164,8 +167,9 @@ Value *PHINode::removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty) {
/// 3. If NumOps == NumOperands, trim the reserved space.
///
void PHINode::resizeOperands(unsigned NumOps) {
unsigned e = getNumOperands();
if (NumOps == 0) {
NumOps = (getNumOperands())*3/2;
NumOps = e*3/2;
if (NumOps < 4) NumOps = 4; // 4 op PHI nodes are VERY common.
} else if (NumOps*2 > NumOperands) {
// No resize needed.
@ -177,14 +181,13 @@ void PHINode::resizeOperands(unsigned NumOps) {
}
ReservedSpace = NumOps;
Use *NewOps = new Use[NumOps];
Use *OldOps = OperandList;
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
Use *NewOps = allocHungoffUses(NumOps);
for (unsigned i = 0; i != e; ++i) {
NewOps[i].init(OldOps[i], this);
OldOps[i].set(0);
}
delete [] OldOps;
OperandList = NewOps;
if (OldOps) Use::zap(OldOps, OldOps + e, true);
}
/// hasConstantValue - If the specified PHI node always merges together the same
@ -241,12 +244,11 @@ Value *PHINode::hasConstantValue(bool AllowNonDominatingInstruction) const {
//===----------------------------------------------------------------------===//
CallInst::~CallInst() {
delete [] OperandList;
}
void CallInst::init(Value *Func, Value* const *Params, unsigned NumParams) {
NumOperands = NumParams+1;
Use *OL = OperandList = new Use[NumParams+1];
assert(NumOperands == NumParams+1 && "NumOperands not set up?");
Use *OL = OperandList;
OL[0].init(Func, this);
const FunctionType *FTy =
@ -265,8 +267,8 @@ void CallInst::init(Value *Func, Value* const *Params, unsigned NumParams) {
}
void CallInst::init(Value *Func, Value *Actual1, Value *Actual2) {
NumOperands = 3;
Use *OL = OperandList = new Use[3];
assert(NumOperands == 3 && "NumOperands not set up?");
Use *OL = OperandList;
OL[0].init(Func, this);
OL[1].init(Actual1, this);
OL[2].init(Actual2, this);
@ -287,8 +289,8 @@ void CallInst::init(Value *Func, Value *Actual1, Value *Actual2) {
}
void CallInst::init(Value *Func, Value *Actual) {
NumOperands = 2;
Use *OL = OperandList = new Use[2];
assert(NumOperands == 2 && "NumOperands not set up?");
Use *OL = OperandList;
OL[0].init(Func, this);
OL[1].init(Actual, this);
@ -305,8 +307,8 @@ void CallInst::init(Value *Func, Value *Actual) {
}
void CallInst::init(Value *Func) {
NumOperands = 1;
Use *OL = OperandList = new Use[1];
assert(NumOperands == 1 && "NumOperands not set up?");
Use *OL = OperandList;
OL[0].init(Func, this);
const FunctionType *FTy =
@ -320,7 +322,9 @@ CallInst::CallInst(Value *Func, Value* Actual, const std::string &Name,
Instruction *InsertBefore)
: Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
->getElementType())->getReturnType(),
Instruction::Call, 0, 0, InsertBefore) {
Instruction::Call,
OperandTraits<CallInst>::op_end(this) - 2,
2, InsertBefore) {
init(Func, Actual);
setName(Name);
}
@ -329,7 +333,9 @@ CallInst::CallInst(Value *Func, Value* Actual, const std::string &Name,
BasicBlock *InsertAtEnd)
: Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
->getElementType())->getReturnType(),
Instruction::Call, 0, 0, InsertAtEnd) {
Instruction::Call,
OperandTraits<CallInst>::op_end(this) - 2,
2, InsertAtEnd) {
init(Func, Actual);
setName(Name);
}
@ -337,7 +343,9 @@ CallInst::CallInst(Value *Func, const std::string &Name,
Instruction *InsertBefore)
: Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
->getElementType())->getReturnType(),
Instruction::Call, 0, 0, InsertBefore) {
Instruction::Call,
OperandTraits<CallInst>::op_end(this) - 1,
1, InsertBefore) {
init(Func);
setName(Name);
}
@ -346,13 +354,16 @@ CallInst::CallInst(Value *Func, const std::string &Name,
BasicBlock *InsertAtEnd)
: Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
->getElementType())->getReturnType(),
Instruction::Call, 0, 0, InsertAtEnd) {
Instruction::Call,
OperandTraits<CallInst>::op_end(this) - 1,
1, InsertAtEnd) {
init(Func);
setName(Name);
}
CallInst::CallInst(const CallInst &CI)
: Instruction(CI.getType(), Instruction::Call, new Use[CI.getNumOperands()],
: Instruction(CI.getType(), Instruction::Call,
OperandTraits<CallInst>::op_end(this) - CI.getNumOperands(),
CI.getNumOperands()) {
setParamAttrs(CI.getParamAttrs());
SubclassData = CI.SubclassData;
@ -384,14 +395,10 @@ void CallInst::setDoesNotThrow(bool doesNotThrow) {
// InvokeInst Implementation
//===----------------------------------------------------------------------===//
InvokeInst::~InvokeInst() {
delete [] OperandList;
}
void InvokeInst::init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException,
Value* const *Args, unsigned NumArgs) {
NumOperands = 3+NumArgs;
Use *OL = OperandList = new Use[3+NumArgs];
assert(NumOperands == 3+NumArgs && "NumOperands not set up?");
Use *OL = OperandList;
OL[0].init(Fn, this);
OL[1].init(IfNormal, this);
OL[2].init(IfException, this);
@ -414,7 +421,8 @@ void InvokeInst::init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException,
InvokeInst::InvokeInst(const InvokeInst &II)
: TerminatorInst(II.getType(), Instruction::Invoke,
new Use[II.getNumOperands()], II.getNumOperands()) {
OperandTraits<InvokeInst>::op_end(this) - II.getNumOperands(),
II.getNumOperands()) {
setParamAttrs(II.getParamAttrs());
SubclassData = II.SubclassData;
Use *OL = OperandList, *InOL = II.OperandList;
@ -456,45 +464,51 @@ void InvokeInst::setDoesNotThrow(bool doesNotThrow) {
ReturnInst::ReturnInst(const ReturnInst &RI)
: TerminatorInst(Type::VoidTy, Instruction::Ret,
&RetVal, RI.getNumOperands()) {
OperandTraits<ReturnInst>::op_end(this) - RI.getNumOperands(),
RI.getNumOperands()) {
unsigned N = RI.getNumOperands();
if (N == 1)
RetVal.init(RI.RetVal, this);
if (N == 1)
Op<0>().init(RI.Op<0>(), this);
else if (N) {
Use *OL = OperandList = new Use[N];
Use *OL = OperandList;
for (unsigned i = 0; i < N; ++i)
OL[i].init(RI.getOperand(i), this);
}
}
ReturnInst::ReturnInst(Value *retVal, Instruction *InsertBefore)
: TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, 0, InsertBefore) {
: TerminatorInst(Type::VoidTy, Instruction::Ret,
OperandTraits<ReturnInst>::op_end(this) - (retVal != 0),
retVal != 0, InsertBefore) {
if (retVal)
init(&retVal, 1);
}
ReturnInst::ReturnInst(Value *retVal, BasicBlock *InsertAtEnd)
: TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, 0, InsertAtEnd) {
: TerminatorInst(Type::VoidTy, Instruction::Ret,
OperandTraits<ReturnInst>::op_end(this) - (retVal != 0),
retVal != 0, InsertAtEnd) {
if (retVal)
init(&retVal, 1);
}
ReturnInst::ReturnInst(BasicBlock *InsertAtEnd)
: TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, 0, InsertAtEnd) {
: TerminatorInst(Type::VoidTy, Instruction::Ret,
OperandTraits<ReturnInst>::op_end(this),
0, InsertAtEnd) {
}
ReturnInst::ReturnInst(Value * const* retVals, unsigned N,
Instruction *InsertBefore)
: TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, N, InsertBefore) {
: TerminatorInst(Type::VoidTy, Instruction::Ret,
OperandTraits<ReturnInst>::op_end(this) - N,
N, InsertBefore) {
if (N != 0)
init(retVals, N);
}
ReturnInst::ReturnInst(Value * const* retVals, unsigned N,
BasicBlock *InsertAtEnd)
: TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, N, InsertAtEnd) {
if (N != 0)
init(retVals, N);
}
ReturnInst::ReturnInst(Value * const* retVals, unsigned N)
: TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, N) {
: TerminatorInst(Type::VoidTy, Instruction::Ret,
OperandTraits<ReturnInst>::op_end(this) - N,
N, InsertAtEnd) {
if (N != 0)
init(retVals, N);
}
@ -507,11 +521,11 @@ void ReturnInst::init(Value * const* retVals, unsigned N) {
Value *V = *retVals;
if (V->getType() == Type::VoidTy)
return;
RetVal.init(V, this);
Op<0>().init(V, this);
return;
}
Use *OL = OperandList = new Use[NumOperands];
Use *OL = OperandList;
for (unsigned i = 0; i < NumOperands; ++i) {
Value *V = *retVals++;
assert(!isa<BasicBlock>(V) &&
@ -537,8 +551,6 @@ BasicBlock *ReturnInst::getSuccessorV(unsigned idx) const {
}
ReturnInst::~ReturnInst() {
if (NumOperands > 1)
delete [] OperandList;
}
//===----------------------------------------------------------------------===//
@ -603,33 +615,41 @@ void BranchInst::AssertOK() {
}
BranchInst::BranchInst(BasicBlock *IfTrue, Instruction *InsertBefore)
: TerminatorInst(Type::VoidTy, Instruction::Br, Ops, 1, InsertBefore) {
: TerminatorInst(Type::VoidTy, Instruction::Br,
OperandTraits<BranchInst>::op_end(this) - 1,
1, InsertBefore) {
assert(IfTrue != 0 && "Branch destination may not be null!");
Ops[0].init(reinterpret_cast<Value*>(IfTrue), this);
Op<0>().init(reinterpret_cast<Value*>(IfTrue), this);
}
BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond,
Instruction *InsertBefore)
: TerminatorInst(Type::VoidTy, Instruction::Br, Ops, 3, InsertBefore) {
Ops[0].init(reinterpret_cast<Value*>(IfTrue), this);
Ops[1].init(reinterpret_cast<Value*>(IfFalse), this);
Ops[2].init(Cond, this);
: TerminatorInst(Type::VoidTy, Instruction::Br,
OperandTraits<BranchInst>::op_end(this) - 3,
3, InsertBefore) {
Op<0>().init(reinterpret_cast<Value*>(IfTrue), this);
Op<1>().init(reinterpret_cast<Value*>(IfFalse), this);
Op<2>().init(Cond, this);
#ifndef NDEBUG
AssertOK();
#endif
}
BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *InsertAtEnd)
: TerminatorInst(Type::VoidTy, Instruction::Br, Ops, 1, InsertAtEnd) {
: TerminatorInst(Type::VoidTy, Instruction::Br,
OperandTraits<BranchInst>::op_end(this) - 1,
1, InsertAtEnd) {
assert(IfTrue != 0 && "Branch destination may not be null!");
Ops[0].init(reinterpret_cast<Value*>(IfTrue), this);
Op<0>().init(reinterpret_cast<Value*>(IfTrue), this);
}
BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond,
BasicBlock *InsertAtEnd)
: TerminatorInst(Type::VoidTy, Instruction::Br, Ops, 3, InsertAtEnd) {
Ops[0].init(reinterpret_cast<Value*>(IfTrue), this);
Ops[1].init(reinterpret_cast<Value*>(IfFalse), this);
Ops[2].init(Cond, this);
: TerminatorInst(Type::VoidTy, Instruction::Br,
OperandTraits<BranchInst>::op_end(this) - 3,
3, InsertAtEnd) {
Op<0>().init(reinterpret_cast<Value*>(IfTrue), this);
Op<1>().init(reinterpret_cast<Value*>(IfFalse), this);
Op<2>().init(Cond, this);
#ifndef NDEBUG
AssertOK();
#endif
@ -637,7 +657,9 @@ BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond,
BranchInst::BranchInst(const BranchInst &BI) :
TerminatorInst(Type::VoidTy, Instruction::Br, Ops, BI.getNumOperands()) {
TerminatorInst(Type::VoidTy, Instruction::Br,
OperandTraits<BranchInst>::op_end(this) - BI.getNumOperands(),
BI.getNumOperands()) {
OperandList[0].init(BI.getOperand(0), this);
if (BI.getNumOperands() != 1) {
assert(BI.getNumOperands() == 3 && "BR can have 1 or 3 operands!");
@ -869,18 +891,24 @@ void StoreInst::AssertOK() {
StoreInst::StoreInst(Value *val, Value *addr, Instruction *InsertBefore)
: Instruction(Type::VoidTy, Store, Ops, 2, InsertBefore) {
Ops[0].init(val, this);
Ops[1].init(addr, this);
: Instruction(Type::VoidTy, Store,
OperandTraits<StoreInst>::op_begin(this),
OperandTraits<StoreInst>::operands(this),
InsertBefore) {
Op<0>().init(val, this);
Op<1>().init(addr, this);
setVolatile(false);
setAlignment(0);
AssertOK();
}
StoreInst::StoreInst(Value *val, Value *addr, BasicBlock *InsertAtEnd)
: Instruction(Type::VoidTy, Store, Ops, 2, InsertAtEnd) {
Ops[0].init(val, this);
Ops[1].init(addr, this);
: Instruction(Type::VoidTy, Store,
OperandTraits<StoreInst>::op_begin(this),
OperandTraits<StoreInst>::operands(this),
InsertAtEnd) {
Op<0>().init(val, this);
Op<1>().init(addr, this);
setVolatile(false);
setAlignment(0);
AssertOK();
@ -888,9 +916,12 @@ StoreInst::StoreInst(Value *val, Value *addr, BasicBlock *InsertAtEnd)
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
Instruction *InsertBefore)
: Instruction(Type::VoidTy, Store, Ops, 2, InsertBefore) {
Ops[0].init(val, this);
Ops[1].init(addr, this);
: Instruction(Type::VoidTy, Store,
OperandTraits<StoreInst>::op_begin(this),
OperandTraits<StoreInst>::operands(this),
InsertBefore) {
Op<0>().init(val, this);
Op<1>().init(addr, this);
setVolatile(isVolatile);
setAlignment(0);
AssertOK();
@ -898,9 +929,12 @@ StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
unsigned Align, Instruction *InsertBefore)
: Instruction(Type::VoidTy, Store, Ops, 2, InsertBefore) {
Ops[0].init(val, this);
Ops[1].init(addr, this);
: Instruction(Type::VoidTy, Store,
OperandTraits<StoreInst>::op_begin(this),
OperandTraits<StoreInst>::operands(this),
InsertBefore) {
Op<0>().init(val, this);
Op<1>().init(addr, this);
setVolatile(isVolatile);
setAlignment(Align);
AssertOK();
@ -908,9 +942,12 @@ StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
unsigned Align, BasicBlock *InsertAtEnd)
: Instruction(Type::VoidTy, Store, Ops, 2, InsertAtEnd) {
Ops[0].init(val, this);
Ops[1].init(addr, this);
: Instruction(Type::VoidTy, Store,
OperandTraits<StoreInst>::op_begin(this),
OperandTraits<StoreInst>::operands(this),
InsertAtEnd) {
Op<0>().init(val, this);
Op<1>().init(addr, this);
setVolatile(isVolatile);
setAlignment(Align);
AssertOK();
@ -918,9 +955,12 @@ StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
BasicBlock *InsertAtEnd)
: Instruction(Type::VoidTy, Store, Ops, 2, InsertAtEnd) {
Ops[0].init(val, this);
Ops[1].init(addr, this);
: Instruction(Type::VoidTy, Store,
OperandTraits<StoreInst>::op_begin(this),
OperandTraits<StoreInst>::operands(this),
InsertAtEnd) {
Op<0>().init(val, this);
Op<1>().init(addr, this);
setVolatile(isVolatile);
setAlignment(0);
AssertOK();
@ -940,8 +980,8 @@ static unsigned retrieveAddrSpace(const Value *Val) {
}
void GetElementPtrInst::init(Value *Ptr, Value* const *Idx, unsigned NumIdx) {
NumOperands = 1+NumIdx;
Use *OL = OperandList = new Use[NumOperands];
assert(NumOperands == 1+NumIdx && "NumOperands not initialized?");
Use *OL = OperandList;
OL[0].init(Ptr, this);
for (unsigned i = 0; i != NumIdx; ++i)
@ -949,17 +989,29 @@ void GetElementPtrInst::init(Value *Ptr, Value* const *Idx, unsigned NumIdx) {
}
void GetElementPtrInst::init(Value *Ptr, Value *Idx) {
NumOperands = 2;
Use *OL = OperandList = new Use[2];
assert(NumOperands == 2 && "NumOperands not initialized?");
Use *OL = OperandList;
OL[0].init(Ptr, this);
OL[1].init(Idx, this);
}
GetElementPtrInst::GetElementPtrInst(const GetElementPtrInst &GEPI)
: Instruction(reinterpret_cast<const Type*>(GEPI.getType()), GetElementPtr,
OperandTraits<GetElementPtrInst>::op_end(this) - GEPI.getNumOperands(),
GEPI.getNumOperands()) {
Use *OL = OperandList;
Use *GEPIOL = GEPI.OperandList;
for (unsigned i = 0, E = NumOperands; i != E; ++i)
OL[i].init(GEPIOL[i], this);
}
GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
const std::string &Name, Instruction *InBe)
: Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),Idx)),
retrieveAddrSpace(Ptr)),
GetElementPtr, 0, 0, InBe) {
GetElementPtr,
OperandTraits<GetElementPtrInst>::op_end(this) - 2,
2, InBe) {
init(Ptr, Idx);
setName(Name);
}
@ -968,15 +1020,13 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
const std::string &Name, BasicBlock *IAE)
: Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),Idx)),
retrieveAddrSpace(Ptr)),
GetElementPtr, 0, 0, IAE) {
GetElementPtr,
OperandTraits<GetElementPtrInst>::op_end(this) - 2,
2, IAE) {
init(Ptr, Idx);
setName(Name);
}
GetElementPtrInst::~GetElementPtrInst() {
delete[] OperandList;
}
// getIndexedType - Returns the type of the element that would be loaded with
// a load instruction with the specified parameters.
//
@ -1067,11 +1117,13 @@ ExtractElementInst::ExtractElementInst(Value *Val, Value *Index,
const std::string &Name,
Instruction *InsertBef)
: Instruction(cast<VectorType>(Val->getType())->getElementType(),
ExtractElement, Ops, 2, InsertBef) {
ExtractElement,
OperandTraits<ExtractElementInst>::op_begin(this),
2, InsertBef) {
assert(isValidOperands(Val, Index) &&
"Invalid extractelement instruction operands!");
Ops[0].init(Val, this);
Ops[1].init(Index, this);
Op<0>().init(Val, this);
Op<1>().init(Index, this);
setName(Name);
}
@ -1079,12 +1131,14 @@ ExtractElementInst::ExtractElementInst(Value *Val, unsigned IndexV,
const std::string &Name,
Instruction *InsertBef)
: Instruction(cast<VectorType>(Val->getType())->getElementType(),
ExtractElement, Ops, 2, InsertBef) {
ExtractElement,
OperandTraits<ExtractElementInst>::op_begin(this),
2, InsertBef) {
Constant *Index = ConstantInt::get(Type::Int32Ty, IndexV);
assert(isValidOperands(Val, Index) &&
"Invalid extractelement instruction operands!");
Ops[0].init(Val, this);
Ops[1].init(Index, this);
Op<0>().init(Val, this);
Op<1>().init(Index, this);
setName(Name);
}
@ -1093,12 +1147,14 @@ ExtractElementInst::ExtractElementInst(Value *Val, Value *Index,
const std::string &Name,
BasicBlock *InsertAE)
: Instruction(cast<VectorType>(Val->getType())->getElementType(),
ExtractElement, Ops, 2, InsertAE) {
ExtractElement,
OperandTraits<ExtractElementInst>::op_begin(this),
2, InsertAE) {
assert(isValidOperands(Val, Index) &&
"Invalid extractelement instruction operands!");
Ops[0].init(Val, this);
Ops[1].init(Index, this);
Op<0>().init(Val, this);
Op<1>().init(Index, this);
setName(Name);
}
@ -1106,13 +1162,15 @@ ExtractElementInst::ExtractElementInst(Value *Val, unsigned IndexV,
const std::string &Name,
BasicBlock *InsertAE)
: Instruction(cast<VectorType>(Val->getType())->getElementType(),
ExtractElement, Ops, 2, InsertAE) {
ExtractElement,
OperandTraits<ExtractElementInst>::op_begin(this),
2, InsertAE) {
Constant *Index = ConstantInt::get(Type::Int32Ty, IndexV);
assert(isValidOperands(Val, Index) &&
"Invalid extractelement instruction operands!");
Ops[0].init(Val, this);
Ops[1].init(Index, this);
Op<0>().init(Val, this);
Op<1>().init(Index, this);
setName(Name);
}
@ -1129,33 +1187,38 @@ bool ExtractElementInst::isValidOperands(const Value *Val, const Value *Index) {
//===----------------------------------------------------------------------===//
InsertElementInst::InsertElementInst(const InsertElementInst &IE)
: Instruction(IE.getType(), InsertElement, Ops, 3) {
Ops[0].init(IE.Ops[0], this);
Ops[1].init(IE.Ops[1], this);
Ops[2].init(IE.Ops[2], this);
: Instruction(IE.getType(), InsertElement,
OperandTraits<InsertElementInst>::op_begin(this), 3) {
Op<0>().init(IE.Op<0>(), this);
Op<1>().init(IE.Op<1>(), this);
Op<2>().init(IE.Op<2>(), this);
}
InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, Value *Index,
const std::string &Name,
Instruction *InsertBef)
: Instruction(Vec->getType(), InsertElement, Ops, 3, InsertBef) {
: Instruction(Vec->getType(), InsertElement,
OperandTraits<InsertElementInst>::op_begin(this),
3, InsertBef) {
assert(isValidOperands(Vec, Elt, Index) &&
"Invalid insertelement instruction operands!");
Ops[0].init(Vec, this);
Ops[1].init(Elt, this);
Ops[2].init(Index, this);
Op<0>().init(Vec, this);
Op<1>().init(Elt, this);
Op<2>().init(Index, this);
setName(Name);
}
InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, unsigned IndexV,
const std::string &Name,
Instruction *InsertBef)
: Instruction(Vec->getType(), InsertElement, Ops, 3, InsertBef) {
: Instruction(Vec->getType(), InsertElement,
OperandTraits<InsertElementInst>::op_begin(this),
3, InsertBef) {
Constant *Index = ConstantInt::get(Type::Int32Ty, IndexV);
assert(isValidOperands(Vec, Elt, Index) &&
"Invalid insertelement instruction operands!");
Ops[0].init(Vec, this);
Ops[1].init(Elt, this);
Ops[2].init(Index, this);
Op<0>().init(Vec, this);
Op<1>().init(Elt, this);
Op<2>().init(Index, this);
setName(Name);
}
@ -1163,27 +1226,31 @@ InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, unsigned IndexV,
InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, Value *Index,
const std::string &Name,
BasicBlock *InsertAE)
: Instruction(Vec->getType(), InsertElement, Ops, 3, InsertAE) {
: Instruction(Vec->getType(), InsertElement,
OperandTraits<InsertElementInst>::op_begin(this),
3, InsertAE) {
assert(isValidOperands(Vec, Elt, Index) &&
"Invalid insertelement instruction operands!");
Ops[0].init(Vec, this);
Ops[1].init(Elt, this);
Ops[2].init(Index, this);
Op<0>().init(Vec, this);
Op<1>().init(Elt, this);
Op<2>().init(Index, this);
setName(Name);
}
InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, unsigned IndexV,
const std::string &Name,
BasicBlock *InsertAE)
: Instruction(Vec->getType(), InsertElement, Ops, 3, InsertAE) {
: Instruction(Vec->getType(), InsertElement,
OperandTraits<InsertElementInst>::op_begin(this),
3, InsertAE) {
Constant *Index = ConstantInt::get(Type::Int32Ty, IndexV);
assert(isValidOperands(Vec, Elt, Index) &&
"Invalid insertelement instruction operands!");
Ops[0].init(Vec, this);
Ops[1].init(Elt, this);
Ops[2].init(Index, this);
Op<0>().init(Vec, this);
Op<1>().init(Elt, this);
Op<2>().init(Index, this);
setName(Name);
}
@ -1206,34 +1273,42 @@ bool InsertElementInst::isValidOperands(const Value *Vec, const Value *Elt,
//===----------------------------------------------------------------------===//
ShuffleVectorInst::ShuffleVectorInst(const ShuffleVectorInst &SV)
: Instruction(SV.getType(), ShuffleVector, Ops, 3) {
Ops[0].init(SV.Ops[0], this);
Ops[1].init(SV.Ops[1], this);
Ops[2].init(SV.Ops[2], this);
: Instruction(SV.getType(), ShuffleVector,
OperandTraits<ShuffleVectorInst>::op_begin(this),
OperandTraits<ShuffleVectorInst>::operands(this)) {
Op<0>().init(SV.Op<0>(), this);
Op<1>().init(SV.Op<1>(), this);
Op<2>().init(SV.Op<2>(), this);
}
ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask,
const std::string &Name,
Instruction *InsertBefore)
: Instruction(V1->getType(), ShuffleVector, Ops, 3, InsertBefore) {
: Instruction(V1->getType(), ShuffleVector,
OperandTraits<ShuffleVectorInst>::op_begin(this),
OperandTraits<ShuffleVectorInst>::operands(this),
InsertBefore) {
assert(isValidOperands(V1, V2, Mask) &&
"Invalid shuffle vector instruction operands!");
Ops[0].init(V1, this);
Ops[1].init(V2, this);
Ops[2].init(Mask, this);
Op<0>().init(V1, this);
Op<1>().init(V2, this);
Op<2>().init(Mask, this);
setName(Name);
}
ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask,
const std::string &Name,
BasicBlock *InsertAtEnd)
: Instruction(V1->getType(), ShuffleVector, Ops, 3, InsertAtEnd) {
: Instruction(V1->getType(), ShuffleVector,
OperandTraits<ShuffleVectorInst>::op_begin(this),
OperandTraits<ShuffleVectorInst>::operands(this),
InsertAtEnd) {
assert(isValidOperands(V1, V2, Mask) &&
"Invalid shuffle vector instruction operands!");
Ops[0].init(V1, this);
Ops[1].init(V2, this);
Ops[2].init(Mask, this);
Op<0>().init(V1, this);
Op<1>().init(V2, this);
Op<2>().init(Mask, this);
setName(Name);
}
@ -1275,9 +1350,12 @@ int ShuffleVectorInst::getMaskValue(unsigned i) const {
BinaryOperator::BinaryOperator(BinaryOps iType, Value *S1, Value *S2,
const Type *Ty, const std::string &Name,
Instruction *InsertBefore)
: Instruction(Ty, iType, Ops, 2, InsertBefore) {
Ops[0].init(S1, this);
Ops[1].init(S2, this);
: Instruction(Ty, iType,
OperandTraits<BinaryOperator>::op_begin(this),
OperandTraits<BinaryOperator>::operands(this),
InsertBefore) {
Op<0>().init(S1, this);
Op<1>().init(S2, this);
init(iType);
setName(Name);
}
@ -1285,9 +1363,12 @@ BinaryOperator::BinaryOperator(BinaryOps iType, Value *S1, Value *S2,
BinaryOperator::BinaryOperator(BinaryOps iType, Value *S1, Value *S2,
const Type *Ty, const std::string &Name,
BasicBlock *InsertAtEnd)
: Instruction(Ty, iType, Ops, 2, InsertAtEnd) {
Ops[0].init(S1, this);
Ops[1].init(S2, this);
: Instruction(Ty, iType,
OperandTraits<BinaryOperator>::op_begin(this),
OperandTraits<BinaryOperator>::operands(this),
InsertAtEnd) {
Op<0>().init(S1, this);
Op<1>().init(S2, this);
init(iType);
setName(Name);
}
@ -1482,7 +1563,7 @@ const Value *BinaryOperator::getNotArgument(const Value *BinOp) {
bool BinaryOperator::swapOperands() {
if (!isCommutative())
return true; // Can't commute operands
std::swap(Ops[0], Ops[1]);
std::swap(Op<0>(), Op<1>());
return false;
}
@ -2254,9 +2335,12 @@ BitCastInst::BitCastInst(
CmpInst::CmpInst(OtherOps op, unsigned short predicate, Value *LHS, Value *RHS,
const std::string &Name, Instruction *InsertBefore)
: Instruction(Type::Int1Ty, op, Ops, 2, InsertBefore) {
Ops[0].init(LHS, this);
Ops[1].init(RHS, this);
: Instruction(Type::Int1Ty, op,
OperandTraits<CmpInst>::op_begin(this),
OperandTraits<CmpInst>::operands(this),
InsertBefore) {
Op<0>().init(LHS, this);
Op<1>().init(RHS, this);
SubclassData = predicate;
setName(Name);
if (op == Instruction::ICmp) {
@ -2283,12 +2367,15 @@ CmpInst::CmpInst(OtherOps op, unsigned short predicate, Value *LHS, Value *RHS,
assert(Op0Ty->isFloatingPoint() &&
"Invalid operand types for FCmp instruction");
}
CmpInst::CmpInst(OtherOps op, unsigned short predicate, Value *LHS, Value *RHS,
const std::string &Name, BasicBlock *InsertAtEnd)
: Instruction(Type::Int1Ty, op, Ops, 2, InsertAtEnd) {
Ops[0].init(LHS, this);
Ops[1].init(RHS, this);
: Instruction(Type::Int1Ty, op,
OperandTraits<CmpInst>::op_begin(this),
OperandTraits<CmpInst>::operands(this),
InsertAtEnd) {
Op<0>().init(LHS, this);
Op<1>().init(RHS, this);
SubclassData = predicate;
setName(Name);
if (op == Instruction::ICmp) {
@ -2548,7 +2635,7 @@ void SwitchInst::init(Value *Value, BasicBlock *Default, unsigned NumCases) {
assert(Value && Default);
ReservedSpace = 2+NumCases*2;
NumOperands = 2;
OperandList = new Use[ReservedSpace];
OperandList = allocHungoffUses(ReservedSpace);
OperandList[0].init(Value, this);
OperandList[1].init(Default, this);
@ -2576,7 +2663,7 @@ SwitchInst::SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases,
SwitchInst::SwitchInst(const SwitchInst &SI)
: TerminatorInst(Type::VoidTy, Instruction::Switch,
new Use[SI.getNumOperands()], SI.getNumOperands()) {
allocHungoffUses(SI.getNumOperands()), SI.getNumOperands()) {
Use *OL = OperandList, *InOL = SI.OperandList;
for (unsigned i = 0, E = SI.getNumOperands(); i != E; i+=2) {
OL[i].init(InOL[i], this);
@ -2585,7 +2672,7 @@ SwitchInst::SwitchInst(const SwitchInst &SI)
}
SwitchInst::~SwitchInst() {
delete [] OperandList;
dropHungoffUses(OperandList);
}
@ -2632,13 +2719,14 @@ void SwitchInst::removeCase(unsigned idx) {
/// resizeOperands - resize operands - This adjusts the length of the operands
/// list according to the following behavior:
/// 1. If NumOps == 0, grow the operand list in response to a push_back style
/// of operation. This grows the number of ops by 1.5 times.
/// of operation. This grows the number of ops by 3 times.
/// 2. If NumOps > NumOperands, reserve space for NumOps operands.
/// 3. If NumOps == NumOperands, trim the reserved space.
///
void SwitchInst::resizeOperands(unsigned NumOps) {
unsigned e = getNumOperands();
if (NumOps == 0) {
NumOps = getNumOperands()/2*6;
NumOps = e*3;
} else if (NumOps*2 > NumOperands) {
// No resize needed.
if (ReservedSpace >= NumOps) return;
@ -2649,14 +2737,13 @@ void SwitchInst::resizeOperands(unsigned NumOps) {
}
ReservedSpace = NumOps;
Use *NewOps = new Use[NumOps];
Use *NewOps = allocHungoffUses(NumOps);
Use *OldOps = OperandList;
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
for (unsigned i = 0; i != e; ++i) {
NewOps[i].init(OldOps[i], this);
OldOps[i].set(0);
}
delete [] OldOps;
OperandList = NewOps;
if (OldOps) Use::zap(OldOps, OldOps + e, true);
}
@ -2678,9 +2765,12 @@ GetResultInst::GetResultInst(Value *Aggregate, unsigned Index,
const std::string &Name,
Instruction *InsertBef)
: Instruction(cast<StructType>(Aggregate->getType())->getElementType(Index),
GetResult, &Aggr, 1, InsertBef) {
GetResult,
OperandTraits<GetResultInst>::op_begin(this),
OperandTraits<GetResultInst>::operands(this),
InsertBef) {
assert(isValidOperands(Aggregate, Index) && "Invalid GetResultInst operands!");
Aggr.init(Aggregate, this);
Op<0>().init(Aggregate, this);
Idx = Index;
setName(Name);
}
@ -2714,14 +2804,14 @@ GetElementPtrInst *GetElementPtrInst::clone() const {
}
BinaryOperator *BinaryOperator::clone() const {
return create(getOpcode(), Ops[0], Ops[1]);
return create(getOpcode(), Op<0>(), Op<1>());
}
FCmpInst* FCmpInst::clone() const {
return new FCmpInst(getPredicate(), Ops[0], Ops[1]);
return new FCmpInst(getPredicate(), Op<0>(), Op<1>());
}
ICmpInst* ICmpInst::clone() const {
return new ICmpInst(getPredicate(), Ops[0], Ops[1]);
return new ICmpInst(getPredicate(), Op<0>(), Op<1>());
}
MallocInst *MallocInst::clone() const { return new MallocInst(*this); }
@ -2757,7 +2847,7 @@ ShuffleVectorInst *ShuffleVectorInst::clone() const {
PHINode *PHINode::clone() const { return new PHINode(*this); }
ReturnInst *ReturnInst::clone() const { return new(getNumOperands()) ReturnInst(*this); }
BranchInst *BranchInst::clone() const { return new(getNumOperands()) BranchInst(*this); }
SwitchInst *SwitchInst::clone() const { return new(getNumOperands()) SwitchInst(*this); }
SwitchInst *SwitchInst::clone() const { return new SwitchInst(*this); }
InvokeInst *InvokeInst::clone() const { return new(getNumOperands()) InvokeInst(*this); }
UnwindInst *UnwindInst::clone() const { return new UnwindInst(); }
UnreachableInst *UnreachableInst::clone() const { return new UnreachableInst();}

131
lib/VMCore/Use.cpp Normal file
View File

@ -0,0 +1,131 @@
//===-- Use.cpp - Implement the Use class -------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the algorithm for finding the User of a Use.
//
//===----------------------------------------------------------------------===//
#include "llvm/User.h"
namespace llvm {
//===----------------------------------------------------------------------===//
// Use getImpliedUser Implementation
//===----------------------------------------------------------------------===//
const Use *Use::getImpliedUser() const {
const Use *Current = this;
while (true) {
unsigned Tag = extractTag<PrevPtrTag, fullStopTag>((Current++)->Prev);
switch (Tag) {
case zeroDigitTag:
case oneDigitTag:
continue;
case stopTag: {
++Current;
ptrdiff_t Offset = 1;
while (true) {
unsigned Tag = extractTag<PrevPtrTag, fullStopTag>(Current->Prev);
switch (Tag) {
case zeroDigitTag:
case oneDigitTag:
++Current;
Offset = (Offset << 1) + Tag;
continue;
default:
return Current + Offset;
}
}
}
case fullStopTag:
return Current;
}
}
}
//===----------------------------------------------------------------------===//
// Use initTags Implementation
//===----------------------------------------------------------------------===//
Use *Use::initTags(Use * const Start, Use *Stop, ptrdiff_t Done) {
ptrdiff_t Count = Done;
while (Start != Stop) {
--Stop;
Stop->Val = 0;
if (!Count) {
Stop->Prev = reinterpret_cast<Use**>(Done == 0 ? fullStopTag : stopTag);
++Done;
Count = Done;
} else {
Stop->Prev = reinterpret_cast<Use**>(Count & 1);
Count >>= 1;
++Done;
}
}
return Start;
}
//===----------------------------------------------------------------------===//
// Use zap Implementation
//===----------------------------------------------------------------------===//
void Use::zap(Use *Start, const Use *Stop, bool del) {
if (del) {
while (Start != Stop) {
(--Stop)->~Use();
}
::operator delete(Start);
return;
}
while (Start != Stop) {
(Start++)->set(0);
}
}
//===----------------------------------------------------------------------===//
// AugmentedUse layout struct
//===----------------------------------------------------------------------===//
struct AugmentedUse : Use {
User *ref;
AugmentedUse(); // not implemented
};
//===----------------------------------------------------------------------===//
// Use getUser Implementation
//===----------------------------------------------------------------------===//
User *Use::getUser() const {
const Use *End = getImpliedUser();
User *She = static_cast<const AugmentedUse*>(End - 1)->ref;
She = extractTag<Tag, tagOne>(She)
? llvm::stripTag<tagOne>(She)
: reinterpret_cast<User*>(const_cast<Use*>(End));
return She;
}
//===----------------------------------------------------------------------===//
// User allocHungoffUses Implementation
//===----------------------------------------------------------------------===//
Use *User::allocHungoffUses(unsigned N) const {
Use *Begin = static_cast<Use*>(::operator new(sizeof(Use) * N + sizeof(AugmentedUse) - sizeof(Use)));
Use *End = Begin + N;
static_cast<AugmentedUse&>(End[-1]).ref = addTag(this, tagOne);
return Use::initTags(Begin, End);
}
} // End llvm namespace