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"
35 static inline jit_type_t
psi_jit_decl_arg_type(struct psi_decl_arg
*darg
);
37 static inline jit_type_t
psi_jit_token_type(token_t t
)
46 return jit_type_sbyte
;
48 return jit_type_ubyte
;
50 return jit_type_short
;
52 return jit_type_ushort
;
60 return jit_type_ulong
;
62 return jit_type_sys_bool
;
65 return jit_type_sys_int
;
67 return jit_type_sys_long
;
69 return jit_type_sys_float
;
71 return jit_type_sys_double
;
72 #ifdef HAVE_LONG_DOUBLE
73 case PSI_T_LONG_DOUBLE
:
74 return jit_type_sys_long_double
;
78 return jit_type_void_ptr
;
81 static inline jit_type_t
psi_jit_impl_type(token_t impl_type
)
85 return jit_type_sbyte
;
89 return jit_type_void_ptr
;
92 return jit_type_sys_double
;
93 EMPTY_SWITCH_DEFAULT_CASE()
99 struct psi_jit_struct_type
{
104 static void psi_jit_struct_type_dtor(void *ptr
)
106 struct psi_jit_struct_type
*type
= ptr
;
107 unsigned i
, n
= jit_type_num_fields(type
->strct
);
109 for (i
= 0; i
< n
; ++i
) {
110 jit_type_free(jit_type_get_field(type
->strct
, i
));
112 jit_type_free(type
->strct
);
117 static size_t psi_jit_struct_type_pad(jit_type_t
*els
, size_t padding
)
121 for (i
= 0; i
< padding
; ++i
) {
122 *els
++ = jit_type_copy(jit_type_sys_char
);
128 static unsigned psi_jit_struct_type_elements(struct psi_decl_struct
*strct
,
131 size_t i
= 0, argc
= psi_plist_count(strct
->args
), nels
= 0, offset
= 0,
132 maxalign
= 0, last_arg_pos
= -1;
133 struct psi_decl_arg
*darg
;
136 *fields
= calloc(argc
+ 1, sizeof(*fields
));
138 while (psi_plist_get(strct
->args
, i
++, &darg
)) {
140 size_t padding
, alignment
;
142 if (darg
->layout
->pos
== last_arg_pos
) {
143 /* skip bit fields */
146 last_arg_pos
= darg
->layout
->pos
;
148 type
= jit_type_copy(psi_jit_decl_arg_type(darg
));
150 if ((alignment
= jit_type_get_alignment(type
)) > maxalign
) {
151 maxalign
= alignment
;
154 assert(jit_type_get_size(type
) <= darg
->layout
->len
);
155 if ((padding
= psi_offset_padding(darg
->layout
->pos
- offset
, alignment
))) {
156 if (nels
+ padding
> argc
) {
158 tmp
= realloc(*fields
, (argc
+ 1) * sizeof(*fields
));
166 psi_jit_struct_type_pad(&(*fields
)[nels
], padding
);
170 assert(offset
== darg
->layout
->pos
);
172 offset
= (offset
+ darg
->layout
->len
+ alignment
- 1)
174 (*fields
)[nels
++] = type
;
177 /* apply struct alignment padding */
178 offset
= (offset
+ maxalign
- 1) & ~(maxalign
- 1);
180 assert(offset
<= strct
->size
);
181 if (offset
< strct
->size
) {
182 nels
+= psi_jit_struct_type_pad(&(*fields
)[nels
], strct
->size
- offset
);
187 static inline jit_type_t
psi_jit_decl_type(struct psi_decl_type
*type
)
189 struct psi_decl_type
*real
= psi_decl_type_get_real(type
);
191 switch (real
->type
) {
193 if (!real
->real
.strct
->engine
.type
) {
195 struct psi_jit_struct_type
*type
= calloc(1, sizeof(*type
));
197 count
= psi_jit_struct_type_elements(real
->real
.strct
, &type
->fields
);
198 type
->strct
= jit_type_create_struct(type
->fields
, count
, 0);
200 real
->real
.strct
->engine
.type
= type
;
201 real
->real
.strct
->engine
.dtor
= psi_jit_struct_type_dtor
;
204 return ((struct psi_jit_struct_type
*) real
->real
.strct
->engine
.type
)->strct
;
208 struct psi_decl_arg
*arg
;
209 psi_plist_get(real
->real
.unn
->args
, 0, &arg
);
210 return psi_jit_decl_arg_type(arg
);
214 return psi_jit_token_type(real
->type
);
217 static inline jit_type_t
psi_jit_decl_arg_type(struct psi_decl_arg
*darg
)
219 if (darg
->var
->pointer_level
) {
220 return jit_type_void_ptr
;
222 return psi_jit_decl_type(darg
->type
);
226 static inline jit_abi_t
psi_jit_abi(const char *convention
)
228 if (!strcasecmp(convention
, "stdcall")) {
229 return jit_abi_stdcall
;
231 if (!strcasecmp(convention
, "fastcall")) {
232 return jit_abi_fastcall
;
234 return jit_abi_cdecl
;
237 struct psi_jit_context
{
239 jit_type_t signature
;
242 struct psi_jit_impl_info
{
243 struct psi_context
*context
;
244 struct psi_call_frame
*frame
;
249 struct psi_jit_callback_info
{
250 struct psi_jit_impl_info
*impl_info
;
251 struct psi_let_exp
*let_exp
;
256 struct psi_jit_decl_info
{
257 jit_type_t signature
;
261 static inline struct psi_jit_decl_info
*psi_jit_decl_init(struct psi_decl
*decl
) {
263 size_t i
, c
= psi_plist_count(decl
->args
);
264 struct psi_decl_arg
*arg
;
265 struct psi_jit_decl_info
*info
= calloc(1, sizeof(*info
) + 2 * c
* sizeof(void *));
267 for (i
= 0; psi_plist_get(decl
->args
, i
, &arg
); ++i
) {
268 info
->params
[i
] = psi_jit_decl_arg_type(arg
);
270 info
->params
[c
] = NULL
;
272 info
->signature
= jit_type_create_signature(
273 psi_jit_abi(decl
->abi
->convention
),
274 psi_jit_decl_arg_type(decl
->func
),
275 (jit_type_t
*) info
->params
,
278 if (!info
->signature
) {
288 static inline void psi_jit_decl_dtor(struct psi_decl
*decl
) {
290 struct psi_jit_decl_info
*info
= decl
->info
;
292 jit_type_free(info
->signature
);
298 static void psi_jit_handler(jit_type_t sig
, void *result
, void **args
, void *data
)
300 struct psi_impl
*impl
= data
;
301 struct psi_jit_impl_info
*info
= impl
->info
;
303 psi_context_call(info
->context
, *(zend_execute_data
**)args
[0], *(zval
**) args
[1], impl
);
306 static void psi_jit_callback(jit_type_t sig
, void *result
, void **args
, void *data
)
308 struct psi_jit_callback_info
*cb_info
= data
;
309 struct psi_call_frame_callback cb_data
;
311 assert(cb_info
->impl_info
->frame
);
313 cb_data
.cb
= cb_info
->let_exp
;
314 cb_data
.argc
= jit_type_num_params(sig
);
316 cb_data
.rval
= result
;
318 psi_call_frame_do_callback(cb_info
->impl_info
->frame
, &cb_data
);
321 static inline void psi_jit_callback_init(struct psi_jit_impl_info
*impl_info
,
322 struct psi_let_exp
*let_exp
)
324 struct psi_jit_context
*context
= impl_info
->context
->context
;
325 struct psi_jit_callback_info
*cb_info
;
326 struct psi_jit_decl_info
*decl_info
;
327 struct psi_let_callback
*cb
;
328 struct psi_let_func
*fn
= NULL
;
330 switch (let_exp
->kind
) {
331 case PSI_LET_CALLBACK
:
332 cb
= let_exp
->data
.callback
;
333 if (cb
->decl
->info
) {
334 decl_info
= cb
->decl
->info
;
336 decl_info
= psi_jit_decl_init(cb
->decl
);
339 cb_info
= calloc(1, sizeof(*cb_info
));
340 cb_info
->impl_info
= impl_info
;
341 cb_info
->let_exp
= let_exp
;
342 cb_info
->closure
= jit_closure_create(context
->jit
, decl_info
->signature
,
343 &psi_jit_callback
, cb_info
);
345 if (!cb_info
->closure
) {
351 assert(!cb
->decl
->sym
);
352 cb
->decl
->sym
= cb_info
->closure
;
358 fn
= let_exp
->data
.func
;
362 struct psi_let_exp
*inner_let
;
364 while (psi_plist_get(fn
->inner
, i
++, &inner_let
)) {
365 psi_jit_callback_init(impl_info
, inner_let
);
374 static inline void psi_jit_callback_dtor(struct psi_let_exp
*let_exp
) {
375 struct psi_let_callback
*cb
;
376 struct psi_let_func
*fn
= NULL
;
378 switch (let_exp
->kind
) {
379 case PSI_LET_CALLBACK
:
380 cb
= let_exp
->data
.callback
;
382 psi_jit_decl_dtor(cb
->decl
);
385 struct psi_jit_callback_info
*info
= cb
->info
;
388 /* The memory for the closure will be reclaimed when the context is destroyed.
389 free(info->closure); */
398 fn
= let_exp
->data
.func
;
403 struct psi_let_exp
*cb
;
405 while (psi_plist_get(fn
->inner
, i
++, &cb
)) {
406 psi_jit_callback_dtor(cb
);
415 static inline struct psi_jit_impl_info
*psi_jit_impl_init(struct psi_impl
* impl
,
416 struct psi_context
*C
)
418 struct psi_jit_context
*context
= C
->context
;
419 struct psi_jit_impl_info
*info
= calloc(1, sizeof(*info
));
420 struct psi_let_stmt
*let
;
424 info
->closure
= jit_closure_create(context
->jit
, context
->signature
,
425 &psi_jit_handler
, impl
);
427 if (!info
->closure
) {
432 while (psi_plist_get(impl
->stmts
.let
, l
++, &let
)) {
433 psi_jit_callback_init(info
, let
->exp
);
436 return impl
->info
= info
;
440 static inline void psi_jit_impl_dtor(struct psi_impl
*impl
) {
441 struct psi_jit_impl_info
*info
= impl
->info
;
442 struct psi_let_stmt
*let
;
445 while (psi_plist_get(impl
->stmts
.let
, j
++, &let
)) {
446 psi_jit_callback_dtor(let
->exp
);
451 /* The memory for the closure will be reclaimed when the context is destroyed.
452 free(info->closure); */
459 static inline struct psi_jit_context
*psi_jit_context_init(
460 struct psi_jit_context
*L
)
462 jit_type_t params
[] = {jit_type_void_ptr
, jit_type_void_ptr
};
465 L
= malloc(sizeof(*L
));
467 memset(L
, 0, sizeof(*L
));
469 L
->jit
= jit_context_create();
470 L
->signature
= jit_type_create_signature(jit_abi_cdecl
, jit_type_void
,
476 static inline void psi_jit_context_dtor(struct psi_jit_context
*L
)
478 jit_type_free(L
->signature
);
479 jit_context_destroy(L
->jit
);
482 static inline void psi_jit_context_free(struct psi_jit_context
**L
)
485 psi_jit_context_dtor(*L
);
491 static void psi_jit_init(struct psi_context
*C
)
493 C
->context
= psi_jit_context_init(NULL
);
496 static void psi_jit_dtor(struct psi_context
*C
)
500 struct psi_decl
*decl
;
502 while (psi_plist_get(C
->decls
, i
++, &decl
)) {
503 psi_jit_decl_dtor(decl
);
508 struct psi_impl
*impl
;
510 while (psi_plist_get(C
->impls
, i
++, &impl
)) {
511 psi_jit_impl_dtor(impl
);
514 psi_jit_context_free((void *) &C
->context
);
517 static zend_function_entry
*psi_jit_compile(struct psi_context
*C
)
519 size_t i
= 0, d
= 0, nf
= 0;
520 struct psi_impl
*impl
;
521 struct psi_decl
*decl
;
522 zend_function_entry
*zfe
;
523 struct psi_jit_context
*ctx
= C
->context
;
529 zfe
= calloc(psi_plist_count(C
->impls
) + 1, sizeof(*zfe
));
530 jit_context_build_start(ctx
->jit
);
532 while (psi_plist_get(C
->impls
, i
++, &impl
)) {
533 zend_function_entry
*zf
= &zfe
[nf
];
538 if (!psi_jit_decl_init(impl
->decl
)) {
541 if (!psi_jit_impl_init(impl
, C
)) {
545 zf
->fname
= impl
->func
->name
+ (impl
->func
->name
[0] == '\\');
546 zf
->handler
= ((struct psi_jit_impl_info
*) impl
->info
)->closure
;
547 zf
->num_args
= psi_plist_count(impl
->func
->args
);
548 zf
->arg_info
= psi_internal_arginfo(impl
);
552 while (psi_plist_get(C
->decls
, d
++, &decl
)) {
557 psi_jit_decl_init(decl
);
560 jit_context_build_end(ctx
->jit
);
565 static inline void psi_jit_call_ex(struct psi_call_frame
*frame
) {
566 struct psi_decl
*decl
= psi_call_frame_get_decl(frame
);
567 struct psi_impl
*impl
= psi_call_frame_get_impl(frame
);
568 struct psi_jit_decl_info
*decl_info
= decl
->info
;
569 struct psi_jit_impl_info
*impl_info
;
570 struct psi_call_frame
*prev
;
573 impl_info
= impl
->info
;
574 prev
= impl_info
->frame
;
575 impl_info
->frame
= frame
;
577 jit_apply(decl_info
->signature
, decl
->sym
,
578 psi_call_frame_get_arg_pointers(frame
), psi_plist_count(decl
->args
),
579 psi_call_frame_get_rpointer(frame
));
581 impl_info
->frame
= prev
;
585 static inline void psi_jit_call_va(struct psi_call_frame
*frame
) {
586 jit_type_t signature
;
587 struct psi_call_frame
*prev
;
588 struct psi_decl
*decl
= psi_call_frame_get_decl(frame
);
589 struct psi_impl
*impl
= psi_call_frame_get_impl(frame
);
590 struct psi_jit_decl_info
*decl_info
= decl
->info
;
591 struct psi_jit_impl_info
*impl_info
;
592 size_t i
, va_count
, argc
;
593 jit_type_t
*param_types
;
595 argc
= psi_plist_count(decl
->args
);
596 va_count
= psi_call_frame_num_var_args(frame
);
597 param_types
= ecalloc(argc
+ va_count
+ 1, sizeof(jit_type_t
));
598 memcpy(param_types
, decl_info
->params
, argc
* sizeof(jit_type_t
));
599 for (i
= 0; i
< va_count
; ++i
) {
600 struct psi_call_frame_argument
*frame_arg
;
602 frame_arg
= psi_call_frame_get_var_argument(frame
, i
);
603 param_types
[argc
+ i
] = psi_jit_impl_type(frame_arg
->va_type
);
606 signature
= jit_type_create_signature(jit_abi_vararg
,
607 jit_type_get_return(decl_info
->signature
),
608 param_types
, argc
+ va_count
,
613 impl_info
= impl
->info
;
614 prev
= impl_info
->frame
;
615 impl_info
->frame
= frame
;
617 jit_apply(signature
, decl
->sym
,
618 psi_call_frame_get_arg_pointers(frame
), argc
,
619 psi_call_frame_get_rpointer(frame
));
621 impl_info
->frame
= prev
;
624 jit_type_free(signature
);
629 static void psi_jit_call(struct psi_call_frame
*frame
) {
630 if (psi_call_frame_num_var_args(frame
)) {
631 psi_jit_call_va(frame
);
633 psi_jit_call_ex(frame
);
637 static void *psi_jit_query(struct psi_context
*C
, enum psi_context_query q
,
641 case PSI_CONTEXT_QUERY_SELF
:
643 case PSI_CONTEXT_QUERY_TYPE
:
644 return psi_jit_impl_type(*(token_t
*) arg
);
649 static struct psi_context_ops ops
= {
657 struct psi_context_ops
*psi_libjit_ops(void)
662 #endif /* HAVE_LIBJIT */