[pypy-svn] r76012 - in pypy/trunk/pypy/jit/codewriter: . test
arigo at codespeak.net
arigo at codespeak.net
Thu Jul 8 11:32:49 CEST 2010
Author: arigo
Date: Thu Jul 8 11:32:47 2010
New Revision: 76012
Modified:
pypy/trunk/pypy/jit/codewriter/jtransform.py
pypy/trunk/pypy/jit/codewriter/test/test_flatten.py
Log:
Full support for force_cast. Messy test.
Modified: pypy/trunk/pypy/jit/codewriter/jtransform.py
==============================================================================
--- pypy/trunk/pypy/jit/codewriter/jtransform.py (original)
+++ pypy/trunk/pypy/jit/codewriter/jtransform.py Thu Jul 8 11:32:47 2010
@@ -702,15 +702,40 @@
raise NotImplementedError("cast_ptr_to_int")
def rewrite_op_force_cast(self, op):
- from pypy.rpython.lltypesystem.rffi import size_and_sign
+ from pypy.rpython.lltypesystem.rffi import size_and_sign, sizeof
from pypy.rlib.rarithmetic import intmask
assert not self._is_gc(op.args[0])
size1, unsigned1 = size_and_sign(op.args[0].concretetype)
size2, unsigned2 = size_and_sign(op.result.concretetype)
- if size1 == size2 and unsigned1 == unsigned2:
- return
- raise NotImplementedError("cast not supported yet: %s" % (op, ))
-
+ if size2 >= sizeof(lltype.Signed):
+ return # the target type is LONG or ULONG
+ #
+ def bounds(size, unsigned):
+ if unsigned:
+ return 0, 1<<(8*size)
+ else:
+ return -(1<<(8*size-1)), 1<<(8*size-1)
+ min1, max1 = bounds(size1, unsigned1)
+ min2, max2 = bounds(size2, unsigned2)
+ if min2 <= min1 <= max1 <= max2:
+ return # the target type includes the source range
+ #
+ result = []
+ v1 = op.args[0]
+ if min2:
+ c_min2 = Constant(min2, lltype.Signed)
+ v2 = Variable(); v2.concretetype = lltype.Signed
+ result.append(SpaceOperation('int_sub', [v1, c_min2], v2))
+ else:
+ v2 = v1
+ c_mask = Constant(int((1<<(8*size2))-1), lltype.Signed)
+ v3 = Variable(); v3.concretetype = lltype.Signed
+ result.append(SpaceOperation('int_and', [v2, c_mask], v3))
+ if min2:
+ result.append(SpaceOperation('int_add', [v3, c_min2], op.result))
+ else:
+ result[-1].result = op.result
+ return result
# ----------
# Renames, from the _old opname to the _new one.
Modified: pypy/trunk/pypy/jit/codewriter/test/test_flatten.py
==============================================================================
--- pypy/trunk/pypy/jit/codewriter/test/test_flatten.py (original)
+++ pypy/trunk/pypy/jit/codewriter/test/test_flatten.py Thu Jul 8 11:32:47 2010
@@ -731,25 +731,77 @@
""", transform=True)
def test_force_cast(self):
- py.test.skip("later")
from pypy.rpython.lltypesystem import rffi
- def f(n):
- c = chr(n)
- return rffi.cast(rffi.INT, c)
- self.encoding_test(f, [42], """
- int_return %i0
- """, transform=True)
- def g(n):
- return rffi.cast(rffi.UCHAR, n)
- self.encoding_test(g, [42], """
- int_and %i0, $255 -> %i1
- int_return %i1
- """, transform=True)
- def h(n):
- return rffi.cast(rffi.SCHAR, n)
- self.encoding_test(h, [42], """
- ...
- """, transform=True)
+
+ for FROM, TO, expected in [
+ (rffi.SIGNEDCHAR, rffi.SIGNEDCHAR, ""),
+ (rffi.SIGNEDCHAR, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
+ (rffi.SIGNEDCHAR, rffi.SHORT, ""),
+ (rffi.SIGNEDCHAR, rffi.USHORT, "int_and %i0, $65535 -> %i1"),
+ (rffi.SIGNEDCHAR, rffi.LONG, ""),
+ (rffi.SIGNEDCHAR, rffi.ULONG, ""),
+
+ (rffi.UCHAR, rffi.SIGNEDCHAR, """int_sub %i0, $-128 -> %i1
+ int_and %i1, $255 -> %i2
+ int_add %i2, $-128 -> %i3"""),
+ (rffi.UCHAR, rffi.UCHAR, ""),
+ (rffi.UCHAR, rffi.SHORT, ""),
+ (rffi.UCHAR, rffi.USHORT, ""),
+ (rffi.UCHAR, rffi.LONG, ""),
+ (rffi.UCHAR, rffi.ULONG, ""),
+
+ (rffi.SHORT, rffi.SIGNEDCHAR, """int_sub %i0, $-128 -> %i1
+ int_and %i1, $255 -> %i2
+ int_add %i2, $-128 -> %i3"""),
+ (rffi.SHORT, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
+ (rffi.SHORT, rffi.SHORT, ""),
+ (rffi.SHORT, rffi.USHORT, "int_and %i0, $65535 -> %i1"),
+ (rffi.SHORT, rffi.LONG, ""),
+ (rffi.SHORT, rffi.ULONG, ""),
+
+ (rffi.USHORT, rffi.SIGNEDCHAR, """int_sub %i0, $-128 -> %i1
+ int_and %i1, $255 -> %i2
+ int_add %i2, $-128 -> %i3"""),
+ (rffi.USHORT, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
+ (rffi.USHORT, rffi.SHORT, """int_sub %i0, $-32768 -> %i1
+ int_and %i1, $65535 -> %i2
+ int_add %i2, $-32768 -> %i3"""),
+ (rffi.USHORT, rffi.USHORT, ""),
+ (rffi.USHORT, rffi.LONG, ""),
+ (rffi.USHORT, rffi.ULONG, ""),
+
+ (rffi.LONG, rffi.SIGNEDCHAR, """int_sub %i0, $-128 -> %i1
+ int_and %i1, $255 -> %i2
+ int_add %i2, $-128 -> %i3"""),
+ (rffi.LONG, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
+ (rffi.LONG, rffi.SHORT, """int_sub %i0, $-32768 -> %i1
+ int_and %i1, $65535 -> %i2
+ int_add %i2, $-32768 -> %i3"""),
+ (rffi.LONG, rffi.USHORT, "int_and %i0, $65535 -> %i1"),
+ (rffi.LONG, rffi.LONG, ""),
+ (rffi.LONG, rffi.ULONG, ""),
+
+ (rffi.ULONG, rffi.SIGNEDCHAR, """int_sub %i0, $-128 -> %i1
+ int_and %i1, $255 -> %i2
+ int_add %i2, $-128 -> %i3"""),
+ (rffi.ULONG, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
+ (rffi.ULONG, rffi.SHORT, """int_sub %i0, $-32768 -> %i1
+ int_and %i1, $65535 -> %i2
+ int_add %i2, $-32768 -> %i3"""),
+ (rffi.ULONG, rffi.USHORT, "int_and %i0, $65535 -> %i1"),
+ (rffi.ULONG, rffi.LONG, ""),
+ (rffi.ULONG, rffi.ULONG, ""),
+ ]:
+ expected = [s.strip() for s in expected.splitlines()]
+ check_force_cast(FROM, TO, expected, 42)
+ check_force_cast(FROM, TO, expected, -42)
+ expected.append('int_return %i' + str(len(expected)))
+ expected = '\n'.join(expected)
+ #
+ def f(n):
+ return rffi.cast(TO, n)
+ self.encoding_test(f, [rffi.cast(FROM, 42)], expected,
+ transform=True)
def test_force_cast_pointer(self):
from pypy.rpython.lltypesystem import rffi
@@ -758,3 +810,27 @@
self.encoding_test(h, [lltype.nullptr(rffi.CCHARP.TO)], """
int_return %i0
""", transform=True)
+
+
+def check_force_cast(FROM, TO, operations, value):
+ """Check that the test is correctly written..."""
+ from pypy.rpython.lltypesystem import rffi
+ import re
+ r = re.compile('(\w+) \%i\d, \$(-?\d+)')
+ #
+ value = rffi.cast(FROM, value)
+ value = rffi.cast(lltype.Signed, value)
+ #
+ expected_value = rffi.cast(TO, value)
+ expected_value = rffi.cast(lltype.Signed, expected_value)
+ #
+ for op in operations:
+ match = r.match(op)
+ assert match, "line %r does not match regexp" % (op,)
+ opname = match.group(1)
+ if opname == 'int_add': value += int(match.group(2))
+ elif opname == 'int_sub': value -= int(match.group(2))
+ elif opname == 'int_and': value &= int(match.group(2))
+ else: assert 0, opname
+ #
+ assert rffi.cast(lltype.Signed, value) == expected_value
More information about the Pypy-commit
mailing list