[pypy-svn] r48219 - in pypy/dist/pypy/translator/llvm: . test

rxe at codespeak.net rxe at codespeak.net
Wed Oct 31 00:48:54 CET 2007


Author: rxe
Date: Wed Oct 31 00:48:53 2007
New Revision: 48219

Modified:
   pypy/dist/pypy/translator/llvm/buildllvm.py
   pypy/dist/pypy/translator/llvm/genllvm.py
   pypy/dist/pypy/translator/llvm/modwrapper.py
   pypy/dist/pypy/translator/llvm/test/test_runtest.py
Log:
try and make the interface richer

Modified: pypy/dist/pypy/translator/llvm/buildllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/buildllvm.py	(original)
+++ pypy/dist/pypy/translator/llvm/buildllvm.py	Wed Oct 31 00:48:53 2007
@@ -5,7 +5,7 @@
 
 from pypy.translator.tool import stdoutcapture
 from pypy.translator.llvm.log import log
-from pypy.translator.llvm.modwrapper import write_ctypes_module
+from pypy.translator.llvm.modwrapper import CtypesModule
 
 def llvm_is_on_path():
     if py.path.local.sysfind("llvm-as") is None or \
@@ -153,7 +153,7 @@
 
         try:
             self.execute_cmds()
-            modname = write_ctypes_module(self.genllvm, "%s.so" % base)
+            modname = CtypesModule(self.genllvm, "%s.so" % base).create()
 
         finally:
             self.lastdir.chdir()

Modified: pypy/dist/pypy/translator/llvm/genllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/genllvm.py	(original)
+++ pypy/dist/pypy/translator/llvm/genllvm.py	Wed Oct 31 00:48:53 2007
@@ -250,7 +250,7 @@
             from pypy.translator.tool.cbuild import import_module_from_directory
             mod = import_module_from_directory(dirpath, modname)
 
-        wrap_fun = getattr(mod, 'pypy_' + self.entry_func_name + "_wrapper")
+        wrap_fun = getattr(mod, 'entrypoint')
         return mod, wrap_fun
 
     def compile_standalone(self, exe_name):

Modified: pypy/dist/pypy/translator/llvm/modwrapper.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/modwrapper.py	(original)
+++ pypy/dist/pypy/translator/llvm/modwrapper.py	Wed Oct 31 00:48:53 2007
@@ -1,3 +1,4 @@
+import py
 import ctypes
 from pypy.rpython.lltypesystem import lltype 
 
@@ -35,35 +36,50 @@
 
     return code
 
-TO_CTYPES = {lltype.Bool: "ctypes.c_int",
-             lltype.SingleFloat: "ctypes.c_float",
-             lltype.Float: "ctypes.c_double",
-             lltype.Char: "ctypes.c_char",
-             lltype.Signed: "ctypes.c_int",
-             lltype.Unsigned: "ctypes.c_uint",
-             lltype.SignedLongLong: "ctypes.c_longlong",
-             lltype.UnsignedLongLong: "ctypes.c_ulonglong",
-             lltype.Void: None
-             }
-
-def to_ctype(T):
-    if isinstance(T, lltype.Ptr):
-        return "ctypes.c_void_p"
-    else:
-        return TO_CTYPES[T]
 
-def build_lltype_to_ctypes_to_res(T):
-    identity = """
-def tores(res):
+class CtypesModule:
+    """ use ctypes to create a temporary module """
+
+    prolog = """
+import ctypes
+from os.path import join, dirname, realpath
+
+_c = ctypes.CDLL(join(dirname(realpath(__file__)), "%s"))
+
+raised = _c.__entrypoint__raised_LLVMException
+raised.argtypes = []
+raised.restype = ctypes.c_int
+
+GC_get_heap_size_wrapper = _c.GC_get_heap_size
+GC_get_heap_size_wrapper.argtypes = []
+GC_get_heap_size_wrapper.restype = ctypes.c_int
+
+startup_code = _c.ctypes_RPython_StartupCode
+startup_code.argtypes = []
+startup_code.restype = ctypes.c_int
+
+_setup = False
+
+class LLVMException(Exception):
+    pass
+
+def entrypoint(*args):
+    global _setup
+    if not _setup:
+        if not startup_code():
+            raise LLVMException("Failed to startup")
+        _setup = True
+    args = to_llargs(args)
+    result = __entrypoint__(*args)
+    if raised():
+        raise LLVMException("Exception raised")
+    return ll_to_res(result)
+
+def identity(res):
     return res
-    """
 
-    to_bool = """
-def tores(res):
+def to_bool(res):
     return bool(res)
