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