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
This commit is contained in:
parent
a6137eb928
commit
52a7fb3cd3
4 changed files with 133 additions and 7 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
102
gcc/gengtype.c
102
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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue