Author: Armin Rigo <ar...@tunes.org> Branch: ffi-backend Changeset: r56486:9b542e71c0cf Date: 2012-07-26 23:02 +0200 http://bitbucket.org/pypy/pypy/changeset/9b542e71c0cf/
Log: Second part of the big-endian fix. diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py --- a/pypy/module/_cffi_backend/ccallback.py +++ b/pypy/module/_cffi_backend/ccallback.py @@ -6,9 +6,10 @@ from pypy.rpython.lltypesystem import lltype, llmemory, rffi from pypy.rlib.objectmodel import compute_unique_id, keepalive_until_here from pypy.rlib import clibffi, rweakref, rgc +from pypy.rlib.rarithmetic import r_ulonglong from pypy.module._cffi_backend.cdataobj import W_CData, W_CDataApplevelOwning -from pypy.module._cffi_backend.ctypefunc import SIZE_OF_FFI_ARG +from pypy.module._cffi_backend.ctypefunc import SIZE_OF_FFI_ARG, BIG_ENDIAN from pypy.module._cffi_backend import cerrno # ____________________________________________________________ @@ -32,10 +33,12 @@ fresult = self.ctype.ctitem size = fresult.size if size > 0: + if fresult.is_primitive_integer and size < SIZE_OF_FFI_ARG: + size = SIZE_OF_FFI_ARG self.ll_error = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw', zero=True) if not space.is_w(w_error, space.w_None): - fresult.convert_from_object(self.ll_error, w_error) + convert_from_object_fficallback(fresult, self.ll_error, w_error) # self.unique_id = compute_unique_id(self) global_callback_mapping.set(self.unique_id, self) @@ -76,7 +79,7 @@ w_res = space.call(self.w_callable, space.newtuple(args_w)) # if fresult.size > 0: - fresult.convert_from_object(ll_res, w_res) + convert_from_object_fficallback(fresult, ll_res, w_res) def print_error(self, operr): space = self.space @@ -97,6 +100,44 @@ global_callback_mapping = rweakref.RWeakValueDictionary(int, W_CDataCallback) +def convert_from_object_fficallback(fresult, ll_res, w_res): + if fresult.is_primitive_integer and fresult.size < SIZE_OF_FFI_ARG: + # work work work around a libffi irregularity: for integer return + # types we have to fill at least a complete 'ffi_arg'-sized result + # buffer. + from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveSigned + if type(fresult) is W_CTypePrimitiveSigned: + # It's probably fine to always zero-extend, but you never + # know: maybe some code somewhere expects a negative + # 'short' result to be returned into EAX as a 32-bit + # negative number. Better safe than sorry. This code + # is about that case. Let's ignore this for enums. + # + # do a first conversion only to detect overflows. This + # conversion produces stuff that is otherwise ignored. + fresult.convert_from_object(ll_res, w_res) + # + # manual inlining and tweaking of + # W_CTypePrimitiveSigned.convert_from_object() in order + # to write a whole 'ffi_arg'. + from pypy.module._cffi_backend import misc + value = misc.as_long_long(fresult.space, w_res) + value = r_ulonglong(value) + misc.write_raw_integer_data(ll_res, value, SIZE_OF_FFI_ARG) + return + else: + # zero extension: fill the '*result' with zeros, and (on big- + # endian machines) correct the 'result' pointer to write to + zero = llmemory.itemoffsetof(rffi.CCHARP.TO, 0) + llmemory.raw_memclear(llmemory.cast_ptr_to_adr(ll_res) + zero, + SIZE_OF_FFI_ARG * llmemory.sizeof(lltype.Char)) + if BIG_ENDIAN: + diff = SIZE_OF_FFI_ARG - fresult.size + ll_res = rffi.ptradd(ll_res, diff) + # + fresult.convert_from_object(ll_res, w_res) + + # ____________________________________________________________ STDERR = 2 @@ -122,8 +163,9 @@ pass # In this case, we don't even know how big ll_res is. Let's assume # it is just a 'ffi_arg', and store 0 there. - llmemory.raw_memclear(llmemory.cast_ptr_to_adr(ll_res), - SIZE_OF_FFI_ARG) + zero = llmemory.itemoffsetof(rffi.CCHARP.TO, 0) + llmemory.raw_memclear(llmemory.cast_ptr_to_adr(ll_res) + zero, + SIZE_OF_FFI_ARG * llmemory.sizeof(lltype.Char)) return # try: _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit