From 412dc29d628f7b523790a34042a3c55e77ed1f9f Mon Sep 17 00:00:00 2001 From: Basile Starynkevitch Date: Tue, 23 Nov 2010 15:13:12 +0000 Subject: [PATCH] gengtype.c (enum typekind, [...]): Move to gengtype.h. 2010-11-23 Basile Starynkevitch Jeremie Salvucci * gengtype.c (enum typekind, struct options) (struct nested_ptr_data, struct pair, NUM_PARAM) (enum gc_used_num, struct type, UNION_P, UNION_OR_STRUCT_P): Move to gengtype.h. (string_type, scalar_nonchar, scalar_nonchar, scalar_char): Remove static, add zero state_number. (typedefs, structures, param_structs, variables): Remove static. (create_option): Remove. (create_string_option, create_type_option, create_nested_option): New functions. (create_nested_ptr_option): Use create_nested_option. (note_variable, adjust_field_rtx_def, adjust_field_type): Call the new create*option functions. (process_gc_options): Adjust for discriminated option. (output_mangled_typename): Handle TYPE_NONE. (walk_type): Test option kinds. (write_types_process_field): Handle TYPE_NONE and TYPE_ARRAY. (write_func_for_structure, write_type, write_local, write_root) (write_roots, note_def_vec, dump_options): Adjust for discriminated option. * gengtype.h (typedefs, structures, param_structs, variables, enum typekind): Move from gengtype.c (enum option_kind): New discriminating enumeration. (struct options): Becomes discriminated. (struct nested_ptr_data): Nove from gengtype.c (create_string_option, create_type_option, create_nested_option) (create_nested_ptr_option): New functions (struct pair, enum_gc_used_enum, NUM_PARAM, struct type, UNION_P) (UNION_OR_STRUCT_P): Move from gengtype.c * gengtype-parse.c (str_optvalue_opt, type_optvalue, option): Make discriminated options. Co-Authored-By: Jeremie Salvucci From-SVN: r167080 --- gcc/ChangeLog | 38 +++++ gcc/gengtype-parse.c | 6 +- gcc/gengtype.c | 392 ++++++++++++++++++++----------------------- gcc/gengtype.h | 217 +++++++++++++++++++++++- 4 files changed, 431 insertions(+), 222 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 60c4dc92de3..09053c37400 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,41 @@ +2010-11-23 Basile Starynkevitch + Jeremie Salvucci + + * gengtype.c (enum typekind, struct options) + (struct nested_ptr_data, struct pair, NUM_PARAM) + (enum gc_used_num, struct type, UNION_P, UNION_OR_STRUCT_P): + Move to gengtype.h. + (string_type, scalar_nonchar, scalar_nonchar, scalar_char): + Remove static, add zero state_number. + (typedefs, structures, param_structs, variables): Remove static. + (create_option): Remove. + (create_string_option, create_type_option, create_nested_option): + New functions. + (create_nested_ptr_option): Use create_nested_option. + (note_variable, adjust_field_rtx_def, adjust_field_type): Call the + new create*option functions. + (process_gc_options): Adjust for discriminated option. + (output_mangled_typename): Handle TYPE_NONE. + (walk_type): Test option kinds. + (write_types_process_field): Handle TYPE_NONE and TYPE_ARRAY. + (write_func_for_structure, write_type, write_local, write_root) + (write_roots, note_def_vec, dump_options): Adjust for + discriminated option. + + * gengtype.h + (typedefs, structures, param_structs, variables, enum typekind): + Move from gengtype.c + (enum option_kind): New discriminating enumeration. + (struct options): Becomes discriminated. + (struct nested_ptr_data): Nove from gengtype.c + (create_string_option, create_type_option, create_nested_option) + (create_nested_ptr_option): New functions + (struct pair, enum_gc_used_enum, NUM_PARAM, struct type, UNION_P) + (UNION_OR_STRUCT_P): Move from gengtype.c + + * gengtype-parse.c (str_optvalue_opt, type_optvalue, option): Make + discriminated options. + 2010-11-23 Richard Guenther * tree-ssa-sccvn.c (vn_reference_lookup_3): Avoid doing work diff --git a/gcc/gengtype-parse.c b/gcc/gengtype-parse.c index 476a9fd203c..8f0b0c53233 100644 --- a/gcc/gengtype-parse.c +++ b/gcc/gengtype-parse.c @@ -372,7 +372,7 @@ str_optvalue_opt (options_p prev) value = string_seq (); require (')'); } - return create_option (prev, name, value); + return create_string_option (prev, name, value); } /* absdecl: type '*'* @@ -410,7 +410,7 @@ type_optvalue (options_p prev, const char *name) require ('('); ty = absdecl (); require (')'); - return create_option (prev, name, ty); + return create_type_option (prev, name, ty); } /* Nested pointer data: '(' type '*'* ',' string_seq ',' string_seq ')' */ @@ -459,7 +459,7 @@ option (options_p prev) default: parse_error ("expected an option keyword, have %s", print_cur_token ()); advance (); - return create_option (prev, "", ""); + return create_string_option (prev, "", ""); } } diff --git a/gcc/gengtype.c b/gcc/gengtype.c index 7f7feb0d987..8d13d0eb1d1 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -31,106 +31,6 @@ /* Data types, macros, etc. used only in this file. */ -/* Kinds of types we can understand. */ -enum typekind -{ - TYPE_SCALAR, - TYPE_STRING, - TYPE_STRUCT, - TYPE_UNION, - TYPE_POINTER, - TYPE_ARRAY, - TYPE_LANG_STRUCT, - TYPE_PARAM_STRUCT -}; - - -/* A way to pass data through to the output end. */ -struct options -{ - struct options *next; - const char *name; - const char *info; -}; - -/* Option data for the 'nested_ptr' option. */ -struct nested_ptr_data -{ - type_p type; - const char *convert_to; - const char *convert_from; -}; - -/* A name and a type. */ -struct pair -{ - pair_p next; - const char *name; - type_p type; - struct fileloc line; - options_p opt; -}; - -#define NUM_PARAM 10 - -/* A description of a type. */ -enum gc_used_enum -{ - GC_UNUSED = 0, - GC_USED, - /* Used for structures whose definitions we haven't seen so far when - we encounter a pointer to it that is annotated with ``maybe_undef''. - If after reading in everything we don't have source file - information for it, we assume that it never has been defined. */ - GC_MAYBE_POINTED_TO, - GC_POINTED_TO -}; - -struct type -{ - enum typekind kind; - type_p next; - type_p pointer_to; - enum gc_used_enum gc_used; - union - { - type_p p; - struct - { - const char *tag; - struct fileloc line; - pair_p fields; - options_p opt; - lang_bitmap bitmap; - type_p lang_struct; - } s; - bool scalar_is_char; - struct - { - type_p p; - const char *len; - } a; - struct - { - type_p stru; - type_p param[NUM_PARAM]; - struct fileloc line; - } param_struct; - } u; -}; - -#define UNION_P(x) \ - ((x)->kind == TYPE_UNION || \ - ((x)->kind == TYPE_LANG_STRUCT \ - && (x)->u.s.lang_struct->kind == TYPE_UNION)) -#define UNION_OR_STRUCT_P(x) \ - ((x)->kind == TYPE_UNION \ - || (x)->kind == TYPE_STRUCT \ - || (x)->kind == TYPE_LANG_STRUCT) - - - - /* The list of output files. */ outf_p output_files; @@ -554,27 +454,27 @@ read_input_list (const char *listname) /* The one and only TYPE_STRING. */ -static struct type string_type = { - TYPE_STRING, 0, 0, GC_USED, {0} +struct type string_type = { + TYPE_STRING, 0, 0, 0, GC_USED, {0} }; /* The two and only TYPE_SCALARs. Their u.scalar_is_char flags are - set to appropriate values at the beginning of main. */ + set early in main. */ -static struct type scalar_nonchar = { - TYPE_SCALAR, 0, 0, GC_USED, {0} +struct type scalar_nonchar = { + TYPE_SCALAR, 0, 0, 0, GC_USED, {0} }; -static struct type scalar_char = { - TYPE_SCALAR, 0, 0, GC_USED, {0} +struct type scalar_char = { + TYPE_SCALAR, 0, 0, 0, GC_USED, {0} }; /* Lists of various things. */ -static pair_p typedefs; -static type_p structures; -static type_p param_structs; -static pair_p variables; +pair_p typedefs; +type_p structures; +type_p param_structs; +pair_p variables; static type_p find_param_structure (type_p t, type_p param[NUM_PARAM]); static type_p adjust_field_tree_exp (type_p t, options_p opt); @@ -800,16 +700,44 @@ create_array (type_p t, const char *len) return v; } -/* Return an options structure with name NAME and info INFO. NEXT is the - next option in the chain. */ - +/* Return a string options structure with name NAME and info INFO. + NEXT is the next option in the chain. */ options_p -create_option (options_p next, const char *name, const void *info) +create_string_option (options_p next, const char *name, const char *info) +{ + options_p o = XNEW (struct options); + o->kind = OPTION_STRING; + o->next = next; + o->name = name; + o->info.string = info; + return o; +} + +/* Create a type options structure with name NAME and info INFO. NEXT + is the next option in the chain. */ +options_p +create_type_option (options_p next, const char* name, type_p info) { options_p o = XNEW (struct options); o->next = next; o->name = name; - o->info = (const char *) info; + o->kind = OPTION_TYPE; + o->info.type = info; + return o; +} + +/* Create a nested pointer options structure with name NAME and info + INFO. NEXT is the next option in the chain. */ +options_p +create_nested_option (options_p next, const char* name, + struct nested_ptr_data* info) +{ + options_p o; + o = XNEW (struct options); + o->next = next; + o->name = name; + o->kind = OPTION_NESTED; + o->info.nested = info; return o; } @@ -823,12 +751,11 @@ create_nested_ptr_option (options_p next, type_p t, d->type = adjust_field_type (t, 0); d->convert_to = to; d->convert_from = from; - return create_option (next, "nested_ptr", d); + return create_nested_option (next, "nested_ptr", d); } /* Add a variable named S of type T with options O defined at POS, to `variables'. */ - void note_variable (const char *s, type_p t, options_p o, struct fileloc *pos) { @@ -890,15 +817,19 @@ create_optional_field_ (pair_p next, type_p type, const char *name, The field has a tag of "1". This allows us to make the presence of a field of type TYPE depend on some boolean "desc" being true. */ union_fields = create_field (NULL, type, ""); - union_fields->opt = create_option (union_fields->opt, "dot", ""); - union_fields->opt = create_option (union_fields->opt, "tag", "1"); - union_type = new_structure (xasprintf ("%s_%d", "fake_union", id++), 1, - &lexer_line, union_fields, NULL); + union_fields->opt = + create_string_option (union_fields->opt, "dot", ""); + union_fields->opt = + create_string_option (union_fields->opt, "tag", "1"); + union_type = + new_structure (xasprintf ("%s_%d", "fake_union", id++), 1, + &lexer_line, union_fields, NULL); /* Create the field and give it the new fake union type. Add a "desc" tag that specifies the condition under which the field is valid. */ return create_field_all (next, union_type, name, - create_option (0, "desc", cond), this_file, line); + create_string_option (0, "desc", cond), + this_file, line); } #define create_optional_field(next,type,name,cond) \ @@ -1031,14 +962,16 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) return &string_type; } - nodot = create_option (NULL, "dot", ""); + nodot = create_string_option (NULL, "dot", ""); rtx_tp = create_pointer (find_structure ("rtx_def", 0)); rtvec_tp = create_pointer (find_structure ("rtvec_def", 0)); tree_tp = create_pointer (find_structure ("tree_node", 1)); mem_attrs_tp = create_pointer (find_structure ("mem_attrs", 0)); - reg_attrs_tp = create_pointer (find_structure ("reg_attrs", 0)); - basic_block_tp = create_pointer (find_structure ("basic_block_def", 0)); + reg_attrs_tp = + create_pointer (find_structure ("reg_attrs", 0)); + basic_block_tp = + create_pointer (find_structure ("basic_block_def", 0)); constant_tp = create_pointer (find_structure ("constant_descriptor_rtx", 0)); scalar_tp = &scalar_nonchar; /* rtunion int */ @@ -1072,9 +1005,11 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) /* NOTE_INSN_MAX is used as the default field for line number notes. */ if (c == NOTE_INSN_MAX) - note_flds->opt = create_option (nodot, "default", ""); + note_flds->opt = + create_string_option (nodot, "default", ""); else - note_flds->opt = create_option (nodot, "tag", note_insn_name[c]); + note_flds->opt = + create_string_option (nodot, "tag", note_insn_name[c]); } note_union_tp = new_structure ("rtx_def_note_subunion", 1, &lexer_line, note_flds, NULL); @@ -1082,13 +1017,10 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) /* Create a type to represent the various forms of SYMBOL_REF_DATA. */ { pair_p sym_flds; - sym_flds = create_field (NULL, tree_tp, "rt_tree"); - sym_flds->opt = create_option (nodot, "default", ""); - + sym_flds->opt = create_string_option (nodot, "default", ""); sym_flds = create_field (sym_flds, constant_tp, "rt_constant"); - sym_flds->opt = create_option (nodot, "tag", "1"); - + sym_flds->opt = create_string_option (nodot, "tag", "1"); symbol_union_tp = new_structure ("rtx_def_symbol_subunion", 1, &lexer_line, sym_flds, NULL); } @@ -1152,9 +1084,10 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) t = scalar_tp, subname = "rt_int"; else { - error_at_line (&lexer_line, - "rtx type `%s' has `0' in position %lu, can't handle", - rtx_name[i], (unsigned long) aindex); + error_at_line + (&lexer_line, + "rtx type `%s' has `0' in position %lu, can't handle", + rtx_name[i], (unsigned long) aindex); t = &string_type; subname = "rt_int"; } @@ -1190,10 +1123,11 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) break; default: - error_at_line (&lexer_line, - "rtx type `%s' has `%c' in position %lu, can't handle", - rtx_name[i], rtx_format[i][aindex], - (unsigned long) aindex); + error_at_line + (&lexer_line, + "rtx type `%s' has `%c' in position %lu, can't handle", + rtx_name[i], rtx_format[i][aindex], + (unsigned long) aindex); t = &string_type; subname = "rt_int"; break; @@ -1205,16 +1139,19 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) subname)); subfields->opt = nodot; if (t == note_union_tp) - subfields->opt = create_option (subfields->opt, "desc", - "NOTE_KIND (&%0)"); + subfields->opt = + create_string_option (subfields->opt, "desc", + "NOTE_KIND (&%0)"); if (t == symbol_union_tp) - subfields->opt = create_option (subfields->opt, "desc", - "CONSTANT_POOL_ADDRESS_P (&%0)"); + subfields->opt = + create_string_option (subfields->opt, "desc", + "CONSTANT_POOL_ADDRESS_P (&%0)"); } if (i == SYMBOL_REF) { - /* Add the "block_sym" field if SYMBOL_REF_HAS_BLOCK_INFO_P holds. */ + /* Add the "block_sym" field if SYMBOL_REF_HAS_BLOCK_INFO_P + holds. */ type_p field_tp = find_structure ("block_symbol", 0); subfields = create_optional_field (subfields, field_tp, "block_sym", @@ -1227,11 +1164,9 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) ftag = xstrdup (rtx_name[i]); for (nmindex = 0; nmindex < strlen (ftag); nmindex++) ftag[nmindex] = TOUPPER (ftag[nmindex]); - flds = create_field (flds, substruct, ""); - flds->opt = create_option (nodot, "tag", ftag); + flds->opt = create_string_option (nodot, "tag", ftag); } - return new_structure ("rtx_def_subunion", 1, &lexer_line, flds, nodot); } @@ -1254,12 +1189,12 @@ adjust_field_tree_exp (type_p t, options_p opt ATTRIBUTE_UNUSED) return &string_type; } - nodot = create_option (NULL, "dot", ""); + nodot = create_string_option (NULL, "dot", ""); flds = create_field (NULL, t, ""); - flds->opt = create_option (nodot, "length", - "TREE_OPERAND_LENGTH ((tree) &%0)"); - flds->opt = create_option (flds->opt, "default", ""); + flds->opt = create_string_option (nodot, "length", + "TREE_OPERAND_LENGTH ((tree) &%0)"); + flds->opt = create_string_option (flds->opt, "default", ""); return new_structure ("tree_exp_subunion", 1, &lexer_line, flds, nodot); } @@ -1289,10 +1224,11 @@ adjust_field_type (type_p t, options_p opt) for (; opt; opt = opt->next) if (strcmp (opt->name, "length") == 0) length_p = 1; - else if (strcmp (opt->name, "param_is") == 0 - || (strncmp (opt->name, "param", 5) == 0 - && ISDIGIT (opt->name[5]) - && strcmp (opt->name + 6, "_is") == 0)) + else if ((strcmp (opt->name, "param_is") == 0 + || (strncmp (opt->name, "param", 5) == 0 + && ISDIGIT (opt->name[5]) + && strcmp (opt->name + 6, "_is") == 0)) + && opt->kind == OPTION_TYPE) { int num = ISDIGIT (opt->name[5]) ? opt->name[5] - '0' : 0; @@ -1309,14 +1245,14 @@ adjust_field_type (type_p t, options_p opt) if (params[num] != NULL) error_at_line (&lexer_line, "duplicate `%s' option", opt->name); if (!ISDIGIT (opt->name[5])) - params[num] = - create_pointer (CONST_CAST2 (type_p, const char *, opt->info)); + params[num] = create_pointer (opt->info.type); else - params[num] = CONST_CAST2 (type_p, const char *, opt->info); + params[num] = opt->info.type; } - else if (strcmp (opt->name, "special") == 0) + else if (strcmp (opt->name, "special") == 0 + && opt->kind == OPTION_STRING) { - const char *special_name = opt->info; + const char *special_name = opt->info.string; if (strcmp (special_name, "tree_exp") == 0) t = adjust_field_tree_exp (t, opt); else if (strcmp (special_name, "rtx_def") == 0) @@ -1359,8 +1295,9 @@ process_gc_options (options_p opt, enum gc_used_enum level, int *maybe_undef, { options_p o; for (o = opt; o; o = o->next) - if (strcmp (o->name, "ptr_alias") == 0 && level == GC_POINTED_TO) - set_gc_used_type (CONST_CAST2 (type_p, const char *, o->info), + if (strcmp (o->name, "ptr_alias") == 0 && level == GC_POINTED_TO + && o->kind == OPTION_TYPE) + set_gc_used_type (o->info.type, GC_POINTED_TO, NULL); else if (strcmp (o->name, "maybe_undef") == 0) *maybe_undef = 1; @@ -1370,12 +1307,13 @@ process_gc_options (options_p opt, enum gc_used_enum level, int *maybe_undef, *length = 1; else if (strcmp (o->name, "skip") == 0) *skip = 1; - else if (strcmp (o->name, "nested_ptr") == 0) - *nested_ptr = ((const struct nested_ptr_data *) o->info)->type; + else if (strcmp (o->name, "nested_ptr") == 0 + && o->kind == OPTION_NESTED) + *nested_ptr = ((const struct nested_ptr_data *) o->info.nested)->type; } -/* Set the gc_used field of T to LEVEL, and handle the types it references. */ +/* Set the gc_used field of T to LEVEL, and handle the types it references. */ static void set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM]) { @@ -2318,6 +2256,9 @@ output_mangled_typename (outf_p of, const_type_p t) else switch (t->kind) { + case TYPE_NONE: + gcc_unreachable (); + break; case TYPE_POINTER: oprintf (of, "P"); output_mangled_typename (of, t->u.p); @@ -2413,8 +2354,8 @@ walk_type (type_p t, struct walk_type_data *d) d->needs_cast_p = false; for (oo = d->opt; oo; oo = oo->next) - if (strcmp (oo->name, "length") == 0) - length = oo->info; + if (strcmp (oo->name, "length") == 0 && oo->kind == OPTION_STRING) + length = oo->info.string; else if (strcmp (oo->name, "maybe_undef") == 0) maybe_undef_p = 1; else if (strncmp (oo->name, "use_param", 9) == 0 @@ -2422,12 +2363,13 @@ walk_type (type_p t, struct walk_type_data *d) use_param_num = oo->name[9] == '\0' ? 0 : oo->name[9] - '0'; else if (strcmp (oo->name, "use_params") == 0) use_params_p = 1; - else if (strcmp (oo->name, "desc") == 0) - desc = oo->info; + else if (strcmp (oo->name, "desc") == 0 && oo->kind == OPTION_STRING) + desc = oo->info.string; else if (strcmp (oo->name, "mark_hook") == 0) ; - else if (strcmp (oo->name, "nested_ptr") == 0) - nested_ptr_d = (const struct nested_ptr_data *) oo->info; + else if (strcmp (oo->name, "nested_ptr") == 0 + && oo->kind == OPTION_NESTED) + nested_ptr_d = (const struct nested_ptr_data *) oo->info.nested; else if (strcmp (oo->name, "dot") == 0) ; else if (strcmp (oo->name, "tag") == 0) @@ -2675,8 +2617,9 @@ walk_type (type_p t, struct walk_type_data *d) /* Some things may also be defined in the structure's options. */ for (o = t->u.s.opt; o; o = o->next) - if (!desc && strcmp (o->name, "desc") == 0) - desc = o->info; + if (!desc && strcmp (o->name, "desc") == 0 + && o->kind == OPTION_STRING) + desc = o->info.string; d->prev_val[2] = oldval; d->prev_val[1] = oldprevval2; @@ -2707,16 +2650,19 @@ walk_type (type_p t, struct walk_type_data *d) d->reorder_fn = NULL; for (oo = f->opt; oo; oo = oo->next) - if (strcmp (oo->name, "dot") == 0) - dot = oo->info; - else if (strcmp (oo->name, "tag") == 0) - tagid = oo->info; + if (strcmp (oo->name, "dot") == 0 + && oo->kind == OPTION_STRING) + dot = oo->info.string; + else if (strcmp (oo->name, "tag") == 0 + && oo->kind == OPTION_STRING) + tagid = oo->info.string; else if (strcmp (oo->name, "skip") == 0) skip_p = 1; else if (strcmp (oo->name, "default") == 0) default_p = 1; - else if (strcmp (oo->name, "reorder") == 0) - d->reorder_fn = oo->info; + else if (strcmp (oo->name, "reorder") == 0 + && oo->kind == OPTION_STRING) + d->reorder_fn = oo->info.string; else if (strncmp (oo->name, "use_param", 9) == 0 && (oo->name[9] == '\0' || ISDIGIT (oo->name[9]))) use_param_p = 1; @@ -2830,6 +2776,8 @@ write_types_process_field (type_p f, const struct walk_type_data *d) switch (f->kind) { + case TYPE_NONE: + gcc_unreachable (); case TYPE_POINTER: oprintf (d->of, "%*s%s (%s%s", d->indent, "", wtd->subfield_marker_routine, cast, d->val); @@ -2882,7 +2830,7 @@ write_types_process_field (type_p f, const struct walk_type_data *d) case TYPE_SCALAR: break; - default: + case TYPE_ARRAY: gcc_unreachable (); } } @@ -2950,17 +2898,19 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param, memset (&d, 0, sizeof (d)); d.of = get_output_file_for_structure (s, param); - for (opt = s->u.s.opt; opt; opt = opt->next) - if (strcmp (opt->name, "chain_next") == 0) - chain_next = opt->info; - else if (strcmp (opt->name, "chain_prev") == 0) - chain_prev = opt->info; - else if (strcmp (opt->name, "chain_circular") == 0) - chain_circular = opt->info; - else if (strcmp (opt->name, "mark_hook") == 0) - mark_hook_name = opt->info; - + if (strcmp (opt->name, "chain_next") == 0 + && opt->kind == OPTION_STRING) + chain_next = opt->info.string; + else if (strcmp (opt->name, "chain_prev") == 0 + && opt->kind == OPTION_STRING) + chain_prev = opt->info.string; + else if (strcmp (opt->name, "chain_circular") == 0 + && opt->kind == OPTION_STRING) + chain_circular = opt->info.string; + else if (strcmp (opt->name, "mark_hook") == 0 + && opt->kind == OPTION_STRING) + mark_hook_name = opt->info.string; if (chain_prev != NULL && chain_next == NULL) error_at_line (&s->u.s.line, "chain_prev without chain_next"); if (chain_circular != NULL && chain_next != NULL) @@ -3127,9 +3077,10 @@ write_types (outf_p output_header, type_p structures, type_p param_structs, oprintf (output_header, " } while (0)\n"); for (opt = s->u.s.opt; opt; opt = opt->next) - if (strcmp (opt->name, "ptr_alias") == 0) + if (strcmp (opt->name, "ptr_alias") == 0 + && opt->kind == OPTION_TYPE) { - const_type_p const t = (const_type_p) opt->info; + const_type_p const t = (const_type_p) opt->info.type; if (t->kind == TYPE_STRUCT || t->kind == TYPE_UNION || t->kind == TYPE_LANG_STRUCT) oprintf (output_header, @@ -3352,11 +3303,11 @@ write_local (outf_p output_header, type_p structures, type_p param_structs) if (s->u.s.line.file == NULL) continue; - - for (opt = s->u.s.opt; opt; opt = opt->next) - if (strcmp (opt->name, "ptr_alias") == 0) + for (opt = s->u.s.opt; opt; opt = opt->next) + if (strcmp (opt->name, "ptr_alias") == 0 + && opt->kind == OPTION_TYPE) { - const_type_p const t = (const_type_p) opt->info; + const_type_p const t = (const_type_p) opt->info.type; if (t->kind == TYPE_STRUCT || t->kind == TYPE_UNION || t->kind == TYPE_LANG_STRUCT) { @@ -3679,8 +3630,9 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, for (o = fld->opt; o; o = o->next) if (strcmp (o->name, "skip") == 0) skip_p = 1; - else if (strcmp (o->name, "desc") == 0) - desc = o->info; + else if (strcmp (o->name, "desc") == 0 + && o->kind == OPTION_STRING) + desc = o->info.string; else if (strcmp (o->name, "param_is") == 0) ; else @@ -3699,10 +3651,10 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, { const char *tag = NULL; options_p oo; - - for (oo = ufld->opt; oo; oo = oo->next) - if (strcmp (oo->name, "tag") == 0) - tag = oo->info; + for (oo = ufld->opt; oo; oo = oo->next) + if (strcmp (oo->name, "tag") == 0 + && oo->kind == OPTION_STRING) + tag = oo->info.string; if (tag == NULL || strcmp (tag, desc) != 0) continue; if (validf != NULL) @@ -3873,10 +3825,10 @@ write_roots (pair_p variables, bool emit_pch) const char *length = NULL; int deletable_p = 0; options_p o; - for (o = v->opt; o; o = o->next) - if (strcmp (o->name, "length") == 0) - length = o->info; + if (strcmp (o->name, "length") == 0 + && o->kind == OPTION_STRING) + length = o->info.string; else if (strcmp (o->name, "deletable") == 0) deletable_p = 1; else if (strcmp (o->name, "param_is") == 0) @@ -4003,12 +3955,11 @@ write_roots (pair_p variables, bool emit_pch) for (o = v->opt; o; o = o->next) if (strcmp (o->name, "length") == 0) length_p = 1; - else if (strcmp (o->name, "if_marked") == 0) - if_marked = o->info; - - if (if_marked == NULL) + else if (strcmp (o->name, "if_marked") == 0 + && o->kind == OPTION_STRING) + if_marked = o->info.string; + if (if_marked == NULL) continue; - if (v->type->kind != TYPE_POINTER || v->type->u.p->kind != TYPE_PARAM_STRUCT || v->type->u.p->u.param_struct.stru != find_structure ("htab", 0)) @@ -4143,9 +4094,8 @@ note_def_vec (const char *type_name, bool is_scalar, struct fileloc *pos) else { t = resolve_typedef (type_name, pos); - o = create_option (0, "length", "%h.num"); + o = create_string_option (0, "length", "%h.num"); } - /* We assemble the field list in reverse order. */ fields = create_field_at (0, create_array (t, "1"), "vec", o, pos); fields = create_field_at (fields, len_ty, "alloc", 0, pos); @@ -4463,7 +4413,21 @@ dump_options (int indent, options_p opt) o = opt; while (o) { - printf ("%s:%s ", o->name, o->info); + switch (o->kind) + { + case OPTION_STRING: + printf ("%s:string %s ", o->name, o->info.string); + break; + case OPTION_TYPE: + printf ("%s:type ", o->name); + dump_type (indent+1, o->info.type); + break; + case OPTION_NESTED: + printf ("%s:nested ", o->name); + break; + case OPTION_NONE: + gcc_unreachable (); + } o = o->next; } printf ("\n"); diff --git a/gcc/gengtype.h b/gcc/gengtype.h index 77f121e6c58..2046e40d6e9 100644 --- a/gcc/gengtype.h +++ b/gcc/gengtype.h @@ -116,6 +116,218 @@ typedef struct options *options_p; extern int lexer_toplevel_done; extern struct fileloc lexer_line; +/* Various things, organized as linked lists, needed both in + gengtype.c & in gengtype-state.c files. */ +extern pair_p typedefs; +extern type_p structures; +extern type_p param_structs; +extern pair_p variables; + + + +/* Discrimating kind of types we can understand. */ + +enum typekind { + TYPE_NONE=0, /* Never used, so zeroed memory is invalid. */ + TYPE_SCALAR, /* Scalar types like char. */ + TYPE_STRING, /* The string type. */ + TYPE_STRUCT, /* Type for GTY-ed structs. */ + TYPE_UNION, /* Type for GTY-ed discriminated unions. */ + TYPE_POINTER, /* Pointer type to GTY-ed type. */ + TYPE_ARRAY, /* Array of GTY-ed types. */ + TYPE_LANG_STRUCT, /* GCC front-end language specific structs. + Various languages may have homonymous but + different structs. */ + TYPE_PARAM_STRUCT /* Type for parametrized structs, e.g. hash_t + hash-tables, ... See (param_is, use_param, + param1_is, param2_is,... use_param1, + use_param_2,... use_params) GTY + options. */ +}; + +/* Discriminating kind for options. */ +enum option_kind { + OPTION_NONE=0, /* Never used, so zeroed memory is invalid. */ + OPTION_STRING, /* A string-valued option. Most options are + strings. */ + OPTION_TYPE, /* A type-valued option. */ + OPTION_NESTED /* Option data for 'nested_ptr'. */ +}; + + +/* A way to pass data through to the output end. */ +struct options { + struct options *next; /* next option of the same pair. */ + const char *name; /* GTY option name. */ + enum option_kind kind; /* discriminating option kind. */ + union { + const char* string; /* When OPTION_STRING. */ + type_p type; /* When OPTION_TYPE. */ + struct nested_ptr_data* nested; /* when OPTION_NESTED. */ + } info; +}; + + +/* Option data for the 'nested_ptr' option. */ +struct nested_ptr_data { + type_p type; + const char *convert_to; + const char *convert_from; +}; + +/* Some functions to create various options structures with name NAME + and info INFO. NEXT is the next option in the chain. */ + +/* Create a string option. */ +options_p create_string_option (options_p next, const char* name, + const char* info); + +/* Create a type option. */ +options_p create_type_option (options_p next, const char* name, + type_p info); + +/* Create a nested option. */ +options_p create_nested_option (options_p next, const char* name, + struct nested_ptr_data* info); + +/* Create a nested pointer option. */ +options_p create_nested_ptr_option (options_p, type_p t, + const char *from, const char *to); + +/* A name and a type. */ +struct pair { + pair_p next; /* The next pair in the linked list. */ + const char *name; /* The defined name. */ + type_p type; /* Its GTY-ed type. */ + struct fileloc line; /* The file location. */ + options_p opt; /* GTY options, as a linked list. */ +}; + +/* Usage information for GTY-ed types. Gengtype has to care only of + used GTY-ed types. Types are initially unused, and their usage is + computed by set_gc_used_type and set_gc_used functions. */ + +enum gc_used_enum { + + /* We need that zeroed types are initially unused. */ + GC_UNUSED=0, + + /* The GTY-ed type is used, e.g by a GTY-ed variable or a field + inside a GTY-ed used type. */ + GC_USED, + + /* For GTY-ed structures whose definitions we haven't seen so far + when we encounter a pointer to it that is annotated with + ``maybe_undef''. If after reading in everything we don't have + source file information for it, we assume that it never has been + defined. */ + GC_MAYBE_POINTED_TO, + + /* For known GTY-ed structures which are pointed to by GTY-ed + variables or fields. */ + GC_POINTED_TO +}; + +/* We can have at most ten type parameters in parameterized structures. */ +#define NUM_PARAM 10 + +/* Our type structure describes all types handled by gengtype. */ +struct type { + /* Discriminating kind, cannot be TYPE_NONE. */ + enum typekind kind; + + /* For top-level structs or unions, the 'next' field links the + global list 'structures' or 'param_structs'; for lang_structs, + their homonymous structs are linked using this 'next' field. The + homonymous list starts at the s.lang_struct field of the + lang_struct. See the new_structure function for details. This is + tricky! */ + type_p next; + + /* State number used when writing & reading the persistent state. A + type with a positive number has already been written. For ease + of debugging, newly allocated types have a unique negative + number. */ + int state_number; + + /* Each GTY-ed type which is pointed to by some GTY-ed type knows + the GTY pointer type pointing to it. See create_pointer + function. */ + type_p pointer_to; + + /* Type usage information, computed by set_gc_used_type and + set_gc_used functions. */ + enum gc_used_enum gc_used; + + /* The following union is discriminated by the 'kind' field above. */ + union { + /* TYPE__NONE is impossible. */ + + /* when TYPE_POINTER: */ + type_p p; + + /* when TYPE_STRUCT or TYPE_UNION or TYPE_LANG_STRUCT, we have an + aggregate type containing fields: */ + struct { + const char *tag; /* the aggragate tag, if any. */ + struct fileloc line; /* the source location. */ + pair_p fields; /* the linked list of fields. */ + options_p opt; /* the GTY options if any. */ + lang_bitmap bitmap; /* the set of front-end languages + using that GTY-ed aggregate. */ + /* For TYPE_LANG_STRUCT, the lang_struct field gives the first + element of a linked list of homonymous struct or union types. + Within this list, each homonymous type has as its lang_struct + field the original TYPE_LANG_STRUCT type. This is a dirty + trick, see the new_structure function for details. */ + type_p lang_struct; + } s; + + /* when TYPE_SCALAR: */ + bool scalar_is_char; + + /* when TYPE_ARRAY: */ + struct { + type_p p; /* The array component type. */ + const char *len; /* The string if any giving its length. */ + } a; + + /* When TYPE_PARAM_STRUCT for (param_is, use_param, param1_is, + param2_is, ... use_param1, use_param_2, ... use_params) GTY + options. */ + struct { + type_p stru; /* The generic GTY-ed type. */ + type_p param[NUM_PARAM]; /* The actual parameter types. */ + struct fileloc line; /* The source location. */ + } param_struct; + + } u; +}; + +/* The one and only TYPE_STRING. */ +extern struct type string_type; + +/* The two and only TYPE_SCALARs. Their u.scalar_is_char flags are + set early in main. */ +extern struct type scalar_nonchar; +extern struct type scalar_char; + +/* Test if a type is a union, either a plain one or a language + specific one. */ +#define UNION_P(x) \ + ((x)->kind == TYPE_UNION || \ + ((x)->kind == TYPE_LANG_STRUCT \ + && (x)->u.s.lang_struct->kind == TYPE_UNION)) + +/* Test if a type is a union or a structure, perhaps a language + specific one. */ +#define UNION_OR_STRUCT_P(x) \ + ((x)->kind == TYPE_UNION \ + || (x)->kind == TYPE_STRUCT \ + || (x)->kind == TYPE_LANG_STRUCT) + + + /* Structure representing an output file. */ struct outf { @@ -180,11 +392,6 @@ extern type_p find_structure (const char *s, int isunion); extern type_p create_scalar_type (const char *name); extern type_p create_pointer (type_p t); extern type_p create_array (type_p t, const char *len); -extern options_p create_option (options_p, const char *name, - const void *info); -extern options_p create_nested_ptr_option (options_p, type_p t, - const char *from, - const char *to); extern pair_p create_field_at (pair_p next, type_p type, const char *name, options_p opt, struct fileloc *pos);