[pypy-svn] r25678 - in pypy/dist/pypy/translator/stackless: . test

mwh at codespeak.net mwh at codespeak.net
Mon Apr 10 23:35:45 CEST 2006


Author: mwh
Date: Mon Apr 10 23:35:44 2006
New Revision: 25678

Modified:
   pypy/dist/pypy/translator/stackless/code.py
   pypy/dist/pypy/translator/stackless/test/test_transform.py
   pypy/dist/pypy/translator/stackless/transform.py
Log:
what seems like some good progress with the stackless transformation.
support for catching a resumed exception.  this required surprisingly few
special cases.  the test armin and i wrote earlier today now passes.
support for multiple return types.  only float is tested, though, and the code
is pretty horrible in places.
lots and lots of smaller cleanups.
probably the next step is much more extensive testing.


Modified: pypy/dist/pypy/translator/stackless/code.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/code.py	(original)
+++ pypy/dist/pypy/translator/stackless/code.py	Mon Apr 10 23:35:44 2006
@@ -2,56 +2,65 @@
 from pypy.rpython import rarithmetic
 
 STATE_HEADER = lltype.GcStruct('state_header',
-                             ('f_back', lltype.Ptr(lltype.GcForwardReference())),
-                             ('restartstate', lltype.Signed),
-                             ('function', llmemory.Address),)
+                               ('f_back',       lltype.Ptr(lltype.GcForwardReference())),
+                               ('restartstate', lltype.Signed),
+                               ('function',     llmemory.Address),
+                               ('retval_type',  lltype.Signed))
 STATE_HEADER.f_back.TO.become(STATE_HEADER)
 
 null_state = lltype.nullptr(STATE_HEADER)
 
 def decode_state(currentframe): 
-    return currentframe.function, "long", currentframe.restartstate
+    return (currentframe.function,
+            currentframe.retval_type,
+            currentframe.restartstate)
 
 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.retval_float = 0.0
+        self.retval_void_p = llmemory.NULL
         self.exception = None
 
 global_state = StacklessData()
 
-def call_function(fn, signature):
-    if signature == 'void':
+RETVAL_VOID, RETVAL_LONG, RETVAL_LONGLONG, RETVAL_FLOAT, RETVAL_VOID_P = \
+             range(5)
+
+def call_function(fn, retval_code):
+    if retval_code == RETVAL_VOID:
         lloperation.llop.unsafe_call(lltype.Void, fn)
-    elif signature == 'long':
+    elif retval_code == RETVAL_LONG:
         global_state.retval_long = lloperation.llop.unsafe_call(
             lltype.Signed, fn)
-    elif signature == 'longlong':
+    elif retval_code == RETVAL_LONGLONG:
         global_state.retval_longlong = lloperation.llop.unsafe_call(
             lltype.SignedLongLong, fn)
