[pypy-svn] r10291 - in pypy/dist/pypy/translator/llvm: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Mon Apr 4 17:26:06 CEST 2005
Author: cfbolz
Date: Mon Apr 4 17:26:06 2005
New Revision: 10291
Modified:
pypy/dist/pypy/translator/llvm/build_llvm_module.py
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/genllvm.py
pypy/dist/pypy/translator/llvm/list.c
pypy/dist/pypy/translator/llvm/list_template.ll
pypy/dist/pypy/translator/llvm/llvmbc.py
pypy/dist/pypy/translator/llvm/make_runtime.py
pypy/dist/pypy/translator/llvm/representation.py
pypy/dist/pypy/translator/llvm/test/llvmsnippet.py
pypy/dist/pypy/translator/llvm/test/test_genllvm.py
Log:
Added minimal exception support: All exceptions have to be caught, only
builtin exceptions, raising doesn't work yet, only list.getitem raises
IndexError.
Modified: pypy/dist/pypy/translator/llvm/build_llvm_module.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/build_llvm_module.py (original)
+++ pypy/dist/pypy/translator/llvm/build_llvm_module.py Mon Apr 4 17:26:06 2005
@@ -31,13 +31,13 @@
"opt %s -f %s.bc -o %s_optimized.bc" % (OPTIMIZATION_SWITCHES,
llvmfile.purebasename,
llvmfile.purebasename),
- "llc %s_optimized.bc -f -o %s.s" % (llvmfile.purebasename,
- llvmfile.purebasename),
+ "llc -enable-correct-eh-support %s_optimized.bc -f -o %s.s" % \
+ (llvmfile.purebasename, llvmfile.purebasename),
"as %s.s -o %s.o" % (llvmfile.purebasename, llvmfile.purebasename)]
if not optimize:
ops1 = ["llvm-as %s -f" % llvmfile,
- "llc %s.bc -f -o %s.s" % (llvmfile.purebasename,
- llvmfile.purebasename),
+ "llc -enable-correct-eh-support %s.bc -f -o %s.s" % \
+ (llvmfile.purebasename, llvmfile.purebasename),
"as %s.s -o %s.o" % (llvmfile.purebasename,
llvmfile.purebasename)]
ops2 = ["gcc -c -fPIC -I/usr/include/python2.3 %s.c" % pyxfile.purebasename,
Modified: pypy/dist/pypy/translator/llvm/class.ll
==============================================================================
--- pypy/dist/pypy/translator/llvm/class.ll (original)
+++ pypy/dist/pypy/translator/llvm/class.ll Mon Apr 4 17:26:06 2005
@@ -5,8 +5,8 @@
%std.list.sbyte = type {uint, sbyte*}
%std.exception = type {%std.class*, %std.list.sbyte*}
-%std.last_exception.type = internal global %std.class {%std.class* null, uint 0}
-%std.last_exception.value = internal global %std.exception {%std.class* null, %std.list.sbyte* null}
+%std.last_exception.type = internal global %std.class* null
+%std.last_exception.value = internal global %std.exception* null
implementation
@@ -46,3 +46,8 @@
ret bool %result
}
+
+internal sbyte %std.unwind() {
+entry:
+ unwind
+}
\ No newline at end of file
Modified: pypy/dist/pypy/translator/llvm/classrepr.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/classrepr.py (original)
+++ pypy/dist/pypy/translator/llvm/classrepr.py Mon Apr 4 17:26:06 2005
@@ -200,6 +200,14 @@
for l_c in l_cls.iter_subclasses():
yield l_c
+def create_builtin_exceptions(gen, dependencies):
+ import exceptions
+ for exc in dir(exceptions):
+ print exc, "#############"
+ if "__" not in exc:
+ l_exc = gen.get_repr(getattr(exceptions, exc))
+ dependencies.add(l_exc)
+
class ExceptionTypeRepr(TypeRepr):
def get(obj, gen):
try:
Modified: pypy/dist/pypy/translator/llvm/funcrepr.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/funcrepr.py (original)
+++ pypy/dist/pypy/translator/llvm/funcrepr.py Mon Apr 4 17:26:06 2005
@@ -133,27 +133,15 @@
exceptblock = "block%i.except" % self.blocknum[pyblock]
lblock = llvmbc.TryBasicBlock("block%i" % number,
regularblock, exceptblock)
- l_excblock = llvmbc.BasicBlock("block%i.except" % number)
- l_excp = self.gen.get_repr(last_exception)
- l_uip = self.gen.get_local_tmp(PointerTypeRepr("uint",
- self.gen), self)
- l_ui = self.gen.get_local_tmp(
- self.gen.get_repr(annmodel.SomeInteger(True, True)), self)
- self.dependencies.update([l_excp, l_uip, l_ui])
- l_excblock.load(l_cl, l_excp)
- l_excblock.getelementptr(l_uip, l_cl, [0, 1])
- l_excblock.load(l_ui, l_uip)
- l_excblock.switch(l_ui, "%%block%i.unwind" % number,
- [(str(abs(id(l_c))),
- XXXXXXXXXXXXX)
- for exc in pyblock.exits[1:]])
else:
lblock = llvmbc.BasicBlock("block%i" % number)
if number == 0:
self.llvm_func = llvmbc.Function(self.llvmfuncdef(), lblock)
else:
self.llvm_func.basic_block(lblock)
- #Create Phi nodes (but not for the first block)
+ if is_tryblock:
+ self.build_exc_blocks(number, pyblock)
+ #Create Phi nodes
incoming_links = []
def visit(node):
if isinstance(node, Link) and node.target == pyblock:
@@ -177,7 +165,9 @@
["%%block%i" % self.blocknum[l.prevblock]
for l in incoming_links])
#Handle SpaceOperations
- for op in pyblock.operations:
+ for opnumber, op in enumerate(pyblock.operations):
+ if opnumber == len(pyblock.operations) - 1 and is_tryblock:
+ lblock.last_op = True
l_target = self.gen.get_repr(op.result)
self.dependencies.add(l_target)
l_arg0 = self.gen.get_repr(op.args[0])
@@ -228,8 +218,8 @@
"%%block%i" % self.blocknum[pyblock.exits[0].target])
elif isinstance(pyblock.exitswitch, Constant) and \
pyblock.exitswitch.value == last_exception:
- lblock.uncond_branch(
- "%%block%i" % self.blocknum[pyblock.exits[0].target])
+ #The branch has already be created by the last space op
+ assert lblock.closed
else:
assert isinstance(a.binding(pyblock.exitswitch),
annmodel.SomeBool)
@@ -240,6 +230,30 @@
"%%block%i" % self.blocknum[pyblock.exits[1].target],
"%%block%i" % self.blocknum[pyblock.exits[0].target])
+ def build_exc_blocks(self, number, pyblock):
+ lexcblock = llvmbc.BasicBlock("block%i.except" % number)
+ self.llvm_func.basic_block(lexcblock)
+ l_excp = self.gen.get_repr(last_exception)
+ l_exc = self.gen.get_local_tmp(PointerTypeRepr("%std.class", self.gen),
+ self)
+ l_uip = self.gen.get_local_tmp(PointerTypeRepr("uint", self.gen), self)
+ l_ui = self.gen.get_local_tmp(
+ self.gen.get_repr(annmodel.SomeInteger(True, True)), self)
+ self.dependencies.update([l_excp, l_exc, l_uip, l_ui])
+ lexcblock.load(l_exc, l_excp)
+ lexcblock.getelementptr(l_uip, l_exc, [0, 1])
+ lexcblock.load(l_ui, l_uip)
+ exits = pyblock.exits[1:]
+ l_exitcases = [self.gen.get_repr(ex.exitcase) for ex in exits]
+ self.dependencies.update(l_exitcases)
+ sw = [(str(abs(id(ex.exitcase))),
+ "%%block%i" % self.blocknum[ex.target])
+ for ex in exits]
+ lexcblock.switch(l_ui, "%%block%i.unwind" % number, sw)
+ lunwindblock = llvmbc.BasicBlock("block%i.unwind" % number)
+ lunwindblock.unwind()
+ self.llvm_func.basic_block(lunwindblock)
+
def llvmfuncdef(self):
s = "internal %s %s(" % (self.retvalue.llvmtype(), self.name)
return s + ", ".join([a.typed_name() for a in self.l_args]) + ")"
@@ -265,10 +279,6 @@
lblock.call(l_target, l_args[0], l_args[1:])
class EntryFunctionRepr(LLVMRepr):
- def get(obj, gen):
- return None
- get = staticmethod(get)
-
def __init__(self, name, function, gen):
self.gen = gen
self.function = function
@@ -280,8 +290,11 @@
self.l_function = self.gen.get_repr(self.function)
self.dependencies.add(self.l_function)
lblock = llvmbc.BasicBlock("entry")
+ #XXX clean this up
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)
self.init_block = llvmbc.BasicBlock("init")
self.init_block.instruction("store bool true, bool* %Initialized.0__")
@@ -457,9 +470,6 @@
return self.retvalue.llvmtype()
class BoundMethodRepr(LLVMRepr):
- def get(obj, gen):
- return None
- get = staticmethod(get)
def __init__(self, l_func, l_self, l_class, gen):
self.gen = gen
self.l_func = l_func
Modified: pypy/dist/pypy/translator/llvm/genllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/genllvm.py (original)
+++ pypy/dist/pypy/translator/llvm/genllvm.py Mon Apr 4 17:26:06 2005
@@ -3,12 +3,9 @@
"""
import autopath
-import os, sys, exceptions, sets, StringIO
+import sets, StringIO
-from pypy.objspace.flow.model import Variable, Constant, SpaceOperation
-from pypy.objspace.flow.model import FunctionGraph, Block, Link
-from pypy.objspace.flow.model import last_exception, last_exc_value
-from pypy.objspace.flow.model import traverse, uniqueitems, checkgraph
+from pypy.objspace.flow.model import Constant
from pypy.annotation import model as annmodel
from pypy.translator import transform
from pypy.translator.translator import Translator
@@ -22,6 +19,7 @@
from pypy.translator.llvm import classrepr
from pypy.translator.llvm.representation import LLVMRepr, TmpVariableRepr
+from pypy.translator.llvm.representation import CompileError
from pypy.translator.llvm.funcrepr import EntryFunctionRepr
debug = True
@@ -51,12 +49,15 @@
for mod in [representation, funcrepr, typerepr, seqrepr, classrepr]:
self.repr_classes += [getattr(mod, s)
for s in dir(mod) if "Repr" in s]
+ self.repr_classes = [c for c in self.repr_classes if hasattr(c, "get")]
self.llvm_reprs = {}
self.depth = 0
self.entryname = self.translator.functions[0].__name__
self.l_entrypoint = EntryFunctionRepr("%__entry__" + self.entryname,
self.translator.functions[0],
self)
+ classrepr.create_builtin_exceptions(self,
+ self.l_entrypoint.dependencies)
self.local_counts[self.l_entrypoint] = 0
self.l_entrypoint.setup()
@@ -91,9 +92,10 @@
def get_repr(self, obj):
self.depth += 1
+ flag = False
if debug:
print " " * self.depth,
- print "looking for object", obj, type(obj).__name__, obj.__class__,
+ print "looking for object", obj, type(obj).__name__,
print id(obj), get_key(obj),
if isinstance(obj, LLVMRepr):
self.depth -= 1
@@ -104,6 +106,12 @@
print "->exists already:", self.llvm_reprs[get_key(obj)]
return self.llvm_reprs[get_key(obj)]
for cl in self.repr_classes:
+ #XXXXXX: Got
+ try:
+ obj.__class__
+ except AttributeError:
+ obj.__class__ = None
+ flag = True
g = cl.get(obj, self)
if g is not None:
self.llvm_reprs[get_key(obj)] = g
@@ -113,7 +121,11 @@
print "calling setup of %s, repr of %s" % (g, obj)
g.setup()
self.depth -= 1
+ if flag:
+ del obj.__class__
return g
+ if flag:
+ del obj.__class__
raise CompileError, "Can't get repr of %s, %s" % (obj, obj.__class__)
def write(self, f):
@@ -164,8 +176,3 @@
yield l_repr
-t = Translator(test2.two_exceptions)
-a = t.annotate([int])
-a.simplify()
-## t.view()
-f = llvmcompile(t)
Modified: pypy/dist/pypy/translator/llvm/list.c
==============================================================================
--- pypy/dist/pypy/translator/llvm/list.c (original)
+++ pypy/dist/pypy/translator/llvm/list.c Mon Apr 4 17:26:06 2005
@@ -1,9 +1,21 @@
#include <stdio.h>
+signed char unwind();
+
struct item {
char* dummy;
};
+struct class {
+ char dummy;
+};
+
+
+struct class* LAST_EXCEPTION_TYPE = 0;
+struct class INDEX_ERROR = {0};
+
+
+
struct list {
unsigned int length;
struct item** data;
@@ -21,6 +33,14 @@
return (int) l->length;
}
+int valid_index(int i, struct list* l) {
+ if (i < 0)
+ return 0;
+ if (i >= len(l))
+ return 0;
+ return 1;
+}
+
struct list* newlist() {
struct list* nlist = malloc(sizeof(struct list));
nlist->length = 0;
@@ -87,6 +107,16 @@
return l->data[index];
}
+struct item* getitem_EXCEPTION(struct list* l, int index) {
+ if (index < 0)
+ index = l->length + index;
+ if (valid_index(index, l) == 0) {
+ LAST_EXCEPTION_TYPE = &INDEX_ERROR;
+ return unwind();
+ }
+ return l->data[index];
+}
+
void setitem(struct list* l, int index, struct item* value) {
if (index < 0)
index = l->length + index;
Modified: pypy/dist/pypy/translator/llvm/list_template.ll
==============================================================================
--- pypy/dist/pypy/translator/llvm/list_template.ll (original)
+++ pypy/dist/pypy/translator/llvm/list_template.ll Mon Apr 4 17:26:06 2005
@@ -27,6 +27,23 @@
ret int %tmp.3
}
+internal int %std.valid_index(int %i, %std.list.%(name)s* %l) {
+entry:
+ %tmp.1 = setlt int %i, 0
+ br bool %tmp.1, label %UnifiedReturnBlock, label %endif.0
+
+endif.0:
+ %tmp.1.i = getelementptr %std.list.%(name)s* %l, int 0, uint 0
+ %tmp.2.i = load uint* %tmp.1.i
+ %tmp.3.i = cast uint %tmp.2.i to int
+ %not.tmp.6 = setgt int %tmp.3.i, %i
+ %retval = cast bool %not.tmp.6 to int
+ ret int %retval
+
+UnifiedReturnBlock:
+ ret int 0
+}
+
internal %std.list.%(name)s* %std.newlist() {
entry:
%tmp.0 = malloc %std.list.%(name)s
@@ -148,6 +165,39 @@
ret %(item)s %tmp.15
}
+internal %(item)s %std.getitem.exc(%std.list.%(name)s* %l, int %index.1) {
+entry:
+ %tmp.1 = setlt int %index.1, 0
+ br bool %tmp.1, label %then.0, label %endif.0.i
+
+then.0:
+ %tmp.4 = getelementptr %std.list.%(name)s* %l, int 0, uint 0
+ %tmp.5 = load uint* %tmp.4
+ %tmp.5 = cast uint %tmp.5 to int
+ %tmp.9 = add int %tmp.5, %index.1
+ %tmp.1.i5 = setlt int %tmp.9, 0
+ br bool %tmp.1.i5, label %then.1, label %endif.0.i
+
+endif.0.i:
+ %index_addr.0.0 = phi int [ %tmp.9, %then.0 ], [ %index.1, %entry ]
+ %tmp.1.i.i = getelementptr %std.list.%(name)s* %l, int 0, uint 0
+ %tmp.2.i.i = load uint* %tmp.1.i.i
+ %tmp.3.i.i = cast uint %tmp.2.i.i to int
+ %tmp.6.i = setgt int %tmp.3.i.i, %index_addr.0.0
+ br bool %tmp.6.i, label %endif.1, label %then.1
+
+then.1:
+ store %std.class* %glb.class.IndexError.object, %std.class** %std.last_exception.type
+ unwind
+endif.1:
+ %tmp.19 = getelementptr %std.list.%(name)s* %l, int 0, uint 1
+ %tmp.20 = load %(item)s** %tmp.19
+ %tmp.22 = getelementptr %(item)s* %tmp.20, int %index_addr.0.0
+ %tmp.23 = load %(item)s* %tmp.22
+ ret %(item)s %tmp.23
+}
+
+
internal void %std.setitem(%std.list.%(name)s* %l, int %index.1, %(item)s %value) {
entry:
%tmp.1 = setlt int %index.1, 0
Modified: pypy/dist/pypy/translator/llvm/llvmbc.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/llvmbc.py (original)
+++ pypy/dist/pypy/translator/llvm/llvmbc.py Mon Apr 4 17:26:06 2005
@@ -8,6 +8,8 @@
from pypy.objspace.flow.model import Variable, Constant, SpaceOperation
+class LLVMError(Exception):
+ pass
class Function(object):
def __init__(self, funcdef, startbb):
@@ -28,63 +30,42 @@
def __init__(self, label):
self.label = label
self.instructions = []
-
+ self.closed = False
+ #True after the first non-phi instruction has been added
+ self.phi_done = False
+
def instruction(self, instr): #should not be used
self.instructions.append(instr)
- def select(self, l_arg, l_select, l_v1, l_v2):
- s = "%s = select bool %s, %s, %s"
- s = s % (l_arg.llvmname(), l_select.llvmname(), l_v1.typed_name(),
- l_v2.typed_name())
- self.instructions.append(s)
-
- def phi(self, l_arg, l_values, blocks):
- assert len(l_values) == len(blocks)
- vars_string = []
- print "inserting phi node", l_arg, l_values, blocks
- print l_arg.llvmname(), l_arg.llvmtype()
- fd = "" + "%s = phi %s " % (l_arg.llvmname(), l_arg.llvmtype())
- fd += ", ".join(["[%s, %s]" % (v.llvmname(), b)
- for v, b in zip(l_values, blocks)])
- self.instructions.append(fd)
-
- def spaceop(self, l_target, opname, l_args):
- if l_target.llvmtype() == "void":
- s = "call void %%std.%s(" % opname
- else:
- s = "%s = call %s %%std.%s(" % (l_target.llvmname(),
- l_target.llvmtype(), opname)
- self.instructions.append(s +
- ", ".join([a.typed_name() for a in l_args]) + ")")
-
- def call(self, l_target, l_func, l_args):
- if l_target.llvmtype() == "void":
- s = "call void %s(" % l_func.llvmname()
- elif l_target.llvmtype() == "%std.void":
- s = "call %std.void %s(" % l_func.llvmname()
- else:
- s = "%s = call %s %s(" % (l_target.llvmname(), l_target.llvmtype(),
- l_func.llvmname())
- self.instructions.append(s +
- ", ".join([a.typed_name() for a in l_args]) + ")")
-
- def call_void(self, l_func, l_args):
- s = "call %s %s(" % (l_func.rettype(), l_func.llvmname())
- self.instructions.append(s +
- ", ".join([a.typed_name() for a in l_args]) + ")")
-
+ #Terminator instuctions
def ret(self, l_value):
+ self.phi_done = True
+ if self.closed:
+ raise LLVMError, "Can't add second terminator instruction."
+ self.closed = True
self.instructions.append("ret %s" % l_value.typed_name())
def uncond_branch(self, block):
+ if self.closed:
+ raise LLVMError, "Can't add second terminator instruction."
+ self.closed = True
+ self.phi_done = True
self.instructions.append("br label " + block)
def cond_branch(self, l_switch, blocktrue, blockfalse):
+ if self.closed:
+ raise LLVMError, "Can't add second terminator instruction."
+ self.closed = True
+ self.phi_done = True
s = "br %s, label %s, label %s" % (l_switch.typed_name(),
blocktrue, blockfalse)
self.instructions.append(s)
def switch(self, l_switch, default, rest=None):
+ if self.closed:
+ raise LLVMError, "Can't add second terminator instruction."
+ self.closed = True
+ self.phi_done = True
s = "switch %s, label %s " % (l_switch.typed_name(), default)
if rest is not None:
s += "[" + "\n\t".join(["%s %s, label %s" % (l_switch.llvmtype(),
@@ -92,7 +73,27 @@
for c, l in rest]) + "]"
self.instructions.append(s)
+ def unwind(self):
+ if self.closed:
+ raise LLVMError, "Can't add second terminator instruction."
+ self.closed = True
+ self.phi_done = True
+ self.instructions.append("unwind")
+
+ #Memory access instructions
+ def load(self, l_target, l_pter):
+ self.phi_done = True
+ s = "%s = load %s %s" % (l_target.llvmname(), l_pter.llvmtype(),
+ l_pter.llvmname())
+ self.instructions.append(s)
+
+ def store(self, l_value, l_pter):
+ self.phi_done = True
+ s = "store %s, %s" % (l_value.typed_name(), l_pter.typed_name())
+ self.instructions.append(s)
+
def malloc(self, l_target, l_type, num=1):
+ self.phi_done = True
s = "%s = malloc %s" % (l_target.llvmname(),
l_type.llvmname_wo_pointer())
if num > 1:
@@ -100,6 +101,7 @@
self.instructions.append(s)
def getelementptr(self, l_target, l_ptr, adresses):
+ self.phi_done = True
s = "%s = getelementptr %s %s, " % (l_target.llvmname(),
l_ptr.llvmtype(), l_ptr.llvmname())
adr = []
@@ -114,31 +116,138 @@
adr.append("int %i" % a)
self.instructions.append(s + ", ".join(adr))
- def load(self, l_target, l_pter):
- s = "%s = load %s %s" % (l_target.llvmname(), l_pter.llvmtype(),
- l_pter.llvmname())
- self.instructions.append(s)
+ #Function calls
+ def spaceop(self, l_target, opname, l_args):
+ self.phi_done = True
+ if l_target.llvmtype() == "void":
+ s = "call void %%std.%s(" % opname
+ else:
+ s = "%s = call %s %%std.%s(" % (l_target.llvmname(),
+ l_target.llvmtype(), opname)
+ self.instructions.append(s +
+ ", ".join([a.typed_name() for a in l_args]) + ")")
+
+ def call(self, l_target, l_func, l_args):
+ self.phi_done = True
+ if l_target.llvmtype() == "void":
+ s = "call void %s(" % l_func.llvmname()
+ elif l_target.llvmtype() == "%std.void":
+ s = "call %std.void %s(" % l_func.llvmname()
+ else:
+ s = "%s = call %s %s(" % (l_target.llvmname(), l_target.llvmtype(),
+ l_func.llvmname())
+ self.instructions.append(s +
+ ", ".join([a.typed_name() for a in l_args]) + ")")
- def store(self, l_value, l_pter):
- s = "store %s, %s" % (l_value.typed_name(), l_pter.typed_name())
- self.instructions.append(s)
+ def call_void(self, l_func, l_args):
+ self.phi_done = True
+ s = "call %s %s(" % (l_func.rettype(), l_func.llvmname())
+ self.instructions.append(s +
+ ", ".join([a.typed_name() for a in l_args]) + ")")
+
+ #Other instructions
+ def select(self, l_arg, l_select, l_v1, l_v2):
+ self.phi_done = True
+ s = "%s = select bool %s, %s, %s"
+ s = s % (l_arg.llvmname(), l_select.llvmname(), l_v1.typed_name(),
+ l_v2.typed_name())
+ self.instructions.append(s)
+
+ def phi(self, l_arg, l_values, blocks):
+ assert len(l_values) == len(blocks)
+ if self.phi_done:
+ raise LLVMError, "Can't create phi node."
+ vars_string = []
+ print "inserting phi node", l_arg, l_values, blocks
+ print l_arg.llvmname(), l_arg.llvmtype()
+ fd = "" + "%s = phi %s " % (l_arg.llvmname(), l_arg.llvmtype())
+ fd += ", ".join(["[%s, %s]" % (v.llvmname(), b)
+ for v, b in zip(l_values, blocks)])
+ self.instructions.append(fd)
def cast(self, l_target, l_value):
+ self.phi_done = True
s = "%s = cast %s to %s" % (l_target.llvmname(), l_value.typed_name(),
l_target.llvmtype())
self.instructions.append(s)
- def unwind(self):
- self.instructions.append("unwind")
-
+ #Non-instructions methods
def __str__(self):
s = [self.label + ":\n"]
for ins in self.instructions:
s += ["\t%s\n" % ins]
+ if not self.closed:
+ print "".join(s)
+ raise LLVMError, "Block lacks a terminator instruction."
return "".join(s)
-
class TryBasicBlock(BasicBlock):
+ """A basic block for which the last operation is turned into an invoke.
+Used for exception handling."""
+ def __init__(self, label, regularblock, exceptblock):
+ BasicBlock.__init__(self, label)
+ self.exceptblock = exceptblock
+ self.regularblock = regularblock
+ self.pending_call = None
+ self.pending_args = None
+ #This is set to True before the last operation
+ #XXX Find a more elegant solution for this
+ self.last_op = False
+
+ def spaceop(self, l_target, opname, l_args):
+ if not self.last_op:
+ return BasicBlock.spaceop(self, l_target, opname, l_args)
+ self.phi_done = True
+ if self.closed:
+ raise LLVMError, "Can't add second terminator instruction."
+ self.closed = True
+ if l_target.llvmtype() == "void":
+ s = "invoke void %%std.%s.exc(" % opname
+ else:
+ s = "%s = invoke %s %%std.%s.exc(" % (l_target.llvmname(),
+ l_target.llvmtype(), opname)
+ s += ", ".join([a.typed_name() for a in l_args]) + ")"
+ s += "\n\t\tto label %%%s\n\t\texcept label %%%s" % \
+ (self.regularblock, self.exceptblock)
+ self.instructions.append(s)
+
+ def call(self, l_target, l_func, l_args):
+ if not self.last_op:
+ return BasicBlock.call(self, l_target, l_func, l_args)
+ self.phi_done = True
+ if self.closed:
+ raise LLVMError, "Can't add second terminator instruction."
+ self.closed = True
+ if l_target.llvmtype() == "void":
+ s = "invoke void %s(" % l_func.llvmname()
+ elif l_target.llvmtype() == "%std.void":
+ s = "invoke %std.void %s(" % l_func.llvmname()
+ else:
+ s = "%s = invoke %s %s(" % (l_target.llvmname(),
+ l_target.llvmtype(), l_func.llvmname())
+ s += ", ".join([a.typed_name() for a in l_args]) + ")"
+ s += "\n\t\tto label %%%s\n\t\texcept label %%%s" % \
+ (self.regularblock, self.exceptblock)
+ self.instructions.append(s)
+
+ def call_void(self, l_func, l_args):
+ if not self.last_op:
+ return BasicBlock.call_void(self, l_func, l_args)
+ self.phi_done = True
+ if self.closed:
+ raise LLVMError, "Can't add second terminator instruction."
+ self.closed = True
+ s = "invoke %s %s(" % (l_func.rettype(), l_func.llvmname())
+ s += ", ".join([a.typed_name() for a in l_args]) + ")"
+ s += "\n\t\tto label %%%s\n\t\texcept label %%%s" % \
+ (self.regularblock, self.exceptblock)
+ self.instructions.append(s)
+
+class TraceBasicBlock(BasicBlock):
+ """A basic block that will make it possible to create a sort of
+'tracebacks' at some point in the future: Every call is turned into an invoke.
+Then the corresponding exceptblock will have to append a string to a global
+traceback object."""
def __init__(self, label, regularblock, exceptblock):
self.label = label
self.exceptblock = exceptblock
@@ -178,7 +287,7 @@
call = invoke
def invoke_void(self, l_func, l_args):
- s = "call %s %s(" % (l_func.rettype(), l_func.llvmname())
+ s = "invoke %s %s(" % (l_func.rettype(), l_func.llvmname())
s += ", ".join([a.typed_name() for a in l_args]) + ")"
s += "\n\t\tto label %%%s.%i\n\t\texcept label %%%s" % \
(self.label, len(self.llvmblocks), self.exceptblock)
@@ -190,8 +299,9 @@
def __str__(self):
if not self.finalized:
- self.llvmblocks.append(self.instructions)
- self.instructions = []
+ if len(self.instructions) != 0:
+ self.llvmblocks.append(self.instructions)
+ self.instructions = []
self.finalized = True
s = []
for i, instrs in enumerate(self.llvmblocks):
Modified: pypy/dist/pypy/translator/llvm/make_runtime.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/make_runtime.py (original)
+++ pypy/dist/pypy/translator/llvm/make_runtime.py Mon Apr 4 17:26:06 2005
@@ -12,8 +12,8 @@
print cfile
bytecode = udir.join("temp.bc")
lastdir = path.local()
- ops = ["llvm-gcc -O3 -c %s -o %s" % (cfile, bytecode),
- "llvm-dis %s -f" % bytecode]
+ ops = ["llvm-gcc -enable-correct-eh-support-O3 -c %s -o %s" % \
+ (cfile, bytecode), "llvm-dis %s -f" % bytecode]
for op in ops:
print op
cmdexec(op)
@@ -48,7 +48,9 @@
if f in line:
line = line.replace(f, "std." + f)
ret.append(line)
- continue
+ break
+ else:
+ ret.append(line)
else:
ret.append(line)
return "\n".join(ret)
@@ -58,6 +60,15 @@
code = code.replace("_ALTERNATIVE%i" % i, "")
return code
+def create_exceptions(code):
+ code = code.replace("%LAST_EXCEPTION_TYPE", "%std.last_exception.type")
+ code = code.replace("%INDEX_ERROR", "%glb.class.IndexError.object")
+ return code
+
+def remove_exception(code):
+ code = code.replace("_EXCEPTION", ".exc")
+ return code
+
def remove_header(code):
code = code.split("implementation")
return code[1]
@@ -71,12 +82,37 @@
ret.append(line)
return "\n".join(ret)
+def create_unwind(code):
+ ret = []
+ remove = False
+ for line in code.split("\n"):
+ if "call" in line and "%unwind(" in line:
+ ret.append("\tunwind")
+ remove = True
+ elif "declare" in line and "unwind" in line:
+ pass
+ elif remove:
+ if not line.startswith("\t") and ":" in line:
+ remove = False
+ ret.append(line)
+ else:
+ ret.append(line)
+ return "\n".join(ret)
+
+def remove_structs(code):
+ code = code.replace("struct.class", "std.class")
+ return code
+
def cleanup_code(code):
code = remove_comments(code)
code = add_std(code)
code = remove_header(code)
code = internal_functions(code)
code = remove_alternatives(code)
+ code = create_exceptions(code)
+ code = remove_exception(code)
+ code = remove_structs(code)
+ code = create_unwind(code)
return code
def make_list_template():
Modified: pypy/dist/pypy/translator/llvm/representation.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/representation.py (original)
+++ pypy/dist/pypy/translator/llvm/representation.py Mon Apr 4 17:26:06 2005
@@ -2,6 +2,7 @@
import sets
from pypy.objspace.flow.model import Variable, Constant
+from pypy.objspace.flow.model import last_exception, last_exc_value
from pypy.annotation import model as annmodel
LLVM_SIMPLE_TYPES = {annmodel.SomeChar: "sbyte",
@@ -51,24 +52,27 @@
class SimpleRepr(LLVMRepr):
- """Representation of values that are directly mapped to types in LLVM:
-bool, char (string of length 1)"""
+ """Representation of values that only need simple representation:
+bool, char (string of length 1), last_exception, last_exc_value"""
def get(obj, gen):
- if not isinstance(obj, Constant):
- return None
- type = gen.annotator.binding(obj)
- if type.__class__ in LLVM_SIMPLE_TYPES:
- llvmtype = LLVM_SIMPLE_TYPES[type.__class__]
- l_repr = SimpleRepr(llvmtype, repr(obj.value), gen)
- return l_repr
+ if isinstance(obj, Constant):
+ type_ = gen.annotator.binding(obj)
+ if type_.__class__ in LLVM_SIMPLE_TYPES:
+ llvmtype = LLVM_SIMPLE_TYPES[type_.__class__]
+ return SimpleRepr(llvmtype, repr(obj.value), gen)
+ if obj == last_exception:
+ return SimpleRepr("%std.class**", "%std.last_exception.type", gen)
+ if obj == last_exc_value:
+ return SimpleRepr("%std.exception**", "%std.last_exception.value",
+ gen)
return None
get = staticmethod(get)
- def __init__(self, type, llvmname, gen):
+ def __init__(self, type_, llvmname, gen):
if debug:
print "SimpleRepr: %s, %s" % (type, llvmname)
- self.type = type
+ self.type = type_
if llvmname in ("False", "True"):
llvmname = llvmname.lower()
self.name = llvmname
@@ -84,13 +88,13 @@
class IntRepr(LLVMRepr):
def get(obj, gen):
if obj.__class__ is int:
- type = gen.annotator.binding(Constant(obj))
- return IntRepr(type, obj, gen)
+ type_ = gen.annotator.binding(Constant(obj))
+ return IntRepr(type_, obj, gen)
if not isinstance(obj, Constant):
return None
- type = gen.annotator.binding(obj)
- if type.__class__ == annmodel.SomeInteger:
- return IntRepr(type, obj.value, gen)
+ type_ = gen.annotator.binding(obj)
+ if type_.__class__ == annmodel.SomeInteger:
+ return IntRepr(type_, obj.value, gen)
get = staticmethod(get)
def __init__(self, annotation, value, gen):
@@ -129,8 +133,8 @@
if debug:
print "VariableRepr: %s" % (var.name)
self.var = var
- type = gen.annotator.binding(var)
- self.type = gen.get_repr(type)
+ type_ = gen.annotator.binding(var)
+ self.type = gen.get_repr(type_)
self.dependencies = sets.Set([self.type])
def llvmname(self):
@@ -146,11 +150,11 @@
% repr(name))
class TmpVariableRepr(LLVMRepr):
- def __init__(self, name, type, gen):
+ def __init__(self, name, type_, gen):
if debug:
- print "TmpVariableRepr: %s %s" % (type, name)
+ print "TmpVariableRepr: %s %s" % (type_, name)
self.name = name
- self.type = type
+ self.type = type_
self.dependencies = sets.Set()
def llvmname(self):
@@ -178,8 +182,8 @@
class StringRepr(LLVMRepr):
def get(obj, gen):
if isinstance(obj, Constant):
- type = gen.annotator.binding(obj)
- if isinstance(type, annmodel.SomeString):
+ type_ = gen.annotator.binding(obj)
+ if isinstance(type_, annmodel.SomeString):
return StringRepr(obj.value, gen)
elif isinstance(obj, str):
return StringRepr(obj, gen)
@@ -217,8 +221,8 @@
class TupleRepr(LLVMRepr):
def get(obj, gen):
if isinstance(obj, Constant):
- type = gen.annotator.binding(obj)
- if isinstance(type, annmodel.SomeTuple):
+ type_ = gen.annotator.binding(obj)
+ if isinstance(type_, annmodel.SomeTuple):
return TupleRepr(obj, gen)
return None
get = staticmethod(get)
@@ -253,4 +257,3 @@
raise AttributeError, ("TupleRepr instance has no attribute %s"
% repr(name))
-
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 Mon Apr 4 17:26:06 2005
@@ -272,7 +272,6 @@
def two_exceptions(n):
lst = range(10)
try:
- lst[n] += 1
lst[n]
except IndexError:
return 2
@@ -280,3 +279,11 @@
return 3
return 4
+def catch_base_exception(n):
+ lst = range(10)
+ try:
+ lst[n]
+ except LookupError:
+ return 2
+ return 4
+
Modified: pypy/dist/pypy/translator/llvm/test/test_genllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/test/test_genllvm.py (original)
+++ pypy/dist/pypy/translator/llvm/test/test_genllvm.py Mon Apr 4 17:26:06 2005
@@ -17,7 +17,7 @@
a = t.annotate(annotate)
a.simplify()
gen = LLVMGenerator(t)
- return gen.compile()
+ return gen.compile(True)
def is_on_path(name):
try:
@@ -27,6 +27,7 @@
else:
return True
+
class TestLLVMRepr(object):
def setup_method(self,method):
if not llvm_found:
@@ -249,6 +250,21 @@
assert f(15) == 15
assert f(30) == 30
+class TestException(object):
+ def test_two_exception(self):
+ f = compile_function(llvmsnippet.two_exceptions, [int])
+ for i in range(10):
+ assert f(i) == 4
+ for i in range(10, 20):
+ assert f(i) == 2
+
+ def test_catch_base_exception(self):
+ f = compile_function(llvmsnippet.catch_base_exception, [int])
+ for i in range(10):
+ assert f(i) == 4
+ for i in range(10, 20):
+ assert f(i) == 2
+
class TestSnippet(object):
def setup_method(self, method):
@@ -328,7 +344,7 @@
with_init = compile_function(test.with_init, [int])
assert with_init(42) == 42
- def DONOTtest_with_more_init(self):
+ def DONOT_test_with_more_init(self):
with_more_init = compile_function(test.with_more_init, [int, bool])
assert with_more_init(42, True) == 42
assert with_more_init(42, False) == -42
More information about the Pypy-commit
mailing list