summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndi Gutmans <andi@php.net>1999-12-15 09:10:22 +0000
committerAndi Gutmans <andi@php.net>1999-12-15 09:10:22 +0000
commit4e1a9625c61098bdd209a9a6015f592485d15a91 (patch)
tree8db7cd385569282e7c40fd71a6e641c030443c29
parent05f8c04928a53ad64f43ed78eddae684f513aefa (diff)
downloadphp-git-4e1a9625c61098bdd209a9a6015f592485d15a91.tar.gz
- Preliminary return ref patch. It breaks libzend so don't use this branch
right now.
-rw-r--r--Zend/zend-parser.y16
-rw-r--r--Zend/zend_compile.c8
-rw-r--r--Zend/zend_compile.h8
-rw-r--r--Zend/zend_execute.c5
-rw-r--r--Zend/zend_opcode.c2
5 files changed, 26 insertions, 13 deletions
diff --git a/Zend/zend-parser.y b/Zend/zend-parser.y
index 81e9408718..da95f04f97 100644
--- a/Zend/zend-parser.y
+++ b/Zend/zend-parser.y
@@ -179,9 +179,8 @@ statement:
| T_BREAK expr ';' { do_brk_cont(ZEND_BRK, &$2 CLS_CC); }
| T_CONTINUE ';' { do_brk_cont(ZEND_CONT, NULL CLS_CC); }
| T_CONTINUE expr ';' { do_brk_cont(ZEND_CONT, &$2 CLS_CC); }
- | T_RETURN ';' { do_return(NULL, 0 CLS_CC); }
- | T_RETURN expr ';' { do_return(&$2, 0 CLS_CC); }
- | T_RETURN '&' w_cvar ';' { do_return(&$3, 1 CLS_CC); }
+ | T_RETURN ';' { do_return(NULL CLS_CC); }
+ | T_RETURN expr ';' { do_return(&$2 CLS_CC); }
| T_GLOBAL global_var_list
| T_STATIC static_var_list
| T_ECHO echo_expr_list ';'
@@ -202,9 +201,9 @@ use_filename:
declaration_statement:
- T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } T_STRING { do_begin_function_declaration(&$1, &$3, 0 CLS_CC); }
+ T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { do_begin_function_declaration(&$1, &$4, 0, $3.op_type CLS_CC); }
'(' parameter_list ')' '{' inner_statement_list '}' { do_end_function_declaration(&$1 CLS_CC); }
- | T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } T_STRING { do_begin_function_declaration(&$1, &$3, 0 CLS_CC); }
+ | T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { do_begin_function_declaration(&$1, &$4, 0, $3.op_type CLS_CC); }
parameter_list '(' inner_statement_list ')' ';' { do_end_function_declaration(&$1 CLS_CC); }
| T_CLASS T_STRING { do_begin_class_declaration(&$2, NULL CLS_CC); } '{' class_statement_list '}' { do_end_class_declaration(CLS_C); }
| T_CLASS T_STRING T_EXTENDS T_STRING { do_begin_class_declaration(&$2, &$4 CLS_CC); } '{' class_statement_list '}' { do_end_class_declaration(CLS_C); }
@@ -348,13 +347,16 @@ class_statement_list:
class_statement:
T_VAR class_variable_decleration ';'
- | T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } T_STRING { do_begin_function_declaration(&$1, &$3, 1 CLS_CC); } '('
+ | T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { do_begin_function_declaration(&$1, &$4, 1, $3.op_type CLS_CC); } '('
parameter_list ')' '{' inner_statement_list '}' { do_end_function_declaration(&$1 CLS_CC); }
- | T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } T_STRING { do_begin_function_declaration(&$1, &$3, 1 CLS_CC); }
+ | T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { do_begin_function_declaration(&$1, &$4, 1, $3.op_type CLS_CC); }
parameter_list '(' inner_statement_list ')' ';' { do_end_function_declaration(&$1 CLS_CC); }
;
+is_reference:
+ /* empty */ { $$.op_type = ZEND_RETURN_VAL; }
+ | '&' { $$.op_type = ZEND_RETURN_REF; }
class_variable_decleration:
class_variable_decleration ',' T_VARIABLE { do_declare_property(&$3, NULL CLS_CC); }
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 9922466aa6..539bfaa613 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -667,7 +667,7 @@ void do_free(znode *op1 CLS_DC)
}
-void do_begin_function_declaration(znode *function_token, znode *function_name, int is_method CLS_DC)
+void do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference CLS_DC)
{
zend_op_array op_array;
char *name = function_name->u.constant.value.str.val;
@@ -678,8 +678,10 @@ void do_begin_function_declaration(znode *function_token, znode *function_name,
zend_str_tolower(name, name_len);
init_op_array(&op_array, INITIAL_OP_ARRAY_SIZE);
+
op_array.function_name = name;
op_array.arg_types = NULL;
+ op_array.return_reference = return_reference;
if (is_method) {
zend_hash_update(&CG(active_class_entry)->function_table, name, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
@@ -948,7 +950,7 @@ static int generate_free_foreach_copy(znode *foreach_copy CLS_DC)
return 0;
}
-void do_return(znode *expr, int return_reference CLS_DC)
+void do_return(znode *expr CLS_DC)
{
zend_op *opline;
@@ -963,7 +965,7 @@ void do_return(znode *expr, int return_reference CLS_DC)
opline = get_next_op(CG(active_op_array) CLS_CC);
opline->opcode = ZEND_RETURN;
- opline->extended_value = return_reference;
+
if (expr) {
opline->op1 = *expr;
} else {
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index f8a1d6abdc..a026b2c4b0 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -115,6 +115,7 @@ struct _zend_op_array {
int last_executed_op_number;
int backpatch_count;
#endif
+ zend_bool return_reference;
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
};
@@ -260,14 +261,14 @@ void do_add_char(znode *result, znode *op1, znode *op2 CLS_DC);
void do_add_string(znode *result, znode *op1, znode *op2 CLS_DC);
void do_add_variable(znode *result, znode *op1, znode *op2 CLS_DC);
-void do_begin_function_declaration(znode *function_token, znode *function_name, int is_method CLS_DC);
+void do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference CLS_DC);
void do_end_function_declaration(znode *function_token CLS_DC);
void do_receive_arg(int op, znode *var, znode *offset, znode *initialization, unsigned char pass_type CLS_DC);
int do_begin_function_call(znode *function_name CLS_DC);
void do_begin_dynamic_function_call(znode *function_name CLS_DC);
void do_begin_class_member_function_call(znode *class_name, znode *function_name CLS_DC);
void do_end_function_call(znode *function_name, znode *result, znode *argument_list, int is_method, int is_dynamic_fcall CLS_DC);
-void do_return(znode *expr, int return_reference CLS_DC);
+void do_return(znode *expr CLS_DC);
ZEND_API int do_bind_function_or_class(zend_op *opline, HashTable *function_table, HashTable *class_table, int compile_time);
void do_early_binding(CLS_D);
@@ -612,4 +613,7 @@ int zendlex(znode *zendlval CLS_DC);
) \
)
+#define ZEND_RETURN_VAL 0
+#define ZEND_RETURN_REF 1
+
#endif /* _COMPILE_H */
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 59918742ed..9ba08a857c 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -1549,7 +1549,10 @@ do_fcall_common:
zval *retval_ptr;
zval **retval_ptr_ptr;
- if (opline->extended_value) {
+ if ((EG(active_op_array)->return_reference == ZEND_RETURN_REF) &&
+ (opline->op1.op_type != IS_CONST) &&
+ (opline->op1.op_type != IS_TMP_VAR)) {
+
retval_ptr_ptr = get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_R);
if (!PZVAL_IS_REF(*retval_ptr_ptr)) {
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index 5aa107305b..53d066ac09 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -99,6 +99,8 @@ void init_op_array(zend_op_array *op_array, int initial_ops_size)
op_array->uses_globals = 0;
+ op_array->return_reference = 0;
+
zend_llist_apply_with_argument(&zend_extensions, (void (*)(void *, void *)) zend_extension_op_array_ctor_handler, op_array);
}