summaryrefslogtreecommitdiffstats
path: root/lib/Support/APFloat.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-02-28 12:49:50 +0000
committerJohn McCall <rjmccall@apple.com>2010-02-28 12:49:50 +0000
commit165e96bd25200ccabe4539aaf29a249b61074d11 (patch)
tree4b55e2f5d26b248d827d1da784f8e3ff16c182e5 /lib/Support/APFloat.cpp
parent1e7ad3993d8700488895fa372ecad55443f53485 (diff)
downloadexternal_llvm-165e96bd25200ccabe4539aaf29a249b61074d11.zip
external_llvm-165e96bd25200ccabe4539aaf29a249b61074d11.tar.gz
external_llvm-165e96bd25200ccabe4539aaf29a249b61074d11.tar.bz2
Properly clear all the extra bits in a significand when making a NaN from an
APInt. Be certain to set the integer bit in an x87 extended-precision significand so that we don't accidentally make a pseudo-NaN. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97382 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Support/APFloat.cpp')
-rw-r--r--lib/Support/APFloat.cpp36
1 files changed, 28 insertions, 8 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp
index 4f1b854..16a0c23 100644
--- a/lib/Support/APFloat.cpp
+++ b/lib/Support/APFloat.cpp
@@ -631,25 +631,45 @@ void APFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill)
category = fcNaN;
sign = Negative;
+ integerPart *significand = significandParts();
+ unsigned numParts = partCount();
+
// Set the significand bits to the fill.
- if (!fill || fill->getNumWords() < partCount())
- APInt::tcSet(significandParts(), 0, partCount());
- if (fill)
- APInt::tcAssign(significandParts(), fill->getRawData(), partCount());
+ if (!fill || fill->getNumWords() < numParts)
+ APInt::tcSet(significand, 0, numParts);
+ if (fill) {
+ APInt::tcAssign(significand, fill->getRawData(), partCount());
+
+ // Zero out the excess bits of the significand.
+ unsigned bitsToPreserve = semantics->precision - 1;
+ unsigned part = bitsToPreserve / 64;
+ bitsToPreserve %= 64;
+ significand[part] &= ((1ULL << bitsToPreserve) - 1);
+ for (part++; part != numParts; ++part)
+ significand[part] = 0;
+ }
+
+ unsigned QNaNBit = semantics->precision - 2;
if (SNaN) {
// We always have to clear the QNaN bit to make it an SNaN.
- APInt::tcClearBit(significandParts(), semantics->precision - 2);
+ APInt::tcClearBit(significand, QNaNBit);
// If there are no bits set in the payload, we have to set
// *something* to make it a NaN instead of an infinity;
// conventionally, this is the next bit down from the QNaN bit.
- if (APInt::tcIsZero(significandParts(), partCount()))
- APInt::tcSetBit(significandParts(), semantics->precision - 3);
+ if (APInt::tcIsZero(significand, numParts))
+ APInt::tcSetBit(significand, QNaNBit - 1);
} else {
// We always have to set the QNaN bit to make it a QNaN.
- APInt::tcSetBit(significandParts(), semantics->precision - 2);
+ APInt::tcSetBit(significand, QNaNBit);
}
+
+ // For x87 extended precision, we want to make a NaN, not a
+ // pseudo-NaN. Maybe we should expose the ability to make
+ // pseudo-NaNs?
+ if (semantics == &APFloat::x87DoubleExtended)
+ APInt::tcSetBit(significand, QNaNBit + 1);
}
APFloat APFloat::makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative,