[pypy-svn] r14067 - in pypy/dist/pypy/translator/llvm2: . test
rxe at codespeak.net
rxe at codespeak.net
Fri Jul 1 20:58:56 CEST 2005
Author: rxe
Date: Fri Jul 1 20:58:54 2005
New Revision: 14067
Added:
pypy/dist/pypy/translator/llvm2/arraynode.py
Modified:
pypy/dist/pypy/translator/llvm2/codewriter.py
pypy/dist/pypy/translator/llvm2/database.py
pypy/dist/pypy/translator/llvm2/funcnode.py
pypy/dist/pypy/translator/llvm2/genllvm.py
pypy/dist/pypy/translator/llvm2/pyxwrapper.py
pypy/dist/pypy/translator/llvm2/structnode.py
pypy/dist/pypy/translator/llvm2/test/test_genllvm.py
Log:
A WIP progress of variable length sturcts. Including globals and function
pointers.
Sorry for big checkin. :-(
Added: pypy/dist/pypy/translator/llvm2/arraynode.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm2/arraynode.py Fri Jul 1 20:58:54 2005
@@ -0,0 +1,25 @@
+import py
+from pypy.translator.llvm2.log import log
+log = log.structnode
+
+class ArrayNode(object):
+ _issetup = False
+ array_counter = 0
+
+ def __init__(self, db, array):
+ self.db = db
+ self.array = array
+ self.ref = "%%array.%s.%s" % (array.OF, ArrayNode.array_counter)
+ ArrayNode.array_counter += 1
+
+ def __str__(self):
+ return "<ArrayNode %r>" % self.ref
+
+ def setup(self):
+ self._issetup = True
+
+ # ______________________________________________________________________
+ # entry points from genllvm
+ #
+ def writedatatypedecl(self, codewriter):
+ codewriter.arraydef(self.ref, self.db.repr_arg_type(self.array.OF))
Modified: pypy/dist/pypy/translator/llvm2/codewriter.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/codewriter.py (original)
+++ pypy/dist/pypy/translator/llvm2/codewriter.py Fri Jul 1 20:58:54 2005
@@ -11,6 +11,9 @@
self._lines.append(line)
log(line)
+ def comment(self, line):
+ self.append(";; " + line)
+
def indent(self, line):
self.append(" " + line)
@@ -20,6 +23,9 @@
def structdef(self, name, typereprs):
self.append("%s = type { %s }" %(name, ", ".join(typereprs)))
+ def arraydef(self, name, typerepr):
+ self.append("%s = type { int, [0 x %s] }" % (name, typerepr))
+
def declare(self, decl):
self.append("declare %s" %(decl,))
@@ -64,12 +70,17 @@
self.indent("%(targetvar)s = cast %(fromtype)s "
"%(fromvar)s to %(targettype)s" % locals())
- def malloc(self, targetvar, type):
- self.indent("%(targetvar)s = malloc %(type)s" % locals())
-
- def getelementptr(self, targetvar, type, typevar, index):
- self.indent("%(targetvar)s = getelementptr "
- "%(type)s %(typevar)s, int 0, uint %(index)s" % locals())
+ def malloc(self, targetvar, type, sizetype=None, size=None):
+ if size is None:
+ assert sizetype is None
+ self.indent("%(targetvar)s = malloc %(type)s" % locals())
+ else:
+ self.indent("%(targetvar)s = malloc %(type)s, %(sizetype)s %(size)s" % locals())
+
+ def getelementptr(self, targetvar, type, typevar, *indices):
+ res = "%(targetvar)s = getelementptr %(type)s %(typevar)s, int 0, " % locals()
+ res += ", ".join(["%s %s" % (t, i) for t, i in indices])
+ self.indent(res)
def load(self, targetvar, targettype, ptr):
self.indent("%(targetvar)s = load %(targettype)s* %(ptr)s" % locals())
Modified: pypy/dist/pypy/translator/llvm2/database.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/database.py (original)
+++ pypy/dist/pypy/translator/llvm2/database.py Fri Jul 1 20:58:54 2005
@@ -1,12 +1,15 @@
from pypy.translator.llvm2.log import log
-from pypy.translator.llvm2.funcnode import FuncNode
-from pypy.translator.llvm2.structnode import StructNode
+from pypy.translator.llvm2.funcnode import FuncNode, FuncSig
+from pypy.translator.llvm2.structnode import StructNode, StructInstance
+from pypy.translator.llvm2.arraynode import ArrayNode
+ArrayNode
from pypy.rpython import lltype
from pypy.objspace.flow.model import Block, Constant, Variable
log = log.database
PRIMITIVES_TO_LLVM = {lltype.Signed: "int",
+ lltype.Char: "sbyte",
lltype.Unsigned: "uint",
lltype.Bool: "bool",
lltype.Float: "double" }
@@ -17,7 +20,7 @@
self.obj2node = {}
self._pendingsetup = []
self._tmpcount = 1
-
+
def addpending(self, key, node):
assert key not in self.obj2node, (
"node with key %r already known!" %(key,))
@@ -32,11 +35,25 @@
if const_or_var in self.obj2node:
return
if isinstance(const_or_var, Constant):
- if isinstance(const_or_var.concretetype, lltype.Primitive):
- pass
- #log.prepare(const_or_var, "(is primitive)")
+
+ ct = const_or_var.concretetype
+ while isinstance(ct, lltype.Ptr):
+ ct = ct.TO
+
+ if isinstance(ct, lltype.FuncType):
+ self.addpending(const_or_var, FuncNode(self, const_or_var))
else:
- self.addpending(const_or_var, FuncNode(self, const_or_var))
+ #value = const_or_var.value
+ #while hasattr(value, "_obj"):
+ # value = value._obj
+
+ if isinstance(ct, lltype.Struct):
+ self.addpending(const_or_var, StructInstance(self, value))
+
+ elif isinstance(ct, lltype.Primitive):
+ log.prepare(const_or_var, "(is primitive)")
+ else:
+ log.XXX("not sure what to do about %s(%s)" % (ct, const_or_var))
else:
log.prepare.ignore(const_or_var)
@@ -47,23 +64,80 @@
pass
elif isinstance(type_, lltype.Ptr):
self.prepare_repr_arg_type(type_.TO)
+
elif isinstance(type_, lltype.Struct):
self.addpending(type_, StructNode(self, type_))
+
+ elif isinstance(type_, lltype.FuncType):
+ self.addpending(type_, FuncSig(self, type_))
+
+ elif isinstance(type_, lltype.Array):
+ self.addpending(type_, ArrayNode(self, type_))
+
else:
log.XXX("need to prepare typerepr", type_)
def prepare_arg(self, const_or_var):
log.prepare(const_or_var)
- self.prepare_repr_arg(const_or_var)
self.prepare_repr_arg_type(const_or_var.concretetype)
-
+ self.prepare_repr_arg(const_or_var)
+
def setup_all(self):
while self._pendingsetup:
self._pendingsetup.pop().setup()
- def getobjects(self):
- return self.obj2node.values()
-
+ def getobjects(self, subset_types=None):
+ res = []
+ for v in self.obj2node.values():
+ if subset_types is None or isinstance(v, subset_types):
+ res.append(v)
+ res.reverse()
+ return res
+
+ def get_typedecls(self):
+ return self.getobjects((StructNode, ArrayNode))
+
+ def get_globaldata(self):
+ return self.getobjects((StructInstance))
+
+ def get_functions(self):
+ struct_nodes = [n for n in self.getobjects(StructNode) if n.inline_struct]
+ return struct_nodes + self.getobjects(FuncNode)
+
+ def dump(self):
+
+ # get and reverse the order in which seen objs
+ all_objs = self.obj2node.items()
+ all_objs.reverse()
+
+ log.dump_db("*** type declarations ***")
+ for k,v in all_objs:
+ if isinstance(v, (StructNode, ArrayNode)):
+ log.dump_db("%s ---> %s" % (k, v))
+
+ log.dump_db("*** global data ***")
+ for k,v in all_objs:
+ if isinstance(v, (StructInstance)):
+ log.dump_db("%s ---> %s" % (k, v))
+
+ log.dump_db("*** function protos ***")
+ for k,v in all_objs:
+ if isinstance(v, (FuncNode)):
+ log.dump_db("%s ---> %s" % (k, v))
+
+ log.dump_db("*** function implementations ***")
+ for k,v in all_objs:
+ if isinstance(v, (FuncNode)):
+ log.dump_db("%s ---> %s" % (k, v))
+
+ log.dump_db("*** unknown ***")
+ for k,v in all_objs:
+ if isinstance(v, (FuncSig)):
+ log.dump_db("%s ---> %s" % (k, v))
+
+ # __________________________________________________________
+ # Getters
+
def repr_arg(self, arg):
if (isinstance(arg, Constant) and
isinstance(arg.concretetype, lltype.Primitive)):
@@ -95,5 +169,3 @@
count = self._tmpcount
self._tmpcount += 1
return "%tmp." + str(count)
-
-
Modified: pypy/dist/pypy/translator/llvm2/funcnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/funcnode.py (original)
+++ pypy/dist/pypy/translator/llvm2/funcnode.py Fri Jul 1 20:58:54 2005
@@ -6,6 +6,24 @@
from pypy.translator.llvm2.log import log
log = log.funcnode
+class FuncSig(object):
+ """ XXX Not sure about this - should be combined with FuncNode?
+ Abstract function signature. """
+ def __init__(self, db, typ):
+ self.db = db
+ self.typ = typ
+ # Hack around some debug statements
+ self.ref = "pending setup!"
+
+ def __str__(self):
+ return "<FuncSig %r>" % self.ref
+
+ def setup(self):
+ returntype = self.db.repr_arg_type(self.typ.RESULT)
+ inputargtypes = self.db.repr_arg_type_multi(self.typ.ARGS)
+ self.ref = "%s (%s)" % (returntype, ", ".join(inputargtypes))
+
+
class FuncNode(object):
_issetup = False
@@ -14,7 +32,6 @@
self.ref = "%" + const_ptr_func.value._obj._name
self.graph = prepare_graph(const_ptr_func.value._obj.graph,
db._translator)
-
def __str__(self):
return "<FuncNode %r>" %(self.ref,)
@@ -30,19 +47,6 @@
self.db.prepare_arg(op.result)
traverse(visit, self.graph)
self._issetup = True
-
- def getdecl(self):
- assert self._issetup
- startblock = self.graph.startblock
- returnblock = self.graph.returnblock
- inputargs = self.db.repr_arg_multi(startblock.inputargs)
- inputargtypes = self.db.repr_arg_type_multi(startblock.inputargs)
- returntype = self.db.repr_arg_type(self.graph.returnblock.inputargs[0])
- result = "%s %s" % (returntype, self.ref)
- args = ["%s %s" % item for item in zip(inputargtypes, inputargs)]
- result += "(%s)" % ", ".join(args)
- return result
-
# ______________________________________________________________________
# main entry points from genllvm
def writedecl(self, codewriter):
@@ -72,6 +76,18 @@
# ______________________________________________________________________
# writing helpers for entry points
+ def getdecl(self):
+ assert self._issetup
+ startblock = self.graph.startblock
+ returnblock = self.graph.returnblock
+ inputargs = self.db.repr_arg_multi(startblock.inputargs)
+ inputargtypes = self.db.repr_arg_type_multi(startblock.inputargs)
+ returntype = self.db.repr_arg_type(self.graph.returnblock.inputargs[0])
+ result = "%s %s" % (returntype, self.ref)
+ args = ["%s %s" % item for item in zip(inputargtypes, inputargs)]
+ result += "(%s)" % ", ".join(args)
+ return result
+
def write_block(self, codewriter, block):
self.write_block_phi_nodes(codewriter, block)
self.write_block_operations(codewriter, block)
@@ -101,7 +117,6 @@
opwriter = OpWriter(self.db, codewriter)
for op in block.operations:
opwriter.write_operation(op)
-
def write_startblock(self, codewriter, block):
self.write_block_operations(codewriter, block)
self.write_block_branches(codewriter, block)
@@ -218,17 +233,36 @@
type = self.db.obj2node[arg.value].ref
self.codewriter.malloc(targetvar, type)
+ def malloc_varsize(self, op):
+ targetvar = self.db.repr_arg(op.result)
+ arg_type = op.args[0]
+ assert (isinstance(arg_type, Constant) and
+ isinstance(arg_type.value, lltype.Struct))
+ struct_type = self.db.obj2node[arg_type.value].ref
+ struct_cons = self.db.obj2node[arg_type.value].new_var_name
+ argrefs = self.db.repr_arg_multi(op.args[1:])
+ argtypes = self.db.repr_arg_type_multi(op.args[1:])
+ self.codewriter.call(targetvar, struct_type + " *",
+ struct_cons, argrefs, argtypes)
+
def getfield(self, op):
tmpvar = self.db.repr_tmpvar()
- type = self.db.repr_arg_type(op.args[0])
- typevar = self.db.repr_arg(op.args[0])
+ typ = self.db.repr_arg_type(op.args[0])
+ typevar = self.db.repr_arg(op.args[0])
fieldnames = list(op.args[0].concretetype.TO._names)
index = fieldnames.index(op.args[1].value)
- self.codewriter.getelementptr(tmpvar, type, typevar, index)
-
+ self.codewriter.getelementptr(tmpvar, typ, typevar, ("uint", index))
+
targetvar = self.db.repr_arg(op.result)
targettype = self.db.repr_arg_type(op.result)
- self.codewriter.load(targetvar, targettype, tmpvar)
+ #XXX This doesnt work - yet
+ #if isinstance(op.result.concretetype, lltype.Ptr):
+ # self.codewriter.cast(targetvar, targettype, tmpvar, targettype)
+ #else:
+ # Moving to correct result variable
+ #self.codewriter.load(targetvar, targettype, tmpvar)
+ self.codewriter.load(targetvar, targettype, tmpvar)
+ getsubstruct = getfield
def setfield(self, op):
tmpvar = self.db.repr_tmpvar()
@@ -236,8 +270,51 @@
typevar = self.db.repr_arg(op.args[0])
fieldnames = list(op.args[0].concretetype.TO._names)
index = fieldnames.index(op.args[1].value)
- self.codewriter.getelementptr(tmpvar, type, typevar, index)
+ self.codewriter.getelementptr(tmpvar, type, typevar, ("uint", index))
+
+ valuevar = self.db.repr_arg(op.args[2])
+ valuetype = self.db.repr_arg_type(op.args[2])
+ self.codewriter.store(valuetype, valuevar, tmpvar)
+
+ def getarrayitem(self, op):
+ var = self.db.repr_arg(op.args[0])
+ vartype = self.db.repr_arg_type(op.args[0])
+ index = self.db.repr_arg(op.args[1])
+ indextype = self.db.repr_arg_type(op.args[1])
+
+ tmpvar = self.db.repr_tmpvar()
+ self.codewriter.getelementptr(tmpvar, vartype, var,
+ ("uint", 1), (indextype, index))
+
+ targetvar = self.db.repr_arg(op.result)
+ targettype = self.db.repr_arg_type(op.result)
+
+ # Ditto see getfield
+ if not isinstance(op.result.concretetype, lltype.Ptr):
+ self.codewriter.load(targetvar, targettype, tmpvar)
+ else:
+ # XXX noop
+ self.codewriter.cast(targetvar, targettype, tmpvar, targettype)
+
+ def setarrayitem(self, op):
+ array = self.db.repr_arg(op.args[0])
+ arraytype = self.db.repr_arg_type(op.args[0])
+ index = self.db.repr_arg(op.args[1])
+ indextype = self.db.repr_arg_type(op.args[1])
+
+ tmpvar = self.db.repr_tmpvar()
+ self.codewriter.getelementptr(tmpvar, arraytype, array,
+ ("uint", 1), (indextype, index))
valuevar = self.db.repr_arg(op.args[2])
valuetype = self.db.repr_arg_type(op.args[2])
self.codewriter.store(valuetype, valuevar, tmpvar)
+
+ def getarraysize(self, op):
+ var = self.db.repr_arg(op.args[0])
+ vartype = self.db.repr_arg_type(op.args[0])
+ tmpvar = self.db.repr_tmpvar()
+ self.codewriter.getelementptr(tmpvar, vartype, var, ("uint", 0))
+ targetvar = self.db.repr_arg(op.result)
+ targettype = self.db.repr_arg_type(op.result)
+ self.codewriter.load(targetvar, targettype, tmpvar)
Modified: pypy/dist/pypy/translator/llvm2/genllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/genllvm.py (original)
+++ pypy/dist/pypy/translator/llvm2/genllvm.py Fri Jul 1 20:58:54 2005
@@ -20,14 +20,27 @@
db.setup_all()
entrynode = db.obj2node[c]
codewriter = CodeWriter()
- dbobjects = db.getobjects()
- log.debug(dbobjects)
- log.debug(db.obj2node)
- for node in dbobjects:
- node.writedecl(codewriter)
- codewriter.startimpl()
- for node in dbobjects:
- node.writeimpl(codewriter)
+ comment = codewriter.comment
+ nl = lambda: codewriter.append("")
+
+ nl(); comment("Type Declarations"); nl()
+ for typ_decl in db.get_typedecls():
+ typ_decl.writedatatypedecl(codewriter)
+
+ nl(); comment("Global Data") ; nl()
+ for typ_decl in db.get_globaldata():
+ typ_decl.writedata(codewriter)
+
+ nl(); comment("Function Prototypes") ; nl()
+ for typ_decl in db.get_functions():
+ typ_decl.writedecl(codewriter)
+
+ nl(); comment("Function Implementation")
+ codewriter.startimpl()
+ for typ_decl in db.get_functions():
+ typ_decl.writeimpl(codewriter)
+
+ comment("End of file") ; nl()
targetdir = udir
llvmsource = targetdir.join(func.func_name).new(ext='.ll')
Modified: pypy/dist/pypy/translator/llvm2/pyxwrapper.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/pyxwrapper.py (original)
+++ pypy/dist/pypy/translator/llvm2/pyxwrapper.py Fri Jul 1 20:58:54 2005
@@ -6,6 +6,7 @@
lltype.Unsigned: "unsigned int",
lltype.Bool: "char",
lltype.Float: "double",
+ lltype.Char: "char",
}
def write_pyx_wrapper(funcgen, targetpath):
Modified: pypy/dist/pypy/translator/llvm2/structnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/structnode.py (original)
+++ pypy/dist/pypy/translator/llvm2/structnode.py Fri Jul 1 20:58:54 2005
@@ -1,6 +1,7 @@
import py
from pypy.objspace.flow.model import Block, Constant, Variable, Link
from pypy.translator.llvm2.log import log
+from pypy.rpython import lltype
log = log.structnode
class StructNode(object):
@@ -8,22 +9,39 @@
struct_counter = 0
def __init__(self, db, struct):
+ assert isinstance(struct, lltype.Struct)
+
self.db = db
- self.struct = struct
- self.ref = "%%st.%s.%s" % (struct._name, StructNode.struct_counter)
+ self.struct = struct
+
+ self.name = "%s.%s" % (self.struct._name, StructNode.struct_counter)
+ self.ref = "%%st.%s" % self.name
+ self.inline_struct = self.struct._arrayfld
+
StructNode.struct_counter += 1
def __str__(self):
return "<StructNode %r>" %(self.ref,)
def setup(self):
- log.XXX("setup", self)
+ # Recurse
+ for fieldname in self.struct._names:
+ field_type = getattr(self.struct, fieldname)
+ self.db.prepare_repr_arg_type(field_type)
+
+ if self.inline_struct:
+ log.XXX("Register me", self)
+
self._issetup = True
+ def get_decl_for_varsize(self):
+ self.new_var_name = "%%new.st.%s" % self.name
+ return "%s * %s(int %%len)" % (self.ref, self.new_var_name)
+
# ______________________________________________________________________
- # entry points from genllvm
- #
- def writedecl(self, codewriter):
+ # main entry points from genllvm
+
+ def writedatatypedecl(self, codewriter):
assert self._issetup
struct = self.struct
l = []
@@ -32,5 +50,81 @@
l.append(self.db.repr_arg_type(type_))
codewriter.structdef(self.ref, l)
+ def writedecl(self, codewriter):
+ # declaration for constructor
+ if self.inline_struct:
+ # XXX Not well thought out - hack / better to modify the graph
+ codewriter.declare(self.get_decl_for_varsize())
+
def writeimpl(self, codewriter):
- assert self._issetup
+
+ if self.inline_struct:
+ log.writeimpl(self.ref)
+ codewriter.openfunc(self.get_decl_for_varsize())
+ codewriter.label("block0")
+
+ # XXX TODO
+ arraytype = "sbyte"
+ indices_to_array = [("uint", 1)]
+
+ # Into array and length
+ indices = indices_to_array + [("uint", 1), ("int", "%len")]
+ codewriter.getelementptr("%size", self.ref + "*",
+ "null", *indices)
+
+ #XXX is this ok for 64bit?
+ codewriter.cast("%sizeu", arraytype + "*", "%size", "uint")
+ codewriter.malloc("%resulttmp", "sbyte", "uint", "%sizeu")
+ codewriter.cast("%result", "sbyte*", "%resulttmp", self.ref + "*")
+
+ # remember the allocated length for later use.
+ indices = indices_to_array + [("uint", 0)]
+ codewriter.getelementptr("%size_ptr", self.ref + "*",
+ "%result", *indices)
+
+ codewriter.cast("%signedsize", "uint", "%sizeu", "int")
+ codewriter.store("int", "%signedsize", "%size_ptr")
+
+ codewriter.ret(self.ref + "*", "%result")
+ codewriter.closefunc()
+
+
+class StructInstance(object):
+ _issetup = False
+ struct_counter = 0
+
+ def __init__(self, db, value):
+ self.db = db
+ self.name = "%s.%s" % (value._TYPE._name, StructInstance.struct_counter)
+ self.ref = "%%stinstance.%s" % self.name
+ self.value = value
+ StructInstance.struct_counter += 1
+
+ def __str__(self):
+ return "<StructInstance %r>" %(self.ref,)
+
+ def setup(self):
+ # Recurse fields (XXX Messy!)
+ for name in self.value._TYPE._names:
+ T = self.value._TYPE._flds[name]
+ self.db.prepare_repr_arg_type(T)
+ if not isinstance(T, lltype.Primitive):
+ value = getattr(self.value, name)
+ self.db.prepare_repr_arg(value)
+
+ self._issetup = True
+
+# def struct_repr(self):
+# typ = repr_arg_type(self.value)
+# self.value._TYPE._names
+# typevaluepairs = ["%s %s" % for t, v in
+# typevaluepairsstr = ", ".join(typevaluepairs)
+# return "%s { %s }" % (typ, typevaluepairsstr)
+
+ def writedata(self, codewriter):
+ log.XXXXXXXXXX("ooops TODO should write - ", self.ref)
+ for name in self.value._TYPE._names:
+ log.XXXXXXXXXX("ooops ", getattr(self.value, name))
+ typ = self.db.repr_arg_type(self.value._TYPE)
+ # XXX constant you say?
+ codewriter.append("%s = internal constant %s* null" % (self.ref, typ))
Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original)
+++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Fri Jul 1 20:58:54 2005
@@ -168,7 +168,31 @@
l = (1,(1,2,i),i)
return l[1][2]
f = compile_function(nested_tuple, [int])
- assert f(4) == 4
+ assert f(4) == 4
+
+def test_pbc_fns():
+ def f2(x):
+ return x+1
+ def f3(x):
+ return x+2
+ def g(y):
+ if y < 0:
+ f = f2
+ else:
+ f = f3
+ return f(y+3)
+ f = compile_function(g, [int])
+ assert f(-1) == 3
+ assert f(0) == 5
+
+def DONOT_test_simple_chars():
+ def char_constant2(s):
+ s = s + s + s
+ return len(s + '.')
+ def char_constant():
+ return char_constant2("kk")
+ f = compile_function(char_constant, [])
+ assert f() == 7
def DONOTtest_string_getitem():
def string_test(i):
@@ -192,4 +216,3 @@
except TestException:
return 0
f = compile_function(catch, [int])
-
More information about the Pypy-commit
mailing list