X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Fcompiler.c;fp=src%2Fcompiler.c;h=f2821ca5cc78ff4aed4a580b40dbf92edc62b054;hp=5e5ebde9e7e2b1073126ec321dc728b47603e19b;hb=9c72f6584bd95dd6e9c7dcb314a6583f7130362f;hpb=3bca631112f4865510ea91c85e8c820c4465fc14 diff --git a/src/compiler.c b/src/compiler.c index 5e5ebde..f2821ca 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -38,6 +38,8 @@ void PSI_Compiler_Free(PSI_Compiler **C) 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) { @@ -60,12 +62,67 @@ static inline size_t impl_num_min_args(impl *impl) { return n; } -static void psi_jit_closure_handler(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 = *(zend_execute_data **)args[0]; - zval *return_value = *(zval **)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()) { @@ -85,12 +142,12 @@ static void psi_jit_closure_handler(jit_type_t signature, void *result, void **a 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) { @@ -104,8 +161,83 @@ static void psi_jit_closure_handler(jit_type_t signature, void *result, void **a 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) @@ -119,19 +251,17 @@ zend_function_entry *PSI_CompilerCompile(PSI_Compiler *C) for (i = 0; i < C->impls->count; ++i) { zend_function_entry *zf; - volatile PSI_ClosureData *data; + PSI_ClosureData *data; if (!C->impls->list[i]->decl) { continue; } - signature = jit_type_create_signature(jit_abi_vararg, jit_type_void, params, 2, 1); zf = &zfe[j++]; data = PSI_ClosureDataAlloc(C->context, C->impls->list[i]); - zf->fname = C->impls->list[i]->func->name; + 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); - fprintf(stderr, "Compiled closure for %s\n", zf->fname); - printf("Closuredata: %p of closure %p\n", data, zf->handler); } return zfe;