]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-dump.c
PR middle-end/44828
[thirdparty/gcc.git] / gcc / tree-dump.c
CommitLineData
74338ff6 1/* Tree-dumping functionality for intermediate representation.
8fb69344 2 Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
3 2010 Free Software Foundation, Inc.
74338ff6 4 Written by Mark Mitchell <mark@codesourcery.com>
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
8c4c00c1 10Software Foundation; either version 3, or (at your option) any later
74338ff6 11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
8c4c00c1 19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
74338ff6 21
22#include "config.h"
23#include "system.h"
805e22b2 24#include "coretypes.h"
25#include "tm.h"
74338ff6 26#include "tree.h"
74338ff6 27#include "splay-tree.h"
74338ff6 28#include "toplev.h"
3119c950 29#include "tree-dump.h"
0f9005dd 30#include "tree-pass.h"
74338ff6 31#include "langhooks.h"
e8c5dd3c 32#include "tree-iterator.h"
74338ff6 33
9f627b1a 34static unsigned int queue (dump_info_p, const_tree, int);
d598ad0d 35static void dump_index (dump_info_p, unsigned int);
36static void dequeue_and_dump (dump_info_p);
37static void dump_new_line (dump_info_p);
38static void dump_maybe_newline (dump_info_p);
74338ff6 39
40/* Add T to the end of the queue of nodes to dump. Returns the index
41 assigned to T. */
42
43static unsigned int
9f627b1a 44queue (dump_info_p di, const_tree t, int flags)
74338ff6 45{
46 dump_queue_p dq;
47 dump_node_info_p dni;
48 unsigned int index;
49
50 /* Assign the next available index to T. */
51 index = ++di->index;
52
53 /* Obtain a new queue node. */
54 if (di->free_list)
55 {
56 dq = di->free_list;
57 di->free_list = dq->next;
58 }
59 else
4c36ffe6 60 dq = XNEW (struct dump_queue);
74338ff6 61
62 /* Create a new entry in the splay-tree. */
4c36ffe6 63 dni = XNEW (struct dump_node_info);
74338ff6 64 dni->index = index;
65 dni->binfo_p = ((flags & DUMP_BINFO) != 0);
40570cc2 66 dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
74338ff6 67 (splay_tree_value) dni);
68
69 /* Add it to the end of the queue. */
70 dq->next = 0;
71 if (!di->queue_end)
72 di->queue = dq;
73 else
74 di->queue_end->next = dq;
75 di->queue_end = dq;
76
77 /* Return the index. */
78 return index;
79}
80
81static void
d598ad0d 82dump_index (dump_info_p di, unsigned int index)
74338ff6 83{
84 fprintf (di->stream, "@%-6u ", index);
85 di->column += 8;
86}
87
88/* If T has not already been output, queue it for subsequent output.
89 FIELD is a string to print before printing the index. Then, the
90 index of T is printed. */
91
92void
9f627b1a 93queue_and_dump_index (dump_info_p di, const char *field, const_tree t, int flags)
74338ff6 94{
95 unsigned int index;
96 splay_tree_node n;
97
98 /* If there's no node, just return. This makes for fewer checks in
99 our callers. */
100 if (!t)
101 return;
102
103 /* See if we've already queued or dumped this node. */
104 n = splay_tree_lookup (di->nodes, (splay_tree_key) t);
105 if (n)
106 index = ((dump_node_info_p) n->value)->index;
107 else
108 /* If we haven't, add it to the queue. */
109 index = queue (di, t, flags);
110
111 /* Print the index of the node. */
112 dump_maybe_newline (di);
113 fprintf (di->stream, "%-4s: ", field);
114 di->column += 6;
115 dump_index (di, index);
116}
117
118/* Dump the type of T. */
119
120void
9f627b1a 121queue_and_dump_type (dump_info_p di, const_tree t)
74338ff6 122{
123 queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
124}
125
126/* Dump column control */
127#define SOL_COLUMN 25 /* Start of line column. */
128#define EOL_COLUMN 55 /* End of line column. */
129#define COLUMN_ALIGNMENT 15 /* Alignment. */
130
131/* Insert a new line in the dump output, and indent to an appropriate
132 place to start printing more fields. */
133
134static void
d598ad0d 135dump_new_line (dump_info_p di)
74338ff6 136{
137 fprintf (di->stream, "\n%*s", SOL_COLUMN, "");
138 di->column = SOL_COLUMN;
139}
140
141/* If necessary, insert a new line. */
142
143static void
d598ad0d 144dump_maybe_newline (dump_info_p di)
74338ff6 145{
146 int extra;
40570cc2 147
74338ff6 148 /* See if we need a new line. */
149 if (di->column > EOL_COLUMN)
150 dump_new_line (di);
151 /* See if we need any padding. */
152 else if ((extra = (di->column - SOL_COLUMN) % COLUMN_ALIGNMENT) != 0)
153 {
154 fprintf (di->stream, "%*s", COLUMN_ALIGNMENT - extra, "");
155 di->column += COLUMN_ALIGNMENT - extra;
156 }
157}
158
159/* Dump pointer PTR using FIELD to identify it. */
160
161void
d598ad0d 162dump_pointer (dump_info_p di, const char *field, void *ptr)
74338ff6 163{
164 dump_maybe_newline (di);
de064be9 165 fprintf (di->stream, "%-4s: %-8lx ", field, (unsigned long) ptr);
74338ff6 166 di->column += 15;
167}
168
169/* Dump integer I using FIELD to identify it. */
170
171void
d598ad0d 172dump_int (dump_info_p di, const char *field, int i)
74338ff6 173{
174 dump_maybe_newline (di);
175 fprintf (di->stream, "%-4s: %-7d ", field, i);
176 di->column += 14;
177}
178
905582c1 179/* Dump the floating point value R, using FIELD to identify it. */
180
181static void
182dump_real (dump_info_p di, const char *field, const REAL_VALUE_TYPE *r)
183{
184 char buf[32];
185 real_to_decimal (buf, r, sizeof (buf), 0, true);
186 dump_maybe_newline (di);
187 fprintf (di->stream, "%-4s: %s ", field, buf);
188 di->column += strlen (buf) + 7;
189}
190
06f0b99c 191/* Dump the fixed-point value F, using FIELD to identify it. */
192
193static void
194dump_fixed (dump_info_p di, const char *field, const FIXED_VALUE_TYPE *f)
195{
196 char buf[32];
197 fixed_to_decimal (buf, f, sizeof (buf));
198 dump_maybe_newline (di);
199 fprintf (di->stream, "%-4s: %s ", field, buf);
200 di->column += strlen (buf) + 7;
201}
202
905582c1 203
74338ff6 204/* Dump the string S. */
205
206void
d598ad0d 207dump_string (dump_info_p di, const char *string)
74338ff6 208{
209 dump_maybe_newline (di);
210 fprintf (di->stream, "%-13s ", string);
211 if (strlen (string) > 13)
212 di->column += strlen (string) + 1;
213 else
214 di->column += 14;
215}
216
217/* Dump the string field S. */
218
5a471c32 219void
d598ad0d 220dump_string_field (dump_info_p di, const char *field, const char *string)
74338ff6 221{
222 dump_maybe_newline (di);
223 fprintf (di->stream, "%-4s: %-7s ", field, string);
224 if (strlen (string) > 7)
225 di->column += 6 + strlen (string) + 1;
226 else
227 di->column += 14;
228}
229
74338ff6 230/* Dump the next node in the queue. */
231
40570cc2 232static void
d598ad0d 233dequeue_and_dump (dump_info_p di)
74338ff6 234{
235 dump_queue_p dq;
236 splay_tree_node stn;
237 dump_node_info_p dni;
238 tree t;
239 unsigned int index;
240 enum tree_code code;
ce45a448 241 enum tree_code_class code_class;
74338ff6 242 const char* code_name;
243
244 /* Get the next node from the queue. */
245 dq = di->queue;
246 stn = dq->node;
247 t = (tree) stn->key;
248 dni = (dump_node_info_p) stn->value;
249 index = dni->index;
250
251 /* Remove the node from the queue, and put it on the free list. */
252 di->queue = dq->next;
253 if (!di->queue)
254 di->queue_end = 0;
255 dq->next = di->free_list;
256 di->free_list = dq;
257
258 /* Print the node index. */
259 dump_index (di, index);
260 /* And the type of node this is. */
261 if (dni->binfo_p)
262 code_name = "binfo";
263 else
264 code_name = tree_code_name[(int) TREE_CODE (t)];
265 fprintf (di->stream, "%-16s ", code_name);
266 di->column = 25;
267
268 /* Figure out what kind of node this is. */
269 code = TREE_CODE (t);
270 code_class = TREE_CODE_CLASS (code);
271
272 /* Although BINFOs are TREE_VECs, we dump them specially so as to be
273 more informative. */
274 if (dni->binfo_p)
275 {
95f3173a 276 unsigned ix;
f6cc6a08 277 tree base;
046bfc77 278 VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (t);
d598ad0d 279
95f3173a 280 dump_child ("type", BINFO_TYPE (t));
281
57c28194 282 if (BINFO_VIRTUAL_P (t))
5a471c32 283 dump_string_field (di, "spec", "virt");
40570cc2 284
f6cc6a08 285 dump_int (di, "bases", BINFO_N_BASE_BINFOS (t));
286 for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++)
95f3173a 287 {
db77fe17 288 tree access = (accesses ? VEC_index (tree, accesses, ix)
95f3173a 289 : access_public_node);
290 const char *string = NULL;
291
292 if (access == access_public_node)
293 string = "pub";
294 else if (access == access_protected_node)
295 string = "prot";
296 else if (access == access_private_node)
297 string = "priv";
298 else
8c0963c4 299 gcc_unreachable ();
d598ad0d 300
5a471c32 301 dump_string_field (di, "accs", string);
95f3173a 302 queue_and_dump_index (di, "binf", base, DUMP_BINFO);
303 }
d598ad0d 304
74338ff6 305 goto done;
306 }
307
308 /* We can knock off a bunch of expression nodes in exactly the same
309 way. */
310 if (IS_EXPR_CODE_CLASS (code_class))
311 {
312 /* If we're dumping children, dump them now. */
313 queue_and_dump_type (di, t);
314
315 switch (code_class)
316 {
ce45a448 317 case tcc_unary:
74338ff6 318 dump_child ("op 0", TREE_OPERAND (t, 0));
319 break;
40570cc2 320
ce45a448 321 case tcc_binary:
322 case tcc_comparison:
74338ff6 323 dump_child ("op 0", TREE_OPERAND (t, 0));
324 dump_child ("op 1", TREE_OPERAND (t, 1));
325 break;
40570cc2 326
ce45a448 327 case tcc_expression:
328 case tcc_reference:
329 case tcc_statement:
f43a1a60 330 case tcc_vl_exp:
74338ff6 331 /* These nodes are handled explicitly below. */
332 break;
40570cc2 333
74338ff6 334 default:
8c0963c4 335 gcc_unreachable ();
74338ff6 336 }
337 }
338 else if (DECL_P (t))
339 {
2ed8b5d0 340 expanded_location xloc;
74338ff6 341 /* All declarations have names. */
342 if (DECL_NAME (t))
343 dump_child ("name", DECL_NAME (t));
40570cc2 344 if (DECL_ASSEMBLER_NAME_SET_P (t)
74338ff6 345 && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t))
346 dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
9021d2da 347 if (DECL_ABSTRACT_ORIGIN (t))
348 dump_child ("orig", DECL_ABSTRACT_ORIGIN (t));
74338ff6 349 /* And types. */
350 queue_and_dump_type (di, t);
351 dump_child ("scpe", DECL_CONTEXT (t));
352 /* And a source position. */
2ed8b5d0 353 xloc = expand_location (DECL_SOURCE_LOCATION (t));
354 if (xloc.file)
74338ff6 355 {
2ed8b5d0 356 const char *filename = strrchr (xloc.file, '/');
74338ff6 357 if (!filename)
2ed8b5d0 358 filename = xloc.file;
74338ff6 359 else
360 /* Skip the slash. */
361 ++filename;
362
363 dump_maybe_newline (di);
40570cc2 364 fprintf (di->stream, "srcp: %s:%-6d ", filename,
2ed8b5d0 365 xloc.line);
74338ff6 366 di->column += 6 + strlen (filename) + 8;
367 }
368 /* And any declaration can be compiler-generated. */
437f5d6b 369 if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_COMMON)
370 && DECL_ARTIFICIAL (t))
5a471c32 371 dump_string_field (di, "note", "artificial");
74338ff6 372 if (TREE_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
373 dump_child ("chan", TREE_CHAIN (t));
374 }
ce45a448 375 else if (code_class == tcc_type)
74338ff6 376 {
377 /* All types have qualifiers. */
dc24ddbd 378 int quals = lang_hooks.tree_dump.type_quals (t);
40570cc2 379
74338ff6 380 if (quals != TYPE_UNQUALIFIED)
381 {
382 fprintf (di->stream, "qual: %c%c%c ",
383 (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
384 (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
385 (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
386 di->column += 14;
387 }
388
389 /* All types have associated declarations. */
390 dump_child ("name", TYPE_NAME (t));
391
392 /* All types have a main variant. */
393 if (TYPE_MAIN_VARIANT (t) != t)
394 dump_child ("unql", TYPE_MAIN_VARIANT (t));
40570cc2 395
74338ff6 396 /* And sizes. */
397 dump_child ("size", TYPE_SIZE (t));
398
399 /* All types have alignments. */
400 dump_int (di, "algn", TYPE_ALIGN (t));
401 }
ce45a448 402 else if (code_class == tcc_constant)
74338ff6 403 /* All constants can have types. */
404 queue_and_dump_type (di, t);
405
406 /* Give the language-specific code a chance to print something. If
407 it's completely taken care of things, don't bother printing
408 anything more ourselves. */
dc24ddbd 409 if (lang_hooks.tree_dump.dump_tree (di, t))
74338ff6 410 goto done;
411
412 /* Now handle the various kinds of nodes. */
413 switch (code)
414 {
415 int i;
416
417 case IDENTIFIER_NODE:
418 dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
419 dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
420 break;
421
422 case TREE_LIST:
423 dump_child ("purp", TREE_PURPOSE (t));
424 dump_child ("valu", TREE_VALUE (t));
425 dump_child ("chan", TREE_CHAIN (t));
426 break;
427
e8c5dd3c 428 case STATEMENT_LIST:
429 {
430 tree_stmt_iterator it;
431 for (i = 0, it = tsi_start (t); !tsi_end_p (it); tsi_next (&it), i++)
432 {
433 char buffer[32];
434 sprintf (buffer, "%u", i);
435 dump_child (buffer, tsi_stmt (it));
436 }
437 }
438 break;
439
74338ff6 440 case TREE_VEC:
441 dump_int (di, "lngt", TREE_VEC_LENGTH (t));
442 for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
443 {
444 char buffer[32];
445 sprintf (buffer, "%u", i);
446 dump_child (buffer, TREE_VEC_ELT (t, i));
447 }
448 break;
449
450 case INTEGER_TYPE:
451 case ENUMERAL_TYPE:
452 dump_int (di, "prec", TYPE_PRECISION (t));
5a471c32 453 dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
74338ff6 454 dump_child ("min", TYPE_MIN_VALUE (t));
455 dump_child ("max", TYPE_MAX_VALUE (t));
456
457 if (code == ENUMERAL_TYPE)
458 dump_child ("csts", TYPE_VALUES (t));
459 break;
460
461 case REAL_TYPE:
462 dump_int (di, "prec", TYPE_PRECISION (t));
463 break;
464
06f0b99c 465 case FIXED_POINT_TYPE:
466 dump_int (di, "prec", TYPE_PRECISION (t));
467 dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
468 dump_string_field (di, "saturating",
469 TYPE_SATURATING (t) ? "saturating": "non-saturating");
470 break;
471
74338ff6 472 case POINTER_TYPE:
473 dump_child ("ptd", TREE_TYPE (t));
474 break;
475
476 case REFERENCE_TYPE:
477 dump_child ("refd", TREE_TYPE (t));
478 break;
479
480 case METHOD_TYPE:
481 dump_child ("clas", TYPE_METHOD_BASETYPE (t));
482 /* Fall through. */
483
484 case FUNCTION_TYPE:
485 dump_child ("retn", TREE_TYPE (t));
486 dump_child ("prms", TYPE_ARG_TYPES (t));
487 break;
488
489 case ARRAY_TYPE:
490 dump_child ("elts", TREE_TYPE (t));
491 dump_child ("domn", TYPE_DOMAIN (t));
492 break;
493
494 case RECORD_TYPE:
495 case UNION_TYPE:
496 if (TREE_CODE (t) == RECORD_TYPE)
5a471c32 497 dump_string_field (di, "tag", "struct");
74338ff6 498 else
5a471c32 499 dump_string_field (di, "tag", "union");
40570cc2 500
74338ff6 501 dump_child ("flds", TYPE_FIELDS (t));
502 dump_child ("fncs", TYPE_METHODS (t));
40570cc2 503 queue_and_dump_index (di, "binf", TYPE_BINFO (t),
74338ff6 504 DUMP_BINFO);
505 break;
506
507 case CONST_DECL:
508 dump_child ("cnst", DECL_INITIAL (t));
509 break;
510
688ff29b 511 case DEBUG_EXPR_DECL:
512 dump_int (di, "-uid", DEBUG_TEMP_UID (t));
513 /* Fall through. */
514
74338ff6 515 case VAR_DECL:
516 case PARM_DECL:
517 case FIELD_DECL:
518 case RESULT_DECL:
519 if (TREE_CODE (t) == PARM_DECL)
520 dump_child ("argt", DECL_ARG_TYPE (t));
521 else
522 dump_child ("init", DECL_INITIAL (t));
523 dump_child ("size", DECL_SIZE (t));
524 dump_int (di, "algn", DECL_ALIGN (t));
525
526 if (TREE_CODE (t) == FIELD_DECL)
527 {
74338ff6 528 if (DECL_FIELD_OFFSET (t))
529 dump_child ("bpos", bit_position (t));
530 }
40570cc2 531 else if (TREE_CODE (t) == VAR_DECL
74338ff6 532 || TREE_CODE (t) == PARM_DECL)
533 {
534 dump_int (di, "used", TREE_USED (t));
535 if (DECL_REGISTER (t))
5a471c32 536 dump_string_field (di, "spec", "register");
74338ff6 537 }
538 break;
539
540 case FUNCTION_DECL:
541 dump_child ("args", DECL_ARGUMENTS (t));
542 if (DECL_EXTERNAL (t))
5a471c32 543 dump_string_field (di, "body", "undefined");
74338ff6 544 if (TREE_PUBLIC (t))
5a471c32 545 dump_string_field (di, "link", "extern");
74338ff6 546 else
5a471c32 547 dump_string_field (di, "link", "static");
de9ebaea 548 if (DECL_SAVED_TREE (t) && !dump_flag (di, TDF_SLIM, t))
74338ff6 549 dump_child ("body", DECL_SAVED_TREE (t));
550 break;
551
74338ff6 552 case INTEGER_CST:
553 if (TREE_INT_CST_HIGH (t))
554 dump_int (di, "high", TREE_INT_CST_HIGH (t));
555 dump_int (di, "low", TREE_INT_CST_LOW (t));
556 break;
557
558 case STRING_CST:
559 fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
560 dump_int (di, "lngt", TREE_STRING_LENGTH (t));
561 break;
562
905582c1 563 case REAL_CST:
564 dump_real (di, "valu", TREE_REAL_CST_PTR (t));
565 break;
566
06f0b99c 567 case FIXED_CST:
568 dump_fixed (di, "valu", TREE_FIXED_CST_PTR (t));
569 break;
570
74338ff6 571 case TRUTH_NOT_EXPR:
572 case ADDR_EXPR:
573 case INDIRECT_REF:
b056d812 574 case MISALIGNED_INDIRECT_REF:
74338ff6 575 case CLEANUP_POINT_EXPR:
576 case SAVE_EXPR:
b25de375 577 case REALPART_EXPR:
578 case IMAGPART_EXPR:
74338ff6 579 /* These nodes are unary, but do not have code class `1'. */
580 dump_child ("op 0", TREE_OPERAND (t, 0));
581 break;
582
583 case TRUTH_ANDIF_EXPR:
584 case TRUTH_ORIF_EXPR:
585 case INIT_EXPR:
586 case MODIFY_EXPR:
74338ff6 587 case COMPOUND_EXPR:
74338ff6 588 case PREDECREMENT_EXPR:
589 case PREINCREMENT_EXPR:
590 case POSTDECREMENT_EXPR:
591 case POSTINCREMENT_EXPR:
592 /* These nodes are binary, but do not have code class `2'. */
593 dump_child ("op 0", TREE_OPERAND (t, 0));
594 dump_child ("op 1", TREE_OPERAND (t, 1));
595 break;
596
6374121b 597 case COMPONENT_REF:
598 dump_child ("op 0", TREE_OPERAND (t, 0));
599 dump_child ("op 1", TREE_OPERAND (t, 1));
600 dump_child ("op 2", TREE_OPERAND (t, 2));
601 break;
602
603 case ARRAY_REF:
604 case ARRAY_RANGE_REF:
605 dump_child ("op 0", TREE_OPERAND (t, 0));
606 dump_child ("op 1", TREE_OPERAND (t, 1));
607 dump_child ("op 2", TREE_OPERAND (t, 2));
608 dump_child ("op 3", TREE_OPERAND (t, 3));
609 break;
610
74338ff6 611 case COND_EXPR:
612 dump_child ("op 0", TREE_OPERAND (t, 0));
613 dump_child ("op 1", TREE_OPERAND (t, 1));
614 dump_child ("op 2", TREE_OPERAND (t, 2));
615 break;
616
9021d2da 617 case TRY_FINALLY_EXPR:
618 dump_child ("op 0", TREE_OPERAND (t, 0));
619 dump_child ("op 1", TREE_OPERAND (t, 1));
620 break;
621
74338ff6 622 case CALL_EXPR:
c2f47e15 623 {
624 int i = 0;
625 tree arg;
626 call_expr_arg_iterator iter;
627 dump_child ("fn", CALL_EXPR_FN (t));
628 FOR_EACH_CALL_EXPR_ARG (arg, iter, t)
629 {
630 char buffer[32];
631 sprintf (buffer, "%u", i);
632 dump_child (buffer, arg);
633 i++;
634 }
635 }
74338ff6 636 break;
637
638 case CONSTRUCTOR:
c75b4594 639 {
640 unsigned HOST_WIDE_INT cnt;
641 tree index, value;
642 dump_int (di, "lngt", VEC_length (constructor_elt,
643 CONSTRUCTOR_ELTS (t)));
644 FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value)
645 {
646 dump_child ("idx", index);
647 dump_child ("val", value);
648 }
649 }
74338ff6 650 break;
651
74338ff6 652 case BIND_EXPR:
653 dump_child ("vars", TREE_OPERAND (t, 0));
654 dump_child ("body", TREE_OPERAND (t, 1));
655 break;
656
657 case LOOP_EXPR:
658 dump_child ("body", TREE_OPERAND (t, 0));
659 break;
660
661 case EXIT_EXPR:
662 dump_child ("cond", TREE_OPERAND (t, 0));
663 break;
664
9021d2da 665 case RETURN_EXPR:
666 dump_child ("expr", TREE_OPERAND (t, 0));
667 break;
668
74338ff6 669 case TARGET_EXPR:
670 dump_child ("decl", TREE_OPERAND (t, 0));
671 dump_child ("init", TREE_OPERAND (t, 1));
672 dump_child ("clnp", TREE_OPERAND (t, 2));
673 /* There really are two possible places the initializer can be.
674 After RTL expansion, the second operand is moved to the
675 position of the fourth operand, and the second operand
676 becomes NULL. */
677 dump_child ("init", TREE_OPERAND (t, 3));
678 break;
40570cc2 679
9021d2da 680 case CASE_LABEL_EXPR:
681 dump_child ("name", CASE_LABEL (t));
7d4c98bc 682 if (CASE_LOW (t))
683 {
684 dump_child ("low ", CASE_LOW (t));
685 if (CASE_HIGH (t))
686 dump_child ("high", CASE_HIGH (t));
9021d2da 687 }
9021d2da 688 break;
689 case LABEL_EXPR:
690 dump_child ("name", TREE_OPERAND (t,0));
691 break;
692 case GOTO_EXPR:
693 dump_child ("labl", TREE_OPERAND (t, 0));
694 break;
695 case SWITCH_EXPR:
696 dump_child ("cond", TREE_OPERAND (t, 0));
697 dump_child ("body", TREE_OPERAND (t, 1));
698 if (TREE_OPERAND (t, 2))
699 {
700 dump_child ("labl", TREE_OPERAND (t,2));
701 }
702 break;
55d6e7cd 703 case OMP_CLAUSE:
704 {
705 int i;
706 fprintf (di->stream, "%s\n", omp_clause_code_name[OMP_CLAUSE_CODE (t)]);
707 for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; i++)
708 dump_child ("op: ", OMP_CLAUSE_OPERAND (t, i));
709 }
710 break;
74338ff6 711 default:
712 /* There are no additional fields to print. */
713 break;
714 }
715
716 done:
717 if (dump_flag (di, TDF_ADDRESS, NULL))
718 dump_pointer (di, "addr", (void *)t);
40570cc2 719
74338ff6 720 /* Terminate the line. */
721 fprintf (di->stream, "\n");
722}
723
f712a0dc 724/* Return nonzero if FLAG has been specified for the dump, and NODE
74338ff6 725 is not the root node of the dump. */
726
9f627b1a 727int dump_flag (dump_info_p di, int flag, const_tree node)
74338ff6 728{
729 return (di->flags & flag) && (node != di->node);
730}
731
732/* Dump T, and all its children, on STREAM. */
733
734void
9f627b1a 735dump_node (const_tree t, int flags, FILE *stream)
74338ff6 736{
737 struct dump_info di;
738 dump_queue_p dq;
739 dump_queue_p next_dq;
740
741 /* Initialize the dump-information structure. */
742 di.stream = stream;
743 di.index = 0;
744 di.column = 0;
745 di.queue = 0;
746 di.queue_end = 0;
747 di.free_list = 0;
748 di.flags = flags;
749 di.node = t;
40570cc2 750 di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
74338ff6 751 (splay_tree_delete_value_fn) &free);
752
753 /* Queue up the first node. */
754 queue (&di, t, DUMP_NONE);
755
756 /* Until the queue is empty, keep dumping nodes. */
757 while (di.queue)
758 dequeue_and_dump (&di);
759
760 /* Now, clean up. */
761 for (dq = di.free_list; dq; dq = next_dq)
762 {
763 next_dq = dq->next;
764 free (dq);
765 }
766 splay_tree_delete (di.nodes);
767}
0f9005dd 768\f
74338ff6 769
770/* Table of tree dump switches. This must be consistent with the
fb5b6d1b 771 tree_dump_index enumeration in tree-pass.h. */
74338ff6 772static struct dump_file_info dump_files[TDI_end] =
773{
5d48fdb4 774 {NULL, NULL, NULL, 0, 0, 0},
775 {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0, 0},
776 {".tu", "translation-unit", NULL, TDF_TREE, 0, 1},
777 {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2},
778 {".original", "tree-original", NULL, TDF_TREE, 0, 3},
779 {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4},
780 {".nested", "tree-nested", NULL, TDF_TREE, 0, 5},
781 {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 6},
f608fcb7 782 {".ads", "ada-spec", NULL, 0, 0, 7},
783#define FIRST_AUTO_NUMBERED_DUMP 8
6354626c 784
5d48fdb4 785 {NULL, "tree-all", NULL, TDF_TREE, 0, 0},
786 {NULL, "rtl-all", NULL, TDF_RTL, 0, 0},
787 {NULL, "ipa-all", NULL, TDF_IPA, 0, 0},
74338ff6 788};
789
4ee9c684 790/* Dynamically registered tree dump files and switches. */
791static struct dump_file_info *extra_dump_files;
792static size_t extra_dump_files_in_use;
793static size_t extra_dump_files_alloced;
794
74338ff6 795/* Define a name->number mapping for a dump flag value. */
796struct dump_option_value_info
797{
798 const char *const name; /* the name of the value */
799 const int value; /* the value of the name */
800};
801
802/* Table of dump options. This must be consistent with the TDF_* flags
803 in tree.h */
804static const struct dump_option_value_info dump_options[] =
805{
806 {"address", TDF_ADDRESS},
8c1f2562 807 {"asmname", TDF_ASMNAME},
74338ff6 808 {"slim", TDF_SLIM},
4ee9c684 809 {"raw", TDF_RAW},
48926532 810 {"graph", TDF_GRAPH},
4ee9c684 811 {"details", TDF_DETAILS},
812 {"stats", TDF_STATS},
813 {"blocks", TDF_BLOCKS},
814 {"vops", TDF_VOPS},
815 {"lineno", TDF_LINENO},
816 {"uid", TDF_UID},
22aa74c4 817 {"stmtaddr", TDF_STMTADDR},
4fb5e5ca 818 {"memsyms", TDF_MEMSYMS},
46412a37 819 {"verbose", TDF_VERBOSE},
d60ec13d 820 {"eh", TDF_EH},
1a981e1a 821 {"alias", TDF_ALIAS},
00753696 822 {"nouid", TDF_NOUID},
48e1416a 823 {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA
75a70cf9 824 | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE
43bb43e1 825 | TDF_RHS_ONLY | TDF_NOUID)},
74338ff6 826 {NULL, 0}
827};
828
4ee9c684 829unsigned int
53907817 830dump_register (const char *suffix, const char *swtch, const char *glob,
20099e35 831 int flags)
4ee9c684 832{
6354626c 833 static int next_dump = FIRST_AUTO_NUMBERED_DUMP;
834 int num = next_dump++;
835
f4e36c33 836 size_t count = extra_dump_files_in_use++;
4ee9c684 837
f4e36c33 838 if (count >= extra_dump_files_alloced)
4ee9c684 839 {
840 if (extra_dump_files_alloced == 0)
841 extra_dump_files_alloced = 32;
842 else
843 extra_dump_files_alloced *= 2;
45ba1503 844 extra_dump_files = XRESIZEVEC (struct dump_file_info,
845 extra_dump_files,
846 extra_dump_files_alloced);
4ee9c684 847 }
848
f4e36c33 849 memset (&extra_dump_files[count], 0, sizeof (struct dump_file_info));
850 extra_dump_files[count].suffix = suffix;
851 extra_dump_files[count].swtch = swtch;
852 extra_dump_files[count].glob = glob;
853 extra_dump_files[count].flags = flags;
854 extra_dump_files[count].num = num;
4ee9c684 855
f4e36c33 856 return count + TDI_end;
4ee9c684 857}
858
0f9005dd 859
4ee9c684 860/* Return the dump_file_info for the given phase. */
861
0f9005dd 862struct dump_file_info *
b9c74b4d 863get_dump_file_info (int phase)
4ee9c684 864{
865 if (phase < TDI_end)
866 return &dump_files[phase];
b9c74b4d 867 else if ((size_t) (phase - TDI_end) >= extra_dump_files_in_use)
0f9005dd 868 return NULL;
4ee9c684 869 else
870 return extra_dump_files + (phase - TDI_end);
871}
872
873
0f9005dd 874/* Return the name of the dump file for the given phase.
875 If the dump is not enabled, returns NULL. */
876
877char *
b9c74b4d 878get_dump_file_name (int phase)
0f9005dd 879{
6354626c 880 char dump_id[10];
0f9005dd 881 struct dump_file_info *dfi;
882
883 if (phase == TDI_none)
884 return NULL;
885
886 dfi = get_dump_file_info (phase);
887 if (dfi->state == 0)
888 return NULL;
889
121f3051 890 if (dfi->num < 0)
0f9005dd 891 dump_id[0] = '\0';
121f3051 892 else
893 {
6354626c 894 char suffix;
121f3051 895 if (dfi->flags & TDF_TREE)
6354626c 896 suffix = 't';
121f3051 897 else if (dfi->flags & TDF_IPA)
6354626c 898 suffix = 'i';
121f3051 899 else
6354626c 900 suffix = 'r';
121f3051 901
6354626c 902 if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
121f3051 903 dump_id[0] = '\0';
904 }
0f9005dd 905
906 return concat (dump_base_name, dump_id, dfi->suffix, NULL);
907}
908
74338ff6 909/* Begin a tree dump for PHASE. Stores any user supplied flag in
910 *FLAG_PTR and returns a stream to write to. If the dump is not
911 enabled, returns NULL.
912 Multiple calls will reopen and append to the dump file. */
913
914FILE *
b9c74b4d 915dump_begin (int phase, int *flag_ptr)
74338ff6 916{
74338ff6 917 char *name;
4ee9c684 918 struct dump_file_info *dfi;
0f9005dd 919 FILE *stream;
40570cc2 920
0f9005dd 921 if (phase == TDI_none || !dump_enabled_p (phase))
74338ff6 922 return NULL;
40570cc2 923
0f9005dd 924 name = get_dump_file_name (phase);
4ee9c684 925 dfi = get_dump_file_info (phase);
4ee9c684 926 stream = fopen (name, dfi->state < 0 ? "w" : "a");
74338ff6 927 if (!stream)
8fb69344 928 error ("could not open dump file %qs: %m", name);
74338ff6 929 else
4ee9c684 930 dfi->state = 1;
74338ff6 931 free (name);
4ee9c684 932
74338ff6 933 if (flag_ptr)
4ee9c684 934 *flag_ptr = dfi->flags;
40570cc2 935
74338ff6 936 return stream;
937}
938
9021d2da 939/* Returns nonzero if tree dump PHASE is enabled. If PHASE is
940 TDI_tree_all, return nonzero if any dump is enabled. */
74338ff6 941
942int
b9c74b4d 943dump_enabled_p (int phase)
74338ff6 944{
9021d2da 945 if (phase == TDI_tree_all)
946 {
947 size_t i;
948 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
949 if (dump_files[i].state)
950 return 1;
951 for (i = 0; i < extra_dump_files_in_use; i++)
952 if (extra_dump_files[i].state)
953 return 1;
954 return 0;
955 }
956 else
957 {
958 struct dump_file_info *dfi = get_dump_file_info (phase);
959 return dfi->state;
960 }
74338ff6 961}
962
0f9005dd 963/* Returns nonzero if tree dump PHASE has been initialized. */
964
965int
b9c74b4d 966dump_initialized_p (int phase)
0f9005dd 967{
968 struct dump_file_info *dfi = get_dump_file_info (phase);
969 return dfi->state > 0;
970}
971
74338ff6 972/* Returns the switch name of PHASE. */
973
974const char *
b9c74b4d 975dump_flag_name (int phase)
74338ff6 976{
4ee9c684 977 struct dump_file_info *dfi = get_dump_file_info (phase);
978 return dfi->swtch;
74338ff6 979}
980
981/* Finish a tree dump for PHASE. STREAM is the stream created by
982 dump_begin. */
983
984void
b9c74b4d 985dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
74338ff6 986{
987 fclose (stream);
988}
989
0f9005dd 990/* Enable all tree dumps. Return number of enabled tree dumps. */
4ee9c684 991
0f9005dd 992static int
5d48fdb4 993dump_enable_all (int flags)
4ee9c684 994{
15b8fe07 995 int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
0f9005dd 996 int n = 0;
4ee9c684 997 size_t i;
998
999 for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
5d48fdb4 1000 if ((dump_files[i].flags & ir_dump_type))
0f9005dd 1001 {
1002 dump_files[i].state = -1;
75ab26dc 1003 dump_files[i].flags |= flags;
0f9005dd 1004 n++;
1005 }
4ee9c684 1006
1007 for (i = 0; i < extra_dump_files_in_use; i++)
5d48fdb4 1008 if ((extra_dump_files[i].flags & ir_dump_type))
0f9005dd 1009 {
1010 extra_dump_files[i].state = -1;
75ab26dc 1011 extra_dump_files[i].flags |= flags;
0f9005dd 1012 n++;
1013 }
4ee9c684 1014
0f9005dd 1015 return n;
4ee9c684 1016}
1017
f712a0dc 1018/* Parse ARG as a dump switch. Return nonzero if it is, and store the
74338ff6 1019 relevant details in the dump_files array. */
1020
4ee9c684 1021static int
53907817 1022dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
74338ff6 1023{
74338ff6 1024 const char *option_value;
4ee9c684 1025 const char *ptr;
1026 int flags;
48e1416a 1027
53907817 1028 if (doglob && !dfi->glob)
1029 return 0;
40570cc2 1030
53907817 1031 option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
4ee9c684 1032 if (!option_value)
1033 return 0;
40570cc2 1034
2b304bd2 1035 if (*option_value && *option_value != '-')
1036 return 0;
1037
4ee9c684 1038 ptr = option_value;
1039 flags = 0;
1040
1041 while (*ptr)
1042 {
1043 const struct dump_option_value_info *option_ptr;
1044 const char *end_ptr;
1045 unsigned length;
1046
1047 while (*ptr == '-')
1048 ptr++;
1049 end_ptr = strchr (ptr, '-');
1050 if (!end_ptr)
1051 end_ptr = ptr + strlen (ptr);
1052 length = end_ptr - ptr;
1053
1054 for (option_ptr = dump_options; option_ptr->name; option_ptr++)
1055 if (strlen (option_ptr->name) == length
1056 && !memcmp (option_ptr->name, ptr, length))
74338ff6 1057 {
4ee9c684 1058 flags |= option_ptr->value;
1059 goto found;
74338ff6 1060 }
c3ceba8e 1061 warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
4ee9c684 1062 length, ptr, dfi->swtch);
1063 found:;
1064 ptr = end_ptr;
1065 }
1066
1067 dfi->state = -1;
0f9005dd 1068 dfi->flags |= flags;
4ee9c684 1069
0f9005dd 1070 /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
1071 known dumps. */
4ee9c684 1072 if (dfi->suffix == NULL)
5d48fdb4 1073 dump_enable_all (dfi->flags);
4ee9c684 1074
1075 return 1;
1076}
40570cc2 1077
4ee9c684 1078int
1079dump_switch_p (const char *arg)
1080{
1081 size_t i;
1082 int any = 0;
1083
1084 for (i = TDI_none + 1; i != TDI_end; i++)
53907817 1085 any |= dump_switch_p_1 (arg, &dump_files[i], false);
1086
1087 /* Don't glob if we got a hit already */
1088 if (!any)
1089 for (i = TDI_none + 1; i != TDI_end; i++)
1090 any |= dump_switch_p_1 (arg, &dump_files[i], true);
4ee9c684 1091
1092 for (i = 0; i < extra_dump_files_in_use; i++)
53907817 1093 any |= dump_switch_p_1 (arg, &extra_dump_files[i], false);
48e1416a 1094
53907817 1095 if (!any)
1096 for (i = 0; i < extra_dump_files_in_use; i++)
1097 any |= dump_switch_p_1 (arg, &extra_dump_files[i], true);
1098
4ee9c684 1099
1100 return any;
1101}
40570cc2 1102
4ee9c684 1103/* Dump FUNCTION_DECL FN as tree dump PHASE. */
1104
1105void
b9c74b4d 1106dump_function (int phase, tree fn)
4ee9c684 1107{
1108 FILE *stream;
1109 int flags;
1110
1111 stream = dump_begin (phase, &flags);
1112 if (stream)
1113 {
1114 dump_function_to_file (fn, stream, flags);
1115 dump_end (phase, stream);
1116 }
74338ff6 1117}
0f9005dd 1118
1119bool
5d48fdb4 1120enable_rtl_dump_file (void)
0f9005dd 1121{
5d48fdb4 1122 return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
0f9005dd 1123}