From d3cb2393052d435abdad7dcdeaa726c949a37668 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 27 Jul 2014 22:26:06 +0200 Subject: [PATCH] Use separate node type for lists This saves storing the children count for normal ast nodes. --- Zend/zend_ast.c | 134 ++++++++------- Zend/zend_ast.h | 181 ++++++++++++-------- Zend/zend_compile.c | 331 +++++++++++++++++++----------------- Zend/zend_language_parser.y | 56 +++--- 4 files changed, 381 insertions(+), 321 deletions(-) diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index c52291cfc0d..de5787895fa 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -79,7 +79,6 @@ static zend_ast *zend_ast_create_from_va_list( ast->kind = kind; ast->attr = attr; ast->lineno = UINT_MAX; - ast->children = children; for (i = 0; i < children; ++i) { ast->child[i] = va_arg(va, zend_ast *); @@ -124,16 +123,16 @@ ZEND_API zend_ast *zend_ast_create( return ast; } -ZEND_API zend_ast *zend_ast_create_dynamic(zend_ast_kind kind) -{ +ZEND_API zend_ast *zend_ast_create_dynamic(zend_ast_kind kind) { /* use 4 children as default */ TSRMLS_FETCH(); - zend_ast *ast = zend_arena_alloc(&CG(ast_arena), sizeof(zend_ast) + sizeof(zend_ast *) * 3); - ast->kind = kind; - ast->attr = 0; - ast->lineno = CG(zend_lineno); - ast->children = 0; - return ast; + zend_ast_list *list = zend_arena_alloc(&CG(ast_arena), + sizeof(zend_ast_list) + sizeof(zend_ast *) * 3); + list->kind = kind; + list->attr = 0; + list->lineno = CG(zend_lineno); + list->children = 0; + return (zend_ast *) list; } static inline zend_bool is_power_of_two(unsigned short n) { @@ -142,39 +141,17 @@ static inline zend_bool is_power_of_two(unsigned short n) { ZEND_API zend_ast *zend_ast_dynamic_add(zend_ast *ast, zend_ast *op) { - if (ast->children >= 4 && is_power_of_two(ast->children)) { + zend_ast_list *list = zend_ast_get_list(ast); + if (list->children >= 4 && is_power_of_two(list->children)) { TSRMLS_FETCH(); - size_t old_size = sizeof(zend_ast) + sizeof(zend_ast *) * (ast->children - 1); - zend_ast *new_ast = zend_arena_alloc(&CG(ast_arena), - sizeof(zend_ast) + sizeof(zend_ast *) * (ast->children * 2 - 1)); - memcpy(new_ast, ast, old_size); - ast = new_ast; - } - ast->child[ast->children++] = op; - return ast; -} - -ZEND_API void zend_ast_dynamic_shrink(zend_ast **ast) -{ - *ast = erealloc(*ast, sizeof(zend_ast) + sizeof(zend_ast *) * ((*ast)->children - 1)); -} - -ZEND_API int zend_ast_is_ct_constant(zend_ast *ast) -{ - int i; - - if (ast->kind == ZEND_AST_ZVAL) { - return !Z_CONSTANT_P(zend_ast_get_zval(ast)); - } else { - for (i = 0; i < ast->children; i++) { - if (ast->child[i]) { - if (!zend_ast_is_ct_constant(ast->child[i])) { - return 0; - } - } - } - return 1; + size_t old_size = sizeof(zend_ast_list) + sizeof(zend_ast *) * (list->children - 1); + zend_ast_list *new_list = zend_arena_alloc(&CG(ast_arena), + sizeof(zend_ast_list) + sizeof(zend_ast *) * (list->children * 2 - 1)); + memcpy(new_list, list, old_size); + list = new_list; } + list->child[list->children++] = op; + return (zend_ast *) list; } static void zend_ast_add_array_element(zval *result, zval *offset, zval *expr TSRMLS_DC) @@ -237,16 +214,14 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s zval_dtor(&op2); break; } - case ZEND_BW_NOT: + case ZEND_AST_UNARY_OP: + { + unary_op_type op = get_unary_op(ast->attr); zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC); - bitwise_not_function(result, &op1 TSRMLS_CC); - zval_dtor(&op1); - break; - case ZEND_BOOL_NOT: - zend_ast_evaluate(&op1, ast->child[0], scope TSRMLS_CC); - boolean_not_function(result, &op1 TSRMLS_CC); + op(result, &op1 TSRMLS_CC); zval_dtor(&op1); break; + } case ZEND_AST_ZVAL: ZVAL_DUP(result, zend_ast_get_zval(ast)); if (Z_OPT_CONSTANT_P(result)) { @@ -305,8 +280,9 @@ ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *s array_init(result); { zend_uint i; - for (i = 0; i < ast->children; i++) { - zend_ast *elem = ast->child[i]; + zend_ast_list *list = zend_ast_get_list(ast); + for (i = 0; i < list->children; i++) { + zend_ast *elem = list->child[i]; if (elem->child[1]) { zend_ast_evaluate(&op1, elem->child[1], scope TSRMLS_CC); } else { @@ -341,18 +317,29 @@ ZEND_API zend_ast *zend_ast_copy(zend_ast *ast) if (ast == NULL) { return NULL; } else if (ast->kind == ZEND_AST_ZVAL) { - zend_ast_zval *copy = emalloc(sizeof(zend_ast_zval)); - copy->kind = ZEND_AST_ZVAL; - copy->attr = ast->attr; - ZVAL_DUP(©->val, zend_ast_get_zval(ast)); - return (zend_ast *) copy; + zend_ast_zval *new = emalloc(sizeof(zend_ast_zval)); + new->kind = ZEND_AST_ZVAL; + new->attr = ast->attr; + ZVAL_DUP(&new->val, zend_ast_get_zval(ast)); + return (zend_ast *) new; + } else if (zend_ast_is_list(ast)) { + zend_ast_list *list = zend_ast_get_list(ast); + zend_ast_list *new = emalloc(sizeof(zend_ast_list) + + sizeof(zend_ast *) * (list->children - 1)); + zend_uint i; + new->kind = list->kind; + new->attr = list->attr; + new->children = list->children; + for (i = 0; i < list->children; i++) { + new->child[i] = zend_ast_copy(list->child[i]); + } + return (zend_ast *) new; } else { - zend_ast *new = emalloc(sizeof(zend_ast) + sizeof(zend_ast *) * (ast->children - 1)); - int i; + zend_uint i, children = zend_ast_get_num_children(ast); + zend_ast *new = emalloc(sizeof(zend_ast) + sizeof(zend_ast *) * (children - 1)); new->kind = ast->kind; new->attr = ast->attr; - new->children = ast->children; - for (i = 0; i < ast->children; i++) { + for (i = 0; i < children; i++) { new->child[i] = zend_ast_copy(ast->child[i]); } return new; @@ -386,12 +373,18 @@ static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) { break; } default: - { - zend_uint i; - for (i = 0; i < ast->children; i++) { - zend_ast_destroy_ex(ast->child[i], free); + if (zend_ast_is_list(ast)) { + zend_ast_list *list = zend_ast_get_list(ast); + zend_uint i; + for (i = 0; i < list->children; i++) { + zend_ast_destroy_ex(list->child[i], free); + } + } else { + zend_uint i, children = zend_ast_get_num_children(ast); + for (i = 0; i < children; i++) { + zend_ast_destroy_ex(ast->child[i], free); + } } - } } if (free) { @@ -405,3 +398,18 @@ ZEND_API void zend_ast_destroy(zend_ast *ast) { ZEND_API void zend_ast_destroy_and_free(zend_ast *ast) { zend_ast_destroy_ex(ast, 1); } + +ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn TSRMLS_DC) { + if (zend_ast_is_list(ast)) { + zend_ast_list *list = zend_ast_get_list(ast); + zend_uint i; + for (i = 0; i < list->children; ++i) { + fn(&list->child[i] TSRMLS_CC); + } + } else { + zend_uint i, children = zend_ast_get_num_children(ast); + for (i = 0; i < children; ++i) { + fn(&ast->child[i] TSRMLS_CC); + } + } +} diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 5288ad80237..87b26405a60 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -25,31 +25,49 @@ #include "zend.h" + +#define ZEND_AST_IS_LIST_SHIFT 11 +#define ZEND_AST_NUM_CHILDREN_SHIFT 12 + enum _zend_ast_kind { /* first 256 kinds are reserved for opcodes */ ZEND_AST_ZVAL = 256, ZEND_AST_ZNODE, - ZEND_AST_VAR, - ZEND_AST_DIM, - ZEND_AST_PROP, - ZEND_AST_STATIC_PROP, + /* declaration nodes */ + ZEND_AST_FUNC_DECL, + ZEND_AST_CLOSURE, + ZEND_AST_METHOD, + ZEND_AST_CLASS, - ZEND_AST_CALL, - ZEND_AST_METHOD_CALL, - ZEND_AST_STATIC_CALL, - ZEND_AST_ARG_LIST, - ZEND_AST_UNPACK, - - ZEND_AST_CONST, - ZEND_AST_CLASS_CONST, - ZEND_AST_RESOLVE_CLASS_NAME, - - ZEND_AST_ASSIGN, - ZEND_AST_ASSIGN_REF, - ZEND_AST_ASSIGN_OP, + /* list nodes */ + ZEND_AST_ARG_LIST = 1 << ZEND_AST_IS_LIST_SHIFT, ZEND_AST_LIST, + ZEND_AST_ARRAY, + ZEND_AST_ENCAPS_LIST, + ZEND_AST_EXPR_LIST, + ZEND_AST_STMT_LIST, + ZEND_AST_IF, + ZEND_AST_SWITCH_LIST, + ZEND_AST_CATCH_LIST, + ZEND_AST_PARAM_LIST, + ZEND_AST_CLOSURE_USES, + ZEND_AST_PROP_DECL, + ZEND_AST_CONST_DECL, + ZEND_AST_CLASS_CONST_DECL, + ZEND_AST_NAME_LIST, + ZEND_AST_TRAIT_ADAPTATIONS, + ZEND_AST_USE, + /* 0 child nodes */ + ZEND_AST_MAGIC_CONST = 0 << ZEND_AST_NUM_CHILDREN_SHIFT, + ZEND_AST_TYPE, + + /* 1 child node */ + ZEND_AST_VAR = 1 << ZEND_AST_NUM_CHILDREN_SHIFT, + ZEND_AST_CONST, + ZEND_AST_RESOLVE_CLASS_NAME, + ZEND_AST_UNPACK, ZEND_AST_UNARY_PLUS, ZEND_AST_UNARY_MINUS, ZEND_AST_CAST, @@ -57,75 +75,75 @@ enum _zend_ast_kind { ZEND_AST_ISSET, ZEND_AST_SILENCE, ZEND_AST_SHELL_EXEC, + ZEND_AST_CLONE, + ZEND_AST_EXIT, + ZEND_AST_PRINT, + ZEND_AST_INCLUDE_OR_EVAL, + ZEND_AST_UNARY_OP, + ZEND_AST_PRE_INC, + ZEND_AST_PRE_DEC, + ZEND_AST_POST_INC, + ZEND_AST_POST_DEC, + ZEND_AST_GLOBAL, + ZEND_AST_UNSET, + ZEND_AST_RETURN, + ZEND_AST_LABEL, + ZEND_AST_REF, + ZEND_AST_HALT_COMPILER, + ZEND_AST_ECHO, + ZEND_AST_THROW, + ZEND_AST_GOTO, + ZEND_AST_BREAK, + ZEND_AST_CONTINUE, + + /* 2 child nodes */ + ZEND_AST_DIM = 2 << ZEND_AST_NUM_CHILDREN_SHIFT, + ZEND_AST_PROP, + ZEND_AST_STATIC_PROP, + ZEND_AST_CALL, + ZEND_AST_CLASS_CONST, + ZEND_AST_ASSIGN, + ZEND_AST_ASSIGN_REF, + ZEND_AST_ASSIGN_OP, ZEND_AST_BINARY_OP, ZEND_AST_GREATER, ZEND_AST_GREATER_EQUAL, ZEND_AST_AND, ZEND_AST_OR, - - ZEND_AST_CONDITIONAL, - - ZEND_AST_ARRAY, ZEND_AST_ARRAY_ELEM, - ZEND_AST_ENCAPS_LIST, - ZEND_AST_MAGIC_CONST, + ZEND_AST_NEW, + ZEND_AST_INSTANCEOF, + ZEND_AST_YIELD, - ZEND_AST_EXPR_LIST, - ZEND_AST_STMT_LIST, - - ZEND_AST_GLOBAL, ZEND_AST_STATIC, - ZEND_AST_UNSET, - ZEND_AST_RETURN, - ZEND_AST_LABEL, - ZEND_AST_WHILE, ZEND_AST_DO_WHILE, - ZEND_AST_FOR, - ZEND_AST_FOREACH, - ZEND_AST_REF, - ZEND_AST_IF, ZEND_AST_IF_ELEM, - ZEND_AST_SWITCH, - ZEND_AST_SWITCH_LIST, ZEND_AST_SWITCH_CASE, + ZEND_AST_DECLARE, + ZEND_AST_PROP_ELEM, + ZEND_AST_CONST_ELEM, + ZEND_AST_USE_TRAIT, + ZEND_AST_TRAIT_PRECEDENCE, + ZEND_AST_METHOD_REFERENCE, + ZEND_AST_NAMESPACE, + ZEND_AST_USE_ELEM, + ZEND_AST_TRAIT_ALIAS, + + /* 3 child nodes */ + ZEND_AST_METHOD_CALL = 3 << ZEND_AST_NUM_CHILDREN_SHIFT, + ZEND_AST_STATIC_CALL, + ZEND_AST_CONDITIONAL, ZEND_AST_TRY, - ZEND_AST_CATCH_LIST, ZEND_AST_CATCH, - ZEND_AST_DECLARE, - - ZEND_AST_PARAM_LIST, ZEND_AST_PARAM, - ZEND_AST_TYPE, - ZEND_AST_FUNC_DECL, - ZEND_AST_CLOSURE, - ZEND_AST_CLOSURE_USES, - ZEND_AST_METHOD, - - ZEND_AST_PROP_DECL, - ZEND_AST_PROP_ELEM, - - ZEND_AST_CONST_DECL, - ZEND_AST_CLASS_CONST_DECL, - ZEND_AST_CONST_ELEM, - - ZEND_AST_USE_TRAIT, - ZEND_AST_NAME_LIST, - ZEND_AST_TRAIT_ADAPTATIONS, - ZEND_AST_TRAIT_PRECEDENCE, - ZEND_AST_TRAIT_ALIAS, - ZEND_AST_METHOD_REFERENCE, - - ZEND_AST_CLASS, - - ZEND_AST_USE, - ZEND_AST_USE_ELEM, - ZEND_AST_NAMESPACE, - ZEND_AST_HALT_COMPILER, + /* 4 child nodes */ + ZEND_AST_FOR = 4 << ZEND_AST_NUM_CHILDREN_SHIFT, + ZEND_AST_FOREACH, }; typedef unsigned short zend_ast_kind; @@ -135,10 +153,18 @@ struct _zend_ast { zend_ast_kind kind; /* Type of the node (either opcode or ZEND_AST_* constant) */ zend_ast_attr attr; /* Additional attribute, use depending on node type */ zend_uint lineno; /* Line number */ - zend_uint children; /* Number of children */ zend_ast *child[1]; /* Array of children (using struct hack) */ }; +/* Same as zend_ast, but with children count, which is updated dynamically */ +typedef struct _zend_ast_list { + zend_ast_kind kind; + zend_ast_attr attr; + zend_uint lineno; + zend_uint children; + zend_ast *child[1]; +} zend_ast_list; + typedef struct _zend_ast_zval { zend_ast_kind kind; zend_ast_attr attr; @@ -173,9 +199,6 @@ ZEND_API zend_ast *zend_ast_create_decl( ZEND_API zend_ast *zend_ast_create_dynamic(zend_ast_kind kind); ZEND_API zend_ast *zend_ast_dynamic_add(zend_ast *ast, zend_ast *op); -ZEND_API void zend_ast_dynamic_shrink(zend_ast **ast); - -ZEND_API int zend_ast_is_ct_constant(zend_ast *ast); ZEND_API void zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope TSRMLS_DC); @@ -183,6 +206,22 @@ ZEND_API zend_ast *zend_ast_copy(zend_ast *ast); ZEND_API void zend_ast_destroy(zend_ast *ast); ZEND_API void zend_ast_destroy_and_free(zend_ast *ast); +typedef void (*zend_ast_apply_func)(zend_ast **ast_ptr TSRMLS_DC); +ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn TSRMLS_DC); + +static inline zend_bool zend_ast_is_list(zend_ast *ast) { + return (ast->kind >> ZEND_AST_IS_LIST_SHIFT) & 1; +} +static inline zend_ast_list *zend_ast_get_list(zend_ast *ast) { + ZEND_ASSERT(zend_ast_is_list(ast)); + return (zend_ast_list *) ast; +} + +/* Only for non-lists! */ +static inline zend_uint zend_ast_get_num_children(zend_ast *ast) { + return ast->kind >> ZEND_AST_NUM_CHILDREN_SHIFT; +} + static inline zval *zend_ast_get_zval(zend_ast *ast) { return &((zend_ast_zval *) ast)->val; } diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index f98808cd1bb..abf931ea627 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3823,15 +3823,16 @@ static zend_uchar get_list_fetch_opcode(zend_uchar op_type) { } } -static void zend_compile_list_assign(znode *result, zend_ast *list_ast, znode *expr_node TSRMLS_DC) { +static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node TSRMLS_DC) { + zend_ast_list *list = zend_ast_get_list(ast); zend_uint i; - if (list_ast->children == 1 && !list_ast->child[0]) { + if (list->children == 1 && !list->child[0]) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use empty list"); } - for (i = 0; i < list_ast->children; ++i) { - zend_ast *var_ast = list_ast->child[i]; + for (i = 0; i < list->children; ++i) { + zend_ast *var_ast = list->child[i]; znode fetch_result, dim_node, var_node, assign_result; zend_op *opline; @@ -3985,7 +3986,7 @@ void zend_compile_assign_ref(znode *result, zend_ast *ast TSRMLS_DC) { if (zend_is_call(source_ast)) { opline->extended_value = ZEND_RETURNS_FUNCTION; - } else if (source_ast->kind == ZEND_NEW) { + } else if (source_ast->kind == ZEND_AST_NEW) { opline->extended_value = ZEND_RETURNS_NEW; } } @@ -4031,8 +4032,9 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast TSRMLS_DC) { } } -zend_uint zend_compile_args(zend_ast *args, zend_function *fbc TSRMLS_DC) { +zend_uint zend_compile_args(zend_ast *ast, zend_function *fbc TSRMLS_DC) { // TODO.AST &var error + zend_ast_list *args = zend_ast_get_list(ast); zend_uint i; zend_bool uses_arg_unpack = 0; zend_uint arg_count = 0; /* number of arguments not including unpacks */ @@ -4183,7 +4185,7 @@ void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_a zend_compile_call_common(result, args_ast, NULL TSRMLS_CC); } -static zend_bool zend_args_contain_unpack(zend_ast *args) { +static zend_bool zend_args_contain_unpack(zend_ast_list *args) { zend_uint i; for (i = 0; i < args->children; ++i) { if (args->child[i]->kind == ZEND_AST_UNPACK) { @@ -4193,43 +4195,43 @@ static zend_bool zend_args_contain_unpack(zend_ast *args) { return 0; } -int zend_compile_func_strlen(znode *result, zend_ast *args_ast TSRMLS_DC) { +int zend_compile_func_strlen(znode *result, zend_ast_list *args TSRMLS_DC) { znode arg_node; if ((CG(compiler_options) & ZEND_COMPILE_NO_BUILTIN_STRLEN) - || args_ast->children != 1 || args_ast->child[0]->kind == ZEND_AST_UNPACK + || args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK ) { return FAILURE; } - zend_compile_expr(&arg_node, args_ast->child[0] TSRMLS_CC); + zend_compile_expr(&arg_node, args->child[0] TSRMLS_CC); emit_op(result, ZEND_STRLEN, &arg_node, NULL TSRMLS_CC); return SUCCESS; } -int zend_compile_func_typecheck(znode *result, zend_ast *args_ast, zend_uint type TSRMLS_DC) { +int zend_compile_func_typecheck(znode *result, zend_ast_list *args, zend_uint type TSRMLS_DC) { znode arg_node; zend_op *opline; - if (args_ast->children != 1 || args_ast->child[0]->kind == ZEND_AST_UNPACK) { + if (args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK) { return FAILURE; } - zend_compile_expr(&arg_node, args_ast->child[0] TSRMLS_CC); + zend_compile_expr(&arg_node, args->child[0] TSRMLS_CC); opline = emit_op(result, ZEND_TYPE_CHECK, &arg_node, NULL TSRMLS_CC); opline->extended_value = type; return SUCCESS; } -int zend_compile_func_defined(znode *result, zend_ast *args_ast TSRMLS_DC) { +int zend_compile_func_defined(znode *result, zend_ast_list *args TSRMLS_DC) { zend_string *name; zend_op *opline; - if (args_ast->children != 1 || args_ast->child[0]->kind != ZEND_AST_ZVAL) { + if (args->children != 1 || args->child[0]->kind != ZEND_AST_ZVAL) { return FAILURE; } - name = zval_get_string(zend_ast_get_zval(args_ast->child[0])); + name = zval_get_string(zend_ast_get_zval(args->child[0])); if (zend_memrchr(name->val, '\\', name->len) || zend_memrchr(name->val, ':', name->len)) { STR_RELEASE(name); return FAILURE; @@ -4301,15 +4303,15 @@ static void zend_compile_init_user_func( } /* cufa = call_user_func_array */ -int zend_compile_func_cufa(znode *result, zend_ast *args_ast, zend_string *lcname TSRMLS_DC) { +int zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_string *lcname TSRMLS_DC) { znode arg_node; - if (args_ast->children != 2 || zend_args_contain_unpack(args_ast)) { + if (args->children != 2 || zend_args_contain_unpack(args)) { return FAILURE; } - zend_compile_init_user_func(NULL, args_ast->child[0], 1, lcname TSRMLS_CC); - zend_compile_expr(&arg_node, args_ast->child[1] TSRMLS_CC); + zend_compile_init_user_func(NULL, args->child[0], 1, lcname TSRMLS_CC); + zend_compile_expr(&arg_node, args->child[1] TSRMLS_CC); emit_op(NULL, ZEND_SEND_ARRAY, &arg_node, NULL TSRMLS_CC); emit_op(result, ZEND_DO_FCALL, NULL, NULL TSRMLS_CC); @@ -4317,16 +4319,16 @@ int zend_compile_func_cufa(znode *result, zend_ast *args_ast, zend_string *lcnam } /* cuf = call_user_func */ -int zend_compile_func_cuf(znode *result, zend_ast *args_ast, zend_string *lcname TSRMLS_DC) { +int zend_compile_func_cuf(znode *result, zend_ast_list *args, zend_string *lcname TSRMLS_DC) { zend_uint i; - if (args_ast->children < 1 || zend_args_contain_unpack(args_ast)) { + if (args->children < 1 || zend_args_contain_unpack(args)) { return FAILURE; } - zend_compile_init_user_func(NULL, args_ast->child[0], args_ast->children - 1, lcname TSRMLS_CC); - for (i = 1; i < args_ast->children; ++i) { - zend_ast *arg_ast = args_ast->child[i]; + zend_compile_init_user_func(NULL, args->child[0], args->children - 1, lcname TSRMLS_CC); + for (i = 1; i < args->children; ++i) { + zend_ast *arg_ast = args->child[i]; znode arg_node; zend_op *opline; zend_bool send_user = 0; @@ -4355,32 +4357,32 @@ int zend_compile_func_cuf(znode *result, zend_ast *args_ast, zend_string *lcname } int zend_try_compile_special_func( - znode *result, zend_string *lcname, zend_ast *args_ast TSRMLS_DC + znode *result, zend_string *lcname, zend_ast_list *args TSRMLS_DC ) { if (zend_str_equals(lcname, "strlen")) { - return zend_compile_func_strlen(result, args_ast TSRMLS_CC); + return zend_compile_func_strlen(result, args TSRMLS_CC); } else if (zend_str_equals(lcname, "is_null")) { - return zend_compile_func_typecheck(result, args_ast, IS_NULL TSRMLS_CC); + return zend_compile_func_typecheck(result, args, IS_NULL TSRMLS_CC); } else if (zend_str_equals(lcname, "is_bool")) { - return zend_compile_func_typecheck(result, args_ast, _IS_BOOL TSRMLS_CC); + return zend_compile_func_typecheck(result, args, _IS_BOOL TSRMLS_CC); } else if (zend_str_equals(lcname, "is_long")) { - return zend_compile_func_typecheck(result, args_ast, IS_LONG TSRMLS_CC); + return zend_compile_func_typecheck(result, args, IS_LONG TSRMLS_CC); } else if (zend_str_equals(lcname, "is_float")) { - return zend_compile_func_typecheck(result, args_ast, IS_DOUBLE TSRMLS_CC); + return zend_compile_func_typecheck(result, args, IS_DOUBLE TSRMLS_CC); } else if (zend_str_equals(lcname, "is_string")) { - return zend_compile_func_typecheck(result, args_ast, IS_STRING TSRMLS_CC); + return zend_compile_func_typecheck(result, args, IS_STRING TSRMLS_CC); } else if (zend_str_equals(lcname, "is_array")) { - return zend_compile_func_typecheck(result, args_ast, IS_ARRAY TSRMLS_CC); + return zend_compile_func_typecheck(result, args, IS_ARRAY TSRMLS_CC); } else if (zend_str_equals(lcname, "is_object")) { - return zend_compile_func_typecheck(result, args_ast, IS_OBJECT TSRMLS_CC); + return zend_compile_func_typecheck(result, args, IS_OBJECT TSRMLS_CC); } else if (zend_str_equals(lcname, "is_resource")) { - return zend_compile_func_typecheck(result, args_ast, IS_RESOURCE TSRMLS_CC); + return zend_compile_func_typecheck(result, args, IS_RESOURCE TSRMLS_CC); } else if (zend_str_equals(lcname, "defined")) { - return zend_compile_func_defined(result, args_ast TSRMLS_CC); + return zend_compile_func_defined(result, args TSRMLS_CC); } else if (zend_str_equals(lcname, "call_user_func_array")) { - return zend_compile_func_cufa(result, args_ast, lcname TSRMLS_CC); + return zend_compile_func_cufa(result, args, lcname TSRMLS_CC); } else if (zend_str_equals(lcname, "call_user_func")) { - return zend_compile_func_cuf(result, args_ast, lcname TSRMLS_CC); + return zend_compile_func_cuf(result, args, lcname TSRMLS_CC); } else { return FAILURE; } @@ -4423,7 +4425,9 @@ void zend_compile_call(znode *result, zend_ast *ast, int type TSRMLS_DC) { return; } - if (zend_try_compile_special_func(result, lcname, args_ast TSRMLS_CC) == SUCCESS) { + if (zend_try_compile_special_func(result, lcname, + zend_ast_get_list(args_ast) TSRMLS_CC) == SUCCESS + ) { STR_RELEASE(lcname); zval_ptr_dtor(&name_node.u.constant); return; @@ -4731,31 +4735,31 @@ void zend_compile_throw(zend_ast *ast TSRMLS_DC) { void zend_compile_break_continue(zend_ast *ast TSRMLS_DC) { zend_ast *depth_ast = ast->child[0]; - zend_uint opcode = ast->kind; znode depth_node; zend_op *opline; - ZEND_ASSERT(opcode == ZEND_BRK || opcode == ZEND_CONT); + ZEND_ASSERT(ast->kind == ZEND_AST_BREAK || ast->kind == ZEND_AST_CONTINUE); if (depth_ast) { if (depth_ast->kind != ZEND_AST_ZVAL) { zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-constant operand " - "is no longer supported", opcode == ZEND_BRK ? "break" : "continue"); + "is no longer supported", ast->kind == ZEND_AST_BREAK ? "break" : "continue"); } zend_compile_expr(&depth_node, depth_ast TSRMLS_CC); if (Z_TYPE(depth_node.u.constant) != IS_LONG || Z_LVAL(depth_node.u.constant) < 1) { zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers", - opcode == ZEND_BRK ? "break" : "continue"); + ast->kind == ZEND_AST_BREAK ? "break" : "continue"); } } else { depth_node.op_type = IS_CONST; ZVAL_LONG(&depth_node.u.constant, 1); } - opline = emit_op(NULL, opcode, NULL, &depth_node TSRMLS_CC); + opline = emit_op(NULL, ast->kind == ZEND_AST_BREAK ? ZEND_BRK : ZEND_CONT, + NULL, &depth_node TSRMLS_CC); opline->op1.opline_num = CG(context).current_brk_cont; } @@ -4832,6 +4836,7 @@ void zend_compile_do_while(zend_ast *ast TSRMLS_DC) { } void zend_compile_expr_list(znode *result, zend_ast *ast TSRMLS_DC) { + zend_ast_list *list; zend_uint i; result->op_type = IS_CONST; @@ -4840,8 +4845,10 @@ void zend_compile_expr_list(znode *result, zend_ast *ast TSRMLS_DC) { if (!ast) { return; } - for (i = 0; i < ast->children; ++i) { - zend_ast *expr_ast = ast->child[i]; + + list = zend_ast_get_list(ast); + for (i = 0; i < list->children; ++i) { + zend_ast *expr_ast = list->child[i]; zend_do_free(result TSRMLS_CC); zend_compile_expr(result, expr_ast TSRMLS_CC); @@ -4988,12 +4995,13 @@ void zend_compile_foreach(zend_ast *ast TSRMLS_DC) { } void zend_compile_if(zend_ast *ast TSRMLS_DC) { + zend_ast_list *list = zend_ast_get_list(ast); zend_uint i; - zend_uint *jmp_opnums = safe_emalloc(sizeof(zend_uint), ast->children - 1, 0); + zend_uint *jmp_opnums = safe_emalloc(sizeof(zend_uint), list->children - 1, 0); zend_uint opnum_last_jmpz = 0; - for (i = 0; i < ast->children; ++i) { - zend_ast *elem_ast = ast->child[i]; + for (i = 0; i < list->children; ++i) { + zend_ast *elem_ast = list->child[i]; zend_ast *cond_ast = elem_ast->child[0]; zend_ast *stmt_ast = elem_ast->child[1]; @@ -5005,7 +5013,7 @@ void zend_compile_if(zend_ast *ast TSRMLS_DC) { zend_compile_stmt(stmt_ast TSRMLS_CC); - if (i != ast->children - 1) { + if (i != list->children - 1) { jmp_opnums[i] = zend_emit_jump(0 TSRMLS_CC); } @@ -5014,7 +5022,7 @@ void zend_compile_if(zend_ast *ast TSRMLS_DC) { } } - for (i = 0; i < ast->children - 1; ++i) { + for (i = 0; i < list->children - 1; ++i) { zend_update_jump_target_to_next(jmp_opnums[i] TSRMLS_CC); } @@ -5023,7 +5031,7 @@ void zend_compile_if(zend_ast *ast TSRMLS_DC) { void zend_compile_switch(zend_ast *ast TSRMLS_DC) { zend_ast *expr_ast = ast->child[0]; - zend_ast *cases_ast = ast->child[1]; + zend_ast_list *cases = zend_ast_get_list(ast->child[1]); zend_uint i; zend_bool has_default_case = 0; @@ -5031,7 +5039,7 @@ void zend_compile_switch(zend_ast *ast TSRMLS_DC) { znode expr_node, case_node; zend_op *opline; - zend_uint *jmpnz_opnums = safe_emalloc(sizeof(zend_uint), cases_ast->children, 0); + zend_uint *jmpnz_opnums = safe_emalloc(sizeof(zend_uint), cases->children, 0); zend_uint opnum_default_jmp; zend_compile_expr(&expr_node, expr_ast TSRMLS_CC); @@ -5046,8 +5054,8 @@ void zend_compile_switch(zend_ast *ast TSRMLS_DC) { case_node.op_type = IS_TMP_VAR; case_node.u.op.var = get_temporary_variable(CG(active_op_array)); - for (i = 0; i < cases_ast->children; ++i) { - zend_ast *case_ast = cases_ast->child[i]; + for (i = 0; i < cases->children; ++i) { + zend_ast *case_ast = cases->child[i]; zend_ast *cond_ast = case_ast->child[0]; znode cond_node; @@ -5069,8 +5077,8 @@ void zend_compile_switch(zend_ast *ast TSRMLS_DC) { opnum_default_jmp = zend_emit_jump(0 TSRMLS_CC); - for (i = 0; i < cases_ast->children; ++i) { - zend_ast *case_ast = cases_ast->child[i]; + for (i = 0; i < cases->children; ++i) { + zend_ast *case_ast = cases->child[i]; zend_ast *cond_ast = case_ast->child[0]; zend_ast *stmt_ast = case_ast->child[1]; @@ -5102,32 +5110,32 @@ void zend_compile_switch(zend_ast *ast TSRMLS_DC) { void zend_compile_try(zend_ast *ast TSRMLS_DC) { zend_ast *try_ast = ast->child[0]; - zend_ast *catches_ast = ast->child[1]; + zend_ast_list *catches = zend_ast_get_list(ast->child[1]); zend_ast *finally_ast = ast->child[2]; zend_uint i; zend_op *opline; zend_uint try_catch_offset = zend_add_try_element( get_next_op_number(CG(active_op_array)) TSRMLS_CC); - zend_uint *jmp_opnums = safe_emalloc(sizeof(zend_uint), catches_ast->children, 0); + zend_uint *jmp_opnums = safe_emalloc(sizeof(zend_uint), catches->children, 0); - if (catches_ast->children == 0 && !finally_ast) { + if (catches->children == 0 && !finally_ast) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use try without catch or finally"); } zend_compile_stmt(try_ast TSRMLS_CC); - if (catches_ast->children != 0) { + if (catches->children != 0) { jmp_opnums[0] = zend_emit_jump(0 TSRMLS_CC); } - for (i = 0; i < catches_ast->children; ++i) { - zend_ast *catch_ast = catches_ast->child[i]; + for (i = 0; i < catches->children; ++i) { + zend_ast *catch_ast = catches->child[i]; zend_ast *class_ast = catch_ast->child[0]; zend_ast *var_ast = catch_ast->child[1]; zend_ast *stmt_ast = catch_ast->child[2]; zval *var_name = zend_ast_get_zval(var_ast); - zend_bool is_last_catch = (i + 1 == catches_ast->children); + zend_bool is_last_catch = (i + 1 == catches->children); zend_uint opnum_catch; @@ -5162,7 +5170,7 @@ void zend_compile_try(zend_ast *ast TSRMLS_DC) { opline->extended_value = get_next_op_number(CG(active_op_array)); } - for (i = 0; i < catches_ast->children; ++i) { + for (i = 0; i < catches->children; ++i) { zend_update_jump_target_to_next(jmp_opnums[i] TSRMLS_CC); } @@ -5192,13 +5200,13 @@ void zend_compile_try(zend_ast *ast TSRMLS_DC) { } void zend_compile_declare(zend_ast *ast TSRMLS_DC) { - zend_ast *declares_ast = ast->child[0]; + zend_ast_list *declares = zend_ast_get_list(ast->child[0]); zend_ast *stmt_ast = ast->child[1]; zend_declarables orig_declarables = CG(declarables); zend_uint i; - for (i = 0; i < declares_ast->children; ++i) { - zend_ast *declare_ast = declares_ast->child[i]; + for (i = 0; i < declares->children; ++i) { + zend_ast *declare_ast = declares->child[i]; zend_ast *name_ast = declare_ast->child[0]; zend_ast *value_ast = declare_ast->child[1]; @@ -5276,24 +5284,26 @@ void zend_compile_declare(zend_ast *ast TSRMLS_DC) { } void zend_compile_stmt_list(zend_ast *ast TSRMLS_DC) { + zend_ast_list *list = zend_ast_get_list(ast); zend_uint i; - for (i = 0; i < ast->children; ++i) { - zend_compile_stmt(ast->child[i] TSRMLS_CC); + for (i = 0; i < list->children; ++i) { + zend_compile_stmt(list->child[i] TSRMLS_CC); } } void zend_compile_params(zend_ast *ast TSRMLS_DC) { + zend_ast_list *list = zend_ast_get_list(ast); zend_uint i; zend_op_array *op_array = CG(active_op_array); zend_arg_info *arg_infos; - if (ast->children == 0) { + if (list->children == 0) { return; } - arg_infos = safe_emalloc(sizeof(zend_arg_info), ast->children, 0); - for (i = 0; i < ast->children; ++i) { - zend_ast *param_ast = ast->child[i]; + arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children, 0); + for (i = 0; i < list->children; ++i) { + zend_ast *param_ast = list->child[i]; zend_ast *type_ast = param_ast->child[0]; zend_ast *var_ast = param_ast->child[1]; zend_ast *default_ast = param_ast->child[2]; @@ -5412,19 +5422,16 @@ void zend_compile_params(zend_ast *ast TSRMLS_DC) { } /* These are assigned at the end to avoid unitialized memory in case of an error */ - op_array->num_args = ast->children; + op_array->num_args = list->children; op_array->arg_info = arg_infos; } void zend_compile_closure_uses(zend_ast *ast TSRMLS_DC) { + zend_ast_list *list = zend_ast_get_list(ast); zend_uint i; - if (!ast) { - return; - } - - for (i = 0; i < ast->children; ++i) { - zend_ast *var_ast = ast->child[i]; + for (i = 0; i < list->children; ++i) { + zend_ast *var_ast = list->child[i]; zend_string *name = Z_STR_P(zend_ast_get_zval(var_ast)); zend_bool by_ref = var_ast->attr; zval zv; @@ -5657,7 +5664,9 @@ static void zend_begin_func_decl( } } - if (zend_str_equals(lcname, ZEND_AUTOLOAD_FUNC_NAME) && params_ast->children != 1) { + if (zend_str_equals(lcname, ZEND_AUTOLOAD_FUNC_NAME) + && zend_ast_get_list(params_ast)->children != 1 + ) { zend_error_noreturn(E_COMPILE_ERROR, "%s() must take exactly 1 argument", ZEND_AUTOLOAD_FUNC_NAME); } @@ -5745,7 +5754,9 @@ void zend_compile_func_decl(znode *result, zend_ast *ast TSRMLS_DC) { } zend_compile_params(params_ast TSRMLS_CC); - zend_compile_closure_uses(uses_ast TSRMLS_CC); + if (uses_ast) { + zend_compile_closure_uses(uses_ast TSRMLS_CC); + } zend_compile_stmt(stmt_ast TSRMLS_CC); if (is_method) { @@ -5767,7 +5778,8 @@ void zend_compile_func_decl(znode *result, zend_ast *ast TSRMLS_DC) { } void zend_compile_prop_decl(zend_ast *ast TSRMLS_DC) { - zend_uint flags = ast->attr; + zend_ast_list *list = zend_ast_get_list(ast); + zend_uint flags = list->attr; zend_class_entry *ce = CG(active_class_entry); zend_uint i; @@ -5779,8 +5791,8 @@ void zend_compile_prop_decl(zend_ast *ast TSRMLS_DC) { zend_error_noreturn(E_COMPILE_ERROR, "Properties cannot be declared abstract"); } - for (i = 0; i < ast->children; ++i) { - zend_ast *prop_ast = ast->child[i]; + for (i = 0; i < list->children; ++i) { + zend_ast *prop_ast = list->child[i]; zend_ast *name_ast = prop_ast->child[0]; zend_ast *value_ast = prop_ast->child[1]; zend_string *name = Z_STR_P(zend_ast_get_zval(name_ast)); @@ -5809,11 +5821,12 @@ void zend_compile_prop_decl(zend_ast *ast TSRMLS_DC) { } void zend_compile_class_const_decl(zend_ast *ast TSRMLS_DC) { + zend_ast_list *list = zend_ast_get_list(ast); zend_class_entry *ce = CG(active_class_entry); zend_uint i; - for (i = 0; i < ast->children; ++i) { - zend_ast *const_ast = ast->child[i]; + for (i = 0; i < list->children; ++i) { + zend_ast *const_ast = list->child[i]; zend_ast *name_ast = const_ast->child[0]; zend_ast *value_ast = const_ast->child[1]; zend_string *name = Z_STR_P(zend_ast_get_zval(name_ast)); @@ -5862,15 +5875,16 @@ static zend_trait_method_reference *zend_compile_method_ref(zend_ast *ast TSRMLS } static zend_string **zend_compile_name_list(zend_ast *ast TSRMLS_DC) { - zend_string **names = safe_emalloc(sizeof(zend_string *), ast->children + 1, 0); + zend_ast_list *list = zend_ast_get_list(ast); + zend_string **names = safe_emalloc(sizeof(zend_string *), list->children + 1, 0); zend_uint i; - for (i = 0; i < ast->children; ++i) { - zend_ast *name_ast = ast->child[i]; + for (i = 0; i < list->children; ++i) { + zend_ast *name_ast = list->child[i]; names[i] = zend_resolve_class_name_ast(name_ast TSRMLS_CC); } - names[ast->children] = NULL; + names[list->children] = NULL; return names; } @@ -5916,14 +5930,14 @@ static void zend_compile_trait_alias(zend_ast *ast TSRMLS_DC) { } void zend_compile_use_trait(zend_ast *ast TSRMLS_DC) { - zend_ast *traits_ast = ast->child[0]; - zend_ast *adaptations_ast = ast->child[1]; + zend_ast_list *traits = zend_ast_get_list(ast->child[0]); + zend_ast_list *adaptations = ast->child[1] ? zend_ast_get_list(ast->child[1]) : NULL; zend_class_entry *ce = CG(active_class_entry); zend_op *opline; zend_uint i; - for (i = 0; i < traits_ast->children; ++i) { - zend_ast *trait_ast = traits_ast->child[i]; + for (i = 0; i < traits->children; ++i) { + zend_ast *trait_ast = traits->child[i]; zend_string *name = Z_STR_P(zend_ast_get_zval(trait_ast)); if (ce->ce_flags & ZEND_ACC_INTERFACE) { @@ -5951,12 +5965,12 @@ void zend_compile_use_trait(zend_ast *ast TSRMLS_DC) { ce->num_traits++; } - if (!adaptations_ast) { + if (!adaptations) { return; } - for (i = 0; i < adaptations_ast->children; ++i) { - zend_ast *adaptation_ast = adaptations_ast->child[i]; + for (i = 0; i < adaptations->children; ++i) { + zend_ast *adaptation_ast = adaptations->child[i]; switch (adaptation_ast->kind) { case ZEND_AST_TRAIT_PRECEDENCE: zend_compile_trait_precedence(adaptation_ast TSRMLS_CC); @@ -5970,9 +5984,10 @@ void zend_compile_use_trait(zend_ast *ast TSRMLS_DC) { } void zend_compile_implements(znode *class_node, zend_ast *ast TSRMLS_DC) { + zend_ast_list *list = zend_ast_get_list(ast); zend_uint i; - for (i = 0; i < ast->children; ++i) { - zend_ast *class_ast = ast->child[i]; + for (i = 0; i < list->children; ++i) { + zend_ast *class_ast = list->child[i]; zend_string *name = Z_STR_P(zend_ast_get_zval(class_ast)); zend_op *opline; @@ -6221,6 +6236,7 @@ static void zend_check_already_in_use( } void zend_compile_use(zend_ast *ast TSRMLS_DC) { + zend_ast_list *list = zend_ast_get_list(ast); zend_uint i; zend_string *current_ns = Z_TYPE(CG(current_namespace)) != IS_UNDEF ? Z_STR(CG(current_namespace)) : NULL; @@ -6228,8 +6244,8 @@ void zend_compile_use(zend_ast *ast TSRMLS_DC) { HashTable *current_import = zend_get_import_ht(type TSRMLS_CC); zend_bool case_sensitive = type == T_CONST; - for (i = 0; i < ast->children; ++i) { - zend_ast *use_ast = ast->child[i]; + for (i = 0; i < list->children; ++i) { + zend_ast *use_ast = list->child[i]; zend_ast *old_name_ast = use_ast->child[0]; zend_ast *new_name_ast = use_ast->child[1]; zend_string *old_name = Z_STR_P(zend_ast_get_zval(old_name_ast)); @@ -6328,9 +6344,10 @@ void zend_compile_use(zend_ast *ast TSRMLS_DC) { } void zend_compile_const_decl(zend_ast *ast TSRMLS_DC) { + zend_ast_list *list = zend_ast_get_list(ast); zend_uint i; - for (i = 0; i < ast->children; ++i) { - zend_ast *const_ast = ast->child[i]; + for (i = 0; i < list->children; ++i) { + zend_ast *const_ast = list->child[i]; zend_ast *name_ast = const_ast->child[0]; zend_ast *value_ast = const_ast->child[1]; zend_string *name = Z_STR_P(zend_ast_get_zval(name_ast)); @@ -6518,11 +6535,12 @@ void zend_compile_greater(znode *result, zend_ast *ast TSRMLS_DC) { void zend_compile_unary_op(znode *result, zend_ast *ast TSRMLS_DC) { zend_ast *expr_ast = ast->child[0]; + zend_uint opcode = ast->attr; znode expr_node; zend_compile_expr(&expr_node, expr_ast TSRMLS_CC); - emit_op_tmp(result, ast->kind, &expr_node, NULL TSRMLS_CC); + emit_op_tmp(result, opcode, &expr_node, NULL TSRMLS_CC); } void zend_compile_unary_pm(znode *result, zend_ast *ast TSRMLS_DC) { @@ -6578,17 +6596,18 @@ void zend_compile_post_incdec(znode *result, zend_ast *ast TSRMLS_DC) { znode var_node; zend_op *opline; - ZEND_ASSERT(ast->kind == ZEND_POST_INC || ast->kind == ZEND_POST_DEC); + ZEND_ASSERT(ast->kind == ZEND_AST_POST_INC || ast->kind == ZEND_AST_POST_DEC); if (var_ast->kind == ZEND_AST_PROP) { opline = zend_compile_prop_common(NULL, var_ast, BP_VAR_RW TSRMLS_CC); - opline->opcode = ast->kind == ZEND_POST_INC ? ZEND_POST_INC_OBJ : ZEND_POST_DEC_OBJ; + opline->opcode = ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC_OBJ : ZEND_POST_DEC_OBJ; opline->result_type = IS_TMP_VAR; opline->result.var = get_temporary_variable(CG(active_op_array)); GET_NODE(result, opline->result); } else { zend_compile_var(&var_node, var_ast, BP_VAR_RW TSRMLS_CC); - emit_op_tmp(result, ast->kind, &var_node, NULL TSRMLS_CC); + emit_op_tmp(result, ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC : ZEND_POST_DEC, + &var_node, NULL TSRMLS_CC); } } @@ -6598,14 +6617,15 @@ void zend_compile_pre_incdec(znode *result, zend_ast *ast TSRMLS_DC) { znode var_node; zend_op *opline; - ZEND_ASSERT(ast->kind == ZEND_PRE_INC || ast->kind == ZEND_PRE_DEC); + ZEND_ASSERT(ast->kind == ZEND_AST_PRE_INC || ast->kind == ZEND_AST_PRE_DEC); if (var_ast->kind == ZEND_AST_PROP) { opline = zend_compile_prop_common(result, var_ast, BP_VAR_RW TSRMLS_CC); - opline->opcode = ast->kind == ZEND_PRE_INC ? ZEND_PRE_INC_OBJ : ZEND_PRE_DEC_OBJ; + opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_OBJ : ZEND_PRE_DEC_OBJ; } else { zend_compile_var(&var_node, var_ast, BP_VAR_RW TSRMLS_CC); - emit_op(result, ast->kind, &var_node, NULL TSRMLS_CC); + emit_op(result, ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC : ZEND_PRE_DEC, + &var_node, NULL TSRMLS_CC); } } @@ -6801,7 +6821,7 @@ void zend_compile_isset_or_empty(znode *result, zend_ast *ast TSRMLS_DC) { if (!zend_is_variable(var_ast) || zend_is_call(var_ast)) { if (ast->kind == ZEND_AST_EMPTY) { /* empty(expr) can be transformed to !expr */ - zend_ast *not_ast = zend_ast_create_unary(ZEND_BOOL_NOT, var_ast); + zend_ast *not_ast = zend_ast_create_ex(1, ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, var_ast); zend_compile_expr(result, not_ast TSRMLS_CC); return; } else { @@ -6874,14 +6894,15 @@ void zend_compile_shell_exec(znode *result, zend_ast *ast TSRMLS_DC) { } void zend_compile_array(znode *result, zend_ast *ast TSRMLS_DC) { + zend_ast_list *list = zend_ast_get_list(ast); zend_op *opline; zend_uint i, opnum_init; zend_bool packed = 1; opnum_init = get_next_op_number(CG(active_op_array)); - for (i = 0; i < ast->children; ++i) { - zend_ast *elem_ast = ast->child[i]; + for (i = 0; i < list->children; ++i) { + zend_ast *elem_ast = list->child[i]; zend_ast *value_ast = elem_ast->child[0]; zend_ast *key_ast = elem_ast->child[1]; zend_bool by_ref = elem_ast->attr; @@ -6902,7 +6923,7 @@ void zend_compile_array(znode *result, zend_ast *ast TSRMLS_DC) { if (i == 0) { opline = emit_op_tmp(result, ZEND_INIT_ARRAY, &value_node, key_node_ptr TSRMLS_CC); - opline->extended_value = ast->children << ZEND_ARRAY_SIZE_SHIFT; + opline->extended_value = list->children << ZEND_ARRAY_SIZE_SHIFT; } else { opline = emit_op(NULL, ZEND_ADD_ARRAY_ELEMENT, &value_node, key_node_ptr TSRMLS_CC); SET_NODE(opline->result, result); @@ -6918,7 +6939,7 @@ void zend_compile_array(znode *result, zend_ast *ast TSRMLS_DC) { } /* Handle empty array */ - if (!ast->children) { + if (!list->children) { emit_op_tmp(result, ZEND_INIT_ARRAY, NULL, NULL TSRMLS_CC); } @@ -7035,15 +7056,16 @@ void zend_compile_resolve_class_name(znode *result, zend_ast *ast TSRMLS_DC) { } void zend_compile_encaps_list(znode *result, zend_ast *ast TSRMLS_DC) { + zend_ast_list *list = zend_ast_get_list(ast); zend_uint i; - ZEND_ASSERT(ast->children > 0); + ZEND_ASSERT(list->children > 0); result->op_type = IS_TMP_VAR; result->u.op.var = get_temporary_variable(CG(active_op_array)); - for (i = 0; i < ast->children; ++i) { - zend_ast *elem_ast = ast->child[i]; + for (i = 0; i < list->children; ++i) { + zend_ast *elem_ast = list->child[i]; znode elem_node; zend_op *opline; @@ -7165,7 +7187,7 @@ zend_bool zend_is_allowed_in_const_expr(zend_ast_kind kind) { return kind == ZEND_AST_ZVAL || kind == ZEND_AST_BINARY_OP || kind == ZEND_AST_GREATER || kind == ZEND_AST_GREATER_EQUAL || kind == ZEND_AST_AND || kind == ZEND_AST_OR - || kind == ZEND_BW_NOT || kind == ZEND_BOOL_NOT + || kind == ZEND_AST_UNARY_OP || kind == ZEND_AST_UNARY_PLUS || kind == ZEND_AST_UNARY_MINUS || kind == ZEND_AST_CONDITIONAL || kind == ZEND_AST_ARRAY || kind == ZEND_AST_ARRAY_ELEM @@ -7301,12 +7323,7 @@ void zend_compile_const_expr(zend_ast **ast_ptr TSRMLS_DC) { zend_error_noreturn(E_COMPILE_ERROR, "Constant expression contains invalid operations"); } - { - zend_uint i; - for (i = 0; i < ast->children; ++i) { - zend_compile_const_expr(&ast->child[i] TSRMLS_CC); - } - } + zend_ast_apply(ast, zend_compile_const_expr TSRMLS_CC); switch (ast->kind) { case ZEND_AST_CLASS_CONST: @@ -7331,9 +7348,10 @@ void zend_compile_top_stmt(zend_ast *ast TSRMLS_DC) { } if (ast->kind == ZEND_AST_STMT_LIST) { + zend_ast_list *list = zend_ast_get_list(ast); zend_uint i; - for (i = 0; i < ast->children; ++i) { - zend_compile_top_stmt(ast->child[i] TSRMLS_CC); + for (i = 0; i < list->children; ++i) { + zend_compile_top_stmt(list->child[i] TSRMLS_CC); } return; } @@ -7372,17 +7390,17 @@ void zend_compile_stmt(zend_ast *ast TSRMLS_DC) { case ZEND_AST_RETURN: zend_compile_return(ast TSRMLS_CC); break; - case ZEND_ECHO: + case ZEND_AST_ECHO: zend_compile_echo(ast TSRMLS_CC); break; - case ZEND_THROW: + case ZEND_AST_THROW: zend_compile_throw(ast TSRMLS_CC); break; - case ZEND_BRK: - case ZEND_CONT: + case ZEND_AST_BREAK: + case ZEND_AST_CONTINUE: zend_compile_break_continue(ast TSRMLS_CC); break; - case ZEND_GOTO: + case ZEND_AST_GOTO: zend_compile_goto(ast TSRMLS_CC); break; case ZEND_AST_LABEL: @@ -7480,10 +7498,10 @@ void zend_compile_expr(znode *result, zend_ast *ast TSRMLS_DC) { case ZEND_AST_ASSIGN_REF: zend_compile_assign_ref(result, ast TSRMLS_CC); return; - case ZEND_NEW: + case ZEND_AST_NEW: zend_compile_new(result, ast TSRMLS_CC); return; - case ZEND_CLONE: + case ZEND_AST_CLONE: zend_compile_clone(result, ast TSRMLS_CC); return; case ZEND_AST_ASSIGN_OP: @@ -7496,8 +7514,7 @@ void zend_compile_expr(znode *result, zend_ast *ast TSRMLS_DC) { case ZEND_AST_GREATER_EQUAL: zend_compile_greater(result, ast TSRMLS_CC); return; - case ZEND_BOOL_NOT: - case ZEND_BW_NOT: + case ZEND_AST_UNARY_OP: zend_compile_unary_op(result, ast TSRMLS_CC); return; case ZEND_AST_UNARY_PLUS: @@ -7508,12 +7525,12 @@ void zend_compile_expr(znode *result, zend_ast *ast TSRMLS_DC) { case ZEND_AST_OR: zend_compile_short_circuiting(result, ast TSRMLS_CC); return; - case ZEND_POST_INC: - case ZEND_POST_DEC: + case ZEND_AST_POST_INC: + case ZEND_AST_POST_DEC: zend_compile_post_incdec(result, ast TSRMLS_CC); return; - case ZEND_PRE_INC: - case ZEND_PRE_DEC: + case ZEND_AST_PRE_INC: + case ZEND_AST_PRE_DEC: zend_compile_pre_incdec(result, ast TSRMLS_CC); return; case ZEND_AST_CAST: @@ -7522,19 +7539,19 @@ void zend_compile_expr(znode *result, zend_ast *ast TSRMLS_DC) { case ZEND_AST_CONDITIONAL: zend_compile_conditional(result, ast TSRMLS_CC); return; - case ZEND_PRINT: + case ZEND_AST_PRINT: zend_compile_print(result, ast TSRMLS_CC); return; - case ZEND_EXIT: + case ZEND_AST_EXIT: zend_compile_exit(result, ast TSRMLS_CC); return; - case ZEND_YIELD: + case ZEND_AST_YIELD: zend_compile_yield(result, ast TSRMLS_CC); return; - case ZEND_INSTANCEOF: + case ZEND_AST_INSTANCEOF: zend_compile_instanceof(result, ast TSRMLS_CC); return; - case ZEND_INCLUDE_OR_EVAL: + case ZEND_AST_INCLUDE_OR_EVAL: zend_compile_include_or_eval(result, ast TSRMLS_CC); return; case ZEND_AST_ISSET: @@ -7601,7 +7618,7 @@ void zend_compile_var(znode *result, zend_ast *ast, int type TSRMLS_DC) { || type == BP_VAR_RW || type == BP_VAR_UNSET ) { /* For BC reasons =& new Foo is allowed */ - if (type != BP_VAR_REF || ast->kind != ZEND_NEW) { + if (type != BP_VAR_REF || ast->kind != ZEND_AST_NEW) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use temporary expression in write context"); } @@ -7665,12 +7682,13 @@ void zend_eval_const_greater(zend_ast **ast_ptr TSRMLS_DC) { void zend_eval_const_array(zend_ast **ast_ptr TSRMLS_DC) { zend_ast *ast = *ast_ptr; + zend_ast_list *list = zend_ast_get_list(ast); zend_uint i; zval array; /* First ensure that *all* child nodes are constant */ - for (i = 0; i < ast->children; ++i) { - zend_ast *elem_ast = ast->child[i]; + for (i = 0; i < list->children; ++i) { + zend_ast *elem_ast = list->child[i]; zend_ast *value_ast = elem_ast->child[0]; zend_ast *key_ast = elem_ast->child[1]; zend_bool by_ref = elem_ast->attr; @@ -7680,9 +7698,9 @@ void zend_eval_const_array(zend_ast **ast_ptr TSRMLS_DC) { } } - array_init_size(&array, ast->children); - for (i = 0; i < ast->children; ++i) { - zend_ast *elem_ast = ast->child[i]; + array_init_size(&array, list->children); + for (i = 0; i < list->children; ++i) { + zend_ast *elem_ast = list->child[i]; zend_ast *value_ast = elem_ast->child[0]; zend_ast *key_ast = elem_ast->child[1]; @@ -7741,12 +7759,7 @@ void zend_eval_const_expr(zend_ast **ast_ptr TSRMLS_DC) { return; } - { - zend_uint i; - for (i = 0; i < ast->children; ++i) { - zend_eval_const_expr(&ast->child[i] TSRMLS_CC); - } - } + zend_ast_apply(ast, zend_eval_const_expr TSRMLS_CC); switch (ast->kind) { case ZEND_AST_BINARY_OP: diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 03bfab3814b..f48fffcf8bf 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -329,10 +329,10 @@ unticked_statement: { $$.ast = zend_ast_create(4, ZEND_AST_FOR, $3.ast, $5.ast, $7.ast, $9.ast); } | T_SWITCH parenthesis_expr switch_case_list { $$.ast = zend_ast_create_binary(ZEND_AST_SWITCH, $2.ast, $3.ast); } - | T_BREAK ';' { $$.ast = zend_ast_create_unary(ZEND_BRK, NULL); } - | T_BREAK expr ';' { $$.ast = zend_ast_create_unary(ZEND_BRK, $2.ast); } - | T_CONTINUE ';' { $$.ast = zend_ast_create_unary(ZEND_CONT, NULL); } - | T_CONTINUE expr ';' { $$.ast = zend_ast_create_unary(ZEND_CONT, $2.ast); } + | T_BREAK ';' { $$.ast = zend_ast_create_unary(ZEND_AST_BREAK, NULL); } + | T_BREAK expr ';' { $$.ast = zend_ast_create_unary(ZEND_AST_BREAK, $2.ast); } + | T_CONTINUE ';' { $$.ast = zend_ast_create_unary(ZEND_AST_CONTINUE, NULL); } + | T_CONTINUE expr ';' { $$.ast = zend_ast_create_unary(ZEND_AST_CONTINUE, $2.ast); } | T_RETURN ';' { $$.ast = zend_ast_create_unary(ZEND_AST_RETURN, NULL); } | T_RETURN expr ';' @@ -340,7 +340,7 @@ unticked_statement: | T_GLOBAL global_var_list ';' { $$.ast = $2.ast; } | T_STATIC static_var_list ';' { $$.ast = $2.ast; } | T_ECHO echo_expr_list ';' { $$.ast = $2.ast; } - | T_INLINE_HTML { $$.ast = zend_ast_create_unary(ZEND_ECHO, $1.ast); } + | T_INLINE_HTML { $$.ast = zend_ast_create_unary(ZEND_AST_ECHO, $1.ast); } | expr ';' { $$.ast = $1.ast; } | T_UNSET '(' unset_variables ')' ';' { $$.ast = $3.ast; } | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement @@ -355,8 +355,8 @@ unticked_statement: | ';' /* empty statement */ { $$.ast = NULL; } | T_TRY '{' inner_statement_list '}' catch_list finally_statement { $$.ast = zend_ast_create_ternary(ZEND_AST_TRY, $3.ast, $5.ast, $6.ast); } - | T_THROW expr ';' { $$.ast = zend_ast_create_unary(ZEND_THROW, $2.ast); } - | T_GOTO T_STRING ';' { $$.ast = zend_ast_create_unary(ZEND_GOTO, $2.ast); } + | T_THROW expr ';' { $$.ast = zend_ast_create_unary(ZEND_AST_THROW, $2.ast); } + | T_GOTO T_STRING ';' { $$.ast = zend_ast_create_unary(ZEND_AST_GOTO, $2.ast); } ; catch_list: @@ -733,7 +733,7 @@ echo_expr_list: | echo_expr { $$.ast = zend_ast_create_dynamic_and_add(ZEND_AST_STMT_LIST, $1.ast); } ; echo_expr: - expr { $$.ast = zend_ast_create_unary(ZEND_ECHO, $1.ast); } + expr { $$.ast = zend_ast_create_unary(ZEND_AST_ECHO, $1.ast); } ; for_expr: @@ -748,7 +748,7 @@ non_empty_for_expr: new_expr: T_NEW class_name_reference ctor_arguments - { $$.ast = zend_ast_create_binary(ZEND_NEW, $2.ast, $3.ast); } + { $$.ast = zend_ast_create_binary(ZEND_AST_NEW, $2.ast, $3.ast); } ; expr_without_variable: @@ -761,8 +761,8 @@ expr_without_variable: | variable '=' '&' T_NEW class_name_reference ctor_arguments { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated"); $$.ast = zend_ast_create_binary(ZEND_AST_ASSIGN_REF, $1.ast, - zend_ast_create_binary(ZEND_NEW, $5.ast, $6.ast)); } - | T_CLONE expr { $$.ast = zend_ast_create_unary(ZEND_CLONE, $2.ast); } + zend_ast_create_binary(ZEND_AST_NEW, $5.ast, $6.ast)); } + | T_CLONE expr { $$.ast = zend_ast_create_unary(ZEND_AST_CLONE, $2.ast); } | variable T_PLUS_EQUAL expr { $$.ast = zend_ast_create_assign_op(ZEND_ASSIGN_ADD, $1.ast, $3.ast); } | variable T_MINUS_EQUAL expr @@ -787,10 +787,10 @@ expr_without_variable: { $$.ast = zend_ast_create_assign_op(ZEND_ASSIGN_SL, $1.ast, $3.ast); } | variable T_SR_EQUAL expr { $$.ast = zend_ast_create_assign_op(ZEND_ASSIGN_SR, $1.ast, $3.ast); } - | variable T_INC { $$.ast = zend_ast_create_unary(ZEND_POST_INC, $1.ast); } - | T_INC variable { $$.ast = zend_ast_create_unary(ZEND_PRE_INC, $2.ast); } - | variable T_DEC { $$.ast = zend_ast_create_unary(ZEND_POST_DEC, $1.ast); } - | T_DEC variable { $$.ast = zend_ast_create_unary(ZEND_PRE_DEC, $2.ast); } + | variable T_INC { $$.ast = zend_ast_create_unary(ZEND_AST_POST_INC, $1.ast); } + | T_INC variable { $$.ast = zend_ast_create_unary(ZEND_AST_PRE_INC, $2.ast); } + | variable T_DEC { $$.ast = zend_ast_create_unary(ZEND_AST_POST_DEC, $1.ast); } + | T_DEC variable { $$.ast = zend_ast_create_unary(ZEND_AST_PRE_DEC, $2.ast); } | expr T_BOOLEAN_OR expr { $$.ast = zend_ast_create_binary(ZEND_AST_OR, $1.ast, $3.ast); } | expr T_BOOLEAN_AND expr @@ -815,8 +815,8 @@ expr_without_variable: | expr T_SR expr { $$.ast = zend_ast_create_binary_op(ZEND_SR, $1.ast, $3.ast); } | '+' expr %prec T_INC { $$.ast = zend_ast_create_unary(ZEND_AST_UNARY_PLUS, $2.ast); } | '-' expr %prec T_INC { $$.ast = zend_ast_create_unary(ZEND_AST_UNARY_MINUS, $2.ast); } - | '!' expr { $$.ast = zend_ast_create_unary(ZEND_BOOL_NOT, $2.ast); } - | '~' expr { $$.ast = zend_ast_create_unary(ZEND_BW_NOT, $2.ast); } + | '!' expr { $$.ast = zend_ast_create_ex(1, ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, $2.ast); } + | '~' expr { $$.ast = zend_ast_create_ex(1, ZEND_AST_UNARY_OP, ZEND_BW_NOT, $2.ast); } | expr T_IS_IDENTICAL expr { $$.ast = zend_ast_create_binary_op(ZEND_IS_IDENTICAL, $1.ast, $3.ast); } | expr T_IS_NOT_IDENTICAL expr @@ -834,7 +834,7 @@ expr_without_variable: | expr T_IS_GREATER_OR_EQUAL expr { $$.ast = zend_ast_create_binary(ZEND_AST_GREATER_EQUAL, $1.ast, $3.ast); } | expr T_INSTANCEOF class_name_reference - { $$.ast = zend_ast_create_binary(ZEND_INSTANCEOF, $1.ast, $3.ast); } + { $$.ast = zend_ast_create_binary(ZEND_AST_INSTANCEOF, $1.ast, $3.ast); } | parenthesis_expr { $$.ast = $1.ast; } | new_expr { $$.ast = $1.ast; } | expr '?' expr ':' expr @@ -857,15 +857,15 @@ expr_without_variable: { $$.ast = zend_ast_create_cast(_IS_BOOL, $2.ast); } | T_UNSET_CAST expr { $$.ast = zend_ast_create_cast(IS_NULL, $2.ast); } - | T_EXIT exit_expr { $$.ast = zend_ast_create_unary(ZEND_EXIT, $2.ast); } + | T_EXIT exit_expr { $$.ast = zend_ast_create_unary(ZEND_AST_EXIT, $2.ast); } | '@' expr { $$.ast = zend_ast_create_unary(ZEND_AST_SILENCE, $2.ast); } | scalar { $$.ast = $1.ast; } | '`' backticks_expr '`' { $$.ast = zend_ast_create_unary(ZEND_AST_SHELL_EXEC, $2.ast); } - | T_PRINT expr { $$.ast = zend_ast_create_unary(ZEND_PRINT, $2.ast); } - | T_YIELD { $$.ast = zend_ast_create_binary(ZEND_YIELD, NULL, NULL); } - | T_YIELD expr { $$.ast = zend_ast_create_binary(ZEND_YIELD, $2.ast, NULL); } + | T_PRINT expr { $$.ast = zend_ast_create_unary(ZEND_AST_PRINT, $2.ast); } + | T_YIELD { $$.ast = zend_ast_create_binary(ZEND_AST_YIELD, NULL, NULL); } + | T_YIELD expr { $$.ast = zend_ast_create_binary(ZEND_AST_YIELD, $2.ast, NULL); } | T_YIELD expr T_DOUBLE_ARROW expr - { $$.ast = zend_ast_create_binary(ZEND_YIELD, $4.ast, $2.ast); } + { $$.ast = zend_ast_create_binary(ZEND_AST_YIELD, $4.ast, $2.ast); } | function returns_ref '(' parameter_list ')' lexical_vars { $$.str = CG(doc_comment); CG(doc_comment) = NULL; } '{' inner_statement_list '}' @@ -1151,15 +1151,15 @@ internal_functions_in_yacc: T_ISSET '(' isset_variables ')' { $$.ast = $3.ast; } | T_EMPTY '(' expr ')' { $$.ast = zend_ast_create_unary(ZEND_AST_EMPTY, $3.ast); } | T_INCLUDE expr - { $$.ast = zend_ast_create_ex(1, ZEND_INCLUDE_OR_EVAL, ZEND_INCLUDE, $2.ast); } + { $$.ast = zend_ast_create_ex(1, ZEND_AST_INCLUDE_OR_EVAL, ZEND_INCLUDE, $2.ast); } | T_INCLUDE_ONCE expr - { $$.ast = zend_ast_create_ex(1, ZEND_INCLUDE_OR_EVAL, ZEND_INCLUDE_ONCE, $2.ast); } + { $$.ast = zend_ast_create_ex(1, ZEND_AST_INCLUDE_OR_EVAL, ZEND_INCLUDE_ONCE, $2.ast); } | T_EVAL '(' expr ')' - { $$.ast = zend_ast_create_ex(1, ZEND_INCLUDE_OR_EVAL, ZEND_EVAL, $3.ast); } + { $$.ast = zend_ast_create_ex(1, ZEND_AST_INCLUDE_OR_EVAL, ZEND_EVAL, $3.ast); } | T_REQUIRE expr - { $$.ast = zend_ast_create_ex(1, ZEND_INCLUDE_OR_EVAL, ZEND_REQUIRE, $2.ast); } + { $$.ast = zend_ast_create_ex(1, ZEND_AST_INCLUDE_OR_EVAL, ZEND_REQUIRE, $2.ast); } | T_REQUIRE_ONCE expr - { $$.ast = zend_ast_create_ex(1, ZEND_INCLUDE_OR_EVAL, ZEND_REQUIRE_ONCE, $2.ast); } + { $$.ast = zend_ast_create_ex(1, ZEND_AST_INCLUDE_OR_EVAL, ZEND_REQUIRE_ONCE, $2.ast); } ; isset_variables: