[pypy-svn] r10247 - in pypy/dist/pypy/translator: . tool

arigo at codespeak.net arigo at codespeak.net
Sat Apr 2 16:44:36 CEST 2005


Author: arigo
Date: Sat Apr  2 16:44:36 2005
New Revision: 10247

Added:
   pypy/dist/pypy/translator/unsimplify.py   (contents, props changed)
Modified:
   pypy/dist/pypy/translator/genc_funcdef.py
   pypy/dist/pypy/translator/geninterplevel.py
   pypy/dist/pypy/translator/simplify.py
   pypy/dist/pypy/translator/tool/graphpage.py
   pypy/dist/pypy/translator/typer.py
Log:
A stupid bug prevented blocks with no operation from having their input/output
variables typed.  Aaargh.

Also in this check-in:
* _temporarily_ moved remove_direct_loops() into "unsimplify.py", with a
     copyvar() method taking a translator argument.
* type conversion of variables across links is delicate.  It might be more
     correct now.
* display the results of typer.py in the pygame graphs.



Modified: pypy/dist/pypy/translator/genc_funcdef.py
==============================================================================
--- pypy/dist/pypy/translator/genc_funcdef.py	(original)
+++ pypy/dist/pypy/translator/genc_funcdef.py	Sat Apr  2 16:44:36 2005
@@ -3,7 +3,7 @@
 from pypy.objspace.flow.model import traverse, uniqueitems, checkgraph
 from pypy.objspace.flow.model import Block, Link
 from pypy.objspace.flow.model import last_exception, last_exc_value
-from pypy.translator.simplify import remove_direct_loops
+from pypy.translator.unsimplify import remove_direct_loops
 from pypy.interpreter.pycode import CO_VARARGS
 from types import FunctionType
 
@@ -44,8 +44,11 @@
         self.wrapper_name = None                                     # pyfn_xxx
         self.globalobject_name = None                                # gfunc_xxx
         self.localscope = namespace.localScope()
+
+        # get the flow graph, and ensure that there is no direct loop in it
+        # as we cannot generate valid code for this case.
         self.graph = graph = genc.translator.getflowgraph(func)
-        remove_direct_loops(graph) # this can introduce new vars! we need to declare them
+        remove_direct_loops(genc.translator, graph)
         checkgraph(graph)
         graph_args = graph.getargs()
 

Modified: pypy/dist/pypy/translator/geninterplevel.py
==============================================================================
--- pypy/dist/pypy/translator/geninterplevel.py	(original)
+++ pypy/dist/pypy/translator/geninterplevel.py	Sat Apr  2 16:44:36 2005
@@ -23,7 +23,6 @@
 from pypy.objspace.flow.model import FunctionGraph, Block, Link
 from pypy.objspace.flow.model import last_exception, last_exc_value
 from pypy.objspace.flow.model import traverse, uniqueitems, checkgraph
-from pypy.translator.simplify import remove_direct_loops
 from pypy.interpreter.pycode import CO_VARARGS, CO_VARKEYWORDS
 from pypy.annotation import model as annmodel
 from types import FunctionType, CodeType, ModuleType

Modified: pypy/dist/pypy/translator/simplify.py
==============================================================================
--- pypy/dist/pypy/translator/simplify.py	(original)
+++ pypy/dist/pypy/translator/simplify.py	Sat Apr  2 16:44:36 2005
@@ -3,8 +3,6 @@
 'Syntactic-ish' simplifications on a flow graph.
 
 simplify_graph() applies all simplifications defined in this file.
