3 #include "parser_proc.h"
8 static void init(PSI_Context
*C
)
10 C
->context
= jit_context_create();
13 static void dtor(PSI_Context
*C
)
15 jit_context_destroy(C
->context
);
19 static inline size_t impl_num_min_args(impl
*impl
) {
20 size_t i
, n
= impl
->func
->args
->count
;
22 for (i
= 0; i
< impl
->func
->args
->count
; ++i
) {
23 if (impl
->func
->args
->args
[i
]->def
) {
30 static inline jit_abi_t
psi_jit_abi(const char *convention
) {
33 static inline jit_type_t
psi_jit_type(token_t t
) {
41 return jit_type_sbyte
;
43 return jit_type_ubyte
;
45 return jit_type_short
;
47 return jit_type_ushort
;
55 return jit_type_ulong
;
57 return jit_type_sys_bool
;
59 return jit_type_sys_char
;
61 return jit_type_sys_short
;
63 return jit_type_sys_int
;
65 return jit_type_sys_long
;
67 return jit_type_sys_float
;
69 return jit_type_sys_double
;
72 static inline jit_type_t
psi_jit_decl_type(decl_type
*type
) {
73 return psi_jit_type(real_decl_type(type
)->type
);
75 static inline jit_type_t
psi_jit_decl_arg_type(decl_arg
*darg
) {
76 if (darg
->var
->pointer_level
) {
77 return jit_type_void_ptr
;
79 return psi_jit_decl_type(darg
->type
);
83 typedef struct PSI_ClosureData
{
90 static inline PSI_ClosureData
*PSI_ClosureDataAlloc(void *context
, impl
*impl
) {
91 size_t i
, c
= impl
->decl
->args
->count
;
92 PSI_ClosureData
*data
= malloc(sizeof(*data
) + (c
? c
-1 : c
) * sizeof(jit_type_t
));
94 data
->context
= context
;
96 for (i
= 0; i
< c
; ++i
) {
97 data
->params
[i
] = psi_jit_decl_arg_type(impl
->decl
->args
->args
[i
]);
99 data
->signature
= jit_type_create_signature(
100 psi_jit_abi(data
->impl
->decl
->abi
->convention
),
101 psi_jit_decl_arg_type(data
->impl
->decl
->func
),
103 data
->impl
->decl
->args
->count
,
109 static inline impl_val
*deref(unsigned level
, impl_val
*ret_val
, decl_arg
*darg
) {
112 for (i
= level
; i
< darg
->var
->pointer_level
; ++i
&& ret_val
->ptr
) {
113 ret_val
= *(void **)ret_val
;
118 static void to_int(impl_val
*ret_val
, decl_arg
*func
, zval
*return_value
) {
119 switch (real_decl_type(func
->type
)->type
) {
122 RETVAL_DOUBLE(deref(0, ret_val
, func
)->dval
);
123 convert_to_long(return_value
);
126 RETVAL_LONG(deref(0, ret_val
, func
)->lval
);
129 static void to_string(impl_val
*ret_val
, decl_arg
*func
, zval
*return_value
) {
130 switch (real_decl_type(func
->type
)->type
) {
134 if (!func
->var
->pointer_level
) {
135 char chr
= ret_val
->lval
;
136 RETVAL_STRINGL(&chr
, 1);
138 ret_val
= deref(1, ret_val
, func
);
140 RETVAL_STRING(ret_val
->ptr
);
142 RETVAL_EMPTY_STRING();
148 RETVAL_DOUBLE(deref(0, ret_val
, func
)->dval
);
149 convert_to_string(return_value
);
152 RETVAL_LONG(deref(0, ret_val
, func
)->lval
);
153 convert_to_string(return_value
);
158 static ZEND_RESULT_CODE
handle_args(zend_execute_data
*execute_data
, impl
*impl
) {
161 if (!impl
->func
->args
->count
) {
162 return zend_parse_parameters_none();
165 ZEND_PARSE_PARAMETERS_START(impl_num_min_args(impl
), impl
->func
->args
->count
)
167 iarg
= impl
->func
->args
->args
[_i
];
171 if (PSI_T_BOOL
== iarg
->type
->type
) {
173 iarg
->val
.cval
= iarg
->def
->type
== PSI_T_TRUE
? 1 : 0;
175 Z_PARAM_BOOL(iarg
->val
.cval
);
176 } else if (PSI_T_INT
== iarg
->type
->type
) {
178 iarg
->val
.lval
= zend_atol(iarg
->def
->text
, strlen(iarg
->def
->text
));
180 Z_PARAM_LONG(iarg
->val
.lval
);
181 } else if (PSI_T_FLOAT
== iarg
->type
->type
) {
183 iarg
->val
.dval
= zend_strtod(iarg
->def
->text
, NULL
);
185 Z_PARAM_DOUBLE(iarg
->val
.dval
);
186 } else if (PSI_T_STRING
== iarg
->type
->type
) {
187 struct {char *val
; size_t len
;} str
;
190 str
.len
= strlen(iarg
->def
->text
) - 2;
191 str
.val
= &iarg
->def
->text
[1];
193 Z_PARAM_STR_EX(iarg
->val
.str
, 1, 0);
195 zend_string_addref(iarg
->val
.str
);
196 } else if (iarg
->def
) {
197 iarg
->val
.str
= zend_string_init(str
.val
, str
.len
, 0);
200 error_code
= ZPP_ERROR_FAILURE
;
204 if (_i
< _max_num_args
) {
207 ZEND_PARSE_PARAMETERS_END_EX(return FAILURE
);
212 static impl_val
*handle_let(decl_arg
*darg
, impl_arg
*iarg
) {
213 impl_val
*arg_val
= &darg
->let
->out
;
217 memset(arg_val
, 0, sizeof(*arg_val
));
220 switch (darg
->let
->val
->func
->type
) {
222 if (iarg
->type
->type
== PSI_T_BOOL
) {
223 arg_val
->cval
= iarg
->val
.cval
;
225 arg_val
->cval
= zend_is_true(iarg
->_zv
);
229 if (iarg
->type
->type
== PSI_T_INT
) {
230 arg_val
->lval
= iarg
->val
.lval
;
232 arg_val
->lval
= zval_get_long(iarg
->_zv
);
236 if (iarg
->type
->type
== PSI_T_STRING
) {
237 arg_val
->ptr
= estrdup(iarg
->val
.str
->val
);
238 darg
->let
->mem
= arg_val
->ptr
;
239 zend_string_release(iarg
->val
.str
);
241 zend_string
*zs
= zval_get_string(iarg
->_zv
);
242 arg_val
->ptr
= estrdup(zs
->val
);
243 darg
->let
->mem
= arg_val
->ptr
;
244 zend_string_release(zs
);
248 if (iarg
->type
->type
== PSI_T_STRING
) {
249 arg_val
->lval
= iarg
->val
.str
->len
;
250 zend_string_release(iarg
->val
.str
);
252 zend_string
*zs
= zval_get_string(iarg
->_zv
);
253 arg_val
->lval
= zs
->len
;
254 zend_string_release(zs
);
257 EMPTY_SWITCH_DEFAULT_CASE();
263 static void handle_rval(impl
*impl
, impl_val
*ret_val
, zval
*return_value
) {
264 switch (impl
->stmts
->ret
.list
[0]->func
->type
) {
265 case PSI_T_TO_STRING
:
266 to_string(ret_val
, impl
->decl
->func
, return_value
);
269 to_int(ret_val
, impl
->decl
->func
, return_value
);
271 EMPTY_SWITCH_DEFAULT_CASE();
275 static void handle_set(zval
*return_value
, set_func
*func
, decl_vars
*vars
) {
276 impl_val
*val
= &vars
->vars
[0]->arg
->let
->ptr
;
278 ZVAL_DEREF(return_value
);
279 zval_dtor(return_value
);
281 switch (func
->type
) {
282 case PSI_T_TO_STRING
:
283 to_string(val
, vars
->vars
[0]->arg
, return_value
);
285 EMPTY_SWITCH_DEFAULT_CASE();
289 static void handle_free(free_stmt
*fre
) {
292 for (i
= 0; i
< fre
->vars
->count
; ++i
) {
293 decl_var
*dvar
= fre
->vars
->vars
[i
];
295 if (dvar
->arg
&& dvar
->arg
->let
->out
.ptr
) {
296 free(dvar
->arg
->let
->out
.ptr
);
297 dvar
->arg
->let
->out
.ptr
= NULL
;
302 static void handler(jit_type_t _sig
, void *result
, void **_args
, void *_data
)
304 PSI_ClosureData
*data
= _data
;
306 void **arg_ptr
= NULL
, **arg_prm
= NULL
;
309 if (SUCCESS
!= handle_args(*(zend_execute_data
**)_args
[0], data
->impl
)) {
313 if (data
->impl
->decl
->args
->count
) {
314 arg_ptr
= malloc(data
->impl
->decl
->args
->count
* sizeof(*arg_ptr
));
315 arg_prm
= malloc(data
->impl
->decl
->args
->count
* sizeof(*arg_prm
));
317 for (i
= 0; i
< data
->impl
->decl
->args
->count
; ++i
) {
318 decl_arg
*darg
= data
->impl
->decl
->args
->args
[i
];
319 impl_arg
*iarg
= darg
->let
? darg
->let
->arg
: NULL
;
321 arg_ptr
[i
] = handle_let(darg
, iarg
);
322 arg_prm
[i
] = darg
->let
->val
->is_reference
? &arg_ptr
[i
] : arg_ptr
[i
];
324 darg
->let
->ptr
= arg_ptr
[i
];
328 jit_apply(data
->signature
, data
->impl
->decl
->dlptr
, arg_prm
, data
->impl
->decl
->args
->count
, &ret_val
);
330 handle_rval(data
->impl
, &ret_val
, *(zval
**)_args
[1]);
332 for (i
= 0; i
< data
->impl
->stmts
->set
.count
; ++i
) {
333 set_stmt
*set
= data
->impl
->stmts
->set
.list
[i
];
335 handle_set(set
->arg
->_zv
, set
->val
->func
, set
->val
->vars
);
338 if (data
->impl
->decl
->args
->count
) {
339 for (i
= 0; i
< data
->impl
->decl
->args
->count
; ++i
) {
340 decl_arg
*darg
= data
->impl
->decl
->args
->args
[i
];
342 if (darg
->let
&& darg
->let
->mem
) {
343 efree(darg
->let
->mem
);
344 darg
->let
->mem
= NULL
;
351 for (i
= 0; i
< data
->impl
->stmts
->fre
.count
; ++i
) {
352 free_stmt
*fre
= data
->impl
->stmts
->fre
.list
[i
];
358 static inline int fill_type_hint(impl_type
*type
) {
359 switch (type
->type
) {
377 static inline zend_internal_arg_info
*fill_arginfo(impl
*impl
) {
379 zend_internal_arg_info
*aip
;
380 zend_internal_function_info
*fi
;
382 aip
= calloc(impl
->func
->args
->count
+ 1, sizeof(*aip
));
384 fi
= (zend_internal_function_info
*) &aip
[0];
385 fi
->required_num_args
= impl_num_min_args(impl
);
386 fi
->return_reference
= impl
->func
->return_reference
;
387 fi
->type_hint
= fill_type_hint(impl
->func
->return_type
);
389 for (i
= 0; i
< impl
->func
->args
->count
; ++i
) {
390 impl_arg
*iarg
= impl
->func
->args
->args
[i
];
391 zend_internal_arg_info
*ai
= &aip
[i
+1];
393 ai
->name
= iarg
->var
->name
;
394 ai
->type_hint
= fill_type_hint(iarg
->type
);
395 if (iarg
->var
->reference
) {
396 ai
->pass_by_reference
= 1;
398 if (iarg
->var
->reference
|| (iarg
->def
&& iarg
->def
->type
== PSI_T_NULL
)) {
406 static zend_function_entry
*compile(PSI_Context
*C
, PSI_Data
*D
)
409 jit_type_t signature
, params
[] = {
413 zend_function_entry
*zfe
= calloc(D
->impls
->count
+ 1, sizeof(*zfe
));
415 jit_context_build_start(C
->context
);
417 for (i
= 0; i
< D
->impls
->count
; ++i
) {
418 zend_function_entry
*zf
= &zfe
[j
];
419 PSI_ClosureData
*data
;
421 if (!D
->impls
->list
[i
]->decl
) {
425 data
= PSI_ClosureDataAlloc(C
, D
->impls
->list
[i
]);
426 signature
= jit_type_create_signature(jit_abi_cdecl
, jit_type_void
, params
, 2, 1);
427 zf
->fname
= D
->impls
->list
[i
]->func
->name
+ (D
->impls
->list
[i
]->func
->name
[0] == '\\');
428 zf
->handler
= jit_closure_create(C
->context
, signature
, &handler
, data
);
429 zf
->num_args
= D
->impls
->list
[i
]->func
->args
->count
;
430 zf
->arg_info
= fill_arginfo(D
->impls
->list
[i
]);
434 jit_context_build_end(C
->context
);
439 static PSI_ContextOps ops
= {
445 PSI_ContextOps
*PSI_Libjit(void)