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