}
/* }}} */
-void zend_do_while_cond(znode *expr, znode *close_bracket_token TSRMLS_DC) /* {{{ */
-{
- int while_cond_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_JMPZ;
- SET_NODE(opline->op1, expr);
- close_bracket_token->u.op.opline_num = while_cond_op_number;
- SET_UNUSED(opline->op2);
-
- do_begin_loop(TSRMLS_C);
- INC_BPC(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_while_end(const znode *while_token, const znode *close_bracket_token TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- /* add unconditional jump */
- opline->opcode = ZEND_JMP;
- opline->op1.opline_num = while_token->u.op.opline_num;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
-
- /* update while's conditional jmp */
- CG(active_op_array)->opcodes[close_bracket_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
-
- do_end_loop(while_token->u.op.opline_num, 0 TSRMLS_CC);
-
- DEC_BPC(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_for_cond(znode *expr, znode *second_semicolon_token TSRMLS_DC) /* {{{ */
-{
- int for_cond_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_JMPZNZ;
- SET_NODE(opline->op1, expr); /* the conditional expression */
- second_semicolon_token->u.op.opline_num = for_cond_op_number;
- SET_UNUSED(opline->op2);
-}
-/* }}} */
-
-void zend_do_for_before_statement(const znode *cond_start, const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_JMP;
- opline->op1.opline_num = cond_start->u.op.opline_num;
- CG(active_op_array)->opcodes[second_semicolon_token->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
-
- do_begin_loop(TSRMLS_C);
-
- INC_BPC(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_for_end(const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_JMP;
- opline->op1.opline_num = second_semicolon_token->u.op.opline_num+1;
- CG(active_op_array)->opcodes[second_semicolon_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
-
- do_end_loop(second_semicolon_token->u.op.opline_num+1, 0 TSRMLS_CC);
-
- DEC_BPC(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_pre_incdec(znode *result, znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
-{
- int last_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline;
-
- if (last_op_number > 0) {
- zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
-
- if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
- last_op->opcode = (op==ZEND_PRE_INC)?ZEND_PRE_INC_OBJ:ZEND_PRE_DEC_OBJ;
- last_op->result_type = IS_VAR;
- last_op->result.var = get_temporary_variable(CG(active_op_array));
- GET_NODE(result, last_op->result);
- return;
- }
- }
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = op;
- SET_NODE(opline->op1, op1);
- SET_UNUSED(opline->op2);
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- GET_NODE(result, opline->result);
-}
-/* }}} */
-
-void zend_do_post_incdec(znode *result, znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
-{
- int last_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline;
-
- if (last_op_number > 0) {
- zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
-
- if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
- last_op->opcode = (op==ZEND_POST_INC)?ZEND_POST_INC_OBJ:ZEND_POST_DEC_OBJ;
- last_op->result_type = IS_TMP_VAR;
- last_op->result.var = get_temporary_variable(CG(active_op_array));
- GET_NODE(result, last_op->result);
- return;
- }
- }
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = op;
- SET_NODE(opline->op1, op1);
- SET_UNUSED(opline->op2);
- opline->result_type = IS_TMP_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- GET_NODE(result, opline->result);
-}
-/* }}} */
-
-void zend_do_if_cond(znode *cond, znode *closing_bracket_token TSRMLS_DC) /* {{{ */
-{
- int if_cond_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_JMPZ;
- SET_NODE(opline->op1, cond);
- closing_bracket_token->u.op.opline_num = if_cond_op_number;
- SET_UNUSED(opline->op2);
- INC_BPC(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_if_after_statement(const znode *closing_bracket_token, unsigned char initialize TSRMLS_DC) /* {{{ */
-{
- int if_end_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- zend_llist *jmp_list_ptr;
-
- opline->opcode = ZEND_JMP;
- /* save for backpatching */
- if (initialize) {
- zend_llist jmp_list;
-
- zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
- zend_stack_push(&CG(bp_stack), (void *) &jmp_list);
- }
- jmp_list_ptr = zend_stack_top(&CG(bp_stack));
- zend_llist_add_element(jmp_list_ptr, &if_end_op_number);
-
- CG(active_op_array)->opcodes[closing_bracket_token->u.op.opline_num].op2.opline_num = if_end_op_number+1;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
-}
-/* }}} */
-
-void zend_do_if_end(TSRMLS_D) /* {{{ */
-{
- int next_op_number = get_next_op_number(CG(active_op_array));
- zend_llist *jmp_list_ptr = zend_stack_top(&CG(bp_stack));
- zend_llist_element *le;
-
- for (le=jmp_list_ptr->head; le; le = le->next) {
- CG(active_op_array)->opcodes[*((int *) le->data)].op1.opline_num = next_op_number;
- }
- zend_llist_destroy(jmp_list_ptr);
- zend_stack_del_top(&CG(bp_stack));
- DEC_BPC(CG(active_op_array));
-}
-/* }}} */
-
void zend_check_writable_variable(const znode *variable) /* {{{ */
{
zend_uint type = variable->EA;
}
/* }}} */
-void zend_do_do_while_begin(TSRMLS_D) /* {{{ */
-{
- do_begin_loop(TSRMLS_C);
- INC_BPC(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_do_while_end(const znode *do_token, const znode *expr_open_bracket, znode *expr TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_JMPNZ;
- SET_NODE(opline->op1, expr);
- opline->op2.opline_num = do_token->u.op.opline_num;
- SET_UNUSED(opline->op2);
-
- do_end_loop(expr_open_bracket->u.op.opline_num, 0 TSRMLS_CC);
-
- DEC_BPC(CG(active_op_array));
-}
-/* }}} */
-
void zend_do_brk_cont(zend_uchar op, znode *expr TSRMLS_DC) /* {{{ */
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
}
/* }}} */
-void zend_do_switch_cond(const znode *cond TSRMLS_DC) /* {{{ */
-{
- zend_switch_entry switch_entry;
-
- switch_entry.cond = *cond;
- switch_entry.default_case = -1;
- switch_entry.control_var = -1;
- zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry);
-
- do_begin_loop(TSRMLS_C);
-
- INC_BPC(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_switch_end(const znode *case_list TSRMLS_DC) /* {{{ */
-{
- zend_op *opline;
- zend_switch_entry *switch_entry_ptr = zend_stack_top(&CG(switch_cond_stack));
-
- /* add code to jmp to default case */
- if (switch_entry_ptr->default_case != -1) {
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_JMP;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
- opline->op1.opline_num = switch_entry_ptr->default_case;
- }
-
- if (case_list->op_type != IS_UNUSED) { /* non-empty switch */
- int next_op_number = get_next_op_number(CG(active_op_array));
-
- CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
- }
-
- /* remember break/continue loop information */
- CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].brk = get_next_op_number(CG(active_op_array));
- CG(context).current_brk_cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].parent;
-
- if (switch_entry_ptr->cond.op_type==IS_VAR || switch_entry_ptr->cond.op_type==IS_TMP_VAR) {
- /* emit free for the switch condition*/
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = (switch_entry_ptr->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
- SET_NODE(opline->op1, &switch_entry_ptr->cond);
- SET_UNUSED(opline->op2);
- }
- if (switch_entry_ptr->cond.op_type == IS_CONST) {
- zval_dtor(&switch_entry_ptr->cond.u.constant);
- }
-
- zend_stack_del_top(&CG(switch_cond_stack));
-
- DEC_BPC(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_case_before_statement(const znode *case_list, znode *case_token, znode *case_expr TSRMLS_DC) /* {{{ */
-{
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- int next_op_number;
- zend_switch_entry *switch_entry_ptr = zend_stack_top(&CG(switch_cond_stack));
- znode result;
-
- if (switch_entry_ptr->control_var == -1) {
- switch_entry_ptr->control_var = get_temporary_variable(CG(active_op_array));
- }
- opline->opcode = ZEND_CASE;
- opline->result.var = switch_entry_ptr->control_var;
- opline->result_type = IS_TMP_VAR;
- SET_NODE(opline->op1, &switch_entry_ptr->cond);
- SET_NODE(opline->op2, case_expr);
- if (opline->op1_type == IS_CONST) {
- zval_copy_ctor(&CONSTANT(opline->op1.constant));
- }
- GET_NODE(&result, opline->result);
-
- next_op_number = get_next_op_number(CG(active_op_array));
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_JMPZ;
- SET_NODE(opline->op1, &result);
- SET_UNUSED(opline->op2);
- case_token->u.op.opline_num = next_op_number;
-
- if (case_list->op_type==IS_UNUSED) {
- return;
- }
- next_op_number = get_next_op_number(CG(active_op_array));
- CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
-}
-/* }}} */
-
-void zend_do_case_after_statement(znode *result, const znode *case_token TSRMLS_DC) /* {{{ */
-{
- int next_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_JMP;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
- result->u.op.opline_num = next_op_number;
-
- switch (CG(active_op_array)->opcodes[case_token->u.op.opline_num].opcode) {
- case ZEND_JMP:
- CG(active_op_array)->opcodes[case_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array));
- break;
- case ZEND_JMPZ:
- CG(active_op_array)->opcodes[case_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
- break;
- }
-}
-/* }}} */
-
-void zend_do_default_before_statement(const znode *case_list, znode *default_token TSRMLS_DC) /* {{{ */
-{
- int next_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- zend_switch_entry *switch_entry_ptr = zend_stack_top(&CG(switch_cond_stack));
-
- opline->opcode = ZEND_JMP;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
- default_token->u.op.opline_num = next_op_number;
-
- next_op_number = get_next_op_number(CG(active_op_array));
- switch_entry_ptr->default_case = next_op_number;
-
- if (case_list->op_type==IS_UNUSED) {
- return;
- }
- CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
-}
-/* }}} */
-
void zend_do_begin_class_declaration(const znode *class_token, znode *class_name, const znode *parent_class_name TSRMLS_DC) /* {{{ */
{
zend_op *opline;
}
/* }}} */
-static zend_bool zend_can_write_to_variable(zend_ast *ast);
-
-void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, znode *array, znode *as_token, int variable TSRMLS_DC) /* {{{ */
-{
- zend_op *opline;
- zend_bool is_variable;
- zend_op dummy_opline;
-
- open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
- if (variable) {
- if (zend_is_call(array->u.ast) || !zend_can_write_to_variable(array->u.ast)) {
- is_variable = 0;
- AST_COMPILE_VAR(array, array->u.ast, BP_VAR_R);
- } else {
- is_variable = 1;
- AST_COMPILE_VAR(array, array->u.ast, BP_VAR_W);
- }
- } else {
- is_variable = 0;
- }
-
- /* save the location of FE_RESET */
- foreach_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- /* Preform array reset */
- opline->opcode = ZEND_FE_RESET;
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- SET_NODE(opline->op1, array);
- SET_UNUSED(opline->op2);
- opline->extended_value = is_variable ? ZEND_FE_RESET_VARIABLE : 0;
-
- COPY_NODE(dummy_opline.result, opline->result);
- zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline);
-
- /* save the location of FE_FETCH */
- as_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_FE_FETCH;
- opline->result_type = IS_VAR;
- opline->result.var = get_temporary_variable(CG(active_op_array));
- COPY_NODE(opline->op1, dummy_opline.result);
- opline->extended_value = 0;
- SET_UNUSED(opline->op2);
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- opline->opcode = ZEND_OP_DATA;
- /* Allocate enough space to keep HashPointer on VM stack */
- opline->op1_type = IS_TMP_VAR;
- opline->op1.var = get_temporary_variable(CG(active_op_array));
- if (sizeof(HashPointer) > sizeof(zval)) {
- /* Make shure 1 zval is enough for HashPointer (2 must be enough) */
- get_temporary_variable(CG(active_op_array));
- }
- SET_UNUSED(opline->op2);
- SET_UNUSED(opline->result);
-}
-/* }}} */
-
-void zend_compile_assign(znode *result, zend_ast *ast TSRMLS_DC);
-static void zend_compile_list_assign(znode *result, zend_ast *list_ast, znode *expr_node TSRMLS_DC);
-zend_op *zend_compile_assign_ref_common(znode *result, zend_ast *target_ast, znode *source_node TSRMLS_DC);
-
-void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token, const znode *as_token, znode *value, znode *key TSRMLS_DC) /* {{{ */
-{
- zend_op *opline;
- znode dummy, value_node;
- zend_bool assign_by_ref=0;
-
- opline = &CG(active_op_array)->opcodes[as_token->u.op.opline_num];
- if (key->op_type != IS_UNUSED) {
- znode *tmp;
-
- /* switch between the key and value... */
- tmp = key;
- key = value;
- value = tmp;
-
- /* Mark extended_value in case both key and value are being used */
- opline->extended_value |= ZEND_FE_FETCH_WITH_KEY;
- }
-
- if ((key->op_type != IS_UNUSED)) {
- if (key->EA & ZEND_PARSED_REFERENCE_VARIABLE) {
- zend_error_noreturn(E_COMPILE_ERROR, "Key element cannot be a reference");
- }
- if (key->EA & ZEND_PARSED_LIST_EXPR) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use list as key element");
- }
- }
-
- // TODO.AST check writable
- if (value->EA & ZEND_PARSED_REFERENCE_VARIABLE) {
- assign_by_ref = 1;
-
- /* Mark extended_value for assign-by-reference */
- opline->extended_value |= ZEND_FE_FETCH_BYREF;
- CG(active_op_array)->opcodes[foreach_token->u.op.opline_num].extended_value |= ZEND_FE_RESET_REFERENCE;
- } else {
- zend_op *fetch = &CG(active_op_array)->opcodes[foreach_token->u.op.opline_num];
- if (fetch->extended_value == ZEND_FE_RESET_VARIABLE) {
- zend_op *end = &CG(active_op_array)->opcodes[open_brackets_token->u.op.opline_num];
-
- /* Change "write context" into "read context" */
- fetch->extended_value = 0; /* reset ZEND_FE_RESET_VARIABLE */
- while (fetch != end) {
- --fetch;
- if (fetch->opcode == ZEND_FETCH_DIM_W && fetch->op2_type == IS_UNUSED) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
- }
- if (fetch->opcode == ZEND_SEPARATE) {
- MAKE_NOP(fetch);
- } else {
- fetch->opcode -= 3; /* FETCH_W -> FETCH_R */
- }
- }
- }
- }
-
- GET_NODE(&value_node, opline->result);
-
- if (value->EA & ZEND_PARSED_LIST_EXPR) {
- zend_compile_list_assign(&dummy, value->u.ast, &value_node TSRMLS_CC);
- zend_do_free(&dummy TSRMLS_CC);
- zend_ast_destroy(value->u.ast);
- } else {
- if (assign_by_ref) {
- zend_compile_assign_ref_common(NULL, value->u.ast, &value_node TSRMLS_CC);
- zend_ast_destroy(value->u.ast);
- } else {
- zend_ast *assign_ast = zend_ast_create_binary(
- ZEND_AST_ASSIGN, value->u.ast, AST_ZNODE(&value_node));
- AST_COMPILE(&dummy, assign_ast);
- zend_do_free(&dummy TSRMLS_CC);
- }
- }
-
- if (key->op_type != IS_UNUSED) {
- znode key_node;
-
- opline = &CG(active_op_array)->opcodes[as_token->u.op.opline_num+1];
- opline->result_type = IS_TMP_VAR;
- opline->result.opline_num = get_temporary_variable(CG(active_op_array));
- GET_NODE(&key_node, opline->result);
-
- zend_ast *assign_ast = zend_ast_create_binary(
- ZEND_AST_ASSIGN, key->u.ast, AST_ZNODE(&key_node));
- AST_COMPILE(&dummy, assign_ast);
- zend_do_free(&dummy TSRMLS_CC);
- }
-
- do_begin_loop(TSRMLS_C);
- INC_BPC(CG(active_op_array));
-}
-/* }}} */
-
-void zend_do_foreach_end(const znode *foreach_token, const znode *as_token TSRMLS_DC) /* {{{ */
-{
- zend_op *container_ptr;
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- opline->opcode = ZEND_JMP;
- opline->op1.opline_num = as_token->u.op.opline_num;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
-
- CG(active_op_array)->opcodes[foreach_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array)); /* FE_RESET */
- CG(active_op_array)->opcodes[as_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array)); /* FE_FETCH */
-
- do_end_loop(as_token->u.op.opline_num, 1 TSRMLS_CC);
-
- container_ptr = zend_stack_top(&CG(foreach_copy_stack));
- generate_free_foreach_copy(container_ptr TSRMLS_CC);
- zend_stack_del_top(&CG(foreach_copy_stack));
-
- DEC_BPC(CG(active_op_array));
-}
-/* }}} */
-
void zend_do_declare_begin(TSRMLS_D) /* {{{ */
{
zend_stack_push(&CG(declare_stack), &CG(declarables));