[pypy-svn] r10385 - in pypy/dist/pypy/translator/llvm: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Thu Apr 7 00:37:20 CEST 2005


Author: cfbolz
Date: Thu Apr  7 00:37:20 2005
New Revision: 10385

Modified:
   pypy/dist/pypy/translator/llvm/class.ll
   pypy/dist/pypy/translator/llvm/classrepr.py
   pypy/dist/pypy/translator/llvm/funcrepr.py
   pypy/dist/pypy/translator/llvm/llvmbc.py
   pypy/dist/pypy/translator/llvm/seqrepr.py
   pypy/dist/pypy/translator/llvm/test/llvmsnippet.py
Log:
Some various fixes:
 * Exceptions that occur in LLVM code are caught and turned into a
   RuntimeError (which avoids crashing the interpreter)
 * The code generator tries to avoid creating empty blocks.


Modified: pypy/dist/pypy/translator/llvm/class.ll
==============================================================================
--- pypy/dist/pypy/translator/llvm/class.ll	(original)
+++ pypy/dist/pypy/translator/llvm/class.ll	Thu Apr  7 00:37:20 2005
@@ -8,6 +8,8 @@
 %std.last_exception.type = internal global %std.class* null
 %std.last_exception.value = internal global %std.exception* null
 
+%pypy__uncaught_exception = global int 0
+
 implementation
 
 

Modified: pypy/dist/pypy/translator/llvm/classrepr.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/classrepr.py	(original)
+++ pypy/dist/pypy/translator/llvm/classrepr.py	Thu Apr  7 00:37:20 2005
@@ -23,7 +23,7 @@
             bind = gen.annotator.binding(obj)
             if bind.__class__ is annmodel.SomePBC and \
                 gen.annotator.bookkeeper.userclasses.has_key(bind.const):
-                    classdef = gen.annotator.bookkeeper.userclasses[bind.const]
+                classdef = gen.annotator.bookkeeper.userclasses[bind.const]
         elif isinstance(obj, annmodel.SomeInstance):
             classdef = obj.classdef
         elif isinstance(obj, ClassDef):
@@ -46,6 +46,8 @@
                                              self.classdef.cls.__name__)
         if debug:
             print self.name
+        if ".Exception.object" in self.objectname:
+            1/0
         self.dependencies = sets.Set()
         self.setup_done = False
         self.attr_num = {}
@@ -59,9 +61,18 @@
             print len(ClassRepr.l_classes)
         gen = self.gen
         if self.classdef.basedef is not None: #get attributes from base classes
-            self.l_base = gen.get_repr(self.classdef.basedef)
+            #XXX if the base class is a builtin Exception we want the
+            #ExceptionTypeRepr, not the ClassRepr
+            if self.classdef.basedef.cls.__module__ == "exceptions":
+                self.l_base = gen.get_repr(self.classdef.basedef.cls)
+                #XXX we want something more complicated here:
+                #if the class has no __init__ function we need to insert the
+                #'args' attribute the builtin exceptions have
+                attribs = []
+            else:
+                self.l_base = gen.get_repr(self.classdef.basedef)
+                attribs = self.l_base.attributes
             self.dependencies.add(self.l_base)
-            attribs = self.l_base.attributes
         else:
             self.l_base = None
             attribs = []
@@ -114,7 +125,7 @@
             (l_tmp.llvmname(), self.objectname)
         lblock.instruction(i)
         lblock.instruction("store %%std.class* %s, %%std.class** %s" %
-                           (self.l_base.objectname, l_tmp.llvmname()))
+                           (self.l_base.llvmname(), l_tmp.llvmname()))
 
     def llvmtype(self):
         return "%std.class*"
@@ -212,7 +223,7 @@
 
 def create_builtin_exceptions(gen, dependencies):
     import exceptions
-    for exc in dir(exceptions):
+    for exc in ["IndexError"]:
         if "__" not in exc:
             l_exc = gen.get_repr(getattr(exceptions, exc))
             dependencies.add(l_exc)
@@ -256,6 +267,9 @@
     def llvmtype(self):
         return "%std.class* "
 
+    def llvmname(self):
+        return self.objectname
+
     def typed_name(self):
         return "%%std.class* %s" % self.objectname
 
@@ -267,7 +281,7 @@
             (l_tmp.llvmname(), self.objectname)
         lblock.instruction(i)
         lblock.instruction("store %%std.class* %s, %%std.class** %s" %
-                           (self.l_base.objectname, l_tmp.llvmname()))
+                           (self.l_base.llvmname(), l_tmp.llvmname()))
 
     def op_simple_call(self, l_target, args, lblock, l_func):
         lblock.malloc(l_target)

Modified: pypy/dist/pypy/translator/llvm/funcrepr.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/funcrepr.py	(original)
+++ pypy/dist/pypy/translator/llvm/funcrepr.py	Thu Apr  7 00:37:20 2005
@@ -197,7 +197,7 @@
                 l_arg = self.gen.get_repr(arg)
                 l_values = [l_l.l_args[i] for l_l in l_incoming_links]
                 self.l_func.dependencies.add(l_arg)
