flush
authorMichael Wallner <mike@php.net>
Wed, 11 Nov 2015 18:35:10 +0000 (19:35 +0100)
committerMichael Wallner <mike@php.net>
Wed, 11 Nov 2015 18:35:10 +0000 (19:35 +0100)
config.m4
php_psi.h
src/context.c
src/libffi.c
src/libjit.c
src/module.c
src/parser.h

index 6854fd20d99037ac30f6647ed461e34212922d95..647b0a9eb82faa27b7a73a56d7436d9e8006b65f 100644 (file)
--- a/config.m4
+++ b/config.m4
@@ -92,7 +92,8 @@ if test "$PHP_PSI" != "no"; then
        ])
 
        psi_type_pair() { # (type, size)
-               local psi_type_lower=`tr A-Z a-z <<<$1`
+               local psi_type_name=`tr -cd A-Za-z <<<$1` 
+               local psi_type_lower=`tr A-Z a-z <<<$psi_type_name`
                case $psi_type_lower in
                int*|uint*)
                        local psi_type_upper=`tr a-z A-Z <<<$1`
@@ -103,7 +104,7 @@ if test "$PHP_PSI" != "no"; then
                        echo "PSI_T_STRUCT, \"$2\""
                        ;;
                *)
-                       echo "PSI_T_NAME, \"$1\""
+                       echo "PSI_T_NAME, \"$psi_type_name\""
                        ;;
                esac
        }
@@ -192,7 +193,7 @@ if test "$PHP_PSI" != "no"; then
                AC_DEFINE_UNQUOTED(
                        AS_TR_CPP(offsetof_$1_$2),
                        $AS_TR_SH([ac_cv_offsetof_$1_$2]),
-                       [The offset of `$1' in `$2', as computed by offsetof.]
+                       [The offset of `$2' in `$1', as computed by offsetof.]
                )
        ])
 
@@ -200,26 +201,31 @@ if test "$PHP_PSI" != "no"; then
        PSI_STRUCTS=
        AC_DEFUN(PSI_STRUCT, [
                AC_CHECK_SIZEOF(struct $1, [], PSI_INCLUDES_DEFAULT($4))
+               psi_struct_size=$ac_cv_sizeof_struct_$1
                psi_struct_members=
                m4_foreach(member, [$2], [
                        AC_CHECK_MEMBER(struct $1.member, [
-                               case member in
-                               $3
-                               *) psi_member_type=int ;;
-                               esac
+                               psi_member_name=member
                                AC_CHECK_SIZEOF(struct_$1[_]member, [], PSI_INCLUDES_DEFAULT($4,
                                        [#define struct_$1_]member ((struct $1 *)0)->member
                                ))
+                               psi_member_size=$ac_cv_sizeof_struct_$1[]_[]member
                                PSI_CHECK_OFFSETOF(struct $1, member, PSI_INCLUDES_DEFAULT($4))
+                               psi_member_offset=$ac_cv_offsetof_struct_$1[]_[]member
+                               # type
+                               case member in
+                               $3
+                               *) psi_member_type=int ;;
+                               esac
                                # pointer level
                                psi_struct_member_pl=`echo $psi_member_type | tr -cd '*' | wc -c`
                                # array size
-                               psi_struct_member_as=`echo $psi_member_type | $AWK -F'\x5b\x5d\x5b\x5d' 'END {print 0} /\\x5b\x5b\x5b:digit:\x5d\x5d+\\x5d/ {print$[]2; exit}'`
+                               psi_struct_member_as=`echo $psi_member_type | $AWK -F'\x5b\x5d\x5b\x5d' 'END {if(!found)print 0} /\\x5b\x5b\x5b:digit:\x5d\x5d+\\x5d/ {found=1; print$[]2}'`
                                if test $psi_struct_member_as -gt 0
                                then
                                        psi_struct_member_pl=`expr $psi_struct_member_pl + 1`
                                fi
-                               psi_struct_member="{`psi_type_pair $psi_member_type $ac_cv_sizeof_struct_$1[]_[]member`, \"[]member[]\", $ac_cv_offsetof_struct_$1[]_[]member, $ac_cv_sizeof_struct_$1[]_[]member, $psi_struct_member_pl, $psi_struct_member_as}"
+                               psi_struct_member="{`psi_type_pair $psi_member_type $psi_member_size`, \"$psi_member_name\", $psi_member_offset, $psi_member_size, $psi_struct_member_pl, $psi_struct_member_as}"
                                if test "$psi_struct_members"
                                then
                                        psi_struct_members="$psi_struct_members, $psi_struct_member"
@@ -228,7 +234,7 @@ if test "$PHP_PSI" != "no"; then
                                fi
                        ], [], PSI_INCLUDES_DEFAULT($4))
                ])
-               PSI_STRUCTS="{\"$1\", $ac_cv_sizeof_struct_$1, {$psi_struct_members}}, $PSI_STRUCTS"
+               PSI_STRUCTS="{\"$1\", $psi_struct_size, {$psi_struct_members}}, $PSI_STRUCTS"
        ])
 
        AC_TYPE_INT8_T
