[pypy-commit] pypy default: Work around a MSVC bug

arigo pypy.commits at gmail.com
Wed Aug 3 09:39:31 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r86004:1512e98263d9
Date: 2016-08-03 15:41 +0200
http://bitbucket.org/pypy/pypy/changeset/1512e98263d9/

Log:	Work around a MSVC bug

diff --git a/rpython/translator/c/src/float.h b/rpython/translator/c/src/float.h
--- a/rpython/translator/c/src/float.h
+++ b/rpython/translator/c/src/float.h
@@ -34,10 +34,39 @@
 #define OP_CAST_FLOAT_TO_UINT(x,r)   r = (Unsigned)(x)
 #define OP_CAST_INT_TO_FLOAT(x,r)    r = (double)(x)
 #define OP_CAST_UINT_TO_FLOAT(x,r)   r = (double)(x)
-#define OP_CAST_LONGLONG_TO_FLOAT(x,r) r = (double)(x)
-#define OP_CAST_ULONGLONG_TO_FLOAT(x,r) r = (double)(x)
+#define OP_CAST_LONGLONG_TO_FLOAT(x,r) r = rpy_cast_longlong_to_float(x)
+#define OP_CAST_ULONGLONG_TO_FLOAT(x,r) r = rpy_cast_ulonglong_to_float(x)
 #define OP_CAST_BOOL_TO_FLOAT(x,r)   r = (double)(x)
 
+#ifdef _WIN32
+/* The purpose of these two functions is to work around a MSVC bug.
+   The expression '(double)131146795334735160LL' will lead to bogus
+   rounding, but apparently everything is fine if we write instead
+   rpy_cast_longlong_to_float(131146795334735160LL).  Tested with 
+   MSVC 2008.  Note that even if the two functions contain just
+   'return (double)x;' it seems to work on MSVC 2008, but I don't
+   trust that there are no other corner cases.
+   http://stackoverflow.com/questions/33829101/incorrect-double-to-long-conversion
+*/
+static _inline double rpy_cast_longlong_to_float(long long x)
+{
+    unsigned int lo = (unsigned int)x;
+    double result = lo;
+    result += ((int)(x >> 32)) * 4294967296.0;
+    return result;
+}
+static _inline double rpy_cast_ulonglong_to_float(unsigned long long x)
+{
+    unsigned int lo = (unsigned int)x;
+    double result = lo;
+    result += ((unsigned int)(x >> 32)) * 4294967296.0;
+    return result;
+}
+#else
+#  define rpy_cast_longlong_to_float(x) ((double)(x))
+#  define rpy_cast_ulonglong_to_float(x) ((double)(x))
+#endif
+
 #ifdef HAVE_LONG_LONG
 #define OP_CAST_FLOAT_TO_LONGLONG(x,r) r = (long long)(x)
 #define OP_CAST_FLOAT_TO_ULONGLONG(x,r) r = (unsigned long long)(x)


More information about the pypy-commit mailing list