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