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: Miscellaneous bug fixes
D: Register allocation refactoring D: Register allocation refactoring
N: Gabor Greif
E: ggreif@gmail.com
D: Improvements for space efficiency
N: Gordon Henriksen N: Gordon Henriksen
E: gordonhenriksen@mac.com E: gordonhenriksen@mac.com
D: Pluggable GC support D: Pluggable GC support

View File

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

View File

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

View File

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

View File

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

View File

@ -20,7 +20,6 @@
namespace llvm { namespace llvm {
struct AssemblyAnnotationWriter; struct AssemblyAnnotationWriter;
class BinaryOperator;
template<typename ValueSubClass, typename ItemParentClass> template<typename ValueSubClass, typename ItemParentClass>
class SymbolTableListTraits; 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; 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 // Use Class
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -35,20 +69,36 @@ class Use {
public: public:
inline void init(Value *V, User *U); inline void init(Value *V, User *U);
Use(Value *V, User *U) { init(V, U); } private:
Use(const Use &U) { init(U.Val, U.U); } /// 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() { 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. /// 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; } operator Value*() const { return Val; }
Value *get() 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); inline void set(Value *Val);
@ -57,7 +107,7 @@ public:
return RHS; return RHS;
} }
const Use &operator=(const Use &RHS) { const Use &operator=(const Use &RHS) {
set(RHS.Val); set(RHS.get());
return *this; return *this;
} }
@ -66,19 +116,22 @@ public:
Use *getNext() const { return Next; } Use *getNext() const { return Next; }
private: private:
Use *Next, **Prev;
Value *Val; Value *Val;
User *U; Use *Next, **Prev;
void setPrev(Use **NewPrev) {
Prev = transferTag<fullStopTag>(Prev, NewPrev);
}
void addToList(Use **List) { void addToList(Use **List) {
Next = *List; Next = *List;
if (Next) Next->Prev = &Next; if (Next) Next->setPrev(&Next);
Prev = List; setPrev(List);
*List = this; *List = this;
} }
void removeFromList() { void removeFromList() {
*Prev = Next; Use **StrippedPrev = stripTag<fullStopTag>(Prev);
if (Next) Next->Prev = Prev; *StrippedPrev = Next;
if (Next) Next->setPrev(StrippedPrev);
} }
friend class Value; friend class Value;
@ -138,7 +191,7 @@ public:
// Retrieve a reference to the current User // Retrieve a reference to the current User
UserTy *operator*() const { UserTy *operator*() const {
assert(U && "Cannot increment end iterator!"); assert(U && "Cannot dereference end iterator!");
return U->getUser(); return U->getUser();
} }

View File

