Generic .opt support for enumerated option arguments
Richard Guenther
richard.guenther@gmail.com
Sat Nov 27 07:54:00 GMT 2010
On Fri, Nov 26, 2010 at 11:13 PM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> This patch adds generic .opt support for options whose arguments come
> from some enumerated set of strings. Such options may now be marked
> with Enum, and optionally Var to cause the generic option-processing
> machinery to set a gcc_options field directly for the option; this is
> accompanied by Enum and EnumValue entries to define the sets of option
> arguments.
>
> The opts.c options - apart from -fstack-check=, which is pending
> review of <http://gcc.gnu.org/ml/gcc-patches/2010-11/msg02483.html> -
> are converted to the new mechanism where they take such enumerated
> arguments. This means six options no longer need any special code
> there, and one option just needs to set a diagnostic context field in
> its code without first decoding strings.
>
> If an invalid option argument is passed to such an option, generic
> code will produce an error (some existing options used warnings, but I
> think always using errors is appropriate, just like for unknown
> options) and an informative note listing the valid arguments.
>
> The --help code can report current values of these options with -Q
> --help, and can also report the sets of possible values for such
> options. The latter isn't currently enabled for any option because
> the common options already have the list of possible values in the
> help text for the individual options. I have however tested it, and
> it will be useful for options such as -march= (where it will allow
> removing the TARGET_HELP hook once ARM has been converted to the new
> system; notice incidentally that TARGET_HELP only gets called for
> --target-help, not for --help=target which is supposed to mean the
> same thing or any other --help variant).
>
> Bootstrapped with no regressions on x86_64-unknown-linux-gnu. OK to
> commit?
Ok.
Thanks,
Richard.
> 2010-11-26 Joseph Myers <joseph@codesourcery.com>
>
> * doc/options.texi (Enum, EnumValue): Document new record types.
> (Enum): Document new option flag.
> * opt-functions.awk
> * optc-gen.awk: Handle enumerated option arguments.
> * opth-gen.awk: Handle enumerated option arguments.
> * opts-common.c (enum_arg_ok_for_language, enum_arg_to_value,
> enum_value_to_arg): New.
> (decode_cmdline_option): Handle enumerated arguments.
> (read_cmdline_option): Handle CL_ERR_ENUM_ARG.
> (set_option, option_enabled, get_option_state): Handle CLVC_ENUM.
> * opts.c (print_filtered_help, print_specific_help): Take
> lang_mask arguments.
> (print_filtered_help): Handle printing values of enumerated
> options. Print possible arguments for enumerated options.
> (print_specific_help): Update call to print_filtered_help.
> (common_handle_option): Update calls to print_specific_help. Use
> value rather than arg for OPT_fdiagnostics_show_location_. Don't
> handle OPT_ffp_contract_, OPT_fexcess_precision_,
> OPT_fvisibility_, OPT_ftls_model_, OPT_fira_algorithm_ or
> OPT_fira_region_ here.
> * opts.h (enum cl_var_type): Add CLVC_ENUM.
> (struct cl_option): Add var_enum.
> (CL_ENUM_CANONICAL, CL_ENUM_DRIVER_ONLY, struct cl_enum_arg,
> struct cl_enum, cl_enums, cl_enums_count): New.
> (CL_ERR_ENUM_ARG): Define.
> (CL_ERR_NEGATIVE): Update value.
> (enum_value_to_arg): Declare.
> * common.opt (flag_ira_algorithm, flag_ira_region,
> flag_fp_contract_mode, flag_excess_precision_cmdline,
> default_visibility, flag_tls_default): Remove Variable entries.
> (help_enum_printed): New Variable.
> (fdiagnostics-show-location=): Use Enum. Add associated
> SourceInclude, Enum and EnumValue entries.
> (fexcess-precision=, ffp-contract=, fira-algorithm=, fira-region=,
> ftls-model=, fvisibility=): Use Enum, Var and Init. Add
> associated Enum and EnumValue entries.
>
> po:
> 2010-11-26 Joseph Myers <joseph@codesourcery.com>
>
> * exgettext: Handle UnknownError.
>
> Index: gcc/doc/options.texi
> ===================================================================
> --- gcc/doc/options.texi (revision 167145)
> +++ gcc/doc/options.texi (working copy)
> @@ -78,6 +78,63 @@ two fields: the string @samp{SourceInclu
> include file.
>
> @item
> +An enumeration record to define a set of strings that may be used as
> +arguments to an option or options. These records have three fields:
> +the string @samp{Enum}, a space-separated list of properties and help
> +text used to describe the set of strings in @option{--help} output.
> +Properties use the same format as option properties; the following are
> +valid:
> +@table @code
> +@item Name(@var{name})
> +This property is required; @var{name} must be a name (suitable for use
> +in C identifiers) used to identify the set of strings in @code{Enum}
> +option properties.
> +
> +@item Type(@var{type})
> +This property is required; @var{type} is the C type for variables set
> +by options using this enumeration together with @code{Var}.
> +
> +@item UnknownError(@var{message})
> +The message @var{message} will be used as an error message if the
> +argument is invalid; for enumerations without @code{UnknownError}, a
> +generic error message is used. @var{message} should contain a single
> +@samp{%qs} format, which will be used to format the invalid argument.
> +@end table
> +
> +@item
> +An enumeration value record to define one of the strings in a set
> +given in an @samp{Enum} record. These records have two fields: the
> +string @samp{EnumValue} and a space-separated list of properties.
> +Properties use the same format as option properties; the following are
> +valid:
> +@table @code
> +@item Enum(@var{name})
> +This property is required; @var{name} says which @samp{Enum} record
> +this @samp{EnumValue} record corresponds to.
> +
> +@item String(@var{string})
> +This property is required; @var{string} is the string option argument
> +being described by this record.
> +
> +@item Value(@var{value})
> +This property is required; it says what value (representable as
> +@code{int}) should be used for the given string.
> +
> +@item Canonical
> +This property is optional. If present, it says the present string is
> +the canonical one among all those with the given value. Other strings
> +yielding that value will be mapped to this one so specs do not need to
> +handle them.
> +
> +@item DriverOnly
> +This property is optional. If present, the present string will only
> +be accepted by the driver. This is used for cases such as
> +@option{-march=native} that are processed by the driver so that
> +@samp{gcc -v} shows how the options chosen depended on the system on
> +which the compiler was run.
> +@end table
> +
> +@item
> An option definition record. These records have the following fields:
> @enumerate
> @item
> @@ -227,6 +284,13 @@ If the option takes an argument and has
> @var{var} is an integer variable that stores the value of the argument.
>
> @item
> +If the option takes an argument and has the @code{Enum} property,
> +@var{var} is a variable (type given in the @code{Type} property of the
> +@samp{Enum} record whose @code{Name} property has the same argument as
> +the @code{Enum} property of this option) that stores the value of the
> +argument.
> +
> +@item
> If the option has the @code{Defer} property, @var{var} is a pointer to
> a @code{VEC(cl_deferred_option,heap)} that stores the option for later
> processing. (@var{var} is declared with type @code{void *} and needs
> @@ -287,6 +351,12 @@ The main purpose of this property is to
> The first option should use @samp{Mask(@var{name})} and the others
> should use @samp{Mask(@var{name}) MaskExists}.
>
> +@item Enum(@var{name})
> +The option's argument is a string from the set of strings associated
> +with the corresponding @samp{Enum} record. The string is checked and
> +converted to the integer specified in the corresponding
> +@samp{EnumValue} record before being passed to option handlers.
> +
> @item Defer
> The option should be stored in a vector, specified with @code{Var},
> for later processing.
> Index: gcc/opts-common.c
> ===================================================================
> --- gcc/opts-common.c (revision 167145)
> +++ gcc/opts-common.c (working copy)
> @@ -181,6 +181,70 @@ option_ok_for_language (const struct cl_
> return true;
> }
>
> +/* Return whether ENUM_ARG is OK for the language given by
> + LANG_MASK. */
> +
> +static bool
> +enum_arg_ok_for_language (const struct cl_enum_arg *enum_arg,
> + unsigned int lang_mask)
> +{
> + return (lang_mask & CL_DRIVER) || !(enum_arg->flags & CL_ENUM_DRIVER_ONLY);
> +}
> +
> +/* Look up ARG in ENUM_ARGS for language LANG_MASK, returning true and
> + storing the value in *VALUE if found, and returning false without
> + modifying *VALUE if not found. */
> +
> +static bool
> +enum_arg_to_value (const struct cl_enum_arg *enum_args,
> + const char *arg, int *value, unsigned int lang_mask)
> +{
> + unsigned int i;
> +
> + for (i = 0; enum_args[i].arg != NULL; i++)
> + if (strcmp (arg, enum_args[i].arg) == 0
> + && enum_arg_ok_for_language (&enum_args[i], lang_mask))
> + {
> + *value = enum_args[i].value;
> + return true;
> + }
> +
> + return false;
> +}
> +
> +/* Look of VALUE in ENUM_ARGS for language LANG_MASK and store the
> + corresponding string in *ARGP, returning true if the found string
> + was marked as canonical, false otherwise. If VALUE is not found
> + (which may be the case for uninitialized values if the relevant
> + option has not been passed), set *ARGP to NULL and return
> + false. */
> +
> +bool
> +enum_value_to_arg (const struct cl_enum_arg *enum_args,
> + const char **argp, int value, unsigned int lang_mask)
> +{
> + unsigned int i;
> +
> + for (i = 0; enum_args[i].arg != NULL; i++)
> + if (enum_args[i].value == value
> + && (enum_args[i].flags & CL_ENUM_CANONICAL)
> + && enum_arg_ok_for_language (&enum_args[i], lang_mask))
> + {
> + *argp = enum_args[i].arg;
> + return true;
> + }
> +
> + for (i = 0; enum_args[i].arg != NULL; i++)
> + if (enum_args[i].value == value
> + && enum_arg_ok_for_language (&enum_args[i], lang_mask))
> + {
> + *argp = enum_args[i].arg;
> + return false;
> + }
> +
> + *argp = NULL;
> + return false;
> +}
>
> /* Fill in the canonical option part of *DECODED with an option
> described by OPT_INDEX, ARG and VALUE. */
> @@ -508,6 +572,24 @@ decode_cmdline_option (const char **argv
> errors |= CL_ERR_UINT_ARG;
> }
>
> + /* If the switch takes an enumerated argument, convert it. */
> + if (arg && (option->var_type == CLVC_ENUM))
> + {
> + const struct cl_enum *e = &cl_enums[option->var_enum];
> +
> + gcc_assert (value == 1);
> + if (enum_arg_to_value (e->values, arg, &value, lang_mask))
> + {
> + const char *carg = NULL;
> +
> + if (enum_value_to_arg (e->values, &carg, value, lang_mask))
> + arg = carg;
> + gcc_assert (carg != NULL);
> + }
> + else
> + errors |= CL_ERR_ENUM_ARG;
> + }
> +
> done:
> decoded->opt_index = opt_index;
> decoded->arg = arg;
> @@ -900,6 +982,36 @@ read_cmdline_option (struct gcc_options
> return;
> }
>
> + if (decoded->errors & CL_ERR_ENUM_ARG)
> + {
> + const struct cl_enum *e = &cl_enums[option->var_enum];
> + unsigned int i;
> + size_t len;
> + char *s, *p;
> +
> + if (e->unknown_error)
> + error_at (loc, e->unknown_error, decoded->arg);
> + else
> + error_at (loc, "unrecognized argument in option %qs", opt);
> +
> + len = 0;
> + for (i = 0; e->values[i].arg != NULL; i++)
> + len += strlen (e->values[i].arg) + 1;
> +
> + s = XALLOCAVEC (char, len);
> + p = s;
> + for (i = 0; e->values[i].arg != NULL; i++)
> + {
> + size_t arglen = strlen (e->values[i].arg);
> + memcpy (p, e->values[i].arg, arglen);
> + p[arglen] = ' ';
> + p += arglen + 1;
> + }
> + p[-1] = 0;
> + inform (loc, "valid arguments to %qs are: %s", option->opt_text, s);
> + return;
> + }
> +
> gcc_assert (!decoded->errors);
>
> if (!handle_option (opts, opts_set, decoded, lang_mask, DK_UNSPECIFIED,
> @@ -959,6 +1071,16 @@ set_option (struct gcc_options *opts, st
> *(const char **) set_flag_var = "";
> break;
>
> + case CLVC_ENUM:
> + {
> + const struct cl_enum *e = &cl_enums[option->var_enum];
> +
> + e->set (flag_var, value);
> + if (set_flag_var)
> + e->set (set_flag_var, 1);
> + }
> + break;
> +
> case CLVC_DEFER:
> {
> VEC(cl_deferred_option,heap) *vec
> @@ -1020,6 +1142,7 @@ option_enabled (int opt_idx, void *opts)
> return (*(int *) flag_var & option->var_value) != 0;
>
> case CLVC_STRING:
> + case CLVC_ENUM:
> case CLVC_DEFER:
> break;
> }
> @@ -1060,6 +1183,11 @@ get_option_state (struct gcc_options *op
> state->size = strlen ((const char *) state->data) + 1;
> break;
>
> + case CLVC_ENUM:
> + state->data = flag_var;
> + state->size = cl_enums[cl_options[option].var_enum].var_size;
> + break;
> +
> case CLVC_DEFER:
> return false;
> }
> Index: gcc/opts.c
> ===================================================================
> --- gcc/opts.c (revision 167145)
> +++ gcc/opts.c (working copy)
> @@ -885,7 +885,8 @@ print_filtered_help (unsigned int includ
> unsigned int exclude_flags,
> unsigned int any_flags,
> unsigned int columns,
> - struct gcc_options *opts)
> + struct gcc_options *opts,
> + unsigned int lang_mask)
> {
> unsigned int i;
> const char *help;
> @@ -918,6 +919,9 @@ print_filtered_help (unsigned int includ
> if (!opts->x_help_printed)
> opts->x_help_printed = XCNEWVAR (char, cl_options_count);
>
> + if (!opts->x_help_enum_printed)
> + opts->x_help_enum_printed = XCNEWVAR (char, cl_enums_count);
> +
> for (i = 0; i < cl_options_count; i++)
> {
> char new_help[128];
> @@ -999,6 +1003,20 @@ print_filtered_help (unsigned int includ
> sizeof (new_help) - strlen (new_help),
> * (const char **) flag_var);
> }
> + else if (option->var_type == CLVC_ENUM)
> + {
> + const struct cl_enum *e = &cl_enums[option->var_enum];
> + int value;
> + const char *arg = NULL;
> +
> + value = e->get (flag_var);
> + enum_value_to_arg (e->values, &arg, value, lang_mask);
> + if (arg == NULL)
> + arg = _("[default]");
> + snprintf (new_help + strlen (new_help),
> + sizeof (new_help) - strlen (new_help),
> + arg);
> + }
> else
> sprintf (new_help + strlen (new_help),
> "%#x", * (int *) flag_var);
> @@ -1013,6 +1031,10 @@ print_filtered_help (unsigned int includ
>
> wrap_help (help, opt, len, columns);
> displayed = true;
> +
> + if (option->var_type == CLVC_ENUM
> + && opts->x_help_enum_printed[option->var_enum] != 2)
> + opts->x_help_enum_printed[option->var_enum] = 1;
> }
>
> if (! found)
> @@ -1038,18 +1060,57 @@ print_filtered_help (unsigned int includ
> printf (_(" All options with the desired characteristics have already been displayed\n"));
>
> putchar ('\n');
> +
> + /* Print details of enumerated option arguments, if those
> + enumerations have help text headings provided. If no help text
> + is provided, presume that the possible values are listed in the
> + help text for the relevant options. */
> + for (i = 0; i < cl_enums_count; i++)
> + {
> + unsigned int j, pos;
> +
> + if (opts->x_help_enum_printed[i] != 1)
> + continue;
> + if (cl_enums[i].help == NULL)
> + continue;
> + printf (" %s\n ", _(cl_enums[i].help));
> + pos = 4;
> + for (j = 0; cl_enums[i].values[j].arg != NULL; j++)
> + {
> + unsigned int len = strlen (cl_enums[i].values[j].arg);
> +
> + if (pos > 4 && pos + 1 + len <= columns)
> + {
> + printf (" %s", cl_enums[i].values[j].arg);
> + pos += 1 + len;
> + }
> + else
> + {
> + if (pos > 4)
> + {
> + printf ("\n ");
> + pos = 4;
> + }
> + printf ("%s", cl_enums[i].values[j].arg);
> + pos += len;
> + }
> + }
> + printf ("\n\n");
> + opts->x_help_enum_printed[i] = 2;
> + }
> }
>
> /* Display help for a specified type of option.
> The options must have ALL of the INCLUDE_FLAGS set
> ANY of the flags in the ANY_FLAGS set
> and NONE of the EXCLUDE_FLAGS set. The current option state is in
> - OPTS. */
> + OPTS; LANG_MASK is used for interpreting enumerated option state. */
> static void
> print_specific_help (unsigned int include_flags,
> unsigned int exclude_flags,
> unsigned int any_flags,
> - struct gcc_options *opts)
> + struct gcc_options *opts,
> + unsigned int lang_mask)
> {
> unsigned int all_langs_mask = (1U << cl_lang_count) - 1;
> const char * description = NULL;
> @@ -1145,7 +1206,7 @@ print_specific_help (unsigned int includ
>
> printf ("%s%s:\n", description, descrip_extra);
> print_filtered_help (include_flags, exclude_flags, any_flags,
> - opts->x_help_columns, opts);
> + opts->x_help_columns, opts, lang_mask);
> }
>
> /* Handle target- and language-independent options. Return zero to
> @@ -1187,19 +1248,20 @@ common_handle_option (struct gcc_options
> /* First display any single language specific options. */
> for (i = 0; i < cl_lang_count; i++)
> print_specific_help
> - (1U << i, (all_langs_mask & (~ (1U << i))) | undoc_mask, 0, opts);
> + (1U << i, (all_langs_mask & (~ (1U << i))) | undoc_mask, 0, opts,
> + lang_mask);
> /* Next display any multi language specific options. */
> - print_specific_help (0, undoc_mask, all_langs_mask, opts);
> + print_specific_help (0, undoc_mask, all_langs_mask, opts, lang_mask);
> /* Then display any remaining, non-language options. */
> for (i = CL_MIN_OPTION_CLASS; i <= CL_MAX_OPTION_CLASS; i <<= 1)
> if (i != CL_DRIVER)
> - print_specific_help (i, undoc_mask, 0, opts);
> + print_specific_help (i, undoc_mask, 0, opts, lang_mask);
> opts->x_exit_after_options = true;
> break;
> }
>
> case OPT__target_help:
> - print_specific_help (CL_TARGET, CL_UNDOCUMENTED, 0, opts);
> + print_specific_help (CL_TARGET, CL_UNDOCUMENTED, 0, opts, lang_mask);
> opts->x_exit_after_options = true;
>
> /* Allow the target a chance to give the user some additional information. */
> @@ -1321,7 +1383,8 @@ common_handle_option (struct gcc_options
> }
>
> if (include_flags)
> - print_specific_help (include_flags, exclude_flags, 0, opts);
> + print_specific_help (include_flags, exclude_flags, 0, opts,
> + lang_mask);
> opts->x_exit_after_options = true;
> break;
> }
> @@ -1405,13 +1468,7 @@ common_handle_option (struct gcc_options
> break;
>
> case OPT_fdiagnostics_show_location_:
> - if (!strcmp (arg, "once"))
> - diagnostic_prefixing_rule (dc) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
> - else if (!strcmp (arg, "every-line"))
> - diagnostic_prefixing_rule (dc)
> - = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
> - else
> - return false;
> + diagnostic_prefixing_rule (dc) = (diagnostic_prefixing_rule_t) value;
> break;
>
> case OPT_fdiagnostics_show_option:
> @@ -1422,27 +1479,6 @@ common_handle_option (struct gcc_options
> /* Deferred. */
> break;
>
> - case OPT_ffp_contract_:
> - if (!strcmp (arg, "on"))
> - /* Not implemented, fall back to conservative FP_CONTRACT_OFF. */
> - opts->x_flag_fp_contract_mode = FP_CONTRACT_OFF;
> - else if (!strcmp (arg, "off"))
> - opts->x_flag_fp_contract_mode = FP_CONTRACT_OFF;
> - else if (!strcmp (arg, "fast"))
> - opts->x_flag_fp_contract_mode = FP_CONTRACT_FAST;
> - else
> - error_at (loc, "unknown floating point contraction style \"%s\"", arg);
> - break;
> -
> - case OPT_fexcess_precision_:
> - if (!strcmp (arg, "fast"))
> - opts->x_flag_excess_precision_cmdline = EXCESS_PRECISION_FAST;
> - else if (!strcmp (arg, "standard"))
> - opts->x_flag_excess_precision_cmdline = EXCESS_PRECISION_STANDARD;
> - else
> - error_at (loc, "unknown excess precision style \"%s\"", arg);
> - break;
> -
> case OPT_ffast_math:
> set_fast_math_flags (opts, value);
> break;
> @@ -1542,21 +1578,6 @@ common_handle_option (struct gcc_options
> dc->show_column = value;
> break;
>
> - case OPT_fvisibility_:
> - {
> - if (!strcmp(arg, "default"))
> - opts->x_default_visibility = VISIBILITY_DEFAULT;
> - else if (!strcmp(arg, "internal"))
> - opts->x_default_visibility = VISIBILITY_INTERNAL;
> - else if (!strcmp(arg, "hidden"))
> - opts->x_default_visibility = VISIBILITY_HIDDEN;
> - else if (!strcmp(arg, "protected"))
> - opts->x_default_visibility = VISIBILITY_PROTECTED;
> - else
> - error_at (loc, "unrecognized visibility value \"%s\"", arg);
> - }
> - break;
> -
> case OPT_frandom_seed:
> /* The real switch is -fno-random-seed. */
> if (value)
> @@ -1621,39 +1642,6 @@ common_handle_option (struct gcc_options
> vect_set_verbosity_level (opts, value);
> break;
>
> - case OPT_ftls_model_:
> - if (!strcmp (arg, "global-dynamic"))
> - opts->x_flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC;
> - else if (!strcmp (arg, "local-dynamic"))
> - opts->x_flag_tls_default = TLS_MODEL_LOCAL_DYNAMIC;
> - else if (!strcmp (arg, "initial-exec"))
> - opts->x_flag_tls_default = TLS_MODEL_INITIAL_EXEC;
> - else if (!strcmp (arg, "local-exec"))
> - opts->x_flag_tls_default = TLS_MODEL_LOCAL_EXEC;
> - else
> - warning_at (loc, 0, "unknown tls-model \"%s\"", arg);
> - break;
> -
> - case OPT_fira_algorithm_:
> - if (!strcmp (arg, "CB"))
> - opts->x_flag_ira_algorithm = IRA_ALGORITHM_CB;
> - else if (!strcmp (arg, "priority"))
> - opts->x_flag_ira_algorithm = IRA_ALGORITHM_PRIORITY;
> - else
> - warning_at (loc, 0, "unknown ira algorithm \"%s\"", arg);
> - break;
> -
> - case OPT_fira_region_:
> - if (!strcmp (arg, "one"))
> - opts->x_flag_ira_region = IRA_REGION_ONE;
> - else if (!strcmp (arg, "all"))
> - opts->x_flag_ira_region = IRA_REGION_ALL;
> - else if (!strcmp (arg, "mixed"))
> - opts->x_flag_ira_region = IRA_REGION_MIXED;
> - else
> - warning_at (loc, 0, "unknown ira region \"%s\"", arg);
> - break;
> -
> case OPT_g:
> set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg, opts, opts_set,
> loc);
> Index: gcc/opts.h
> ===================================================================
> --- gcc/opts.h (revision 167145)
> +++ gcc/opts.h (working copy)
> @@ -42,6 +42,10 @@ enum cl_var_type {
> argument. */
> CLVC_STRING,
>
> + /* The switch takes an enumerated argument (VAR_ENUM says what
> + enumeration) and FLAG_VAR points to that argument. */
> + CLVC_ENUM,
> +
> /* The switch should be stored in the VEC pointed to by FLAG_VAR for
> later processing. */
> CLVC_DEFER
> @@ -61,6 +65,7 @@ struct cl_option
> int neg_index;
> unsigned int flags;
> unsigned short flag_var_offset;
> + unsigned short var_enum;
> enum cl_var_type var_type;
> int var_value;
> };
> @@ -111,6 +116,52 @@ extern const unsigned int cl_lang_count;
> #define CL_UINTEGER (1 << 29) /* Argument is an integer >=0. */
> #define CL_UNDOCUMENTED (1 << 30) /* Do not output with --help. */
>
> +/* Flags for an enumerated option argument. */
> +#define CL_ENUM_CANONICAL (1 << 0) /* Canonical for this value. */
> +#define CL_ENUM_DRIVER_ONLY (1 << 1) /* Only accepted in the driver. */
> +
> +/* Structure describing an enumerated option argument. */
> +
> +struct cl_enum_arg
> +{
> + /* The argument text, or NULL at the end of the array. */
> + const char *arg;
> +
> + /* The corresponding integer value. */
> + int value;
> +
> + /* Flags associated with this argument. */
> + unsigned int flags;
> +};
> +
> +/* Structure describing an enumerated set of option arguments. */
> +
> +struct cl_enum
> +{
> + /* Help text, or NULL if the values should not be listed in --help
> + output. */
> + const char *help;
> +
> + /* Error message for unknown arguments, or NULL to use a generic
> + error. */
> + const char *unknown_error;
> +
> + /* Array of possible values. */
> + const struct cl_enum_arg *values;
> +
> + /* The size of the type used to store a value. */
> + size_t var_size;
> +
> + /* Function to set a variable of this type. */
> + void (*set) (void *var, int value);
> +
> + /* Function to get the value of a variable of this type. */
> + int (*get) (const void *var);
> +};
> +
> +extern const struct cl_enum cl_enums[];
> +extern const unsigned int cl_enums_count;
> +
> /* Possible ways in which a command-line option may be erroneous.
> These do not include not being known at all; an option index of
> OPT_SPECIAL_unknown is used for that. */
> @@ -119,7 +170,8 @@ extern const unsigned int cl_lang_count;
> #define CL_ERR_MISSING_ARG (1 << 1) /* Argument required but missing. */
> #define CL_ERR_WRONG_LANG (1 << 2) /* Option for wrong language. */
> #define CL_ERR_UINT_ARG (1 << 3) /* Bad unsigned integer argument. */
> -#define CL_ERR_NEGATIVE (1 << 4) /* Negative form of option
> +#define CL_ERR_ENUM_ARG (1 << 4) /* Bad enumerated argument. */
> +#define CL_ERR_NEGATIVE (1 << 5) /* Negative form of option
> not permitted (together
> with OPT_SPECIAL_unknown). */
>
> @@ -230,6 +282,9 @@ extern unsigned num_in_fnames;
>
> size_t find_opt (const char *input, int lang_mask);
> extern int integral_argument (const char *arg);
> +extern bool enum_value_to_arg (const struct cl_enum_arg *enum_args,
> + const char **argp, int value,
> + unsigned int lang_mask);
> extern void decode_cmdline_options_to_array (unsigned int argc,
> const char **argv,
> unsigned int lang_mask,
> Index: gcc/optc-gen.awk
> ===================================================================
> --- gcc/optc-gen.awk (revision 167145)
> +++ gcc/optc-gen.awk (working copy)
> @@ -34,6 +34,7 @@ BEGIN {
> n_extra_target_vars = 0
> n_extra_c_includes = 0
> n_extra_h_includes = 0
> + n_enums = 0
> quote = "\042"
> comma = ","
> FS=SUBSEP
> @@ -80,6 +81,31 @@ BEGIN {
> else if ($1 == "SourceInclude") {
> extra_c_includes[n_extra_c_includes++] = $2;
> }
> + else if ($1 == "Enum") {
> + props = $2
> + name = opt_args("Name", props)
> + type = opt_args("Type", props)
> + unknown_error = opt_args("UnknownError", props)
> + enum_names[n_enums] = name
> + enum_type[name] = type
> + enum_index[name] = n_enums
> + enum_unknown_error[name] = unknown_error
> + enum_help[name] = $3
> + n_enums++
> + }
> + else if ($1 == "EnumValue") {
> + props = $2
> + enum_name = opt_args("Enum", props)
> + string = opt_args("String", props)
> + value = opt_args("Value", props)
> + val_flags = "0"
> + val_flags = val_flags \
> + test_flag("Canonical", props, "| CL_ENUM_CANONICAL") \
> + test_flag("DriverOnly", props, "| CL_ENUM_DRIVER_ONLY")
> + enum_data[enum_name] = enum_data[enum_name] \
> + " { " quote string quote ", " value ", " val_flags \
> + " },\n"
> + }
> else {
> name = opt_args("Mask", $1)
> if (name == "") {
> @@ -116,6 +142,56 @@ if (n_extra_c_includes > 0) {
> print ""
> }
>
> +for (i = 0; i < n_enums; i++) {
> + name = enum_names[i]
> + type = enum_type[name]
> + print "static const struct cl_enum_arg cl_enum_" name \
> + "_data[] = "
> + print "{"
> + print enum_data[name] " { NULL, 0, 0 }"
> + print "};"
> + print ""
> + print "static void"
> + print "cl_enum_" name "_set (void *var, int value)"
> + print "{"
> + print " *((" type " *) var) = (" type ") value;"
> + print "}"
> + print ""
> + print "static int"
> + print "cl_enum_" name "_get (const void *var)"
> + print "{"
> + print " return (int) *((const " type " *) var);"
> + print "}"
> + print ""
> +}
> +
> +print "const struct cl_enum cl_enums[] ="
> +print "{"
> +for (i = 0; i < n_enums; i++) {
> + name = enum_names[i]
> + ehelp = enum_help[name]
> + if (ehelp == "")
> + ehelp = "NULL"
> + else
> + ehelp = quote ehelp quote
> + unknown_error = enum_unknown_error[name]
> + if (unknown_error == "")
> + unknown_error = "NULL"
> + else
> + unknown_error = quote unknown_error quote
> + print " {"
> + print " " ehelp ","
> + print " " unknown_error ","
> + print " cl_enum_" name "_data,"
> + print " sizeof (" enum_type[name] "),"
> + print " cl_enum_" name "_set,"
> + print " cl_enum_" name "_get"
> + print " },"
> +}
> +print "};"
> +print "const unsigned int cl_enums_count = " n_enums ";"
> +print ""
> +
> have_save = 0;
> if (n_extra_target_vars)
> have_save = 1
> Index: gcc/opth-gen.awk
> ===================================================================
> --- gcc/opth-gen.awk (revision 167145)
> +++ gcc/opth-gen.awk (working copy)
> @@ -77,6 +77,31 @@ BEGIN {
> else if ($1 == "SourceInclude") {
> extra_c_includes[n_extra_c_includes++] = $2;
> }
> + else if ($1 == "Enum") {
> + props = $2
> + name = opt_args("Name", props)
> + type = opt_args("Type", props)
> + unknown_error = opt_args("UnknownError", props)
> + enum_names[n_enums] = name
> + enum_type[name] = type
> + enum_index[name] = n_enums
> + enum_unknown_error[name] = unknown_error
> + enum_help[name] = $3
> + n_enums++
> + }
> + else if ($1 == "EnumValue") {
> + props = $2
> + enum_name = opt_args("Enum", props)
> + string = opt_args("String", props)
> + value = opt_args("Value", props)
> + val_flags = "0"
> + val_flags = val_flags \
> + test_flag("Canonical", props, "| CL_ENUM_CANONICAL") \
> + test_flag("DriverOnly", props, "| CL_ENUM_DRIVER_ONLY")
> + enum_data[enum_name] = enum_data[enum_name] \
> + " { " quote string quote ", " value ", " val_flags \
> + " },\n"
> + }
> else {
> name = opt_args("Mask", $1)
> if (name == "") {
> Index: gcc/po/exgettext
> ===================================================================
> --- gcc/po/exgettext (revision 167145)
> +++ gcc/po/exgettext (working copy)
> @@ -246,6 +246,17 @@ echo "scanning option files..." >&2
> printf("#line %d \"%s\"\n", lineno, file)
> printf("_(\"%s\")\n", line)
> }
> + if ((field == 1) && /UnknownError/) {
> + line = $0
> + sub(".*UnknownError\\(", "", line)
> + if (line ~ "^{") {
> + sub("^{", "", line)
> + sub("}\\).*", "", line)
> + } else
> + sub("\\).*", "", line)
> + printf("#line %d \"%s\"\n", lineno, file)
> + printf("_(\"%s\")\n", line)
> + }
> if ((field == 1) && /Warn\(/) {
> line = $0
> sub(".*Warn\\(", "", line)
> Index: gcc/common.opt
> ===================================================================
> --- gcc/common.opt (revision 167145)
> +++ gcc/common.opt (working copy)
> @@ -42,15 +42,6 @@ int flag_complex_method = 1
> Variable
> int flag_evaluation_order = 0
>
> -; Set the default region and algorithm for the integrated register
> -; allocator.
> -
> -Variable
> -enum ira_algorithm flag_ira_algorithm = IRA_ALGORITHM_CB
> -
> -Variable
> -enum ira_region flag_ira_region = IRA_REGION_MIXED
> -
> ; Language specific warning pass for unused results.
> Variable
> bool flag_warn_unused_result = false
> @@ -58,15 +49,6 @@ bool flag_warn_unused_result = false
> Variable
> int *param_values
>
> -; Floating-point contraction mode, fast by default.
> -Variable
> -enum fp_contract_mode flag_fp_contract_mode = FP_CONTRACT_FAST
> -
> -; The excess precision specified on the command line, or defaulted by
> -; the front end.
> -Variable
> -enum excess_precision flag_excess_precision_cmdline = EXCESS_PRECISION_DEFAULT
> -
> ; Nonzero if we should write GIMPLE bytecode for link-time optimization.
> Variable
> int flag_generate_lto
> @@ -97,14 +79,6 @@ int flag_gen_aux_info = 0
> Variable
> int flag_shlib
>
> -; The default visibility for all symbols (unless overridden).
> -Variable
> -enum symbol_visibility default_visibility = VISIBILITY_DEFAULT
> -
> -; Set to the default thread-local storage (tls) model to use.
> -Variable
> -enum tls_model flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC
> -
> ; These two are really VEC(char_p,heap) *.
>
> Variable
> @@ -187,6 +161,12 @@ enum graph_dump_types graph_dump_format
> Variable
> char *help_printed
>
> +; Which enums have been printed by --help. 0 = not printed, no
> +; relevant options seen, 1 = relevant option seen, not yet printed, 2
> +; = printed.
> +Variable
> +char *help_enum_printed
> +
> ; The number of columns for --help output.
> Variable
> unsigned int help_columns
> @@ -897,9 +877,22 @@ Common Report Var(flag_delete_null_point
> Delete useless null pointer checks
>
> fdiagnostics-show-location=
> -Common Joined RejectNegative
> +Common Joined RejectNegative Enum(diagnostic_prefixing_rule)
> -fdiagnostics-show-location=[once|every-line] How often to emit source location at the beginning of line-wrapped diagnostics
>
> +; Required for these enum values.
> +SourceInclude
> +pretty-print.h
> +
> +Enum
> +Name(diagnostic_prefixing_rule) Type(int)
> +
> +EnumValue
> +Enum(diagnostic_prefixing_rule) String(once) Value(DIAGNOSTICS_SHOW_PREFIX_ONCE)
> +
> +EnumValue
> +Enum(diagnostic_prefixing_rule) String(every-line) Value(DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE)
> +
> fdiagnostics-show-option
> Common Var(flag_diagnostics_show_option) Init(1)
> Amend appropriate diagnostic messages with the command line option that controls them
> @@ -972,9 +965,18 @@ Common Report Var(flag_expensive_optimiz
> Perform a number of minor, expensive optimizations
>
> fexcess-precision=
> -Common Joined RejectNegative
> +Common Joined RejectNegative Enum(excess_precision) Var(flag_excess_precision_cmdline) Init(EXCESS_PRECISION_DEFAULT)
> -fexcess-precision=[fast|standard] Specify handling of excess floating-point precision
>
> +Enum
> +Name(excess_precision) Type(enum excess_precision) UnknownError(unknown excess precision style %qs)
> +
> +EnumValue
> +Enum(excess_precision) String(fast) Value(EXCESS_PRECISION_FAST)
> +
> +EnumValue
> +Enum(excess_precision) String(standard) Value(EXCESS_PRECISION_STANDARD)
> +
> ffast-math
> Common
>
> @@ -999,9 +1001,22 @@ Common Report Var(flag_forward_propagate
> Perform a forward propagation pass on RTL
>
> ffp-contract=
> -Common Joined RejectNegative
> +Common Joined RejectNegative Enum(fp_contract_mode) Var(flag_fp_contract_mode) Init(FP_CONTRACT_FAST)
> -ffp-contract=[off|on|fast] Perform floating-point expression contraction.
>
> +Enum
> +Name(fp_contract_mode) Type(enum fp_contract_mode) UnknownError(unknown floating point contraction style %qs)
> +
> +EnumValue
> +Enum(fp_contract_mode) String(off) Value(FP_CONTRACT_OFF)
> +
> +; Not implemented, fall back to conservative FP_CONTRACT_OFF.
> +EnumValue
> +Enum(fp_contract_mode) String(on) Value(FP_CONTRACT_OFF)
> +
> +EnumValue
> +Enum(fp_contract_mode) String(fast) Value(FP_CONTRACT_FAST)
> +
> ; Nonzero means don't put addresses of constant functions in registers.
> ; Used for compiling the Unix kernel, where strange substitutions are
> ; done on the assembly output.
> @@ -1183,13 +1198,34 @@ Perform structure layout optimizations b
> on profiling information.
>
> fira-algorithm=
> -Common Joined RejectNegative
> +Common Joined RejectNegative Enum(ira_algorithm) Var(flag_ira_algorithm) Init(IRA_ALGORITHM_CB)
> -fira-algorithm=[CB|priority] Set the used IRA algorithm
>
> +Enum
> +Name(ira_algorithm) Type(enum ira_algorithm) UnknownError(unknown IRA algorithm %qs)
> +
> +EnumValue
> +Enum(ira_algorithm) String(CB) Value(IRA_ALGORITHM_CB)
> +
> +EnumValue
> +Enum(ira_algorithm) String(priority) Value(IRA_ALGORITHM_PRIORITY)
> +
> fira-region=
> -Common Joined RejectNegative
> +Common Joined RejectNegative Enum(ira_region) Var(flag_ira_region) Init(IRA_REGION_MIXED)
> -fira-region=[one|all|mixed] Set regions for IRA
>
> +Enum
> +Name(ira_region) Type(enum ira_region) UnknownError(unknown IRA region %qs)
> +
> +EnumValue
> +Enum(ira_region) String(one) Value(IRA_REGION_ONE)
> +
> +EnumValue
> +Enum(ira_region) String(all) Value(IRA_REGION_ALL)
> +
> +EnumValue
> +Enum(ira_region) String(mixed) Value(IRA_REGION_MIXED)
> +
> fira-loop-pressure
> Common Report Var(flag_ira_loop_pressure)
> Use IRA based register pressure calculation
> @@ -1718,9 +1754,24 @@ Common Report Var(time_report)
> Report the time taken by each compiler pass
>
> ftls-model=
> -Common Joined RejectNegative
> +Common Joined RejectNegative Enum(tls_model) Var(flag_tls_default) Init(TLS_MODEL_GLOBAL_DYNAMIC)
> -ftls-model=[global-dynamic|local-dynamic|initial-exec|local-exec] Set the default thread-local storage code generation model
>
> +Enum
> +Name(tls_model) Type(enum tls_model) UnknownError(unknown TLS model %qs)
> +
> +EnumValue
> +Enum(tls_model) String(global-dynamic) Value(TLS_MODEL_GLOBAL_DYNAMIC)
> +
> +EnumValue
> +Enum(tls_model) String(local-dynamic) Value(TLS_MODEL_LOCAL_DYNAMIC)
> +
> +EnumValue
> +Enum(tls_model) String(initial-exec) Value(TLS_MODEL_INITIAL_EXEC)
> +
> +EnumValue
> +Enum(tls_model) String(local-exec) Value(TLS_MODEL_LOCAL_EXEC)
> +
> ftoplevel-reorder
> Common Report Var(flag_toplevel_reorder) Init(2) Optimization
> Reorder top level functions, variables, and asms
> @@ -1973,9 +2024,23 @@ Common Report Var(flag_verbose_asm)
> Add extra commentary to assembler output
>
> fvisibility=
> -Common Joined RejectNegative
> +Common Joined RejectNegative Enum(symbol_visibility) Var(default_visibility) Init(VISIBILITY_DEFAULT)
> -fvisibility=[default|internal|hidden|protected] Set the default symbol visibility
>
> +Enum
> +Name(symbol_visibility) Type(enum symbol_visibility) UnknownError(unrecognized visibility value %qs)
> +
> +EnumValue
> +Enum(symbol_visibility) String(default) Value(VISIBILITY_DEFAULT)
> +
> +EnumValue
> +Enum(symbol_visibility) String(internal) Value(VISIBILITY_INTERNAL)
> +
> +EnumValue
> +Enum(symbol_visibility) String(hidden) Value(VISIBILITY_HIDDEN)
> +
> +EnumValue
> +Enum(symbol_visibility) String(protected) Value(VISIBILITY_PROTECTED)
>
> fvpt
> Common Report Var(flag_value_profile_transformations) Optimization
> Index: gcc/opt-functions.awk
> ===================================================================
> --- gcc/opt-functions.awk (revision 167145)
> +++ gcc/opt-functions.awk (working copy)
> @@ -150,6 +150,10 @@ function var_type(flags)
> {
> if (flag_set_p("Defer", flags))
> return "void *"
> + else if (flag_set_p("Enum.*", flags)) {
> + en = opt_args("Enum", flags);
> + return enum_type[en] " "
> + }
> else if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags))
> return "int "
> else if (flag_set_p("UInteger", flags))
> @@ -176,33 +180,37 @@ function var_type_struct(flags)
> }
>
> # Given that an option has flags FLAGS, return an initializer for the
> -# "var_cond" and "var_value" fields of its cl_options[] entry.
> +# "var_enum", "var_type" and "var_value" fields of its cl_options[] entry.
> function var_set(flags)
> {
> if (flag_set_p("Defer", flags))
> - return "CLVC_DEFER, 0"
> + return "0, CLVC_DEFER, 0"
> s = nth_arg(1, opt_args("Var", flags))
> if (s != "")
> - return "CLVC_EQUAL, " s
> + return "0, CLVC_EQUAL, " s
> s = opt_args("Mask", flags);
> if (s != "") {
> vn = var_name(flags);
> if (vn)
> - return "CLVC_BIT_SET, OPTION_MASK_" s
> + return "0, CLVC_BIT_SET, OPTION_MASK_" s
> else
> - return "CLVC_BIT_SET, MASK_" s
> + return "0, CLVC_BIT_SET, MASK_" s
> }
> s = nth_arg(0, opt_args("InverseMask", flags));
> if (s != "") {
> vn = var_name(flags);
> if (vn)
> - return "CLVC_BIT_CLEAR, OPTION_MASK_" s
> + return "0, CLVC_BIT_CLEAR, OPTION_MASK_" s
> else
> - return "CLVC_BIT_CLEAR, MASK_" s
> + return "0, CLVC_BIT_CLEAR, MASK_" s
> + }
> + if (flag_set_p("Enum.*", flags)) {
> + en = opt_args("Enum", flags);
> + return enum_index[en] ", CLVC_ENUM, 0"
> }
> if (var_type(flags) == "const char *")
> - return "CLVC_STRING, 0"
> - return "CLVC_BOOLEAN, 0"
> + return "0, CLVC_STRING, 0"
> + return "0, CLVC_BOOLEAN, 0"
> }
>
> # Given that an option called NAME has flags FLAGS, return an initializer
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>
More information about the Gcc-patches
mailing list