[pypy-svn] r33945 - in pypy/dist/pypy/translator: cli jvm jvm/src jvm/test oosupport

niko at codespeak.net niko at codespeak.net
Tue Oct 31 13:58:47 CET 2006


Author: niko
Date: Tue Oct 31 13:58:47 2006
New Revision: 33945

Added:
   pypy/dist/pypy/translator/jvm/test/test_snippet.py
Modified:
   pypy/dist/pypy/translator/cli/function.py
   pypy/dist/pypy/translator/jvm/conftest.py
   pypy/dist/pypy/translator/jvm/database.py
   pypy/dist/pypy/translator/jvm/generator.py
   pypy/dist/pypy/translator/jvm/genjvm.py
   pypy/dist/pypy/translator/jvm/node.py
   pypy/dist/pypy/translator/jvm/opcodes.py
   pypy/dist/pypy/translator/jvm/option.py
   pypy/dist/pypy/translator/jvm/src/PyPy.java
   pypy/dist/pypy/translator/jvm/test/runtest.py
   pypy/dist/pypy/translator/jvm/test/test_bool.py
   pypy/dist/pypy/translator/oosupport/function.py
Log:
(antocuni, niko) 

Get the jvm backend to run the merciless and terrifying test_snippet.
Refactor the oosupport/function very slightly to emit labels for each block
in a central place.



Modified: pypy/dist/pypy/translator/cli/function.py
==============================================================================
--- pypy/dist/pypy/translator/cli/function.py	(original)
+++ pypy/dist/pypy/translator/cli/function.py	Tue Oct 31 13:58:47 2006
@@ -87,14 +87,12 @@
         self.ilasm.label(label)
 
     def render_return_block(self, block):
-        self.set_label(self._get_block_name(block))
         return_var = block.inputargs[0]
         if return_var.concretetype is not Void:
             self.load(return_var)
         self.ilasm.opcode('ret')
 
     def render_raise_block(self, block):
-        self.set_label(self._get_block_name(block))        
         exc = block.inputargs[1]
         self.load(exc)
         self.ilasm.opcode('throw')

