[pypy-svn] r13583 - in pypy/dist/pypy/translator/llvm2: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Sat Jun 18 18:28:30 CEST 2005
Author: cfbolz
Date: Sat Jun 18 18:28:29 2005
New Revision: 13583
Added:
pypy/dist/pypy/translator/llvm2/cfgtransform.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/pyxwrapper.py
pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py
pypy/dist/pypy/translator/llvm2/test/test_genllvm.py
Log:
(cfbolz,hpk)
- added flow graph transform remove_same_as, because same_as is
incompatible with SSA in LLVM.
- refactored and extended functions (branches work)
Added: pypy/dist/pypy/translator/llvm2/cfgtransform.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm2/cfgtransform.py Sat Jun 18 18:28:29 2005
@@ -0,0 +1,34 @@
+from pypy.objspace.flow.model import traverse, Block, checkgraph
+
+def remove_same_as(graph):
+ same_as_positions = []
+ def visit(node):
+ if isinstance(node, Block):
+ for i, op in enumerate(node.operations):
+ if op.opname == 'same_as':
+ same_as_positions.append((node, i))
+ traverse(visit, graph)
+ while same_as_positions:
+ block, index = same_as_positions.pop()
+ same_as_result = block.operations[index].result
+ same_as_arg = block.operations[index].args[0]
+ # replace the new variable (same_as_result) with the old variable
+ # (from all subsequent positions)
+ for op in block.operations[index:]:
+ for i in range(len(op.args)):
+ if op.args[i] == same_as_result:
+ op.args[i] = same_as_arg
+ for link in block.exits:
+ for i in range(len(link.args)):
+ if link.args[i] == same_as_result:
+ link.args[i] = same_as_arg
+ if block.exitswitch == same_as_result:
+ block.exitswitch = same_as_arg
+ block.operations[index] = None
+
+ # remove all same_as operations
+ def visit(node):
+ if isinstance(node, Block) and node.operations:
+ node.operations[:] = filter(None, node.operations)
+ traverse(visit, graph)
+ checkgraph(graph)
Modified: pypy/dist/pypy/translator/llvm2/codewriter.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/codewriter.py (original)
+++ pypy/dist/pypy/translator/llvm2/codewriter.py Sat Jun 18 18:28:29 2005
@@ -23,6 +23,10 @@
def br_uncond(self, blockname):
self.indent("br label %%%s" %(blockname,))
+ def br(self, switch, blockname_false, blockname_true):
+ self.indent("br bool %s, label %%%s, label %%%s"
+ % (switch, blockname_true, blockname_false))
+
def openfunc(self, decl):
self.append("%s {" % (decl,))
@@ -34,6 +38,7 @@
def phi(self, targetvar, type_, refs, blocknames):
assert targetvar.startswith('%')
+ assert refs and len(refs) == len(blocknames), "phi node requires blocks"
mergelist = ", ".join(
["[%s, %%%s]" % item
for item in zip(refs, blocknames)])
Modified: pypy/dist/pypy/translator/llvm2/database.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/database.py (original)
+++ pypy/dist/pypy/translator/llvm2/database.py Sat Jun 18 18:28:29 2005
@@ -2,10 +2,13 @@
from pypy.translator.llvm2.funcnode import FuncNode
from pypy.rpython import lltype
from pypy.objspace.flow.model import Block, Constant, Variable
+from pypy.translator.unsimplify import remove_double_links
+from pypy.translator.llvm2.cfgtransform import remove_same_as
log = log.database
-PRIMITIVES_TO_LLVM = {lltype.Signed: "int"}
+PRIMITIVES_TO_LLVM = {lltype.Signed: "int",
+ lltype.Bool: "bool"}
class Database(object):
def __init__(self, translator):
@@ -13,9 +16,12 @@
self.obj2node = {}
self._pendingsetup = []
- def getgraph(self, func):
- return self._translator.flowgraphs[func]
-
+ def getgraph(self, func):
+ graph = self._translator.flowgraphs[func]
+ remove_same_as(graph)
+ remove_double_links(self._translator, graph)
+ return graph
+
def getnode(self, obj):
assert hasattr(obj, 'func_code')
try:
@@ -25,7 +31,7 @@
self.obj2node[obj] = node
log("add pending setup", node.ref)
self._pendingsetup.append(node)
- return node
+ return node
def process(self):
if self._pendingsetup:
Modified: pypy/dist/pypy/translator/llvm2/funcnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/funcnode.py (original)
+++ pypy/dist/pypy/translator/llvm2/funcnode.py Sat Jun 18 18:28:29 2005
@@ -23,7 +23,7 @@
inputargtypes = self.db.multi_gettyperef(startblock.inputargs)
returntype = self.db.gettyperef(self.graph.returnblock.inputargs[0])
result = "%s %%%s" % (returntype, self.ref)
- args = ["%s %s" % item for item in zip(inputargs, inputargtypes)]
+ args = ["%s %s" % item for item in zip(inputargtypes, inputargs)]
result += "(%s)" % ", ".join(args)
return result
@@ -42,24 +42,60 @@
for i, block in enumerate(l):
self.block_to_name[block] = "block%s" % i
for block in l:
- self.write_block(codewriter, block)
- codewriter.closefunc()
+ codewriter.label(self.block_to_name[block])
+ for name in 'startblock returnblock exceptblock'.split():
+ if block is getattr(graph, name):
+ getattr(self, 'write_' + name)(codewriter, block)
+ break
+ else:
+ self.write_block(codewriter, block)
+ codewriter.closefunc()
def write_block(self, codewriter, block):
+ self.write_block_phi_nodes(codewriter, block)
+ self.write_block_operations(codewriter, block)
+ self.write_block_branches(codewriter, block)
+
+
+ def write_block_phi_nodes(self, codewriter, block):
+ entrylinks = mkentrymap(self.graph)[block]
+ entrylinks = [x for x in entrylinks if x.prevblock is not None]
inputargs = self.db.multi_getref(block.inputargs)
inputargtypes = self.db.multi_gettyperef(block.inputargs)
- codewriter.label(self.block_to_name[block])
- entrylinks = mkentrymap(self.graph)[block]
for i, (arg, type_) in enumerate(zip(inputargs, inputargtypes)):
names = self.db.multi_getref([link.args[i] for link in entrylinks])
- blocknames = [self.block_to_name[link.prevblock] for link in entrylinks]
+ blocknames = [self.block_to_name[link.prevblock]
+ for link in entrylinks]
codewriter.phi(arg, type_, names, blocknames)
- if block is self.graph.returnblock:
- assert len(inputargs) == 1
- codewriter.ret(inputargtypes[0], inputargs[0])
- else:
- #operations
- #branches
- assert len(block.exits) == 1
+
+ def write_block_branches(self, codewriter, block):
+ if len(block.exits) == 1:
codewriter.br_uncond(self.block_to_name[block.exits[0].target])
+ elif len(block.exits) == 2:
+ switch = self.db.getref(block.exitswitch)
+ codewriter.br(switch, self.block_to_name[block.exits[0].target],
+ self.block_to_name[block.exits[1].target])
+
+ def write_block_operations(self, codewriter, block):
+ opwriter = OpWriter(self.db, codewriter)
+ for op in block.operations:
+ meth = getattr(opwriter, op.opname, None)
+ assert meth is not None, "operation %r not found" %(op.opname,)
+ meth(op)
+
+
+ def write_startblock(self, codewriter, block):
+ self.write_block_operations(codewriter, block)
+ self.write_block_branches(codewriter, block)
+
+ def write_returnblock(self, codewriter, block):
+ assert len(block.inputargs) == 1
+ self.write_block_phi_nodes(codewriter, block)
+ inputargtype = self.db.gettyperef(block.inputargs[0])
+ inputarg = self.db.getref(block.inputargs[0])
+ codewriter.ret(inputargtype, inputarg)
+class OpWriter(object):
+ def __init__(self, db, codewriter):
+ self.db = db
+ self.codewriter = codewriter
Modified: pypy/dist/pypy/translator/llvm2/pyxwrapper.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/pyxwrapper.py (original)
+++ pypy/dist/pypy/translator/llvm2/pyxwrapper.py Sat Jun 18 18:28:29 2005
@@ -2,7 +2,8 @@
from pypy.rpython import lltype
log = log.pyrex
-PRIMITIVES_TO_C = {lltype.Signed: "int"}
+PRIMITIVES_TO_C = {lltype.Signed: "int",
+ lltype.Bool: "char"}
def write_pyx_wrapper(funcgen, targetpath):
def c_declaration():
@@ -16,10 +17,11 @@
lines = []
append = lines.append
inputargs = funcgen.db.multi_getref(funcgen.graph.startblock.inputargs)
+ inputargs = [x.strip("%") for x in inputargs]
append("cdef extern " + c_declaration())
append("")
- append("def %s_wrapper(%s):" % (funcgen.ref, ", ".join(inputargs)))
- append(" return %s(%s)" % (funcgen.ref, ", ".join(inputargs)))
+ append("def %s_wrapper(%s):" % (funcgen.ref.strip("%"), ", ".join(inputargs)))
+ append(" return %s(%s)" % (funcgen.ref.strip("%"), ", ".join(inputargs)))
append("")
targetpath.write("\n".join(lines))
-
+
Modified: pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py (original)
+++ pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py Sat Jun 18 18:28:29 2005
@@ -1,7 +1,5 @@
#function snippets
-def simple1():
- return 1
def simple2():
return False
@@ -13,12 +11,6 @@
def simple4():
return 3 + simple1()
-def simple5(b):
- if b:
- x = 12
- else:
- x = 13
- return x
def simple6():
simple4()
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 Sat Jun 18 18:28:29 2005
@@ -23,6 +23,20 @@
a.simplify()
return genllvm(t)
-def test_genllvm():
- f = compile_function(llvmsnippet.simple1, [])
+
+def test_return1():
+ def simple1():
+ return 1
+ f = compile_function(simple1, [])
assert f() == 1
+
+def test_simple_branching():
+ def simple5(b):
+ if b:
+ x = 12
+ else:
+ x = 13
+ return x
+ f = compile_function(simple5, [bool])
+ assert f(True) == 12
+ assert f(False) == 13
More information about the Pypy-commit
mailing list