source: src/router/php7/ext/opcache/Optimizer/zend_dump.c @ 31874

Last change on this file since 31874 was 31874, checked in by brainslayer, 3 months ago

update php

File size: 34.1 KB
Line 
1/*
2   +----------------------------------------------------------------------+
3   | Zend Engine, Bytecode Visualisation                                  |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1998-2017 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
28static 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
58static 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
91static 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
113void 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
126static 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
144static 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
303static 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
313static 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
335static 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
341static 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
383static 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
654static 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
752static 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
788static 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
807void 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
1048void 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
1063void 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
1077void 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
1102static 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
1121void 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
1137void 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 */
Note: See TracBrowser for help on using the repository browser.