[pypy-svn] commit/pypy: 2 new changesets

Bitbucket commits-noreply at bitbucket.org
Mon Dec 20 18:58:24 CET 2010


2 new changesets in pypy:

http://bitbucket.org/pypy/pypy/changeset/eebf821bae16/
changeset:   r40150:eebf821bae16
branch:      jitypes2
user:        antocuni
date:        2010-12-20 13:55:11
summary:     implement getaddressindll and expose it at applevel
affected #:  3 files (798 bytes)

--- a/pypy/module/_ffi/interp_ffi.py	Mon Dec 20 13:16:48 2010 +0100
+++ b/pypy/module/_ffi/interp_ffi.py	Mon Dec 20 13:55:11 2010 +0100
@@ -209,6 +209,16 @@
             
         return W_FuncPtr(func)
 
+    @unwrap_spec('self', ObjSpace, str)
+    def getaddressindll(self, space, name):
+        try:
+            address_as_uint = rffi.cast(lltype.Unsigned,
+                                        self.cdll.getaddressindll(name))
+        except KeyError:
+            raise operationerrfmt(space.w_ValueError,
+                                  "No symbol %s found in library %s", name, self.name)
+        return space.wrap(address_as_uint)
+
 
 @unwrap_spec(ObjSpace, W_Root, str)
 def descr_new_cdll(space, w_type, name):
@@ -219,6 +229,7 @@
     'CDLL',
     __new__     = interp2app(descr_new_cdll),
     getfunc     = interp2app(W_CDLL.getfunc),
+    getaddressindll = interp2app(W_CDLL.getaddressindll),
     )
 
 # ========================================================================


--- a/pypy/module/_ffi/test/test__ffi.py	Mon Dec 20 13:16:48 2010 +0100
+++ b/pypy/module/_ffi/test/test__ffi.py	Mon Dec 20 13:55:11 2010 +0100
@@ -77,7 +77,14 @@
         libm = CDLL(self.libm_name)
         pow = libm.getfunc('pow', [types.double, types.double], types.double)
         assert pow.getaddr() == self.pow_addr
-        
+
+    def test_getaddressindll(self):
+        import sys
+        from _ffi import CDLL, types
+        libm = CDLL(self.libm_name)
+        pow_addr = libm.getaddressindll('pow')
+        assert pow_addr == self.pow_addr & (sys.maxint*2-1)
+
     def test_int_args(self):
         """
             int sum_xy(int x, int y)


--- a/pypy/rlib/libffi.py	Mon Dec 20 13:16:48 2010 +0100
+++ b/pypy/rlib/libffi.py	Mon Dec 20 13:55:11 2010 +0100
@@ -336,3 +336,6 @@
     def getpointer(self, name, argtypes, restype, flags=FUNCFLAG_CDECL):
         return Func(name, argtypes, restype, dlsym(self.lib, name),
                     flags=flags, keepalive=self)
+
+    def getaddressindll(self, name):
+        return dlsym(self.lib, name)


http://bitbucket.org/pypy/pypy/changeset/4788cf042dc2/
changeset:   r40151:4788cf042dc2
branch:      jitypes2
user:        antocuni
date:        2010-12-20 18:57:47
summary:     ugly hack to support longlongs on 32bit and not having the jit to complain: we
store them as DOUBLEs (really reinterpreting the bit pattern) and do the
conversion only around the actual ffi call.

The current version is even worse than needed because e.g. if you do a .call
with a LONGLONG result, you can get either a lltype.Signed or lltype.Float as
a result, depending if you are on 64 or 32 bit. I'll try to improve this later
affected #:  2 files (3.6 KB)

--- a/pypy/rlib/libffi.py	Mon Dec 20 13:55:11 2010 +0100
+++ b/pypy/rlib/libffi.py	Mon Dec 20 18:57:47 2010 +0100
@@ -30,6 +30,8 @@
                 setattr(cls, name, value)
         cls.slong = clibffi.cast_type_to_ffitype(rffi.LONG)
         cls.ulong = clibffi.cast_type_to_ffitype(rffi.ULONG)
+        cls.slonglong = clibffi.cast_type_to_ffitype(rffi.LONGLONG)
+        cls.ulonglong = clibffi.cast_type_to_ffitype(rffi.ULONGLONG)
         del cls._import
 
     @staticmethod
@@ -78,6 +80,7 @@
     sz = rffi.sizeof(TYPE)
     return sz <= rffi.sizeof(rffi.LONG)
 
+
 # ======================================================================
 
 @specialize.memo()
@@ -105,6 +108,8 @@
             val = rffi.cast(rffi.LONG, val)
         elif TYPE is rffi.DOUBLE:
             cls = FloatArg
+        elif TYPE in (rffi.LONGLONG, rffi.ULONGLONG):
+            raise TypeError, 'r_(u)longlong not supported by arg(), use arg_longlong()'
         elif TYPE is rffi.FLOAT:
             raise TypeError, 'r_singlefloat not supported by arg(), use arg_singlefloat()'
         else:
@@ -112,6 +117,16 @@
         self._append(cls(val))
         return self
 
+    def arg_longlong(self, val):
+        """
+        Note: this is a hack. So far, the JIT does not support long longs, so
+        you must pass it as if it were a python Float (rffi.DOUBLE).  You can
+        use the convenience functions longlong2float and float2longlong to do
+        the conversions.  Note that if you use long longs, the call won't
+        be jitted at all.
+        """
+        self._append(LongLongArg(val))
+
     def arg_singlefloat(self, val):
         """
         Note: you must pass a python Float (rffi.DOUBLE), not a r_singlefloat
