OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / tree-dump.c
index b171abd..2882611 100644 (file)
@@ -1,12 +1,13 @@
 /* Tree-dumping functionality for intermediate representation.
 /* Tree-dumping functionality for intermediate representation.
-   Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+   2010, 2011 Free Software Foundation, Inc.
    Written by Mark Mitchell <mark@codesourcery.com>
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
    Written by Mark Mitchell <mark@codesourcery.com>
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -15,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
 
 #include "config.h"
 #include "system.h"
@@ -25,26 +25,30 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tm.h"
 #include "tree.h"
 #include "splay-tree.h"
 #include "tm.h"
 #include "tree.h"
 #include "splay-tree.h"
-#include "diagnostic.h"
+#include "filenames.h"
+#include "diagnostic-core.h"
 #include "toplev.h"
 #include "tree-dump.h"
 #include "toplev.h"
 #include "tree-dump.h"
+#include "tree-pass.h"
 #include "langhooks.h"
 #include "langhooks.h"
+#include "tree-iterator.h"
 
 
-static unsigned int queue PARAMS ((dump_info_p, tree, int));
-static void dump_index PARAMS ((dump_info_p, unsigned int));
-static void dequeue_and_dump PARAMS ((dump_info_p));
-static void dump_new_line PARAMS ((dump_info_p));
-static void dump_maybe_newline PARAMS ((dump_info_p));
-static void dump_string_field PARAMS ((dump_info_p, const char *, const char *));
+/* If non-NULL, return one past-the-end of the matching SUBPART of
+   the WHOLE string.  */
+#define skip_leading_substring(whole,  part) \
+   (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
+
+static unsigned int queue (dump_info_p, const_tree, int);
+static void dump_index (dump_info_p, unsigned int);
+static void dequeue_and_dump (dump_info_p);
+static void dump_new_line (dump_info_p);
+static void dump_maybe_newline (dump_info_p);
 
 /* Add T to the end of the queue of nodes to dump.  Returns the index
    assigned to T.  */
 
 static unsigned int
 
 /* Add T to the end of the queue of nodes to dump.  Returns the index
    assigned to T.  */
 
 static unsigned int
-queue (di, t, flags)
-     dump_info_p di;
-     tree t;
-     int flags;
+queue (dump_info_p di, const_tree t, int flags)
 {
   dump_queue_p dq;
   dump_node_info_p dni;
 {
   dump_queue_p dq;
   dump_node_info_p dni;
@@ -60,10 +64,10 @@ queue (di, t, flags)
       di->free_list = dq->next;
     }
   else
       di->free_list = dq->next;
     }
   else
-    dq = (dump_queue_p) xmalloc (sizeof (struct dump_queue));
+    dq = XNEW (struct dump_queue);
 
   /* Create a new entry in the splay-tree.  */
 
   /* Create a new entry in the splay-tree.  */
-  dni = (dump_node_info_p) xmalloc (sizeof (struct dump_node_info));
+  dni = XNEW (struct dump_node_info);
   dni->index = index;
   dni->binfo_p = ((flags & DUMP_BINFO) != 0);
   dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
   dni->index = index;
   dni->binfo_p = ((flags & DUMP_BINFO) != 0);
   dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
@@ -82,9 +86,7 @@ queue (di, t, flags)
 }
 
 static void
 }
 
 static void
-dump_index (di, index)
-     dump_info_p di;
-     unsigned int index;
+dump_index (dump_info_p di, unsigned int index)
 {
   fprintf (di->stream, "@%-6u ", index);
   di->column += 8;
 {
   fprintf (di->stream, "@%-6u ", index);
   di->column += 8;
@@ -95,11 +97,7 @@ dump_index (di, index)
    index of T is printed.  */
 
 void
    index of T is printed.  */
 
 void
-queue_and_dump_index (di, field, t, flags)
-     dump_info_p di;
-     const char *field;
-     tree t;
-     int flags;
+queue_and_dump_index (dump_info_p di, const char *field, const_tree t, int flags)
 {
   unsigned int index;
   splay_tree_node n;
 {
   unsigned int index;
   splay_tree_node n;
@@ -127,9 +125,7 @@ queue_and_dump_index (di, field, t, flags)
 /* Dump the type of T.  */
 
 void
 /* Dump the type of T.  */
 
 void
-queue_and_dump_type (di, t)
-     dump_info_p di;
-     tree t;
+queue_and_dump_type (dump_info_p di, const_tree t)
 {
   queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
 }
 {
   queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
 }
@@ -143,8 +139,7 @@ queue_and_dump_type (di, t)
    place to start printing more fields.  */
 
 static void
    place to start printing more fields.  */
 
 static void
-dump_new_line (di)
-     dump_info_p di;
+dump_new_line (dump_info_p di)
 {
   fprintf (di->stream, "\n%*s", SOL_COLUMN, "");
   di->column = SOL_COLUMN;
 {
   fprintf (di->stream, "\n%*s", SOL_COLUMN, "");
   di->column = SOL_COLUMN;
@@ -153,8 +148,7 @@ dump_new_line (di)
 /* If necessary, insert a new line.  */
 
 static void
 /* If necessary, insert a new line.  */
 
 static void
-dump_maybe_newline (di)
-     dump_info_p di;
+dump_maybe_newline (dump_info_p di)
 {
   int extra;
 
 {
   int extra;
 
@@ -172,35 +166,53 @@ dump_maybe_newline (di)
 /* Dump pointer PTR using FIELD to identify it.  */
 
 void
 /* Dump pointer PTR using FIELD to identify it.  */
 
 void
-dump_pointer (di, field, ptr)
-     dump_info_p di;
-     const char *field;
-     void *ptr;
+dump_pointer (dump_info_p di, const char *field, void *ptr)
 {
   dump_maybe_newline (di);
 {
   dump_maybe_newline (di);
-  fprintf (di->stream, "%-4s: %-8lx ", field, (long) ptr);
+  fprintf (di->stream, "%-4s: %-8" HOST_WIDE_INT_PRINT "x ", field,
+          (unsigned HOST_WIDE_INT) (uintptr_t) ptr);
   di->column += 15;
 }
 
 /* Dump integer I using FIELD to identify it.  */
 
 void
   di->column += 15;
 }
 
 /* Dump integer I using FIELD to identify it.  */
 
 void
-dump_int (di, field, i)
-     dump_info_p di;
-     const char *field;
-     int i;
+dump_int (dump_info_p di, const char *field, int i)
 {
   dump_maybe_newline (di);
   fprintf (di->stream, "%-4s: %-7d ", field, i);
   di->column += 14;
 }
 
 {
   dump_maybe_newline (di);
   fprintf (di->stream, "%-4s: %-7d ", field, i);
   di->column += 14;
 }
 
+/* Dump the floating point value R, using FIELD to identify it.  */
+
+static void
+dump_real (dump_info_p di, const char *field, const REAL_VALUE_TYPE *r)
+{
+  char buf[32];
+  real_to_decimal (buf, r, sizeof (buf), 0, true);
+  dump_maybe_newline (di);
+  fprintf (di->stream, "%-4s: %s ", field, buf);
+  di->column += strlen (buf) + 7;
+}
+
+/* Dump the fixed-point value F, using FIELD to identify it.  */
+
+static void
+dump_fixed (dump_info_p di, const char *field, const FIXED_VALUE_TYPE *f)
+{
+  char buf[32];
+  fixed_to_decimal (buf, f, sizeof (buf));
+  dump_maybe_newline (di);
+  fprintf (di->stream, "%-4s: %s ", field, buf);
+  di->column += strlen (buf) + 7;
+}
+
+
 /* Dump the string S.  */
 
 void
 /* Dump the string S.  */
 
 void
-dump_string (di, string)
-     dump_info_p di;
-     const char *string;
+dump_string (dump_info_p di, const char *string)
 {
   dump_maybe_newline (di);
   fprintf (di->stream, "%-13s ", string);
 {
   dump_maybe_newline (di);
   fprintf (di->stream, "%-13s ", string);
@@ -212,11 +224,8 @@ dump_string (di, string)
 
 /* Dump the string field S.  */
 
 
 /* Dump the string field S.  */
 
-static void
-dump_string_field (di, field, string)
-     dump_info_p di;
-     const char *field;
-     const char *string;
+void
+dump_string_field (dump_info_p di, const char *field, const char *string)
 {
   dump_maybe_newline (di);
   fprintf (di->stream, "%-4s: %-7s ", field, string);
 {
   dump_maybe_newline (di);
   fprintf (di->stream, "%-4s: %-7s ", field, string);
@@ -229,8 +238,7 @@ dump_string_field (di, field, string)
 /* Dump the next node in the queue.  */
 
 static void
 /* Dump the next node in the queue.  */
 
 static void
-dequeue_and_dump (di)
-     dump_info_p di;
+dequeue_and_dump (dump_info_p di)
 {
   dump_queue_p dq;
   splay_tree_node stn;
 {
   dump_queue_p dq;
   splay_tree_node stn;
@@ -238,7 +246,7 @@ dequeue_and_dump (di)
   tree t;
   unsigned int index;
   enum tree_code code;
   tree t;
   unsigned int index;
   enum tree_code code;
-  char code_class;
+  enum tree_code_class code_class;
   const char* code_name;
 
   /* Get the next node from the queue.  */
   const char* code_name;
 
   /* Get the next node from the queue.  */
@@ -274,20 +282,18 @@ dequeue_and_dump (di)
   if (dni->binfo_p)
     {
       unsigned ix;
   if (dni->binfo_p)
     {
       unsigned ix;
-      tree bases = BINFO_BASETYPES (t);
-      unsigned n_bases = bases ? TREE_VEC_LENGTH (bases): 0;
-      tree accesses = BINFO_BASEACCESSES (t);
-      
+      tree base;
+      VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (t);
+
       dump_child ("type", BINFO_TYPE (t));
 
       dump_child ("type", BINFO_TYPE (t));
 
-      if (TREE_VIA_VIRTUAL (t))
-       dump_string (di, "virt");
+      if (BINFO_VIRTUAL_P (t))
+       dump_string_field (di, "spec", "virt");
 
 
-      dump_int (di, "bases", n_bases);
-      for (ix = 0; ix != n_bases; ix++)
+      dump_int (di, "bases", BINFO_N_BASE_BINFOS (t));
+      for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++)
        {
        {
-         tree base = TREE_VEC_ELT (bases, ix);
-         tree access = (accesses ? TREE_VEC_ELT (accesses, ix)
+         tree access = (accesses ? VEC_index (tree, accesses, ix)
                         : access_public_node);
          const char *string = NULL;
 
                         : access_public_node);
          const char *string = NULL;
 
@@ -298,12 +304,12 @@ dequeue_and_dump (di)
          else if (access == access_private_node)
            string = "priv";
          else
          else if (access == access_private_node)
            string = "priv";
          else
-           abort ();
-         
-         dump_string (di, string);
+           gcc_unreachable ();
+
+         dump_string_field (di, "accs", string);
          queue_and_dump_index (di, "binf", base, DUMP_BINFO);
        }
          queue_and_dump_index (di, "binf", base, DUMP_BINFO);
        }
-      
+
       goto done;
     }
 
       goto done;
     }
 
@@ -316,60 +322,63 @@ dequeue_and_dump (di)
 
       switch (code_class)
        {
 
       switch (code_class)
        {
-       case '1':
+       case tcc_unary:
          dump_child ("op 0", TREE_OPERAND (t, 0));
          break;
 
          dump_child ("op 0", TREE_OPERAND (t, 0));
          break;
 
-       case '2':
-       case '<':
+       case tcc_binary:
+       case tcc_comparison:
          dump_child ("op 0", TREE_OPERAND (t, 0));
          dump_child ("op 1", TREE_OPERAND (t, 1));
          break;
 
          dump_child ("op 0", TREE_OPERAND (t, 0));
          dump_child ("op 1", TREE_OPERAND (t, 1));
          break;
 
-       case 'e':
+       case tcc_expression:
+       case tcc_reference:
+       case tcc_statement:
+       case tcc_vl_exp:
          /* These nodes are handled explicitly below.  */
          break;
 
        default:
          /* These nodes are handled explicitly below.  */
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
   else if (DECL_P (t))
     {
        }
     }
   else if (DECL_P (t))
     {
+      expanded_location xloc;
       /* All declarations have names.  */
       if (DECL_NAME (t))
        dump_child ("name", DECL_NAME (t));
       if (DECL_ASSEMBLER_NAME_SET_P (t)
          && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t))
        dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
       /* All declarations have names.  */
       if (DECL_NAME (t))
        dump_child ("name", DECL_NAME (t));
       if (DECL_ASSEMBLER_NAME_SET_P (t)
          && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t))
        dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
+      if (DECL_ABSTRACT_ORIGIN (t))
+        dump_child ("orig", DECL_ABSTRACT_ORIGIN (t));
       /* And types.  */
       queue_and_dump_type (di, t);
       dump_child ("scpe", DECL_CONTEXT (t));
       /* And a source position.  */
       /* And types.  */
       queue_and_dump_type (di, t);
       dump_child ("scpe", DECL_CONTEXT (t));
       /* And a source position.  */
-      if (DECL_SOURCE_FILE (t))
+      xloc = expand_location (DECL_SOURCE_LOCATION (t));
+      if (xloc.file)
        {
        {
-         const char *filename = strrchr (DECL_SOURCE_FILE (t), '/');
-         if (!filename)
-           filename = DECL_SOURCE_FILE (t);
-         else
-           /* Skip the slash.  */
-           ++filename;
+         const char *filename = lbasename (xloc.file);
 
          dump_maybe_newline (di);
          fprintf (di->stream, "srcp: %s:%-6d ", filename,
 
          dump_maybe_newline (di);
          fprintf (di->stream, "srcp: %s:%-6d ", filename,
-                  DECL_SOURCE_LINE (t));
+                  xloc.line);
          di->column += 6 + strlen (filename) + 8;
        }
       /* And any declaration can be compiler-generated.  */
          di->column += 6 + strlen (filename) + 8;
        }
       /* And any declaration can be compiler-generated.  */
-      if (DECL_ARTIFICIAL (t))
-       dump_string (di, "artificial");
-      if (TREE_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
-       dump_child ("chan", TREE_CHAIN (t));
+      if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_COMMON)
+         && DECL_ARTIFICIAL (t))
+       dump_string_field (di, "note", "artificial");
+      if (DECL_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
+       dump_child ("chain", DECL_CHAIN (t));
     }
     }
-  else if (code_class == 't')
+  else if (code_class == tcc_type)
     {
       /* All types have qualifiers.  */
     {
       /* All types have qualifiers.  */
-      int quals = (*lang_hooks.tree_dump.type_quals) (t);
+      int quals = lang_hooks.tree_dump.type_quals (t);
 
       if (quals != TYPE_UNQUALIFIED)
        {
 
       if (quals != TYPE_UNQUALIFIED)
        {
@@ -393,14 +402,14 @@ dequeue_and_dump (di)
       /* All types have alignments.  */
       dump_int (di, "algn", TYPE_ALIGN (t));
     }
       /* All types have alignments.  */
       dump_int (di, "algn", TYPE_ALIGN (t));
     }
-  else if (code_class == 'c')
+  else if (code_class == tcc_constant)
     /* All constants can have types.  */
     queue_and_dump_type (di, t);
 
   /* Give the language-specific code a chance to print something.  If
      it's completely taken care of things, don't bother printing
      anything more ourselves.  */
     /* All constants can have types.  */
     queue_and_dump_type (di, t);
 
   /* Give the language-specific code a chance to print something.  If
      it's completely taken care of things, don't bother printing
      anything more ourselves.  */
-  if ((*lang_hooks.tree_dump.dump_tree) (di, t))
+  if (lang_hooks.tree_dump.dump_tree (di, t))
     goto done;
 
   /* Now handle the various kinds of nodes.  */
     goto done;
 
   /* Now handle the various kinds of nodes.  */
@@ -419,6 +428,18 @@ dequeue_and_dump (di)
       dump_child ("chan", TREE_CHAIN (t));
       break;
 
       dump_child ("chan", TREE_CHAIN (t));
       break;
 
+    case STATEMENT_LIST:
+      {
+       tree_stmt_iterator it;
+       for (i = 0, it = tsi_start (t); !tsi_end_p (it); tsi_next (&it), i++)
+         {
+           char buffer[32];
+           sprintf (buffer, "%u", i);
+           dump_child (buffer, tsi_stmt (it));
+         }
+      }
+      break;
+
     case TREE_VEC:
       dump_int (di, "lngt", TREE_VEC_LENGTH (t));
       for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
     case TREE_VEC:
       dump_int (di, "lngt", TREE_VEC_LENGTH (t));
       for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
@@ -432,8 +453,7 @@ dequeue_and_dump (di)
     case INTEGER_TYPE:
     case ENUMERAL_TYPE:
       dump_int (di, "prec", TYPE_PRECISION (t));
     case INTEGER_TYPE:
     case ENUMERAL_TYPE:
       dump_int (di, "prec", TYPE_PRECISION (t));
-      if (TREE_UNSIGNED (t))
-       dump_string (di, "unsigned");
+      dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
       dump_child ("min", TYPE_MIN_VALUE (t));
       dump_child ("max", TYPE_MAX_VALUE (t));
 
       dump_child ("min", TYPE_MIN_VALUE (t));
       dump_child ("max", TYPE_MAX_VALUE (t));
 
@@ -445,6 +465,13 @@ dequeue_and_dump (di)
       dump_int (di, "prec", TYPE_PRECISION (t));
       break;
 
       dump_int (di, "prec", TYPE_PRECISION (t));
       break;
 
+    case FIXED_POINT_TYPE:
+      dump_int (di, "prec", TYPE_PRECISION (t));
+      dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
+      dump_string_field (di, "saturating",
+                        TYPE_SATURATING (t) ? "saturating": "non-saturating");
+      break;
+
     case POINTER_TYPE:
       dump_child ("ptd", TREE_TYPE (t));
       break;
     case POINTER_TYPE:
       dump_child ("ptd", TREE_TYPE (t));
       break;
@@ -470,9 +497,9 @@ dequeue_and_dump (di)
     case RECORD_TYPE:
     case UNION_TYPE:
       if (TREE_CODE (t) == RECORD_TYPE)
     case RECORD_TYPE:
     case UNION_TYPE:
       if (TREE_CODE (t) == RECORD_TYPE)
-       dump_string (di, "struct");
+       dump_string_field (di, "tag", "struct");
       else
       else
-       dump_string (di, "union");
+       dump_string_field (di, "tag", "union");
 
       dump_child ("flds", TYPE_FIELDS (t));
       dump_child ("fncs", TYPE_METHODS (t));
 
       dump_child ("flds", TYPE_FIELDS (t));
       dump_child ("fncs", TYPE_METHODS (t));
@@ -484,6 +511,10 @@ dequeue_and_dump (di)
       dump_child ("cnst", DECL_INITIAL (t));
       break;
 
       dump_child ("cnst", DECL_INITIAL (t));
       break;
 
+    case DEBUG_EXPR_DECL:
+      dump_int (di, "-uid", DEBUG_TEMP_UID (t));
+      /* Fall through.  */
+
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
@@ -505,19 +536,19 @@ dequeue_and_dump (di)
        {
          dump_int (di, "used", TREE_USED (t));
          if (DECL_REGISTER (t))
        {
          dump_int (di, "used", TREE_USED (t));
          if (DECL_REGISTER (t))
-           dump_string (di, "register");
+           dump_string_field (di, "spec", "register");
        }
       break;
 
     case FUNCTION_DECL:
       dump_child ("args", DECL_ARGUMENTS (t));
       if (DECL_EXTERNAL (t))
        }
       break;
 
     case FUNCTION_DECL:
       dump_child ("args", DECL_ARGUMENTS (t));
       if (DECL_EXTERNAL (t))
-       dump_string (di, "undefined");
+       dump_string_field (di, "body", "undefined");
       if (TREE_PUBLIC (t))
       if (TREE_PUBLIC (t))
-       dump_string (di, "extern");
+       dump_string_field (di, "link", "extern");
       else
       else
-       dump_string (di, "static");
-      if (DECL_LANG_SPECIFIC (t) && !dump_flag (di, TDF_SLIM, t))
+       dump_string_field (di, "link", "static");
+      if (DECL_SAVED_TREE (t) && !dump_flag (di, TDF_SLIM, t))
        dump_child ("body", DECL_SAVED_TREE (t));
       break;
 
        dump_child ("body", DECL_SAVED_TREE (t));
       break;
 
@@ -532,11 +563,21 @@ dequeue_and_dump (di)
       dump_int (di, "lngt", TREE_STRING_LENGTH (t));
       break;
 
       dump_int (di, "lngt", TREE_STRING_LENGTH (t));
       break;
 
+    case REAL_CST:
+      dump_real (di, "valu", TREE_REAL_CST_PTR (t));
+      break;
+
+    case FIXED_CST:
+      dump_fixed (di, "valu", TREE_FIXED_CST_PTR (t));
+      break;
+
     case TRUTH_NOT_EXPR:
     case ADDR_EXPR:
     case INDIRECT_REF:
     case CLEANUP_POINT_EXPR:
     case SAVE_EXPR:
     case TRUTH_NOT_EXPR:
     case ADDR_EXPR:
     case INDIRECT_REF:
     case CLEANUP_POINT_EXPR:
     case SAVE_EXPR:
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
       /* These nodes are unary, but do not have code class `1'.  */
       dump_child ("op 0", TREE_OPERAND (t, 0));
       break;
       /* These nodes are unary, but do not have code class `1'.  */
       dump_child ("op 0", TREE_OPERAND (t, 0));
       break;
@@ -545,9 +586,7 @@ dequeue_and_dump (di)
     case TRUTH_ORIF_EXPR:
     case INIT_EXPR:
     case MODIFY_EXPR:
     case TRUTH_ORIF_EXPR:
     case INIT_EXPR:
     case MODIFY_EXPR:
-    case COMPONENT_REF:
     case COMPOUND_EXPR:
     case COMPOUND_EXPR:
-    case ARRAY_REF:
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
@@ -557,19 +596,59 @@ dequeue_and_dump (di)
       dump_child ("op 1", TREE_OPERAND (t, 1));
       break;
 
       dump_child ("op 1", TREE_OPERAND (t, 1));
       break;
 
+    case COMPONENT_REF:
+      dump_child ("op 0", TREE_OPERAND (t, 0));
+      dump_child ("op 1", TREE_OPERAND (t, 1));
+      dump_child ("op 2", TREE_OPERAND (t, 2));
+      break;
+
+    case ARRAY_REF:
+    case ARRAY_RANGE_REF:
+      dump_child ("op 0", TREE_OPERAND (t, 0));
+      dump_child ("op 1", TREE_OPERAND (t, 1));
+      dump_child ("op 2", TREE_OPERAND (t, 2));
+      dump_child ("op 3", TREE_OPERAND (t, 3));
+      break;
+
     case COND_EXPR:
       dump_child ("op 0", TREE_OPERAND (t, 0));
       dump_child ("op 1", TREE_OPERAND (t, 1));
       dump_child ("op 2", TREE_OPERAND (t, 2));
       break;
 
     case COND_EXPR:
       dump_child ("op 0", TREE_OPERAND (t, 0));
       dump_child ("op 1", TREE_OPERAND (t, 1));
       dump_child ("op 2", TREE_OPERAND (t, 2));
       break;
 
+    case TRY_FINALLY_EXPR:
+      dump_child ("op 0", TREE_OPERAND (t, 0));
+      dump_child ("op 1", TREE_OPERAND (t, 1));
+      break;
+
     case CALL_EXPR:
     case CALL_EXPR:
-      dump_child ("fn", TREE_OPERAND (t, 0));
-      dump_child ("args", TREE_OPERAND (t, 1));
+      {
+       int i = 0;
+       tree arg;
+       call_expr_arg_iterator iter;
+       dump_child ("fn", CALL_EXPR_FN (t));
+       FOR_EACH_CALL_EXPR_ARG (arg, iter, t)
+         {
+           char buffer[32];
+           sprintf (buffer, "%u", i);
+           dump_child (buffer, arg);
+           i++;
+         }
+      }
       break;
 
     case CONSTRUCTOR:
       break;
 
     case CONSTRUCTOR:
-      dump_child ("elts", CONSTRUCTOR_ELTS (t));
+      {
+       unsigned HOST_WIDE_INT cnt;
+       tree index, value;
+       dump_int (di, "lngt", VEC_length (constructor_elt,
+                                         CONSTRUCTOR_ELTS (t)));
+       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value)
+         {
+           dump_child ("idx", index);
+           dump_child ("val", value);
+         }
+      }
       break;
 
     case BIND_EXPR:
       break;
 
     case BIND_EXPR:
@@ -585,6 +664,10 @@ dequeue_and_dump (di)
       dump_child ("cond", TREE_OPERAND (t, 0));
       break;
 
       dump_child ("cond", TREE_OPERAND (t, 0));
       break;
 
+    case RETURN_EXPR:
+      dump_child ("expr", TREE_OPERAND (t, 0));
+      break;
+
     case TARGET_EXPR:
       dump_child ("decl", TREE_OPERAND (t, 0));
       dump_child ("init", TREE_OPERAND (t, 1));
     case TARGET_EXPR:
       dump_child ("decl", TREE_OPERAND (t, 0));
       dump_child ("init", TREE_OPERAND (t, 1));
@@ -596,10 +679,37 @@ dequeue_and_dump (di)
       dump_child ("init", TREE_OPERAND (t, 3));
       break;
 
       dump_child ("init", TREE_OPERAND (t, 3));
       break;
 
-    case EXPR_WITH_FILE_LOCATION:
-      dump_child ("expr", EXPR_WFL_NODE (t));
+    case CASE_LABEL_EXPR:
+      dump_child ("name", CASE_LABEL (t));
+      if (CASE_LOW (t))
+       {
+         dump_child ("low ", CASE_LOW (t));
+         if (CASE_HIGH (t))
+           dump_child ("high", CASE_HIGH (t));
+       }
+      break;
+    case LABEL_EXPR:
+      dump_child ("name", TREE_OPERAND (t,0));
+      break;
+    case GOTO_EXPR:
+      dump_child ("labl", TREE_OPERAND (t, 0));
+      break;
+    case SWITCH_EXPR:
+      dump_child ("cond", TREE_OPERAND (t, 0));
+      dump_child ("body", TREE_OPERAND (t, 1));
+      if (TREE_OPERAND (t, 2))
+        {
+         dump_child ("labl", TREE_OPERAND (t,2));
+        }
+      break;
+    case OMP_CLAUSE:
+      {
+       int i;
+       fprintf (di->stream, "%s\n", omp_clause_code_name[OMP_CLAUSE_CODE (t)]);
+       for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; i++)
+         dump_child ("op: ", OMP_CLAUSE_OPERAND (t, i));
+      }
       break;
       break;
-
     default:
       /* There are no additional fields to print.  */
       break;
     default:
       /* There are no additional fields to print.  */
       break;
@@ -616,10 +726,7 @@ dequeue_and_dump (di)
 /* Return nonzero if FLAG has been specified for the dump, and NODE
    is not the root node of the dump.  */
 
 /* Return nonzero if FLAG has been specified for the dump, and NODE
    is not the root node of the dump.  */
 
-int dump_flag (di, flag, node)
-     dump_info_p di;
-     int flag;
-     tree node;
+int dump_flag (dump_info_p di, int flag, const_tree node)
 {
   return (di->flags & flag) && (node != di->node);
 }
 {
   return (di->flags & flag) && (node != di->node);
 }
@@ -627,10 +734,7 @@ int dump_flag (di, flag, node)
 /* Dump T, and all its children, on STREAM.  */
 
 void
 /* Dump T, and all its children, on STREAM.  */
 
 void
-dump_node (t, flags, stream)
-     tree t;
-     int flags;
-     FILE *stream;
+dump_node (const_tree t, int flags, FILE *stream)
 {
   struct dump_info di;
   dump_queue_p dq;
 {
   struct dump_info di;
   dump_queue_p dq;
@@ -663,27 +767,33 @@ dump_node (t, flags, stream)
     }
   splay_tree_delete (di.nodes);
 }
     }
   splay_tree_delete (di.nodes);
 }
-
-/* Define a tree dump switch.  */
-struct dump_file_info
-{
-  const char *const suffix;    /* suffix to give output file.  */
-  const char *const swtch;     /* command line switch */
-  int flags;                   /* user flags */
-  int state;                   /* state of play */
-};
+\f
 
 /* Table of tree dump switches. This must be consistent with the
 
 /* Table of tree dump switches. This must be consistent with the
-   TREE_DUMP_INDEX enumeration in tree.h */
+   tree_dump_index enumeration in tree-pass.h.  */
 static struct dump_file_info dump_files[TDI_end] =
 {
 static struct dump_file_info dump_files[TDI_end] =
 {
-  {".tu", "dump-translation-unit", 0, 0},
-  {".class", "dump-class-hierarchy", 0, 0},
-  {".original", "dump-tree-original", 0, 0},
-  {".optimized", "dump-tree-optimized", 0, 0},
-  {".inlined", "dump-tree-inlined", 0, 0},
+  {NULL, NULL, NULL, 0, 0, 0},
+  {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0,  0},
+  {".tu", "translation-unit", NULL, TDF_TREE, 0, 1},
+  {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2},
+  {".original", "tree-original", NULL, TDF_TREE, 0, 3},
+  {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4},
+  {".nested", "tree-nested", NULL, TDF_TREE, 0, 5},
+  {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 6},
+  {".ads", "ada-spec", NULL, 0, 0, 7},
+#define FIRST_AUTO_NUMBERED_DUMP 8
+
+  {NULL, "tree-all", NULL, TDF_TREE, 0, 0},
+  {NULL, "rtl-all", NULL, TDF_RTL, 0, 0},
+  {NULL, "ipa-all", NULL, TDF_IPA, 0, 0},
 };
 
 };
 
+/* Dynamically registered tree dump files and switches.  */
+static struct dump_file_info *extra_dump_files;
+static size_t extra_dump_files_in_use;
+static size_t extra_dump_files_alloced;
+
 /* Define a name->number mapping for a dump flag value.  */
 struct dump_option_value_info
 {
 /* Define a name->number mapping for a dump flag value.  */
 struct dump_option_value_info
 {
@@ -696,116 +806,323 @@ struct dump_option_value_info
 static const struct dump_option_value_info dump_options[] =
 {
   {"address", TDF_ADDRESS},
 static const struct dump_option_value_info dump_options[] =
 {
   {"address", TDF_ADDRESS},
+  {"asmname", TDF_ASMNAME},
   {"slim", TDF_SLIM},
   {"slim", TDF_SLIM},
-  {"all", ~0},
+  {"raw", TDF_RAW},
+  {"graph", TDF_GRAPH},
+  {"details", TDF_DETAILS},
+  {"cselib", TDF_CSELIB},
+  {"stats", TDF_STATS},
+  {"blocks", TDF_BLOCKS},
+  {"vops", TDF_VOPS},
+  {"lineno", TDF_LINENO},
+  {"uid", TDF_UID},
+  {"stmtaddr", TDF_STMTADDR},
+  {"memsyms", TDF_MEMSYMS},
+  {"verbose", TDF_VERBOSE},
+  {"eh", TDF_EH},
+  {"alias", TDF_ALIAS},
+  {"nouid", TDF_NOUID},
+  {"enumerate_locals", TDF_ENUMERATE_LOCALS},
+  {"scev", TDF_SCEV},
+  {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA
+           | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE
+           | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV)},
   {NULL, 0}
 };
 
   {NULL, 0}
 };
 
+unsigned int
+dump_register (const char *suffix, const char *swtch, const char *glob,
+              int flags)
+{
+  static int next_dump = FIRST_AUTO_NUMBERED_DUMP;
+  int num = next_dump++;
+
+  size_t count = extra_dump_files_in_use++;
+
+  if (count >= extra_dump_files_alloced)
+    {
+      if (extra_dump_files_alloced == 0)
+       extra_dump_files_alloced = 32;
+      else
+       extra_dump_files_alloced *= 2;
+      extra_dump_files = XRESIZEVEC (struct dump_file_info,
+                                    extra_dump_files,
+                                    extra_dump_files_alloced);
+    }
+
+  memset (&extra_dump_files[count], 0, sizeof (struct dump_file_info));
+  extra_dump_files[count].suffix = suffix;
+  extra_dump_files[count].swtch = swtch;
+  extra_dump_files[count].glob = glob;
+  extra_dump_files[count].flags = flags;
+  extra_dump_files[count].num = num;
+
+  return count + TDI_end;
+}
+
+
+/* Return the dump_file_info for the given phase.  */
+
+struct dump_file_info *
+get_dump_file_info (int phase)
+{
+  if (phase < TDI_end)
+    return &dump_files[phase];
+  else if ((size_t) (phase - TDI_end) >= extra_dump_files_in_use)
+    return NULL;
+  else
+    return extra_dump_files + (phase - TDI_end);
+}
+
+
+/* Return the name of the dump file for the given phase.
+   If the dump is not enabled, returns NULL.  */
+
+char *
+get_dump_file_name (int phase)
+{
+  char dump_id[10];
+  struct dump_file_info *dfi;
+
+  if (phase == TDI_none)
+    return NULL;
+
+  dfi = get_dump_file_info (phase);
+  if (dfi->state == 0)
+    return NULL;
+
+  if (dfi->num < 0)
+    dump_id[0] = '\0';
+  else
+    {
+      char suffix;
+      if (dfi->flags & TDF_TREE)
+       suffix = 't';
+      else if (dfi->flags & TDF_IPA)
+       suffix = 'i';
+      else
+       suffix = 'r';
+
+      if (snprintf (dump_id, sizeof (dump_id), ".%03d%c", dfi->num, suffix) < 0)
+       dump_id[0] = '\0';
+    }
+
+  return concat (dump_base_name, dump_id, dfi->suffix, NULL);
+}
+
 /* Begin a tree dump for PHASE. Stores any user supplied flag in
    *FLAG_PTR and returns a stream to write to. If the dump is not
    enabled, returns NULL.
    Multiple calls will reopen and append to the dump file.  */
 
 FILE *
 /* Begin a tree dump for PHASE. Stores any user supplied flag in
    *FLAG_PTR and returns a stream to write to. If the dump is not
    enabled, returns NULL.
    Multiple calls will reopen and append to the dump file.  */
 
 FILE *
-dump_begin (phase, flag_ptr)
-     enum tree_dump_index phase;
-     int *flag_ptr;
+dump_begin (int phase, int *flag_ptr)
 {
 {
-  FILE *stream;
   char *name;
   char *name;
+  struct dump_file_info *dfi;
+  FILE *stream;
 
 
-  if (!dump_files[phase].state)
+  if (phase == TDI_none || !dump_enabled_p (phase))
     return NULL;
 
     return NULL;
 
-  name = concat (dump_base_name, dump_files[phase].suffix, NULL);
-  stream = fopen (name, dump_files[phase].state < 0 ? "w" : "a");
+  name = get_dump_file_name (phase);
+  dfi = get_dump_file_info (phase);
+  stream = fopen (name, dfi->state < 0 ? "w" : "a");
   if (!stream)
   if (!stream)
-    error ("could not open dump file `%s'", name);
+    error ("could not open dump file %qs: %m", name);
   else
   else
-    dump_files[phase].state = 1;
+    dfi->state = 1;
   free (name);
   free (name);
+
   if (flag_ptr)
   if (flag_ptr)
-    *flag_ptr = dump_files[phase].flags;
+    *flag_ptr = dfi->flags;
 
   return stream;
 }
 
 
   return stream;
 }
 
-/* Returns nonzero if tree dump PHASE is enabled.  */
+/* Returns nonzero if tree dump PHASE is enabled.  If PHASE is
+   TDI_tree_all, return nonzero if any dump is enabled.  */
 
 int
 
 int
-dump_enabled_p (phase)
-     enum tree_dump_index phase;
+dump_enabled_p (int phase)
 {
 {
-  return dump_files[phase].state;
+  if (phase == TDI_tree_all)
+    {
+      size_t i;
+      for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
+       if (dump_files[i].state)
+         return 1;
+      for (i = 0; i < extra_dump_files_in_use; i++)
+       if (extra_dump_files[i].state)
+         return 1;
+      return 0;
+    }
+  else
+    {
+      struct dump_file_info *dfi = get_dump_file_info (phase);
+      return dfi->state;
+    }
+}
+
+/* Returns nonzero if tree dump PHASE has been initialized.  */
+
+int
+dump_initialized_p (int phase)
+{
+  struct dump_file_info *dfi = get_dump_file_info (phase);
+  return dfi->state > 0;
 }
 
 /* Returns the switch name of PHASE.  */
 
 const char *
 }
 
 /* Returns the switch name of PHASE.  */
 
 const char *
-dump_flag_name (phase)
-     enum tree_dump_index phase;
+dump_flag_name (int phase)
 {
 {
-  return dump_files[phase].swtch;
+  struct dump_file_info *dfi = get_dump_file_info (phase);
+  return dfi->swtch;
 }
 
 /* Finish a tree dump for PHASE. STREAM is the stream created by
    dump_begin.  */
 
 void
 }
 
 /* Finish a tree dump for PHASE. STREAM is the stream created by
    dump_begin.  */
 
 void
-dump_end (phase, stream)
-     enum tree_dump_index phase ATTRIBUTE_UNUSED;
-     FILE *stream;
+dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
 {
   fclose (stream);
 }
 
 {
   fclose (stream);
 }
 
+/* Enable all tree dumps.  Return number of enabled tree dumps.  */
+
+static int
+dump_enable_all (int flags)
+{
+  int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
+  int n = 0;
+  size_t i;
+
+  for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
+    if ((dump_files[i].flags & ir_dump_type))
+      {
+        dump_files[i].state = -1;
+        dump_files[i].flags |= flags;
+        n++;
+      }
+
+  for (i = 0; i < extra_dump_files_in_use; i++)
+    if ((extra_dump_files[i].flags & ir_dump_type))
+      {
+        extra_dump_files[i].state = -1;
+        extra_dump_files[i].flags |= flags;
+       n++;
+      }
+
+  return n;
+}
+
 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
    relevant details in the dump_files array.  */
 
 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
    relevant details in the dump_files array.  */
 
-int
-dump_switch_p (arg)
-     const char *arg;
+static int
+dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
 {
 {
-  unsigned ix;
   const char *option_value;
   const char *option_value;
+  const char *ptr;
+  int flags;
 
 
-  for (ix = 0; ix != TDI_end; ix++)
-    if ((option_value = skip_leading_substring (arg, dump_files[ix].swtch)))
-      {
-       const char *ptr = option_value;
-       int flags = 0;
+  if (doglob && !dfi->glob)
+    return 0;
+
+  option_value = skip_leading_substring (arg, doglob ? dfi->glob : dfi->swtch);
+  if (!option_value)
+    return 0;
+
+  if (*option_value && *option_value != '-')
+    return 0;
 
 
-       while (*ptr)
+  ptr = option_value;
+  flags = 0;
+
+  while (*ptr)
+    {
+      const struct dump_option_value_info *option_ptr;
+      const char *end_ptr;
+      unsigned length;
+
+      while (*ptr == '-')
+       ptr++;
+      end_ptr = strchr (ptr, '-');
+      if (!end_ptr)
+       end_ptr = ptr + strlen (ptr);
+      length = end_ptr - ptr;
+
+      for (option_ptr = dump_options; option_ptr->name; option_ptr++)
+       if (strlen (option_ptr->name) == length
+           && !memcmp (option_ptr->name, ptr, length))
          {
          {
-           const struct dump_option_value_info *option_ptr;
-           const char *end_ptr;
-           unsigned length;
-
-           while (*ptr == '-')
-             ptr++;
-           end_ptr = strchr (ptr, '-');
-           if (!end_ptr)
-             end_ptr = ptr + strlen (ptr);
-           length = end_ptr - ptr;
-
-           for (option_ptr = dump_options; option_ptr->name;
-                option_ptr++)
-             if (strlen (option_ptr->name) == length
-                 && !memcmp (option_ptr->name, ptr, length))
-               {
-                 flags |= option_ptr->value;
-                 goto found;
-               }
-           warning ("ignoring unknown option `%.*s' in `-f%s'",
-                    length, ptr, dump_files[ix].swtch);
-         found:;
-           ptr = end_ptr;
+           flags |= option_ptr->value;
+           goto found;
          }
          }
+      warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
+              length, ptr, dfi->swtch);
+    found:;
+      ptr = end_ptr;
+    }
 
 
-       dump_files[ix].state = -1;
-       dump_files[ix].flags = flags;
+  dfi->state = -1;
+  dfi->flags |= flags;
 
 
-       return 1;
-      }
-  return 0;
+  /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
+     known dumps.  */
+  if (dfi->suffix == NULL)
+    dump_enable_all (dfi->flags);
+
+  return 1;
+}
+
+int
+dump_switch_p (const char *arg)
+{
+  size_t i;
+  int any = 0;
+
+  for (i = TDI_none + 1; i != TDI_end; i++)
+    any |= dump_switch_p_1 (arg, &dump_files[i], false);
+
+  /* Don't glob if we got a hit already */
+  if (!any)
+    for (i = TDI_none + 1; i != TDI_end; i++)
+      any |= dump_switch_p_1 (arg, &dump_files[i], true);
+
+  for (i = 0; i < extra_dump_files_in_use; i++)
+    any |= dump_switch_p_1 (arg, &extra_dump_files[i], false);
+
+  if (!any)
+    for (i = 0; i < extra_dump_files_in_use; i++)
+      any |= dump_switch_p_1 (arg, &extra_dump_files[i], true);
+
+
+  return any;
+}
+
+/* Dump FUNCTION_DECL FN as tree dump PHASE.  */
+
+void
+dump_function (int phase, tree fn)
+{
+  FILE *stream;
+  int flags;
+
+  stream = dump_begin (phase, &flags);
+  if (stream)
+    {
+      dump_function_to_file (fn, stream, flags);
+      dump_end (phase, stream);
+    }
+}
+
+bool
+enable_rtl_dump_file (void)
+{
+  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
 }
 }