[pypy-svn] r13589 - in pypy/dist/pypy/translator/llvm2: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Sat Jun 18 21:51:54 CEST 2005


Author: cfbolz
Date: Sat Jun 18 21:51:54 2005
New Revision: 13589

Modified:
   pypy/dist/pypy/translator/llvm2/cfgtransform.py
   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/test/llvmsnippet.py
   pypy/dist/pypy/translator/llvm2/test/test_genllvm.py
Log:
(cfbolz, hpk)

made directcalls (recursive and non-recursive) work.

the setup() phase for FunctionNodes now traverses
the graph and adds any pending nodes so that 
references can be used without having looked 
at the function. 

improved logging and code output

added a cfg transformation to remove same_as operations 
(only tested implicitely) 



Modified: pypy/dist/pypy/translator/llvm2/cfgtransform.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/cfgtransform.py	(original)
+++ pypy/dist/pypy/translator/llvm2/cfgtransform.py	Sat Jun 18 21:51:54 2005
@@ -1,4 +1,6 @@
 from pypy.objspace.flow.model import traverse, Block, checkgraph
+from pypy.translator.unsimplify import remove_double_links
+
 
 def remove_same_as(graph): 
     same_as_positions = []
@@ -32,3 +34,10 @@
             node.operations[:] = filter(None, node.operations)
     traverse(visit, graph)
     checkgraph(graph)
+
+
+def prepare_graph(graph, translator):
+    remove_same_as(graph)
+    remove_double_links(translator, graph)
+    return 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 21:51:54 2005
@@ -12,10 +12,10 @@
         log(line) 
 
     def indent(self, line): 
-        self.append("   " + line) 
+        self.append("        " + line) 
 
     def label(self, name): 
-        self.append("%s:" % name)
+        self.append("    %s:" % name)
 
     def declare(self, decl): 
         self.append("declare %s" %(decl,))
@@ -47,5 +47,10 @@
     def binaryop(self, name, targetvar, type_, ref1, ref2):
         self.indent("%s = %s %s %s, %s" % (targetvar, name, type_, ref1, ref2))
 
+    def call(self, targetvar, returntype, functionref, argrefs, argtypes):
+        arglist = ["%s %s" % item for item in zip(argtypes, argrefs)]
+        self.indent("%s = call %s %s(%s)" % (targetvar, returntype, functionref,
+                                             ", ".join(arglist)))
+
     def __str__(self): 
         return "\n".join(self._lines)

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 21:51:54 2005
@@ -2,8 +2,6 @@
 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 
 
@@ -13,27 +11,32 @@
 class Database(object): 
     def __init__(self, translator): 
         self._translator = translator
-        self.obj2node = {}   
+        self.obj2node = {}
         self._pendingsetup = []
 
-    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:
-            return self.obj2node[obj]
-        except KeyError: 
-            node = FuncNode(self, obj) 
-            self.obj2node[obj] = node
-            log("add pending setup", node.ref) 
-            self._pendingsetup.append(node) 
-            return node
+    def prepare_ref(self, const_or_var):
+        if const_or_var in self.obj2node:
+            return
+        if isinstance(const_or_var, Constant):
+            if isinstance(const_or_var.concretetype, lltype.Primitive):
+                pass
+            else:
+                node = FuncNode(self, const_or_var) 
+                self.obj2node[const_or_var] = node
+                log("added to pending nodes:", node) 
+                self._pendingsetup.append(node) 
+
+    def prepare_typeref(self, type_):
+        if not isinstance(type_, lltype.Primitive):
+            log.XXX("need to prepare typeref")
+
+    def prepare_arg(self, const_or_var):
+        log.prepare(const_or_var)
+        self.prepare_ref(const_or_var)
+        self.prepare_typeref(const_or_var.concretetype)
 
-    def process(self): 
+            
+    def process(self):
         if self._pendingsetup: 
             self._pendingsetup.pop().setup()
         return bool(self._pendingsetup) 
@@ -42,14 +45,12 @@
         return self.obj2node.values()
 
     def getref(self, arg):
-        if isinstance(arg, Constant):
-            if isinstance(arg.concretetype, lltype.Primitive):
-                return str(arg.value).lower() #False --> false
-            raise TypeError, "can't handle the Constant %s" % arg
+        if (isinstance(arg, Constant) and 
+            isinstance(arg.concretetype, lltype.Primitive)):
+            return str(arg.value).lower() #False --> false
         elif isinstance(arg, Variable):
             return "%" + str(arg)
-        else:
-            raise TypeError, arg
+        return self.obj2node[arg].ref
 
     def gettyperef(self, arg):
         return PRIMITIVES_TO_LLVM[arg.concretetype]

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 21:51:54 2005
@@ -1,18 +1,33 @@
 import py
-from pypy.objspace.flow.model import Block, Constant, Variable, flatten, mkentrymap
+from pypy.objspace.flow.model import Block, Constant, Variable, Link
+from pypy.objspace.flow.model import flatten, mkentrymap, traverse
+from pypy.translator.llvm2.cfgtransform import prepare_graph
 from pypy.translator.llvm2.log import log 
 log = log.funcnode
 
 class FuncNode(object):
     _issetup = False 
 
-    def __init__(self, db, func):
+    def __init__(self, db, const_ptr_func):
         self.db = db
-        self.func = func
-        self.ref = self.func.func_name
-
-    def setup(self): 
-        self.graph = self.db.getgraph(self.func)
+        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 ref=%s>" %(self.ref,)
+    
+    def setup(self):
+        log("setup", self)
+        def visit(node):
+            if isinstance(node, Link):
+                map(self.db.prepare_arg, node.args)
+            elif isinstance(node, Block):
+                map(self.db.prepare_arg, node.inputargs)
+                for op in node.operations:
+                    map(self.db.prepare_arg, op.args)
+                    self.db.prepare_arg(op.result)
+        traverse(visit, self.graph)
         self._issetup = True
 
     def getdecl(self):
