From 957caa243d9270df37a566aedae3f1244e7b62ef Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Mon, 20 Mar 2017 14:40:12 +0000 Subject: [PATCH] Use MutableArrayRef for APFloat::convertToInteger As discussed on D31074, use MutableArrayRef for destination integer buffers to help assert before stack overflows happen. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298253 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/APFloat.h | 18 ++++--- include/llvm/ADT/ArrayRef.h | 12 +++++ lib/Analysis/ConstantFolding.cpp | 6 +-- lib/ExecutionEngine/ExecutionEngine.cpp | 2 +- lib/Support/APFloat.cpp | 63 +++++++++++++----------- lib/Transforms/Scalar/IndVarSimplify.cpp | 5 +- 6 files changed, 63 insertions(+), 43 deletions(-) diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 46b9de0df93..d2b3b57f0d2 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -18,6 +18,7 @@ #define LLVM_ADT_APFLOAT_H #include "llvm/ADT/APInt.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/ErrorHandling.h" #include @@ -273,8 +274,8 @@ public: /// @{ opStatus convert(const fltSemantics &, roundingMode, bool *); - opStatus convertToInteger(integerPart *, unsigned int, bool, roundingMode, - bool *) const; + opStatus convertToInteger(MutableArrayRef, unsigned int, bool, + roundingMode, bool *) const; opStatus convertFromAPInt(const APInt &, bool, roundingMode); opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int, bool, roundingMode); @@ -495,8 +496,9 @@ private: opStatus addOrSubtract(const IEEEFloat &, roundingMode, bool subtract); opStatus handleOverflow(roundingMode); bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const; - opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool, - roundingMode, bool *) const; + opStatus convertToSignExtendedInteger(MutableArrayRef, + unsigned int, bool, roundingMode, + bool *) const; opStatus convertFromUnsignedParts(const integerPart *, unsigned int, roundingMode); opStatus convertFromHexadecimalString(StringRef, roundingMode); @@ -625,8 +627,8 @@ public: opStatus convertFromString(StringRef, roundingMode); opStatus next(bool nextDown); - opStatus convertToInteger(integerPart *Input, unsigned int Width, - bool IsSigned, roundingMode RM, + opStatus convertToInteger(MutableArrayRef Input, + unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const; opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM); opStatus convertFromSignExtendedInteger(const integerPart *Input, @@ -1055,8 +1057,8 @@ public: opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo); - opStatus convertToInteger(integerPart *Input, unsigned int Width, - bool IsSigned, roundingMode RM, + opStatus convertToInteger(MutableArrayRef Input, + unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const { APFLOAT_DISPATCH_ON_SEMANTICS( convertToInteger(Input, Width, IsSigned, RM, IsExact)); diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index b3fe31f4a80..6b35d0aec8b 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -487,6 +487,18 @@ namespace llvm { return ArrayRef(Arr); } + /// Construct a MutableArrayRef from a single element. + template + MutableArrayRef makeMutableArrayRef(T &OneElt) { + return OneElt; + } + + /// Construct a MutableArrayRef from a pointer and length. + template + MutableArrayRef makeMutableArrayRef(T *data, size_t length) { + return MutableArrayRef(data, length); + } + /// @} /// @name ArrayRef Comparison Operators /// @{ diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp index 85ca622a25d..e6939c02238 100644 --- a/lib/Analysis/ConstantFolding.cpp +++ b/lib/Analysis/ConstantFolding.cpp @@ -1518,9 +1518,9 @@ Constant *ConstantFoldSSEConvertToInt(const APFloat &Val, bool roundTowardZero, bool isExact = false; APFloat::roundingMode mode = roundTowardZero? APFloat::rmTowardZero : APFloat::rmNearestTiesToEven; - APFloat::opStatus status = Val.convertToInteger(&UIntVal, ResultWidth, - /*isSigned=*/true, mode, - &isExact); + APFloat::opStatus status = + Val.convertToInteger(makeMutableArrayRef(UIntVal), ResultWidth, + /*isSigned=*/true, mode, &isExact); if (status != APFloat::opOK && (!roundTowardZero || status != APFloat::opInexact)) return nullptr; diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index ef7e3508964..2ee72f9a8c1 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -727,7 +727,7 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { APFloat apf = APFloat(APFloat::x87DoubleExtended(), GV.IntVal); uint64_t v; bool ignored; - (void)apf.convertToInteger(&v, BitWidth, + (void)apf.convertToInteger(makeMutableArrayRef(v), BitWidth, CE->getOpcode()==Instruction::FPToSI, APFloat::rmTowardZero, &ignored); GV.IntVal = v; // endian? diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 59d4047206c..dd878562a1c 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -1716,9 +1716,10 @@ IEEEFloat::opStatus IEEEFloat::remainder(const IEEEFloat &rhs) { int parts = partCount(); integerPart *x = new integerPart[parts]; bool ignored; - fs = V.convertToInteger(x, parts * integerPartWidth, true, - rmNearestTiesToEven, &ignored); - if (fs==opInvalidOp) { + fs = V.convertToInteger(makeMutableArrayRef(x, parts), + parts * integerPartWidth, true, rmNearestTiesToEven, + &ignored); + if (fs == opInvalidOp) { delete[] x; return fs; } @@ -1756,9 +1757,10 @@ IEEEFloat::opStatus IEEEFloat::mod(const IEEEFloat &rhs) { int parts = partCount(); integerPart *x = new integerPart[parts]; bool ignored; - fs = V.convertToInteger(x, parts * integerPartWidth, true, - rmTowardZero, &ignored); - if (fs==opInvalidOp) { + fs = V.convertToInteger(makeMutableArrayRef(x, parts), + parts * integerPartWidth, true, rmTowardZero, + &ignored); + if (fs == opInvalidOp) { delete[] x; return fs; } @@ -2051,7 +2053,7 @@ IEEEFloat::opStatus IEEEFloat::convert(const fltSemantics &toSemantics, Note that for conversions to integer type the C standard requires round-to-zero to always be used. */ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( - integerPart *parts, unsigned int width, bool isSigned, + MutableArrayRef parts, unsigned int width, bool isSigned, roundingMode rounding_mode, bool *isExact) const { lostFraction lost_fraction; const integerPart *src; @@ -2064,9 +2066,10 @@ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( return opInvalidOp; dstPartsCount = partCountForBits(width); + assert(dstPartsCount <= parts.size() && "Integer too big"); if (category == fcZero) { - APInt::tcSet(parts, 0, dstPartsCount); + APInt::tcSet(parts.data(), 0, dstPartsCount); // Negative zero can't be represented as an int. *isExact = !sign; return opOK; @@ -2078,7 +2081,7 @@ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( the destination. */ if (exponent < 0) { /* Our absolute value is less than one; truncate everything. */ - APInt::tcSet(parts, 0, dstPartsCount); + APInt::tcSet(parts.data(), 0, dstPartsCount); /* For exponent -1 the integer bit represents .5, look at that. For smaller exponents leftmost truncated bit is 0. */ truncatedBits = semantics->precision -1U - exponent; @@ -2094,11 +2097,13 @@ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( if (bits < semantics->precision) { /* We truncate (semantics->precision - bits) bits. */ truncatedBits = semantics->precision - bits; - APInt::tcExtract(parts, dstPartsCount, src, bits, truncatedBits); + APInt::tcExtract(parts.data(), dstPartsCount, src, bits, truncatedBits); } else { /* We want at least as many bits as are available. */ - APInt::tcExtract(parts, dstPartsCount, src, semantics->precision, 0); - APInt::tcShiftLeft(parts, dstPartsCount, bits - semantics->precision); + APInt::tcExtract(parts.data(), dstPartsCount, src, semantics->precision, + 0); + APInt::tcShiftLeft(parts.data(), dstPartsCount, + bits - semantics->precision); truncatedBits = 0; } } @@ -2110,7 +2115,7 @@ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( truncatedBits); if (lost_fraction != lfExactlyZero && roundAwayFromZero(rounding_mode, lost_fraction, truncatedBits)) { - if (APInt::tcIncrement(parts, dstPartsCount)) + if (APInt::tcIncrement(parts.data(), dstPartsCount)) return opInvalidOp; /* Overflow. */ } } else { @@ -2118,7 +2123,7 @@ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( } /* Step 3: check if we fit in the destination. */ - unsigned int omsb = APInt::tcMSB(parts, dstPartsCount) + 1; + unsigned int omsb = APInt::tcMSB(parts.data(), dstPartsCount) + 1; if (sign) { if (!isSigned) { @@ -2129,7 +2134,8 @@ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( /* It takes omsb bits to represent the unsigned integer value. We lose a bit for the sign, but care is needed as the maximally negative integer is a special case. */ - if (omsb == width && APInt::tcLSB(parts, dstPartsCount) + 1 != omsb) + if (omsb == width && + APInt::tcLSB(parts.data(), dstPartsCount) + 1 != omsb) return opInvalidOp; /* This case can happen because of rounding. */ @@ -2137,7 +2143,7 @@ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( return opInvalidOp; } - APInt::tcNegate (parts, dstPartsCount); + APInt::tcNegate (parts.data(), dstPartsCount); } else { if (omsb >= width + !isSigned) return opInvalidOp; @@ -2159,11 +2165,10 @@ IEEEFloat::opStatus IEEEFloat::convertToSignExtendedInteger( the original value. This is almost equivalent to result==opOK, except for negative zeroes. */ -IEEEFloat::opStatus IEEEFloat::convertToInteger(integerPart *parts, - unsigned int width, - bool isSigned, - roundingMode rounding_mode, - bool *isExact) const { +IEEEFloat::opStatus +IEEEFloat::convertToInteger(MutableArrayRef parts, + unsigned int width, bool isSigned, + roundingMode rounding_mode, bool *isExact) const { opStatus fs; fs = convertToSignExtendedInteger(parts, width, isSigned, rounding_mode, @@ -2173,6 +2178,7 @@ IEEEFloat::opStatus IEEEFloat::convertToInteger(integerPart *parts, unsigned int bits, dstPartsCount; dstPartsCount = partCountForBits(width); + assert(dstPartsCount <= parts.size() && "Integer too big"); if (category == fcNaN) bits = 0; @@ -2181,9 +2187,9 @@ IEEEFloat::opStatus IEEEFloat::convertToInteger(integerPart *parts, else bits = width - isSigned; - APInt::tcSetLeastSignificantBits(parts, dstPartsCount, bits); + APInt::tcSetLeastSignificantBits(parts.data(), dstPartsCount, bits); if (sign && isSigned) - APInt::tcShiftLeft(parts, dstPartsCount, width - 1); + APInt::tcShiftLeft(parts.data(), dstPartsCount, width - 1); } return fs; @@ -4293,11 +4299,10 @@ APFloat::opStatus DoubleAPFloat::next(bool nextDown) { return Ret; } -APFloat::opStatus DoubleAPFloat::convertToInteger(integerPart *Input, - unsigned int Width, - bool IsSigned, - roundingMode RM, - bool *IsExact) const { +APFloat::opStatus +DoubleAPFloat::convertToInteger(MutableArrayRef Input, + unsigned int Width, bool IsSigned, + roundingMode RM, bool *IsExact) const { assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); return APFloat(semPPCDoubleDoubleLegacy, bitcastToAPInt()) .convertToInteger(Input, Width, IsSigned, RM, IsExact); @@ -4511,7 +4516,7 @@ APFloat::opStatus APFloat::convertToInteger(APSInt &result, bool *isExact) const { unsigned bitWidth = result.getBitWidth(); SmallVector parts(result.getNumWords()); - opStatus status = convertToInteger(parts.data(), bitWidth, result.isSigned(), + opStatus status = convertToInteger(parts, bitWidth, result.isSigned(), rounding_mode, isExact); // Keeps the original signed-ness. result = APInt(bitWidth, parts); diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index a9516be8c53..dcb2a4a0c6e 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -231,8 +231,9 @@ static bool ConvertToSInt(const APFloat &APF, int64_t &IntVal) { bool isExact = false; // See if we can convert this to an int64_t uint64_t UIntVal; - if (APF.convertToInteger(&UIntVal, 64, true, APFloat::rmTowardZero, - &isExact) != APFloat::opOK || !isExact) + if (APF.convertToInteger(makeMutableArrayRef(UIntVal), 64, true, + APFloat::rmTowardZero, &isExact) != APFloat::opOK || + !isExact) return false; IntVal = UIntVal; return true; -- 2.40.0