const Type *Ty ///< The type to which the constant is converted
);
+ // This method uses the CastInst::getCastOpcode method to infer the
+ // cast opcode to use.
// @brief Get a ConstantExpr Conversion operator that casts C to Ty
- static Constant *getCast(Constant *C, const Type *Ty);
+ static Constant *getInferredCast(Constant *C, bool SrcIsSigned,
+ const Type *Ty, bool DestIsSigned);
+
+ static Constant *getCast(Constant *C, const Type *Ty) {
+ return getInferredCast(C, C->getType()->isSigned(), Ty, Ty->isSigned());
+ }
/// @brief Return true if this is a convert constant expression
bool isCast() const;
/// rules.
static Instruction::CastOps getCastOpcode(
const Value *Val, ///< The value to cast
- const Type *Ty ///< The Type to which the value should be casted
+ bool SrcIsSigned, ///< Whether to treat the source as signed
+ const Type *Ty, ///< The Type to which the value should be casted
+ bool DstIsSigned ///< Whether to treate the dest. as signed
);
/// Joins the create method (with insert-before-instruction semantics) above
/// @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, Ty), S, Ty, Name, InsertBefore);
+ 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
/// @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, Ty), S, Ty, Name, InsertAtEnd);
+ 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.
return ExprConstants->getOrCreate(Ty, Key);
}
-Constant *ConstantExpr::getCast( Constant *C, const Type *Ty ) {
+Constant *ConstantExpr::getInferredCast(Constant *C, bool SrcIsSigned,
+ const Type *Ty, bool DestIsSigned) {
// Note: we can't inline this because it requires the Instructions.h header
- return getCast(CastInst::getCastOpcode(C, Ty), C, Ty);
+ return getCast(
+ CastInst::getCastOpcode(C, SrcIsSigned, Ty, DestIsSigned), C, Ty);
}
Constant *ConstantExpr::getCast(unsigned oc, Constant *C, const Type *Ty) {
Constant *ConstantExpr::getSizeOf(const Type *Ty) {
// sizeof is implemented as: (ulong) gep (Ty*)null, 1
- return getCast(
- getGetElementPtr(getNullValue(PointerType::get(Ty)),
- std::vector<Constant*>(1, ConstantInt::get(Type::UIntTy, 1))),
- Type::ULongTy);
+ return getCast(Instruction::PtrToInt, getGetElementPtr(getNullValue(
+ PointerType::get(Ty)), std::vector<Constant*>(1,
+ ConstantInt::get(Type::UIntTy, 1))), Type::ULongTy);
}
Constant *ConstantExpr::getPtrPtrFromArrayPtr(Constant *C) {
// should not assert in checkCast. In other words, this produces a "correct"
// casting opcode for the arguments passed to it.
Instruction::CastOps
-CastInst::getCastOpcode(const Value *Src, const Type *DestTy) {
+CastInst::getCastOpcode(
+ const Value *Src, bool SrcIsSigned, const Type *DestTy, bool DestIsSigned) {
// Get the bit sizes, we'll need these
const Type *SrcTy = Src->getType();
unsigned SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr/packed
if (DestBits < SrcBits)
return Trunc; // int -> smaller int
else if (DestBits > SrcBits) { // its an extension
- if (SrcTy->isSigned())
+ if (SrcIsSigned)
return SExt; // signed -> SEXT
else
return ZExt; // unsigned -> ZEXT
return BitCast; // Same size, No-op cast
}
} else if (SrcTy->isFloatingPoint()) { // Casting from floating pt
- if (DestTy->isSigned())
+ if (DestIsSigned)
return FPToSI; // FP -> sint
else
return FPToUI; // FP -> uint
}
} else if (DestTy->isFloatingPoint()) { // Casting to floating pt
if (SrcTy->isIntegral()) { // Casting from integral
- if (SrcTy->isSigned())
+ if (SrcIsSigned)
return SIToFP; // sint -> FP
else
return UIToFP; // uint -> FP
}
}
+CastInst *CastInst::createInferredCast(
+ Value *S, const Type *Ty, const std::string &Name, Instruction *InsertBefore)
+{
+ return createInferredCast(S, S->getType()->isSigned(), Ty, Ty->isSigned(),
+ Name, InsertBefore);
+}
+
+CastInst *CastInst::createInferredCast(
+ Value *S, const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd)
+{
+ return createInferredCast(S, S->getType()->isSigned(), Ty, Ty->isSigned(),
+ Name, InsertAtEnd);
+}
+
TruncInst::TruncInst(
Value *S, const Type *Ty, const std::string &Name, Instruction *InsertBefore
) : CastInst(Ty, Trunc, S, Name, InsertBefore) {