7 static void handler(ffi_cif
*signature
, void *_result
, void **_args
, void *_data
);
9 static inline ffi_abi
psi_ffi_abi(const char *convention
) {
10 return FFI_DEFAULT_ABI
;
12 static inline ffi_type
*psi_ffi_type(token_t t
) {
18 return &ffi_type_void
;
20 return &ffi_type_sint8
;
22 return &ffi_type_uint8
;
24 return &ffi_type_sint16
;
26 return &ffi_type_uint16
;
28 return &ffi_type_sint32
;
30 return &ffi_type_uint32
;
32 return &ffi_type_sint64
;
34 return &ffi_type_uint64
;
36 return &ffi_type_uchar
;
38 return &ffi_type_schar
;
40 return &ffi_type_sshort
;
42 return &ffi_type_sint
;
44 return &ffi_type_slong
;
46 return &ffi_type_float
;
48 return &ffi_type_double
;
51 static inline ffi_type
*psi_ffi_decl_type(decl_type
*type
) {
52 return psi_ffi_type(real_decl_type(type
)->type
);
54 static inline ffi_type
*psi_ffi_decl_arg_type(decl_arg
*darg
) {
55 if (darg
->var
->pointer_level
) {
56 return &ffi_type_pointer
;
58 return psi_ffi_decl_type(darg
->type
);
62 typedef struct PSI_LibffiContext
{
66 struct PSI_LibffiData
**list
;
71 typedef struct PSI_LibffiData
{
72 PSI_LibffiContext
*context
;
74 zend_internal_arg_info
*arginfo
;
81 static inline PSI_LibffiData
*PSI_LibffiDataAlloc(PSI_LibffiContext
*context
, impl
*impl
) {
83 size_t i
, c
= impl
->decl
->args
->count
;
84 PSI_LibffiData
*data
= malloc(sizeof(*data
) + c
* sizeof(ffi_type
*));
86 data
->context
= context
;
88 data
->arginfo
= psi_internal_arginfo(impl
);
89 for (i
= 0; i
< c
; ++i
) {
90 data
->params
[i
] = psi_ffi_decl_arg_type(impl
->decl
->args
->args
[i
]);
92 data
->params
[c
] = NULL
;
96 psi_ffi_abi(data
->impl
->decl
->abi
->convention
),
98 psi_ffi_decl_arg_type(data
->impl
->decl
->func
),
100 ZEND_ASSERT(FFI_OK
== rc
);
101 data
->closure
= ffi_closure_alloc(sizeof(ffi_closure
), &data
->code
);
102 rc
= ffi_prep_closure_loc(
108 ZEND_ASSERT(FFI_OK
== rc
);
110 context
->data
.list
= realloc(context
->data
.list
, ++context
->data
.count
* sizeof(*context
->data
.list
));
111 context
->data
.list
[context
->data
.count
-1] = data
;
116 static inline void PSI_LibffiDataFree(PSI_LibffiData
*data
) {
118 ffi_closure_free(data
->closure
);
122 static inline PSI_LibffiContext
*PSI_LibffiContextInit(PSI_LibffiContext
*L
) {
126 L
= malloc(sizeof(*L
));
128 memset(L
, 0, sizeof(*L
));
130 L
->params
[0] = &ffi_type_pointer
;
131 L
->params
[1] = &ffi_type_pointer
;
132 rc
= ffi_prep_cif(&L
->signature
, FFI_DEFAULT_ABI
, 2, &ffi_type_void
, L
->params
);
133 ZEND_ASSERT(rc
== FFI_OK
);
138 static inline void PSI_LibffiContextDtor(PSI_LibffiContext
*L
) {
141 for (i
= 0; i
< L
->data
.count
; ++i
) {
142 PSI_LibffiDataFree(L
->data
.list
[i
]);
149 static inline void PSI_LibffiContextFree(PSI_LibffiContext
**L
) {
151 PSI_LibffiContextDtor(*L
);
157 static void handler(ffi_cif
*_sig
, void *_result
, void **_args
, void *_data
)
159 PSI_LibffiData
*data
= _data
;
161 void **arg_ptr
= NULL
, **arg_prm
= NULL
;
164 if (SUCCESS
!= psi_parse_args(*(zend_execute_data
**)_args
[0], data
->impl
)) {
168 if (data
->impl
->decl
->args
->count
) {
169 arg_ptr
= malloc(data
->impl
->decl
->args
->count
* sizeof(*arg_ptr
));
170 arg_prm
= malloc(data
->impl
->decl
->args
->count
* sizeof(*arg_prm
));
172 for (i
= 0; i
< data
->impl
->decl
->args
->count
; ++i
) {
173 decl_arg
*darg
= data
->impl
->decl
->args
->args
[i
];
175 arg_ptr
[i
] = psi_do_let(darg
);
176 arg_prm
[i
] = darg
->let
->val
->is_reference
? &arg_ptr
[i
] : arg_ptr
[i
];
178 darg
->let
->ptr
= arg_ptr
[i
];
182 ffi_call(&data
->signature
, FFI_FN(data
->impl
->decl
->dlptr
), &ret_val
, arg_prm
);
184 psi_do_return(data
->impl
, &ret_val
, *(zval
**)_args
[1]);
186 for (i
= 0; i
< data
->impl
->stmts
->set
.count
; ++i
) {
187 set_stmt
*set
= data
->impl
->stmts
->set
.list
[i
];
189 psi_do_set(set
->arg
->_zv
, set
->val
->func
, set
->val
->vars
);
192 for (i
= 0; i
< data
->impl
->stmts
->fre
.count
; ++i
) {
193 free_stmt
*fre
= data
->impl
->stmts
->fre
.list
[i
];
198 psi_do_clean(data
->impl
);
208 static void init(PSI_Context
*C
)
210 C
->context
= PSI_LibffiContextInit(NULL
);
213 static void dtor(PSI_Context
*C
)
215 PSI_LibffiContextFree((void *) &C
->context
);
218 static zend_function_entry
*compile(PSI_Context
*C
, PSI_Data
*D
)
221 zend_function_entry
*zfe
= calloc(D
->impls
->count
+ 1, sizeof(*zfe
));
222 PSI_LibffiContext
*ctx
= C
->context
;
224 for (i
= 0; i
< D
->impls
->count
; ++i
) {
225 zend_function_entry
*zf
= &zfe
[j
];
226 PSI_LibffiData
*data
;
228 if (!D
->impls
->list
[i
]->decl
) {
232 data
= PSI_LibffiDataAlloc(ctx
, D
->impls
->list
[i
]);
233 zf
->fname
= D
->impls
->list
[i
]->func
->name
+ (D
->impls
->list
[i
]->func
->name
[0] == '\\');
234 zf
->num_args
= D
->impls
->list
[i
]->func
->args
->count
;
235 zf
->handler
= data
->code
;
236 zf
->arg_info
= data
->arginfo
;
243 static PSI_ContextOps ops
= {
249 PSI_ContextOps
*PSI_Libffi(void)