58 "ZEND_VM_OP_SPEC" => 1<<0,
59 "ZEND_VM_OP_CONST" => 1<<1,
60 "ZEND_VM_OP_TMPVAR" => 1<<2,
61 "ZEND_VM_OP_TMPVARCV" => 1<<3,
62 "ZEND_VM_OP_MASK" => 0xf0,
63 "ZEND_VM_OP_NUM" => 0x10,
64 "ZEND_VM_OP_JMP_ADDR" => 0x20,
65 "ZEND_VM_OP_TRY_CATCH" => 0x30,
67 "ZEND_VM_OP_THIS" => 0x50,
68 "ZEND_VM_OP_NEXT" => 0x60,
69 "ZEND_VM_OP_CLASS_FETCH" => 0x70,
70 "ZEND_VM_OP_CONSTRUCTOR" => 0x80,
71 "ZEND_VM_OP_CONST_FETCH" => 0x90,
72 "ZEND_VM_OP_CACHE_SLOT" => 0xa0,
74 "ZEND_VM_EXT_VAR_FETCH" => 1<<16,
75 "ZEND_VM_EXT_ISSET" => 1<<17,
76 "ZEND_VM_EXT_CACHE_SLOT" => 1<<18,
77 "ZEND_VM_EXT_ARRAY_INIT" => 1<<19,
78 "ZEND_VM_EXT_REF" => 1<<20,
79 "ZEND_VM_EXT_FETCH_REF" => 1<<21,
80 "ZEND_VM_EXT_DIM_WRITE" => 1<<22,
81 "ZEND_VM_EXT_MASK" => 0x0f000000,
82 "ZEND_VM_EXT_NUM" => 0x01000000,
83 "ZEND_VM_EXT_LAST_CATCH" => 0x02000000,
84 "ZEND_VM_EXT_JMP_ADDR" => 0x03000000,
85 "ZEND_VM_EXT_OP" => 0x04000000,
88 "ZEND_VM_EXT_TYPE" => 0x07000000,
89 "ZEND_VM_EXT_EVAL" => 0x08000000,
90 "ZEND_VM_EXT_TYPE_MASK" => 0x09000000,
92 "ZEND_VM_EXT_SRC" => 0x0b000000,
94 "ZEND_VM_NO_CONST_CONST" => 0x40000000,
95 "ZEND_VM_COMMUTATIVE" => 0x80000000,
172 "UNUSED" =>
"_UNUSED",
174 "TMPVAR" =>
"_TMPVAR",
175 "TMPVARCV" =>
"_TMPVARCV",
190 "ANY" =>
"opline->op1_type",
191 "TMP" =>
"IS_TMP_VAR",
193 "CONST" =>
"IS_CONST",
194 "UNUSED" =>
"IS_UNUSED",
196 "TMPVAR" =>
"(IS_TMP_VAR|IS_VAR)",
197 "TMPVARCV" =>
"(IS_TMP_VAR|IS_VAR|IS_CV)",
201 "ANY" =>
"opline->op2_type",
202 "TMP" =>
"IS_TMP_VAR",
204 "CONST" =>
"IS_CONST",
205 "UNUSED" =>
"IS_UNUSED",
207 "TMPVAR" =>
"(IS_TMP_VAR|IS_VAR)",
208 "TMPVARCV" =>
"(IS_TMP_VAR|IS_VAR|IS_CV)",
212 "ANY" =>
"get_zval_ptr(opline->op1_type, opline->op1, \\1)",
213 "TMP" =>
"_get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC)",
214 "VAR" =>
"_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)",
215 "CONST" =>
"RT_CONSTANT(opline, opline->op1)",
217 "CV" =>
"_get_zval_ptr_cv_\\1(opline->op1.var EXECUTE_DATA_CC)",
218 "TMPVAR" =>
"_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)",
223 "ANY" =>
"get_zval_ptr(opline->op2_type, opline->op2, \\1)",
224 "TMP" =>
"_get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC)",
225 "VAR" =>
"_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)",
226 "CONST" =>
"RT_CONSTANT(opline, opline->op2)",
228 "CV" =>
"_get_zval_ptr_cv_\\1(opline->op2.var EXECUTE_DATA_CC)",
229 "TMPVAR" =>
"_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)",
234 "ANY" =>
"get_zval_ptr_ptr(opline->op1_type, opline->op1, \\1)",
235 "TMP" =>
"zend_get_bad_ptr()",
236 "VAR" =>
"_get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC)",
237 "CONST" =>
"zend_get_bad_ptr()",
239 "CV" =>
"_get_zval_ptr_cv_\\1(opline->op1.var EXECUTE_DATA_CC)",
245 "ANY" =>
"get_zval_ptr_ptr(opline->op2_type, opline->op2, \\1)",
246 "TMP" =>
"zend_get_bad_ptr()",
247 "VAR" =>
"_get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC)",
248 "CONST" =>
"zend_get_bad_ptr()",
250 "CV" =>
"_get_zval_ptr_cv_\\1(opline->op2.var EXECUTE_DATA_CC)",
256 "ANY" =>
"get_zval_ptr_deref(opline->op1_type, opline->op1, \\1)",
257 "TMP" =>
"_get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC)",
258 "VAR" =>
"_get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC)",
259 "CONST" =>
"RT_CONSTANT(opline, opline->op1)",
261 "CV" =>
"_get_zval_ptr_cv_deref_\\1(opline->op1.var EXECUTE_DATA_CC)",
263 "TMPVARCV" =>
"_get_zval_ptr_tmpvarcv(opline->op1_type, opline->op1, \\1 EXECUTE_DATA_CC)",
267 "ANY" =>
"get_zval_ptr_deref(opline->op2_type, opline->op2, \\1)",
268 "TMP" =>
"_get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC)",
269 "VAR" =>
"_get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC)",
270 "CONST" =>
"RT_CONSTANT(opline, opline->op2)",
272 "CV" =>
"_get_zval_ptr_cv_deref_\\1(opline->op2.var EXECUTE_DATA_CC)",
274 "TMPVARCV" =>
"_get_zval_ptr_tmpvarcv(opline->op2_type, opline->op2, \\1 EXECUTE_DATA_CC)",
278 "ANY" =>
"get_zval_ptr_undef(opline->op1_type, opline->op1, \\1)",
279 "TMP" =>
"_get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC)",
280 "VAR" =>
"_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)",
281 "CONST" =>
"RT_CONSTANT(opline, opline->op1)",
283 "CV" =>
"EX_VAR(opline->op1.var)",
284 "TMPVAR" =>
"_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)",
285 "TMPVARCV" =>
"EX_VAR(opline->op1.var)",
289 "ANY" =>
"get_zval_ptr_undef(opline->op2_type, opline->op2, \\1)",
290 "TMP" =>
"_get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC)",
291 "VAR" =>
"_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)",
292 "CONST" =>
"RT_CONSTANT(opline, opline->op2)",
294 "CV" =>
"EX_VAR(opline->op2.var)",
295 "TMPVAR" =>
"_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)",
296 "TMPVARCV" =>
"EX_VAR(opline->op2.var)",
300 "ANY" =>
"get_zval_ptr_ptr_undef(opline->op1_type, opline->op1, \\1)",
301 "TMP" =>
"zend_get_bad_ptr()",
302 "VAR" =>
"_get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC)",
303 "CONST" =>
"zend_get_bad_ptr()",
305 "CV" =>
"EX_VAR(opline->op1.var)",
311 "ANY" =>
"get_zval_ptr_ptr_undef(opline->op2_type, opline->op2, \\1)",
312 "TMP" =>
"zend_get_bad_ptr()",
313 "VAR" =>
"_get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC)",
314 "CONST" =>
"zend_get_bad_ptr()",
316 "CV" =>
"EX_VAR(opline->op2.var)",
322 "ANY" =>
"get_obj_zval_ptr(opline->op1_type, opline->op1, \\1)",
323 "TMP" =>
"_get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC)",
324 "VAR" =>
"_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)",
325 "CONST" =>
"RT_CONSTANT(opline, opline->op1)",
326 "UNUSED" =>
"&EX(This)",
327 "CV" =>
"_get_zval_ptr_cv_\\1(opline->op1.var EXECUTE_DATA_CC)",
328 "TMPVAR" =>
"_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)",
333 "ANY" =>
"get_obj_zval_ptr(opline->op2_type, opline->op2, \\1)",
334 "TMP" =>
"_get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC)",
335 "VAR" =>
"_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)",
336 "CONST" =>
"RT_CONSTANT(opline, opline->op2)",
337 "UNUSED" =>
"&EX(This)",
338 "CV" =>
"_get_zval_ptr_cv_\\1(opline->op2.var EXECUTE_DATA_CC)",
339 "TMPVAR" =>
"_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)",
344 "ANY" =>
"get_obj_zval_ptr_undef(opline->op1_type, opline->op1, \\1)",
345 "TMP" =>
"_get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC)",
346 "VAR" =>
"_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)",
347 "CONST" =>
"RT_CONSTANT(opline, opline->op1)",
348 "UNUSED" =>
"&EX(This)",
349 "CV" =>
"EX_VAR(opline->op1.var)",
350 "TMPVAR" =>
"_get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC)",
351 "TMPVARCV" =>
"EX_VAR(opline->op1.var)",
355 "ANY" =>
"get_obj_zval_ptr_undef(opline->op2_type, opline->op2, \\1)",
356 "TMP" =>
"_get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC)",
357 "VAR" =>
"_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)",
358 "CONST" =>
"RT_CONSTANT(opline, opline->op2)",
359 "UNUSED" =>
"&EX(This)",
360 "CV" =>
"EX_VAR(opline->op2.var)",
361 "TMPVAR" =>
"_get_zval_ptr_var(opline->op2.var EXECUTE_DATA_CC)",
362 "TMPVARCV" =>
"EX_VAR(opline->op2.var)",
366 "ANY" =>
"get_obj_zval_ptr(opline->op1_type, opline->op1, \\1)",
367 "TMP" =>
"_get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC)",
368 "VAR" =>
"_get_zval_ptr_var_deref(opline->op1.var EXECUTE_DATA_CC)",
369 "CONST" =>
"RT_CONSTANT(opline, opline->op1)",
370 "UNUSED" =>
"&EX(This)",
371 "CV" =>
"_get_zval_ptr_cv_deref_\\1(opline->op1.var EXECUTE_DATA_CC)",
377 "ANY" =>
"get_obj_zval_ptr(opline->op2_type, opline->op2, \\1)",
378 "TMP" =>
"_get_zval_ptr_tmp(opline->op2.var EXECUTE_DATA_CC)",
379 "VAR" =>
"_get_zval_ptr_var_deref(opline->op2.var EXECUTE_DATA_CC)",
380 "CONST" =>
"RT_CONSTANT(opline, opline->op2)",
381 "UNUSED" =>
"&EX(This)",
382 "CV" =>
"_get_zval_ptr_cv_deref_\\1(opline->op2.var EXECUTE_DATA_CC)",
388 "ANY" =>
"get_obj_zval_ptr_ptr(opline->op1_type, opline->op1, \\1)",
389 "TMP" =>
"zend_get_bad_ptr()",
390 "VAR" =>
"_get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC)",
391 "CONST" =>
"zend_get_bad_ptr()",
392 "UNUSED" =>
"&EX(This)",
393 "CV" =>
"_get_zval_ptr_cv_\\1(opline->op1.var EXECUTE_DATA_CC)",
399 "ANY" =>
"get_obj_zval_ptr_ptr(opline->op2_type, opline->op2, \\1)",
400 "TMP" =>
"zend_get_bad_ptr()",
401 "VAR" =>
"_get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC)",
402 "CONST" =>
"zend_get_bad_ptr()",
403 "UNUSED" =>
"&EX(This)",
404 "CV" =>
"_get_zval_ptr_cv_\\1(opline->op2.var EXECUTE_DATA_CC)",
410 "ANY" =>
"get_obj_zval_ptr_ptr(opline->op1_type, opline->op1, \\1)",
411 "TMP" =>
"zend_get_bad_ptr()",
412 "VAR" =>
"_get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC)",
413 "CONST" =>
"zend_get_bad_ptr()",
414 "UNUSED" =>
"&EX(This)",
415 "CV" =>
"EX_VAR(opline->op1.var)",
421 "ANY" =>
"get_obj_zval_ptr_ptr(opline->op2_type, opline->op2, \\1)",
422 "TMP" =>
"zend_get_bad_ptr()",
423 "VAR" =>
"_get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC)",
424 "CONST" =>
"zend_get_bad_ptr()",
425 "UNUSED" =>
"&EX(This)",
426 "CV" =>
"EX_VAR(opline->op2.var)",
432 "ANY" =>
"FREE_OP(opline->op1_type, opline->op1.var)",
433 "TMP" =>
"zval_ptr_dtor_nogc(EX_VAR(opline->op1.var))",
434 "VAR" =>
"zval_ptr_dtor_nogc(EX_VAR(opline->op1.var))",
438 "TMPVAR" =>
"zval_ptr_dtor_nogc(EX_VAR(opline->op1.var))",
439 "TMPVARCV" =>
"FREE_OP(opline->op1_type, opline->op1.var)",
443 "ANY" =>
"FREE_OP(opline->op2_type, opline->op2.var)",
444 "TMP" =>
"zval_ptr_dtor_nogc(EX_VAR(opline->op2.var))",
445 "VAR" =>
"zval_ptr_dtor_nogc(EX_VAR(opline->op2.var))",
449 "TMPVAR" =>
"zval_ptr_dtor_nogc(EX_VAR(opline->op2.var))",
450 "TMPVARCV" =>
"FREE_OP(opline->op2_type, opline->op2.var)",
454 "ANY" =>
"if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));}",
456 "VAR" =>
"zval_ptr_dtor_nogc(EX_VAR(opline->op1.var))",
465 "ANY" =>
"if (opline->op2_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));}",
467 "VAR" =>
"zval_ptr_dtor_nogc(EX_VAR(opline->op2.var))",
476 "ANY" =>
"(opline+1)->op1_type",
477 "TMP" =>
"IS_TMP_VAR",
479 "CONST" =>
"IS_CONST",
480 "UNUSED" =>
"IS_UNUSED",
482 "TMPVAR" =>
"(IS_TMP_VAR|IS_VAR)",
483 "TMPVARCV" =>
"(IS_TMP_VAR|IS_VAR|IS_CV)",
487 "ANY" =>
"get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1)",
488 "TMP" =>
"_get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC)",
489 "VAR" =>
"_get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC)",
490 "CONST" =>
"RT_CONSTANT((opline+1), (opline+1)->op1)",
492 "CV" =>
"_get_zval_ptr_cv_\\1((opline+1)->op1.var EXECUTE_DATA_CC)",
493 "TMPVAR" =>
"_get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC)",
498 "ANY" =>
"get_op_data_zval_ptr_undef((opline+1)->op1_type, (opline+1)->op1)",
499 "TMP" =>
"_get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC)",
500 "VAR" =>
"_get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC)",
501 "CONST" =>
"RT_CONSTANT((opline+1), (opline+1)->op1)",
503 "CV" =>
"EX_VAR((opline+1)->op1.var)",
504 "TMPVAR" =>
"_get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC)",
505 "TMPVARCV" =>
"EX_VAR((opline+1)->op1.var)",
509 "ANY" =>
"get_op_data_zval_ptr_deref_r((opline+1)->op1_type, (opline+1)->op1)",
510 "TMP" =>
"_get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC)",
511 "VAR" =>
"_get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC)",
512 "CONST" =>
"RT_CONSTANT((opline+1), (opline+1)->op1)",
514 "CV" =>
"_get_zval_ptr_cv_deref_\\1((opline+1)->op1.var EXECUTE_DATA_CC)",
520 "ANY" =>
"get_zval_ptr_ptr((opline+1)->op1_type, (opline+1)->op1, \\1)",
521 "TMP" =>
"zend_get_bad_ptr()",
522 "VAR" =>
"_get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC)",
523 "CONST" =>
"zend_get_bad_ptr()",
525 "CV" =>
"_get_zval_ptr_cv_\\1((opline+1)->op1.var EXECUTE_DATA_CC)",
531 "ANY" =>
"FREE_OP((opline+1)->op1_type, (opline+1)->op1.var)",
532 "TMP" =>
"zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var))",
533 "VAR" =>
"zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var))",
537 "TMPVAR" =>
"zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var))",
586 if (($op1 ==
'TMP' || $op1 ==
'VAR') &&
589 }
else if (($op1 ==
'TMP' || $op1 ==
'VAR') &&
592 }
else if ($op1 ==
'CV' &&
600 if (($op2 ==
'TMP' || $op2 ==
'VAR') &&
603 }
else if (($op2 ==
'TMP' || $op2 ==
'VAR') &&
606 }
else if ($op2 ==
'CV' &&
631 if (!isset($opcode[
"op1"][$op1])) {
632 if (($op1 ==
'TMP' || $op1 ==
'VAR') &&
633 isset($opcode[
"op1"][
"TMPVAR"])) {
635 }
else if (($op1 ==
'TMP' || $op1 ==
'VAR') &&
636 isset($opcode[
"op1"][
"TMPVARCV"])) {
638 }
else if ($op1 ==
'CV' &&
639 isset($opcode[
"op1"][
"TMPVARCV"])) {
641 }
else if (isset($opcode[
"op1"][
"ANY"])) {
648 if (!isset($opcode[
"op2"][$op2])) {
649 if (($op2 ==
'TMP' || $op2 ==
'VAR') &&
650 isset($opcode[
"op2"][
"TMPVAR"])) {
652 }
else if (($op2 ==
'TMP' || $op2 ==
'VAR') &&
653 isset($opcode[
"op2"][
"TMPVARCV"])) {
655 }
else if ($op2 ==
'CV' &&
656 isset($opcode[
"op2"][
"TMPVARCV"])) {
658 }
else if (isset($opcode[
"op2"][
"ANY"])) {
666 if (isset($extra_spec, $opcode[
"spec"])) {
676 if ($condition ===
"") {
680 if ($condition[0] ===
"(" &&
substr($condition, -1) ===
")") {
684 return "(" . $condition .
")";
688function gen_code($f, $spec, $kind, $code, $op1, $op2,
$name, $extra_spec=
null) {
706 $specialized_replacements = array(
733 "/\!ZEND_VM_SPEC/m" => ($op1!=
"ANY"||$op2!=
"ANY"||$extra_spec)?
"0":
"1",
734 "/ZEND_VM_SPEC/m" => ($op1!=
"ANY"||$op2!=
"ANY"||$extra_spec)?
"1":
"0",
737 "/^#(\s*)if\s+1\s*\\|\\|.*[^\\\\]$/m" =>
"#\\1if 1",
738 "/^#(\s*)if\s+0\s*&&.*[^\\\\]$/m" =>
"#\\1if 0",
739 "/^#(\s*)elif\s+1\s*\\|\\|.*[^\\\\]$/m" =>
"#\\1elif 1",
740 "/^#(\s*)elif\s+0\s*&&.*[^\\\\]$/m" =>
"#\\1elif 0",
741 "/OP_DATA_TYPE/" =>
$op_data_type[isset($extra_spec[
'OP_DATA']) ? $extra_spec[
'OP_DATA'] :
"ANY"],
742 "/GET_OP_DATA_ZVAL_PTR\(([^)]*)\)/" =>
$op_data_get_zval_ptr[isset($extra_spec[
'OP_DATA']) ? $extra_spec[
'OP_DATA'] :
"ANY"],
743 "/GET_OP_DATA_ZVAL_PTR_UNDEF\(([^)]*)\)/" =>
$op_data_get_zval_ptr_undef[isset($extra_spec[
'OP_DATA']) ? $extra_spec[
'OP_DATA'] :
"ANY"],
744 "/GET_OP_DATA_ZVAL_PTR_DEREF\(([^)]*)\)/" =>
$op_data_get_zval_ptr_deref[isset($extra_spec[
'OP_DATA']) ? $extra_spec[
'OP_DATA'] :
"ANY"],
745 "/GET_OP_DATA_ZVAL_PTR_PTR\(([^)]*)\)/" =>
$op_data_get_zval_ptr_ptr[isset($extra_spec[
'OP_DATA']) ? $extra_spec[
'OP_DATA'] :
"ANY"],
746 "/FREE_OP_DATA\(\)/" =>
$op_data_free_op[isset($extra_spec[
'OP_DATA']) ? $extra_spec[
'OP_DATA'] :
"ANY"],
747 "/RETURN_VALUE_USED\(opline\)/" => isset($extra_spec[
'RETVAL']) ? $extra_spec[
'RETVAL'] :
"RETURN_VALUE_USED(opline)",
748 "/arg_num <= MAX_ARG_FLAG_NUM/" => isset($extra_spec[
'QUICK_ARG']) ? $extra_spec[
'QUICK_ARG'] :
"arg_num <= MAX_ARG_FLAG_NUM",
749 "/ZEND_VM_SMART_BRANCH\(\s*([^,)]*)\s*,\s*([^)]*)\s*\)/" => isset($extra_spec[
'SMART_BRANCH']) ?
750 ($extra_spec[
'SMART_BRANCH'] == 1 ?
751 "ZEND_VM_SMART_BRANCH_JMPZ(\\1, \\2)"
752 : ($extra_spec[
'SMART_BRANCH'] == 2 ?
753 "ZEND_VM_SMART_BRANCH_JMPNZ(\\1, \\2)" :
"ZEND_VM_SMART_BRANCH_NONE(\\1, \\2)"))
754 :
"ZEND_VM_SMART_BRANCH(\\1, \\2)",
755 "/ZEND_VM_SMART_BRANCH_TRUE\(\s*\)/" => isset($extra_spec[
'SMART_BRANCH']) ?
756 ($extra_spec[
'SMART_BRANCH'] == 1 ?
757 "ZEND_VM_SMART_BRANCH_TRUE_JMPZ()"
758 : ($extra_spec[
'SMART_BRANCH'] == 2 ?
759 "ZEND_VM_SMART_BRANCH_TRUE_JMPNZ()" :
"ZEND_VM_SMART_BRANCH_TRUE_NONE()"))
760 :
"ZEND_VM_SMART_BRANCH_TRUE()",
761 "/ZEND_VM_SMART_BRANCH_FALSE\(\s*\)/" => isset($extra_spec[
'SMART_BRANCH']) ?
762 ($extra_spec[
'SMART_BRANCH'] == 1 ?
763 "ZEND_VM_SMART_BRANCH_FALSE_JMPZ()"
764 : ($extra_spec[
'SMART_BRANCH'] == 2 ?
765 "ZEND_VM_SMART_BRANCH_FALSE_JMPNZ()" :
"ZEND_VM_SMART_BRANCH_FALSE_NONE()"))
766 :
"ZEND_VM_SMART_BRANCH_FALSE()",
767 "/opline->extended_value\s*&\s*ZEND_ISEMPTY/" => isset($extra_spec[
'ISSET']) ?
768 ($extra_spec[
'ISSET'] == 0 ?
"0" :
"1")
770 "/opline->extended_value\s*&\s*~\s*ZEND_ISEMPTY/" => isset($extra_spec[
'ISSET']) ?
771 ($extra_spec[
'ISSET'] == 0 ?
"\\0" :
"opline->extended_value")
773 "/ZEND_OBSERVER_ENABLED/" => isset($extra_spec[
'OBSERVER']) && $extra_spec[
'OBSERVER'] == 1 ?
"1" :
"0",
774 "/ZEND_OBSERVER_USE_RETVAL/" => isset($extra_spec[
'OBSERVER']) && $extra_spec[
'OBSERVER'] == 1 ?
"zval observer_retval" :
"",
775 "/ZEND_OBSERVER_SET_RETVAL\(\)/" => isset($extra_spec[
'OBSERVER']) && $extra_spec[
'OBSERVER'] == 1 ?
"if (!return_value) { return_value = &observer_retval; }" :
"",
776 "/ZEND_OBSERVER_FREE_RETVAL\(\)/" => isset($extra_spec[
'OBSERVER']) && $extra_spec[
'OBSERVER'] == 1 ?
"if (return_value == &observer_retval) { zval_ptr_dtor_nogc(&observer_retval); }" :
"",
777 "/ZEND_OBSERVER_SAVE_OPLINE\(\)/" => isset($extra_spec[
'OBSERVER']) && $extra_spec[
'OBSERVER'] == 1 ?
"SAVE_OPLINE()" :
"",
778 "/ZEND_OBSERVER_FCALL_BEGIN\(\s*(.*)\s*\)/" => isset($extra_spec[
'OBSERVER']) ?
779 ($extra_spec[
'OBSERVER'] == 0 ?
"" :
"zend_observer_fcall_begin_specialized(\\1, false)")
781 "/ZEND_OBSERVER_FCALL_END\(\s*([^,]*)\s*,\s*(.*)\s*\)/" => isset($extra_spec[
'OBSERVER']) ?
782 ($extra_spec[
'OBSERVER'] == 0 ?
"" :
"zend_observer_fcall_end(\\1, \\2)")
787 if (0 &&
strpos($code,
'{') === 0) {
788 $code =
"{\n\tfprintf(stderr, \"$name\\n\");\n" .
substr($code, 1);
795 "/EXECUTE_DATA(?=[^_])/m",
796 "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m",
797 "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*(,[^)]*)?\)/m",
799 function($matches) use ($spec,
$prefix, $op1, $op2, $extra_spec) {
801 return "execute_data";
802 }
else if (
strncasecmp($matches[0],
"ZEND_VM_DISPATCH_TO_HANDLER",
strlen(
"ZEND_VM_DISPATCH_TO_HANDLER")) == 0) {
807 return "goto " .
opcode_name(
$name, $spec, $op1, $op2, $extra_spec) .
"_LABEL";
811 if (isset($matches[2])) {
813 $args =
preg_replace(
"/,\s*([A-Za-z0-9_]*)\s*,\s*([^,)\s]*)\s*/",
"$1 = $2; ", $matches[2]);
814 return $args .
"goto " .
helper_name($matches[1], $spec, $op1, $op2, $extra_spec) .
"_LABEL";
816 return "goto " .
helper_name($matches[1], $spec, $op1, $op2, $extra_spec) .
"_LABEL";
818 if (isset($matches[2])) {
820 $args =
substr(
preg_replace(
"/,\s*[A-Za-z0-9_]*\s*,\s*([^,)\s]*)\s*/",
", $1", $matches[2]), 2);
821 return "ZEND_VM_TAIL_CALL(" .
helper_name($matches[1], $spec, $op1, $op2, $extra_spec) .
"(" . $args.
" ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC))";
823 return "ZEND_VM_TAIL_CALL(" .
helper_name($matches[1], $spec, $op1, $op2, $extra_spec) .
"(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))";
831 "/EXECUTE_DATA(?=[^_])/m",
832 "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m",
833 "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*(,[^)]*)?\)/m",
835 function($matches) use ($spec,
$prefix, $op1, $op2, $extra_spec,
$name) {
837 return "execute_data";
838 }
else if (
strncasecmp($matches[0],
"ZEND_VM_DISPATCH_TO_HANDLER",
strlen(
"ZEND_VM_DISPATCH_TO_HANDLER")) == 0) {
841 $handler = $matches[1];
845 isset($opcode[
"use"]) &&
849 return "ZEND_VM_TAIL_CALL(" .
opcode_name($handler, $spec, $op1, $op2, $extra_spec) . $inline .
"_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))";
852 if (isset($matches[2])) {
854 $args =
substr(
preg_replace(
"/,\s*[A-Za-z0-9_]*\s*,\s*([^,)\s]*)\s*/",
", $1", $matches[2]), 2);
855 return "ZEND_VM_TAIL_CALL(" .
helper_name($matches[1], $spec, $op1, $op2, $extra_spec) .
"(" . $args.
" ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC))";
857 return "ZEND_VM_TAIL_CALL(" .
helper_name($matches[1], $spec, $op1, $op2, $extra_spec) .
"(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))";
865 "/EXECUTE_DATA(?=[^_])/m",
866 "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m",
867 "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*(,[^)]*)?\)/m",
869 function($matches) use ($spec,
$prefix, $op1, $op2, $extra_spec) {
871 return "execute_data";
872 }
else if (
strncasecmp($matches[0],
"ZEND_VM_DISPATCH_TO_HANDLER",
strlen(
"ZEND_VM_DISPATCH_TO_HANDLER")) == 0) {
873 return "goto " .
opcode_name($matches[1], $spec, $op1, $op2, $extra_spec) .
"_LABEL";
876 if (isset($matches[2])) {
878 $args =
preg_replace(
"/,\s*([A-Za-z0-9_]*)\s*,\s*([^,)\s]*)\s*/",
"$1 = $2; ", $matches[2]);
879 return $args .
"goto " .
helper_name($matches[1], $spec, $op1, $op2, $extra_spec);
881 return "goto " .
helper_name($matches[1], $spec, $op1, $op2, $extra_spec);
889 "/EXECUTE_DATA(?=[^_])/m",
890 "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m",
891 "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*(,[^)]*)?\)/m",
893 function($matches) use ($spec,
$prefix, $op1, $op2, $extra_spec) {
895 return "execute_data";
896 }
else if (
strncasecmp($matches[0],
"ZEND_VM_DISPATCH_TO_HANDLER",
strlen(
"ZEND_VM_DISPATCH_TO_HANDLER")) == 0) {
897 return "goto " .
opcode_name($matches[1], $spec, $op1, $op2, $extra_spec) .
"_LABEL";
900 if (isset($matches[2])) {
902 $args =
preg_replace(
"/,\s*([A-Za-z0-9_]*)\s*,\s*([^,)\s]*)\s*/",
"$1 = $2; ", $matches[2]);
903 return $args .
"goto " .
helper_name($matches[1], $spec, $op1, $op2, $extra_spec);
905 return "goto " .
helper_name($matches[1], $spec, $op1, $op2, $extra_spec);
924 if (isset($extra_spec[
"NO_CONST_CONST"]) &&
925 $op1 ==
"CONST" && $op2 ==
"CONST") {
930 if (isset($extra_spec[
"COMMUTATIVE"]) &&
940 if (isset($extra_spec[
"SMART_BRANCH"]) && $extra_spec[
"SMART_BRANCH"] == 0) {
943 if (isset($extra_spec[
"OBSERVER"]) && $extra_spec[
"OBSERVER"] == 1) {
946 if ($hot ===
'HOT_' || $hot ===
'INLINE_') {
948 }
else if ($hot ===
'HOT_NOCONST_') {
949 return ($op1 !==
'CONST');
950 }
else if ($hot ===
'HOT_NOCONSTCONST_') {
951 return (($op1 !==
'CONST') || ($op2 !==
'CONST')) ;
952 }
else if ($hot ===
'HOT_OBJ_') {
953 return (($op1 ===
'UNUSED') || ($op1 ===
'CV')) && ($op2 ===
'CONST');
954 }
else if ($hot ===
'HOT_SEND_') {
955 return !empty($extra_spec[
"QUICK_ARG"]);
962 if ($hot ===
'COLD_') {
964 }
else if (isset($extra_spec[
"OBSERVER"]) && $extra_spec[
"OBSERVER"] == 1) {
966 }
else if ($hot ===
'COLD_CONST_') {
967 return ($op1 ===
'CONST');
968 }
else if ($hot ===
'COLD_CONSTCONST_') {
969 return ($op1 ===
'CONST' && $op2 ===
'CONST');
970 }
else if ($hot ===
'HOT_OBJ_') {
971 return ($op1 ===
'CONST');
972 }
else if ($hot ===
'HOT_NOCONST_') {
973 return ($op1 ===
'CONST');
974 }
else if ($hot ===
'HOT_NOCONSTCONST_') {
975 return ($op1 ===
'CONST' && $op2 ===
'CONST');
982 return ($hot ===
'INLINE_');
986function gen_handler($f, $spec, $kind,
$name, $op1, $op2, $use, $code, $lineno, $opcode, $extra_spec =
null, &$switch_labels = array()) {
989 static $used_observer_handlers = array();
1000 if (isset($extra_spec[
"SMART_BRANCH"])) {
1001 if ($opcode[
"hot"] ===
'HOT_NOCONSTCONST_'
1002 || $opcode[
"hot"] ===
'COLD_CONSTCONST_') {
1003 if (($op1 ===
'CONST') && ($op2 ===
'CONST')) {
1004 if ($extra_spec[
"SMART_BRANCH"] == 0) {
1005 unset($extra_spec[
"SMART_BRANCH"]);
1014 if (isset($extra_spec[
"QUICK_ARG"])) {
1015 if ($op2 ===
"CONST") {
1016 if ($extra_spec[
"QUICK_ARG"] == 0) {
1017 unset($extra_spec[
"QUICK_ARG"]);
1025 if (isset($extra_spec[
"OBSERVER"]) && $extra_spec[
"OBSERVER"] == 1) {
1026 if (isset($extra_spec[
"RETVAL"])) {
1027 if ($extra_spec[
"RETVAL"] == 0) {
1028 unset($extra_spec[
"RETVAL"]);
1033 if ($op1 !=
"ANY" || $op2 !=
"ANY") {
1034 if (!isset($used_observer_handlers[$kind][$opcode[
"op"]])) {
1035 $used_observer_handlers[$kind][$opcode[
"op"]] =
true;
1045 out($f,
"#line $lineno \"$definition_file\"\n");
1049 $additional_func =
false;
1054 $out =
fopen(
'php://memory',
'w+');
1055 gen_code($out, $spec, $kind, $code, $op1, $op2,
$name, $extra_spec);
1058 "\t\t\tHYBRID_CASE({$spec_name}):\n"
1059 .
"\t\t\t\tVM_TRACE($spec_name)\n"
1061 .
"\t\t\t\tVM_TRACE_OP_END($spec_name)\n";
1065 isset($opcode[
"use"]) &&
1069 "\t\t\tHYBRID_CASE({$spec_name}):\n"
1070 .
"\t\t\t\tVM_TRACE($spec_name)\n"
1071 .
"\t\t\t\t{$spec_name}{$inline}_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"
1072 .
"\t\t\t\tVM_TRACE_OP_END($spec_name)\n"
1073 .
"\t\t\t\tHYBRID_BREAK();\n";
1076 $gen_order[$spec_name] = $code;
1083 if (isset($opcode[
"use"])) {
1084 out($f,
"static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
1085 $additional_func =
true;
1087 out($f,
"static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
1089 }
else if ($opcode[
"hot"] &&
is_cold_handler($opcode[
"hot"], $op1, $op2, $extra_spec)) {
1090 out($f,
"static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
1092 out($f,
"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
1097 $cur = $switch_labels ?
end($switch_labels) + 1 : 0;
1098 out($f,
"case $cur: /* $spec_name */");
1099 $switch_labels[$spec_name] = $cur;
1105 out($f,
" {$spec_name}_LABEL: ZEND_ATTRIBUTE_UNUSED_LABEL\n");
1111 out($f,
"{$spec_name}_LABEL: ZEND_VM_GUARD($spec_name);\n");
1116 gen_code($f, $spec, $kind, $code, $op1, $op2,
$name, $extra_spec);
1118 if ($additional_func) {
1119 out($f,
"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
1121 out($f,
"\tZEND_VM_TAIL_CALL({$spec_name}_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n");
1128function gen_helper($f, $spec, $kind,
$name, $op1, $op2, $param, $code, $lineno, $inline, $cold =
false, $hot =
false, $extra_spec =
null) {
1129 global $definition_file,
$prefix;
1140 out($f,
"#line $lineno \"$definition_file\"\n");
1148 out($f, $spec_name .
"_LABEL:\n");
1152 $zend_attributes =
" zend_always_inline";
1153 $zend_fastcall =
"";
1156 $zend_attributes =
" zend_never_inline ZEND_COLD";
1158 $zend_attributes =
" zend_never_inline";
1160 $zend_fastcall =
" ZEND_FASTCALL";
1162 if ($param ==
null) {
1164 out($f,
"static$zend_attributes ZEND_OPCODE_HANDLER_RET$zend_fastcall $spec_name(ZEND_OPCODE_HANDLER_ARGS)\n");
1167 out($f,
"static$zend_attributes ZEND_OPCODE_HANDLER_RET$zend_fastcall $spec_name($param ZEND_OPCODE_HANDLER_ARGS_DC)\n");
1171 out($f,
"$spec_name:\n");
1174 out($f,
"$spec_name:\n");
1179 gen_code($f, $spec, $kind, $code, $op1, $op2,
$name, $extra_spec);
1186 out($f,$prolog.
"ZEND_NULL_HANDLER,\n");
1189 out($f,$prolog.
"(void*)(uintptr_t)-1,\n");
1192 out($f,$prolog.
"(void*)&&ZEND_NULL_LABEL,\n");
1198function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array()) {
1208 foreach (
$opcodes as $num => $dsc) {
1209 if (isset($dsc[
'alias'])) {
1210 $specs[$num] = $specs[
$opnames[$dsc[
'alias']]];
1213 $specs[$num] =
"$label";
1214 $spec_op1 = $spec_op2 = $spec_extra =
false;
1215 $def_op1_type = $def_op2_type =
"ANY";
1217 if (isset($dsc[
"op1"]) && !isset($dsc[
"op1"][
"ANY"])) {
1220 if (isset($dsc[
"op1"][
$t])) {
1227 $specs[$num] .=
" | SPEC_RULE_OP1";
1228 $def_op1_type =
"ANY";
1231 if (isset($dsc[
"op2"]) && !isset($dsc[
"op2"][
"ANY"])) {
1234 if (isset($dsc[
"op2"][
$t])) {
1241 $specs[$num] .=
" | SPEC_RULE_OP2";
1242 $def_op2_type =
"ANY";
1248 $specs[$num] .=
" | " .
implode(
" | ", $flags);
1251 $opcodes[$num][
'spec_code'] = $specs[$num];
1252 unset($specs[$num]);
1255 $foreach_op1 =
function($do) use ($dsc,
$op_types) {
1256 return function($_, $op2) use ($do, $dsc,
$op_types) {
1259 if ($op1 !=
"ANY") {
1260 if (!isset($dsc[
"op1"][$op1])) {
1261 if ($op1 ==
"TMP" || $op1 ==
"VAR") {
1262 if (isset($dsc[
"op1"][
"TMPVAR"])) {
1264 }
else if (isset($dsc[
"op1"][
"TMPVARCV"])) {
1269 }
else if ($op1 ==
"CV" && isset($dsc[
"op1"][
"TMPVARCV"])) {
1281 $foreach_op2 =
function($do) use ($dsc,
$op_types) {
1282 return function($op1, $_) use ($do, $dsc,
$op_types) {
1285 if ($op2 !=
"ANY") {
1286 if (!isset($dsc[
"op2"][$op2])) {
1287 if ($op2 ==
"TMP" || $op2 ==
"VAR") {
1288 if (isset($dsc[
"op2"][
"TMPVAR"])) {
1290 }
else if (isset($dsc[
"op2"][
"TMPVARCV"])) {
1295 }
else if ($op2 ==
"CV" && isset($dsc[
"op2"][
"TMPVARCV"])) {
1307 $foreach_op_data =
function($do) use ($dsc,
$op_types) {
1308 return function($op1, $op2, $extra_spec = array()) use ($do, $dsc,
$op_types) {
1311 if ($op_data !=
"ANY") {
1312 if (!isset($dsc[
"spec"][
"OP_DATA"][$op_data])) {
1313 if ($op_data ==
"TMP" || $op_data ==
"VAR") {
1314 if (isset($dsc[
"spec"][
"OP_DATA"][
"TMPVAR"])) {
1315 $op_data =
"TMPVAR";
1316 }
else if (isset($dsc[
"spec"][
"OP_DATA"][
"TMPVARCV"])) {
1317 $op_data =
"TMPVARCV";
1322 }
else if ($op_data ==
"CV" && isset($dsc[
"OP_DATA"][
"TMPVARCV"])) {
1323 $op_data =
"TMPVARCV";
1329 $do($op1, $op2, array(
"OP_DATA" => $op_data) + $extra_spec);
1334 $foreach_extra_spec =
function($do, $spec) use ($dsc) {
1335 return function($op1, $op2, $extra_spec = array()) use ($do, $spec, $dsc) {
1336 foreach ($dsc[
"spec"][$spec] as $val) {
1337 $do($op1, $op2, array($spec => $val) + $extra_spec);
1341 $generate =
function ($op1, $op2, $extra_spec = array()) use ($f, $kind, $dsc,
$prefix, $prolog, $num, $switch_labels, &$label, &
$list) {
1346 if (isset($dsc[
"op1"][$op1]) &&
1347 isset($dsc[
"op2"][$op2]) &&
1348 (!isset($extra_spec[
"OP_DATA"]) || isset($dsc[
"spec"][
"OP_DATA"][$extra_spec[
"OP_DATA"]]))) {
1351 $list[$label] =
null;
1357 if (isset($extra_spec[
"SMART_BRANCH"])) {
1358 if ($dsc[
"hot"] ===
'HOT_NOCONSTCONST_'
1359 || $dsc[
"hot"] ===
'COLD_CONSTCONST_') {
1360 if (($op1 ===
'CONST') && ($op2 ===
'CONST')) {
1361 unset($extra_spec[
"SMART_BRANCH"]);
1367 if (isset($extra_spec[
"QUICK_ARG"])) {
1368 if ($op2 ===
"CONST") {
1369 unset($extra_spec[
"QUICK_ARG"]);
1374 if (isset($extra_spec[
"OBSERVER"]) && $extra_spec[
"OBSERVER"] == 1) {
1375 if (isset($extra_spec[
"RETVAL"])) {
1376 unset($extra_spec[
"RETVAL"]);
1378 if ($op1 !=
"ANY" || $op2 !=
"ANY") {
1385 $spec_name = $dsc[
"op"].
"_SPEC".
$prefix[$op1].$prefix[$op2].extra_spec_name($extra_spec);
1388 out($f,
"$prolog{$spec_name}_HANDLER,\n");
1391 out($f,$prolog.
"(void*)(uintptr_t)$switch_labels[$spec_name],\n");
1394 out($f,$prolog.
"(void*)&&{$spec_name}_LABEL,\n");
1397 $list[$label] = $spec_name;
1402 $list[$label] =
null;
1409 foreach ($spec_extra as $extra => $devnull) {
1410 if ($extra ==
"OP_DATA") {
1411 $do = $foreach_op_data($do);
1413 $do = $foreach_extra_spec($do, $extra);
1418 $do = $foreach_op2($do);
1421 $do = $foreach_op1($do);
1424 $do($def_op1_type, $def_op2_type);
1430 foreach (
$opcodes as $num => $dsc) {
1431 while ($next != $num) {
1436 out($f,$prolog.
"ZEND_NULL_HANDLER,\n");
1439 out($f,$prolog.
"(void*)(uintptr_t)-1,\n");
1442 out($f,$prolog.
"(void*)&&ZEND_NULL_LABEL,\n");
1456 out($f,$prolog.$dsc[
'alias'].
"_HANDLER,\n");
1459 out($f,$prolog.
"(void*)&&".$dsc[
'alias'].
"_LABEL,\n");
1462 $list[] = $dsc[
"op"];
1463 }
else if ($dsc[
"code"]) {
1467 out($f,$prolog.$dsc[
"op"].
"_HANDLER,\n");
1470 out($f,$prolog.
"(void*)(uintptr_t)".((
string)$num).
",\n");
1473 out($f,$prolog.
"(void*)&&".$dsc[
"op"].
"_LABEL,\n");
1476 $list[] = $dsc[
"op"];
1480 out($f,$prolog.
"ZEND_NULL_HANDLER,\n");
1483 out($f,$prolog.
"(void*)(uintptr_t)-1,\n");
1486 out($f,$prolog.
"(void*)&&ZEND_NULL_LABEL,\n");
1497 out($f,$prolog.
"ZEND_NULL_HANDLER\n");
1500 out($f,$prolog.
"(void*)(uintptr_t)-1\n");
1503 out($f,$prolog.
"(void*)&&ZEND_NULL_LABEL\n");
1506 $specs[$num + 1] =
"$label";
1508 $l =
fopen(__DIR__ .
"/zend_vm_handlers.h",
"w+") or
die(
"ERROR: Cannot create zend_vm_handlers.h\n");
1509 out($l,
"#define VM_HANDLERS(_) \\\n");
1511 if (
null !==
$name) {
1512 out($l,
"\t_($n, $name) \\\n");
1515 out($l,
"\t_($n+1, ZEND_NULL)\n");
1523 foreach ($specs as $num => $def) {
1524 while (++$last < $num) {
1525 out($f,
"$prolog$lastdef,\n");
1528 out($f,
"$prolog$def,\n");
1530 while ($last++ < 255) {
1531 out($f,
"$prolog$lastdef,\n");
1543 out($f,
"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
1545 out($f,
"\tUSE_OPLINE\n");
1547 out($f,
"\tSAVE_OPLINE();\n");
1548 out($f,
"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n");
1549 out($f,
"\tZEND_VM_NEXT_OPCODE(); /* Never reached */\n");
1558 if (isset($extra_spec[
"OP_DATA"])) {
1559 $s .=
"_OP_DATA" .
$prefix[$extra_spec[
"OP_DATA"]];
1561 if (isset($extra_spec[
"RETVAL"])) {
1562 $s .=
"_RETVAL_".($extra_spec[
"RETVAL"] ?
"USED" :
"UNUSED");
1564 if (isset($extra_spec[
"QUICK_ARG"])) {
1565 if ($extra_spec[
"QUICK_ARG"]) {
1569 if (isset($extra_spec[
"SMART_BRANCH"])) {
1570 if ($extra_spec[
"SMART_BRANCH"] == 1) {
1572 }
else if ($extra_spec[
"SMART_BRANCH"] == 2) {
1576 if (isset($extra_spec[
"ISSET"])) {
1577 if ($extra_spec[
"ISSET"] == 0) {
1583 if (isset($extra_spec[
"OBSERVER"])) {
1584 if ($extra_spec[
"OBSERVER"]) {
1593 if (isset($extra_spec[
"OP_DATA"])) {
1594 $s[] =
"SPEC_RULE_OP_DATA";
1596 if (isset($extra_spec[
"RETVAL"])) {
1597 $s[] =
"SPEC_RULE_RETVAL";
1599 if (isset($extra_spec[
"QUICK_ARG"])) {
1600 $s[] =
"SPEC_RULE_QUICK_ARG";
1602 if (isset($extra_spec[
"SMART_BRANCH"])) {
1603 $s[] =
"SPEC_RULE_SMART_BRANCH";
1605 if (isset($extra_spec[
"COMMUTATIVE"])) {
1606 $s[] =
"SPEC_RULE_COMMUTATIVE";
1608 if (isset($extra_spec[
"ISSET"])) {
1609 $s[] =
"SPEC_RULE_ISSET";
1611 if (isset($extra_spec[
"OBSERVER"])) {
1612 $s[] =
"SPEC_RULE_OBSERVER";
1620 if (!isset($dsc[
"spec"])) {
1621 return array(array());
1623 $specs = $dsc[
"spec"];
1625 if (isset($specs[
"OP_DATA"])) {
1626 $op_data_specs = $specs[
"OP_DATA"];
1627 $specs[
"OP_DATA"] = array();
1629 if (isset($dsc[
"spec"][
"OP_DATA"][$op_data])) {
1630 $specs[
"OP_DATA"][] = $op_data;
1635 $f =
function($specs) use (&$f) {
1636 $spec =
key($specs);
1641 $next = array(array());
1644 foreach ($next as $existing) {
1645 foreach ($top as $mode) {
1646 $ret[] = array($spec => $mode) + $existing;
1655 $f =
fopen($fn,
"r");
1678 foreach ($op1t as $op1) {
1681 foreach ($op2t as $op2) {
1683 foreach (
$list as $lineno => $dsc) {
1684 if (isset($dsc[
"handler"])) {
1685 $num = $dsc[
"handler"];
1688 if (isset(
$opcodes[$num][
"op1"][$op1]) &&
1689 isset(
$opcodes[$num][
"op2"][$op2])) {
1691 gen_handler($f, 1, $kind,
$opcodes[$num][
"op"], $op1, $op2, isset(
$opcodes[$num][
"use"]),
$opcodes[$num][
"code"], $lineno,
$opcodes[$num], $extra_spec, $switch_labels);
1694 }
else if (isset($dsc[
"helper"])) {
1695 $num = $dsc[
"helper"];
1698 if (isset(
$helpers[$num][
"op1"][$op1]) &&
1699 isset(
$helpers[$num][
"op2"][$op2])) {
1701 gen_helper($f, 1, $kind, $num, $op1, $op2,
$helpers[$num][
"param"],
$helpers[$num][
"code"], $lineno,
$helpers[$num][
"inline"],
$helpers[$num][
"cold"],
$helpers[$num][
"hot"], $extra_spec);
1706 die(
"??? $kind:$num\n");
1715 foreach (
$list as $lineno => $dsc) {
1716 if (isset($dsc[
"handler"])) {
1717 $num = $dsc[
"handler"];
1722 }
else if (isset($dsc[
"helper"])) {
1723 $num = $dsc[
"helper"];
1725 gen_helper($f, 0, $kind, $num,
"ANY",
"ANY",
$helpers[$num][
"param"],
$helpers[$num][
"code"], $lineno,
$helpers[$num][
"inline"],
$helpers[$num][
"cold"],
$helpers[$num][
"hot"]);
1728 die(
"??? $kind:$num\n");
1734 foreach ($gen_order as $txt) {
1735 if ($txt !==
null) {
1752 out($f,
"default: ZEND_NULL_LABEL:\n");
1753 out($f,
"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n");
1754 out($f,
"\tZEND_VM_NEXT_OPCODE(); /* Never reached */\n");
1757 out($f,
"ZEND_NULL_LABEL:\n");
1758 out($f,
"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n");
1759 out($f,
"\tZEND_VM_NEXT_OPCODE(); /* Never reached */\n");
1762 out($f,
"\t\t\tHYBRID_CASE(HYBRID_HALT):\n");
1763 out($f,
"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
1764 out($f,
"\t\t\t\texecute_data = vm_stack_data.orig_execute_data;\n");
1766 out($f,
"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
1767 out($f,
"\t\t\t\topline = vm_stack_data.orig_opline;\n");
1769 out($f,
"\t\t\t\treturn;\n");
1770 out($f,
"\t\t\tHYBRID_DEFAULT:\n");
1771 out($f,
"\t\t\t\tVM_TRACE(ZEND_NULL)\n");
1772 out($f,
"\t\t\t\tZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
1773 out($f,
"\t\t\t\tVM_TRACE_OP_END(ZEND_NULL)\n");
1774 out($f,
"\t\t\t\tHYBRID_BREAK(); /* Never reached */\n");
1780 if (
trim($prolog) !=
"" ||
trim($epilog) !=
"") {
1781 out($f, $prolog.$epilog);
1786function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) {
1795 $switch_labels = array();
1797 foreach ($skl as $line) {
1800 if (
preg_match(
"/(.*)[{][%]([A-Z_]*)[%][}](.*)/", $line, $m)) {
1803 out($f,
"#define SPEC_START_MASK 0x0000ffff\n");
1804 out($f,
"#define SPEC_EXTRA_MASK 0xfffc0000\n");
1805 out($f,
"#define SPEC_RULE_OP1 0x00010000\n");
1806 out($f,
"#define SPEC_RULE_OP2 0x00020000\n");
1807 out($f,
"#define SPEC_RULE_OP_DATA 0x00040000\n");
1808 out($f,
"#define SPEC_RULE_RETVAL 0x00080000\n");
1809 out($f,
"#define SPEC_RULE_QUICK_ARG 0x00100000\n");
1810 out($f,
"#define SPEC_RULE_SMART_BRANCH 0x00200000\n");
1811 out($f,
"#define SPEC_RULE_COMMUTATIVE 0x00800000\n");
1812 out($f,
"#define SPEC_RULE_ISSET 0x01000000\n");
1813 out($f,
"#define SPEC_RULE_OBSERVER 0x02000000\n");
1815 out($f,
"static const uint32_t *zend_spec_handlers;\n");
1816 out($f,
"static const void * const *zend_opcode_handlers;\n");
1817 out($f,
"static int zend_handlers_count;\n");
1819 out($f,
"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
1820 out($f,
"static const void * const * zend_opcode_handler_funcs;\n");
1821 out($f,
"static zend_op hybrid_halt_op;\n");
1824 out($f,
"#if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID) || !ZEND_VM_SPEC\n");
1825 out($f,
"static const void *zend_vm_get_opcode_handler(uint8_t opcode, const zend_op* op);\n");
1826 out($f,
"#endif\n\n");
1828 out($f,
"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
1829 out($f,
"static const void *zend_vm_get_opcode_handler_func(uint8_t opcode, const zend_op* op);\n");
1831 out($f,
"# define zend_vm_get_opcode_handler_func zend_vm_get_opcode_handler\n");
1832 out($f,
"#endif\n\n");
1834 out($f,
"#ifndef VM_TRACE\n");
1836 out($f,
"# define VM_TRACE(op) ZEND_VM_GUARD(op);\n");
1838 out($f,
"# define VM_TRACE(op)\n");
1841 out($f,
"#ifndef VM_TRACE_OP_END\n");
1842 out($f,
"# define VM_TRACE_OP_END(op)\n");
1844 out($f,
"#ifndef VM_TRACE_START\n");
1845 out($f,
"# define VM_TRACE_START()\n");
1847 out($f,
"#ifndef VM_TRACE_END\n");
1848 out($f,
"# define VM_TRACE_END()\n");
1852 out($f,
"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
1853 out($f,
"# if defined(__GNUC__) && defined(__i386__)\n");
1854 out($f,
"# define HYBRID_JIT_GUARD() __asm__ __volatile__ (\"\"::: \"ebx\")\n");
1855 out($f,
"# elif defined(__GNUC__) && defined(__x86_64__)\n");
1856 out($f,
"# define HYBRID_JIT_GUARD() __asm__ __volatile__ (\"\"::: \"rbx\",\"r12\",\"r13\")\n");
1857 out($f,
"# elif defined(__GNUC__) && defined(__aarch64__)\n");
1858 out($f,
"# define HYBRID_JIT_GUARD() __asm__ __volatile__ (\"\"::: \"x19\",\"x20\",\"x21\",\"x22\",\"x23\",\"x24\",\"x25\",\"x26\")\n");
1860 out($f,
"# define HYBRID_JIT_GUARD()\n");
1861 out($f,
"# endif\n");
1862 out($f,
"#define HYBRID_NEXT() HYBRID_JIT_GUARD(); goto *(void**)(OPLINE->handler)\n");
1863 out($f,
"#define HYBRID_SWITCH() HYBRID_NEXT();\n");
1864 out($f,
"#define HYBRID_CASE(op) op ## _LABEL\n");
1865 out($f,
"#define HYBRID_BREAK() HYBRID_NEXT()\n");
1866 out($f,
"#define HYBRID_DEFAULT ZEND_NULL_LABEL\n");
1870 out($f,
"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
1871 out($f,
"# define ZEND_OPCODE_HANDLER_ARGS void\n");
1872 out($f,
"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU\n");
1873 out($f,
"# define ZEND_OPCODE_HANDLER_ARGS_DC\n");
1874 out($f,
"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC\n");
1876 out($f,
"# define ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data\n");
1877 out($f,
"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU execute_data\n");
1878 out($f,
"# define ZEND_OPCODE_HANDLER_ARGS_DC , ZEND_OPCODE_HANDLER_ARGS\n");
1879 out($f,
"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC , ZEND_OPCODE_HANDLER_ARGS_PASSTHRU\n");
1882 out($f,
"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n");
1883 out($f,
"# define ZEND_OPCODE_HANDLER_RET void\n");
1884 out($f,
"# define ZEND_VM_TAIL_CALL(call) call; return\n");
1885 out($f,
"# ifdef ZEND_VM_TAIL_CALL_DISPATCH\n");
1886 out($f,
"# define ZEND_VM_CONTINUE() ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); return\n");
1888 out($f,
"# define ZEND_VM_CONTINUE() return\n");
1889 out($f,
"# endif\n");
1891 out($f,
"# if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
1892 out($f,
"# define ZEND_VM_RETURN() opline = &hybrid_halt_op; return\n");
1893 out($f,
"# define ZEND_VM_HOT zend_always_inline ZEND_COLD ZEND_OPT_SIZE\n");
1894 out($f,
"# define ZEND_VM_COLD ZEND_COLD ZEND_OPT_SIZE\n");
1896 out($f,
"# define ZEND_VM_RETURN() opline = NULL; return\n");
1897 out($f,
"# define ZEND_VM_HOT\n");
1898 out($f,
"# define ZEND_VM_COLD ZEND_COLD ZEND_OPT_SIZE\n");
1899 out($f,
"# endif\n");
1901 out($f,
"# define ZEND_VM_RETURN() opline = NULL; return\n");
1902 out($f,
"# define ZEND_VM_COLD ZEND_COLD ZEND_OPT_SIZE\n");
1905 out($f,
"# define ZEND_OPCODE_HANDLER_RET int\n");
1906 out($f,
"# define ZEND_VM_TAIL_CALL(call) return call\n");
1907 out($f,
"# define ZEND_VM_CONTINUE() return 0\n");
1908 out($f,
"# define ZEND_VM_RETURN() return -1\n");
1910 out($f,
"# define ZEND_VM_HOT\n");
1912 out($f,
"# define ZEND_VM_COLD ZEND_COLD ZEND_OPT_SIZE\n");
1915 out($f,
"typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS);\n");
1917 out($f,
"#define DCL_OPLINE\n");
1918 out($f,
"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
1919 out($f,
"# define OPLINE opline\n");
1920 out($f,
"# define USE_OPLINE\n");
1921 out($f,
"# define LOAD_OPLINE() opline = EX(opline)\n");
1922 out($f,
"# define LOAD_OPLINE_EX()\n");
1923 out($f,
"# define LOAD_NEXT_OPLINE() opline = EX(opline) + 1\n");
1924 out($f,
"# define SAVE_OPLINE() EX(opline) = opline\n");
1925 out($f,
"# define SAVE_OPLINE_EX() SAVE_OPLINE()\n");
1927 out($f,
"# define OPLINE EX(opline)\n");
1928 out($f,
"# define USE_OPLINE const zend_op *opline = EX(opline);\n");
1929 out($f,
"# define LOAD_OPLINE()\n");
1930 out($f,
"# define LOAD_OPLINE_EX()\n");
1931 out($f,
"# define LOAD_NEXT_OPLINE() ZEND_VM_INC_OPCODE()\n");
1932 out($f,
"# define SAVE_OPLINE()\n");
1933 out($f,
"# define SAVE_OPLINE_EX()\n");
1935 out($f,
"#define HANDLE_EXCEPTION() ZEND_ASSERT(EG(exception)); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
1936 out($f,
"#define HANDLE_EXCEPTION_LEAVE() ZEND_ASSERT(EG(exception)); LOAD_OPLINE(); ZEND_VM_LEAVE()\n");
1937 out($f,
"#if defined(ZEND_VM_FP_GLOBAL_REG)\n");
1938 out($f,
"# define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n");
1939 out($f,
"# define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n");
1940 out($f,
"# define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n");
1941 out($f,
"#elif defined(ZEND_VM_IP_GLOBAL_REG)\n");
1942 out($f,
"# define ZEND_VM_ENTER_EX() return 1\n");
1943 out($f,
"# define ZEND_VM_ENTER() opline = EG(current_execute_data)->opline; ZEND_VM_ENTER_EX()\n");
1944 out($f,
"# define ZEND_VM_LEAVE() return 2\n");
1946 out($f,
"# define ZEND_VM_ENTER_EX() return 1\n");
1947 out($f,
"# define ZEND_VM_ENTER() return 1\n");
1948 out($f,
"# define ZEND_VM_LEAVE() return 2\n");
1950 out($f,
"#define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper".($spec?
"_SPEC":
"").
"(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n");
1951 out($f,
"#define ZEND_VM_LOOP_INTERRUPT() zend_interrupt_helper".($spec?
"_SPEC":
"").
"(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
1953 out($f,
"#define ZEND_VM_DISPATCH(opcode, opline) ZEND_VM_TAIL_CALL(((opcode_handler_t)zend_vm_get_opcode_handler_func(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n");
1955 out($f,
"#define ZEND_VM_DISPATCH(opcode, opline) ZEND_VM_TAIL_CALL(((opcode_handler_t)zend_vm_get_opcode_handler(opcode, opline))(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n");
1958 out($f,
"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_helper".($spec?
"_SPEC":
"").
"(ZEND_OPCODE_HANDLER_ARGS);\n");
1959 out($f,
"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS);\n");
1964 out($f,
"#define OPLINE opline\n");
1965 out($f,
"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
1966 out($f,
"# define DCL_OPLINE register const zend_op *opline __asm__(ZEND_VM_IP_GLOBAL_REG);\n");
1968 out($f,
"# define DCL_OPLINE const zend_op *opline;\n");
1970 out($f,
"#define USE_OPLINE\n");
1971 out($f,
"#define LOAD_OPLINE() opline = EX(opline)\n");
1972 out($f,
"# define LOAD_OPLINE_EX() LOAD_OPLINE()\n");
1973 out($f,
"#define LOAD_NEXT_OPLINE() opline = EX(opline) + 1\n");
1974 out($f,
"#define SAVE_OPLINE() EX(opline) = opline\n");
1975 out($f,
"#define SAVE_OPLINE_EX()\n");
1976 out($f,
"#define HANDLE_EXCEPTION() ZEND_ASSERT(EG(exception)); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
1977 out($f,
"#define HANDLE_EXCEPTION_LEAVE() ZEND_ASSERT(EG(exception)); LOAD_OPLINE(); ZEND_VM_LEAVE()\n");
1978 out($f,
"#define ZEND_VM_CONTINUE() goto zend_vm_continue\n");
1979 out($f,
"#define ZEND_VM_RETURN() return\n");
1980 out($f,
"#define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n");
1981 out($f,
"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n");
1982 out($f,
"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n");
1983 out($f,
"#define ZEND_VM_INTERRUPT() goto zend_interrupt_helper".($spec?
"_SPEC":
"").
";\n");
1984 out($f,
"#define ZEND_VM_LOOP_INTERRUPT() goto zend_interrupt_helper".($spec?
"_SPEC":
"").
";\n");
1985 out($f,
"#define ZEND_VM_DISPATCH(opcode, opline) dispatch_handler = zend_vm_get_opcode_handler(opcode, opline); goto zend_vm_dispatch;\n");
1990 out($f,
"#define OPLINE opline\n");
1991 out($f,
"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
1992 out($f,
"# define DCL_OPLINE register const zend_op *opline __asm__(ZEND_VM_IP_GLOBAL_REG);\n");
1994 out($f,
"# define DCL_OPLINE const zend_op *opline;\n");
1996 out($f,
"#define USE_OPLINE\n");
1997 out($f,
"#define LOAD_OPLINE() opline = EX(opline)\n");
1998 out($f,
"#define LOAD_OPLINE_EX() LOAD_OPLINE()\n");
1999 out($f,
"#define LOAD_NEXT_OPLINE() opline = EX(opline) + 1\n");
2000 out($f,
"#define SAVE_OPLINE() EX(opline) = opline\n");
2001 out($f,
"#define SAVE_OPLINE_EX()\n");
2003 out($f,
"#define HANDLE_EXCEPTION() ZEND_ASSERT(EG(exception)); goto ZEND_HANDLE_EXCEPTION_SPEC_LABEL\n");
2004 out($f,
"#define HANDLE_EXCEPTION_LEAVE() ZEND_ASSERT(EG(exception)); goto ZEND_HANDLE_EXCEPTION_SPEC_LABEL\n");
2006 out($f,
"#define HANDLE_EXCEPTION() ZEND_ASSERT(EG(exception)); goto ZEND_HANDLE_EXCEPTION_LABEL\n");
2007 out($f,
"#define HANDLE_EXCEPTION_LEAVE() ZEND_ASSERT(EG(exception)); goto ZEND_HANDLE_EXCEPTION_LABEL\n");
2009 out($f,
"#define ZEND_VM_CONTINUE() goto *(void**)(OPLINE->handler)\n");
2010 out($f,
"#define ZEND_VM_RETURN() return\n");
2011 out($f,
"#define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n");
2012 out($f,
"#define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n");
2013 out($f,
"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n");
2014 out($f,
"#define ZEND_VM_INTERRUPT() goto zend_interrupt_helper".($spec?
"_SPEC":
"").
";\n");
2015 out($f,
"#define ZEND_VM_LOOP_INTERRUPT() goto zend_interrupt_helper".($spec?
"_SPEC":
"").
";\n");
2016 out($f,
"#define ZEND_VM_DISPATCH(opcode, opline) goto *(void**)(zend_vm_get_opcode_handler(opcode, opline));\n");
2023 out($f,
"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
2024 out($f,
"# undef ZEND_VM_TAIL_CALL\n");
2025 out($f,
"# undef ZEND_VM_CONTINUE\n");
2026 out($f,
"# undef ZEND_VM_RETURN\n");
2029 out($f,
"# define ZEND_VM_TAIL_CALL(call) call; ZEND_VM_CONTINUE()\n");
2030 out($f,
"# define ZEND_VM_CONTINUE() HYBRID_NEXT()\n");
2031 out($f,
"# define ZEND_VM_RETURN() goto HYBRID_HALT_LABEL\n");
2033 out($f,
"#endif\n\n");
2036 case "EXECUTOR_NAME":
2037 out($f, $m[1].$executor_name.$m[3].
"\n");
2041 out($f,$m[1].
"const void *dispatch_handler;\n");
2045 out($f,
"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
2049 out($f,$m[1].$param.
";\n");
2052 out($f,
"#endif\n");
2056 out($f,
"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
2057 out($f,$m[1].
"register zend_execute_data *execute_data __asm__(ZEND_VM_FP_GLOBAL_REG) = ex;\n");
2059 out($f,$m[1].
"zend_execute_data *execute_data = ex;\n");
2062 out($f,
"#if defined(ZEND_VM_IP_GLOBAL_REG) || defined(ZEND_VM_FP_GLOBAL_REG)\n");
2063 out($f,$m[1].
"struct {\n");
2064 out($f,
"#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE\n");
2065 out($f,$m[1].
"\tchar hybrid_jit_red_zone[ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE];\n");
2067 out($f,
"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
2068 out($f,$m[1].
"\tconst zend_op *orig_opline;\n");
2070 out($f,
"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
2071 out($f,$m[1].
"\tzend_execute_data *orig_execute_data;\n");
2073 out($f,$m[1].
"} vm_stack_data;\n");
2075 out($f,
"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
2076 out($f,$m[1].
"vm_stack_data.orig_opline = opline;\n");
2078 out($f,
"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
2079 out($f,$m[1].
"vm_stack_data.orig_execute_data = execute_data;\n");
2080 out($f,$m[1].
"execute_data = ex;\n");
2082 out($f,$m[1].
"zend_execute_data *execute_data = ex;\n");
2086 case "INTERNAL_LABELS":
2091 out($f,
"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
2094 out($f,$prolog.
"if (UNEXPECTED(execute_data == NULL)) {\n");
2095 out($f,$prolog.
"\tstatic const void * const labels[] = {\n");
2097 out($f,$prolog.
"\t};\n");
2098 out($f,$prolog.
"\tzend_opcode_handlers = (const void **) labels;\n");
2099 out($f,$prolog.
"\tzend_handlers_count = sizeof(labels) / sizeof(void*);\n");
2101 out($f,$prolog.
"\tmemset(&hybrid_halt_op, 0, sizeof(hybrid_halt_op));\n");
2102 out($f,$prolog.
"\thybrid_halt_op.handler = (void*)&&HYBRID_HALT_LABEL;\n");
2103 out($f,
"#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE\n");
2104 out($f,$prolog.
"\tmemset(vm_stack_data.hybrid_jit_red_zone, 0, ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE);\n");
2106 out($f,$prolog.
"\tif (zend_touch_vm_stack_data) {\n");
2107 out($f,$prolog.
"\t\tzend_touch_vm_stack_data(&vm_stack_data);\n");
2108 out($f,$prolog.
"\t}\n");
2109 out($f,$prolog.
"\tgoto HYBRID_HALT_LABEL;\n");
2111 out($f,$prolog.
"\treturn;\n");
2113 out($f,$prolog.
"}\n");
2121 case "ZEND_VM_CONTINUE_LABEL":
2124 out($f,
"#if !defined(ZEND_VM_FP_GLOBAL_REG) || !defined(ZEND_VM_IP_GLOBAL_REG)\n");
2125 out($f,$m[1].
"\tint ret;".$m[3].
"\n");
2129 out($f,
"zend_vm_continue:".$m[3].
"\n");
2134 case "ZEND_VM_DISPATCH":
2138 out($f, $m[1].
"dispatch_handler = OPLINE->handler;\nzend_vm_dispatch:\n".$m[1].
"switch ((int)(uintptr_t)dispatch_handler)".$m[3].
"\n");
2141 out($f, $m[1].
"goto *(void**)(OPLINE->handler);".$m[3].
"\n");
2144 out($f,
"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
2145 out($f, $m[1].
"HYBRID_SWITCH()".$m[3].
"\n");
2148 out($f,
"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n");
2149 out($f, $m[1].
"((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
2150 out($f, $m[1].
"if (UNEXPECTED(!OPLINE))".$m[3].
"\n");
2152 out($f, $m[1].
"if (UNEXPECTED((ret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) != 0))".$m[3].
"\n");
2160 case "INTERNAL_EXECUTOR":
2164 out($f,
"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
2174 "#ifdef ZEND_VM_FP_GLOBAL_REG\n" .
2175 $m[1].
"execute_data = vm_stack_data.orig_execute_data;\n" .
2176 "# ifdef ZEND_VM_IP_GLOBAL_REG\n" .
2177 $m[1].
"opline = vm_stack_data.orig_opline;\n" .
2181 $m[1].
"if (EXPECTED(ret > 0)) {\n" .
2182 $m[1].
"\texecute_data = EG(current_execute_data);\n".
2183 $m[1].
"\tZEND_VM_LOOP_INTERRUPT_CHECK();\n".
2184 $m[1].
"} else {\n" .
2185 "# ifdef ZEND_VM_IP_GLOBAL_REG\n" .
2186 $m[1].
"\topline = vm_stack_data.orig_opline;\n" .
2188 $m[1].
"\treturn;\n".
2196 case "EXTERNAL_EXECUTOR":
2201 case "INITIALIZER_NAME":
2202 out($f, $m[1].$initializer_name.$m[3].
"\n");
2204 case "EXTERNAL_LABELS":
2210 out($f,$prolog.
"static const uint32_t specs[] = {\n");
2212 out($f,$prolog.
"};\n");
2213 out($f,$prolog.
"zend_spec_handlers = specs;\n");
2214 out($f,$prolog.$executor_name.
"_ex(NULL);\n");
2216 out($f,$prolog.
"static const void * const labels[] = {\n");
2218 out($f,$prolog.
"};\n");
2219 out($f,$prolog.
"static const uint32_t specs[] = {\n");
2221 out($f,$prolog.
"};\n");
2223 out($f,
"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
2224 out($f,$prolog.
"zend_opcode_handler_funcs = labels;\n");
2225 out($f,$prolog.
"zend_spec_handlers = specs;\n");
2226 out($f,$prolog.$executor_name.
"_ex(NULL);\n");
2229 out($f,$prolog.
"zend_opcode_handlers = labels;\n");
2230 out($f,$prolog.
"zend_handlers_count = sizeof(labels) / sizeof(void*);\n");
2231 out($f,$prolog.
"zend_spec_handlers = specs;\n");
2238 die(
"ERROR: Unknown keyword ".$m[2].
" in skeleton file.\n");
2252 foreach (
$a as $val) {
2256 die(
"ERROR ($def:$lineno): Wrong operand type '$str'\n");
2261 die(
"ERROR ($def:$lineno): Wrong operand type '$str'\n");
2273 foreach (
$a as $val) {
2277 die(
"ERROR ($def:$lineno): Wrong extended_value type '$str'\n");
2288 foreach (
$a as $rule) {
2298 die(
"ERROR ($def:$lineno): Wrong specialization rules '$str'\n");
2304 $ret[
"RETVAL"] = array(0, 1);
2307 $ret[
"QUICK_ARG"] = array(0, 1);
2309 case "SMART_BRANCH":
2310 $ret[
"SMART_BRANCH"] = array(0, 1, 2);
2312 case "NO_CONST_CONST":
2313 $ret[
"NO_CONST_CONST"] = array(1);
2316 $ret[
"COMMUTATIVE"] = array(1);
2319 $ret[
"ISSET"] = array(0, 1);
2322 $ret[
"OBSERVER"] = array(0, 1);
2325 die(
"ERROR ($def:$lineno): Wrong specialization rules '$str'\n");
2337 $str .=
"#ifndef ZEND_VM_OPCODES_H\n#define ZEND_VM_OPCODES_H\n\n";
2338 $str .=
"#define ZEND_VM_SPEC\t\t" .
ZEND_VM_SPEC .
"\n";
2344 if ($GLOBALS[
"vm_kind_name"][
ZEND_VM_KIND] ===
"ZEND_VM_KIND_HYBRID") {
2345 $str .=
"/* HYBRID requires support for computed GOTO and global register variables*/\n";
2346 $str .=
"#if (defined(__GNUC__) && defined(HAVE_GCC_GLOBAL_REGS))\n";
2347 $str .=
"# define ZEND_VM_KIND\t\tZEND_VM_KIND_HYBRID\n";
2349 $str .=
"# define ZEND_VM_KIND\t\tZEND_VM_KIND_CALL\n";
2352 $str .=
"#define ZEND_VM_KIND\t\t" . $GLOBALS[
"vm_kind_name"][
ZEND_VM_KIND] .
"\n";
2355 $str .=
"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) && !defined(__SANITIZE_ADDRESS__)\n";
2356 $str .=
"# if ((defined(i386) && !defined(__PIC__)) || defined(__x86_64__) || defined(_M_X64))\n";
2357 $str .=
"# define ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE 48\n";
2358 $str .=
"# endif\n";
2362 $str .=
sprintf(
"#define %-24s 0x%08x\n",
$name, $val);
2364 $str .=
"#define ZEND_VM_OP1_FLAGS(flags) (flags & 0xff)\n";
2365 $str .=
"#define ZEND_VM_OP2_FLAGS(flags) ((flags >> 8) & 0xff)\n";
2367 $str .=
"BEGIN_EXTERN_C()\n\n";
2368 $str .=
"ZEND_API const char* ZEND_FASTCALL zend_get_opcode_name(uint8_t opcode);\n";
2369 $str .=
"ZEND_API uint32_t ZEND_FASTCALL zend_get_opcode_flags(uint8_t opcode);\n";
2370 $str .=
"ZEND_API uint8_t zend_get_opcode_id(const char *name, size_t length);\n\n";
2371 $str .=
"END_EXTERN_C()\n\n";
2373 $code_len =
strlen((
string) $max_opcode);
2374 foreach (
$opcodes as $code => $dsc) {
2376 $op =
str_pad($dsc[
"op"], $max_opcode_len);
2377 if ($code <= $max_opcode) {
2378 $str .=
"#define $op $code\n";
2383 $op =
str_pad(
"ZEND_VM_LAST_OPCODE", $max_opcode_len);
2384 $str .=
"\n#define $op $code\n";
2386 $str .=
"\n#endif\n";
2391 global $definition_file, $skeleton_file, $executor_file,
2398 die(
"ERROR: Cannot open definition file '$def'\n");
2404 $skl = @
file($skel);
2406 die(
"ERROR: Cannot open skeleton file '$skel'\n");
2415 $max_opcode_len = 0;
2418 foreach ($in as $line) {
2422 if (
substr($line, -2) ===
"\r\n") {
2426 if (
strpos($line,
"ZEND_VM_HANDLER(") === 0 ||
2427 strpos($line,
"ZEND_VM_INLINE_HANDLER(") === 0 ||
2428 strpos($line,
"ZEND_VM_HOT_HANDLER(") === 0 ||
2429 strpos($line,
"ZEND_VM_HOT_NOCONST_HANDLER(") === 0 ||
2430 strpos($line,
"ZEND_VM_HOT_NOCONSTCONST_HANDLER(") === 0 ||
2431 strpos($line,
"ZEND_VM_HOT_SEND_HANDLER(") === 0 ||
2432 strpos($line,
"ZEND_VM_HOT_OBJ_HANDLER(") === 0 ||
2433 strpos($line,
"ZEND_VM_COLD_HANDLER(") === 0 ||
2434 strpos($line,
"ZEND_VM_COLD_CONST_HANDLER(") === 0 ||
2435 strpos($line,
"ZEND_VM_COLD_CONSTCONST_HANDLER(") === 0) {
2439 ZEND_VM_(HOT_|INLINE_|HOT_OBJ_|HOT_SEND_|HOT_NOCONST_|HOT_NOCONSTCONST_|COLD_|COLD_CONST_|COLD_CONSTCONST_)?HANDLER\(
2441 \s*([A-Z_][A-Z0-9_]*)\s*,
2444 (,\s*([A-Z_|]+)\s*)?
2445 (,\s*SPEC\(([A-Z_|=,]+)\)\s*)?
2450 die(
"ERROR ($def:$lineno): Invalid ZEND_VM_HANDLER definition.\n");
2452 $hot = !empty($m[1]) ? $m[1] :
false;
2458 $flags = $flags1 | ($flags2 << 8);
2459 if (!empty($m[7])) {
2463 if ($len > $max_opcode_len) {
2464 $max_opcode_len = $len;
2466 if ($code > $max_opcode) {
2467 $max_opcode = $code;
2470 die(
"ERROR ($def:$lineno): Opcode with code '$code' is already defined.\n");
2473 die(
"ERROR ($def:$lineno): Opcode with name '$op' is already defined.\n");
2475 $opcodes[$code] = array(
"op"=>$op,
"op1"=>$op1,
"op2"=>$op2,
"code"=>
"",
"flags"=>$flags,
"hot"=>$hot);
2478 if (isset(
$opcodes[$code][
"spec"][
"NO_CONST_CONST"])) {
2481 if (isset(
$opcodes[$code][
"spec"][
"COMMUTATIVE"])) {
2488 $list[$lineno] = array(
"handler"=>$handler);
2489 }
else if (
strpos($line,
"ZEND_VM_TYPE_SPEC_HANDLER(") === 0 ||
2490 strpos($line,
"ZEND_VM_INLINE_TYPE_SPEC_HANDLER(") === 0 ||
2491 strpos($line,
"ZEND_VM_HOT_TYPE_SPEC_HANDLER(") === 0 ||
2492 strpos($line,
"ZEND_VM_HOT_NOCONST_TYPE_SPEC_HANDLER(") === 0 ||
2493 strpos($line,
"ZEND_VM_HOT_NOCONSTCONST_TYPE_SPEC_HANDLER(") === 0 ||
2494 strpos($line,
"ZEND_VM_HOT_SEND_TYPE_SPEC_HANDLER(") === 0 ||
2495 strpos($line,
"ZEND_VM_HOT_OBJ_TYPE_SPEC_HANDLER(") === 0) {
2499 ZEND_VM_(HOT_|INLINE_|HOT_OBJ_|HOT_SEND_|HOT_NOCONST_|HOT_NOCONSTCONST_)?TYPE_SPEC_HANDLER\(
2501 \s*((?:[^(,]|\([^()]*|(?R)*\))*),
2505 (,\s*([A-Z_|]+)\s*)?
2506 (,\s*SPEC\(([A-Z_|=,]+)\)\s*)?
2511 die(
"ERROR ($def:$lineno): Invalid ZEND_VM_TYPE_HANDLER_HANDLER definition.\n");
2513 $hot = !empty($m[1]) ? $m[1] :
false;
2514 $orig_op_list = $m[2];
2515 $code = $extra_num++;
2516 foreach (
explode(
'|', $orig_op_list) as $orig_op) {
2518 die(
"ERROR ($def:$lineno): Opcode with name '$orig_op' is not defined.\n");
2522 $opcodes[$orig_code][
'type_spec'][$code] = $condition;
2527 $flags = $flags1 | ($flags2 << 8);
2528 if (!empty($m[8])) {
2533 die(
"ERROR ($def:$lineno): Opcode with name '$code' is already defined.\n");
2536 $opcodes[$code] = array(
"op"=>$op,
"op1"=>$op1,
"op2"=>$op2,
"code"=>
"",
"flags"=>$flags,
"hot"=>$hot,
"is_type_spec"=>
true);
2537 if (isset($m[10])) {
2539 if (isset(
$opcodes[$code][
"spec"][
"NO_CONST_CONST"])) {
2542 if (isset(
$opcodes[$code][
"spec"][
"COMMUTATIVE"])) {
2549 $list[$lineno] = array(
"handler"=>$handler);
2550 }
else if (
strpos($line,
"ZEND_VM_HELPER(") === 0 ||
2551 strpos($line,
"ZEND_VM_INLINE_HELPER(") === 0 ||
2552 strpos($line,
"ZEND_VM_COLD_HELPER(") === 0 ||
2553 strpos($line,
"ZEND_VM_HOT_HELPER(") === 0) {
2557 ZEND_VM(_INLINE|_COLD|_HOT)?_HELPER\(
2561 (?:,\s*SPEC\(([A-Z_|=,]+)\)\s*)?
2567 die(
"ERROR ($def:$lineno): Invalid ZEND_VM_HELPER definition.\n");
2569 $inline = !empty($m[1]) && $m[1] ===
"_INLINE";
2570 $cold = !empty($m[1]) && $m[1] ===
"_COLD";
2571 $hot = !empty($m[1]) && $m[1] ===
"_HOT";
2575 $param = isset($m[6]) ? $m[6] :
null;
2577 die(
"ERROR ($def:$lineno): Helper with name '$helper' is already defined.\n");
2585 foreach (
explode(
",", $param ) as $p) {
2593 $helpers[$helper] = array(
"op1"=>$op1,
"op2"=>$op2,
"param"=>$param,
"code"=>
"",
"inline"=>$inline,
"cold"=>$cold,
"hot"=>$hot);
2595 if (!empty($m[5])) {
2600 $list[$lineno] = array(
"helper"=>$helper);
2601 }
else if (
strpos($line,
"ZEND_VM_DEFINE_OP(") === 0) {
2603 "/^ZEND_VM_DEFINE_OP\(\s*([0-9]+)\s*,\s*([A-Z_]+)\s*\);/",
2606 die(
"ERROR ($def:$lineno): Invalid ZEND_VM_DEFINE_OP definition.\n");
2612 if ($len > $max_opcode_len) {
2613 $max_opcode_len = $len;
2615 if ($code > $max_opcode) {
2616 $max_opcode = $code;
2619 die(
"ERROR ($def:$lineno): Opcode with code '$code' is already defined.\n");
2622 die(
"ERROR ($def:$lineno): Opcode with name '$op' is already defined.\n");
2624 $opcodes[$code] = array(
"op"=>$op,
"code"=>
"");
2626 }
else if ($handler !==
null) {
2628 $opcodes[$handler][
"code"] .= $line;
2629 }
else if ($helper !==
null) {
2631 $helpers[$helper][
"code"] .= $line;
2639 if (
preg_match(
"/^\s*{\s*ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)\s*;\s*}\s*/", $dsc[
"code"], $m)) {
2642 die(
"ERROR ($def:$lineno): Opcode with name '$op' is not defined.\n");
2650 foreach ($mm as $m) {
2653 die(
"ERROR ($def:$lineno): Opcode with name '$op' is not defined.\n");
2664 echo
"zend_vm_opcodes.h generated successfully.\n";
2667 $f =
fopen(__DIR__ .
"/zend_vm_opcodes.c",
"w+") or
die(
"ERROR: Cannot create zend_vm_opcodes.c\n");
2671 fputs($f,
"#include <stdio.h>\n");
2672 fputs($f,
"#include <zend.h>\n");
2673 fputs($f,
"#include <zend_vm_opcodes.h>\n\n");
2675 fputs($f,
"static const char *zend_vm_opcodes_names[".($max_opcode + 1).
"] = {\n");
2676 for ($i = 0; $i <= $max_opcode; $i++) {
2679 fputs($f,
"};\n\n");
2681 fputs($f,
"static uint32_t zend_vm_opcodes_flags[".($max_opcode + 1).
"] = {\n");
2682 for ($i = 0; $i <= $max_opcode; $i++) {
2685 fputs($f,
"};\n\n");
2687 fputs($f,
"ZEND_API const char* ZEND_FASTCALL zend_get_opcode_name(uint8_t opcode) {\n");
2688 fputs($f,
"\tif (UNEXPECTED(opcode > ZEND_VM_LAST_OPCODE)) {\n");
2689 fputs($f,
"\t\treturn NULL;\n");
2691 fputs($f,
"\treturn zend_vm_opcodes_names[opcode];\n");
2694 fputs($f,
"ZEND_API uint32_t ZEND_FASTCALL zend_get_opcode_flags(uint8_t opcode) {\n");
2695 fputs($f,
"\tif (UNEXPECTED(opcode > ZEND_VM_LAST_OPCODE)) {\n");
2696 fputs($f,
"\t\topcode = ZEND_NOP;\n");
2698 fputs($f,
"\treturn zend_vm_opcodes_flags[opcode];\n");
2701 fputs($f,
"ZEND_API uint8_t zend_get_opcode_id(const char *name, size_t length) {\n");
2702 fputs($f,
"\tuint8_t opcode;\n");
2703 fputs($f,
"\tfor (opcode = 0; opcode < (sizeof(zend_vm_opcodes_names) / sizeof(zend_vm_opcodes_names[0])) - 1; opcode++) {\n");
2704 fputs($f,
"\t\tconst char *opcode_name = zend_vm_opcodes_names[opcode];\n");
2705 fputs($f,
"\t\tif (opcode_name && strncmp(opcode_name, name, length) == 0) {\n");
2706 fputs($f,
"\t\t\treturn opcode;\n");
2707 fputs($f,
"\t\t}\n");
2709 fputs($f,
"\treturn ZEND_VM_LAST_OPCODE + 1;\n");
2713 echo
"zend_vm_opcodes.c generated successfully.\n";
2716 $f =
fopen(__DIR__ .
"/zend_vm_execute.h",
"w+") or
die(
"ERROR: Cannot create zend_vm_execute.h\n");
2717 $executor_file =
realpath(__DIR__ .
"/zend_vm_execute.h");
2722 out($f,
"#ifdef ZEND_WIN32\n");
2724 out($f,
"# pragma warning(disable : 4101)\n");
2727 out($f,
"# pragma warning(once : 6235)\n");
2729 out($f,
"# pragma warning(once : 6237)\n");
2731 out($f,
"# pragma warning(once : 6239)\n");
2733 out($f,
"# pragma warning(once : 6240)\n");
2735 out($f,
"# pragma warning(once : 6285)\n");
2737 out($f,
"# pragma warning(once : 6286)\n");
2739 out($f,
"# pragma warning(once : 6326)\n");
2741 out($f,
"#endif\n");
2744 out($f,
"static user_opcode_handler_t zend_user_opcode_handlers[256] = {\n");
2745 for ($i = 0; $i < 255; ++$i) {
2746 out($f,
"\t(user_opcode_handler_t)NULL,\n");
2748 out($f,
"\t(user_opcode_handler_t)NULL\n};\n\n");
2750 out($f,
"static uint8_t zend_user_opcodes[256] = {");
2751 for ($i = 0; $i < 255; ++$i) {
2752 if ($i % 16 == 1)
out($f,
"\n\t");
2755 out($f,
"255\n};\n\n");
2762 out($f,
"static uint32_t ZEND_FASTCALL zend_vm_get_opcode_handler_idx(uint32_t spec, const zend_op* op)\n");
2765 out($f,
"\treturn spec;\n");
2767 out($f,
"\tstatic const int zend_vm_decode[] = {\n");
2768 out($f,
"\t\t_UNUSED_CODE, /* 0 = IS_UNUSED */\n");
2769 out($f,
"\t\t_CONST_CODE, /* 1 = IS_CONST */\n");
2770 out($f,
"\t\t_TMP_CODE, /* 2 = IS_TMP_VAR */\n");
2771 out($f,
"\t\t_UNUSED_CODE, /* 3 */\n");
2772 out($f,
"\t\t_VAR_CODE, /* 4 = IS_VAR */\n");
2773 out($f,
"\t\t_UNUSED_CODE, /* 5 */\n");
2774 out($f,
"\t\t_UNUSED_CODE, /* 6 */\n");
2775 out($f,
"\t\t_UNUSED_CODE, /* 7 */\n");
2776 out($f,
"\t\t_CV_CODE /* 8 = IS_CV */\n");
2778 out($f,
"\tuint32_t offset = 0;\n");
2779 out($f,
"\tif (spec & SPEC_RULE_OP1) offset = offset * 5 + zend_vm_decode[op->op1_type];\n");
2780 out($f,
"\tif (spec & SPEC_RULE_OP2) offset = offset * 5 + zend_vm_decode[op->op2_type];\n");
2790 out($f,
"\tif (spec & SPEC_EXTRA_MASK) {\n");
2793 out($f,
"\t\t{$else}if (spec & SPEC_RULE_RETVAL) {\n");
2794 out($f,
"\t\t\toffset = offset * 2 + (op->result_type != IS_UNUSED);\n");
2795 out($f,
"\t\t\tif ((spec & SPEC_RULE_OBSERVER) && ZEND_OBSERVER_ENABLED) {\n");
2796 out($f,
"\t\t\t\toffset += 2;\n");
2797 out($f,
"\t\t\t}\n");
2801 out($f,
"\t\t{$else}if (spec & SPEC_RULE_QUICK_ARG) {\n");
2802 out($f,
"\t\t\toffset = offset * 2 + (op->op2.num <= MAX_ARG_FLAG_NUM);\n");
2806 out($f,
"\t\t{$else}if (spec & SPEC_RULE_OP_DATA) {\n");
2807 out($f,
"\t\t\toffset = offset * 5 + zend_vm_decode[(op + 1)->op1_type];\n");
2811 out($f,
"\t\t{$else}if (spec & SPEC_RULE_ISSET) {\n");
2812 out($f,
"\t\t\toffset = offset * 2 + (op->extended_value & ZEND_ISEMPTY);\n");
2816 out($f,
"\t\t{$else}if (spec & SPEC_RULE_SMART_BRANCH) {\n");
2817 out($f,
"\t\t\toffset = offset * 3;\n");
2818 out($f,
"\t\t\tif (op->result_type == (IS_SMART_BRANCH_JMPZ|IS_TMP_VAR)) {\n");
2819 out($f,
"\t\t\t\toffset += 1;\n");
2820 out($f,
"\t\t\t} else if (op->result_type == (IS_SMART_BRANCH_JMPNZ|IS_TMP_VAR)) {\n");
2821 out($f,
"\t\t\t\toffset += 2;\n");
2822 out($f,
"\t\t\t}\n");
2826 out($f,
"\t\t{$else}if (spec & SPEC_RULE_OBSERVER) {\n");
2827 out($f,
"\t\t\toffset = offset * 2;\n");
2828 out($f,
"\t\t\tif (ZEND_OBSERVER_ENABLED) {\n");
2829 out($f,
"\t\t\t\toffset += 1;\n");
2830 out($f,
"\t\t\t}\n");
2838 out($f,
"\treturn (spec & SPEC_START_MASK) + offset;\n");
2841 out($f,
"#if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID) || !ZEND_VM_SPEC\n");
2842 out($f,
"static const void *zend_vm_get_opcode_handler(uint8_t opcode, const zend_op* op)\n");
2845 out($f,
"\treturn zend_opcode_handlers[zend_vm_get_opcode_handler_idx(opcode, op)];\n");
2847 out($f,
"\treturn zend_opcode_handlers[zend_vm_get_opcode_handler_idx(zend_spec_handlers[opcode], op)];\n");
2850 out($f,
"#endif\n\n");
2854 out($f,
"#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID\n");
2855 out($f,
"static const void *zend_vm_get_opcode_handler_func(uint8_t opcode, const zend_op* op)\n");
2857 out($f,
"\tuint32_t spec = zend_spec_handlers[opcode];\n");
2859 out($f,
"\treturn zend_opcode_handler_funcs[spec];\n");
2861 out($f,
"\treturn zend_opcode_handler_funcs[zend_vm_get_opcode_handler_idx(spec, op)];\n");
2864 out($f,
"#endif\n\n");
2868 out($f,
"ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler(zend_op* op)\n");
2870 out($f,
"\tuint8_t opcode = zend_user_opcodes[op->opcode];\n");
2872 out($f,
"\top->handler = zend_opcode_handlers[zend_vm_get_opcode_handler_idx(opcode, op)];\n");
2875 out($f,
"\tif (zend_spec_handlers[op->opcode] & SPEC_RULE_COMMUTATIVE) {\n");
2876 out($f,
"\t\tif (op->op1_type < op->op2_type) {\n");
2877 out($f,
"\t\t\tzend_swap_operands(op);\n");
2880 out($f,
"\top->handler = zend_opcode_handlers[zend_vm_get_opcode_handler_idx(zend_spec_handlers[opcode], op)];\n");
2885 out($f,
"ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint32_t op2_info, uint32_t res_info)\n");
2887 out($f,
"\tuint8_t opcode = zend_user_opcodes[op->opcode];\n");
2889 out($f,
"\top->handler = zend_opcode_handlers[zend_vm_get_opcode_handler_idx(opcode, op)];\n");
2891 out($f,
"\tuint32_t spec = zend_spec_handlers[opcode];\n");
2893 out($f,
"\tswitch (opcode) {\n");
2894 foreach (
$opcodes as $code => $dsc) {
2895 if (isset($dsc[
'type_spec'])) {
2896 $orig_op = $dsc[
'op'];
2897 out($f,
"\t\tcase $orig_op:\n");
2898 if (isset($dsc[
"spec"][
"COMMUTATIVE"])) {
2899 out($f,
"\t\t\tif (op->op1_type < op->op2_type) {\n");
2900 out($f,
"\t\t\t\tzend_swap_operands(op);\n");
2901 out($f,
"\t\t\t}\n");
2904 foreach ($dsc[
'type_spec'] as $code => $condition) {
2907 out($f,
"\t\t\tif $condition {\n");
2910 out($f,
"\t\t\t} else if $condition {\n");
2913 if (isset($spec_dsc[
"spec"][
"NO_CONST_CONST"])) {
2914 out($f,
"\t\t\t\tif (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {\n");
2915 out($f,
"\t\t\t\t\tbreak;\n");
2916 out($f,
"\t\t\t\t}\n");
2918 out($f,
"\t\t\t\tspec = {$spec_dsc['spec_code']};\n");
2919 if (isset($spec_dsc[
"spec"][
"COMMUTATIVE"]) && !isset($dsc[
"spec"][
"COMMUTATIVE"])) {
2920 out($f,
"\t\t\t\tif (op->op1_type < op->op2_type) {\n");
2921 out($f,
"\t\t\t\t\tzend_swap_operands(op);\n");
2922 out($f,
"\t\t\t\t}\n");
2926 out($f,
"\t\t\t}\n");
2928 out($f,
"\t\t\tbreak;\n");
2931 $has_commutative =
false;
2932 foreach (
$opcodes as $code => $dsc) {
2933 if (!isset($dsc[
'is_type_spec']) &&
2934 !isset($dsc[
'type_spec']) &&
2935 isset($dsc[
"spec"][
"COMMUTATIVE"])) {
2936 $orig_op = $dsc[
'op'];
2937 out($f,
"\t\tcase $orig_op:\n");
2938 $has_commutative =
true;
2941 if ($has_commutative) {
2942 out($f,
"\t\t\tif (op->op1_type < op->op2_type) {\n");
2943 out($f,
"\t\t\t\tzend_swap_operands(op);\n");
2944 out($f,
"\t\t\t}\n");
2945 out($f,
"\t\t\tbreak;\n");
2946 out($f,
"\t\tcase ZEND_USER_OPCODE:\n");
2947 out($f,
"\t\t\tif (zend_spec_handlers[op->opcode] & SPEC_RULE_COMMUTATIVE) {\n");
2948 out($f,
"\t\t\t\tif (op->op1_type < op->op2_type) {\n");
2949 out($f,
"\t\t\t\t\tzend_swap_operands(op);\n");
2950 out($f,
"\t\t\t\t}\n");
2951 out($f,
"\t\t\t}\n");
2952 out($f,
"\t\t\tbreak;\n");
2954 out($f,
"\t\tdefault:\n");
2955 out($f,
"\t\t\tbreak;\n");
2958 out($f,
"\top->handler = zend_opcode_handlers[zend_vm_get_opcode_handler_idx(spec, op)];\n");
2964 out($f,
"ZEND_API int ZEND_FASTCALL zend_vm_call_opcode_handler(zend_execute_data* ex)\n");
2967 out($f,
"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
2968 out($f,
"\topcode_handler_t handler;\n");
2971 out($f,
"\tint ret;\n");
2972 out($f,
"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
2973 out($f,
"\tconst zend_op *orig_opline = opline;\n");
2974 out($f,
"#endif\n");
2975 out($f,
"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
2976 out($f,
"\tzend_execute_data *orig_execute_data = execute_data;\n");
2977 out($f,
"\texecute_data = ex;\n");
2979 out($f,
"\tzend_execute_data *execute_data = ex;\n");
2980 out($f,
"#endif\n");
2982 out($f,
"\tLOAD_OPLINE();\n");
2983 out($f,
"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n");
2985 out($f,
"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
2986 out($f,
"\thandler = (opcode_handler_t)zend_vm_get_opcode_handler_func(zend_user_opcodes[opline->opcode], opline);\n");
2987 out($f,
"\thandler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
2988 out($f,
"\tif (EXPECTED(opline != &hybrid_halt_op)) {\n");
2991 out($f,
"\t((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
2993 out($f,
"\tif (EXPECTED(opline)) {\n");
2996 out($f,
"\tif (EXPECTED(opline)) {\n");
2998 out($f,
"\t\tret = execute_data != ex ? (int)(execute_data->prev_execute_data != ex) + 1 : 0;\n");
2999 out($f,
"\t\tSAVE_OPLINE();\n");
3000 out($f,
"\t} else {\n");
3001 out($f,
"\t\tret = -1;\n");
3004 out($f,
"\tret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
3005 out($f,
"\tSAVE_OPLINE();\n");
3006 out($f,
"#endif\n");
3007 out($f,
"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
3008 out($f,
"\texecute_data = orig_execute_data;\n");
3009 out($f,
"#endif\n");
3010 out($f,
"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
3011 out($f,
"\topline = orig_opline;\n");
3012 out($f,
"#endif\n");
3013 out($f,
"\treturn ret;\n");
3016 out($f,
"ZEND_API int ZEND_FASTCALL zend_vm_call_opcode_handler(zend_execute_data* ex)\n");
3018 out($f,
"\tzend_error_noreturn(E_CORE_ERROR, \"zend_vm_call_opcode_handler() is not supported\");\n");
3019 out($f,
"\treturn 0;\n");
3024 echo
"zend_vm_execute.h generated successfully.\n";
3030 if ($orig_contents === $contents) {
3040 echo(
"\nUsage: php zend_vm_gen.php [options]\n".
3042 "\n --with-vm-kind=CALL|SWITCH|GOTO|HYBRID - select threading model (default is HYBRID)".
3043 "\n --without-specializer - disable executor specialization".
3044 "\n --with-lines - enable #line directives".
3049for ($i = 1; $i < $argc; $i++) {
3050 if (
strpos($argv[$i],
"--with-vm-kind=") === 0) {
3066 echo(
"ERROR: Invalid vm kind '$kind'\n");
3070 }
else if ($argv[$i] ==
"--without-specializer") {
3072 define(
"ZEND_VM_SPEC", 0);
3073 }
else if ($argv[$i] ==
"--with-lines") {
3075 define(
"ZEND_VM_LINES", 1);
3076 }
else if ($argv[$i] ==
"--help") {
3080 echo(
"ERROR: Invalid option '".$argv[$i].
"'\n");
3087if (!
defined(
"ZEND_VM_KIND")) {
3091if (!
defined(
"ZEND_VM_SPEC")) {
3093 define(
"ZEND_VM_SPEC", 1);
3095if (!
defined(
"ZEND_VM_LINES")) {
3097 define(
"ZEND_VM_LINES", 0);
3100gen_vm(__DIR__ .
"/zend_vm_def.h", __DIR__ .
"/zend_vm_execute.skl");
array_intersect_key(array $array, array ... $arrays)
call_user_func_array(callable $callback, array $args)
implode(string|array $separator, ?array $array=null)
array_shift(array &$array)
fprintf($stream, string $format, mixed ... $values)
trim(string $string, string $characters=" \n\r\t\v\0")
substr_count(string $haystack, string $needle, int $offset=0, ?int $length=null)
array_keys(array $array, mixed $filter_value=UNKNOWN, bool $strict=false)
file_exists(string $filename)
file_get_contents(string $filename, bool $use_include_path=false, $context=null, int $offset=0, ?int $length=null)
array_values(array $array)
file(string $filename, int $flags=0, $context=null)
explode(string $separator, string $string, int $limit=PHP_INT_MAX)
substr_replace(array|string $string, array|string $replace, array|int $offset, array|int|null $length=null)
strpos(string $haystack, string $needle, int $offset=0)
file_put_contents(string $filename, mixed $data, int $flags=0, $context=null)
var_dump(mixed $value, mixed ... $values)
str_pad(string $string, int $length, string $pad_string=" ", int $pad_type=STR_PAD_RIGHT)
fputs($stream, string $data, ?int $length=null)
fopen(string $filename, string $mode, bool $use_include_path=false, $context=null)
count(Countable|array $value, int $mode=COUNT_NORMAL)
is_resource(mixed $value)
ksort(array &$array, int $flags=SORT_REGULAR)
fgets($stream, ?int $length=null)
stream_get_contents($stream, ?int $length=null, int $offset=-1)
substr(string $string, int $offset, ?int $length=null)
sprintf("0x%X", $numelems)
unsigned const char * end
preg_replace(string|array $pattern, string|array $replacement, string|array $subject, int $limit=-1, &$count=null)
preg_replace_callback(string|array $pattern, callable $callback, string|array $subject, int $limit=-1, &$count=null, int $flags=0)
preg_match_all(string $pattern, string $subject, &$matches=null, int $flags=0, int $offset=0)
preg_match(string $pattern, string $subject, &$matches=null, int $flags=0, int $offset=0)
unsigned char key[REFLECTION_KEY_LEN]
define(string $constant_name, mixed $value, bool $case_insensitive=false)
error_reporting(?int $error_level=null)
defined(string $constant_name)
die(string|int $status=0)
exit(string|int $status=0)
#define strncasecmp(s1, s2, n)
gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno, $inline, $cold=false, $hot=false, $extra_spec=null)
gen_code($f, $spec, $kind, $code, $op1, $op2, $name, $extra_spec=null)
format_condition($condition)
extra_spec_flags($extra_spec)
extra_spec_name($extra_spec)
$op1_get_zval_ptr_ptr_undef
$op_data_get_zval_ptr_undef
$op1_get_obj_zval_ptr_ptr_undef
gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
is_cold_handler($hot, $op1, $op2, $extra_spec)
is_hot_handler($hot, $op1, $op2, $extra_spec)
$op2_get_obj_zval_ptr_ptr_undef
$op_data_get_zval_ptr_deref
$op1_get_obj_zval_ptr_ptr
parse_operand_spec($def, $lineno, $str, &$flags)
skip_extra_spec_function($op1, $op2, $extra_spec)
gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels=array())
write_file_if_changed(string $filename, string $contents)
gen_specs($f, $prolog, $specs)
$op_data_get_zval_ptr_ptr
opcode_name($name, $spec, $op1, $op2, $extra_spec)
$op2_get_zval_ptr_ptr_undef
$op2_get_obj_zval_ptr_deref
gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels=array())
$op1_get_obj_zval_ptr_undef
$op2_get_obj_zval_ptr_ptr
foreach($vm_op_flags as $name=> $val) $vm_op_decode
gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno, $opcode, $extra_spec=null, &$switch_labels=array())
parse_ext_spec($def, $lineno, $str)
$op2_get_obj_zval_ptr_undef
is_inline_hybrid_handler($name, $hot, $op1, $op2, $extra_spec)
$op1_get_obj_zval_ptr_deref
parse_spec_rules($def, $lineno, $str)
helper_name($name, $spec, $op1, $op2, $extra_spec)
skip_blanks($f, $prolog, $epilog)
gen_vm_opcodes_header(array $opcodes, int $max_opcode, int $max_opcode_len, array $vm_op_flags)
gen_null_label($f, $kind, $prolog)
#define ZEND_VM_EXT_DIM_WRITE
#define ZEND_VM_EXT_CACHE_SLOT
#define ZEND_VM_KIND_GOTO
#define ZEND_VM_OP_CLASS_FETCH
#define ZEND_VM_EXT_TYPE_MASK
#define ZEND_VM_KIND_HYBRID
#define ZEND_VM_OP_TMPVAR
#define ZEND_VM_OP_TMPVARCV
#define ZEND_VM_OP_CONSTRUCTOR
#define ZEND_VM_EXT_JMP_ADDR
#define ZEND_VM_KIND_SWITCH
#define ZEND_VM_EXT_VAR_FETCH
#define ZEND_VM_OP_TRY_CATCH
#define ZEND_VM_EXT_LAST_CATCH
#define ZEND_VM_EXT_ARRAY_INIT
#define ZEND_VM_OP_JMP_ADDR
#define ZEND_VM_OP_CONST_FETCH
#define ZEND_VM_EXT_FETCH_REF
#define ZEND_VM_EXT_ISSET
#define ZEND_VM_OP_CACHE_SLOT
#define ZEND_VM_KIND_CALL