[pypy-svn] r75026 - in pypy/branch/fast-ctypes/pypy/rlib: . test

getxsick at codespeak.net getxsick at codespeak.net
Wed Jun 2 23:29:51 CEST 2010


Author: getxsick
Date: Wed Jun  2 23:29:50 2010
New Revision: 75026

Added:
   pypy/branch/fast-ctypes/pypy/rlib/jitffi.py   (contents, props changed)
   pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py   (contents, props changed)
Log:
add pypy/rlib/jitffi module

Added: pypy/branch/fast-ctypes/pypy/rlib/jitffi.py
==============================================================================
--- (empty file)
+++ pypy/branch/fast-ctypes/pypy/rlib/jitffi.py	Wed Jun  2 23:29:50 2010
@@ -0,0 +1,79 @@
+from pypy.interpreter.error import operationerrfmt
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.typedef import TypeDef
+from pypy.rlib import rdynload
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.jit.backend.x86.runner import CPU
+from pypy.jit.metainterp.history import LoopToken, BasicFailDescr
+from pypy.jit.metainterp.history import BoxInt, BoxFloat, BoxPtr
+from pypy.jit.metainterp.resoperation import ResOperation, rop
+from pypy.jit.metainterp.typesystem import deref
+
+class CDLL(object):
+    def __init__(self, name):
+        try:
+            self.lib = rdynload.dlopen(name)
+        except libffi.DLOpenError, e:
+            raise operationerrfmt(space.w_OSError, '%s: %s', name,
+                                  e.msg or 'unspecified error')
+        self.name = name
+        self.cpu = CPU(None, None)
+
+    def call(self, func, func_args, res_type='void'):
+        # only integers are supported for now
+        assert isinstance(func_args, list)
+
+        if res_type == 'int':
+            bres = BoxInt()
+        elif res_type == 'float':
+            bres = BoxFloat()
+        elif res_type == 'ref':
+            bres = BoxPtr()
+        elif res_type == 'void':
+            bres = None
+        else:
+            raise ValueError(res_type)
+
+        try:
+            addr = rffi.cast(lltype.Signed, rdynload.dlsym(self.lib, func))
+        except KeyError:
+            raise operationerrfmt(space.w_ValueError,
+                                  "Cannot find symbol %s", func)
+        bfuncaddr = BoxInt(addr)
+
+        args_type = [ lltype.Signed for i in func_args ]
+        FPTR = lltype.Ptr(lltype.FuncType(args_type, lltype.Signed))
+        FUNC = deref(FPTR)
+        calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
+
+        bargs = [ BoxInt(x) for x in func_args ]
+        inputargs = [bfuncaddr] + bargs
+
+        oplist = [ResOperation(rop.CALL, inputargs, bres, descr=calldescr),
+                  ResOperation(rop.FINISH, [bres], None,
+                               descr=BasicFailDescr(0))]
+        looptoken = LoopToken()
+        self.cpu.compile_loop(inputargs, oplist, looptoken)
+
+        i = 0
+        for box in inputargs:
+            self.cpu.set_future_value_int(i, box.getint())
+            i += 1
+
+        res = self.cpu.execute_token(looptoken)
+        if res is oplist[-1].descr:
+            self.guard_failed = False
+        else:
+            self.guard_failed = True
+
+        if res_type == 'int':
+            r = BoxInt(self.cpu.get_latest_value_int(0)).getint()
+        elif res_type == 'float':
+            r = BoxFloat(self.cpu.get_latest_value_float(0)).getfloat()
+        elif res_type == 'ref':
+            r = BoxPtr(self.cpu.get_latest_value_ref(0)).getref()
+        elif res_type == 'void':
+            r = None
+        else:
+            raise ValueError(res_type)
+        return r

Added: pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py
==============================================================================
--- (empty file)
+++ pypy/branch/fast-ctypes/pypy/rlib/test/test_jitffi.py	Wed Jun  2 23:29:50 2010
@@ -0,0 +1,64 @@
+#from pypy.conftest import gettestobjspace
+from pypy.rlib import jitffi
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
+from pypy.translator.platform import platform
+
+import py
+
+class TestJitffi(object):
+    @staticmethod
+    def preprare_c_example():
+        from pypy.tool.udir import udir
+        c_file = udir.ensure("test_jitffi", dir=True).join("xlib.c")
+        c_file.write(py.code.Source('''
+        int add_integers(int a, int b)
+        {
+           return a+b;
+        }
+
+        float return_float(int a, int b)
+        {
+           return a+b;
+        }
+
+        int max3(int a, int b, int c)
+        {
+           int max = a;
+           if (b > max) max = b;
+           if (c > max) max = c;
+           return max;
+        }
+        '''
+        ))
+
+        symbols = ["add_integers"]
+        eci = ExternalCompilationInfo(export_symbols=symbols)
+
+        return str(platform.compile([c_file], eci, 'x', standalone=False))
+
+    def setup_class(cls):
+        #space = gettestobjspace(usemodules=('jitffi',))
+        #cls.space = space
+        #cls.w_lib_name = space.wrap(cls.preprare_c_example())
+        cls.lib_name = cls.preprare_c_example()
+
+    def test_call(self):
+        lib = jitffi.CDLL(self.lib_name)
+
+        res = lib.call('add_integers', [1, 2], 'int')
+        assert 3 == res
+        assert isinstance(res, int)
+        res = lib.call('add_integers', [-1, 2], 'int')
+        assert 1 == res
+        res = lib.call('add_integers', [0, 0], 'int')
+        assert 0 == res
+
+        res = lib.call('max3', [2, 8, 3], 'int')
+        assert 8 == res
+
+        res = lib.call('return_float', [1, 2], 'float')
+        assert 3.0 == res
+        assert isinstance(res, float)
+        #res = lib.call('return_float', [1.5, 1.2], 'float')
+        #assert 2.7 == res
+



More information about the Pypy-commit mailing list