diff mbox

Introduce gcc::dump_manager class

Message ID 1381541486.1809.14.camel@surprise
State New
Headers show

Commit Message

David Malcolm Oct. 12, 2013, 1:31 a.m. UTC
When repeatedly compiling within one process, the dumpfile numbering
doesn't reset, leading to dumpfiles after the initial ones having
unpredictable numbers like here (-fdump-tree-all at -O0):
    
      fake.c.000i.cgraph
      fake.c.004t.gimple
      fake.c.1477t.omplower
      fake.c.1478t.lower
      (etc)
    
Note the large (and increasing) leap in the numbering from the base
dumpfiles which get consistent numbering (000, 004 here) to the
autonumbered ones (1477 in this example).  This was due to this implicit
state within dump_register:
    
      static int next_dump = FIRST_AUTO_NUMBERED_DUMP;
      int num = next_dump++;

messing up the numbering on subsequent in-process creation of passes.

This patch introduces a new gcc::dump_manager class to hold such state,
with a singleton owned by the gcc::context, fixing the inconsistent
dumpfile numbering.
    
Specifically, the following variables from dumpfile.c are moved from
being statically allocated to being fields of gcc::dump_manager (gaining
"m_" prefixes):
    
      * next_dump
      * extra_dump_files
      * extra_dump_files_in_use
      * extra_dump_files_alloced

Potentially other aspects of dumping could be moved here, but this
seemed like a logically self-contained change.

Successfully bootstrapped and regtested on x86_64-unknown-linux.

OK for trunk?

(I've already applied this to the "dmalcolm/jit" branch as commits
190e9835a3ad4f43abf68aa7e400597d992525be
6c1464cdf7c9644383796b0ff5f1756d5279d6cb
c07d4be4d6e3e732ba36a5ac7b69cce461c44c79)
    
gcc/
	* dumpfile.h (gcc::dump_manager): New class, to hold state
	relating to dumpfile management.
	(get_dump_file_name): Remove in favor of method of dump_manager.
	(dump_initialized_p): Likewise.
	(dump_start): Likewise.
	(dump_finish): Likewise.
	(dump_switch_p): Likewise.
	(dump_register): Likewise.
	(get_dump_file_info): Likewise.
	* context.c (gcc::context::context): Construct the dump_manager
	instance.
	* context.h (gcc::context::get_dumps): New.
	(gcc::context::m_dumps): New.
	* coverage.c (coverage_init): Port to dump_manager API.
	* dumpfile.c (extra_dump_files): Convert to field of
	gcc::dump_manager.
	(extra_dump_files_in_use): Likewise.
	(extra_dump_files_alloced): Likewise.
	(gcc::dump_manager::dump_manager): New.
	(dump_register): Convert to...
	(gcc::dump_manager::dump_register): ...method, replacing
	function-static next_dump with m_next_dump field.
	(get_dump_file_info): Convert to...
	(gcc::dump_manager::get_dump_file_info): ...method.
	(get_dump_file_name): Convert to...
	(gcc::dump_manager::get_dump_file_name): ...method.
	(dump_start): Convert to...
	(gcc::dump_manager::dump_start): ...method.
	(dump_finish): Convert to...
	(gcc::dump_manager::dump_finish): ...method.
	(dump_begin): Replace body with...
	(gcc::dump_manager::dump_begin): ...new method.
	(dump_phase_enabled_p): Convert to...
	(gcc::dump_manager::dump_phase_enabled_p): ...method.
	(dump_phase_enabled_p): Convert to...
	(gcc::dump_manager::dump_phase_enabled_p): ...method.
	(dump_initialized_p):  Convert to...
	(gcc::dump_manager::dump_initialized_p): ...method.
	(dump_flag_name): Replace body with...
	(gcc::dump_manager::dump_flag_name): ...new method.
	(dump_enable_all): Convert to...
	(gcc::dump_manager::dump_enable_all): ...new method.
	(opt_info_enable_passes): Convert to...
	(gcc::dump_manager::opt_info_enable_passes): ...new method.
	(dump_switch_p_1): Convert to...
	(gcc::dump_manager::dump_switch_p_1): ...new method.
	(dump_switch_p):  Convert to...
	(gcc::dump_manager::dump_switch_p): ...new method.
	(opt_info_switch_p): Port to dump_manager API.
	(enable_rtl_dump_file): Likewise.
	* opts-global.c (handle_common_deferred_options): Port to new
	dump_manager API.
	* passes.c (pass_manager::finish_optimization_passes): Likewise.
	(pass_manager::register_one_dump_file): Likewise.
	(pass_manager::register_pass): Likewise.
	(pass_init_dump_file): Likewise.
	(pass_fini_dump_file): Likewise.
	* statistics.c (statistics_early_init): Likewise.

