[pypy-svn] r14361 - in pypy/dist/pypy: rpython translator/llvm2 translator/llvm2/test

rxe at codespeak.net rxe at codespeak.net
Wed Jul 6 22:09:43 CEST 2005


Author: rxe
Date: Wed Jul  6 22:09:40 2005
New Revision: 14361

Modified:
   pypy/dist/pypy/rpython/extfunctable.py
   pypy/dist/pypy/translator/llvm2/database.py
   pypy/dist/pypy/translator/llvm2/extfunction.py
   pypy/dist/pypy/translator/llvm2/funcnode.py
   pypy/dist/pypy/translator/llvm2/test/test_genllvm.py
Log:
(ericvrp, rxe) an initial stab at external functions in llvm.

Added external func node which can translate simple cases of calling external
functions.  Provides some functionality for special cases.



Modified: pypy/dist/pypy/rpython/extfunctable.py
==============================================================================
--- pypy/dist/pypy/rpython/extfunctable.py	(original)
+++ pypy/dist/pypy/rpython/extfunctable.py	Wed Jul  6 22:09:40 2005
@@ -14,7 +14,7 @@
         self.backend_functiontemplate = backend_functiontemplate
 
 table = {}
-def declare(func, annotation, ll_function, ll_annotable=True, backend_functiontemplate=None):
+def declare(func, annotation, ll_function, ll_annotable=False, backend_functiontemplate=None):
     # annotation can be a function computing the annotation
     # or a simple python type from which an annotation will be constructed
     global table
@@ -58,13 +58,15 @@
 def ll_time_sleep(t):
     time.sleep(t)
 
+nonefactory = lambda a: None
+
 # external function declarations
-declare(os.open   , int           , ll_os_open   , True             )   #this is not annotatable actually, but llvm has an issue
-declare(os.read   , str           , ll_os_read   , True             )
-declare(os.write  , int           , ll_os_write  , True             )
-declare(os.close  , lambda a: None, ll_os_close  , True , 'C:close' )
-declare(os.getcwd , str           , ll_os_getcwd , True             )
-declare(os.dup    , int           , ll_os_dup    , True , 'C:dup'   )
-declare(time.time , float         , ll_time_time , True             )
-declare(time.clock, float         , ll_time_clock, True             )
-declare(time.sleep, lambda a: None, ll_time_sleep, True             )
+declare(os.open   , int        , ll_os_open)
+declare(os.read   , str        , ll_os_read)
+declare(os.write  , int        , ll_os_write)
+declare(os.close  , nonefactory, ll_os_close)
+declare(os.getcwd , str        , ll_os_getcwd)
+declare(os.dup    , int        , ll_os_dup)
+declare(time.time , float      , ll_time_time)
+declare(time.clock, float      , ll_time_clock)
+declare(time.sleep, nonefactory, ll_time_sleep)

Modified: pypy/dist/pypy/translator/llvm2/database.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/database.py	(original)
+++ pypy/dist/pypy/translator/llvm2/database.py	Wed Jul  6 22:09:40 2005
@@ -1,5 +1,5 @@
 from pypy.translator.llvm2.log import log 
-from pypy.translator.llvm2.funcnode import FuncNode, FuncTypeNode
+from pypy.translator.llvm2.funcnode import ExternalFuncNode, FuncNode, FuncTypeNode
 from pypy.translator.llvm2.structnode import StructNode, StructVarsizeNode, \
      StructTypeNode, StructVarsizeTypeNode
 from pypy.translator.llvm2.arraynode import ArrayNode, ArrayTypeNode
@@ -86,10 +86,8 @@
         type_ = lltype.typeOf(value)
         node = None
         if isinstance(type_, lltype.FuncType):
-            
-            if value._callable \
-                   and not hasattr(value, 'graph'):
-                log('EXTERNAL FUNCTION' + str(dir(value)))
+            if ((not hasattr(value, "graph")) or value.graph is None) and value._callable:
+                node = ExternalFuncNode(self, value)
             else:
                 node = FuncNode(self, value)
 
@@ -126,6 +124,7 @@
 
             assert isinstance(ct, lltype.Ptr), "Preperation of non primitive and non pointer" 
             value = const_or_var.value._obj            
+                
             self.addpending(const_or_var, self.create_constant_node(value))
         else:
             log.prepare(const_or_var, type(const_or_var))

Modified: pypy/dist/pypy/translator/llvm2/extfunction.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/extfunction.py	(original)
+++ pypy/dist/pypy/translator/llvm2/extfunction.py	Wed Jul  6 22:09:40 2005
@@ -1,4 +1,5 @@
-extdeclarations = """; External declarations
+extdeclarations =  """; External declarations
+
 
 ; XXX these int's might need to be long's on 64 bit CPU's :(
 
@@ -7,6 +8,7 @@
 declare void %sleep(int)
 
 ; End of external declarations
+
 """
 
 extfunctions = """; External functions (will be inlined by LLVM)
@@ -24,7 +26,7 @@
     ret double %v2
 }
 