Modified: pypy/dist/pypy/translator/jvm/conftest.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/conftest.py	(original)
+++ pypy/dist/pypy/translator/jvm/conftest.py	Tue Oct 31 13:58:47 2006
@@ -5,10 +5,10 @@
 option = py.test.Config.addoptions(
     "pypy-jvm options",
 
-    Option('--javac', action='store', dest='javac', default='javac',
-           help='Define the java compiler to use'),
     Option('--java', action='store', dest='java', default='java',
            help='Define the java executable to use'),
+    Option('--jasmin', action='store', dest='java', default='java',
+           help='Define the jasmin script to use'),
     Option('--noassemble', action='store_true', dest="noasm", default=False,
            help="don't assemble jasmin files"),
     Option('--package', action='store', dest='package', default='pypy',

Modified: pypy/dist/pypy/translator/jvm/database.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/database.py	(original)
+++ pypy/dist/pypy/translator/jvm/database.py	Tue Oct 31 13:58:47 2006
@@ -95,7 +95,7 @@
         """
         if graph in self._functions:
             return self._functions[graph]
-        classnm = self._make_unique_name(graph.name)
+        classnm = "pypy."+self._make_unique_name(graph.name)
         classobj = node.Class(classnm)
         funcobj = self._function_for_graph(classobj, "invoke", True, graph)
         classobj.add_method(funcobj)
@@ -109,6 +109,9 @@
     def pop(self):
         return self._pending_nodes.pop()
 
+    def gen_constants(self, gen):
+        pass
+
     # Type translation functions
 
     def escape_name(self, nm):
@@ -139,7 +142,7 @@
             return XXX
 
         # Uh-oh
-        unhandled_case    
+        unhandled_case
 
     # Invoked by genoo:
     #   I am not sure that we need them

Modified: pypy/dist/pypy/translator/jvm/generator.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/generator.py	(original)
+++ pypy/dist/pypy/translator/jvm/generator.py	Tue Oct 31 13:58:47 2006
@@ -14,7 +14,7 @@
 BRANCH    = 1          # Opcode is a branching opcode (implies a label argument)
 INVOKE    = 2          # Opcode is some kind of method invocation
 CONST5    = 4          # Opcode is specialized for int arguments from -1 to 5
-CONST3    = 4          # Opcode is specialized for int arguments from 0 to 3
+CONST3    = 8          # Opcode is specialized for int arguments from 0 to 3
 
 # ___________________________________________________________________________
 # JVM Opcodes:
@@ -29,6 +29,9 @@
         """
         self.flags = flags
         self.jvmstr = jvmstr
+
+    def __repr__(self):
+        return "<Opcode %s:%x>" % (self.jvmstr, self.flags)
         
     def specialize_opcode(self, args):
         """ Process the argument list according to the various flags.
@@ -197,11 +200,15 @@
 class Method(object):
     def __init__(self, classnm, methnm, desc, opcode=INVOKESTATIC):
         self.opcode = opcode
-        self.class_name = classnm
-        self.method_name = methnm
-        self.descriptor = desc
+        self.class_name = classnm  # String, ie. "java.lang.Math"
+        self.method_name = methnm  # String "abs"
+        self.descriptor = desc     # String, (I)I
     def invoke(self, gen):
         gen._instr(self.opcode, self)
+    def jasmin_syntax(self):
+        return "%s/%s%s" % (self.class_name.replace('.','/'),
+                            self.method_name,
+                            self.descriptor)
 
 MATHIABS =              Method('java.lang.Math', 'abs', '(I)I')
 MATHLABS =              Method('java.lang.Math', 'abs', '(L)L')
@@ -228,6 +235,12 @@
                                '(Ljava/lang/String;)D')
 PYPYSTRTOCHAR =         Method('pypy.PyPy', 'str_to_char',
                                '(Ljava/lang/String;)C')
+PYPYDUMPINT  =          Method('pypy.PyPy', 'dump_int', '(I)V')
+PYPYDUMPUINT  =         Method('pypy.PyPy', 'dump_uint', '(I)V')
+PYPYDUMPLONG  =         Method('pypy.PyPy', 'dump_long', '(L)V')
+PYPYDUMPDOUBLE  =       Method('pypy.PyPy', 'dump_double', '(D)V')
+PYPYDUMPSTRING  =       Method('pypy.PyPy', 'dump_string', '([B)V')
+PYPYDUMPBOOLEAN =       Method('pypy.PyPy', 'dump_boolean', '(Z)V')
 
 class JVMGenerator(Generator):
 
@@ -283,9 +296,11 @@
         # depending on their type [this is compute by type_width()]
         self.next_offset = 0
         self.local_vars = {}
-        for idx, var in enumerate(argvars):
-            self.local_vars[var] = self.next_offset
-            self.next_offset += argtypes[idx].type_width()
+        for idx, ty in enumerate(argtypes):
+            if idx < len(argvars):
+                var = argvars[idx]
+                self.local_vars[var] = self.next_offset
+            self.next_offset += ty.type_width()
         # Prepare a map for the local variable indices we will add
         # Let the subclass do the rest of the work; note that it does
         # not need to know the argvars parameter, so don't pass it
@@ -299,9 +314,9 @@
         unimplemented        
 
     def end_function(self):
+        self._end_function()
         del self.next_offset
         del self.local_vars
-        self._end_function()
 
     def _end_function(self):
         unimplemented
@@ -322,7 +337,10 @@
     def load_jvm_var(self, vartype, varidx):
         """ Loads from jvm slot #varidx, which is expected to hold a value of
         type vartype """
-        self._instr(LOAD.for_type(vartype), varidx)
+        opc = LOAD.for_type(vartype)
+        print "load_jvm_jar: vartype=%s varidx=%s opc=%s" % (
+            repr(vartype), repr(varidx), repr(opc))
+        self._instr(opc, varidx)
 
     def store_jvm_var(self, vartype, varidx):
         """ Loads from jvm slot #varidx, which is expected to hold a value of
@@ -442,6 +460,7 @@
     def load(self, value):
         if isinstance(value, flowmodel.Variable):
             jty, idx = self._var_data(value)
+            print "load_jvm_var: jty=%s idx=%s" % (repr(jty), repr(idx))
             return self.load_jvm_var(jty, idx)
 
         if isinstance(value, flowmodel.Constant):
@@ -608,7 +627,7 @@
         self.out = open(jfile, 'w')
 
         # Write the JasminXT header
-        self.out.write(".bytecode XX\n")
+        #self.out.write(".bytecode XX\n")
         #self.out.write(".source \n")
         self.out.write(".class public %s\n" % iclassnm)
         self.out.write(".super java/lang/Object\n") # ?
@@ -617,6 +636,9 @@
         self.out.close()
         self.out = None
 
+    def close(self):
+        assert self.out is None, "Unended class"
+
     def add_field(self, fname, fdesc):
         # TODO --- Signature for generics?
         # TODO --- these must appear before methods, do we want to buffer
@@ -628,11 +650,13 @@
         # Throws clause?  Only use RuntimeExceptions?
         kw = ['public']
         if static: kw.append('static')
-        self.out.write('.method %s %s (%s)%s\n' % (
-            funcname, " ".join(kw),
+        self.out.write('.method %s %s(%s)%s\n' % (
+            " ".join(kw), funcname,
             "".join(argtypes), rettype))
 
     def _end_function(self):
+        self.out.write('.limit stack 100\n') # HACK, track max offset
+        self.out.write('.limit locals %d\n' % self.next_offset)
         self.out.write('.end method\n')
 
     def mark(self, lbl):
@@ -643,10 +667,14 @@
 
     def _instr(self, opcode, *args):
         jvmstr, args = opcode.specialize_opcode(args)
+        # XXX this whole opcode flag things is stupid, redo to be class based
         if opcode.flags & BRANCH:
             assert len(args) == 1
             _, lblnum, lbldesc = args[0]
             args = ('%s_%s' % (lbldesc, lblnum),)
+        if opcode.flags & INVOKE:
+            assert len(args) == 1
+            args = (args[0].jasmin_syntax(),)
         self.out.write('    %s %s\n' % (
             jvmstr, " ".join([str(s) for s in args])))
 

Modified: pypy/dist/pypy/translator/jvm/genjvm.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/genjvm.py	(original)
+++ pypy/dist/pypy/translator/jvm/genjvm.py	Tue Oct 31 13:58:47 2006
@@ -2,7 +2,7 @@
 Backend for the JVM.
 """
 
-import os, os.path, subprocess
+import os, os.path, subprocess, sys
 
 import py
 from pypy.tool.udir import udir
@@ -17,7 +17,30 @@
 from pypy.translator.jvm.opcodes import opcodes
 
 class JvmError(Exception):
-    """ Indicates an error occurred in the JVM runtime """
+    """ Indicates an error occurred in JVM backend """
+
+    def pretty_print(self):
+        print str(self)
+    pass
+
+class JvmSubprogramError(JvmError):
+    """ Indicates an error occurred running some program """
+    def __init__(self, res, args, stdout, stderr):
+        self.res = res
+        self.args = args
+        self.stdout = stdout
+        self.stderr = stderr
+
+    def __str__(self):
+        return "Error code %d running %s" % (self.res, repr(self.args))
+        
+    def pretty_print(self):
+        JvmError.pretty_print(self)
+        print "vvv Stdout vvv\n"
+        print self.stdout
+        print "vvv Stderr vvv\n"
+        print self.stderr
+        
     pass
 
 class JvmGeneratedSource(object):
@@ -56,17 +79,35 @@
         # Compute directory where .class files should go
         self.classdir = self.javadir
 
+    def _invoke(self, args, allow_stderr):
+        subp = subprocess.Popen(
+            args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        stdout, stderr = subp.communicate()
+        res = subp.wait()
+        if res or (not allow_stderr and stderr):
+            raise JvmSubprogramError(res, args, stdout, stderr)
+        return stdout
+
     def compile(self):
         """
         Compiles the .java sources into .class files, ready for execution.
-        Raises a JvmError if compilation fails.
         """
-        javac = getoption('javac')
-        javafiles = [f for f in self.javadir.listdir()
-                     if f.endswith('.java')]
-        res = subprocess.call([javac] + javafiles)
-        if res: raise JvmError('Failed to compile!')
-        else: self.compiled = True
+        javacmd = [getoption('jasmin'), '-d', str(self.javadir)]
+        pypydir = self.javadir.join("pypy") # HACK; should do recursive
+        javafiles = [str(f) for f in pypydir.listdir()
+                     if str(f).endswith('.j')]
+
+        for javafile in javafiles:
+            print "Invoking jasmin on %s" % javafile
+            self._invoke(javacmd+[javafile], False)
+
+        # HACK: compile the Java helper class.  Should eventually
+        # use rte.py
+        sl = __file__.rindex('/')
+        javasrc = __file__[:sl]+"/src/PyPy.java"
+        self._invoke(['javac', '-nowarn', '-d', str(self.javadir), javasrc], True)
+                           
+        self.compiled = True
 
     def execute(self, args):
         """
@@ -76,15 +117,18 @@
         """
         assert self.compiled
         strargs = [str(a) for a in args]
-        cmd = [getoption('java'), '%s.Main' % self.package]
-        pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout
-        return pipe.read()
+        cmd = [getoption('java'),
+               '-cp',
+               str(self.javadir),
+               self.package+".Main"] + strargs
+        return self._invoke(cmd, True)
         
 def generate_source_for_function(func, annotation):
     
     """
     Given a Python function and some hints about its argument types,
-    generates JVM sources.  Returns the JvmGeneratedSource object.
+    generates JVM sources that call it and print the result.  Returns
+    the JvmGeneratedSource object.
     """
     
     if hasattr(func, 'im_func'):
@@ -97,7 +141,7 @@
     if getoption('view'): t.view()
     if getoption('wd'): tmpdir = py.path.local('.')
     else: tmpdir = udir
-    jvm = GenJvm(tmpdir, t, EntryPoint(main_graph, True))
+    jvm = GenJvm(tmpdir, t, EntryPoint(main_graph, True, True))
     return jvm.generate_source()
 
 class GenJvm(GenOO):

Modified: pypy/dist/pypy/translator/jvm/node.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/node.py	(original)
+++ pypy/dist/pypy/translator/jvm/node.py	Tue Oct 31 13:58:47 2006
@@ -6,7 +6,8 @@
 
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.ootypesystem import ootype
-from pypy.translator.jvm.typesystem import jStringArray, jVoid, jThrowable
+from pypy.translator.jvm.typesystem import \
+     jString, jStringArray, jVoid, jThrowable
 from pypy.translator.jvm.typesystem import jvm_for_class, jvm_method_desc
 from pypy.translator.jvm.opcodes import opcodes
 from pypy.translator.oosupport.function import Function as OOFunction
@@ -24,7 +25,7 @@
     testing (see __init__)
     """
 
-    def __init__(self, graph, expandargs):
+    def __init__(self, graph, expandargs, printresult):
         """
         'graph' --- The initial graph to invoke from main()
         'expandargs' --- controls whether the arguments passed to main()
@@ -44,6 +45,7 @@
         """
         self.graph = graph
         self.expand_arguments = expandargs
+        self.print_result = printresult
         pass
 
     # XXX --- perhaps this table would be better placed in typesystem.py
@@ -58,6 +60,14 @@
         ootype.Char:jvmgen.PYPYSTRTOCHAR
         }
 
+    _type_printing_methods = {
+        ootype.Signed:jvmgen.PYPYDUMPINT,
+        ootype.Unsigned:jvmgen.PYPYDUMPUINT,
+        ootype.SignedLongLong:jvmgen.PYPYDUMPLONG,
+        ootype.Float:jvmgen.PYPYDUMPDOUBLE,
+        ootype.Bool:jvmgen.PYPYDUMPBOOLEAN,
+        }
+
     def render(self, gen):
         gen.begin_class('pypy.Main')
         gen.begin_function(
@@ -68,7 +78,10 @@
             # Convert each entry into the array to the desired type by
             # invoking an appropriate helper function on each one
             for i, arg in enumerate(self.graph.getargs()):
+                jty = self.db.lltype_to_cts(arg.concretetype)
+                gen.load_jvm_var(jStringArray, 0)
                 gen.emit(jvmgen.ICONST, i)
+                gen.load_from_array(jString)
                 gen.emit(self._type_conversion_methods[arg.concretetype])
         else:
             # Convert the array of strings to a List<String> as the
@@ -81,6 +94,16 @@
 
         # Generate a call to this method
         gen.emit(self.db.pending_function(self.graph))
+
+        # Print result?
+        if self.print_result:
+            resootype = self.graph.getreturnvar().concretetype
+            resjtype = self.db.lltype_to_cts(resootype)
+            meth = self._type_printing_methods[resootype]
+            gen.emit(meth)
+
+        # And finish up
+        gen.return_val(jVoid)
         
         gen.end_function()
         gen.end_class()

Modified: pypy/dist/pypy/translator/jvm/opcodes.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/opcodes.py	(original)
+++ pypy/dist/pypy/translator/jvm/opcodes.py	Tue Oct 31 13:58:47 2006
@@ -222,7 +222,7 @@
 for opc in opcodes:
     val = opcodes[opc]
     if not isinstance(val, list):
-        val = InstructionList((PushAllArgs, val))
+        val = InstructionList((PushAllArgs, val, StoreResult))
     else:
         val = InstructionList(val)
     opcodes[opc] = val

Modified: pypy/dist/pypy/translator/jvm/option.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/option.py	(original)
+++ pypy/dist/pypy/translator/jvm/option.py	Tue Oct 31 13:58:47 2006
@@ -4,9 +4,11 @@
 _default_values = {
     'javac':'javac',
     'java':'java',
+    'jasmin':'jasmin',
     'noasm':False,
     'package':'pypy',
-    'wd':False
+    'wd':False,
+    'norun':False
     }
 
 def getoption(name):

Modified: pypy/dist/pypy/translator/jvm/src/PyPy.java
==============================================================================
--- pypy/dist/pypy/translator/jvm/src/PyPy.java	(original)
+++ pypy/dist/pypy/translator/jvm/src/PyPy.java	Tue Oct 31 13:58:47 2006
@@ -98,10 +98,10 @@
 
     public static int double_to_uint(double value) {
         if (value <= Integer.MAX_VALUE)
-            return value;
+            return (int)value;
 
-        int loword = value % BITS16;
-        int hiword = Math.floor(value / BITS16);
+        int loword = (int)(value % BITS16);
+        int hiword = (int)(Math.floor(value / BITS16));
         assert (loword & 0xFFFF0000) == 0;
         assert (hiword & 0xFFFF0000) == 0;
         return (hiword << 16) + loword;
@@ -112,7 +112,7 @@
     }
 
     public static List<?> array_to_list(Object[] array) {
-        List<?> l = new ArrayList();
+        List l = new ArrayList();
         for (Object o : array) {
             l.add(o);
         }
@@ -131,9 +131,9 @@
         try {
             long l = Long.parseLong(s);
             if (l < Integer.MAX_VALUE)
-                return l;
-            int lowerword = l & 0xFFFF;
-            int upperword = l >> 16;
+                return (int)l;
+            int lowerword = (int)(l & 0xFFFF);
+            int upperword = (int)(l >> 16);
             return lowerword + (upperword << 16);
         } catch (NumberFormatException fe) {
             throw new RuntimeException(fe);
@@ -182,4 +182,44 @@
             throw new RuntimeException("String not single character: '"+s+"'");
         return s.charAt(0);
     }
+
+    // Used in testing:
+
+    public static void dump_int(int i) {
+        System.out.println(i);
+    }
+
+    public static void dump_uint(int i) {
+        if (i >= 0)
+            System.out.println(i);
+        else {
+            throw new RuntimeException("TODO");
+        }
+    }
+
+    public static void dump_boolean(boolean l) {
+        if (l)
+            System.out.println("True");
+        else
+            System.out.println("False");
+    }
+
+    public static void dump_long(long l) {
+        System.out.println(l);
+    }
+
+    public static void dump_double(double d) {
+        System.out.println(d);
+    }
+
+    public static void dump_string(char[] b) {
+        System.out.print('"');
+        for (char c : b) {
+            if (c == '"') 
+                System.out.print("\\\"");
+            System.out.print(c);
+        }
+        System.out.print('"');
+        System.out.println();
+    }
 }
\ No newline at end of file

Modified: pypy/dist/pypy/translator/jvm/test/runtest.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/test/runtest.py	(original)
+++ pypy/dist/pypy/translator/jvm/test/runtest.py	Tue Oct 31 13:58:47 2006
@@ -9,7 +9,7 @@
 from pypy.rpython.ootypesystem import ootype
 from pypy.annotation.model import lltype_to_annotation
 from pypy.translator.translator import TranslationContext
-from pypy.translator.jvm.genjvm import generate_source_for_function
+from pypy.translator.jvm.genjvm import generate_source_for_function, JvmError
 from pypy.translator.jvm.option import getoption
 
 FLOAT_PRECISION = 8
@@ -53,12 +53,13 @@
             py.test.skip("Execution disabled")
 
         resstr = self.gensrc.execute(args)
+        print "resstr=%s" % repr(resstr)
         res = eval(resstr)
         if isinstance(res, tuple):
             res = StructTuple(res) # so tests can access tuple elements with .item0, .item1, etc.
         elif isinstance(res, list):
             res = OOList(res)
-        return res        
+        return res
 
 class JvmTest(BaseRtypingTest, OORtypeMixin):
     def __init__(self):
@@ -84,12 +85,15 @@
             py.test.skip('Windows --> %s' % reason)
 
     def interpret(self, fn, args, annotation=None):
-        py.test.skip("jvm tests don't work yet")
-        src = self._compile(fn, args, annotation)
-        res = src(*args)
-        if isinstance(res, ExceptionWrapper):
-            raise res
-        return res
+        try:
+            src = self._compile(fn, args, annotation)
+            res = src(*args)
+            if isinstance(res, ExceptionWrapper):
+                raise res
+            return res
+        except JvmError, e:
+            e.pretty_print()
+            raise
 
     def interpret_raises(self, exception, fn, args):
         import exceptions # needed by eval

Modified: pypy/dist/pypy/translator/jvm/test/test_bool.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/test/test_bool.py	(original)
+++ pypy/dist/pypy/translator/jvm/test/test_bool.py	Tue Oct 31 13:58:47 2006
@@ -1,7 +1,7 @@
 import py
 from pypy.translator.jvm.test.runtest import JvmTest
-from pypy.rpython.test.test_rbool import BaseTestRbool
+#from pypy.rpython.test.test_rbool import BaseTestRbool
 
-class TestJvmBool(JvmTest, BaseTestRbool):
-    pass
+#class TestJvmBool(JvmTest, BaseTestRbool):
+#    pass
 

Added: pypy/dist/pypy/translator/jvm/test/test_snippet.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/jvm/test/test_snippet.py	Tue Oct 31 13:58:47 2006
@@ -0,0 +1,24 @@
+from pypy.translator.test import snippet as s
+from pypy.translator.jvm.test.runtest import JvmTest
+
+snippets = [
+    [s.if_then_else, (0, 42, 43), (1, 42, 43)],
+    [s.simple_func, (42,)],
+    [s.while_func, (0,), (13,)],
+    [s.my_bool, (0,), (42,)],
+    [s.my_gcd, (30, 18)],
+    [s.is_perfect_number, (28,), (27,)],
+    ]
+
+class TestSnippets(JvmTest):
+
+    def test_snippers(self):
+        for item in snippets:
+            func = item[0]
+            for arglist in item[1:]:
+                yield self.interpret, func, arglist
+    
+    def test_add(self):
+        def fn(x, y):
+            return x+y
+        assert self.interpret(fn, [4,7]) == 11

Modified: pypy/dist/pypy/translator/oosupport/function.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/function.py	(original)
+++ pypy/dist/pypy/translator/oosupport/function.py	Tue Oct 31 13:58:47 2006
@@ -86,17 +86,20 @@
         for block in graph.iterblocks():
             if self._is_return_block(block):
                 return_blocks.append(block)
-            elif self._is_raise_block(block):
-                self.render_raise_block(block)
-            elif self._is_exc_handling_block(block):
-                self.render_exc_handling_block(block)
             else:
-                self.render_normal_block(block)
+                self.set_label(self._get_block_name(block))
+                if self._is_raise_block(block):
+                    self.render_raise_block(block)
+                elif self._is_exc_handling_block(block):
+                    self.render_exc_handling_block(block)
+                else:
+                    self.render_normal_block(block)
 
         # render return blocks at the end just to please the .NET
         # runtime that seems to need a return statement at the end of
         # the function
         for block in return_blocks:
+            self.set_label(self._get_block_name(block))
             self.render_return_block(block)
 
         self.end_render()
@@ -104,8 +107,6 @@
             self.db.record_function(self.graph, self.name)
 
     def render_exc_handling_block(self, block):
-        self.set_label(self._get_block_name(block))
-
         # renders all ops but the last one
         for op in block.operations[:-1]:
             self._render_op(op)
@@ -141,8 +142,6 @@
         raise NotImplementedError
             
     def render_normal_block(self, block):
-        self.set_label(self._get_block_name(block))
-
         # renders all ops but the last one
         for op in block.operations:
             self._render_op(op)



More information about the Pypy-commit mailing list