-See also remove_direct_loops(), which is a 'de-simplification' useful
-for code generators.
 """
 
 from pypy.objspace.flow.model import *
@@ -103,21 +101,6 @@
                     link.prevblock.exitswitch = None
     traverse(visit, graph)
 
-def remove_direct_loops(graph):
-    """This is useful for code generators: it ensures that no link has
-    common input and output variables, which could occur if a block's exit
-    points back directly to the same block.  It allows code generators to be
-    simpler because they don't have to worry about overwriting input
-    variables when generating a sequence of assignments."""
-    def visit(link):
-        if isinstance(link, Link) and link.prevblock is link.target:
-            # insert an empty block with fresh variables.
-            intermediate = [Variable() for a in link.args]
-            b = Block(intermediate)
-            b.closeblock(Link(intermediate, link.target))
-            link.target = b
-    traverse(visit, graph)
-
 def transform_dead_op_vars(graph):
     """Remove dead operations and variables that are passed over a link
     but not used in the target block. Input is a graph."""

Modified: pypy/dist/pypy/translator/tool/graphpage.py
==============================================================================
--- pypy/dist/pypy/translator/tool/graphpage.py	(original)
+++ pypy/dist/pypy/translator/tool/graphpage.py	Sat Apr  2 16:44:36 2005
@@ -1,5 +1,5 @@
 import inspect
-from pypy.objspace.flow.model import traverse
+from pypy.objspace.flow.model import traverse, Block
 from pypy.translator.tool.make_dot import DotGen, make_dot, make_dot_graphs
 from pypy.interpreter.pycode import CO_VARARGS, CO_VARKEYWORDS
 from pypy.annotation import model
@@ -124,6 +124,16 @@
                     self.annotator.binding_cause_history.get(var, []))
                 self.binding_history[var.name] = zip(history, cause_history)
 
+        def visit(node):
+            if isinstance(node, Block):
+                for var in node.getvariables():
+                    if hasattr(var, 'type_cls'):
+                        info = self.links.get(var.name, var.name)
+                        info = '(%s) %s' % (var.type_cls.__name__, info)
+                        self.links[var.name] = info
+        for graph in graphs:
+            traverse(visit, graph)
+
     def followlink(self, varname):
         # clicking on a variable name shows its binding history
         cur_value = self.current_value[varname]

Modified: pypy/dist/pypy/translator/typer.py
==============================================================================
--- pypy/dist/pypy/translator/typer.py	(original)
+++ pypy/dist/pypy/translator/typer.py	Sat Apr  2 16:44:36 2005
@@ -1,6 +1,6 @@
 import autopath
 from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
-from pypy.objspace.flow.model import Block, Link
+from pypy.objspace.flow.model import Block, Link, uniqueitems
 
 
 class TypeMatch:
@@ -8,6 +8,9 @@
         self.s_type = s_type
         self.type_cls = type_cls
 
+class TyperError:
+    pass
+
 
 class Specializer:
     specializationdict = {}
@@ -28,12 +31,13 @@
 
     def specialize(self):
         for block in self.annotator.annotated:
-            if block.operations:
+            if block.operations != ():
                 self.specialize_block(block)
 
     def settype(self, a, type_cls):
         """Set the type_cls of a Variable or Constant."""
-        assert not hasattr(a, 'type_cls')
+        if hasattr(a, 'type_cls') and a.type_cls != type_cls:
+            raise TyperError, "inconsitent type for %r" % (a,)
         a.type_cls = type_cls
 
     def setbesttype(self, a):
@@ -56,7 +60,12 @@
         """Get the operation(s) needed to convert 'v' to the given type."""
         ops = []
         if isinstance(v, Constant):
-            self.settype(v, type_cls)  # mark the concrete type of the Constant
+            try:
+                # mark the concrete type of the Constant
+                self.settype(v, type_cls)
+            except TyperError:
+                v = Constant(v.value)   # need a copy of the Constant
+                self.settype(v, type_cls)
 
         elif v.type_cls is not type_cls:
             # XXX do we need better conversion paths?
@@ -123,6 +132,7 @@
             #    a2 in the inserted block before conversion
             #    a3 in the inserted block after conversion
             #    a4 in the original target block's inputargs
+            # warning, link.args may contain the same Variable multiple times!
             convargs = []
             convops = []
             for i in range(len(link.args)):
@@ -135,9 +145,11 @@
             # if there are conversion operations, they are inserted into
             # a new block along this link
             if convops:
+                vars = uniqueitems([a1 for a1 in link.args
+                                       if isinstance(a1, Variable)])
                 newblock = Block([])
                 mapping = {}
-                for a1 in link.args:
+                for a1 in vars:
                     a2 = Variable()
                     a2.type_cls = a1.type_cls
                     newblock.inputargs.append(a2)
@@ -146,6 +158,9 @@
                 newblock.closeblock(Link(convargs, link.target))
                 newblock.renamevariables(mapping)
                 link.target = newblock
+                link.args[:] = vars
+            else:
+                link.args[:] = convargs   # some Constants may have changed
 
     def getspecializedop(self, op, bindings):
         specializations = self.specializationdict.get(op.opname, ())

Added: pypy/dist/pypy/translator/unsimplify.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/unsimplify.py	Sat Apr  2 16:44:36 2005
@@ -0,0 +1,27 @@
+from pypy.objspace.flow.model import *
+
+def copyvar(v):
+    """Make a copy of the Variable v, preserving annotations and type_cls."""
+    assert isinstance(v, Variable)
+    newvar = Variable(v)
+    annotator = translator.annotator
+    if annotator is not None and v in annotator.bindings:
+        annotator.bindings[newvar] = annotator.bindings[v]
+    if hasattr(v, 'type_cls'):
+        newvar.type_cls = v.type_cls
+    return newvar
+
+def remove_direct_loops(translator, graph):
+    """This is useful for code generators: it ensures that no link has
+    common input and output variables, which could occur if a block's exit
+    points back directly to the same block.  It allows code generators to be
+    simpler because they don't have to worry about overwriting input
+    variables when generating a sequence of assignments."""
+    def visit(link):
+        if isinstance(link, Link) and link.prevblock is link.target:
+            # insert an empty block with fresh variables.
+            intermediate = [copyvar(a) for a in link.args]
+            b = Block(intermediate)
+            b.closeblock(Link(intermediate, link.target))
+            link.target = b
+    traverse(visit, graph)



More information about the Pypy-commit mailing list