[pypy-svn] r25412 - in pypy/dist/pypy: annotation rpython/rctypes rpython/rctypes/test

arigo at codespeak.net arigo at codespeak.net
Wed Apr 5 20:06:55 CEST 2006


Author: arigo
Date: Wed Apr  5 20:06:52 2006
New Revision: 25412

Added:
   pypy/dist/pypy/rpython/rctypes/rfunc.py
   pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py
Modified:
   pypy/dist/pypy/annotation/binaryop.py
   pypy/dist/pypy/annotation/model.py
   pypy/dist/pypy/rpython/rctypes/implementation.py
   pypy/dist/pypy/rpython/rctypes/rmodel.py
   pypy/dist/pypy/rpython/rctypes/rpointer.py
   pypy/dist/pypy/rpython/rctypes/rprimitive.py
   pypy/dist/pypy/rpython/rctypes/test/test_rarray.py
   pypy/dist/pypy/rpython/rctypes/test/test_rctypes.py
Log:
(arre, arigo)  (dinner time!)

Completed an rarray test: missing conversion from ints to c_long.
Started function support (mostly by copying code from implementation.py).
Pushed and pulled a bit and 42 fell out.


Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py	(original)
+++ pypy/dist/pypy/annotation/binaryop.py	Wed Apr  5 20:06:52 2006
@@ -765,16 +765,10 @@
         # Note: The following works for index either pointers and arrays,
         # because both have a _type_ attribute that contains the type of the
         # object pointed to or in the case of an array the element type.
-        assert hasattr(s_cto.knowntype, '_type_')
-        assert extregistry.is_registered_type(s_cto.knowntype._type_)
-        entry = extregistry.lookup_type(s_cto.knowntype._type_)
-        if hasattr(entry, 'lowleveltype'):
-            # special case for reading primitives out of arrays
-            return lltype_to_annotation(entry.lowleveltype)
-        else:
-            return SomeCTypesObject(
-                s_cto.knowntype._type_,
-                memorystate=SomeCTypesObject.MEMORYALIAS)
+        result_ctype = s_cto.knowntype._type_
+        s_result = SomeCTypesObject(result_ctype,
+                                    memorystate=SomeCTypesObject.MEMORYALIAS)
+        return s_result.return_annotation()
 
 class __extend__(pairtype(SomeCTypesObject, SomeSlice)):
     def setitem((s_cto, s_slice), s_iterable):

Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py	(original)
+++ pypy/dist/pypy/annotation/model.py	Wed Apr  5 20:06:52 2006
@@ -443,6 +443,21 @@
     def can_be_none(self):
         return False
 
+    def return_annotation(self):
+        """Returns either 'self' or the annotation of the unwrapped version
+        of this ctype, following the logic used when ctypes operations
+        return a value.
+        """
+        from pypy.rpython import extregistry
+        assert extregistry.is_registered_type(self.knowntype)
+        entry = extregistry.lookup_type(self.knowntype)
+        if hasattr(entry, 'lowleveltype'):
+            # special case for returning primitives
+            return lltype_to_annotation(entry.lowleveltype)
+        else:
+            return self
+
+
 class SomeImpossibleValue(SomeObject):
     """The empty set.  Instances are placeholders for objects that
     will never show up at run-time, e.g. elements of an empty list."""

Modified: pypy/dist/pypy/rpython/rctypes/implementation.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/implementation.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/implementation.py	Wed Apr  5 20:06:52 2006
@@ -24,6 +24,7 @@
 import pypy.rpython.rctypes.rarray
 import pypy.rpython.rctypes.rprimitive
 import pypy.rpython.rctypes.rpointer
+import pypy.rpython.rctypes.rfunc
 
 # ctypes_annotation_list contains various attributes that
 # are used by the pypy annotation.
@@ -81,79 +82,6 @@
 
 create_ctypes_annotations()
 