@@ -22,7 +37,7 @@
         inputargs = self.db.multi_getref(startblock.inputargs)
         inputargtypes = self.db.multi_gettyperef(startblock.inputargs)
         returntype = self.db.gettyperef(self.graph.returnblock.inputargs[0])
-        result = "%s %%%s" % (returntype, self.ref)
+        result = "%s %s" % (returntype, self.ref)
         args = ["%s %s" % item for item in zip(inputargtypes, inputargs)]
         result += "(%s)" % ", ".join(args)
         return result 
@@ -104,7 +119,7 @@
         assert len(op.args) == 2
         self.codewriter.binaryop(name,
                                  self.db.getref(op.result),
-                                 self.db.gettyperef(op.result),
+                                 self.db.gettyperef(op.args[0]),
                                  self.db.getref(op.args[0]),
                                  self.db.getref(op.args[1]))
     def int_mul(self, op):
@@ -118,4 +133,16 @@
 
     def int_sub(self, op):
         self.binaryop('sub', op)
+
+    def int_eq(self, op):
+        self.binaryop('seteq', op)
         
+    def direct_call(self, op):
+        assert len(op.args) >= 1
+        targetvar = self.db.getref(op.result)
+        returntype = self.db.gettyperef(op.result)
+        functionref = self.db.getref(op.args[0])
+        argrefs = self.db.multi_getref(op.args[1:])
+        argtypes = self.db.multi_gettyperef(op.args[1:])
+        self.codewriter.call(targetvar, returntype, functionref, argrefs,
+                             argtypes)

Modified: pypy/dist/pypy/translator/llvm2/genllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/genllvm.py	(original)
+++ pypy/dist/pypy/translator/llvm2/genllvm.py	Sat Jun 18 21:51:54 2005
@@ -1,7 +1,10 @@
 from pypy.translator.llvm2 import build_llvm_module
 from pypy.translator.llvm2.database import Database 
 from pypy.translator.llvm2.pyxwrapper import write_pyx_wrapper 
-from pypy.translator.llvm2.log import log 
+from pypy.translator.llvm2.log import log
+from pypy.objspace.flow.model import Constant
+from pypy.rpython.rmodel import inputconst, getfunctionptr
+from pypy.rpython import lltype
 
 from pypy.tool.udir import udir
 from pypy.translator.llvm2.codewriter import CodeWriter
@@ -10,13 +13,17 @@
     func = translator.entrypoint
 
     db = Database(translator)
-    entrynode = db.getnode(func)
-
+    ptr = getfunctionptr(translator, func)
+    c = inputconst(lltype.typeOf(ptr), ptr)
+    db.prepare_ref(c)
+    assert c in db.obj2node
     while db.process(): 
         pass
-
+    entrynode = db.obj2node[c]
     codewriter = CodeWriter()
     dbobjects =  db.getobjects()
+    log.debug(dbobjects)
+    log.debug(db.obj2node)
     for node in dbobjects:
         node.writedecl(codewriter) 
     for node in dbobjects:

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 21:51:54 2005
@@ -11,7 +11,7 @@
             funcgen.graph.returnblock.inputargs[0].concretetype]
         inputargtypes = [PRIMITIVES_TO_C[arg.concretetype]
                              for arg in funcgen.graph.startblock.inputargs]
-        result = "%s %s(%s)" % (returntype, funcgen.ref,
+        result = "%s %s(%s)" % (returntype, funcgen.ref.lstrip("%"),
                                 ", ".join(inputargtypes))
         return result
     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 21:51:54 2005
@@ -1,27 +1,7 @@
 
 #function snippets
 
-def simple2():
-    return False
 
-def simple3(i):
-    c = "Hello, Stars!"
-    return c[i]
-
-def simple4():
-    return 3 + simple1()
-
-
-def simple6():
-    simple4()
-    return 1
-
-def ackermann(n, m):
-    if n == 0:
-        return m + 1
-    if m == 0:
-        return ackermann(n - 1, 1)
-    return ackermann(n - 1, ackermann(n, m - 1))
 
 def calling1(m):
     if m > 1:

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 21:51:54 2005
@@ -11,6 +11,8 @@
 from pypy.rpython.rtyper import RPythonTyper
 
 py.log.setconsumer("genllvm", py.log.STDOUT)
+py.log.setconsumer("genllvm database prepare", None)
+
 
 ## def setup_module(mod):
 ##     mod.llvm_found = is_on_path("llvm-as")
@@ -18,8 +20,7 @@
 def compile_function(function, annotate):
     t = Translator(function)
     a = t.annotate(annotate)
-    rt = RPythonTyper(a)
-    rt.specialize()
+    t.specialize()
     a.simplify()
     return genllvm(t)
 
@@ -47,4 +48,24 @@
     f = compile_function(ops, [int])
     assert f(1) == 1
     assert f(2) == 2
+
+def test_function_call():
+    def callee():
+        return 1
+    def caller():
+        return 3 + callee()
+    f = compile_function(caller, [])
+    assert f() == 4
+
+def test_recursive_call():
+    def call_ackermann(n, m):
+        return ackermann(n, m)
+    def ackermann(n, m):
+        if n == 0:
+            return m + 1
+        if m == 0:
+            return ackermann(n - 1, 1)
+        return ackermann(n - 1, ackermann(n, m - 1))
+    f = compile_function(call_ackermann, [int, int])
+    assert f(0, 2) == 3
     



More information about the Pypy-commit mailing list