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