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

ericvrp at codespeak.net ericvrp at codespeak.net
Wed Jul 27 22:00:47 CEST 2005


Author: ericvrp
Date: Wed Jul 27 22:00:45 2005
New Revision: 15211

Modified:
   pypy/dist/pypy/translator/llvm2/arraynode.py
   pypy/dist/pypy/translator/llvm2/build_llvm_module.py
   pypy/dist/pypy/translator/llvm2/codewriter.py
   pypy/dist/pypy/translator/llvm2/funcnode.py
   pypy/dist/pypy/translator/llvm2/module/extfunction.py
   pypy/dist/pypy/translator/llvm2/opaquenode.py
   pypy/dist/pypy/translator/llvm2/opwriter.py
   pypy/dist/pypy/translator/llvm2/structnode.py
   pypy/dist/pypy/translator/llvm2/test/test_class.py
   pypy/dist/pypy/translator/llvm2/test/test_exception.py
Log:
- made llvm output more verbose, it is so hard to read already
- refactored build_llvm_module a little
- funcnode.py phi node blocknames modified when coming from an invoke
  (because I needed to add a block when an exception occured)

All in all exceptions are getting real close (or so it seems)



Modified: pypy/dist/pypy/translator/llvm2/arraynode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/arraynode.py	(original)
+++ pypy/dist/pypy/translator/llvm2/arraynode.py	Wed Jul 27 22:00:45 2005
@@ -22,7 +22,7 @@
         # constructor_decl is used to declare the constructor
         # for the array type (see writeimpl)
         c = nextnum()
-        self.ref = "%%array.%s.%s" % (c, self.arraytype)
+        self.ref = "%%arraytype.%s.%s" % (c, self.arraytype)
         self.constructor_ref = "%%new.array.%s" % c 
         self.constructor_decl = "%s * %s(int %%len)" % \
                                 (self.ref, self.constructor_ref)
@@ -101,7 +101,18 @@
                                               typeval,
                                               ", ".join(arrayvalues))
 
-        return "%s {%s}" % (self.get_typerepr(), value)
+        s = "%s {%s}" % (self.get_typerepr(), value)
+        #XXX this does not work for arrays inlined in struct. How else to do this?
+        #if typeval == 'sbyte':  #give more feedback for strings
+        #    limited_printable = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/-.'
+        #    s += ' ;"'
+        #    for item in items:
+        #        if item in limited_printable:
+        #            s += item
+        #        else:
+        #            s += '_'
+        #    s += '" '
+        return s
     
     # ______________________________________________________________________
     # entry points from genllvm

Modified: pypy/dist/pypy/translator/llvm2/build_llvm_module.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/build_llvm_module.py	(original)
+++ pypy/dist/pypy/translator/llvm2/build_llvm_module.py	Wed Jul 27 22:00:45 2005
@@ -18,6 +18,7 @@
     pass
 
 OPTIMIZATION_SWITCHES = "-simplifycfg -mem2reg -instcombine -dce -inline"
+EXCEPTIONS_SWITCHES   = "-enable-correct-eh-support"
 
 def compile_module(module, source_files, object_files, library_files):
     open("%s_setup.py" % module, "w").write(str(py.code.Source(
@@ -52,10 +53,10 @@
         if optimize:
             cmds = ["llvm-as %s.ll -f -o %s.bc" % (b, b), 
                     "opt %s -f %s.bc -o %s_optimized.bc" % (OPTIMIZATION_SWITCHES, b, b),
-                    "llc -enable-correct-eh-support %s_optimized.bc -f -o %s.s" % (b, b)]
+                    "llc %s %s_optimized.bc -f -o %s.s" % (EXCEPTIONS_SWITCHES, b, b)]
         else:
             cmds = ["llvm-as %s.ll -f -o %s.bc" % (b, b),
-                    "llc -enable-correct-eh-support %s.bc -f -o %s.s" % (b, b)]
+                    "llc %s %s.bc -f -o %s.s" % (EXCEPTIONS_SWITCHES, b, b)]
         cmds.append("as %s.s -o %s.o" % (b, b))
         object_files.append("%s.o" % b)
     else:       #assume 64 bit platform (x86-64?)
@@ -63,10 +64,10 @@
         if optimize:
             cmds = ["llvm-as %s.ll -f -o %s.bc" % (b, b), 
                     "opt %s -f %s.bc -o %s_optimized.bc" % (OPTIMIZATION_SWITCHES, b, b),
-                    "llc -enable-correct-eh-support %s_optimized.bc -march=c -f -o %s.c" % (b, b)]
+                    "llc %s %s_optimized.bc -march=c -f -o %s.c" % (EXCEPTIONS_SWITCHES, b, b)]
         else:
             cmds = ["llvm-as %s.ll -f -o %s.bc" % (b, b),
-                    "llc -enable-correct-eh-support %s.bc -march=c -f -o %s.c" % (b, b)]
+                    "llc %s %s.bc -march=c -f -o %s.c" % (EXCEPTIONS_SWITCHES, b, b)]
         source_files.append("%s.c" % b)
 
     try:

