Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r63808:e23dbce85236
Date: 2013-05-02 23:00 +0200
http://bitbucket.org/pypy/pypy/changeset/e23dbce85236/

Log:    Fix the failing tests added in f81be71175fe:

        - support for singlefloat return values

        - if the backend says it doesn't support some of the types, don't
        crash with a KeyError

        Moreover, avoids casting a real longlong temporarily into a float.
        This is frowned upon by now, because a small fraction of longlongs
        don't cast correctly to float and back.

diff --git a/rpython/jit/codewriter/jtransform.py 
b/rpython/jit/codewriter/jtransform.py
--- a/rpython/jit/codewriter/jtransform.py
+++ b/rpython/jit/codewriter/jtransform.py
@@ -1751,7 +1751,7 @@
 
     def rewrite_op_jit_ffi_save_result(self, op):
         kind = op.args[0].value
-        assert kind in ('int', 'float')
+        assert kind in ('int', 'float', 'longlong', 'singlefloat')
         return SpaceOperation('libffi_save_result_%s' % kind, op.args[1:], 
None)
 
     def rewrite_op_jit_force_virtual(self, op):
diff --git a/rpython/jit/metainterp/blackhole.py 
b/rpython/jit/metainterp/blackhole.py
--- a/rpython/jit/metainterp/blackhole.py
+++ b/rpython/jit/metainterp/blackhole.py
@@ -1351,24 +1351,39 @@
     def bhimpl_ll_read_timestamp():
         return read_timestamp()
 
-    @arguments("cpu", "i", "i", "i")
-    def bhimpl_libffi_save_result_int(self, cif_description, exchange_buffer, 
result):
-        ARRAY = lltype.Ptr(rffi.CArray(lltype.Signed))
-        cif_description = self.cast_int_to_ptr(cif_description, 
CIF_DESCRIPTION_P)
-        exchange_buffer = self.cast_int_to_ptr(exchange_buffer, rffi.CCHARP)
+    def _libffi_save_result(self, cif_description, exchange_buffer, result):
+        ARRAY = lltype.Ptr(rffi.CArray(lltype.typeOf(result)))
+        cast_int_to_ptr = self.cpu.cast_int_to_ptr
+        cif_description = cast_int_to_ptr(cif_description, CIF_DESCRIPTION_P)
+        exchange_buffer = cast_int_to_ptr(exchange_buffer, rffi.CCHARP)
         #
         data_out = rffi.ptradd(exchange_buffer, 
cif_description.exchange_result)
         rffi.cast(ARRAY, data_out)[0] = result
+    _libffi_save_result._annspecialcase_ = 'specialize:argtype(3)'
 
-    @arguments("cpu", "i", "i", "f")
-    def bhimpl_libffi_save_result_float(self, cif_description, 
exchange_buffer, result):
+    @arguments("self", "i", "i", "i")
+    def bhimpl_libffi_save_result_int(self, cif_description,
+                                      exchange_buffer, result):
+        self._libffi_save_result(cif_description, exchange_buffer, result)
+
+    @arguments("self", "i", "i", "f")
+    def bhimpl_libffi_save_result_float(self, cif_description,
+                                        exchange_buffer, result):
         result = longlong.getrealfloat(result)
-        ARRAY = lltype.Ptr(rffi.CArray(lltype.Float))
-        cif_description = self.cast_int_to_ptr(cif_description, 
CIF_DESCRIPTION_P)
-        exchange_buffer = self.cast_int_to_ptr(exchange_buffer, rffi.CCHARP)
-        #
-        data_out = rffi.ptradd(exchange_buffer, 
cif_description.exchange_result)
-        rffi.cast(ARRAY, data_out)[0] = result
+        self._libffi_save_result(cif_description, exchange_buffer, result)
+
+    @arguments("self", "i", "i", "f")
+    def bhimpl_libffi_save_result_longlong(self, cif_description,
+                                           exchange_buffer, result):
+        # 32-bit only: 'result' is here a LongLong
+        assert longlong.is_longlong(lltype.typeOf(result))
+        self._libffi_save_result(cif_description, exchange_buffer, result)
+
+    @arguments("self", "i", "i", "i")
+    def bhimpl_libffi_save_result_singlefloat(self, cif_description,
+                                              exchange_buffer, result):
+        result = longlong.int2singlefloat(result)
+        self._libffi_save_result(cif_description, exchange_buffer, result)
 
 
     # ----------
