diff options
author | Michael Matz <matz@suse.de> | 2012-04-19 13:29:29 +0000 |
---|---|---|
committer | Michael Matz <matz@suse.de> | 2012-04-19 13:29:29 +0000 |
commit | e77812d169ba4df33e9455067cc323baf24492c8 (patch) | |
tree | 8f69ea3822d53cbb5ee137c295bc3fb2dec89d98 /gcc/gengtype.c | |
parent | 03b3ab2baca4b9d16f2bec452b09dec2849ac89c (diff) |
PR middle-end/52977
* tree.h (VECTOR_CST_NELTS): Use part number of types again.
(struct tree_vector): Adjust GTY length.
* tree.c (make_vector_stat): Don't set VECTOR_CST_NELTS.
* gengtype.c (struct walk_type_data): Add in_record_p and loopcounter
members.
(walk_type, <TYPE_POINTER, TYPE_ARRAY>): Handle case where our
caller emitted the length calulation already.
(walk_type, <TYPE_UNION, TYPE_STRUCT>): Emit length calculations
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@186593 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/gengtype.c')
-rw-r--r-- | gcc/gengtype.c | 92 |
1 files changed, 82 insertions, 10 deletions
diff --git a/gcc/gengtype.c b/gcc/gengtype.c index fa453929814..abafaa9bc12 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -2291,6 +2291,8 @@ struct walk_type_data const char *reorder_fn; bool needs_cast_p; bool fn_wants_lvalue; + bool in_record_p; + int loopcounter; }; /* Print a mangled name representing T to OF. */ @@ -2592,7 +2594,7 @@ walk_type (type_p t, struct walk_type_data *d) } else { - int loopcounter = d->counter++; + int loopcounter = d->loopcounter; const char *oldval = d->val; const char *oldprevval3 = d->prev_val[3]; char *newval; @@ -2602,7 +2604,10 @@ walk_type (type_p t, struct walk_type_data *d) oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter); oprintf (d->of, "%*sfor (i%d = 0; i%d != (size_t)(", d->indent, "", loopcounter, loopcounter); - output_escaped_param (d, length, "length"); + if (!d->in_record_p) + output_escaped_param (d, length, "length"); + else + oprintf (d->of, "l%d", loopcounter); oprintf (d->of, "); i%d++) {\n", loopcounter); d->indent += 2; d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter); @@ -2624,7 +2629,7 @@ walk_type (type_p t, struct walk_type_data *d) case TYPE_ARRAY: { - int loopcounter = d->counter++; + int loopcounter; const char *oldval = d->val; char *newval; @@ -2633,6 +2638,11 @@ walk_type (type_p t, struct walk_type_data *d) if (t->u.a.p->kind == TYPE_SCALAR) break; + if (length) + loopcounter = d->loopcounter; + else + loopcounter = d->counter++; + /* When walking an array, compute the length and store it in a local variable before walking the array elements, instead of recomputing the length expression each time through the loop. @@ -2643,13 +2653,16 @@ walk_type (type_p t, struct walk_type_data *d) oprintf (d->of, "%*s{\n", d->indent, ""); d->indent += 2; oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter); - oprintf (d->of, "%*ssize_t l%d = (size_t)(", - d->indent, "", loopcounter); - if (length) - output_escaped_param (d, length, "length"); - else - oprintf (d->of, "%s", t->u.a.len); - oprintf (d->of, ");\n"); + if (!d->in_record_p || !length) + { + oprintf (d->of, "%*ssize_t l%d = (size_t)(", + d->indent, "", loopcounter); + if (length) + output_escaped_param (d, length, "length"); + else + oprintf (d->of, "%s", t->u.a.len); + oprintf (d->of, ");\n"); + } oprintf (d->of, "%*sfor (i%d = 0; i%d != l%d; i%d++) {\n", d->indent, "", @@ -2678,6 +2691,9 @@ walk_type (type_p t, struct walk_type_data *d) const int union_p = t->kind == TYPE_UNION; int seen_default_p = 0; options_p o; + int lengths_seen = 0; + int endcounter; + bool any_length_seen = false; if (!t->u.s.line.file) error_at_line (d->line, "incomplete structure `%s'", t->u.s.tag); @@ -2713,6 +2729,45 @@ walk_type (type_p t, struct walk_type_data *d) d->indent += 2; oprintf (d->of, "%*s{\n", d->indent, ""); } + + for (f = t->u.s.fields; f; f = f->next) + { + options_p oo; + int skip_p = 0; + const char *fieldlength = NULL; + + d->reorder_fn = NULL; + for (oo = f->opt; oo; oo = oo->next) + if (strcmp (oo->name, "skip") == 0) + skip_p = 1; + else if (strcmp (oo->name, "length") == 0 + && oo->kind == OPTION_STRING) + fieldlength = oo->info.string; + + if (skip_p) + continue; + if (fieldlength) + { + lengths_seen++; + d->counter++; + if (!union_p) + { + if (!any_length_seen) + { + oprintf (d->of, "%*s{\n", d->indent, ""); + d->indent += 2; + } + any_length_seen = true; + + oprintf (d->of, "%*ssize_t l%d = (size_t)(", + d->indent, "", d->counter - 1); + output_escaped_param (d, fieldlength, "length"); + oprintf (d->of, ");\n"); + } + } + } + endcounter = d->counter; + for (f = t->u.s.fields; f; f = f->next) { options_p oo; @@ -2721,6 +2776,7 @@ walk_type (type_p t, struct walk_type_data *d) int skip_p = 0; int default_p = 0; int use_param_p = 0; + const char *fieldlength = NULL; char *newval; d->reorder_fn = NULL; @@ -2741,6 +2797,9 @@ walk_type (type_p t, struct walk_type_data *d) else if (strncmp (oo->name, "use_param", 9) == 0 && (oo->name[9] == '\0' || ISDIGIT (oo->name[9]))) use_param_p = 1; + else if (strcmp (oo->name, "length") == 0 + && oo->kind == OPTION_STRING) + fieldlength = oo->info.string; if (skip_p) continue; @@ -2774,16 +2833,24 @@ walk_type (type_p t, struct walk_type_data *d) "field `%s' is missing `tag' or `default' option", f->name); + if (fieldlength) + { + d->loopcounter = endcounter - lengths_seen--; + } + d->line = &f->line; d->val = newval = xasprintf ("%s%s%s", oldval, dot, f->name); d->opt = f->opt; d->used_length = false; + d->in_record_p = !union_p; if (union_p && use_param_p && d->param == NULL) oprintf (d->of, "%*sgcc_unreachable ();\n", d->indent, ""); else walk_type (f->type, d); + d->in_record_p = false; + free (newval); if (union_p) @@ -2808,6 +2875,11 @@ walk_type (type_p t, struct walk_type_data *d) oprintf (d->of, "%*s}\n", d->indent, ""); d->indent -= 2; } + if (any_length_seen) + { + d->indent -= 2; + oprintf (d->of, "%*s}\n", d->indent, ""); + } } break; |