@@ -447,6 +453,16 @@ if test "$PHP_PSI" != "no"; then
        PSI_TYPE(time_t, int)
        PSI_TYPE(timer_t, int)
        PSI_TYPE(uid_t)
+       dnl sys/utsname.h
+       PSI_STRUCT(utsname, [
+               [sysname],
+               [nodename],
+               [release],
+               [version],
+               [machine],
+               [domainname]], [
+               *) psi_member_type="char@<:@$psi_member_size@:>@" ;;
+       ], sys/utsname.h)
        dnl time.h
        PSI_STRUCT(tm, [
                [tm_sec],
index f9e89b798c1bd5b7357c781b2303cc7d9e1df29f..d387a06c45282a18ae05c6fdb5805edc7f80bdd9 100644 (file)
--- a/php_psi.h
+++ b/php_psi.h
@@ -32,14 +32,16 @@ int psi_internal_type(impl_type *type);
 zend_internal_arg_info *psi_internal_arginfo(impl *impl);
 size_t psi_num_min_args(impl *impl);
 
+void psi_to_bool(zval *return_value, token_t t, impl_val *ret_val, decl_var *var);
 void psi_to_int(zval *return_value, token_t t, impl_val *ret_val, decl_var *var);
 void psi_to_double(zval *return_value, token_t t, impl_val *ret_val, decl_var *var);
 void psi_to_string(zval *return_value, token_t t, impl_val *ret_val, decl_var *var);
+void psi_to_array(zval *return_value, token_t t, impl_val *ret_val, decl_var *var);
 
 ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, impl *impl);
 void *psi_do_let(decl_arg *darg);
-void psi_do_set(zval *return_value, set_func *func, decl_vars *vars);
-void psi_do_return(impl *impl, impl_val *ret_val, zval *return_value);
+void psi_do_set(zval *return_value, set_value *set);
+void psi_do_return(zval *return_value, return_stmt *ret, impl_val *ret_val);
 void psi_do_free(free_stmt *fre);
 void psi_do_clean(impl *impl);
 
index 35cedeeb22f661ce3a920c892a30389ade7b8047..3ff510f2f8aa47a6002dcedafb9ce9b45890fb78 100644 (file)
@@ -254,21 +254,78 @@ static inline int validate_decl(PSI_Data *data, void *dl, decl *decl) {
        }
        return 1;
 }