diff --git a/rpython/jit/metainterp/pyjitpl.py 
b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -1190,8 +1190,8 @@
         return self.metainterp.execute_and_record(rop.READ_TIMESTAMP, None)
 
     @arguments("box", "box", "box")
-    def opimpl_libffi_save_result_int(self, box_cif_description, 
box_exchange_buffer,
-                                      box_result):
+    def _opimpl_libffi_save_result(self, box_cif_description,
+                                   box_exchange_buffer, box_result):
         from rpython.rtyper.lltypesystem import llmemory
         from rpython.rlib.jit_libffi import CIF_DESCRIPTION_P
         from rpython.jit.backend.llsupport.ffisupport import get_arg_descr
@@ -1208,10 +1208,14 @@
             assert ofs % itemsize == 0     # alignment check (result)
             self.metainterp.history.record(rop.SETARRAYITEM_RAW,
                                            [box_exchange_buffer,
-                                            ConstInt(ofs // itemsize), 
box_result],
+                                            ConstInt(ofs // itemsize),
+                                            box_result],
                                            None, descr)
 
-    opimpl_libffi_save_result_float = opimpl_libffi_save_result_int
+    opimpl_libffi_save_result_int         = _opimpl_libffi_save_result
+    opimpl_libffi_save_result_float       = _opimpl_libffi_save_result
+    opimpl_libffi_save_result_longlong    = _opimpl_libffi_save_result
+    opimpl_libffi_save_result_singlefloat = _opimpl_libffi_save_result
 
     # ------------------------------
 
diff --git a/rpython/jit/metainterp/test/support.py 
b/rpython/jit/metainterp/test/support.py
--- a/rpython/jit/metainterp/test/support.py
+++ b/rpython/jit/metainterp/test/support.py
@@ -14,7 +14,10 @@
 
 
 def _get_jitcodes(testself, CPUClass, func, values, type_system,
-                  supports_longlong=False, translationoptions={}, **kwds):
+                  supports_floats=True,
+                  supports_longlong=False,
+                  supports_singlefloats=False,
+                  translationoptions={}, **kwds):
     from rpython.jit.codewriter import support
 
     class FakeJitCell(object):
@@ -68,8 +71,9 @@
     cw.debug = True
     testself.cw = cw
     policy = JitPolicy()
-    policy.set_supports_floats(True)
+    policy.set_supports_floats(supports_floats)
     policy.set_supports_longlong(supports_longlong)
+    policy.set_supports_singlefloats(supports_singlefloats)
     graphs = cw.find_all_graphs(policy)
     if kwds.get("backendopt"):
         backend_optimizations(rtyper.annotator.translator, graphs=graphs)
diff --git a/rpython/jit/metainterp/test/test_fficall.py 
b/rpython/jit/metainterp/test/test_fficall.py
--- a/rpython/jit/metainterp/test/test_fficall.py
+++ b/rpython/jit/metainterp/test/test_fficall.py
@@ -5,7 +5,7 @@
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rtyper.annlowlevel import llhelper
 from rpython.jit.metainterp.test.support import LLJitMixin
-from rpython.jit.codewriter.longlong import is_longlong
+from rpython.jit.codewriter.longlong import is_longlong, is_64_bit
 from rpython.rlib import jit
 from rpython.rlib import jit_libffi
 from rpython.rlib.jit_libffi import (types, CIF_DESCRIPTION, FFI_TYPE_PP,
@@ -45,7 +45,12 @@
 
 class FfiCallTests(object):
 
-    def _run(self, atypes, rtype, avalues, rvalue, 
expected_call_release_gil=1):
+    def _run(self, atypes, rtype, avalues, rvalue,
+             expected_call_release_gil=1,
+             supports_floats=True,
+             supports_longlong=True,
+             supports_singlefloats=True):
+
         cif_description = get_description(atypes, rtype)
 
         def verify(*args):
@@ -100,17 +105,30 @@
                 data = rffi.ptradd(exbuf, ofs)
                 res = rffi.cast(lltype.Ptr(TYPE), data)[0]
             lltype.free(exbuf, flavor='raw')
+            if lltype.typeOf(res) is lltype.SingleFloat:
+                res = float(res)
             return res
 
+        def matching_result(res, rvalue):
+            if rvalue is None:
+                return res == 654321
+            if isinstance(rvalue, r_singlefloat):
+                rvalue = float(rvalue)
+            return res == rvalue
+
         with FakeFFI(fake_call_impl_any):
             res = f()
-            assert res == rvalue or (res, rvalue) == (654321, None)
-            res = self.interp_operations(f, [])
+            assert matching_result(res, rvalue)
+            res = self.interp_operations(f, [],
+                            supports_floats = supports_floats,
+                          supports_longlong = supports_longlong,
+                      supports_singlefloats = supports_singlefloats)
             if is_longlong(FUNC.RESULT):
-                # longlongs are passed around as floats inside the JIT, we
-                # need to convert it back before checking the value
+                # longlongs are returned as floats, but that's just
+                # an inconvenience of interp_operations().  Normally both
+                # longlong and floats are passed around as longlongs.
                 res = float2longlong(res)
-            assert res == rvalue or (res, rvalue) == (654321, None)
+            assert matching_result(res, rvalue)
             self.check_operations_history(call_may_force=0,
                                           
call_release_gil=expected_call_release_gil)
 
@@ -123,22 +141,24 @@
                       [-123456*j for j in range(i)],
                       -42434445)
 
-    def test_simple_call_float(self):
-        self._run([types.double] * 2, types.double, [45.6, 78.9], -4.2)
+    def test_simple_call_float(self, **kwds):
+        self._run([types.double] * 2, types.double, [45.6, 78.9], -4.2, **kwds)
 
-    def test_simple_call_longlong(self):
+    def test_simple_call_longlong(self, **kwds):
         maxint32 = 2147483647
         a = r_longlong(maxint32) + 1
         b = r_longlong(maxint32) + 2
-        self._run([types.slonglong] * 2, types.slonglong, [a, b], a)
+        self._run([types.slonglong] * 2, types.slonglong, [a, b], a, **kwds)
 
     def test_simple_call_singlefloat_args(self):
-        self._run([types.float] * 2, types.double, [r_singlefloat(10.5),
-                                                    r_singlefloat(31.5)], -4.5)
+        self._run([types.float] * 2, types.double,
+                  [r_singlefloat(10.5), r_singlefloat(31.5)],
+                  -4.5)
 
-    def test_simple_call_singlefloat(self):
-        self._run([types.float] * 2, types.float, [r_singlefloat(10.5),
-                                                   r_singlefloat(31.5)], -4.5)
+    def test_simple_call_singlefloat(self, **kwds):
+        self._run([types.float] * 2, types.float,
+                  [r_singlefloat(10.5), r_singlefloat(31.5)],
+                  r_singlefloat(-4.5), **kwds)
 
     def test_simple_call_longdouble(self):
         # longdouble is not supported, so we expect NOT to generate a 
call_release_gil
@@ -279,23 +299,19 @@
 
         lltype.free(atypes, flavor='raw')
 
-    def _patch_cpuclass(self, **change):
-        def make_cpu(*args, **kwds):
-            cpu = CPUClass(*args, **kwds)
-            for key, value in change.items():
-                setattr(cpu, key, value)
-            return cpu
-        CPUClass = self.CPUClass
-        self.CPUClass = make_cpu
-
     def test_simple_call_float_unsupported(self):
-        self._patch_cpuclass(supports_floats=False)
-        self.test_simple_call_float()
+        self.test_simple_call_float(supports_floats=False,
+                                    expected_call_release_gil=0)
 
     def test_simple_call_longlong_unsupported(self):
-        self._patch_cpuclass(supports_longlong=False)
-        self.test_simple_call_longlong()
+        self.test_simple_call_longlong(supports_longlong=False,
+                                       expected_call_release_gil=is_64_bit)
 
     def test_simple_call_singlefloat_unsupported(self):
-        self._patch_cpuclass(supports_singlefloats=False)
-        self.test_simple_call_singlefloat()
+        self.test_simple_call_singlefloat(supports_singlefloats=False,
+                                          expected_call_release_gil=0)
+
+    def test_simple_call_float_even_if_other_unsupported(self):
+        self.test_simple_call_float(supports_longlong=False,
+                                    supports_singlefloats=False)
+        # this is the default:      expected_call_release_gil=1
diff --git a/rpython/rlib/jit_libffi.py b/rpython/rlib/jit_libffi.py
--- a/rpython/rlib/jit_libffi.py
+++ b/rpython/rlib/jit_libffi.py
@@ -2,6 +2,7 @@
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rtyper.extregistry import ExtRegistryEntry
 from rpython.rlib import clibffi, jit
