[Pyrex] Re: pyrex patch misses a few labels

David M. Cooke cookedm at physics.mcmaster.ca
Mon Mar 13 09:47:47 CET 2006


[cc:ing the Pyrex list]
On Sun, Mar 12, 2006 at 08:03:17PM -0500, chris erway wrote:
> hi landon, david:
> 
> last week the darwinports maintainer (landon) for Pyrex added your  
> (david's) patch to suppress unused labels (patch-emit-only-used- 
> labels) in Pyrex-generated code.  i upgraded to the patched version  
> today, and found it prevented me from building two Pyrex extensions  
> used by the "democracy player" project (getdemocracy.com) -- a few  
> errors about missing labels.  maybe this patch should taken off the  
> Pyrex Portfile?
> 
> attached is an example Pyrex file from the democracy project, the  
> working C code that Pyrex generates without the patch, and the code  
> generated by the patch that fails compilation.
> 
> -chris

I've found a minimal test case for this:

def testx():
    for d in (1,2,3):
        try:
            pass
        finally:
            pass

The unpatched Pyrex generates a label just after the for, and the
finally will jump to that if a continue is used in the try: block. I've
updated the patches so that the label is generated at the end of the
for.

Updated patches that should apply cleanly to Pyrex 0.9.3.1 are available at
http://arbutus.mcmaster.ca/dmc/software/pyrex/

(this includes Elias Pschernig's patch (04) to not output declarations
for unused utility functions.)

I've attached the new 02-emit-only-used-labels patch for mail archive
goodness. There's still compiler warnings about unused labels due to the
finally: declaring more than needed, but that's less harmful than an
error ;-)

-- 
|>|\/|<
/--------------------------------------------------------------------------\
|David M. Cooke                      http://arbutus.physics.mcmaster.ca/dmc/
|cookedm at physics.mcmaster.ca
-------------- next part --------------
Mon Mar 13 03:27:55 EST 2006  David M. Cooke <cookedm at physics.mcmaster.ca>
  * [02-emit-only-used-labels] Only emit labels if they've been used
diff -rN -u old-Pyrex--dmc2/Pyrex/Compiler/Code.py new-Pyrex--dmc2/Pyrex/Compiler/Code.py
--- old-Pyrex--dmc2/Pyrex/Compiler/Code.py	2006-03-13 03:34:04.000000000 -0500
+++ new-Pyrex--dmc2/Pyrex/Compiler/Code.py	2006-03-13 03:34:05.000000000 -0500
@@ -79,6 +79,7 @@
 
     def init_labels(self):
         self.label_counter = 0
+        self.used_labels = {}
         self.return_label = self.new_label()
         self.new_error_label()
         self.continue_label = None
@@ -134,8 +135,16 @@
         self.set_all_labels(new_labels)
         return old_labels
 
+    def mark_label_used(self, lbl):
+        self.used_labels[lbl] = 1
+
     def put_label(self, lbl):
-        self.putln("%s:;" % lbl)
+        if lbl in self.used_labels:
+            self.putln("%s:;" % lbl)
+
+    def put_goto(self, lbl):
+        self.putln("goto %s;" % lbl)
+        self.mark_label_used(lbl)
 
     def put_var_declarations(self, entries, static = 0, dll_linkage = None):
         for entry in entries:
@@ -245,6 +254,7 @@
                 term))
 
     def error_goto(self, pos):
+        self.mark_label_used(self.error_label)
         return "{%s = %s[%s]; %s = %s; goto %s;}" % (
             Naming.filename_cname,
             Naming.filetable_cname,
diff -rN -u old-Pyrex--dmc2/Pyrex/Compiler/Nodes.py new-Pyrex--dmc2/Pyrex/Compiler/Nodes.py
--- old-Pyrex--dmc2/Pyrex/Compiler/Nodes.py	2006-03-13 03:34:04.000000000 -0500
+++ new-Pyrex--dmc2/Pyrex/Compiler/Nodes.py	2006-03-13 03:34:05.000000000 -0500
@@ -1707,7 +1707,7 @@
             val = self.return_type.default_value
             if val:
                 code.putln("%s = %s;" % (Naming.retval_cname, val))
-        code.putln("goto %s;" % code.return_label)
+        code.put_goto(code.return_label)
         # ----- Error cleanup
         code.put_label(code.error_label)
         code.put_var_xdecrefs(lenv.temp_entries)
@@ -2699,9 +2699,7 @@
         if not code.break_label:
             error(self.pos, "break statement not inside loop")
         else:
-            code.putln(
-                "goto %s;" %
-                    code.break_label)
+            code.put_goto(code.break_label)
 
 
 class ContinueStatNode(StatNode):
@@ -2715,9 +2713,7 @@
         elif not code.continue_label:
             error(self.pos, "continue statement not inside loop")
         else:
-            code.putln(
-                "goto %s;" %
-                    code.continue_label)
+            code.put_goto(code.continue_label)
 
 
 class ReturnStatNode(StatNode):
@@ -2776,9 +2772,7 @@
                     "%s = %s;" % (
                         Naming.retval_cname,
                         self.return_type.default_value))