-void %ll_time_sleep__Float(double %f) {
+void %ll_time_sleep(double %f) {
     %i = cast double %f to int
     call void %sleep(int %i)
     ret void

Modified: pypy/dist/pypy/translator/llvm2/funcnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm2/funcnode.py	(original)
+++ pypy/dist/pypy/translator/llvm2/funcnode.py	Wed Jul  6 22:09:40 2005
@@ -32,8 +32,7 @@
         decl = "%s type %s (%s)*" % (self.ref, returntype,
                                      ", ".join(inputargtypes))
         codewriter.funcdef(self.ref, returntype, inputargtypes)
-
-
+                
 class FuncNode(LLVMNode):
     _issetup = False 
 
@@ -61,12 +60,16 @@
         assert self.graph, "cannot traverse"
         traverse(visit, self.graph)
         self._issetup = True
+
     # ______________________________________________________________________
     # main entry points from genllvm 
     def writedecl(self, codewriter): 
         codewriter.declare(self.getdecl())
 
     def writeimpl(self, codewriter):
+
+        # XXX Code checks for when the rpython extfunctable has set the annotable
+        # flag to True?????
         _callable = self.value._callable
         for func, extfuncinfo in extfunctable.iteritems():  # precompute a dict?
             if _callable is extfuncinfo.ll_function:
@@ -153,6 +156,88 @@
         else:
             codewriter.ret_void()
 
+
+class ExternalFuncNode(LLVMNode):
+
+    fnmapping = {
+        "%ll_os_dup": "%dup",
+        "%ll_os_open": "%open",
+        "%ll_os_close": "%close",
+        #"%": ("int" "%open", "sbyte*", "int"),
+        #"%ll_os_write": ("int" "%write", "int", "sbyte*", "int"),
+        }
+
+    ignoreset = "%ll_time_time %ll_time_clock %ll_time_sleep".split() 
+
+    def __init__(self, db, value):
+        self.db = db
+        self.value = value
+        self.ref = "%" + value._name
+
+    def setup(self):
+        self._issetup = True
+
+    def getdecl(self):
+        T = self.value._TYPE
+        args = [self.db.repr_arg_type(a) for a in T.ARGS]
+        decl = "%s %s(%s)" % (self.db.repr_arg_type(T.RESULT),
+                              self.ref,
+                              ", ".join(args))
+        return decl
+
+    def getcdecl(self):        
+        #XXX Mapping
+        T = self.value._TYPE
+        args = [self.db.repr_arg_type(a) for a in T.ARGS]
+        decl = "%s %s(%s)" % (self.db.repr_arg_type(T.RESULT),
+                              self.fnmapping[self.ref],
+                              ", ".join(args))
+        return decl        
+
+    # ______________________________________________________________________
+    # main entry points from genllvm 
+    def writedecl(self, codewriter): 
+        codewriter.declare(self.getdecl())
+
+        if self.ref not in self.ignoreset:
+            codewriter.declare(self.getcdecl())
+
+    def writeimpl(self, codewriter): 
+        if self.ref in self.ignoreset:
+            return
+
+        T = self.value._TYPE
+        args = ["%s %%a%s" % (self.db.repr_arg_type(a), c)
+                for c, a in enumerate(T.ARGS)]
+
+        decl = "%s %s(%s)" % (self.db.repr_arg_type(T.RESULT),
+                              self.ref,
+                              ", ".join(args))
+
+        codewriter.openfunc(decl)
+
+        # go thru and map argsXXX
+        argrefs = ["%%a%s" % c for c in range(len(T.ARGS))]
+        argtypes = [self.db.repr_arg_type(a) for a in T.ARGS]
+
+        # get return type (mapped perhaps)
+        resulttype = self.db.repr_arg_type(T.RESULT)
+
+        # get function name
+        fnname = self.fnmapping[self.ref]
+        
+        # call 
+
+        # map resulttype ??? XXX
+        if resulttype != "void":
+            codewriter.call("%res", resulttype, fnname, argrefs, argtypes)
+            codewriter.ret(resulttype, "%res")
+        else:
+            codewriter.call_void(fnname, argrefs, argtypes)
+            codewriter.ret_void()
+        
+        codewriter.closefunc()
+
 class OpWriter(object):
     binary_operations = {'int_mul': 'mul',
                          'int_add': 'add',

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	Wed Jul  6 22:09:40 2005
@@ -41,9 +41,21 @@
     import os
     def fn():
         return os.dup(0)
-    f = compile_function(fn, [], view=False)
+    f = compile_function(fn, [])
     assert os.path.sameopenfile(f(), fn())
 
+def test_external_file_fns():
+    import os
+    def external_file_fns(intname, flags):
+        name = str(intname)
+        fd = os.open(name, flags)
+        #os.write(fd, name)
+        os.close(fd)
+        return fd
+    
+    f = compile_function(external_file_fns, [int, int])
+    assert isinstance(f(1209319, 64), int)
+    
 def DONTtest_external_function_ll_os_getcmd():
     import os
     def fn():



More information about the Pypy-commit mailing list