-    elif signature == 'float':
-        global_state.retval_double = lloperation.llop.unsafe_call(
+    elif retval_code == RETVAL_FLOAT:
+        global_state.retval_float = lloperation.llop.unsafe_call(
             lltype.Float, fn)
-    elif signature == 'pointer':
+    elif retval_code == RETVAL_VOID_P:
         global_state.retval_void_p = lloperation.llop.unsafe_call(
             llmemory.Address, fn)
 
-null_address = llmemory.fakeaddress(None)
-
 class UnwindException(Exception):
     def __init__(self):
-        self.frame_top = null_state   # points to frame that first caught 
-                                      # the UnwindException 
-        self.frame_bottom = null_state 
-        # walking frame_top.f_back.f_back... goes to frame_bottom 
-        #
+        # frame_top points to frame that first caught the
+        # UnwindException, whilst frame_bottom points to the frame
+        # that most recently caught the UnwindException.  frame_bottom
+        # is only needed to efficiently tack frames on to the end of
+        # the stack.  walking frame_top.f_back.f_back... goes to
+        # frame_bottom
+        self.frame_top = null_state
+        self.frame_bottom = null_state
 
 def slp_main_loop():
+    """
+    slp_main_loop() keeps resuming...
+    """
     currentframe = global_state.top
     
     while currentframe:
@@ -60,7 +69,7 @@
         fn, signature, global_state.restart_substate = decode_state(currentframe)
         try:
             call_function(fn, signature)
-        except UnwindException, u:   #XXX annotation support needed 
+        except UnwindException, u:   #XXX annotation support needed
             nextframe = u.frame_top 
         except Exception, e:
             global_state.exception = e
@@ -81,6 +90,8 @@
         u.frame_bottom = frame_state
 
 def resume_state():
+    """Return and zero the 'restart_substate', the index of the resume
+    point to jump to or zero for the not resuming case."""
     x = global_state.restart_substate
     global_state.restart_substate = 0
     return x 
@@ -93,8 +104,31 @@
 #        global_state.top = None
 # XXX and then insert the rtyped graph of this into functions
         
+def fetch_retval_void():
+    if global_state.exception:
+        raise global_state.exception
+
 def fetch_retval_long():
     if global_state.exception:
         raise global_state.exception
     else:
         return global_state.retval_long
+
+def fetch_retval_longlong():
+    if global_state.exception:
+        raise global_state.exception
+    else:
+        return global_state.retval_longlong
+
+def fetch_retval_float():
+    if global_state.exception:
+        raise global_state.exception
+    else:
+        return global_state.retval_float
+
+def fetch_retval_void_p():
+    if global_state.exception:
+        raise global_state.exception
+    else:
+        return global_state.retval_void_p
+

Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/test/test_transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/test/test_transform.py	Mon Apr 10 23:35:44 2006
@@ -46,6 +46,18 @@
     res = llinterp_stackless_function(example, example, g)
     assert res == 3
 
+def test_simple_transform_llinterp_float():
+    def check(x):
+        if x:
+            raise code.UnwindException
+    def g(x):
+        check(x)
+        return x + 0.125
+    def example(x):
+        return int((g(x) + 1)*1000.0)
+    res = llinterp_stackless_function(example, example, g)
+    assert res == 2125
+
 def test_simple_transform():
     def check(x):
         if x:
@@ -97,7 +109,6 @@
     assert llinterp.type_name(info.value.args[0]) == 'KeyError'
 
 def test_resume_with_exception_handling():
-    py.test.skip("in progress")
     def check(x):
         if x:
             raise code.UnwindException
@@ -117,9 +128,6 @@
         return y + 1
     res = llinterp_stackless_function(example, example, g, h)
     assert res == 0
-    
-    
-    
 
 def rtype_stackless_function(fn, *stacklessfuncs):
     s_list_of_strings = annmodel.SomeList(ListDef(None, annmodel.SomeString()))
@@ -133,10 +141,14 @@
     # helpers which can cause slp_main_loop to get re-annotated after
     # it is rtyped.  which is bad.
     unwind_def = bk.getuniqueclassdef(code.UnwindException)
-    unwind_def.generalize_attr('frame_top', annmodel.SomePtr(lltype.Ptr(code.STATE_HEADER)))
-    unwind_def.generalize_attr('frame_bottom', annmodel.SomePtr(lltype.Ptr(code.STATE_HEADER)))
+    unwind_def.generalize_attr('frame_top',
+                               annmodel.SomePtr(lltype.Ptr(code.STATE_HEADER)))
+    unwind_def.generalize_attr('frame_bottom',
+                               annmodel.SomePtr(lltype.Ptr(code.STATE_HEADER)))
     
-    annotator.build_types(fn, [s_list_of_strings])
+    s_returnvar = annotator.build_types(fn, [s_list_of_strings])
+    if not isinstance(s_returnvar, annmodel.SomeInteger):
+        raise Exception, "this probably isn't going to work"
     t.buildrtyper().specialize()
 
     st = StacklessTransfomer(t)
@@ -161,7 +173,7 @@
 
     t = rtype_stackless_function(entry_point, *stacklessfuncs)
 
-    cbuilder = CStandaloneBuilder(t, entry_point)#, gcpolicy=gc.BoehmGcPolicy)
+    cbuilder = CStandaloneBuilder(t, entry_point)
     cbuilder.generate_source()
     cbuilder.compile()
     return cbuilder.cmdexec('').strip()
@@ -173,7 +185,7 @@
         except code.UnwindException, u:
             code.global_state.top = u.frame_top
             code.slp_main_loop()
-            r = code.global_state.retval_long
+            return code.global_state.retval_long
         return r
 
     t = rtype_stackless_function(entry_point, *stacklessfuncs)

Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Mon Apr 10 23:35:44 2006
@@ -36,38 +36,41 @@
     else:
         raise Exception("don't know about %r" % (T,))
 
-## 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
+# a simple example of what the stackless transform does
+#
+# def func(x):
+#     return g() + x + 1
+#
+# STATE_func_0 = lltype.Struct('STATE_func_0',
+#                              ('header', code.STATE_HEADER),
+#                              ('saved_long_0', Signed))
+#
+# def func(x):
+#     if global_state.restart_substate == 0:
+#         try:
+#             retval = g(x)
+#         except code.UnwindException, u:
+#             state = lltype.malloc(STATE_func_0)
+#             state.header.restartstate = 1
+#             state.header.function = llmemory.cast_ptr_to_adr(func)
+#             state.header.retval_type = code.RETVAL_LONG
+#             state.saved_long_0 = x
+#             code.add_frame_state(u, state.header)
+#             raise
+#     elif global_state.restart_substate == 1:
+#         state = lltype.cast_pointer(lltype.Ptr(STATE_func_0),
+#                                     global_state.top)
+#         x = state.saved_long_0
+#         retval = global_state.long_retval
+#     else:
+#         abort()
+#     return retval + x + 1
 
 class ResumePoint:
-    def __init__(self, var_result, link_to_resumption, frame_state_type):
+    def __init__(self, var_result, args, links_to_resumption, frame_state_type):
         self.var_result = var_result
-        self.link_to_resumption = link_to_resumption
+        self.args = args
+        self.links_to_resumption = links_to_resumption
         self.frame_state_type = frame_state_type
 
 class StacklessTransfomer(object):
@@ -86,8 +89,9 @@
         mixlevelannotator = MixLevelHelperAnnotator(translator.rtyper)
         l2a = annmodel.lltype_to_annotation
 
-        annotations = [annmodel.SomeInstance(bk.getuniqueclassdef(code.UnwindException)),
-                       annmodel.SomePtr(lltype.Ptr(STATE_HEADER))]
+        annotations = [
+            annmodel.SomeInstance(bk.getuniqueclassdef(code.UnwindException)),
+            annmodel.SomePtr(lltype.Ptr(STATE_HEADER))]
 
         add_frame_state_graph = mixlevelannotator.getgraph(
             code.add_frame_state,
@@ -108,6 +112,14 @@
             graph=resume_state_graph),
             lltype.Ptr(RESUME_STATE_TYPE))
 
