[pypy-commit] pypy ffi-backend: Port the first part of the big-endian fix

arigo noreply at buildbot.pypy.org
Thu Jul 26 22:33:47 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: ffi-backend
Changeset: r56485:2775b12955ba
Date: 2012-07-26 22:33 +0200
http://bitbucket.org/pypy/pypy/changeset/2775b12955ba/

Log:	Port the first part of the big-endian fix

diff --git a/pypy/module/_cffi_backend/ctypefunc.py b/pypy/module/_cffi_backend/ctypefunc.py
--- a/pypy/module/_cffi_backend/ctypefunc.py
+++ b/pypy/module/_cffi_backend/ctypefunc.py
@@ -2,6 +2,7 @@
 Function pointers.
 """
 
+import sys
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
 from pypy.rlib import jit, clibffi
@@ -98,7 +99,7 @@
             cif_descr = self.cif_descr
 
         size = cif_descr.exchange_size
-        mustfree_count_plus_1 = 0
+        mustfree_max_plus_1 = 0
         buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw')
         try:
             buffer_array = rffi.cast(rffi.VOIDPP, buffer)
@@ -120,7 +121,7 @@
                         rffi.cast(rffi.CCHARPP, data)[0] = raw_string
                         # set the "must free" flag to 1
                         set_mustfree_flag(data, 1)
-                        mustfree_count_plus_1 = i + 1
+                        mustfree_max_plus_1 = i + 1
                         continue   # skip the convert_from_object()
 
                     # set the "must free" flag to 0
@@ -148,14 +149,24 @@
                                buffer_array)
             cerrno.save_errno()
 
-            if isinstance(self.ctitem, W_CTypeVoid):
+            if self.ctitem.is_primitive_integer:
+                if BIG_ENDIAN:
+                    # For results of precisely these types, libffi has a
+                    # strange rule that they will be returned as a whole
+                    # 'ffi_arg' if they are smaller.  The difference
+                    # only matters on big-endian.
+                    if self.ctitem.size < SIZE_OF_FFI_ARG:
+                        diff = SIZE_OF_FFI_ARG - self.ctitem.size
+                        resultdata = rffi.ptradd(resultdata, diff)
+                w_res = self.ctitem.convert_to_object(resultdata)
+            elif isinstance(self.ctitem, W_CTypeVoid):
                 w_res = space.w_None
             elif isinstance(self.ctitem, W_CTypeStructOrUnion):
                 w_res = self.ctitem.copy_and_convert_to_object(resultdata)
             else:
                 w_res = self.ctitem.convert_to_object(resultdata)
         finally:
-            for i in range(mustfree_count_plus_1):
+            for i in range(mustfree_max_plus_1):
                 argtype = self.fargs[i]
                 if argtype.is_char_ptr_or_array:
                     data = rffi.ptradd(buffer, cif_descr.exchange_args[i])
@@ -203,7 +214,8 @@
 FFI_TYPE = clibffi.FFI_TYPE_P.TO
 FFI_TYPE_P = clibffi.FFI_TYPE_P
 FFI_TYPE_PP = clibffi.FFI_TYPE_PP
-SIZE_OF_FFI_ARG = 8     # good enough
+SIZE_OF_FFI_ARG = rffi.sizeof(clibffi.ffi_arg)
+BIG_ENDIAN = sys.byteorder == 'big'
 
 CIF_DESCRIPTION = lltype.Struct(
     'CIF_DESCRIPTION',
@@ -355,7 +367,7 @@
         cif_descr.exchange_result = exchange_offset
 
         # then enough room for the result --- which means at least
-        # sizeof(ffi_arg), according to the ffi docs (this is 8).
+        # sizeof(ffi_arg), according to the ffi docs
         exchange_offset += max(rffi.getintfield(self.rtype, 'c_size'),
                                SIZE_OF_FFI_ARG)
 
diff --git a/pypy/module/_cffi_backend/ctypeobj.py b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -14,6 +14,7 @@
     cast_anything = False
     is_char_ptr_or_array = False
     is_unichar_ptr_or_array = False
+    is_primitive_integer = False
 
     def __init__(self, space, size, name, name_position):
         self.space = space
diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py
--- a/pypy/module/_cffi_backend/ctypeprim.py
+++ b/pypy/module/_cffi_backend/ctypeprim.py
@@ -70,7 +70,7 @@
 
 
 class W_CTypePrimitiveCharOrUniChar(W_CTypePrimitive):
-    pass
+    is_primitive_integer = True
 
 
 class W_CTypePrimitiveChar(W_CTypePrimitiveCharOrUniChar):
@@ -138,6 +138,7 @@
 
 
 class W_CTypePrimitiveSigned(W_CTypePrimitive):
+    is_primitive_integer = True
 
     def __init__(self, *args):
         W_CTypePrimitive.__init__(self, *args)
@@ -173,6 +174,7 @@
 
 
 class W_CTypePrimitiveUnsigned(W_CTypePrimitive):
+    is_primitive_integer = True
 
     def __init__(self, *args):
         W_CTypePrimitive.__init__(self, *args)
diff --git a/pypy/rlib/clibffi.py b/pypy/rlib/clibffi.py
--- a/pypy/rlib/clibffi.py
+++ b/pypy/rlib/clibffi.py
@@ -157,6 +157,7 @@
 
     size_t = rffi_platform.SimpleType("size_t", rffi.ULONG)
     ffi_abi = rffi_platform.SimpleType("ffi_abi", rffi.USHORT)
+    ffi_arg = rffi_platform.SimpleType("ffi_arg", lltype.Signed)
 
     ffi_type = rffi_platform.Struct('ffi_type', [('size', rffi.ULONG),
                                                  ('alignment', rffi.USHORT),
@@ -202,6 +203,7 @@
 FFI_TYPE_P.TO.become(cConfig.ffi_type)
 size_t = cConfig.size_t
 ffi_abi = cConfig.ffi_abi
+ffi_arg = cConfig.ffi_arg
 
 for name in type_names:
     locals()[name] = configure_simple_type(name)


More information about the pypy-commit mailing list