From: Michael Wallner Date: Tue, 17 Nov 2015 14:06:29 +0000 (+0100) Subject: flush X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=commitdiff_plain;h=d560a27ff8431c678d25ecf4d8190b562a766f41 flush --- diff --git a/config.m4 b/config.m4 index d83fb73..71ac862 100644 --- a/config.m4 +++ b/config.m4 @@ -202,7 +202,7 @@ if test "$PHP_PSI" != "no"; then AC_DEFUN(PSI_STRUCT, [ AC_CHECK_SIZEOF($1, [], PSI_INCLUDES_DEFAULT($4)) psi_struct_name=`echo $1 | cut -d" " -f2` - psi_struct_size=$AS_TR_SH(ac_cv_sizeof_struct_$1) + psi_struct_size=$AS_TR_SH(ac_cv_sizeof_$1) psi_struct_members= m4_foreach(member, [$2], [ AC_CHECK_MEMBER($1.member, [ @@ -649,10 +649,10 @@ if test "$PHP_PSI" != "no"; then PSI_MACRO(S_ISREG, int, [(mode_t m)], [(m)], sys/stat.h) PSI_MACRO(S_ISLNK, int, [(mode_t m)], [(m)], sys/stat.h) PSI_MACRO(S_ISSOCK, int, [(mode_t m)], [(m)], sys/stat.h) - PSI_MACRO(S_TYPEISMQ, int, [(mode_t m)], [(m)], sys/stat.h) - PSI_MACRO(S_TYPEISSEM, int, [(mode_t m)], [(m)], sys/stat.h) - PSI_MACRO(S_TYPEISSHM, int, [(mode_t m)], [(m)], sys/stat.h) - PSI_MACRO(S_TYPEISTMO, int, [(mode_t m)], [(m)], sys/stat.h) + PSI_MACRO(S_TYPEISMQ, int, [(struct stat *s)], [(s)], sys/stat.h) + PSI_MACRO(S_TYPEISSEM, int, [(struct stat *s)], [(s)], sys/stat.h) + PSI_MACRO(S_TYPEISSHM, int, [(struct stat *s)], [(s)], sys/stat.h) + PSI_MACRO(S_TYPEISTMO, int, [(struct stat *s)], [(s)], sys/stat.h) dnl sys/time.h PSI_STRUCT(struct timeval, [ [tv_sec], @@ -751,7 +751,7 @@ if test "$PHP_PSI" != "no"; then AC_DEFINE_UNQUOTED(PHP_PSI_CONSTS, $PSI_CONSTS, Predefined constants) AC_DEFINE_UNQUOTED(PHP_PSI_STRUCTS, $PSI_STRUCTS, Predefined structs) - AC_DEFINE_UNQUOTED(PHP_PSI_SHLIB_SUFFIX, $SHLIB_SUFFIX_NAME, DL suffix) + AC_DEFINE_UNQUOTED(PHP_PSI_SHLIB_SUFFIX, ["]$SHLIB_SUFFIX_NAME["], DL suffix) PHP_PSI_SRCDIR=PHP_EXT_SRCDIR(psi) PHP_PSI_BUILDDIR=PHP_EXT_BUILDDIR(psi) diff --git a/src/context.c b/src/context.c index c431618..18e76e4 100644 --- a/src/context.c +++ b/src/context.c @@ -482,34 +482,59 @@ static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) { } return 1; } +static inline decl *locate_free_decl(decls *decls, free_call *f) { + size_t i; + + for (i = 0; i < decls->count; ++i) { + if (!strcmp(decls->list[i]->func->var->name, f->func)) { + f->decl = decls->list[i]; + return decls->list[i]; + } + } + return NULL; +} static inline int validate_impl_free_stmts(PSI_Data *data, impl *impl) { - size_t i, j, k; + size_t i, j, k, l; /* we can have any count of free stmts; freeing any out vars */ for (i = 0; i < impl->stmts->fre.count; ++i) { free_stmt *fre = impl->stmts->fre.list[i]; - for (j = 0; j < fre->vars->count; ++j) { - decl_var *free_var = fre->vars->vars[j]; - int check = 0; + for (j = 0; j < fre->calls->count; ++j) { + free_call *free_call = fre->calls->list[j]; - if (!strcmp(free_var->name, impl->decl->func->var->name)) { - continue; + /* first find the decl of the free func */ + if (!locate_free_decl(data->decls, free_call)) { + data->error(PSI_WARNING, "Unknown function '%s' in `free` statement" + " of implementation '%s'", free_call->func, impl->func->name); + return 0; + } + if (!impl->decl->args) { + data->error(PSI_WARNING, "Declaration '%s' of implementation '%s'" + " does not have any arguments to free", + impl->decl->func->var->name, impl->func->name); } - if (impl->decl->args) for (k = 0; k < impl->decl->args->count; ++k) { - decl_arg *free_arg = impl->decl->args->args[k]; - if (!strcmp(free_var->name, free_arg->var->name)) { - check = 1; - free_var->arg = free_arg; - break; + /* now check for known vars */ + for (l = 0; l < free_call->vars->count; ++l) { + int check = 0; + decl_var *free_var = free_call->vars->vars[l]; + + for (k = 0; k < impl->decl->args->count; ++k) { + decl_arg *free_arg = impl->decl->args->args[k]; + + if (!strcmp(free_var->name, free_arg->var->name)) { + check = 1; + free_var->arg = free_arg; + break; + } } - } - if (!check) { - data->error(PSI_WARNING, "Unknown variable '%s' of `free` statement" - " of implementation '%s'", - free_var->name, impl->func->name); - return 0; + if (!check) { + data->error(PSI_WARNING, "Unknown variable '%s' of `free` statement" + " of implementation '%s'", + free_var->name, impl->func->name); + return 0; + } } } } @@ -782,6 +807,12 @@ zend_function_entry *PSI_ContextCompile(PSI_Context *C) return C->closures = C->ops->compile(C); } + +void PSI_ContextCall(PSI_Context *C, impl_val *ret_val, decl *decl, impl_val **args) +{ + C->ops->call(C, ret_val, decl, args); +} + void PSI_ContextDtor(PSI_Context *C) { size_t i; diff --git a/src/context.h b/src/context.h index 351799b..77db31a 100644 --- a/src/context.h +++ b/src/context.h @@ -14,6 +14,7 @@ struct PSI_ContextOps { void (*init)(PSI_Context *C); void (*dtor)(PSI_Context *C); zend_function_entry *(*compile)(PSI_Context *C); + void (*call)(PSI_Context *C, impl_val *ret_val, decl *decl, impl_val **args); }; struct PSI_Context { @@ -29,6 +30,7 @@ PSI_Context *PSI_ContextInit(PSI_Context *C, PSI_ContextOps *ops, PSI_ContextErr void PSI_ContextBuild(PSI_Context *C, const char *path); int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P); zend_function_entry *PSI_ContextCompile(PSI_Context *C); +void PSI_ContextCall(PSI_Context *C, impl_val *ret_val, decl *decl, impl_val **args); void PSI_ContextDtor(PSI_Context *C); void PSI_ContextFree(PSI_Context **C); diff --git a/src/libffi.c b/src/libffi.c index 34a1598..f1d7282 100644 --- a/src/libffi.c +++ b/src/libffi.c @@ -287,10 +287,36 @@ static zend_function_entry *psi_ffi_compile(PSI_Context *C) return zfe; } +static void psi_ffi_call(PSI_Context *C, impl_val *ret_val, decl *decl, impl_val **args) { + ffi_cif signature; + ffi_type **types; + void **argps; + size_t i; + + /* FIXME: cache in decl */ + + types = calloc(decl->args->count + 1, sizeof(*types)); + argps = calloc(decl->args->count + 1, sizeof(*argps)); + for (i = 0; i < decl->args->count; ++i) { + decl_arg *darg = decl->args->args[i]; + + types[i] = psi_ffi_decl_arg_type(darg); + argps[i] = args[i]; + } + + ffi_prep_cif(&signature, psi_ffi_abi(decl->abi->convention), decl->args->count, + psi_ffi_decl_arg_type(decl->func), types); + ffi_call(&signature, FFI_FN(decl->dlptr), ret_val, argps); + + free(types); + free(argps); +} + static PSI_ContextOps ops = { psi_ffi_init, psi_ffi_dtor, psi_ffi_compile, + psi_ffi_call, }; PSI_ContextOps *PSI_Libffi(void) diff --git a/src/libjit.c b/src/libjit.c index f4f57c5..e1d6cf8 100644 --- a/src/libjit.c +++ b/src/libjit.c @@ -230,10 +230,39 @@ static zend_function_entry *psi_jit_compile(PSI_Context *C) return zfe; } +static void psi_jit_call(PSI_Context *C, impl_val *ret_val, decl *decl, impl_val **args) { + jit_type_t signature, *types; + void **argps; + size_t i; + + /* FIXME: cache in decl */ + + types = calloc(decl->args->count + 1, sizeof(*types)); + argps = calloc(decl->args->count + 1, sizeof(*argps)); + for (i = 0; i < decl->args->count; ++i) { + decl_arg *darg = decl->args->args[i]; + + types[i] = psi_jit_decl_arg_type(darg); + argps[i] = args[i]; + } + + signature = jit_type_create_signature( + psi_jit_abi(decl->abi->convention), + psi_jit_decl_arg_type(decl->func), + types, decl->args->count, 1); + jit_apply(signature, decl->dlptr, argps, decl->args->count, ret_val); + + jit_type_free(signature); + free(types); + free(argps); + +} + static PSI_ContextOps ops = { psi_jit_init, psi_jit_dtor, psi_jit_compile, + psi_jit_call, }; PSI_ContextOps *PSI_Libjit(void) diff --git a/src/module.c b/src/module.c index 508fdea..811d4e4 100644 --- a/src/module.c +++ b/src/module.c @@ -616,15 +616,20 @@ void psi_do_return(zval *return_value, return_stmt *ret, impl_val *ret_val) void psi_do_free(free_stmt *fre) { - size_t i; + size_t i, j; + impl_val dummy, *argps[0x20]; + + for (i = 0; i < fre->calls->count; ++i) { + free_call *f = fre->calls->list[i]; - for (i = 0; i < fre->vars->count; ++i) { - decl_var *dvar = fre->vars->vars[i]; + for (j = 0; j < f->vars->count; ++j) { + decl_var *dvar = f->vars->vars[j]; + decl_arg *darg = dvar->arg; - if (dvar->arg && dvar->arg->let->out.ptr) { - free(dvar->arg->let->out.ptr); - dvar->arg->let->out.ptr = NULL; + argps[j] = &darg->let->out; } + + PSI_ContextCall(&PSI_G(context), &dummy, f->decl, argps); } } diff --git a/src/parser.h b/src/parser.h index 6dcd6bf..67252e2 100644 --- a/src/parser.h +++ b/src/parser.h @@ -674,19 +674,68 @@ static inline void free_return_stmt(return_stmt *ret) { free(ret); } -typedef struct free_stmt { +typedef struct free_call { + char *func; decl_vars *vars; + decl *decl; +} free_call; + +static inline free_call *init_free_call(const char *func, decl_vars *vars) { + free_call *f = calloc(1, sizeof(*f)); + f->func = strdup(func); + f->vars = vars; + return f; +} + +static inline void free_free_call(free_call *f) { + free(f->func); + free(f); +} + +typedef struct free_calls { + free_call **list; + size_t count; +} free_calls; + +static inline free_calls *init_free_calls(free_call *f) { + free_calls *fcs = calloc(1, sizeof(*fcs)); + if (f) { + fcs->count = 1; + fcs->list = calloc(1, sizeof(*fcs->list)); + fcs->list[0] = f; + } + return fcs; +} + +static inline void free_free_calls(free_calls *fcs) { + size_t i; + + for (i = 0; i < fcs->count; ++i) { + free_free_call(fcs->list[i]); + } + free(fcs->list); + free(fcs); +} + +static inline free_calls *add_free_call(free_calls *fcs, free_call *f) { + fcs->list = realloc(fcs->list, ++fcs->count * sizeof(*fcs->list)); + fcs->list[fcs->count-1] = f; + return fcs; +} + +typedef struct free_stmt { + free_calls *calls; } free_stmt; -static inline free_stmt *init_free_stmt(decl_vars *vars) { - free_stmt *free_ = calloc(1, sizeof(*free_)); - free_->vars = vars; - return free_; +static inline free_stmt *init_free_stmt(free_calls *calls) { + free_stmt *f = calloc(1, sizeof(*f)); + f->calls = calls; + return f; } -static inline void free_free_stmt(free_stmt *free_) { - free_decl_vars(free_->vars); - free(free_); +static inline void free_free_stmt(free_stmt *f) { + free_free_calls(f->calls); + free(f); } typedef struct impl_stmt { diff --git a/src/parser_proc.y b/src/parser_proc.y index a189a88..32cba5d 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -16,6 +16,7 @@ /* TOKEN is defined inside syntax_error */ %syntax_error { PSI_ParserSyntaxError(P, P->psi.file.fn, P->line, "Unexpected token '%s'", TOKEN->text); + TOKEN->type = PSI_T_NAME; } %nonassoc NAME. @@ -457,8 +458,23 @@ return_stmt(ret) ::= RETURN set_value(val) EOS. { %type free_stmt {free_stmt*} %destructor free_stmt {free_free_stmt($$);} -free_stmt(free) ::= FREE decl_vars(vars) EOS. { - free = init_free_stmt(vars); +free_stmt(free) ::= FREE free_calls(calls) EOS. { + free = init_free_stmt(calls); +} + +%type free_calls {free_calls*} +%destructor free_calls {free_free_calls($$);} +free_calls(calls) ::= free_call(call). { + calls = init_free_calls(call); +} +free_calls(calls) ::= free_calls(calls_) COMMA free_call(call). { + calls = add_free_call(calls_, call); +} + +%type free_call {free_call*} +%destructor free_call {free_free_call($$);} +free_call(call) ::= NAME(F) LPAREN decl_vars(vars) RPAREN. { + call = init_free_call(F->text, vars); } %type impl_type {impl_type*} diff --git a/tests/idn/idn.psi b/tests/idn/idn.psi index 845335b..2bed911 100644 --- a/tests/idn/idn.psi +++ b/tests/idn/idn.psi @@ -27,7 +27,7 @@ function idn\utf8_to_ascii(string $host, string &$result, int $flags = 0) : int let flags = intval($flags); set $result = to_string(*buffer); return to_int(idna_to_ascii_8z); - free *buffer; + free free(buffer); } default char *idna_strerror(int rc); function idn\strerror(int $rc) : string {