php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
zend_dump.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Zend Engine, Bytecode Visualisation |
4 +----------------------------------------------------------------------+
5 | Copyright (c) The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | https://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Dmitry Stogov <dmitry@php.net> |
16 +----------------------------------------------------------------------+
17*/
18
19#include "zend_compile.h"
20#include "zend_cfg.h"
21#include "zend_ssa.h"
22#include "zend_inference.h"
23#include "zend_func_info.h"
24#include "zend_call_graph.h"
25#include "zend_dump.h"
27
29{
30 zend_ulong index;
32 zval *val;
33 bool first = 1;
34
36 if (first) {
37 first = 0;
38 } else {
39 fprintf(stderr, ", ");
40 }
41 if (key) {
42 fprintf(stderr, "\"%s\"", ZSTR_VAL(key));
43 } else {
44 fprintf(stderr, ZEND_LONG_FMT, index);
45 }
46 fprintf(stderr, " =>");
49}
50
52{
53 switch (Z_TYPE_P(zv)) {
54 case IS_NULL:
55 fprintf(stderr, " null");
56 break;
57 case IS_FALSE:
58 fprintf(stderr, " bool(false)");
59 break;
60 case IS_TRUE:
61 fprintf(stderr, " bool(true)");
62 break;
63 case IS_LONG:
64 fprintf(stderr, " int(" ZEND_LONG_FMT ")", Z_LVAL_P(zv));
65 break;
66 case IS_DOUBLE:
67 fprintf(stderr, " float(%g)", Z_DVAL_P(zv));
68 break;
69 case IS_STRING:;
70 zend_string *escaped_string = php_addcslashes(Z_STR_P(zv), "\"\\", 2);
71
72 fprintf(stderr, " string(\"%s\")", ZSTR_VAL(escaped_string));
73
74 zend_string_release(escaped_string);
75 break;
76 case IS_ARRAY:
77 fprintf(stderr, " array(...)");
78 break;
79 default:
80 fprintf(stderr, " zval(type=%d)", Z_TYPE_P(zv));
81 break;
82 }
83}
84
85static void zend_dump_class_fetch_type(uint32_t fetch_type)
86{
87 switch (fetch_type & ZEND_FETCH_CLASS_MASK) {
89 fprintf(stderr, " (self)");
90 break;
92 fprintf(stderr, " (parent)");
93 break;
95 fprintf(stderr, " (static)");
96 break;
98 fprintf(stderr, " (auto)");
99 break;
101 fprintf(stderr, " (interface)");
102 break;
104 fprintf(stderr, " (trait)");
105 break;
106 }
107 if (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) {
108 fprintf(stderr, " (no-autoload)");
109 }
110 if (fetch_type & ZEND_FETCH_CLASS_SILENT) {
111 fprintf(stderr, " (silent)");
112 }
113 if (fetch_type & ZEND_FETCH_CLASS_EXCEPTION) {
114 fprintf(stderr, " (exception)");
115 }
116}
117
118static void zend_dump_unused_op(const zend_op *opline, znode_op op, uint32_t flags) {
120 fprintf(stderr, " %u", op.num);
121 } else if (ZEND_VM_OP_TRY_CATCH == (flags & ZEND_VM_OP_MASK)) {
122 if (op.num != (uint32_t)-1) {
123 fprintf(stderr, " try-catch(%u)", op.num);
124 }
125 } else if (ZEND_VM_OP_THIS == (flags & ZEND_VM_OP_MASK)) {
126 fprintf(stderr, " THIS");
127 } else if (ZEND_VM_OP_NEXT == (flags & ZEND_VM_OP_MASK)) {
128 fprintf(stderr, " NEXT");
129 } else if (ZEND_VM_OP_CLASS_FETCH == (flags & ZEND_VM_OP_MASK)) {
130 zend_dump_class_fetch_type(op.num);
131 } else if (ZEND_VM_OP_CONSTRUCTOR == (flags & ZEND_VM_OP_MASK)) {
132 fprintf(stderr, " CONSTRUCTOR");
133 } else if (ZEND_VM_OP_CONST_FETCH == (flags & ZEND_VM_OP_MASK)) {
135 fprintf(stderr, " (unqualified-in-namespace)");
136 }
137 }
138}
139
140ZEND_API void zend_dump_var(const zend_op_array *op_array, uint8_t var_type, uint32_t var_num)
141{
142 if (var_type == IS_CV && var_num < op_array->last_var) {
143 fprintf(stderr, "CV%d($%s)", var_num, op_array->vars[var_num]->val);
144 } else if (var_type == IS_VAR) {
145 fprintf(stderr, "V%d", var_num);
146 } else if ((var_type & (IS_VAR|IS_TMP_VAR)) == IS_TMP_VAR) {
147 fprintf(stderr, "T%d", var_num);
148 } else {
149 fprintf(stderr, "X%d", var_num);
150 }
151}
152
153static void zend_dump_range(const zend_ssa_range *r)
154{
155 if (r->underflow && r->overflow) {
156 return;
157 }
158 fprintf(stderr, " RANGE[");
159 if (r->underflow) {
160 fprintf(stderr, "--..");
161 } else if (r->min == ZEND_LONG_MIN) {
162 fprintf(stderr, "MIN..");
163 } else {
164 fprintf(stderr, ZEND_LONG_FMT "..", r->min);
165 }
166 if (r->overflow) {
167 fprintf(stderr, "++]");
168 } else if (r->max == ZEND_LONG_MAX) {
169 fprintf(stderr, "MAX]");
170 } else {
171 fprintf(stderr, ZEND_LONG_FMT "]", r->max);
172 }
173}
174
175static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_instanceof, uint32_t dump_flags)
176{
177 bool first = 1;
178
179 fprintf(stderr, " [");
180 if (info & MAY_BE_GUARD) {
181 fprintf(stderr, "!");
182 }
183 if (info & MAY_BE_UNDEF) {
184 if (first) first = 0; else fprintf(stderr, ", ");
185 fprintf(stderr, "undef");
186 }
187 if (info & MAY_BE_INDIRECT) {
188 if (first) first = 0; else fprintf(stderr, ", ");
189 fprintf(stderr, "ind");
190 }
191 if (info & MAY_BE_REF) {
192 if (first) first = 0; else fprintf(stderr, ", ");
193 fprintf(stderr, "ref");
194 }
195 if (dump_flags & ZEND_DUMP_RC_INFERENCE) {
196 if (info & MAY_BE_RC1) {
197 if (first) first = 0; else fprintf(stderr, ", ");
198 fprintf(stderr, "rc1");
199 }
200 if (info & MAY_BE_RCN) {
201 if (first) first = 0; else fprintf(stderr, ", ");
202 fprintf(stderr, "rcn");
203 }
204 }
205 if (info & MAY_BE_CLASS) {
206 if (first) first = 0; else fprintf(stderr, ", ");
207 fprintf(stderr, "class");
208 if (ce) {
209 if (is_instanceof) {
210 fprintf(stderr, " (instanceof %s)", ce->name->val);
211 } else {
212 fprintf(stderr, " (%s)", ce->name->val);
213 }
214 }
215 } else if ((info & MAY_BE_ANY) == MAY_BE_ANY) {
216 if (first) first = 0; else fprintf(stderr, ", ");
217 fprintf(stderr, "any");
218 } else {
219 if (info & MAY_BE_NULL) {
220 if (first) first = 0; else fprintf(stderr, ", ");
221 fprintf(stderr, "null");
222 }
223 if ((info & MAY_BE_FALSE) && (info & MAY_BE_TRUE)) {
224 if (first) first = 0; else fprintf(stderr, ", ");
225 fprintf(stderr, "bool");
226 } else if (info & MAY_BE_FALSE) {
227 if (first) first = 0; else fprintf(stderr, ", ");
228 fprintf(stderr, "false");
229 } else if (info & MAY_BE_TRUE) {
230 if (first) first = 0; else fprintf(stderr, ", ");
231 fprintf(stderr, "true");
232 }
233 if (info & MAY_BE_LONG) {
234 if (first) first = 0; else fprintf(stderr, ", ");
235 fprintf(stderr, "long");
236 }
237 if (info & MAY_BE_DOUBLE) {
238 if (first) first = 0; else fprintf(stderr, ", ");
239 fprintf(stderr, "double");
240 }
241 if (info & MAY_BE_STRING) {
242 if (first) first = 0; else fprintf(stderr, ", ");
243 fprintf(stderr, "string");
244 }
245 if (info & MAY_BE_ARRAY) {
246 if (first) first = 0; else fprintf(stderr, ", ");
247 if (info & MAY_BE_PACKED_GUARD) {
248 fprintf(stderr, "!");
249 }
250 if (MAY_BE_EMPTY_ONLY(info)) {
251 fprintf(stderr, "empty ");
252 } else if (MAY_BE_PACKED_ONLY(info)) {
253 fprintf(stderr, "packed ");
254 } else if (MAY_BE_HASH_ONLY(info)) {
255 fprintf(stderr, "hash ");
256 } else if ((info & MAY_BE_ARRAY_KEY_ANY) != MAY_BE_ARRAY_KEY_ANY && (info & MAY_BE_ARRAY_KEY_ANY) != 0) {
257 bool afirst = 1;
258 fprintf(stderr, "[");
259 if (info & MAY_BE_ARRAY_EMPTY) {
260 if (afirst) afirst = 0; else fprintf(stderr, ", ");
261 fprintf(stderr, "empty");
262 }
263 if (MAY_BE_PACKED(info)) {
264 if (afirst) afirst = 0; else fprintf(stderr, ", ");
265 fprintf(stderr, "packed");
266 }
267 if (MAY_BE_HASH(info)) {
268 if (afirst) afirst = 0; else fprintf(stderr, ", ");
269 fprintf(stderr, "hash");
270 }
271 fprintf(stderr, "] ");
272 }
273 fprintf(stderr, "array");
275 ((info & MAY_BE_ARRAY_KEY_LONG) == 0 ||
276 (info & MAY_BE_ARRAY_KEY_STRING) == 0)) {
277 bool afirst = 1;
278 fprintf(stderr, " [");
279 if (info & MAY_BE_ARRAY_KEY_LONG) {
280 if (afirst) afirst = 0; else fprintf(stderr, ", ");
281 fprintf(stderr, "long");
282 }
283 if (info & MAY_BE_ARRAY_KEY_STRING) {
284 if (afirst) afirst = 0; else fprintf(stderr, ", ");
285 fprintf(stderr, "string");
286 }
287 fprintf(stderr, "]");
288 }
290 bool afirst = 1;
291 fprintf(stderr, " of [");
293 if (afirst) afirst = 0; else fprintf(stderr, ", ");
294 fprintf(stderr, "any");
295 } else {
296 if (info & MAY_BE_ARRAY_OF_NULL) {
297 if (afirst) afirst = 0; else fprintf(stderr, ", ");
298 fprintf(stderr, "null");
299 }
300 if (info & MAY_BE_ARRAY_OF_FALSE) {
301 if (afirst) afirst = 0; else fprintf(stderr, ", ");
302 fprintf(stderr, "false");
303 }
304 if (info & MAY_BE_ARRAY_OF_TRUE) {
305 if (afirst) afirst = 0; else fprintf(stderr, ", ");
306 fprintf(stderr, "true");
307 }
308 if (info & MAY_BE_ARRAY_OF_LONG) {
309 if (afirst) afirst = 0; else fprintf(stderr, ", ");
310 fprintf(stderr, "long");
311 }
312 if (info & MAY_BE_ARRAY_OF_DOUBLE) {
313 if (afirst) afirst = 0; else fprintf(stderr, ", ");
314 fprintf(stderr, "double");
315 }
316 if (info & MAY_BE_ARRAY_OF_STRING) {
317 if (afirst) afirst = 0; else fprintf(stderr, ", ");
318 fprintf(stderr, "string");
319 }
320 if (info & MAY_BE_ARRAY_OF_ARRAY) {
321 if (afirst) afirst = 0; else fprintf(stderr, ", ");
322 fprintf(stderr, "array");
323 }
324 if (info & MAY_BE_ARRAY_OF_OBJECT) {
325 if (afirst) afirst = 0; else fprintf(stderr, ", ");
326 fprintf(stderr, "object");
327 }
328 if (info & MAY_BE_ARRAY_OF_RESOURCE) {
329 if (afirst) afirst = 0; else fprintf(stderr, ", ");
330 fprintf(stderr, "resource");
331 }
332 }
333 if (info & MAY_BE_ARRAY_OF_REF) {
334 if (afirst) afirst = 0; else fprintf(stderr, ", ");
335 fprintf(stderr, "ref");
336 }
337 fprintf(stderr, "]");
338 }
339 }
340 if (info & MAY_BE_OBJECT) {
341 if (first) first = 0; else fprintf(stderr, ", ");
342 fprintf(stderr, "object");
343 if (ce) {
344 if (is_instanceof) {
345 fprintf(stderr, " (instanceof %s)", ce->name->val);
346 } else {
347 fprintf(stderr, " (%s)", ce->name->val);
348 }
349 }
350 }
351 if (info & MAY_BE_RESOURCE) {
352 if (first) first = 0; else fprintf(stderr, ", ");
353 fprintf(stderr, "resource");
354 }
355 }
356 fprintf(stderr, "]");
357}
358
359static void zend_dump_ssa_var_info(const zend_ssa *ssa, int ssa_var_num, uint32_t dump_flags)
360{
361 zend_dump_type_info(
362 ssa->var_info[ssa_var_num].type,
363 ssa->var_info[ssa_var_num].ce,
364 ssa->var_info[ssa_var_num].ce ?
365 ssa->var_info[ssa_var_num].is_instanceof : 0,
366 dump_flags);
367}
368
369ZEND_API void zend_dump_ssa_var(const zend_op_array *op_array, const zend_ssa *ssa, int ssa_var_num, uint8_t var_type, uint32_t var_num, uint32_t dump_flags)
370{
371 if (ssa_var_num >= 0) {
372 fprintf(stderr, "#%d.", ssa_var_num);
373 } else {
374 fprintf(stderr, "#?.");
375 }
376 zend_dump_var(op_array, (var_num < op_array->last_var ? IS_CV : var_type), var_num);
377
378 if (ssa_var_num >= 0 && ssa->vars) {
379 if (ssa->vars[ssa_var_num].no_val) {
380 fprintf(stderr, " NOVAL");
381 }
382 if (ssa->vars[ssa_var_num].escape_state == ESCAPE_STATE_NO_ESCAPE) {
383 fprintf(stderr, " NOESC");
384 }
385 if (ssa->var_info) {
386 zend_dump_ssa_var_info(ssa, ssa_var_num, dump_flags);
387 if (ssa->var_info[ssa_var_num].has_range) {
388 zend_dump_range(&ssa->var_info[ssa_var_num].range);
389 }
390 }
391 }
392}
393
394static void zend_dump_type_constraint(const zend_op_array *op_array, const zend_ssa *ssa, const zend_ssa_type_constraint *constraint, uint32_t dump_flags)
395{
396 fprintf(stderr, " TYPE");
397 zend_dump_type_info(constraint->type_mask, constraint->ce, 1, dump_flags);
398}
399
400static void zend_dump_range_constraint(const zend_op_array *op_array, const zend_ssa *ssa, const zend_ssa_range_constraint *r, uint32_t dump_flags)
401{
402 if (r->range.underflow && r->range.overflow) {
403 return;
404 }
405 fprintf(stderr, " RANGE");
406 if (r->negative) {
407 fprintf(stderr, "~");
408 }
409 fprintf(stderr, "[");
410 if (r->range.underflow) {
411 fprintf(stderr, "-- .. ");
412 } else {
413 if (r->min_ssa_var >= 0) {
414 zend_dump_ssa_var(op_array, ssa, r->min_ssa_var, (r->min_var < op_array->last_var ? IS_CV : 0), r->min_var, dump_flags);
415 if (r->range.min > 0) {
416 fprintf(stderr, " + " ZEND_LONG_FMT, r->range.min);
417 } else if (r->range.min < 0) {
418 fprintf(stderr, " - " ZEND_LONG_FMT, -r->range.min);
419 }
420 fprintf(stderr, " .. ");
421 } else {
422 fprintf(stderr, ZEND_LONG_FMT " .. ", r->range.min);
423 }
424 }
425 if (r->range.overflow) {
426 fprintf(stderr, "++]");
427 } else {
428 if (r->max_ssa_var >= 0) {
429 zend_dump_ssa_var(op_array, ssa, r->max_ssa_var, (r->max_var < op_array->last_var ? IS_CV : 0), r->max_var, dump_flags);
430 if (r->range.max > 0) {
431 fprintf(stderr, " + " ZEND_LONG_FMT, r->range.max);
432 } else if (r->range.max < 0) {
433 fprintf(stderr, " - " ZEND_LONG_FMT, -r->range.max);
434 }
435 fprintf(stderr, "]");
436 } else {
437 fprintf(stderr, ZEND_LONG_FMT "]", r->range.max);
438 }
439 }
440}
441
442ZEND_API void zend_dump_op(const zend_op_array *op_array, const zend_basic_block *b, const zend_op *opline, uint32_t dump_flags, const zend_ssa *ssa, const zend_ssa_op *ssa_op)
443{
444 const char *name = zend_get_opcode_name(opline->opcode);
445 uint32_t flags = zend_get_opcode_flags(opline->opcode);
446 uint32_t n = 0;
447
448 if (!ssa_op || ssa_op->result_use < 0) {
449 if (opline->result_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
450 if (ssa_op && ssa_op->result_def >= 0) {
451 int ssa_var_num = ssa_op->result_def;
452 zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->result_type, EX_VAR_TO_NUM(opline->result.var), dump_flags);
453 } else {
454 zend_dump_var(op_array, opline->result_type, EX_VAR_TO_NUM(opline->result.var));
455 }
456 fprintf(stderr, " = ");
457 }
458 }
459
460 if (name) {
461 fprintf(stderr, "%s", (name + 5));
462 } else {
463 fprintf(stderr, "OP_%d", (int)opline->opcode);
464 }
465
466 if (ZEND_OP_IS_FRAMELESS_ICALL(opline->opcode)) {
468 fprintf(stderr, "(%s)", ZSTR_VAL(func->common.function_name));
469 }
470
472 fprintf(stderr, " %u", opline->extended_value);
473 } else if (ZEND_VM_EXT_OP == (flags & ZEND_VM_EXT_MASK)) {
474 fprintf(stderr, " (%s)", zend_get_opcode_name(opline->extended_value) + 5);
475 } else if (ZEND_VM_EXT_TYPE == (flags & ZEND_VM_EXT_MASK)) {
476 switch (opline->extended_value) {
477 case IS_NULL:
478 fprintf(stderr, " (null)");
479 break;
480 case IS_FALSE:
481 fprintf(stderr, " (false)");
482 break;
483 case IS_TRUE:
484 fprintf(stderr, " (true)");
485 break;
486 case IS_LONG:
487 fprintf(stderr, " (long)");
488 break;
489 case IS_DOUBLE:
490 fprintf(stderr, " (double)");
491 break;
492 case IS_STRING:
493 fprintf(stderr, " (string)");
494 break;
495 case IS_ARRAY:
496 fprintf(stderr, " (array)");
497 break;
498 case IS_OBJECT:
499 fprintf(stderr, " (object)");
500 break;
501 case IS_RESOURCE:
502 fprintf(stderr, " (resource)");
503 break;
504 case _IS_BOOL:
505 fprintf(stderr, " (bool)");
506 break;
507 case IS_CALLABLE:
508 fprintf(stderr, " (callable)");
509 break;
510 case IS_VOID:
511 fprintf(stderr, " (void)");
512 break;
513 case IS_NEVER:
514 fprintf(stderr, " (never)");
515 break;
516 default:
517 fprintf(stderr, " (\?\?\?)");
518 break;
519 }
520 } else if (ZEND_VM_EXT_TYPE_MASK == (flags & ZEND_VM_EXT_MASK)) {
521 switch (opline->extended_value) {
522 case (1<<IS_NULL):
523 fprintf(stderr, " (null)");
524 break;
525 case (1<<IS_FALSE):
526 fprintf(stderr, " (false)");
527 break;
528 case (1<<IS_TRUE):
529 fprintf(stderr, " (true)");
530 break;
531 case (1<<IS_LONG):
532 fprintf(stderr, " (long)");
533 break;
534 case (1<<IS_DOUBLE):
535 fprintf(stderr, " (double)");
536 break;
537 case (1<<IS_STRING):
538 fprintf(stderr, " (string)");
539 break;
540 case (1<<IS_ARRAY):
541 fprintf(stderr, " (array)");
542 break;
543 case (1<<IS_OBJECT):
544 fprintf(stderr, " (object)");
545 break;
546 case (1<<IS_RESOURCE):
547 fprintf(stderr, " (resource)");
548 break;
549 case ((1<<IS_FALSE)|(1<<IS_TRUE)):
550 fprintf(stderr, " (bool)");
551 break;
552 default:
553 fprintf(stderr, " TYPE");
554 zend_dump_type_info(opline->extended_value, NULL, 0, dump_flags);
555 break;
556 }
557 } else if (ZEND_VM_EXT_EVAL == (flags & ZEND_VM_EXT_MASK)) {
558 switch (opline->extended_value) {
559 case ZEND_EVAL:
560 fprintf(stderr, " (eval)");
561 break;
562 case ZEND_INCLUDE:
563 fprintf(stderr, " (include)");
564 break;
566 fprintf(stderr, " (include_once)");
567 break;
568 case ZEND_REQUIRE:
569 fprintf(stderr, " (require)");
570 break;
572 fprintf(stderr, " (require_once)");
573 break;
574 default:
575 fprintf(stderr, " (\?\?\?)");
576 break;
577 }
578 } else if (ZEND_VM_EXT_SRC == (flags & ZEND_VM_EXT_MASK)) {
579 if (opline->extended_value == ZEND_RETURNS_VALUE) {
580 fprintf(stderr, " (value)");
581 } else if (opline->extended_value & ZEND_RETURNS_FUNCTION) {
582 fprintf(stderr, " (function)");
583 }
584 } else {
586 if (opline->extended_value & ZEND_FETCH_GLOBAL) {
587 fprintf(stderr, " (global)");
588 } else if (opline->extended_value & ZEND_FETCH_LOCAL) {
589 fprintf(stderr, " (local)");
590 } else if (opline->extended_value & ZEND_FETCH_GLOBAL_LOCK) {
591 fprintf(stderr, " (global+lock)");
592 }
593 }
594 if (ZEND_VM_EXT_ISSET & flags) {
595 if (!(opline->extended_value & ZEND_ISEMPTY)) {
596 fprintf(stderr, " (isset)");
597 } else {
598 fprintf(stderr, " (empty)");
599 }
600 }
602 fprintf(stderr, " %u", opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT);
603 if (!(opline->extended_value & ZEND_ARRAY_NOT_PACKED)) {
604 fprintf(stderr, " (packed)");
605 }
606 }
607 if (ZEND_VM_EXT_REF & flags) {
609 fprintf(stderr, " (ref)");
610 }
611 }
613 uint32_t obj_flags = opline->extended_value & ZEND_FETCH_OBJ_FLAGS;
614 if (obj_flags == ZEND_FETCH_REF) {
615 fprintf(stderr, " (ref)");
616 } else if (obj_flags == ZEND_FETCH_DIM_WRITE) {
617 fprintf(stderr, " (dim write)");
618 }
619 }
620 }
621
622 if (opline->op1_type == IS_CONST) {
624 } else if (opline->op1_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
625 if (ssa_op) {
626 int ssa_var_num = ssa_op->op1_use;
627 if (ssa_var_num >= 0) {
628 fprintf(stderr, " ");
629 zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->op1_type, EX_VAR_TO_NUM(opline->op1.var), dump_flags);
630 } else if (ssa_op->op1_def < 0) {
631 fprintf(stderr, " ");
632 zend_dump_var(op_array, opline->op1_type, EX_VAR_TO_NUM(opline->op1.var));
633 }
634 } else {
635 fprintf(stderr, " ");
636 zend_dump_var(op_array, opline->op1_type, EX_VAR_TO_NUM(opline->op1.var));
637 }
638 if (ssa_op) {
639 int ssa_var_num = ssa_op->op1_def;
640 if (ssa_var_num >= 0) {
641 fprintf(stderr, " -> ");
642 zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->op1_type, EX_VAR_TO_NUM(opline->op1.var), dump_flags);
643 }
644 }
645 } else {
646 uint32_t op1_flags = ZEND_VM_OP1_FLAGS(flags);
647 if (ZEND_VM_OP_JMP_ADDR == (op1_flags & ZEND_VM_OP_MASK)) {
648 if (b) {
649 fprintf(stderr, " BB%d", b->successors[n++]);
650 } else {
651 fprintf(stderr, " %04u", (uint32_t)(OP_JMP_ADDR(opline, opline->op1) - op_array->opcodes));
652 }
653 } else {
654 zend_dump_unused_op(opline, opline->op1, op1_flags);
655 }
656 }
657
658 if (opline->op2_type == IS_CONST) {
659 zval *op = CRT_CONSTANT(opline->op2);
660 if (
661 opline->opcode == ZEND_SWITCH_LONG
662 || opline->opcode == ZEND_SWITCH_STRING
663 || opline->opcode == ZEND_MATCH
664 ) {
665 HashTable *jumptable = Z_ARRVAL_P(op);
667 zend_ulong num_key;
668 zval *zv;
669 ZEND_HASH_FOREACH_KEY_VAL(jumptable, num_key, key, zv) {
670 if (key) {
671 fprintf(stderr, " \"%s\":", ZSTR_VAL(key));
672 } else {
673 fprintf(stderr, " " ZEND_LONG_FMT ":", num_key);
674 }
675 if (b) {
676 fprintf(stderr, " BB%d,", b->successors[n++]);
677 } else {
678 fprintf(stderr, " %04u,", (uint32_t)ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(zv)));
679 }
681 fprintf(stderr, " default:");
682 } else {
683 zend_dump_const(op);
684 }
685 } else if (opline->op2_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
686 if (ssa_op) {
687 int ssa_var_num = ssa_op->op2_use;
688 if (ssa_var_num >= 0) {
689 fprintf(stderr, " ");
690 zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->op2_type, EX_VAR_TO_NUM(opline->op2.var), dump_flags);
691 } else if (ssa_op->op2_def < 0) {
692 fprintf(stderr, " ");
693 zend_dump_var(op_array, opline->op2_type, EX_VAR_TO_NUM(opline->op2.var));
694 }
695 } else {
696 fprintf(stderr, " ");
697 zend_dump_var(op_array, opline->op2_type, EX_VAR_TO_NUM(opline->op2.var));
698 }
699 if (ssa_op) {
700 int ssa_var_num = ssa_op->op2_def;
701 if (ssa_var_num >= 0) {
702 fprintf(stderr, " -> ");
703 zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->op2_type, EX_VAR_TO_NUM(opline->op2.var), dump_flags);
704 }
705 }
706 } else {
707 uint32_t op2_flags = ZEND_VM_OP2_FLAGS(flags);
708 if (ZEND_VM_OP_JMP_ADDR == (op2_flags & ZEND_VM_OP_MASK)) {
709 if (opline->opcode != ZEND_CATCH || !(opline->extended_value & ZEND_LAST_CATCH)) {
710 if (b) {
711 fprintf(stderr, " BB%d", b->successors[n++]);
712 } else {
713 fprintf(stderr, " %04u", (uint32_t)(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes));
714 }
715 }
716 } else {
717 zend_dump_unused_op(opline, opline->op2, op2_flags);
718 }
719 }
720
722 if (b) {
723 fprintf(stderr, " BB%d", b->successors[n++]);
724 } else {
725 fprintf(stderr, " %04u", (uint32_t)ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value));
726 }
727 }
728 if (opline->result_type == IS_CONST) {
730#if 0
731 } else if (opline->result_type & IS_SMART_BRANCH_JMPZ) {
732 fprintf(stderr, " jmpz");
733 } else if (opline->result_type & IS_SMART_BRANCH_JMPNZ) {
734 fprintf(stderr, " jmpnz");
735#endif
736 } else if (ssa_op && ssa_op->result_use >= 0) {
737 if (opline->result_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
738 if (ssa_op) {
739 int ssa_var_num = ssa_op->result_use;
740 if (ssa_var_num >= 0) {
741 fprintf(stderr, " ");
742 zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->result_type, EX_VAR_TO_NUM(opline->result.var), dump_flags);
743 }
744 } else {
745 fprintf(stderr, " ");
746 zend_dump_var(op_array, opline->result_type, EX_VAR_TO_NUM(opline->result.var));
747 }
748 if (ssa_op) {
749 int ssa_var_num = ssa_op->result_def;
750 if (ssa_var_num >= 0) {
751 fprintf(stderr, " -> ");
752 zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->result_type, EX_VAR_TO_NUM(opline->result.var), dump_flags);
753 }
754 }
755 }
756 }
757}
758
759ZEND_API void zend_dump_op_line(const zend_op_array *op_array, const zend_basic_block *b, const zend_op *opline, uint32_t dump_flags, const void *data)
760{
761 int len = 0;
762 const zend_ssa *ssa = NULL;
763 zend_ssa_op *ssa_op = NULL;
764
765 if (dump_flags & ZEND_DUMP_LINE_NUMBERS) {
766 fprintf(stderr, "L%04u ", opline->lineno);
767 }
768
769 len = fprintf(stderr, "%04u", (uint32_t)(opline - op_array->opcodes));
770 fprintf(stderr, "%*c", 5-len, ' ');
771
772 if (dump_flags & ZEND_DUMP_SSA) {
773 ssa = (const zend_ssa*)data;
774 if (ssa && ssa->ops) {
775 ssa_op = &ssa->ops[opline - op_array->opcodes];
776 }
777 }
778
779 zend_dump_op(op_array, b, opline, dump_flags, ssa, ssa_op);
780 fprintf(stderr, "\n");
781}
782
783static void zend_dump_block_info(const zend_cfg *cfg, int n, uint32_t dump_flags)
784{
785 zend_basic_block *b = cfg->blocks + n;
786
787 if (n > 0) {
788 fprintf(stderr, "\n");
789 }
790 fprintf(stderr, "BB%d:\n ;", n);
791 if (b->flags & ZEND_BB_START) {
792 fprintf(stderr, " start");
793 }
794 if (b->flags & ZEND_BB_RECV_ENTRY) {
795 fprintf(stderr, " recv");
796 }
797 if (b->flags & ZEND_BB_FOLLOW) {
798 fprintf(stderr, " follow");
799 }
800 if (b->flags & ZEND_BB_TARGET) {
801 fprintf(stderr, " target");
802 }
803 if (b->flags & ZEND_BB_EXIT) {
804 fprintf(stderr, " exit");
805 }
807 fprintf(stderr, " entry");
808 }
809 if (b->flags & ZEND_BB_TRY) {
810 fprintf(stderr, " try");
811 }
812 if (b->flags & ZEND_BB_CATCH) {
813 fprintf(stderr, " catch");
814 }
815 if (b->flags & ZEND_BB_FINALLY) {
816 fprintf(stderr, " finally");
817 }
818 if (b->flags & ZEND_BB_FINALLY_END) {
819 fprintf(stderr, " finally_end");
820 }
821 if (!(dump_flags & ZEND_DUMP_HIDE_UNREACHABLE) && !(b->flags & ZEND_BB_REACHABLE)) {
822 fprintf(stderr, " unreachable");
823 }
825 fprintf(stderr, " unreachable_free");
826 }
827 if (b->flags & ZEND_BB_LOOP_HEADER) {
828 fprintf(stderr, " loop_header");
829 }
831 fprintf(stderr, " irreducible");
832 }
833 if (b->len != 0) {
834 fprintf(stderr, " lines=[%d-%d]", b->start, b->start + b->len - 1);
835 } else {
836 fprintf(stderr, " empty");
837 }
838 fprintf(stderr, "\n");
839
840 if (b->predecessors_count) {
841 int *p = cfg->predecessors + b->predecessor_offset;
842 int *end = p + b->predecessors_count;
843
844 fprintf(stderr, " ; from=(BB%d", *p);
845 for (p++; p < end; p++) {
846 fprintf(stderr, ", BB%d", *p);
847 }
848 fprintf(stderr, ")\n");
849 }
850
851 if (b->successors_count > 0) {
852 int s;
853 fprintf(stderr, " ; to=(BB%d", b->successors[0]);
854 for (s = 1; s < b->successors_count; s++) {
855 fprintf(stderr, ", BB%d", b->successors[s]);
856 }
857 fprintf(stderr, ")\n");
858 }
859
860 if (b->idom >= 0) {
861 fprintf(stderr, " ; idom=BB%d\n", b->idom);
862 }
863 if (b->level >= 0) {
864 fprintf(stderr, " ; level=%d\n", b->level);
865 }
866 if (b->loop_header >= 0) {
867 fprintf(stderr, " ; loop_header=%d\n", b->loop_header);
868 }
869 if (b->children >= 0) {
870 int j = b->children;
871 fprintf(stderr, " ; children=(BB%d", j);
872 j = cfg->blocks[j].next_child;
873 while (j >= 0) {
874 fprintf(stderr, ", BB%d", j);
875 j = cfg->blocks[j].next_child;
876 }
877 fprintf(stderr, ")\n");
878 }
879}
880
881static void zend_dump_block_header(const zend_cfg *cfg, const zend_op_array *op_array, const zend_ssa *ssa, int n, uint32_t dump_flags)
882{
883 zend_dump_block_info(cfg, n, dump_flags);
884 if (ssa && ssa->blocks && ssa->blocks[n].phis) {
885 zend_ssa_phi *p = ssa->blocks[n].phis;
886
887 do {
888 int j;
889
890 fprintf(stderr, " ");
891 zend_dump_ssa_var(op_array, ssa, p->ssa_var, 0, p->var, dump_flags);
892 if (p->pi < 0) {
893 fprintf(stderr, " = Phi(");
894 for (j = 0; j < cfg->blocks[n].predecessors_count; j++) {
895 if (j > 0) {
896 fprintf(stderr, ", ");
897 }
898 zend_dump_ssa_var(op_array, ssa, p->sources[j], 0, p->var, dump_flags);
899 }
900 fprintf(stderr, ")\n");
901 } else {
902 fprintf(stderr, " = Pi<BB%d>(", p->pi);
903 zend_dump_ssa_var(op_array, ssa, p->sources[0], 0, p->var, dump_flags);
904 fprintf(stderr, " &");
905 if (p->has_range_constraint) {
906 zend_dump_range_constraint(op_array, ssa, &p->constraint.range, dump_flags);
907 } else {
908 zend_dump_type_constraint(op_array, ssa, &p->constraint.type, dump_flags);
909 }
910 fprintf(stderr, ")\n");
911 }
912 p = p->next;
913 } while (p);
914 }
915}
916
918{
919 if (op_array->function_name) {
920 if (op_array->scope && op_array->scope->name) {
921 fprintf(stderr, "%s::%s", op_array->scope->name->val, op_array->function_name->val);
922 } else {
923 fprintf(stderr, "%s", op_array->function_name->val);
924 }
925 } else {
926 fprintf(stderr, "%s", "$_main");
927 }
928}
929
930ZEND_API void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_flags, const char *msg, const void *data)
931{
932 const zend_cfg *cfg = NULL;
933 const zend_ssa *ssa = NULL;
934 zend_func_info *func_info = NULL;
935 uint32_t func_flags = 0;
936
937 if (dump_flags & (ZEND_DUMP_CFG|ZEND_DUMP_SSA)) {
938 cfg = (const zend_cfg*)data;
939 if (!cfg->blocks) {
940 cfg = data = NULL;
941 }
942 }
943 if (dump_flags & ZEND_DUMP_SSA) {
944 ssa = (const zend_ssa*)data;
945 }
946
947 func_info = ZEND_FUNC_INFO(op_array);
948 if (func_info) {
949 func_flags = func_info->flags;
950 }
951
952 fprintf(stderr, "\n");
953 zend_dump_op_array_name(op_array);
954 fprintf(stderr, ":\n ; (lines=%d, args=%d",
955 op_array->last,
956 op_array->num_args);
957 fprintf(stderr, ", vars=%d, tmps=%d", op_array->last_var, op_array->T);
958 if (ssa) {
959 fprintf(stderr, ", ssa_vars=%d", ssa->vars_count);
960 }
961 if (func_flags & ZEND_FUNC_INDIRECT_VAR_ACCESS) {
962 fprintf(stderr, ", dynamic");
963 }
964 if (func_flags & ZEND_FUNC_RECURSIVE) {
965 fprintf(stderr, ", recursive");
966 if (func_flags & ZEND_FUNC_RECURSIVE_DIRECTLY) {
967 fprintf(stderr, " directly");
968 }
969 if (func_flags & ZEND_FUNC_RECURSIVE_INDIRECTLY) {
970 fprintf(stderr, " indirectly");
971 }
972 }
973 if (func_flags & ZEND_FUNC_IRREDUCIBLE) {
974 fprintf(stderr, ", irreducible");
975 }
976 if (func_flags & ZEND_FUNC_NO_LOOPS) {
977 fprintf(stderr, ", no_loops");
978 }
979 if (func_flags & ZEND_FUNC_HAS_EXTENDED_STMT) {
980 fprintf(stderr, ", extended_stmt");
981 }
982 if (func_flags & ZEND_FUNC_HAS_EXTENDED_FCALL) {
983 fprintf(stderr, ", extended_fcall");
984 }
985//TODO: this is useful only for JIT???
986#if 0
987 if (info->flags & ZEND_JIT_FUNC_NO_IN_MEM_CVS) {
988 fprintf(stderr, ", no_in_mem_cvs");
989 }
990 if (info->flags & ZEND_JIT_FUNC_NO_USED_ARGS) {
991 fprintf(stderr, ", no_used_args");
992 }
993 if (info->flags & ZEND_JIT_FUNC_NO_SYMTAB) {
994 fprintf(stderr, ", no_symtab");
995 }
996 if (info->flags & ZEND_JIT_FUNC_NO_FRAME) {
997 fprintf(stderr, ", no_frame");
998 }
999 if (info->flags & ZEND_JIT_FUNC_INLINE) {
1000 fprintf(stderr, ", inline");
1001 }
1002#endif
1003 fprintf(stderr, ")\n");
1004 if (msg) {
1005 fprintf(stderr, " ; (%s)\n", msg);
1006 }
1007 fprintf(stderr, " ; %s:%u-%u\n", op_array->filename->val, op_array->line_start, op_array->line_end);
1008
1009 if (func_info) {
1010 fprintf(stderr, " ; return ");
1011 zend_dump_type_info(func_info->return_info.type, func_info->return_info.ce, func_info->return_info.is_instanceof, dump_flags);
1012 zend_dump_range(&func_info->return_info.range);
1013 fprintf(stderr, "\n");
1014 }
1015
1016 if (ssa && ssa->var_info) {
1017 for (uint32_t i = 0; i < op_array->last_var; i++) {
1018 fprintf(stderr, " ; ");
1019 zend_dump_ssa_var(op_array, ssa, i, IS_CV, i, dump_flags);
1020 fprintf(stderr, "\n");
1021 }
1022 }
1023
1024 if (cfg) {
1025 int n;
1027
1028 for (n = 0; n < cfg->blocks_count; n++) {
1029 b = cfg->blocks + n;
1030 if (!(dump_flags & ZEND_DUMP_HIDE_UNREACHABLE) || (b->flags & ZEND_BB_REACHABLE)) {
1031 const zend_op *opline;
1032 const zend_op *end;
1033
1034 zend_dump_block_header(cfg, op_array, ssa, n, dump_flags);
1035 opline = op_array->opcodes + b->start;
1036 end = opline + b->len;
1037 while (opline < end) {
1038 zend_dump_op_line(op_array, b, opline, dump_flags, data);
1039 opline++;
1040 }
1041 }
1042 }
1043 if (op_array->last_live_range && (dump_flags & ZEND_DUMP_LIVE_RANGES)) {
1044 fprintf(stderr, "LIVE RANGES:\n");
1045 for (int i = 0; i < op_array->last_live_range; i++) {
1046 fprintf(stderr,
1047 " %u: %04u - %04u ",
1048 EX_VAR_TO_NUM(op_array->live_range[i].var & ~ZEND_LIVE_MASK),
1049 op_array->live_range[i].start,
1050 op_array->live_range[i].end);
1051 switch (op_array->live_range[i].var & ZEND_LIVE_MASK) {
1052 case ZEND_LIVE_TMPVAR:
1053 fprintf(stderr, "(tmp/var)\n");
1054 break;
1055 case ZEND_LIVE_LOOP:
1056 fprintf(stderr, "(loop)\n");
1057 break;
1058 case ZEND_LIVE_SILENCE:
1059 fprintf(stderr, "(silence)\n");
1060 break;
1061 case ZEND_LIVE_ROPE:
1062 fprintf(stderr, "(rope)\n");
1063 break;
1064 case ZEND_LIVE_NEW:
1065 fprintf(stderr, "(new)\n");
1066 break;
1067 }
1068 }
1069 }
1070 if (op_array->last_try_catch) {
1071 fprintf(stderr, "EXCEPTION TABLE:\n");
1072 for (int i = 0; i < op_array->last_try_catch; i++) {
1073 fprintf(stderr, " BB%u",
1074 cfg->map[op_array->try_catch_array[i].try_op]);
1075 if (op_array->try_catch_array[i].catch_op) {
1076 fprintf(stderr, ", BB%u",
1077 cfg->map[op_array->try_catch_array[i].catch_op]);
1078 } else {
1079 fprintf(stderr, ", -");
1080 }
1081 if (op_array->try_catch_array[i].finally_op) {
1082 fprintf(stderr, ", BB%u",
1083 cfg->map[op_array->try_catch_array[i].finally_op]);
1084 } else {
1085 fprintf(stderr, ", -");
1086 }
1087 if (op_array->try_catch_array[i].finally_end) {
1088 fprintf(stderr, ", BB%u\n",
1089 cfg->map[op_array->try_catch_array[i].finally_end]);
1090 } else {
1091 fprintf(stderr, ", -\n");
1092 }
1093 }
1094 }
1095 } else {
1096 const zend_op *opline = op_array->opcodes;
1097 const zend_op *end = opline + op_array->last;
1098
1099 while (opline < end) {
1100 zend_dump_op_line(op_array, NULL, opline, dump_flags, data);
1101 opline++;
1102 }
1103 if (op_array->last_live_range && (dump_flags & ZEND_DUMP_LIVE_RANGES)) {
1104 fprintf(stderr, "LIVE RANGES:\n");
1105 for (int i = 0; i < op_array->last_live_range; i++) {
1106 fprintf(stderr,
1107 " %u: %04u - %04u ",
1108 EX_VAR_TO_NUM(op_array->live_range[i].var & ~ZEND_LIVE_MASK),
1109 op_array->live_range[i].start,
1110 op_array->live_range[i].end);
1111 switch (op_array->live_range[i].var & ZEND_LIVE_MASK) {
1112 case ZEND_LIVE_TMPVAR:
1113 fprintf(stderr, "(tmp/var)\n");
1114 break;
1115 case ZEND_LIVE_LOOP:
1116 fprintf(stderr, "(loop)\n");
1117 break;
1118 case ZEND_LIVE_SILENCE:
1119 fprintf(stderr, "(silence)\n");
1120 break;
1121 case ZEND_LIVE_ROPE:
1122 fprintf(stderr, "(rope)\n");
1123 break;
1124 case ZEND_LIVE_NEW:
1125 fprintf(stderr, "(new)\n");
1126 break;
1127 }
1128 }
1129 }
1130 if (op_array->last_try_catch) {
1131 fprintf(stderr, "EXCEPTION TABLE:\n");
1132 for (int i = 0; i < op_array->last_try_catch; i++) {
1133 fprintf(stderr,
1134 " %04u",
1135 op_array->try_catch_array[i].try_op);
1136
1137 if (op_array->try_catch_array[i].catch_op) {
1138 fprintf(stderr,
1139 ", %04u",
1140 op_array->try_catch_array[i].catch_op);
1141 } else {
1142 fprintf(stderr, ", -");
1143 }
1144 if (op_array->try_catch_array[i].finally_op) {
1145 fprintf(stderr,
1146 ", %04u",
1147 op_array->try_catch_array[i].finally_op);
1148 } else {
1149 fprintf(stderr, ", -");
1150 }
1151 if (op_array->try_catch_array[i].finally_end) {
1152 fprintf(stderr,
1153 ", %04u",
1154 op_array->try_catch_array[i].finally_end);
1155 } else {
1156 fprintf(stderr, ", -\n");
1157 }
1158 }
1159 }
1160 }
1161}
1162
1163void zend_dump_dominators(const zend_op_array *op_array, const zend_cfg *cfg)
1164{
1165 int j;
1166
1167 fprintf(stderr, "\nDOMINATORS-TREE for \"");
1168 zend_dump_op_array_name(op_array);
1169 fprintf(stderr, "\"\n");
1170 for (j = 0; j < cfg->blocks_count; j++) {
1171 zend_basic_block *b = cfg->blocks + j;
1172 if (b->flags & ZEND_BB_REACHABLE) {
1173 zend_dump_block_info(cfg, j, 0);
1174 }
1175 }
1176}
1177
1178void zend_dump_ssa_variables(const zend_op_array *op_array, const zend_ssa *ssa, uint32_t dump_flags)
1179{
1180 int j;
1181
1182 if (ssa->vars) {
1183 fprintf(stderr, "\nSSA Variable for \"");
1184 zend_dump_op_array_name(op_array);
1185 fprintf(stderr, "\"\n");
1186
1187 for (j = 0; j < ssa->vars_count; j++) {
1188 fprintf(stderr, " ");
1189 zend_dump_ssa_var(op_array, ssa, j, IS_CV, ssa->vars[j].var, dump_flags);
1190 if (ssa->vars[j].scc >= 0) {
1191 if (ssa->vars[j].scc_entry) {
1192 fprintf(stderr, " *");
1193 } else {
1194 fprintf(stderr, " ");
1195 }
1196 fprintf(stderr, "SCC=%d", ssa->vars[j].scc);
1197 }
1198 fprintf(stderr, "\n");
1199 }
1200 }
1201}
1202
1203static void zend_dump_var_set(const zend_op_array *op_array, const char *name, zend_bitset set)
1204{
1205 bool first = 1;
1206 uint32_t i;
1207
1208 fprintf(stderr, " ; %s = {", name);
1209 for (i = 0; i < op_array->last_var + op_array->T; i++) {
1210 if (zend_bitset_in(set, i)) {
1211 if (first) {
1212 first = 0;
1213 } else {
1214 fprintf(stderr, ", ");
1215 }
1216 zend_dump_var(op_array, IS_CV, i);
1217 }
1218 }
1219 fprintf(stderr, "}\n");
1220}
1221
1222void zend_dump_dfg(const zend_op_array *op_array, const zend_cfg *cfg, const zend_dfg *dfg)
1223{
1224 int j;
1225 fprintf(stderr, "\nVariable Liveness for \"");
1226 zend_dump_op_array_name(op_array);
1227 fprintf(stderr, "\"\n");
1228
1229 for (j = 0; j < cfg->blocks_count; j++) {
1230 fprintf(stderr, " BB%d:\n", j);
1231 zend_dump_var_set(op_array, "def", DFG_BITSET(dfg->def, dfg->size, j));
1232 zend_dump_var_set(op_array, "use", DFG_BITSET(dfg->use, dfg->size, j));
1233 zend_dump_var_set(op_array, "in ", DFG_BITSET(dfg->in, dfg->size, j));
1234 zend_dump_var_set(op_array, "out", DFG_BITSET(dfg->out, dfg->size, j));
1235 }
1236}
1237
1238void zend_dump_phi_placement(const zend_op_array *op_array, const zend_ssa *ssa)
1239{
1240 int j;
1241 zend_ssa_block *ssa_blocks = ssa->blocks;
1242 int blocks_count = ssa->cfg.blocks_count;
1243
1244 fprintf(stderr, "\nSSA Phi() Placement for \"");
1245 zend_dump_op_array_name(op_array);
1246 fprintf(stderr, "\"\n");
1247 for (j = 0; j < blocks_count; j++) {
1248 if (ssa_blocks && ssa_blocks[j].phis) {
1249 zend_ssa_phi *p = ssa_blocks[j].phis;
1250 int first = 1;
1251
1252 fprintf(stderr, " BB%d:\n", j);
1253 if (p->pi >= 0) {
1254 fprintf(stderr, " ; pi={");
1255 } else {
1256 fprintf(stderr, " ; phi={");
1257 }
1258 do {
1259 if (first) {
1260 first = 0;
1261 } else {
1262 fprintf(stderr, ", ");
1263 }
1264 zend_dump_var(op_array, IS_CV, p->var);
1265 p = p->next;
1266 } while (p);
1267 fprintf(stderr, "}\n");
1268 }
1269 }
1270}
size_t len
Definition apprentice.c:174
fprintf($stream, string $format, mixed ... $values)
char s[4]
Definition cdf.c:77
zval * zv
Definition ffi.c:3975
zend_long n
Definition ffi.c:4979
zval * val
Definition ffi.c:4262
HashTable * ht
Definition ffi.c:4838
#define NULL
Definition gdcache.h:45
again j
unsigned const char * end
Definition php_ffi.h:51
unsigned char key[REFLECTION_KEY_LEN]
PHPAPI zend_string * php_addcslashes(zend_string *str, const char *what, size_t what_len)
Definition string.c:3836
char * msg
Definition phpdbg.h:289
zend_constant * data
p
Definition session.c:1105
uint32_t start
Definition zend_cfg.h:45
uint32_t flags
Definition zend_cfg.h:44
uint32_t * map
Definition zend_cfg.h:89
int blocks_count
Definition zend_cfg.h:85
int * predecessors
Definition zend_cfg.h:88
zend_basic_block * blocks
Definition zend_cfg.h:87
zend_string * name
Definition zend.h:149
zend_bitset def
Definition zend_dfg.h:29
uint32_t size
Definition zend_dfg.h:27
zend_bitset use
Definition zend_dfg.h:30
zend_bitset in
Definition zend_dfg.h:31
zend_bitset out
Definition zend_dfg.h:32
zend_string * filename
uint32_t line_start
zend_class_entry * scope
uint32_t num_args
zend_try_catch_element * try_catch_array
zend_string ** vars
zend_op * opcodes
zend_live_range * live_range
uint32_t line_end
zend_string * function_name
znode_op op1
uint8_t result_type
znode_op op2
znode_op result
uint8_t opcode
uint8_t op1_type
uint32_t extended_value
uint32_t lineno
uint8_t op2_type
zend_ssa_phi * phis
Definition zend_ssa.h:79
int result_use
Definition zend_ssa.h:85
int result_def
Definition zend_ssa.h:88
zend_ssa_negative_lat negative
Definition zend_ssa.h:48
zend_ssa_range range
Definition zend_ssa.h:43
zend_long max
Definition zend_ssa.h:27
zend_long min
Definition zend_ssa.h:26
zend_class_entry * ce
Definition zend_ssa.h:53
zend_ssa_range range
Definition zend_ssa.h:131
zend_class_entry * ce
Definition zend_ssa.h:132
unsigned int escape_state
Definition zend_ssa.h:118
int vars_count
Definition zend_ssa.h:137
zend_ssa_var * vars
Definition zend_ssa.h:141
zend_cfg cfg
Definition zend_ssa.h:136
zend_ssa_var_info * var_info
Definition zend_ssa.h:142
zend_ssa_op * ops
Definition zend_ssa.h:140
zend_ssa_block * blocks
Definition zend_ssa.h:139
char val[1]
Definition zend_types.h:377
uint32_t var
uint32_t num
zend_ulong * zend_bitset
Definition zend_bitset.h:29
struct _zval_struct zval
struct _zend_basic_block zend_basic_block
#define ZEND_BB_FINALLY
Definition zend_cfg.h:30
#define ZEND_BB_START
Definition zend_cfg.h:23
#define ZEND_BB_FINALLY_END
Definition zend_cfg.h:31
#define ZEND_BB_IRREDUCIBLE_LOOP
Definition zend_cfg.h:36
#define ZEND_BB_REACHABLE
Definition zend_cfg.h:38
#define ZEND_BB_UNREACHABLE_FREE
Definition zend_cfg.h:32
#define ZEND_BB_EXIT
Definition zend_cfg.h:26
struct _zend_cfg zend_cfg
#define ZEND_BB_ENTRY
Definition zend_cfg.h:27
#define CRT_CONSTANT(node)
Definition zend_cfg.h:110
#define ZEND_BB_FOLLOW
Definition zend_cfg.h:24
#define ZEND_BB_TRY
Definition zend_cfg.h:28
#define ZEND_BB_TARGET
Definition zend_cfg.h:25
#define ZEND_BB_LOOP_HEADER
Definition zend_cfg.h:35
#define ZEND_BB_CATCH
Definition zend_cfg.h:29
#define ZEND_BB_RECV_ENTRY
Definition zend_cfg.h:33
execute_data func
#define ZEND_FETCH_CLASS_SELF
#define ZEND_LIVE_MASK
#define ZEND_LIVE_TMPVAR
struct _zend_op zend_op
#define ZEND_FETCH_CLASS_AUTO
#define ZEND_LIVE_LOOP
#define ZEND_LIVE_NEW
#define ZEND_FETCH_CLASS_MASK
#define ZEND_FETCH_GLOBAL_LOCK
#define IS_CONST
#define ZEND_ARRAY_NOT_PACKED
#define IS_SMART_BRANCH_JMPNZ
#define ZEND_EVAL
#define EX_VAR_TO_NUM(n)
#define IS_VAR
#define ZEND_OFFSET_TO_OPLINE_NUM(op_array, base, offset)
#define IS_SMART_BRANCH_JMPZ
#define ZEND_FETCH_CLASS_TRAIT
#define ZEND_RETURNS_VALUE
#define ZEND_FETCH_CLASS_INTERFACE
#define ZEND_FETCH_CLASS_NO_AUTOLOAD
#define ZEND_REQUIRE
struct _zend_op_array zend_op_array
union _znode_op znode_op
#define ZEND_FETCH_REF
#define ZEND_FETCH_CLASS_STATIC
#define ZEND_FETCH_DIM_WRITE
#define ZEND_INCLUDE_ONCE
#define ZEND_FETCH_CLASS_EXCEPTION
#define ZEND_FETCH_CLASS_PARENT
#define ZEND_ARRAY_ELEMENT_REF
#define OP_JMP_ADDR(opline, node)
#define ZEND_FETCH_OBJ_FLAGS
#define ZEND_LIVE_ROPE
#define ZEND_FETCH_GLOBAL
#define ZEND_REQUIRE_ONCE
#define ZEND_INCLUDE
#define ZEND_ARRAY_SIZE_SHIFT
#define ZEND_LIVE_SILENCE
#define ZEND_ISEMPTY
#define IS_CV
#define IS_TMP_VAR
#define ZEND_FETCH_LOCAL
#define ZEND_FETCH_CLASS_SILENT
#define IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE
#define ZEND_RETURNS_FUNCTION
#define ZEND_LAST_CATCH
#define ZEND_API
struct _zend_dfg zend_dfg
#define DFG_BITSET(set, set_size, block_num)
Definition zend_dfg.h:35
void zend_dump_op_array_name(const zend_op_array *op_array)
Definition zend_dump.c:917
void zend_dump_ssa_variables(const zend_op_array *op_array, const zend_ssa *ssa, uint32_t dump_flags)
Definition zend_dump.c:1178
ZEND_API void zend_dump_op(const zend_op_array *op_array, const zend_basic_block *b, const zend_op *opline, uint32_t dump_flags, const zend_ssa *ssa, const zend_ssa_op *ssa_op)
Definition zend_dump.c:442
void zend_dump_dfg(const zend_op_array *op_array, const zend_cfg *cfg, const zend_dfg *dfg)
Definition zend_dump.c:1222
void zend_dump_const(const zval *zv)
Definition zend_dump.c:51
ZEND_API void zend_dump_var(const zend_op_array *op_array, uint8_t var_type, uint32_t var_num)
Definition zend_dump.c:140
ZEND_API void zend_dump_ssa_var(const zend_op_array *op_array, const zend_ssa *ssa, int ssa_var_num, uint8_t var_type, uint32_t var_num, uint32_t dump_flags)
Definition zend_dump.c:369
ZEND_API void zend_dump_op_line(const zend_op_array *op_array, const zend_basic_block *b, const zend_op *opline, uint32_t dump_flags, const void *data)
Definition zend_dump.c:759
void zend_dump_ht(HashTable *ht)
Definition zend_dump.c:28
ZEND_API void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_flags, const char *msg, const void *data)
Definition zend_dump.c:930
void zend_dump_phi_placement(const zend_op_array *op_array, const zend_ssa *ssa)
Definition zend_dump.c:1238
void zend_dump_dominators(const zend_op_array *op_array, const zend_cfg *cfg)
Definition zend_dump.c:1163
#define ZEND_DUMP_HIDE_UNREACHABLE
Definition zend_dump.h:27
#define ZEND_DUMP_CFG
Definition zend_dump.h:29
#define ZEND_DUMP_RC_INFERENCE
Definition zend_dump.h:28
#define ZEND_DUMP_SSA
Definition zend_dump.h:30
#define ZEND_DUMP_LINE_NUMBERS
Definition zend_dump.h:32
#define ZEND_DUMP_LIVE_RANGES
Definition zend_dump.h:31
union _zend_function zend_function
#define ZEND_OP_IS_FRAMELESS_ICALL(opcode)
#define ZEND_FLF_FUNC(opline)
#define ZEND_FUNC_NO_LOOPS
#define ZEND_FUNC_RECURSIVE_INDIRECTLY
#define ZEND_FUNC_HAS_EXTENDED_STMT
#define ZEND_FUNC_RECURSIVE_DIRECTLY
#define ZEND_FUNC_INDIRECT_VAR_ACCESS
#define ZEND_FUNC_INFO(op_array)
#define ZEND_FUNC_RECURSIVE
struct _zend_func_info zend_func_info
#define ZEND_FUNC_HAS_EXTENDED_FCALL
#define ZEND_FUNC_IRREDUCIBLE
#define ZEND_HASH_FOREACH_KEY_VAL(ht, _h, _key, _val)
Definition zend_hash.h:1181
#define ZEND_HASH_FOREACH_END()
Definition zend_hash.h:1086
#define MAY_BE_PACKED_GUARD
#define MAY_BE_GUARD
#define ZEND_LONG_MIN
Definition zend_long.h:46
uint32_t zend_ulong
Definition zend_long.h:43
#define ZEND_LONG_FMT
Definition zend_long.h:87
#define ZEND_LONG_MAX
Definition zend_long.h:45
struct _zend_string zend_string
struct _zend_class_entry zend_class_entry
struct _zend_ssa_range zend_ssa_range
struct _zend_ssa_block zend_ssa_block
@ ESCAPE_STATE_NO_ESCAPE
Definition zend_ssa.h:102
struct _zend_ssa_type_constraint zend_ssa_type_constraint
struct _zend_ssa zend_ssa
struct _zend_ssa_phi zend_ssa_phi
Definition zend_ssa.h:62
struct _zend_ssa_op zend_ssa_op
struct _zend_ssa_range_constraint zend_ssa_range_constraint
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define MAY_BE_REF
#define MAY_BE_ARRAY_OF_ANY
#define MAY_BE_STRING
#define MAY_BE_HASH(t)
#define MAY_BE_ARRAY_OF_ARRAY
#define MAY_BE_RC1
#define MAY_BE_FALSE
#define MAY_BE_ARRAY_OF_OBJECT
#define MAY_BE_ARRAY_OF_DOUBLE
#define MAY_BE_ARRAY_OF_FALSE
#define MAY_BE_ARRAY_KEY_STRING
#define MAY_BE_ARRAY_OF_NULL
#define MAY_BE_ARRAY_OF_TRUE
#define MAY_BE_ARRAY_OF_REF
#define MAY_BE_CLASS
#define MAY_BE_UNDEF
#define MAY_BE_NULL
#define MAY_BE_ARRAY_EMPTY
#define MAY_BE_PACKED_ONLY(t)
#define MAY_BE_DOUBLE
#define MAY_BE_ARRAY_OF_RESOURCE
#define MAY_BE_ARRAY_OF_LONG
#define MAY_BE_LONG
#define MAY_BE_TRUE
#define MAY_BE_ANY
#define MAY_BE_HASH_ONLY(t)
#define MAY_BE_OBJECT
#define MAY_BE_ARRAY_KEY_LONG
#define MAY_BE_PACKED(t)
#define MAY_BE_ARRAY_KEY_ANY
#define MAY_BE_INDIRECT
#define MAY_BE_ARRAY_OF_STRING
#define MAY_BE_RESOURCE
#define MAY_BE_EMPTY_ONLY(t)
#define MAY_BE_RCN
#define MAY_BE_ARRAY
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define IS_TRUE
Definition zend_types.h:603
#define IS_FALSE
Definition zend_types.h:602
#define Z_ARRVAL_P(zval_p)
Definition zend_types.h:987
#define IS_STRING
Definition zend_types.h:606
struct _zend_array HashTable
Definition zend_types.h:386
#define IS_RESOURCE
Definition zend_types.h:609
#define IS_ARRAY
Definition zend_types.h:607
#define IS_VOID
Definition zend_types.h:617
#define IS_DOUBLE
Definition zend_types.h:605
#define Z_STR_P(zval_p)
Definition zend_types.h:972
#define IS_NULL
Definition zend_types.h:601
#define IS_OBJECT
Definition zend_types.h:608
#define IS_LONG
Definition zend_types.h:604
#define _IS_BOOL
Definition zend_types.h:629
#define Z_DVAL_P(zval_p)
Definition zend_types.h:969
#define IS_NEVER
Definition zend_types.h:620
#define Z_LVAL_P(zval_p)
Definition zend_types.h:966
#define IS_CALLABLE
Definition zend_types.h:615
zend_string * name
ZEND_API const char *ZEND_FASTCALL zend_get_opcode_name(uint8_t opcode)
ZEND_API uint32_t ZEND_FASTCALL zend_get_opcode_flags(uint8_t opcode)
#define ZEND_VM_EXT_DIM_WRITE
#define ZEND_VM_EXT_EVAL
#define ZEND_VM_EXT_TYPE
#define ZEND_SWITCH_LONG
#define ZEND_VM_EXT_OP
#define ZEND_VM_EXT_REF
#define ZEND_VM_OP_THIS
#define ZEND_VM_EXT_NUM
#define ZEND_VM_OP_CLASS_FETCH
#define ZEND_VM_OP1_FLAGS(flags)
#define ZEND_VM_EXT_TYPE_MASK
#define ZEND_SWITCH_STRING
#define ZEND_VM_OP_MASK
#define ZEND_MATCH
#define ZEND_VM_OP_NUM
#define ZEND_VM_OP_CONSTRUCTOR
#define ZEND_VM_OP2_FLAGS(flags)
#define ZEND_VM_EXT_JMP_ADDR
#define ZEND_VM_EXT_SRC
#define ZEND_VM_EXT_VAR_FETCH
#define ZEND_VM_EXT_MASK
#define ZEND_VM_OP_NEXT
#define ZEND_VM_OP_TRY_CATCH
#define ZEND_VM_EXT_ARRAY_INIT
#define ZEND_VM_OP_JMP_ADDR
#define ZEND_VM_OP_CONST_FETCH
#define ZEND_CATCH
#define ZEND_VM_EXT_FETCH_REF
#define ZEND_VM_EXT_ISSET