-static inline int validate_set_value(PSI_Data *data, set_value *set) {
-       set->
+
+static inline decl_arg *locate_struct_member(decl_struct *s, decl_var *var) {
+       size_t i;
+
+       ZEND_ASSERT(s);
+       for (i = 0; i < s->args->count; ++i) {
+               decl_arg *darg = s->args->args[i];
+
+               if (!strcmp(var->name, darg->var->name)) {
+                       return darg;
+               }
+       }
+
+       return NULL;
+}
+static inline int validate_set_value(PSI_Data *data, set_value *set, decl_arg *ref) {
+       size_t i;
+
+       switch (set->func->type) {
+       case PSI_T_TO_BOOL:
+               set->func->handler = psi_to_bool;
+               break;
+       case PSI_T_TO_INT:
+               set->func->handler = psi_to_int;
+               break;
+       case PSI_T_TO_FLOAT:
+               set->func->handler = psi_to_double;
+               break;
+       case PSI_T_TO_STRING:
+               set->func->handler = psi_to_string;
+               break;
+       case PSI_T_TO_ARRAY:
+               set->func->handler = psi_to_array;
+               break;
+       EMPTY_SWITCH_DEFAULT_CASE();
+       }
+
+       if (strcmp(set->vars->vars[0]->name, ref->var->name)) {
+               return 0;
+       }
+
+       if (set->count && (set->func->type != PSI_T_TO_ARRAY || real_decl_type(ref->type)->type != PSI_T_STRUCT)) {
+               data->error(E_WARNING, "Inner `set` statement casts only work with to_array() casts on structs");
+               return 0;
+       }
+       for (i = 0; i < set->count; ++i) {
+               decl_arg *sub_ref = locate_struct_member(real_decl_type(ref->type)->strct, set->inner[i]->vars->vars[0]);
+
+               if (!sub_ref) {
+                       return 0;
+               }
+               if (!validate_set_value(data, set->inner[i], sub_ref)) {
+                       return 0;
+               }
+       }
+
+       return 1;
 }
 static inline decl *locate_impl_decl(decls *decls, return_stmt *ret) {
        size_t i;
 
        for (i = 0; i < decls->count; ++i) {
-               if (!strcmp(decls->list[i]->func->var->name, ret->decl->name)) {
-                       ret->decl->arg = decls->list[i]->func;
+               if (!strcmp(decls->list[i]->func->var->name, ret->set->vars->vars[0]->name)) {
+                       ret->decl = decls->list[i]->func;
                        return decls->list[i];
                }
        }
        return NULL;
 }
 static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) {
+       return_stmt *ret;
+
        /* we must have exactly one ret stmt delcaring the native func to call */
        /* and which type cast to apply */
        if (impl->stmts->ret.count != 1) {
@@ -282,14 +339,17 @@ static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) {
                }
                return 0;
        }
-       if (!validate_impl_set_value(data, impl->stmts->ret.list[0]->set)) {
-               return 0;
-       }
-       if (!(impl->decl = locate_impl_decl(data->decls, impl->stmts->ret.list[0]))) {
+
+       ret = impl->stmts->ret.list[0];
+
+       if (!(impl->decl = locate_impl_decl(data->decls, ret))) {
                data->error(PSI_WARNING, "Missing declaration for implementation %s",
                                impl->func->name);
                return 0;
        }
+       if (!validate_set_value(data, ret->set, ret->decl)) {
+               return 0;
+       }
 
        return 1;
 }
@@ -383,6 +443,9 @@ static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) {
 
                                if (!strcmp(set_var->name, set_arg->var->name)) {
                                        check = 1;
+                                       if (!validate_set_value(data, set->val, set_arg)) {
+                                               return 0;
+                                       }
                                        set_var->arg = set_arg;
                                        break;
                                }
index e50ca0f56f9da2e16be3d55df99bab1879597bf0..34a15987a729143b2272c0bafd64f4b53154f090 100644 (file)
@@ -224,7 +224,7 @@ static void psi_ffi_handler(ffi_cif *_sig, void *_result, void **_args, void *_d
 
        ffi_call(&data->signature, FFI_FN(data->impl->decl->dlptr), &ret_val, arg_prm);
 
-       psi_do_return(data->impl->stmts->ret.list[0], &ret_val, *(zval **)_args[1]);
+       psi_do_return(*(zval **)_args[1], data->impl->stmts->ret.list[0], &ret_val);
 
        for (i = 0; i < data->impl->stmts->set.count; ++i) {
                set_stmt *set = data->impl->stmts->set.list[i];
index ee9b1f341bb7d5380f4fb069d711f4ee74702b76..f4f57c538018a8007ed9c54ae824779e2a79e68f 100644 (file)
@@ -163,7 +163,7 @@ static void psi_jit_handler(jit_type_t _sig, void *result, void **_args, void *_
 
        jit_apply(data->signature, data->impl->decl->dlptr, arg_prm, data->impl->decl->args->count, &ret_val);
 
-       psi_do_return(data->impl->stmts->ret.list[0], &ret_val, *(zval **)_args[1]);
+       psi_do_return(*(zval **)_args[1], data->impl->stmts->ret.list[0], &ret_val);
 
        for (i = 0; i < data->impl->stmts->set.count; ++i) {
                set_stmt *set = data->impl->stmts->set.list[i];
index a883e62bd982dd721d405362166f691de90aad49..eec8611178bc4189d3129fd50a36aff86a793ff1 100644 (file)
@@ -93,6 +93,24 @@ size_t psi_num_min_args(impl *impl)
        return n;
 }
 
+void psi_to_bool(zval *return_value, token_t t, impl_val *ret_val, decl_var *var)
+{
+       switch (t) {
+       case PSI_T_FLOAT:
+               RETVAL_DOUBLE((double) deref_impl_val(ret_val, var)->fval);
+               convert_to_boolean(return_value);
+               break;
+       case PSI_T_DOUBLE:
+               RETVAL_DOUBLE(deref_impl_val(ret_val, var)->dval);
+               convert_to_boolean(return_value);
+               break;
+       default:
+               RETVAL_LONG(deref_impl_val(ret_val, var)->lval);
+               convert_to_boolean(return_value);
+               break;
+       }
+}
+
 void psi_to_int(zval *return_value, token_t t, impl_val *ret_val, decl_var *var)
 {
        switch (t) {
@@ -550,35 +568,19 @@ void *psi_do_let(decl_arg *darg)
 void psi_do_set(zval *return_value, set_value *set)
 {
        impl_val *val = (impl_val *) &set->vars->vars[0]->arg->let->ptr;
+       token_t t = real_decl_type(set->vars->vars[0]->arg->type)->type;
 
        ZVAL_DEREF(return_value);
        zval_dtor(return_value);
 
-       switch (func->type) {
-       case PSI_T_TO_STRING:
-               psi_to_string(return_value, real_decl_type(vars->vars[0]->arg->type)->type, val, vars->vars[0]);
-               break;
-       case PSI_T_TO_ARRAY:
-               psi_to_array(return_value, real_decl_type(vars->vars[0]->arg->type)->type, val, vars->vars[0]);
-               break;
-       EMPTY_SWITCH_DEFAULT_CASE();
-       }
+       set->func->handler(return_value, t, val, set->vars->vars[0]);
 }
 
-void psi_do_return(return_stmt *ret, impl_val *ret_val, zval *return_value)
+void psi_do_return(zval *return_value, return_stmt *ret, impl_val *ret_val)
 {
-       switch (ret->func->type) {
-       case PSI_T_TO_STRING:
-               psi_to_string(return_value, real_decl_type(impl->decl->func->type)->type, ret_val, ret->decl);
-               break;
-       case PSI_T_TO_INT:
-               psi_to_int(return_value, real_decl_type(impl->decl->func->type)->type, ret_val, ret->decl);
-               break;
-       case PSI_T_TO_ARRAY:
-               psi_to_array(return_value, real_decl_type(impl->decl->func->type)->type, ret_val, ret->decl);
-               break;
-       EMPTY_SWITCH_DEFAULT_CASE();
-       }
+       token_t t = real_decl_type(ret->decl->type)->type;
+
+       ret->set->func->handler(return_value, t, ret_val, ret->decl->var);
 }
 
 void psi_do_free(free_stmt *fre)
index 84de6e8d53689bc96b4edac0af8436f406c3ca56..a9060bd5a67d5973edeae5b486935ce751fa52f2 100644 (file)
@@ -573,6 +573,7 @@ static inline void free_let_stmt(let_stmt *stmt) {
 typedef struct set_func {
        token_t type;
        char *name;
+       void (*handler)(zval *, token_t, impl_val *, decl_var *);
 } set_func;
 
 static inline set_func *init_set_func(token_t type, const char *name) {
@@ -639,13 +640,12 @@ static inline void free_set_stmt(set_stmt *set) {
 
 typedef struct return_stmt {
        set_value *set;
-       decl_var *decl;
+       decl_arg *decl;
 } return_stmt;
 
 static inline return_stmt *init_return_stmt(set_value *val) {
        return_stmt *ret = calloc(1, sizeof(*ret));
        ret->set = val;
-       ret->decl = val->vars->vars[0];
        return ret;
 }