[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