Author: Antonio Cuni <[email protected]>
Branch: hpy
Changeset: r98123:f9c2cfcfaafa
Date: 2019-11-19 11:48 +0100
http://bitbucket.org/pypy/pypy/changeset/f9c2cfcfaafa/

Log:    This checkin might win the prize for the highest amount of
        XXXs/lines of code: it needs a deep review, please :)

        Fix W_ExtensionFunction_call_varargs to use the updated calling
        convention, and implement ctx_Arg_Parse.

diff --git a/pypy/module/hpy_universal/interp_extfunc.py 
b/pypy/module/hpy_universal/interp_extfunc.py
--- a/pypy/module/hpy_universal/interp_extfunc.py
+++ b/pypy/module/hpy_universal/interp_extfunc.py
@@ -47,9 +47,33 @@
         return handles.consume(space, h_result)
 
     def call_varargs(self, space, arguments_w):
-        w_tuple = space.newtuple(arguments_w)
-        # xxx here we just invoke call_o() with the w_tuple
-        return self.call_o(space, w_tuple)
+        # this function is more or less the equivalent of
+        # ctx_CallRealFunctionFromTrampoline in cpython-universal
+        state = space.fromcache(State)
+        n = len(arguments_w)
+
+        # XXX this looks inefficient: ideally, we would like the equivalent of
+        # alloca(): do we have it in RPython? The alternative is to wrap
+        # arguments_w in a tuple, convert to handle and pass it to a C
+        # function whichs calls alloca() and the forwards everything to the
+        # functpr
+        with handles.using(space, self.w_self) as h_self:
+            with lltype.scoped_alloc(rffi.CArray(llapi.HPy), n) as args_h:
+                for i, w_obj in enumerate(arguments_w):
+                    args_h[i] = handles.new(space, w_obj)
+
+                # XXX: is it correct to use rffi.cast instead of some kind of
+                # lltype.cast_*?
+                fptr = rffi.cast(llapi.HPyMeth_VarArgs, self.cfuncptr)
+                h_result = generic_cpy_call_dont_convert_result(space, fptr,
+                                                        state.ctx, h_self, 
args_h, n)
+
+                # XXX this should probably be in a try/finally. We should add a
+                # test to check that we don't leak handles
+                for i in range(n):
+                    handles.close(space, args_h[i])
+
+        return handles.consume(space, h_result)
 
     def descr_call(self, space, __args__):
         flags = self.flags
diff --git a/pypy/module/hpy_universal/llapi.py 
b/pypy/module/hpy_universal/llapi.py
--- a/pypy/module/hpy_universal/llapi.py
+++ b/pypy/module/hpy_universal/llapi.py
@@ -1,23 +1,37 @@
 import py
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from pypy import pypydir
 from pypy.module.hpy_universal import _vendored
 
