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:
David Malcolm 2013-10-29 01:01:52 +00:00 committed by David Malcolm
parent a6137eb928
commit 52a7fb3cd3
4 changed files with 133 additions and 7 deletions

View 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

View 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)

View 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)

View 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