190075Sobrien/* Tree-dumping functionality for intermediate representation.
2169689Skan   Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006
3169689Skan   Free Software Foundation, Inc.
490075Sobrien   Written by Mark Mitchell <mark@codesourcery.com>
590075Sobrien
690075SobrienThis file is part of GCC.
790075Sobrien
890075SobrienGCC is free software; you can redistribute it and/or modify it under
990075Sobrienthe terms of the GNU General Public License as published by the Free
1090075SobrienSoftware Foundation; either version 2, or (at your option) any later
1190075Sobrienversion.
1290075Sobrien
1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1590075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1690075Sobrienfor more details.
1790075Sobrien
1890075SobrienYou should have received a copy of the GNU General Public License
1990075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21169689Skan02110-1301, USA.  */
2290075Sobrien
2390075Sobrien#include "config.h"
2490075Sobrien#include "system.h"
25132718Skan#include "coretypes.h"
26132718Skan#include "tm.h"
2790075Sobrien#include "tree.h"
2890075Sobrien#include "splay-tree.h"
2990075Sobrien#include "diagnostic.h"
3090075Sobrien#include "toplev.h"
3190075Sobrien#include "tree-dump.h"
32169689Skan#include "tree-pass.h"
3390075Sobrien#include "langhooks.h"
34169689Skan#include "tree-iterator.h"
35169689Skan#include "real.h"
3690075Sobrien
37132718Skanstatic unsigned int queue (dump_info_p, tree, int);
38132718Skanstatic void dump_index (dump_info_p, unsigned int);
39132718Skanstatic void dequeue_and_dump (dump_info_p);
40132718Skanstatic void dump_new_line (dump_info_p);
41132718Skanstatic void dump_maybe_newline (dump_info_p);
42169689Skanstatic int dump_enable_all (int, int);
4390075Sobrien
4490075Sobrien/* Add T to the end of the queue of nodes to dump.  Returns the index
4590075Sobrien   assigned to T.  */
4690075Sobrien
4790075Sobrienstatic unsigned int
48132718Skanqueue (dump_info_p di, tree t, int flags)
4990075Sobrien{
5090075Sobrien  dump_queue_p dq;
5190075Sobrien  dump_node_info_p dni;
5290075Sobrien  unsigned int index;
5390075Sobrien
5490075Sobrien  /* Assign the next available index to T.  */
5590075Sobrien  index = ++di->index;
5690075Sobrien
5790075Sobrien  /* Obtain a new queue node.  */
5890075Sobrien  if (di->free_list)
5990075Sobrien    {
6090075Sobrien      dq = di->free_list;
6190075Sobrien      di->free_list = dq->next;
6290075Sobrien    }
6390075Sobrien  else
64169689Skan    dq = XNEW (struct dump_queue);
6590075Sobrien
6690075Sobrien  /* Create a new entry in the splay-tree.  */
67169689Skan  dni = XNEW (struct dump_node_info);
6890075Sobrien  dni->index = index;
6990075Sobrien  dni->binfo_p = ((flags & DUMP_BINFO) != 0);
70117395Skan  dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
7190075Sobrien				(splay_tree_value) dni);
7290075Sobrien
7390075Sobrien  /* Add it to the end of the queue.  */
7490075Sobrien  dq->next = 0;
7590075Sobrien  if (!di->queue_end)
7690075Sobrien    di->queue = dq;
7790075Sobrien  else
7890075Sobrien    di->queue_end->next = dq;
7990075Sobrien  di->queue_end = dq;
8090075Sobrien
8190075Sobrien  /* Return the index.  */
8290075Sobrien  return index;
8390075Sobrien}
8490075Sobrien
8590075Sobrienstatic void
86132718Skandump_index (dump_info_p di, unsigned int index)
8790075Sobrien{
8890075Sobrien  fprintf (di->stream, "@%-6u ", index);
8990075Sobrien  di->column += 8;
9090075Sobrien}
9190075Sobrien
9290075Sobrien/* If T has not already been output, queue it for subsequent output.
9390075Sobrien   FIELD is a string to print before printing the index.  Then, the
9490075Sobrien   index of T is printed.  */
9590075Sobrien
9690075Sobrienvoid
97132718Skanqueue_and_dump_index (dump_info_p di, const char *field, tree t, int flags)
9890075Sobrien{
9990075Sobrien  unsigned int index;
10090075Sobrien  splay_tree_node n;
10190075Sobrien
10290075Sobrien  /* If there's no node, just return.  This makes for fewer checks in
10390075Sobrien     our callers.  */
10490075Sobrien  if (!t)
10590075Sobrien    return;
10690075Sobrien
10790075Sobrien  /* See if we've already queued or dumped this node.  */
10890075Sobrien  n = splay_tree_lookup (di->nodes, (splay_tree_key) t);
10990075Sobrien  if (n)
11090075Sobrien    index = ((dump_node_info_p) n->value)->index;
11190075Sobrien  else
11290075Sobrien    /* If we haven't, add it to the queue.  */
11390075Sobrien    index = queue (di, t, flags);
11490075Sobrien
11590075Sobrien  /* Print the index of the node.  */
11690075Sobrien  dump_maybe_newline (di);
11790075Sobrien  fprintf (di->stream, "%-4s: ", field);
11890075Sobrien  di->column += 6;
11990075Sobrien  dump_index (di, index);
12090075Sobrien}
12190075Sobrien
12290075Sobrien/* Dump the type of T.  */
12390075Sobrien
12490075Sobrienvoid
125132718Skanqueue_and_dump_type (dump_info_p di, tree t)
12690075Sobrien{
12790075Sobrien  queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
12890075Sobrien}
12990075Sobrien
13090075Sobrien/* Dump column control */
13190075Sobrien#define SOL_COLUMN 25		/* Start of line column.  */
13290075Sobrien#define EOL_COLUMN 55		/* End of line column.  */
13390075Sobrien#define COLUMN_ALIGNMENT 15	/* Alignment.  */
13490075Sobrien
13590075Sobrien/* Insert a new line in the dump output, and indent to an appropriate
13690075Sobrien   place to start printing more fields.  */
13790075Sobrien
13890075Sobrienstatic void
139132718Skandump_new_line (dump_info_p di)
14090075Sobrien{
14190075Sobrien  fprintf (di->stream, "\n%*s", SOL_COLUMN, "");
14290075Sobrien  di->column = SOL_COLUMN;
14390075Sobrien}
14490075Sobrien
14590075Sobrien/* If necessary, insert a new line.  */
14690075Sobrien
14790075Sobrienstatic void
148132718Skandump_maybe_newline (dump_info_p di)
14990075Sobrien{
15090075Sobrien  int extra;
151117395Skan
15290075Sobrien  /* See if we need a new line.  */
15390075Sobrien  if (di->column > EOL_COLUMN)
15490075Sobrien    dump_new_line (di);
15590075Sobrien  /* See if we need any padding.  */
15690075Sobrien  else if ((extra = (di->column - SOL_COLUMN) % COLUMN_ALIGNMENT) != 0)
15790075Sobrien    {
15890075Sobrien      fprintf (di->stream, "%*s", COLUMN_ALIGNMENT - extra, "");
15990075Sobrien      di->column += COLUMN_ALIGNMENT - extra;
16090075Sobrien    }
16190075Sobrien}
16290075Sobrien
16390075Sobrien/* Dump pointer PTR using FIELD to identify it.  */
16490075Sobrien
16590075Sobrienvoid
166132718Skandump_pointer (dump_info_p di, const char *field, void *ptr)
16790075Sobrien{
16890075Sobrien  dump_maybe_newline (di);
169259948Spfg  fprintf (di->stream, "%-4s: %-8lx ", field, (unsigned long) ptr);
17090075Sobrien  di->column += 15;
17190075Sobrien}
17290075Sobrien
17390075Sobrien/* Dump integer I using FIELD to identify it.  */
17490075Sobrien
17590075Sobrienvoid
176132718Skandump_int (dump_info_p di, const char *field, int i)
17790075Sobrien{
17890075Sobrien  dump_maybe_newline (di);
17990075Sobrien  fprintf (di->stream, "%-4s: %-7d ", field, i);
18090075Sobrien  di->column += 14;
18190075Sobrien}
18290075Sobrien
183169689Skan/* Dump the floating point value R, using FIELD to identify it.  */
184169689Skan
185169689Skanstatic void
186169689Skandump_real (dump_info_p di, const char *field, const REAL_VALUE_TYPE *r)
187169689Skan{
188169689Skan  char buf[32];
189169689Skan  real_to_decimal (buf, r, sizeof (buf), 0, true);
190169689Skan  dump_maybe_newline (di);
191169689Skan  fprintf (di->stream, "%-4s: %s ", field, buf);
192169689Skan  di->column += strlen (buf) + 7;
193169689Skan}
194169689Skan
195169689Skan
19690075Sobrien/* Dump the string S.  */
19790075Sobrien
19890075Sobrienvoid
199132718Skandump_string (dump_info_p di, const char *string)
20090075Sobrien{
20190075Sobrien  dump_maybe_newline (di);
20290075Sobrien  fprintf (di->stream, "%-13s ", string);
20390075Sobrien  if (strlen (string) > 13)
20490075Sobrien    di->column += strlen (string) + 1;
20590075Sobrien  else
20690075Sobrien    di->column += 14;
20790075Sobrien}
20890075Sobrien
20990075Sobrien/* Dump the string field S.  */
21090075Sobrien
211169689Skanvoid
212132718Skandump_string_field (dump_info_p di, const char *field, const char *string)
21390075Sobrien{
21490075Sobrien  dump_maybe_newline (di);
21590075Sobrien  fprintf (di->stream, "%-4s: %-7s ", field, string);
21690075Sobrien  if (strlen (string) > 7)
21790075Sobrien    di->column += 6 + strlen (string) + 1;
21890075Sobrien  else
21990075Sobrien    di->column += 14;
22090075Sobrien}
22190075Sobrien
22290075Sobrien/* Dump the next node in the queue.  */
22390075Sobrien
224117395Skanstatic void
225132718Skandequeue_and_dump (dump_info_p di)
22690075Sobrien{
22790075Sobrien  dump_queue_p dq;
22890075Sobrien  splay_tree_node stn;
22990075Sobrien  dump_node_info_p dni;
23090075Sobrien  tree t;
23190075Sobrien  unsigned int index;
23290075Sobrien  enum tree_code code;
233169689Skan  enum tree_code_class code_class;
23490075Sobrien  const char* code_name;
23590075Sobrien
23690075Sobrien  /* Get the next node from the queue.  */
23790075Sobrien  dq = di->queue;
23890075Sobrien  stn = dq->node;
23990075Sobrien  t = (tree) stn->key;
24090075Sobrien  dni = (dump_node_info_p) stn->value;
24190075Sobrien  index = dni->index;
24290075Sobrien
24390075Sobrien  /* Remove the node from the queue, and put it on the free list.  */
24490075Sobrien  di->queue = dq->next;
24590075Sobrien  if (!di->queue)
24690075Sobrien    di->queue_end = 0;
24790075Sobrien  dq->next = di->free_list;
24890075Sobrien  di->free_list = dq;
24990075Sobrien
25090075Sobrien  /* Print the node index.  */
25190075Sobrien  dump_index (di, index);
25290075Sobrien  /* And the type of node this is.  */
25390075Sobrien  if (dni->binfo_p)
25490075Sobrien    code_name = "binfo";
25590075Sobrien  else
25690075Sobrien    code_name = tree_code_name[(int) TREE_CODE (t)];
25790075Sobrien  fprintf (di->stream, "%-16s ", code_name);
25890075Sobrien  di->column = 25;
25990075Sobrien
26090075Sobrien  /* Figure out what kind of node this is.  */
26190075Sobrien  code = TREE_CODE (t);
26290075Sobrien  code_class = TREE_CODE_CLASS (code);
26390075Sobrien
26490075Sobrien  /* Although BINFOs are TREE_VECs, we dump them specially so as to be
26590075Sobrien     more informative.  */
26690075Sobrien  if (dni->binfo_p)
26790075Sobrien    {
268132718Skan      unsigned ix;
269169689Skan      tree base;
270169689Skan      VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (t);
271132718Skan
272132718Skan      dump_child ("type", BINFO_TYPE (t));
273132718Skan
274169689Skan      if (BINFO_VIRTUAL_P (t))
275169689Skan	dump_string_field (di, "spec", "virt");
276117395Skan
277169689Skan      dump_int (di, "bases", BINFO_N_BASE_BINFOS (t));
278169689Skan      for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++)
279132718Skan	{
280169689Skan	  tree access = (accesses ? VEC_index (tree, accesses, ix)
281132718Skan			 : access_public_node);
282132718Skan	  const char *string = NULL;
28390075Sobrien
284132718Skan	  if (access == access_public_node)
285132718Skan	    string = "pub";
286132718Skan	  else if (access == access_protected_node)
287132718Skan	    string = "prot";
288132718Skan	  else if (access == access_private_node)
289132718Skan	    string = "priv";
290132718Skan	  else
291169689Skan	    gcc_unreachable ();
292132718Skan
293169689Skan	  dump_string_field (di, "accs", string);
294132718Skan	  queue_and_dump_index (di, "binf", base, DUMP_BINFO);
295132718Skan	}
296132718Skan
29790075Sobrien      goto done;
29890075Sobrien    }
29990075Sobrien
30090075Sobrien  /* We can knock off a bunch of expression nodes in exactly the same
30190075Sobrien     way.  */
30290075Sobrien  if (IS_EXPR_CODE_CLASS (code_class))
30390075Sobrien    {
30490075Sobrien      /* If we're dumping children, dump them now.  */
30590075Sobrien      queue_and_dump_type (di, t);
30690075Sobrien
30790075Sobrien      switch (code_class)
30890075Sobrien	{
309169689Skan	case tcc_unary:
31090075Sobrien	  dump_child ("op 0", TREE_OPERAND (t, 0));
31190075Sobrien	  break;
312117395Skan
313169689Skan	case tcc_binary:
314169689Skan	case tcc_comparison:
31590075Sobrien	  dump_child ("op 0", TREE_OPERAND (t, 0));
31690075Sobrien	  dump_child ("op 1", TREE_OPERAND (t, 1));
31790075Sobrien	  break;
318117395Skan
319169689Skan	case tcc_expression:
320169689Skan	case tcc_reference:
321169689Skan	case tcc_statement:
32290075Sobrien	  /* These nodes are handled explicitly below.  */
32390075Sobrien	  break;
324117395Skan
32590075Sobrien	default:
326169689Skan	  gcc_unreachable ();
32790075Sobrien	}
32890075Sobrien    }
32990075Sobrien  else if (DECL_P (t))
33090075Sobrien    {
331169689Skan      expanded_location xloc;
33290075Sobrien      /* All declarations have names.  */
33390075Sobrien      if (DECL_NAME (t))
33490075Sobrien	dump_child ("name", DECL_NAME (t));
335117395Skan      if (DECL_ASSEMBLER_NAME_SET_P (t)
33690075Sobrien	  && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t))
33790075Sobrien	dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
338169689Skan      if (DECL_ABSTRACT_ORIGIN (t))
339169689Skan        dump_child ("orig", DECL_ABSTRACT_ORIGIN (t));
34090075Sobrien      /* And types.  */
34190075Sobrien      queue_and_dump_type (di, t);
34290075Sobrien      dump_child ("scpe", DECL_CONTEXT (t));
34390075Sobrien      /* And a source position.  */
344169689Skan      xloc = expand_location (DECL_SOURCE_LOCATION (t));
345169689Skan      if (xloc.file)
34690075Sobrien	{
347169689Skan	  const char *filename = strrchr (xloc.file, '/');
34890075Sobrien	  if (!filename)
349169689Skan	    filename = xloc.file;
35090075Sobrien	  else
35190075Sobrien	    /* Skip the slash.  */
35290075Sobrien	    ++filename;
35390075Sobrien
35490075Sobrien	  dump_maybe_newline (di);
355117395Skan	  fprintf (di->stream, "srcp: %s:%-6d ", filename,
356169689Skan		   xloc.line);
35790075Sobrien	  di->column += 6 + strlen (filename) + 8;
35890075Sobrien	}
35990075Sobrien      /* And any declaration can be compiler-generated.  */
360169689Skan      if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_COMMON)
361169689Skan	  && DECL_ARTIFICIAL (t))
362169689Skan	dump_string_field (di, "note", "artificial");
36390075Sobrien      if (TREE_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
36490075Sobrien	dump_child ("chan", TREE_CHAIN (t));
36590075Sobrien    }
366169689Skan  else if (code_class == tcc_type)
36790075Sobrien    {
36890075Sobrien      /* All types have qualifiers.  */
369169689Skan      int quals = lang_hooks.tree_dump.type_quals (t);
370117395Skan
37190075Sobrien      if (quals != TYPE_UNQUALIFIED)
37290075Sobrien	{
37390075Sobrien	  fprintf (di->stream, "qual: %c%c%c     ",
37490075Sobrien		   (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
37590075Sobrien		   (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
37690075Sobrien		   (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
37790075Sobrien	  di->column += 14;
37890075Sobrien	}
37990075Sobrien
38090075Sobrien      /* All types have associated declarations.  */
38190075Sobrien      dump_child ("name", TYPE_NAME (t));
38290075Sobrien
38390075Sobrien      /* All types have a main variant.  */
38490075Sobrien      if (TYPE_MAIN_VARIANT (t) != t)
38590075Sobrien	dump_child ("unql", TYPE_MAIN_VARIANT (t));
386117395Skan
38790075Sobrien      /* And sizes.  */
38890075Sobrien      dump_child ("size", TYPE_SIZE (t));
38990075Sobrien
39090075Sobrien      /* All types have alignments.  */
39190075Sobrien      dump_int (di, "algn", TYPE_ALIGN (t));
39290075Sobrien    }
393169689Skan  else if (code_class == tcc_constant)
39490075Sobrien    /* All constants can have types.  */
39590075Sobrien    queue_and_dump_type (di, t);
39690075Sobrien
39790075Sobrien  /* Give the language-specific code a chance to print something.  If
39890075Sobrien     it's completely taken care of things, don't bother printing
39990075Sobrien     anything more ourselves.  */
400169689Skan  if (lang_hooks.tree_dump.dump_tree (di, t))
40190075Sobrien    goto done;
40290075Sobrien
40390075Sobrien  /* Now handle the various kinds of nodes.  */
40490075Sobrien  switch (code)
40590075Sobrien    {
40690075Sobrien      int i;
40790075Sobrien
40890075Sobrien    case IDENTIFIER_NODE:
40990075Sobrien      dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
41090075Sobrien      dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
41190075Sobrien      break;
41290075Sobrien
41390075Sobrien    case TREE_LIST:
41490075Sobrien      dump_child ("purp", TREE_PURPOSE (t));
41590075Sobrien      dump_child ("valu", TREE_VALUE (t));
41690075Sobrien      dump_child ("chan", TREE_CHAIN (t));
41790075Sobrien      break;
41890075Sobrien
419169689Skan    case STATEMENT_LIST:
420169689Skan      {
421169689Skan	tree_stmt_iterator it;
422169689Skan	for (i = 0, it = tsi_start (t); !tsi_end_p (it); tsi_next (&it), i++)
423169689Skan	  {
424169689Skan	    char buffer[32];
425169689Skan	    sprintf (buffer, "%u", i);
426169689Skan	    dump_child (buffer, tsi_stmt (it));
427169689Skan	  }
428169689Skan      }
429169689Skan      break;
430169689Skan
43190075Sobrien    case TREE_VEC:
43290075Sobrien      dump_int (di, "lngt", TREE_VEC_LENGTH (t));
43390075Sobrien      for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
43490075Sobrien	{
43590075Sobrien	  char buffer[32];
43690075Sobrien	  sprintf (buffer, "%u", i);
43790075Sobrien	  dump_child (buffer, TREE_VEC_ELT (t, i));
43890075Sobrien	}
43990075Sobrien      break;
44090075Sobrien
44190075Sobrien    case INTEGER_TYPE:
44290075Sobrien    case ENUMERAL_TYPE:
44390075Sobrien      dump_int (di, "prec", TYPE_PRECISION (t));
444169689Skan      dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
44590075Sobrien      dump_child ("min", TYPE_MIN_VALUE (t));
44690075Sobrien      dump_child ("max", TYPE_MAX_VALUE (t));
44790075Sobrien
44890075Sobrien      if (code == ENUMERAL_TYPE)
44990075Sobrien	dump_child ("csts", TYPE_VALUES (t));
45090075Sobrien      break;
45190075Sobrien
45290075Sobrien    case REAL_TYPE:
45390075Sobrien      dump_int (di, "prec", TYPE_PRECISION (t));
45490075Sobrien      break;
45590075Sobrien
45690075Sobrien    case POINTER_TYPE:
45790075Sobrien      dump_child ("ptd", TREE_TYPE (t));
45890075Sobrien      break;
45990075Sobrien
46090075Sobrien    case REFERENCE_TYPE:
46190075Sobrien      dump_child ("refd", TREE_TYPE (t));
46290075Sobrien      break;
46390075Sobrien
46490075Sobrien    case METHOD_TYPE:
46590075Sobrien      dump_child ("clas", TYPE_METHOD_BASETYPE (t));
46690075Sobrien      /* Fall through.  */
46790075Sobrien
46890075Sobrien    case FUNCTION_TYPE:
46990075Sobrien      dump_child ("retn", TREE_TYPE (t));
47090075Sobrien      dump_child ("prms", TYPE_ARG_TYPES (t));
47190075Sobrien      break;
47290075Sobrien
47390075Sobrien    case ARRAY_TYPE:
47490075Sobrien      dump_child ("elts", TREE_TYPE (t));
47590075Sobrien      dump_child ("domn", TYPE_DOMAIN (t));
47690075Sobrien      break;
47790075Sobrien
47890075Sobrien    case RECORD_TYPE:
47990075Sobrien    case UNION_TYPE:
48090075Sobrien      if (TREE_CODE (t) == RECORD_TYPE)
481169689Skan	dump_string_field (di, "tag", "struct");
48290075Sobrien      else
483169689Skan	dump_string_field (di, "tag", "union");
484117395Skan
48590075Sobrien      dump_child ("flds", TYPE_FIELDS (t));
48690075Sobrien      dump_child ("fncs", TYPE_METHODS (t));
487117395Skan      queue_and_dump_index (di, "binf", TYPE_BINFO (t),
48890075Sobrien			    DUMP_BINFO);
48990075Sobrien      break;
49090075Sobrien
49190075Sobrien    case CONST_DECL:
49290075Sobrien      dump_child ("cnst", DECL_INITIAL (t));
49390075Sobrien      break;
494169689Skan
495169689Skan    case SYMBOL_MEMORY_TAG:
496169689Skan    case NAME_MEMORY_TAG:
497169689Skan    case STRUCT_FIELD_TAG:
498169689Skan      break;
49990075Sobrien
50090075Sobrien    case VAR_DECL:
50190075Sobrien    case PARM_DECL:
50290075Sobrien    case FIELD_DECL:
50390075Sobrien    case RESULT_DECL:
50490075Sobrien      if (TREE_CODE (t) == PARM_DECL)
50590075Sobrien	dump_child ("argt", DECL_ARG_TYPE (t));
50690075Sobrien      else
50790075Sobrien	dump_child ("init", DECL_INITIAL (t));
50890075Sobrien      dump_child ("size", DECL_SIZE (t));
50990075Sobrien      dump_int (di, "algn", DECL_ALIGN (t));
51090075Sobrien
51190075Sobrien      if (TREE_CODE (t) == FIELD_DECL)
51290075Sobrien	{
51390075Sobrien	  if (DECL_FIELD_OFFSET (t))
51490075Sobrien	    dump_child ("bpos", bit_position (t));
51590075Sobrien	}
516117395Skan      else if (TREE_CODE (t) == VAR_DECL
51790075Sobrien	       || TREE_CODE (t) == PARM_DECL)
51890075Sobrien	{
51990075Sobrien	  dump_int (di, "used", TREE_USED (t));
52090075Sobrien	  if (DECL_REGISTER (t))
521169689Skan	    dump_string_field (di, "spec", "register");
52290075Sobrien	}
52390075Sobrien      break;
52490075Sobrien
52590075Sobrien    case FUNCTION_DECL:
52690075Sobrien      dump_child ("args", DECL_ARGUMENTS (t));
52790075Sobrien      if (DECL_EXTERNAL (t))
528169689Skan	dump_string_field (di, "body", "undefined");
52990075Sobrien      if (TREE_PUBLIC (t))
530169689Skan	dump_string_field (di, "link", "extern");
53190075Sobrien      else
532169689Skan	dump_string_field (di, "link", "static");
53390075Sobrien      if (DECL_LANG_SPECIFIC (t) && !dump_flag (di, TDF_SLIM, t))
53490075Sobrien	dump_child ("body", DECL_SAVED_TREE (t));
53590075Sobrien      break;
53690075Sobrien
53790075Sobrien    case INTEGER_CST:
53890075Sobrien      if (TREE_INT_CST_HIGH (t))
53990075Sobrien	dump_int (di, "high", TREE_INT_CST_HIGH (t));
54090075Sobrien      dump_int (di, "low", TREE_INT_CST_LOW (t));
54190075Sobrien      break;
54290075Sobrien
54390075Sobrien    case STRING_CST:
54490075Sobrien      fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
54590075Sobrien      dump_int (di, "lngt", TREE_STRING_LENGTH (t));
54690075Sobrien      break;
54790075Sobrien
548169689Skan    case REAL_CST:
549169689Skan      dump_real (di, "valu", TREE_REAL_CST_PTR (t));
550169689Skan      break;
551169689Skan
55290075Sobrien    case TRUTH_NOT_EXPR:
55390075Sobrien    case ADDR_EXPR:
55490075Sobrien    case INDIRECT_REF:
555169689Skan    case ALIGN_INDIRECT_REF:
556169689Skan    case MISALIGNED_INDIRECT_REF:
55790075Sobrien    case CLEANUP_POINT_EXPR:
55890075Sobrien    case SAVE_EXPR:
559169689Skan    case REALPART_EXPR:
560169689Skan    case IMAGPART_EXPR:
56190075Sobrien      /* These nodes are unary, but do not have code class `1'.  */
56290075Sobrien      dump_child ("op 0", TREE_OPERAND (t, 0));
56390075Sobrien      break;
56490075Sobrien
56590075Sobrien    case TRUTH_ANDIF_EXPR:
56690075Sobrien    case TRUTH_ORIF_EXPR:
56790075Sobrien    case INIT_EXPR:
56890075Sobrien    case MODIFY_EXPR:
56990075Sobrien    case COMPOUND_EXPR:
57090075Sobrien    case PREDECREMENT_EXPR:
57190075Sobrien    case PREINCREMENT_EXPR:
57290075Sobrien    case POSTDECREMENT_EXPR:
57390075Sobrien    case POSTINCREMENT_EXPR:
57490075Sobrien      /* These nodes are binary, but do not have code class `2'.  */
57590075Sobrien      dump_child ("op 0", TREE_OPERAND (t, 0));
57690075Sobrien      dump_child ("op 1", TREE_OPERAND (t, 1));
57790075Sobrien      break;
57890075Sobrien
579169689Skan    case COMPONENT_REF:
580169689Skan      dump_child ("op 0", TREE_OPERAND (t, 0));
581169689Skan      dump_child ("op 1", TREE_OPERAND (t, 1));
582169689Skan      dump_child ("op 2", TREE_OPERAND (t, 2));
583169689Skan      break;
584169689Skan
585169689Skan    case ARRAY_REF:
586169689Skan    case ARRAY_RANGE_REF:
587169689Skan      dump_child ("op 0", TREE_OPERAND (t, 0));
588169689Skan      dump_child ("op 1", TREE_OPERAND (t, 1));
589169689Skan      dump_child ("op 2", TREE_OPERAND (t, 2));
590169689Skan      dump_child ("op 3", TREE_OPERAND (t, 3));
591169689Skan      break;
592169689Skan
59390075Sobrien    case COND_EXPR:
59490075Sobrien      dump_child ("op 0", TREE_OPERAND (t, 0));
59590075Sobrien      dump_child ("op 1", TREE_OPERAND (t, 1));
59690075Sobrien      dump_child ("op 2", TREE_OPERAND (t, 2));
59790075Sobrien      break;
59890075Sobrien
599169689Skan    case TRY_FINALLY_EXPR:
600169689Skan      dump_child ("op 0", TREE_OPERAND (t, 0));
601169689Skan      dump_child ("op 1", TREE_OPERAND (t, 1));
602169689Skan      break;
603169689Skan
60490075Sobrien    case CALL_EXPR:
60590075Sobrien      dump_child ("fn", TREE_OPERAND (t, 0));
60690075Sobrien      dump_child ("args", TREE_OPERAND (t, 1));
60790075Sobrien      break;
60890075Sobrien
60990075Sobrien    case CONSTRUCTOR:
610169689Skan      {
611169689Skan	unsigned HOST_WIDE_INT cnt;
612169689Skan	tree index, value;
613169689Skan	dump_int (di, "lngt", VEC_length (constructor_elt,
614169689Skan					  CONSTRUCTOR_ELTS (t)));
615169689Skan	FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value)
616169689Skan	  {
617169689Skan	    dump_child ("idx", index);
618169689Skan	    dump_child ("val", value);
619169689Skan	  }
620169689Skan      }
62190075Sobrien      break;
62290075Sobrien
62390075Sobrien    case BIND_EXPR:
62490075Sobrien      dump_child ("vars", TREE_OPERAND (t, 0));
62590075Sobrien      dump_child ("body", TREE_OPERAND (t, 1));
62690075Sobrien      break;
62790075Sobrien
62890075Sobrien    case LOOP_EXPR:
62990075Sobrien      dump_child ("body", TREE_OPERAND (t, 0));
63090075Sobrien      break;
63190075Sobrien
63290075Sobrien    case EXIT_EXPR:
63390075Sobrien      dump_child ("cond", TREE_OPERAND (t, 0));
63490075Sobrien      break;
63590075Sobrien
636169689Skan    case RETURN_EXPR:
637169689Skan      dump_child ("expr", TREE_OPERAND (t, 0));
638169689Skan      break;
639169689Skan
64090075Sobrien    case TARGET_EXPR:
64190075Sobrien      dump_child ("decl", TREE_OPERAND (t, 0));
64290075Sobrien      dump_child ("init", TREE_OPERAND (t, 1));
64390075Sobrien      dump_child ("clnp", TREE_OPERAND (t, 2));
64490075Sobrien      /* There really are two possible places the initializer can be.
64590075Sobrien	 After RTL expansion, the second operand is moved to the
64690075Sobrien	 position of the fourth operand, and the second operand
64790075Sobrien	 becomes NULL.  */
64890075Sobrien      dump_child ("init", TREE_OPERAND (t, 3));
64990075Sobrien      break;
650117395Skan
651169689Skan    case CASE_LABEL_EXPR:
652169689Skan      dump_child ("name", CASE_LABEL (t));
653169689Skan      if (CASE_LOW (t)) {
654169689Skan        dump_child ("low ", CASE_LOW (t));
655169689Skan	if (CASE_HIGH (t)) {
656169689Skan	  dump_child ("high", CASE_HIGH (t));
657169689Skan	}
658169689Skan      }
65990075Sobrien      break;
660169689Skan    case LABEL_EXPR:
661169689Skan      dump_child ("name", TREE_OPERAND (t,0));
662169689Skan      break;
663169689Skan    case GOTO_EXPR:
664169689Skan      dump_child ("labl", TREE_OPERAND (t, 0));
665169689Skan      break;
666169689Skan    case SWITCH_EXPR:
667169689Skan      dump_child ("cond", TREE_OPERAND (t, 0));
668169689Skan      dump_child ("body", TREE_OPERAND (t, 1));
669169689Skan      if (TREE_OPERAND (t, 2))
670169689Skan        {
671169689Skan      	  dump_child ("labl", TREE_OPERAND (t,2));
672169689Skan        }
673169689Skan      break;
674169689Skan    case OMP_CLAUSE:
675169689Skan      {
676169689Skan	int i;
677169689Skan	fprintf (di->stream, "%s\n", omp_clause_code_name[OMP_CLAUSE_CODE (t)]);
678169689Skan	for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; i++)
679169689Skan	  dump_child ("op: ", OMP_CLAUSE_OPERAND (t, i));
680169689Skan      }
681169689Skan      break;
68290075Sobrien    default:
68390075Sobrien      /* There are no additional fields to print.  */
68490075Sobrien      break;
68590075Sobrien    }
68690075Sobrien
68790075Sobrien done:
68890075Sobrien  if (dump_flag (di, TDF_ADDRESS, NULL))
68990075Sobrien    dump_pointer (di, "addr", (void *)t);
690117395Skan
69190075Sobrien  /* Terminate the line.  */
69290075Sobrien  fprintf (di->stream, "\n");
69390075Sobrien}
69490075Sobrien
695117395Skan/* Return nonzero if FLAG has been specified for the dump, and NODE
69690075Sobrien   is not the root node of the dump.  */
69790075Sobrien
698132718Skanint dump_flag (dump_info_p di, int flag, tree node)
69990075Sobrien{
70090075Sobrien  return (di->flags & flag) && (node != di->node);
70190075Sobrien}
70290075Sobrien
70390075Sobrien/* Dump T, and all its children, on STREAM.  */
70490075Sobrien
70590075Sobrienvoid
706132718Skandump_node (tree t, int flags, FILE *stream)
70790075Sobrien{
70890075Sobrien  struct dump_info di;
70990075Sobrien  dump_queue_p dq;
71090075Sobrien  dump_queue_p next_dq;
71190075Sobrien
71290075Sobrien  /* Initialize the dump-information structure.  */
71390075Sobrien  di.stream = stream;
71490075Sobrien  di.index = 0;
71590075Sobrien  di.column = 0;
71690075Sobrien  di.queue = 0;
71790075Sobrien  di.queue_end = 0;
71890075Sobrien  di.free_list = 0;
71990075Sobrien  di.flags = flags;
72090075Sobrien  di.node = t;
721117395Skan  di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
72290075Sobrien			     (splay_tree_delete_value_fn) &free);
72390075Sobrien
72490075Sobrien  /* Queue up the first node.  */
72590075Sobrien  queue (&di, t, DUMP_NONE);
72690075Sobrien
72790075Sobrien  /* Until the queue is empty, keep dumping nodes.  */
72890075Sobrien  while (di.queue)
72990075Sobrien    dequeue_and_dump (&di);
73090075Sobrien
73190075Sobrien  /* Now, clean up.  */
73290075Sobrien  for (dq = di.free_list; dq; dq = next_dq)
73390075Sobrien    {
73490075Sobrien      next_dq = dq->next;
73590075Sobrien      free (dq);
73690075Sobrien    }
73790075Sobrien  splay_tree_delete (di.nodes);
73890075Sobrien}
739169689Skan
74090075Sobrien
74190075Sobrien/* Table of tree dump switches. This must be consistent with the
742169689Skan   TREE_DUMP_INDEX enumeration in tree.h.  */
74390075Sobrienstatic struct dump_file_info dump_files[TDI_end] =
74490075Sobrien{
745169689Skan  {NULL, NULL, NULL, 0, 0, 0, 0},
746169689Skan  {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0,  0, 0},
747169689Skan  {".tu", "translation-unit", NULL, TDF_TREE, 0, 1, 0},
748169689Skan  {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2, 0},
749169689Skan  {".original", "tree-original", NULL, TDF_TREE, 0, 3, 0},
750169689Skan  {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4, 0},
751169689Skan  {".nested", "tree-nested", NULL, TDF_TREE, 0, 5, 0},
752169689Skan  {".inlined", "tree-inlined", NULL, TDF_TREE, 0, 6, 0},
753169689Skan  {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 7, 0},
754169689Skan#define FIRST_AUTO_NUMBERED_DUMP 8
755169689Skan
756169689Skan  {NULL, "tree-all", NULL, TDF_TREE, 0, 0, 0},
757169689Skan  {NULL, "rtl-all", NULL, TDF_RTL, 0, 0, 0},
758169689Skan  {NULL, "ipa-all", NULL, TDF_IPA, 0, 0, 0},
75990075Sobrien};
76090075Sobrien
761169689Skan/* Dynamically registered tree dump files and switches.  */
762169689Skanstatic struct dump_file_info *extra_dump_files;
763169689Skanstatic size_t extra_dump_files_in_use;
764169689Skanstatic size_t extra_dump_files_alloced;
765169689Skan
76690075Sobrien/* Define a name->number mapping for a dump flag value.  */
76790075Sobrienstruct dump_option_value_info
76890075Sobrien{
76990075Sobrien  const char *const name;	/* the name of the value */
77090075Sobrien  const int value;		/* the value of the name */
77190075Sobrien};
77290075Sobrien
77390075Sobrien/* Table of dump options. This must be consistent with the TDF_* flags
77490075Sobrien   in tree.h */
77590075Sobrienstatic const struct dump_option_value_info dump_options[] =
77690075Sobrien{
77790075Sobrien  {"address", TDF_ADDRESS},
77890075Sobrien  {"slim", TDF_SLIM},
779169689Skan  {"raw", TDF_RAW},
780169689Skan  {"details", TDF_DETAILS},
781169689Skan  {"stats", TDF_STATS},
782169689Skan  {"blocks", TDF_BLOCKS},
783169689Skan  {"vops", TDF_VOPS},
784169689Skan  {"lineno", TDF_LINENO},
785169689Skan  {"uid", TDF_UID},
786169689Skan  {"stmtaddr", TDF_STMTADDR},
787169689Skan  {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA
788169689Skan	    | TDF_STMTADDR | TDF_GRAPH)},
78990075Sobrien  {NULL, 0}
79090075Sobrien};
79190075Sobrien
792169689Skanunsigned int
793169689Skandump_register (const char *suffix, const char *swtch, const char *glob,
794169689Skan	       int flags, int letter)
795169689Skan{
796169689Skan  static int next_dump = FIRST_AUTO_NUMBERED_DUMP;
797169689Skan  int num = next_dump++;
798169689Skan
799169689Skan  size_t this = extra_dump_files_in_use++;
800169689Skan
801169689Skan  if (this >= extra_dump_files_alloced)
802169689Skan    {
803169689Skan      if (extra_dump_files_alloced == 0)
804169689Skan	extra_dump_files_alloced = 32;
805169689Skan      else
806169689Skan	extra_dump_files_alloced *= 2;
807169689Skan      extra_dump_files = xrealloc (extra_dump_files,
808169689Skan				   sizeof (struct dump_file_info)
809169689Skan				   * extra_dump_files_alloced);
810169689Skan    }
811169689Skan
812169689Skan  memset (&extra_dump_files[this], 0, sizeof (struct dump_file_info));
813169689Skan  extra_dump_files[this].suffix = suffix;
814169689Skan  extra_dump_files[this].swtch = swtch;
815169689Skan  extra_dump_files[this].glob = glob;
816169689Skan  extra_dump_files[this].flags = flags;
817169689Skan  extra_dump_files[this].num = num;
818169689Skan  extra_dump_files[this].letter = letter;
819169689Skan
820169689Skan  return this + TDI_end;
821169689Skan}
822169689Skan
823169689Skan
824169689Skan/* Return the dump_file_info for the given phase.  */
825169689Skan
826169689Skanstruct dump_file_info *
827169689Skanget_dump_file_info (enum tree_dump_index phase)
828169689Skan{
829169689Skan  if (phase < TDI_end)
830169689Skan    return &dump_files[phase];
831169689Skan  else if (phase - TDI_end >= extra_dump_files_in_use)
832169689Skan    return NULL;
833169689Skan  else
834169689Skan    return extra_dump_files + (phase - TDI_end);
835169689Skan}
836169689Skan
837169689Skan
838169689Skan/* Return the name of the dump file for the given phase.
839169689Skan   If the dump is not enabled, returns NULL.  */
840169689Skan
841169689Skanchar *
842169689Skanget_dump_file_name (enum tree_dump_index phase)
843169689Skan{
844169689Skan  char dump_id[10];
845169689Skan  struct dump_file_info *dfi;
846169689Skan
847169689Skan  if (phase == TDI_none)
848169689Skan    return NULL;
849169689Skan
850169689Skan  dfi = get_dump_file_info (phase);
851169689Skan  if (dfi->state == 0)
852169689Skan    return NULL;
853169689Skan
854169689Skan  if (dfi->num < 0)
855169689Skan    dump_id[0] = '\0';
856169689Skan  else
857169689Skan    {
858169689Skan      char suffix;
859169689Skan      if (dfi->flags & TDF_TREE)
860169689Skan	suffix = 't';
861169689Skan      else if (dfi->flags & TDF_IPA)
862169689Skan	suffix = 'i';
863169689Skan      else
864169689Skan	suffix = 'r';
865169689Skan
866169689Skan      if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
867169689Skan	dump_id[0] = '\0';
868169689Skan    }
869169689Skan
870169689Skan  return concat (dump_base_name, dump_id, dfi->suffix, NULL);
871169689Skan}
872169689Skan
87390075Sobrien/* Begin a tree dump for PHASE. Stores any user supplied flag in
87490075Sobrien   *FLAG_PTR and returns a stream to write to. If the dump is not
87590075Sobrien   enabled, returns NULL.
87690075Sobrien   Multiple calls will reopen and append to the dump file.  */
87790075Sobrien
87890075SobrienFILE *
879132718Skandump_begin (enum tree_dump_index phase, int *flag_ptr)
88090075Sobrien{
881169689Skan  char *name;
882169689Skan  struct dump_file_info *dfi;
88390075Sobrien  FILE *stream;
884117395Skan
885169689Skan  if (phase == TDI_none || !dump_enabled_p (phase))
88690075Sobrien    return NULL;
887117395Skan
888169689Skan  name = get_dump_file_name (phase);
889169689Skan  dfi = get_dump_file_info (phase);
890169689Skan  stream = fopen (name, dfi->state < 0 ? "w" : "a");
89190075Sobrien  if (!stream)
892169689Skan    error ("could not open dump file %qs: %s", name, strerror (errno));
89390075Sobrien  else
894169689Skan    dfi->state = 1;
89590075Sobrien  free (name);
896169689Skan
89790075Sobrien  if (flag_ptr)
898169689Skan    *flag_ptr = dfi->flags;
899117395Skan
90090075Sobrien  return stream;
90190075Sobrien}
90290075Sobrien
903169689Skan/* Returns nonzero if tree dump PHASE is enabled.  If PHASE is
904169689Skan   TDI_tree_all, return nonzero if any dump is enabled.  */
90590075Sobrien
90690075Sobrienint
907132718Skandump_enabled_p (enum tree_dump_index phase)
90890075Sobrien{
909169689Skan  if (phase == TDI_tree_all)
910169689Skan    {
911169689Skan      size_t i;
912169689Skan      for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
913169689Skan	if (dump_files[i].state)
914169689Skan	  return 1;
915169689Skan      for (i = 0; i < extra_dump_files_in_use; i++)
916169689Skan	if (extra_dump_files[i].state)
917169689Skan	  return 1;
918169689Skan      return 0;
919169689Skan    }
920169689Skan  else
921169689Skan    {
922169689Skan      struct dump_file_info *dfi = get_dump_file_info (phase);
923169689Skan      return dfi->state;
924169689Skan    }
92590075Sobrien}
92690075Sobrien
927169689Skan/* Returns nonzero if tree dump PHASE has been initialized.  */
928169689Skan
929169689Skanint
930169689Skandump_initialized_p (enum tree_dump_index phase)
931169689Skan{
932169689Skan  struct dump_file_info *dfi = get_dump_file_info (phase);
933169689Skan  return dfi->state > 0;
934169689Skan}
935169689Skan
93690075Sobrien/* Returns the switch name of PHASE.  */
93790075Sobrien
93890075Sobrienconst char *
939132718Skandump_flag_name (enum tree_dump_index phase)
94090075Sobrien{
941169689Skan  struct dump_file_info *dfi = get_dump_file_info (phase);
942169689Skan  return dfi->swtch;
94390075Sobrien}
94490075Sobrien
94590075Sobrien/* Finish a tree dump for PHASE. STREAM is the stream created by
94690075Sobrien   dump_begin.  */
94790075Sobrien
94890075Sobrienvoid
949132718Skandump_end (enum tree_dump_index phase ATTRIBUTE_UNUSED, FILE *stream)
95090075Sobrien{
95190075Sobrien  fclose (stream);
95290075Sobrien}
95390075Sobrien
954169689Skan/* Enable all tree dumps.  Return number of enabled tree dumps.  */
955169689Skan
956169689Skanstatic int
957169689Skandump_enable_all (int flags, int letter)
958169689Skan{
959169689Skan  int ir_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
960169689Skan  int n = 0;
961169689Skan  size_t i;
962169689Skan
963169689Skan  for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
964169689Skan    if ((dump_files[i].flags & ir_type)
965169689Skan	&& (letter == 0 || letter == dump_files[i].letter))
966169689Skan      {
967169689Skan        dump_files[i].state = -1;
968169689Skan        dump_files[i].flags |= flags;
969169689Skan        n++;
970169689Skan      }
971169689Skan
972169689Skan  for (i = 0; i < extra_dump_files_in_use; i++)
973169689Skan    if ((extra_dump_files[i].flags & ir_type)
974169689Skan	&& (letter == 0 || letter == extra_dump_files[i].letter))
975169689Skan      {
976169689Skan        extra_dump_files[i].state = -1;
977169689Skan        extra_dump_files[i].flags |= flags;
978169689Skan	n++;
979169689Skan      }
980169689Skan
981169689Skan  return n;
982169689Skan}
983169689Skan
984117395Skan/* Parse ARG as a dump switch. Return nonzero if it is, and store the
98590075Sobrien   relevant details in the dump_files array.  */
98690075Sobrien
987169689Skanstatic int
988169689Skandump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
98990075Sobrien{
99090075Sobrien  const char *option_value;
991169689Skan  const char *ptr;
992169689Skan  int flags;
993169689Skan
994169689Skan  if (doglob && !dfi->glob)
995169689Skan    return 0;
996117395Skan
997169689Skan  option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
998169689Skan  if (!option_value)
999169689Skan    return 0;
1000117395Skan
1001169689Skan  ptr = option_value;
1002169689Skan  flags = 0;
1003117395Skan
1004169689Skan  while (*ptr)
1005169689Skan    {
1006169689Skan      const struct dump_option_value_info *option_ptr;
1007169689Skan      const char *end_ptr;
1008169689Skan      unsigned length;
1009117395Skan
1010169689Skan      while (*ptr == '-')
1011169689Skan	ptr++;
1012169689Skan      end_ptr = strchr (ptr, '-');
1013169689Skan      if (!end_ptr)
1014169689Skan	end_ptr = ptr + strlen (ptr);
1015169689Skan      length = end_ptr - ptr;
1016169689Skan
1017169689Skan      for (option_ptr = dump_options; option_ptr->name; option_ptr++)
1018169689Skan	if (strlen (option_ptr->name) == length
1019169689Skan	    && !memcmp (option_ptr->name, ptr, length))
1020169689Skan	  {
1021169689Skan	    flags |= option_ptr->value;
1022169689Skan	    goto found;
102390075Sobrien	  }
1024169689Skan      warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
1025169689Skan	       length, ptr, dfi->swtch);
1026169689Skan    found:;
1027169689Skan      ptr = end_ptr;
1028169689Skan    }
1029117395Skan
1030169689Skan  dfi->state = -1;
1031169689Skan  dfi->flags |= flags;
1032117395Skan
1033169689Skan  /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
1034169689Skan     known dumps.  */
1035169689Skan  if (dfi->suffix == NULL)
1036169689Skan    dump_enable_all (dfi->flags, 0);
1037169689Skan
1038169689Skan  return 1;
103990075Sobrien}
1040169689Skan
1041169689Skanint
1042169689Skandump_switch_p (const char *arg)
1043169689Skan{
1044169689Skan  size_t i;
1045169689Skan  int any = 0;
1046169689Skan
1047169689Skan  for (i = TDI_none + 1; i != TDI_end; i++)
1048169689Skan    any |= dump_switch_p_1 (arg, &dump_files[i], false);
1049169689Skan
1050169689Skan  /* Don't glob if we got a hit already */
1051169689Skan  if (!any)
1052169689Skan    for (i = TDI_none + 1; i != TDI_end; i++)
1053169689Skan      any |= dump_switch_p_1 (arg, &dump_files[i], true);
1054169689Skan
1055169689Skan  for (i = 0; i < extra_dump_files_in_use; i++)
1056169689Skan    any |= dump_switch_p_1 (arg, &extra_dump_files[i], false);
1057169689Skan
1058169689Skan  if (!any)
1059169689Skan    for (i = 0; i < extra_dump_files_in_use; i++)
1060169689Skan      any |= dump_switch_p_1 (arg, &extra_dump_files[i], true);
1061169689Skan
1062169689Skan
1063169689Skan  return any;
1064169689Skan}
1065169689Skan
1066169689Skan/* Dump FUNCTION_DECL FN as tree dump PHASE.  */
1067169689Skan
1068169689Skanvoid
1069169689Skandump_function (enum tree_dump_index phase, tree fn)
1070169689Skan{
1071169689Skan  FILE *stream;
1072169689Skan  int flags;
1073169689Skan
1074169689Skan  stream = dump_begin (phase, &flags);
1075169689Skan  if (stream)
1076169689Skan    {
1077169689Skan      dump_function_to_file (fn, stream, flags);
1078169689Skan      dump_end (phase, stream);
1079169689Skan    }
1080169689Skan}
1081169689Skan
1082169689Skanbool
1083169689Skanenable_rtl_dump_file (int letter)
1084169689Skan{
1085169689Skan  if (letter == 'a')
1086169689Skan    letter = 0;
1087169689Skan
1088169689Skan  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, letter) > 0;
1089169689Skan}
1090169689Skan
1091169689Skan
1092