gcc/java/
	* lang.c (java_handle_option): Update for introduction of
	gcc::dump_manager.

Comments

Richard Biener Oct. 14, 2013, 10:13 a.m. UTC | #1
On Sat, Oct 12, 2013 at 3:31 AM, David Malcolm <dmalcolm@redhat.com> wrote:
> When repeatedly compiling within one process, the dumpfile numbering
> doesn't reset, leading to dumpfiles after the initial ones having
> unpredictable numbers like here (-fdump-tree-all at -O0):
>
>       fake.c.000i.cgraph
>       fake.c.004t.gimple
>       fake.c.1477t.omplower
>       fake.c.1478t.lower
>       (etc)
>
> Note the large (and increasing) leap in the numbering from the base
> dumpfiles which get consistent numbering (000, 004 here) to the
> autonumbered ones (1477 in this example).  This was due to this implicit
> state within dump_register:
>
>       static int next_dump = FIRST_AUTO_NUMBERED_DUMP;
>       int num = next_dump++;
>
> messing up the numbering on subsequent in-process creation of passes.
>
> This patch introduces a new gcc::dump_manager class to hold such state,
> with a singleton owned by the gcc::context, fixing the inconsistent
> dumpfile numbering.
>
> Specifically, the following variables from dumpfile.c are moved from
> being statically allocated to being fields of gcc::dump_manager (gaining
> "m_" prefixes):
>
>       * next_dump
>       * extra_dump_files
>       * extra_dump_files_in_use
>       * extra_dump_files_alloced
>
> Potentially other aspects of dumping could be moved here, but this
> seemed like a logically self-contained change.
>
> Successfully bootstrapped and regtested on x86_64-unknown-linux.
>
> OK for trunk?

Why can't we have the dump numbering determined at the same time
we build up the pass pipeline?  That is, why are gcc:dump_manager
and gcc:pass_manager separate at all?

That said, the patch is a trivial re-org and thus ok.

Thanks,
Richard.

> (I've already applied this to the "dmalcolm/jit" branch as commits
> 190e9835a3ad4f43abf68aa7e400597d992525be
> 6c1464cdf7c9644383796b0ff5f1756d5279d6cb
> c07d4be4d6e3e732ba36a5ac7b69cce461c44c79)
>
> gcc/
>         * dumpfile.h (gcc::dump_manager): New class, to hold state
>         relating to dumpfile management.
>         (get_dump_file_name): Remove in favor of method of dump_manager.
>         (dump_initialized_p): Likewise.
>         (dump_start): Likewise.
>         (dump_finish): Likewise.
>         (dump_switch_p): Likewise.
>         (dump_register): Likewise.
>         (get_dump_file_info): Likewise.
>         * context.c (gcc::context::context): Construct the dump_manager
>         instance.
>         * context.h (gcc::context::get_dumps): New.
>         (gcc::context::m_dumps): New.
>         * coverage.c (coverage_init): Port to dump_manager API.
>         * dumpfile.c (extra_dump_files): Convert to field of
>         gcc::dump_manager.
>         (extra_dump_files_in_use): Likewise.
>         (extra_dump_files_alloced): Likewise.
>         (gcc::dump_manager::dump_manager): New.
>         (dump_register): Convert to...
>         (gcc::dump_manager::dump_register): ...method, replacing
>         function-static next_dump with m_next_dump field.
>         (get_dump_file_info): Convert to...
>         (gcc::dump_manager::get_dump_file_info): ...method.
>         (get_dump_file_name): Convert to...
>         (gcc::dump_manager::get_dump_file_name): ...method.
>         (dump_start): Convert to...
>         (gcc::dump_manager::dump_start): ...method.
>         (dump_finish): Convert to...
>         (gcc::dump_manager::dump_finish): ...method.
>         (dump_begin): Replace body with...
>         (gcc::dump_manager::dump_begin): ...new method.
>         (dump_phase_enabled_p): Convert to...
>         (gcc::dump_manager::dump_phase_enabled_p): ...method.
>         (dump_phase_enabled_p): Convert to...
>         (gcc::dump_manager::dump_phase_enabled_p): ...method.
>         (dump_initialized_p):  Convert to...
>         (gcc::dump_manager::dump_initialized_p): ...method.
>         (dump_flag_name): Replace body with...
>         (gcc::dump_manager::dump_flag_name): ...new method.
>         (dump_enable_all): Convert to...
>         (gcc::dump_manager::dump_enable_all): ...new method.
>         (opt_info_enable_passes): Convert to...
>         (gcc::dump_manager::opt_info_enable_passes): ...new method.
>         (dump_switch_p_1): Convert to...
>         (gcc::dump_manager::dump_switch_p_1): ...new method.
>         (dump_switch_p):  Convert to...
>         (gcc::dump_manager::dump_switch_p): ...new method.
>         (opt_info_switch_p): Port to dump_manager API.
>         (enable_rtl_dump_file): Likewise.
>         * opts-global.c (handle_common_deferred_options): Port to new
>         dump_manager API.
>         * passes.c (pass_manager::finish_optimization_passes): Likewise.
>         (pass_manager::register_one_dump_file): Likewise.
>         (pass_manager::register_pass): Likewise.
>         (pass_init_dump_file): Likewise.
>         (pass_fini_dump_file): Likewise.
>         * statistics.c (statistics_early_init): Likewise.
>
> gcc/java/
>         * lang.c (java_handle_option): Update for introduction of
>         gcc::dump_manager.
>
David Malcolm Oct. 14, 2013, 5:58 p.m. UTC | #2
On Mon, 2013-10-14 at 12:13 +0200, Richard Biener wrote:
> On Sat, Oct 12, 2013 at 3:31 AM, David Malcolm <dmalcolm@redhat.com> wrote:
> > When repeatedly compiling within one process, the dumpfile numbering
> > doesn't reset, leading to dumpfiles after the initial ones having
> > unpredictable numbers like here (-fdump-tree-all at -O0):
> >
> >       fake.c.000i.cgraph
> >       fake.c.004t.gimple
> >       fake.c.1477t.omplower
> >       fake.c.1478t.lower
> >       (etc)
> >
> > Note the large (and increasing) leap in the numbering from the base
> > dumpfiles which get consistent numbering (000, 004 here) to the
> > autonumbered ones (1477 in this example).  This was due to this implicit
> > state within dump_register:
> >
> >       static int next_dump = FIRST_AUTO_NUMBERED_DUMP;
> >       int num = next_dump++;
> >
> > messing up the numbering on subsequent in-process creation of passes.
> >
> > This patch introduces a new gcc::dump_manager class to hold such state,
> > with a singleton owned by the gcc::context, fixing the inconsistent
> > dumpfile numbering.
> >
> > Specifically, the following variables from dumpfile.c are moved from
> > being statically allocated to being fields of gcc::dump_manager (gaining
> > "m_" prefixes):
> >
> >       * next_dump
> >       * extra_dump_files
> >       * extra_dump_files_in_use
> >       * extra_dump_files_alloced
> >
> > Potentially other aspects of dumping could be moved here, but this
> > seemed like a logically self-contained change.
> >
> > Successfully bootstrapped and regtested on x86_64-unknown-linux.
> >
> > OK for trunk?
> 
> Why can't we have the dump numbering determined at the same time
> we build up the pass pipeline?  That is, why are gcc:dump_manager
> and gcc:pass_manager separate at all?

