f2821ca5cc78ff4aed4a580b40dbf92edc62b054
6 #include <Zend/zend_API.h>
10 PSI_Compiler
*PSI_CompilerInit(PSI_Compiler
*C
, PSI_Validator
*V
, void *context
)
13 C
= malloc(sizeof(*C
));
15 memset(C
, 0, sizeof(*C
));
17 PSI_DataExchange((PSI_Data
*) C
, (PSI_Data
*) V
);
24 void PSI_CompilerDtor(PSI_Compiler
*C
)
26 PSI_DataDtor((PSI_Data
*) C
);
29 void PSI_Compiler_Free(PSI_Compiler
**C
)
38 typedef struct PSI_ClosureData
{
45 static inline PSI_ClosureData
*PSI_ClosureDataAlloc(void *context
, impl
*impl
) {
46 PSI_ClosureData
*data
= malloc(sizeof(*data
));
48 data
->context
= context
;
54 static inline size_t impl_num_min_args(impl
*impl
) {
55 size_t i
, n
= impl
->func
->args
->count
;
57 for (i
= 0; i
< impl
->func
->args
->count
; ++i
) {
58 if (impl
->func
->args
->args
[i
]->def
) {
65 static inline jit_abi_t
psi_jit_abi(const char *convention
) {
68 static inline jit_type_t
psi_jit_type(token_t t
) {
73 return jit_type_sbyte
;
75 return jit_type_ubyte
;
77 return jit_type_short
;
79 return jit_type_ushort
;
87 return jit_type_ulong
;
89 return jit_type_sys_bool
;
91 return jit_type_sys_char
;
93 return jit_type_sys_short
;
95 return jit_type_sys_int
;
97 return jit_type_sys_long
;
99 return jit_type_sys_float
;
101 return jit_type_sys_double
;
106 static inline jit_type_t
psi_jit_decl_type(decl_type
*type
) {
107 return psi_jit_type(real_decl_type(type
)->type
);
109 static inline jit_type_t
psi_jit_decl_arg_type(decl_arg
*darg
) {
110 if (darg
->var
->pointer_level
) {
111 return jit_type_void_ptr
;
113 return psi_jit_decl_type(darg
->type
);
116 static void psi_jit_closure_handler(jit_type_t _sig
, void *result
, void **_args
, void *_data
)
118 zend_execute_data
*execute_data
= *(zend_execute_data
**)_args
[0];
119 zval
*return_value
= *(zval
**)_args
[1];
120 PSI_ClosureData
*data
= _data
;
123 void **arg_ptr
= NULL
, **arg_prm
= NULL
;
124 impl_val ret_val
, *arg_val
= NULL
;
125 jit_type_t signature
, *sig_prm
;
127 if (!data
->impl
->func
->args
->count
) {
128 if (SUCCESS
!= zend_parse_parameters_none()) {
132 ZEND_PARSE_PARAMETERS_START(impl_num_min_args(data
->impl
), data
->impl
->func
->args
->count
)
134 iarg
= data
->impl
->func
->args
->args
[_i
];
138 if (PSI_T_BOOL
== iarg
->type
->type
) {
140 iarg
->val
.bval
= iarg
->def
->type
== PSI_T_TRUE
? 1 : 0;
142 Z_PARAM_BOOL(iarg
->val
.bval
);
143 } else if (PSI_T_INT
== iarg
->type
->type
) {
145 iarg
->val
.lval
= zend_atol(iarg
->def
->text
, strlen(iarg
->def
->text
));
147 Z_PARAM_LONG(iarg
->val
.lval
);
148 } else if (PSI_T_FLOAT
== iarg
->type
->type
) {
150 iarg
->val
.dval
= zend_strtod(iarg
->def
->text
, NULL
);
152 Z_PARAM_DOUBLE(iarg
->val
.dval
);
153 } else if (PSI_T_STRING
== iarg
->type
->type
) {
156 iarg
->val
.str
.len
= strlen(iarg
->def
->text
) - 2;
157 iarg
->val
.str
.val
= &iarg
->def
->text
[1];
159 Z_PARAM_STRING(iarg
->val
.str
.val
, iarg
->val
.str
.len
);
161 error_code
= ZPP_ERROR_FAILURE
;
165 if (_i
< _max_num_args
) {
168 ZEND_PARSE_PARAMETERS_END();
170 if (data
->impl
->decl
->args
->count
) {
171 arg_ptr
= malloc(data
->impl
->decl
->args
->count
* sizeof(*arg_ptr
));
172 arg_prm
= malloc(data
->impl
->decl
->args
->count
* sizeof(*arg_prm
));
173 arg_val
= malloc(data
->impl
->decl
->args
->count
* sizeof(*arg_val
));
174 sig_prm
= malloc(data
->impl
->decl
->args
->count
* sizeof(*sig_prm
));
176 for (i
= 0; i
< data
->impl
->decl
->args
->count
; ++i
) {
177 decl_arg
*darg
= data
->impl
->decl
->args
->args
[i
];
178 impl_arg
*iarg
= darg
->let
->arg
;
180 switch (darg
->let
->val
->func
->type
) {
182 if (iarg
->type
->type
== PSI_T_BOOL
) {
183 arg_val
[i
].bval
= iarg
->val
.bval
;
185 arg_val
[i
].bval
= zend_is_true(iarg
->_zv
);
189 if (iarg
->type
->type
== PSI_T_INT
) {
190 arg_val
[i
].lval
= iarg
->val
.lval
;
192 arg_val
[i
].lval
= zval_get_long(iarg
->_zv
);
196 if (iarg
->type
->type
== PSI_T_STRING
) {
197 arg_val
[i
].str
.val
= estrndup(iarg
->val
.str
.val
, iarg
->val
.str
.len
);
199 zend_string
*zs
= zval_get_string(iarg
->_zv
);
200 arg_val
[i
].str
.val
= estrndup(zs
->val
, zs
->len
);
201 zend_string_release(zs
);
205 if (iarg
->type
->type
== PSI_T_STRING
) {
206 arg_val
[i
].lval
=iarg
->val
.str
.len
;
208 zend_string
*zs
= zval_get_string(iarg
->_zv
);
209 arg_val
[i
].lval
= zs
->len
;
210 zend_string_release(zs
);
214 arg_ptr
[i
] = &arg_val
[i
];
215 arg_prm
[i
] = darg
->let
->val
->is_reference
? &arg_ptr
[i
] : arg_ptr
[i
];
216 sig_prm
[i
] = psi_jit_decl_arg_type(darg
);
220 signature
= jit_type_create_signature(
221 psi_jit_abi(data
->impl
->decl
->abi
->convention
),
222 psi_jit_decl_arg_type(data
->impl
->decl
->func
),
224 data
->impl
->decl
->args
->count
,
226 jit_apply(signature
, data
->impl
->decl
->dlptr
, arg_prm
, data
->impl
->decl
->args
->count
, &ret_val
);
228 switch (data
->impl
->stmts
->ret
.list
[0]->func
->type
) {
229 case PSI_T_TO_STRING
:
230 if (data
->impl
->decl
->func
->var
->pointer_level
) {
231 switch (real_decl_type(data
->impl
->decl
->func
->type
)->type
) {
235 RETVAL_STRING(ret_val
.str
.val
);
243 zend_function_entry
*PSI_CompilerCompile(PSI_Compiler
*C
)
246 jit_type_t signature
, params
[] = {
250 zend_function_entry
*zfe
= calloc(C
->impls
->count
+ 1, sizeof(*zfe
));
252 for (i
= 0; i
< C
->impls
->count
; ++i
) {
253 zend_function_entry
*zf
;
254 PSI_ClosureData
*data
;
256 if (!C
->impls
->list
[i
]->decl
) {
261 data
= PSI_ClosureDataAlloc(C
->context
, C
->impls
->list
[i
]);
262 signature
= jit_type_create_signature(jit_abi_vararg
, jit_type_void
, params
, 2, 1);
263 zf
->fname
= C
->impls
->list
[i
]->func
->name
+ (C
->impls
->list
[i
]->func
->name
[0] == '\\');
264 zf
->handler
= jit_closure_create(C
->context
, signature
, &psi_jit_closure_handler
, data
);