[pypy-svn] r78179 - in pypy/trunk/pypy: module/_ffi rlib rlib/test

antocuni at codespeak.net antocuni at codespeak.net
Thu Oct 21 17:30:46 CEST 2010


Author: antocuni
Date: Thu Oct 21 17:30:45 2010
New Revision: 78179

Modified:
   pypy/trunk/pypy/module/_ffi/interp_ffi.py
   pypy/trunk/pypy/rlib/libffi.py
   pypy/trunk/pypy/rlib/test/test_libffi.py
Log:
(antocuni, arigo around): finally fix test_unsigned_short_arguments on 64
bits, by handling all the possible cases separately.



Modified: pypy/trunk/pypy/module/_ffi/interp_ffi.py
==============================================================================
--- pypy/trunk/pypy/module/_ffi/interp_ffi.py	(original)
+++ pypy/trunk/pypy/module/_ffi/interp_ffi.py	Thu Oct 21 17:30:45 2010
@@ -89,11 +89,9 @@
         argchain = self.build_argchain(space, self.func.argtypes, args_w)
         reskind = libffi.types.getkind(self.func.restype)
         if reskind == 'i':
-            intres = self.func.call(argchain, rffi.LONG)
-            return space.wrap(intres)
+            return self._call_int(space, argchain)
         elif reskind == 'u':
-            intres = self.func.call(argchain, rffi.ULONG)
-            return space.wrap(intres)
+            return self._call_uint(space, argchain)
         elif reskind == 'f':
             floatres = self.func.call(argchain, rffi.DOUBLE)
             return space.wrap(floatres)
@@ -102,6 +100,58 @@
             assert voidres is None
             return space.w_None
 
+    def _call_int(self, space, argchain):
+        # if the declared return type of the function is smaller than LONG,
+        # the result buffer may contains garbage in its higher bits.  To get
+        # the correct value, and to be sure to handle the signed/unsigned case
+        # correctly, we need to cast the result to the correct type.  After
+        # that, we cast it back to LONG, because this is what we want to pass
+        # to space.wrap in order to get a nice applevel <int>.
+        #
+        restype = self.func.restype
+        call = self.func.call
+        if restype is libffi.types.slong:
+            intres = call(argchain, rffi.LONG)
+        elif restype is libffi.types.sint:
+            intres = rffi.cast(rffi.LONG, call(argchain, rffi.INT))
+        elif restype is libffi.types.sshort:
+            intres = rffi.cast(rffi.LONG, call(argchain, rffi.SHORT))
+        elif restype is libffi.types.schar:
+            intres = rffi.cast(rffi.LONG, call(argchain, rffi.SIGNEDCHAR))
+        else:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap('Unsupported restype'))
+        return space.wrap(intres)
+
+    def _call_uint(self, space, argchain):
+        # the same comment as above apply. Moreover, we need to be careful
+        # when the return type is ULONG, because the value might not fit into
+        # a signed LONG: this is the only case in which we cast the result to
+        # something different than LONG; as a result, the applevel value will
+        # be a <long>.
+        #
+        # Note that we check for ULONG before UINT: this is needed on 32bit
+        # machines, where they are they same: if we checked for UINT before
+        # ULONG, we would cast to the wrong type.  Note that this also means
+        # that on 32bit the UINT case will never be entered (because it is
+        # handled by the ULONG case).
+        restype = self.func.restype
+        call = self.func.call
+        if restype is libffi.types.ulong:
+            # special case
+            uintres = call(argchain, rffi.ULONG)
+            return space.wrap(uintres)
+        elif restype is libffi.types.uint:
+            intres = rffi.cast(rffi.LONG, call(argchain, rffi.UINT))
+        elif restype is libffi.types.ushort:
+            intres = rffi.cast(rffi.LONG, call(argchain, rffi.USHORT))
+        elif restype is libffi.types.uchar:
+            intres = rffi.cast(rffi.LONG, call(argchain, rffi.UCHAR))
+        else:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap('Unsupported restype'))
+        return space.wrap(intres)
+
     @unwrap_spec('self', ObjSpace)
     def getaddr(self, space):
         """

Modified: pypy/trunk/pypy/rlib/libffi.py
==============================================================================
--- pypy/trunk/pypy/rlib/libffi.py	(original)
+++ pypy/trunk/pypy/rlib/libffi.py	Thu Oct 21 17:30:45 2010
@@ -188,9 +188,6 @@
         #
         if _fits_into_long(RESULT):
             res = self._do_call_int(self.funcsym, ll_args)
-            if self.restype.c_size < types.slong.c_size:
-                # mask res to keep only the bits we are interested in
-                res &= ~(-1 << self.restype.c_size*8)
         elif RESULT is rffi.DOUBLE:
             return self._do_call_float(self.funcsym, ll_args)
         elif RESULT is lltype.Void:

Modified: pypy/trunk/pypy/rlib/test/test_libffi.py
==============================================================================
--- pypy/trunk/pypy/rlib/test/test_libffi.py	(original)
+++ pypy/trunk/pypy/rlib/test/test_libffi.py	Thu Oct 21 17:30:45 2010
@@ -182,9 +182,7 @@
         """
         libfoo = self.get_libfoo()
         func = (libfoo, 'sum_xy_us', [types.ushort, types.ushort], types.ushort)
-        # the ULONG in the next line is not a typo: we really want to test
-        # that we get the correct value even if we cast it to a larger type
-        res = self.call(func, [32000, 8000], rffi.ULONG)
+        res = self.call(func, [32000, 8000], rffi.USHORT)
         assert res == 40000
 
 



More information about the Pypy-commit mailing list