-CFuncPtrType = type(ctypes.CFUNCTYPE(None))
-
-def cfuncptrtype_compute_annotation(type, instance):
-    from pypy.annotation.model import ll_to_annotation_map
-
-    def compute_result_annotation(*args_s):
-        """
-        Answer the annotation of the external function's result
-        """
-
-        # results of external function calls *must* be in the registry
-        # XXX: goden: check metatype too?
-        assert extregistry.is_registered_type(instance.restype)
-
-        entry = extregistry.lookup_type(instance.restype)
-
-        # XXX: goden: this probably isn't right
-        return ll_to_annotation_map.get(entry.lowleveltype)
-        
-        # Take 3, Check whether we can get away with the cheap
-        # precomputed solution and if not it, use a special
-        # attribute with the memory state
-        try:
-            return instance.restype.annotator_type
-        except AttributeError:
-            return SomeCTypesObject( 
-                    instance.restype, 
-                    instance.restype.external_function_result_memorystate )
-        # Take 2, looks like we need another level of indirection
-        # That's to complicated
-        #o#return self.restype.compute_external_function_result_annotator_type()
-        # TODO: Check whether the function returns a pointer
-        # an correct the memory state appropriately
-        try:
-            return instance.restype.annotator_type
-        except AttributeError:
-            return SomeCTypesObject(instance.restype)
-        
-    return SomeBuiltin(compute_result_annotation, 
-        methodname=instance.__name__)
-
-def cfuncptrtype_specialize_call(hop):
-    # this is necessary to get the original function pointer when specializing
-    # the metatype
-    cfuncptr = hop.spaceop.args[0].value
-
-    def convert_params(backend, param_info_list):
-        assert "c" == backend.lower()
-        assert cfuncptr.argtypes is not None
-        answer = []
-        for ctype_type, (ll_type, arg_name) in zip(cfuncptr.argtypes,
-                                                    param_info_list):
-            if ll_type == ctype_type.ll_type:
-                answer.append(arg_name)
-            else:
-                answer.append(ctype_type.wrap_arg(ll_type, arg_name))
-        return answer
-
-    assert extregistry.is_registered_type(cfuncptr.restype)
-
-    # results of external function calls *must* be in the registry
-    entry = extregistry.lookup_type(cfuncptr.restype)
-
-    return hop.llops.gencapicall(
-            cfuncptr.__name__,
-            hop.args_v,
-            resulttype = entry.lowleveltype,
-            _callable=None,
-            convert_params = convert_params ) 
-
-extregistry.register_metatype(CFuncPtrType, 
-    compute_annotation=cfuncptrtype_compute_annotation,
-    specialize_call=cfuncptrtype_specialize_call)
 
 class FunctionPointerTranslation(object):
 

Added: pypy/dist/pypy/rpython/rctypes/rfunc.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/rctypes/rfunc.py	Wed Apr  5 20:06:52 2006
@@ -0,0 +1,46 @@
+from pypy.annotation import model as annmodel
+from pypy.rpython import extregistry
+
+import ctypes
+
+
+CFuncPtrType = type(ctypes.CFUNCTYPE(None))
+
+def cfuncptrtype_compute_annotation(type, instance):
+
+    def compute_result_annotation(*args_s):
+        """
+        Answer the annotation of the external function's result
+        """
+        result_ctype = instance.restype
+        s_result = annmodel.SomeCTypesObject(result_ctype,
+                                         annmodel.SomeCTypesObject.OWNSMEMORY)
+        return s_result.return_annotation()
+
+    return annmodel.SomeBuiltin(compute_result_annotation, 
+        methodname=instance.__name__)
+
+def cfuncptrtype_specialize_call(hop):
+    # this is necessary to get the original function pointer when specializing
+    # the metatype
+    assert hop.spaceop.opname == "simple_call"
+    cfuncptr = hop.spaceop.args[0].value
+
+    args_r = []
+    for ctype in cfuncptr.argtypes:
+        s_arg = annmodel.SomeCTypesObject(ctype,
+                              annmodel.SomeCTypesObject.MEMORYALIAS)
+        r_arg = hop.rtyper.getrepr(s_arg)
+        args_r.append(r_arg)
+
+    vlist = hop.inputargs(*args_r)
+    unwrapped_args_v = [r_arg.getvalue(hop.llops, v)
+                        for r_arg, v in zip(args_r, vlist)]
+
+    ll_func = cfuncptr.llinterp_friendly_version
+    v_result = hop.llops.gendirectcall(ll_func, *unwrapped_args_v)
+    return v_result
+
+extregistry.register_metatype(CFuncPtrType, 
+    compute_annotation=cfuncptrtype_compute_annotation,
+    specialize_call=cfuncptrtype_specialize_call)

