]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Handle simple inheritance in gengtype
authorDavid Malcolm <dmalcolm@redhat.com>
Tue, 29 Oct 2013 01:01:52 +0000 (01:01 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Tue, 29 Oct 2013 01:01:52 +0000 (01:01 +0000)
* 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.

From-SVN: r204146

gcc/ChangeLog
gcc/gengtype-parse.c
gcc/gengtype.c
gcc/gengtype.h

index 70193b49d13be1313eb3d64859362f2fc1696da3..3a391b091572b7d8cdece93494c36a31e9ed0c6c 100644 (file)
@@ -1,3 +1,31 @@
+2013-10-29  David Malcolm  <dmalcolm@redhat.com>
+
+       * 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.
+
 2013-10-28  Vladimir Makarov  <vmakarov@redhat.com>
 
        * lra-spills.c (lra_final_code_change): Remove useless move insns
index 31d493a46f52b1133b5fc221d0b215ecf64f63c5..f480503f8f1b3644218261a63ed7635e28fdccb5 100644 (file)
@@ -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)
index 79ada1f0aa65f6852a8bdefce5a2183f68633204..31e0f998a03e8c80d8d2c440fe078b4865a74ed7 100644 (file)
@@ -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;
@@ -2547,6 +2551,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);
@@ -2609,6 +2618,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
@@ -2626,6 +2673,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;
@@ -2654,7 +2702,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)
@@ -2973,8 +3021,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;
@@ -3012,7 +3070,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 = ".";
@@ -3114,11 +3172,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;
@@ -3464,6 +3537,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)
@@ -3640,7 +3718,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;
 
@@ -3945,6 +4026,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;
@@ -4089,7 +4175,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?  */
@@ -4373,6 +4461,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)
index 06ebbed55a824d168b2d87dec11d0fbbde86b3fc..2d20bf98efb7b3c4dc2279026b70844abbade1af 100644 (file)
@@ -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