@ -23,15 +23,203 @@
namespace llvm { 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 { class User : public Value {
User(const User &); // Do not implement User(const User &); // Do not implement
void *operator new(size_t); // Do not implement void *operator new(size_t); // Do not implement
template <unsigned>
friend struct HungoffOperandTraits;
protected: protected:
/// OperandList - This is a pointer to the array of Users for this operand. /// 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 /// For nodes of fixed arity (e.g. a binary operator) this array will live
/// embedded into the derived class. For nodes of variable arity /// prefixed to the derived class. For nodes of resizable variable arity
/// (e.g. ConstantArrays, CallInst, PHINodes, ReturnInst etc), this memory /// (e.g. PHINodes, SwitchInst etc.), this memory will be dynamically
/// will be dynamically allocated and should be destroyed by the classes /// allocated and should be destroyed by the classes'
/// virtual dtor. /// virtual dtor.
Use *OperandList; Use *OperandList;
@ -39,13 +227,43 @@ protected:
/// ///
unsigned NumOperands; unsigned NumOperands;
void *operator new(size_t s, size_t) { void *operator new(size_t s, unsigned Us) {
return ::operator new(s); 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) User(const Type *Ty, unsigned vty, Use *OpList, unsigned NumOps)
: Value(Ty, vty), OperandList(OpList), NumOperands(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: 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 { Value *getOperand(unsigned i) const {
assert(i < NumOperands && "getOperand() out of range!"); assert(i < NumOperands && "getOperand() out of range!");
return OperandList[i]; 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> { template<> struct simplify_type<User::op_iterator> {
typedef Value* SimpleType; typedef Value* SimpleType;

View File

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

View File

@ -23,6 +23,7 @@
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/Support/MathExtras.h" #include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include "llvm/OperandTraits.h"
using namespace llvm; using namespace llvm;
void BitcodeReader::FreeState() { void BitcodeReader::FreeState() {
@ -115,55 +116,81 @@ static int GetDecodedBinaryOpcode(unsigned Val, const Type *Ty) {
} }
} }
namespace llvm {
namespace { namespace {
/// @brief A class for maintaining the slot number definition /// @brief A class for maintaining the slot number definition
/// as a placeholder for the actual definition for forward constants defs. /// as a placeholder for the actual definition for forward constants defs.
class ConstantPlaceHolder : public ConstantExpr { class ConstantPlaceHolder : public ConstantExpr {
ConstantPlaceHolder(); // DO NOT IMPLEMENT ConstantPlaceHolder(); // DO NOT IMPLEMENT
void operator=(const ConstantPlaceHolder &); // DO NOT IMPLEMENT void operator=(const ConstantPlaceHolder &); // DO NOT IMPLEMENT
Use Op;
public: public:
// allocate space for exactly one operand // allocate space for exactly one operand
void *operator new(size_t s) { void *operator new(size_t s) {
return User::operator new(s, 1); return User::operator new(s, 1);
} }
explicit ConstantPlaceHolder(const Type *Ty) explicit ConstantPlaceHolder(const Type *Ty)
: ConstantExpr(Ty, Instruction::UserOp1, &Op, 1), : ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) {
Op(UndefValue::get(Type::Int32Ty), this) { 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, Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx,
const Type *Ty) { const Type *Ty) {
if (Idx >= size()) { if (Idx >= size()) {
// Insert a bunch of null values. // Insert a bunch of null values.
Uses.resize(Idx+1); resize(Idx + 1);
OperandList = &Uses[0];
NumOperands = Idx+1; NumOperands = Idx+1;
} }
if (Value *V = Uses[Idx]) { if (Value *V = OperandList[Idx]) {
assert(Ty == V->getType() && "Type mismatch in constant table!"); assert(Ty == V->getType() && "Type mismatch in constant table!");
return cast<Constant>(V); return cast<Constant>(V);
} }
// Create and return a placeholder, which will later be RAUW'd. // Create and return a placeholder, which will later be RAUW'd.
Constant *C = new ConstantPlaceHolder(Ty); Constant *C = new ConstantPlaceHolder(Ty);
Uses[Idx].init(C, this); OperandList[Idx].init(C, this);
return C; return C;
} }
Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, const Type *Ty) { Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, const Type *Ty) {
if (Idx >= size()) { if (Idx >= size()) {
// Insert a bunch of null values. // Insert a bunch of null values.
Uses.resize(Idx+1); resize(Idx + 1);
OperandList = &Uses[0];
NumOperands = 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!"); assert((Ty == 0 || Ty == V->getType()) && "Type mismatch in value table!");
return V; 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. // Create and return a placeholder, which will later be RAUW'd.
Value *V = new Argument(Ty); Value *V = new Argument(Ty);
Uses[Idx].init(V, this); OperandList[Idx].init(V, this);
return V; return V;
} }

View File

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

View File

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

View File

@ -354,7 +354,9 @@ ConstantFP *ConstantFP::get(const Type *Ty, double V) {
ConstantArray::ConstantArray(const ArrayType *T, ConstantArray::ConstantArray(const ArrayType *T,
const std::vector<Constant*> &V) 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() && assert(V.size() == T->getNumElements() &&
"Invalid initializer vector for constant array"); "Invalid initializer vector for constant array");
Use *OL = OperandList; Use *OL = OperandList;
@ -369,13 +371,12 @@ ConstantArray::ConstantArray(const ArrayType *T,
} }
} }
ConstantArray::~ConstantArray() {
delete [] OperandList;
}
ConstantStruct::ConstantStruct(const StructType *T, ConstantStruct::ConstantStruct(const StructType *T,
const std::vector<Constant*> &V) 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() && assert(V.size() == T->getNumElements() &&
"Invalid initializer vector for constant structure"); "Invalid initializer vector for constant structure");
Use *OL = OperandList; Use *OL = OperandList;
@ -392,14 +393,12 @@ ConstantStruct::ConstantStruct(const StructType *T,
} }
} }
ConstantStruct::~ConstantStruct() {
delete [] OperandList;
}
ConstantVector::ConstantVector(const VectorType *T, ConstantVector::ConstantVector(const VectorType *T,
const std::vector<Constant*> &V) 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; Use *OL = OperandList;
for (std::vector<Constant*>::const_iterator I = V.begin(), E = V.end(); for (std::vector<Constant*>::const_iterator I = V.begin(), E = V.end();
I != E; ++I, ++OL) { 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 // We declare several classes private to this file, so use an anonymous
// namespace // namespace
namespace { namespace {
@ -424,49 +421,54 @@ namespace {
/// behind the scenes to implement unary constant exprs. /// behind the scenes to implement unary constant exprs.
class VISIBILITY_HIDDEN UnaryConstantExpr : public ConstantExpr { class VISIBILITY_HIDDEN UnaryConstantExpr : public ConstantExpr {
void *operator new(size_t, unsigned); // DO NOT IMPLEMENT void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
Use Op;
public: public:
// allocate space for exactly one operand // allocate space for exactly one operand
void *operator new(size_t s) { void *operator new(size_t s) {
return User::operator new(s, 1); return User::operator new(s, 1);
} }
UnaryConstantExpr(unsigned Opcode, Constant *C, const Type *Ty) 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 /// BinaryConstantExpr - This class is private to Constants.cpp, and is used
/// behind the scenes to implement binary constant exprs. /// behind the scenes to implement binary constant exprs.
class VISIBILITY_HIDDEN BinaryConstantExpr : public ConstantExpr { class VISIBILITY_HIDDEN BinaryConstantExpr : public ConstantExpr {
void *operator new(size_t, unsigned); // DO NOT IMPLEMENT void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
Use Ops[2];
public: public:
// allocate space for exactly two operands // allocate space for exactly two operands
void *operator new(size_t s) { void *operator new(size_t s) {
return User::operator new(s, 2); return User::operator new(s, 2);
} }
BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2) BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2)
: ConstantExpr(C1->getType(), Opcode, Ops, 2) { : ConstantExpr(C1->getType(), Opcode, &Op<0>(), 2) {
Ops[0].init(C1, this); Op<0>().init(C1, this);
Ops[1].init(C2, 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 /// SelectConstantExpr - This class is private to Constants.cpp, and is used
/// behind the scenes to implement select constant exprs. /// behind the scenes to implement select constant exprs.
class VISIBILITY_HIDDEN SelectConstantExpr : public ConstantExpr { class VISIBILITY_HIDDEN SelectConstantExpr : public ConstantExpr {
void *operator new(size_t, unsigned); // DO NOT IMPLEMENT void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
Use Ops[3];
public: public:
// allocate space for exactly three operands // allocate space for exactly three operands
void *operator new(size_t s) { void *operator new(size_t s) {
return User::operator new(s, 3); return User::operator new(s, 3);
} }
SelectConstantExpr(Constant *C1, Constant *C2, Constant *C3) SelectConstantExpr(Constant *C1, Constant *C2, Constant *C3)
: ConstantExpr(C2->getType(), Instruction::Select, Ops, 3) { : ConstantExpr(C2->getType(), Instruction::Select, &Op<0>(), 3) {
Ops[0].init(C1, this); Op<0>().init(C1, this);
Ops[1].init(C2, this); Op<1>().init(C2, this);
Ops[2].init(C3, this); Op<2>().init(C3, this);
} }
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
}; };
/// ExtractElementConstantExpr - This class is private to /// ExtractElementConstantExpr - This class is private to
@ -474,7 +476,6 @@ public:
/// extractelement constant exprs. /// extractelement constant exprs.
class VISIBILITY_HIDDEN ExtractElementConstantExpr : public ConstantExpr { class VISIBILITY_HIDDEN ExtractElementConstantExpr : public ConstantExpr {
void *operator new(size_t, unsigned); // DO NOT IMPLEMENT void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
Use Ops[2];
public: public:
// allocate space for exactly two operands // allocate space for exactly two operands
void *operator new(size_t s) { void *operator new(size_t s) {
@ -482,10 +483,12 @@ public:
} }
ExtractElementConstantExpr(Constant *C1, Constant *C2) ExtractElementConstantExpr(Constant *C1, Constant *C2)
: ConstantExpr(cast<VectorType>(C1->getType())->getElementType(), : ConstantExpr(cast<VectorType>(C1->getType())->getElementType(),
Instruction::ExtractElement, Ops, 2) { Instruction::ExtractElement, &Op<0>(), 2) {
Ops[0].init(C1, this); Op<0>().init(C1, this);
Ops[1].init(C2, this); Op<1>().init(C2, this);
} }
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
}; };
/// InsertElementConstantExpr - This class is private to /// InsertElementConstantExpr - This class is private to
@ -493,7 +496,6 @@ public:
/// insertelement constant exprs. /// insertelement constant exprs.
class VISIBILITY_HIDDEN InsertElementConstantExpr : public ConstantExpr { class VISIBILITY_HIDDEN InsertElementConstantExpr : public ConstantExpr {
void *operator new(size_t, unsigned); // DO NOT IMPLEMENT void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
Use Ops[3];
public: public:
// allocate space for exactly three operands // allocate space for exactly three operands
void *operator new(size_t s) { void *operator new(size_t s) {
@ -501,11 +503,13 @@ public:
} }
InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3) InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3)
: ConstantExpr(C1->getType(), Instruction::InsertElement, : ConstantExpr(C1->getType(), Instruction::InsertElement,
Ops, 3) { &Op<0>(), 3) {
Ops[0].init(C1, this); Op<0>().init(C1, this);
Ops[1].init(C2, this); Op<1>().init(C2, this);
Ops[2].init(C3, this); Op<2>().init(C3, this);
} }
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
}; };
/// ShuffleVectorConstantExpr - This class is private to /// ShuffleVectorConstantExpr - This class is private to
@ -513,7 +517,6 @@ public:
/// shufflevector constant exprs. /// shufflevector constant exprs.
class VISIBILITY_HIDDEN ShuffleVectorConstantExpr : public ConstantExpr { class VISIBILITY_HIDDEN ShuffleVectorConstantExpr : public ConstantExpr {
void *operator new(size_t, unsigned); // DO NOT IMPLEMENT void *operator new(size_t, unsigned); // DO NOT IMPLEMENT
Use Ops[3];
public: public:
// allocate space for exactly three operands // allocate space for exactly three operands
void *operator new(size_t s) { void *operator new(size_t s) {
@ -521,32 +524,27 @@ public:
} }
ShuffleVectorConstantExpr(Constant *C1, Constant *C2, Constant *C3) ShuffleVectorConstantExpr(Constant *C1, Constant *C2, Constant *C3)
: ConstantExpr(C1->getType(), Instruction::ShuffleVector, : ConstantExpr(C1->getType(), Instruction::ShuffleVector,
Ops, 3) { &Op<0>(), 3) {
Ops[0].init(C1, this); Op<0>().init(C1, this);
Ops[1].init(C2, this); Op<1>().init(C2, this);
Ops[2].init(C3, 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 /// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
/// used behind the scenes to implement getelementpr constant exprs. /// used behind the scenes to implement getelementpr constant exprs.
class VISIBILITY_HIDDEN GetElementPtrConstantExpr : public ConstantExpr { class VISIBILITY_HIDDEN GetElementPtrConstantExpr : public ConstantExpr {
GetElementPtrConstantExpr(Constant *C, const std::vector<Constant*> &IdxList, GetElementPtrConstantExpr(Constant *C, const std::vector<Constant*> &IdxList,
const Type *DestTy) 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);
}
public: public:
static GetElementPtrConstantExpr *Create(Constant *C, const std::vector<Constant*> &IdxList, static GetElementPtrConstantExpr *Create(Constant *C, const std::vector<Constant*> &IdxList,
const Type *DestTy) { const Type *DestTy) {
return new(IdxList.size() + 1/*FIXME*/) GetElementPtrConstantExpr(C, IdxList, DestTy); return new(IdxList.size() + 1) GetElementPtrConstantExpr(C, IdxList, DestTy);
}
~GetElementPtrConstantExpr() {
delete [] OperandList;
} }
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
}; };
// CompareConstantExpr - This class is private to Constants.cpp, and is used // 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); return User::operator new(s, 2);
} }
unsigned short predicate; unsigned short predicate;
Use Ops[2];
CompareConstantExpr(Instruction::OtherOps opc, unsigned short pred, CompareConstantExpr(Instruction::OtherOps opc, unsigned short pred,
Constant* LHS, Constant* RHS) Constant* LHS, Constant* RHS)
: ConstantExpr(Type::Int1Ty, opc, Ops, 2), predicate(pred) { : ConstantExpr(Type::Int1Ty, opc, &Op<0>(), 2), predicate(pred) {
OperandList[0].init(LHS, this); Op<0>().init(LHS, this);
OperandList[1].init(RHS, this); Op<1>().init(RHS, this);
} }
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
}; };
} // end anonymous namespace } // 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 // 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 // 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 // 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 // ConstantCreator - A class that is used to create constants by
// ValueMap*. This class should be partially specialized if there is // ValueMap*. This class should be partially specialized if there is
// something strange that needs to be done to interface to the ctor for the // something strange that needs to be done to interface to the ctor for the
// constant. // constant.
// //
namespace llvm { 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> template<class ConstantClass, class TypeClass, class ValType>
struct VISIBILITY_HIDDEN ConstantCreator { struct VISIBILITY_HIDDEN ConstantCreator {
static ConstantClass *create(const TypeClass *Ty, const ValType &V) { static ConstantClass *create(const TypeClass *Ty, const ValType &V) {
unsigned FIXME = 0; // = traits<ValType>::uses(V) return new(ConstantTraits<ValType>::uses(V)) ConstantClass(Ty, V);
return new(FIXME) ConstantClass(Ty, V);
} }
}; };

View File

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

View File

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