-    """
-
-    to_str = """
 
 class Chars(ctypes.Structure):
     _fields_ = [("size", ctypes.c_int),
@@ -73,115 +89,117 @@
     _fields_ = [("hash", ctypes.c_int),
                 ("array", Chars)]
 
-def tores(res):
+def to_str(res):
     if res:
         s = ctypes.cast(res, ctypes.POINTER(STR)).contents
         return ctypes.string_at(res + (STR.array.offset + Chars.data.offset), s.array.size)
     else:
         return None
-    """
 
-    to_tuple = """
-def tores(res):
+def to_tuple(res, size, C_TYPE, action):
     if res:
-        t = ctypes.cast(res, ctypes.POINTER(%s * %s)).contents
-        return tuple(t)
+        t = ctypes.cast(res, ctypes.POINTER(C_TYPE * size)).contents
+        return tuple([action(ii) for ii in t])
     else:
         return None
-    """
-
-    to_list = """
 
-def tores(res):
+def to_list(res, C_TYPE, action):
     if res:
         size = ctypes.cast(res, ctypes.POINTER(ctypes.c_int)).contents.value
         class Array(ctypes.Structure):
             _fields_ = [("size", ctypes.c_int),
-                        ("data", %s * size)]
+                        ("data", C_TYPE * size)]
         array = ctypes.cast(res, ctypes.POINTER(Array)).contents
-        return list(array.data)
+        return [action(array.data[ii]) for ii in range(size)]
     else:
         return None
