aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDale Johannesen <dalej@apple.com>2007-09-25 17:25:00 +0000
committerDale Johannesen <dalej@apple.com>2007-09-25 17:25:00 +0000
commit902ff94aff34acb2b11f4651f4a4006cb788301a (patch)
tree18f981dcd3b8deaea4728a4551c6fe8b7b8d2c8c
parentc3b0b5ca1d5772cf90c0c66e03412da33a0d7cdb (diff)
downloadexternal_llvm-902ff94aff34acb2b11f4651f4a4006cb788301a.zip
external_llvm-902ff94aff34acb2b11f4651f4a4006cb788301a.tar.gz
external_llvm-902ff94aff34acb2b11f4651f4a4006cb788301a.tar.bz2
Fix long double<->shorter FP type conversions
of zero, infinity, and NaNs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42298 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Support/APFloat.cpp41
1 files changed, 29 insertions, 12 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp
index 2b9930c..b3705f5 100644
--- a/lib/Support/APFloat.cpp
+++ b/lib/Support/APFloat.cpp
@@ -1329,26 +1329,30 @@ APFloat::convert(const fltSemantics &toSemantics,
/* Handle storage complications. If our new form is wider,
re-allocate our bit pattern into wider storage. If it is
narrower, we ignore the excess parts, but if narrowing to a
- single part we need to free the old storage. */
+ single part we need to free the old storage.
+ Be careful not to reference significandParts for zeroes
+ and infinities, since it aborts. */
if (newPartCount > oldPartCount) {
integerPart *newParts;
-
newParts = new integerPart[newPartCount];
APInt::tcSet(newParts, 0, newPartCount);
- APInt::tcAssign(newParts, significandParts(), oldPartCount);
+ if (category==fcNormal || category==fcNaN)
+ APInt::tcAssign(newParts, significandParts(), oldPartCount);
freeSignificand();
significand.parts = newParts;
} else if (newPartCount < oldPartCount) {
/* Capture any lost fraction through truncation of parts so we get
correct rounding whilst normalizing. */
- lostFraction = lostFractionThroughTruncation
- (significandParts(), oldPartCount, toSemantics.precision);
- if (newPartCount == 1)
- {
- integerPart newPart = significandParts()[0];
- freeSignificand();
- significand.part = newPart;
- }
+ if (category==fcNormal)
+ lostFraction = lostFractionThroughTruncation
+ (significandParts(), oldPartCount, toSemantics.precision);
+ if (newPartCount == 1) {
+ integerPart newPart = 0;
+ if (category==fcNormal || category==fcNaN)
+ newPart = significandParts()[0];
+ freeSignificand();
+ significand.part = newPart;
+ }
}
if(category == fcNormal) {
@@ -1356,6 +1360,19 @@ APFloat::convert(const fltSemantics &toSemantics,
exponent += toSemantics.precision - semantics->precision;
semantics = &toSemantics;
fs = normalize(rounding_mode, lostFraction);
+ } else if (category == fcNaN) {
+ int shift = toSemantics.precision - semantics->precision;
+ // No normalization here, just truncate
+ if (shift>0)
+ APInt::tcShiftLeft(significandParts(), newPartCount, shift);
+ else if (shift < 0)
+ APInt::tcShiftRight(significandParts(), newPartCount, -shift);
+ // gcc forces the Quiet bit on, which means (float)(double)(float_sNan)
+ // does not give you back the same bits. This is dubious, and we
+ // don't currently do it. You're really supposed to get
+ // an invalid operation signal at runtime, but nobody does that.
+ semantics = &toSemantics;
+ fs = opOK;
} else {
semantics = &toSemantics;
fs = opOK;
@@ -1818,7 +1835,7 @@ APFloat::initFromFloatAPInt(const APInt & api) {
} else if (myexponent==0xff && mysignificand==0) {
// exponent, significand meaningless
category = fcInfinity;
- } else if (myexponent==0xff && (mysignificand & 0x400000)) {
+ } else if (myexponent==0xff && mysignificand!=0) {
// sign, exponent, significand meaningless
category = fcNaN;
*significandParts() = mysignificand;