[pypy-svn] r12018 - in pypy/dist/pypy: annotation translator translator/genc translator/genc/test translator/test
tismer at codespeak.net
tismer at codespeak.net
Fri May 6 14:19:03 CEST 2005
Author: tismer
Date: Fri May 6 14:19:03 2005
New Revision: 12018
Modified:
pypy/dist/pypy/annotation/binaryop.py
pypy/dist/pypy/translator/genc/ctyper.py
pypy/dist/pypy/translator/genc/test/test_typed.py
pypy/dist/pypy/translator/test/snippet.py
pypy/dist/pypy/translator/transform.py
Log:
temporary check-in of a working version
of ovfcheck handling.
Please don't look into transform.py,
this is completely a hack
and will be replaced by the real one, today.
I had to merge stuff before I get too big diffs.
Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py (original)
+++ pypy/dist/pypy/annotation/binaryop.py Fri May 6 14:19:03 2005
@@ -164,16 +164,17 @@
unsigned=unsigned)
- add = mul = or_ = xor = _clone(union, [])
- div = floordiv = mod = _clone(union, [ZeroDivisionError])
+ or_ = xor = _clone(union, [])
+ add = mul = _clone(union, [OverflowError])
+ div = floordiv = mod = _clone(union, [ZeroDivisionError, OverflowError])
def truediv((int1, int2)):
return SomeFloat()
- truediv.can_only_throw = [ZeroDivisionError]
+ truediv.can_only_throw = [ZeroDivisionError, OverflowError]
def sub((int1, int2)):
return SomeInteger(unsigned = int1.unsigned or int2.unsigned)
- sub.can_only_throw = []
+ sub.can_only_throw = [OverflowError]
def and_((int1, int2)):
unsigned = int1.unsigned or int2.unsigned
@@ -185,14 +186,15 @@
if int1.unsigned:
return SomeInteger(unsigned=True)
return SomeInteger()
- lshift.can_only_throw = []
+ lshift.can_only_throw = [ValueError]
rshift = lshift
+ lshift_ovf = _clone(lshift, [ValueError, OverflowError])
def pow((int1, int2), obj3):
if int1.unsigned or int2.unsigned or getattr(obj3, 'unsigned', False):
return SomeInteger(unsigned=True)
return SomeInteger()
- pow.can_only_throw = [ZeroDivisionError]
+ pow.can_only_throw = [ZeroDivisionError, OverflowError]
class __extend__(pairtype(SomeBool, SomeBool)):
Modified: pypy/dist/pypy/translator/genc/ctyper.py
==============================================================================
--- pypy/dist/pypy/translator/genc/ctyper.py (original)
+++ pypy/dist/pypy/translator/genc/ctyper.py Fri May 6 14:19:03 2005
@@ -44,32 +44,22 @@
])
for op in "rshift".split():
specializationtable.extend([
- ('%s' % op, 'int_%s' % op) + ii_i,
- ('inplace_%s' % op, 'int_%s' % op) + ii_i,
- ('%s_val' % op, 'int_%s_val' % op) + ii_i,
- ('inplace_%s_val' % op, 'int_%s_val' % op) + ii_i,
+ ('%s' % op, 'int_%s_val' % op) + ii_i,
+ ('inplace_%s' % op, 'int_%s_val' % op) + ii_i,
])
for op in "lshift".split():
specializationtable.extend([
- ('%s' % op, 'int_%s' % op) + ii_i,
- ('inplace_%s' % op, 'int_%s' % op) + ii_i,
- ('%s_ovf' % op, 'int_%s_ovf' % op) + ii_i,
- ('inplace_%s_ovf' % op, 'int_%s_ovf' % op) + ii_i,
- ('%s_val' % op, 'int_%s_val' % op) + ii_i,
- ('inplace_%s_val' % op, 'int_%s_val' % op) + ii_i,
- ('%s_ovf_val' % op, 'int_%s_ovf_val' % op) + ii_i,
- ('inplace_%s_ovf_val' % op, 'int_%s_ovf_val' % op) + ii_i,
+ ('%s' % op, 'int_%s_val' % op) + ii_i,
+ ('inplace_%s' % op, 'int_%s_val' % op) + ii_i,
+ ('%s_ovf' % op, 'int_%s_ovf_val' % op) + ii_i,
+ ('inplace_%s_ovf' % op, 'int_%s_ovf_val' % op) + ii_i,
])
for op in "floordiv mod".split():
specializationtable.extend([
- ('%s' % op, 'int_%s' % op) + ii_i,
- ('inplace_%s' % op, 'int_%s' % op) + ii_i,
- ('%s_ovf' % op, 'int_%s_ovf' % op) + ii_i,
- ('inplace_%s_ovf' % op, 'int_%s_ovf' % op) + ii_i,
- ('%s_zer' % op, 'int_%s_zer' % op) + ii_i,
- ('inplace_%s_zer' % op, 'int_%s_zer' % op) + ii_i,
- ('%s_ovf_zer' % op, 'int_%s_ovf_zer' % op) + ii_i,
- ('inplace_%s_ovf_zer' % op, 'int_%s_ovf_zer' % op) + ii_i,
+ ('%s' % op, 'int_%s_zer' % op) + ii_i,
+ ('inplace_%s' % op, 'int_%s_zer' % op) + ii_i,
+ ('%s_ovf' % op, 'int_%s_ovf_zer' % op) + ii_i,
+ ('inplace_%s_ovf' % op, 'int_%s_ovf_zer' % op) + ii_i,
])
# initialization
Modified: pypy/dist/pypy/translator/genc/test/test_typed.py
==============================================================================
--- pypy/dist/pypy/translator/genc/test/test_typed.py (original)
+++ pypy/dist/pypy/translator/genc/test/test_typed.py Fri May 6 14:19:03 2005
@@ -8,7 +8,7 @@
from pypy.translator.genc.test.test_annotated import TestAnnotatedTestCase as _TestAnnotatedTestCase
-class TestTypedTestCase:##!!(_TestAnnotatedTestCase):
+class TestTypedTestCase(_TestAnnotatedTestCase):
def getcompiled(self, func):
t = Translator(func, simplifying=True)
@@ -19,35 +19,31 @@
if isinstance(spec, tuple):
spec = spec[0] # use the first type only for the tests
argstypelist.append(spec)
- t.view()##!!
a = t.annotate(argstypelist)
- t.view()##!!
a.simplify()
- t.view()##!!
GenCSpecializer(a).specialize()
- t.view()##!!
t.checkgraphs()
return skip_missing_compiler(t.ccompile)
- def xxx_testint_overflow(self):
+ def test_int_overflow(self):
fn = self.getcompiled(snippet.add_func)
raises(OverflowError, fn, sys.maxint)
- def xxx_testint_div_ovf_zer(self):
+ def test_int_div_ovf_zer(self):
fn = self.getcompiled(snippet.div_func)
raises(OverflowError, fn, -1)
raises(ZeroDivisionError, fn, 0)
- def testint_mod_ovf_zer(self):
+ def test_int_mod_ovf_zer(self):
fn = self.getcompiled(snippet.mod_func)
raises(OverflowError, fn, -1)
raises(ZeroDivisionError, fn, 0)
- def xxx_testint_rshift_val(self):
+ def test_int_rshift_val(self):
fn = self.getcompiled(snippet.rshift_func)
raises(ValueError, fn, -1)
- def testint_lshift_ovf_val(self):
+ def test_int_lshift_ovf_val(self):
fn = self.getcompiled(snippet.lshift_func)
raises(ValueError, fn, -1)
raises(OverflowError, fn, 1)
Modified: pypy/dist/pypy/translator/test/snippet.py
==============================================================================
--- pypy/dist/pypy/translator/test/snippet.py (original)
+++ pypy/dist/pypy/translator/test/snippet.py Fri May 6 14:19:03 2005
@@ -84,6 +84,46 @@
def simple_func(i=numtype):
return i + 1
+from pypy.tool.rarithmetic import ovfcheck, ovfcheck_lshift
+
+def add_func(i=numtype):
+ try:
+ return ovfcheck(i + 1)
+ except OverflowError:
+ raise
+
+from sys import maxint
+
+def div_func(i=numtype):
+ try:
+ return ovfcheck((-maxint-1) // i)
+ except OverflowError:
+ raise
+ except ZeroDivisionError:
+ raise
+
+def mod_func(i=numtype):
+ try:
+ return ovfcheck((-maxint-1) % i)
+ except OverflowError:
+ raise
+ except ZeroDivisionError:
+ raise
+
+def rshift_func(i=numtype):
+ try:
+ return (-maxint-1) >> i
+ except ValueError:
+ raise
+
+def lshift_func(i=numtype):
+ try:
+ return ovfcheck_lshift((-maxint-1), i)
+ except OverflowError:
+ raise
+ except ValueError:
+ raise
+
def while_func(i=numtype):
total = 0
while i > 0:
Modified: pypy/dist/pypy/translator/transform.py
==============================================================================
--- pypy/dist/pypy/translator/transform.py (original)
+++ pypy/dist/pypy/translator/transform.py Fri May 6 14:19:03 2005
@@ -96,7 +96,7 @@
return (ops and ops[-1].opname == "simple_call"
and ops[-1].args[0] in covf)
def is_single(bl):
- return is_ovfcheck(bl) and len(bl.operations) > 1
+ return is_ovfcheck(bl)## and len(bl.operations) > 1
def is_paired(bl):
return bl.exits and is_ovfcheck(bl.exits[0].target)
def rename(v):
@@ -104,8 +104,15 @@
for block in fully_annotated_blocks(self):
renaming = {}
if is_single(block):
- print 100*"*"
- print block.operations[-2]
+ print 79*"*"
+ print block.operations
+ if block.operations[-1].args[0] == covf[-1]: # rewrite it
+ op = block.operations[-1]
+ op.opname = "lshift_ovf" # XXX
+ op.args = op.args[1:]
+ continue
+ if len(block.operations) < 2:
+ continue
delop = block.operations.pop()
op = block.operations[-1]
assert len(delop.args) == 2
@@ -115,9 +122,14 @@
args = [rename(a) for a in exit.args]
exits.append(Link(args, exit.target, exit.exitcase))
elif is_paired(block):
- print 100*"+"
- print block.operations[-1]
+ print 79*"+"
+ print block.operations
ovfblock = block.exits[0].target
+ if ovfblock.operations[0].args[0] == covf[-1]: # rewrite it
+ op = ovfblock.operations[0]
+ op.opname = "lshift_ovf" # XXX
+ op.args = op.args[1:]
+ continue
assert len(ovfblock.operations) == 1
op = block.operations[-1]
exits = list(block.exits)
@@ -128,7 +140,7 @@
assert len(ovfblock.exits) == 2
ovexp = ovfblock.exits[1]
# space from block, last_ from ovfblock
- args = exits[0].args[:1] + ovexp.args[1:]
+ args = exits[0].args[:len(ovexp.args)-2] + ovexp.args[-2:]
exits.append(Link(args, ovexp.target, ovexp.exitcase))
block.exitswitch = ovfblock.exitswitch
else:
@@ -138,20 +150,75 @@
if exit.exitcase is Exception:
bl = exit.target
while len(bl.exits) == 2:
- if bl.operations[0].args[-1] == covfExc:
+ lastoparg = bl.operations[0].args[-1]
+ del bl.operations[:]
+ bl.exitswitch = None
+ if lastoparg == covfExc:
exit.exitcase = OverflowError
- exit.target = bl.exits[1].target
- assert len(exit.target.inputargs) == 1
- del exit.args[1:] # space only
+ bl.exits = [bl.exits[1]]
+ bl.exits[0].exitcase = None
break
else:
+ bl.exits = [bl.exits[0]]
bl = bl.exits[0].target
block.exits = []
block.recloseblock(*exits)
# finally, mangle the operation name
- apps = [op_appendices[exit.exitcase] for exit in block.exits[1:]]
- apps.sort()
- op.opname = '_'.join([op.opname]+apps)
+ #apps = [op_appendices[exit.exitcase] for exit in block.exits[1:]]
+ #apps.sort()
+ #if apps.count("ovf") == 2: apps.remove("ovf") # XXX HACK
+ op.opname += '_ovf' # .join([op.opname]+apps)
+
+def xxx_transform_ovfcheck(self):
+ """removes ovfcheck and ovfcheck_lshift calls"""
+ from pypy.tool.rarithmetic import ovfcheck, ovfcheck_lshift
+ covf = Constant(ovfcheck)
+ covflshift = Constant(ovfcheck_lshift)
+ covf_tests = covf, covflshift
+
+ def get_ovfcheck(bl):
+ ops = bl.operations
+ if ops:
+ op = ops[-1]
+ if (op.opname == "simple_call" and op.args[0] in covf_tests):
+ return op.args[0]
+ return None
+
+ def rename(v):
+ return renaming.get(v, v)
+
+ for block in fully_annotated_blocks(self):
+ renaming = {}
+ func = get_ovfcheck(block)
+ if not func:
+ continue
+ if func == covf:
+ print 30*"*", "ovfcheck"
+ # it is considered a programming error if ovfcheck is
+ # called on an operation that cannot raise.
+ # That means ovfcheck must be the blocks's only operation
+ assert len(block.operations) == 1, """ovfcheck is called on
+an operation that cannot raise an exception"""
+ # we remove the operation and error exits.
+ delop = block.operations.pop()
+ assert len(delop.args) == 2
+ renaming[delop.result] = delop.args[1]
+ exits = []
+ # leave the default exit, only
+ for exit in block.exits[:1]:
+ args = [rename(a) for a in exit.args]
+ exits.append(Link(args, exit.target, exit.exitcase))
+ block.exits = exits
+ block.exitswitch = None
+ else:
+ print 30*"+", "ovfcheck_lshift"
+ # the only thing we have to do here is to replace
+ # the function call by an lshift operator
+ op = block.operations[-1]
+ op.opname = "lshift"
+ op.args = op.args[1:] # drop the function
+
+
# a(*b)
# -->
# c = newtuple(*b)
More information about the Pypy-commit
mailing list