+from rpython.rlib.rarithmetic import r_longlong, r_singlefloat
 from rpython.rlib.nonconst import NonConstant
 
 
@@ -107,12 +108,14 @@
     reskind = types.getkind(cif_description.rtype)
     if reskind == 'v':
         jit_ffi_call_impl_void(cif_description, func_addr, exchange_buffer)
-    elif reskind == 'f' or reskind == 'L': # L is for longlongs, on 32bit
-        result = jit_ffi_call_impl_float(cif_description, func_addr, 
exchange_buffer)
-        jit_ffi_save_result('float', cif_description, exchange_buffer, result)
     elif reskind == 'i' or reskind == 'u':
-        result = jit_ffi_call_impl_int(cif_description, func_addr, 
exchange_buffer)
-        jit_ffi_save_result('int', cif_description, exchange_buffer, result)
+        _do_ffi_call_int(cif_description, func_addr, exchange_buffer)
+    elif reskind == 'f':
+        _do_ffi_call_float(cif_description, func_addr, exchange_buffer)
+    elif reskind == 'L': # L is for longlongs, on 32bit
+        _do_ffi_call_longlong(cif_description, func_addr, exchange_buffer)
+    elif reskind == 'S': # SingleFloat
+        _do_ffi_call_singlefloat(cif_description, func_addr, exchange_buffer)
     else:
         # the result kind is not supported: we disable the jit_ffi_call
         # optimization by calling directly jit_ffi_call_impl_any, so the JIT
@@ -123,6 +126,30 @@
         jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer)
 
 
+def _do_ffi_call_int(cif_description, func_addr, exchange_buffer):
+    result = jit_ffi_call_impl_int(cif_description, func_addr,
+                                   exchange_buffer)
+    jit_ffi_save_result('int', cif_description, exchange_buffer, result)
+
+def _do_ffi_call_float(cif_description, func_addr, exchange_buffer):
+    # a separate function in case the backend doesn't support floats
+    result = jit_ffi_call_impl_float(cif_description, func_addr,
+                                     exchange_buffer)
+    jit_ffi_save_result('float', cif_description, exchange_buffer, result)
+
+def _do_ffi_call_longlong(cif_description, func_addr, exchange_buffer):
+    # a separate function in case the backend doesn't support longlongs
+    result = jit_ffi_call_impl_longlong(cif_description, func_addr,
+                                        exchange_buffer)
+    jit_ffi_save_result('longlong', cif_description, exchange_buffer, result)
+
+def _do_ffi_call_singlefloat(cif_description, func_addr, exchange_buffer):
+    # a separate function in case the backend doesn't support singlefloats
+    result = jit_ffi_call_impl_singlefloat(cif_description, func_addr,
+                                           exchange_buffer)
+    jit_ffi_save_result('singlefloat', cif_description, exchange_buffer,result)
+
+
 # we must return a NonConstant else we get the constant -1 as the result of
 # the flowgraph, and the codewriter does not produce a box for the
 # result. Note that when not-jitted, the result is unused, but when jitted the
@@ -139,6 +166,16 @@
     return NonConstant(-1.0)
 
 @jit.oopspec("libffi_call(cif_description,func_addr,exchange_buffer)")
+def jit_ffi_call_impl_longlong(cif_description, func_addr, exchange_buffer):
+    jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer)
+    return r_longlong(-1)
+
[email protected]("libffi_call(cif_description,func_addr,exchange_buffer)")
+def jit_ffi_call_impl_singlefloat(cif_description, func_addr, exchange_buffer):
+    jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer)
+    return r_singlefloat(-1.0)
+
[email protected]("libffi_call(cif_description,func_addr,exchange_buffer)")
 def jit_ffi_call_impl_void(cif_description, func_addr, exchange_buffer):
     jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer)
     return None
@@ -175,7 +212,7 @@
     def compute_result_annotation(self, kind_s, *args_s):
         from rpython.annotator import model as annmodel
         assert isinstance(kind_s, annmodel.SomeString)
-        assert kind_s.const in ('int', 'float')
+        assert kind_s.const in ('int', 'float', 'longlong', 'singlefloat')
 
     def specialize_call(self, hop):
         hop.exception_cannot_occur()
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to