1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *******************************************************************************/
26 #include "php_psi_stdinc.h"
34 #undef PACKAGE_BUGREPORT
37 #undef PACKAGE_TARNAME
38 #undef PACKAGE_VERSION
42 #ifndef PSI_HAVE_FFI_CLOSURE_ALLOC
47 # include <sys/mman.h>
48 # ifndef MAP_ANONYMOUS
49 # define MAP_ANONYMOUS MAP_ANON
54 struct psi_ffi_context
{
59 struct psi_ffi_impl_info
{
60 struct psi_context
*context
;
61 struct psi_call_frame
*frame
;
67 struct psi_ffi_callback_info
{
68 struct psi_ffi_impl_info
*impl_info
;
69 struct psi_let_exp
*let_exp
;
75 struct psi_ffi_decl_info
{
81 static void *psi_ffi_closure_alloc(size_t s
, void **code
)
83 #ifdef PSI_HAVE_FFI_CLOSURE_ALLOC
84 return ffi_closure_alloc(s
, code
);
86 *code
= mmap(NULL
, s
, PROT_EXEC
|PROT_WRITE
|PROT_READ
,
87 MAP_PRIVATE
|MAP_ANONYMOUS
, -1, 0);
88 if (MAP_FAILED
== *code
) {
93 # error "Neither ffi_closure_alloc() nor mmap() available"
97 static ffi_status
psi_ffi_prep_closure(ffi_closure
**closure
, void **code
, ffi_cif
*sig
, void (*handler
)(ffi_cif
*,void*,void**,void*), void *data
) {
98 *closure
= psi_ffi_closure_alloc(sizeof(ffi_closure
), code
);
99 assert(*closure
!= NULL
);
101 #if PSI_HAVE_FFI_PREP_CLOSURE_LOC
102 return ffi_prep_closure_loc(*closure
, sig
, handler
, data
, *code
);
104 #elif PSI_HAVE_FFI_PREP_CLOSURE
105 return ffi_prep_closure(*code
, sig
, handler
, data
);
107 # error "Neither ffi_prep_closure() nor ffi_prep_closure_loc() is available"
111 static void psi_ffi_closure_free(void *c
)
113 #ifdef PSI_HAVE_FFI_CLOSURE_ALLOC
116 munmap(c
, sizeof(ffi_closure
));
120 static void psi_ffi_prep_va(ffi_cif
*base
, ffi_cif
*signature
, size_t argc
, size_t va_count
,
121 ffi_type
**param_types
) {
124 #ifdef PSI_HAVE_FFI_PREP_CIF_VAR
125 rc
= ffi_prep_cif_var(signature
, base
->abi
, argc
, argc
+ va_count
,
126 base
->rtype
, param_types
);
128 /* FIXME: test in config.m4; assume we can just call anyway */
129 rc
= ffi_prep_cif(signature
, base
->abi
, argc
+ va_count
, base
->rtype
, param_types
);
132 assert(FFI_OK
== rc
);
136 static ffi_type
*ffi_type_sint128
;
137 static ffi_type
*ffi_type_uint128
;
140 static inline ffi_type
*psi_ffi_decl_arg_type(struct psi_decl_arg
*darg
);
142 static inline ffi_type
*psi_ffi_token_type(token_t t
) {
148 return &ffi_type_void
;
150 return &ffi_type_sint8
;
152 return &ffi_type_uint8
;
154 return &ffi_type_sint16
;
156 return &ffi_type_uint16
;
158 return &ffi_type_sint32
;
160 return &ffi_type_uint32
;
162 return &ffi_type_sint64
;
164 return &ffi_type_uint64
;
167 return ffi_type_sint128
;
169 return ffi_type_uint128
;
172 return &ffi_type_uchar
;
174 return &ffi_type_sint
;
176 return &ffi_type_float
;
178 return &ffi_type_double
;
179 #ifdef HAVE_LONG_DOUBLE
180 case PSI_T_LONG_DOUBLE
:
181 return &ffi_type_longdouble
;
185 return &ffi_type_pointer
;
188 static inline ffi_type
*psi_ffi_impl_type(token_t impl_type
) {
191 return &ffi_type_sint8
;
193 return &ffi_type_sint64
;
195 return &ffi_type_pointer
;
198 return &ffi_type_double
;
199 EMPTY_SWITCH_DEFAULT_CASE();
203 static void psi_ffi_type_dtor(void *type
) {
204 ffi_type
*strct
= type
;
206 if (strct
->elements
) {
209 for (ptr
= strct
->elements
; *ptr
; ++ptr
) {
212 free(strct
->elements
);
217 static size_t psi_ffi_struct_type_pad(ffi_type
**els
, size_t padding
) {
220 for (i
= 0; i
< padding
; ++i
) {
221 ffi_type
*pad
= malloc(sizeof(*pad
));
223 memcpy(pad
, &ffi_type_schar
, sizeof(*pad
));
230 struct psi_ffi_struct_element_storage
{
239 static inline void psi_ffi_struct_type_element(
240 struct psi_ffi_struct_element_storage
*s
, struct psi_decl_arg
*darg
,
241 ffi_type
*darg_type
) {
243 ffi_type
*type
, **tmp
;
246 if (darg
->layout
->pos
== s
->last_arg_pos
) {
247 /* skip bit fields */
250 s
->last_arg_pos
= darg
->layout
->pos
;
252 type
= malloc(sizeof(*type
));
255 if (type
->alignment
> s
->max_align
) {
256 s
->max_align
= type
->alignment
;
259 assert(type
->size
<= darg
->layout
->len
);
260 if ((padding
= psi_offset_padding(darg
->layout
->pos
- s
->offset
, type
->alignment
))) {
261 if (s
->nels
+ padding
+ 1 > s
->argc
) {
263 tmp
= realloc(s
->els
, (s
->argc
+ 1) * sizeof(*s
->els
));
270 s
->els
[s
->argc
] = NULL
;
272 psi_ffi_struct_type_pad(&s
->els
[s
->nels
], padding
);
274 s
->offset
+= padding
;
276 assert(s
->offset
== darg
->layout
->pos
);
278 s
->offset
= (s
->offset
+ darg
->layout
->len
+ type
->alignment
- 1) & ~(type
->alignment
- 1);
279 s
->els
[s
->nels
++] = type
;
282 static ffi_type
**psi_ffi_struct_type_elements(struct psi_decl_struct
*strct
) {
285 struct psi_decl_arg
*darg
;
286 struct psi_ffi_struct_element_storage s
= {0};
289 s
.argc
= psi_plist_count(strct
->args
);
290 s
.els
= calloc(s
.argc
+ 1, sizeof(*s
.els
));
292 while (psi_plist_get(strct
->args
, i
++, &darg
)) {
293 psi_ffi_struct_type_element(&s
, darg
, psi_ffi_decl_arg_type(darg
));
296 /* apply struct alignment padding */
297 s
.offset
= (s
.offset
+ s
.max_align
- 1) & ~(s
.max_align
- 1);
299 assert(s
.offset
<= strct
->size
);
300 if (s
.offset
< strct
->size
) { /* WTF? */
301 size_t padding
= strct
->size
- s
.offset
;
303 tmp
= realloc(s
.els
, (padding
+ s
.argc
+ 1) * sizeof(*s
.els
));
310 psi_ffi_struct_type_pad(&s
.els
[s
.nels
], padding
);
311 s
.els
[s
.argc
+ padding
] = NULL
;
317 static inline ffi_type
*psi_ffi_decl_type(struct psi_decl_type
*type
) {
318 struct psi_decl_type
*real
= psi_decl_type_get_real(type
);
320 if (real
!= type
&& type
->real
.def
->var
->pointer_level
) {
321 return &ffi_type_pointer
;
324 switch (real
->type
) {
326 if (!real
->real
.strct
->engine
.type
) {
327 ffi_type
*strct
= calloc(1, sizeof(ffi_type
));
329 strct
->type
= FFI_TYPE_STRUCT
;
331 strct
->elements
= psi_ffi_struct_type_elements(real
->real
.strct
);
333 real
->real
.strct
->engine
.type
= strct
;
334 real
->real
.strct
->engine
.dtor
= psi_ffi_type_dtor
;
337 return real
->real
.strct
->engine
.type
;
341 struct psi_decl_arg
*arg
;
342 psi_plist_get(real
->real
.unn
->args
, 0, &arg
);
343 return psi_ffi_decl_arg_type(arg
);
350 return psi_ffi_token_type(real
->type
);
353 static inline ffi_type
*psi_ffi_decl_func_array_type(struct psi_decl
*fn
) {
354 struct psi_ffi_decl_info
*info
= fn
->info
;
355 struct psi_ffi_struct_element_storage s
= {0};
360 if (info
->rv_array
) {
361 return info
->rv_array
;
365 s
.argc
= fn
->func
->var
->array_size
;
366 s
.els
= calloc(s
.argc
+ 1, sizeof(*s
.els
));
368 info
->rv_array
= calloc(1, sizeof(ffi_type
));
369 info
->rv_array
->type
= FFI_TYPE_STRUCT
;
370 info
->rv_array
->size
= 0;
371 info
->rv_array
->elements
= s
.els
;
374 if (fn
->func
->var
->pointer_level
> 1) {
375 l
.len
= SIZEOF_VOID_P
;
376 type
= &ffi_type_pointer
;
378 l
.len
= psi_decl_type_get_size(fn
->func
->type
, NULL
);
379 type
= psi_ffi_decl_type(fn
->func
->type
);
382 assert(!fn
->func
->layout
);
383 fn
->func
->layout
= &l
;
384 for (i
= 0; i
< fn
->func
->var
->array_size
; ++i
) {
385 psi_ffi_struct_type_element(&s
, fn
->func
, type
);
386 info
->rv_array
->elements
= s
.els
;
389 fn
->func
->layout
= NULL
;
391 return info
->rv_array
;
394 static inline ffi_type
*psi_ffi_decl_arg_type(struct psi_decl_arg
*darg
) {
395 if (darg
->var
->pointer_level
) {
396 return &ffi_type_pointer
;
398 return psi_ffi_decl_type(darg
->type
);
402 static inline ffi_type
*psi_ffi_decl_func_type(struct psi_decl
*fn
) {
403 struct psi_decl_arg
*darg
= fn
->func
;
405 if (darg
->var
->pointer_level
) {
406 if (darg
->var
->array_size
) {
407 /* mimic a struct resembling the array return type of fn */
408 return psi_ffi_decl_func_array_type(fn
);
410 return &ffi_type_pointer
;
412 return psi_ffi_decl_type(darg
->type
);
416 static inline ffi_abi
psi_ffi_abi(const char *convention
) {
417 if (FFI_LAST_ABI
- 2 != FFI_FIRST_ABI
) {
418 #ifdef HAVE_FFI_STDCALL
419 if (!strcasecmp(convention
, "stdcall")) {
423 #ifdef HAVE_FFI_FASTCALL
424 if (!strcasecmp(convention
, "fastcall")) {
429 return FFI_DEFAULT_ABI
;
432 static inline struct psi_ffi_decl_info
*psi_ffi_decl_init(struct psi_decl
*decl
) {
435 size_t i
, c
= psi_plist_count(decl
->args
);
436 struct psi_decl_arg
*arg
;
437 struct psi_ffi_decl_info
*info
= calloc(1, sizeof(*info
) + 2 * c
* sizeof(void *));
441 for (i
= 0; psi_plist_get(decl
->args
, i
, &arg
); ++i
) {
442 info
->params
[i
] = psi_ffi_decl_arg_type(arg
);
444 info
->params
[c
] = NULL
;
446 rc
= ffi_prep_cif(&info
->signature
, psi_ffi_abi(decl
->abi
->convention
),
447 c
, psi_ffi_decl_func_type(decl
), info
->params
);
458 static inline void psi_ffi_decl_dtor(struct psi_decl
*decl
) {
460 struct psi_ffi_decl_info
*info
= decl
->info
;
462 if (info
->rv_array
) {
463 psi_ffi_type_dtor(info
->rv_array
);
470 static void psi_ffi_handler(ffi_cif
*sig
, void *result
, void **args
, void *data
)
472 struct psi_impl
*impl
= data
;
473 struct psi_ffi_impl_info
*info
= impl
->info
;
475 psi_context_call(info
->context
, *(zend_execute_data
**)args
[0], *(zval
**)args
[1], impl
);
478 static void psi_ffi_callback(ffi_cif
*sig
, void *result
, void **args
, void *data
)
480 struct psi_ffi_callback_info
*cb_info
= data
;
481 struct psi_call_frame_callback cb_data
;
483 assert(cb_info
->impl_info
->frame
);
485 cb_data
.cb
= cb_info
->let_exp
;
486 cb_data
.argc
= sig
->nargs
;
488 cb_data
.rval
= result
;
490 psi_call_frame_do_callback(cb_info
->impl_info
->frame
, &cb_data
);
493 static inline void psi_ffi_callback_init(struct psi_ffi_impl_info
*impl_info
,
494 struct psi_let_exp
*let_exp
) {
495 struct psi_ffi_callback_info
*cb_info
;
496 struct psi_ffi_decl_info
*decl_info
;
497 struct psi_let_callback
*cb
;
498 struct psi_let_func
*fn
= NULL
;
501 switch (let_exp
->kind
) {
502 case PSI_LET_CALLBACK
:
503 cb
= let_exp
->data
.callback
;
504 if (cb
->decl
->info
) {
505 decl_info
= cb
->decl
->info
;
507 decl_info
= psi_ffi_decl_init(cb
->decl
);
510 cb_info
= calloc(1, sizeof(*cb_info
));
511 cb_info
->impl_info
= impl_info
;
512 cb_info
->let_exp
= let_exp
;
513 rc
= psi_ffi_prep_closure(&cb_info
->closure
, &cb_info
->code
,
514 &decl_info
->signature
, psi_ffi_callback
, cb_info
);
522 assert(!cb
->decl
->sym
);
523 cb
->decl
->sym
= cb_info
->code
;
529 fn
= let_exp
->data
.func
;
533 struct psi_let_exp
*inner_let
;
535 while (psi_plist_get(fn
->inner
, i
++, &inner_let
)) {
536 psi_ffi_callback_init(impl_info
, inner_let
);
545 static inline void psi_ffi_callback_dtor(struct psi_let_exp
*let_exp
) {
546 struct psi_let_callback
*cb
;
547 struct psi_let_func
*fn
= NULL
;
549 switch (let_exp
->kind
) {
550 case PSI_LET_CALLBACK
:
551 cb
= let_exp
->data
.callback
;
553 psi_ffi_decl_dtor(cb
->decl
);
556 struct psi_ffi_callback_info
*info
= cb
->info
;
559 psi_ffi_closure_free(info
->closure
);
568 fn
= let_exp
->data
.func
;
573 struct psi_let_exp
*cb
;
575 while (psi_plist_get(fn
->inner
, i
++, &cb
)) {
576 psi_ffi_callback_dtor(cb
);
585 static inline struct psi_ffi_impl_info
*psi_ffi_impl_init(struct psi_impl
*impl
,
586 struct psi_context
*C
) {
587 struct psi_ffi_context
*context
= C
->context
;
588 struct psi_ffi_impl_info
*info
= calloc(1, sizeof(*info
));
589 struct psi_let_stmt
*let
;
595 rc
= psi_ffi_prep_closure(&info
->closure
, &info
->code
,
596 &context
->signature
, psi_ffi_handler
, impl
);
603 while (psi_plist_get(impl
->stmts
.let
, l
++, &let
)) {
604 psi_ffi_callback_init(info
, let
->exp
);
607 return impl
->info
= info
;
610 static inline void psi_ffi_impl_dtor(struct psi_impl
*impl
) {
611 struct psi_ffi_impl_info
*info
= impl
->info
;
612 struct psi_let_stmt
*let
;
615 while (psi_plist_get(impl
->stmts
.let
, j
++, &let
)) {
616 psi_ffi_callback_dtor(let
->exp
);
621 psi_ffi_closure_free(info
->closure
);
628 static void psi_ffi_extvar_get(ffi_cif
*sig
, void *result
, void **args
, void *data
) {
629 struct psi_decl_extvar
*evar
= data
;
631 psi_decl_extvar_get(evar
, result
);
634 static void psi_ffi_extvar_set(ffi_cif
*sig
, void *result
, void **args
, void *data
) {
635 struct psi_decl_extvar
*evar
= data
;
637 psi_decl_extvar_set(evar
, args
[0]);
640 struct psi_ffi_extvar_info
{
644 ffi_closure
*closure
;
650 ffi_closure
*closure
;
654 static inline ffi_status
psi_ffi_extvar_init(struct psi_decl_extvar
*evar
) {
655 struct psi_ffi_extvar_info
*info
= calloc(1, sizeof(*info
));
660 psi_ffi_decl_init(evar
->getter
);
661 psi_ffi_decl_init(evar
->setter
);
663 rc
= ffi_prep_cif(&info
->get
.signature
, FFI_DEFAULT_ABI
, 0,
664 psi_ffi_decl_func_type(evar
->getter
), NULL
);
668 rc
= psi_ffi_prep_closure(&info
->get
.closure
, &info
->get
.code
,
669 &info
->get
.signature
, psi_ffi_extvar_get
, evar
);
674 info
->set
.params
[0] = psi_ffi_decl_arg_type(evar
->arg
);
675 rc
= ffi_prep_cif(&info
->set
.signature
, FFI_DEFAULT_ABI
, 1,
676 &ffi_type_void
, info
->set
.params
);
680 rc
= psi_ffi_prep_closure(&info
->set
.closure
, &info
->set
.code
,
681 &info
->set
.signature
, psi_ffi_extvar_set
, evar
);
686 evar
->getter
->sym
= info
->get
.code
;
687 evar
->setter
->sym
= info
->set
.code
;
692 static inline void psi_ffi_extvar_dtor(struct psi_decl_extvar
*evar
) {
699 static inline struct psi_ffi_context
*psi_ffi_context_init(struct psi_ffi_context
*L
) {
703 L
= malloc(sizeof(*L
));
705 memset(L
, 0, sizeof(*L
));
707 L
->params
[0] = &ffi_type_pointer
;
708 L
->params
[1] = &ffi_type_pointer
;
709 rc
= ffi_prep_cif(&L
->signature
, FFI_DEFAULT_ABI
, 2, &ffi_type_void
, L
->params
);
710 assert(rc
== FFI_OK
);
715 static inline void psi_ffi_context_free(struct psi_ffi_context
**L
) {
722 static void psi_ffi_init(struct psi_context
*C
)
724 C
->context
= psi_ffi_context_init(NULL
);
727 static void psi_ffi_dtor(struct psi_context
*C
)
731 struct psi_decl
*decl
;
733 while (psi_plist_get(C
->decls
, i
++, &decl
)) {
734 psi_ffi_decl_dtor(decl
);
740 struct psi_decl_extvar
*evar
;
742 while (psi_plist_get(C
->vars
, i
++, &evar
)) {
743 psi_ffi_extvar_dtor(evar
);
748 struct psi_impl
*impl
;
750 while (psi_plist_get(C
->impls
, i
++, &impl
)) {
751 psi_ffi_impl_dtor(impl
);
754 psi_ffi_context_free((void *) &C
->context
);
758 static zend_function_entry
*psi_ffi_compile(struct psi_context
*C
)
760 size_t i
= 0, d
= 0, v
= 0, nf
= 0;
761 struct psi_impl
*impl
;
762 struct psi_decl
*decl
;
763 struct psi_decl_extvar
*evar
;
764 zend_function_entry
*zfe
= NULL
;
766 while (psi_plist_get(C
->vars
, v
++, &evar
)) {
767 if (FFI_OK
== psi_ffi_extvar_init(evar
)) {
773 zfe
= calloc(psi_plist_count(C
->impls
) + 1, sizeof(*zfe
));
775 while (psi_plist_get(C
->impls
, i
++, &impl
)) {
776 zend_function_entry
*zf
= &zfe
[nf
];
781 if (!psi_ffi_decl_init(impl
->decl
)) {
784 if (!psi_ffi_impl_init(impl
, C
)) {
788 zf
->fname
= impl
->func
->name
+ (impl
->func
->name
[0] == '\\');
789 zf
->handler
= ((struct psi_ffi_impl_info
*) impl
->info
)->code
;
790 zf
->num_args
= psi_plist_count(impl
->func
->args
);
791 zf
->arg_info
= psi_internal_arginfo(impl
);
796 while (psi_plist_get(C
->decls
, d
++, &decl
)) {
801 psi_ffi_decl_init(decl
);
807 static inline void psi_ffi_call_ex(struct psi_call_frame
*frame
) {
808 struct psi_decl
*decl
= psi_call_frame_get_decl(frame
);
809 struct psi_impl
*impl
= psi_call_frame_get_impl(frame
);
810 struct psi_ffi_decl_info
*decl_info
= decl
->info
;
811 struct psi_ffi_impl_info
*impl_info
;
812 struct psi_call_frame
*prev
;
815 impl_info
= impl
->info
;
816 prev
= impl_info
->frame
;
817 impl_info
->frame
= frame
;
819 ffi_call(&decl_info
->signature
, FFI_FN(decl
->sym
),
820 psi_call_frame_get_rpointer(frame
),
821 psi_call_frame_get_arg_pointers(frame
));
823 impl_info
->frame
= prev
;
827 static inline void psi_ffi_call_va(struct psi_call_frame
*frame
) {
829 struct psi_call_frame
*prev
;
830 struct psi_decl
*decl
= psi_call_frame_get_decl(frame
);
831 struct psi_impl
*impl
= psi_call_frame_get_impl(frame
);
832 struct psi_ffi_decl_info
*decl_info
= decl
->info
;
833 struct psi_ffi_impl_info
*impl_info
;
834 size_t i
, va_count
, argc
;
835 ffi_type
**param_types
;
837 argc
= psi_plist_count(decl
->args
);
838 va_count
= psi_call_frame_num_var_args(frame
);
839 param_types
= ecalloc(argc
+ va_count
+ 1, sizeof(ffi_type
*));
840 memcpy(param_types
, decl_info
->params
, argc
* sizeof(ffi_type
*));
841 for (i
= 0; i
< va_count
; ++i
) {
842 struct psi_call_frame_argument
*frame_arg
;
844 frame_arg
= psi_call_frame_get_var_argument(frame
, i
);
845 param_types
[argc
+ i
] = psi_ffi_impl_type(frame_arg
->va_type
);
848 psi_ffi_prep_va(&decl_info
->signature
, &signature
, argc
, va_count
, param_types
);
851 impl_info
= impl
->info
;
852 prev
= impl_info
->frame
;
853 impl_info
->frame
= frame
;
855 ffi_call(&signature
, FFI_FN(decl
->sym
),
856 psi_call_frame_get_rpointer(frame
),
857 psi_call_frame_get_arg_pointers(frame
));
859 impl_info
->frame
= prev
;
865 static void psi_ffi_call(struct psi_call_frame
*frame
) {
866 if (psi_call_frame_num_var_args(frame
)) {
867 psi_ffi_call_va(frame
);
869 psi_ffi_call_ex(frame
);
873 static void *psi_ffi_query(struct psi_context
*C
, enum psi_context_query q
, void *arg
) {
875 case PSI_CONTEXT_QUERY_SELF
:
877 case PSI_CONTEXT_QUERY_TYPE
:
878 return psi_ffi_impl_type(*(token_t
*) arg
);
883 static ZEND_RESULT_CODE
psi_ffi_load()
886 ffi_type
*i128
, *u128
;
888 i128
= calloc(1, 3*sizeof(ffi_type
));
889 i128
->type
= FFI_TYPE_STRUCT
;
891 i128
->elements
= (ffi_type
**) (i128
+ 1);
892 i128
->elements
[0] = &ffi_type_sint64
;
893 i128
->elements
[1] = &ffi_type_sint64
;
895 ffi_type_sint128
= i128
;
897 u128
= calloc(1, 3*sizeof(ffi_type
));
898 u128
->type
= FFI_TYPE_STRUCT
;
900 u128
->elements
= (ffi_type
**) (u128
+ 1);
901 u128
->elements
[0] = &ffi_type_uint64
;
902 u128
->elements
[1] = &ffi_type_uint64
;
904 ffi_type_uint128
= u128
;
909 static void psi_ffi_free()
912 free(ffi_type_sint128
);
913 free(ffi_type_uint128
);
917 static struct psi_context_ops ops
= {
927 struct psi_context_ops
*psi_libffi_ops(void)
932 #endif /* HAVE_LIBFFI */