[pypy-commit] pypy default: Fix the declaration of the lloperation 'cast_float_to_int' to
arigo
noreply at buildbot.pypy.org
Mon Oct 24 14:43:43 CEST 2011
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r48372:4241a19c0141
Date: 2011-10-24 14:35 +0200
http://bitbucket.org/pypy/pypy/changeset/4241a19c0141/
Log: Fix the declaration of the lloperation 'cast_float_to_int' to no
longer pretend it raises OverflowError, which is wrong.
Fix the JIT by refusing to jtransform operationsl like
'cast_float_to_uint' and 'cast_uint_to_float' and their longlong and
ulonglong equivalents. These would each require their own custom
messy code in the backends. (If really needed, they are probably
better written as '_ll_1_cast_x_to_y' support functions.)
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -847,6 +847,12 @@
return self._float_to_float_cast(v_arg, v_result)
elif not float_arg and float_res:
# some int -> some float
+ size1, unsigned1 = rffi.size_and_sign(v_arg.concretetype)
+ assert size1 <= rffi.sizeof(lltype.Signed), (
+ "not implemented: cast_longlong_to_float")
+ assert size1 < rffi.sizeof(lltype.Signed) or not unsigned1, (
+ "not implemented: cast_uint_to_float")
+ #
ops = []
v1 = varoftype(lltype.Signed)
oplist = self.rewrite_operation(
@@ -871,6 +877,12 @@
return ops
elif float_arg and not float_res:
# some float -> some int
+ size2, unsigned2 = rffi.size_and_sign(v_result.concretetype)
+ assert size2 <= rffi.sizeof(lltype.Signed), (
+ "not implemented: cast_float_to_longlong")
+ assert size2 < rffi.sizeof(lltype.Signed) or not unsigned2, (
+ "not implemented: cast_float_to_uint")
+ #
ops = []
v1 = varoftype(lltype.Float)
op1 = self.rewrite_operation(
@@ -1097,8 +1109,8 @@
# The new operation is optionally further processed by rewrite_operation().
for _old, _new in [('bool_not', 'int_is_zero'),
('cast_bool_to_float', 'cast_int_to_float'),
- ('cast_uint_to_float', 'cast_int_to_float'),
- ('cast_float_to_uint', 'cast_float_to_int'),
+ ('cast_uint_to_float', 'cast_primitive'),
+ ('cast_float_to_uint', 'cast_primitive'),
('int_add_nonneg_ovf', 'int_add_ovf'),
('keepalive', '-live-'),
diff --git a/pypy/jit/metainterp/blackhole.py b/pypy/jit/metainterp/blackhole.py
--- a/pypy/jit/metainterp/blackhole.py
+++ b/pypy/jit/metainterp/blackhole.py
@@ -630,6 +630,9 @@
a = longlong.getrealfloat(a)
# note: we need to call int() twice to care for the fact that
# int(-2147483648.0) returns a long :-(
+ # we could also call intmask() instead of the outermost int(), but
+ # it's probably better to explicitly crash (by getting a long) if a
+ # non-translated version tries to cast a too large float to an int.
return int(int(a))
@arguments("i", returns="f")
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -404,8 +404,8 @@
'FLOAT_TRUEDIV/2',
'FLOAT_NEG/1',
'FLOAT_ABS/1',
- 'CAST_FLOAT_TO_INT/1',
- 'CAST_INT_TO_FLOAT/1',
+ 'CAST_FLOAT_TO_INT/1', # don't use for unsigned ints; we would
+ 'CAST_INT_TO_FLOAT/1', # need some messy code in the backend
'CAST_FLOAT_TO_SINGLEFLOAT/1',
'CAST_SINGLEFLOAT_TO_FLOAT/1',
#
diff --git a/pypy/jit/metainterp/test/test_float.py b/pypy/jit/metainterp/test/test_float.py
--- a/pypy/jit/metainterp/test/test_float.py
+++ b/pypy/jit/metainterp/test/test_float.py
@@ -1,5 +1,6 @@
-import math
+import math, sys
from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
+from pypy.rlib.rarithmetic import intmask, r_uint
class FloatTests:
@@ -45,6 +46,41 @@
res = self.interp_operations(f, [-2.0])
assert res == -8.5
+ def test_cast_float_to_int(self):
+ def g(f):
+ return int(f)
+ res = self.interp_operations(g, [-12345.9])
+ assert res == -12345
+
+ def test_cast_float_to_uint(self):
+ def g(f):
+ return intmask(r_uint(f))
+ raises(AssertionError, self.interp_operations, g, [0.0]) # for now
+ #res = self.interp_operations(g, [sys.maxint*2.0])
+ #assert res == intmask(long(sys.maxint*2.0))
+ #res = self.interp_operations(g, [-12345.9])
+ #assert res == -12345
+
+ def test_cast_int_to_float(self):
+ def g(i):
+ return float(i)
+ res = self.interp_operations(g, [-12345])
+ assert type(res) is float and res == -12345.0
+
+ def test_cast_uint_to_float(self):
+ def g(i):
+ return float(r_uint(i))
+ raises(AssertionError, self.interp_operations, g, [0]) # for now
+ #res = self.interp_operations(g, [sys.maxint*2])
+ #assert type(res) is float and res == float(sys.maxint*2)
+ #res = self.interp_operations(g, [-12345])
+ #assert type(res) is float and res == float(long(r_uint(-12345)))
+
+ #def test_cast_longlong_to_float(self):
+ #def test_cast_ulonglong_to_float(self):
+ #def test_cast_float_to_longlong(self):
+ #def test_cast_float_to_ulonglong(self):
+
class TestOOtype(FloatTests, OOJitMixin):
pass
diff --git a/pypy/rpython/llinterp.py b/pypy/rpython/llinterp.py
--- a/pypy/rpython/llinterp.py
+++ b/pypy/rpython/llinterp.py
@@ -1095,13 +1095,6 @@
assert y >= 0
return self.op_int_add_ovf(x, y)
- def op_cast_float_to_int(self, f):
- assert type(f) is float
- try:
- return ovfcheck(int(f))
- except OverflowError:
- self.make_llexception()
-
def op_int_is_true(self, x):
# special case
if type(x) is CDefinedIntSymbolic:
diff --git a/pypy/rpython/lltypesystem/lloperation.py b/pypy/rpython/lltypesystem/lloperation.py
--- a/pypy/rpython/lltypesystem/lloperation.py
+++ b/pypy/rpython/lltypesystem/lloperation.py
@@ -343,8 +343,8 @@
'cast_uint_to_float': LLOp(canfold=True),
'cast_longlong_to_float' :LLOp(canfold=True),
'cast_ulonglong_to_float':LLOp(canfold=True),
- 'cast_float_to_int': LLOp(canraise=(OverflowError,), tryfold=True),
- 'cast_float_to_uint': LLOp(canfold=True), # XXX need OverflowError?
+ 'cast_float_to_int': LLOp(canfold=True),
+ 'cast_float_to_uint': LLOp(canfold=True),
'cast_float_to_longlong' :LLOp(canfold=True),
'cast_float_to_ulonglong':LLOp(canfold=True),
'truncate_longlong_to_int':LLOp(canfold=True),
diff --git a/pypy/rpython/lltypesystem/opimpl.py b/pypy/rpython/lltypesystem/opimpl.py
--- a/pypy/rpython/lltypesystem/opimpl.py
+++ b/pypy/rpython/lltypesystem/opimpl.py
@@ -355,6 +355,10 @@
assert type(b) is bool
return float(b)
+def op_cast_float_to_int(f):
+ assert type(f) is float
+ return intmask(int(f))
+
def op_cast_float_to_uint(f):
assert type(f) is float
return r_uint(long(f))
More information about the pypy-commit
mailing list