[pypy-svn] r15701 - in pypy/dist/pypy/translator/llvm2: . module test

ericvrp at codespeak.net ericvrp at codespeak.net
Fri Aug 5 17:51:31 CEST 2005


Author: ericvrp
Date: Fri Aug  5 17:51:30 2005
New Revision: 15701

Modified:
   pypy/dist/pypy/translator/llvm2/funcnode.py
   pypy/dist/pypy/translator/llvm2/genllvm.py
   pypy/dist/pypy/translator/llvm2/module/support.py
   pypy/dist/pypy/translator/llvm2/opwriter.py
   pypy/dist/pypy/translator/llvm2/test/test_exception.py
   pypy/dist/pypy/translator/llvm2/test/test_typed.py
Log:
- fixed bug that only direct_calls could raise exceptions, operations can now also
- added int_floordiv_zer and uint_floordiv_zer
- cleaned up similar attempt in genllvm.py



Modified: pypy/dist/pypy/translator/llvm2/funcnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/funcnode.py	(original)
+++ pypy/dist/pypy/translator/llvm2/funcnode.py	Fri Aug  5 17:51:30 2005
@@ -156,30 +156,28 @@
             codewriter.br(cond, self.block_to_name[block.exits[0].target],
                           self.block_to_name[block.exits[1].target])
 
-    def _last_operation(self, block, opname):
-        last_index = None
-        for op_index, op in enumerate(block.operations):
-            if op.opname == opname:
-                last_index = op_index
-        return last_index
-
     def write_block_operations(self, codewriter, block):
         opwriter = OpWriter(self.db, codewriter, self, block)
-        last_direct_call_index = self._last_operation(block, 'direct_call')
+        if block.exitswitch == Constant(last_exception):
+            last_op_index = len(block.operations) - 1
+        else:
+            last_op_index = None
         for op_index, op in enumerate(block.operations):
-
-            # print out debug string
-            codewriter.newline()
-            codewriter.comment("** %s **" % str(op))
-            info = self.db.get_op2comment(op)
-            if info is not None:
-                lenofopstr, opstrname = info
-                codewriter.debugcomment(self.db.repr_tmpvar(),
-                                        lenofopstr,
-                                        opstrname)
-                
-            if op_index == last_direct_call_index and block.exitswitch == Constant(last_exception):
-                op.opname = 'direct_invoke'
+            if False:   # print out debug string
+                codewriter.newline()
+                codewriter.comment("** %s **" % str(op))
+                info = self.db.get_op2comment(op)
+                if info is not None:
+                    lenofopstr, opstrname = info
+                    codewriter.debugcomment(self.db.repr_tmpvar(),
+                                            lenofopstr,
+                                            opstrname)
+            if op_index == last_op_index:
+                #could raise an exception and should therefor have a function
+                #implementation that can be invoked by the llvm-code.
+                invoke_prefix = 'invoke:'
+                assert not op.opname.startswith(invoke_prefix)
+                op.opname = invoke_prefix + op.opname
             opwriter.write_operation(op)
 
     def write_startblock(self, codewriter, block):

Modified: pypy/dist/pypy/translator/llvm2/genllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/genllvm.py	(original)
+++ pypy/dist/pypy/translator/llvm2/genllvm.py	Fri Aug  5 17:51:30 2005
@@ -20,18 +20,6 @@
 
 function_count = {}
 
-# XXX Temp
-raise_impl = """
-ccc void %RaiseSimpleException(int %t, sbyte* %ptErr) {
-entry:
-        unwind
-	ret void
-}
-"""
-
-# XXX Temp
-raise_decl = "declare ccc void %RaiseSimpleException(int, sbyte*)"
-
 class GenLLVM(object):
 
     def __init__(self, translator, debug=False, embedexterns=True):
@@ -89,7 +77,6 @@
             
         nl(); comment("Function Prototypes") ; nl()
         if self.embedexterns:
-            codewriter.append(raise_decl)
             for extdecl in extdeclarations.split('\n'):
                 codewriter.append(extdecl)
 
@@ -125,9 +112,6 @@
                         codewriter.append(extfunc)
                     depdone[dep] = True
 
-        if self.embedexterns:
-            codewriter.append(raise_impl)
-
         #XXX use codewriter methods here
         decl = self.entrynode.getdecl()
         t = decl.split('%', 1)

Modified: pypy/dist/pypy/translator/llvm2/module/support.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/module/support.py	(original)
+++ pypy/dist/pypy/translator/llvm2/module/support.py	Fri Aug  5 17:51:30 2005
@@ -23,3 +23,54 @@
 }
 
 """)
+
+extfunctions["%__prepare_ZeroDivisionError"] = ((), """
+fastcc void %__prepare_ZeroDivisionError() {
+
+    %exception_value = call fastcc %structtype.object* %instantiate_ZeroDivisionError()
+
+    %tmp             = getelementptr %structtype.object* %exception_value, int 0, uint 0
+    %exception_type  = load %structtype.object_vtable** %tmp
+    store %structtype.object_vtable* %exception_type, %structtype.object_vtable** %last_exception_type
+    store %structtype.object* %exception_value, %structtype.object** %last_exception_value
+
+    ret void
+}
+
+""")
+
+extfunctions["%int_floordiv_zer"] = (("%__prepare_ZeroDivisionError",), """
+fastcc int %int_floordiv_zer(int %x, int %y) {
+    %cond = seteq int %y, 0
+    br bool %cond, label %is_0, label %is_not_0
+is_not_0:
+    %z = add int %x, %y
+    ret int %z
+is_0:
+    call fastcc void %__prepare_ZeroDivisionError()
+    unwind
+}
+
+""")
+
+#XXX could use template here
+extfunctions["%uint_floordiv_zer"] = (("%__prepare_ZeroDivisionError",), """
+fastcc uint %uint_floordiv_zer(uint %x, uint %y) {
+    %cond = seteq uint %y, 0
+    br bool %cond, label %is_0, label %is_not_0
+is_not_0:
+    %z = add uint %x, %y
+    ret uint %z
+is_0:
+    call fastcc void %__prepare_ZeroDivisionError()
+    unwind
+}
+
+""")
+
+#src/int.h:#define OP_INT_FLOORDIV_ZER(x,y,r,err) \     done
+#src/int.h:#define OP_UINT_FLOORDIV_ZER(x,y,r,err) \    done
+#src/int.h:#define OP_INT_FLOORDIV_OVF_ZER(x,y,r,err) \
+#src/int.h:#define OP_INT_MOD_ZER(x,y,r,err) \
+#src/int.h:#define OP_UINT_MOD_ZER(x,y,r,err) \
+#src/int.h:#define OP_INT_MOD_OVF_ZER(x,y,r,err) 

Modified: pypy/dist/pypy/translator/llvm2/opwriter.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/opwriter.py	(original)
+++ pypy/dist/pypy/translator/llvm2/opwriter.py	Fri Aug  5 17:51:30 2005
@@ -1,6 +1,8 @@
 import py
 from pypy.objspace.flow.model import Constant
 from pypy.rpython import lltype
+from pypy.translator.llvm2.module.extfunction import extfunctions
+from pypy.translator.llvm2.extfuncnode import ExternalFuncNode
 from pypy.translator.llvm2.log import log 
 log = log.opwriter
 
@@ -79,14 +81,18 @@
         self.block = block
 
     def write_operation(self, op):
-        if op.opname in self.binary_operations:
-            self.binaryop(op)
-        elif op.opname in self.shift_operations:
-            self.shiftop(op)
+        invoke = op.opname.startswith('invoke:')
+        if invoke:
+            self.invoke(op)
         else:
-            meth = getattr(self, op.opname, None)
-            assert meth is not None, "operation %r not found" %(op.opname,)
-            meth(op)    
+            if op.opname in self.binary_operations:
+                self.binaryop(op)
+            elif op.opname in self.shift_operations:
+                self.shiftop(op)
+            else:
+                meth = getattr(self, op.opname, None)
+                assert meth is not None, "operation %s not found" %(op.opname,)
+                meth(op)    
 
     def _generic_pow(self, op, onestr): 
         mult_type = self.db.repr_arg_type(op.args[0])
@@ -228,11 +234,21 @@
         else:
             self.codewriter.call_void(functionref, argrefs, argtypes)
 
-    def direct_invoke(self, op):
+    def invoke(self, op):
         # XXX hack as per remove_voids()
         op_args = [arg for arg in op.args
                    if arg.concretetype is not lltype.Void]
 
+        if op.opname == 'invoke:direct_call':
+            functionref = self.db.repr_arg(op_args[0])
+        else:   #operation
+            opname = op.opname.split(':',1)[1]
+            op_args = ['%' + opname] + op_args
+            functionref = op_args[0]
+            ExternalFuncNode.used_external_functions[functionref] = True
+            assert functionref in extfunctions, \
+                   "exception raising operation %(opname)s has no implementation" % locals()
+        
         assert len(op_args) >= 1
         assert len(self.block.exits) >= 2   #at least one label and one exception label
 
@@ -241,7 +257,6 @@
 
         targetvar = self.db.repr_arg(op.result)
         returntype = self.db.repr_arg_type(op.result)
-        functionref = self.db.repr_arg(op_args[0])
         argrefs = self.db.repr_arg_multi(op_args[1:])
         argtypes = self.db.repr_arg_type_multi(op_args[1:])
 

Modified: pypy/dist/pypy/translator/llvm2/test/test_exception.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/test/test_exception.py	(original)
+++ pypy/dist/pypy/translator/llvm2/test/test_exception.py	Fri Aug  5 17:51:30 2005
@@ -2,6 +2,7 @@
 
 from pypy.translator.llvm2.genllvm import compile_function
 from pypy.translator.test.snippet import try_raise_choose
+from pypy.rpython.rarithmetic import r_uint
 
 class TestException(Exception):
     pass
@@ -91,17 +92,28 @@
     assert f( 0) == fn( 0)
     assert f(10) == fn(10)
 
-#def test_divzero():
-#    py.test.skip("divzero not working yet")
-#    def fn(n):
-#        try:
-#            n/0
-#        except:
-#            return 2
-#        return 4
-#    f = compile_function(fn, [int])
-#    assert f(0) == fn(0)
-    
+def test_zerodiv_int():
+    def zerodiv_int(n):
+        try:
+            100/n
+        except ZeroDivisionError:
+            return n+7
+        return n+4
+    f = compile_function(zerodiv_int, [int])
+    assert f(1) == zerodiv_int(1)
+    assert f(0) == zerodiv_int(0)
+
+def test_zerodiv_uint():
+    def zerodiv_uint(n):
+        try:
+            100/n
+        except ZeroDivisionError:
+            return n+7
+        return n+4
+    f = compile_function(zerodiv_uint, [r_uint])
+    assert f(1) == zerodiv_uint(1)
+    assert f(0) == zerodiv_uint(0)
+
 def test_reraise1():
     def fn(n):
         lst = range(10)

Modified: pypy/dist/pypy/translator/llvm2/test/test_typed.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/test/test_typed.py	(original)
+++ pypy/dist/pypy/translator/llvm2/test/test_typed.py	Fri Aug  5 17:51:30 2005
@@ -211,7 +211,7 @@
 
 # floats 
 def test_float_operations(): 
-    py.test.skip("llvm rem operation doesnt seem to work...fixed in llvm cvs")    
+    #llvm rem operation working starting llvm1.6")    
     #see: http://llvm.cs.uiuc.edu/bugs/show_bug.cgi?id=611
     def func(x, y): 
         z = x + y / 2.1 * x 



More information about the Pypy-commit mailing list