aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog28
-rw-r--r--gcc/gengtype-parse.c2
-rw-r--r--gcc/gengtype.c102
-rw-r--r--gcc/gengtype.h8
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, " &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