[pypy-svn] r77642 - in pypy/branch/jitffi/pypy: jit/backend/llgraph rlib rlib/test rpython/lltypesystem
antocuni at codespeak.net
antocuni at codespeak.net
Wed Oct 6 11:19:42 CEST 2010
Author: antocuni
Date: Wed Oct 6 11:19:40 2010
New Revision: 77642
Modified:
pypy/branch/jitffi/pypy/jit/backend/llgraph/llimpl.py
pypy/branch/jitffi/pypy/rlib/libffi.py
pypy/branch/jitffi/pypy/rlib/test/test_libffi.py
pypy/branch/jitffi/pypy/rpython/lltypesystem/lltype.py
Log:
add support for passing pointers as arguments to ffi calls
Modified: pypy/branch/jitffi/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/jitffi/pypy/jit/backend/llgraph/llimpl.py (original)
+++ pypy/branch/jitffi/pypy/jit/backend/llgraph/llimpl.py Wed Oct 6 11:19:40 2010
@@ -1018,6 +1018,9 @@
if isinstance(TYPE, lltype.Ptr):
if isinstance(x, (int, long, llmemory.AddressAsInt)):
x = llmemory.cast_int_to_adr(x)
+ if TYPE is rffi.VOIDP:
+ # assume that we want a "C-style" cast, without typechecking the value
+ return rffi.cast(TYPE, x)
return llmemory.cast_adr_to_ptr(x, TYPE)
elif TYPE == llmemory.Address:
if isinstance(x, (int, long, llmemory.AddressAsInt)):
Modified: pypy/branch/jitffi/pypy/rlib/libffi.py
==============================================================================
--- pypy/branch/jitffi/pypy/rlib/libffi.py (original)
+++ pypy/branch/jitffi/pypy/rlib/libffi.py Wed Oct 6 11:19:40 2010
@@ -1,5 +1,5 @@
from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.rlib.objectmodel import specialize, enforceargs
+from pypy.rlib.objectmodel import specialize, enforceargs, we_are_translated
from pypy.rlib.rarithmetic import intmask, r_uint
from pypy.rlib import jit
from pypy.rlib import clibffi
@@ -35,6 +35,8 @@
@specialize.arg(0)
def _fits_into_long(TYPE):
+ if isinstance(TYPE, lltype.Ptr):
+ return True # pointers always fits into longs
if not isinstance(TYPE, lltype.Primitive):
return False
if TYPE is lltype.Void or TYPE is rffi.FLOAT or TYPE is rffi.DOUBLE:
@@ -44,6 +46,17 @@
# ======================================================================
+ at specialize.memo()
+def _check_type(TYPE):
+ if isinstance(TYPE, lltype.Ptr):
+ if TYPE.TO._gckind != 'raw':
+ raise TypeError, "Can only push raw values to C, not 'gc'"
+ # XXX probably we should recursively check for struct fields here,
+ # lets just ignore that for now
+ if isinstance(TYPE.TO, lltype.Array) and 'nolength' not in TYPE.TO._hints:
+ raise TypeError, "Can only push to C arrays without length info"
+
+
class ArgChain(object):
first = None
last = None
@@ -52,6 +65,7 @@
@specialize.argtype(1)
def arg(self, val):
TYPE = lltype.typeOf(val)
+ _check_type(TYPE)
if _fits_into_long(TYPE):
cls = IntArg
val = rffi.cast(rffi.LONG, val)
Modified: pypy/branch/jitffi/pypy/rlib/test/test_libffi.py
==============================================================================
--- pypy/branch/jitffi/pypy/rlib/test/test_libffi.py (original)
+++ pypy/branch/jitffi/pypy/rlib/test/test_libffi.py Wed Oct 6 11:19:40 2010
@@ -25,6 +25,18 @@
floatarg = intarg.next
assert floatarg.floatval == 123.45
+ def test_wrong_args(self):
+ # so far the test passes but for the wrong reason :-), i.e. because
+ # .arg() only supports integers and floats
+ chain = ArgChain()
+ x = lltype.malloc(lltype.GcStruct('xxx'))
+ y = lltype.malloc(lltype.GcArray(rffi.LONG), 3)
+ z = lltype.malloc(lltype.Array(rffi.LONG), 4, flavor='raw')
+ py.test.raises(TypeError, "chain.arg(x)")
+ py.test.raises(TypeError, "chain.arg(y)")
+ py.test.raises(TypeError, "chain.arg(z)")
+ lltype.free(z, flavor='raw')
+
def test_library_open(self):
lib = self.get_libc()
del lib
@@ -159,3 +171,27 @@
func = (libfoo, 'many_args', [types.uchar, types.sint], types.sint)
res = self.call(func, [chr(20), 22], rffi.LONG)
assert res == 42
+
+ def test_call_time(self):
+ import time
+ libc = self.get_libc()
+ # XXX assume time_t is long
+ # XXX: on msvcr80 the name of the function is _time32, fix it in that case
+ func = (libc, 'time', [types.pointer], types.ulong)
+ LONGP = rffi.CArray(rffi.LONG)
+ null = lltype.nullptr(LONGP)
+ t0 = self.call(func, [null], rffi.LONG)
+ time.sleep(1)
+ t1 = self.call(func, [null], rffi.LONG)
+ assert t1 > t0
+ #
+ ptr_result = lltype.malloc(LONGP, 1, flavor='raw')
+ t2 = self.call(func, [ptr_result], rffi.LONG)
+ assert ptr_result[0] == t2
+ lltype.free(ptr_result, flavor='raw')
+ if self.__class__ is TestLibffiCall:
+ # the test does not make sense when run with the JIT through
+ # meta_interp, because the __del__ are not properly called (hence
+ # we "leak" memory)
+ del libc
+ assert not ALLOCATED
Modified: pypy/branch/jitffi/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/branch/jitffi/pypy/rpython/lltypesystem/lltype.py (original)
+++ pypy/branch/jitffi/pypy/rpython/lltypesystem/lltype.py Wed Oct 6 11:19:40 2010
@@ -794,6 +794,8 @@
return llmemory.cast_adr_to_ptr(value, TGT)
elif TGT == llmemory.Address and isinstance(ORIG, Ptr):
return llmemory.cast_ptr_to_adr(value)
+ elif TGT == Signed and isinstance(ORIG, Ptr) and ORIG.TO._gckind == 'raw':
+ return llmemory.cast_adr_to_int(llmemory.cast_ptr_to_adr(value), 'symbolic')
raise TypeError("don't know how to cast from %r to %r" % (ORIG, TGT))
More information about the Pypy-commit
mailing list