Modified: pypy/dist/pypy/translator/llvm2/codewriter.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/codewriter.py	(original)
+++ pypy/dist/pypy/translator/llvm2/codewriter.py	Wed Jul 27 22:00:45 2005
@@ -16,7 +16,7 @@
         self._lines.append(line) 
         log(line) 
 
-    def comment(self, line, indent=False):
+    def comment(self, line, indent=True):
         line = ";; " + line
         if indent:
             self.indent(line)
@@ -30,6 +30,7 @@
         self.append("        " + line) 
 
     def label(self, name):
+        self.newline()
         self.append("    %s:" % name)
 
     def globalinstance(self, name, typeandata):
@@ -49,18 +50,26 @@
         self.append("declare %s" %(decl,))
 
     def startimpl(self):
-        self.append("")
+        self.newline()
         self.append("implementation")
-        self.append("")
+        self.newline()
 
     def br_uncond(self, blockname): 
         self.indent("br label %%%s" %(blockname,))
 
-    def br(self, switch, blockname_false, blockname_true):
+    def br(self, cond, blockname_false, blockname_true):
         self.indent("br bool %s, label %%%s, label %%%s"
-                    % (switch, blockname_true, blockname_false))
+                    % (cond, blockname_true, blockname_false))
+
+    def switch(self, intty, cond, defaultdest, value_label):
+        labels = ''
+        for value, label in value_label:
+            labels += ' %s %s, label %%%s' % (intty, value, label)
+        self.indent("switch %s %s, label %%%s [%s ]"
+                    % (intty, cond, defaultdest, labels))
 
     def openfunc(self, decl): 
+        self.newline()
         self.append("%s {" % (decl,))
 
     def closefunc(self): 

Modified: pypy/dist/pypy/translator/llvm2/funcnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/funcnode.py	(original)
+++ pypy/dist/pypy/translator/llvm2/funcnode.py	Wed Jul 27 22:00:45 2005
@@ -17,7 +17,7 @@
         self.type_ = type_
         # XXX Make simplier for now, it is far too hard to read otherwise
         #self.ref = 'ft.%s.%s' % (type_, nextnum())
-        self.ref = '%%ft.%s' % (nextnum(),)
+        self.ref = '%%functiontype.%s' % (nextnum(),)
         
     def __str__(self):
         return "<FuncTypeNode %r>" % self.ref
@@ -114,6 +114,10 @@
             names = self.db.repr_arg_multi([link.args[i] for link in entrylinks])
             blocknames = [self.block_to_name[link.prevblock]
                               for link in entrylinks]
+            for i, link in enumerate(entrylinks):
+                if link.prevblock.exitswitch == Constant(last_exception) and \
+                   link.prevblock.exits[0].target != block:
+                    blocknames[i] += '_exception'
             if type_ != "void":
                 codewriter.phi(arg, type_, names, blocknames) 
 
@@ -137,7 +141,7 @@
         opwriter = OpWriter(self.db, codewriter, self, block)
         last_direct_call_index = self._last_operation(block, 'direct_call')
         for op_index, op in enumerate(block.operations):
