Patchwork [v2,3/4] Handle simple inheritance in gengtype.

login
register
mail settings
Submitter David Malcolm
Date Sept. 24, 2013, 5:49 p.m.
Message ID <1380044971-11810-4-git-send-email-dmalcolm@redhat.com>
Download mbox | patch
Permalink /patch/277555/
State New
Headers show

Comments

David Malcolm - Sept. 24, 2013, 5:49 p.m.
Treat GTY structs that have a "desc" as being the root of an inheritance
hierarchy.  Generate a switch on desc within the marking function with
cases for each subclass, visiting all fields of the type (including
inherited ones).

Don't create marking functions for subclasses, instead using the base
class marking functions.  Use walk_type on them within walk_subclasses
to generate the case within the switch for handling the tag, directly
walking all fields of the type.

	* gengtype-parse.c (opts_have): Drop "static" so that
	we can use this from gengtype.c.
	* gengtype.c (set_gc_used_type): Mark any base class as used;
	update field traversal to visit inherited fields.
	(output_mangled_typename):  Convert references to classes within
	an inheritance hierarchy to reference the ultimate base class,
	since only it will have gt_ functions.
	(get_string_option): New.
	(walk_subclasses): New.
	(walk_type): Treat GTY structs that have a "desc" as being the
	root of an inheritance hierarchy.  Generate a switch on it
	within the marking function which walks all subclasses, adding
	cases for them via walk_subclasses.  For subclasses, visit all
	fields of the type (including inherited ones).
	(write_func_for_structure): Don't write fns for subclasses, only
	for the ultimate base class within an inheritance hierarchy.
	Subclasses-marking will be handled by the base class marking
	functions.
	(write_types): Likewise.
	(write_local_func_for_structure): Likewise.
	(USED_BY_TYPED_GC_P): Emit allocators for subclasses that have
	a "tag" option (and are thus concrete subclasses).
	(write_root): Use the marker function for the ultimate base class.
	* gengtype.h (FOR_ALL_INHERITED_FIELDS): New.
	(opts_have): Add declaration.
---
 gcc/gengtype-parse.c |   2 +-
 gcc/gengtype.c       | 102 ++++++++++++++++++++++++++++++++++++++++++++++++---
 gcc/gengtype.h       |   8 ++++
 3 files changed, 105 insertions(+), 7 deletions(-)

Patch

diff --git a/gcc/gengtype-parse.c b/gcc/gengtype-parse.c
index 31d493a..f480503 100644
--- a/gcc/gengtype-parse.c
+++ b/gcc/gengtype-parse.c
@@ -793,7 +793,7 @@  struct_field_seq (void)
 
 /* Return true if OPTS contain the option named STR.  */
 
-static bool
+bool
 opts_have (options_p opts, const char *str)
 {
   for (options_p opt = opts; opt; opt = opt->next)
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index a6dc221..4224a5e 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1532,7 +1532,11 @@  set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM],
 	process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy, &dummy,
 			    &dummy2);
 