@@ -154,7 +169,7 @@
 
 
 class SingleFloatArg(AbstractArg):
-    """ An argument holding a C float
+    """ An argument representing a C float (but holding a C double)
     """
 
     def __init__(self, floatval):
@@ -164,6 +179,36 @@
         func._push_single_float(self.floatval, ll_args, i)
 
 
+class LongLongArg(AbstractArg):
+    """ An argument representing a C long long (but holding a C double)
+    """
+
+    def __init__(self, floatval):
+        self.floatval = floatval
+
+    def push(self, func, ll_args, i):
+        func._push_longlong(self.floatval, ll_args, i)
+
+
+DOUBLE_ARRAY_PTR = lltype.Ptr(lltype.Array(rffi.DOUBLE))
+LONGLONG_ARRAY_PTR = lltype.Ptr(lltype.Array(rffi.LONGLONG))
+def longlong2float(llval):
+    d_array = lltype.malloc(DOUBLE_ARRAY_PTR.TO, 1, flavor='raw')
+    ll_array = rffi.cast(LONGLONG_ARRAY_PTR, d_array)
+    ll_array[0] = llval
+    floatval = d_array[0]
+    lltype.free(d_array, flavor='raw')
+    return floatval
+
+def float2longlong(floatval):
+    d_array = lltype.malloc(DOUBLE_ARRAY_PTR.TO, 1, flavor='raw')
+    ll_array = rffi.cast(LONGLONG_ARRAY_PTR, d_array)
+    d_array[0] = floatval
+    llval = ll_array[0]
+    lltype.free(d_array, flavor='raw')
+    return llval
+
+
 # ======================================================================
 
 
@@ -219,6 +264,10 @@
             # XXX: even if RESULT is FLOAT, we still return a DOUBLE, else the
             # jit complains. Note that the jit is disabled in this case
             return self._do_call_single_float(self.funcsym, ll_args)
+        elif RESULT is rffi.LONGLONG:
+            # XXX: even if RESULT is LONGLONG, we still return a DOUBLE, else the
+            # jit complains. Note that the jit is disabled in this case
+            return self._do_call_longlong(self.funcsym, ll_args)
         elif RESULT is lltype.Void:
             return self._do_call_void(self.funcsym, ll_args)
         else:
@@ -256,6 +305,13 @@
     def _push_single_float(self, value, ll_args, i):
         self._push_arg(r_singlefloat(value), ll_args, i)
 
+    @jit.dont_look_inside
+    def _push_longlong(self, floatval, ll_args, i):
+        """
+        Takes a longlong represented as a python Float. It's a hack for the
+        jit, else we could not see the whole libffi module at all"""  
+        self._push_arg(float2longlong(floatval), ll_args, i)
+
     @jit.oopspec('libffi_call_int(self, funcsym, ll_args)')
     def _do_call_int(self, funcsym, ll_args):
         return self._do_call(funcsym, ll_args, rffi.LONG)
@@ -269,6 +325,11 @@
         single_res = self._do_call(funcsym, ll_args, rffi.FLOAT)
         return float(single_res)
 
+    @jit.dont_look_inside
+    def _do_call_longlong(self, funcsym, ll_args):
+        llres = self._do_call(funcsym, ll_args, rffi.LONGLONG)
+        return longlong2float(llres)
+
     @jit.oopspec('libffi_call_void(self, funcsym, ll_args)')
     def _do_call_void(self, funcsym, ll_args):
         return self._do_call(funcsym, ll_args, lltype.Void)


--- a/pypy/rlib/test/test_libffi.py	Mon Dec 20 13:55:11 2010 +0100
+++ b/pypy/rlib/test/test_libffi.py	Mon Dec 20 18:57:47 2010 +0100
@@ -2,9 +2,9 @@
 import sys
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED
-from pypy.rlib.rarithmetic import r_singlefloat
+from pypy.rlib.rarithmetic import r_singlefloat, r_longlong
 from pypy.rlib.test.test_clibffi import BaseFfiTest, get_libm_name
-from pypy.rlib.libffi import CDLL, Func, get_libc_name, ArgChain, types
+from pypy.rlib.libffi import CDLL, Func, get_libc_name, ArgChain, types, longlong2float, float2longlong
 
 class TestLibffiMisc(BaseFfiTest):
 
@@ -51,6 +51,12 @@
         del lib
         assert not ALLOCATED
 
+    def test_longlong_as_float(self):
+        maxint64 = r_longlong(9223372036854775807)
+        d = longlong2float(maxint64)
+        ll = float2longlong(d)
+        assert ll == maxint64
+        
 
 class TestLibffiCall(BaseFfiTest):
     """