Modified: pypy/dist/pypy/rpython/rctypes/rmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rmodel.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rmodel.py	Wed Apr  5 20:06:52 2006
@@ -26,8 +26,8 @@
     #                   traked by our GC around the raw 'c_data_type'-shaped
     #                   data.
     #
-    #  * 'owner_lowleveltype' is the lowleveltype of the repr for the same
-    #                         ctype but for ownsmemory=True.
+    #  * 'r_memoryowner.lowleveltype' is the lowleveltype of the repr for the
+    #                                 same ctype but for ownsmemory=True.
 
     def __init__(self, rtyper, s_ctypesobject, ll_type):
         # s_ctypesobject: the annotation to represent
@@ -49,20 +49,23 @@
         self.c_data_type = self.get_c_data_type(ll_type)
         content_keepalives = self.get_content_keepalives()
 
-        self.owner_lowleveltype = lltype.Ptr(
-                lltype.GcStruct( "CtypesBox_%s" % (ctype.__name__,),
-                    ( "c_data", self.c_data_type ),
-                    *content_keepalives
-                )
-            )
         if self.ownsmemory:
-            self.lowleveltype = self.owner_lowleveltype
+            self.r_memoryowner = self
+            self.lowleveltype = lltype.Ptr(
+                    lltype.GcStruct( "CtypesBox_%s" % (ctype.__name__,),
+                        ( "c_data", self.c_data_type ),
+                        *content_keepalives
+                    )
+                )
         else:
+            s_memoryowner = SomeCTypesObject(ctype,
+                                             SomeCTypesObject.OWNSMEMORY)
+            self.r_memoryowner = rtyper.getrepr(s_memoryowner)
             self.lowleveltype = lltype.Ptr(
                 lltype.GcStruct( "CtypesBox_%s" % (ctype.__name__,),
-                    ( "c_data_ref", lltype.Ptr(self.c_data_type) ),
-                    ( "c_data_owner_keepalive", self.owner_lowleveltype ),
-                    *content_keepalives
+                 ( "c_data_ref", lltype.Ptr(self.c_data_type) ),
+                 ( "c_data_owner_keepalive", self.r_memoryowner.lowleveltype ),
+                 *content_keepalives
                 )
             )
         self.const_cache = {} # store generated const values+original value
@@ -88,7 +91,7 @@
             inputargs = [v_box, inputconst(lltype.Void,
                                            "c_data_owner_keepalive")]
             return llops.genop('getfield', inputargs,
-                               self.owner_lowleveltype)
+                               self.r_memoryowner.lowleveltype)
 
     def allocate_instance(self, llops):
         c1 = inputconst(lltype.Void, self.lowleveltype.TO) 
@@ -104,7 +107,8 @@
         inputargs = [v_box, inputconst(lltype.Void, "c_data_ref"), v_c_data]
         llops.genop('setfield', inputargs)
         if v_c_data_owner is not None:
-            assert v_c_data_owner.concretetype == self.owner_lowleveltype
+            assert (v_c_data_owner.concretetype ==
+                    self.r_memoryowner.lowleveltype)
             inputargs = [v_box,
                          inputconst(lltype.Void, "c_data_owner_keepalive"),
                          v_c_data_owner]

Modified: pypy/dist/pypy/rpython/rctypes/rpointer.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rpointer.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rpointer.py	Wed Apr  5 20:06:52 2006
@@ -22,7 +22,8 @@
 
     def get_content_keepalives(self):
         "Return an extra keepalive field used for the pointer's contents."
