[pypy-svn] r25513 - in pypy/branch/stacklesscfg/pypy/translator/c: . test

mwh at codespeak.net mwh at codespeak.net
Fri Apr 7 18:58:24 CEST 2006


Author: mwh
Date: Fri Apr  7 18:58:23 2006
New Revision: 25513

Added:
   pypy/branch/stacklesscfg/pypy/translator/c/stacklesscode.py   (contents, props changed)
Modified:
   pypy/branch/stacklesscfg/pypy/translator/c/stacklesstransform.py
   pypy/branch/stacklesscfg/pypy/translator/c/test/test_stacklesstransform.py
Log:
(hpk, mwh)
a start at an RPython main loop for stackless.
a start at a transform to insert state saving blocks into a function
more implicit XXXs than you could possibly imagine


Added: pypy/branch/stacklesscfg/pypy/translator/c/stacklesscode.py
==============================================================================
--- (empty file)
+++ pypy/branch/stacklesscfg/pypy/translator/c/stacklesscode.py	Fri Apr  7 18:58:23 2006
@@ -0,0 +1,87 @@
+from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython import rarithmetic
+
+STATE_HEADER = lltype.Struct('state_header',
+                             ('f_back', lltype.Ptr(lltype.ForwardReference())),
+                             ('state', lltype.Signed))
+STATE_HEADER.f_back.TO.become(STATE_HEADER)
+
+null_state = lltype.nullptr(STATE_HEADER)
+
+class StacklessData:
+    def __init__(self):
+        self.top = null_state
+        self.bottom = null_state
+        self.restart_substate = 0
+        self.retval_long = 0
+        self.retval_longlong = rarithmetic.r_longlong(0)
+        self.retval_double = 0.0
+        self.retval_void_p = llmemory.fakeaddress(None)
+        self.exception = None
+
+global_state = StacklessData()
+
+class UnwindException(Exception):
+    def __init__(self):
+        self.frame = null_state
+
+void_void_func = lltype.FuncType([], lltype.Void)
+long_void_func = lltype.FuncType([], lltype.Signed)
+longlong_void_func = lltype.FuncType([], lltype.SignedLongLong)
+pointer_void_func = lltype.FuncType([], llmemory.Address)
+float_void_func = lltype.FuncType([], lltype.Float)
+
+def call_function(fn, signature):
+    pass
+##     if signature == 'void':
+##         fn2 = llmemory.cast_adr_to_ptr(fn, void_void_func)
+##         fn2()
+##     elif signature == 'long':
+##         fn3 = llmemory.cast_adr_to_ptr(fn, long_void_func)
+##         global_state.long_retval = fn3()
+##     elif signature == 'long long':
+##         fn4 = llmemory.cast_adr_to_ptr(fn, longlong_void_func)
+##         global_state.longlong_retval = fn4()
+##     elif signature == 'pointer':
+##         fn5 = llmemory.cast_adr_to_ptr(fn, pointer_void_func)
+##         global_state.pointer_retval = fn5()
+##     elif signature == 'float':
+##         fn6 = llmemory.cast_adr_to_ptr(fn, float_void_func)
+##         global_state.float_retval = fn6()
+
+
+null_address = llmemory.fakeaddress(None)
+
+def decode_state(state):
+    return null_address, 'void', 0
+
+def slp_main_loop():
+    while 1:
+        pending = global_state.top
+        while 1:
+            back = pending.f_back
+
+            state = pending.state
+            fn, signature, global_state.restart_substate = decode_state(state)
+
+            try:
+                call_function(fn, signature)
+##             except UnwindException, u:
+##                 pending = u.frame
+##                 break
+            except Exception, e:
+                global_state.exception = e
+            else:
+                global_state.exception = None
+
+            if not back:
+                if global_state.exception:
+                    raise global_state.exception
+                return
+
+            pending = back
+            global_state.top = pending
+
+        if global_state.bottom:
+            assert global_state.bottom.f_back is None
+            global_state.bottom.f_back = back

Modified: pypy/branch/stacklesscfg/pypy/translator/c/stacklesstransform.py
==============================================================================
--- pypy/branch/stacklesscfg/pypy/translator/c/stacklesstransform.py	(original)
+++ pypy/branch/stacklesscfg/pypy/translator/c/stacklesstransform.py	Fri Apr  7 18:58:23 2006
@@ -1,5 +1,12 @@
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython import rarithmetic
+from pypy.translator.backendopt import support
+from pypy.objspace.flow import model
+from pypy.rpython.memory.gctransform import varoftype
+from pypy.translator.unsimplify import copyvar
+from pypy.annotation import model as annmodel
+from pypy.rpython.annlowlevel import MixLevelHelperAnnotator
+from pypy.translator.c import stacklesscode
 
 STORAGE_TYPES = [llmemory.Address,
                  lltype.Signed,
@@ -11,7 +18,7 @@
                   'longlong']
 
 def storage_type(T):
