X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Fcompiler.c;h=f2821ca5cc78ff4aed4a580b40dbf92edc62b054;hp=e075a398d9ed3f9005ee4034d1639375e6af19ea;hb=9c72f6584bd95dd6e9c7dcb314a6583f7130362f;hpb=f1a387482a9270a34ae684109ad8be7c104148d6 diff --git a/src/compiler.c b/src/compiler.c index e075a39..f2821ca 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -3,11 +3,11 @@ #include #include -#include +#include #include "compiler.h" -PSI_Compiler *PSI_CompilerInit(PSI_Compiler *C, PSI_Validator *V) +PSI_Compiler *PSI_CompilerInit(PSI_Compiler *C, PSI_Validator *V, void *context) { if (!C) { C = malloc(sizeof(*C)); @@ -15,13 +15,42 @@ PSI_Compiler *PSI_CompilerInit(PSI_Compiler *C, PSI_Validator *V) memset(C, 0, sizeof(*C)); PSI_DataExchange((PSI_Data *) C, (PSI_Data *) V); + + C->context = context; + return C; } +void PSI_CompilerDtor(PSI_Compiler *C) +{ + PSI_DataDtor((PSI_Data *) C); +} + +void PSI_Compiler_Free(PSI_Compiler **C) +{ + if (*C) { + PSI_CompilerDtor(*C); + free(*C); + *C = NULL; + } +} + typedef struct PSI_ClosureData { + void *context; impl *impl; + jit_type_t signature; + zval return_value; } PSI_ClosureData; +static inline PSI_ClosureData *PSI_ClosureDataAlloc(void *context, impl *impl) { + PSI_ClosureData *data = malloc(sizeof(*data)); + + data->context = context; + data->impl = impl; + + return data; +} + static inline size_t impl_num_min_args(impl *impl) { size_t i, n = impl->func->args->count; @@ -32,12 +61,68 @@ static inline size_t impl_num_min_args(impl *impl) { } return n; } -void PSI_Closure(jit_type_t signature, void *result, void **args, void *user_data) + +static inline jit_abi_t psi_jit_abi(const char *convention) { + return jit_abi_cdecl; +} +static inline jit_type_t psi_jit_type(token_t t) { + switch (t) { + case PSI_T_VOID: + return jit_type_void; + case PSI_T_SINT8: + return jit_type_sbyte; + case PSI_T_UINT8: + return jit_type_ubyte; + case PSI_T_SINT16: + return jit_type_short; + case PSI_T_UINT16: + return jit_type_ushort; + case PSI_T_SINT32: + return jit_type_int; + case PSI_T_UINT32: + return jit_type_uint; + case PSI_T_SINT64: + return jit_type_long; + case PSI_T_UINT64: + return jit_type_ulong; + case PSI_T_BOOL: + return jit_type_sys_bool; + case PSI_T_CHAR: + return jit_type_sys_char; + case PSI_T_SHORT: + return jit_type_sys_short; + case PSI_T_INT: + return jit_type_sys_int; + case PSI_T_LONG: + return jit_type_sys_long; + case PSI_T_FLOAT: + return jit_type_sys_float; + case PSI_T_DOUBLE: + return jit_type_sys_double; + default: + abort(); + } +} +static inline jit_type_t psi_jit_decl_type(decl_type *type) { + return psi_jit_type(real_decl_type(type)->type); +} +static inline jit_type_t psi_jit_decl_arg_type(decl_arg *darg) { + if (darg->var->pointer_level) { + return jit_type_void_ptr; + } else { + return psi_jit_decl_type(darg->type); + } +} +static void psi_jit_closure_handler(jit_type_t _sig, void *result, void **_args, void *_data) { - zend_execute_data *execute_data = args[0]; - zval *return_value = args[1]; - PSI_ClosureData *data = user_data; + zend_execute_data *execute_data = *(zend_execute_data **)_args[0]; + zval *return_value = *(zval **)_args[1]; + PSI_ClosureData *data = _data; impl_arg *iarg; + size_t i; + void **arg_ptr = NULL, **arg_prm = NULL; + impl_val ret_val, *arg_val = NULL; + jit_type_t signature, *sig_prm; if (!data->impl->func->args->count) { if (SUCCESS != zend_parse_parameters_none()) { @@ -57,12 +142,12 @@ void PSI_Closure(jit_type_t signature, void *result, void **args, void *user_dat Z_PARAM_BOOL(iarg->val.bval); } else if (PSI_T_INT == iarg->type->type) { if (iarg->def) { - iarg->val.lval = atol(iarg->def->text); + iarg->val.lval = zend_atol(iarg->def->text, strlen(iarg->def->text)); } Z_PARAM_LONG(iarg->val.lval); } else if (PSI_T_FLOAT == iarg->type->type) { if (iarg->def) { - iarg->val.dval = strtod(iarg->def->text, NULL); + iarg->val.dval = zend_strtod(iarg->def->text, NULL); } Z_PARAM_DOUBLE(iarg->val.dval); } else if (PSI_T_STRING == iarg->type->type) { @@ -76,6 +161,108 @@ void PSI_Closure(jit_type_t signature, void *result, void **args, void *user_dat error_code = ZPP_ERROR_FAILURE; break; } - goto nextarg; + iarg->_zv = _arg; + if (_i < _max_num_args) { + goto nextarg; + } ZEND_PARSE_PARAMETERS_END(); + + if (data->impl->decl->args->count) { + arg_ptr = malloc(data->impl->decl->args->count * sizeof(*arg_ptr)); + arg_prm = malloc(data->impl->decl->args->count * sizeof(*arg_prm)); + arg_val = malloc(data->impl->decl->args->count * sizeof(*arg_val)); + sig_prm = malloc(data->impl->decl->args->count * sizeof(*sig_prm)); + + for (i = 0; i < data->impl->decl->args->count; ++i) { + decl_arg *darg = data->impl->decl->args->args[i]; + impl_arg *iarg = darg->let->arg; + + switch (darg->let->val->func->type) { + case PSI_T_BOOLVAL: + if (iarg->type->type == PSI_T_BOOL) { + arg_val[i].bval = iarg->val.bval; + } else { + arg_val[i].bval = zend_is_true(iarg->_zv); + } + break; + case PSI_T_INTVAL: + if (iarg->type->type == PSI_T_INT) { + arg_val[i].lval = iarg->val.lval; + } else { + arg_val[i].lval = zval_get_long(iarg->_zv); + } + break; + case PSI_T_STRVAL: + if (iarg->type->type == PSI_T_STRING) { + arg_val[i].str.val = estrndup(iarg->val.str.val, iarg->val.str.len); + } else { + zend_string *zs = zval_get_string(iarg->_zv); + arg_val[i].str.val = estrndup(zs->val, zs->len); + zend_string_release(zs); + } + break; + case PSI_T_STRLEN: + if (iarg->type->type == PSI_T_STRING) { + arg_val[i].lval =iarg->val.str.len; + } else { + zend_string *zs = zval_get_string(iarg->_zv); + arg_val[i].lval = zs->len; + zend_string_release(zs); + } + break; + } + arg_ptr[i] = &arg_val[i]; + arg_prm[i] = darg->let->val->is_reference ? &arg_ptr[i] : arg_ptr[i]; + sig_prm[i] = psi_jit_decl_arg_type(darg); + } + } + + signature = jit_type_create_signature( + psi_jit_abi(data->impl->decl->abi->convention), + psi_jit_decl_arg_type(data->impl->decl->func), + sig_prm, + data->impl->decl->args->count, + 1); + jit_apply(signature, data->impl->decl->dlptr, arg_prm, data->impl->decl->args->count, &ret_val); + + switch (data->impl->stmts->ret.list[0]->func->type) { + case PSI_T_TO_STRING: + if (data->impl->decl->func->var->pointer_level) { + switch (real_decl_type(data->impl->decl->func->type)->type) { + case PSI_T_CHAR: + case PSI_T_SINT8: + case PSI_T_UINT8: + RETVAL_STRING(ret_val.str.val); + break; + } + } + break; + } +} + +zend_function_entry *PSI_CompilerCompile(PSI_Compiler *C) +{ + size_t i, j = 0; + jit_type_t signature, params[] = { + jit_type_void_ptr, + jit_type_void_ptr + }; + zend_function_entry *zfe = calloc(C->impls->count + 1, sizeof(*zfe)); + + for (i = 0; i < C->impls->count; ++i) { + zend_function_entry *zf; + PSI_ClosureData *data; + + if (!C->impls->list[i]->decl) { + continue; + } + + zf = &zfe[j++]; + data = PSI_ClosureDataAlloc(C->context, C->impls->list[i]); + signature = jit_type_create_signature(jit_abi_vararg, jit_type_void, params, 2, 1); + zf->fname = C->impls->list[i]->func->name + (C->impls->list[i]->func->name[0] == '\\'); + zf->handler = jit_closure_create(C->context, signature, &psi_jit_closure_handler, data); + } + + return zfe; }