+        FETCH_RETVAL_VOID_TYPE = lltype.FuncType([], lltype.Void)
+        fetch_retval_void_graph = mixlevelannotator.getgraph(
+            code.fetch_retval_void, [], annmodel.s_None)
+        self.fetch_retval_void_ptr = model.Constant(lltype.functionptr(
+            FETCH_RETVAL_VOID_TYPE, "fetch_retval_void",
+            graph=fetch_retval_void_graph),
+            lltype.Ptr(FETCH_RETVAL_VOID_TYPE))
+
         FETCH_RETVAL_LONG_TYPE = lltype.FuncType([], lltype.Signed)
         fetch_retval_long_graph = mixlevelannotator.getgraph(
             code.fetch_retval_long, [], annmodel.SomeInteger())
@@ -116,13 +128,38 @@
             graph=fetch_retval_long_graph),
             lltype.Ptr(FETCH_RETVAL_LONG_TYPE))
 
+        FETCH_RETVAL_LONGLONG_TYPE = lltype.FuncType([], lltype.Signed)
+        fetch_retval_longlong_graph = mixlevelannotator.getgraph( # WAA!
+            code.fetch_retval_longlong, [], annmodel.SomeInteger(size=2))
+        self.fetch_retval_longlong_ptr = model.Constant(lltype.functionptr(
+            FETCH_RETVAL_LONGLONG_TYPE, "fetch_retval_longlong",
+            graph=fetch_retval_longlong_graph),
+            lltype.Ptr(FETCH_RETVAL_LONGLONG_TYPE))
+
+        FETCH_RETVAL_FLOAT_TYPE = lltype.FuncType([], lltype.Float)
+        fetch_retval_float_graph = mixlevelannotator.getgraph(
+            code.fetch_retval_float, [], annmodel.SomeFloat())
+        self.fetch_retval_float_ptr = model.Constant(lltype.functionptr(
+            FETCH_RETVAL_FLOAT_TYPE, "fetch_retval_float",
+            graph=fetch_retval_float_graph),
+            lltype.Ptr(FETCH_RETVAL_FLOAT_TYPE))
+
+        FETCH_RETVAL_VOID_P_TYPE = lltype.FuncType([], llmemory.Address)
+        fetch_retval_void_p_graph = mixlevelannotator.getgraph(
+            code.fetch_retval_void_p, [], annmodel.SomeAddress())
+        self.fetch_retval_void_p_ptr = model.Constant(lltype.functionptr(
+            FETCH_RETVAL_VOID_P_TYPE, "fetch_retval_void_p",
+            graph=fetch_retval_void_p_graph),
+            lltype.Ptr(FETCH_RETVAL_VOID_P_TYPE))
+
         mixlevelannotator.finish()
 
         s_global_state = bk.immutablevalue(code.global_state)
         r_global_state = translator.rtyper.getrepr(s_global_state)
