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