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