[pypy-svn] r59991 - pypy/branch/oo-jit/pypy/rpython/lltypesystem

arigo at codespeak.net arigo at codespeak.net
Wed Nov 19 17:20:32 CET 2008


Author: arigo
Date: Wed Nov 19 17:20:31 2008
New Revision: 59991

Modified:
   pypy/branch/oo-jit/pypy/rpython/lltypesystem/ll2ctypes.py
Log:
Huf.  Mostly just inserting 'rtyper' everywhere...


Modified: pypy/branch/oo-jit/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/branch/oo-jit/pypy/rpython/lltypesystem/ll2ctypes.py	(original)
+++ pypy/branch/oo-jit/pypy/rpython/lltypesystem/ll2ctypes.py	Wed Nov 19 17:20:31 2008
@@ -14,6 +14,7 @@
 from pypy.tool.tls import tlsobject
 from pypy.rlib.rarithmetic import r_uint, r_singlefloat
 from pypy.annotation import model as annmodel
+from pypy.rpython.llinterp import LLInterpreter
 
 def uaddressof(obj):
     return fixid(ctypes.addressof(obj))
@@ -47,7 +48,7 @@
 
 
 
-def build_ctypes_struct(S, delayed_builders, max_n=None):
+def build_ctypes_struct(rtyper, S, delayed_builders, max_n=None):
     def builder():
         # called a bit later to fill in _fields_
         # (to handle recursive structure pointers)
@@ -55,9 +56,9 @@
         for fieldname in S._names:
             FIELDTYPE = S._flds[fieldname]
             if max_n is not None and fieldname == S._arrayfld:
-                cls = get_ctypes_array_of_size(FIELDTYPE, max_n)
+                cls = get_ctypes_array_of_size(rtyper, FIELDTYPE, max_n)
             else:
-                cls = get_ctypes_type(FIELDTYPE)
+                cls = get_ctypes_type(rtyper, FIELDTYPE)
             fields.append((fieldname, cls))
         CStruct._fields_ = fields
 
@@ -73,7 +74,7 @@
             else:
                 if n is None:
                     raise TypeError("%r is variable-sized" % (S,))
-                biggercls = build_ctypes_struct(S, None, n)
+                biggercls = build_ctypes_struct(rtyper, S, None, n)
                 bigstruct = biggercls()
                 array = getattr(bigstruct, S._arrayfld)
                 if hasattr(array, 'length'):
@@ -83,16 +84,16 @@
 
     CStruct.__name__ = 'ctypes_%s' % (S,)
     if max_n is not None:
-        CStruct._normalized_ctype = get_ctypes_type(S)
+        CStruct._normalized_ctype = get_ctypes_type(rtyper, S)
         builder()    # no need to be lazy here
     else:
         delayed_builders.append(builder)
     return CStruct
 
-def build_ctypes_array(A, delayed_builders, max_n=0):
+def build_ctypes_array(rtyper, A, delayed_builders, max_n=0):
     assert max_n >= 0
     ITEM = A.OF
-    ctypes_item = get_ctypes_type(ITEM, delayed_builders)
+    ctypes_item = get_ctypes_type(rtyper, ITEM, delayed_builders)
 
     class CArray(ctypes.Structure):
         if not A._hints.get('nolength'):
@@ -104,7 +105,7 @@
         def _malloc(cls, n=None):
             if not isinstance(n, int):
                 raise TypeError, "array length must be an int"
-            biggercls = get_ctypes_array_of_size(A, n)
+            biggercls = get_ctypes_array_of_size(rtyper, A, n)
             bigarray = biggercls()
             if hasattr(bigarray, 'length'):
                 bigarray.length = n
@@ -123,67 +124,72 @@
                 items = self._indexable(index)
             cobj = items[index]
             if isinstance(ITEM, lltype.ContainerType):
-                return ctypes2lltype(lltype.Ptr(ITEM), ctypes.pointer(cobj))
+                return ctypes2lltype(lltype.Ptr(ITEM), ctypes.pointer(cobj),
+                                     rtyper)
             else:
-                return ctypes2lltype(ITEM, cobj)
+                return ctypes2lltype(ITEM, cobj, rtyper)
 
         def _setitem(self, index, value, boundscheck=True):
             if boundscheck:
                 items = self.items
             else:
                 items = self._indexable(index)
-            cobj = lltype2ctypes(value)
+            cobj = lltype2ctypes(value, rtyper)
             items[index] = cobj
 
     CArray.__name__ = 'ctypes_%s*%d' % (A, max_n)
     if max_n > 0:
