return value of the function
The function in PHP has a return value, and no return returns null
(1) Return statement
From the Zend/zend_language_parser.y file, you can confirm that the Zend_do_return function is called by its generated intermediate code.
void Zend_do_return (znode *expr, int do_end_vparse TSRMLS_DC)/* * {{*/{zend_op * Opline; int Start_op_number, End_op_number; if (do_end_vparse) {if (CG (active_op_array)->return_reference &&!zend_is_function_or_me Thod_call (expr)) {Zend_do_end_variable_parse (expr, bp_var_w, 0 TSRMLS_CC);/* Process return reference */} else { Zend_do_end_variable_parse (expr, bp_var_r, 0 TSRMLS_CC);/* Handle General variable return */}} ...//omit, take other intermediate code operation opline- >opcode = Zend_return; if (expr) {opline->op1 = *expr; if (do_end_vparse && zend_is_function_or_method_call (expr)) {Opline->extended_value = Zend_returns_ FUNCTION; }} else {opline->op1.op_type = Is_const; Init_zval (opline->op1.u.constant); } set_unused (OPLINE->OP2);} /* }}} */
The
Generates an intermediate code of Zend_return. The type of the first operand is the action type of the expression when the return value is an expression that is available, otherwise the type is is_const. This is useful when performing intermediate code functions in subsequent computations. Depending on the operand, the Zend_return intermediate code executes Zend_return_spec_const_handler,zend_return_spec_tmp_handler or ZEND_RETURN_SPEC_TMP_ HANDLER. The execution flow of these three functions is basically similar, including the handling of some errors. Here we take Zend_return_spec_const_handler as an example to illustrate the execution of function return values:
static int Zend_fastcall Zend_return_spec_const_handler (zend_opcode_handler_args) {Zend_op *opline = EX (opline); Zval *retval_ptr; Zval **retval_ptr_ptr; if (EG (active_op_array)->return_reference = = Zend_return_ref) {//ǔǔŷsá\ɂƶmļ@ɗáļļif (Is_const = = IS_C Onst | | Is_const = = Is_tmp_var) {/* Not supposed to happen, but we'll allow it */Zend_error (E_notice, " Only variable references \ Should is returned by reference "); Goto Return_by_value; } retval_ptr_ptr = NULL; Ǔǔŕif (Is_const = = Is_var &&!retval_ptr_ptr) {Zend_error_noreturn (E_error, "Cannot retur n string offsets by reference "); } if (Is_const = = Is_var &&!) Z_ISREF_PP (retval_ptr_ptr)) {if (Opline->extended_value = = Zend_returns_function && ex_t (Opline->op1.u.var). var.fcall_returned_reference) {} else if (ex_t (Opline->op1.u.var). var.ptr_ptr = = &ex_t (opline->op1.u.var). var.ptr) {if (Is_const = = Is_var && amp;!0) {/* undo the effect of get_zval_ptr_ptr () */Pzval_lock (*RETVAL_PTR_PTR) ; } zend_error (E_notice, "only variable references \ Should is returned by reference"); Goto Return_by_value; }} if (EG (return_value_ptr_ptr)) {//ǔǔŷs separate_zval_to_make_is_ref (retval_ptr_ptr); IS_REFGCŐĘZ_ADDREF_PP (RETVAL_PTR_PTR); Refcountgcœďx1 (*eg (return_value_ptr_ptr)) = (*retval_ptr_ptr); }} else {return_by_value:retval_ptr = &opline->op1.u.constant; if (! EG (return_value_ptr_ptr)) {if (Is_const = = Is_tmp_var) {}} else if (!0) {/* Not a temp V AR */if (Is_const = = Is_const | | EG (Active_op_array)->return_rEference = = Zend_return_ref | | (Pzval_is_ref (retval_ptr) && z_refcount_p (retval_ptr) > 0)) {Zval *ret; Alloc_zval (ret); Init_pzval_copy (ret, retval_ptr); ŁͿʍǔǔŕzval_copy_ctor (ret); *eg (return_value_ptr_ptr) = ret; } else {*eg (return_value_ptr_ptr) = Retval_ptr;//ħ6ɶŕz_addref_p (RETVAL_PTR); }} else {Zval *ret; Alloc_zval (ret); Init_pzval_copy (ret, retval_ptr); ŁͿʍǔǔŕ*eg (return_value_ptr_ptr) = ret; }} return Zend_leave_helper_spec (Zend_opcode_handler_args_passthru); Ǔǔĉșʒ}
The return value of the
function is stored in *eg (RETURN_VALUE_PTR_PTR) when the program executes. The Zend kernel distinguishes between value return and reference return, and on this basis the constants, temporary variables, and other types of variables are treated differently on return. After the return is executed, the Zend kernel clears the variables used inside the function by calling the Zend_leave_helper_spec function. This is one of the reasons why the Zend kernel automatically adds null to the function.