diff options
author | David Malcolm <dmalcolm@redhat.com> | 2013-10-29 01:01:52 +0000 |
---|---|---|
committer | David Malcolm <dmalcolm@gcc.gnu.org> | 2013-10-29 01:01:52 +0000 |
commit | 52a7fb3cd396a30bf370d267d9ca685bbd4394cd (patch) | |
tree | 500792a83215ba241bd2dddaaebc624b38f6e335 | |
parent | a6137eb928a21241857e488a70d0dc0de2c4cd4f (diff) | |
download | gcc-52a7fb3cd396a30bf370d267d9ca685bbd4394cd.zip gcc-52a7fb3cd396a30bf370d267d9ca685bbd4394cd.tar.gz gcc-52a7fb3cd396a30bf370d267d9ca685bbd4394cd.tar.bz2 |
Handle simple inheritance in gengtype
* 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
-rw-r--r-- | gcc/ChangeLog | 28 | ||||
-rw-r--r-- | gcc/gengtype-parse.c | 2 | ||||
-rw-r--r-- | gcc/gengtype.c | 102 | ||||
-rw-r--r-- | gcc/gengtype.h | 8 |
4 files changed, 133 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 70193b49..3a391b0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 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 79ada1f..31e0f99 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; @@ -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, " >_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 |