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

antocuni at codespeak.net antocuni at codespeak.net
Wed Mar 29 10:33:38 CEST 2006


Author: antocuni
Date: Wed Mar 29 10:33:36 2006
New Revision: 25099

Modified:
   pypy/dist/pypy/translator/cli/function.py
   pypy/dist/pypy/translator/cli/opcodes.py
   pypy/dist/pypy/translator/cli/test/compile.py
Log:
Some refactoring around opcodes.py and function.py


Modified: pypy/dist/pypy/translator/cli/function.py
==============================================================================
--- pypy/dist/pypy/translator/cli/function.py	(original)
+++ pypy/dist/pypy/translator/cli/function.py	Wed Mar 29 10:33:36 2006
@@ -2,7 +2,7 @@
 from pypy.rpython.lltypesystem.lltype import Void
 from pypy.translator.cli.option import getoption
 from pypy.translator.cli import cts
-from pypy.translator.cli.opcodes import opcodes, DoNothing, PushArgs, PushArg
+from pypy.translator.cli.opcodes import opcodes, MicroInstruction, PushAllArgs, Literal
 
 from pypy.tool.ansi_print import ansi_log
 import py
@@ -57,11 +57,11 @@
             if self._is_return_block(block):
                 return_var = block.inputargs[0]
                 if return_var.concretetype is not Void:
-                    self._push(return_var)
+                    self.load(return_var)
                 self.ilasm.opcode('ret')
             elif self._is_raise_block(block):
                 exc = block.inputargs[1]
-                self._push(exc)
+                self.load(exc)
                 self.ilasm.opcode('throw')
 
             if handle_exc:
@@ -87,7 +87,7 @@
                         # the exception value is on the stack, use it as the 2nd target arg
                         assert len(link.args) == 2
                         assert len(target.inputargs) == 2
-                        self._store(link.target.inputargs[1])
+                        self.store(link.target.inputargs[1])
                     else:
                         # pop the unused exception value
                         self.ilasm.opcode('pop')
@@ -107,7 +107,7 @@
                     else:
                         assert type(link.exitcase is bool)
                         assert block.exitswitch is not None
-                        self._push(block.exitswitch)
+                        self.load(block.exitswitch)
                         self.ilasm.branch_if(link.exitcase, target_label)
 
 
@@ -125,8 +125,8 @@
         target = link.target
         for to_load, to_store in zip(link.args, target.inputargs):
             if to_load.concretetype is not Void:
-                self._push(to_load)
-                self._store(to_store)
+                self.load(to_load)
+                self.store(to_store)
 
 
     def _set_locals(self):
@@ -182,10 +182,7 @@
         opname = op.opname
 
         cli_opcode = opcodes.get(opname, None)
-        if cli_opcode is DoNothing: # simply rename the variable
-            self._push(op.args[0])
-            self._store(op.result)
-        elif cli_opcode is not None:
+        if cli_opcode is not None:
             self._render_cli_opcode(cli_opcode, op)
         elif opname == 'direct_call':
             self._call(op)
@@ -198,20 +195,18 @@
 
     def _render_cli_opcode(self, cli_opcode, op):
         if type(cli_opcode) is str:
-            instructions = [PushArgs, cli_opcode]
+            instructions = [PushAllArgs(), cli_opcode]
         else:
             instructions = cli_opcode
 
         for instr in instructions:
-            if instr is PushArgs:
-                for arg in op.args:
-                    self._push(arg)
-            elif isinstance(instr, PushArg):
-                self._push(op.args[instr.arg])
-            else:
-                self.ilasm.opcode(instr)
+            if type(instr) is str:
+                instr = Literal(instr)
+
+            assert isinstance(instr, MicroInstruction)
+            instr.render(self, op)
 
-        self._store(op.result)
+        self.store(op.result)
 
 
     def _call(self, op):
@@ -219,12 +214,15 @@
 
         # push parameters
         for func_arg in op.args[1:]:
-            self._push(func_arg)
+            self.load(func_arg)
 
         self.ilasm.call(func_name)
-        self._store(op.result)
+        self.store(op.result)
+
+    def emit(self, instr, *args):
+        self.ilasm.opcode(instr, *args)
 
-    def _push(self, v):
+    def load(self, v):
         if isinstance(v, flowmodel.Variable):
             if v.name in self.argset:
                 self.ilasm.opcode('ldarg', repr(v.name))
@@ -237,7 +235,7 @@
         else:
             assert False
 
-    def _store(self, v):
+    def store(self, v):
         if isinstance(v, flowmodel.Variable):
             if v.concretetype is not Void:
                 self.ilasm.opcode('stloc', repr(v.name))

Modified: pypy/dist/pypy/translator/cli/opcodes.py
==============================================================================
--- pypy/dist/pypy/translator/cli/opcodes.py	(original)
+++ pypy/dist/pypy/translator/cli/opcodes.py	Wed Mar 29 10:33:36 2006
@@ -1,15 +1,36 @@
-DoNothing = object()
-PushArgs = object()
+class MicroInstruction(object):
+    def render(self, generator, op):
+        pass
 