-    """Return the type used to save values of this type
+    """Return the index into STORAGE_TYPES 
     """
     if T is lltype.Void:
         return None
@@ -26,28 +33,64 @@
     else:
         raise Exception("don't know about %r" % (T,))
 
+
+
 STATE_HEADER = lltype.Struct('state_header',
                              ('f_back', lltype.Ptr(lltype.ForwardReference())),
                              ('state', lltype.Signed))
 STATE_HEADER.f_back.TO.become(STATE_HEADER)
 
+null_state = lltype.nullptr(STATE_HEADER)
+    
+## def func(x):
+##     return g() + x + 1
+
+## STATE_func_0 = lltype.Struct('STATE_func_0',
+##                              ('header', STATE_HEADER),
+##                              ('saved_long_0', Signed))
+
+## def func(x):
+##     if global_state.top:
+##         if global_state.restart_substate == 0:
+##             frame = cast_pointer(lltype.Ptr(STATE_func_0), global_state.top)
+##             x = frame.saved_long_0
+##             retval = global_state.long_retval
+##         else:
+##             abort()
+##     else:
+##         try:
+##             retval = g(x)
+##         except UnwindException, u:
+##             state = lltype.raw_malloc(STATE_func_0)
+##             state.saved_long_0 = x
+##             state.header.f_back = u.frame
+##             state.header.state = XXX
+##             u.frame = state.header
+##             raise
+        
+##     return retval + x + 1
+
+
 class StacklessTransfomer(object):
     def __init__(self, translator):
         self.translator = translator
 
-        null_frame_p = lltype.nullptr(STATE_HEADER)
-        
-        class StacklessData:
-            def __init__(self):
-                top = null_frame_p
-                bottom = null_frame_p
-                restart_substate = 0
-                retval_long = 0
-                retval_longlong = rarithmetic.r_longlong(0)
-                retval_double = 0.0
-                retval_void_p = llmemory.fakeaddress(None)
-
+        edata = translator.rtyper.getexceptiondata()
         self.frametypes = {}
+        self.curr_graph = None
+                
+        mixlevelannotator = MixLevelHelperAnnotator(translator.rtyper)
+        l2a = annmodel.lltype_to_annotation
+
+        slp_main_loop_graph = mixlevelannotator.getgraph(
+            stacklesscode.slp_main_loop, [], l2a(lltype.Void))
+        SLP_MAIN_LOOP_TYPE = lltype.FuncType([], lltype.Void)
+        self.slp_main_loop_type_ptr = model.Constant(lltype.functionptr(
+            SLP_MAIN_LOOP_TYPE, "slp_main_loop",
+            graph=slp_main_loop_graph),
+            SLP_MAIN_LOOP_TYPE)
+
+        mixlevelannotator.finish()
 
     def frame_type_for_vars(self, vars):
         types = [storage_type(v.concretetype) for v in vars]
@@ -71,6 +114,105 @@
             return T
 
     def transform_graph(self, graph):
+        self.resume_points = []
+        
+        assert self.curr_graph is None
+        self.curr_graph = graph
+        
         for block in graph.iterblocks():
-            pass
+            self.transform_block(block)
+        if self.resume_points:
+            XXX
+
+        self.curr_graph = None
+
+    def transform_block(self, block):
+        i = 0
+
+        edata = self.translator.rtyper.getexceptiondata()
+        etype = edata.lltype_of_exception_type
+        evalue = edata.lltype_of_exception_value
+        
+        while i < len(block.operations):
+            op = block.operations[i]
+            if op.opname in ('direct_call', 'indirect_call'):
+                after_block = support.split_block_with_keepalive(self.translator, self.curr_graph, block, i+1)
+                link = block.exits[0]
+
+                var_unwind_exception = varoftype(evalue)
+                
+                save_block = self.generate_save_block(link.args, var_unwind_exception)
+
+                newlink = model.Link(link.args + [var_unwind_exception], save_block, model.Constant(SystemExit))
+                block.exitswitch = model.c_last_exception
+                block.exits.append(newlink)
+                block = after_block
+                i = 0
+            else:
+                i += 1
+
+    def generate_save_block(self, varstosave, var_unwind_exception):
+        edata = self.translator.rtyper.getexceptiondata()
+        etype = edata.lltype_of_exception_type
+        evalue = edata.lltype_of_exception_value
+        inputargs = [copyvar(self.translator, v) for v in varstosave]
+        var_unwind_exception0 = copyvar(self.translator, var_unwind_exception)
+        from pypy.rpython.rclass import getinstancerepr
+        var_unwind_exception = varoftype(getinstancerepr(self.translator.rtyper,
+            self.translator.annotator.bookkeeper.getuniqueclassdef(SystemExit)).lowleveltype)
+
+        fields = []
+        for i, v in enumerate(varstosave):
+            if v.concretetype is not lltype.Void:
+                fields.append(('field_%d'%(i,), v.concretetype))
+        frame_type = lltype.Struct("S",
+                            ('header', STATE_HEADER),
+                            *fields)
+        
+
+        save_state_block = model.Block(inputargs + [var_unwind_exception])
+        saveops = save_state_block.operations
+        frame_state_var = varoftype(lltype.Ptr(frame_type))
+
+        saveops.append(model.SpaceOperation('malloc',
+                                        [model.Constant(frame_type, lltype.Void)],
+                                        frame_state_var))
+        
+        saveops.extend(self.generate_saveops(frame_state_var, inputargs))
+
+##             state.header.f_back = u.frame
+##             state.header.state = XXX
+##             u.frame = state.header
+        header_var = varoftype(lltype.Ptr(STATE_HEADER))
+        saveops.append(model.SpaceOperation("cast_pointer", [frame_state_var], header_var))
+        var_unwind_exception_frame = varoftype(lltype.Ptr(STATE_HEADER))
+        saveops.append(model.SpaceOperation("getfield",
+                                            [var_unwind_exception, model.Constant("frame", lltype.Void)],
+                                            var_unwind_exception_frame))
+        saveops.append(model.SpaceOperation("setfield",
+                                            [header_var, model.Constant("f_back", lltype.Void), var_unwind_exception_frame],
+                                            varoftype(lltype.Void)))
+        saveops.append(model.SpaceOperation("setfield",
+                                            [var_unwind_exception, model.Constant("frame", lltype.Void)],
+                                            varoftype(lltype.Void)))
+
+        save_state_block.closeblock(model.Link([varoftype(etype), varoftype(evalue)],
+                                               self.curr_graph.exceptblock))
+
+        return save_state_block
 
+        
+
+    def generate_saveops(self, frame_state_var, varstosave):
+        frame_type = frame_state_var.concretetype.TO
+        ops = []
+        for i, var in enumerate(varstosave):
+            t = storage_type(var.concretetype)
+            fname = model.Constant(frame_type._names[i+1], lltype.Void)
+            ops.append(model.SpaceOperation('setfield',
+                                            [frame_state_var, fname, var],
+                                            varoftype(lltype.Void)))
+
+        return ops
+        
+        

Modified: pypy/branch/stacklesscfg/pypy/translator/c/test/test_stacklesstransform.py
==============================================================================
--- pypy/branch/stacklesscfg/pypy/translator/c/test/test_stacklesstransform.py	(original)
+++ pypy/branch/stacklesscfg/pypy/translator/c/test/test_stacklesstransform.py	Fri Apr  7 18:58:23 2006
@@ -1,23 +1,40 @@
 from pypy.translator.c.stacklesstransform import StacklessTransfomer
 from pypy.rpython.memory.gctransform import varoftype
 from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.translator.translator import TranslationContext, graphof
+from pypy import conftest
 
-def test_frame_types():
-    st = StacklessTransfomer(None)
+## def test_frame_types():
+##     st = StacklessTransfomer(None)
 
-    signed = varoftype(lltype.Signed)
-    ptr = varoftype(lltype.Ptr(lltype.GcStruct("S")))
-    addr = varoftype(llmemory.Address)
-    float = varoftype(lltype.Float)
-    longlong = varoftype(lltype.SignedLongLong)
+##     signed = varoftype(lltype.Signed)
+##     ptr = varoftype(lltype.Ptr(lltype.GcStruct("S")))
+##     addr = varoftype(llmemory.Address)
+##     float = varoftype(lltype.Float)
+##     longlong = varoftype(lltype.SignedLongLong)
 
-    ft4vars = st.frame_type_for_vars
+##     ft4vars = st.frame_type_for_vars
     
-    s1 = ft4vars([signed])
-    assert 'header' in s1._flds
-    assert len(s1._flds) == 2
+##     s1 = ft4vars([signed])
+##     assert 'header' in s1._flds
+##     assert len(s1._flds) == 2
 
-    s2_1 = ft4vars([signed, ptr])
-    s2_2 = ft4vars([ptr, signed])
+##     s2_1 = ft4vars([signed, ptr])
+##     s2_2 = ft4vars([ptr, signed])
 
-    assert s2_1 is s2_2
+##     assert s2_1 is s2_2
+
+def test_simple_transform():
+    def g():
+        return 2
+    def example(x):
+        return g() + x + 1
+    t = TranslationContext()
+    t.buildannotator().build_types(example, [int])
+    t.buildrtyper().specialize()
+    example_graph = graphof(t, example)
+    st = StacklessTransfomer(t)
+    st.transform_graph(example_graph)
+    if conftest.option.view:
+        t.view()
+    



More information about the Pypy-commit mailing list