[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