diff options
Diffstat (limited to 'gcc/gengtype.c')
-rw-r--r-- | gcc/gengtype.c | 125 |
1 files changed, 88 insertions, 37 deletions
diff --git a/gcc/gengtype.c b/gcc/gengtype.c index b16a33ac04d..9a7de9fb9a9 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -1571,7 +1571,7 @@ open_base_files (void) "optabs.h", "libfuncs.h", "debug.h", "ggc.h", "cgraph.h", "tree-flow.h", "reload.h", "cpp-id-data.h", "tree-chrec.h", "cfglayout.h", "except.h", "output.h", "gimple.h", "cfgloop.h", - "target.h", "ipa-prop.h", "lto-streamer.h", NULL + "target.h", "ipa-prop.h", "lto-streamer.h", "target-globals.h", NULL }; const char *const *ifp; outf_p gtype_desc_c; @@ -3174,8 +3174,81 @@ finish_root_table (struct flist *flp, const char *pfx, const char *lastname, } } +/* Write the first three fields (pointer, count and stride) for + root NAME to F. V and LINE are as for write_root. + + Return true if the entry could be written; return false on error. */ + +static bool +start_root_entry (outf_p f, pair_p v, const char *name, struct fileloc *line) +{ + type_p ap; + + if (!v) + { + error_at_line (line, "`%s' is too complex to be a root", name); + return false; + } + + oprintf (f, " {\n"); + oprintf (f, " &%s,\n", name); + oprintf (f, " 1"); + + for (ap = v->type; ap->kind == TYPE_ARRAY; ap = ap->u.a.p) + if (ap->u.a.len[0]) + oprintf (f, " * (%s)", ap->u.a.len); + else if (ap == v->type) + oprintf (f, " * ARRAY_SIZE (%s)", v->name); + oprintf (f, ",\n"); + oprintf (f, " sizeof (%s", v->name); + for (ap = v->type; ap->kind == TYPE_ARRAY; ap = ap->u.a.p) + oprintf (f, "[0]"); + oprintf (f, "),\n"); + return true; +} + +/* A subroutine of write_root for writing the roots for field FIELD_NAME, + which has type FIELD_TYPE. Parameters F to EMIT_PCH are the parameters + of the caller. */ + +static void +write_field_root (outf_p f, pair_p v, type_p type, const char *name, + int has_length, struct fileloc *line, const char *if_marked, + bool emit_pch, type_p field_type, const char *field_name) +{ + /* If the field reference is relative to V, rather than to some + subcomponent of V, we can mark any subarrays with a single stride. + We're effectively treating the field as a global variable in its + own right. */ + if (v && type == v->type) + { + struct pair newv; + + newv = *v; + newv.type = field_type; + newv.name = ACONCAT ((v->name, ".", field_name, NULL)); + v = &newv; + } + /* Otherwise, any arrays nested in the structure are too complex to + handle. */ + else if (field_type->kind == TYPE_ARRAY) + v = NULL; + write_root (f, v, field_type, ACONCAT ((name, ".", field_name, NULL)), + has_length, line, if_marked, emit_pch); +} + /* Write out to F the table entry and any marker routines needed to - mark NAME as TYPE. The original variable is V, at LINE. + mark NAME as TYPE. V can be one of three values: + + - null, if NAME is too complex to represent using a single + count and stride. In this case, it is an error for NAME to + contain any gc-ed data. + + - the outermost array that contains NAME, if NAME is part of an array. + + - the C variable that contains NAME, if NAME is not part of an array. + + LINE is the line of the C source that declares the root variable. HAS_LENGTH is nonzero iff V was a variable-length array. IF_MARKED is nonzero iff we are building the root table for hash table caches. */ @@ -3232,27 +3305,18 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, validf = ufld; } if (validf != NULL) - { - char *newname; - newname = xasprintf ("%s.%s.%s", - name, fld->name, validf->name); - write_root (f, v, validf->type, newname, 0, line, - if_marked, emit_pch); - free (newname); - } + write_field_root (f, v, type, name, 0, line, if_marked, + emit_pch, validf->type, + ACONCAT ((fld->name, ".", + validf->name, NULL))); } else if (desc) error_at_line (line, "global `%s.%s' has `desc' option but is not union", name, fld->name); else - { - char *newname; - newname = xasprintf ("%s.%s", name, fld->name); - write_root (f, v, fld->type, newname, 0, line, if_marked, - emit_pch); - free (newname); - } + write_field_root (f, v, type, name, 0, line, if_marked, + emit_pch, fld->type, fld->name); } } break; @@ -3269,22 +3333,10 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, case TYPE_POINTER: { - type_p ap, tp; - - oprintf (f, " {\n"); - oprintf (f, " &%s,\n", name); - oprintf (f, " 1"); - - for (ap = v->type; ap->kind == TYPE_ARRAY; ap = ap->u.a.p) - if (ap->u.a.len[0]) - oprintf (f, " * (%s)", ap->u.a.len); - else if (ap == v->type) - oprintf (f, " * ARRAY_SIZE (%s)", v->name); - oprintf (f, ",\n"); - oprintf (f, " sizeof (%s", v->name); - for (ap = v->type; ap->kind == TYPE_ARRAY; ap = ap->u.a.p) - oprintf (f, "[0]"); - oprintf (f, "),\n"); + type_p tp; + + if (!start_root_entry (f, v, name, line)) + return; tp = type->u.p; @@ -3331,10 +3383,9 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, case TYPE_STRING: { - oprintf (f, " {\n"); - oprintf (f, " &%s,\n", name); - oprintf (f, " 1, \n"); - oprintf (f, " sizeof (%s),\n", v->name); + if (!start_root_entry (f, v, name, line)) + return; + oprintf (f, " (gt_pointer_walker) >_ggc_m_S,\n"); oprintf (f, " (gt_pointer_walker) >_pch_n_S\n"); oprintf (f, " },\n"); |