-        return [('keepalive_contents', self.r_contents.owner_lowleveltype)]
+        return [('keepalive_contents',
+                 self.r_contents.r_memoryowner.lowleveltype)]
 
     def setkeepalive(self, llops, v_box, v_owner):
         inputargs = [v_box, inputconst(lltype.Void, 'keepalive_contents'),

Modified: pypy/dist/pypy/rpython/rctypes/rprimitive.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rprimitive.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rprimitive.py	Wed Apr  5 20:06:52 2006
@@ -6,7 +6,7 @@
 from pypy.rpython.rmodel import Repr, inputconst
 from pypy.rpython.lltypesystem import lltype
 from pypy.annotation.pairtype import pairtype
-from pypy.rpython.rmodel import IntegerRepr
+from pypy.rpython.rmodel import IntegerRepr, FloatRepr, CharRepr
 from pypy.rpython.error import TyperError
 from pypy.rpython.rctypes.rmodel import CTypesValueRepr
 
@@ -49,7 +49,7 @@
         try:
             return self.const_cache[key][0]
         except KeyError:
-            p = lltype.malloc(self.owner_lowleveltype.TO)
+            p = lltype.malloc(self.r_memoryowner.lowleveltype.TO)
             p.c_data.value = value
             if self.ownsmemory:
                 result = p
@@ -78,6 +78,14 @@
         self.setvalue(hop.llops, v_primitive, v_value)
 
 
+class __extend__(pairtype(IntegerRepr, PrimitiveRepr)):
+    def convert_from_to((r_from, r_to), v, llops):
+        r_temp = r_to.r_memoryowner
+        v_owned_box = r_temp.allocate_instance(llops)
+        r_temp.setvalue(llops, v_owned_box, v)
+        return llops.convertvar(v_owned_box, r_temp, r_to)
+
+
 def primitive_specialize_call(hop):
     r_primitive = hop.r_result
     v_result = r_primitive.allocate_instance(hop.llops)

Modified: pypy/dist/pypy/rpython/rctypes/test/test_rarray.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rarray.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rarray.py	Wed Apr  5 20:06:52 2006
@@ -34,16 +34,17 @@
             a.translator.view()
 
     def test_annotate_array_access(self):
-        def access_array():
+        def access_array(n):
             my_array = c_int_10()
             my_array[0] = c_int(1)
             my_array[1] = 2
+            my_array[2] = n
 
             return my_array[0]
 
         t = TranslationContext()
         a = t.buildannotator()
-        s = a.build_types(access_array, [])
+        s = a.build_types(access_array, [int])
         assert s.knowntype == int
 
         if conftest.option.view:
@@ -114,14 +115,15 @@
         assert len(c_data) == 10
 
     def test_specialize_array_access(self):
-        def access_array():
+        def access_array(n):
             my_array = c_int_10()
             my_array[0] = 1
             my_array[1] = c_int(1)
+            my_array[2] = n
 
             return my_array[0]
 
-        res = interpret(access_array, [])
+        res = interpret(access_array, [44])
         assert res == 1
 
 class Test_compilation:

Modified: pypy/dist/pypy/rpython/rctypes/test/test_rctypes.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rctypes.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rctypes.py	Wed Apr  5 20:06:52 2006
@@ -257,7 +257,7 @@
         # result should be an integer
         assert s.knowntype == int
 
-    def test_specialize_simple(self):
+    def x_test_specialize_simple(self):
         t = TranslationContext()
         a = t.buildannotator()
         s = a.build_types(o_atoi, [str])

Added: pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py	Wed Apr  5 20:06:52 2006
@@ -0,0 +1,36 @@
+from pypy.annotation.annrpython import RPythonAnnotator
+from pypy.rpython.rctypes.test.test_rctypes import mylib
+from pypy.rpython.test.test_llinterp import interpret
+from pypy import conftest
+
+from ctypes import c_long
+
+
+labs = mylib.labs
+labs.restype = c_long
+labs.argtypes = [c_long]
+
+def ll_labs(n):
+    return abs(n)
+
+labs.llinterp_friendly_version = ll_labs
+
+
+def test_labs(n=6):
+    assert labs(n) == abs(n)
+    assert labs(c_long(0)) == 0
+    assert labs(-42) == 42
+    return labs(n)
+
+class Test_annotation:
+    def test_annotate_labs(self):
+        a = RPythonAnnotator()
+        s = a.build_types(test_labs, [int])
+        assert s.knowntype == int
+        if conftest.option.view:
+            a.translator.view()
+
+class Test_specialization:
+    def test_specialize_labs(self):
+        res = interpret(test_labs, [-11])
+        assert res == 11



More information about the Pypy-commit mailing list