Commits

Armin Rigo  committed 2775b12

Port the first part of the big-endian fix

  • Participants
  • Parent commits d7a65a9
  • Branches ffi-backend

Comments (0)

Files changed (4)

File pypy/module/_cffi_backend/ctypefunc.py

 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
             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)
                         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
                                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])
 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',
         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)
 

File pypy/module/_cffi_backend/ctypeobj.py

     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

File pypy/module/_cffi_backend/ctypeprim.py

 
 
 class W_CTypePrimitiveCharOrUniChar(W_CTypePrimitive):
-    pass
+    is_primitive_integer = True
 
 
 class W_CTypePrimitiveChar(W_CTypePrimitiveCharOrUniChar):
 
 
 class W_CTypePrimitiveSigned(W_CTypePrimitive):
+    is_primitive_integer = True
 
     def __init__(self, *args):
         W_CTypePrimitive.__init__(self, *args)
 
 
 class W_CTypePrimitiveUnsigned(W_CTypePrimitive):
+    is_primitive_integer = True
 
     def __init__(self, *args):
         W_CTypePrimitive.__init__(self, *args)

File pypy/rlib/clibffi.py

 
     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),
 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)