@@ -113,6 +119,8 @@
         for arg in args:
             if isinstance(arg, r_singlefloat):
                 chain.arg_singlefloat(float(arg))
+            elif isinstance(arg, r_longlong):
+                chain.arg_longlong(longlong2float(arg))
             else:
                 chain.arg(arg)
         return func.call(chain, RESULT)
@@ -283,6 +291,29 @@
         expected = c_float(c_float(12.34).value + c_float(56.78).value).value
         assert res == expected
 
+    def test_longlong_args(self):
+        """
+            long long sum_xy_longlong(long long x, long long y)
+            {
+                return x+y;
+            }
+        """
+        maxint32 = 2147483647 # we cannot really go above maxint on 64 bits
+                              # (and we would not test anything, as there long
+                              # is the same as long long)
+        libfoo = self.get_libfoo()
+        func = (libfoo, 'sum_xy_longlong', [types.slonglong, types.slonglong], types.slonglong)
+        x = r_longlong(maxint32+1)
+        y = r_longlong(maxint32+2)
+        res = self.call(func, [x, y], rffi.LONGLONG, init_result=0)
+        if sys.maxint == maxint32:
+            # obscure, on 32bit it's really a long long, so it returns a
+            # DOUBLE because of the JIT hack
+            res = float2longlong(res)
+        expected = maxint32*2 + 3
+        assert res == expected
+
+
     def test_wrong_number_of_arguments(self):
         from pypy.rpython.llinterp import LLException
         libfoo = self.get_libfoo()

Repository URL: https://bitbucket.org/pypy/pypy/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.



More information about the Pypy-commit mailing list