This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 03/11] Handwritten part of conversion of passes to C++ classes


This patch is the hand-written part of the conversion of passes from
C structs to C++ classes.  It does not work without the subsequent
autogenerated part, which is huge.

Given that the autogenerated part of the conversion is very large
(500k), for the sake of human comprehension I have kept the change as
two separate patches to keep the hand-written changes separate from the
automatically-generated ones.  I would commit these as two separate
changes to SVN in order to keep this readability for posterity in the
logs as well as at review-time.

This pair of patches eliminates the mutable global variables
representing the passes, allowing for multiple compilation contexts in
one process, potentially with different combinations of passes, and with
pass instance owning additional data.

It converts the hierarchy of opt_pass types into an actual C++ class
hierarchy, where each of:

  * gimple_opt_pass
  * rtl_opt_pass
  * ipa_opt_pass_d
  * simple_ipa_opt_pass

all become subclasses of opt_pass.

The gate and execute function pointers become virtual functions.  This
gives us type-safety, allowing the possibility of adding custom fields
to opt_pass subclasses accessible from the execute vfunc without a cast.
There is an additional "clone" virtual function, which exists so that:

  (a) passes can wire themselves up within a context, so that all sister
      passes within a context can share state with each other, without
      sharing state with their cousins in another compilation context:

  (b) pass subclasses can be encapsulated, and the hardcoded sizeof()
      logic in passes.c:make_pass_instance can be removed, allowing
      pass subclasses to have additional fields.

Most of the metadata about passes is moved to a new struct pass_data,
keeping just the "sub", "next" and "static_pass_number" fields in the
pass instances.  Passes also gain a:

   gcc::context * ctxt_;

field, so that a pass instance always "knows" which compilation context
it is associated with, giving an easy way to avoid thread-local lookups
in a future gcc-as-a-shared-library build.

The pass_data has an extra pair of fields: "has_gate" and "has_execute".
These exist to deal with existing code that checks to see if a pass
has a non-NULL gate or execute function ptr.  Given that we can't
portably do that on a vfunc, it's simplest to add a couple of extra
bools to the pass_data struct, preserving the exact existing behaviors.

In this patch opt_pass has an "is a" relationship to pass_data, rather
than a "references" relationship, i.e.:

   class opt_pass : public pass_data

Doing this minimizes the size of the patch and avoids an extra
dereference when looking up patch metadata, but is perhaps something
of a wart.

gcc/
	* Makefile.in (PIPELINE_H): Add dep on pass-instances.def.
	(toplev.o): Add dep on PIPELINE_H.
	* cgraphunit.c (cgraph_process_new_functions): Rework invocation
	of early local pases to reflect this moving from a global to a
	member of gcc::pipeline.
	(cgraph_add_new_function): Likewise.
	* lto-cgraph.c (lto_output_node): Update for conversion of
	struct ipa_opt_pass_d to a C++ subclass of opt_pass.
	* passes.c (opt_pass::clone): New.
	(opt_pass::gate): New.
	(opt_pass::execute): New.
	(opt_pass::opt_pass): New.
	(pipeline::execute_early_local_passes): New.
	(pipeline::execute_pass_mode_switching): new.
	(finish_optimization_passes): Convert to...
	(pipeline::finish_optimization_passes): ...this.
	(finish_optimization_passes): Update for conversion of passes to
	C++ classes.
	(register_dump_files_1): Use has_gate since we cannot portably
	check a vtable entry against NULL.
	(dump_one_pass): Likewise.
	(ipa_write_summaries_2): Likewise.
	(ipa_write_optimization_summaries_1): Likewise.
	(ipa_read_summaries_1): Likewise.
	(ipa_read_optimization_summaries_1): Likewise.
	(execute_ipa_stmt_fixups): Likewise.
	(pipeline::pipeline): Rewrite pass-creation, invoking
	pass-creation functions rather than wiring up globals, and
	storing the results in fields of pipeline generated using
	pass-instances.def.
	(pipeline::dump_profile_report): Update for conversion of passes
	to C++ classes.
	(pipeline::execute_ipa_summary_passes): Likewise.
	(execute_one_ipa_transform_pass): Likewise.
	(execute_one_pass): Use has_gate and has_execute since we cannot
	portably check a vtable entry against NULL.
	* pipeline.h (pipeline::finish_optimization_passes): New.
	(pipeline): Use pass-instances.def to add fields for the
	various pass instances.
	* toplev.c (finalize): Update for move of
	finish_optimization_passes to a method of gcc::pipeline.
	* toplev.h (finish_optimization_passes): Move to method of class
	pipeline.
	* tree-pass.h (struct pass_data): New.
	(opt_pass): Convert to C++ class, make it a subclass of pass_data.
	(opt_pass::gate): Convert to virtual function.
	(opt_pass::~opt_pass): New.
	(opt_pass::clone): New.
	(opt_pass::execute): Convert to virtual function.
	(opt_pass::opt_pass): New.
	(opt_pass::ctxt_): new.
	(gimple_opt_pass): Convert to subclass of opt_pass.
	(gimple_opt_pass::gimple_opt_pass): New.
	(rtl_opt_pass): Convert to subclass of opt_pass.
	(rtl_opt_pass::rtl_opt_pass): New.
	(ipa_opt_pass_d): Convert to subclass of opt_pass.
	(ipa_opt_pass_d::ipa_opt_pass_d): New.
	(simple_ipa_opt_pass): Convert to subclass of opt_pass.
	(simple_ipa_opt_pass::simple_ipa_opt_pass): New.