-        self.ll_global_state = model.Constant(r_global_state.convert_const(code.global_state),
-                                              r_global_state.lowleveltype)
-        
+        self.ll_global_state = model.Constant(
+            r_global_state.convert_const(code.global_state),
+            r_global_state.lowleveltype)
+
 
     def frame_type_for_vars(self, vars):
         types = [storage_type(v.concretetype) for v in vars]
@@ -138,7 +175,8 @@
             fields = []
             for i, k in enumerate(key):
                 for j in range(k):
-                    fields.append(('state_%s_%d'%(STORAGE_FIELDS[i], j), STORAGE_TYPES[i]))
+                    fields.append(
+                        ('state_%s_%d'%(STORAGE_FIELDS[i], j), STORAGE_TYPES[i]))
             T = lltype.Struct("state_%d_%d_%d_%d"%tuple(key),
                               ('header', STATE_HEADER),
                               *fields)
@@ -171,7 +209,8 @@
    
         ops.append(model.SpaceOperation(
             "getfield",
-            [self.ll_global_state, model.Constant(llfieldname, lltype.Void)],
+            [self.ll_global_state,
+             model.Constant(llfieldname, lltype.Void)],
             tmpvar))
         if tmpvar is not targetvar: 
             ops.append(model.SpaceOperation(
@@ -181,11 +220,14 @@
 
     def insert_resume_handling(self, graph):
         old_start_block = graph.startblock
-        newinputargs = [copyvar(self.translator, v) for v in old_start_block.inputargs]
+        newinputargs = [copyvar(self.translator, v)
+                        for v in old_start_block.inputargs]
         new_start_block = model.Block(newinputargs)
         var_resume_state = varoftype(lltype.Signed)
         new_start_block.operations.append(
-            model.SpaceOperation("direct_call", [self.resume_state_ptr], var_resume_state))
+            model.SpaceOperation("direct_call",
+                                 [self.resume_state_ptr],
+                                 var_resume_state))
         not_resuming_link = model.Link(newinputargs, old_start_block, 0)
         not_resuming_link.llexitcase = 0
         resuming_links = []
@@ -197,25 +239,62 @@
             frame_top = varoftype(lltype.Ptr(frame_state_type))
             ops.extend(self.ops_read_global_state_field(frame_top, "top"))
             ops.append(model.SpaceOperation(
-                "setfield", [self.ll_global_state, model.Constant("inst_top", lltype.Void),
-                             model.Constant(null_state, lltype.typeOf(null_state))],
-                            varoftype(lltype.Void)))
-            i = 0
-            for arg in resume_point.link_to_resumption.args:
-                newarg = copyvar(self.translator, arg)
-                if arg is resume_point.var_result:
-                    ops.append(model.SpaceOperation("direct_call", [self.fetch_retval_long_ptr], newarg))
-                else:
-                    # frame_state_type._names[0] is 'header'
-                    fname = model.Constant(frame_state_type._names[i+1], lltype.Void)
-                    ops.append(model.SpaceOperation(
-                        'getfield', [frame_top, fname], newarg))
-                    i += 1
-                newargs.append(newarg)
+                "setfield",
+                [self.ll_global_state,
+                 model.Constant("inst_top", lltype.Void),
+                 model.Constant(null_state, lltype.typeOf(null_state))],
+                varoftype(lltype.Void)))
+            varmap = {}
+            for i, arg in enumerate(resume_point.args):
+                newarg = varmap[arg] = copyvar(self.translator, arg)
+                assert arg is not resume_point.var_result
+                fname = model.Constant(frame_state_type._names[i+1], lltype.Void)
+                ops.append(model.SpaceOperation(
+                    'getfield', [frame_top, fname], newarg))
+
+            r = storage_type(resume_point.var_result.concretetype)
+            if r is not None:
+                rettype = STORAGE_TYPES[r]
+            else:
+                rettype = lltype.Void
+            if rettype == lltype.Signed:
+                getretval = self.fetch_retval_long_ptr
+            if rettype == lltype.SignedLongLong:
+                getretval = self.fetch_retval_longlong_ptr
+            elif rettype == lltype.Void:
+                getretval = self.fetch_retval_void_ptr
+            elif rettype == lltype.Float:
+                getretval = self.fetch_retval_float_ptr
+            elif rettype == llmemory.Address:
+                getretval = self.fetch_retval_void_p_ptr
+            varmap[resume_point.var_result] = retval = (
+                copyvar(self.translator, resume_point.var_result))
+            ops.append(model.SpaceOperation("direct_call", [getretval], retval))
+
             newblock.operations.extend(ops)
