de743a1295fd7bc1ec128703d461814d61e8d154
15 static void psi_jit_handler(jit_type_t _sig
, void *_result
, void **_args
, void *_data
)
17 psi_call(*(zend_execute_data
**)_args
[0], *(zval
**)_args
[1], _data
);
20 static void psi_jit_callback(jit_type_t _sig
, void *_result
, void **_args
, void *_data
)
22 psi_callback(_data
, _result
, jit_type_num_params(_sig
), _args
);
25 static inline jit_type_t
psi_jit_decl_arg_type(decl_arg
*darg
);
27 static inline jit_abi_t
psi_jit_abi(const char *convention
) {
30 static inline jit_type_t
psi_jit_token_type(token_t t
) {
38 return jit_type_sbyte
;
40 return jit_type_ubyte
;
42 return jit_type_short
;
44 return jit_type_ushort
;
52 return jit_type_ulong
;
54 return jit_type_sys_bool
;
57 return jit_type_sys_int
;
59 return jit_type_sys_long
;
61 return jit_type_sys_float
;
63 return jit_type_sys_double
;
64 #ifdef HAVE_LONG_DOUBLE
65 case PSI_T_LONG_DOUBLE
:
66 return jit_type_sys_long_double
;
70 return jit_type_void_ptr
;
73 static inline jit_type_t
psi_jit_impl_type(token_t impl_type
) {
76 return jit_type_sbyte
;
80 return jit_type_void_ptr
;
83 return jit_type_sys_double
;
84 EMPTY_SWITCH_DEFAULT_CASE();
89 static void psi_jit_struct_type_dtor(void *type
) {
90 jit_type_t strct
= type
;
95 static size_t psi_jit_struct_type_pad(jit_type_t
*els
, size_t padding
) {
98 for (i
= 0; i
< padding
; ++i
) {
99 *els
++ = jit_type_copy(jit_type_sys_char
);
105 static unsigned psi_jit_struct_type_elements(decl_struct
*strct
, jit_type_t
**fields
) {
106 size_t i
, argc
= strct
->args
->count
, nels
= 0, offset
= 0, maxalign
;
107 *fields
= calloc(argc
+ 1, sizeof(*fields
));
109 for (i
= 0; i
< strct
->args
->count
; ++i
) {
110 decl_arg
*darg
= strct
->args
->args
[i
];
111 jit_type_t type
= jit_type_copy(psi_jit_decl_arg_type(darg
));
112 size_t padding
, alignment
;
114 ZEND_ASSERT(jit_type_get_size(type
) == darg
->layout
->len
);
116 if ((alignment
= jit_type_get_alignment(type
)) > maxalign
) {
117 maxalign
= alignment
;
120 if ((padding
= psi_offset_padding(darg
->layout
->pos
- offset
, alignment
))) {
121 if (nels
+ padding
> argc
) {
123 *fields
= realloc(*fields
, (argc
+ 1) * sizeof(*fields
));
125 psi_jit_struct_type_pad(&(*fields
)[nels
], padding
);
129 ZEND_ASSERT(offset
== darg
->layout
->pos
);
131 offset
= (offset
+ darg
->layout
->len
+ alignment
- 1) & ~(alignment
- 1);
132 (*fields
)[nels
++] = type
;
135 /* apply struct alignment padding */
136 offset
= (offset
+ maxalign
- 1) & ~(maxalign
- 1);
138 ZEND_ASSERT(offset
<= strct
->size
);
139 if (offset
< strct
->size
) {
140 nels
+= psi_jit_struct_type_pad(&(*fields
)[nels
], strct
->size
- offset
);
145 static inline jit_type_t
psi_jit_decl_type(decl_type
*type
) {
146 decl_type
*real
= real_decl_type(type
);
148 switch (real
->type
) {
150 if (!real
->real
.strct
->engine
.type
) {
152 jit_type_t strct
, *fields
= NULL
;
154 count
= psi_jit_struct_type_elements(real
->real
.strct
, &fields
);
155 strct
= jit_type_create_struct(fields
, count
, 0);
157 real
->real
.strct
->engine
.type
= strct
;
158 real
->real
.strct
->engine
.dtor
= psi_jit_struct_type_dtor
;
161 return real
->real
.strct
->engine
.type
;
164 return psi_jit_decl_arg_type(real
->real
.unn
->args
->args
[0]);
167 return psi_jit_token_type(real
->type
);
170 static inline jit_type_t
psi_jit_decl_arg_type(decl_arg
*darg
) {
171 if (darg
->var
->pointer_level
) {
172 return jit_type_void_ptr
;
174 return psi_jit_decl_type(darg
->type
);
178 struct psi_jit_context
{
180 jit_type_t signature
;
182 struct psi_jit_data
**list
;
187 struct psi_jit_call
{
189 jit_type_t signature
;
190 void *params
[1]; /* [type1, type2, NULL, arg1, arg2] ... */
193 struct psi_jit_data
{
194 struct psi_jit_context
*context
;
196 zend_internal_arg_info
*arginfo
;
199 static inline struct psi_jit_call
*psi_jit_call_alloc(struct psi_context
*C
, decl
*decl
) {
200 size_t i
, c
= decl
->args
? decl
->args
->count
: 0;
201 struct psi_jit_call
*call
= calloc(1, sizeof(*call
) + 2 * c
* sizeof(void *));
203 for (i
= 0; i
< c
; ++i
) {
204 call
->params
[i
] = psi_jit_decl_arg_type(decl
->args
->args
[i
]);
206 call
->params
[c
] = NULL
;
208 decl
->call
.info
= call
;
209 decl
->call
.rval
= &decl
->func
->ptr
;
211 decl
->call
.args
= (void **) &call
->params
[c
+1];
213 call
->signature
= jit_type_create_signature(
214 psi_jit_abi(decl
->abi
->convention
),
215 psi_jit_decl_arg_type(decl
->func
),
216 (jit_type_t
*) call
->params
, c
, 1);
217 ZEND_ASSERT(call
->signature
);
222 static inline void *psi_jit_call_init_closure(struct psi_context
*C
, struct psi_jit_call
*call
, impl
*impl
) {
223 struct psi_jit_context
*context
= C
->context
;
224 return call
->closure
= jit_closure_create(context
->jit
, context
->signature
,
225 &psi_jit_handler
, impl
);
228 static inline void *psi_jit_call_init_callback_closure(struct psi_context
*C
, struct psi_jit_call
*call
, let_callback
*cb
) {
229 struct psi_jit_context
*context
= C
->context
;
230 return call
->closure
= jit_closure_create(context
->jit
, call
->signature
,
231 &psi_jit_callback
, cb
);
234 static inline void psi_jit_call_free(struct psi_jit_call
*call
) {
235 jit_type_free(call
->signature
);
239 static inline struct psi_jit_context
*psi_jit_context_init(struct psi_jit_context
*L
) {
240 jit_type_t params
[] = {
246 L
= malloc(sizeof(*L
));
248 memset(L
, 0, sizeof(*L
));
250 L
->jit
= jit_context_create();
251 L
->signature
= jit_type_create_signature(jit_abi_cdecl
, jit_type_void
,
257 static inline void psi_jit_context_dtor(struct psi_jit_context
*L
) {
258 jit_type_free(L
->signature
);
259 jit_context_destroy(L
->jit
);
262 static inline void psi_jit_context_free(struct psi_jit_context
**L
) {
264 psi_jit_context_dtor(*L
);
270 static void psi_jit_init(struct psi_context
*C
)
272 C
->context
= psi_jit_context_init(NULL
);
275 static inline void psi_jit_destroy_callbacks(struct psi_context
*C
, let_val
*let_val
) {
279 switch (let_val
->kind
) {
280 case PSI_LET_CALLBACK
:
281 cb
= let_val
->data
.callback
;
283 if (cb
->decl
&& cb
->decl
->call
.info
) {
284 psi_jit_call_free(cb
->decl
->call
.info
);
290 fn
= let_val
->data
.func
;
296 for (i
= 0; i
< fn
->inner
->count
; ++i
) {
297 psi_jit_destroy_callbacks(C
, fn
->inner
->vals
[i
]);
306 static void psi_jit_dtor(struct psi_context
*C
)
311 for (i
= 0; i
< C
->decls
->count
; ++i
) {
312 decl
*decl
= C
->decls
->list
[i
];
314 if (decl
->call
.info
) {
315 psi_jit_call_free(decl
->call
.info
);
322 for (i
= 0; i
< C
->impls
->count
; ++i
) {
323 impl
*impl
= C
->impls
->list
[i
];
325 for (j
= 0; j
< impl
->stmts
->let
.count
; ++j
) {
326 psi_jit_destroy_callbacks(C
, impl
->stmts
->let
.list
[j
]->val
);
330 psi_jit_context_free((void *) &C
->context
);
333 static inline void psi_jit_compile_callbacks(struct psi_context
*C
, let_val
*let_val
) {
334 struct psi_jit_call
*call
;
338 switch (let_val
->kind
) {
339 case PSI_LET_CALLBACK
:
340 cb
= let_val
->data
.callback
;
341 if ((call
= psi_jit_call_alloc(C
, cb
->decl
))) {
342 if (!psi_jit_call_init_callback_closure(C
, call
, cb
)) {
343 psi_jit_call_free(call
);
347 cb
->decl
->call
.sym
= call
->closure
;
353 fn
= let_val
->data
.func
;
358 for (i
= 0; i
< fn
->inner
->count
; ++i
) {
359 psi_jit_compile_callbacks(C
, fn
->inner
->vals
[i
]);
368 static zend_function_entry
*psi_jit_compile(struct psi_context
*C
)
371 zend_function_entry
*zfe
;
372 struct psi_jit_context
*ctx
= C
->context
;
378 zfe
= calloc(C
->impls
->count
+ 1, sizeof(*zfe
));
379 jit_context_build_start(ctx
->jit
);
381 for (i
= 0; i
< C
->impls
->count
; ++i
) {
382 zend_function_entry
*zf
= &zfe
[j
];
383 struct psi_jit_call
*call
;
384 impl
*impl
= C
->impls
->list
[i
];
390 if ((call
= psi_jit_call_alloc(C
, impl
->decl
))) {
391 if (!psi_jit_call_init_closure(C
, call
, impl
)) {
392 psi_jit_call_free(call
);
397 zf
->fname
= impl
->func
->name
+ (impl
->func
->name
[0] == '\\');
398 zf
->num_args
= impl
->func
->args
->count
;
399 zf
->handler
= call
->closure
;
400 zf
->arg_info
= psi_internal_arginfo(impl
);
403 for (c
= 0; c
< impl
->stmts
->let
.count
; ++c
) {
404 psi_jit_compile_callbacks(C
, impl
->stmts
->let
.list
[c
]->val
);
408 for (i
= 0; i
< C
->decls
->count
; ++i
) {
409 decl
*decl
= C
->decls
->list
[i
];
411 if (decl
->call
.info
) {
415 psi_jit_call_alloc(C
, decl
);
418 jit_context_build_end(ctx
->jit
);
423 static void psi_jit_call(struct psi_context
*C
, decl_callinfo
*decl_call
, impl_vararg
*va
) {
424 struct psi_jit_call
*call
= decl_call
->info
;
427 jit_type_t signature
;
428 size_t i
, nfixedargs
= decl_call
->argc
, ntotalargs
= nfixedargs
+ va
->args
->count
;
429 void **params
= calloc(2 * ntotalargs
+ 2, sizeof(void *));
431 for (i
= 0; i
< nfixedargs
; ++i
) {
432 params
[i
] = call
->params
[i
];
433 params
[i
+ ntotalargs
+ 1] = call
->params
[i
+ nfixedargs
+ 1];
435 for (i
= 0; i
< va
->args
->count
; ++i
) {
436 params
[nfixedargs
+ i
] = psi_jit_impl_type(va
->types
[i
]);
437 params
[nfixedargs
+ i
+ ntotalargs
+ 1] = &va
->values
[i
];
440 signature
= jit_type_create_signature(
441 jit_type_get_abi(call
->signature
),
442 jit_type_get_return(call
->signature
),
443 (jit_type_t
*) params
, ntotalargs
, 1);
444 ZEND_ASSERT(signature
);
446 jit_apply(signature
, decl_call
->sym
, ¶ms
[ntotalargs
+ 1],
447 nfixedargs
, *decl_call
->rval
);
448 jit_type_free(signature
);
451 jit_apply(call
->signature
, decl_call
->sym
, decl_call
->args
,
452 decl_call
->argc
, *decl_call
->rval
);
456 static struct psi_context_ops ops
= {
463 struct psi_context_ops
*psi_libjit_ops(void)
468 #endif /* HAVE_LIBJIT */