Not every dumpfile relates to a specific pass: statistics.c registers
and uses a dumpfile in ways that don't look like how the passes do.
Although this is obviously for recording events that happen within
passes, it covers *all* passes, rather than being a per-pass thing.
This is clearly a gray area, but the single responsibility principle
suggests that managing passes vs managing dumpfiles should be separate,
especially since I may want to make future dumpfile-handling cleanups.
(Also, I'm nervous about "blob" classes with too many responsibilities).

> That said, the patch is a trivial re-org and thus ok.

Thanks; committed to trunk as r203569.
diff mbox

Patch

diff --git a/gcc/context.c b/gcc/context.c
index 09e1f89..3dd4526 100644
--- a/gcc/context.c
+++ b/gcc/context.c
@@ -23,11 +23,16 @@  along with GCC; see the file COPYING3.  If not see
 #include "ggc.h"
 #include "context.h"
 #include "pass_manager.h"
+#include "dumpfile.h"
 
 /* The singleton holder of global state: */
 gcc::context *g;
 
 gcc::context::context ()
 {
+  /* The pass manager's constructor uses the dump manager (to set up
+     dumps for the various passes), so the dump manager must be set up
+     before the pass manager.  */
+  m_dumps = new gcc::dump_manager ();
   m_passes = new gcc::pass_manager (this);
 }
diff --git a/gcc/context.h b/gcc/context.h
index 4aab6de..d6555cc 100644
--- a/gcc/context.h
+++ b/gcc/context.h
@@ -23,6 +23,7 @@  along with GCC; see the file COPYING3.  If not see
 namespace gcc {
 
 class pass_manager;
+class dump_manager;
 
 /* GCC's internal state can be divided into zero or more
    "parallel universe" of state; an instance of this class is one such
@@ -36,10 +37,17 @@  public:
 
   pass_manager *get_passes () { gcc_assert (m_passes); return m_passes; }
 
+  /* Handling dump files.  */
+
+  dump_manager *get_dumps () {gcc_assert (m_dumps); return m_dumps; }
+
 private:
   /* Pass-management.  */
   pass_manager *m_passes;
 
+  /* Dump files.  */
+  dump_manager *m_dumps;
+
 }; // class context
 
 } // namespace gcc
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 3c36c6f..e450151 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -1137,7 +1137,9 @@  coverage_init (const char *filename)
   /* Since coverage_init is invoked very early, before the pass
      manager, we need to set up the dumping explicitly. This is
      similar to the handling in finish_optimization_passes.  */
