xref: /PHP-8.0/Zend/zend_vm_gen.php (revision 09547c64)
1#!/usr/bin/env php
2<?php
3/*
4   +----------------------------------------------------------------------+
5   | Zend Engine                                                          |
6   +----------------------------------------------------------------------+
7   | Copyright (c) Zend Technologies Ltd. (http://www.zend.com)           |
8   +----------------------------------------------------------------------+
9   | This source file is subject to version 2.00 of the Zend license,     |
10   | that is bundled with this package in the file LICENSE, and is        |
11   | available through the world-wide-web at the following url:           |
12   | http://www.zend.com/license/2_00.txt.                                |
13   | If you did not receive a copy of the Zend license and are unable to  |
14   | obtain it through the world-wide-web, please send a note to          |
15   | license@zend.com so we can mail you a copy immediately.              |
16   +----------------------------------------------------------------------+
17   | Authors: Dmitry Stogov <dmitry@php.net>                              |
18   +----------------------------------------------------------------------+
19*/
20
21const HEADER_TEXT = <<< DATA
22/*
23   +----------------------------------------------------------------------+
24   | Zend Engine                                                          |
25   +----------------------------------------------------------------------+
26   | Copyright (c) Zend Technologies Ltd. (http://www.zend.com)           |
27   +----------------------------------------------------------------------+
28   | This source file is subject to version 2.00 of the Zend license,     |
29   | that is bundled with this package in the file LICENSE, and is        |
30   | available through the world-wide-web at the following url:           |
31   | http://www.zend.com/license/2_00.txt.                                |
32   | If you did not receive a copy of the Zend license and are unable to  |
33   | obtain it through the world-wide-web, please send a note to          |
34   | license@zend.com so we can mail you a copy immediately.              |
35   +----------------------------------------------------------------------+
36   | Authors: Andi Gutmans <andi@php.net>                                 |
37   |          Zeev Suraski <zeev@php.net>                                 |
38   |          Dmitry Stogov <dmitry@php.net>                              |
39   +----------------------------------------------------------------------+
40*/
41
42
43DATA;
44
45/*
46    This script creates zend_vm_execute.h and zend_vm_opcodes.h
47    from existing zend_vm_def.h and zend_vm_execute.skl
48*/
49
50error_reporting(E_ALL);
51
52const ZEND_VM_KIND_CALL   = 1;
53const ZEND_VM_KIND_SWITCH = 2;
54const ZEND_VM_KIND_GOTO   = 3;
55const ZEND_VM_KIND_HYBRID = 4;
56
57$vm_op_flags = array(
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,
66    // unused 0x40
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,
73
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,
86    // unused 0x5000000
87    // unused 0x6000000
88    "ZEND_VM_EXT_TYPE"        => 0x07000000,
89    "ZEND_VM_EXT_EVAL"        => 0x08000000,
90    "ZEND_VM_EXT_TYPE_MASK"   => 0x09000000,
91    // unused 0x0a000000,
92    "ZEND_VM_EXT_SRC"         => 0x0b000000,
93    // unused 0x0c000000,
94    "ZEND_VM_NO_CONST_CONST"  => 0x40000000,
95    "ZEND_VM_COMMUTATIVE"     => 0x80000000,
96);
97
98foreach ($vm_op_flags as $name => $val) {
99    define($name, $val);
100}
101
102$vm_op_decode = array(
103    "ANY"                  => 0,
104    "CONST"                => ZEND_VM_OP_SPEC | ZEND_VM_OP_CONST,
105    "TMP"                  => ZEND_VM_OP_SPEC,
106    "VAR"                  => ZEND_VM_OP_SPEC,
107    "UNUSED"               => ZEND_VM_OP_SPEC,
108    "CV"                   => ZEND_VM_OP_SPEC,
109    "TMPVAR"               => ZEND_VM_OP_SPEC | ZEND_VM_OP_TMPVAR,
110    "TMPVARCV"             => ZEND_VM_OP_SPEC | ZEND_VM_OP_TMPVARCV,
111    "NUM"                  => ZEND_VM_OP_NUM,
112    "JMP_ADDR"             => ZEND_VM_OP_JMP_ADDR,
113    "TRY_CATCH"            => ZEND_VM_OP_TRY_CATCH,
114    "THIS"                 => ZEND_VM_OP_THIS,
115    "NEXT"                 => ZEND_VM_OP_NEXT,
116    "CLASS_FETCH"          => ZEND_VM_OP_CLASS_FETCH,
117    "CONSTRUCTOR"          => ZEND_VM_OP_CONSTRUCTOR,
118    "CONST_FETCH"          => ZEND_VM_OP_CONST_FETCH,
119    "CACHE_SLOT"           => ZEND_VM_OP_CACHE_SLOT,
120);
121
122$vm_ext_decode = array(
123    "NUM"                  => ZEND_VM_EXT_NUM,
124    "LAST_CATCH"           => ZEND_VM_EXT_LAST_CATCH,
125    "JMP_ADDR"             => ZEND_VM_EXT_JMP_ADDR,
126    "OP"                   => ZEND_VM_EXT_OP,
127    "VAR_FETCH"            => ZEND_VM_EXT_VAR_FETCH,
128    "ARRAY_INIT"           => ZEND_VM_EXT_ARRAY_INIT,
129    "TYPE"                 => ZEND_VM_EXT_TYPE,
130    "EVAL"                 => ZEND_VM_EXT_EVAL,
131    "TYPE_MASK"            => ZEND_VM_EXT_TYPE_MASK,
132    "ISSET"                => ZEND_VM_EXT_ISSET,
133    "REF"                  => ZEND_VM_EXT_REF,
134    "FETCH_REF"            => ZEND_VM_EXT_FETCH_REF,
135    "SRC"                  => ZEND_VM_EXT_SRC,
136    "CACHE_SLOT"           => ZEND_VM_EXT_CACHE_SLOT,
137    "DIM_WRITE"            => ZEND_VM_EXT_DIM_WRITE,
138);
139
140$vm_kind_name = array(
141    ZEND_VM_KIND_CALL => "ZEND_VM_KIND_CALL",
142    ZEND_VM_KIND_SWITCH => "ZEND_VM_KIND_SWITCH",
143    ZEND_VM_KIND_GOTO => "ZEND_VM_KIND_GOTO",
144    ZEND_VM_KIND_HYBRID => "ZEND_VM_KIND_HYBRID",
145);
146
147$op_types = array(
148    "ANY",
149    "CONST",
150    "TMP",
151    "VAR",
152    "UNUSED",
153    "CV"
154);
155
156$op_types_ex = array(
157    "ANY",
158    "CONST",
159    "TMPVARCV",
160    "TMPVAR",
161    "TMP",
162    "VAR",
163    "UNUSED",
164    "CV",
165);
166
167$prefix = array(
168    "ANY"      => "",
169    "TMP"      => "_TMP",
170    "VAR"      => "_VAR",
171    "CONST"    => "_CONST",
172    "UNUSED"   => "_UNUSED",
173    "CV"       => "_CV",
174    "TMPVAR"   => "_TMPVAR",
175    "TMPVARCV" => "_TMPVARCV",
176);
177
178$commutative_order = array(
179    "ANY"      => 0,
180    "TMP"      => 1,
181    "VAR"      => 2,
182    "CONST"    => 0,
183    "UNUSED"   => 0,
184    "CV"       => 4,
185    "TMPVAR"   => 2,
186    "TMPVARCV" => 4,
187);
188
189$op1_type = array(
190    "ANY"      => "opline->op1_type",
191    "TMP"      => "IS_TMP_VAR",
192    "VAR"      => "IS_VAR",
193    "CONST"    => "IS_CONST",
194    "UNUSED"   => "IS_UNUSED",
195    "CV"       => "IS_CV",
196    "TMPVAR"   => "(IS_TMP_VAR|IS_VAR)",
197    "TMPVARCV" => "(IS_TMP_VAR|IS_VAR|IS_CV)",
198);
199
200$op2_type = array(
201    "ANY"      => "opline->op2_type",
202    "TMP"      => "IS_TMP_VAR",
203    "VAR"      => "IS_VAR",
204    "CONST"    => "IS_CONST",
205    "UNUSED"   => "IS_UNUSED",
206    "CV"       => "IS_CV",
207    "TMPVAR"   => "(IS_TMP_VAR|IS_VAR)",
208    "TMPVARCV" => "(IS_TMP_VAR|IS_VAR|IS_CV)",
209);
210
211$op1_get_zval_ptr = array(
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)",
216    "UNUSED"   => "NULL",
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)",
219    "TMPVARCV" => "???",
220);
221
222$op2_get_zval_ptr = array(
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)",
227    "UNUSED"   => "NULL",
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)",
230    "TMPVARCV" => "???",
231);
232
233$op1_get_zval_ptr_ptr = array(
234    "ANY"      => "get_zval_ptr_ptr(opline->op1_type, opline->op1, \\1)",
235    "TMP"      => "NULL",
236    "VAR"      => "_get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC)",
237    "CONST"    => "NULL",
238    "UNUSED"   => "NULL",
239    "CV"       => "_get_zval_ptr_cv_\\1(opline->op1.var EXECUTE_DATA_CC)",
240    "TMPVAR"   => "???",
241    "TMPVARCV" => "???",
242);
243
244$op2_get_zval_ptr_ptr = array(
245    "ANY"      => "get_zval_ptr_ptr(opline->op2_type, opline->op2, \\1)",
246    "TMP"      => "NULL",
247    "VAR"      => "_get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC)",
248    "CONST"    => "NULL",
249    "UNUSED"   => "NULL",
250    "CV"       => "_get_zval_ptr_cv_\\1(opline->op2.var EXECUTE_DATA_CC)",
251    "TMPVAR"   => "???",
252    "TMPVARCV" => "???",
253);
254
255$op1_get_zval_ptr_deref = array(
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)",
260    "UNUSED"   => "NULL",
261    "CV"       => "_get_zval_ptr_cv_deref_\\1(opline->op1.var EXECUTE_DATA_CC)",
262    "TMPVAR"   => "???",
263    "TMPVARCV" => "???",
264);
265
266$op2_get_zval_ptr_deref = array(
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)",
271    "UNUSED"   => "NULL",
272    "CV"       => "_get_zval_ptr_cv_deref_\\1(opline->op2.var EXECUTE_DATA_CC)",
273    "TMPVAR"   => "???",
274    "TMPVARCV" => "???",
275);
276
277$op1_get_zval_ptr_undef = array(
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)",
282    "UNUSED"   => "NULL",
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)",
286);
287
288$op2_get_zval_ptr_undef = array(
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)",
293    "UNUSED"   => "NULL",
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)",
297);
298
299$op1_get_zval_ptr_ptr_undef = array(
300    "ANY"      => "get_zval_ptr_ptr_undef(opline->op1_type, opline->op1, \\1)",
301    "TMP"      => "NULL",
302    "VAR"      => "_get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC)",
303    "CONST"    => "NULL",
304    "UNUSED"   => "NULL",
305    "CV"       => "EX_VAR(opline->op1.var)",
306    "TMPVAR"   => "???",
307    "TMPVARCV" => "???",
308);
309
310$op2_get_zval_ptr_ptr_undef = array(
311    "ANY"      => "get_zval_ptr_ptr_undef(opline->op2_type, opline->op2, \\1)",
312    "TMP"      => "NULL",
313    "VAR"      => "_get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC)",
314    "CONST"    => "NULL",
315    "UNUSED"   => "NULL",
316    "CV"       => "EX_VAR(opline->op2.var)",
317    "TMPVAR"   => "???",
318    "TMPVARCV" => "???",
319);
320
321$op1_get_obj_zval_ptr = array(
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)",
329    "TMPVARCV" => "???",
330);
331
332$op2_get_obj_zval_ptr = array(
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)",
340    "TMPVARCV" => "???",
341);
342
343$op1_get_obj_zval_ptr_undef = array(
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)",
352);
353
354$op2_get_obj_zval_ptr_undef = array(
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)",
363);
364
365$op1_get_obj_zval_ptr_deref = array(
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)",
372    "TMPVAR"   => "???",
373    "TMPVARCV" => "???",
374);
375
376$op2_get_obj_zval_ptr_deref = array(
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)",
383    "TMPVAR"   => "???",
384    "TMPVARCV" => "???",
385);
386
387$op1_get_obj_zval_ptr_ptr = array(
388    "ANY"      => "get_obj_zval_ptr_ptr(opline->op1_type, opline->op1, \\1)",
389    "TMP"      => "NULL",
390    "VAR"      => "_get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC)",
391    "CONST"    => "NULL",
392    "UNUSED"   => "&EX(This)",
393    "CV"       => "_get_zval_ptr_cv_\\1(opline->op1.var EXECUTE_DATA_CC)",
394    "TMPVAR"   => "???",
395    "TMPVARCV" => "???",
396);
397
398$op2_get_obj_zval_ptr_ptr = array(
399    "ANY"      => "get_obj_zval_ptr_ptr(opline->op2_type, opline->op2, \\1)",
400    "TMP"      => "NULL",
401    "VAR"      => "_get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC)",
402    "CONST"    => "NULL",
403    "UNUSED"   => "&EX(This)",
404    "CV"       => "_get_zval_ptr_cv_\\1(opline->op2.var EXECUTE_DATA_CC)",
405    "TMPVAR"   => "???",
406    "TMPVARCV" => "???",
407);
408
409$op1_get_obj_zval_ptr_ptr_undef = array(
410    "ANY"      => "get_obj_zval_ptr_ptr(opline->op1_type, opline->op1, \\1)",
411    "TMP"      => "NULL",
412    "VAR"      => "_get_zval_ptr_ptr_var(opline->op1.var EXECUTE_DATA_CC)",
413    "CONST"    => "NULL",
414    "UNUSED"   => "&EX(This)",
415    "CV"       => "EX_VAR(opline->op1.var)",
416    "TMPVAR"   => "???",
417    "TMPVARCV" => "???",
418);
419
420$op2_get_obj_zval_ptr_ptr_undef = array(
421    "ANY"      => "get_obj_zval_ptr_ptr(opline->op2_type, opline->op2, \\1)",
422    "TMP"      => "NULL",
423    "VAR"      => "_get_zval_ptr_ptr_var(opline->op2.var EXECUTE_DATA_CC)",
424    "CONST"    => "NULL",
425    "UNUSED"   => "&EX(This)",
426    "CV"       => "EX_VAR(opline->op2.var)",
427    "TMPVAR"   => "???",
428    "TMPVARCV" => "???",
429);
430
431$op1_free_op = array(
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))",
435    "CONST"    => "",
436    "UNUSED"   => "",
437    "CV"       => "",
438    "TMPVAR"   => "zval_ptr_dtor_nogc(EX_VAR(opline->op1.var))",
439    "TMPVARCV" => "???",
440);
441
442$op2_free_op = array(
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))",
446    "CONST"    => "",
447    "UNUSED"   => "",
448    "CV"       => "",
449    "TMPVAR"   => "zval_ptr_dtor_nogc(EX_VAR(opline->op2.var))",
450    "TMPVARCV" => "???",
451);
452
453$op1_free_op_if_var = array(
454    "ANY"      => "if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));}",
455    "TMP"      => "",
456    "VAR"      => "zval_ptr_dtor_nogc(EX_VAR(opline->op1.var))",
457    "CONST"    => "",
458    "UNUSED"   => "",
459    "CV"       => "",
460    "TMPVAR"   => "???",
461    "TMPVARCV" => "???",
462);
463
464$op2_free_op_if_var = array(
465    "ANY"      => "if (opline->op2_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));}",
466    "TMP"      => "",
467    "VAR"      => "zval_ptr_dtor_nogc(EX_VAR(opline->op2.var))",
468    "CONST"    => "",
469    "UNUSED"   => "",
470    "CV"       => "",
471    "TMPVAR"   => "???",
472    "TMPVARCV" => "???",
473);
474
475$op1_free_op_var_ptr = array(
476    "ANY"      => "if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));}",
477    "TMP"      => "",
478    "VAR"      => "zval_ptr_dtor_nogc(EX_VAR(opline->op1.var))",
479    "CONST"    => "",
480    "UNUSED"   => "",
481    "CV"       => "",
482    "TMPVAR"   => "???",
483    "TMPVARCV" => "???",
484);
485
486$op2_free_op_var_ptr = array(
487    "ANY"      => "if (opline->op2_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));}",
488    "TMP"      => "",
489    "VAR"      => "zval_ptr_dtor_nogc(EX_VAR(opline->op2.var))",
490    "CONST"    => "",
491    "UNUSED"   => "",
492    "CV"       => "",
493    "TMPVAR"   => "???",
494    "TMPVARCV" => "???",
495);
496
497$op_data_type = array(
498    "ANY"      => "(opline+1)->op1_type",
499    "TMP"      => "IS_TMP_VAR",
500    "VAR"      => "IS_VAR",
501    "CONST"    => "IS_CONST",
502    "UNUSED"   => "IS_UNUSED",
503    "CV"       => "IS_CV",
504    "TMPVAR"   => "(IS_TMP_VAR|IS_VAR)",
505    "TMPVARCV" => "(IS_TMP_VAR|IS_VAR|IS_CV)",
506);
507
508$op_data_get_zval_ptr = array(
509    "ANY"      => "get_op_data_zval_ptr_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((opline+1)->op1.var EXECUTE_DATA_CC)",
512    "CONST"    => "RT_CONSTANT((opline+1), (opline+1)->op1)",
513    "UNUSED"   => "NULL",
514    "CV"       => "_get_zval_ptr_cv_\\1((opline+1)->op1.var EXECUTE_DATA_CC)",
515    "TMPVAR"   => "_get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC)",
516    "TMPVARCV" => "???",
517);
518
519$op_data_get_zval_ptr_undef = array(
520    "ANY"      => "get_op_data_zval_ptr_undef((opline+1)->op1_type, (opline+1)->op1)",
521    "TMP"      => "_get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC)",
522    "VAR"      => "_get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC)",
523    "CONST"    => "RT_CONSTANT((opline+1), (opline+1)->op1)",
524    "UNUSED"   => "NULL",
525    "CV"       => "EX_VAR((opline+1)->op1.var)",
526    "TMPVAR"   => "_get_zval_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC)",
527    "TMPVARCV" => "EX_VAR((opline+1)->op1.var)",
528);
529
530$op_data_get_zval_ptr_deref = array(
531    "ANY"      => "get_op_data_zval_ptr_deref_r((opline+1)->op1_type, (opline+1)->op1)",
532    "TMP"      => "_get_zval_ptr_tmp((opline+1)->op1.var EXECUTE_DATA_CC)",
533    "VAR"      => "_get_zval_ptr_var_deref((opline+1)->op1.var EXECUTE_DATA_CC)",
534    "CONST"    => "RT_CONSTANT((opline+1), (opline+1)->op1)",
535    "UNUSED"   => "NULL",
536    "CV"       => "_get_zval_ptr_cv_deref_\\1((opline+1)->op1.var EXECUTE_DATA_CC)",
537    "TMPVAR"   => "???",
538    "TMPVARCV" => "???",
539);
540
541$op_data_get_zval_ptr_ptr = array(
542    "ANY"      => "get_zval_ptr_ptr((opline+1)->op1_type, (opline+1)->op1, \\1)",
543    "TMP"      => "NULL",
544    "VAR"      => "_get_zval_ptr_ptr_var((opline+1)->op1.var EXECUTE_DATA_CC)",
545    "CONST"    => "NULL",
546    "UNUSED"   => "NULL",
547    "CV"       => "_get_zval_ptr_cv_\\1((opline+1)->op1.var EXECUTE_DATA_CC)",
548    "TMPVAR"   => "???",
549    "TMPVARCV" => "???",
550);
551
552$op_data_free_op = array(
553    "ANY"      => "FREE_OP((opline+1)->op1_type, (opline+1)->op1.var)",
554    "TMP"      => "zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var))",
555    "VAR"      => "zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var))",
556    "CONST"    => "",
557    "UNUSED"   => "",
558    "CV"       => "",
559    "TMPVAR"   => "zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var))",
560    "TMPVARCV" => "???",
561);
562
563$op_data_free_op_var_ptr = array(
564    "ANY"      => "if ((opline+1)->op1_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));}",
565    "TMP"      => "",
566    "VAR"      => "zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));",
567    "CONST"    => "",
568    "UNUSED"   => "",
569    "CV"       => "",
570    "TMPVAR"   => "???",
571    "TMPVARCV" => "???",
572);
573
574$list    = array(); // list of opcode handlers and helpers in original order
575$opcodes = array(); // opcode handlers by code
576$helpers = array(); // opcode helpers by name
577$params  = array(); // parameters of helpers
578$opnames = array(); // opcode name to code mapping
579$line_no = 1;
580
581$used_extra_spec = array();
582
583// Writes $s into resulting executor
584function out($f, $s) {
585    global $line_no;
586
587    fputs($f,$s);
588    $line_no += substr_count($s, "\n");
589}
590
591// Resets #line directives in resulting executor
592function out_line($f) {
593    global $line_no, $executor_file;
594
595    fputs($f,"#line ".($line_no+1)." \"".$executor_file."\"\n");
596    ++$line_no;
597}
598
599function is_hot_helper($name) {
600    global $helpers;
601
602    if (isset($helpers[$name]["hot"])) {
603        return $helpers[$name]["hot"];
604    } else {
605        return false;
606    }
607}
608
609// Returns name of specialized helper
610function helper_name($name, $spec, $op1, $op2, $extra_spec) {
611    global $prefix, $helpers;
612
613    $extra = "";
614
615    if (isset($helpers[$name])) {
616        // If we have no helper with specified specialized operands then
617        // using unspecialized helper
618        if (!isset($helpers[$name]["op1"][$op1])) {
619            if (($op1 == 'TMP' || $op1 == 'VAR') &&
620                isset($helpers[$name]["op1"]["TMPVAR"])) {
621                $op1 = "TMPVAR";
622            } else if (($op1 == 'TMP' || $op1 == 'VAR') &&
623                isset($helpers[$name]["op1"]["TMPVARCV"])) {
624                $op1 = "TMPVARCV";
625            } else if ($op1 == 'CV' &&
626                isset($helpers[$name]["op1"]["TMPVARCV"])) {
627                $op1 = "TMPVARCV";
628            } else if (isset($helpers[$name]["op1"]["ANY"])) {
629                $op1 = "ANY";
630            }
631        }
632        if (!isset($helpers[$name]["op2"][$op2])) {
633            if (($op2 == 'TMP' || $op2 == 'VAR') &&
634                isset($helpers[$name]["op2"]["TMPVAR"])) {
635                $op2 = "TMPVAR";
636            } else if (($op2 == 'TMP' || $op2 == 'VAR') &&
637                isset($helpers[$name]["op2"]["TMPVARCV"])) {
638                $op2 = "TMPVARCV";
639            } else if ($op2 == 'CV' &&
640                isset($helpers[$name]["op2"]["TMPVARCV"])) {
641                $op2 = "TMPVARCV";
642            } else if (isset($helpers[$name]["op2"]["ANY"])) {
643                $op2 = "ANY";
644            }
645        }
646        /* forward common specs (e.g. in ZEND_VM_DISPATCH_TO_HELPER) */
647        if (isset($extra_spec, $helpers[$name]["spec"])) {
648            $extra = extra_spec_name(array_intersect_key($extra_spec, $helpers[$name]["spec"]));
649        }
650    }
651    return $name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2].$extra;
652}
653
654function opcode_name($name, $spec, $op1, $op2, $extra_spec) {
655    global $prefix, $opnames, $opcodes;
656
657    $extra = "";
658
659    if (isset($opnames[$name])) {
660        $opcode = $opcodes[$opnames[$name]];
661        // If we have no helper with specified specialized operands then
662        // using unspecialized helper
663        if (!isset($opcode["op1"][$op1])) {
664            if (($op1 == 'TMP' || $op1 == 'VAR') &&
665                isset($opcode["op1"]["TMPVAR"])) {
666                $op1 = "TMPVAR";
667            } else if (($op1 == 'TMP' || $op1 == 'VAR') &&
668                isset($opcode["op1"]["TMPVARCV"])) {
669                $op1 = "TMPVARCV";
670            } else if ($op1 == 'CV' &&
671                isset($opcode["op1"]["TMPVARCV"])) {
672                $op1 = "TMPVARCV";
673            } else if (isset($opcode["op1"]["ANY"])) {
674                $op1 = "ANY";
675            } else if ($spec) {
676                /* dispatch to invalid handler from unreachable code */
677                return "ZEND_NULL";
678            }
679        }
680        if (!isset($opcode["op2"][$op2])) {
681            if (($op2 == 'TMP' || $op2 == 'VAR') &&
682                isset($opcode["op2"]["TMPVAR"])) {
683                $op2 = "TMPVAR";
684            } else if (($op2 == 'TMP' || $op2 == 'VAR') &&
685                isset($opcode["op2"]["TMPVARCV"])) {
686                $op2 = "TMPVARCV";
687            } else if ($op2 == 'CV' &&
688                isset($opcode["op2"]["TMPVARCV"])) {
689                $op2 = "TMPVARCV";
690            } else if (isset($opcode["op2"]["ANY"])) {
691                $op2 = "ANY";
692            } else if ($spec) {
693                /* dispatch to unknown handler in unreachable code */
694                return "ZEND_NULL";
695            }
696        }
697        /* forward common specs (e.g. in ZEND_VM_DISPATCH_TO_HANDLER) */
698        if (isset($extra_spec, $opcode["spec"])) {
699            $extra = extra_spec_name(array_intersect_key($extra_spec, $opcode["spec"]));
700        }
701    }
702    return $name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2].$extra;
703}
704
705// Formats condition, protecting it by parentheses when needed.
706function format_condition($condition) {
707    if ($condition === "") {
708        throw new InvalidArgumentException("A non empty string condition was expected.");
709    }
710
711    if ($condition[0] === "(" && substr($condition, -1) === ")") {
712        return $condition;
713    }
714
715    return "(".$condition.")";
716}
717
718// Generates code for opcode handler or helper
719function gen_code($f, $spec, $kind, $code, $op1, $op2, $name, $extra_spec=null) {
720    global $op1_type, $op2_type, $op1_get_zval_ptr, $op2_get_zval_ptr,
721        $op1_get_zval_ptr_deref, $op2_get_zval_ptr_deref,
722        $op1_get_zval_ptr_undef, $op2_get_zval_ptr_undef,
723        $op1_get_zval_ptr_ptr, $op2_get_zval_ptr_ptr,
724        $op1_get_zval_ptr_ptr_undef, $op2_get_zval_ptr_ptr_undef,
725        $op1_get_obj_zval_ptr, $op2_get_obj_zval_ptr,
726        $op1_get_obj_zval_ptr_undef, $op2_get_obj_zval_ptr_undef,
727        $op1_get_obj_zval_ptr_deref, $op2_get_obj_zval_ptr_deref,
728        $op1_get_obj_zval_ptr_ptr, $op2_get_obj_zval_ptr_ptr,
729        $op1_get_obj_zval_ptr_ptr_undef, $op2_get_obj_zval_ptr_ptr_undef,
730        $op1_free_unfetched, $op2_free_unfetched,
731        $op1_free_op, $op2_free_op, $op1_free_op_if_var, $op2_free_op_if_var,
732        $op1_free_op_var_ptr, $op2_free_op_var_ptr, $prefix,
733        $op_data_type, $op_data_get_zval_ptr, $op_data_get_zval_ptr_undef,
734        $op_data_get_zval_ptr_deref, $op_data_get_zval_ptr_ptr,
735        $op_data_free_op, $op_data_free_op_var_ptr, $op_data_free_unfetched;
736
737    // Specializing
738    $specialized_replacements = array(
739        "/OP1_TYPE/" => $op1_type[$op1],
740        "/OP2_TYPE/" => $op2_type[$op2],
741        "/GET_OP1_ZVAL_PTR\(([^)]*)\)/" => $op1_get_zval_ptr[$op1],
742        "/GET_OP2_ZVAL_PTR\(([^)]*)\)/" => $op2_get_zval_ptr[$op2],
743        "/GET_OP1_ZVAL_PTR_DEREF\(([^)]*)\)/" => $op1_get_zval_ptr_deref[$op1],
744        "/GET_OP2_ZVAL_PTR_DEREF\(([^)]*)\)/" => $op2_get_zval_ptr_deref[$op2],
745        "/GET_OP1_ZVAL_PTR_UNDEF\(([^)]*)\)/" => $op1_get_zval_ptr_undef[$op1],
746        "/GET_OP2_ZVAL_PTR_UNDEF\(([^)]*)\)/" => $op2_get_zval_ptr_undef[$op2],
747        "/GET_OP1_ZVAL_PTR_PTR\(([^)]*)\)/" => $op1_get_zval_ptr_ptr[$op1],
748        "/GET_OP2_ZVAL_PTR_PTR\(([^)]*)\)/" => $op2_get_zval_ptr_ptr[$op2],
749        "/GET_OP1_ZVAL_PTR_PTR_UNDEF\(([^)]*)\)/" => $op1_get_zval_ptr_ptr_undef[$op1],
750        "/GET_OP2_ZVAL_PTR_PTR_UNDEF\(([^)]*)\)/" => $op2_get_zval_ptr_ptr_undef[$op2],
751        "/GET_OP1_OBJ_ZVAL_PTR\(([^)]*)\)/" => $op1_get_obj_zval_ptr[$op1],
752        "/GET_OP2_OBJ_ZVAL_PTR\(([^)]*)\)/" => $op2_get_obj_zval_ptr[$op2],
753        "/GET_OP1_OBJ_ZVAL_PTR_UNDEF\(([^)]*)\)/" => $op1_get_obj_zval_ptr_undef[$op1],
754        "/GET_OP2_OBJ_ZVAL_PTR_UNDEF\(([^)]*)\)/" => $op2_get_obj_zval_ptr_undef[$op2],
755        "/GET_OP1_OBJ_ZVAL_PTR_DEREF\(([^)]*)\)/" => $op1_get_obj_zval_ptr_deref[$op1],
756        "/GET_OP2_OBJ_ZVAL_PTR_DEREF\(([^)]*)\)/" => $op2_get_obj_zval_ptr_deref[$op2],
757        "/GET_OP1_OBJ_ZVAL_PTR_PTR\(([^)]*)\)/" => $op1_get_obj_zval_ptr_ptr[$op1],
758        "/GET_OP2_OBJ_ZVAL_PTR_PTR\(([^)]*)\)/" => $op2_get_obj_zval_ptr_ptr[$op2],
759        "/GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF\(([^)]*)\)/" => $op1_get_obj_zval_ptr_ptr_undef[$op1],
760        "/GET_OP2_OBJ_ZVAL_PTR_PTR_UNDEF\(([^)]*)\)/" => $op2_get_obj_zval_ptr_ptr_undef[$op2],
761        "/FREE_OP1\(\)/" => $op1_free_op[$op1],
762        "/FREE_OP2\(\)/" => $op2_free_op[$op2],
763        "/FREE_OP1_IF_VAR\(\)/" => $op1_free_op_if_var[$op1],
764        "/FREE_OP2_IF_VAR\(\)/" => $op2_free_op_if_var[$op2],
765        "/FREE_OP1_VAR_PTR\(\)/" => $op1_free_op_var_ptr[$op1],
766        "/FREE_OP2_VAR_PTR\(\)/" => $op2_free_op_var_ptr[$op2],
767        "/\!ZEND_VM_SPEC/m" => ($op1!="ANY"||$op2!="ANY")?"0":"1",
768        "/ZEND_VM_SPEC/m" => ($op1!="ANY"||$op2!="ANY")?"1":"0",
769        "/ZEND_VM_C_LABEL\(\s*([A-Za-z_]*)\s*\)/m" => "\\1".(($spec && $kind != ZEND_VM_KIND_CALL)?("_SPEC".$prefix[$op1].$prefix[$op2].extra_spec_name($extra_spec)):""),
770        "/ZEND_VM_C_GOTO\(\s*([A-Za-z_]*)\s*\)/m" => "goto \\1".(($spec && $kind != ZEND_VM_KIND_CALL)?("_SPEC".$prefix[$op1].$prefix[$op2].extra_spec_name($extra_spec)):""),
771        "/^#(\s*)if\s+1\s*\\|\\|.*[^\\\\]$/m" => "#\\1if 1",
772        "/^#(\s*)if\s+0\s*&&.*[^\\\\]$/m" => "#\\1if 0",
773        "/^#(\s*)elif\s+1\s*\\|\\|.*[^\\\\]$/m" => "#\\1elif 1",
774        "/^#(\s*)elif\s+0\s*&&.*[^\\\\]$/m" => "#\\1elif 0",
775        "/OP_DATA_TYPE/" => $op_data_type[isset($extra_spec['OP_DATA']) ? $extra_spec['OP_DATA'] : "ANY"],
776        "/GET_OP_DATA_ZVAL_PTR\(([^)]*)\)/" => $op_data_get_zval_ptr[isset($extra_spec['OP_DATA']) ? $extra_spec['OP_DATA'] : "ANY"],
777        "/GET_OP_DATA_ZVAL_PTR_UNDEF\(([^)]*)\)/" => $op_data_get_zval_ptr_undef[isset($extra_spec['OP_DATA']) ? $extra_spec['OP_DATA'] : "ANY"],
778        "/GET_OP_DATA_ZVAL_PTR_DEREF\(([^)]*)\)/" => $op_data_get_zval_ptr_deref[isset($extra_spec['OP_DATA']) ? $extra_spec['OP_DATA'] : "ANY"],
779        "/GET_OP_DATA_ZVAL_PTR_PTR\(([^)]*)\)/" => $op_data_get_zval_ptr_ptr[isset($extra_spec['OP_DATA']) ? $extra_spec['OP_DATA'] : "ANY"],
780        "/FREE_OP_DATA\(\)/" => $op_data_free_op[isset($extra_spec['OP_DATA']) ? $extra_spec['OP_DATA'] : "ANY"],
781        "/FREE_OP_DATA_VAR_PTR\(\)/" => $op_data_free_op_var_ptr[isset($extra_spec['OP_DATA']) ? $extra_spec['OP_DATA'] : "ANY"],
782        "/RETURN_VALUE_USED\(opline\)/" => isset($extra_spec['RETVAL']) ? $extra_spec['RETVAL'] : "RETURN_VALUE_USED(opline)",
783        "/arg_num <= MAX_ARG_FLAG_NUM/" => isset($extra_spec['QUICK_ARG']) ? $extra_spec['QUICK_ARG'] : "arg_num <= MAX_ARG_FLAG_NUM",
784        "/ZEND_VM_SMART_BRANCH\(\s*([^,)]*)\s*,\s*([^)]*)\s*\)/" => isset($extra_spec['SMART_BRANCH']) ?
785            ($extra_spec['SMART_BRANCH'] == 1 ?
786                    "ZEND_VM_SMART_BRANCH_JMPZ(\\1, \\2)"
787                :	($extra_spec['SMART_BRANCH'] == 2 ?
788                        "ZEND_VM_SMART_BRANCH_JMPNZ(\\1, \\2)" : "ZEND_VM_SMART_BRANCH_NONE(\\1, \\2)"))
789            :	"ZEND_VM_SMART_BRANCH(\\1, \\2)",
790        "/ZEND_VM_SMART_BRANCH_TRUE\(\s*\)/" => isset($extra_spec['SMART_BRANCH']) ?
791            ($extra_spec['SMART_BRANCH'] == 1 ?
792                    "ZEND_VM_SMART_BRANCH_TRUE_JMPZ()"
793                :	($extra_spec['SMART_BRANCH'] == 2 ?
794                        "ZEND_VM_SMART_BRANCH_TRUE_JMPNZ()" : "ZEND_VM_SMART_BRANCH_TRUE_NONE()"))
795            :	"ZEND_VM_SMART_BRANCH_TRUE()",
796        "/ZEND_VM_SMART_BRANCH_FALSE\(\s*\)/" => isset($extra_spec['SMART_BRANCH']) ?
797            ($extra_spec['SMART_BRANCH'] == 1 ?
798                    "ZEND_VM_SMART_BRANCH_FALSE_JMPZ()"
799                :	($extra_spec['SMART_BRANCH'] == 2 ?
800                        "ZEND_VM_SMART_BRANCH_FALSE_JMPNZ()" : "ZEND_VM_SMART_BRANCH_FALSE_NONE()"))
801            :	"ZEND_VM_SMART_BRANCH_FALSE()",
802        "/opline->extended_value\s*&\s*ZEND_ISEMPTY/" => isset($extra_spec['ISSET']) ?
803            ($extra_spec['ISSET'] == 0 ? "0" : "1")
804            : "\\0",
805        "/opline->extended_value\s*&\s*~\s*ZEND_ISEMPTY/" => isset($extra_spec['ISSET']) ?
806            ($extra_spec['ISSET'] == 0 ? "\\0" : "opline->extended_value")
807            : "\\0",
808        "/ZEND_OBSERVER_ENABLED/" => isset($extra_spec['OBSERVER']) && $extra_spec['OBSERVER'] == 1 ? "1" : "0",
809        "/ZEND_OBSERVER_USE_RETVAL/" => isset($extra_spec['OBSERVER']) && $extra_spec['OBSERVER'] == 1 ? "zval observer_retval" : "",
810        "/ZEND_OBSERVER_SET_RETVAL\(\)/" => isset($extra_spec['OBSERVER']) && $extra_spec['OBSERVER'] == 1 ? "if (!return_value) { return_value = &observer_retval; }" : "",
811        "/ZEND_OBSERVER_FREE_RETVAL\(\)/" => isset($extra_spec['OBSERVER']) && $extra_spec['OBSERVER'] == 1 ? "if (return_value == &observer_retval) { zval_ptr_dtor_nogc(&observer_retval); }" : "",
812        "/ZEND_OBSERVER_SAVE_OPLINE\(\)/" => isset($extra_spec['OBSERVER']) && $extra_spec['OBSERVER'] == 1 ? "SAVE_OPLINE()" : "",
813        "/ZEND_OBSERVER_FCALL_BEGIN\(\s*(.*)\s*\)/" => isset($extra_spec['OBSERVER']) ?
814            ($extra_spec['OBSERVER'] == 0 ? "" : "zend_observer_fcall_begin(\\1)")
815            : "",
816        "/ZEND_OBSERVER_FCALL_END\(\s*([^,]*)\s*,\s*(.*)\s*\)/" => isset($extra_spec['OBSERVER']) ?
817            ($extra_spec['OBSERVER'] == 0 ? "" : "zend_observer_fcall_end(\\1, \\2)")
818            : "",
819    );
820    $code = preg_replace(array_keys($specialized_replacements), array_values($specialized_replacements), $code);
821
822    if (0 && strpos($code, '{') === 0) {
823        $code = "{\n\tfprintf(stderr, \"$name\\n\");\n" . substr($code, 1);
824    }
825    // Updating code according to selected threading model
826    switch($kind) {
827        case ZEND_VM_KIND_HYBRID:
828            $code = preg_replace_callback(
829                array(
830                    "/EXECUTE_DATA(?=[^_])/m",
831                    "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m",
832                    "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*(,[^)]*)?\)/m",
833                ),
834                function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec) {
835                    if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) {
836                        return "execute_data";
837                    } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) {
838                        global $opcodes, $opnames;
839
840                        $name = $matches[1];
841                        $opcode = $opcodes[$opnames[$name]];
842                        return "goto " . opcode_name($name, $spec, $op1, $op2, $extra_spec) . "_LABEL";
843                    } else {
844                        // ZEND_VM_DISPATCH_TO_HELPER
845                        if (is_hot_helper($matches[1])) {
846                            if (isset($matches[2])) {
847                                // extra args
848                                $args = preg_replace("/,\s*([A-Za-z0-9_]*)\s*,\s*([^,)\s]*)\s*/", "$1 = $2; ", $matches[2]);
849                                return $args . "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "_LABEL";
850                            }
851                            return "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "_LABEL";
852                        }
853                        if (isset($matches[2])) {
854                            // extra args
855                            $args = substr(preg_replace("/,\s*[A-Za-z0-9_]*\s*,\s*([^,)\s]*)\s*/", ", $1", $matches[2]), 2);
856                            return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(" . $args. " ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC))";
857                        }
858                        return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))";
859                    }
860                },
861                $code);
862            break;
863        case ZEND_VM_KIND_CALL:
864            $code = preg_replace_callback(
865                array(
866                    "/EXECUTE_DATA(?=[^_])/m",
867                    "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m",
868                    "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*(,[^)]*)?\)/m",
869                ),
870                function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec, $name) {
871                    if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) {
872                        return "execute_data";
873                    } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) {
874                        global $opcodes, $opnames;
875
876                        $handler = $matches[1];
877                        $opcode = $opcodes[$opnames[$handler]];
878                        $inline =
879                            ZEND_VM_KIND == ZEND_VM_KIND_HYBRID &&
880                            isset($opcode["use"]) &&
881                            is_hot_handler($opcode["hot"], $op1, $op2, $extra_spec) &&
882                            is_hot_handler($opcodes[$opnames[$name]]["hot"], $op1, $op2, $extra_spec) ?
883                            "_INLINE" : "";
884                        return "ZEND_VM_TAIL_CALL(" . opcode_name($handler, $spec, $op1, $op2, $extra_spec) . $inline . "_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))";
885                    } else {
886                        // ZEND_VM_DISPATCH_TO_HELPER
887                        if (isset($matches[2])) {
888                            // extra args
889                            $args = substr(preg_replace("/,\s*[A-Za-z0-9_]*\s*,\s*([^,)\s]*)\s*/", ", $1", $matches[2]), 2);
890                            return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(" . $args. " ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC))";
891                        }
892                        return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))";
893                    }
894                },
895                $code);
896            break;
897        case ZEND_VM_KIND_SWITCH:
898            $code = preg_replace_callback(
899                array(
900                    "/EXECUTE_DATA(?=[^_])/m",
901                    "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m",
902                    "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*(,[^)]*)?\)/m",
903                ),
904                function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec) {
905                    if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) {
906                        return "execute_data";
907                    } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) {
908                        return "goto " . opcode_name($matches[1], $spec, $op1, $op2, $extra_spec) . "_LABEL";
909                    } else {
910                        // ZEND_VM_DISPATCH_TO_HELPER
911                        if (isset($matches[2])) {
912                            // extra args
913                            $args = preg_replace("/,\s*([A-Za-z0-9_]*)\s*,\s*([^,)\s]*)\s*/", "$1 = $2; ", $matches[2]);
914                            return $args .  "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec);
915                        }
916                        return "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec);
917                    }
918                },
919                    $code);
920            break;
921        case ZEND_VM_KIND_GOTO:
922            $code = preg_replace_callback(
923                array(
924                    "/EXECUTE_DATA(?=[^_])/m",
925                    "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m",
926                    "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*(,[^)]*)?\)/m",
927                ),
928                function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec) {
929                    if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) {
930                        return "execute_data";
931                    } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) {
932                        return "goto " . opcode_name($matches[1], $spec, $op1, $op2, $extra_spec) . "_LABEL";
933                    } else {
934                        // ZEND_VM_DISPATCH_TO_HELPER
935                        if (isset($matches[2])) {
936                            // extra args
937                            $args = preg_replace("/,\s*([A-Za-z0-9_]*)\s*,\s*([^,)\s]*)\s*/", "$1 = $2; ", $matches[2]);
938                            return $args .  "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec);
939                        }
940                        return "goto " . helper_name($matches[1], $spec, $op1, $op2, $extra_spec);
941                    }
942                },
943                    $code);
944            break;
945    }
946
947    /* Remove unnecessary ';' */
948    $code = preg_replace('/^\s*;\s*$/m', '', $code);
949
950    /* Remove WS */
951    $code = preg_replace('/[ \t]+\n/m', "\n", $code);
952
953    out($f, $code);
954}
955
956function skip_extra_spec_function($op1, $op2, $extra_spec) {
957    global $commutative_order;
958
959    if (isset($extra_spec["NO_CONST_CONST"]) &&
960        $op1 == "CONST" && $op2 == "CONST") {
961        // Skip useless constant handlers
962        return true;
963    }
964
965    if (isset($extra_spec["COMMUTATIVE"]) &&
966        $commutative_order[$op1] < $commutative_order[$op2]) {
967        // Skip duplicate commutative handlers
968        return true;
969    }
970
971    return false;
972}
973
974function is_hot_handler($hot, $op1, $op2, $extra_spec) {
975    if (isset($extra_spec["SMART_BRANCH"]) && $extra_spec["SMART_BRANCH"] == 0) {
976        return false;
977    }
978    if (isset($extra_spec["OBSERVER"]) && $extra_spec["OBSERVER"] == 1) {
979        return false;
980    }
981    if ($hot === 'HOT_' || $hot === 'INLINE_') {
982        return true;
983    } else if ($hot === 'HOT_NOCONST_') {
984        return ($op1 !== 'CONST');
985    } else if ($hot === 'HOT_NOCONSTCONST_') {
986        return (($op1 !== 'CONST') || ($op2 !== 'CONST')) ;
987    } else if ($hot === 'HOT_OBJ_') {
988        return (($op1 === 'UNUSED') || ($op1 === 'CV')) && ($op2 === 'CONST');
989    } else if ($hot === 'HOT_SEND_') {
990        return !empty($extra_spec["QUICK_ARG"]);
991    } else {
992        return false;
993    }
994}
995
996function is_cold_handler($hot, $op1, $op2, $extra_spec) {
997    if ($hot === 'COLD_') {
998        return true;
999    } else if (isset($extra_spec["OBSERVER"]) && $extra_spec["OBSERVER"] == 1) {
1000        return true;
1001    } else if ($hot === 'COLD_CONST_') {
1002        return ($op1 === 'CONST');
1003    } else if ($hot === 'COLD_CONSTCONST_') {
1004        return ($op1 === 'CONST' && $op2 === 'CONST');
1005    } else if ($hot === 'HOT_OBJ_') {
1006        return ($op1 === 'CONST');
1007    } else if ($hot === 'HOT_NOCONST_') {
1008        return ($op1 === 'CONST');
1009    } else if ($hot === 'HOT_NOCONSTCONST_') {
1010        return ($op1 === 'CONST' && $op2 === 'CONST');
1011    } else {
1012        return false;
1013    }
1014}
1015
1016function is_inline_hybrid_handler($name, $hot, $op1, $op2, $extra_spec) {
1017    return ($hot === 'INLINE_');
1018}
1019
1020// Generates opcode handler
1021function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno, $opcode, $extra_spec = null, &$switch_labels = array()) {
1022    global $definition_file, $prefix, $opnames, $gen_order;
1023
1024    static $used_observer_handlers = array();
1025
1026    if (isset($opcode['alias']) && ($spec || $kind != ZEND_VM_KIND_SWITCH)) {
1027        return;
1028    }
1029
1030    if ($spec && skip_extra_spec_function($op1, $op2, $extra_spec)) {
1031        return;
1032    }
1033
1034    /* Skip SMART_BRANCH specialization for "cold" CONST_CONST instructions */
1035    if (isset($extra_spec["SMART_BRANCH"])) {
1036        if ($opcode["hot"] === 'HOT_NOCONSTCONST_'
1037         || $opcode["hot"] === 'COLD_CONSTCONST_') {
1038            if (($op1 === 'CONST') && ($op2 === 'CONST')) {
1039                if ($extra_spec["SMART_BRANCH"] == 0) {
1040                    unset($extra_spec["SMART_BRANCH"]);
1041                } else {
1042                    return;
1043                }
1044            }
1045        }
1046    }
1047
1048    /* Skip QUICK_ARG specialization for named parameters */
1049    if (isset($extra_spec["QUICK_ARG"])) {
1050        if ($op2 === "CONST") {
1051            if ($extra_spec["QUICK_ARG"] == 0) {
1052                unset($extra_spec["QUICK_ARG"]);
1053            } else {
1054                return;
1055            }
1056        }
1057    }
1058
1059    /* Skip all specialization for OBSERVER handlers */
1060    if (isset($extra_spec["OBSERVER"]) && $extra_spec["OBSERVER"] == 1) {
1061        if (isset($extra_spec["RETVAL"])) {
1062            if ($extra_spec["RETVAL"] == 0) {
1063                unset($extra_spec["RETVAL"]);
1064            } else {
1065                return;
1066            }
1067        }
1068        if ($op1 != "ANY" || $op2 != "ANY") {
1069            if (!isset($used_observer_handlers[$kind][$opcode["op"]])) {
1070                $used_observer_handlers[$kind][$opcode["op"]] = true;
1071                $op1 = "ANY";
1072                $op2 = "ANY";
1073            } else {
1074                return;
1075            }
1076        }
1077    }
1078
1079    if (ZEND_VM_LINES) {
1080        out($f, "#line $lineno \"$definition_file\"\n");
1081    }
1082
1083    // Generate opcode handler's entry point according to selected threading model
1084    $additional_func = false;
1085    $spec_name = $name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2].($spec?extra_spec_name($extra_spec):"");
1086    switch($kind) {
1087        case ZEND_VM_KIND_HYBRID:
1088            if (is_inline_hybrid_handler($name, $opcode["hot"], $op1, $op2, $extra_spec)) {
1089                $out = fopen('php://memory', 'w+');
1090                gen_code($out, $spec, $kind, $code, $op1, $op2, $name, $extra_spec);
1091                rewind($out);
1092                $code =
1093                      "\t\t\tHYBRID_CASE({$spec_name}):\n"
1094                    . "\t\t\t\tVM_TRACE($spec_name)\n"
1095                    . stream_get_contents($out);
1096                fclose($out);
1097            } else {
1098                $inline =
1099                    isset($opcode["use"]) &&
1100                    is_hot_handler($opcode["hot"], $op1, $op2, $extra_spec) ?
1101                    "_INLINE" : "";
1102                $code =
1103                      "\t\t\tHYBRID_CASE({$spec_name}):\n"
1104                    . "\t\t\t\tVM_TRACE($spec_name)\n"
1105                    . "\t\t\t\t{$spec_name}{$inline}_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n"
1106                    . "\t\t\t\tHYBRID_BREAK();\n";
1107            }
1108            if (is_array($gen_order)) {
1109                $gen_order[$spec_name] = $code;
1110            } else {
1111                out($f, $code);
1112            }
1113            return;
1114        case ZEND_VM_KIND_CALL:
1115            if ($opcode["hot"] && ZEND_VM_KIND == ZEND_VM_KIND_HYBRID && is_hot_handler($opcode["hot"], $op1, $op2, $extra_spec)) {
1116                if (isset($opcode["use"])) {
1117                    out($f,"static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
1118                    $additional_func = true;
1119                } else {
1120                    out($f,"static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
1121                }
1122            } else if ($opcode["hot"] && is_cold_handler($opcode["hot"], $op1, $op2, $extra_spec)) {
1123                out($f,"static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
1124            } else {
1125                out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
1126            }
1127            break;
1128        case ZEND_VM_KIND_SWITCH:
1129            if ($spec) {
1130                $cur = $switch_labels ? end($switch_labels) + 1 : 0;
1131                out($f,"case $cur: /* $spec_name */");
1132                $switch_labels[$spec_name] = $cur;
1133            } else {
1134                out($f,"case ".$name.":");
1135            }
1136            if ($use) {
1137                // This handler is used by other handlers. We will add label to call it.
1138                out($f," {$spec_name}_LABEL: ZEND_ATTRIBUTE_UNUSED_LABEL\n");
1139            } else {
1140                out($f,"\n");
1141            }
1142            break;
1143        case ZEND_VM_KIND_GOTO:
1144            out($f,"{$spec_name}_LABEL: ZEND_VM_GUARD($spec_name);\n");
1145            break;
1146    }
1147
1148    // Generate opcode handler's code
1149    gen_code($f, $spec, $kind, $code, $op1, $op2, $name, $extra_spec);
1150
1151    if ($additional_func) {
1152        out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
1153        out($f,"{\n");
1154        out($f,"\tZEND_VM_TAIL_CALL({$spec_name}_INLINE_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n");
1155        out($f,"}\n");
1156        out($f,"\n");
1157    }
1158}
1159
1160// Generates helper
1161function gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno, $inline, $cold = false, $hot = false, $extra_spec = null) {
1162    global $definition_file, $prefix;
1163
1164    if ($kind == ZEND_VM_KIND_HYBRID && !$hot) {
1165        return;
1166    }
1167
1168    if ($spec && skip_extra_spec_function($op1, $op2, $extra_spec)) {
1169        return;
1170    }
1171
1172    if (ZEND_VM_LINES) {
1173        out($f, "#line $lineno \"$definition_file\"\n");
1174    }
1175
1176    $spec_name = $name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2].($spec?extra_spec_name($extra_spec):"");
1177
1178    // Generate helper's entry point according to selected threading model
1179    switch($kind) {
1180        case ZEND_VM_KIND_HYBRID:
1181            out($f, $spec_name . "_LABEL:\n");
1182            break;
1183        case ZEND_VM_KIND_CALL:
1184            if ($inline) {
1185                $zend_attributes = " zend_always_inline";
1186                $zend_fastcall = "";
1187            } else {
1188                if ($cold) {
1189                    $zend_attributes = " zend_never_inline ZEND_COLD";
1190                } else {
1191                    $zend_attributes = " zend_never_inline";
1192                }
1193                $zend_fastcall = " ZEND_FASTCALL";
1194            }
1195            if ($param == null) {
1196              // Helper without parameters
1197                out($f, "static$zend_attributes ZEND_OPCODE_HANDLER_RET$zend_fastcall $spec_name(ZEND_OPCODE_HANDLER_ARGS)\n");
1198            } else {
1199              // Helper with parameter
1200                out($f, "static$zend_attributes ZEND_OPCODE_HANDLER_RET$zend_fastcall $spec_name($param ZEND_OPCODE_HANDLER_ARGS_DC)\n");
1201            }
1202            break;
1203        case ZEND_VM_KIND_SWITCH:
1204            out($f, "$spec_name:\n");
1205            break;
1206        case ZEND_VM_KIND_GOTO:
1207            out($f, "$spec_name:\n");
1208            break;
1209    }
1210
1211    // Generate helper's code
1212    gen_code($f, $spec, $kind, $code, $op1, $op2, $name, $extra_spec);
1213}
1214
1215
1216function gen_null_label($f, $kind, $prolog) {
1217    switch ($kind) {
1218        case ZEND_VM_KIND_CALL:
1219            out($f,$prolog."ZEND_NULL_HANDLER,\n");
1220            break;
1221        case ZEND_VM_KIND_SWITCH:
1222            out($f,$prolog."(void*)(uintptr_t)-1,\n");
1223            break;
1224        case ZEND_VM_KIND_GOTO:
1225            out($f,$prolog."(void*)&&ZEND_NULL_LABEL,\n");
1226            break;
1227    }
1228}
1229
1230// Generates array of opcode handlers (specialized or unspecialized)
1231function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array()) {
1232    global $opcodes, $opnames, $op_types, $prefix, $op_types_ex;
1233
1234    $list = [];
1235    $next = 0;
1236    $label = 0;
1237    if ($spec) {
1238      // Emit labels for specialized executor
1239
1240      // For each opcode in opcode number order
1241        foreach($opcodes as $num => $dsc) {
1242            if (isset($dsc['alias'])) {
1243                $specs[$num] = $specs[$opnames[$dsc['alias']]];
1244                continue;
1245            }
1246            $specs[$num] = "$label";
1247            $spec_op1 = $spec_op2 = $spec_extra = false;
1248            $def_op1_type = $def_op2_type = "ANY";
1249            $next = $num + 1;
1250            if (isset($dsc["op1"]) && !isset($dsc["op1"]["ANY"])) {
1251                $count = 0;
1252                foreach ($op_types_ex as $t) {
1253                    if (isset($dsc["op1"][$t])) {
1254                        $def_op1_type = $t;
1255                        $count++;
1256                    }
1257                }
1258                if ($count > 1) {
1259                    $spec_op1 = true;
1260                    $specs[$num] .= " | SPEC_RULE_OP1";
1261                    $def_op1_type = "ANY";
1262                }
1263            }
1264            if (isset($dsc["op2"]) && !isset($dsc["op2"]["ANY"])) {
1265                $count = 0;
1266                foreach ($op_types_ex as $t) {
1267                    if (isset($dsc["op2"][$t])) {
1268                        $def_op2_type = $t;
1269                        $count++;
1270                    }
1271                }
1272                if ($count > 1) {
1273                    $spec_op2 = true;
1274                    $specs[$num] .= " | SPEC_RULE_OP2";
1275                    $def_op2_type = "ANY";
1276                }
1277            }
1278            $spec_extra = call_user_func_array("array_merge", extra_spec_handler($dsc) ?: array(array()));
1279            $flags = extra_spec_flags($spec_extra);
1280            if ($flags) {
1281                $specs[$num] .= " | " . implode(" | ", $flags);
1282            }
1283            if ($num >= 256) {
1284                $opcodes[$num]['spec_code'] = $specs[$num];
1285                unset($specs[$num]);
1286            }
1287
1288            $foreach_op1 = function($do) use ($dsc, $op_types) {
1289                return function($_, $op2) use ($do, $dsc, $op_types) {
1290                    // For each op1.op_type except ANY
1291                    foreach($op_types as $op1) {
1292                        if ($op1 != "ANY") {
1293                            if (!isset($dsc["op1"][$op1])) {
1294                                if ($op1 == "TMP" || $op1 == "VAR") {
1295                                    if (isset($dsc["op1"]["TMPVAR"])) {
1296                                        $op1 = "TMPVAR";
1297                                    } else if (isset($dsc["op1"]["TMPVARCV"])) {
1298                                        $op1 = "TMPVARCV";
1299                                    } else {
1300                                        $op1 = "ANY";
1301                                    }
1302                                } else if ($op1 == "CV" && isset($dsc["op1"]["TMPVARCV"])) {
1303                                    $op1 = "TMPVARCV";
1304                                } else {
1305                                    // Try to use unspecialized handler
1306                                    $op1 = "ANY";
1307                                }
1308                            }
1309                            $do($op1, $op2);
1310                        }
1311                    }
1312                };
1313            };
1314            $foreach_op2 = function($do) use ($dsc, $op_types) {
1315                return function($op1, $_) use ($do, $dsc, $op_types) {
1316                    // For each op2.op_type except ANY
1317                    foreach($op_types as $op2) {
1318                        if ($op2 != "ANY") {
1319                            if (!isset($dsc["op2"][$op2])) {
1320                                if ($op2 == "TMP" || $op2 == "VAR") {
1321                                    if (isset($dsc["op2"]["TMPVAR"])) {
1322                                        $op2 = "TMPVAR";
1323                                    } else if (isset($dsc["op2"]["TMPVARCV"])) {
1324                                        $op2 = "TMPVARCV";
1325                                    } else {
1326                                        $op2 = "ANY";
1327                                    }
1328                                } else if ($op2 == "CV" && isset($dsc["op2"]["TMPVARCV"])) {
1329                                    $op2 = "TMPVARCV";
1330                                } else {
1331                                    // Try to use unspecialized handler
1332                                    $op2 = "ANY";
1333                                }
1334                            }
1335                            $do($op1, $op2);
1336                        }
1337                    }
1338                };
1339            };
1340            $foreach_op_data = function($do) use ($dsc, $op_types) {
1341                return function($op1, $op2, $extra_spec = array()) use ($do, $dsc, $op_types) {
1342                    // For each op_data.op_type except ANY
1343                    foreach($op_types as $op_data) {
1344                        if ($op_data != "ANY") {
1345                            if (!isset($dsc["spec"]["OP_DATA"][$op_data])) {
1346                                if ($op_data == "TMP" || $op_data == "VAR") {
1347                                    if (isset($dsc["spec"]["OP_DATA"]["TMPVAR"])) {
1348                                        $op_data = "TMPVAR";
1349                                    } else if (isset($dsc["spec"]["OP_DATA"]["TMPVARCV"])) {
1350                                        $op_data = "TMPVARCV";
1351                                    } else {
1352                                        // Try to use unspecialized handler
1353                                        $op_data = "ANY";
1354                                    }
1355                                } else if ($op_data == "CV" && isset($dsc["OP_DATA"]["TMPVARCV"])) {
1356                                    $op_data = "TMPVARCV";
1357                                } else {
1358                                    // Try to use unspecialized handler
1359                                    $op_data = "ANY";
1360                                }
1361                            }
1362                            $do($op1, $op2, array("OP_DATA" => $op_data) + $extra_spec);
1363                        }
1364                    }
1365                };
1366            };
1367            $foreach_extra_spec = function($do, $spec) use ($dsc) {
1368                return function($op1, $op2, $extra_spec = array()) use ($do, $spec, $dsc) {
1369                    foreach ($dsc["spec"][$spec] as $val) {
1370                        $do($op1, $op2, array($spec => $val) + $extra_spec);
1371                    }
1372                };
1373            };
1374            $generate = function ($op1, $op2, $extra_spec = array()) use ($f, $kind, $dsc, $prefix, $prolog, $num, $switch_labels, &$label, &$list) {
1375                global $commutative_order;
1376
1377                // Check if specialized handler is defined
1378                /* TODO: figure out better way to signal "specialized and not defined" than an extra lookup */
1379                if (isset($dsc["op1"][$op1]) &&
1380                    isset($dsc["op2"][$op2]) &&
1381                    (!isset($extra_spec["OP_DATA"]) || isset($dsc["spec"]["OP_DATA"][$extra_spec["OP_DATA"]]))) {
1382                    if (skip_extra_spec_function($op1, $op2, $extra_spec)) {
1383                        gen_null_label($f, $kind, $prolog);
1384                        $list[$label] = null;
1385                        $label++;
1386                        return;
1387                    }
1388
1389                    /* Skip SMART_BRANCH specialization for "cold" CONST_CONST instructions */
1390                    if (isset($extra_spec["SMART_BRANCH"])) {
1391                        if ($dsc["hot"] === 'HOT_NOCONSTCONST_'
1392                         || $dsc["hot"] === 'COLD_CONSTCONST_') {
1393                            if (($op1 === 'CONST') && ($op2 === 'CONST')) {
1394                                unset($extra_spec["SMART_BRANCH"]);
1395                            }
1396                        }
1397                    }
1398
1399                    /* Skip QUICK_ARG specialization for named parameters */
1400                    if (isset($extra_spec["QUICK_ARG"])) {
1401                        if ($op2 === "CONST") {
1402                            unset($extra_spec["QUICK_ARG"]);
1403                        }
1404                    }
1405
1406                    /* Skip all specialization for OBSERVER handlers */
1407                    if (isset($extra_spec["OBSERVER"]) && $extra_spec["OBSERVER"] == 1) {
1408                        if (isset($extra_spec["RETVAL"])) {
1409                            unset($extra_spec["RETVAL"]);
1410                        }
1411                        if ($op1 != "ANY" || $op2 != "ANY") {
1412                            $op1 = "ANY";
1413                            $op2 = "ANY";
1414                        }
1415                    }
1416
1417                    // Emit pointer to specialized handler
1418                    $spec_name = $dsc["op"]."_SPEC".$prefix[$op1].$prefix[$op2].extra_spec_name($extra_spec);
1419                    switch ($kind) {
1420                        case ZEND_VM_KIND_CALL:
1421                            out($f,"$prolog{$spec_name}_HANDLER,\n");
1422                            break;
1423                        case ZEND_VM_KIND_SWITCH:
1424                            out($f,$prolog."(void*)(uintptr_t)$switch_labels[$spec_name],\n");
1425                            break;
1426                        case ZEND_VM_KIND_GOTO:
1427                            out($f,$prolog."(void*)&&{$spec_name}_LABEL,\n");
1428                            break;
1429                    }
1430                    $list[$label] = $spec_name;
1431                    $label++;
1432                } else {
1433                    // Emit pointer to handler of undefined opcode
1434                    gen_null_label($f, $kind, $prolog);
1435                    $list[$label] = null;
1436                    $label++;
1437                }
1438            };
1439
1440            $do = $generate;
1441            if ($spec_extra) {
1442                foreach ($spec_extra as $extra => $devnull) {
1443                    if ($extra == "OP_DATA") {
1444                        $do = $foreach_op_data($do);
1445                    } else {
1446                        $do = $foreach_extra_spec($do, $extra);
1447                    }
1448                }
1449            }
1450            if ($spec_op2) {
1451                $do = $foreach_op2($do);
1452            }
1453            if ($spec_op1) {
1454                $do = $foreach_op1($do);
1455            }
1456
1457            $do($def_op1_type, $def_op2_type);
1458        }
1459    } else {
1460      // Emit labels for unspecialized executor
1461
1462      // For each opcode in opcode number order
1463        foreach($opcodes as $num => $dsc) {
1464            while ($next != $num) {
1465              // If some opcode numbers are not used then fill hole with pointers
1466              // to handler of undefined opcode
1467                switch ($kind) {
1468                    case ZEND_VM_KIND_CALL:
1469                        out($f,$prolog."ZEND_NULL_HANDLER,\n");
1470                        break;
1471                    case ZEND_VM_KIND_SWITCH:
1472                        out($f,$prolog."(void*)(uintptr_t)-1,\n");
1473                        break;
1474                    case ZEND_VM_KIND_GOTO:
1475                        out($f,$prolog."(void*)&&ZEND_NULL_LABEL,\n");
1476                        break;
1477                }
1478                $next++;
1479            }
1480            if ($num >= 256) {
1481                continue;
1482            }
1483            $next = $num+1;
1484
1485            if (isset($dsc['alias']) && $kind != ZEND_VM_KIND_SWITCH) {
1486                // Emit pointer to unspecialized handler
1487                switch ($kind) {
1488                case ZEND_VM_KIND_CALL:
1489                    out($f,$prolog.$dsc['alias']."_HANDLER,\n");
1490                    break;
1491                case ZEND_VM_KIND_GOTO:
1492                    out($f,$prolog."(void*)&&".$dsc['alias']."_LABEL,\n");
1493                    break;
1494                }
1495                $list[] = $dsc["op"];
1496            } else if ($dsc["code"]) { //ugly trick for ZEND_VM_DEFINE_OP
1497                // Emit pointer to unspecialized handler
1498                switch ($kind) {
1499                case ZEND_VM_KIND_CALL:
1500                    out($f,$prolog.$dsc["op"]."_HANDLER,\n");
1501                    break;
1502                case ZEND_VM_KIND_SWITCH:
1503                    out($f,$prolog."(void*)(uintptr_t)".((string)$num).",\n");
1504                    break;
1505                case ZEND_VM_KIND_GOTO:
1506                    out($f,$prolog."(void*)&&".$dsc["op"]."_LABEL,\n");
1507                    break;
1508                }
1509                $list[] = $dsc["op"];
1510            } else {
1511                switch ($kind) {
1512                    case ZEND_VM_KIND_CALL:
1513                        out($f,$prolog."ZEND_NULL_HANDLER,\n");
1514                        break;
1515                    case ZEND_VM_KIND_SWITCH:
1516                        out($f,$prolog."(void*)(uintptr_t)-1,\n");
1517                        break;
1518                    case ZEND_VM_KIND_GOTO:
1519                        out($f,$prolog."(void*)&&ZEND_NULL_LABEL,\n");
1520                        break;
1521                }
1522                $list[] = null;
1523            }
1524        }
1525    }
1526
1527    // Emit last handler's label (undefined opcode)
1528    switch ($kind) {
1529        case ZEND_VM_KIND_CALL:
1530            out($f,$prolog."ZEND_NULL_HANDLER\n");
1531            break;
1532        case ZEND_VM_KIND_SWITCH:
1533            out($f,$prolog."(void*)(uintptr_t)-1\n");
1534            break;
1535        case ZEND_VM_KIND_GOTO:
1536            out($f,$prolog."(void*)&&ZEND_NULL_LABEL\n");
1537            break;
1538    }
1539    $specs[$num + 1] = "$label";
1540
1541    $l = fopen(__DIR__ . "/zend_vm_handlers.h", "w+") or die("ERROR: Cannot create zend_vm_handlers.h\n");
1542    out($l, "#define VM_HANDLERS(_) \\\n");
1543    foreach ($list as $n => $name) {
1544        if (!is_null($name)) {
1545            out($l, "\t_($n, $name) \\\n");
1546        }
1547    }
1548    out($l, "\t_($n+1, ZEND_NULL)\n");
1549    fclose($l);
1550}
1551
1552// Generates specialized offsets
1553function gen_specs($f, $prolog, $specs) {
1554    $lastdef = array_pop($specs);
1555    $last = 0;
1556    foreach ($specs as $num => $def) {
1557        while (++$last < $num) {
1558            out($f, "$prolog$lastdef,\n");
1559        }
1560        $last = $num;
1561        out($f, "$prolog$def,\n");
1562    }
1563    out($f, "$prolog$lastdef\n");
1564}
1565
1566// Generates handler for undefined opcodes (CALL threading model)
1567function gen_null_handler($f) {
1568    static $done = 0;
1569
1570    // New and all executors with CALL threading model can use the same handler
1571    // for undefined opcodes, do we emit code for it only once
1572    if (!$done) {
1573        $done = 1;
1574        out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n");
1575        out($f,"{\n");
1576        out($f,"\tUSE_OPLINE\n");
1577        out($f,"\n");
1578        out($f,"\tSAVE_OPLINE();\n");
1579        out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n");
1580        out($f,"\tZEND_VM_NEXT_OPCODE(); /* Never reached */\n");
1581        out($f,"}\n\n");
1582    }
1583}
1584
1585function extra_spec_name($extra_spec) {
1586    global $prefix;
1587
1588    $s = "";
1589    if (isset($extra_spec["OP_DATA"])) {
1590        $s .= "_OP_DATA" . $prefix[$extra_spec["OP_DATA"]];
1591    }
1592    if (isset($extra_spec["RETVAL"])) {
1593        $s .= "_RETVAL_".($extra_spec["RETVAL"] ? "USED" : "UNUSED");
1594    }
1595    if (isset($extra_spec["QUICK_ARG"])) {
1596        if ($extra_spec["QUICK_ARG"]) {
1597            $s .= "_QUICK";
1598        }
1599    }
1600    if (isset($extra_spec["SMART_BRANCH"])) {
1601        if ($extra_spec["SMART_BRANCH"] == 1) {
1602            $s .= "_JMPZ";
1603        } else if ($extra_spec["SMART_BRANCH"] == 2) {
1604            $s .= "_JMPNZ";
1605        }
1606    }
1607    if (isset($extra_spec["ISSET"])) {
1608        if ($extra_spec["ISSET"] == 0) {
1609            $s .= "_SET";
1610        } else {
1611            $s .= "_EMPTY";
1612        }
1613    }
1614    if (isset($extra_spec["OBSERVER"])) {
1615        if ($extra_spec["OBSERVER"]) {
1616            $s .= "_OBSERVER";
1617        }
1618    }
1619    return $s;
1620}
1621
1622function extra_spec_flags($extra_spec) {
1623    $s = array();
1624    if (isset($extra_spec["OP_DATA"])) {
1625        $s[] = "SPEC_RULE_OP_DATA";
1626    }
1627    if (isset($extra_spec["RETVAL"])) {
1628        $s[] = "SPEC_RULE_RETVAL";
1629    }
1630    if (isset($extra_spec["QUICK_ARG"])) {
1631        $s[] = "SPEC_RULE_QUICK_ARG";
1632    }
1633    if (isset($extra_spec["SMART_BRANCH"])) {
1634        $s[] = "SPEC_RULE_SMART_BRANCH";
1635    }
1636    if (isset($extra_spec["COMMUTATIVE"])) {
1637        $s[] = "SPEC_RULE_COMMUTATIVE";
1638    }
1639    if (isset($extra_spec["ISSET"])) {
1640        $s[] = "SPEC_RULE_ISSET";
1641    }
1642    if (isset($extra_spec["OBSERVER"])) {
1643        $s[] = "SPEC_RULE_OBSERVER";
1644    }
1645    return $s;
1646}
1647
1648function extra_spec_handler($dsc) {
1649    global $op_types_ex;
1650
1651    if (!isset($dsc["spec"])) {
1652        return array(array());
1653    }
1654    $specs = $dsc["spec"];
1655
1656    if (isset($specs["OP_DATA"])) {
1657        $op_data_specs = $specs["OP_DATA"];
1658        $specs["OP_DATA"] = array();
1659        foreach($op_types_ex as $op_data) {
1660            if (isset($dsc["spec"]["OP_DATA"][$op_data])) {
1661                $specs["OP_DATA"][] = $op_data;
1662            }
1663        }
1664    }
1665
1666    $f = function($specs) use (&$f) {
1667        $spec = key($specs);
1668        $top = array_shift($specs);
1669        if ($specs) {
1670            $next = $f($specs);
1671        } else {
1672            $next = array(array());
1673        }
1674        $ret = array();
1675        foreach ($next as $existing) {
1676            foreach ($top as $mode) {
1677                $ret[] = array($spec => $mode) + $existing;
1678            }
1679        }
1680        return $ret;
1681    };
1682    return $f($specs);
1683}
1684
1685function read_order_file($fn) {
1686    $f = fopen($fn, "r");
1687    if (!is_resource($f)) {
1688        return false;
1689    }
1690    $order = [];
1691    while (!feof($f)) {
1692        $op = trim(fgets($f));
1693        if ($op !== "") {
1694            $order[$op] = null;
1695        }
1696    }
1697    fclose($f);
1698    return $order;
1699}
1700
1701// Generates all opcode handlers and helpers (specialized or unspecialized)
1702function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array()) {
1703    global $list, $opcodes, $helpers, $op_types_ex, $gen_order;
1704
1705    if ($spec) {
1706        // Produce specialized executor
1707        $op1t = $op_types_ex;
1708        // for each op1.op_type
1709        foreach($op1t as $op1) {
1710            $op2t = $op_types_ex;
1711            // for each op2.op_type
1712            foreach($op2t as $op2) {
1713                // for each handlers in helpers in original order
1714                foreach ($list as $lineno => $dsc) {
1715                    if (isset($dsc["handler"])) {
1716                        $num = $dsc["handler"];
1717                        foreach (extra_spec_handler($opcodes[$num]) as $extra_spec) {
1718                            // Check if handler accepts such types of operands (op1 and op2)
1719                            if (isset($opcodes[$num]["op1"][$op1]) &&
1720                                isset($opcodes[$num]["op2"][$op2])) {
1721                              // Generate handler code
1722                                gen_handler($f, 1, $kind, $opcodes[$num]["op"], $op1, $op2, isset($opcodes[$num]["use"]), $opcodes[$num]["code"], $lineno, $opcodes[$num], $extra_spec, $switch_labels);
1723                            }
1724                        }
1725                    } else if (isset($dsc["helper"])) {
1726                        $num = $dsc["helper"];
1727                        foreach (extra_spec_handler($helpers[$num]) as $extra_spec) {
1728                            // Check if handler accepts such types of operands (op1 and op2)
1729                            if (isset($helpers[$num]["op1"][$op1]) &&
1730                                isset($helpers[$num]["op2"][$op2])) {
1731                              // Generate helper code
1732                                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);
1733                            }
1734                        }
1735                    } else {
1736                        var_dump($dsc);
1737                        die("??? $kind:$num\n");
1738                    }
1739                }
1740            }
1741        }
1742    } else {
1743        // Produce unspecialized executor
1744
1745        // for each handlers in helpers in original order
1746        foreach ($list as $lineno => $dsc) {
1747            if (isset($dsc["handler"])) {
1748                $num = $dsc["handler"];
1749                // Generate handler code
1750                if ($num < 256) {
1751                    gen_handler($f, 0, $kind, $opcodes[$num]["op"], "ANY", "ANY", isset($opcodes[$num]["use"]), $opcodes[$num]["code"], $lineno, $opcodes[$num]);
1752                }
1753            } else if (isset($dsc["helper"])) {
1754                $num = $dsc["helper"];
1755                // Generate helper code
1756                gen_helper($f, 0, $kind, $num, "ANY", "ANY", $helpers[$num]["param"], $helpers[$num]["code"], $lineno, $helpers[$num]["inline"], $helpers[$num]["cold"], $helpers[$num]["hot"]);
1757            } else {
1758                var_dump($dsc);
1759                die("??? $kind:$num\n");
1760            }
1761        }
1762    }
1763
1764    if (is_array($gen_order)) {
1765        foreach ($gen_order as $txt) {
1766            if ($txt !== null) {
1767                out($f, $txt);
1768            }
1769        }
1770    }
1771
1772    if (ZEND_VM_LINES) {
1773        // Reset #line directives
1774        out_line($f);
1775    }
1776
1777    // Generate handler for undefined opcodes
1778    switch ($kind) {
1779        case ZEND_VM_KIND_CALL:
1780            gen_null_handler($f);
1781            break;
1782        case ZEND_VM_KIND_SWITCH:
1783            out($f,"default: ZEND_NULL_LABEL:\n");
1784            out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n");
1785            out($f,"\tZEND_VM_NEXT_OPCODE(); /* Never reached */\n");
1786            break;
1787        case ZEND_VM_KIND_GOTO:
1788            out($f,"ZEND_NULL_LABEL:\n");
1789            out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n");
1790            out($f,"\tZEND_VM_NEXT_OPCODE(); /* Never reached */\n");
1791            break;
1792        case ZEND_VM_KIND_HYBRID:
1793            out($f,"\t\t\tHYBRID_CASE(HYBRID_HALT):\n");
1794            out($f,"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
1795            out($f,"\t\t\t\texecute_data = vm_stack_data.orig_execute_data;\n");
1796            out($f,"#endif\n");
1797            out($f,"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
1798            out($f,"\t\t\t\topline = vm_stack_data.orig_opline;\n");
1799            out($f,"#endif\n");
1800            out($f,"\t\t\t\treturn;\n");
1801            out($f,"\t\t\tHYBRID_DEFAULT:\n");
1802            out($f,"\t\t\t\tVM_TRACE(ZEND_NULL)\n");
1803            out($f,"\t\t\t\tZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
1804            out($f,"\t\t\t\tHYBRID_BREAK(); /* Never reached */\n");
1805            break;
1806    }
1807}
1808
1809function skip_blanks($f, $prolog, $epilog) {
1810    if (trim($prolog) != "" || trim($epilog) != "") {
1811        out($f, $prolog.$epilog);
1812    }
1813}
1814
1815// Generates executor from skeleton file and definition (specialized or unspecialized)
1816function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) {
1817    global $params, $skeleton_file, $line_no, $gen_order;
1818
1819    if ($kind == ZEND_VM_KIND_HYBRID && file_exists(__DIR__ . "/zend_vm_order.txt")) {
1820        $gen_order = read_order_file(__DIR__ . "/zend_vm_order.txt");
1821    } else {
1822        $gen_order = null;
1823    }
1824
1825    $switch_labels = array();
1826    $lineno = 0;
1827    foreach ($skl as $line) {
1828      // Skeleton file contains special markers in form %NAME% those are
1829      // substituted by custom code
1830        if (preg_match("/(.*)[{][%]([A-Z_]*)[%][}](.*)/", $line, $m)) {
1831            switch ($m[2]) {
1832                case "DEFINES":
1833                    out($f,"#define SPEC_START_MASK        0x0000ffff\n");
1834                    out($f,"#define SPEC_EXTRA_MASK        0xfffc0000\n");
1835                    out($f,"#define SPEC_RULE_OP1          0x00010000\n");
1836                    out($f,"#define SPEC_RULE_OP2          0x00020000\n");
1837                    out($f,"#define SPEC_RULE_OP_DATA      0x00040000\n");
1838                    out($f,"#define SPEC_RULE_RETVAL       0x00080000\n");
1839                    out($f,"#define SPEC_RULE_QUICK_ARG    0x00100000\n");
1840                    out($f,"#define SPEC_RULE_SMART_BRANCH 0x00200000\n");
1841                    out($f,"#define SPEC_RULE_COMMUTATIVE  0x00800000\n");
1842                    out($f,"#define SPEC_RULE_ISSET        0x01000000\n");
1843                    out($f,"#define SPEC_RULE_OBSERVER     0x02000000\n");
1844                    out($f,"\n");
1845                    out($f,"static const uint32_t *zend_spec_handlers;\n");
1846                    out($f,"static const void * const *zend_opcode_handlers;\n");
1847                    out($f,"static int zend_handlers_count;\n");
1848                    if ($kind == ZEND_VM_KIND_HYBRID) {
1849                        out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
1850                        out($f,"static const void * const * zend_opcode_handler_funcs;\n");
1851                        out($f,"static zend_op hybrid_halt_op;\n");
1852                        out($f,"#endif\n");
1853                    }
1854                    out($f,"#if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID) || !ZEND_VM_SPEC\n");
1855                    out($f,"static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op);\n");
1856                    out($f,"#endif\n\n");
1857                    if ($kind == ZEND_VM_KIND_HYBRID) {
1858                        out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
1859                        out($f,"static const void *zend_vm_get_opcode_handler_func(zend_uchar opcode, const zend_op* op);\n");
1860                        out($f,"#else\n");
1861                        out($f,"# define zend_vm_get_opcode_handler_func zend_vm_get_opcode_handler\n");
1862                        out($f,"#endif\n\n");
1863                    }
1864                    out($f,"#ifndef VM_TRACE\n");
1865                    if (is_array($gen_order)) {
1866                        out($f,"# define VM_TRACE(op) ZEND_VM_GUARD(op);\n");
1867                    } else {
1868                        out($f,"# define VM_TRACE(op)\n");
1869                    }
1870                    out($f,"#endif\n");
1871                    out($f,"#ifndef VM_TRACE_START\n");
1872                    out($f,"# define VM_TRACE_START()\n");
1873                    out($f,"#endif\n");
1874                    out($f,"#ifndef VM_TRACE_END\n");
1875                    out($f,"# define VM_TRACE_END()\n");
1876                    out($f,"#endif\n");
1877                    switch ($kind) {
1878                        case ZEND_VM_KIND_HYBRID:
1879                            out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
1880                            out($f,"#define HYBRID_NEXT()     goto *(void**)(OPLINE->handler)\n");
1881                            out($f,"#define HYBRID_SWITCH()   HYBRID_NEXT();\n");
1882                            out($f,"#define HYBRID_CASE(op)   op ## _LABEL\n");
1883                            out($f,"#define HYBRID_BREAK()    HYBRID_NEXT()\n");
1884                            out($f,"#define HYBRID_DEFAULT    ZEND_NULL_LABEL\n");
1885                            out($f,"#endif\n");
1886                        case ZEND_VM_KIND_CALL:
1887                            out($f,"\n");
1888                            out($f,"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
1889                            out($f,"# define ZEND_OPCODE_HANDLER_ARGS void\n");
1890                            out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU\n");
1891                            out($f,"# define ZEND_OPCODE_HANDLER_ARGS_DC\n");
1892                            out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC\n");
1893                            out($f,"#else\n");
1894                            out($f,"# define ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data\n");
1895                            out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU execute_data\n");
1896                            out($f,"# define ZEND_OPCODE_HANDLER_ARGS_DC , ZEND_OPCODE_HANDLER_ARGS\n");
1897                            out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC , ZEND_OPCODE_HANDLER_ARGS_PASSTHRU\n");
1898                            out($f,"#endif\n");
1899                            out($f,"\n");
1900                            out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n");
1901                            out($f,"# define ZEND_OPCODE_HANDLER_RET void\n");
1902                            out($f,"# define ZEND_VM_TAIL_CALL(call) call; return\n");
1903                            out($f,"# ifdef ZEND_VM_TAIL_CALL_DISPATCH\n");
1904                            out($f,"#  define ZEND_VM_CONTINUE()     ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); return\n");
1905                            out($f,"# else\n");
1906                            out($f,"#  define ZEND_VM_CONTINUE()     return\n");
1907                            out($f,"# endif\n");
1908                            if ($kind == ZEND_VM_KIND_HYBRID) {
1909                                out($f,"# if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
1910                                out($f,"#  define ZEND_VM_RETURN()        opline = &hybrid_halt_op; return\n");
1911                                out($f,"#  define ZEND_VM_HOT             zend_always_inline ZEND_COLD ZEND_OPT_SIZE\n");
1912                                out($f,"#  define ZEND_VM_COLD            ZEND_COLD ZEND_OPT_SIZE\n");
1913                                out($f,"# else\n");
1914                                out($f,"#  define ZEND_VM_RETURN()        opline = NULL; return\n");
1915                                out($f,"#  define ZEND_VM_HOT\n");
1916                                out($f,"#  define ZEND_VM_COLD            ZEND_COLD ZEND_OPT_SIZE\n");
1917                                out($f,"# endif\n");
1918                            } else {
1919                                out($f,"# define ZEND_VM_RETURN()        opline = NULL; return\n");
1920                                out($f,"# define ZEND_VM_COLD            ZEND_COLD ZEND_OPT_SIZE\n");
1921                            }
1922                            out($f,"#else\n");
1923                            out($f,"# define ZEND_OPCODE_HANDLER_RET int\n");
1924                            out($f,"# define ZEND_VM_TAIL_CALL(call) return call\n");
1925                            out($f,"# define ZEND_VM_CONTINUE()      return  0\n");
1926                            out($f,"# define ZEND_VM_RETURN()        return -1\n");
1927                            if ($kind == ZEND_VM_KIND_HYBRID) {
1928                                out($f,"# define ZEND_VM_HOT\n");
1929                            }
1930                            out($f,"# define ZEND_VM_COLD            ZEND_COLD ZEND_OPT_SIZE\n");
1931                            out($f,"#endif\n");
1932                            out($f,"\n");
1933                            out($f,"typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS);\n");
1934                            out($f,"\n");
1935                            out($f,"#define DCL_OPLINE\n");
1936                            out($f,"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
1937                            out($f,"# define OPLINE opline\n");
1938                            out($f,"# define USE_OPLINE\n");
1939                            out($f,"# define LOAD_OPLINE() opline = EX(opline)\n");
1940                            out($f,"# define LOAD_OPLINE_EX()\n");
1941                            out($f,"# define LOAD_NEXT_OPLINE() opline = EX(opline) + 1\n");
1942                            out($f,"# define SAVE_OPLINE() EX(opline) = opline\n");
1943                            out($f,"# define SAVE_OPLINE_EX() SAVE_OPLINE()\n");
1944                            out($f,"#else\n");
1945                            out($f,"# define OPLINE EX(opline)\n");
1946                            out($f,"# define USE_OPLINE const zend_op *opline = EX(opline);\n");
1947                            out($f,"# define LOAD_OPLINE()\n");
1948                            out($f,"# define LOAD_OPLINE_EX()\n");
1949                            out($f,"# define LOAD_NEXT_OPLINE() ZEND_VM_INC_OPCODE()\n");
1950                            out($f,"# define SAVE_OPLINE()\n");
1951                            out($f,"# define SAVE_OPLINE_EX()\n");
1952                            out($f,"#endif\n");
1953                            out($f,"#define HANDLE_EXCEPTION() ZEND_ASSERT(EG(exception)); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
1954                            out($f,"#define HANDLE_EXCEPTION_LEAVE() ZEND_ASSERT(EG(exception)); LOAD_OPLINE(); ZEND_VM_LEAVE()\n");
1955                            out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG)\n");
1956                            out($f,"# define ZEND_VM_ENTER_EX()        ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n");
1957                            out($f,"# define ZEND_VM_ENTER()           execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n");
1958                            out($f,"# define ZEND_VM_LEAVE()           ZEND_VM_CONTINUE()\n");
1959                            out($f,"#elif defined(ZEND_VM_IP_GLOBAL_REG)\n");
1960                            out($f,"# define ZEND_VM_ENTER_EX()        return  1\n");
1961                            out($f,"# define ZEND_VM_ENTER()           opline = EG(current_execute_data)->opline; ZEND_VM_ENTER_EX()\n");
1962                            out($f,"# define ZEND_VM_LEAVE()           return  2\n");
1963                            out($f,"#else\n");
1964                            out($f,"# define ZEND_VM_ENTER_EX()        return  1\n");
1965                            out($f,"# define ZEND_VM_ENTER()           return  1\n");
1966                            out($f,"# define ZEND_VM_LEAVE()           return  2\n");
1967                            out($f,"#endif\n");
1968                            out($f,"#define ZEND_VM_INTERRUPT()      ZEND_VM_TAIL_CALL(zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n");
1969                            out($f,"#define ZEND_VM_LOOP_INTERRUPT() zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
1970                            if ($kind == ZEND_VM_KIND_HYBRID) {
1971                                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");
1972                            } else {
1973                                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");
1974                            }
1975                            out($f,"\n");
1976                            out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS);\n");
1977                            out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS);\n");
1978                            out($f,"\n");
1979                            break;
1980                        case ZEND_VM_KIND_SWITCH:
1981                            out($f,"\n");
1982                            out($f,"#define OPLINE opline\n");
1983                            out($f,"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
1984                            out($f,"# define DCL_OPLINE register const zend_op *opline __asm__(ZEND_VM_IP_GLOBAL_REG);\n");
1985                            out($f,"#else\n");
1986                            out($f,"# define DCL_OPLINE const zend_op *opline;\n");
1987                            out($f,"#endif\n");
1988                            out($f,"#define USE_OPLINE\n");
1989                            out($f,"#define LOAD_OPLINE() opline = EX(opline)\n");
1990                            out($f,"# define LOAD_OPLINE_EX() LOAD_OPLINE()\n");
1991                            out($f,"#define LOAD_NEXT_OPLINE() opline = EX(opline) + 1\n");
1992                            out($f,"#define SAVE_OPLINE() EX(opline) = opline\n");
1993                            out($f,"#define SAVE_OPLINE_EX()\n");
1994                            out($f,"#define HANDLE_EXCEPTION() ZEND_ASSERT(EG(exception)); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
1995                            out($f,"#define HANDLE_EXCEPTION_LEAVE() ZEND_ASSERT(EG(exception)); LOAD_OPLINE(); ZEND_VM_LEAVE()\n");
1996                            out($f,"#define ZEND_VM_CONTINUE() goto zend_vm_continue\n");
1997                            out($f,"#define ZEND_VM_RETURN()   return\n");
1998                            out($f,"#define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n");
1999                            out($f,"#define ZEND_VM_ENTER()    execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n");
2000                            out($f,"#define ZEND_VM_LEAVE()    ZEND_VM_CONTINUE()\n");
2001                            out($f,"#define ZEND_VM_INTERRUPT()              goto zend_interrupt_helper".($spec?"_SPEC":"").";\n");
2002                            out($f,"#define ZEND_VM_LOOP_INTERRUPT()         goto zend_interrupt_helper".($spec?"_SPEC":"").";\n");
2003                            out($f,"#define ZEND_VM_DISPATCH(opcode, opline) dispatch_handler = zend_vm_get_opcode_handler(opcode, opline); goto zend_vm_dispatch;\n");
2004                            out($f,"\n");
2005                            break;
2006                        case ZEND_VM_KIND_GOTO:
2007                            out($f,"\n");
2008                            out($f,"#define OPLINE opline\n");
2009                            out($f,"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
2010                            out($f,"# define DCL_OPLINE register const zend_op *opline __asm__(ZEND_VM_IP_GLOBAL_REG);\n");
2011                            out($f,"#else\n");
2012                            out($f,"# define DCL_OPLINE const zend_op *opline;\n");
2013                            out($f,"#endif\n");
2014                            out($f,"#define USE_OPLINE\n");
2015                            out($f,"#define LOAD_OPLINE() opline = EX(opline)\n");
2016                            out($f,"#define LOAD_OPLINE_EX() LOAD_OPLINE()\n");
2017                            out($f,"#define LOAD_NEXT_OPLINE() opline = EX(opline) + 1\n");
2018                            out($f,"#define SAVE_OPLINE() EX(opline) = opline\n");
2019                            out($f,"#define SAVE_OPLINE_EX()\n");
2020                            if (ZEND_VM_SPEC) {
2021                                out($f,"#define HANDLE_EXCEPTION() ZEND_ASSERT(EG(exception)); goto ZEND_HANDLE_EXCEPTION_SPEC_LABEL\n");
2022                                out($f,"#define HANDLE_EXCEPTION_LEAVE() ZEND_ASSERT(EG(exception)); goto ZEND_HANDLE_EXCEPTION_SPEC_LABEL\n");
2023                            } else {
2024                                out($f,"#define HANDLE_EXCEPTION() ZEND_ASSERT(EG(exception)); goto ZEND_HANDLE_EXCEPTION_LABEL\n");
2025                                out($f,"#define HANDLE_EXCEPTION_LEAVE() ZEND_ASSERT(EG(exception)); goto ZEND_HANDLE_EXCEPTION_LABEL\n");
2026                            }
2027                            out($f,"#define ZEND_VM_CONTINUE() goto *(void**)(OPLINE->handler)\n");
2028                            out($f,"#define ZEND_VM_RETURN()   return\n");
2029                            out($f,"#define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n");
2030                            out($f,"#define ZEND_VM_ENTER()    execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n");
2031                            out($f,"#define ZEND_VM_LEAVE()    ZEND_VM_CONTINUE()\n");
2032                            out($f,"#define ZEND_VM_INTERRUPT()              goto zend_interrupt_helper".($spec?"_SPEC":"").";\n");
2033                            out($f,"#define ZEND_VM_LOOP_INTERRUPT()         goto zend_interrupt_helper".($spec?"_SPEC":"").";\n");
2034                            out($f,"#define ZEND_VM_DISPATCH(opcode, opline) goto *(void**)(zend_vm_get_opcode_handler(opcode, opline));\n");
2035                            out($f,"\n");
2036                            break;
2037                    }
2038                    if ($kind == ZEND_VM_KIND_HYBRID) {
2039                        gen_executor_code($f, $spec, ZEND_VM_KIND_CALL, $m[1]);
2040                        out($f,"\n");
2041                        out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
2042                        out($f,"# undef ZEND_VM_TAIL_CALL\n");
2043                        out($f,"# undef ZEND_VM_CONTINUE\n");
2044                        out($f,"# undef ZEND_VM_RETURN\n");
2045//						out($f,"# undef ZEND_VM_INTERRUPT\n");
2046                        out($f,"\n");
2047                        out($f,"# define ZEND_VM_TAIL_CALL(call) call; ZEND_VM_CONTINUE()\n");
2048                        out($f,"# define ZEND_VM_CONTINUE()      HYBRID_NEXT()\n");
2049                        out($f,"# define ZEND_VM_RETURN()        goto HYBRID_HALT_LABEL\n");
2050//						out($f,"# define ZEND_VM_INTERRUPT()     goto zend_interrupt_helper_SPEC_LABEL\n");
2051                        out($f,"#endif\n\n");
2052                    }
2053                    break;
2054                case "EXECUTOR_NAME":
2055                    out($f, $m[1].$executor_name.$m[3]."\n");
2056                    break;
2057                case "HELPER_VARS":
2058                    if ($kind == ZEND_VM_KIND_SWITCH) {
2059                        out($f,$m[1]."const void *dispatch_handler;\n");
2060                    }
2061                    if ($kind != ZEND_VM_KIND_CALL && count($params)) {
2062                        if ($kind == ZEND_VM_KIND_HYBRID) {
2063                            out($f, "#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
2064                        }
2065                        // Emit local variables those are used for helpers' parameters
2066                        foreach ($params as $param => $x) {
2067                            out($f,$m[1].$param.";\n");
2068                        }
2069                        if ($kind == ZEND_VM_KIND_HYBRID) {
2070                            out($f, "#endif\n");
2071                        }
2072                    }
2073                    if ($kind != ZEND_VM_KIND_CALL && $kind != ZEND_VM_KIND_HYBRID) {
2074                        out($f,"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
2075                        out($f,$m[1]."register zend_execute_data *execute_data __asm__(ZEND_VM_FP_GLOBAL_REG) = ex;\n");
2076                        out($f,"#else\n");
2077                        out($f,$m[1]."zend_execute_data *execute_data = ex;\n");
2078                        out($f,"#endif\n");
2079                    } else {
2080                        out($f,"#if defined(ZEND_VM_IP_GLOBAL_REG) || defined(ZEND_VM_IP_GLOBAL_REG)\n");
2081                        out($f,$m[1]."struct {\n");
2082                        out($f,"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
2083                        out($f,$m[1]."\tconst zend_op *orig_opline;\n");
2084                        out($f,"#endif\n");
2085                        out($f,"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
2086                        out($f,$m[1]."\tzend_execute_data *orig_execute_data;\n");
2087                        out($f,"#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE\n");
2088                        out($f,$m[1]."\tchar hybrid_jit_red_zone[ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE];\n");
2089                        out($f,"#endif\n");
2090                        out($f,"#endif\n");
2091                        out($f,$m[1]."} vm_stack_data;\n");
2092                        out($f,"#endif\n");
2093                        out($f,"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
2094                        out($f,$m[1]."vm_stack_data.orig_opline = opline;\n");
2095                        out($f,"#endif\n");
2096                        out($f,"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
2097                        out($f,$m[1]."vm_stack_data.orig_execute_data = execute_data;\n");
2098                        out($f,$m[1]."execute_data = ex;\n");
2099                        out($f,"#else\n");
2100                        out($f,$m[1]."zend_execute_data *execute_data = ex;\n");
2101                        out($f,"#endif\n");
2102                        out($f,"#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE\n");
2103                        out($f,$m[1]."memset(vm_stack_data.hybrid_jit_red_zone, 0, ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE);\n");
2104                        out($f,$m[1]."if (zend_touch_vm_stack_data) {\n");
2105                        out($f,$m[1]."\tzend_touch_vm_stack_data(&vm_stack_data);\n");
2106                        out($f,$m[1]."}\n");
2107                        out($f,"#endif\n");
2108                    }
2109                    break;
2110                case "INTERNAL_LABELS":
2111                    if ($kind == ZEND_VM_KIND_GOTO || $kind == ZEND_VM_KIND_HYBRID) {
2112                      // Emit array of labels of opcode handlers and code for
2113                      // zend_opcode_handlers initialization
2114                        if ($kind == ZEND_VM_KIND_HYBRID) {
2115                            out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
2116                        }
2117                        $prolog = $m[1];
2118                        out($f,$prolog."if (UNEXPECTED(execute_data == NULL)) {\n");
2119                        out($f,$prolog."\tstatic const void * const labels[] = {\n");
2120                        gen_labels($f, $spec, ($kind == ZEND_VM_KIND_HYBRID) ? ZEND_VM_KIND_GOTO : $kind, $prolog."\t\t", $specs);
2121                        out($f,$prolog."\t};\n");
2122                        out($f,$prolog."\tzend_opcode_handlers = (const void **) labels;\n");
2123                        out($f,$prolog."\tzend_handlers_count = sizeof(labels) / sizeof(void*);\n");
2124                        if ($kind == ZEND_VM_KIND_HYBRID) {
2125                            out($f,$prolog."\tmemset(&hybrid_halt_op, 0, sizeof(hybrid_halt_op));\n");
2126                            out($f,$prolog."\thybrid_halt_op.handler = (void*)&&HYBRID_HALT_LABEL;\n");
2127                            out($f,$prolog."\tgoto HYBRID_HALT_LABEL;\n");
2128                        } else {
2129                            out($f,$prolog."\treturn;\n");
2130                        }
2131                        out($f,$prolog."}\n");
2132                        if ($kind == ZEND_VM_KIND_HYBRID) {
2133                            out($f,"#endif\n");
2134                        }
2135                    } else {
2136                        skip_blanks($f, $m[1], $m[3]);
2137                    }
2138                    break;
2139                case "ZEND_VM_CONTINUE_LABEL":
2140                    if ($kind == ZEND_VM_KIND_CALL || $kind == ZEND_VM_KIND_HYBRID) {
2141                      // Only SWITCH dispatch method use it
2142                        out($f,"#if !defined(ZEND_VM_FP_GLOBAL_REG) || !defined(ZEND_VM_IP_GLOBAL_REG)\n");
2143                        out($f,$m[1]."\tint ret;".$m[3]."\n");
2144                        out($f,"#endif\n");
2145                    } else if ($kind == ZEND_VM_KIND_SWITCH) {
2146                      // Only SWITCH dispatch method use it
2147                        out($f,"zend_vm_continue:".$m[3]."\n");
2148                    } else {
2149                        skip_blanks($f, $m[1], $m[3]);
2150                    }
2151                    break;
2152                case "ZEND_VM_DISPATCH":
2153                  // Emit code that dispatches to opcode handler
2154                    switch ($kind) {
2155                        case ZEND_VM_KIND_SWITCH:
2156                            out($f, $m[1]."dispatch_handler = OPLINE->handler;\nzend_vm_dispatch:\n".$m[1]."switch ((int)(uintptr_t)dispatch_handler)".$m[3]."\n");
2157                            break;
2158                        case ZEND_VM_KIND_GOTO:
2159                            out($f, $m[1]."goto *(void**)(OPLINE->handler);".$m[3]."\n");
2160                            break;
2161                        case ZEND_VM_KIND_HYBRID:
2162                            out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
2163                            out($f, $m[1]."HYBRID_SWITCH()".$m[3]."\n");
2164                            out($f,"#else\n");
2165                        case ZEND_VM_KIND_CALL:
2166                            out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n");
2167                            out($f, $m[1]."((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
2168                            out($f, $m[1]."if (UNEXPECTED(!OPLINE))".$m[3]."\n");
2169                            out($f,"#else\n");
2170                            out($f, $m[1]."if (UNEXPECTED((ret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) != 0))".$m[3]."\n");
2171                            out($f,"#endif\n");
2172                            if ($kind == ZEND_VM_KIND_HYBRID) {
2173                                out($f,"#endif\n");
2174                            }
2175                            break;
2176                    }
2177                    break;
2178                case "INTERNAL_EXECUTOR":
2179                    if ($kind != ZEND_VM_KIND_CALL) {
2180                        // Emit executor code
2181                        if ($kind == ZEND_VM_KIND_HYBRID) {
2182                            out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
2183                        }
2184                        gen_executor_code($f, $spec, $kind, $m[1], $switch_labels);
2185                    }
2186                    if ($kind == ZEND_VM_KIND_CALL || $kind == ZEND_VM_KIND_HYBRID) {
2187                        // Executor is defined as a set of functions
2188                        if ($kind == ZEND_VM_KIND_HYBRID) {
2189                            out($f,"#else\n");
2190                        }
2191                        out($f,
2192                                "#ifdef ZEND_VM_FP_GLOBAL_REG\n" .
2193                                $m[1]."execute_data = vm_stack_data.orig_execute_data;\n" .
2194                                "# ifdef ZEND_VM_IP_GLOBAL_REG\n" .
2195                                $m[1]."opline = vm_stack_data.orig_opline;\n" .
2196                                "# endif\n" .
2197                                $m[1]."return;\n" .
2198                                "#else\n" .
2199                                $m[1]."if (EXPECTED(ret > 0)) {\n" .
2200                                $m[1]."\texecute_data = EG(current_execute_data);\n".
2201                                $m[1]."\tZEND_VM_LOOP_INTERRUPT_CHECK();\n".
2202                                $m[1]."} else {\n" .
2203                                "# ifdef ZEND_VM_IP_GLOBAL_REG\n" .
2204                                $m[1]."\topline = vm_stack_data.orig_opline;\n" .
2205                                "# endif\n".
2206                                $m[1]."\treturn;\n".
2207                                $m[1]."}\n".
2208                                "#endif\n");
2209                        if ($kind == ZEND_VM_KIND_HYBRID) {
2210                            out($f,"#endif\n");
2211                        }
2212                    }
2213                    break;
2214                case "EXTERNAL_EXECUTOR":
2215                    if ($kind == ZEND_VM_KIND_CALL) {
2216                        gen_executor_code($f, $spec, $kind, $m[1]);
2217                    }
2218                    break;
2219                case "INITIALIZER_NAME":
2220                    out($f, $m[1].$initializer_name.$m[3]."\n");
2221                    break;
2222                case "EXTERNAL_LABELS":
2223                  // Emit code that initializes zend_opcode_handlers array
2224                    $prolog = $m[1];
2225                    if ($kind == ZEND_VM_KIND_GOTO) {
2226                      // Labels are defined in the executor itself, so we call it
2227                      // with execute_data NULL and it sets zend_opcode_handlers array
2228                        out($f,$prolog."static const uint32_t specs[] = {\n");
2229                        gen_specs($f, $prolog."\t", $specs);
2230                        out($f,$prolog."};\n");
2231                        out($f,$prolog."zend_spec_handlers = specs;\n");
2232                        out($f,$prolog.$executor_name."_ex(NULL);\n");
2233                    } else {
2234                        out($f,$prolog."static const void * const labels[] = {\n");
2235                        gen_labels($f, $spec, ($kind == ZEND_VM_KIND_HYBRID) ? ZEND_VM_KIND_CALL : $kind, $prolog."\t", $specs, $switch_labels);
2236                        out($f,$prolog."};\n");
2237                        out($f,$prolog."static const uint32_t specs[] = {\n");
2238                        gen_specs($f, $prolog."\t", $specs);
2239                        out($f,$prolog."};\n");
2240                        if ($kind == ZEND_VM_KIND_HYBRID) {
2241                            out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
2242                            out($f,$prolog."zend_opcode_handler_funcs = labels;\n");
2243                            out($f,$prolog."zend_spec_handlers = specs;\n");
2244                            out($f,$prolog.$executor_name."_ex(NULL);\n");
2245                            out($f,"#else\n");
2246                        }
2247                        out($f,$prolog."zend_opcode_handlers = labels;\n");
2248                        out($f,$prolog."zend_handlers_count = sizeof(labels) / sizeof(void*);\n");
2249                        out($f,$prolog."zend_spec_handlers = specs;\n");
2250                        if ($kind == ZEND_VM_KIND_HYBRID) {
2251                            out($f,"#endif\n");
2252                        }
2253                    }
2254                    break;
2255                default:
2256                    die("ERROR: Unknown keyword ".$m[2]." in skeleton file.\n");
2257            }
2258        } else {
2259          // Copy the line as is
2260            out($f, $line);
2261        }
2262    }
2263}
2264
2265function parse_operand_spec($def, $lineno, $str, &$flags) {
2266    global $vm_op_decode;
2267
2268    $flags = 0;
2269    $a = explode("|",$str);
2270    foreach($a as $val) {
2271        if (isset($vm_op_decode[$val])) {
2272            $flags |= $vm_op_decode[$val];
2273        } else {
2274            die("ERROR ($def:$lineno): Wrong operand type '$str'\n");
2275        }
2276    }
2277    if (!($flags & ZEND_VM_OP_SPEC)) {
2278        if (count($a) != 1) {
2279            die("ERROR ($def:$lineno): Wrong operand type '$str'\n");
2280        }
2281        $a = array("ANY");
2282    }
2283    return array_flip($a);
2284}
2285
2286function parse_ext_spec($def, $lineno, $str) {
2287    global $vm_ext_decode;
2288
2289    $flags = 0;
2290    $a = explode("|",$str);
2291    foreach($a as $val) {
2292        if (isset($vm_ext_decode[$val])) {
2293            $flags |= $vm_ext_decode[$val];
2294        } else {
2295            die("ERROR ($def:$lineno): Wrong extended_value type '$str'\n");
2296        }
2297    }
2298    return $flags;
2299}
2300
2301function parse_spec_rules($def, $lineno, $str) {
2302    global $used_extra_spec;
2303
2304    $ret = array();
2305    $a = explode(",", $str);
2306    foreach($a as $rule) {
2307        $n = strpos($rule, "=");
2308        if ($n !== false) {
2309            $id = trim(substr($rule, 0, $n));
2310            $val = trim(substr($rule, $n+1));
2311            switch ($id) {
2312                case "OP_DATA":
2313                    $ret["OP_DATA"] = parse_operand_spec($def, $lineno, $val, $devnull);
2314                    break;
2315                default:
2316                    die("ERROR ($def:$lineno): Wrong specialization rules '$str'\n");
2317            }
2318            $used_extra_spec[$id] = 1;
2319        } else {
2320            switch ($rule) {
2321                case "RETVAL":
2322                    $ret["RETVAL"] = array(0, 1);
2323                    break;
2324                case "QUICK_ARG":
2325                    $ret["QUICK_ARG"] = array(0, 1);
2326                    break;
2327                case "SMART_BRANCH":
2328                    $ret["SMART_BRANCH"] = array(0, 1, 2);
2329                    break;
2330                case "NO_CONST_CONST":
2331                    $ret["NO_CONST_CONST"] = array(1);
2332                    break;
2333                case "COMMUTATIVE":
2334                    $ret["COMMUTATIVE"] = array(1);
2335                    break;
2336                case "ISSET":
2337                    $ret["ISSET"] = array(0, 1);
2338                    break;
2339                case "OBSERVER":
2340                    $ret["OBSERVER"] = array(0, 1);
2341                    break;
2342                default:
2343                    die("ERROR ($def:$lineno): Wrong specialization rules '$str'\n");
2344            }
2345            $used_extra_spec[$rule] = 1;
2346        }
2347    }
2348    return $ret;
2349}
2350
2351function gen_vm($def, $skel) {
2352    global $definition_file, $skeleton_file, $executor_file,
2353        $op_types, $list, $opcodes, $helpers, $params, $opnames,
2354        $vm_op_flags, $used_extra_spec;
2355
2356    // Load definition file
2357    $in = @file($def);
2358    if (!$in) {
2359        die("ERROR: Can not open definition file '$def'\n");
2360    }
2361    // We need absolute path to definition file to use it in #line directives
2362    $definition_file = realpath($def);
2363
2364    // Load skeleton file
2365    $skl = @file($skel);
2366    if (!$skl) {
2367        die("ERROR: Can not open skeleton file '$skel'\n");
2368    }
2369    // We need absolute path to skeleton file to use it in #line directives
2370    $skeleton_file = realpath($skel);
2371
2372    // Parse definition file into tree
2373    $lineno         = 0;
2374    $handler        = null;
2375    $helper         = null;
2376    $max_opcode_len = 0;
2377    $max_opcode     = 0;
2378    $extra_num      = 256;
2379    foreach ($in as $line) {
2380        ++$lineno;
2381        if (strpos($line,"ZEND_VM_HANDLER(") === 0 ||
2382            strpos($line,"ZEND_VM_INLINE_HANDLER(") === 0 ||
2383            strpos($line,"ZEND_VM_HOT_HANDLER(") === 0 ||
2384            strpos($line,"ZEND_VM_HOT_NOCONST_HANDLER(") === 0 ||
2385            strpos($line,"ZEND_VM_HOT_NOCONSTCONST_HANDLER(") === 0 ||
2386            strpos($line,"ZEND_VM_HOT_SEND_HANDLER(") === 0 ||
2387            strpos($line,"ZEND_VM_HOT_OBJ_HANDLER(") === 0 ||
2388            strpos($line,"ZEND_VM_COLD_HANDLER(") === 0 ||
2389            strpos($line,"ZEND_VM_COLD_CONST_HANDLER(") === 0 ||
2390            strpos($line,"ZEND_VM_COLD_CONSTCONST_HANDLER(") === 0) {
2391          // Parsing opcode handler's definition
2392            if (preg_match(
2393                    "/^ZEND_VM_(HOT_|INLINE_|HOT_OBJ_|HOT_SEND_|HOT_NOCONST_|HOT_NOCONSTCONST_|COLD_|COLD_CONST_|COLD_CONSTCONST_)?HANDLER\(\s*([0-9]+)\s*,\s*([A-Z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(,\s*([A-Z_|]+)\s*)?(,\s*SPEC\(([A-Z_|=,]+)\)\s*)?\)/",
2394                    $line,
2395                    $m) == 0) {
2396                die("ERROR ($def:$lineno): Invalid ZEND_VM_HANDLER definition.\n");
2397            }
2398            $hot = !empty($m[1]) ? $m[1] : false;
2399            $code = (int)$m[2];
2400            $op   = $m[3];
2401            $len  = strlen($op);
2402            $op1  = parse_operand_spec($def, $lineno, $m[4], $flags1);
2403            $op2  = parse_operand_spec($def, $lineno, $m[5], $flags2);
2404            $flags = $flags1 | ($flags2 << 8);
2405            if (!empty($m[7])) {
2406                $flags |= parse_ext_spec($def, $lineno, $m[7]);
2407            }
2408
2409            if ($len > $max_opcode_len) {
2410                $max_opcode_len = $len;
2411            }
2412            if ($code > $max_opcode) {
2413                $max_opcode = $code;
2414            }
2415            if (isset($opcodes[$code])) {
2416                die("ERROR ($def:$lineno): Opcode with code '$code' is already defined.\n");
2417            }
2418            if (isset($opnames[$op])) {
2419                die("ERROR ($def:$lineno): Opcode with name '$op' is already defined.\n");
2420            }
2421            $opcodes[$code] = array("op"=>$op,"op1"=>$op1,"op2"=>$op2,"code"=>"","flags"=>$flags,"hot"=>$hot);
2422            if (isset($m[9])) {
2423                $opcodes[$code]["spec"] = parse_spec_rules($def, $lineno, $m[9]);
2424                if (isset($opcodes[$code]["spec"]["NO_CONST_CONST"])) {
2425                    $opcodes[$code]["flags"] |= $vm_op_flags["ZEND_VM_NO_CONST_CONST"];
2426                }
2427                if (isset($opcodes[$code]["spec"]["COMMUTATIVE"])) {
2428                    $opcodes[$code]["flags"] |= $vm_op_flags["ZEND_VM_COMMUTATIVE"];
2429                }
2430            }
2431            $opnames[$op] = $code;
2432            $handler = $code;
2433            $helper = null;
2434            $list[$lineno] = array("handler"=>$handler);
2435        } else if (strpos($line,"ZEND_VM_TYPE_SPEC_HANDLER(") === 0 ||
2436                   strpos($line,"ZEND_VM_INLINE_TYPE_SPEC_HANDLER(") === 0 ||
2437                   strpos($line,"ZEND_VM_HOT_TYPE_SPEC_HANDLER(") === 0 ||
2438                   strpos($line,"ZEND_VM_HOT_NOCONST_TYPE_SPEC_HANDLER(") === 0 ||
2439                   strpos($line,"ZEND_VM_HOT_NOCONSTCONST_TYPE_SPEC_HANDLER(") === 0 ||
2440                   strpos($line,"ZEND_VM_HOT_SEND_TYPE_SPEC_HANDLER(") === 0 ||
2441                   strpos($line,"ZEND_VM_HOT_OBJ_TYPE_SPEC_HANDLER(") === 0) {
2442          // Parsing opcode handler's definition
2443            if (preg_match(
2444                    "/^ZEND_VM_(HOT_|INLINE_|HOT_OBJ_|HOT_SEND_|HOT_NOCONST_|HOT_NOCONSTCONST_)?TYPE_SPEC_HANDLER\(\s*([A-Z_|]+)\s*,\s*((?:[^(,]|\([^()]*|(?R)*\))*),\s*([A-Za-z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(,\s*([A-Z_|]+)\s*)?(,\s*SPEC\(([A-Z_|=,]+)\)\s*)?\)/",
2445                    $line,
2446                    $m) == 0) {
2447                die("ERROR ($def:$lineno): Invalid ZEND_VM_TYPE_HANDLER_HANDLER definition.\n");
2448            }
2449            $hot = !empty($m[1]) ? $m[1] : false;
2450            $orig_op_list = $m[2];
2451            $code = $extra_num++;
2452            foreach (explode('|', $orig_op_list) as $orig_op) {
2453                if (!isset($opnames[$orig_op])) {
2454                    die("ERROR ($def:$lineno): Opcode with name '$orig_op' is not defined.\n");
2455                }
2456                $orig_code = $opnames[$orig_op];
2457                $condition = $m[3];
2458                $opcodes[$orig_code]['type_spec'][$code] = $condition;
2459            }
2460            $op = $m[4];
2461            $op1  = parse_operand_spec($def, $lineno, $m[5], $flags1);
2462            $op2  = parse_operand_spec($def, $lineno, $m[6], $flags2);
2463            $flags = $flags1 | ($flags2 << 8);
2464            if (!empty($m[8])) {
2465                $flags |= parse_ext_spec($def, $lineno, $m[8]);
2466            }
2467
2468            if (isset($opcodes[$code])) {
2469                die("ERROR ($def:$lineno): Opcode with name '$code' is already defined.\n");
2470            }
2471            $used_extra_spec["TYPE"] = 1;
2472            $opcodes[$code] = array("op"=>$op,"op1"=>$op1,"op2"=>$op2,"code"=>"","flags"=>$flags,"hot"=>$hot,"is_type_spec"=>true);
2473            if (isset($m[10])) {
2474                $opcodes[$code]["spec"] = parse_spec_rules($def, $lineno, $m[10]);
2475                if (isset($opcodes[$code]["spec"]["NO_CONST_CONST"])) {
2476                    $opcodes[$code]["flags"] |= $vm_op_flags["ZEND_VM_NO_CONST_CONST"];
2477                }
2478                if (isset($opcodes[$code]["spec"]["COMMUTATIVE"])) {
2479                    $opcodes[$code]["flags"] |= $vm_op_flags["ZEND_VM_COMMUTATIVE"];
2480                }
2481            }
2482            $opnames[$op] = $code;
2483            $handler = $code;
2484            $helper = null;
2485            $list[$lineno] = array("handler"=>$handler);
2486        } else if (strpos($line,"ZEND_VM_HELPER(") === 0 ||
2487                   strpos($line,"ZEND_VM_INLINE_HELPER(") === 0 ||
2488                   strpos($line,"ZEND_VM_COLD_HELPER(") === 0 ||
2489                   strpos($line,"ZEND_VM_HOT_HELPER(") === 0) {
2490          // Parsing helper's definition
2491            if (preg_match(
2492                    "/^ZEND_VM(_INLINE|_COLD|_HOT)?_HELPER\(\s*([A-Za-z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(?:,\s*SPEC\(([A-Z_|=,]+)\)\s*)?(?:,\s*([^)]*)\s*)?\)/",
2493                    $line,
2494                    $m) == 0) {
2495                die("ERROR ($def:$lineno): Invalid ZEND_VM_HELPER definition.\n");
2496            }
2497            $inline = !empty($m[1]) && $m[1] === "_INLINE";
2498            $cold   = !empty($m[1]) && $m[1] === "_COLD";
2499            $hot    = !empty($m[1]) && $m[1] === "_HOT";
2500            $helper = $m[2];
2501            $op1    = parse_operand_spec($def, $lineno, $m[3], $flags1);
2502            $op2    = parse_operand_spec($def, $lineno, $m[4], $flags2);
2503            $param  = isset($m[6]) ? $m[6] : null;
2504            if (isset($helpers[$helper])) {
2505                die("ERROR ($def:$lineno): Helper with name '$helper' is already defined.\n");
2506            }
2507
2508            // Store parameters
2509            if (ZEND_VM_KIND == ZEND_VM_KIND_GOTO
2510             || ZEND_VM_KIND == ZEND_VM_KIND_SWITCH
2511             || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID && $hot)) {
2512                foreach (explode(",", $param) as $p) {
2513                    $p = trim($p);
2514                    if ($p !== "") {
2515                        $params[$p] = 1;
2516                    }
2517                }
2518            }
2519
2520            $helpers[$helper] = array("op1"=>$op1,"op2"=>$op2,"param"=>$param,"code"=>"","inline"=>$inline,"cold"=>$cold,"hot"=>$hot);
2521
2522            if (!empty($m[5])) {
2523                $helpers[$helper]["spec"] = parse_spec_rules($def, $lineno, $m[5]);
2524            }
2525
2526            $handler = null;
2527            $list[$lineno] = array("helper"=>$helper);
2528        } else if (strpos($line,"ZEND_VM_DEFINE_OP(") === 0) {
2529            if (preg_match(
2530                    "/^ZEND_VM_DEFINE_OP\(\s*([0-9]+)\s*,\s*([A-Z_]+)\s*\);/",
2531                    $line,
2532                    $m) == 0) {
2533                die("ERROR ($def:$lineno): Invalid ZEND_VM_DEFINE_OP definition.\n");
2534            }
2535            $code = (int)$m[1];
2536            $op   = $m[2];
2537            $len  = strlen($op);
2538
2539            if ($len > $max_opcode_len) {
2540                $max_opcode_len = $len;
2541            }
2542            if ($code > $max_opcode) {
2543                $max_opcode = $code;
2544            }
2545            if (isset($opcodes[$code])) {
2546                die("ERROR ($def:$lineno): Opcode with code '$code' is already defined.\n");
2547            }
2548            if (isset($opnames[$op])) {
2549                die("ERROR ($def:$lineno): Opcode with name '$op' is already defined.\n");
2550            }
2551            $opcodes[$code] = array("op"=>$op,"code"=>"");
2552            $opnames[$op] = $code;
2553        } else if ($handler !== null) {
2554          // Add line of code to current opcode handler
2555            $opcodes[$handler]["code"] .= $line;
2556        } else if ($helper !== null) {
2557          // Add line of code to current helper
2558            $helpers[$helper]["code"] .= $line;
2559        }
2560    }
2561
2562    ksort($opcodes);
2563
2564    // Search for opcode handlers those are used by other opcode handlers
2565    foreach ($opcodes as $dsc) {
2566        if (preg_match("/^\s*{\s*ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)\s*;\s*}\s*/", $dsc["code"], $m)) {
2567            $op = $m[1];
2568            if (!isset($opnames[$op])) {
2569                die("ERROR ($def:$lineno): Opcode with name '$op' is not defined.\n");
2570            }
2571            $opcodes[$opnames[$dsc['op']]]['alias'] = $op;
2572            if (!ZEND_VM_SPEC && ZEND_VM_KIND == ZEND_VM_KIND_SWITCH) {
2573                $code = $opnames[$op];
2574                $opcodes[$code]['use'] = 1;
2575            }
2576        } else if (preg_match_all("/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m", $dsc["code"], $mm, PREG_SET_ORDER)) {
2577            foreach ($mm as $m) {
2578                $op = $m[1];
2579                if (!isset($opnames[$op])) {
2580                    die("ERROR ($def:$lineno): Opcode with name '$op' is not defined.\n");
2581                }
2582                $code = $opnames[$op];
2583                $opcodes[$code]['use'] = 1;
2584            }
2585        }
2586    }
2587
2588    // Generate opcode #defines (zend_vm_opcodes.h)
2589    $code_len = strlen((string)$max_opcode);
2590    $f = fopen(__DIR__ . "/zend_vm_opcodes.h", "w+") or die("ERROR: Cannot create zend_vm_opcodes.h\n");
2591
2592    // Insert header
2593    out($f, HEADER_TEXT);
2594    fputs($f, "#ifndef ZEND_VM_OPCODES_H\n#define ZEND_VM_OPCODES_H\n\n");
2595    fputs($f, "#define ZEND_VM_SPEC\t\t" . ZEND_VM_SPEC . "\n");
2596    fputs($f, "#define ZEND_VM_LINES\t\t" . ZEND_VM_LINES . "\n");
2597    fputs($f, "#define ZEND_VM_KIND_CALL\t" . ZEND_VM_KIND_CALL . "\n");
2598    fputs($f, "#define ZEND_VM_KIND_SWITCH\t" . ZEND_VM_KIND_SWITCH . "\n");
2599    fputs($f, "#define ZEND_VM_KIND_GOTO\t" . ZEND_VM_KIND_GOTO . "\n");
2600    fputs($f, "#define ZEND_VM_KIND_HYBRID\t" . ZEND_VM_KIND_HYBRID . "\n");
2601    if ($GLOBALS["vm_kind_name"][ZEND_VM_KIND] === "ZEND_VM_KIND_HYBRID") {
2602        fputs($f, "/* HYBRID requires support for computed GOTO and global register variables*/\n");
2603        fputs($f, "#if (defined(__GNUC__) && defined(HAVE_GCC_GLOBAL_REGS))\n");
2604        fputs($f, "# define ZEND_VM_KIND\t\tZEND_VM_KIND_HYBRID\n");
2605        fputs($f, "#else\n");
2606        fputs($f, "# define ZEND_VM_KIND\t\tZEND_VM_KIND_CALL\n");
2607        fputs($f, "#endif\n");
2608    } else {
2609        fputs($f, "#define ZEND_VM_KIND\t\t" . $GLOBALS["vm_kind_name"][ZEND_VM_KIND] . "\n");
2610    }
2611    fputs($f, "\n");
2612    fputs($f, "#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) && !defined(__SANITIZE_ADDRESS__)\n");
2613    fputs($f, "# if ((defined(i386) && !defined(__PIC__)) || defined(__x86_64__) || defined(_M_X64))\n");
2614    fputs($f, "#  define ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE 16\n");
2615    fputs($f, "# endif\n");
2616    fputs($f, "#endif\n");
2617    fputs($f, "\n");
2618    foreach($vm_op_flags as $name => $val) {
2619        fprintf($f, "#define %-24s 0x%08x\n", $name, $val);
2620    }
2621    fputs($f, "#define ZEND_VM_OP1_FLAGS(flags) (flags & 0xff)\n");
2622    fputs($f, "#define ZEND_VM_OP2_FLAGS(flags) ((flags >> 8) & 0xff)\n");
2623    fputs($f, "\n");
2624    fputs($f, "BEGIN_EXTERN_C()\n\n");
2625    fputs($f, "ZEND_API const char* ZEND_FASTCALL zend_get_opcode_name(zend_uchar opcode);\n");
2626    fputs($f, "ZEND_API uint32_t ZEND_FASTCALL zend_get_opcode_flags(zend_uchar opcode);\n\n");
2627    fputs($f, "END_EXTERN_C()\n\n");
2628
2629    foreach ($opcodes as $code => $dsc) {
2630        $code = str_pad((string)$code,$code_len," ",STR_PAD_LEFT);
2631        $op = str_pad($dsc["op"],$max_opcode_len);
2632        if ($code <= $max_opcode) {
2633            fputs($f,"#define $op $code\n");
2634        }
2635    }
2636
2637    $code = str_pad((string)$max_opcode,$code_len," ",STR_PAD_LEFT);
2638    $op = str_pad("ZEND_VM_LAST_OPCODE",$max_opcode_len);
2639    fputs($f,"\n#define $op $code\n");
2640
2641    fputs($f, "\n#endif\n");
2642    fclose($f);
2643    echo "zend_vm_opcodes.h generated successfully.\n";
2644
2645    // zend_vm_opcodes.c
2646    $f = fopen(__DIR__ . "/zend_vm_opcodes.c", "w+") or die("ERROR: Cannot create zend_vm_opcodes.c\n");
2647
2648    // Insert header
2649    out($f, HEADER_TEXT);
2650    fputs($f,"#include <stdio.h>\n");
2651    fputs($f,"#include <zend.h>\n");
2652    fputs($f,"#include <zend_vm_opcodes.h>\n\n");
2653
2654    fputs($f,"static const char *zend_vm_opcodes_names[".($max_opcode + 1)."] = {\n");
2655    for ($i = 0; $i <= $max_opcode; $i++) {
2656        fputs($f,"\t".(isset($opcodes[$i]["op"])?'"'.$opcodes[$i]["op"].'"':"NULL").",\n");
2657    }
2658    fputs($f, "};\n\n");
2659
2660    fputs($f,"static uint32_t zend_vm_opcodes_flags[".($max_opcode + 1)."] = {\n");
2661    for ($i = 0; $i <= $max_opcode; $i++) {
2662        fprintf($f, "\t0x%08x,\n", isset($opcodes[$i]["flags"]) ? $opcodes[$i]["flags"] : 0);
2663    }
2664    fputs($f, "};\n\n");
2665
2666    fputs($f, "ZEND_API const char* ZEND_FASTCALL zend_get_opcode_name(zend_uchar opcode) {\n");
2667    fputs($f, "\tif (UNEXPECTED(opcode > ZEND_VM_LAST_OPCODE)) {\n");
2668    fputs($f, "\t\treturn NULL;\n");
2669    fputs($f, "\t}\n");
2670    fputs($f, "\treturn zend_vm_opcodes_names[opcode];\n");
2671    fputs($f, "}\n");
2672
2673    fputs($f, "ZEND_API uint32_t ZEND_FASTCALL zend_get_opcode_flags(zend_uchar opcode) {\n");
2674    fputs($f, "\tif (UNEXPECTED(opcode > ZEND_VM_LAST_OPCODE)) {\n");
2675    fputs($f, "\t\topcode = ZEND_NOP;\n");
2676    fputs($f, "\t}\n");
2677    fputs($f, "\treturn zend_vm_opcodes_flags[opcode];\n");
2678    fputs($f, "}\n");
2679
2680    fclose($f);
2681    echo "zend_vm_opcodes.c generated successfully.\n";
2682
2683    // Generate zend_vm_execute.h
2684    $f = fopen(__DIR__ . "/zend_vm_execute.h", "w+") or die("ERROR: Cannot create zend_vm_execute.h\n");
2685    $executor_file = realpath(__DIR__ . "/zend_vm_execute.h");
2686
2687    // Insert header
2688    out($f, HEADER_TEXT);
2689
2690    out($f, "#ifdef ZEND_WIN32\n");
2691    // Suppress free_op1 warnings on Windows
2692    out($f, "# pragma warning(disable : 4101)\n");
2693    if (ZEND_VM_SPEC) {
2694        // Suppress (<non-zero constant> || <expression>) warnings on windows
2695        out($f, "# pragma warning(once : 6235)\n");
2696        // Suppress (<zero> && <expression>) warnings on windows
2697        out($f, "# pragma warning(once : 6237)\n");
2698        // Suppress (<non-zero constant> && <expression>) warnings on windows
2699        out($f, "# pragma warning(once : 6239)\n");
2700        // Suppress (<expression> && <non-zero constant>) warnings on windows
2701        out($f, "# pragma warning(once : 6240)\n");
2702        // Suppress (<non-zero constant> || <non-zero constant>) warnings on windows
2703        out($f, "# pragma warning(once : 6285)\n");
2704        // Suppress (<non-zero constant> || <expression>) warnings on windows
2705        out($f, "# pragma warning(once : 6286)\n");
2706        // Suppress constant with constant comparison warnings on windows
2707        out($f, "# pragma warning(once : 6326)\n");
2708    }
2709    out($f, "#endif\n");
2710
2711    // Support for ZEND_USER_OPCODE
2712    out($f, "static user_opcode_handler_t zend_user_opcode_handlers[256] = {\n");
2713    for ($i = 0; $i < 255; ++$i) {
2714        out($f, "\t(user_opcode_handler_t)NULL,\n");
2715    }
2716    out($f, "\t(user_opcode_handler_t)NULL\n};\n\n");
2717
2718    out($f, "static zend_uchar zend_user_opcodes[256] = {");
2719    for ($i = 0; $i < 255; ++$i) {
2720        if ($i % 16 == 1) out($f, "\n\t");
2721        out($f, "$i,");
2722    }
2723    out($f, "255\n};\n\n");
2724
2725    // Generate specialized executor
2726    gen_executor($f, $skl, ZEND_VM_SPEC, ZEND_VM_KIND, "execute", "zend_vm_init");
2727    out($f, "\n");
2728
2729    // Generate zend_vm_get_opcode_handler() function
2730    out($f, "static uint32_t ZEND_FASTCALL zend_vm_get_opcode_handler_idx(uint32_t spec, const zend_op* op)\n");
2731    out($f, "{\n");
2732    if (!ZEND_VM_SPEC) {
2733        out($f, "\treturn spec;\n");
2734    } else {
2735        out($f, "\tstatic const int zend_vm_decode[] = {\n");
2736        out($f, "\t\t_UNUSED_CODE, /* 0 = IS_UNUSED  */\n");
2737        out($f, "\t\t_CONST_CODE,  /* 1 = IS_CONST   */\n");
2738        out($f, "\t\t_TMP_CODE,    /* 2 = IS_TMP_VAR */\n");
2739        out($f, "\t\t_UNUSED_CODE, /* 3              */\n");
2740        out($f, "\t\t_VAR_CODE,    /* 4 = IS_VAR     */\n");
2741        out($f, "\t\t_UNUSED_CODE, /* 5              */\n");
2742        out($f, "\t\t_UNUSED_CODE, /* 6              */\n");
2743        out($f, "\t\t_UNUSED_CODE, /* 7              */\n");
2744        out($f, "\t\t_CV_CODE      /* 8 = IS_CV      */\n");
2745        out($f, "\t};\n");
2746        out($f, "\tuint32_t offset = 0;\n");
2747        out($f, "\tif (spec & SPEC_RULE_OP1) offset = offset * 5 + zend_vm_decode[op->op1_type];\n");
2748        out($f, "\tif (spec & SPEC_RULE_OP2) offset = offset * 5 + zend_vm_decode[op->op2_type];\n");
2749
2750        if (isset($used_extra_spec["OP_DATA"]) ||
2751            isset($used_extra_spec["RETVAL"]) ||
2752            isset($used_extra_spec["QUICK_ARG"]) ||
2753            isset($used_extra_spec["SMART_BRANCH"]) ||
2754            isset($used_extra_spec["ISSET"]) ||
2755            isset($used_extra_spec["OBSERVER"])) {
2756
2757            $else = "";
2758            out($f, "\tif (spec & SPEC_EXTRA_MASK) {\n");
2759
2760            if (isset($used_extra_spec["RETVAL"])) {
2761                out($f, "\t\t{$else}if (spec & SPEC_RULE_RETVAL) {\n");
2762                out($f, "\t\t\toffset = offset * 2 + (op->result_type != IS_UNUSED);\n");
2763                out($f, "\t\t\tif ((spec & SPEC_RULE_OBSERVER) && ZEND_OBSERVER_ENABLED) {\n");
2764                out($f,	"\t\t\t\toffset += 2;\n");
2765                out($f, "\t\t\t}\n");
2766                $else = "} else ";
2767            }
2768            if (isset($used_extra_spec["QUICK_ARG"])) {
2769                out($f, "\t\t{$else}if (spec & SPEC_RULE_QUICK_ARG) {\n");
2770                out($f, "\t\t\toffset = offset * 2 + (op->op2.num <= MAX_ARG_FLAG_NUM);\n");
2771                $else = "} else ";
2772            }
2773            if (isset($used_extra_spec["OP_DATA"])) {
2774                out($f, "\t\t{$else}if (spec & SPEC_RULE_OP_DATA) {\n");
2775                out($f, "\t\t\toffset = offset * 5 + zend_vm_decode[(op + 1)->op1_type];\n");
2776                $else = "} else ";
2777            }
2778            if (isset($used_extra_spec["ISSET"])) {
2779                out($f, "\t\t{$else}if (spec & SPEC_RULE_ISSET) {\n");
2780                out($f, "\t\t\toffset = offset * 2 + (op->extended_value & ZEND_ISEMPTY);\n");
2781                $else = "} else ";
2782            }
2783            if (isset($used_extra_spec["SMART_BRANCH"])) {
2784                out($f, "\t\t{$else}if (spec & SPEC_RULE_SMART_BRANCH) {\n");
2785                out($f,	"\t\t\toffset = offset * 3;\n");
2786                out($f, "\t\t\tif (op->result_type == (IS_SMART_BRANCH_JMPZ|IS_TMP_VAR)) {\n");
2787                out($f,	"\t\t\t\toffset += 1;\n");
2788                out($f, "\t\t\t} else if (op->result_type == (IS_SMART_BRANCH_JMPNZ|IS_TMP_VAR)) {\n");
2789                out($f,	"\t\t\t\toffset += 2;\n");
2790                out($f, "\t\t\t}\n");
2791                $else = "} else ";
2792            }
2793            if (isset($used_extra_spec["OBSERVER"])) {
2794                out($f, "\t\t{$else}if (spec & SPEC_RULE_OBSERVER) {\n");
2795                out($f,	"\t\t\toffset = offset * 2;\n");
2796                out($f, "\t\t\tif (ZEND_OBSERVER_ENABLED) {\n");
2797                out($f,	"\t\t\t\toffset += 1;\n");
2798                out($f, "\t\t\t}\n");
2799                $else = "} else ";
2800            }
2801            if ($else !== "") {
2802                out($f, "\t\t}\n");
2803            }
2804            out($f, "\t}\n");
2805        }
2806        out($f, "\treturn (spec & SPEC_START_MASK) + offset;\n");
2807    }
2808    out($f, "}\n\n");
2809    out($f, "#if (ZEND_VM_KIND != ZEND_VM_KIND_HYBRID) || !ZEND_VM_SPEC\n");
2810    out($f, "static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op)\n");
2811    out($f, "{\n");
2812    if (!ZEND_VM_SPEC) {
2813        out($f, "\treturn zend_opcode_handlers[zend_vm_get_opcode_handler_idx(opcode, op)];\n");
2814    } else {
2815        out($f, "\treturn zend_opcode_handlers[zend_vm_get_opcode_handler_idx(zend_spec_handlers[opcode], op)];\n");
2816    }
2817    out($f, "}\n");
2818    out($f, "#endif\n\n");
2819
2820    if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) {
2821        // Generate zend_vm_get_opcode_handler_func() function
2822        out($f, "#if ZEND_VM_KIND == ZEND_VM_KIND_HYBRID\n");
2823        out($f,"static const void *zend_vm_get_opcode_handler_func(zend_uchar opcode, const zend_op* op)\n");
2824        out($f, "{\n");
2825        out($f, "\tuint32_t spec = zend_spec_handlers[opcode];\n");
2826        if (!ZEND_VM_SPEC) {
2827            out($f, "\treturn zend_opcode_handler_funcs[spec];\n");
2828        } else {
2829            out($f, "\treturn zend_opcode_handler_funcs[zend_vm_get_opcode_handler_idx(spec, op)];\n");
2830        }
2831        out($f, "}\n\n");
2832        out($f, "#endif\n\n");
2833    }
2834
2835    // Generate zend_vm_get_opcode_handler() function
2836    out($f, "ZEND_API void ZEND_FASTCALL zend_vm_set_opcode_handler(zend_op* op)\n");
2837    out($f, "{\n");
2838    out($f, "\tzend_uchar opcode = zend_user_opcodes[op->opcode];\n");
2839    if (!ZEND_VM_SPEC) {
2840        out($f, "\top->handler = zend_opcode_handlers[zend_vm_get_opcode_handler_idx(opcode, op)];\n");
2841    } else {
2842        out($f, "\n");
2843        out($f, "\tif (zend_spec_handlers[op->opcode] & SPEC_RULE_COMMUTATIVE) {\n");
2844        out($f, "\t\tif (op->op1_type < op->op2_type) {\n");
2845        out($f, "\t\t\tzend_swap_operands(op);\n");
2846        out($f, "\t\t}\n");
2847        out($f, "\t}\n");
2848        out($f, "\top->handler = zend_opcode_handlers[zend_vm_get_opcode_handler_idx(zend_spec_handlers[opcode], op)];\n");
2849    }
2850    out($f, "}\n\n");
2851
2852    // Generate zend_vm_set_opcode_handler_ex() function
2853    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");
2854    out($f, "{\n");
2855    out($f, "\tzend_uchar opcode = zend_user_opcodes[op->opcode];\n");
2856    if (!ZEND_VM_SPEC) {
2857        out($f, "\top->handler = zend_opcode_handlers[zend_vm_get_opcode_handler_idx(opcode, op)];\n");
2858    } else {
2859        out($f, "\tuint32_t spec = zend_spec_handlers[opcode];\n");
2860        if (isset($used_extra_spec["TYPE"])) {
2861            out($f, "\tswitch (opcode) {\n");
2862            foreach($opcodes as $code => $dsc) {
2863                if (isset($dsc['type_spec'])) {
2864                    $orig_op = $dsc['op'];
2865                    out($f, "\t\tcase $orig_op:\n");
2866                    if (isset($dsc["spec"]["COMMUTATIVE"])) {
2867                        out($f, "\t\t\tif (op->op1_type < op->op2_type) {\n");
2868                        out($f, "\t\t\t\tzend_swap_operands(op);\n");
2869                        out($f, "\t\t\t}\n");
2870                    }
2871                    $first = true;
2872                    foreach($dsc['type_spec'] as $code => $condition) {
2873                        $condition = format_condition($condition);
2874                        if ($first) {
2875                            out($f, "\t\t\tif $condition {\n");
2876                            $first = false;
2877                        } else {
2878                            out($f, "\t\t\t} else if $condition {\n");
2879                        }
2880                        $spec_dsc = $opcodes[$code];
2881                        if (isset($spec_dsc["spec"]["NO_CONST_CONST"])) {
2882                            out($f, "\t\t\t\tif (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {\n");
2883                            out($f, "\t\t\t\t\tbreak;\n");
2884                            out($f, "\t\t\t\t}\n");
2885                        }
2886                        out($f, "\t\t\t\tspec = ${spec_dsc['spec_code']};\n");
2887                        if (isset($spec_dsc["spec"]["COMMUTATIVE"]) && !isset($dsc["spec"]["COMMUTATIVE"])) {
2888                            out($f, "\t\t\t\tif (op->op1_type < op->op2_type) {\n");
2889                            out($f, "\t\t\t\t\tzend_swap_operands(op);\n");
2890                            out($f, "\t\t\t\t}\n");
2891                        }
2892                    }
2893                    if (!$first) {
2894                        out($f, "\t\t\t}\n");
2895                    }
2896                    out($f, "\t\t\tbreak;\n");
2897                }
2898            }
2899            $has_commutative = false;
2900            foreach($opcodes as $code => $dsc) {
2901                if (!isset($dsc['is_type_spec']) &&
2902                    !isset($dsc['type_spec']) &&
2903                    isset($dsc["spec"]["COMMUTATIVE"])) {
2904                    $orig_op = $dsc['op'];
2905                    out($f, "\t\tcase $orig_op:\n");
2906                    $has_commutative = true;
2907                }
2908            }
2909            if ($has_commutative) {
2910                out($f, "\t\t\tif (op->op1_type < op->op2_type) {\n");
2911                out($f, "\t\t\t\tzend_swap_operands(op);\n");
2912                out($f, "\t\t\t}\n");
2913                out($f, "\t\t\tbreak;\n");
2914                out($f, "\t\tcase ZEND_USER_OPCODE:\n");
2915                out($f, "\t\t\tif (zend_spec_handlers[op->opcode] & SPEC_RULE_COMMUTATIVE) {\n");
2916                out($f, "\t\t\t\tif (op->op1_type < op->op2_type) {\n");
2917                out($f, "\t\t\t\t\tzend_swap_operands(op);\n");
2918                out($f, "\t\t\t\t}\n");
2919                out($f, "\t\t\t}\n");
2920                out($f, "\t\t\tbreak;\n");
2921            }
2922            out($f, "\t\tdefault:\n");
2923            out($f, "\t\t\tbreak;\n");
2924            out($f, "\t}\n");
2925        }
2926        out($f, "\top->handler = zend_opcode_handlers[zend_vm_get_opcode_handler_idx(spec, op)];\n");
2927    }
2928    out($f, "}\n\n");
2929
2930    // Generate zend_vm_call_opcode_handler() function
2931    if (ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) {
2932        out($f, "ZEND_API int ZEND_FASTCALL zend_vm_call_opcode_handler(zend_execute_data* ex)\n");
2933        out($f, "{\n");
2934        if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) {
2935            out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
2936            out($f, "\topcode_handler_t handler;\n");
2937            out($f,"#endif\n");
2938        }
2939        out($f, "\tint ret;\n");
2940        out($f, "#ifdef ZEND_VM_IP_GLOBAL_REG\n");
2941        out($f, "\tconst zend_op *orig_opline = opline;\n");
2942        out($f, "#endif\n");
2943        out($f, "#ifdef ZEND_VM_FP_GLOBAL_REG\n");
2944        out($f, "\tzend_execute_data *orig_execute_data = execute_data;\n");
2945        out($f, "\texecute_data = ex;\n");
2946        out($f, "#else\n");
2947        out($f, "\tzend_execute_data *execute_data = ex;\n");
2948        out($f, "#endif\n");
2949        out($f, "\n");
2950        out($f, "\tLOAD_OPLINE();\n");
2951        out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n");
2952        if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) {
2953            out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
2954            out($f, "\thandler = (opcode_handler_t)zend_vm_get_opcode_handler_func(zend_user_opcodes[opline->opcode], opline);\n");
2955            out($f, "\thandler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
2956            out($f, "\tif (EXPECTED(opline != &hybrid_halt_op)) {\n");
2957            out($f,"#else\n");
2958        }
2959        out($f, "\t((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
2960        if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) {
2961            out($f, "\tif (EXPECTED(opline)) {\n");
2962            out($f,"#endif\n");
2963        } else {
2964            out($f, "\tif (EXPECTED(opline)) {\n");
2965        }
2966        out($f, "\t\tret = execute_data != ex ? (int)(execute_data->prev_execute_data != ex) + 1 : 0;\n");
2967        out($f, "\t\tSAVE_OPLINE();\n");
2968        out($f, "\t} else {\n");
2969        out($f, "\t\tret = -1;\n");
2970        out($f, "\t}\n");
2971        out($f, "#else\n");
2972        out($f, "\tret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
2973        out($f, "\tSAVE_OPLINE();\n");
2974        out($f, "#endif\n");
2975        out($f, "#ifdef ZEND_VM_FP_GLOBAL_REG\n");
2976        out($f, "\texecute_data = orig_execute_data;\n");
2977        out($f, "#endif\n");
2978        out($f, "#ifdef ZEND_VM_IP_GLOBAL_REG\n");
2979        out($f, "\topline = orig_opline;\n");
2980        out($f, "#endif\n");
2981        out($f, "\treturn ret;\n");
2982        out($f, "}\n\n");
2983    } else {
2984        out($f, "ZEND_API int ZEND_FASTCALL zend_vm_call_opcode_handler(zend_execute_data* ex)\n");
2985        out($f, "{\n");
2986        out($f, "\tzend_error_noreturn(E_CORE_ERROR, \"zend_vm_call_opcode_handler() is not supported\");\n");
2987        out($f, "\treturn 0;\n");
2988        out($f, "}\n\n");
2989    }
2990
2991    fclose($f);
2992    echo "zend_vm_execute.h generated successfully.\n";
2993}
2994
2995function usage() {
2996    echo("\nUsage: php zend_vm_gen.php [options]\n".
2997         "\nOptions:".
2998         "\n  --with-vm-kind=CALL|SWITCH|GOTO|HYBRID - select threading model (default is HYBRID)".
2999         "\n  --without-specializer                  - disable executor specialization".
3000         "\n  --with-lines                           - enable #line directives".
3001         "\n\n");
3002}
3003
3004// Parse arguments
3005for ($i = 1; $i < $argc; $i++) {
3006    if (strpos($argv[$i],"--with-vm-kind=") === 0) {
3007        $kind = substr($argv[$i], strlen("--with-vm-kind="));
3008        switch ($kind) {
3009            case "CALL":
3010                define("ZEND_VM_KIND", ZEND_VM_KIND_CALL);
3011                break;
3012            case "SWITCH":
3013                define("ZEND_VM_KIND", ZEND_VM_KIND_SWITCH);
3014                break;
3015            case "GOTO":
3016                define("ZEND_VM_KIND", ZEND_VM_KIND_GOTO);
3017                break;
3018            case "HYBRID":
3019                define("ZEND_VM_KIND", ZEND_VM_KIND_HYBRID);
3020                break;
3021            default:
3022                echo("ERROR: Invalid vm kind '$kind'\n");
3023                usage();
3024                die();
3025        }
3026    } else if ($argv[$i] == "--without-specializer") {
3027        // Disabling specialization
3028        define("ZEND_VM_SPEC", 0);
3029    } else if ($argv[$i] == "--with-lines") {
3030        // Enabling debugging using original zend_vm_def.h
3031        define("ZEND_VM_LINES", 1);
3032    } else if ($argv[$i] == "--help") {
3033        usage();
3034        exit();
3035    } else {
3036        echo("ERROR: Invalid option '".$argv[$i]."'\n");
3037        usage();
3038        die();
3039    }
3040}
3041
3042// Using defaults
3043if (!defined("ZEND_VM_KIND")) {
3044    // Using CALL threading by default
3045    define("ZEND_VM_KIND", ZEND_VM_KIND_HYBRID);
3046}
3047if (!defined("ZEND_VM_SPEC")) {
3048    // Using specialized executor by default
3049    define("ZEND_VM_SPEC", 1);
3050}
3051if (!defined("ZEND_VM_LINES")) {
3052    // Disabling #line directives
3053    define("ZEND_VM_LINES", 0);
3054}
3055
3056gen_vm(__DIR__ . "/zend_vm_def.h", __DIR__ . "/zend_vm_execute.skl");
3057