-            newblock.closeblock(model.Link(newargs, resume_point.link_to_resumption.target))
+
+            def rename(arg):
+                if isinstance(arg, model.Variable):
+                    if arg in varmap:
+                        return varmap[arg]
+                    else:
+                        assert arg in [l.last_exception, l.last_exc_value]
+                        r = copyvar(self.translator, arg)
+                        varmap[arg] = r
+                        return r
+                else:
+                    return arg
+
+            newblock.closeblock(*[l.copy(rename)
+                                  for l in resume_point.links_to_resumption])
+            # this check is a bit implicit!
+            if len(resume_point.links_to_resumption) > 1:
+                newblock.exitswitch = model.c_last_exception
+            else:
+                newblock.exitswitch = None
             
-            resuming_links.append(model.Link([], newblock, resume_point_index+1))
+            resuming_links.append(
+                model.Link([], newblock, resume_point_index+1))
             resuming_links[-1].llexitcase = resume_point_index+1
         new_start_block.exitswitch = var_resume_state
         new_start_block.closeblock(not_resuming_link, *resuming_links)
@@ -234,11 +313,14 @@
         while i < len(block.operations):
             op = block.operations[i]
             if op.opname in ('direct_call', 'indirect_call'):
-                if i == len(block.operations) - 1 and block.exitswitch == model.c_last_exception:
+                if i == len(block.operations) - 1 \
+                       and block.exitswitch == model.c_last_exception:
                     link = block.exits[0]
                 else:
-                    link = support.split_block_with_keepalive(self.translator, block, i+1)
+                    link = support.split_block_with_keepalive(
+                        self.translator, block, i+1)
                     block.exitswitch = model.c_last_exception
+                    link.llexitcase = None
                 var_unwind_exception = varoftype(evalue)
                
                 # for the case where we are resuming to an except:
@@ -254,16 +336,25 @@
                 # function be called right at the end of the resuming
                 # block, and that it is called even if the return
                 # value is not again used.
-                args = [v for v in link.args 
-                        if v is not op.result and v.concretetype is not lltype.Void]
+                args = []
+                for l in block.exits:
+                    for arg in link.args:
+                        if isinstance(arg, model.Variable) \
+                           and arg.concretetype is not lltype.Void \
+                           and arg is not op.result \
+                           and arg not in args:
+                            args.append(arg)
+                
                 save_block, frame_state_type = self.generate_save_block(
                                 args, var_unwind_exception)
 
-                self.resume_points.append(ResumePoint(op.result, link, frame_state_type))
+                self.resume_points.append(
+                    ResumePoint(op.result, args, block.exits, frame_state_type))
 
                 newlink = model.Link(args + [var_unwind_exception], 
                                      save_block, code.UnwindException)
