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

antocuni at codespeak.net antocuni at codespeak.net
Thu Mar 23 23:08:59 CET 2006


Author: antocuni
Date: Thu Mar 23 23:07:56 2006
New Revision: 24918

Added:
   pypy/dist/pypy/translator/cli/opcodes.py   (contents, props changed)
   pypy/dist/pypy/translator/cli/test/test_op.py   (contents, props changed)
Modified:
   pypy/dist/pypy/translator/cli/cts.py
   pypy/dist/pypy/translator/cli/function.py
   pypy/dist/pypy/translator/cli/ilgenerator.py
   pypy/dist/pypy/translator/cli/test/compile.py
   pypy/dist/pypy/translator/cli/test/runtest.py
   pypy/dist/pypy/translator/cli/test/test_flow.py
Log:
Moved opcodes mapping from function.py to the new opcodes.py.
Added some new opcodes to the mapping
Added some tests



Modified: pypy/dist/pypy/translator/cli/cts.py
==============================================================================
--- pypy/dist/pypy/translator/cli/cts.py	(original)
+++ pypy/dist/pypy/translator/cli/cts.py	Thu Mar 23 23:07:56 2006
@@ -18,7 +18,8 @@
     }
 
 _cts_to_ilasm = {
-    'int32': 'i4'
+    'int32': 'i4',
+    'bool': 'i4'
     }
 
 def lltype_to_cts(t):
@@ -48,7 +49,11 @@
     return lltype_to_cts(const.concretetype), const.value
 
 def llconst_to_ilasm(const):
-    return lltype_to_ilasm(const.concretetype), const.value
+    ilasm_type = lltype_to_ilasm(const.concretetype)
+    if const.concretetype is Bool:
+        return ilasm_type, int(const.value)
+    else:
+        return ilasm_type, const.value
 
 def graph_to_signature(graph):
     ret_type, ret_var = llvar_to_cts(graph.getreturnvar())

Modified: pypy/dist/pypy/translator/cli/function.py
==============================================================================
--- pypy/dist/pypy/translator/cli/function.py	(original)
+++ pypy/dist/pypy/translator/cli/function.py	Thu Mar 23 23:07:56 2006
@@ -2,6 +2,7 @@
 from pypy.rpython.lltypesystem.lltype import Void
 from pypy.translator.cli import conftest
 from pypy.translator.cli import cts
+from pypy.translator.cli.opcodes import opcodes, DoNothing, PushArgs
 
 from pypy.tool.ansi_print import ansi_log
 import py
@@ -9,16 +10,6 @@
 py.log.setconsumer("cli", ansi_log) 
 
 
-DoNothing = object()
-opcodes = {
-    'int_add': 'add',
-    'int_sub': 'sub',
-    'int_gt': 'cgt',
-    'int_lt': 'clt',
-    'int_is_true': DoNothing,
-    'same_as': DoNothing, # TODO: does same_as really do nothing else than renaming?
-    }
-
 class Node(object):
     def get_name(self):
         pass
@@ -77,6 +68,14 @@
                     self._push(block.exitswitch)
                     self.ilasm.branch_if(link.exitcase, target_label)
 
+        # add a block that will never be executed, just to please the
+        # .NET runtime that seems to need a return statement at the
+        # end of the function
+        if returntype != 'void':
+            self.ilasm.opcode('ldc.i4.0')
+
+        self.ilasm.opcode('ret')
+        
         ilasm.end_function()
 
     def _set_locals(self):
@@ -132,12 +131,11 @@
         opname = op.opname
 
         cli_opcode = opcodes.get(opname, None)
-        if cli_opcode is DoNothing:
-            # simply rename the variable
+        if cli_opcode is DoNothing: # simply rename the variable
             self._push(op.args[0])
             self._store(op.result)
         elif cli_opcode is not None:
-            self._simple_op(cli_opcode, op)
+            self._render_cli_opcode(cli_opcode, op)
         elif opname == 'direct_call':
             self._call(op)
         else:
@@ -147,6 +145,22 @@
             else:
                 assert False, 'Unknown opcode: %s ' % op
 
+    def _render_cli_opcode(self, cli_opcode, op):
+        if type(cli_opcode) is str:
+            instructions = [PushArgs, cli_opcode]
+        else:
+            instructions = cli_opcode
+
+        for instr in instructions:
+            if instr is PushArgs:
+                for arg in op.args:
+                    self._push(arg)
+            else:
+                self.ilasm.opcode(instr)
+
+        self._store(op.result)
+
+
     def _call(self, op):
         func_name = cts.graph_to_signature(op.args[0].value.graph)
 