gcc/config/
	* i386/i386.c (rest_of_handle_insert_vzeroupper): Rework
	invocation of pass_mode_switching to reflect this moving from a
	global to a member of gcc::pipeline.
	(ix86_option_override): Rework how pass_insert_vzeroupper is
	added to the pipeline to reflect autogenerated changes.
	* i386/t-i386 (i386.o) Add deps on CONTEXT_H and PIPELINE_H.

gcc/testsuite/
	* g++.dg/plugin/dumb_plugin.c (plugin_init): Rework how the pass
	is created and added to the pipeline to reflect autogenerated
	changes.
	* g++.dg/plugin/selfassign.c (plugin_init): Likewise.
	* gcc.dg/plugin/one_time_plugin.c (plugin_init): Likewise.
	* gcc.dg/plugin/selfassign.c (plugin_init): Likewise.
---
 gcc/Makefile.in                               |   4 +-
 gcc/cgraphunit.c                              |   6 +-
 gcc/config/i386/i386.c                        |   7 +-
 gcc/config/i386/t-i386                        |   2 +-
 gcc/lto-cgraph.c                              |   2 +-
 gcc/passes.c                                  | 102 +++++++++++++++-----
 gcc/pipeline.h                                |  37 ++++++++
 gcc/testsuite/g++.dg/plugin/dumb_plugin.c     |   3 +-
 gcc/testsuite/g++.dg/plugin/selfassign.c      |   3 +-
 gcc/testsuite/gcc.dg/plugin/one_time_plugin.c |   3 +-
 gcc/testsuite/gcc.dg/plugin/selfassign.c      |   3 +-
 gcc/toplev.c                                  |   3 +-
 gcc/toplev.h                                  |   1 -
 gcc/tree-pass.h                               | 129 ++++++++++++++++++++------
 14 files changed, 241 insertions(+), 64 deletions(-)

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 6d1f32c..c1fdb8a 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -987,7 +987,7 @@ PLUGIN_VERSION_H = plugin-version.h configargs.h
 LIBFUNCS_H = libfuncs.h $(HASHTAB_H)
 GRAPHITE_HTAB_H = graphite-htab.h graphite-clast-to-gimple.h $(HASH_TABLE_H)
 CONTEXT_H = context.h
-PIPELINE_H = pipeline.h
+PIPELINE_H = pipeline.h pass-instances.def
 
 #
 # Now figure out from those variables how to compile and link.
@@ -2733,7 +2733,7 @@ toplev.o : toplev.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
    $(OPTS_H) params.def tree-mudflap.h $(TREE_PASS_H) $(GIMPLE_H) \
    tree-ssa-alias.h $(PLUGIN_H) realmpfr.h tree-diagnostic.h \
    $(TREE_PRETTY_PRINT_H) opts-diagnostic.h $(COMMON_TARGET_H) \
-   tsan.h diagnostic-color.h $(CONTEXT_H)
+   tsan.h diagnostic-color.h $(CONTEXT_H) $(PIPELINE_H)
 
 hwint.o : hwint.c $(CONFIG_H) $(SYSTEM_H) $(DIAGNOSTIC_CORE_H)
 
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index dc489fb..0bc7d02 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -328,7 +328,7 @@ cgraph_process_new_functions (void)
 	      /* When not optimizing, be sure we run early local passes anyway
 		 to expand OMP.  */
 	      || !optimize)
