about summary refs log tree commit diff
path: root/compiler/rustc_apfloat/src/ieee.rs
diff options
context:
space:
mode:
authorest31 <MTest31@outlook.com>2020-09-30 17:46:18 +0200
committerest31 <MTest31@outlook.com>2020-09-30 17:48:26 +0200
commit7f5008c8293a4d1eb3e4557a36a6bfdef34de284 (patch)
tree728d353ca824250abd9606cec36a4f0183b2979c /compiler/rustc_apfloat/src/ieee.rs
parentc6e4db620a7d2f569f11dcab627430921ea8aacf (diff)
downloadrust-7f5008c8293a4d1eb3e4557a36a6bfdef34de284.tar.gz
rust-7f5008c8293a4d1eb3e4557a36a6bfdef34de284.zip
Backport LLVM apfloat commit to rustc_apfloat
Backports LLVM commit: https://github.com/llvm/llvm-project/commit/e34bd1e0b03d20a506ada156d87e1b3a96d82fa2

Fixes #69532
Diffstat (limited to 'compiler/rustc_apfloat/src/ieee.rs')
-rw-r--r--compiler/rustc_apfloat/src/ieee.rs12
1 files changed, 12 insertions, 0 deletions
diff --git a/compiler/rustc_apfloat/src/ieee.rs b/compiler/rustc_apfloat/src/ieee.rs
index e3d941cad7a..aafd6dfb89a 100644
--- a/compiler/rustc_apfloat/src/ieee.rs
+++ b/compiler/rustc_apfloat/src/ieee.rs
@@ -1511,6 +1511,18 @@ impl<S: Semantics, T: Semantics> FloatConvert<IeeeFloat<T>> for IeeeFloat<S> {
                 sig::set_bit(&mut r.sig, T::PRECISION - 1);
             }
 
+            // If we are truncating NaN, it is possible that we shifted out all of the
+            // set bits in a signalling NaN payload. But NaN must remain NaN, so some
+            // bit in the significand must be set (otherwise it is Inf).
+            // This can only happen with sNaN. Set the 1st bit after the quiet bit,
+            // so that we still have an sNaN.
+            if r.sig[0] == 0 {
+                assert!(shift < 0, "Should not lose NaN payload on extend");
+                assert!(T::PRECISION >= 3, "Unexpectedly narrow significand");
+                assert!(*loses_info, "Missing payload should have set lost info");
+                sig::set_bit(&mut r.sig, T::PRECISION - 3);
+            }
+
             // 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