-                self.lblock.phi(l_arg, l_values, ["%" + l_l.blockname
+                self.lblock.phi(l_arg, l_values, ["%" + l_l.fromblock
                                                   for l_l in l_incoming_links])
 
     def create_space_ops(self):
@@ -232,14 +232,14 @@
         l_func = self.l_func
         l_link = LinkRepr.get_link(pyblock.exits[0], l_func, self.gen)
         if self.pyblock.exitswitch is None:
-            self.lblock.uncond_branch("%" + l_link.blockname)
+            self.lblock.uncond_branch("%" + l_link.toblock)
         else:
             l_switch = self.gen.get_repr(pyblock.exitswitch)
             l_link = LinkRepr.get_link(pyblock.exits[0], l_func, self.gen)
             l_link2 = LinkRepr.get_link(pyblock.exits[1], l_func, self.gen)
             l_func.dependencies.add(l_switch)
-            self.lblock.cond_branch(l_switch, "%" + l_link2.blockname,
-                                    "%" + l_link.blockname)
+            self.lblock.cond_branch(l_switch, "%" + l_link2.toblock,
+                                    "%" + l_link.toblock)
         #1 / 0
 
 
@@ -270,7 +270,7 @@
                                            regularblock, exceptblock)
         l_func.add_block(self.lblock)
         l_link = LinkRepr.get_link(pyblock.exits[0], l_func, gen)
-        self.lblock.regularblock = l_link.blockname
+        self.lblock.regularblock = l_link.toblock
         self.build_bb()
         self.build_exc_block()
 
@@ -303,7 +303,7 @@
         l_exitcases = [self.gen.get_repr(ex.exitcase)
                        for ex in self.pyblock.exits[1:]]
         self.l_func.dependencies.update(l_exitcases)
-        sw = [(str(abs(id(ex.exitcase))), "%" + l_l.blockname)
+        sw = [(str(abs(id(ex.exitcase))), "%" + l_l.toblock)
               for ex, l_l in zip(self.pyblock.exits[1:], l_exits)]
         lexcblock.switch(l_ui, "%" + self.lblock.label + ".unwind", sw)
         lunwindblock = llvmbc.BasicBlock(self.lblock.label + ".unwind")
@@ -357,6 +357,7 @@
         self.create_link_block()
 
     def create_link_block(self):
+        #a block is created in which the neccessary cast can be performed
         link = self.link
         l_func = self.l_func
         self.blockname = "bl%i_to_bl%i" % (l_func.blocknum[link.prevblock],
@@ -382,7 +383,18 @@
                 self.lblock.cast(l_tmp, l_a)
                 self.l_args[i] = l_tmp
         self.lblock.uncond_branch("%%block%i" % l_func.blocknum[link.target])
-        self.l_func.add_block(self.lblock)
+        #try to remove unneded blocks to increase readability
+        if len(self.lblock.instructions) == 1:
+            prevblock = self.link.prevblock
+            self.fromblock = "block%i" % self.l_func.blocknum[prevblock]
+            is_tryblock = isinstance(prevblock.exitswitch, Constant) and \
+                          prevblock.exitswitch.value == last_exception
+            if is_tryblock and self.link.exitcase not in (None, True, False):
+                 self.fromblock += ".except"
+            self.toblock = "block%i" % self.l_func.blocknum[self.link.target]
+        else:
+            self.fromblock = self.toblock = self.blockname
+            self.l_func.add_block(self.lblock)
 
 
 class EntryFunctionRepr(LLVMRepr):
@@ -396,23 +408,39 @@
     def setup(self):
         self.l_function = self.gen.get_repr(self.function)
         self.dependencies.add(self.l_function)
-        lblock = llvmbc.BasicBlock("entry")
         #XXX clean this up
+        #create entry block
+        lblock = llvmbc.BasicBlock("entry")
         lblock.instruction("%tmp = load bool* %Initialized.0__")
         lblock.instruction("br bool %tmp, label %real_entry, label %init")
         lblock.phi_done = True
         lblock.closed = True
         self.llvm_func = llvmbc.Function(self.llvmfuncdef(), lblock)
+        #create init block. The LLVM "module" is initialized there
         self.init_block = llvmbc.BasicBlock("init")
         self.init_block.instruction("store bool true, bool* %Initialized.0__")
-        real_entry = llvmbc.BasicBlock("real_entry")
+        self.llvm_func.basic_block(self.init_block)
+        #create the block that calls the "real" function
+        real_entry = llvmbc.TryBasicBlock("real_entry", "retblock", "exc")
         l_ret = self.gen.get_local_tmp(self.l_function.retvalue.type,
                                        self)
+        real_entry.last_op = True
         self.l_function.op_simple_call(
             l_ret, [self.function] + self.l_function.l_args, real_entry, self)
-        real_entry.ret(l_ret)
         self.llvm_func.basic_block(real_entry)
-        self.llvm_func.basic_block(self.init_block)
+        #create the block that catches remaining unwinds and sets
+        #pypy____uncaught_exception to 1
+        self.exceptblock = llvmbc.BasicBlock("exc")
+        ins = """store int 1, int* %%pypy__uncaught_exception
+\t%%dummy_ret = cast int 0 to %s
+\tret %s %%dummy_ret""" % tuple([self.l_function.retvalue.llvmtype()] * 2)
+        self.exceptblock.instruction(ins)
+        self.exceptblock.closed = True
+        self.llvm_func.basic_block(self.exceptblock)
+        #create the return block
+        retblock = llvmbc.BasicBlock("retblock")
+        retblock.ret(l_ret)
+        self.llvm_func.basic_block(retblock)
         
     def cfuncdef(self):
         a = self.l_function.translator.annotator
@@ -433,13 +461,23 @@
         name = self.name[1:]
         args = self.l_function.graph.startblock.inputargs
         self.pyrex_source = ["cdef extern %s\n" %
-                             (self.cfuncdef())]
-        self.pyrex_source += ["def wrap_%s(" % name]
+                             (self.cfuncdef()),
+                             "cdef extern int pypy__uncaught_exception\n"]
+        
+        self.pyrex_source.append("def wrap_%s(" % name)
         t = []
         for i, a in enumerate(args):
             t += ["%s" % a]
         t = ", ".join(t)
-        self.pyrex_source += t + "):\n\treturn %s(%s)\n\n" % (name, t)
+        s = """
+    result = %s(%s)
+    global pypy__uncaught_exception
+    if pypy__uncaught_exception != 0:
+        pypy__uncaught_exception = 0
+        raise RuntimeError('An uncaught exception occured in the LLVM code.')
+    else:
+        return result""" % (name, t)
+        self.pyrex_source.append(t + "):\n" + s)
         self.pyrex_source = "".join(self.pyrex_source)
         return self.pyrex_source
 

Modified: pypy/dist/pypy/translator/llvm/llvmbc.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/llvmbc.py	(original)
+++ pypy/dist/pypy/translator/llvm/llvmbc.py	Thu Apr  7 00:37:20 2005
@@ -16,14 +16,19 @@
         self.funcdef = funcdef
         self.startbb = startbb
         self.blocks = {}
+        self.blocklist = []
 
     def basic_block(self, block):
-        assert block.label != self.startbb.label, "Block has same label as startblock!"
+        assert block.label != self.startbb.label, \
+               "Block has same label as startblock!"
+        if block.label in self.blocks:
+            raise ValueError, "Can't add another block with the same name."
         self.blocks[block.label] = block
+        self.blocklist.append(block)
 
     def __str__(self):
         r = [self.funcdef, " {\n", str(self.startbb)]
-        r += [str(bb) for bb in self.blocks.values()] + ["}\n\n"]
+        r += [str(bb) for bb in self.blocklist] + ["}\n\n"]
         return "".join(r)
 
 class BasicBlock(object):
@@ -97,7 +102,7 @@
         if l_type is None:
             #XXX assuming that l_target.llvmtype() ends with an "*" here
             s = "%s = malloc %s" % (l_target.llvmname(),
-                                    l_target.llvmtype()[:1])
+                                    l_target.llvmtype()[:-1])
         else:
             s = "%s = malloc %s" % (l_target.llvmname(),
                                     l_type.typename_wo_pointer())

Modified: pypy/dist/pypy/translator/llvm/seqrepr.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/seqrepr.py	(original)
+++ pypy/dist/pypy/translator/llvm/seqrepr.py	Thu Apr  7 00:37:20 2005
@@ -92,7 +92,7 @@
     def t_op_newtuple(self, l_target, args, lblock, l_func):
         l_args = [self.gen.get_repr(arg) for arg in args]
         l_func.dependencies.update(l_args)
-        lblock.malloc(l_target, self)
+        lblock.malloc(l_target)
         l_ptrs = [self.gen.get_local_tmp(\
             PointerTypeRepr(l.typename(),self.gen), l_func)
                   for l in self.l_itemtypes]

Modified: pypy/dist/pypy/translator/llvm/test/llvmsnippet.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/test/llvmsnippet.py	(original)
+++ pypy/dist/pypy/translator/llvm/test/llvmsnippet.py	Thu Apr  7 00:37:20 2005
@@ -298,15 +298,16 @@
 
 #doesn't work yet!
 class MyException(Exception):
-    pass
+    def __init__(self, n):
+        self.n = n
 
 def raises(i):
     if i:
-        raise MyException
+        raise MyException, 10
     return 1
 
 def catches(i):
     try:
         return raises(i)
-    except MyException:
-        return 2
+    except MyException, e:
+        return e.n



More information about the Pypy-commit mailing list