-	    execute_pass_list (pass_early_local_passes.pass.sub);
+	    g->get_passes ().execute_early_local_passes ();
 	  else
 	    compute_inline_parameters (node, true);
 	  free_dominance_info (CDI_POST_DOMINATORS);
@@ -512,7 +512,7 @@ cgraph_add_new_function (tree fndecl, bool lowered)
 	    gimple_register_cfg_hooks ();
 	    bitmap_obstack_initialize (NULL);
 	    execute_pass_list (passes.all_lowering_passes);
-	    execute_pass_list (pass_early_local_passes.pass.sub);
+	    passes.execute_early_local_passes ();
 	    bitmap_obstack_release (NULL);
 	    pop_cfun ();
 
@@ -537,7 +537,7 @@ cgraph_add_new_function (tree fndecl, bool lowered)
 	gimple_register_cfg_hooks ();
 	bitmap_obstack_initialize (NULL);
 	if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
-	  execute_pass_list (pass_early_local_passes.pass.sub);
+	  g->get_passes ().execute_early_local_passes ();
 	bitmap_obstack_release (NULL);
 	pop_cfun ();
 	expand_function (node);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 0c546af..88ba218 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -62,6 +62,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "dumpfile.h"
 #include "tree-pass.h"
 #include "tree-flow.h"
+#include "context.h"
+#include "pipeline.h"
 
 static rtx legitimize_dllimport_symbol (rtx, bool);
 static rtx legitimize_pe_coff_extern_decl (rtx, bool);
@@ -2596,7 +2598,7 @@ rest_of_handle_insert_vzeroupper (void)
   ix86_optimize_mode_switching[AVX_U128] = 1;
 
   /* Call optimize_mode_switching.  */
-  pass_mode_switching.pass.execute ();
+  g->get_passes ().execute_pass_mode_switching ();
   return 0;
 }
 