-	for (f = t->u.s.fields; f; f = f->next)
+	if (t->u.s.base_class)
+	  set_gc_used_type (t->u.s.base_class, level, param,
+			    allow_undefined_types);
+
+	FOR_ALL_INHERITED_FIELDS(t, f)
 	  {
 	    int maybe_undef = 0;
 	    int pass_param = 0;
@@ -2534,6 +2538,11 @@  output_mangled_typename (outf_p of, const_type_p t)
       case TYPE_LANG_STRUCT:
       case TYPE_USER_STRUCT:
 	{
+	  /* For references to classes within an inheritance hierarchy,
+	     only ever reference the ultimate base class, since only
+	     it will have gt_ functions.  */
+	  while (t->u.s.base_class)
+	    t = t->u.s.base_class;
 	  const char *id_for_tag = filter_type_name (t->u.s.tag);
 	  oprintf (of, "%lu%s", (unsigned long) strlen (id_for_tag),
 		   id_for_tag);
@@ -2596,6 +2605,44 @@  output_escaped_param (struct walk_type_data *d, const char *param,
 	}
 }
 
+const char *
+get_string_option (options_p opt, const char *key)
+{
+  for (; opt; opt = opt->next)
+    if (strcmp (opt->name, key) == 0)
+      return opt->info.string;
+  return NULL;
+}
+
+static void
+walk_subclasses (type_p base, struct walk_type_data *d)
+{
+  for (type_p sub = structures; sub != NULL; sub = sub->next)
+    {
+      if (sub->u.s.base_class == base)
+	{
+	  const char *type_tag = get_string_option (sub->u.s.opt, "tag");
+	  if (type_tag)
+	    {
+	      oprintf (d->of, "%*scase %s:\n", d->indent, "", type_tag);
+	      d->indent += 2;
+	      oprintf (d->of, "%*s{\n", d->indent, "");
+	      d->indent += 2;
+	      oprintf (d->of, "%*s%s *sub = static_cast <%s *> (x);\n",
+		       d->indent, "", sub->u.s.tag, sub->u.s.tag);
+	      const char *old_val = d->val;
+	      d->val = "(*sub)";
+	      walk_type (sub, d);
+	      d->val = old_val;
+	      d->indent -= 2;
+	      oprintf (d->of, "%*s}\n", d->indent, "");
+	      oprintf (d->of, "%*sbreak;\n", d->indent, "");
+	      d->indent -= 2;
+	    }
+	  walk_subclasses (sub, d);
+	}
+    }
+}
 
 /* Call D->PROCESS_FIELD for every field (or subfield) of D->VAL,
    which is of type T.  Write code to D->OF to constrain execution (at
@@ -2613,6 +2660,7 @@  walk_type (type_p t, struct walk_type_data *d)
 {
   const char *length = NULL;
   const char *desc = NULL;
+  const char *type_tag = NULL;
   int maybe_undef_p = 0;
   int use_param_num = -1;
   int use_params_p = 0;
@@ -2641,7 +2689,7 @@  walk_type (type_p t, struct walk_type_data *d)
     else if (strcmp (oo->name, "dot") == 0)
       ;
     else if (strcmp (oo->name, "tag") == 0)
-      ;
+      type_tag = oo->info.string;
     else if (strcmp (oo->name, "special") == 0)
       ;
     else if (strcmp (oo->name, "skip") == 0)
@@ -2960,8 +3008,18 @@  walk_type (type_p t, struct walk_type_data *d)
 	    d->indent += 2;
 	    oprintf (d->of, "%*s{\n", d->indent, "");
 	  }
+	else if (desc)
+	  {
+	    oprintf (d->of, "%*sswitch (", d->indent, "");
+	    output_escaped_param (d, desc, "desc");
+	    oprintf (d->of, ")\n");
+	    d->indent += 2;
+	    oprintf (d->of, "%*s{\n", d->indent, "");
+	    oprintf (d->of, "%*scase %s:\n", d->indent, "", type_tag);
+	    d->indent += 2;
+	  }
 
-	for (f = t->u.s.fields; f; f = f->next)
+	FOR_ALL_INHERITED_FIELDS (t, f)
 	  {
 	    options_p oo;
 	    int skip_p = 0;
@@ -2999,7 +3057,7 @@  walk_type (type_p t, struct walk_type_data *d)
 	  }
 	endcounter = d->counter;
 
-	for (f = t->u.s.fields; f; f = f->next)
+	FOR_ALL_INHERITED_FIELDS (t, f)
 	  {
 	    options_p oo;
 	    const char *dot = ".";
@@ -3101,11 +3159,26 @@  walk_type (type_p t, struct walk_type_data *d)
 	    oprintf (d->of, "%*sdefault:\n", d->indent, "");
 	    oprintf (d->of, "%*s  break;\n", d->indent, "");
 	  }
+
+	if (desc && !union_p)
+	  {
+		oprintf (d->of, "%*sbreak;\n", d->indent, "");
+		d->indent -= 2;
+          }
 	if (union_p)
 	  {
 	    oprintf (d->of, "%*s}\n", d->indent, "");
 	    d->indent -= 2;
 	  }
+	else if (desc)
+	  {
+	    /* Add cases to handle subclasses.  */
+	    walk_subclasses (t, d);
+
+	    /* End of the switch statement */
+	    oprintf (d->of, "%*s}\n", d->indent, "");
+	    d->indent -= 2;
+	  }
 	if (any_length_seen)
 	  {
 	    d->indent -= 2;
@@ -3451,6 +3524,11 @@  write_func_for_structure (type_p orig_s, type_p s, type_p *param,
   options_p opt;
   struct walk_type_data d;
 
+  /* Don't write fns for subclasses, only for the ultimate base class
+     within an inheritance hierarchy.  */
+  if (s->u.s.base_class)
+    return;
+
   memset (&d, 0, sizeof (d));
   d.of = get_output_file_for_structure (s, param);
   for (opt = s->u.s.opt; opt; opt = opt->next)
@@ -3627,7 +3705,10 @@  write_types (outf_p output_header, type_p structures, type_p param_structs,
      emitted afterwards.  This is needed in plugin mode.  */
   oprintf (output_header, "/* Macros and declarations.  */\n");
   for (s = structures; s; s = s->next)
-    if (s->gc_used == GC_POINTED_TO || s->gc_used == GC_MAYBE_POINTED_TO)
+    /* Do not emit handlers for derived classes; we only ever deal with
+       the ultimate base class within an inheritance hierarchy.  */
+    if ((s->gc_used == GC_POINTED_TO || s->gc_used == GC_MAYBE_POINTED_TO)
+        && !s->u.s.base_class)
       {
 	options_p opt;
 
@@ -3932,6 +4013,11 @@  write_local_func_for_structure (const_type_p orig_s, type_p s, type_p *param)
 {
   struct walk_type_data d;
 
+  /* Don't write fns for subclasses, only for the ultimate base class
+     within an inheritance hierarchy.  */
+  if (s->u.s.base_class)
+    return;
+
   memset (&d, 0, sizeof (d));
   d.of = get_output_file_for_structure (s, param);
   d.process_field = write_types_local_process_field;
@@ -4076,7 +4162,9 @@  write_local (outf_p output_header, type_p structures, type_p param_structs)
 	   || ((s)->gc_used == GC_MAYBE_POINTED_TO			\
 	       && s->u.s.line.file != NULL)				\
 	   || ((s)->gc_used == GC_USED					\
-	       && strncmp (s->u.s.tag, "anonymous", strlen ("anonymous"))))))
+	       && strncmp (s->u.s.tag, "anonymous", strlen ("anonymous"))) \
+	   || (s->u.s.base_class && opts_have (s->u.s.opt, "tag")))))
+
 
 
 /* Might T contain any non-pointer elements?  */
