@@ -6653,7 +6653,7 @@ typedef struct {
66536653 znode value ;
66546654} zend_pm_binding ;
66556655
6656- static void zend_compile_pattern (zend_ast * ast , znode * expr_node , bool consume_expr , uint32_t false_opnum , zend_pm_context * context );
6656+ static void zend_compile_pattern (zend_ast * ast , znode * result , znode * expr_node , bool consume_expr , uint32_t false_opnum , zend_pm_context * context );
66576657static zend_type zend_compile_single_typename (zend_ast * ast );
66586658
66596659static void zend_pm_context_init (zend_pm_context * context )
@@ -6699,7 +6699,7 @@ static void zend_pm_labels_replace(zend_pm_context *context, uint32_t start_opnu
66996699 opline -> op1 .opline_num = labels [- opline -> op1 .opline_num ];
67006700 }
67016701 break ;
6702- case ZEND_JMPZ :
6702+ case ZEND_JMPZ_EX :
67036703 if (opline -> op2 .opline_num >= label_lower_bound ) {
67046704 opline -> op2 .opline_num = labels [- opline -> op2 .opline_num ];
67056705 }
@@ -6709,12 +6709,21 @@ static void zend_pm_labels_replace(zend_pm_context *context, uint32_t start_opnu
67096709 }
67106710}
67116711
6712- static void zend_pm_compile_expr_like ( zend_ast * ast , znode * expr_node , bool consume_expr , uint32_t false_opnum )
6712+ static void zend_pm_emit_jmpz_ex ( znode * result , uint32_t opnum_target )
67136713{
6714- znode result , value ;
6714+ zend_op * opline = zend_emit_op (NULL , ZEND_JMPZ_EX , result , NULL );
6715+ opline -> op2 .opline_num = opnum_target ;
6716+ SET_NODE (opline -> result , result );
6717+ }
6718+
6719+ static void zend_pm_compile_expr_like (zend_ast * ast , znode * result , znode * expr_node , bool consume_expr , uint32_t false_opnum )
6720+ {
6721+ znode value ;
67156722 zend_compile_expr (& value , ast -> child [0 ]);
6716- zend_emit_op_tmp (& result , expr_node -> op_type == IS_CV || consume_expr ? ZEND_IS_IDENTICAL : ZEND_CASE_STRICT , expr_node , & value );
6717- zend_emit_cond_jump (ZEND_JMPZ , & result , false_opnum );
6723+ zend_op * opline = zend_emit_op_tmp (NULL , expr_node -> op_type == IS_CV || consume_expr ? ZEND_IS_IDENTICAL : ZEND_CASE_STRICT , expr_node , & value );
6724+ SET_NODE (opline -> result , result );
6725+
6726+ zend_pm_emit_jmpz_ex (result , false_opnum );
67186727}
67196728
67206729static void zend_pm_verify_parenthesized_compound_pattern (zend_ast * ast , zend_ast_kind kind )
@@ -6729,7 +6738,7 @@ static void zend_pm_verify_parenthesized_compound_pattern(zend_ast *ast, zend_as
67296738 }
67306739}
67316740
6732- static void zend_pm_compile_or (zend_ast * ast , znode * expr_node , bool consume_expr , uint32_t false_opnum , zend_pm_context * context )
6741+ static void zend_pm_compile_or (zend_ast * ast , znode * result , znode * expr_node , bool consume_expr , uint32_t false_opnum , zend_pm_context * context )
67336742{
67346743 zend_pm_verify_parenthesized_compound_pattern (ast , ZEND_AST_AND_PATTERN );
67356744
@@ -6745,12 +6754,12 @@ static void zend_pm_compile_or(zend_ast *ast, znode *expr_node, bool consume_exp
67456754 zend_pm_label_set_next (context , next_label );
67466755 }
67476756 next_label = zend_pm_label_create (context );
6748- zend_compile_pattern (ast_list -> child [i ], expr_node , false, next_label , context );
6757+ zend_compile_pattern (ast_list -> child [i ], result , expr_node , false, next_label , context );
67496758 zend_emit_jump (true_label );
67506759 }
67516760 zend_pm_label_set_next (context , next_label );
67526761
6753- zend_compile_pattern (ast_list -> child [ast_list -> children - 1 ], expr_node , false, false_label , context );
6762+ zend_compile_pattern (ast_list -> child [ast_list -> children - 1 ], result , expr_node , false, false_label , context );
67546763
67556764 zend_pm_label_set_next (context , true_label );
67566765 if (consume_expr ) {
@@ -6767,15 +6776,15 @@ static void zend_pm_compile_or(zend_ast *ast, znode *expr_node, bool consume_exp
67676776 context -> inside_or_pattern = false;
67686777}
67696778
6770- static void zend_pm_compile_and (zend_ast * ast , znode * expr_node , bool consume_expr , uint32_t false_opnum , zend_pm_context * context )
6779+ static void zend_pm_compile_and (zend_ast * ast , znode * result , znode * expr_node , bool consume_expr , uint32_t false_opnum , zend_pm_context * context )
67716780{
67726781 zend_pm_verify_parenthesized_compound_pattern (ast , ZEND_AST_OR_PATTERN );
67736782
67746783 zend_ast_list * ast_list = zend_ast_get_list (ast );
67756784 uint32_t false_label = consume_expr ? zend_pm_label_create (context ) : false_opnum ;
67766785
67776786 for (uint32_t i = 0 ; i < ast_list -> children ; i ++ ) {
6778- zend_compile_pattern (ast_list -> child [i ], expr_node , false, false_label , context );
6787+ zend_compile_pattern (ast_list -> child [i ], result , expr_node , false, false_label , context );
67796788 }
67806789
67816790 if (consume_expr ) {
@@ -6790,7 +6799,7 @@ static void zend_pm_compile_and(zend_ast *ast, znode *expr_node, bool consume_ex
67906799 }
67916800}
67926801
6793- static void zend_pm_compile_type (zend_ast * ast , znode * expr_node , bool consume_expr , uint32_t false_opnum )
6802+ static void zend_pm_compile_type (zend_ast * ast , znode * result , znode * expr_node , bool consume_expr , uint32_t false_opnum )
67946803{
67956804 zend_ast * type_ast = ast -> child [0 ];
67966805 bool nullable = type_ast -> attr & ZEND_TYPE_NULLABLE ;
@@ -6808,12 +6817,12 @@ static void zend_pm_compile_type(zend_ast *ast, znode *expr_node, bool consume_e
68086817 Z_PTR_P (& type_node .u .constant ) = type ;
68096818 Z_TYPE_INFO_P (& type_node .u .constant ) = IS_TYPE ;
68106819
6811- znode result ;
6812- zend_emit_op ( & result , ZEND_HAS_TYPE , expr_node , & type_node );
6820+ zend_op * opline = zend_emit_op ( NULL , ZEND_HAS_TYPE , expr_node , & type_node ) ;
6821+ SET_NODE ( opline -> result , result );
68136822 if (consume_expr ) {
68146823 zend_emit_op (NULL , ZEND_FREE , expr_node , NULL );
68156824 }
6816- zend_emit_cond_jump ( ZEND_JMPZ , & result , false_opnum );
6825+ zend_pm_emit_jmpz_ex ( result , false_opnum );
68176826}
68186827
68196828static void zend_pm_copy_tmp (znode * dest , znode * src , bool consume )
@@ -6825,7 +6834,7 @@ static void zend_pm_copy_tmp(znode *dest, znode *src, bool consume)
68256834 }
68266835}
68276836
6828- static void zend_pm_compile_binding (zend_ast * ast , znode * expr_node , bool consume_expr , uint32_t false_opnum , zend_pm_context * context )
6837+ static void zend_pm_compile_binding (zend_ast * ast , znode * result , znode * expr_node , bool consume_expr , uint32_t false_opnum , zend_pm_context * context )
68296838{
68306839 if (context -> inside_or_pattern ) {
68316840 zend_error_noreturn (E_COMPILE_ERROR , "Must not bind to variables inside | pattern" );
@@ -6843,10 +6852,20 @@ static void zend_pm_compile_binding(zend_ast *ast, znode *expr_node, bool consum
68436852 }
68446853
68456854 zend_stack_push (& context -> bindings , & binding );
6855+
6856+ // FIXME: This can be elided most of the time. It may not for:
6857+ // - $a is $b
6858+ // - $a is 42|$b
6859+ znode true_node ;
6860+ true_node .op_type = IS_CONST ;
6861+ ZVAL_TRUE (& true_node .u .constant );
6862+ zend_op * opline = zend_emit_op_tmp (NULL , ZEND_QM_ASSIGN , & true_node , NULL );
6863+ SET_NODE (opline -> result , result );
68466864}
68476865
68486866static void zend_pm_compile_container (
68496867 zend_ast * ast ,
6868+ znode * result ,
68506869 znode * expr_node ,
68516870 bool consume_expr ,
68526871 uint32_t false_opnum ,
@@ -6860,10 +6879,10 @@ static void zend_pm_compile_container(
68606879
68616880 /* Make sure the value is actually of the right type. */
68626881 zend_pm_copy_tmp (& expr_copy_node , expr_node , false);
6863- znode is_array_node ;
6864- zend_op * is_array_op = zend_emit_op ( & is_array_node , ZEND_TYPE_CHECK , & expr_copy_node , NULL );
6882+ zend_op * is_array_op = zend_emit_op ( NULL , ZEND_TYPE_CHECK , & expr_copy_node , NULL ) ;
6883+ SET_NODE ( is_array_op -> result , result );
68656884 is_array_op -> extended_value = is_array ? MAY_BE_ARRAY : MAY_BE_OBJECT ;
6866- zend_emit_cond_jump ( ZEND_JMPZ , & is_array_node , false_label );
6885+ zend_pm_emit_jmpz_ex ( result , false_label );
68676886
68686887 if (is_array ) {
68696888 /* Make sure the array has the right size. */
@@ -6875,11 +6894,11 @@ static void zend_pm_compile_container(
68756894 count_target_node .op_type = IS_CONST ;
68766895 ZVAL_LONG (& count_target_node .u .constant , element_list -> children );
68776896
6878- znode count_ok_node ;
6879- zend_emit_op (& count_ok_node ,
6897+ zend_op * count_ok_op = zend_emit_op (NULL ,
68806898 (ast -> attr & ZEND_ARRAY_PATTERN_NON_EXHAUSTIVE ) ? ZEND_IS_SMALLER_OR_EQUAL : ZEND_IS_EQUAL ,
68816899 & count_target_node , & count_node );
6882- zend_emit_cond_jump (ZEND_JMPZ , & count_ok_node , false_label );
6900+ SET_NODE (count_ok_op -> result , result );
6901+ zend_pm_emit_jmpz_ex (result , false_label );
68836902 }
68846903
68856904 /* Check elements. */
@@ -6908,7 +6927,7 @@ static void zend_pm_compile_container(
69086927 }
69096928
69106929 /* Compile element check. */
6911- zend_compile_pattern (element_value_ast , & element_value_node , true, false_label , context );
6930+ zend_compile_pattern (element_value_ast , result , & element_value_node , true, false_label , context );
69126931 }
69136932
69146933 if (consume_expr ) {
@@ -6927,29 +6946,29 @@ static void zend_pm_compile_container(
69276946 }
69286947}
69296948
6930- static void zend_compile_pattern (zend_ast * ast , znode * expr_node , bool consume_expr , uint32_t false_opnum , zend_pm_context * context )
6949+ static void zend_compile_pattern (zend_ast * ast , znode * result , znode * expr_node , bool consume_expr , uint32_t false_opnum , zend_pm_context * context )
69316950{
69326951 switch (ast -> kind ) {
69336952 case ZEND_AST_EXPR_LIKE_PATTERN :
6934- zend_pm_compile_expr_like (ast , expr_node , consume_expr , false_opnum );
6953+ zend_pm_compile_expr_like (ast , result , expr_node , consume_expr , false_opnum );
69356954 break ;
69366955 case ZEND_AST_OR_PATTERN :
6937- zend_pm_compile_or (ast , expr_node , consume_expr , false_opnum , context );
6956+ zend_pm_compile_or (ast , result , expr_node , consume_expr , false_opnum , context );
69386957 break ;
69396958 case ZEND_AST_AND_PATTERN :
6940- zend_pm_compile_and (ast , expr_node , consume_expr , false_opnum , context );
6959+ zend_pm_compile_and (ast , result , expr_node , consume_expr , false_opnum , context );
69416960 break ;
69426961 case ZEND_AST_TYPE_PATTERN :
6943- zend_pm_compile_type (ast , expr_node , consume_expr , false_opnum );
6962+ zend_pm_compile_type (ast , result , expr_node , consume_expr , false_opnum );
69446963 break ;
69456964 case ZEND_AST_BINDING_PATTERN :
6946- zend_pm_compile_binding (ast , expr_node , consume_expr , false_opnum , context );
6965+ zend_pm_compile_binding (ast , result , expr_node , consume_expr , false_opnum , context );
69476966 break ;
69486967 case ZEND_AST_ARRAY_PATTERN :
6949- zend_pm_compile_container (ast , expr_node , consume_expr , false_opnum , context , true);
6968+ zend_pm_compile_container (ast , result , expr_node , consume_expr , false_opnum , context , true);
69506969 break ;
69516970 case ZEND_AST_OBJECT_PATTERN :
6952- zend_pm_compile_container (ast , expr_node , consume_expr , false_opnum , context , false);
6971+ zend_pm_compile_container (ast , result , expr_node , consume_expr , false_opnum , context , false);
69536972 break ;
69546973 EMPTY_SWITCH_DEFAULT_CASE ();
69556974 }
@@ -7002,7 +7021,7 @@ static void zend_emit_is(znode *result, znode *expr_node, bool consume_expr, zen
70027021
70037022 uint32_t start_opnum = get_next_op_number ();
70047023 uint32_t false_label = zend_pm_label_create (& context );
7005- zend_compile_pattern (pattern_ast , & expr_copy_node , consume_expr , false_label , & context );
7024+ zend_compile_pattern (pattern_ast , result , & expr_copy_node , consume_expr , false_label , & context );
70067025
70077026 if (context .num_bindings ) {
70087027 zend_pm_binding * binding = zend_stack_base (& context .bindings );
@@ -7028,35 +7047,21 @@ static void zend_emit_is(znode *result, znode *expr_node, bool consume_expr, zen
70287047 }
70297048 }
70307049
7031- znode true_node ;
7032- true_node .op_type = IS_CONST ;
7033- ZVAL_TRUE (& true_node .u .constant );
7034- if (result -> op_type == IS_UNUSED ) {
7035- zend_emit_op_tmp (result , ZEND_QM_ASSIGN , & true_node , NULL );
7036- } else {
7037- zend_op * opline_qm_assign = zend_emit_op_tmp (NULL , ZEND_QM_ASSIGN , & true_node , NULL );
7038- SET_NODE (opline_qm_assign -> result , result );
7039- }
7040- uint32_t jmp_end = zend_emit_jump (0 );
7041-
7042- zend_pm_label_set_next (& context , false_label );
7043-
70447050 if (context .num_bindings ) {
7051+ uint32_t jmp_end = zend_emit_jump (0 );
7052+ zend_pm_label_set_next (& context , false_label );
7053+
70457054 zend_pm_binding * binding = zend_stack_base (& context .bindings );
70467055 zend_pm_binding * binding_end = zend_stack_top (& context .bindings );
70477056 while (binding <= binding_end ) {
70487057 zend_emit_op (NULL , ZEND_FREE , & binding -> value , NULL );
70497058 binding ++ ;
70507059 }
7051- }
7052-
7053- znode false_node ;
7054- false_node .op_type = IS_CONST ;
7055- ZVAL_FALSE (& false_node .u .constant );
7056- zend_op * opline_qm_assign = zend_emit_op_tmp (NULL , ZEND_QM_ASSIGN , & false_node , NULL );
7057- SET_NODE (opline_qm_assign -> result , result );
70587060
7059- zend_update_jump_target_to_next (jmp_end );
7061+ zend_update_jump_target_to_next (jmp_end );
7062+ } else {
7063+ zend_pm_label_set_next (& context , false_label );
7064+ }
70607065
70617066 zend_pm_labels_replace (& context , start_opnum );
70627067 zend_pm_context_free (& context );
@@ -7070,7 +7075,9 @@ static void zend_compile_is(znode *result, zend_ast *ast)
70707075 znode expr_node ;
70717076 zend_compile_expr (& expr_node , expr_ast );
70727077
7073- result -> op_type = IS_UNUSED ;
7078+ result -> op_type = IS_TMP_VAR ;
7079+ result -> u .op .var = get_temporary_variable ();
7080+
70747081 zend_emit_is (result , & expr_node , (expr_node .op_type & (IS_VAR |IS_TMP_VAR )), pattern_ast );
70757082}
70767083
0 commit comments