-                newlink.last_exception = model.Constant(code.UnwindException, etype) 
+                newlink.last_exception = model.Constant(code.UnwindException,
+                                                        etype)
                 newlink.last_exc_value = var_unwind_exception
                 newexits = list(block.exits)
                 newexits.insert(1, newlink)
@@ -299,20 +390,23 @@
         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.append(model.SpaceOperation(
+            'malloc',
+            [model.Constant(frame_type, lltype.Void)],
+            frame_state_var))
         
         saveops.extend(self.generate_saveops(frame_state_var, inputargs))
 
         var_exc = varoftype(self.unwind_exception_type)
-        saveops.append(model.SpaceOperation("cast_pointer", [var_unwind_exception], 
-                                            var_exc))
+        saveops.append(model.SpaceOperation(
+            "cast_pointer",
+            [var_unwind_exception], 
+            var_exc))
         
         var_header = varoftype(lltype.Ptr(STATE_HEADER))
     
-        # XXX should this be getsubstruct?
-        saveops.append(model.SpaceOperation("getsubstruct", [frame_state_var, model.Constant("header", lltype.Void)], var_header))
+        saveops.append(model.SpaceOperation(
+            "cast_pointer", [frame_state_var], var_header))
 
         saveops.append(model.SpaceOperation(
             "direct_call",
@@ -320,39 +414,51 @@
             varoftype(lltype.Void)))
 
         saveops.append(model.SpaceOperation(
-            "setfield", [var_header, model.Constant("restartstate", lltype.Void), 
-                         model.Constant(len(self.resume_points)+1, lltype.Signed)],
-                        varoftype(lltype.Void)))
-        # XXX add returntypes 
+            "setfield",
+            [var_header, model.Constant("restartstate", lltype.Void), 
+             model.Constant(len(self.resume_points)+1, lltype.Signed)],
+            varoftype(lltype.Void)))
 
         funcptr = rtyper.type_system.getcallable(self.curr_graph)
         saveops.append(model.SpaceOperation(
-            "setfield", [var_header, model.Constant("function", lltype.Void), 
-                         model.Constant(llmemory.fakeaddress(funcptr), llmemory.Address)],
-                        varoftype(lltype.Void)))
+            "setfield",
+            [var_header, model.Constant("function", lltype.Void), 
+             model.Constant(llmemory.fakeaddress(funcptr), llmemory.Address)],
+            varoftype(lltype.Void)))
+        rettype = lltype.typeOf(funcptr).TO.RESULT
+        retval_type = {None: code.RETVAL_VOID,
+                       0: code.RETVAL_VOID_P,
+                       1: code.RETVAL_LONG,
+                       2: code.RETVAL_FLOAT,
+                       3: code.RETVAL_LONGLONG}[storage_type(rettype)]
+        
+        saveops.append(model.SpaceOperation(
+            "setfield", [var_header, model.Constant("retval_type", lltype.Void), 
+                         model.Constant(retval_type, lltype.Signed)],
+            varoftype(lltype.Void)))
 
         type_repr = rclass.get_type_repr(rtyper)
-        c_unwindexception = model.Constant(type_repr.convert_const(code.UnwindException), etype)
+        c_unwindexception = model.Constant(
+            type_repr.convert_const(code.UnwindException), etype)
         if not hasattr(self.curr_graph.exceptblock.inputargs[0], 'concretetype'):
             self.curr_graph.exceptblock.inputargs[0].concretetype = etype
         if not hasattr(self.curr_graph.exceptblock.inputargs[1], 'concretetype'):
             self.curr_graph.exceptblock.inputargs[1].concretetype = evalue
-        save_state_block.closeblock(model.Link([c_unwindexception, var_unwind_exception], 
-                                               self.curr_graph.exceptblock))
-        self.translator.rtyper._convert_link(save_state_block, save_state_block.exits[0])
+        save_state_block.closeblock(model.Link(
+            [c_unwindexception, var_unwind_exception], 
+            self.curr_graph.exceptblock))
+        self.translator.rtyper._convert_link(
+            save_state_block, save_state_block.exits[0])
         return save_state_block, frame_type
         
-
     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)))
-
+            ops.append(model.SpaceOperation(
+                'setfield',
+                [frame_state_var, fname, var],
+                varoftype(lltype.Void)))
         return ops
-        
-        



More information about the Pypy-commit mailing list