-# come useful instruction patterns
-Not = ['ldc.i4.0', 'ceq']
 
-class PushArg(object):
-    def __init__(self, arg):
-        self.arg = arg
+class Literal(MicroInstruction):
+    def __init__(self, instr):
+        self.instr = instr
+
+    def render(self, generator, op):
+        generator.emit(self.instr)
+
+
+class PushArg(MicroInstruction):
+    def __init__(self, n):
+        self.n = n
+
+    def render(self, generator, op):
+        generator.load(op.args[self.n])
+
+
+class PushAllArgs(MicroInstruction):
+    def render(self, generator, op):
+        for arg in op.args:
+            generator.load(arg)
+
+
+# some useful instruction patterns
+Not = ['ldc.i4.0', 'ceq']
+DoNothing = [PushAllArgs()]
 
 def _not(op):
-    return [PushArgs, op]+Not
+    return [PushAllArgs(), op]+Not
 
 
 opcodes = {
@@ -33,7 +54,7 @@
 
     'int_is_true':              DoNothing,
     'int_neg':                  'neg',
-    'int_neg_ovf':              ['ldc.i4.0', PushArgs, 'sub.ovf'],
+    'int_neg_ovf':              ['ldc.i4.0', PushAllArgs(), 'sub.ovf'],
     'int_abs':                  None, # TODO
     'int_abs_ovf':              None, # TODO
     'int_invert':               'not',
@@ -69,7 +90,11 @@
     'int_ge_ovf':               _not('clt'),
     'int_and_ovf':              'and',
     'int_or_ovf':               'or',
+
+    # are they the same?
+    'int_lshift_ovf':           [PushArg(0), 'conv.i8', PushArg(1), 'shl', 'conv.ovf.i4'],
     'int_lshift_ovf_val':       [PushArg(0), 'conv.i8', PushArg(1), 'shl', 'conv.ovf.i4'],
+
     'int_rshift_ovf':           'shr', # these can't overflow!
     'int_xor_ovf':              'xor',
     'int_floordiv_ovf_zer':     None,  # what's the meaning?
@@ -99,7 +124,7 @@
     'uint_rshift':              'shr.un',
     'uint_xor':                 'xor',
 
-    'float_is_true':            [PushArgs, 'ldc.r8 0', 'ceq']+Not,
+    'float_is_true':            [PushAllArgs(), 'ldc.r8 0', 'ceq']+Not,
     'float_neg':                'neg',
     'float_abs':                None, # TODO
 
@@ -119,7 +144,7 @@
     'float_floor':              None, # TODO
     'float_fmod':               None, # TODO
 
-    'llong_is_true':            [PushArgs, 'ldc.i8 0', 'ceq']+Not,
+    'llong_is_true':            [PushAllArgs(), 'ldc.i8 0', 'ceq']+Not,
     'llong_neg':                'neg',
     'llong_abs':                None, # TODO
     'llong_invert':             'not',
@@ -138,7 +163,7 @@
     'llong_gt':                 'cgt',
     'llong_ge':                 _not('clt'),
 
-    'ullong_is_true':            [PushArgs, 'ldc.i8 0', 'ceq']+Not,
+    'ullong_is_true':            [PushAllArgs(), 'ldc.i8 0', 'ceq']+Not,
     'ullong_neg':                None,
     'ullong_abs':                None, # TODO
     'ullong_invert':             'not',
@@ -161,9 +186,9 @@
     # to 1: we can't simply DoNothing, because the CLI stack could
     # contains a truth value not equal to 1, so we should use the !=0
     # trick.
-    'cast_bool_to_int':         [PushArgs, 'ldc.i4.0', 'ceq']+Not,
-    'cast_bool_to_uint':        [PushArgs, 'ldc.i4.0', 'ceq']+Not,
-    'cast_bool_to_float':       [PushArgs, 'ldc.i4 0', 'ceq']+Not+['conv.r8'],
+    'cast_bool_to_int':         [PushAllArgs(), 'ldc.i4.0', 'ceq']+Not,
+    'cast_bool_to_uint':        [PushAllArgs(), 'ldc.i4.0', 'ceq']+Not,
+    'cast_bool_to_float':       [PushAllArgs(), 'ldc.i4 0', 'ceq']+Not+['conv.r8'],
     'cast_char_to_int':         None,
     'cast_unichar_to_int':      None,
     'cast_int_to_char':         None,

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 Mar 29 10:33:36 2006
@@ -23,12 +23,14 @@
     else:
         print 'OK'
 
-
-def foo(x, y, z):
-    pass
+def foo(x):
+    return x+1
 
 def bar(x, y):
-    foo(x+y, x-y, x*y)
+    if x > y:
+        return x+y+foo(2)
+    else:
+        return x-y
 
 f = compile_function(bar, [int, int])
 



More information about the Pypy-commit mailing list