@@ -156,23 +170,13 @@
 
         self.ilasm.call(func_name)
         self._store(op.result)
-        
-
-    def _simple_op(self, cli_opcode, op):
-        # push arg on stack
-        for arg in op.args:
-            self._push(arg)
-
-        # compute and store value
-        self.ilasm.opcode(cli_opcode)
-        self._store(op.result)
 
     def _push(self, v):
         if isinstance(v, flowmodel.Variable):
             if v.name in self.argset:
-                self.ilasm.opcode('ldarg.s', repr(v.name))
+                self.ilasm.opcode('ldarg', repr(v.name))
             else:
-                self.ilasm.opcode('ldloc.s', repr(v.name))
+                self.ilasm.opcode('ldloc', repr(v.name))
 
         elif isinstance(v, flowmodel.Constant):
             iltype, ilvalue = cts.llconst_to_ilasm(v)
@@ -182,6 +186,6 @@
 
     def _store(self, v):
         if isinstance(v, flowmodel.Variable):
-            self.ilasm.opcode('stloc.s', repr(v.name))
+            self.ilasm.opcode('stloc', repr(v.name))
         else:
             assert False

Modified: pypy/dist/pypy/translator/cli/ilgenerator.py
==============================================================================
--- pypy/dist/pypy/translator/cli/ilgenerator.py	(original)
+++ pypy/dist/pypy/translator/cli/ilgenerator.py	Thu Mar 23 23:07:56 2006
@@ -67,13 +67,13 @@
         self.code.writeline()
 
     def branch(self, lbl):
-        self.code.writeline('br.s ' + lbl)
+        self.code.writeline('br ' + lbl)
 
     def branch_if(self, cond, lbl):
         if cond:
-            opcode = 'brtrue.s '
+            opcode = 'brtrue '
         else:
-            opcode = 'brfalse.s '
+            opcode = 'brfalse '
 
         self.code.writeline(opcode + lbl)
 

