[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