diff options
Diffstat (limited to 'Zend/zend_opcode.c')
-rw-r--r-- | Zend/zend_opcode.c | 487 |
1 files changed, 399 insertions, 88 deletions
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index cd1525bdab..0d26088167 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -76,6 +76,7 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz op_array->last_live_range = 0; op_array->static_variables = NULL; + ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables); op_array->last_try_catch = 0; op_array->fn_flags = 0; @@ -83,8 +84,8 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz op_array->last_literal = 0; op_array->literals = NULL; - op_array->run_time_cache = NULL; - op_array->cache_size = 0; + ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL); + op_array->cache_size = zend_op_array_extension_handles * sizeof(void*); memset(op_array->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*)); @@ -101,6 +102,26 @@ ZEND_API void destroy_zend_function(zend_function *function) zend_function_dtor(&tmp); } +void zend_free_internal_arg_info(zend_internal_function *function) { + if ((function->fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) && + !function->scope && function->arg_info) { + + uint32_t i; + uint32_t num_args = function->num_args + 1; + zend_internal_arg_info *arg_info = function->arg_info - 1; + + if (function->fn_flags & ZEND_ACC_VARIADIC) { + num_args++; + } + for (i = 0 ; i < num_args; i++) { + if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) { + zend_string_release_ex(ZEND_TYPE_NAME(arg_info[i].type), 1); + } + } + free(arg_info); + } +} + ZEND_API void zend_function_dtor(zval *zv) { zend_function *function = Z_PTR_P(zv); @@ -114,23 +135,7 @@ ZEND_API void zend_function_dtor(zval *zv) ZEND_ASSERT(function->common.function_name); zend_string_release_ex(function->common.function_name, 1); - if ((function->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) && - !function->common.scope && function->common.arg_info) { - - uint32_t i; - uint32_t num_args = function->common.num_args + 1; - zend_arg_info *arg_info = function->common.arg_info - 1; - - if (function->common.fn_flags & ZEND_ACC_VARIADIC) { - num_args++; - } - for (i = 0 ; i < num_args; i++) { - if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) { - zend_string_release_ex(ZEND_TYPE_NAME(arg_info[i].type), 1); - } - } - free(arg_info); - } + zend_free_internal_arg_info(&function->internal_function); if (!(function->common.fn_flags & ZEND_ACC_ARENA_ALLOCATED)) { pefree(function, 1); @@ -145,27 +150,36 @@ ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce) zval *p = static_members; zval *end = p + ce->default_static_members_count; -#ifdef ZTS - CG(static_members_table)[(zend_intptr_t)(ce->static_members_table)] = NULL; -#else - ce->static_members_table = NULL; -#endif + ZEND_MAP_PTR_SET(ce->static_members_table, NULL); while (p != end) { - i_zval_ptr_dtor(p ZEND_FILE_LINE_CC); + if (UNEXPECTED(Z_ISREF_P(p))) { + zend_property_info *prop_info; + ZEND_REF_FOREACH_TYPE_SOURCES(Z_REF_P(p), prop_info) { + if (prop_info->ce == ce && p - static_members == prop_info->offset) { + ZEND_REF_DEL_TYPE_SOURCE(Z_REF_P(p), prop_info); + break; /* stop iteration here, the array might be realloc()'ed */ + } + } ZEND_REF_FOREACH_TYPE_SOURCES_END(); + } + i_zval_ptr_dtor(p); p++; } efree(static_members); } } -void _destroy_zend_class_traits_info(zend_class_entry *ce) +static void _destroy_zend_class_traits_info(zend_class_entry *ce) { - if (ce->num_traits > 0 && ce->traits) { - efree(ce->traits); + uint32_t i; + + for (i = 0; i < ce->num_traits; i++) { + zend_string_release_ex(ce->trait_names[i].name, 0); + zend_string_release_ex(ce->trait_names[i].lc_name, 0); } + efree(ce->trait_names); if (ce->trait_aliases) { - size_t i = 0; + i = 0; while (ce->trait_aliases[i]) { if (ce->trait_aliases[i]->trait_method.method_name) { zend_string_release_ex(ce->trait_aliases[i]->trait_method.method_name, 0); @@ -186,9 +200,9 @@ void _destroy_zend_class_traits_info(zend_class_entry *ce) } if (ce->trait_precedences) { - int i = 0; - int j; + uint32_t j; + i = 0; while (ce->trait_precedences[i]) { zend_string_release_ex(ce->trait_precedences[i]->trait_method.method_name, 0); zend_string_release_ex(ce->trait_precedences[i]->trait_method.class_name, 0); @@ -209,17 +223,34 @@ ZEND_API void destroy_zend_class(zval *zv) zend_class_entry *ce = Z_PTR_P(zv); zend_function *fn; - if (--ce->refcount > 0) { + if (ce->ce_flags & (ZEND_ACC_IMMUTABLE|ZEND_ACC_PRELOADED)) { + zend_op_array *op_array; + + if (ce->default_static_members_count) { + zend_cleanup_internal_class_data(ce); + } + if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) { + ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) { + if (op_array->type == ZEND_USER_FUNCTION) { + destroy_op_array(op_array); + } + } ZEND_HASH_FOREACH_END(); + } + return; + } else if (--ce->refcount > 0) { return; } switch (ce->type) { case ZEND_USER_CLASS: + if (ce->parent_name && !(ce->ce_flags & ZEND_ACC_RESOLVED_PARENT)) { + zend_string_release_ex(ce->parent_name, 0); + } if (ce->default_properties_table) { zval *p = ce->default_properties_table; zval *end = p + ce->default_properties_count; while (p != end) { - i_zval_ptr_dtor(p ZEND_FILE_LINE_CC); + i_zval_ptr_dtor(p); p++; } efree(ce->default_properties_table); @@ -229,17 +260,29 @@ ZEND_API void destroy_zend_class(zval *zv) zval *end = p + ce->default_static_members_count; while (p != end) { - i_zval_ptr_dtor(p ZEND_FILE_LINE_CC); + if (UNEXPECTED(Z_ISREF_P(p))) { + zend_property_info *prop_info; + ZEND_REF_FOREACH_TYPE_SOURCES(Z_REF_P(p), prop_info) { + if (prop_info->ce == ce && p - ce->default_static_members_table == prop_info->offset) { + ZEND_REF_DEL_TYPE_SOURCE(Z_REF_P(p), prop_info); + break; /* stop iteration here, the array might be realloc()'ed */ + } + } ZEND_REF_FOREACH_TYPE_SOURCES_END(); + } + i_zval_ptr_dtor(p); p++; } efree(ce->default_static_members_table); } ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) { - if (prop_info->ce == ce || (prop_info->flags & ZEND_ACC_SHADOW)) { + if (prop_info->ce == ce) { zend_string_release_ex(prop_info->name, 0); if (prop_info->doc_comment) { zend_string_release_ex(prop_info->doc_comment, 0); } + if (ZEND_TYPE_IS_NAME(prop_info->type)) { + zend_string_release(ZEND_TYPE_NAME(prop_info->type)); + } } } ZEND_HASH_FOREACH_END(); zend_hash_destroy(&ce->properties_info); @@ -258,14 +301,24 @@ ZEND_API void destroy_zend_class(zval *zv) } ZEND_HASH_FOREACH_END(); } zend_hash_destroy(&ce->constants_table); - if (ce->num_interfaces > 0 && ce->interfaces) { + if (ce->num_interfaces > 0) { + if (!(ce->ce_flags & ZEND_ACC_RESOLVED_INTERFACES)) { + uint32_t i; + + for (i = 0; i < ce->num_interfaces; i++) { + zend_string_release_ex(ce->interface_names[i].name, 0); + zend_string_release_ex(ce->interface_names[i].lc_name, 0); + } + } efree(ce->interfaces); } if (ce->info.user.doc_comment) { zend_string_release_ex(ce->info.user.doc_comment, 0); } - _destroy_zend_class_traits_info(ce); + if (ce->num_traits > 0) { + _destroy_zend_class_traits_info(ce); + } break; case ZEND_INTERNAL_CLASS: @@ -288,6 +341,9 @@ ZEND_API void destroy_zend_class(zval *zv) p++; } free(ce->default_static_members_table); + if (ZEND_MAP_PTR(ce->static_members_table) != &ce->default_static_members_table) { + zend_cleanup_internal_class_data(ce); + } } zend_hash_destroy(&ce->properties_info); zend_string_release_ex(ce->name, 1); @@ -322,6 +378,9 @@ ZEND_API void destroy_zend_class(zval *zv) if (ce->num_interfaces > 0) { free(ce->interfaces); } + if (ce->properties_info_table) { + free(ce->properties_info_table); + } free(ce); break; } @@ -331,23 +390,27 @@ void zend_class_add_ref(zval *zv) { zend_class_entry *ce = Z_PTR_P(zv); - ce->refcount++; + if (!(ce->ce_flags & ZEND_ACC_IMMUTABLE)) { + ce->refcount++; + } } ZEND_API void destroy_op_array(zend_op_array *op_array) { uint32_t i; - if (op_array->static_variables && - !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) { - if (GC_DELREF(op_array->static_variables) == 0) { - zend_array_destroy(op_array->static_variables); + if (op_array->static_variables) { + HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr); + if (ht && !(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + if (GC_DELREF(ht) == 0) { + zend_array_destroy(ht); + } } } - if (op_array->run_time_cache && !op_array->function_name) { - efree(op_array->run_time_cache); - op_array->run_time_cache = NULL; + if ((op_array->fn_flags & ZEND_ACC_HEAP_RT_CACHE) + && ZEND_MAP_PTR(op_array->run_time_cache)) { + efree(ZEND_MAP_PTR(op_array->run_time_cache)); } if (!op_array->refcount || --(*op_array->refcount) > 0) { @@ -419,7 +482,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array) } } -static void zend_update_extended_info(zend_op_array *op_array) +static void zend_update_extended_stmts(zend_op_array *op_array) { zend_op *opline = op_array->opcodes, *end=opline+op_array->last; @@ -488,18 +551,296 @@ static uint32_t zend_get_brk_cont_target(const zend_op_array *op_array, const ze return opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont; } +static void emit_live_range_raw( + zend_op_array *op_array, uint32_t var_num, uint32_t kind, uint32_t start, uint32_t end) { + zend_live_range *range; + + op_array->last_live_range++; + op_array->live_range = erealloc(op_array->live_range, + sizeof(zend_live_range) * op_array->last_live_range); + + ZEND_ASSERT(start < end); + range = &op_array->live_range[op_array->last_live_range - 1]; + range->var = (uint32_t) (intptr_t) ZEND_CALL_VAR_NUM(NULL, op_array->last_var + var_num); + range->var |= kind; + range->start = start; + range->end = end; +} + +static void emit_live_range( + zend_op_array *op_array, uint32_t var_num, uint32_t start, uint32_t end, + zend_needs_live_range_cb needs_live_range) { + zend_op *def_opline = &op_array->opcodes[start], *orig_def_opline = def_opline; + zend_op *use_opline = &op_array->opcodes[end]; + uint32_t kind; + + switch (def_opline->opcode) { + /* These should never be the first def. */ + case ZEND_ADD_ARRAY_ELEMENT: + case ZEND_ADD_ARRAY_UNPACK: + case ZEND_ROPE_ADD: + ZEND_ASSERT(0); + return; + /* Result is boolean, it doesn't have to be destroyed. */ + case ZEND_JMPZ_EX: + case ZEND_JMPNZ_EX: + case ZEND_BOOL: + case ZEND_BOOL_NOT: + /* Classes don't have to be destroyed. */ + case ZEND_FETCH_CLASS: + case ZEND_DECLARE_ANON_CLASS: + /* FAST_CALLs don't have to be destroyed. */ + case ZEND_FAST_CALL: + return; + case ZEND_BEGIN_SILENCE: + kind = ZEND_LIVE_SILENCE; + start++; + break; + case ZEND_ROPE_INIT: + kind = ZEND_LIVE_ROPE; + /* ROPE live ranges include the generating opcode. */ + def_opline--; + break; + case ZEND_FE_RESET_R: + case ZEND_FE_RESET_RW: + kind = ZEND_LIVE_LOOP; + start++; + break; + /* Objects created via ZEND_NEW are only fully initialized + * after the DO_FCALL (constructor call). + * We are creating two live-ranges: ZEND_LINE_NEW for uninitialized + * part, and ZEND_LIVE_TMPVAR for initialized. + */ + case ZEND_NEW: + { + int level = 0; + uint32_t orig_start = start; + + while (def_opline + 1 < use_opline) { + def_opline++; + start++; + if (def_opline->opcode == ZEND_DO_FCALL) { + if (level == 0) { + break; + } + level--; + } else { + switch (def_opline->opcode) { + case ZEND_INIT_FCALL: + case ZEND_INIT_FCALL_BY_NAME: + case ZEND_INIT_NS_FCALL_BY_NAME: + case ZEND_INIT_DYNAMIC_CALL: + case ZEND_INIT_USER_CALL: + case ZEND_INIT_METHOD_CALL: + case ZEND_INIT_STATIC_METHOD_CALL: + case ZEND_NEW: + level++; + break; + case ZEND_DO_ICALL: + case ZEND_DO_UCALL: + case ZEND_DO_FCALL_BY_NAME: + level--; + break; + } + } + } + emit_live_range_raw(op_array, var_num, ZEND_LIVE_NEW, orig_start + 1, start + 1); + if (start + 1 == end) { + /* Trivial live-range, no need to store it. */ + return; + } + /* break missing intentionally */ + default: + start++; + kind = ZEND_LIVE_TMPVAR; + break; + } + case ZEND_COPY_TMP: + { + /* COPY_TMP has a split live-range: One from the definition until the use in + * "null" branch, and another from the start of the "non-null" branch to the + * FREE opcode. */ + uint32_t rt_var_num = + (uint32_t) (intptr_t) ZEND_CALL_VAR_NUM(NULL, op_array->last_var + var_num); + zend_op *block_start_op = use_opline; + + if (needs_live_range && !needs_live_range(op_array, orig_def_opline)) { + return; + } + + while ((block_start_op-1)->opcode == ZEND_FREE) { + block_start_op--; + } + + kind = ZEND_LIVE_TMPVAR; + start = block_start_op - op_array->opcodes; + if (start != end) { + emit_live_range_raw(op_array, var_num, kind, start, end); + } + + do { + use_opline--; + } while (!( + ((use_opline->op1_type & (IS_TMP_VAR|IS_VAR)) && use_opline->op1.var == rt_var_num) || + ((use_opline->op2_type & (IS_TMP_VAR|IS_VAR)) && use_opline->op2.var == rt_var_num) + )); + + start = def_opline + 1 - op_array->opcodes; + end = use_opline - op_array->opcodes; + emit_live_range_raw(op_array, var_num, kind, start, end); + return; + } + } + + /* Check hook to determine whether a live range is necessary, e.g. based on type info. */ + if (needs_live_range && !needs_live_range(op_array, orig_def_opline)) { + return; + } + + emit_live_range_raw(op_array, var_num, kind, start, end); +} + +static zend_bool is_fake_def(zend_op *opline) { + /* These opcodes only modify the result, not create it. */ + return opline->opcode == ZEND_ROPE_ADD + || opline->opcode == ZEND_ADD_ARRAY_ELEMENT + || opline->opcode == ZEND_ADD_ARRAY_UNPACK; +} + +static zend_bool keeps_op1_alive(zend_op *opline) { + /* These opcodes don't consume their OP1 operand, + * it is later freed by something else. */ + if (opline->opcode == ZEND_CASE + || opline->opcode == ZEND_SWITCH_LONG + || opline->opcode == ZEND_FETCH_LIST_R + || opline->opcode == ZEND_COPY_TMP) { + return 1; + } + ZEND_ASSERT(opline->opcode != ZEND_SWITCH_STRING + && opline->opcode != ZEND_FE_FETCH_R + && opline->opcode != ZEND_FE_FETCH_RW + && opline->opcode != ZEND_FETCH_LIST_W + && opline->opcode != ZEND_VERIFY_RETURN_TYPE + && opline->opcode != ZEND_BIND_LEXICAL + && opline->opcode != ZEND_ROPE_ADD); + return 0; +} + /* Live ranges must be sorted by increasing start opline */ static int cmp_live_range(const zend_live_range *a, const zend_live_range *b) { return a->start - b->start; } static void swap_live_range(zend_live_range *a, zend_live_range *b) { - zend_live_range tmp = *a; - *a = *b; - *b = tmp; + uint32_t tmp; + tmp = a->var; + a->var = b->var; + b->var = tmp; + tmp = a->start; + a->start = b->start; + b->start = tmp; + tmp = a->end; + a->end = b->end; + b->end = tmp; } -static void zend_sort_live_ranges(zend_op_array *op_array) { - zend_sort(op_array->live_range, op_array->last_live_range, sizeof(zend_live_range), - (compare_func_t) cmp_live_range, (swap_func_t) swap_live_range); + +static void zend_calc_live_ranges( + zend_op_array *op_array, zend_needs_live_range_cb needs_live_range) { + uint32_t opnum = op_array->last; + zend_op *opline = &op_array->opcodes[opnum]; + ALLOCA_FLAG(use_heap) + uint32_t var_offset = op_array->last_var; + uint32_t *last_use = do_alloca(sizeof(uint32_t) * op_array->T, use_heap); + memset(last_use, -1, sizeof(uint32_t) * op_array->T); + + ZEND_ASSERT(!op_array->live_range); + while (opnum > 0) { + opnum--; + opline--; + + if ((opline->result_type & (IS_TMP_VAR|IS_VAR)) && !is_fake_def(opline)) { + uint32_t var_num = EX_VAR_TO_NUM(opline->result.var) - var_offset; + /* Defs without uses can occur for two reasons: Either because the result is + * genuinely unused (e.g. omitted FREE opcode for an unused boolean result), or + * because there are multiple defining opcodes (e.g. JMPZ_EX and QM_ASSIGN), in + * which case the last one starts the live range. As such, we can simply ignore + * missing uses here. */ + if (EXPECTED(last_use[var_num] != (uint32_t) -1)) { + /* Skip trivial live-range */ + if (opnum + 1 != last_use[var_num]) { + uint32_t num; + +#if 1 + /* OP_DATA uses only op1 operand */ + ZEND_ASSERT(opline->opcode != ZEND_OP_DATA); + num = opnum; +#else + /* OP_DATA is really part of the previous opcode. */ + num = opnum - (opline->opcode == ZEND_OP_DATA); +#endif + emit_live_range(op_array, var_num, num, last_use[var_num], needs_live_range); + } + last_use[var_num] = (uint32_t) -1; + } + } + + if ((opline->op1_type & (IS_TMP_VAR|IS_VAR))) { + uint32_t var_num = EX_VAR_TO_NUM(opline->op1.var) - var_offset; + if (EXPECTED(last_use[var_num] == (uint32_t) -1)) { + if (EXPECTED(!keeps_op1_alive(opline))) { + /* OP_DATA is really part of the previous opcode. */ + last_use[var_num] = opnum - (opline->opcode == ZEND_OP_DATA); + } + } + } + if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) { + uint32_t var_num = EX_VAR_TO_NUM(opline->op2.var) - var_offset; + if (EXPECTED(last_use[var_num] == (uint32_t) -1)) { +#if 1 + /* OP_DATA uses only op1 operand */ + ZEND_ASSERT(opline->opcode != ZEND_OP_DATA); + last_use[var_num] = opnum; +#else + /* OP_DATA is really part of the previous opcode. */ + last_use[var_num] = opnum - (opline->opcode == ZEND_OP_DATA); +#endif + } + } + } + + if (op_array->last_live_range > 1) { + zend_live_range *r1 = op_array->live_range; + zend_live_range *r2 = r1 + op_array->last_live_range - 1; + + /* In most cases we need just revert the array */ + while (r1 < r2) { + swap_live_range(r1, r2); + r1++; + r2--; + } + + r1 = op_array->live_range; + r2 = r1 + op_array->last_live_range - 1; + while (r1 < r2) { + if (r1->start > (r1+1)->start) { + zend_sort(r1, r2 - r1 + 1, sizeof(zend_live_range), + (compare_func_t) cmp_live_range, (swap_func_t) swap_live_range); + break; + } + r1++; + } + } + + free_alloca(last_use, use_heap); +} + +ZEND_API void zend_recalc_live_ranges( + zend_op_array *op_array, zend_needs_live_range_cb needs_live_range) { + /* We assume that we never create live-ranges where there were none before. */ + ZEND_ASSERT(op_array->live_range); + efree(op_array->live_range); + op_array->live_range = NULL; + op_array->last_live_range = 0; + zend_calc_live_ranges(op_array, needs_live_range); } ZEND_API int pass_two(zend_op_array *op_array) @@ -509,8 +850,8 @@ ZEND_API int pass_two(zend_op_array *op_array) if (!ZEND_USER_CODE(op_array->type)) { return 0; } - if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) { - zend_update_extended_info(op_array); + if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_STMT) { + zend_update_extended_stmts(op_array); } if (CG(compiler_options) & ZEND_COMPILE_HANDLE_OP_ARRAY) { if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_HANDLER) { @@ -619,7 +960,6 @@ ZEND_API int pass_two(zend_op_array *op_array) break; } case ZEND_DECLARE_ANON_CLASS: - case ZEND_DECLARE_ANON_INHERITED_CLASS: case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: /* absolute index to relative offset */ @@ -667,16 +1007,7 @@ ZEND_API int pass_two(zend_op_array *op_array) opline++; } - if (op_array->live_range) { - int i; - - zend_sort_live_ranges(op_array); - for (i = 0; i < op_array->last_live_range; i++) { - op_array->live_range[i].var = - (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + (op_array->live_range[i].var / sizeof(zval))) | - (op_array->live_range[i].var & ZEND_LIVE_MASK); - } - } + zend_calc_live_ranges(op_array, NULL); return 0; } @@ -697,32 +1028,24 @@ ZEND_API binary_op_type get_binary_op(int opcode) { switch (opcode) { case ZEND_ADD: - case ZEND_ASSIGN_ADD: return (binary_op_type) add_function; case ZEND_SUB: - case ZEND_ASSIGN_SUB: return (binary_op_type) sub_function; case ZEND_MUL: - case ZEND_ASSIGN_MUL: return (binary_op_type) mul_function; case ZEND_POW: - case ZEND_ASSIGN_POW: return (binary_op_type) pow_function; case ZEND_DIV: - case ZEND_ASSIGN_DIV: return (binary_op_type) div_function; case ZEND_MOD: - case ZEND_ASSIGN_MOD: return (binary_op_type) mod_function; case ZEND_SL: - case ZEND_ASSIGN_SL: return (binary_op_type) shift_left_function; case ZEND_SR: - case ZEND_ASSIGN_SR: return (binary_op_type) shift_right_function; + case ZEND_PARENTHESIZED_CONCAT: case ZEND_FAST_CONCAT: case ZEND_CONCAT: - case ZEND_ASSIGN_CONCAT: return (binary_op_type) concat_function; case ZEND_IS_IDENTICAL: return (binary_op_type) is_identical_function; @@ -740,27 +1063,15 @@ ZEND_API binary_op_type get_binary_op(int opcode) case ZEND_SPACESHIP: return (binary_op_type) compare_function; case ZEND_BW_OR: - case ZEND_ASSIGN_BW_OR: return (binary_op_type) bitwise_or_function; case ZEND_BW_AND: - case ZEND_ASSIGN_BW_AND: return (binary_op_type) bitwise_and_function; case ZEND_BW_XOR: - case ZEND_ASSIGN_BW_XOR: return (binary_op_type) bitwise_xor_function; case ZEND_BOOL_XOR: return (binary_op_type) boolean_xor_function; default: + ZEND_ASSERT(0); return (binary_op_type) NULL; } } - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * indent-tabs-mode: t - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ |