3 #include "parser_proc.h"
5 static void init(PSI_Context
*C
)
7 C
->opaque
= jit_context_create();
10 static void dtor(PSI_Context
*C
)
12 jit_context_destroy(C
->opaque
);
15 typedef struct PSI_ClosureData
{
22 static inline PSI_ClosureData
*PSI_ClosureDataAlloc(void *context
, impl
*impl
) {
23 PSI_ClosureData
*data
= malloc(sizeof(*data
));
25 data
->context
= context
;
31 static inline size_t impl_num_min_args(impl
*impl
) {
32 size_t i
, n
= impl
->func
->args
->count
;
34 for (i
= 0; i
< impl
->func
->args
->count
; ++i
) {
35 if (impl
->func
->args
->args
[i
]->def
) {
42 static inline jit_abi_t
psi_jit_abi(const char *convention
) {
45 static inline jit_type_t
psi_jit_type(token_t t
) {
50 return jit_type_sbyte
;
52 return jit_type_ubyte
;
54 return jit_type_short
;
56 return jit_type_ushort
;
64 return jit_type_ulong
;
66 return jit_type_sys_bool
;
68 return jit_type_sys_char
;
70 return jit_type_sys_short
;
72 return jit_type_sys_int
;
74 return jit_type_sys_long
;
76 return jit_type_sys_float
;
78 return jit_type_sys_double
;
83 static inline jit_type_t
psi_jit_decl_type(decl_type
*type
) {
84 return psi_jit_type(real_decl_type(type
)->type
);
86 static inline jit_type_t
psi_jit_decl_arg_type(decl_arg
*darg
) {
87 if (darg
->var
->pointer_level
) {
88 return jit_type_void_ptr
;
90 return psi_jit_decl_type(darg
->type
);
93 static void handler(jit_type_t _sig
, void *result
, void **_args
, void *_data
)
95 zend_execute_data
*execute_data
= *(zend_execute_data
**)_args
[0];
96 zval
*return_value
= *(zval
**)_args
[1];
97 PSI_ClosureData
*data
= _data
;
100 void **arg_ptr
= NULL
, **arg_prm
= NULL
;
101 impl_val ret_val
, *arg_val
= NULL
;
102 jit_type_t signature
, *sig_prm
;
104 if (!data
->impl
->func
->args
->count
) {
105 if (SUCCESS
!= zend_parse_parameters_none()) {
109 ZEND_PARSE_PARAMETERS_START(impl_num_min_args(data
->impl
), data
->impl
->func
->args
->count
)
111 iarg
= data
->impl
->func
->args
->args
[_i
];
115 if (PSI_T_BOOL
== iarg
->type
->type
) {
117 iarg
->val
.bval
= iarg
->def
->type
== PSI_T_TRUE
? 1 : 0;
119 Z_PARAM_BOOL(iarg
->val
.bval
);
120 } else if (PSI_T_INT
== iarg
->type
->type
) {
122 iarg
->val
.lval
= zend_atol(iarg
->def
->text
, strlen(iarg
->def
->text
));
124 Z_PARAM_LONG(iarg
->val
.lval
);
125 } else if (PSI_T_FLOAT
== iarg
->type
->type
) {
127 iarg
->val
.dval
= zend_strtod(iarg
->def
->text
, NULL
);
129 Z_PARAM_DOUBLE(iarg
->val
.dval
);
130 } else if (PSI_T_STRING
== iarg
->type
->type
) {
133 iarg
->val
.str
.len
= strlen(iarg
->def
->text
) - 2;
134 iarg
->val
.str
.val
= &iarg
->def
->text
[1];
136 Z_PARAM_STRING(iarg
->val
.str
.val
, iarg
->val
.str
.len
);
138 error_code
= ZPP_ERROR_FAILURE
;
142 if (_i
< _max_num_args
) {
145 ZEND_PARSE_PARAMETERS_END();
147 if (data
->impl
->decl
->args
->count
) {
148 arg_ptr
= malloc(data
->impl
->decl
->args
->count
* sizeof(*arg_ptr
));
149 arg_prm
= malloc(data
->impl
->decl
->args
->count
* sizeof(*arg_prm
));
150 arg_val
= malloc(data
->impl
->decl
->args
->count
* sizeof(*arg_val
));
151 sig_prm
= malloc(data
->impl
->decl
->args
->count
* sizeof(*sig_prm
));
153 for (i
= 0; i
< data
->impl
->decl
->args
->count
; ++i
) {
154 decl_arg
*darg
= data
->impl
->decl
->args
->args
[i
];
155 impl_arg
*iarg
= darg
->let
->arg
;
157 switch (darg
->let
->val
->func
->type
) {
159 if (iarg
->type
->type
== PSI_T_BOOL
) {
160 arg_val
[i
].bval
= iarg
->val
.bval
;
162 arg_val
[i
].bval
= zend_is_true(iarg
->_zv
);
166 if (iarg
->type
->type
== PSI_T_INT
) {
167 arg_val
[i
].lval
= iarg
->val
.lval
;
169 arg_val
[i
].lval
= zval_get_long(iarg
->_zv
);
173 if (iarg
->type
->type
== PSI_T_STRING
) {
174 arg_val
[i
].str
.val
= estrndup(iarg
->val
.str
.val
, iarg
->val
.str
.len
);
176 zend_string
*zs
= zval_get_string(iarg
->_zv
);
177 arg_val
[i
].str
.val
= estrndup(zs
->val
, zs
->len
);
178 zend_string_release(zs
);
182 if (iarg
->type
->type
== PSI_T_STRING
) {
183 arg_val
[i
].lval
=iarg
->val
.str
.len
;
185 zend_string
*zs
= zval_get_string(iarg
->_zv
);
186 arg_val
[i
].lval
= zs
->len
;
187 zend_string_release(zs
);
191 arg_ptr
[i
] = &arg_val
[i
];
192 arg_prm
[i
] = darg
->let
->val
->is_reference
? &arg_ptr
[i
] : arg_ptr
[i
];
193 sig_prm
[i
] = psi_jit_decl_arg_type(darg
);
197 signature
= jit_type_create_signature(
198 psi_jit_abi(data
->impl
->decl
->abi
->convention
),
199 psi_jit_decl_arg_type(data
->impl
->decl
->func
),
201 data
->impl
->decl
->args
->count
,
203 jit_apply(signature
, data
->impl
->decl
->dlptr
, arg_prm
, data
->impl
->decl
->args
->count
, &ret_val
);
205 switch (data
->impl
->stmts
->ret
.list
[0]->func
->type
) {
206 case PSI_T_TO_STRING
:
207 if (data
->impl
->decl
->func
->var
->pointer_level
) {
208 switch (real_decl_type(data
->impl
->decl
->func
->type
)->type
) {
212 RETVAL_STRING(ret_val
.str
.val
);
220 static zend_function_entry
*compile(PSI_Context
*C
, PSI_Data
*D
)
223 jit_type_t signature
, params
[] = {
227 zend_function_entry
*zfe
= calloc(D
->impls
->count
+ 1, sizeof(*zfe
));
229 jit_context_build_start(C
->opaque
);
231 for (i
= 0; i
< D
->impls
->count
; ++i
) {
232 zend_function_entry
*zf
;
233 PSI_ClosureData
*data
;
235 if (!D
->impls
->list
[i
]->decl
) {
240 data
= PSI_ClosureDataAlloc(C
, D
->impls
->list
[i
]);
241 signature
= jit_type_create_signature(jit_abi_cdecl
, jit_type_void
, params
, 2, 1);
242 zf
->fname
= D
->impls
->list
[i
]->func
->name
+ (D
->impls
->list
[i
]->func
->name
[0] == '\\');
243 zf
->handler
= jit_closure_create(C
->opaque
, signature
, &handler
, data
);
246 jit_context_build_end(C
->opaque
);
251 static PSI_ContextOps ops
= {
257 PSI_ContextOps
*PSI_Libjit(void)