[pypy-svn] r46021 - in pypy/branch/pypy-more-rtti-inprogress: config translator/cli translator/cli/src translator/cli/test translator/oosupport translator/oosupport/test_template
antocuni at codespeak.net
antocuni at codespeak.net
Mon Aug 27 14:55:29 CEST 2007
Author: antocuni
Date: Mon Aug 27 14:55:29 2007
New Revision: 46021
Modified:
pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py
pypy/branch/pypy-more-rtti-inprogress/translator/cli/class_.py
pypy/branch/pypy-more-rtti-inprogress/translator/cli/constant.py
pypy/branch/pypy-more-rtti-inprogress/translator/cli/cts.py
pypy/branch/pypy-more-rtti-inprogress/translator/cli/function.py
pypy/branch/pypy-more-rtti-inprogress/translator/cli/ilgenerator.py
pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py
pypy/branch/pypy-more-rtti-inprogress/translator/cli/record.py
pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs
pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/runtest.py
pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_snippet.py
pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_string.py
pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/function.py
pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/snippets.py
Log:
merge dist to branch (only gencli-related changes)
Modified: pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py (original)
+++ pypy/branch/pypy-more-rtti-inprogress/config/translationoption.py Mon Aug 27 14:55:29 2007
@@ -196,7 +196,8 @@
OptionDescription("cli", "GenCLI options", [
BoolOption("trace_calls", "Trace function calls", default=False,
- cmdline="--cli-trace-calls")
+ cmdline="--cli-trace-calls"),
+ BoolOption("exception_transformer", "Use exception transformer", default=False),
]),
])
Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/class_.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/cli/class_.py (original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/class_.py Mon Aug 27 14:55:29 2007
@@ -84,7 +84,7 @@
for f_name, (f_type, f_default) in self.INSTANCE._fields.iteritems():
cts_type = self.cts.lltype_to_cts(f_type)
f_name = self.cts.escape_name(f_name)
- if cts_type != 'void':
+ if cts_type != CTS.types.void:
ilasm.field(f_name, cts_type)
self._ctor()
@@ -134,7 +134,7 @@
INSTANCE_DEF, _ = self.INSTANCE._lookup_field(f_name)
cts_type = self.cts.lltype_to_cts(F_TYPE)
f_name = self.cts.escape_name(f_name)
- if cts_type != 'void':
+ if cts_type != CTS.types.void:
self.ilasm.opcode('ldarg.0')
push_constant(self.db, F_TYPE, f_default, self.gen)
class_name = self.db.class_name(INSTANCE_DEF)
Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/constant.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/cli/constant.py (original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/constant.py Mon Aug 27 14:55:29 2007
@@ -265,9 +265,9 @@
class CLIBaseConstMixin(object):
""" A mix-in with a few extra methods the CLI backend uses """
- def get_type(self, include_class=True):
+ def get_type(self):
""" Returns the CLI type for this constant's representation """
- return self.cts.lltype_to_cts(self.value._TYPE, include_class)
+ return self.cts.lltype_to_cts(self.value._TYPE)
def push_inline(self, gen, TYPE):
""" Overload the oosupport version so that we use the CLI opcode
Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/cts.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/cli/cts.py (original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/cts.py Mon Aug 27 14:55:29 2007
@@ -4,61 +4,146 @@
import exceptions
-from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong
+from py.builtin import set
from pypy.rpython.lltypesystem import lltype
from pypy.rpython.ootypesystem import ootype
from pypy.rpython.lltypesystem.llmemory import WeakGcAddress
from pypy.translator.cli.option import getoption
from pypy.translator.cli import oopspec
-try:
- set
-except NameError:
- from sets import Set as set
-
from pypy.tool.ansi_print import ansi_log
import py
log = py.log.Producer("cli")
py.log.setconsumer("cli", ansi_log)
-WEAKREF = '[mscorlib]System.WeakReference'
-PYPY_LIST = '[pypylib]pypy.runtime.List`1<%s>'
-PYPY_LIST_OF_VOID = '[pypylib]pypy.runtime.ListOfVoid'
-PYPY_DICT = '[pypylib]pypy.runtime.Dict`2<%s, %s>'
+class CliType(object):
+ def typename(self):
+ raise NotImplementedError
+
+ def __str__(self):
+ return self.typename()
+
+ def __hash__(self):
+ return hash(self.typename())
+
+ def __eq__(self, other):
+ return self.typename() == other.typename()
+
+ def __ne__(self, other):
+ return self.typename() != other.typename()
+
+
+class CliPrimitiveType(CliType):
+ def __init__(self, name):
+ self.name = name
+
+ def typename(self):
+ return self.name
+
+
+class CliReferenceType(CliType):
+ def typename(self):
+ return 'class ' + self.classname()
+
+ def classname(self):
+ raise NotImplementedError
+
+
+class CliClassType(CliReferenceType):
+ def __init__(self, assembly, name):
+ self.assembly = assembly
+ self.name = name
+
+ def classname(self):
+ if self.assembly:
+ return '[%s]%s' % (self.assembly, self.name)
+ else:
+ return self.name
+
+
+class CliGenericType(CliReferenceType):
+ def __init__(self, assembly, name, numparam):
+ self.assembly = assembly
+ self.name = name
+ self.numparam = numparam
+
+ def classname(self):
+ paramtypes = [self.paramtype(i) for i in range(self.numparam)]
+ thistype = self.specialize(*paramtypes)
+ return thistype.classname()
+
+ def specialize(self, *types):
+ assert len(types) == self.numparam
+ return CliSpecializedType(self, types)
+
+ def paramtype(self, num):
+ assert 0 <= num < self.numparam
+ return CliPrimitiveType('!%d' % num)
+
+class CliSpecializedType(CliReferenceType):
+ def __init__(self, generic_type, arg_types):
+ self.generic_type = generic_type
+ self.arg_types = arg_types
+
+ def classname(self):
+ assembly = self.generic_type.assembly
+ name = self.generic_type.name
+ numparam = self.generic_type.numparam
+ arglist = ', '.join([arg.typename() for arg in self.arg_types])
+ return '[%s]%s`%d<%s>' % (assembly, name, numparam, arglist)
+
+
+T = CliPrimitiveType
+class types:
+ void = T('void')
+ int32 = T('int32')
+ uint32 = T('unsigned int32')
+ int64 = T('int64')
+ uint64 = T('unsigned int64')
+ bool = T('bool')
+ float64 = T('float64')
+ char = T('char')
+ string = T('string')
+
+ weakref = CliClassType('mscorlib', 'System.WeakReference')
+ type = CliClassType('mscorlib', 'System.Type')
+ object = CliClassType('mscorlib', 'System.Object')
+ list = CliGenericType('pypylib', 'pypy.runtime.List', 1)
+ list_of_void = CliClassType('pypylib', 'pypy.runtime.ListOfVoid')
+ dict = CliGenericType('pypylib', 'pypy.runtime.Dict', 2)
+ dict_void_void = CliClassType('pypylib', 'pypy.runtime.DictVoidVoid')
+ dict_items_iterator = CliGenericType('pypylib', 'pypy.runtime.DictItemsIterator', 2)
+ string_builder = CliClassType('pypylib', 'pypy.runtime.StringBuilder')
+del T
+
+WEAKREF = types.weakref.classname()
PYPY_DICT_OF_VOID = '[pypylib]pypy.runtime.DictOfVoid`2<%s, int32>'
-PYPY_DICT_VOID_VOID = '[pypylib]pypy.runtime.DictVoidVoid'
-PYPY_DICT_ITEMS_ITERATOR = '[pypylib]pypy.runtime.DictItemsIterator`2<%s, %s>'
-PYPY_STRING_BUILDER = '[pypylib]pypy.runtime.StringBuilder'
+
_lltype_to_cts = {
- ootype.Void: 'void',
- ootype.Signed: 'int32',
- ootype.Unsigned: 'unsigned int32',
- SignedLongLong: 'int64',
- UnsignedLongLong: 'unsigned int64',
- ootype.Bool: 'bool',
- ootype.Float: 'float64',
- ootype.Char: 'char',
- ootype.UniChar: 'char',
- ootype.Class: 'class [mscorlib]System.Type',
- ootype.String: 'string',
- ootype.StringBuilder: 'class ' + PYPY_STRING_BUILDER,
- WeakGcAddress: 'class ' + WEAKREF,
+ ootype.Void: types.void,
+ ootype.Signed: types.int32,
+ ootype.Unsigned: types.uint32,
+ ootype.SignedLongLong: types.int64,
+ ootype.UnsignedLongLong: types.uint64,
+ ootype.Bool: types.bool,
+ ootype.Float: types.float64,
+ ootype.Char: types.char,
+ ootype.UniChar: types.char,
+ ootype.Class: types.type,
+ ootype.String: types.string,
+ ootype.StringBuilder: types.string_builder,
+ WeakGcAddress: types.weakref,
# maps generic types to their ordinal
- ootype.List.SELFTYPE_T: 'class ' + (PYPY_LIST % '!0'),
- ootype.List.ITEMTYPE_T: '!0',
- ootype.Dict.SELFTYPE_T: 'class ' + (PYPY_DICT % ('!0', '!1')),
- ootype.Dict.KEYTYPE_T: '!0',
- ootype.Dict.VALUETYPE_T: '!1',
- ootype.DictItemsIterator.SELFTYPE_T: 'class ' + (PYPY_DICT_ITEMS_ITERATOR % ('!0', '!1')),
- ootype.DictItemsIterator.KEYTYPE_T: '!0',
- ootype.DictItemsIterator.VALUETYPE_T: '!1',
- }
-
-_pyexception_to_cts = {
- exceptions.Exception: '[mscorlib]System.Exception',
- exceptions.OverflowError: '[mscorlib]System.OverflowException'
+ ootype.List.SELFTYPE_T: types.list,
+ ootype.List.ITEMTYPE_T: types.list.paramtype(0),
+ ootype.Dict.SELFTYPE_T: types.dict,
+ ootype.Dict.KEYTYPE_T: types.dict.paramtype(0),
+ ootype.Dict.VALUETYPE_T: types.dict.paramtype(1),
+ ootype.DictItemsIterator.SELFTYPE_T: types.dict_items_iterator,
+ ootype.DictItemsIterator.KEYTYPE_T: types.dict_items_iterator.paramtype(0),
+ ootype.DictItemsIterator.VALUETYPE_T: types.dict_items_iterator.paramtype(1),
}
@@ -122,17 +207,14 @@
"readonly", "refanytype", "refanyval", "rem", "ret", "rethrow",
"shl", "shr", "sizeof", "starg", "stelem", "stfld", "stind",
"stloc", "stobj", "stsfld", "sub", "switch", "tail", "throw",
- "unaligned", "unbox", "volatile", "xor"])
+ "unaligned", "unbox", "volatile", "xor", "ole"])
+ # ole is not a keyword, but mono ilasm fails if you use it as a field/method name
+
+ types = types # for convenience
def __init__(self, db):
self.db = db
- def __class(self, result, include_class):
- if include_class:
- return 'class ' + result
- else:
- return result
-
def escape_name(self, name):
"""Mangle then name if it's a ilasm reserved word"""
if name in self.ILASM_KEYWORDS:
@@ -140,46 +222,47 @@
else:
return name
- def lltype_to_cts(self, t, include_class=True):
+ def lltype_to_cts(self, t):
if t is ootype.ROOT:
- return self.__class('[mscorlib]System.Object', include_class)
+ return types.object
elif isinstance(t, lltype.Ptr) and isinstance(t.TO, lltype.OpaqueType):
- return self.__class('[mscorlib]System.Object', include_class)
+ return types.object
elif isinstance(t, ootype.Instance):
NATIVE_INSTANCE = t._hints.get('NATIVE_INSTANCE', None)
if NATIVE_INSTANCE:
- return self.__class(NATIVE_INSTANCE._name, include_class)
+ return CliClassType(None, NATIVE_INSTANCE._name)
else:
name = self.db.pending_class(t)
- return self.__class(name, include_class)
+ return CliClassType(None, name)
elif isinstance(t, ootype.Record):
name = self.db.pending_record(t)
- return self.__class(name, include_class)
+ return CliClassType(None, name)
elif isinstance(t, ootype.StaticMethod):
delegate = self.db.record_delegate(t)
- return self.__class(delegate, include_class)
+ return CliClassType(None, delegate)
elif isinstance(t, ootype.List):
item_type = self.lltype_to_cts(t._ITEMTYPE)
- if item_type == 'void': # special case: List of Void
- return self.__class(PYPY_LIST_OF_VOID, include_class)
- return self.__class(PYPY_LIST % item_type, include_class)
+ if item_type == types.void: # special case: List of Void
+ return types.list_of_void
+ return types.list.specialize(item_type)
elif isinstance(t, ootype.Dict):
key_type = self.lltype_to_cts(t._KEYTYPE)
value_type = self.lltype_to_cts(t._VALUETYPE)
- if value_type == 'void': # special cases: Dict with voids
- if key_type == 'void':
- return self.__class(PYPY_DICT_VOID_VOID, include_class)
+ if value_type == types.void: # special cases: Dict with voids
+ if key_type == types.void:
+ return types.dict_void_void
else:
- return self.__class(PYPY_DICT_OF_VOID % key_type, include_class)
- return self.__class(PYPY_DICT % (key_type, value_type), include_class)
+ # XXX
+ return CliClassType(None, PYPY_DICT_OF_VOID % key_type)
+ return types.dict.specialize(key_type, value_type)
elif isinstance(t, ootype.DictItemsIterator):
key_type = self.lltype_to_cts(t._KEYTYPE)
value_type = self.lltype_to_cts(t._VALUETYPE)
- if key_type == 'void':
- key_type = 'int32' # placeholder
- if value_type == 'void':
- value_type = 'int32' # placeholder
- return self.__class(PYPY_DICT_ITEMS_ITERATOR % (key_type, value_type), include_class)
+ if key_type == types.void:
+ key_type = types.int32 # placeholder
+ if value_type == types.void:
+ value_type = types.int32 # placeholder
+ return types.dict_items_iterator.specialize(key_type, value_type)
return _get_from_dict(_lltype_to_cts, t, 'Unknown type %s' % t)
@@ -204,7 +287,7 @@
if is_method:
args = args[1:]
- arg_types = [self.lltype_to_cts(arg.concretetype) for arg in args]
+ arg_types = [self.lltype_to_cts(arg.concretetype).typename() for arg in args]
arg_list = ', '.join(arg_types)
return '%s %s(%s)' % (ret_type, func_name, arg_list)
@@ -216,7 +299,7 @@
args = [arg for arg in op.args[1:]
if arg.concretetype is not ootype.Void]
- arg_types = [self.lltype_to_cts(arg.concretetype) for arg in args]
+ arg_types = [self.lltype_to_cts(arg.concretetype).typename() for arg in args]
arg_list = ', '.join(arg_types)
return '%s %s(%s)' % (ret_type, func_name, arg_list)
@@ -235,9 +318,9 @@
METH = meth._TYPE
virtual = getattr(meth, '_virtual', True)
class_name = self.db.class_name(TYPE)
- full_name = 'class %s::%s' % (class_name, name)
+ full_name = 'class %s::%s' % (class_name, self.escape_name(name))
returntype = self.lltype_to_cts(METH.RESULT)
- arg_types = [self.lltype_to_cts(ARG) for ARG in METH.ARGS if ARG is not ootype.Void]
+ arg_types = [self.lltype_to_cts(ARG).typename() for ARG in METH.ARGS if ARG is not ootype.Void]
arg_list = ', '.join(arg_types)
return '%s %s(%s)' % (returntype, full_name, arg_list), virtual
@@ -255,16 +338,16 @@
name = name_or_desc
if KEY is ootype.Void and VALUE is ootype.Void and name == 'll_get_items_iterator':
# ugly, ugly special case
- ret_type = 'class ' + PYPY_DICT_ITEMS_ITERATOR % ('int32', 'int32')
+ ret_type = types.dict_items_iterator.specialize(types.int32, types.int32)
elif VALUE is ootype.Void and METH.RESULT is ootype.Dict.VALUETYPE_T:
- ret_type = 'void'
+ ret_type = types.void
else:
ret_type = self.lltype_to_cts(METH.RESULT)
ret_type = dict_of_void_ll_copy_hack(TYPE, ret_type)
else:
ret_type = self.lltype_to_cts(METH.RESULT)
generic_types = getattr(TYPE, '_generic_types', {})
- arg_types = [self.lltype_to_cts(arg) for arg in METH.ARGS if
+ arg_types = [self.lltype_to_cts(arg).typename() for arg in METH.ARGS if
arg is not ootype.Void and \
generic_types.get(arg, arg) is not ootype.Void]
arg_list = ', '.join(arg_types)
@@ -277,6 +360,6 @@
# XXX: ugly hack to make the ll_copy signature correct when
# CustomDict is special-cased to DictOfVoid.
if isinstance(TYPE, ootype.CustomDict) and TYPE._VALUETYPE is ootype.Void:
- return ret_type.replace('Dict`2', 'DictOfVoid`2')
+ return ret_type.typename().replace('Dict`2', 'DictOfVoid`2')
else:
return ret_type
Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/function.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/cli/function.py (original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/function.py Mon Aug 27 14:55:29 2007
@@ -227,6 +227,49 @@
self.load(return_var)
self.ilasm.opcode('ret')
+ def begin_try(self, cond):
+ if cond:
+ self.ilasm.begin_try()
+
+ def end_try(self, target_label, cond):
+ if cond:
+ self.ilasm.leave(target_label)
+ self.ilasm.end_try()
+ else:
+ self.ilasm.branch(target_label)
+
+ def begin_catch(self, llexitcase):
+ ll_meta_exc = llexitcase
+ ll_exc = ll_meta_exc._inst.class_._INSTANCE
+ cts_exc = self.cts.lltype_to_cts(ll_exc)
+ self.ilasm.begin_catch(cts_exc.classname())
+
+ def end_catch(self, target_label):
+ self.ilasm.leave(target_label)
+ self.ilasm.end_catch()
+
+ def render_raise_block(self, block):
+ exc = block.inputargs[1]
+ self.load(exc)
+ self.ilasm.opcode('throw')
+
+ def store_exception_and_link(self, link):
+ if self._is_raise_block(link.target):
+ # the exception value is on the stack, use it as the 2nd target arg
+ assert len(link.args) == 2
+ assert len(link.target.inputargs) == 2
+ self.store(link.target.inputargs[1])
+ else:
+ # the exception value is on the stack, store it in the proper place
+ if isinstance(link.last_exception, flowmodel.Variable):
+ self.ilasm.opcode('dup')
+ self.store(link.last_exc_value)
+ self.ilasm.get_field(('class Object_meta', 'Object', 'meta'))
+ self.store(link.last_exception)
+ else:
+ self.store(link.last_exc_value)
+ self._setup_link(link)
+
# XXX: this method should be moved into oosupport, but other
# backends are not ready :-(
def render_bool_switch(self, block):
Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/ilgenerator.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/cli/ilgenerator.py (original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/ilgenerator.py Mon Aug 27 14:55:29 2007
@@ -313,8 +313,8 @@
self.ilasm.call(signature)
def cast_to(self, lltype):
- cts_type = self.cts.lltype_to_cts(lltype, False)
- self.ilasm.opcode('castclass', cts_type)
+ cts_type = self.cts.lltype_to_cts(lltype)
+ self.ilasm.opcode('castclass', cts_type.classname())
def new(self, obj):
self.ilasm.new(self.cts.ctor_name(obj))
@@ -364,6 +364,9 @@
def branch_if_equal(self, target_label):
self.ilasm.opcode('beq', target_label)
+ def branch_if_not_equal(self, target_label):
+ self.ilasm.opcode('bne.un', target_label)
+
def push_primitive_constant(self, TYPE, value):
ilasm = self.ilasm
if TYPE is ootype.Void:
Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py (original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/metavm.py Mon Aug 27 14:55:29 2007
@@ -38,7 +38,9 @@
self._load_arg_or_null(generator, func_arg)
cts = generator.cts
ret_type = cts.lltype_to_cts(funcdesc._TYPE.RESULT)
- arg_types = [cts.lltype_to_cts(arg) for arg in funcdesc._TYPE.ARGS if arg is not ootype.Void]
+ arg_types = [cts.lltype_to_cts(arg).typename()
+ for arg in funcdesc._TYPE.ARGS
+ if arg is not ootype.Void]
arg_list = ', '.join(arg_types)
signature = '%s %s::%s(%s)' % (ret_type, funcdesc._cls._name, funcdesc._name, arg_list)
generator.call_signature(signature)
@@ -70,8 +72,10 @@
METH = this.concretetype._METHODS[method_name]
cts = generator.cts
ret_type = cts.lltype_to_cts(METH.RESULT)
- arg_types = [cts.lltype_to_cts(arg) for arg in METH.ARGS if arg is not ootype.Void]
- arg_types.insert(0, cts.lltype_to_cts(ootype.String))
+ arg_types = [cts.lltype_to_cts(arg).typename()
+ for arg in METH.ARGS
+ if arg is not ootype.Void]
+ arg_types.insert(0, cts.lltype_to_cts(ootype.String).typename())
arg_list = ', '.join(arg_types)
signature = '%s %s::%s(%s)' % (ret_type, STRING_HELPER_CLASS, method_name, arg_list)
generator.call_signature(signature)
Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/record.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/cli/record.py (original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/record.py Mon Aug 27 14:55:29 2007
@@ -30,7 +30,7 @@
for f_name, (FIELD_TYPE, f_default) in self.record._fields.iteritems():
f_name = self.cts.escape_name(f_name)
cts_type = self.cts.lltype_to_cts(FIELD_TYPE)
- if cts_type != 'void':
+ if cts_type != CTS.types.void:
ilasm.field(f_name, cts_type)
self._ctor()
self._toString()
@@ -74,13 +74,12 @@
def _equals(self):
# field by field comparison
- record_type = self.cts.lltype_to_cts(self.record, include_class=False)
- class_record_type = self.cts.lltype_to_cts(self.record, include_class=True)
+ record_type = self.cts.lltype_to_cts(self.record)
self.ilasm.begin_function('Equals', [('object', 'obj')], 'bool',
False, 'virtual', 'instance', 'default')
- self.ilasm.locals([(class_record_type, 'self')])
+ self.ilasm.locals([(record_type, 'self')])
self.ilasm.opcode('ldarg.1')
- self.ilasm.opcode('castclass', record_type)
+ self.ilasm.opcode('castclass', record_type.classname())
self.ilasm.opcode('stloc.0')
equal = 'bool [pypylib]pypy.runtime.Utils::Equal<%s>(!!0, !!0)'
@@ -91,9 +90,9 @@
f_type = self.cts.lltype_to_cts(FIELD_TYPE)
f_name = self.cts.escape_name(f_name)
self.ilasm.opcode('ldarg.0')
- self.ilasm.get_field((f_type, record_type, f_name))
+ self.ilasm.get_field((f_type, record_type.classname(), f_name))
self.ilasm.opcode('ldloc.0')
- self.ilasm.get_field((f_type, record_type, f_name))
+ self.ilasm.get_field((f_type, record_type.classname(), f_name))
self.ilasm.call(equal % f_type)
self.ilasm.opcode('and')
@@ -102,7 +101,7 @@
def _getHashCode(self):
# return the hash of the first field. XXX: it can lead to a bad distribution
- record_type = self.cts.lltype_to_cts(self.record, include_class=False)
+ record_type = self.cts.lltype_to_cts(self.record)
self.ilasm.begin_function('GetHashCode', [], 'int32', False, 'virtual', 'instance', 'default')
gethash = 'int32 [pypylib]pypy.runtime.Utils::GetHashCode<%s>(!!0)'
if self.record._fields:
@@ -113,7 +112,7 @@
f_name = self.cts.escape_name(f_name)
f_type = self.cts.lltype_to_cts(FIELD_TYPE)
self.ilasm.opcode('ldarg.0')
- self.ilasm.get_field((f_type, record_type, f_name))
+ self.ilasm.get_field((f_type, record_type.classname(), f_name))
self.ilasm.call(gethash % f_type)
else:
self.ilasm.opcode('ldc.i4.0')
Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs (original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/src/pypylib.cs Mon Aug 27 14:55:29 2007
@@ -201,7 +201,7 @@
public static int ll_strcmp(string s1, string s2)
{
- return string.Compare(s1, s2);
+ return string.Compare(s1, s2, StringComparison.Ordinal);
}
public static bool ll_startswith(string s1, string s2)
Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/runtest.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/runtest.py (original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/runtest.py Mon Aug 27 14:55:29 2007
@@ -53,7 +53,7 @@
RETURN_TYPE = self.graph.getreturnvar().concretetype
return_type = self.cts.lltype_to_cts(RETURN_TYPE)
- if return_type != 'void':
+ if return_type != CTS.types.void:
ilasm.locals([(return_type, 'res')])
if self.wrap_exceptions:
@@ -70,7 +70,7 @@
# call the function and convert the result to a string containing a valid python expression
ilasm.call(self.cts.graph_to_signature(self.graph))
- if return_type != 'void':
+ if return_type != CTS.types.void:
ilasm.opcode('stloc', 'res')
if self.wrap_exceptions:
ilasm.leave('check_last_exception')
@@ -100,7 +100,7 @@
ilasm.opcode('br', 'return')
ilasm.label('print_result')
- if return_type != 'void':
+ if return_type != CTS.types.void:
ilasm.opcode('ldloc', 'res')
format_object(RETURN_TYPE, self.cts, ilasm)
ilasm.call('void class [mscorlib]System.Console::WriteLine(string)')
@@ -112,13 +112,13 @@
def __convert_method(self, arg_type):
_conv = {
- 'int32': 'ToInt32',
- 'unsigned int32': 'ToUInt32',
- 'int64': 'ToInt64',
- 'unsigned int64': 'ToUInt64',
- 'bool': 'ToBoolean',
- 'float64': 'ToDouble',
- 'char': 'ToChar',
+ CTS.types.int32: 'ToInt32',
+ CTS.types.uint32: 'ToUInt32',
+ CTS.types.int64: 'ToInt64',
+ CTS.types.uint64: 'ToUInt64',
+ CTS.types.bool: 'ToBoolean',
+ CTS.types.float64: 'ToDouble',
+ CTS.types.char: 'ToChar',
}
try:
Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_snippet.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_snippet.py (original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_snippet.py Mon Aug 27 14:55:29 2007
@@ -13,3 +13,31 @@
res = self.ll_to_list(self.interpret(fn, []))
assert res == [52, 53, 54]
+ def test_mangle(self):
+ class Foo:
+ def le(self):
+ return 42
+
+ def fn():
+ f = Foo()
+ return f.le()
+ res = self.interpret(fn, [], backendopt=False)
+
+ def test_link_vars_overlapping(self):
+ from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift
+ def fn(maxofs):
+ lastofs = 0
+ ofs = 1
+ while ofs < maxofs:
+ lastofs = ofs
+ try:
+ ofs = ovfcheck_lshift(ofs, 1)
+ except OverflowError:
+ ofs = maxofs
+ else:
+ ofs = ofs + 1
+ return lastofs
+ res = self.interpret(fn, [64])
+ expected = fn(64)
+ assert res == expected
+
Modified: pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_string.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_string.py (original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/cli/test/test_string.py Mon Aug 27 14:55:29 2007
@@ -24,3 +24,8 @@
def test_getitem_exc(self):
py.test.skip('fixme!')
+ def test_compare(self):
+ strings = ['aa', 'ZZ']
+ def fn(i, j):
+ return strings[i] < strings[j]
+ assert self.interpret(fn, [0, 1], backendopt=False) == fn(0, 1)
Modified: pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/function.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/function.py (original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/function.py Mon Aug 27 14:55:29 2007
@@ -11,6 +11,8 @@
class Function(object):
+
+ auto_propagate_exceptions = False
def __init__(self, db, graph, name = None, is_method = False, is_entrypoint = False):
self.db = db
@@ -140,9 +142,17 @@
for op in block.operations[:-1]:
self._render_op(op)
+ anyHandler = False
+ for link in block.exits:
+ if link.exitcase is None:
+ continue
+ if not self._is_raise_block(link.target):
+ anyHandler = True
+ anyHandler = anyHandler or not self.auto_propagate_exceptions
+
# render the last one (if any!) and prepend a .try
if block.operations:
- self.begin_try()
+ self.begin_try(anyHandler)
self._render_op(block.operations[-1])
# search for the "default" block to be executed when no
@@ -150,7 +160,7 @@
for link in block.exits:
if link.exitcase is None:
self._setup_link(link)
- self.end_try(self._get_block_name(link.target))
+ self.end_try(self._get_block_name(link.target), anyHandler)
break
else:
assert False, "No non-exceptional case from exc_handling block"
@@ -160,6 +170,8 @@
if link.exitcase is None:
continue # see above
assert issubclass(link.exitcase, py.builtin.BaseException)
+ if self._is_raise_block(link.target) and self.auto_propagate_exceptions:
+ continue # let the exception propagate
ll_meta_exc = link.llexitcase
self.record_ll_meta_exc(ll_meta_exc)
self.begin_catch(link.llexitcase)
@@ -218,13 +230,17 @@
def render_numeric_switch_naive(self, block):
for link in block.exits:
target_label = self._get_block_name(link.target)
- self._setup_link(link)
if link.exitcase == 'default':
+ self._setup_link(link)
self.generator.branch_unconditionally(target_label)
else:
+ next_case = self.next_label('next_case')
self.generator.push_primitive_constant(block.exitswitch.concretetype, link.exitcase)
self.generator.load(block.exitswitch)
- self.generator.branch_if_equal(target_label)
+ self.generator.branch_if_not_equal(next_case)
+ self._setup_link(link)
+ self.generator.branch_unconditionally(target_label)
+ self.set_label(next_case)
def _follow_link(self, link):
target_label = self._get_block_name(link.target)
@@ -233,20 +249,54 @@
def _setup_link(self, link):
target = link.target
+ linkvars = []
for to_load, to_store in zip(link.args, target.inputargs):
if isinstance(to_load, flowmodel.Variable) and to_load.name == to_store.name:
continue
if to_load.concretetype is ootype.Void:
continue
- self.generator.add_comment("%r --> %r" % (to_load, to_store))
+ linkvars.append((to_load, to_store))
+
+ # after SSI_to_SSA it can happen to have to_load = [a, b] and
+ # to_store = [b, c]. If we store each variable sequentially,
+ # 'b' would be overwritten before being read. To solve, we
+ # first load all the values on the stack, then store in the
+ # appropriate places.
+
+ if self._trace_enabled():
+ self._trace('link', writeline=True)
+ for to_load, to_store in linkvars:
+ self._trace_value('%s <-- %s' % (to_store, to_load), to_load)
+ self._trace('', writeline=True)
+
+ for to_load, to_store in linkvars:
self.generator.load(to_load)
+ for to_load, to_store in reversed(linkvars):
self.generator.store(to_store)
+ def _trace_enabled(self):
+ return False
+
+ def _trace(self, s):
+ raise NotImplementedError
+
+ def _trace_value(self, prompt, v):
+ raise NotImplementedError
+
def _render_op(self, op):
instr_list = self.db.genoo.opcodes.get(op.opname, None)
assert instr_list is not None, 'Unknown opcode: %s ' % op
assert isinstance(instr_list, InstructionList)
+
+ if self._trace_enabled():
+ self._trace(str(op), writeline=True)
+ for i, arg in enumerate(op.args):
+ self._trace_value('Arg %02d' % i, arg)
+
instr_list.render(self.generator, op)
+
+ if self._trace_enabled():
+ self._trace_value('Result', op.result)
def _render_sub_op(self, sub_op):
op = sub_op.op
Modified: pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/snippets.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/snippets.py (original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/oosupport/test_template/snippets.py Mon Aug 27 14:55:29 2007
@@ -48,3 +48,16 @@
obj.x = x + y
return obj.x
assert self.interpret(fn, [1,3]) == 4
+
+ def test_link(self):
+ def fn():
+ plus = False
+ for c in 'a':
+ if c == 'b':
+ plus = True
+ elif c == 'c':
+ binary = True
+ return plus
+ res = self.interpret(fn, [])
+ expected = fn()
+ assert res == expected
More information about the Pypy-commit
mailing list