-            codewriter.comment(str(op), indent=True)
+            codewriter.comment(str(op))
             if op_index == last_direct_call_index and block.exitswitch == Constant(last_exception):
                 op.opname = 'direct_invoke'
             opwriter.write_operation(op)
@@ -189,4 +193,5 @@
         #   Which is already stored in the global variables.
         #   So nothing needs to happen here!
 
+        codewriter.comment('reraise last exception')
         codewriter.unwind()

Modified: pypy/dist/pypy/translator/llvm2/module/extfunction.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/module/extfunction.py	(original)
+++ pypy/dist/pypy/translator/llvm2/module/extfunction.py	Wed Jul 27 22:00:45 2005
@@ -12,7 +12,7 @@
 declare int %read(int, sbyte*, int)
 declare sbyte* %strncpy(sbyte*, sbyte*, int)
 
-%st.rpy_string.0 = type {int, {int, [0 x sbyte]}}
+%structtype.rpy_string = type {int, {int, [0 x sbyte]}}
 
 %last_exception_type  = global long 0
 %last_exception_value = global long 0
@@ -50,14 +50,14 @@
 extfunctions = {}   #dependencies, llvm-code
 
 extfunctions["%cast"] = ((), """
-sbyte* %cast(%st.rpy_string.0* %structstring) {
-    %reallengthptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 0
+sbyte* %cast(%structtype.rpy_string* %structstring) {
+    %reallengthptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 0
     %reallength = load int* %reallengthptr 
     %length = add int %reallength, 1
     %ulength = cast int %length to uint 
     %dest = call sbyte* %gc_malloc_atomic(uint %ulength)
 
-    %source1ptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 1
+    %source1ptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 1
     %source1 = cast [0 x sbyte]* %source1ptr to sbyte* 
     %dummy = call sbyte* %strncpy(sbyte* %dest, sbyte* %source1, int %reallength) 
 
@@ -117,8 +117,8 @@
 """)
 
 extfunctions["%ll_os_open"] = (("%cast",), """
-int %ll_os_open(%st.rpy_string.0* %structstring, int %flag, int %mode) {
-    %dest  = call sbyte* %cast(%st.rpy_string.0* %structstring)
+int %ll_os_open(%structtype.rpy_string* %structstring, int %flag, int %mode) {
+    %dest  = call sbyte* %cast(%structtype.rpy_string* %structstring)
     %fd    = call int    %open(sbyte* %dest, int %flag, int %mode)
     ret int %fd 
 }
@@ -126,10 +126,10 @@
 """)
 
 extfunctions["%ll_os_write"] = (("%cast",), """
-int %ll_os_write(int %fd, %st.rpy_string.0* %structstring) {
-    %reallengthptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 0
+int %ll_os_write(int %fd, %structtype.rpy_string* %structstring) {
+    %reallengthptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 0
     %reallength    = load int* %reallengthptr 
-    %dest          = call sbyte* %cast(%st.rpy_string.0* %structstring)
+    %dest          = call sbyte* %cast(%structtype.rpy_string* %structstring)
     %byteswritten  = call int    %write(int %fd, sbyte* %dest, int %reallength)
     ret int %byteswritten
 }
@@ -137,11 +137,11 @@
 """)
 
 extfunctions["%ll_read_into"] = ((), """
-int %ll_read_into(int %fd, %st.rpy_string.0* %structstring) {
-    %reallengthptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 0
+int %ll_read_into(int %fd, %structtype.rpy_string* %structstring) {
+    %reallengthptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 0
     %reallength    = load int* %reallengthptr 
 
-    %destptr   = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 1
+    %destptr   = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 1
     %dest      = cast [0 x sbyte]* %destptr to sbyte*
 
     %bytesread = call int %read(int %fd, sbyte* %dest, int %reallength)

Modified: pypy/dist/pypy/translator/llvm2/opaquenode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/opaquenode.py	(original)
+++ pypy/dist/pypy/translator/llvm2/opaquenode.py	Wed Jul 27 22:00:45 2005
@@ -7,7 +7,7 @@
         assert isinstance(opaquetype, lltype.OpaqueType)
         self.db = db
         self.opaquetype = opaquetype
-        self.ref = "%%opaque.%s" % (opaquetype.tag)
+        self.ref = "%%opaquetype.%s" % (opaquetype.tag)
         
     def __str__(self):
         return "<OpaqueNode %r>" %(self.ref,)

Modified: pypy/dist/pypy/translator/llvm2/opwriter.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/opwriter.py	(original)
+++ pypy/dist/pypy/translator/llvm2/opwriter.py	Wed Jul 27 22:00:45 2005
@@ -3,7 +3,6 @@
 from pypy.rpython import lltype
 from pypy.translator.llvm2.atomic import is_atomic
 from pypy.translator.llvm2.log import log 
-nextexclabel = py.std.itertools.count().next
 log = log.opwriter
 
 class OpWriter(object):
@@ -181,33 +180,54 @@
 
     def direct_invoke(self, op):
         assert len(op.args) >= 1
+        assert len(self.block.exits) >= 2   #at least one label and one exception label
+
+        link = self.block.exits[0]
+        assert link.exitcase is None
+
         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:])
 
-        link = self.block.exits[0]
-        assert link.exitcase is None
-        label = self.node.block_to_name[link.target]
-
-        assert len(self.block.exits) > 1
-        link = self.block.exits[1]      #XXX need an additional block if we catch multiple exc.types!
-        exc_label = self.node.block_to_name[link.target]
-
-        if len(self.block.exits) > 2:
-            msg = 'XXX Exception handling incomplete implementation warning: n_exits=%d' % (len(self.block.exits),)
-            print msg
-            self.codewriter.comment(msg, indent=True)
-        #exc_label = 'exception_block.%d' % nextexclabel()
+        none_label      = self.node.block_to_name[link.target]
+        exc_label       = self.node.block_to_name[self.block] + '_exception'
+        exc_error_label = exc_label + '_error'
 
         if returntype != "void":
             self.codewriter.invoke(targetvar, returntype, functionref, argrefs,
-                                 argtypes, label, exc_label)
+                                 argtypes, none_label, exc_label)
         else:
-            self.codewriter.invoke_void(functionref, argrefs, argtypes, label, exc_label)
+            self.codewriter.invoke_void(functionref, argrefs, argtypes, none_label, exc_label)
 
-        #self.codewriter.label(exc_label)
+        self.codewriter.label(exc_label)
+        value_label = []
+        value = 0
+        for link in self.block.exits[1:]:
+            assert issubclass(link.exitcase, Exception)
+
+            target = self.node.block_to_name[link.target]
+            value_label.append( (value,target) )
+            value += 1
+
+            #msg = 'XXX Exception target=%s, exitcase=%s, last_exception.concretetype=%s' % \
+            #    (str(target), str(link.exitcase), link.last_exception.concretetype)
+            #self.codewriter.comment(msg)
+            #self.codewriter.comment('TODO: in %s rename %s to %s' % (target, self.node.block_to_name[self.block], exc_label))
+
+        tmptype1, tmpvar1 = 'long'                , self.db.repr_tmpvar()
+        self.codewriter.load(tmpvar1, tmptype1, '%last_exception_type')
+
+        #tmptype2, tmpvar2 = '%structtype.object_vtable*', self.db.repr_tmpvar()
+        #self.codewriter.cast(tmpvar2, tmptype1, tmpvar1, tmptype2)
+        #self.codewriter.switch(tmptype2, tmpvar2, exc_error_label, value_label)
+
+        self.codewriter.switch(tmptype1, tmpvar1, exc_error_label, value_label)
+        self.codewriter.label(exc_error_label)
+        self.codewriter.comment('dead code ahead')
+        self.codewriter.ret('int', '0')
+        #self.codewriter.unwind()   #this causes llvm to crash?!?
 
     def malloc(self, op): 
         targetvar = self.db.repr_arg(op.result) 
@@ -244,9 +264,8 @@
                                           ("uint", index))        
             self.codewriter.load(targetvar, targettype, tmpvar)
         else:
-            self.codewriter.comment("***Skipping operation getfield()***",
-                                    indent=True)
-                        
+            self.codewriter.comment("***Skipping operation getfield()***")
+ 
     def getsubstruct(self, op): 
         struct, structtype = self.db.repr_argwithtype(op.args[0])
         fieldnames = list(op.args[0].concretetype.TO._names)

Modified: pypy/dist/pypy/translator/llvm2/structnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/structnode.py	(original)
+++ pypy/dist/pypy/translator/llvm2/structnode.py	Wed Jul 27 22:00:45 2005
@@ -17,7 +17,7 @@
         self.db = db
         self.struct = struct
         self.name = "%s.%s" % (self.struct._name , nextnum())
-        self.ref = "%%st.%s" % (self.name)
+        self.ref = "%%structtype.%s" % (self.name)
         
     def __str__(self):
         return "<StructTypeNode %r>" %(self.ref,)
@@ -42,7 +42,7 @@
 
     def __init__(self, db, struct): 
         super(StructVarsizeTypeNode, self).__init__(db, struct)
-        self.constructor_ref = "%%new.st.var.%s" % (self.name)
+        self.constructor_ref = "%%newvarsizestruct.%s" % (self.name)
         self.constructor_decl = "%s * %s(int %%len)" % \
                                 (self.ref, self.constructor_ref)
 
@@ -89,7 +89,7 @@
         self.db = db
         self.value = value
         self.structtype = self.value._TYPE
-        self.ref = "%%stinstance.%s" % (nextnum(),)
+        self.ref = "%%structinstance.%s" % (nextnum(),)
         
     def __str__(self):
         return "<StructNode %r>" % (self.ref,)

Modified: pypy/dist/pypy/translator/llvm2/test/test_class.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/test/test_class.py	(original)
+++ pypy/dist/pypy/translator/llvm2/test/test_class.py	Wed Jul 27 22:00:45 2005
@@ -24,15 +24,18 @@
         f = compile_function(llvmsnippet.class_simple2, [int])
         assert f(2) == 10
 
-    def SEGFAULTtest_method_of_base_class(self):
+    def test_method_of_base_class(self):
+        py.test.skip("not working yet (segfault)")
         f = compile_function(llvmsnippet.method_of_base_class, [])
         assert f() == 14
 
-    def SEGFAULTtest_attribute_from_base_class(self):
+    def test_attribute_from_base_class(self):
+        py.test.skip("not working yet (segfault)")
         f = compile_function(llvmsnippet.attribute_from_base_class, [])
         assert f() == 4
 
-    def SEGFAULTtest_direct_call_of_virtual_method(self):
+    def test_direct_call_of_virtual_method(self):
+        py.test.skip("not working yet (segfault)")
         f = compile_function(llvmsnippet.direct_call_of_virtual_method, [])
         assert f() == 14
 

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	Wed Jul 27 22:00:45 2005
@@ -11,6 +11,7 @@
         self.n = n
 
 def test_simple1():
+    py.test.skip("not working yet")
     def raise_(i):
         if i:
             raise TestException()
@@ -42,6 +43,33 @@
     assert f( 0) == fn( 0)
     assert f(10) == fn(10)
 
+def test_simple3():
+    py.test.skip("not working yet")
+    def raise_(i):
+        if i == 0:
+            raise TestException()
+        elif i == 1:
+            raise MyException(42)
+        else:
+            return 3
+    def fn(i):
+        try:
+            a = raise_(i) + 11
+            b = raise_(i) + 12
+            c = raise_(i) + 13
+            return a+b+c
+        except TestException: 
+            return 7
+        except MyException: 
+            return 123
+        except:
+            return 22
+        return 66
+    f = compile_function(fn, [int])
+    assert f(0) == fn(0)
+    assert f(1) == fn(1)
+    assert f(2) == fn(2)
+
 def test_pass_exc():
     def fn(n):
         lst = range(10)



More information about the Pypy-commit mailing list