[pypy-svn] r20138 - in pypy/dist/pypy/translator/llvm: . module test

rxe at codespeak.net rxe at codespeak.net
Mon Nov 21 16:47:20 CET 2005


Author: rxe
Date: Mon Nov 21 16:47:17 2005
New Revision: 20138

Modified:
   pypy/dist/pypy/translator/llvm/extfuncnode.py
   pypy/dist/pypy/translator/llvm/module/support.py
   pypy/dist/pypy/translator/llvm/test/test_extfunc.py
Log:
Refactor ExternalFuncNode to gererate wrappers when the C function when it has
a different signature to the rtyped one. (really a problem with C)

It is nice when refactoring allows more tests to pass.



Modified: pypy/dist/pypy/translator/llvm/extfuncnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/extfuncnode.py	(original)
+++ pypy/dist/pypy/translator/llvm/extfuncnode.py	Mon Nov 21 16:47:17 2005
@@ -4,8 +4,19 @@
 
 log = log.extfuncnode
 
+class ExtFuncSig(object):
+    def __init__(self, retval, args):
+        self.args = args
+        self.rettype = retval
+
+# signature of external functions differ from C's implementation
+ext_func_sigs = {
+    "%LL_os_isatty" : ExtFuncSig("int", None),
+    "%LL_stack_too_big" : ExtFuncSig("int", None),
+    "%LL_thread_acquirelock" : ExtFuncSig("int", [None, "int"]),
+    "%LL_thread_start" : ExtFuncSig(None, ["sbyte*", "sbyte*"])}
+    
 class ExternalFuncNode(ConstantLLVMNode):
-    used_external_functions = {}
 
     def __init__(self, db, value):
         self.db = db
@@ -15,18 +26,83 @@
 
         mapped_name = EXTERNALS[value._callable]
         self.ref = self.make_ref("%", mapped_name)
-        self.used_external_functions[self.ref] = True
+        self.wrapper = ext_func_sigs.get(self.ref, None)
+        
+    def __str__(self):
+        return "<ExternalFuncNode %r>" % self.ref
 
-    def getdecl(self):
+    def getdecl_parts(self):
         T = self.value._TYPE
-        args = [self.db.repr_type(a) for a in T.ARGS]
-        decl = "%s %s(%s)" % (self.db.repr_type(T.RESULT),
-                              self.ref,
-                              ", ".join(args))
-        return decl
+        rettype = self.db.repr_type(T.RESULT)
+        argtypes = [self.db.repr_type(a) for a in T.ARGS]
+        return rettype, argtypes
+    
+    def getdecl(self):
+        rettype, argtypes = self.getdecl_parts()
+        return "%s %s(%s)" % (rettype, self.ref, ", ".join(argtypes))
 
     def writedecl(self, codewriter): 
         codewriter.declare(self.getdecl())
 
+    def writeimpl(self, codewriter):
+                                   
+        if self.wrapper is None:
+            return
+        
+        rettype, argtypes = self.getdecl_parts()
+        argrefs = [self.db.repr_tmpvar() for ii in argtypes]
+        arg_desription = ", ".join([
+            "%s %s" % (typ_, name)
+            for typ_, name in zip(argtypes, argrefs)])
+        
+        open_decl =  "%s %s(%s)" % (rettype, self.ref, arg_desription)
+        codewriter.openfunc(open_decl)
+        
+        returnval = self.db.repr_tmpvar()
+        
+        # call function with this
+        expected_argrefs = []
+        expected_argtypes = []
+
+        # find out what the args/types should be
+        if self.wrapper.args is not None:
+            assert len(self.wrapper.args) == len(argtypes)
+            
+            for expected_typ, typ, ref in zip(self.wrapper.args,
+                                              argtypes,
+                                              argrefs):
+                if expected_typ is not None:
+
+                    # cast to desired arg type
+                    expected_ref = self.db.repr_tmpvar()
+                    codewriter.cast(expected_ref, typ, ref, expected_typ)
+
+                else:
+                    expected_ref = ref
+                    expected_typ = typ
+
+                expected_argrefs.append(expected_ref)
+                expected_argtypes.append(expected_typ)
+        else:
+            expected_argrefs = argrefs
+            expected_argtypes = argtypes
+
+        # find out what the return type should be 
+        expected_rettype = self.wrapper.rettype or rettype
+
+        # call
+        codewriter.call(returnval, expected_rettype, self.ref,
+                        expected_argrefs, expected_argtypes)
+
+        if self.wrapper.rettype:
+            # cast to desired return type
+            tmpval = returnval
+            returnval = self.db.repr_tmpvar()
+            codewriter.cast(returnval, self.wrapper.rettype,
+                            tmpval, rettype)
+            
+        codewriter.ret(rettype, returnval)
+        codewriter.closefunc()
+
     def writeglobalconstants(self, codewriter):
         pass

Modified: pypy/dist/pypy/translator/llvm/module/support.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/module/support.py	(original)
+++ pypy/dist/pypy/translator/llvm/module/support.py	Mon Nov 21 16:47:17 2005
@@ -70,25 +70,6 @@
     ret double %result
 }
 
-;; functions that should return a bool according to
-;; pypy/rpython/extfunctable.py  , but C doesn't have bools!
-
-internal fastcc bool %LL_os_isatty(int %fd) {
-    %t = call fastcc int %LL_os_isatty(int %fd)
-    %b = cast int %t to bool
-    ret bool %b
-}
-internal fastcc bool %LL_stack_too_big() {
-    %t = call fastcc int %LL_stack_too_big()
-    %b = cast int %t to bool
-    ret bool %b
-}
-internal fastcc bool %LL_thread_acquirelock(%RPyOpaque_ThreadLock* %lock, bool %waitflag) {
-    %waitint = cast bool %waitflag to int
-    %t = call fastcc int %LL_thread_acquirelock(%RPyOpaque_ThreadLock* %lock, int %waitint)
-    %b = cast int %t to bool
-    ret bool %b
-}
 """
 
 def write_raise_exc(c_name, exc_repr, codewriter):

Modified: pypy/dist/pypy/translator/llvm/test/test_extfunc.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/test/test_extfunc.py	(original)
+++ pypy/dist/pypy/translator/llvm/test/test_extfunc.py	Mon Nov 21 16:47:17 2005
@@ -390,7 +390,6 @@
     assert res
 
 def test_simple_start_new_thread():
-    py.test.skip("WIP")    
     import thread
     import pypy.module.thread.rpython.exttable   # for declare()/declaretype()
     class Arg:
@@ -419,7 +418,6 @@
     assert res == 42
 
 def test_start_new_thread():
-    py.test.skip("WIP")    
     import thread
     import pypy.module.thread.rpython.exttable   # for declare()/declaretype()
     class Arg:



More information about the Pypy-commit mailing list