flush
authorMichael Wallner <mike@php.net>
Tue, 17 Nov 2015 14:06:29 +0000 (15:06 +0100)
committerMichael Wallner <mike@php.net>
Tue, 17 Nov 2015 14:06:29 +0000 (15:06 +0100)
config.m4
src/context.c
src/context.h
src/libffi.c
src/libjit.c
src/module.c
src/parser.h
src/parser_proc.y
tests/idn/idn.psi

index d83fb73..71ac862 100644 (file)
--- 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)
index c431618..18e76e4 100644 (file)
@@ -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;
index 351799b..77db31a 100644 (file)
@@ -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);
 
index 34a1598..f1d7282 100644 (file)
@@ -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)
index f4f57c5..e1d6cf8 100644 (file)
@@ -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)
index 508fdea..811d4e4 100644 (file)
@@ -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);
        }
 }
 
index 6dcd6bf..67252e2 100644 (file)
@@ -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 {
index a189a88..32cba5d 100644 (file)
@@ -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*}
index 845335b..2bed911 100644 (file)
@@ -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 {