7 static void psi_jit_handler(jit_type_t _sig
, void *result
, void **_args
, void *_data
);
9 static inline jit_abi_t
psi_jit_abi(const char *convention
) {
12 static inline jit_type_t
psi_jit_type(token_t t
) {
20 return jit_type_sbyte
;
22 return jit_type_ubyte
;
24 return jit_type_short
;
26 return jit_type_ushort
;
34 return jit_type_ulong
;
36 return jit_type_sys_bool
;
38 return jit_type_sys_char
;
40 return jit_type_sys_short
;
42 return jit_type_sys_int
;
44 return jit_type_sys_long
;
46 return jit_type_sys_float
;
48 return jit_type_sys_double
;
51 static inline jit_type_t
psi_jit_decl_type(decl_type
*type
) {
52 return psi_jit_type(real_decl_type(type
)->type
);
54 static inline jit_type_t
psi_jit_decl_arg_type(decl_arg
*darg
) {
55 if (darg
->var
->pointer_level
) {
56 return jit_type_void_ptr
;
58 return psi_jit_decl_type(darg
->type
);
62 typedef struct PSI_LibjitContext
{
66 struct PSI_LibjitData
**list
;
71 typedef struct PSI_LibjitData
{
72 PSI_LibjitContext
*context
;
74 zend_internal_arg_info
*arginfo
;
80 static inline PSI_LibjitData
*PSI_LibjitDataAlloc(PSI_LibjitContext
*context
, impl
*impl
) {
81 size_t i
, c
= impl
->decl
->args
->count
;
82 PSI_LibjitData
*data
= malloc(sizeof(*data
) + (c
? c
-1 : c
) * sizeof(jit_type_t
));
84 data
->context
= context
;
86 data
->arginfo
= psi_internal_arginfo(impl
);
87 for (i
= 0; i
< c
; ++i
) {
88 data
->params
[i
] = psi_jit_decl_arg_type(impl
->decl
->args
->args
[i
]);
91 data
->signature
= jit_type_create_signature(
92 psi_jit_abi(data
->impl
->decl
->abi
->convention
),
93 psi_jit_decl_arg_type(data
->impl
->decl
->func
),
95 data
->impl
->decl
->args
->count
,
97 data
->closure
= jit_closure_create(context
->jit
, context
->signature
, &psi_jit_handler
, data
);
99 context
->data
.list
= realloc(context
->data
.list
, ++context
->data
.count
* sizeof(*context
->data
.list
));
100 context
->data
.list
[context
->data
.count
-1] = data
;
105 static inline void PSI_LibjitDataFree(PSI_LibjitData
*data
) {
107 jit_type_free(data
->signature
);
111 static inline PSI_LibjitContext
*PSI_LibjitContextInit(PSI_LibjitContext
*L
) {
112 jit_type_t params
[] = {
118 L
= malloc(sizeof(*L
));
120 memset(L
, 0, sizeof(*L
));
122 L
->jit
= jit_context_create();
123 L
->signature
= jit_type_create_signature(jit_abi_cdecl
, jit_type_void
, params
, 2, 1);
128 static inline void PSI_LibjitContextDtor(PSI_LibjitContext
*L
) {
131 for (i
= 0; i
< L
->data
.count
; ++i
) {
132 PSI_LibjitDataFree(L
->data
.list
[i
]);
137 jit_type_free(L
->signature
);
138 jit_context_destroy(L
->jit
);
141 static inline void PSI_LibjitContextFree(PSI_LibjitContext
**L
) {
143 PSI_LibjitContextDtor(*L
);
149 static void psi_jit_handler(jit_type_t _sig
, void *result
, void **_args
, void *_data
)
151 PSI_LibjitData
*data
= _data
;
153 void **arg_prm
= NULL
;
156 if (SUCCESS
!= psi_parse_args(*(zend_execute_data
**)_args
[0], data
->impl
)) {
160 if (data
->impl
->decl
->args
->count
) {
161 arg_prm
= malloc(data
->impl
->decl
->args
->count
* sizeof(*arg_prm
));
163 for (i
= 0; i
< data
->impl
->decl
->args
->count
; ++i
) {
164 decl_arg
*darg
= data
->impl
->decl
->args
->args
[i
];
166 arg_prm
[i
] = psi_do_let(darg
);
170 jit_apply(data
->signature
, data
->impl
->decl
->dlptr
, arg_prm
, data
->impl
->decl
->args
->count
, &ret_val
);
172 psi_do_return(data
->impl
, &ret_val
, *(zval
**)_args
[1]);
174 for (i
= 0; i
< data
->impl
->stmts
->set
.count
; ++i
) {
175 set_stmt
*set
= data
->impl
->stmts
->set
.list
[i
];
178 psi_do_set(set
->arg
->_zv
, set
->val
->func
, set
->val
->vars
);
182 for (i
= 0; i
< data
->impl
->stmts
->fre
.count
; ++i
) {
183 free_stmt
*fre
= data
->impl
->stmts
->fre
.list
[i
];
188 psi_do_clean(data
->impl
);
195 static void psi_jit_init(PSI_Context
*C
)
197 C
->context
= PSI_LibjitContextInit(NULL
);
200 static void psi_jit_dtor(PSI_Context
*C
)
202 PSI_LibjitContextFree((void *) &C
->context
);
205 static zend_function_entry
*psi_jit_compile(PSI_Context
*C
, PSI_Data
*D
)
208 zend_function_entry
*zfe
= calloc(D
->impls
->count
+ 1, sizeof(*zfe
));
209 PSI_LibjitContext
*ctx
= C
->context
;
211 jit_context_build_start(ctx
->jit
);
213 for (i
= 0; i
< D
->impls
->count
; ++i
) {
214 zend_function_entry
*zf
= &zfe
[j
];
215 PSI_LibjitData
*data
;
217 if (!D
->impls
->list
[i
]->decl
) {
221 data
= PSI_LibjitDataAlloc(ctx
, D
->impls
->list
[i
]);
222 zf
->fname
= D
->impls
->list
[i
]->func
->name
+ (D
->impls
->list
[i
]->func
->name
[0] == '\\');
223 zf
->num_args
= D
->impls
->list
[i
]->func
->args
->count
;
224 zf
->handler
= data
->closure
;
225 zf
->arg_info
= data
->arginfo
;
229 jit_context_build_end(ctx
->jit
);
234 static PSI_ContextOps ops
= {
240 PSI_ContextOps
*PSI_Libjit(void)