[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