[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