diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index 06aaca65d5d..335913813bc 100644 --- a/include/llvm/Constants.h +++ b/include/llvm/Constants.h @@ -541,8 +541,15 @@ public: 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; diff --git a/include/llvm/InstrTypes.h b/include/llvm/InstrTypes.h index 0a489f3d08d..07d13da59d5 100644 --- a/include/llvm/InstrTypes.h +++ b/include/llvm/InstrTypes.h @@ -303,7 +303,9 @@ public: /// 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 @@ -316,12 +318,21 @@ public: /// @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 @@ -334,13 +345,23 @@ public: /// @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. diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 71615b2c4a9..10fdda504c3 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -1486,9 +1486,11 @@ static inline Constant *getFoldedCast( 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) { @@ -1612,10 +1614,9 @@ Constant *ConstantExpr::getBitCast(Constant *C, const Type *DstTy) { Constant *ConstantExpr::getSizeOf(const Type *Ty) { // sizeof is implemented as: (ulong) gep (Ty*)null, 1 - return getCast( - getGetElementPtr(getNullValue(PointerType::get(Ty)), - std::vector(1, ConstantInt::get(Type::UIntTy, 1))), - Type::ULongTy); + return getCast(Instruction::PtrToInt, getGetElementPtr(getNullValue( + PointerType::get(Ty)), std::vector(1, + ConstantInt::get(Type::UIntTy, 1))), Type::ULongTy); } Constant *ConstantExpr::getPtrPtrFromArrayPtr(Constant *C) { diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index f4866423176..de1ebced7bc 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -1507,7 +1507,8 @@ CastInst *CastInst::create(Instruction::CastOps op, Value *S, const Type *Ty, // 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 @@ -1519,7 +1520,7 @@ CastInst::getCastOpcode(const Value *Src, const Type *DestTy) { 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 @@ -1527,7 +1528,7 @@ CastInst::getCastOpcode(const Value *Src, const Type *DestTy) { 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 @@ -1542,7 +1543,7 @@ CastInst::getCastOpcode(const Value *Src, const Type *DestTy) { } } 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 @@ -1649,6 +1650,20 @@ checkCast(Instruction::CastOps op, Value *S, const Type *DstTy) { } } +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) {