///
class TerminatorInst : public Instruction {
protected:
- TerminatorInst(Instruction::TermOps iType, Use *Ops, unsigned NumOps,
- Instruction *InsertBefore = 0);
TerminatorInst(const Type *Ty, Instruction::TermOps iType,
- Use *Ops, unsigned NumOps,
- const std::string &Name = "", Instruction *InsertBefore = 0)
- : Instruction(Ty, iType, Ops, NumOps, Name, InsertBefore) {}
+ Use *Ops, unsigned NumOps,
+ Instruction *InsertBefore = 0)
+ : Instruction(Ty, iType, Ops, NumOps, InsertBefore) {}
- TerminatorInst(Instruction::TermOps iType, Use *Ops, unsigned NumOps,
- BasicBlock *InsertAtEnd);
TerminatorInst(const Type *Ty, Instruction::TermOps iType,
- Use *Ops, unsigned NumOps,
- const std::string &Name, BasicBlock *InsertAtEnd)
- : Instruction(Ty, iType, Ops, NumOps, Name, InsertAtEnd) {}
+ Use *Ops, unsigned NumOps, BasicBlock *InsertAtEnd)
+ : Instruction(Ty, iType, Ops, NumOps, InsertAtEnd) {}
// Out of line virtual method, so the vtable, etc has a home.
~TerminatorInst();
class UnaryInstruction : public Instruction {
Use Op;
+
+ // avoiding warning: 'this' : used in base member initializer list
+ UnaryInstruction* this_() { return this; }
protected:
- UnaryInstruction(const Type *Ty, unsigned iType, Value *V,
- const std::string &Name = "", Instruction *IB = 0)
- : Instruction(Ty, iType, &Op, 1, Name, IB), Op(V, this) {
+ UnaryInstruction(const Type *Ty, unsigned iType, Value *V, Instruction *IB =0)
+ : Instruction(Ty, iType, &Op, 1, IB), Op(V, this_()) {
}
- UnaryInstruction(const Type *Ty, unsigned iType, Value *V,
- const std::string &Name, BasicBlock *IAE)
- : Instruction(Ty, iType, &Op, 1, Name, IAE), Op(V, this) {
+ UnaryInstruction(const Type *Ty, unsigned iType, Value *V, BasicBlock *IAE)
+ : Instruction(Ty, iType, &Op, 1, IAE), Op(V, this_()) {
}
public:
// Out of line virtual method, so the vtable, etc has a home.
protected:
void init(BinaryOps iType);
BinaryOperator(BinaryOps iType, Value *S1, Value *S2, const Type *Ty,
- const std::string &Name, Instruction *InsertBefore)
- : Instruction(Ty, iType, Ops, 2, Name, InsertBefore) {
- Ops[0].init(S1, this);
- Ops[1].init(S2, this);
- init(iType);
- }
+ const std::string &Name, Instruction *InsertBefore);
BinaryOperator(BinaryOps iType, Value *S1, Value *S2, const Type *Ty,
- const std::string &Name, BasicBlock *InsertAtEnd)
- : Instruction(Ty, iType, Ops, 2, Name, InsertAtEnd) {
- Ops[0].init(S1, this);
- Ops[1].init(S2, this);
- init(iType);
- }
-
+ const std::string &Name, BasicBlock *InsertAtEnd);
public:
/// Transparently provide more efficient getOperand methods.
protected:
/// @brief Constructor with insert-before-instruction semantics for subclasses
CastInst(const Type *Ty, unsigned iType, Value *S,
- const std::string &Name = "", Instruction *InsertBefore = 0)
- : UnaryInstruction(Ty, iType, S, Name, InsertBefore) {
+ const std::string &Name = "", Instruction *InsertBefore = 0)
+ : UnaryInstruction(Ty, iType, S, InsertBefore) {
+ setName(Name);
}
/// @brief Constructor with insert-at-end-of-block semantics for subclasses
CastInst(const Type *Ty, unsigned iType, Value *S,
- const std::string &Name, BasicBlock *InsertAtEnd)
- : UnaryInstruction(Ty, iType, S, Name, InsertAtEnd) {
+ const std::string &Name, BasicBlock *InsertAtEnd)
+ : UnaryInstruction(Ty, iType, S, InsertAtEnd) {
+ setName(Name);
}
public:
/// Provides a way to construct any of the CastInst subclasses using an
Instruction *InsertBefore = 0 ///< Place to insert the instruction
);
+ /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts.
+ static CastInst *createIntegerCast(
+ Value *S, ///< The pointer value to be casted (operand 0)
+ const Type *Ty, ///< The type to which cast should be made
+ bool isSigned, ///< Whether to regard S as signed or not
+ const std::string &Name = "", ///< Name for the instruction
+ Instruction *InsertBefore = 0 ///< Place to insert the instruction
+ );
+
+ /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts.
+ static CastInst *createIntegerCast(
+ Value *S, ///< The integer value to be casted (operand 0)
+ const Type *Ty, ///< The integer type to which operand is casted
+ bool isSigned, ///< Whether to regard S as signed or not
+ const std::string &Name, ///< The name for the instruction
+ BasicBlock *InsertAtEnd ///< The block to insert the instruction into
+ );
+
+ /// @brief Create an FPExt, BitCast, or FPTrunc for fp -> fp casts
+ static CastInst *createFPCast(
+ Value *S, ///< The floating point value to be casted
+ const Type *Ty, ///< The floating point type to cast to
+ const std::string &Name = "", ///< Name for the instruction
+ Instruction *InsertBefore = 0 ///< Place to insert the instruction
+ );
+
+ /// @brief Create an FPExt, BitCast, or FPTrunc for fp -> fp casts
+ static CastInst *createFPCast(
+ Value *S, ///< The floating point value to be casted
+ const Type *Ty, ///< The floating point type to cast to
+ const std::string &Name, ///< The name for the instruction
+ BasicBlock *InsertAtEnd ///< The block to insert the instruction into
+ );
+
/// @brief Create a SExt or BitCast cast instruction
static CastInst *createSExtOrBitCast(
Value *S, ///< The value to be casted (operand 0)
);
/// Returns the opcode necessary to cast Val into Ty using usual casting
- /// rules.
+ /// rules.
+ /// @brief Infer the opcode for cast operand and type
static Instruction::CastOps getCastOpcode(
const Value *Val, ///< The value to cast
bool SrcIsSigned, ///< Whether to treat the source as signed
bool DstIsSigned ///< Whether to treate the dest. as signed
);
- /// Joins the create method (with insert-before-instruction semantics) above
- /// with the getCastOpcode method. getOpcode(S,Ty) is called first to
- /// obtain the opcode for casting S to type Ty. Then the get(...) method is
- /// called to create the CastInst and insert it. The instruction is
- /// inserted before InsertBefore (if it is non-null). The cast created is
- /// inferred, because only the types involved are used in determining which
- /// cast opcode to use. For specific casts, use one of the create methods.
- /// @brief Inline helper method to join create with getCastOpcode.
- inline static CastInst *createInferredCast(
- Value *S, ///< The value to be casted (operand 0)
- bool SrcIsSigned, ///< Whether to treat the source as signed
- const Type *Ty, ///< Type to which operand should be casted
- bool DstIsSigned, ///< Whether to treate the dest. as signed
- const std::string &Name = "", ///< Name for the instruction
- Instruction *InsertBefore = 0 ///< Place to insert the CastInst
- ) {
- return create(getCastOpcode(S, SrcIsSigned, Ty, DstIsSigned),
- S, Ty, Name, InsertBefore);
- }
- static CastInst *createInferredCast(
- Value *S, ///< The value to be casted (operand 0)
- const Type *Ty, ///< Type to which operand should be casted
- const std::string &Name = "", ///< Name for the instruction
- Instruction *InsertBefore = 0 ///< Place to insert the CastInst
- );
-
- /// Joins the get method (with insert-at-end-of-block semantics) method
- /// above with the getCastOpcode method. getOpcode(S,Ty) is called first to
- /// obtain the usual casting opcode for casting S to type Ty. Then the
- /// get(...) method is called to create the CastInst and insert it. The
- /// instruction is inserted at the end of InsertAtEnd (if it is non-null).
- /// The created cast is inferred, because only the types involved are used
- /// in determining which cast opcode to use. For specific casts, use one of
- /// the create methods.
- /// @brief Inline helper method to join create with getCastOpcode.
- inline static CastInst *createInferredCast(
- Value *S, ///< The value to be casted (operand 0)
- bool SrcIsSigned, ///< Whether to treat the source as signed
- const Type *Ty, ///< Type to which operand should be casted
- bool DstIsSigned, ///< Whether to treate the dest. as signed
- const std::string &Name, ///< Name for the instruction
- BasicBlock *InsertAtEnd ///< The block to insert the instruction into
- ) {
- return create(getCastOpcode(S, SrcIsSigned, Ty, DstIsSigned),
- S, Ty, Name, InsertAtEnd);
- }
-
- static CastInst *createInferredCast(
- Value *S, ///< The value to be casted (operand 0)
- const Type *Ty, ///< Type to which operand should be casted
- const std::string &Name, ///< Name for the instruction
- BasicBlock *InsertAtEnd ///< The block to insert the instruction into
- );
-
/// There are several places where we need to know if a cast instruction
/// only deals with integer source and destination types. To simplify that
/// logic, this method is provided.
/// A lossless cast is one that does not alter the basic value. It implies
/// a no-op cast but is more stringent, preventing things like int->float,
- /// long->double, int->ptr, or packed->anything.
+ /// long->double, int->ptr, or vector->anything.
/// @returns true iff the cast is lossless.
/// @brief Determine if this is a lossless cast.
bool isLosslessCast() const;
/// involving Integer and Pointer types. They are no-op casts if the integer
/// is the same size as the pointer. However, pointer size varies with
/// platform. Generally, the result of TargetData::getIntPtrType() should be
- /// passed in. If that's not available, use Type::ULongTy, which will make
+ /// passed in. If that's not available, use Type::Int64Ty, which will make
/// the isNoopCast call conservative.
/// @brief Determine if this cast is a no-op cast.
bool isNoopCast(
return Instruction::CastOps(Instruction::getOpcode());
}
+ /// @brief Return the source type, as a convenience
+ const Type* getSrcTy() const { return getOperand(0)->getType(); }
+ /// @brief Return the destination type, as a convenience
+ const Type* getDestTy() const { return getType(); }
+
+ /// This method can be used to determine if a cast from S to DstTy using
+ /// Opcode op is valid or not.
+ /// @returns true iff the proposed cast is valid.
+ /// @brief Determine if a cast is valid without creating one.
+ static bool castIsValid(Instruction::CastOps op, Value *S, const Type *DstTy);
+
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const CastInst *) { return true; }
static inline bool classof(const Instruction *I) {
Value *S2, const std::string &Name,
BasicBlock *InsertAtEnd);
- /// @brief Implement superclass method.
- virtual CmpInst *clone() const;
-
/// @brief Get the opcode casted to the right type
OtherOps getOpcode() const {
return static_cast<OtherOps>(Instruction::getOpcode());
unsigned getNumOperands() const { return 2; }
/// This is just a convenience that dispatches to the subclasses.
- /// @brief Swap the operands.
+ /// @brief Swap the operands and adjust predicate accordingly to retain
+ /// the same comparison.
void swapOperands();
/// This is just a convenience that dispatches to the subclasses.
/// @brief Determine if this is an equals/not equals predicate.
bool isEquality();
+ /// @returns true if the predicate is unsigned, false otherwise.
+ /// @brief Determine if the predicate is an unsigned operation.
+ static bool isUnsigned(unsigned short predicate);
+
+ /// @returns true if the predicate is signed, false otherwise.
+ /// @brief Determine if the predicate is an signed operation.
+ static bool isSigned(unsigned short predicate);
+
+ /// @brief Determine if the predicate is an ordered operation.
+ static bool isOrdered(unsigned short predicate);
+
+ /// @brief Determine if the predicate is an unordered operation.
+ static bool isUnordered(unsigned short predicate);
+
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const CmpInst *) { return true; }
static inline bool classof(const Instruction *I) {