[pypy-svn] r32870 - in pypy/dist/pypy/translator/cli: . test

antocuni at codespeak.net antocuni at codespeak.net
Wed Oct 4 14:58:21 CEST 2006


Author: antocuni
Date: Wed Oct  4 14:58:20 2006
New Revision: 32870

Added:
   pypy/dist/pypy/translator/cli/stackopt.py   (contents, props changed)
   pypy/dist/pypy/translator/cli/test/test_stackopt.py   (contents, props changed)
Modified:
   pypy/dist/pypy/translator/cli/function.py
   pypy/dist/pypy/translator/cli/gencli.py
   pypy/dist/pypy/translator/cli/ilgenerator.py
   pypy/dist/pypy/translator/cli/test/compile.py
Log:
A trivial implementation of the StackOptimizer: it simply optimizes
nothing so far :-)



Modified: pypy/dist/pypy/translator/cli/function.py
==============================================================================
--- pypy/dist/pypy/translator/cli/function.py	(original)
+++ pypy/dist/pypy/translator/cli/function.py	Wed Oct  4 14:58:20 2006
@@ -306,11 +306,11 @@
             if v.name in self.argset:
                 selftype, selfname = self.args[0]
                 if self.is_method and v.name == selfname:
-                    self.ilasm.opcode('ldarg.0') # special case for 'self'
+                    self.ilasm.load_self() # special case for 'self'
                 else:
-                    self.ilasm.opcode('ldarg', repr(v.name))
+                    self.ilasm.load_arg(v)
             else:
-                self.ilasm.opcode('ldloc', repr(v.name))
+                self.ilasm.load_local(v)
 
         elif isinstance(v, flowmodel.Constant):
             self._load_const(v)
@@ -324,7 +324,7 @@
     def store(self, v):
         if isinstance(v, flowmodel.Variable):
             if v.concretetype is not Void:
-                self.ilasm.opcode('stloc', repr(v.name))
+                self.ilasm.store_local(v)
         else:
             assert False
 

Modified: pypy/dist/pypy/translator/cli/gencli.py
==============================================================================
--- pypy/dist/pypy/translator/cli/gencli.py	(original)
+++ pypy/dist/pypy/translator/cli/gencli.py	Wed Oct  4 14:58:20 2006
@@ -14,6 +14,9 @@
 from pypy.translator.cli.rte import get_pypy_dll
 from pypy.translator.cli.support import Tee
 from pypy.translator.cli.prebuiltnodes import get_prebuilt_nodes
+from pypy.translator.cli.stackopt import StackOptGenerator
+
+USE_STACKOPT = True
 
 class GenCli(object):
     def __init__(self, tmpdir, translator, entrypoint=None, type_system_class=CTS,
@@ -42,8 +45,11 @@
         if getoption('stdout'):
             out = Tee(sys.stdout, out)
 
-        self.ilasm = asm_class(out, self.assembly_name )
-        
+        if USE_STACKOPT:
+            self.ilasm = StackOptGenerator(out, self.assembly_name)
+        else:
+            self.ilasm = asm_class(out, self.assembly_name)
+
         # TODO: instance methods that are also called as unbound
         # methods are rendered twice, once within the class and once
         # as an external function. Fix this.

Modified: pypy/dist/pypy/translator/cli/ilgenerator.py
==============================================================================
--- pypy/dist/pypy/translator/cli/ilgenerator.py	(original)
+++ pypy/dist/pypy/translator/cli/ilgenerator.py	Wed Oct  4 14:58:20 2006
@@ -111,7 +111,7 @@
                     and method_type!='runtime')
 
     def end_function(self):
-        self.render()
+        self.flush()
         self.code.closeblock()
 
     def begin_try(self):
@@ -119,7 +119,7 @@
         self.code.openblock()
 
     def end_try(self):
-        self.render()
+        self.flush()
         self.code.closeblock()
 
     def begin_catch(self, type_):
@@ -127,7 +127,7 @@
         self.code.openblock()
 
     def end_catch(self):
-        self.render()
+        self.flush()
         self.code.closeblock()
 
     def locals(self, vars):
@@ -235,5 +235,5 @@
             self.opcode('ldstr', string_literal(msg))
             self.call_method('void class [mscorlib]System.IO.TextWriter::WriteLine(string)', virtual=True)
 