-INCLUDE_DIR = str(py.path.local(_vendored.__file__).dirpath().join('include'))
+PYPYDIR = py.path.local(pypydir)
+INCLUDE_DIR = PYPYDIR.join('module', 'hpy_universal', '_vendored', 'include')
+SRC_DIR = PYPYDIR.join('module', 'hpy_universal', 'src')
+
+# XXX I don't understand what is going on here: if I put getargs.c as
+# separate_module_files, then ll2ctypes can't find it. I need to #include t in
+# separate_module_sources for now...
 eci = ExternalCompilationInfo(includes=["universal/hpy.h"],
                               include_dirs=[INCLUDE_DIR],
+                              ## separate_module_files=[
+                              ##     SRC_DIR.join('getargs.c'),
+                              ##     ],
                               post_include_bits=["""
 RPY_EXTERN void *_HPy_GetGlobalCtx(void);
+RPY_EXTERN int ctx_Arg_Parse(HPyContext ctx, HPy *args, HPy_ssize_t nargs,
+                             const char *fmt, va_list vl);
 """],
                               separate_module_sources=["""
 
+#include "%s"
+
 struct _HPyContext_s hpy_global_ctx;
 void *_HPy_GetGlobalCtx(void)
 {
     return &hpy_global_ctx;
 }
 
-"""])
+""" % SRC_DIR.join('getargs.c')])
 
 
 HPy = lltype.Signed
@@ -43,11 +57,17 @@
 )
 HPyContext = lltype.Ptr(HPyContextS)
 
+HPy_ssize_t = lltype.Signed # XXXXXXXXX?
+
 HPyInitFuncPtr = lltype.Ptr(lltype.FuncType([HPyContext], HPy))
 
 _HPyCFunctionPtr = lltype.Ptr(lltype.FuncType([HPyContext, HPy, HPy], HPy))
 _HPy_CPyCFunctionPtr = rffi.VOIDP    # not used here
 
+HPyMeth_VarArgs = lltype.Ptr(
+    lltype.FuncType([HPyContext, HPy, lltype.Ptr(rffi.CArray(HPy)), 
HPy_ssize_t], HPy))
+
+
 _HPyMethodPairFuncPtr = lltype.Ptr(lltype.FuncType([
         rffi.CArrayPtr(_HPyCFunctionPtr),
         rffi.CArrayPtr(_HPy_CPyCFunctionPtr)],
@@ -76,8 +96,18 @@
 METH_O        = 0x0008
 
 
+
+
 # ----------------------------------------------------------------
 
 
 _HPy_GetGlobalCtx = rffi.llexternal('_HPy_GetGlobalCtx', [], HPyContext,
                                     compilation_info=eci, _nowrapper=True)
+
+# NOTE: this is not the real signature (we don't know what to put for
+# va_list), but it's good enough to get the address of the function to store
+# in the ctx. DO NOT CALL THIS!. TO avoid possible mistakes, we directly cast
+# it to VOIDP
+ctx_Arg_Parse_fn = rffi.llexternal('ctx_Arg_Parse', [], rffi.INT_real,
+                                compilation_info=eci, _nowrapper=True)
+ctx_Arg_Parse = rffi.cast(rffi.VOIDP, ctx_Arg_Parse_fn)
diff --git a/pypy/module/hpy_universal/src/getargs.c 
b/pypy/module/hpy_universal/src/getargs.c
new file mode 100644
--- /dev/null
+++ b/pypy/module/hpy_universal/src/getargs.c
@@ -0,0 +1,43 @@
+#include "universal/hpy.h"
+
+#include <stdio.h>
+
+/* XXX: this function is copied&pasted THREE times:
+ *     hpy_devel/include/hpy.h
+ *     cpython-universal/api.c
+ *     pypy/module/hpy_universal/src/getargs.c
+ *
+ * We need a way to share this kind of common code
+ */
+
+/* would be nice if this were static :( */
+int
+ctx_Arg_Parse(HPyContext ctx, HPy *args, HPy_ssize_t nargs,
+              const char *fmt, va_list vl)
+{
+    const char *fmt1 = fmt;
+    HPy_ssize_t i = 0;
+
+    while (*fmt1 != 0) {
+        if (i >= nargs) {
+            abort(); // XXX
+        }
+        switch (*fmt1++) {
+        case 'l': {
+            long *output = va_arg(vl, long *);
+            long value = HPyLong_AsLong(ctx, args[i]);
+            // XXX check for exceptions
+            *output = value;
+            break;
+        }
+        default:
+            abort();  // XXX
+        }
+        i++;
+    }
+    if (i != nargs) {
+        abort();   // XXX
+    }
+
+    return 1;
+}
diff --git a/pypy/module/hpy_universal/state.py 
b/pypy/module/hpy_universal/state.py
--- a/pypy/module/hpy_universal/state.py
+++ b/pypy/module/hpy_universal/state.py
@@ -72,3 +72,5 @@
         #
         funcptr = interp_hpy.HPyErr_SetString.get_llhelper(space)
         self.ctx.c_ctx_Err_SetString = rffi.cast(rffi.VOIDP, funcptr)
+        #
+        self.ctx.c_ctx_Arg_Parse = llapi.ctx_Arg_Parse
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to