-    """
-
-    from pypy.rpython.lltypesystem.rstr import STR
-
-    if T is lltype.Bool:
-        return to_bool
-    elif isinstance(T, lltype.Ptr) and T.TO is STR:
-        return to_str
-    elif isinstance(T, lltype.Ptr) and isinstance(T.TO, lltype.Struct):
-        fields = [getattr(T.TO, name) for name in T.TO._names_without_voids()]
-        if fields:
-            F0 = fields[0]
-            for F in fields[1:]:
-                if F0 is not F:
-                    raise Exception("struct must be of same kind")
-            if F0 not in TO_CTYPES:
-                raise Exception("struct must be of primitve type")
-            
-            return to_tuple % (len(fields), TO_CTYPES[F0])
-        
-    elif isinstance(T, lltype.Ptr) and isinstance(T.TO, lltype.Array):
-        OF = T.TO.OF
-        if OF not in TO_CTYPES:
-            raise Exception("struct must be of primitve type")
-            
-        return to_list % TO_CTYPES[OF]
-    else:
-        return identity
-
-def write_ctypes_module(genllvm, dllname):
-    """ use ctypes to create a temporary module """
-
-    template = """
-import ctypes
-from os.path import join, dirname, realpath
-_c = ctypes.CDLL(join(dirname(realpath(__file__)), "%(dllname)s"))
-
-_setup = False
-
-class LLVMException(Exception):
-    pass
-
-%(name)s = _c.__entrypoint__%(name)s
-%(name)s.argtypes = %(args)s
-%(name)s.restype = %(returntype)s
-
-%(name)s_raised = _c.__entrypoint__raised_LLVMException
-%(name)s_raised.argtypes = []
-%(name)s_raised.restype = ctypes.c_int
-
-GC_get_heap_size_wrapper = _c.GC_get_heap_size
-GC_get_heap_size_wrapper.argtypes = []
-GC_get_heap_size_wrapper.restype = ctypes.c_int
-
-startup_code = _c.ctypes_RPython_StartupCode
-startup_code.argtypes = []
-startup_code.restype = ctypes.c_int
-
-def %(name)s_wrapper(*args):
-    global _setup
-    if not _setup:
-        if not startup_code():
-            raise LLVMException("Failed to startup")
-        _setup = True
-    result = %(name)s(*args)
-    if %(name)s_raised():
-        raise LLVMException("Exception raised")
-    return tores(result)
 """
 
-    basename = genllvm.filename.purebasename + '_wrapper.py'
-    modfilename = genllvm.filename.new(basename = basename)
-    name = genllvm.entrynode.ref.strip("%")
-    
-    g = genllvm.entrynode.graph  
-    rt = g.returnblock.inputargs[0].concretetype
-    returntype = to_ctype(rt)
-    inputargtypes = [TO_CTYPES[a.concretetype] for a in g.startblock.inputargs]
-    args = '[%s]' % ", ".join(inputargtypes)
+    epilog = """
+to_llargs = %(to_llargs)s
+ll_to_res = %(ll_to_res)s
+__entrypoint__ = _c.__entrypoint__%(name)s
+__entrypoint__.argtypes = %(args)s
+__entrypoint__.restype = %(returntype)s
+    """
+    def __init__(self, genllvm, dllname):
+        self.genllvm = genllvm
+        self.dllname = dllname
+        basename = self.genllvm.filename.purebasename + '_wrapper.py'
+        self.modfilename = genllvm.filename.new(basename=basename)
+        self.count = 0
+
+    def create(self):
+        self.file = open(str(self.modfilename), 'w')
+        self.file.write(self.prolog % self.dllname)
+        
+        g = self.genllvm.entrynode.graph  
+        name = "pypy_" + g.name
 
-    modfilename.write(template % locals() + build_lltype_to_ctypes_to_res(rt))
+        inputargtypes = [self.to_ctype(a.concretetype) for a in g.startblock.inputargs]
+        to_llargs = 'identity'
+        args = '[%s]' % ', '.join(inputargtypes)
 
-    return modfilename.purebasename
+        RT = g.returnblock.inputargs[0].concretetype
+        returntype, ll_to_res = self.build_lltype_to_ctypes_to_res(RT)
+        
+        self.file.write(self.epilog % locals())
+        self.file.close()
+        return self.modfilename.purebasename
+
+    def create_simple_closure(self, args, code):
+        name = 'tmpfunction_%s' % self.count
+        self.count += 1
+        self.file.write('\n')
+        self.file.write('def %s(%s): return %s' % (name, args, code))
+        self.file.write('\n')
+        return name
+
+    def build_lltype_to_ctypes_to_res(self, T):
+        from pypy.rpython.lltypesystem.rstr import STR
+
+        if T is lltype.Bool:
+            action = 'to_bool'
+
+        elif isinstance(T, lltype.Ptr) and T.TO is STR:
+            action = 'to_str'
+
+        elif isinstance(T, lltype.Ptr) and isinstance(T.TO, lltype.Struct):
+            fields = [getattr(T.TO, name) for name in T.TO._names_without_voids()]
+            if fields:
+                F0 = fields[0]
+                _c_type, _action = self.build_lltype_to_ctypes_to_res(F0)
+                action = self.create_simple_closure('res', 'to_tuple(res, %s, %s, %s)' % (len(fields), 
+                                                                                          _c_type, 
+                                                                                          _action))
+
+        elif isinstance(T, lltype.Ptr) and isinstance(T.TO, lltype.Array):
+            OF = T.TO.OF
+            _c_type, _action = self.build_lltype_to_ctypes_to_res(OF)
+            action = self.create_simple_closure('res', 'to_list(res, %s, %s)' % (_c_type, _action))
+
+        else:
+            assert not isinstance(T, lltype.Ptr)
+            action = 'identity'
+
+        c_type = self.to_ctype(T)
+        return c_type, action
+
+    def to_ctype(self, T):
+        TO_CTYPES = {lltype.Bool: "ctypes.c_byte",
+                     lltype.SingleFloat: "ctypes.c_float",
+                     lltype.Float: "ctypes.c_double",
+                     lltype.Char: "ctypes.c_char",
+                     lltype.Signed: "ctypes.c_int",
+                     lltype.Unsigned: "ctypes.c_uint",
+                     lltype.SignedLongLong: "ctypes.c_longlong",
+                     lltype.UnsignedLongLong: "ctypes.c_ulonglong",
+                     lltype.Void: None,
+                     lltype.UniChar: "ctypes.c_uint",
+                     }
+
+        if isinstance(T, lltype.Ptr):
+            return 'ctypes.c_void_p'
+        else:
+            return TO_CTYPES[T]
+ 

Modified: pypy/dist/pypy/translator/llvm/test/test_runtest.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/test/test_runtest.py	(original)
+++ pypy/dist/pypy/translator/llvm/test/test_runtest.py	Wed Oct 31 00:48:53 2007
@@ -8,3 +8,18 @@
             y = 1 + x
             return None
         assert self.interpret(fn,[1]) == None
+
+    def test_list_of_strings(self):
+        def fn():
+            return ['abc', 'def']
+        assert self.interpret(fn, []) == ['abc', 'def']
+
+    def test_list_of_bools(self):
+        def fn():
+            return [True, True, False]
+        assert self.interpret(fn, []) == [True, True, False]
+
+    def test_tuple_of_list_of_stringss(self):
+        def fn():
+            return ['abc', 'def'],  ['abc', 'def']
+        assert self.interpret(fn, []) == (['abc', 'def'],  ['abc', 'def'])



More information about the Pypy-commit mailing list