summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPat Gavlin <pgavlin@gmail.com>2017-04-10 16:58:46 -0700
committerGitHub <noreply@github.com>2017-04-10 16:58:46 -0700
commit02aa5ce7fc6d866fe368c317d2bc3ab06b766c52 (patch)
tree5045438140cfba996d295b32b180a2d7ef8e4be4 /src
parent8ffb46cd635cd9419cc26315d9eec64b976cbfb0 (diff)
parent58aaf6eaea69afb2f32a1503cc189864b0c0ff82 (diff)
downloadcoreclr-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.cpp50
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();