Added: pypy/dist/pypy/translator/cli/opcodes.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/cli/opcodes.py	Thu Mar 23 23:07:56 2006
@@ -0,0 +1,172 @@
+DoNothing = object()
+PushArgs = object()
+
+# come useful instruction patterns
+Not = ['ldc.i4.0', 'ceq']
+
+def _not(op):
+    return [PushArgs, op]+Not
+
+
+opcodes = {
+    'same_as':                  DoNothing, # TODO: does same_as really do nothing else than renaming?    
+    'direct_call':              None, # for now it's a special case
+    'indirect_call':            None,
+
+    # __________ numeric operations __________
+
+    'bool_not':                 Not,
+
+    'char_lt':                  'clt',
+    'char_le':                  None,
+    'char_eq':                  'ceq',
+    'char_ne':                  None,
+    'char_gt':                  None,
+    'char_ge':                  None,
+
+    'unichar_eq':               None,
+    'unichar_ne':               None,
+
+    'int_is_true':              DoNothing,
+    'int_neg':                  'neg',
+    'int_neg_ovf':              ['ldc.i4.0', PushArgs, 'sub.ovf'],
+    'int_abs':                  None, # TODO
+    'int_abs_ovf':              None, # TODO
+    'int_invert':               'not',
+
+    'int_add':                  'add',
+    'int_sub':                  'sub',
+    'int_mul':                  'mul',
+    'int_div':                  'div',
+    'int_truediv':              None, # TODO
+    'int_floordiv':             'div',
+    'int_mod':                  'rem',
+    'int_lt':                   'clt',
+    'int_le':                   _not('cgt'),
+    'int_eq':                   'ceq',
+    'int_ne':                   _not('ceq'),
+    'int_gt':                   'cgt',
+    'int_ge':                   _not('clt'),
+    'int_and':                  'and',
+    'int_or':                   'or',
+    'int_lshift':               'shl',
+    'int_rshift':               'shr',
+    'int_xor':                  'xor',
+    'int_add_ovf':              None,
+    'int_sub_ovf':              None,
+    'int_mul_ovf':              None,
+    'int_div_ovf':              None,
+    'int_truediv_ovf':          None,
+    'int_floordiv_ovf':         None,
+    'int_mod_ovf':              None,
+    'int_lt_ovf':               None,
+    'int_le_ovf':               None,
+    'int_eq_ovf':               None,
+    'int_ne_ovf':               None,
+    'int_gt_ovf':               None,
+    'int_ge_ovf':               None,
+    'int_and_ovf':              None,
+    'int_or_ovf':               None,
+    'int_lshift_ovf':           None,
+    'int_rshift_ovf':           None,
+    'int_xor_ovf':              None,
+    'int_floordiv_ovf_zer':     None,
+    'int_mod_ovf_zer':          None,
+
+    'uint_is_true':             None,
+    'uint_neg':                 None,
+    'uint_abs':                 None,
+    'uint_invert':              None,
+
+    'uint_add':                 None,
+    'uint_sub':                 None,
+    'uint_mul':                 None,
+    'uint_div':                 None,
+    'uint_truediv':             None,
+    'uint_floordiv':            None,
+    'uint_mod':                 None,
+    'uint_lt':                  None,
+    'uint_le':                  None,
+    'uint_eq':                  None,
+    'uint_ne':                  None,
+    'uint_gt':                  None,
+    'uint_ge':                  None,
+    'uint_and':                 None,
+    'uint_or':                  None,
+    'uint_lshift':              None,
+    'uint_rshift':              None,
+    'uint_xor':                 None,
+
+    'float_is_true':            None,
+    'float_neg':                None,
+    'float_abs':                None,
+
+    'float_add':                None,
+    'float_sub':                None,
+    'float_mul':                None,
+    'float_div':                None,
+    'float_truediv':            None,
+    'float_floordiv':           None,
+    'float_mod':                None,
+    'float_lt':                 None,
+    'float_le':                 None,
+    'float_eq':                 None,
+    'float_ne':                 None,
+    'float_gt':                 None,
+    'float_ge':                 None,
+    'float_floor':              None,
+    'float_fmod':               None,
+
+    'llong_is_true':            None,
+    'llong_neg':                None,
+    'llong_abs':                None,
+    'llong_invert':             None,
+
+    'llong_add':                None,
+    'llong_sub':                None,
+    'llong_mul':                None,
+    'llong_div':                None,
+    'llong_truediv':            None,
+    'llong_floordiv':           None,
+    'llong_mod':                None,
+    'llong_lt':                 None,
+    'llong_le':                 None,
+    'llong_eq':                 None,
+    'llong_ne':                 None,
+    'llong_gt':                 None,
+    'llong_ge':                 None,
+
+    'ullong_is_true':           None,
+    'ullong_neg':               None,
+    'ullong_abs':               None,
+    'ullong_invert':            None,
+
+    'ullong_add':               None,
+    'ullong_sub':               None,
+    'ullong_mul':               None,
+    'ullong_div':               None,
+    'ullong_truediv':           None,
+    'ullong_floordiv':          None,
+    'ullong_mod':               None,
+    'ullong_lt':                None,
+    'ullong_le':                None,
+    'ullong_eq':                None,
+    'ullong_ne':                None,
+    'ullong_gt':                None,
+    'ullong_ge':                None,
+
+    'cast_bool_to_int':         None,
+    'cast_bool_to_uint':        None,
+    'cast_bool_to_float':       None,
+    'cast_char_to_int':         None,
+    'cast_unichar_to_int':      None,
+    'cast_int_to_char':         None,
+    'cast_int_to_unichar':      None,
+    'cast_int_to_uint':         None,
+    'cast_int_to_float':        None,
+    'cast_int_to_longlong':     None,
+    'cast_uint_to_int':         None,
+    'cast_float_to_int':        None,
+    'cast_float_to_uint':       None,
+    'truncate_longlong_to_int': 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	Thu Mar 23 23:07:56 2006
@@ -1,19 +1,35 @@
 #!/bin/env python
 
 import py
+from pypy.translator.test import snippet as s
 from pypy.translator.cli import conftest
 from pypy.translator.cli.test.runtest import compile_function
 
 py.test.Config.parse(py.std.sys.argv[1:])
 
 #conftest.option.view = True
-conftest.option.source = True
+#conftest.option.source = True
 conftest.option.wd = True
-conftest.option.nostop = True
-conftest.option.stdout = True
+#conftest.option.nostop = True
+#conftest.option.stdout = True
+
+def check(f, g, *args):
+    x = f(*args)
+    y = g(*args)
+    if x != y:
+        print x, '!=', y
+    else:
+        print 'OK'
+
 
 def bar(x, y):
-    return x/y
+    return x>>3 + y<<2
+
 
 
 f = compile_function(bar, [int, int])
+
+check(f, bar, 3, 3)
+check(f, bar, 4, 5)
+
+#compile_function(s.is_perfect_number, [int])

Modified: pypy/dist/pypy/translator/cli/test/runtest.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/runtest.py	(original)
+++ pypy/dist/pypy/translator/cli/test/runtest.py	Thu Mar 23 23:07:56 2006
@@ -8,6 +8,11 @@
 from pypy.translator.cli.gencli import GenCli
 from pypy.translator.cli.function import Node
 from pypy.translator.cli.cts import graph_to_signature
+from pypy.translator.cli.cts import llvar_to_cts
+
+def check(func, annotation, args):
+    mono = compile_function(func, annotation)
+    assert func(*args) == mono(*args)
 
 class TestEntryPoint(Node):
     """
@@ -24,15 +29,19 @@
     def render(self, ilasm):
         ilasm.begin_function('main', [('string[]', 'argv')], 'void', True)
 
-        # TODO: add support for non-int32 types
+        # TODO: only int32 and bool are tested
         for i, arg in enumerate(self.graph.getargs()):
             ilasm.opcode('ldarg.0')
             ilasm.opcode('ldc.i4.%d' % i)
             ilasm.opcode('ldelem.ref')
-            ilasm.call('int32 class [mscorlib]System.Convert::ToInt32(string)')
+            arg_type, arg_var = llvar_to_cts(arg)
+            ilasm.call('int32 class [mscorlib]System.Convert::To%s(string)' % arg_type.capitalize())
 
         ilasm.call(graph_to_signature(self.graph))
-        ilasm.call('void class [mscorlib]System.Console::WriteLine(int32)')
+
+        # print the result using the appropriate WriteLine overload
+        ret_type, ret_var = llvar_to_cts(self.graph.getreturnvar())
+        ilasm.call('void class [mscorlib]System.Console::WriteLine(%s)' % ret_type)
         ilasm.opcode('ret')
         ilasm.end_function()
 
@@ -89,7 +98,6 @@
         return tmpfile.replace('.il', '.exe')
 
     def __call__(self, *args):
-        # NB: only integers arguments are supported currently
         if self._exe is None:
             py.test.skip("Compilation disabled")
 
@@ -99,4 +107,11 @@
         stdout, stderr = mono.communicate()
         retval = mono.wait()
         assert retval == 0, stderr
-        return int(stdout)
+
+        ret_type, ret_var = llvar_to_cts(self.graph.getreturnvar())
+        if ret_type == 'int32':
+            return int(stdout)
+        elif ret_type == 'bool':
+            return stdout.strip().lower() == 'true'
+        else:
+            assert False, 'Return type %s is not supported' % ret_type

Modified: pypy/dist/pypy/translator/cli/test/test_flow.py
==============================================================================
--- pypy/dist/pypy/translator/cli/test/test_flow.py	(original)
+++ pypy/dist/pypy/translator/cli/test/test_flow.py	Thu Mar 23 23:07:56 2006
@@ -1,5 +1,5 @@
 from pypy.translator.test import snippet as s
-from pypy.translator.cli.test.runtest import compile_function
+from pypy.translator.cli.test.runtest import check
 
 def fibo(n):
     """Compute the (n+1)th Fibonacci's number"""
@@ -15,13 +15,13 @@
     [s.if_then_else, [int, int, int], (0, 42, 43), (1, 42, 43)],
     [s.simple_func, [int], (42,)],
     [s.while_func, [int], (0,), (13,)],
-    [fibo, [int], (0,), (1,), (10,)]
+    [fibo, [int], (0,), (1,), (10,)],
+    [s.my_bool, [int], (0,), (42,)],
+    [s.my_gcd, [int, int], (30, 18)],
+    [s.is_perfect_number, [int], (28,), (27,)],
     ]
 
 
-def check(func, annotation, args):
-    mono = compile_function(func, annotation)
-    assert func(*args) == mono(*args)
 
 def test_snippets():
     for item in snippets:

Added: pypy/dist/pypy/translator/cli/test/test_op.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/cli/test/test_op.py	Thu Mar 23 23:07:56 2006
@@ -0,0 +1,25 @@
+from pypy.translator.cli.test.runtest import check
+
+def test_op():
+    for name, func in globals().iteritems():
+        if name.startswith('op_'):
+            yield check, func, [int, int], (3, 4)
+
+
+def op_neg(x, y):
+    return -x
+
+def op_less_equal(x, y):
+    return x<=y
+
+def op_and_not(x, y):
+    return x and (not y)
+
+def op_shift(x, y):
+    return x<<3 + y>>4
+
+def op_bit_and_or_not_xor(x, y):
+    return (x&y) | ~(x^y)
+
+def op_operations(x, y):
+    return (x*y) / (x-y) +(-x)



More information about the Pypy-commit mailing list