Skip to content

Commit 4e1a962

Browse files
author
Andi Gutmans
committed
- Preliminary return ref patch. It breaks libzend so don't use this branch
right now.
1 parent 05f8c04 commit 4e1a962

File tree

5 files changed

+26
-13
lines changed

5 files changed

+26
-13
lines changed

Zend/zend-parser.y

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,8 @@ statement:
179179
| T_BREAK expr ';' { do_brk_cont(ZEND_BRK, &$2 CLS_CC); }
180180
| T_CONTINUE ';' { do_brk_cont(ZEND_CONT, NULL CLS_CC); }
181181
| T_CONTINUE expr ';' { do_brk_cont(ZEND_CONT, &$2 CLS_CC); }
182-
| T_RETURN ';' { do_return(NULL, 0 CLS_CC); }
183-
| T_RETURN expr ';' { do_return(&$2, 0 CLS_CC); }
184-
| T_RETURN '&' w_cvar ';' { do_return(&$3, 1 CLS_CC); }
182+
| T_RETURN ';' { do_return(NULL CLS_CC); }
183+
| T_RETURN expr ';' { do_return(&$2 CLS_CC); }
185184
| T_GLOBAL global_var_list
186185
| T_STATIC static_var_list
187186
| T_ECHO echo_expr_list ';'
@@ -202,9 +201,9 @@ use_filename:
202201

203202

204203
declaration_statement:
205-
T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } T_STRING { do_begin_function_declaration(&$1, &$3, 0 CLS_CC); }
204+
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); }
206205
'(' parameter_list ')' '{' inner_statement_list '}' { do_end_function_declaration(&$1 CLS_CC); }
207-
| T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } T_STRING { do_begin_function_declaration(&$1, &$3, 0 CLS_CC); }
206+
| 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); }
208207
parameter_list '(' inner_statement_list ')' ';' { do_end_function_declaration(&$1 CLS_CC); }
209208
| T_CLASS T_STRING { do_begin_class_declaration(&$2, NULL CLS_CC); } '{' class_statement_list '}' { do_end_class_declaration(CLS_C); }
210209
| 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:
348347

349348
class_statement:
350349
T_VAR class_variable_decleration ';'
351-
| T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } T_STRING { do_begin_function_declaration(&$1, &$3, 1 CLS_CC); } '('
350+
| 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); } '('
352351
parameter_list ')' '{' inner_statement_list '}' { do_end_function_declaration(&$1 CLS_CC); }
353-
| T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } T_STRING { do_begin_function_declaration(&$1, &$3, 1 CLS_CC); }
352+
| 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); }
354353
parameter_list '(' inner_statement_list ')' ';' { do_end_function_declaration(&$1 CLS_CC); }
355354

356355
;
357356

357+
is_reference:
358+
/* empty */ { $$.op_type = ZEND_RETURN_VAL; }
359+
| '&' { $$.op_type = ZEND_RETURN_REF; }
358360

359361
class_variable_decleration:
360362
class_variable_decleration ',' T_VARIABLE { do_declare_property(&$3, NULL CLS_CC); }

Zend/zend_compile.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,7 @@ void do_free(znode *op1 CLS_DC)
667667
}
668668

669669

670-
void do_begin_function_declaration(znode *function_token, znode *function_name, int is_method CLS_DC)
670+
void do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference CLS_DC)
671671
{
672672
zend_op_array op_array;
673673
char *name = function_name->u.constant.value.str.val;
@@ -678,8 +678,10 @@ void do_begin_function_declaration(znode *function_token, znode *function_name,
678678
zend_str_tolower(name, name_len);
679679

680680
init_op_array(&op_array, INITIAL_OP_ARRAY_SIZE);
681+
681682
op_array.function_name = name;
682683
op_array.arg_types = NULL;
684+
op_array.return_reference = return_reference;
683685

684686
if (is_method) {
685687
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)
948950
return 0;
949951
}
950952

951-
void do_return(znode *expr, int return_reference CLS_DC)
953+
void do_return(znode *expr CLS_DC)
952954
{
953955
zend_op *opline;
954956

@@ -963,7 +965,7 @@ void do_return(znode *expr, int return_reference CLS_DC)
963965
opline = get_next_op(CG(active_op_array) CLS_CC);
964966

965967
opline->opcode = ZEND_RETURN;
966-
opline->extended_value = return_reference;
968+
967969
if (expr) {
968970
opline->op1 = *expr;
969971
} else {

Zend/zend_compile.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ struct _zend_op_array {
115115
int last_executed_op_number;
116116
int backpatch_count;
117117
#endif
118+
zend_bool return_reference;
118119

119120
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
120121
};
@@ -260,14 +261,14 @@ void do_add_char(znode *result, znode *op1, znode *op2 CLS_DC);
260261
void do_add_string(znode *result, znode *op1, znode *op2 CLS_DC);
261262
void do_add_variable(znode *result, znode *op1, znode *op2 CLS_DC);
262263

263-
void do_begin_function_declaration(znode *function_token, znode *function_name, int is_method CLS_DC);
264+
void do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference CLS_DC);
264265
void do_end_function_declaration(znode *function_token CLS_DC);
265266
void do_receive_arg(int op, znode *var, znode *offset, znode *initialization, unsigned char pass_type CLS_DC);
266267
int do_begin_function_call(znode *function_name CLS_DC);
267268
void do_begin_dynamic_function_call(znode *function_name CLS_DC);
268269
void do_begin_class_member_function_call(znode *class_name, znode *function_name CLS_DC);
269270
void do_end_function_call(znode *function_name, znode *result, znode *argument_list, int is_method, int is_dynamic_fcall CLS_DC);
270-
void do_return(znode *expr, int return_reference CLS_DC);
271+
void do_return(znode *expr CLS_DC);
271272
ZEND_API int do_bind_function_or_class(zend_op *opline, HashTable *function_table, HashTable *class_table, int compile_time);
272273
void do_early_binding(CLS_D);
273274

@@ -612,4 +613,7 @@ int zendlex(znode *zendlval CLS_DC);
612613
) \
613614
)
614615

616+
#define ZEND_RETURN_VAL 0
617+
#define ZEND_RETURN_REF 1
618+
615619
#endif /* _COMPILE_H */

Zend/zend_execute.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1549,7 +1549,10 @@ binary_assign_op_addr: {
15491549
zval *retval_ptr;
15501550
zval **retval_ptr_ptr;
15511551

1552-
if (opline->extended_value) {
1552+
if ((EG(active_op_array)->return_reference == ZEND_RETURN_REF) &&
1553+
(opline->op1.op_type != IS_CONST) &&
1554+
(opline->op1.op_type != IS_TMP_VAR)) {
1555+
15531556
retval_ptr_ptr = get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_R);
15541557

15551558
if (!PZVAL_IS_REF(*retval_ptr_ptr)) {

Zend/zend_opcode.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ void init_op_array(zend_op_array *op_array, int initial_ops_size)
9999

100100
op_array->uses_globals = 0;
101101

102+
op_array->return_reference = 0;
103+
102104
zend_llist_apply_with_argument(&zend_extensions, (void (*)(void *, void *)) zend_extension_op_array_ctor_handler, op_array);
103105
}
104106

0 commit comments

Comments
 (0)