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