Amaury Forgeot d'Arc avatar Amaury Forgeot d'Arc committed 934772e

Finally found how to convert a SomeInstance(classdef=S) to a pointer
to a GCStruct for the same class.
Now a RPython instance can be passed (as reference) between compilation units.

Still in-progress. Next step: move this code to another file.

The hack in exceptiontransform.py is obscure; it seems that some dealloc function
is attached to the GCstruct, together with its graph from the first annotation.

Comments (0)

Files changed (4)

pypy/translator/c/genc.py

 
         for funcname, import_name in self.export_node_names.items():
             functype = lltype.typeOf(self.entrypoint[funcname])
-            setattr(mod, funcname,
-                    rffi.llexternal(
-                        import_name, functype.TO.ARGS, functype.TO.RESULT,
-                        compilation_info=import_eci,
-                        ))
+            from pypy.annotation import model
+
+            imported_func = rffi.llexternal(
+                import_name, functype.TO.ARGS, functype.TO.RESULT,
+                compilation_info=import_eci,
+                )
+
+            if not functype.TO.ARGS:
+                func = imported_func
+            elif len(functype.TO.ARGS) == 1:
+                ARG = functype.TO.ARGS[0]
+                from pypy.rpython.lltypesystem import llmemory
+                from pypy.rpython.extregistry import ExtRegistryEntry
+
+                if isinstance(ARG, lltype.Ptr): # XXX more precise check?
+                    def convert(x):
+                        raiseNameError
+
+                    class Entry(ExtRegistryEntry):
+                        _about_ = convert
+                        s_result_annotation = model.lltype_to_annotation(ARG)
+
+                        def specialize_call(self, hop):
+                            # TODO: input type check
+                            [v_instance] = hop.inputargs(*hop.args_r)
+                            return hop.genop('force_cast', [v_instance],
+                                             resulttype = ARG)
+                else:
+                    def convert(x):
+                        return x
+
+                def func(arg0):
+                    ll_arg0 = convert(arg0)
+                    ll_res = imported_func(ll_arg0)
+                    return ll_res
+            else:
+                raise NotImplementedError("Not supported")
+            setattr(mod, funcname, func)
         return mod
 
     def gen_makefile(self, targetdir):

pypy/translator/c/test/test_separate.py

 from pypy.annotation import model, description
 import py
 import sys, os
+import types
 
 class TestSeparation:
     def compile_function(self, func, argtypes):
             if hasattr(func, 'argtypes'):
                 t.annotator.build_types(func, func.argtypes,
                                         complete_now=False)
+        # annotate classes
+        for funcname, cls in exports.items():
+            if not isinstance(cls, (type, types.ClassType)):
+                continue
+            desc = bk.getdesc(cls)
+            classdef = desc.getuniqueclassdef()
+            s_init = desc.s_read_attribute('__init__')
+            if isinstance(s_init, model.SomeImpossibleValue):
+                continue
+
+            argtypes = (model.SomeInstance(classdef),)
+            argtypes += tuple(cls.__init__.argtypes)
+            t.annotator.build_types(cls.__init__.im_func, argtypes,
+                                    complete_now=False)
+        t.annotator.complete()
 
         # ensure that functions without signature are not constant-folded
         for funcname, func in exports.items():
                         newargs.append(newarg)
                     # and reflow
                     t.annotator.build_types(func, newargs)
-                elif isinstance(desc, description.ClassDesc):
-                    s_init = desc.s_read_attribute('__init__')
-                    initfunc = s_init.const
-                    newargs = [func, float]
-                    t.annotator.build_types(initfunc, newargs)
 
         t.buildrtyper().specialize()
 
 
     def test_pass_structure(self):
         class S:
-            @export
+            @export(float)
             def __init__(self, x):
                 self.x = x
 
         firstmodule = self.compile_separated("first", f=f, S=S)
 
         # call it from a function compiled in another module
-        def fn():
+        @export()
+        def g():
             s = S(41.0)
             return firstmodule.f(s)
+        secondmodule = self.compile_separated("second", g=g)
 
-        #assert fn() == 42.5
+        def fn():
+            return secondmodule.g()
+
+        if sys.platform == 'win32':
+            filepath = os.path.dirname(firstmodule.__file__)
+            os.environ['PATH'] = "%s;%s" % (filepath, os.environ['PATH'])
+
+        assert fn() == 42.5
         c_fn = self.compile_function(fn, [])
         assert c_fn() == 42.5

pypy/translator/exceptiontransform.py

         Because of the added exitswitch we need an additional block.
         """
         if hasattr(graph, 'exceptiontransformed'):
-            assert self.same_obj(self.exc_data_ptr, graph.exceptiontransformed)
-            return
-        else:
-            self.raise_analyzer.analyze_direct_call(graph)
-            graph.exceptiontransformed = self.exc_data_ptr
+            if self.same_obj(self.exc_data_ptr, graph.exceptiontransformed):
+                return
+        self.raise_analyzer.analyze_direct_call(graph)
+        graph.exceptiontransformed = self.exc_data_ptr
 
         self.always_exc_clear = always_exc_clear
         join_blocks(graph)

pypy/translator/separate.py

             decorated = export()(func)
             del decorated.argtypes
             return decorated
-        return object.__new__(cls, *args, **kwds)
+        return object.__new__(cls)
 
     def __init__(self, *args, **kwds):
         self.argtypes = args
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.