diff options
author | JF Bastien <github@jfbastien.com> | 2016-05-05 15:54:23 -0700 |
---|---|---|
committer | JF Bastien <github@jfbastien.com> | 2016-05-05 15:54:23 -0700 |
commit | 727c08faf01da99d57dfe86b3fb0fee9db415f41 (patch) | |
tree | 9f07000d1ef0a5470aff0f56a3e6a0b11c86a7b9 /src | |
parent | 4dfa39338f188ff8e70b8b796dc61d89aadfd3b0 (diff) | |
download | binaryen-727c08faf01da99d57dfe86b3fb0fee9db415f41.tar.gz binaryen-727c08faf01da99d57dfe86b3fb0fee9db415f41.tar.bz2 binaryen-727c08faf01da99d57dfe86b3fb0fee9db415f41.zip |
Fix NaN / 0 (#442)
As discussed in: https://github.com/WebAssembly/spec/pull/282#issuecomment-217280544
Diffstat (limited to 'src')
-rw-r--r-- | src/wasm.h | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/src/wasm.h b/src/wasm.h index 6b171f8bd..9c3bc9022 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -246,11 +246,37 @@ private: } } + static uint32_t NaNPayload(float f) { + assert(std::isnan(f) && "expected a NaN"); + // SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF + // NaN has all-one exponent and non-zero fraction. + return ~0xff800000u & bit_cast<uint32_t>(f); + } + + static uint64_t NaNPayload(double f) { + assert(std::isnan(f) && "expected a NaN"); + // SEEEEEEE EEEEFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF + // NaN has all-one exponent and non-zero fraction. + return ~0xfff0000000000000ull & bit_cast<uint64_t>(f); + } + + static float setQuietNaN(float f) { + assert(std::isnan(f) && "expected a NaN"); + // An SNaN is a NaN with the most significant fraction bit clear. + return bit_cast<float>(0x00400000u | bit_cast<uint32_t>(f)); + } + + static double setQuietNaN(double f) { + assert(std::isnan(f) && "expected a NaN"); + // An SNaN is a NaN with the most significant fraction bit clear. + return bit_cast<double>(0x0008000000000000ull | bit_cast<uint64_t>(f)); + } + static void printFloat(std::ostream &o, float f) { if (std::isnan(f)) { const char *sign = std::signbit(f) ? "-" : ""; o << sign << "nan"; - if (uint32_t payload = ~0xff800000u & bit_cast<uint32_t>(f)) { + if (uint32_t payload = NaNPayload(f)) { o << ":0x" << std::hex << payload << std::dec; } return; @@ -266,7 +292,7 @@ private: if (std::isnan(d)) { const char *sign = std::signbit(d) ? "-" : ""; o << sign << "nan"; - if (uint64_t payload = ~0xfff0000000000000ull & bit_cast<uint64_t>(d)) { + if (uint64_t payload = NaNPayload(d)) { o << ":0x" << std::hex << payload << std::dec; } return; @@ -448,7 +474,7 @@ private: switch (std::fpclassify(rhs)) { case FP_ZERO: switch (std::fpclassify(lhs)) { - case FP_NAN: return *this; + case FP_NAN: return Literal(setQuietNaN(lhs)); case FP_ZERO: return Literal(std::copysign(std::numeric_limits<float>::quiet_NaN(), sign)); case FP_NORMAL: // fallthrough case FP_SUBNORMAL: // fallthrough @@ -468,7 +494,7 @@ private: switch (std::fpclassify(rhs)) { case FP_ZERO: switch (std::fpclassify(lhs)) { - case FP_NAN: return *this; + case FP_NAN: return Literal(setQuietNaN(lhs)); case FP_ZERO: return Literal(std::copysign(std::numeric_limits<double>::quiet_NaN(), sign)); case FP_NORMAL: // fallthrough case FP_SUBNORMAL: // fallthrough |