-        CArray._normalized_ctype = get_ctypes_type(A)
+        CArray._normalized_ctype = get_ctypes_type(rtyper, A)
     return CArray
 
-def get_ctypes_array_of_size(FIELDTYPE, max_n):
+def get_ctypes_array_of_size(rtyper, FIELDTYPE, max_n):
     if max_n > 0:
         # no need to cache the results in this case, because the exact
         # type is never seen - the array instances are cast to the
         # array's _normalized_ctype, which is always the same.
-        return build_ctypes_array(FIELDTYPE, None, max_n)
+        return build_ctypes_array(rtyper, FIELDTYPE, None, max_n)
     else:
-        return get_ctypes_type(FIELDTYPE)
+        return get_ctypes_type(rtyper, FIELDTYPE)
 
-def get_ctypes_type(T, delayed_builders=None):
+def get_ctypes_type(rtyper, T, delayed_builders=None):
     try:
         return _ctypes_cache[T]
     except KeyError:
-        toplevel = delayed_builders is None
-        if toplevel:
-            delayed_builders = []
-        cls = build_new_ctypes_type(T, delayed_builders)
-        if T not in _ctypes_cache:
-            _ctypes_cache[T] = cls
-        else:
-            # check for buggy recursive structure logic
-            assert _ctypes_cache[T] is cls
-        if toplevel:
-            complete_builders(delayed_builders)
-        return cls
+        try:
+            return _ctypes_cache[rtyper, T]
+        except KeyError:
+            toplevel = delayed_builders is None
+            if toplevel:
+                delayed_builders = []
+            cls = build_new_ctypes_type(rtyper, T, delayed_builders)
+            if (rtyper, T) not in _ctypes_cache:
+                _ctypes_cache[rtyper, T] = cls
+            else:
+                # check for buggy recursive structure logic
+                assert _ctypes_cache[rtyper, T] is cls
+            if toplevel:
+                complete_builders(delayed_builders)
+            return cls
 
-def build_new_ctypes_type(T, delayed_builders):
+def build_new_ctypes_type(rtyper, T, delayed_builders):
     if isinstance(T, lltype.Ptr):
         if isinstance(T.TO, lltype.FuncType):
-            argtypes = [get_ctypes_type(ARG) for ARG in T.TO.ARGS
-                                             if ARG is not lltype.Void]
+            argtypes = [get_ctypes_type(rtyper, ARG) for ARG in T.TO.ARGS
+                                                     if ARG is not lltype.Void]
             if T.TO.RESULT is lltype.Void:
                 restype = None
             else:
-                restype = get_ctypes_type(T.TO.RESULT)
+                restype = get_ctypes_type(rtyper, T.TO.RESULT)
             return ctypes.CFUNCTYPE(restype, *argtypes)
         else:
-            return ctypes.POINTER(get_ctypes_type(T.TO, delayed_builders))
+            return ctypes.POINTER(get_ctypes_type(rtyper, T.TO,
+                                                  delayed_builders))
     elif T is lltype.Void:
         return ctypes.c_long # opaque pointer
     elif isinstance(T, lltype.Struct):
-        return build_ctypes_struct(T, delayed_builders)
+        return build_ctypes_struct(rtyper, T, delayed_builders)
     elif isinstance(T, lltype.Array):
-        return build_ctypes_array(T, delayed_builders)
+        return build_ctypes_array(rtyper, T, delayed_builders)
     elif isinstance(T, lltype.OpaqueType):
         if T is lltype.RuntimeTypeInfo:
             return ctypes.c_char * 2
@@ -201,17 +207,17 @@
         delayed_builders.pop()()
 
 
-def convert_struct(container, cstruct=None, acceptgckind=False):
+def convert_struct(rtyper, container, cstruct=None, acceptgckind=False):
     STRUCT = container._TYPE
     if cstruct is None:
         # if 'container' is an inlined substructure, convert the whole
         # bigger structure at once
         parent, parentindex = lltype.parentlink(container)
         if parent is not None:
-            convert_struct(parent)
+            convert_struct(rtyper, parent)
             return
         # regular case: allocate a new ctypes Structure of the proper type
-        cls = get_ctypes_type(STRUCT)
+        cls = get_ctypes_type(rtyper, STRUCT)
         if STRUCT._arrayfld is not None:
             n = getattr(container, STRUCT._arrayfld).getlength()
         else:
