IA MCU psABI support: changes to libraries
[gcc.git] / gcc / tree-dump.c
1 /* Tree-dumping functionality for intermediate representation.
2 Copyright (C) 1999-2015 Free Software Foundation, Inc.
3 Written by Mark Mitchell <mark@codesourcery.com>
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "alias.h"
26 #include "symtab.h"
27 #include "tree.h"
28 #include "splay-tree.h"
29 #include "filenames.h"
30 #include "tree-dump.h"
31 #include "langhooks.h"
32 #include "tree-iterator.h"
33 #include "tree-pretty-print.h"
34 #include "tree-cfg.h"
35 #include "wide-int-print.h"
36
37 static unsigned int queue (dump_info_p, const_tree, int);
38 static void dump_index (dump_info_p, unsigned int);
39 static void dequeue_and_dump (dump_info_p);
40 static void dump_new_line (dump_info_p);
41 static void dump_maybe_newline (dump_info_p);
42
43 /* Add T to the end of the queue of nodes to dump. Returns the index
44 assigned to T. */
45
46 static unsigned int
47 queue (dump_info_p di, const_tree t, int flags)
48 {
49 dump_queue_p dq;
50 dump_node_info_p dni;
51 unsigned int index;
52
53 /* Assign the next available index to T. */
54 index = ++di->index;
55
56 /* Obtain a new queue node. */
57 if (di->free_list)
58 {
59 dq = di->free_list;
60 di->free_list = dq->next;
61 }
62 else
63 dq = XNEW (struct dump_queue);
64
65 /* Create a new entry in the splay-tree. */
66 dni = XNEW (struct dump_node_info);
67 dni->index = index;
68 dni->binfo_p = ((flags & DUMP_BINFO) != 0);
69 dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
70 (splay_tree_value) dni);
71
72 /* Add it to the end of the queue. */
73 dq->next = 0;
74 if (!di->queue_end)
75 di->queue = dq;
76 else
77 di->queue_end->next = dq;
78 di->queue_end = dq;
79
80 /* Return the index. */
81 return index;
82 }
83
84 static void
85 dump_index (dump_info_p di, unsigned int index)
86 {
87 fprintf (di->stream, "@%-6u ", index);
88 di->column += 8;
89 }
90
91 /* If T has not already been output, queue it for subsequent output.
92 FIELD is a string to print before printing the index. Then, the
93 index of T is printed. */
94
95 void
96 queue_and_dump_index (dump_info_p di, const char *field, const_tree t, int flags)
97 {
98 unsigned int index;
99 splay_tree_node n;
100
101 /* If there's no node, just return. This makes for fewer checks in
102 our callers. */
103 if (!t)
104 return;
105
106 /* See if we've already queued or dumped this node. */
107 n = splay_tree_lookup (di->nodes, (splay_tree_key) t);
108 if (n)
109 index = ((dump_node_info_p) n->value)->index;
110 else
111 /* If we haven't, add it to the queue. */
112 index = queue (di, t, flags);
113
114 /* Print the index of the node. */
115 dump_maybe_newline (di);
116 fprintf (di->stream, "%-4s: ", field);
117 di->column += 6;
118 dump_index (di, index);
119 }
120
121 /* Dump the type of T. */
122
123 void
124 queue_and_dump_type (dump_info_p di, const_tree t)
125 {
126 queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
127 }
128
129 /* Dump column control */
130 #define SOL_COLUMN 25 /* Start of line column. */
131 #define EOL_COLUMN 55 /* End of line column. */
132 #define COLUMN_ALIGNMENT 15 /* Alignment. */
133
134 /* Insert a new line in the dump output, and indent to an appropriate
135 place to start printing more fields. */
136
137 static void
138 dump_new_line (dump_info_p di)
139 {
140 fprintf (di->stream, "\n%*s", SOL_COLUMN, "");
141 di->column = SOL_COLUMN;
142 }
143
144 /* If necessary, insert a new line. */
145
146 static void
147 dump_maybe_newline (dump_info_p di)
148 {
149 int extra;
150
151 /* See if we need a new line. */
152 if (di->column > EOL_COLUMN)
153 dump_new_line (di);
154 /* See if we need any padding. */
155 else if ((extra = (di->column - SOL_COLUMN) % COLUMN_ALIGNMENT) != 0)
156 {
157 fprintf (di->stream, "%*s", COLUMN_ALIGNMENT - extra, "");
158 di->column += COLUMN_ALIGNMENT - extra;
159 }
160 }
161
162 /* Dump FUNCTION_DECL FN as tree dump PHASE. */
163
164 void
165 dump_function (int phase, tree fn)
166 {
167 FILE *stream;
168 int flags;
169
170 stream = dump_begin (phase, &flags);
171 if (stream)
172 {
173 dump_function_to_file (fn, stream, flags);
174 dump_end (phase, stream);
175 }
176 }
177
178 /* Dump pointer PTR using FIELD to identify it. */
179
180 void
181 dump_pointer (dump_info_p di, const char *field, void *ptr)
182 {
183 dump_maybe_newline (di);
184 fprintf (di->stream, "%-4s: %-8" HOST_WIDE_INT_PRINT "x ", field,
185 (unsigned HOST_WIDE_INT) (uintptr_t) ptr);
186 di->column += 15;
187 }
188
189 /* Dump integer I using FIELD to identify it. */
190
191 void
192 dump_int (dump_info_p di, const char *field, int i)
193 {
194 dump_maybe_newline (di);
195 fprintf (di->stream, "%-4s: %-7d ", field, i);
196 di->column += 14;
197 }
198
199 /* Dump the floating point value R, using FIELD to identify it. */
200
201 static void
202 dump_real (dump_info_p di, const char *field, const REAL_VALUE_TYPE *r)
203 {
204 char buf[32];
205 real_to_decimal (buf, r, sizeof (buf), 0, true);
206 dump_maybe_newline (di);
207 fprintf (di->stream, "%-4s: %s ", field, buf);
208 di->column += strlen (buf) + 7;
209 }
210
211 /* Dump the fixed-point value F, using FIELD to identify it. */
212
213 static void
214 dump_fixed (dump_info_p di, const char *field, const FIXED_VALUE_TYPE *f)
215 {
216 char buf[32];
217 fixed_to_decimal (buf, f, sizeof (buf));
218 dump_maybe_newline (di);
219 fprintf (di->stream, "%-4s: %s ", field, buf);
220 di->column += strlen (buf) + 7;
221 }
222
223
224 /* Dump the string S. */
225
226 void
227 dump_string (dump_info_p di, const char *string)
228 {
229 dump_maybe_newline (di);
230 fprintf (di->stream, "%-13s ", string);
231 if (strlen (string) > 13)
232 di->column += strlen (string) + 1;
233 else
234 di->column += 14;
235 }
236
237 /* Dump the string field S. */
238
239 void
240 dump_string_field (dump_info_p di, const char *field, const char *string)
241 {
242 dump_maybe_newline (di);
243 fprintf (di->stream, "%-4s: %-7s ", field, string);
244 if (strlen (string) > 7)
245 di->column += 6 + strlen (string) + 1;
246 else
247 di->column += 14;
248 }
249
250 /* Dump the next node in the queue. */
251
252 static void
253 dequeue_and_dump (dump_info_p di)
254 {
255 dump_queue_p dq;
256 splay_tree_node stn;
257 dump_node_info_p dni;
258 tree t;
259 unsigned int index;
260 enum tree_code code;
261 enum tree_code_class code_class;
262 const char* code_name;
263
264 /* Get the next node from the queue. */
265 dq = di->queue;
266 stn = dq->node;
267 t = (tree) stn->key;
268 dni = (dump_node_info_p) stn->value;
269 index = dni->index;
270
271 /* Remove the node from the queue, and put it on the free list. */
272 di->queue = dq->next;
273 if (!di->queue)
274 di->queue_end = 0;
275 dq->next = di->free_list;
276 di->free_list = dq;
277
278 /* Print the node index. */
279 dump_index (di, index);
280 /* And the type of node this is. */
281 if (dni->binfo_p)
282 code_name = "binfo";
283 else
284 code_name = get_tree_code_name (TREE_CODE (t));
285 fprintf (di->stream, "%-16s ", code_name);
286 di->column = 25;
287
288 /* Figure out what kind of node this is. */
289 code = TREE_CODE (t);
290 code_class = TREE_CODE_CLASS (code);
291
292 /* Although BINFOs are TREE_VECs, we dump them specially so as to be
293 more informative. */
294 if (dni->binfo_p)
295 {
296 unsigned ix;
297 tree base;
298 vec<tree, va_gc> *accesses = BINFO_BASE_ACCESSES (t);
299
300 dump_child ("type", BINFO_TYPE (t));
301
302 if (BINFO_VIRTUAL_P (t))
303 dump_string_field (di, "spec", "virt");
304
305 dump_int (di, "bases", BINFO_N_BASE_BINFOS (t));
306 for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++)
307 {
308 tree access = (accesses ? (*accesses)[ix] : access_public_node);
309 const char *string = NULL;
310
311 if (access == access_public_node)
312 string = "pub";
313 else if (access == access_protected_node)
314 string = "prot";
315 else if (access == access_private_node)
316 string = "priv";
317 else
318 gcc_unreachable ();
319
320 dump_string_field (di, "accs", string);
321 queue_and_dump_index (di, "binf", base, DUMP_BINFO);
322 }
323
324 goto done;
325 }
326
327 /* We can knock off a bunch of expression nodes in exactly the same
328 way. */
329 if (IS_EXPR_CODE_CLASS (code_class))
330 {
331 /* If we're dumping children, dump them now. */
332 queue_and_dump_type (di, t);
333
334 switch (code_class)
335 {
336 case tcc_unary:
337 dump_child ("op 0", TREE_OPERAND (t, 0));
338 break;
339
340 case tcc_binary:
341 case tcc_comparison:
342 dump_child ("op 0", TREE_OPERAND (t, 0));
343 dump_child ("op 1", TREE_OPERAND (t, 1));
344 break;
345
346 case tcc_expression:
347 case tcc_reference:
348 case tcc_statement:
349 case tcc_vl_exp:
350 /* These nodes are handled explicitly below. */
351 break;
352
353 default:
354 gcc_unreachable ();
355 }
356 }
357 else if (DECL_P (t))
358 {
359 expanded_location xloc;
360 /* All declarations have names. */
361 if (DECL_NAME (t))
362 dump_child ("name", DECL_NAME (t));
363 if (DECL_ASSEMBLER_NAME_SET_P (t)
364 && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t))
365 dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
366 if (DECL_ABSTRACT_ORIGIN (t))
367 dump_child ("orig", DECL_ABSTRACT_ORIGIN (t));
368 /* And types. */
369 queue_and_dump_type (di, t);
370 dump_child ("scpe", DECL_CONTEXT (t));
371 /* And a source position. */
372 xloc = expand_location (DECL_SOURCE_LOCATION (t));
373 if (xloc.file)
374 {
375 const char *filename = lbasename (xloc.file);
376
377 dump_maybe_newline (di);
378 fprintf (di->stream, "srcp: %s:%-6d ", filename,
379 xloc.line);
380 di->column += 6 + strlen (filename) + 8;
381 }
382 /* And any declaration can be compiler-generated. */
383 if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_COMMON)
384 && DECL_ARTIFICIAL (t))
385 dump_string_field (di, "note", "artificial");
386 if (DECL_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
387 dump_child ("chain", DECL_CHAIN (t));
388 }
389 else if (code_class == tcc_type)
390 {
391 /* All types have qualifiers. */
392 int quals = lang_hooks.tree_dump.type_quals (t);
393
394 if (quals != TYPE_UNQUALIFIED)
395 {
396 fprintf (di->stream, "qual: %c%c%c ",
397 (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
398 (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
399 (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
400 di->column += 14;
401 }
402
403 /* All types have associated declarations. */
404 dump_child ("name", TYPE_NAME (t));
405
406 /* All types have a main variant. */
407 if (TYPE_MAIN_VARIANT (t) != t)
408 dump_child ("unql", TYPE_MAIN_VARIANT (t));
409
410 /* And sizes. */
411 dump_child ("size", TYPE_SIZE (t));
412
413 /* All types have alignments. */
414 dump_int (di, "algn", TYPE_ALIGN (t));
415 }
416 else if (code_class == tcc_constant)
417 /* All constants can have types. */
418 queue_and_dump_type (di, t);
419
420 /* Give the language-specific code a chance to print something. If
421 it's completely taken care of things, don't bother printing
422 anything more ourselves. */
423 if (lang_hooks.tree_dump.dump_tree (di, t))
424 goto done;
425
426 /* Now handle the various kinds of nodes. */
427 switch (code)
428 {
429 int i;
430
431 case IDENTIFIER_NODE:
432 dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
433 dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
434 break;
435
436 case TREE_LIST:
437 dump_child ("purp", TREE_PURPOSE (t));
438 dump_child ("valu", TREE_VALUE (t));
439 dump_child ("chan", TREE_CHAIN (t));
440 break;
441
442 case STATEMENT_LIST:
443 {
444 tree_stmt_iterator it;
445 for (i = 0, it = tsi_start (t); !tsi_end_p (it); tsi_next (&it), i++)
446 {
447 char buffer[32];
448 sprintf (buffer, "%u", i);
449 dump_child (buffer, tsi_stmt (it));
450 }
451 }
452 break;
453
454 case TREE_VEC:
455 dump_int (di, "lngt", TREE_VEC_LENGTH (t));
456 for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
457 {
458 char buffer[32];
459 sprintf (buffer, "%u", i);
460 dump_child (buffer, TREE_VEC_ELT (t, i));
461 }
462 break;
463
464 case INTEGER_TYPE:
465 case ENUMERAL_TYPE:
466 dump_int (di, "prec", TYPE_PRECISION (t));
467 dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
468 dump_child ("min", TYPE_MIN_VALUE (t));
469 dump_child ("max", TYPE_MAX_VALUE (t));
470
471 if (code == ENUMERAL_TYPE)
472 dump_child ("csts", TYPE_VALUES (t));
473 break;
474
475 case REAL_TYPE:
476 dump_int (di, "prec", TYPE_PRECISION (t));
477 break;
478
479 case FIXED_POINT_TYPE:
480 dump_int (di, "prec", TYPE_PRECISION (t));
481 dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
482 dump_string_field (di, "saturating",
483 TYPE_SATURATING (t) ? "saturating": "non-saturating");
484 break;
485
486 case POINTER_TYPE:
487 dump_child ("ptd", TREE_TYPE (t));
488 break;
489
490 case REFERENCE_TYPE:
491 dump_child ("refd", TREE_TYPE (t));
492 break;
493
494 case METHOD_TYPE:
495 dump_child ("clas", TYPE_METHOD_BASETYPE (t));
496 /* Fall through. */
497
498 case FUNCTION_TYPE:
499 dump_child ("retn", TREE_TYPE (t));
500 dump_child ("prms", TYPE_ARG_TYPES (t));
501 break;
502
503 case ARRAY_TYPE:
504 dump_child ("elts", TREE_TYPE (t));
505 dump_child ("domn", TYPE_DOMAIN (t));
506 break;
507
508 case RECORD_TYPE:
509 case UNION_TYPE:
510 if (TREE_CODE (t) == RECORD_TYPE)
511 dump_string_field (di, "tag", "struct");
512 else
513 dump_string_field (di, "tag", "union");
514
515 dump_child ("flds", TYPE_FIELDS (t));
516 dump_child ("fncs", TYPE_METHODS (t));
517 queue_and_dump_index (di, "binf", TYPE_BINFO (t),
518 DUMP_BINFO);
519 break;
520
521 case CONST_DECL:
522 dump_child ("cnst", DECL_INITIAL (t));
523 break;
524
525 case DEBUG_EXPR_DECL:
526 dump_int (di, "-uid", DEBUG_TEMP_UID (t));
527 /* Fall through. */
528
529 case VAR_DECL:
530 case PARM_DECL:
531 case FIELD_DECL:
532 case RESULT_DECL:
533 if (TREE_CODE (t) == PARM_DECL)
534 dump_child ("argt", DECL_ARG_TYPE (t));
535 else
536 dump_child ("init", DECL_INITIAL (t));
537 dump_child ("size", DECL_SIZE (t));
538 dump_int (di, "algn", DECL_ALIGN (t));
539
540 if (TREE_CODE (t) == FIELD_DECL)
541 {
542 if (DECL_FIELD_OFFSET (t))
543 dump_child ("bpos", bit_position (t));
544 }
545 else if (TREE_CODE (t) == VAR_DECL
546 || TREE_CODE (t) == PARM_DECL)
547 {
548 dump_int (di, "used", TREE_USED (t));
549 if (DECL_REGISTER (t))
550 dump_string_field (di, "spec", "register");
551 }
552 break;
553
554 case FUNCTION_DECL:
555 dump_child ("args", DECL_ARGUMENTS (t));
556 if (DECL_EXTERNAL (t))
557 dump_string_field (di, "body", "undefined");
558 if (TREE_PUBLIC (t))
559 dump_string_field (di, "link", "extern");
560 else
561 dump_string_field (di, "link", "static");
562 if (DECL_SAVED_TREE (t) && !dump_flag (di, TDF_SLIM, t))
563 dump_child ("body", DECL_SAVED_TREE (t));
564 break;
565
566 case INTEGER_CST:
567 fprintf (di->stream, "int: ");
568 print_decs (t, di->stream);
569 break;
570
571 case STRING_CST:
572 fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
573 dump_int (di, "lngt", TREE_STRING_LENGTH (t));
574 break;
575
576 case REAL_CST:
577 dump_real (di, "valu", TREE_REAL_CST_PTR (t));
578 break;
579
580 case FIXED_CST:
581 dump_fixed (di, "valu", TREE_FIXED_CST_PTR (t));
582 break;
583
584 case TRUTH_NOT_EXPR:
585 case ADDR_EXPR:
586 case INDIRECT_REF:
587 case CLEANUP_POINT_EXPR:
588 case SAVE_EXPR:
589 case REALPART_EXPR:
590 case IMAGPART_EXPR:
591 /* These nodes are unary, but do not have code class `1'. */
592 dump_child ("op 0", TREE_OPERAND (t, 0));
593 break;
594
595 case TRUTH_ANDIF_EXPR:
596 case TRUTH_ORIF_EXPR:
597 case INIT_EXPR:
598 case MODIFY_EXPR:
599 case COMPOUND_EXPR:
600 case PREDECREMENT_EXPR:
601 case PREINCREMENT_EXPR:
602 case POSTDECREMENT_EXPR:
603 case POSTINCREMENT_EXPR:
604 /* These nodes are binary, but do not have code class `2'. */
605 dump_child ("op 0", TREE_OPERAND (t, 0));
606 dump_child ("op 1", TREE_OPERAND (t, 1));
607 break;
608
609 case COMPONENT_REF:
610 case BIT_FIELD_REF:
611 dump_child ("op 0", TREE_OPERAND (t, 0));
612 dump_child ("op 1", TREE_OPERAND (t, 1));
613 dump_child ("op 2", TREE_OPERAND (t, 2));
614 break;
615
616 case ARRAY_REF:
617 case ARRAY_RANGE_REF:
618 dump_child ("op 0", TREE_OPERAND (t, 0));
619 dump_child ("op 1", TREE_OPERAND (t, 1));
620 dump_child ("op 2", TREE_OPERAND (t, 2));
621 dump_child ("op 3", TREE_OPERAND (t, 3));
622 break;
623
624 case COND_EXPR:
625 dump_child ("op 0", TREE_OPERAND (t, 0));
626 dump_child ("op 1", TREE_OPERAND (t, 1));
627 dump_child ("op 2", TREE_OPERAND (t, 2));
628 break;
629
630 case TRY_FINALLY_EXPR:
631 dump_child ("op 0", TREE_OPERAND (t, 0));
632 dump_child ("op 1", TREE_OPERAND (t, 1));
633 break;
634
635 case CALL_EXPR:
636 {
637 int i = 0;
638 tree arg;
639 call_expr_arg_iterator iter;
640 dump_child ("fn", CALL_EXPR_FN (t));
641 FOR_EACH_CALL_EXPR_ARG (arg, iter, t)
642 {
643 char buffer[32];
644 sprintf (buffer, "%u", i);
645 dump_child (buffer, arg);
646 i++;
647 }
648 }
649 break;
650
651 case CONSTRUCTOR:
652 {
653 unsigned HOST_WIDE_INT cnt;
654 tree index, value;
655 dump_int (di, "lngt", vec_safe_length (CONSTRUCTOR_ELTS (t)));
656 FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value)
657 {
658 dump_child ("idx", index);
659 dump_child ("val", value);
660 }
661 }
662 break;
663
664 case BIND_EXPR:
665 dump_child ("vars", TREE_OPERAND (t, 0));
666 dump_child ("body", TREE_OPERAND (t, 1));
667 break;
668
669 case LOOP_EXPR:
670 dump_child ("body", TREE_OPERAND (t, 0));
671 break;
672
673 case EXIT_EXPR:
674 dump_child ("cond", TREE_OPERAND (t, 0));
675 break;
676
677 case RETURN_EXPR:
678 dump_child ("expr", TREE_OPERAND (t, 0));
679 break;
680
681 case TARGET_EXPR:
682 dump_child ("decl", TREE_OPERAND (t, 0));
683 dump_child ("init", TREE_OPERAND (t, 1));
684 dump_child ("clnp", TREE_OPERAND (t, 2));
685 /* There really are two possible places the initializer can be.
686 After RTL expansion, the second operand is moved to the
687 position of the fourth operand, and the second operand
688 becomes NULL. */
689 dump_child ("init", TREE_OPERAND (t, 3));
690 break;
691
692 case CASE_LABEL_EXPR:
693 dump_child ("name", CASE_LABEL (t));
694 if (CASE_LOW (t))
695 {
696 dump_child ("low ", CASE_LOW (t));
697 if (CASE_HIGH (t))
698 dump_child ("high", CASE_HIGH (t));
699 }
700 break;
701 case LABEL_EXPR:
702 dump_child ("name", TREE_OPERAND (t,0));
703 break;
704 case GOTO_EXPR:
705 dump_child ("labl", TREE_OPERAND (t, 0));
706 break;
707 case SWITCH_EXPR:
708 dump_child ("cond", TREE_OPERAND (t, 0));
709 dump_child ("body", TREE_OPERAND (t, 1));
710 if (TREE_OPERAND (t, 2))
711 {
712 dump_child ("labl", TREE_OPERAND (t,2));
713 }
714 break;
715 case OMP_CLAUSE:
716 {
717 int i;
718 fprintf (di->stream, "%s\n", omp_clause_code_name[OMP_CLAUSE_CODE (t)]);
719 for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; i++)
720 dump_child ("op: ", OMP_CLAUSE_OPERAND (t, i));
721 }
722 break;
723 default:
724 /* There are no additional fields to print. */
725 break;
726 }
727
728 done:
729 if (dump_flag (di, TDF_ADDRESS, NULL))
730 dump_pointer (di, "addr", (void *)t);
731
732 /* Terminate the line. */
733 fprintf (di->stream, "\n");
734 }
735
736 /* Return nonzero if FLAG has been specified for the dump, and NODE
737 is not the root node of the dump. */
738
739 int dump_flag (dump_info_p di, int flag, const_tree node)
740 {
741 return (di->flags & flag) && (node != di->node);
742 }
743
744 /* Dump T, and all its children, on STREAM. */
745
746 void
747 dump_node (const_tree t, int flags, FILE *stream)
748 {
749 struct dump_info di;
750 dump_queue_p dq;
751 dump_queue_p next_dq;
752
753 /* Initialize the dump-information structure. */
754 di.stream = stream;
755 di.index = 0;
756 di.column = 0;
757 di.queue = 0;
758 di.queue_end = 0;
759 di.free_list = 0;
760 di.flags = flags;
761 di.node = t;
762 di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
763 (splay_tree_delete_value_fn) &free);
764
765 /* Queue up the first node. */
766 queue (&di, t, DUMP_NONE);
767
768 /* Until the queue is empty, keep dumping nodes. */
769 while (di.queue)
770 dequeue_and_dump (&di);
771
772 /* Now, clean up. */
773 for (dq = di.free_list; dq; dq = next_dq)
774 {
775 next_dq = dq->next;
776 free (dq);
777 }
778 splay_tree_delete (di.nodes);
779 }