diff options
author | Pat Gavlin <pgavlin@gmail.com> | 2017-04-10 16:58:46 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-10 16:58:46 -0700 |
commit | 02aa5ce7fc6d866fe368c317d2bc3ab06b766c52 (patch) | |
tree | 5045438140cfba996d295b32b180a2d7ef8e4be4 /src | |
parent | 8ffb46cd635cd9419cc26315d9eec64b976cbfb0 (diff) | |
parent | 58aaf6eaea69afb2f32a1503cc189864b0c0ff82 (diff) | |
download | coreclr-02aa5ce7fc6d866fe368c317d2bc3ab06b766c52.tar.gz coreclr-02aa5ce7fc6d866fe368c317d2bc3ab06b766c52.tar.bz2 coreclr-02aa5ce7fc6d866fe368c317d2bc3ab06b766c52.zip |
Merge pull request #10866 from pgavlin/VSO405852
Fix VSO bug 405852.
Diffstat (limited to 'src')
-rw-r--r-- | src/jit/valuenum.cpp | 50 |
1 files changed, 48 insertions, 2 deletions
diff --git a/src/jit/valuenum.cpp b/src/jit/valuenum.cpp index 66b7978674..03bc204070 100644 --- a/src/jit/valuenum.cpp +++ b/src/jit/valuenum.cpp @@ -206,6 +206,52 @@ T ValueNumStore::EvalOp(VNFunc vnf, T v0, T v1, ValueNum* pExcSet) } } +struct FloatTraits +{ + static float NaN() + { + unsigned bits = 0xFFC00000u; + float result; + static_assert(sizeof(bits) == sizeof(result), "sizeof(unsigned) must equal sizeof(float)"); + memcpy(&result, &bits, sizeof(result)); + return result; + } +}; + +struct DoubleTraits +{ + static double NaN() + { + unsigned long long bits = 0xFFF8000000000000ull; + double result; + static_assert(sizeof(bits) == sizeof(result), "sizeof(unsigned long long) must equal sizeof(double)"); + memcpy(&result, &bits, sizeof(result)); + return result; + } +}; + +template <typename TFp, typename TFpTraits> +TFp FpRem(TFp dividend, TFp divisor) +{ + // From the ECMA standard: + // + // If [divisor] is zero or [dividend] is infinity + // the result is NaN. + // If [divisor] is infinity, + // the result is [dividend] + + if (divisor == 0 || !_finite(dividend)) + { + return TFpTraits::NaN(); + } + else if (!_finite(divisor) && !_isnan(divisor)) + { + return dividend; + } + + return (TFp)fmod((double)dividend, (double)divisor); +} + // Specialize for double for floating operations, that doesn't involve unsigned. template <> double ValueNumStore::EvalOp<double>(VNFunc vnf, double v0, double v1, ValueNum* pExcSet) @@ -223,7 +269,7 @@ double ValueNumStore::EvalOp<double>(VNFunc vnf, double v0, double v1, ValueNum* case GT_DIV: return v0 / v1; case GT_MOD: - return fmod(v0, v1); + return FpRem<double, DoubleTraits>(v0, v1); default: unreached(); @@ -247,7 +293,7 @@ float ValueNumStore::EvalOp<float>(VNFunc vnf, float v0, float v1, ValueNum* pEx case GT_DIV: return v0 / v1; case GT_MOD: - return fmodf(v0, v1); + return FpRem<float, FloatTraits>(v0, v1); default: unreached(); |