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