[pypy-svn] r10264 - in pypy/dist/pypy/translator/llvm: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Sun Apr 3 02:42:29 CEST 2005
Author: cfbolz
Date: Sun Apr 3 02:42:28 2005
New Revision: 10264
Modified:
pypy/dist/pypy/translator/llvm/class.ll
pypy/dist/pypy/translator/llvm/llvmbc.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:
Changed genllvm to use remove_double_links, which makes it a bit
simpler.
Furthermore I added some machinery for exception support (which doesn't
work yet, though).
Modified: pypy/dist/pypy/translator/llvm/class.ll
==============================================================================
--- pypy/dist/pypy/translator/llvm/class.ll (original)
+++ pypy/dist/pypy/translator/llvm/class.ll Sun Apr 3 02:42:28 2005
@@ -3,13 +3,17 @@
%std.class = type {%std.class*, uint}
%std.object = type {%std.class*}
+%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}
implementation
;functions for type info at runtime
-bool %std.issubtype(%std.class* %a, %std.class* %b) {
+internal bool %std.issubtype(%std.class* %a, %std.class* %b) {
entry:
br label %not_null
not_null:
@@ -28,7 +32,7 @@
ret bool %result
}
-bool %std.isinstance(%std.object* %a, %std.class* %b) {
+internal bool %std.isinstance(%std.object* %a, %std.class* %b) {
entry:
%baseptr = getelementptr %std.object* %a, int 0, uint 0
%class = load %std.class** %baseptr
@@ -36,5 +40,9 @@
ret bool %result
}
-
+internal bool %std.is_(%std.class* %a, %std.class* %b) {
+entry:
+ %result = seteq %std.class* %a, %b
+ ret bool %result
+}
Modified: pypy/dist/pypy/translator/llvm/llvmbc.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/llvmbc.py (original)
+++ pypy/dist/pypy/translator/llvm/llvmbc.py Sun Apr 3 02:42:28 2005
@@ -73,9 +73,6 @@
self.instructions.append(s +
", ".join([a.typed_name() for a in l_args]) + ")")
- def invoke(self, l_target, l_func, l_args, errorblock):
- pass
-
def ret(self, l_value):
self.instructions.append("ret %s" % l_value.typed_name())
@@ -138,10 +135,54 @@
return "".join(s)
-class ExceptionBasicBlock(BasicBlock):
+class TryBasicBlock(BasicBlock):
def __init__(self, label, regularblock, exceptblock):
self.label = label
self.exceptblock = exceptblock
self.regularblock = regularblock
self.llvmblocks = []
self.instructions = []
+ self.finalized = False
+
+ def invoke(self, l_target, l_func, l_args):
+ 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.%i\n\t\texcept label %s" % \
+ (self.label, len(self.llvmblocks), self.exceptblock)
+ self.instructions.append(s)
+ self.llvmblocks.append(self.instructions)
+ self.instructions = []
+
+ def invoke_void(self, l_func, l_args):
+ s = "call %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)
+ self.instructions.append(s)
+ self.llvmblocks.append(self.instructions)
+ self.instructions = []
+
+ def __str__(self):
+ if not self.finalized:
+ self.uncond_branch(self.regularblock)
+ self.llvmblocks.append(self.instructions)
+ self.instructions = []
+ self.finalized = True
+ s = []
+ for i, instrs in enumerate(self.llvmblocks):
+ if i == 0:
+ label = self.label
+ else:
+ label = "%s.%i" % (self.label, i - 1)
+ s.append(label + ":\n")
+ for ins in instrs:
+ s.append("\t%s\n" % ins)
+ return "".join(s)
+
+
Modified: pypy/dist/pypy/translator/llvm/representation.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/representation.py (original)
+++ pypy/dist/pypy/translator/llvm/representation.py Sun Apr 3 02:42:28 2005
@@ -1,7 +1,7 @@
import autopath
import exceptions, sets, StringIO
-from types import FunctionType, MethodType
+from types import FunctionType, MethodType, ClassType
import new
from pypy.objspace.flow.model import Variable, Constant, SpaceOperation
@@ -10,9 +10,8 @@
from pypy.objspace.flow.model import traverse, uniqueitems, checkgraph
from pypy.annotation import model as annmodel
from pypy.annotation.classdef import ClassDef
-from pypy.translator import transform
from pypy.translator.llvm import llvmbc
-
+from pypy.translator.unsimplify import remove_double_links
INTRINSIC_OPS = ["lt", "le", "eq", "ne", "gt", "ge", "is", "is_true", "len",
"neg", "pos", "invert", "add", "sub", "mul", "truediv",
@@ -492,18 +491,26 @@
lblock.cast(l_tmp, l_val, l_type)
return l_tmp
+class ClassObjectRepr(TypeRepr):
+ def get(obj, gen):
+ pass
+ get = staticmethod(get)
+
class SimpleTypeRepr(TypeRepr):
def get(obj, gen):
if obj.__class__ is annmodel.SomeInteger:
l_repr = SimpleTypeRepr("int", gen)
- return l_repr
+ return l_repr
elif obj.__class__ is annmodel.SomeBool:
l_repr = SimpleTypeRepr("bool", gen)
- return l_repr
+ return l_repr
elif obj.__class__ is annmodel.SomeChar:
l_repr = SimpleTypeRepr("sbyte", gen)
- return l_repr
+ return l_repr
+ elif obj.__class__ is annmodel.SomePBC:
+ if obj.knowntype == object or obj.knowntype == ClassType:
+ return SimpleTypeRepr("%std.class", gen)
return None
get = staticmethod(get)
@@ -552,8 +559,8 @@
if obj.__class__ is Constant:
bind = gen.annotator.binding(obj)
if bind.__class__ is annmodel.SomePBC and \
- bind.const.__class__ == type:
- classdef = gen.annotator.bookkeeper.userclasses[bind.const]
+ gen.annotator.bookkeeper.userclasses.has_key(bind.const):
+ classdef = gen.annotator.bookkeeper.userclasses[bind.const]
elif isinstance(obj, annmodel.SomeInstance):
classdef = obj.classdef
elif isinstance(obj, ClassDef):
@@ -650,6 +657,7 @@
#XXXX: Ouch. I get bitten by the fact that
# in LLVM typedef != class object
# This will work, as long as class objects are only passed to functions
+ # (as opposed to used in LLVM instructions)
return "%%std.class* %s" % self.objectname
def op_simple_call(self, l_target, args, lblock, l_func):
@@ -731,6 +739,58 @@
for l_c in l_cls.iter_subclasses():
yield l_c
+class ExceptionTypeRepr(TypeRepr):
+ def get(obj, gen):
+ try:
+ if isinstance(obj, Constant):
+ if issubclass(obj.value, Exception):
+ return ExceptionTypeRepr(obj.value, gen)
+ return None
+ elif issubclass(obj, Exception):
+ return ExceptionTypeRepr(obj, gen)
+ except TypeError:
+ pass
+ return None
+ get = staticmethod(get)
+
+ def __init__(self, exception, gen):
+ if debug:
+ print "ExceptionTypeRepr: %s" % exception
+ self.gen = gen
+ self.exception = exception
+ self.name = "%std.exception"
+ self.objectname = gen.get_global_tmp("class.%s.object" %
+ self.exception.__name__)
+ s = "%s = internal global %%std.class {%%std.class* null, uint %i}"
+ self.definition = s % (self.objectname, abs(id(exception)))
+ self.dependencies = sets.Set()
+
+ def setup(self):
+ if len(self.exception.__bases__) != 0:
+ self.l_base = self.gen.get_repr(self.exception.__bases__[0])
+ self.dependencies.add(self.l_base)
+ else:
+ self.l_base = None
+
+ def llvmname(self):
+ return "%std.exception* "
+
+ def llvmtype(self):
+ return "%std.class* "
+
+ def typed_name(self):
+ return "%%std.class* %s" % self.objectname
+
+ def collect_init_code(self, lblock, l_func):
+ if self.l_base is None:
+ return
+ l_tmp = self.gen.get_local_tmp(None, l_func)
+ i = "%s = getelementptr %%std.class* %s, int 0, uint 0" % \
+ (l_tmp.llvmname(), self.objectname)
+ lblock.instruction(i)
+ lblock.instruction("store %%std.class* %s, %%std.class** %s" %
+ (self.l_base.objectname, l_tmp.llvmname()))
+
class BuiltinFunctionRepr(LLVMRepr):
def get(obj, gen):
if isinstance(obj, Constant) and \
@@ -796,6 +856,7 @@
self.allblocks = []
self.pyrex_source = ""
self.dependencies = sets.Set()
+ remove_double_links(self.translator, self.graph)
self.get_bbs()
self.se = False
@@ -822,10 +883,19 @@
self.same_origin_block = [False] * len(self.allblocks)
def build_bbs(self):
+ checkgraph(self.graph)
a = self.annotator
for number, pyblock in enumerate(self.allblocks):
- lblock = llvmbc.BasicBlock("block%i" % number)
pyblock = self.allblocks[number]
+ is_tryblock = isinstance(pyblock.exitswitch, Constant) and \
+ pyblock.exitswitch == last_exception
+ if is_tryblock:
+ regularblock = "block%i" % self.blocknum[self.exits[0].target]
+ exceptblock = "block%i" % self.blocknum[self.exits[1].target]
+ pyblock = llvmbc.TryBasicBlock("block%i" % number,
+ regularblock, exceptblock)
+ else:
+ lblock = llvmbc.BasicBlock("block%i" % number)
if number == 0:
self.llvm_func = llvmbc.Function(self.llvmfuncdef(), lblock)
else:
@@ -836,25 +906,18 @@
if isinstance(node, Link) and node.target == pyblock:
incoming_links.append(node)
traverse(visit, self.graph)
- #special case if the incoming links are from the same block
- if len(incoming_links) == 2 and \
- incoming_links[0].prevblock == incoming_links[1].prevblock:
- for i, arg in enumerate(pyblock.inputargs):
- l_select = self.gen.get_repr(
- incoming_links[0].prevblock.exitswitch)
- l_arg = self.gen.get_repr(arg)
- l_v1 = self.gen.get_repr(incoming_links[1].args[i])
- l_v2 = self.gen.get_repr(incoming_links[0].args[i])
- self.dependencies.update([l_arg, l_switch, l_v1, l_v2])
- lblock.select(l_arg, l_select, l_v1, l_v2)
- elif len(incoming_links) != 0:
+ if len(incoming_links) != 0:
for i, arg in enumerate(pyblock.inputargs):
l_arg = self.gen.get_repr(arg)
l_values = [self.gen.get_repr(l.args[i])
for l in incoming_links]
for j in range(len(l_values)):
if l_values[j].llvmtype() != l_arg.llvmtype():
- l_values[j] = l_values[j].alt_types[l_arg.llvmtype()]
+ try:
+ l_values[j] = \
+ l_values[j].alt_types[l_arg.llvmtype()]
+ except KeyError:
+ pass
self.dependencies.add(l_arg)
self.dependencies.update(l_values)
lblock.phi(l_arg, l_values,
@@ -886,7 +949,7 @@
# XXX: If a variable is passed to another block and has a different
# type there, we have to make the cast in this block since the phi
# instructions in the next block cannot be preceded by any other
- # instrcution
+ # instruction
for link in pyblock.exits:
for i, arg in enumerate(link.args):
localtype = self.annotator.binding(arg)
@@ -903,13 +966,17 @@
l_local.alt_types = {l_targettype.llvmname(): l_tmp}
#Create branches
if pyblock.exitswitch is None:
- if pyblock.exits == ():
+ if pyblock == self.graph.returnblock:
l_returnvalue = self.gen.get_repr(pyblock.inputargs[0])
self.dependencies.add(l_returnvalue)
lblock.ret(l_returnvalue)
else:
lblock.uncond_branch(
"%%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])
else:
assert isinstance(a.binding(pyblock.exitswitch),
annmodel.SomeBool)
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 Sun Apr 3 02:42:28 2005
@@ -266,3 +266,16 @@
def tuple_f3(i):
j, s1, s2, l = tuple_f2(i)
return j
+
+
+#exception snippets:
+def two_exceptions(n):
+ lst = range(10)
+ try:
+ lst[n]
+ except IndexError:
+ return 2
+ except KeyError:
+ return 3
+ 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 Sun Apr 3 02:42:28 2005
@@ -5,16 +5,15 @@
from pypy.translator.translator import Translator
from pypy.translator.llvm.genllvm import LLVMGenerator
+from pypy.translator.llvm.test import llvmsnippet
from pypy.translator.test import snippet as test
from pypy.objspace.flow.model import Constant, Variable
-from pypy.translator.llvm.test import llvmsnippet
-
def setup_module(mod):
mod.llvm_found = is_on_path("llvm-as")
def compile_function(function, annotate):
- t = Translator(function, simplifying=True)
+ t = Translator(function)
a = t.annotate(annotate)
a.simplify()
gen = LLVMGenerator(t)
More information about the pypy-svn
mailing list