@@ -223,16 +229,17 @@
         field_value = getattr(container, field_name)
         if not isinstance(FIELDTYPE, lltype.ContainerType):
             # regular field
-            setattr(cstruct, field_name, lltype2ctypes(field_value,
+            setattr(cstruct, field_name, lltype2ctypes(field_value, rtyper,
                                 acceptgckind=acceptgckind))
         else:
             # inlined substructure/subarray
             if isinstance(FIELDTYPE, lltype.Struct):
                 csubstruct = getattr(cstruct, field_name)
-                convert_struct(field_value, csubstruct)
+                convert_struct(rtyper, field_value, csubstruct)
             elif field_name == STRUCT._arrayfld:    # inlined var-sized part
                 csubarray = getattr(cstruct, field_name)
-                convert_array(field_value, csubarray, acceptgckind=acceptgckind)
+                convert_array(rtyper, field_value, csubarray,
+                              acceptgckind=acceptgckind)
             else:
                 raise NotImplementedError('inlined field', FIELDTYPE)
     remove_regular_struct_content(container)
@@ -244,30 +251,31 @@
         if not isinstance(FIELDTYPE, lltype.ContainerType):
             delattr(container, field_name)
 
-def convert_array(container, carray=None, acceptgckind=False):
+def convert_array(rtyper, container, carray=None, acceptgckind=False):
     ARRAY = container._TYPE
     if carray is None:
         # if 'container' is an inlined substructure, convert the whole
         # bigger structure at once
         parent, parentindex = lltype.parentlink(container)
         if parent is not None:
-            convert_struct(parent)
+            convert_struct(rtyper, parent)
             return
         # regular case: allocate a new ctypes array of the proper type
-        cls = get_ctypes_type(ARRAY)
+        cls = get_ctypes_type(rtyper, ARRAY)
         carray = cls._malloc(container.getlength())
     add_storage(container, _array_mixin, carray)
     if not isinstance(ARRAY.OF, lltype.ContainerType):
         for i in range(container.getlength()):
             item_value = container.items[i]    # fish fish
-            carray.items[i] = lltype2ctypes(item_value,
+            carray.items[i] = lltype2ctypes(item_value, rtyper,
                                             acceptgckind=acceptgckind)
         remove_regular_array_content(container)
     else:
         assert isinstance(ARRAY.OF, lltype.Struct)
         for i in range(container.getlength()):
             item_ptr = container.items[i]    # fish fish
-            convert_struct(item_ptr, carray.items[i], acceptgckind=acceptgckind)
+            convert_struct(rtyper, item_ptr, carray.items[i],
+                           acceptgckind=acceptgckind)
 
 def remove_regular_array_content(container):
     for i in range(container.getlength()):
@@ -424,57 +432,59 @@
 # additionally, this adds mess to __del__ "semantics"
 _all_callbacks = []
 
-def lltype2ctypes(llobj, normalize=True, acceptgckind=False):
+def lltype2ctypes(llobj, rtyper=None, normalize=True, acceptgckind=False):
     """Convert the lltype object 'llobj' to its ctypes equivalent.
     'normalize' should only be False in tests, where we want to
     inspect the resulting ctypes object manually.
     """
     if isinstance(llobj, lltype._uninitialized):
-        return uninitialized2ctypes(llobj.TYPE)
+        return uninitialized2ctypes(llobj.TYPE, rtyper)
 
     T = lltype.typeOf(llobj)
     if isinstance(T, lltype.Ptr):
         if not llobj:   # NULL pointer
-            return get_ctypes_type(T)()
+            return get_ctypes_type(rtyper, T)()
 
         container = llobj._obj
         if isinstance(T.TO, lltype.FuncType):
-            if not hasattr(container, '_callable'):
-                raise NotImplementedError("ctypes wrapper for ll function "
-                                          "without a _callable")
-            else:
-                v1voidlist = [(i, getattr(container, '_void' + str(i), None))
-                                 for i in range(len(T.TO.ARGS))
-                                     if T.TO.ARGS[i] is lltype.Void]
-                def callback(*cargs):
-                    cargs = list(cargs)
-                    for v1 in v1voidlist:
-                        cargs.insert(v1[0], v1[1])
-                    assert len(cargs) == len(T.TO.ARGS)
-                    llargs = []
-                    for ARG, carg in zip(T.TO.ARGS, cargs):
-                        if ARG is lltype.Void:
-                            llargs.append(carg)
-                        else:
-                            llargs.append(ctypes2lltype(ARG, carg))
+            if hasattr(container, 'graph'):
+                assert rtyper is not None
+            v1voidlist = [(i, getattr(container, '_void' + str(i), None))
+                             for i in range(len(T.TO.ARGS))
+                                 if T.TO.ARGS[i] is lltype.Void]
+            def callback(*cargs):
+                cargs = list(cargs)
+                for v1 in v1voidlist:
+                    cargs.insert(v1[0], v1[1])
+                assert len(cargs) == len(T.TO.ARGS)
+                llargs = []
+                for ARG, carg in zip(T.TO.ARGS, cargs):
+                    if ARG is lltype.Void:
+                        llargs.append(carg)
+                    else:
+                        llargs.append(ctypes2lltype(ARG, carg, rtyper))
+                if hasattr(container, 'graph'):
+                    llinterp = LLInterpreter(rtyper)
+                    llres = llinterp.eval_graph(container.graph, llargs)
+                else:
                     llres = container._callable(*llargs)
-                    assert lltype.typeOf(llres) == T.TO.RESULT
-                    if T.TO.RESULT is lltype.Void:
-                        return None
-                    res = lltype2ctypes(llres, acceptgckind=acceptgckind)
-                    if isinstance(T.TO.RESULT, lltype.Ptr):
-                        _all_callbacks.append(res)
-                        res = ctypes.cast(res, ctypes.c_void_p).value
-                    return res
+                assert lltype.typeOf(llres) == T.TO.RESULT
+                if T.TO.RESULT is lltype.Void:
+                    return None
+                res = lltype2ctypes(llres, rtyper, acceptgckind=acceptgckind)
                 if isinstance(T.TO.RESULT, lltype.Ptr):
-                    TMod = lltype.Ptr(lltype.FuncType(T.TO.ARGS,
-                                                      lltype.Signed))
-                    ctypes_func_type = get_ctypes_type(TMod)
-                else:
-                    ctypes_func_type = get_ctypes_type(T)
-                res = ctypes_func_type(callback)
-                _all_callbacks.append(res)
+                    _all_callbacks.append(res)
+                    res = ctypes.cast(res, ctypes.c_void_p).value
                 return res
+            if isinstance(T.TO.RESULT, lltype.Ptr):
+                TMod = lltype.Ptr(lltype.FuncType(T.TO.ARGS,
+                                                  lltype.Signed))
+                ctypes_func_type = get_ctypes_type(rtyper, TMod)
+            else:
+                ctypes_func_type = get_ctypes_type(rtyper, T)
+            res = ctypes_func_type(callback)
+            _all_callbacks.append(res)
+            return res
 
         if (T.TO._gckind != 'raw' and not T.TO._hints.get('callback', None)
             and not acceptgckind):
@@ -485,9 +495,9 @@
         if container._storage is True:
             # container has regular lltype storage, convert it to ctypes
             if isinstance(T.TO, lltype.Struct):
-                convert_struct(container, acceptgckind=acceptgckind)
+                convert_struct(rtyper, container, acceptgckind=acceptgckind)
             elif isinstance(T.TO, lltype.Array):
-                convert_array(container, acceptgckind=acceptgckind)
+                convert_array(rtyper, container, acceptgckind=acceptgckind)
             elif isinstance(T.TO, lltype.OpaqueType):
                 if T.TO != lltype.RuntimeTypeInfo:
                     cbuf = ctypes.create_string_buffer(T.TO.hints['getsize']())
@@ -505,7 +515,8 @@
 
     if isinstance(llobj, Symbolic):
         if isinstance(llobj, llmemory.ItemOffset):
-            llobj = ctypes.sizeof(get_ctypes_type(llobj.TYPE)) * llobj.repeat
+            llobj = ctypes.sizeof(get_ctypes_type(rtyper, llobj.TYPE)) \
+                      * llobj.repeat
         elif isinstance(llobj, ComputedIntSymbolic):
             llobj = llobj.compute_fn()
         else:
@@ -519,7 +530,7 @@
 
     return llobj
 
-def ctypes2lltype(T, cobj):
+def ctypes2lltype(T, cobj, rtyper=None):
     """Convert the ctypes object 'cobj' to its lltype equivalent.
     'T' is the expected lltype type.
     """
@@ -541,7 +552,7 @@
                 container = _array_of_known_length(T.TO)
                 container._storage = cobj.contents
         elif isinstance(T.TO, lltype.FuncType):
-            _callable = get_ctypes_trampoline(T.TO, cobj)
+            _callable = get_ctypes_trampoline(rtyper, T.TO, cobj)
             return lltype.functionptr(T.TO, getattr(cobj, '__name__', '?'),
                                       _callable=_callable)
         elif isinstance(T.TO, lltype.OpaqueType):
@@ -573,9 +584,9 @@
     assert lltype.typeOf(llobj) == T
     return llobj
 
-def uninitialized2ctypes(T):
+def uninitialized2ctypes(T, rtyper=None):
     "For debugging, create a ctypes object filled with 0xDD."
-    ctype = get_ctypes_type(T)
+    ctype = get_ctypes_type(rtyper, T)
     cobj = ctype()
     size = ctypes.sizeof(cobj)
     p = ctypes.cast(ctypes.pointer(cobj),
@@ -658,12 +669,12 @@
             funcname, place))
 
     # get_ctypes_type() can raise NotImplementedError too
-    cfunc.argtypes = [get_ctypes_type(T) for T in FUNCTYPE.ARGS
-                                         if T is not lltype.Void]
+    cfunc.argtypes = [get_ctypes_type(None, T) for T in FUNCTYPE.ARGS
+                                               if T is not lltype.Void]
     if FUNCTYPE.RESULT is lltype.Void:
         cfunc.restype = None
     else:
-        cfunc.restype = get_ctypes_type(FUNCTYPE.RESULT)
+        cfunc.restype = get_ctypes_type(None, FUNCTYPE.RESULT)
     return cfunc
 
 class LL2CtypesCallable(object):
@@ -679,11 +690,11 @@
         if self.trampoline is None:
             # lazily build the corresponding ctypes function object
             cfunc = get_ctypes_callable(self.funcptr, self.calling_conv)
-            self.trampoline = get_ctypes_trampoline(self.FUNCTYPE, cfunc)
+            self.trampoline = get_ctypes_trampoline(None, self.FUNCTYPE, cfunc)
         # perform the call
         return self.trampoline(*argvalues)
 
-def get_ctypes_trampoline(FUNCTYPE, cfunc):
+def get_ctypes_trampoline(rtyper, FUNCTYPE, cfunc):
     RESULT = FUNCTYPE.RESULT
     container_arguments = []
     for i in range(len(FUNCTYPE.ARGS)):
@@ -697,14 +708,14 @@
         cargs = []
         for i in range(len(FUNCTYPE.ARGS)):
             if i not in void_arguments:
-                cvalue = lltype2ctypes(argvalues[i])
+                cvalue = lltype2ctypes(argvalues[i], rtyper)
                 for i in container_arguments:
                     cvalue = cvalue.contents
                 cargs.append(cvalue)
         _restore_c_errno()
         cres = cfunc(*cargs)
         _save_c_errno()
-        return ctypes2lltype(RESULT, cres)
+        return ctypes2lltype(RESULT, cres, rtyper)
     return invoke_via_ctypes
 
 def force_cast(RESTYPE, value):
@@ -713,7 +724,7 @@
         raise TypeError("rffi.cast() first arg should be a TYPE")
     TYPE1 = lltype.typeOf(value)
     cvalue = lltype2ctypes(value)
-    cresulttype = get_ctypes_type(RESTYPE)
+    cresulttype = get_ctypes_type(None, RESTYPE)
     if isinstance(TYPE1, lltype.Ptr):
         if isinstance(RESTYPE, lltype.Ptr):
             # shortcut: ptr->ptr cast
@@ -769,15 +780,15 @@
     """
     T = lltype.typeOf(ptr)
     typecheck_ptradd(T)
-    ctypes_item_type = get_ctypes_type(T.TO.OF)
-    ctypes_arrayptr_type = get_ctypes_type(T)
+    ctypes_item_type = get_ctypes_type(None, T.TO.OF)
+    ctypes_arrayptr_type = get_ctypes_type(None, T)
     cptr = lltype2ctypes(ptr)
     baseaddr = ctypes.addressof(cptr.contents.items)
     addr = baseaddr + n * ctypes.sizeof(ctypes_item_type)
     cptr = ctypes.cast(ctypes.c_void_p(addr), ctypes_arrayptr_type)
     return ctypes2lltype(T, cptr)
 
-class ForceCastEntry(ExtRegistryEntry):
+class ForcePtrAddEntry(ExtRegistryEntry):
     _about_ = force_ptradd
 
     def compute_result_annotation(self, s_ptr, s_n):



More information about the Pypy-commit mailing list