-  dump_start (g->get_passes ()->get_pass_profile ()->static_pass_number, NULL);
+  int profile_pass_num =
+    g->get_passes ()->get_pass_profile ()->static_pass_number;
+  g->get_dumps ()->dump_start (profile_pass_num, NULL);
 
   if (!profile_data_prefix && !IS_ABSOLUTE_PATH (filename))
     profile_data_prefix = getpwd ();
@@ -1182,7 +1184,7 @@  coverage_init (const char *filename)
 	}
     }
 
-  dump_finish (g->get_passes ()->get_pass_profile ()->static_pass_number);
+  g->get_dumps ()->dump_finish (profile_pass_num);
 }
 
 /* Performs file-level cleanup.  Close notes file, generate coverage
diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c
index 4a19b6d..e80f9bf 100644
--- a/gcc/dumpfile.c
+++ b/gcc/dumpfile.c
@@ -24,6 +24,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "dumpfile.h"
 #include "tree.h"
 #include "gimple-pretty-print.h"
+#include "context.h"
 
 /* If non-NULL, return one past-the-end of the matching SUBPART of
    the WHOLE string.  */
@@ -34,7 +35,6 @@  static int pflags;                   /* current dump_flags */
 static int alt_flags;                /* current opt_info flags */
 
 static void dump_loc (int, FILE *, source_location);
-static int dump_phase_enabled_p (int);
 static FILE *dump_open_alternate_stream (struct dump_file_info *);
 
 /* These are currently used for communicating between passes.
@@ -74,11 +74,6 @@  static struct dump_file_info dump_files[TDI_end] =
    0, 0, 0, 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
 {
@@ -141,33 +136,41 @@  static const struct dump_option_value_info optgroup_options[] =
   {NULL, 0}
 };
 
+gcc::dump_manager::dump_manager ():
+  m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
+  m_extra_dump_files (NULL),
+  m_extra_dump_files_in_use (0),
+  m_extra_dump_files_alloced (0)
+{
+}
+
 unsigned int
+gcc::dump_manager::
 dump_register (const char *suffix, const char *swtch, const char *glob,
 	       int flags, int optgroup_flags)
 {
-  static int next_dump = FIRST_AUTO_NUMBERED_DUMP;
-  int num = next_dump++;
+  int num = m_next_dump++;
 
-  size_t count = extra_dump_files_in_use++;
+  size_t count = m_extra_dump_files_in_use++;
 
-  if (count >= extra_dump_files_alloced)
+  if (count >= m_extra_dump_files_alloced)
     {
-      if (extra_dump_files_alloced == 0)
-	extra_dump_files_alloced = 32;
+      if (m_extra_dump_files_alloced == 0)
+	m_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);
+	m_extra_dump_files_alloced *= 2;
+      m_extra_dump_files = XRESIZEVEC (struct dump_file_info,
+				       m_extra_dump_files,
+				       m_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].pflags = flags;
-  extra_dump_files[count].optgroup_flags = optgroup_flags;
-  extra_dump_files[count].num = num;
+  memset (&m_extra_dump_files[count], 0, sizeof (struct dump_file_info));
+  m_extra_dump_files[count].suffix = suffix;
+  m_extra_dump_files[count].swtch = swtch;
+  m_extra_dump_files[count].glob = glob;
+  m_extra_dump_files[count].pflags = flags;
+  m_extra_dump_files[count].optgroup_flags = optgroup_flags;
+  m_extra_dump_files[count].num = num;
 
   return count + TDI_end;
 }
@@ -176,14 +179,15 @@  dump_register (const char *suffix, const char *swtch, const char *glob,
 /* Return the dump_file_info for the given phase.  */
 
 struct dump_file_info *
-get_dump_file_info (int phase)
+gcc::dump_manager::
+get_dump_file_info (int phase) const
 {
   if (phase < TDI_end)
     return &dump_files[phase];
-  else if ((size_t) (phase - TDI_end) >= extra_dump_files_in_use)
+  else if ((size_t) (phase - TDI_end) >= m_extra_dump_files_in_use)
     return NULL;
   else
-    return extra_dump_files + (phase - TDI_end);
+    return m_extra_dump_files + (phase - TDI_end);
 }
 
 
@@ -191,7 +195,8 @@  get_dump_file_info (int phase)
    If the dump is not enabled, returns NULL.  */
 
 char *