@@ -4028,8 +4030,9 @@ ix86_option_override_internal (bool main_args_p)
 static void
 ix86_option_override (void)
 {
+  opt_pass *pass_insert_vzeroupper = make_pass_insert_vzeroupper (g);
   static struct register_pass_info insert_vzeroupper_info
-    = { &pass_insert_vzeroupper.pass, "reload",
+    = { pass_insert_vzeroupper, "reload",
 	1, PASS_POS_INSERT_AFTER
       };
 
diff --git a/gcc/config/i386/t-i386 b/gcc/config/i386/t-i386
index 3a77e14..f10d570 100644
--- a/gcc/config/i386/t-i386
+++ b/gcc/config/i386/t-i386
@@ -24,7 +24,7 @@ i386.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h $(TM_H) \
   $(GGC_H) $(TARGET_H) $(TARGET_DEF_H) langhooks.h $(CGRAPH_H) \
   $(TREE_GIMPLE_H) $(DWARF2_H) $(DF_H) tm-constrs.h $(PARAMS_H) \
   i386-builtin-types.inc debug.h dwarf2out.h sbitmap.h $(FIBHEAP_H) \
-  $(OPTS_H) $(DIAGNOSTIC_H) $(COMMON_TARGET_H)
+  $(OPTS_H) $(DIAGNOSTIC_H) $(COMMON_TARGET_H) $(CONTEXT_H) $(PIPELINE_H)
 
 i386-c.o: $(srcdir)/config/i386/i386-c.c \
   $(srcdir)/config/i386/i386-protos.h $(CONFIG_H) $(SYSTEM_H) coretypes.h \
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 90e3a2b..c95b128 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -438,7 +438,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
   streamer_write_hwi_stream (ob->main_stream,
 			     node->ipa_transforms_to_apply.length ());
   FOR_EACH_VEC_ELT (node->ipa_transforms_to_apply, i, pass)
-    streamer_write_hwi_stream (ob->main_stream, pass->pass.static_pass_number);
+    streamer_write_hwi_stream (ob->main_stream, pass->static_pass_number);
 
   if (tag == LTO_symtab_analyzed_node)
     {
diff --git a/gcc/passes.c b/gcc/passes.c
index 1bca68e..0ea0f20 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -82,6 +82,54 @@ struct opt_pass *current_pass;
 
 static void register_pass_name (struct opt_pass *, const char *);
 
+/* Most passes are single-instance (within their context) and thus don't
+   need to implement cloning, but passes that support multiple instances
+   *must* provide their own implementation of the clone method.
+
+   Handle this by providing a default implemenation, but make it a fatal
+   error to call it.  */
+
+opt_pass *
+opt_pass::clone ()
+{
+  internal_error ("pass %s does not support cloning", name);
+}
+
+bool
+opt_pass::gate ()
+{
+  return true;
+}
+
+unsigned int
+opt_pass::execute ()
+{
+  return 0;
+}
+
+opt_pass::opt_pass(const pass_data &data, context *ctxt)
+  : pass_data(data),
+    sub(NULL),
+    next(NULL),
+    static_pass_number(0),
+    ctxt_(ctxt)
+{
+}
+
+
+void
+pipeline::execute_early_local_passes ()
+{
+  execute_pass_list (pass_early_local_passes_1->sub);
+}
+
+unsigned int
+pipeline::execute_pass_mode_switching ()
+{
+  return pass_mode_switching_1->execute ();
+}
+
+
 /* Call from anywhere to find out what pass this is.  Useful for
    printing out debugging information deep inside an service
    routine.  */
@@ -224,6 +272,7 @@ rest_of_type_compilation (tree type, int toplev)
 
 
 void
+pipeline::
 finish_optimization_passes (void)
 {
   int i;
@@ -233,16 +282,16 @@ finish_optimization_passes (void)
   timevar_push (TV_DUMP);
   if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
     {
-      dump_start (pass_profile.pass.static_pass_number, NULL);
+      dump_start (pass_profile_1->static_pass_number, NULL);
       end_branch_prob ();
-      dump_finish (pass_profile.pass.static_pass_number);
+      dump_finish (pass_profile_1->static_pass_number);
     }
 
   if (optimize > 0)
     {
-      dump_start (pass_profile.pass.static_pass_number, NULL);
+      dump_start (pass_profile_1->static_pass_number, NULL);
       print_combine_total_stats ();
-      dump_finish (pass_profile.pass.static_pass_number);
+      dump_finish (pass_profile_1->static_pass_number);
     }
 
   /* Do whatever is necessary to finish printing the graphs.  */
@@ -550,7 +599,7 @@ register_dump_files_1 (struct opt_pass *pass, int properties)
 
       /* If we have a gate, combine the properties that we could have with
          and without the pass being examined.  */
-      if (pass->gate)
+      if (pass->has_gate)
         properties &= new_properties;
       else
         properties = new_properties;
@@ -679,7 +728,7 @@ dump_one_pass (struct opt_pass *pass, int pass_indent)
   const char *pn;
   bool is_on, is_really_on;
 
-  is_on = (pass->gate == NULL) ? true : pass->gate();
+  is_on = pass->has_gate ? pass->gate() : true;
   is_really_on = override_gate_status (pass, current_function_decl, is_on);
 
   if (pass->static_pass_number <= 0)
@@ -1310,12 +1359,23 @@ pipeline::pipeline (context *ctxt)
 
 #define PUSH_INSERT_PASSES_WITHIN(PASS) \
   { \
-    struct opt_pass **p = &(PASS).pass.sub;
+    struct opt_pass **p = &(PASS ## _1)->sub;
 
 #define POP_INSERT_PASSES() \
   }
 
-#define NEXT_PASS(PASS, NUM)  (p = next_pass_1 (p, &((PASS).pass)))
+#define NEXT_PASS(PASS, NUM) \
+  do { \
+    gcc_assert (NULL == PASS ## _ ## NUM); \
+    if ((NUM) == 1)                              \
+      PASS ## _1 = make_##PASS (ctxt_);          \
+    else                                         \
+      {                                          \
+        gcc_assert (PASS ## _1);                 \
+        PASS ## _ ## NUM = PASS ## _1->clone (); \
+      }                                          \
+    p = next_pass_1 (p, PASS ## _ ## NUM);  \
+  } while (0)
 
 #define TERMINATE_PASS_LIST() \
   *p = NULL;
@@ -1541,7 +1601,7 @@ pipeline::dump_profile_report () const
 		fprintf (stderr, "      ");
 
 	      /* Size/time units change across gimple and RTL.  */
-	      if (i == pass_expand.pass.static_pass_number)
+	      if (i == pass_expand_1->static_pass_number)
 		fprintf (stderr, "|----------");
 	      else
 		{
@@ -1778,11 +1838,11 @@ execute_ipa_summary_passes (struct ipa_opt_pass_d *ipa_pass)
 {
   while (ipa_pass)
     {
-      struct opt_pass *pass = &ipa_pass->pass;
+      struct opt_pass *pass = ipa_pass;
 
       /* Execute all of the IPA_PASSes in the list.  */
-      if (ipa_pass->pass.type == IPA_PASS
-	  && (!pass->gate || pass->gate ())
+      if (ipa_pass->type == IPA_PASS
+	  && ((!pass->has_gate) || pass->gate ())
 	  && ipa_pass->generate_summary)
 	{
 	  pass_init_dump_file (pass);
@@ -1799,7 +1859,7 @@ execute_ipa_summary_passes (struct ipa_opt_pass_d *ipa_pass)
 
 	  pass_fini_dump_file (pass);
 	}
-      ipa_pass = (struct ipa_opt_pass_d *)ipa_pass->pass.next;
+      ipa_pass = (struct ipa_opt_pass_d *)ipa_pass->next;
     }
 }
 
@@ -1809,7 +1869,7 @@ static void
 execute_one_ipa_transform_pass (struct cgraph_node *node,
 				struct ipa_opt_pass_d *ipa_pass)
 {
-  struct opt_pass *pass = &ipa_pass->pass;
+  struct opt_pass *pass = ipa_pass;
   unsigned int todo_after = 0;
 
   current_pass = pass;
@@ -1933,7 +1993,7 @@ execute_one_pass (struct opt_pass *pass)
 
   /* Check whether gate check should be avoided.
      User controls the value of the gate through the parameter "gate_status". */
-  gate_status = (pass->gate == NULL) ? true : pass->gate();
+  gate_status = pass->has_gate ? pass->gate() : true;
   gate_status = override_gate_status (pass, current_function_decl, gate_status);
 
   /* Override gate with plugin.  */
@@ -1990,7 +2050,7 @@ execute_one_pass (struct opt_pass *pass)
     timevar_push (pass->tv_id);
 
   /* Do it!  */
-  if (pass->execute)
+  if (pass->has_execute)
     {
       todo_after = pass->execute ();
       do_per_function (clear_last_verified, NULL);
@@ -2066,7 +2126,7 @@ ipa_write_summaries_2 (struct opt_pass *pass, struct lto_out_decl_state *state)
       gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
       if (pass->type == IPA_PASS
 	  && ipa_pass->write_summary
-	  && (!pass->gate || pass->gate ()))
+	  && ((!pass->has_gate) || pass->gate ()))
 	{
 	  /* If a timevar is present, start it.  */
 	  if (pass->tv_id)
@@ -2182,7 +2242,7 @@ ipa_write_optimization_summaries_1 (struct opt_pass *pass, struct lto_out_decl_s
       gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
       if (pass->type == IPA_PASS
 	  && ipa_pass->write_optimization_summary
-	  && (!pass->gate || pass->gate ()))
+	  && ((!pass->has_gate) || pass->gate ()))
 	{
 	  /* If a timevar is present, start it.  */
 	  if (pass->tv_id)
@@ -2259,7 +2319,7 @@ ipa_read_summaries_1 (struct opt_pass *pass)
       gcc_assert (!cfun);
       gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
 
-      if (pass->gate == NULL || pass->gate ())
+      if ((!pass->has_gate) || pass->gate ())
 	{
 	  if (pass->type == IPA_PASS && ipa_pass->read_summary)
 	    {
@@ -2310,7 +2370,7 @@ ipa_read_optimization_summaries_1 (struct opt_pass *pass)
       gcc_assert (!cfun);
       gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
 
-      if (pass->gate == NULL || pass->gate ())
+      if ((!pass->has_gate) || pass->gate ())
 	{
 	  if (pass->type == IPA_PASS && ipa_pass->read_optimization_summary)
 	    {
@@ -2388,7 +2448,7 @@ execute_ipa_stmt_fixups (struct opt_pass *pass,
     {
       /* Execute all of the IPA_PASSes in the list.  */
       if (pass->type == IPA_PASS
-	  && (!pass->gate || pass->gate ()))
+	  && ((!pass->has_gate) || pass->gate ()))
 	{
 	  struct ipa_opt_pass_d *ipa_pass = (struct ipa_opt_pass_d *) pass;
 
diff --git a/gcc/pipeline.h b/gcc/pipeline.h
index 37c90d7..60bde5c 100644
--- a/gcc/pipeline.h
+++ b/gcc/pipeline.h
@@ -58,6 +58,12 @@ public:
 
   void dump_profile_report () const;
 
+  void finish_optimization_passes ();
+
+  /* Access to specific passes, so that the majority can be private.  */
+  void execute_early_local_passes ();
+  unsigned int execute_pass_mode_switching ();
+
 public:
   /* The root of the compilation pass tree, once constructed.  */
   opt_pass *all_passes;
@@ -81,6 +87,37 @@ private:
 private:
   context *ctxt_;
 
+  /* References to all of the individual passes.
+     These fields are generated via macro expansion.
+
+     For example:
+         NEXT_PASS (pass_build_cfg, 1);
+     within pass-instances.def means that there is a field:
+         opt_pass *pass_build_cfg_1;
+
+     Similarly, the various:
+        NEXT_PASS (pass_copy_prop, 1);
+        ...
+        NEXT_PASS (pass_copy_prop, 8);
+     in pass-instances.def lead to fields:
+        opt_pass *pass_copy_prop_1;
+        ...
+        opt_pass *pass_copy_prop_8;  */
+
+#define INSERT_PASSES_AFTER(PASS)
+#define PUSH_INSERT_PASSES_WITHIN(PASS)
+#define POP_INSERT_PASSES()
+#define NEXT_PASS(PASS, NUM) opt_pass *PASS ## _ ## NUM
+#define TERMINATE_PASS_LIST()
+
+#include "pass-instances.def"
+
+#undef INSERT_PASSES_AFTER
+#undef PUSH_INSERT_PASSES_WITHIN
+#undef POP_INSERT_PASSES
+#undef NEXT_PASS
+#undef TERMINATE_PASS_LIST
+
 }; // class pipeline
 
 } // namespace gcc
diff --git a/gcc/testsuite/g++.dg/plugin/dumb_plugin.c b/gcc/testsuite/g++.dg/plugin/dumb_plugin.c
index 0f15140..ab69c14 100644
--- a/gcc/testsuite/g++.dg/plugin/dumb_plugin.c
+++ b/gcc/testsuite/g++.dg/plugin/dumb_plugin.c
@@ -11,6 +11,7 @@
 #include "intl.h"
 #include "toplev.h"
 #include "diagnostic.h"
+#include "context.h"
 
 int plugin_is_GPL_compatible;
 
@@ -124,7 +125,7 @@ plugin_init (struct plugin_name_args *plugin_info,
       return 1;
     }
 
-  pass_info.pass = &pass_dumb_plugin_example.pass;
+  pass_info.pass = make_pass_dumb_plugin_example (g);
   pass_info.reference_pass_name = ref_pass_name;
   pass_info.ref_pass_instance_number = ref_instance_number;
   pass_info.pos_op = PASS_POS_INSERT_AFTER;
diff --git a/gcc/testsuite/g++.dg/plugin/selfassign.c b/gcc/testsuite/g++.dg/plugin/selfassign.c
index 37a0a97..3e0b38e 100644
--- a/gcc/testsuite/g++.dg/plugin/selfassign.c
+++ b/gcc/testsuite/g++.dg/plugin/selfassign.c
@@ -15,6 +15,7 @@
 #include "intl.h"
 #include "plugin-version.h"
 #include "diagnostic.h"
+#include "context.h"
 
 int plugin_is_GPL_compatible;
 
@@ -309,7 +310,7 @@ plugin_init (struct plugin_name_args *plugin_info,
     return 1;
 
   /* Self-assign detection should happen after SSA is constructed.  */
-  pass_info.pass = &pass_warn_self_assign.pass;
+  pass_info.pass = make_pass_warn_self_assign (g);
   pass_info.reference_pass_name = "ssa";
   pass_info.ref_pass_instance_number = 1;
   pass_info.pos_op = PASS_POS_INSERT_AFTER;
diff --git a/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c b/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c
index 45e6257..31dfe69 100644
--- a/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c
+++ b/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c
@@ -8,6 +8,7 @@
 #include "gimple.h"
 #include "tree-pass.h"
 #include "intl.h"
+#include "context.h"
 
 int plugin_is_GPL_compatible;
 
@@ -53,7 +54,7 @@ int plugin_init (struct plugin_name_args *plugin_info,
 {
   struct register_pass_info p;
 
-  p.pass = &one_pass.pass;
+  p.pass = make_one_pass (g);
   p.reference_pass_name = "cfg";
   p.ref_pass_instance_number = 1;
   p.pos_op = PASS_POS_INSERT_AFTER;
diff --git a/gcc/testsuite/gcc.dg/plugin/selfassign.c b/gcc/testsuite/gcc.dg/plugin/selfassign.c
index 37a0a97..3e0b38e 100644
--- a/gcc/testsuite/gcc.dg/plugin/selfassign.c
+++ b/gcc/testsuite/gcc.dg/plugin/selfassign.c
@@ -15,6 +15,7 @@
 #include "intl.h"
 #include "plugin-version.h"
 #include "diagnostic.h"
+#include "context.h"
 
 int plugin_is_GPL_compatible;
 
@@ -309,7 +310,7 @@ plugin_init (struct plugin_name_args *plugin_info,
     return 1;
 
   /* Self-assign detection should happen after SSA is constructed.  */
-  pass_info.pass = &pass_warn_self_assign.pass;
+  pass_info.pass = make_pass_warn_self_assign (g);
   pass_info.reference_pass_name = "ssa";
   pass_info.ref_pass_instance_number = 1;
   pass_info.pos_op = PASS_POS_INSERT_AFTER;
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 1cf98dc..6097290 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -76,6 +76,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "plugin.h"
 #include "diagnostic-color.h"
 #include "context.h"
+#include "pipeline.h"
 
 #if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO)
 #include "dbxout.h"
@@ -1818,7 +1819,7 @@ finalize (bool no_backend)
     {
       statistics_fini ();
 
-      finish_optimization_passes ();
+      g->get_passes ().finish_optimization_passes ();
 
       ira_finish_once ();
     }
diff --git a/gcc/toplev.h b/gcc/toplev.h
index fff452c..84ffdb0 100644
--- a/gcc/toplev.h
+++ b/gcc/toplev.h
@@ -28,7 +28,6 @@ extern int toplev_main (int, char **);
 extern void rest_of_decl_compilation (tree, int, int);
 extern void rest_of_type_compilation (tree, int);
 extern void init_optimization_passes (void);
-extern void finish_optimization_passes (void);
 extern bool enable_rtl_dump_file (void);
 
 /* In except.c.  Initialize exception handling.  This is used by the Ada
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 16442ed..41f7d17 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -34,9 +34,8 @@ enum opt_pass_type
   IPA_PASS
 };
 
-/* Describe one pass; this is the common part shared across different pass
-   types.  */
-struct opt_pass
+/* Metadata for a pass, non-varying across all instances of a pass.  */
+struct pass_data
 {
   /* Optimization pass type.  */
   enum opt_pass_type type;
@@ -48,23 +47,13 @@ struct opt_pass
   /* The -fopt-info optimization group flags as defined in dumpfile.h. */
   unsigned int optinfo_flags;
 
-  /* If non-null, this pass and all sub-passes are executed only if
-     the function returns true.  */
-  bool (*gate) (void);
+  /* If true, this pass has its own implementation of the opt_pass::gate
+     method.  */
+  bool has_gate;
 
-  /* This is the code to run.  If null, then there should be sub-passes
-     otherwise this pass does nothing.  The return value contains
-     TODOs to execute in addition to those in TODO_flags_finish.   */
-  unsigned int (*execute) (void);
-
-  /* A list of sub-passes to run, dependent on gate predicate.  */
-  struct opt_pass *sub;
-
-  /* Next in the list of passes to run, independent of gate predicate.  */
-  struct opt_pass *next;
-
-  /* Static pass number, used as a fragment of the dump file name.  */
-  int static_pass_number;
+  /* If true, this pass has its own implementation of the opt_pass::execute
+     method.  */
+  bool has_execute;
 
   /* The timevar id associated with this pass.  */
   /* ??? Ideally would be dynamically assigned.  */
@@ -80,16 +69,72 @@ struct opt_pass
   unsigned int todo_flags_finish;
 };
 
+namespace gcc
+{
+  class context;
+} // namespace gcc
+
+/* An instance of a pass.  This is also "pass_data" to minimize the
+   changes in existing code.  */
+class opt_pass : public pass_data
+{
+public:
+  virtual ~opt_pass () { }
+
+  /* Create a copy of this pass.
+
+     Passes that can have multiple instances must provide their own
+     implementation of this, to ensure that any sharing of state between
+     this instance and the copy is "wired up" correctly.
+
+     The default implementation prints an error message and aborts.  */
+  virtual opt_pass *clone ();
+
+  /* If has_gate is set, this pass and all sub-passes are executed only if
+     the function returns true.  */
+  virtual bool gate ();
+
+  /* This is the code to run.  If has_execute is false, then there should
+     be sub-passes otherwise this pass does nothing.
+     The return value contains TODOs to execute in addition to those in
+     TODO_flags_finish.   */
+  virtual unsigned int execute ();
+
+protected:
+  opt_pass(const pass_data&, gcc::context *);
+
+public:
+  /* A list of sub-passes to run, dependent on gate predicate.  */
+  struct opt_pass *sub;
+
+  /* Next in the list of passes to run, independent of gate predicate.  */
+  struct opt_pass *next;
+
+  /* Static pass number, used as a fragment of the dump file name.  */
+  int static_pass_number;
+
+protected:
+  gcc::context *ctxt_;
+};
+
 /* Description of GIMPLE pass.  */
-struct gimple_opt_pass
+class gimple_opt_pass : public opt_pass
 {
-  struct opt_pass pass;
+protected:
+  gimple_opt_pass(const pass_data& data, gcc::context *ctxt)
+    : opt_pass(data, ctxt)
+  {
+  }
 };
 
 /* Description of RTL pass.  */
-struct rtl_opt_pass
+class rtl_opt_pass : public opt_pass
 {
-  struct opt_pass pass;
+protected:
+  rtl_opt_pass(const pass_data& data, gcc::context *ctxt)
+    : opt_pass(data, ctxt)
+  {
+  }
 };
 
 struct varpool_node;
@@ -98,10 +143,9 @@ struct lto_symtab_encoder_d;
 
 /* Description of IPA pass with generate summary, write, execute, read and
    transform stages.  */
-struct ipa_opt_pass_d
+class ipa_opt_pass_d : public opt_pass
 {
-  struct opt_pass pass;
-
+public:
   /* IPA passes can analyze function body and variable initializers
       using this hook and produce summary.  */
   void (*generate_summary) (void);
@@ -127,13 +171,42 @@ struct ipa_opt_pass_d
   unsigned int function_transform_todo_flags_start;
   unsigned int (*function_transform) (struct cgraph_node *);
   void (*variable_transform) (struct varpool_node *);
+
+protected:
+  ipa_opt_pass_d(const pass_data& data, gcc::context *ctxt,
+                 void (*generate_summary) (void),
+                 void (*write_summary) (void),
+                 void (*read_summary) (void),
+                 void (*write_optimization_summary) (void),
+                 void (*read_optimization_summary) (void),
+                 void (*stmt_fixup) (struct cgraph_node *, gimple *),
+                 unsigned int function_transform_todo_flags_start,
+                 unsigned int (*function_transform) (struct cgraph_node *),
+                 void (*variable_transform) (struct varpool_node *))
+    : opt_pass(data, ctxt),
+	       generate_summary(generate_summary),
+	       write_summary(write_summary),
+	       read_summary(read_summary),
+	       write_optimization_summary(write_optimization_summary),
+	       read_optimization_summary(read_optimization_summary),
+	       stmt_fixup(stmt_fixup),
+	       function_transform_todo_flags_start(
+	         function_transform_todo_flags_start),
+	       function_transform(function_transform),
+	       variable_transform(variable_transform)
+  {
+  }
 };
 
 /* Description of simple IPA pass.  Simple IPA passes have just one execute
    hook.  */
-struct simple_ipa_opt_pass
+class simple_ipa_opt_pass : public opt_pass
 {
-  struct opt_pass pass;
+protected:
+  simple_ipa_opt_pass(const pass_data& data, gcc::context *ctxt)
+    : opt_pass(data, ctxt)
+  {
+  }
 };
 
 /* Pass properties.  */
-- 
1.7.11.7


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]