-struct psi_ffi_context {
- ffi_cif signature;
- ffi_type *params[2];
-};
-
-struct psi_ffi_call {
- struct psi_context *context;
- union {
- struct {
- struct psi_impl *impl;
- struct psi_call_frame *frame;
- } fn;
- struct {
- struct psi_let_exp *let_exp;
- struct psi_ffi_call *impl_call;
- } cb;
- } impl;
- void *code;
- ffi_closure *closure;
- ffi_cif signature;
- ffi_type *params[1]; /* [type1, type2, ... ] */
-};
-
-static void psi_ffi_handler(ffi_cif *sig, void *result, void **args, void *data)
-{
- struct psi_ffi_call *call = data;
-
- psi_context_call(call->context, *(zend_execute_data **)args[0], *(zval **)args[1], call->impl.fn.impl);
-}
-
-static void psi_ffi_callback(ffi_cif *sig, void *result, void **args, void *data)
-{
- struct psi_ffi_call *call = data, *impl_call = call->impl.cb.impl_call;
-
- if (impl_call->impl.fn.frame) {
- struct psi_call_frame_callback cbdata;
-
- cbdata.cb = call->impl.cb.let_exp;
- cbdata.argc = sig->nargs;
- cbdata.argv = args;
- cbdata.rval = result;
-
- psi_call_frame_do_callback(impl_call->impl.fn.frame, &cbdata);
- } else {
- assert(0);
- }
-}
-
-static inline ffi_abi psi_ffi_abi(const char *convention) {
- if (FFI_LAST_ABI - 2 != FFI_FIRST_ABI) {
-#ifdef HAVE_FFI_STDCALL
- if (!strcasecmp(convention, "stdcall")) {
- return FFI_STDCALL;
- }
-#endif
-#ifdef HAVE_FFI_FASTCALL
- if (!strcasecmp(convention, "fastcall")) {
- return FFI_FASTCALL;
- }
-#endif
- }
- return FFI_DEFAULT_ABI;
-}
-
-static inline struct psi_ffi_call *psi_ffi_call_alloc(struct psi_context *C, struct psi_decl *decl) {
- int rc;
- size_t i, c = psi_plist_count(decl->args);
- struct psi_ffi_call *call = calloc(1, sizeof(*call) + 2 * c * sizeof(void *));
- struct psi_decl_arg *arg;
-
- decl->info = call;
- call->context = C;
-
- for (i = 0; psi_plist_get(decl->args, i, &arg); ++i) {
- call->params[i] = psi_ffi_decl_arg_type(arg);
- }
- call->params[c] = NULL;
-
- rc = ffi_prep_cif(&call->signature, psi_ffi_abi(decl->abi->convention),
- c, psi_ffi_decl_arg_type(decl->func), call->params);
- assert(FFI_OK == rc);
-
- return call;
-}
-
-static inline ffi_status psi_ffi_call_init_closure(struct psi_context *C, struct psi_ffi_call *call, struct psi_impl *impl) {
- struct psi_ffi_context *context = C->context;
-
- call->impl.fn.impl = impl;
- return psi_ffi_prep_closure(&call->closure, &call->code, &context->signature, psi_ffi_handler, call);
-}
-
-static inline ffi_status psi_ffi_call_init_callback_closure(struct psi_context *C,
- struct psi_ffi_call *call, struct psi_ffi_call *impl_call,
- struct psi_let_exp *cb) {
- call->impl.cb.let_exp = cb;
- call->impl.cb.impl_call = impl_call;
- return psi_ffi_prep_closure(&call->closure, &call->code, &call->signature, psi_ffi_callback, call);
-}
-
-static inline void psi_ffi_call_free(struct psi_ffi_call *call) {
- if (call->closure) {
- psi_ffi_closure_free(call->closure);
- }
- free(call);
-}
-