[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