[pypy-commit] pypy ppc-jit-backend: fix an issue in clibffi that is triggered on big endian platforms due to the byte order when casting a larger data type to smaller one to be passed to a function called through ffi
bivab
noreply at buildbot.pypy.org
Wed Nov 9 16:26:22 CET 2011
Author: David Schneider <david.schneider at picle.org>
Branch: ppc-jit-backend
Changeset: r49020:1c63c71d3b29
Date: 2011-11-09 16:22 +0100
http://bitbucket.org/pypy/pypy/changeset/1c63c71d3b29/
Log: fix an issue in clibffi that is triggered on big endian platforms
due to the byte order when casting a larger data type to smaller one
to be passed to a function called through ffi
diff --git a/pypy/rlib/clibffi.py b/pypy/rlib/clibffi.py
--- a/pypy/rlib/clibffi.py
+++ b/pypy/rlib/clibffi.py
@@ -30,6 +30,9 @@
_MAC_OS = platform.name == "darwin"
_FREEBSD_7 = platform.name == "freebsd7"
+_LITTLE_ENDIAN = sys.byteorder == 'little'
+_BIG_ENDIAN = sys.byteorder == 'big'
+
if _WIN32:
from pypy.rlib import rwin32
@@ -337,15 +340,46 @@
return TYPE_MAP[tp]
cast_type_to_ffitype._annspecialcase_ = 'specialize:memo'
-def push_arg_as_ffiptr(ffitp, arg, ll_buf):
+def push_arg_as_ffiptr_base(ffitp, arg, ll_buf):
+ # this is for primitive types. For structures and arrays
+ # would be something different (more dynamic)
+ # XXX is this valid in C?, for args that are larger than the size of
+ # ll_buf we write over the boundaries of the allocated char array and
+ # just keep as much bytes as we need for the target type. Maybe using
+ # memcpy would be better here. Also this
+ # only works on little endian architectures
+ TP = lltype.typeOf(arg)
+ TP_P = lltype.Ptr(rffi.CArray(TP))
+ buf = rffi.cast(TP_P, ll_buf)
+ buf[0] = arg
+push_arg_as_ffiptr_base._annspecialcase_ = 'specialize:argtype(1)'
+
+def push_arg_as_ffiptr_memcpy(ffitp, arg, ll_buf):
# this is for primitive types. For structures and arrays
# would be something different (more dynamic)
TP = lltype.typeOf(arg)
TP_P = lltype.Ptr(rffi.CArray(TP))
- buf = rffi.cast(TP_P, ll_buf)
- buf[0] = arg
-push_arg_as_ffiptr._annspecialcase_ = 'specialize:argtype(1)'
+ TP_size = rffi.sizeof(TP)
+ c_size = intmask(ffitp.c_size)
+ # if both types have the same size, we do not can directly write the
+ # value to the buffer
+ if c_size == TP_size:
+ return push_arg_as_ffiptr_base(ffitp, arg, ll_buf)
+
+ # store arg in a small box in memory
+ # and copy the relevant bytes over to the target buffer (ll_buf)
+ with lltype.scoped_alloc(TP_P.TO, TP_size) as argbuf:
+ argbuf[0] = arg
+ cargbuf = rffi.cast(rffi.CCHARP, argbuf)
+ ptr = rffi.ptradd(cargbuf, TP_size - c_size)
+ rffi.c_memcpy(ll_buf, ptr, c_size)
+push_arg_as_ffiptr_memcpy._annspecialcase_ = 'specialize:argtype(1)'
+
+if _LITTLE_ENDIAN:
+ push_arg_as_ffiptr = push_arg_as_ffiptr_base
+else:
+ push_arg_as_ffiptr = push_arg_as_ffiptr_memcpy
# type defs for callback and closure userdata
USERDATA_P = lltype.Ptr(lltype.ForwardReference())
diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py
--- a/pypy/rlib/libffi.py
+++ b/pypy/rlib/libffi.py
@@ -234,7 +234,7 @@
# It is important that there is no other operation in the middle, else
# the optimizer will fail to recognize the pattern and won't turn it
# into a fast CALL. Note that "arg = arg.next" is optimized away,
- # assuming that archain is completely virtual.
+ # assuming that argchain is completely virtual.
self = jit.promote(self)
if argchain.numargs != len(self.argtypes):
raise TypeError, 'Wrong number of arguments: %d expected, got %d' %\
diff --git a/pypy/rlib/test/test_libffi.py b/pypy/rlib/test/test_libffi.py
--- a/pypy/rlib/test/test_libffi.py
+++ b/pypy/rlib/test/test_libffi.py
@@ -179,6 +179,17 @@
res = self.call(func, [chr(20), 22], rffi.LONG)
assert res == 42
+ def test_char_args(self):
+ """
+ char sum_args(char a, char b) {
+ return a + b;
+ }
+ """
+ libfoo = self.get_libfoo()
+ func = (libfoo, 'sum_args', [types.schar, types.schar], types.schar)
+ res = self.call(func, [123, 43], rffi.CHAR)
+ assert res == chr(166)
+
def test_unsigned_short_args(self):
"""
unsigned short sum_xy_us(unsigned short x, unsigned short y)
More information about the pypy-commit
mailing list