-get_dump_file_name (int phase)
+gcc::dump_manager::
+get_dump_file_name (int phase) const
 {
   char dump_id[10];
   struct dump_file_info *dfi;
@@ -391,6 +396,7 @@  dump_printf_loc (int dump_kind, source_location loc, const char *format, ...)
    -fopt-info stream. */
 
 int
+gcc::dump_manager::
 dump_start (int phase, int *flag_ptr)
 {
   int count = 0;
@@ -443,6 +449,7 @@  dump_start (int phase, int *flag_ptr)
    reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS.  */
 
 void
+gcc::dump_manager::
 dump_finish (int phase)
 {
   struct dump_file_info *dfi;
@@ -476,6 +483,13 @@  dump_finish (int phase)
 FILE *
 dump_begin (int phase, int *flag_ptr)
 {
+  return g->get_dumps ()->dump_begin (phase, flag_ptr);
+}
+
+FILE *
+gcc::dump_manager::
+dump_begin (int phase, int *flag_ptr)
+{
   char *name;
   struct dump_file_info *dfi;
   FILE *stream;
@@ -512,8 +526,9 @@  dump_begin (int phase, int *flag_ptr)
    If PHASE is TDI_tree_all, return nonzero if any dump is enabled for
    any phase.  */
 
-static int
-dump_phase_enabled_p (int phase)
+int
+gcc::dump_manager::
+dump_phase_enabled_p (int phase) const
 {
   if (phase == TDI_tree_all)
     {
@@ -521,8 +536,8 @@  dump_phase_enabled_p (int phase)
       for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
 	if (dump_files[i].pstate || dump_files[i].alt_state)
 	  return 1;
-      for (i = 0; i < extra_dump_files_in_use; i++)
-	if (extra_dump_files[i].pstate || extra_dump_files[i].alt_state)
+      for (i = 0; i < m_extra_dump_files_in_use; i++)
+	if (m_extra_dump_files[i].pstate || m_extra_dump_files[i].alt_state)
 	  return 1;
       return 0;
     }
@@ -536,7 +551,8 @@  dump_phase_enabled_p (int phase)
 /* Returns nonzero if tree dump PHASE has been initialized.  */
 
 int
-dump_initialized_p (int phase)
+gcc::dump_manager::
+dump_initialized_p (int phase) const
 {
   struct dump_file_info *dfi = get_dump_file_info (phase);
   return dfi->pstate > 0 || dfi->alt_state > 0;
@@ -547,6 +563,13 @@  dump_initialized_p (int phase)
 const char *
 dump_flag_name (int phase)
 {
+  return g->get_dumps ()->dump_flag_name (phase);
+}
+
+const char *
+gcc::dump_manager::
+dump_flag_name (int phase) const
+{
   struct dump_file_info *dfi = get_dump_file_info (phase);
   return dfi->swtch;
 }
@@ -564,7 +587,8 @@  dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
 /* Enable all tree dumps with FLAGS on FILENAME.  Return number of
    enabled tree dumps.  */
 
-static int
+int
+gcc::dump_manager::
 dump_enable_all (int flags, const char *filename)
 {
   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
@@ -592,21 +616,21 @@  dump_enable_all (int flags, const char *filename)
         }
     }
 
-  for (i = 0; i < extra_dump_files_in_use; i++)
+  for (i = 0; i < m_extra_dump_files_in_use; i++)
     {
-      if ((extra_dump_files[i].pflags & ir_dump_type))
+      if ((m_extra_dump_files[i].pflags & ir_dump_type))
         {
-          const char *old_filename = extra_dump_files[i].pfilename;
-          extra_dump_files[i].pstate = -1;
-          extra_dump_files[i].pflags |= flags;
+          const char *old_filename = m_extra_dump_files[i].pfilename;
+          m_extra_dump_files[i].pstate = -1;
+          m_extra_dump_files[i].pflags |= flags;
           n++;
           /* Override the existing filename.  */
           if (filename)
             {
-              extra_dump_files[i].pfilename = xstrdup (filename);
+              m_extra_dump_files[i].pfilename = xstrdup (filename);
               /* Since it is a command-line provided file, which is
                  common to all the phases, use it in append mode.  */
-              extra_dump_files[i].pstate = 1;
+              m_extra_dump_files[i].pstate = 1;
             }
           if (old_filename && filename != old_filename)
             free (CONST_CAST (char *, old_filename));
@@ -620,7 +644,8 @@  dump_enable_all (int flags, const char *filename)
    Enable dumps with FLAGS on FILENAME.  Return the number of enabled
    dumps.  */
 
-static int
+int
+gcc::dump_manager::
 opt_info_enable_passes (int optgroup_flags, int flags, const char *filename)
 {
   int n = 0;
@@ -644,19 +669,19 @@  opt_info_enable_passes (int optgroup_flags, int flags, const char *filename)
         }
     }
 
-  for (i = 0; i < extra_dump_files_in_use; i++)
+  for (i = 0; i < m_extra_dump_files_in_use; i++)
     {
-      if ((extra_dump_files[i].optgroup_flags & optgroup_flags))
+      if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
         {
-          const char *old_filename = extra_dump_files[i].alt_filename;
+          const char *old_filename = m_extra_dump_files[i].alt_filename;
           /* Since this file is shared among different passes, it
              should be opened in append mode.  */
-          extra_dump_files[i].alt_state = 1;
-          extra_dump_files[i].alt_flags |= flags;
+          m_extra_dump_files[i].alt_state = 1;
+          m_extra_dump_files[i].alt_flags |= flags;
           n++;
           /* Override the existing filename.  */
           if (filename)
-            extra_dump_files[i].alt_filename = xstrdup (filename);
+            m_extra_dump_files[i].alt_filename = xstrdup (filename);
           if (old_filename && filename != old_filename)
             free (CONST_CAST (char *, old_filename));
         }
@@ -668,7 +693,8 @@  opt_info_enable_passes (int optgroup_flags, int flags, const char *filename)
 /* Parse ARG as a dump switch. Return nonzero if it is, and store the
    relevant details in the dump_files array.  */
 
-static int
+int
+gcc::dump_manager::
 dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
 {
   const char *option_value;
@@ -743,6 +769,7 @@  dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
 }
 
 int
+gcc::dump_manager::
 dump_switch_p (const char *arg)
 {
   size_t i;
@@ -756,12 +783,12 @@  dump_switch_p (const char *arg)
     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);
+  for (i = 0; i < m_extra_dump_files_in_use; i++)
+    any |= dump_switch_p_1 (arg, &m_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);
+    for (i = 0; i < m_extra_dump_files_in_use; i++)
+      any |= dump_switch_p_1 (arg, &m_extra_dump_files[i], true);
 
 
   return any;
@@ -853,6 +880,7 @@  opt_info_switch_p (const char *arg)
   int optgroup_flags;
   char *filename;
   static char *file_seen = NULL;
+  gcc::dump_manager *dumps = g->get_dumps ();
 
   if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
     return 0;
@@ -874,7 +902,7 @@  opt_info_switch_p (const char *arg)
   if (!optgroup_flags)
     optgroup_flags = OPTGROUP_ALL;
 
-  return opt_info_enable_passes (optgroup_flags, flags, filename);
+  return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
 }
 
 /* Print basic block on the dump streams.  */
@@ -902,5 +930,8 @@  print_combine_total_stats (void)
 bool
 enable_rtl_dump_file (void)
 {
-  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
+  gcc::dump_manager *dumps = g->get_dumps ();
+  int num_enabled =
+    dumps->dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL);
+  return num_enabled > 0;
 }
diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h
index ddc770a..a6b377e 100644
--- a/gcc/dumpfile.h
+++ b/gcc/dumpfile.h
@@ -121,13 +121,8 @@  struct dump_file_info
 };
 
 /* In dumpfile.c */
-extern char *get_dump_file_name (int);
-extern int dump_initialized_p (int);
 extern FILE *dump_begin (int, int *);
 extern void dump_end (int, FILE *);
-extern int dump_start (int, int *);
-extern void dump_finish (int);
-extern int dump_switch_p (const char *);
 extern int opt_info_switch_p (const char *);
 extern const char *dump_flag_name (int);
 extern void dump_printf (int, const char *, ...) ATTRIBUTE_PRINTF_2;
@@ -139,8 +134,6 @@  extern void dump_generic_expr (int, int, tree);
 extern void dump_gimple_stmt_loc (int, source_location, int, gimple, int);
 extern void dump_gimple_stmt (int, int, gimple, int);
 extern void print_combine_total_stats (void);
-extern unsigned int dump_register (const char *, const char *, const char *,
-                                   int, int);
 extern bool enable_rtl_dump_file (void);
 
 /* In tree-dump.c  */
@@ -157,9 +150,6 @@  extern FILE *alt_dump_file;
 extern int dump_flags;
 extern const char *dump_file_name;
 
-/* Return the dump_file_info for the given phase.  */
-extern struct dump_file_info *get_dump_file_info (int);
-
 /* Return true if any of the dumps is enabled, false otherwise. */
 static inline bool
 dump_enabled_p (void)
@@ -167,4 +157,84 @@  dump_enabled_p (void)
   return (dump_file || alt_dump_file);
 }
 
+namespace gcc {
+
+class dump_manager
+{
+public:
+
+  dump_manager ();
+
+  unsigned int
+  dump_register (const char *suffix, const char *swtch, const char *glob,
+		 int flags, int optgroup_flags);
+
+  /* Return the dump_file_info for the given phase.  */
+  struct dump_file_info *
+  get_dump_file_info (int phase) const;
+
+  /* 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) const;
+
+  int
+  dump_switch_p (const char *arg);
+
+  /* Start a dump for PHASE. Store user-supplied dump flags in
+     *FLAG_PTR.  Return the number of streams opened.  Set globals
+     DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
+     set dump_flags appropriately for both pass dump stream and
+     -fopt-info stream. */
+  int
+  dump_start (int phase, int *flag_ptr);
+
+  /* Finish a tree dump for PHASE and close associated dump streams.  Also
+     reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS.  */
+  void
+  dump_finish (int phase);
+
+  FILE *
+  dump_begin (int phase, int *flag_ptr);
+
+  /* Returns nonzero if tree dump PHASE has been initialized.  */
+  int
+  dump_initialized_p (int phase) const;
+
+  /* Returns the switch name of PHASE.  */
+  const char *
+  dump_flag_name (int phase) const;
+
+private:
+
+  int
+  dump_phase_enabled_p (int phase) const;
+
+  int
+  dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob);
+
+  int
+  dump_enable_all (int flags, const char *filename);
+
+  int
+  opt_info_enable_passes (int optgroup_flags, int flags, const char *filename);
+
+private:
+
+  /* Dynamically registered dump files and switches.  */
+  int m_next_dump;
+  struct dump_file_info *m_extra_dump_files;
+  size_t m_extra_dump_files_in_use;
+  size_t m_extra_dump_files_alloced;
+
+  /* Grant access to dump_enable_all.  */
+  friend bool ::enable_rtl_dump_file (void);
+
+  /* Grant access to opt_info_enable_passes.  */
+  friend int ::opt_info_switch_p (const char *arg);
+
+}; // class dump_manager
+
+} // namespace gcc
+
 #endif /* GCC_DUMPFILE_H */
diff --git a/gcc/opts-global.c b/gcc/opts-global.c
index 32ea320..8ce705e 100644
--- a/gcc/opts-global.c
+++ b/gcc/opts-global.c
@@ -36,6 +36,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "plugin.h"
 #include "toplev.h"
 #include "tree-pass.h"
+#include "context.h"
 
 typedef const char *const_char_p; /* For DEF_VEC_P.  */
 
@@ -385,7 +386,7 @@  handle_common_deferred_options (void)
 	  break;
 
 	case OPT_fdump_:
-	  if (!dump_switch_p (opt->arg))
+	  if (!g->get_dumps ()->dump_switch_p (opt->arg))
 	    error ("unrecognized command line option %<-fdump-%s%>", opt->arg);
 	  break;
 
diff --git a/gcc/passes.c b/gcc/passes.c
index 8e9a4ef..4ac1ab6 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -278,27 +278,28 @@  finish_optimization_passes (void)
   int i;
   struct dump_file_info *dfi;
   char *name;
+  gcc::dump_manager *dumps = m_ctxt->get_dumps ();
 
   timevar_push (TV_DUMP);
   if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
     {
-      dump_start (pass_profile_1->static_pass_number, NULL);
+      dumps->dump_start (pass_profile_1->static_pass_number, NULL);
       end_branch_prob ();
-      dump_finish (pass_profile_1->static_pass_number);
+      dumps->dump_finish (pass_profile_1->static_pass_number);
     }
 
   if (optimize > 0)
     {
-      dump_start (pass_profile_1->static_pass_number, NULL);
+      dumps->dump_start (pass_profile_1->static_pass_number, NULL);
       print_combine_total_stats ();
-      dump_finish (pass_profile_1->static_pass_number);
+      dumps->dump_finish (pass_profile_1->static_pass_number);
     }
 
   /* Do whatever is necessary to finish printing the graphs.  */
-  for (i = TDI_end; (dfi = get_dump_file_info (i)) != NULL; ++i)
-    if (dump_initialized_p (i)
+  for (i = TDI_end; (dfi = dumps->get_dump_file_info (i)) != NULL; ++i)
+    if (dumps->dump_initialized_p (i)
 	&& (dfi->pflags & TDF_GRAPH) != 0
-	&& (name = get_dump_file_name (i)) != NULL)
+	&& (name = dumps->get_dump_file_name (i)) != NULL)
       {
 	finish_graph_dump_file (name);
 	free (name);
@@ -641,6 +642,7 @@  pass_manager::register_one_dump_file (struct opt_pass *pass)
   char num[10];
   int flags, id;
   int optgroup_flags = OPTGROUP_NONE;
+  gcc::dump_manager *dumps = m_ctxt->get_dumps ();
 
   /* See below in next_pass_1.  */
   num[0] = '\0';
@@ -681,7 +683,8 @@  pass_manager::register_one_dump_file (struct opt_pass *pass)
      any dump messages are emitted properly under -fopt-info(-optall).  */
   if (optgroup_flags == OPTGROUP_NONE)
     optgroup_flags = OPTGROUP_OTHER;
-  id = dump_register (dot_name, flag_name, glob_name, flags, optgroup_flags);
+  id = dumps->dump_register (dot_name, flag_name, glob_name, flags,
+			     optgroup_flags);
   set_pass_for_id (id, pass);
   full_name = concat (prefix, pass->name, num, NULL);
   register_pass_name (pass, full_name);
@@ -1389,6 +1392,7 @@  void
 pass_manager::register_pass (struct register_pass_info *pass_info)
 {
   bool all_instances, success;
+  gcc::dump_manager *dumps = m_ctxt->get_dumps ();
 
   /* The checks below could fail in buggy plugins.  Existing GCC
      passes should never fail these checks, so we mention plugin in
@@ -1446,9 +1450,9 @@  pass_manager::register_pass (struct register_pass_info *pass_info)
       else
         tdi = TDI_rtl_all;
       /* Check if dump-all flag is specified.  */
-      if (get_dump_file_info (tdi)->pstate)
-        get_dump_file_info (added_pass_nodes->pass->static_pass_number)
-            ->pstate = get_dump_file_info (tdi)->pstate;
+      if (dumps->get_dump_file_info (tdi)->pstate)
+        dumps->get_dump_file_info (added_pass_nodes->pass->static_pass_number)
+            ->pstate = dumps->get_dump_file_info (tdi)->pstate;
       XDELETE (added_pass_nodes);
       added_pass_nodes = next_node;
     }
@@ -1931,9 +1935,11 @@  pass_init_dump_file (struct opt_pass *pass)
   if (pass->static_pass_number != -1)
     {
       timevar_push (TV_DUMP);
-      bool initializing_dump = !dump_initialized_p (pass->static_pass_number);
-      dump_file_name = get_dump_file_name (pass->static_pass_number);
-      dump_start (pass->static_pass_number, &dump_flags);
+      gcc::dump_manager *dumps = g->get_dumps ();
+      bool initializing_dump =
+	!dumps->dump_initialized_p (pass->static_pass_number);
+      dump_file_name = dumps->get_dump_file_name (pass->static_pass_number);
+      dumps->dump_start (pass->static_pass_number, &dump_flags);
       if (dump_file && current_function_decl)
         dump_function_header (dump_file, current_function_decl, dump_flags);
       if (initializing_dump
@@ -1962,7 +1968,7 @@  pass_fini_dump_file (struct opt_pass *pass)
       dump_file_name = NULL;
     }
 
-  dump_finish (pass->static_pass_number);
+  g->get_dumps ()->dump_finish (pass->static_pass_number);
   timevar_pop (TV_DUMP);
 }
 
diff --git a/gcc/statistics.c b/gcc/statistics.c
index 62590ba..51d3f3a 100644
--- a/gcc/statistics.c
+++ b/gcc/statistics.c
@@ -260,8 +260,10 @@  statistics_fini (void)
 void
 statistics_early_init (void)
 {
-  statistics_dump_nr = dump_register (".statistics", "statistics",
-				      "statistics", TDF_TREE, OPTGROUP_NONE);
+  gcc::dump_manager *dumps = g->get_dumps ();
+  statistics_dump_nr = dumps->dump_register (".statistics", "statistics",
+					     "statistics", TDF_TREE,
+					     OPTGROUP_NONE);
 }
 
 /* Init the statistics.  */
@@ -269,8 +271,9 @@  statistics_early_init (void)
 void
 statistics_init (void)
 {
+  gcc::dump_manager *dumps = g->get_dumps ();
   statistics_dump_file = dump_begin (statistics_dump_nr, NULL);
-  statistics_dump_flags = get_dump_file_info (statistics_dump_nr)->pflags;
+  statistics_dump_flags = dumps->get_dump_file_info (statistics_dump_nr)->pflags;
 }
 
 /* Lookup or add a statistics counter in the hashtable HASH with ID, VAL
diff --git a/gcc/java/lang.c b/gcc/java/lang.c
index d40af87..6d89134 100644
--- a/gcc/java/lang.c
+++ b/gcc/java/lang.c
@@ -42,6 +42,7 @@  The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "opts.h"
 #include "options.h"
 #include "target.h"
+#include "context.h"
 
 static bool java_init (void);
 static void java_finish (void);
@@ -271,7 +272,7 @@  java_handle_option (size_t scode, const char *arg, int value,
       break;
 
     case OPT_fdump_:
-      if (!dump_switch_p (arg))
+      if (!g->get_dumps ()->dump_switch_p (arg))
 	return false;
       break;