-        code.putln(
-            "goto %s;" %
-                code.return_label)
+        code.put_goto(code.return_label)
 
 
 class RaiseStatNode(StatNode):
@@ -2940,9 +2934,7 @@
             "if (%s) {" %
                 self.condition.result)
         self.body.generate_execution_code(code)
-        code.putln(
-            "goto %s;" %
-                end_label)
+        code.put_goto(end_label)
         code.putln("}")
         
     
@@ -2971,12 +2963,12 @@
         old_loop_labels = code.new_loop_labels()
         code.putln(
             "while (1) {")
-        code.put_label(code.continue_label)
         self.condition.generate_evaluation_code(code)
         code.putln(
             "if (!%s) break;" %
                 self.condition.result)
         self.body.generate_execution_code(code)
+        code.put_label(code.continue_label)
         code.putln("}")
         break_label = code.break_label
         code.set_loop_labels(old_loop_labels)
@@ -3024,10 +3016,10 @@
         self.iterator.generate_evaluation_code(code)
         code.putln(
             "for (;;) {")
-        code.put_label(code.continue_label)
         self.item.generate_evaluation_code(code)
         self.target.generate_assignment_code(self.item, code)
         self.body.generate_execution_code(code)
+        code.put_label(code.continue_label)
         code.putln(
             "}")
         break_label = code.break_label
@@ -3178,9 +3170,7 @@
             self.else_clause.generate_execution_code(code)
             code.putln(
                 "}")
-        code.putln(
-            "goto %s;" %
-                end_label)
+        code.put_goto(end_label)
         code.put_label(our_error_label)
         code.put_var_xdecrefs_clear(self.cleanup_list)
         default_clause_seen = 0
@@ -3192,9 +3182,7 @@
                     error(except_clause.pos, "Default except clause not last")
             except_clause.generate_handling_code(code, end_label)
         if not default_clause_seen:
-            code.putln(
-                "goto %s;" %
-                    code.error_label)
+            code.put_goto(code.error_label)
         code.put_label(end_label)
 
 
@@ -3259,9 +3247,7 @@
         else:
             self.exc_value.generate_disposal_code(code)
         self.body.generate_execution_code(code)
-        code.putln(
-            "goto %s;"
-                % end_label)
+        code.put_goto(end_label)
         code.putln(
             "}")
 
@@ -3334,6 +3320,7 @@
         code.putln(
                 "__pyx_why = 0; goto %s;" %
                     catch_label)
+        code.mark_label_used(catch_label)
         for i in range(len(new_labels)):
             if new_labels[i] and new_labels[i] <> "<try>":
                 if new_labels[i] == new_error_label:
@@ -3345,6 +3332,7 @@
                             new_labels[i],
                             i+1,
                             catch_label))
+                    code.mark_label_used(catch_label)
         code.put_label(catch_label)
         code.set_all_labels(old_labels)
         self.finally_clause.generate_execution_code(code)
@@ -3359,6 +3347,7 @@
                         "case %s: goto %s;" % (
                             i+1,
                             old_labels[i]))
+                    code.mark_label_used(old_labels[i])
         code.putln(
                 "}")		
         code.putln(
@@ -3378,9 +3367,7 @@
         code.putln(
                 "%s = %s;" % (
                     self.lineno_var, Naming.lineno_cname))
-        code.putln(
-                "goto %s;" %
-                    catch_label)
+        code.put_goto(catch_label)
         code.putln(
             "}")
             
@@ -3398,9 +3385,7 @@
             code.putln(
                 "%s = 0;" %
                     var)
-        code.putln(
-                "goto %s;" %
-                    error_label)
+        code.put_goto(error_label)
         code.putln(
             "}")
 



More information about the Pyrex mailing list