-    def render(self):
+    def flush(self):
         pass

Added: pypy/dist/pypy/translator/cli/stackopt.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/cli/stackopt.py	Wed Oct  4 14:58:20 2006
@@ -0,0 +1,55 @@
+from pypy.translator.cli.ilgenerator import IlasmGenerator
+
+class StackOptMixin(object):
+    def __init__(self, *args):
+        self.super = super(StackOptMixin, self)
+        self.super.__init__(*args)
+        self._reset()
+
+    def _reset(self):
+        self.pending_ops = []
+
+    def opcode(self, op, *args):
+        self.pending_ops.append((op, args))
+
+    def writeline(self, s=''):
+        self.pending_ops.append(('WRITELINE', (s,)))
+
+    def write(self, s, indent=0):
+        self.pending_ops.append(('WRITE', (s, indent)))
+
+    def _optimize(self):
+        pass
+
+    def do_load(self, vartype, var):
+        if vartype == 'local':
+            self.super.load_local(var)
+        elif vartype == 'arg':
+            self.super.load_arg(var)
+        elif vartype == 'self':
+            assert var is None
+            self.super.load_self()
+        else:
+            assert False
+
+    def do_store(self, vartype, var):
+        assert vartype == 'local'
+        self.super.store_local(var)
+
+    def do_opcode(self, opcode, *args):
+        self.super.opcode(opcode, *args)
+
+    def flush(self):
+        self._optimize()
+        for opcode, args in self.pending_ops:
+            if opcode == 'WRITELINE':
+                self.super.writeline(*args)
+            elif opcode == 'WRITE':
+                self.super.write(*args)
+            else:
+                self.super.opcode(opcode, *args)
+        self._reset()
+
+class StackOptGenerator(StackOptMixin, IlasmGenerator):
+    pass
+

Modified: pypy/dist/pypy/translator/cli/test/compile.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/compile.py	(original)
+++ pypy/dist/pypy/translator/cli/test/compile.py	Wed Oct  4 14:58:20 2006
@@ -28,16 +28,13 @@
     def __init__(self, x):
         self.x = x
 
-def foo(a, b):
-    pass
+def foo(a, b, c):
+    return c,b,a
 
 mylist = [1,2,3]
 
 def bar(x, y):
-    if x:
-        return mylist
-    else:
-        return []
+    return foo(x+y, x-y, x*y)
 
 f = compile_function(bar, [int, int])
 

Added: pypy/dist/pypy/translator/cli/test/test_stackopt.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/cli/test/test_stackopt.py	Wed Oct  4 14:58:20 2006
@@ -0,0 +1,50 @@
+from pypy.translator.cli.stackopt import StackOptMixin
+
+class FakeGenerator(object):
+    def __init__(self, *args):
+        self.lines = ['']
+        self.opcodes = []
+
+    def opcode(self, opcode, *args):
+        self.opcodes.append((opcode, args))
+        self.lines[-1] += '%s %s' % (opcode, ' '.join(args))
+        self.lines.append('')
+
+    def write(self, s, index=0):
+        self.lines[-1] += s
+
+    def writeline(self, s=''):
+        self.lines[-1] += s
+        self.lines.append('')
+
+    def get_string(self):
+        return '\n'.join(self.lines[:-1])
+
+class TestStackOpt(StackOptMixin, FakeGenerator):
+    pass
+
+
+def test_code_generation():
+    ilasm = TestStackOpt()
+    ilasm.write('.method public static void foo()')
+    ilasm.writeline(' {')
+    ilasm.opcode('ldc.i4.0')
+    ilasm.opcode('pop')
+    ilasm.opcode('ret')
+    ilasm.writeline('}')
+    ilasm.flush()
+    s = ilasm.get_string()
+    assert s.strip() == """
+.method public static void foo() {
+ldc.i4.0 
+pop 
+ret 
+}
+""".strip()    
+
+def test_opcodes():
+    ilasm = TestStackOpt()
+    ilasm.opcode('ldloc', 'x')
+    ilasm.opcode('ldloc', 'y')
+    ilasm.flush()
+    assert ilasm.opcodes == [('ldloc', ('x',)), ('ldloc', ('y',))]



More information about the Pypy-commit mailing list