mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-13 09:33:50 +00:00
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:
parent
4982babf4a
commit
efe65369a7
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
163
include/llvm/OperandTraits.h
Normal file
163
include/llvm/OperandTraits.h
Normal 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
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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
131
lib/VMCore/Use.cpp
Normal 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
|
Loading…
x
Reference in New Issue
Block a user