@@ -4360,6 +4448,8 @@  write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
 
 	if (!has_length && union_or_struct_p (tp))
 	  {
+	    while (tp->u.s.base_class)
+	      tp = tp->u.s.base_class;
 	    const char *id_for_tag = filter_type_name (tp->u.s.tag);
 	    oprintf (f, "    &gt_ggc_mx_%s,\n", id_for_tag);
 	    if (emit_pch)
diff --git a/gcc/gengtype.h b/gcc/gengtype.h
index 06ebbed..2d20bf9 100644
--- a/gcc/gengtype.h
+++ b/gcc/gengtype.h
@@ -506,4 +506,12 @@  void dbgprint_count_type_at (const char *, int, const char *, type_p);
 #define DBGPRINT_COUNT_TYPE(Msg,Ty) do{/*nodbgprint_count_type*/}while (0)
 #endif /*ENABLE_CHECKING */
 
+#define FOR_ALL_INHERITED_FIELDS(TYPE, FIELD_VAR) \
+  for (type_p sub = (TYPE); sub; sub = sub->u.s.base_class) \
+    for (FIELD_VAR = sub->u.s.fields; FIELD_VAR; FIELD_VAR = FIELD_VAR->next)
+
+extern bool
+opts_have (options_p opts, const char *str);
+
+
 #endif