diff mbox

Convert some option flags to bit-fields

Message ID Pine.LNX.4.64.1103312237340.11804@digraph.polyomino.org.uk
State New
Headers show

Commit Message

Joseph Myers March 31, 2011, 10:37 p.m. UTC
As previously noted
<http://gcc.gnu.org/ml/gcc-patches/2010-11/msg00479.html>, we're
running out of option flag bits when you allow for languages not
present on trunk.  This patch alleviates that shortage by converting
most of the flag bits to separate bit-fields, so they no longer need
to be allocated bit numbers manually and so more space is available in
the flags field.

In the course of preparing this patch I found that CL_SAVE was not
used at all (the Save .opt flag has other effects, but the flags bit
it set was not used) so did not create a corresponding bit-field.
This means there was in fact one bit free (allowing for two
out-of-tree languages) - still rather short of bits considering
there's at least one front end on a branch (UPC) that could be hoping
for a merge for 4.7 (and I'd very much welcome merges of other
out-of-tree front ends such as D and Pascal, or others as long as the
languages have real users, if their maintainers are interested).  So
I'm going ahead with this patch even though I only expect to add one
more bit-field flag in the current stage of my options/multilibs work.

I think the flags field should really end up having only the bits used
in lang_mask (languages, CL_COMMON, CL_TARGET, CL_DRIVER), with all
the other bits becoming bit-fields.  The ones that didn't become
bit-fields were left as-is for now because their use in --help
processing would complicate making them into bit-fields, but with a
more complicated structure to describe what help should be printed
(than the present include_flags, exclude_flags, any_flags) it should
be possible to make them bit-fields as well.

Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  Applied
to mainline.

2011-03-31  Joseph Myers  <joseph@codesourcery.com>

	* opts.h (cl_option): Add comments to fields.  Add bit-fields for
	various flags.
	(CL_SEPARATE_NARGS_SHIFT, CL_SEPARATE_NARGS_MASK,
	CL_SEPARATE_ALIAS, CL_NO_DRIVER_ARG, CL_REJECT_DRIVER, CL_SAVE,
	CL_DISABLED, CL_REPOR, CL_REJECT_NEGATIVE, CL_MISSING_OK,
	CL_UINTEGER, CL_NEGATIVE_ALIAS): Remove.
	(CL_JOINED, CL_SEPARATE, CL_UNDOCUMENTED): Update bit positions.
	* opt-functions.awk (flag_init, switch_bit_fields): New.
	(switch_flags): Don't handle flags moved to bit-fields.  Don't
	generate CL_MISSING_OK or CL_SAVE.
	* optc-gen.awk: Update to generate bit-field output as well as
	flags field.
	* gcc.c (driver_wrong_lang_callback): Use cl_reject_driver
	bit-field instead of CL_REJECT_DRIVER flag.
	* opts-common.c (generate_canonical_option,
	decode_cmdline_option): Use bit-fields instead of CL_* flags.
	* opts.c (maybe_default_option): Use cl_reject_negative bit-field
	instead of CL_REJECT_NEGATIVE flag.
	* toplev.c (print_switch_values): Use cl_report bit-field instead
	of CL_REPORT flag.
diff mbox

Patch

Index: gcc/opts-common.c
===================================================================
--- gcc/opts-common.c	(revision 171779)
+++ gcc/opts-common.c	(working copy)
@@ -257,7 +257,7 @@  generate_canonical_option (size_t opt_in
   const char *opt_text = option->opt_text;
 
   if (value == 0
-      && !(option->flags & CL_REJECT_NEGATIVE)
+      && !option->cl_reject_negative
       && (opt_text[1] == 'W' || opt_text[1] == 'f' || opt_text[1] == 'm'))
     {
       char *t = XNEWVEC (char, option->opt_len + 5);
@@ -276,7 +276,7 @@  generate_canonical_option (size_t opt_in
   if (arg)
     {
       if ((option->flags & CL_SEPARATE)
-	  && !(option->flags & CL_SEPARATE_ALIAS))
+	  && !option->cl_separate_alias)
 	{
 	  decoded->canonical_option[0] = opt_text;
 	  decoded->canonical_option[1] = arg;
@@ -412,7 +412,7 @@  decode_cmdline_option (const char **argv
 
   /* Reject negative form of switches that don't take negatives as
      unrecognized.  */
-  if (!value && (option->flags & CL_REJECT_NEGATIVE))
+  if (!value && option->cl_reject_negative)
     {
       opt_index = OPT_SPECIAL_unknown;
       errors |= CL_ERR_NEGATIVE;
@@ -424,18 +424,17 @@  decode_cmdline_option (const char **argv
   warn_message = option->warn_message;
 
   /* Check to see if the option is disabled for this configuration.  */
-  if (option->flags & CL_DISABLED)
+  if (option->cl_disabled)
     errors |= CL_ERR_DISABLED;
 
   /* Determine whether there may be a separate argument based on
      whether this option is being processed for the driver, and, if
      so, how many such arguments.  */
   separate_arg_flag = ((option->flags & CL_SEPARATE)
-		       && !((option->flags & CL_NO_DRIVER_ARG)
+		       && !(option->cl_no_driver_arg
 			    && (lang_mask & CL_DRIVER)));
   separate_args = (separate_arg_flag
-		   ? ((option->flags & CL_SEPARATE_NARGS_MASK)
-		      >> CL_SEPARATE_NARGS_SHIFT) + 1
+		   ? option->cl_separate_nargs + 1
 		   : 0);
   joined_arg_flag = (option->flags & CL_JOINED) != 0;
 
@@ -447,7 +446,7 @@  decode_cmdline_option (const char **argv
 	 argument to be persistent until the program exits.  */
       arg = argv[extra_args] + cl_options[opt_index].opt_len + 1 + adjust_len;
 
-      if (*arg == '\0' && !(option->flags & CL_MISSING_OK))
+      if (*arg == '\0' && !option->cl_missing_ok)
 	{
 	  if (separate_arg_flag)
 	    {
@@ -483,7 +482,7 @@  decode_cmdline_option (const char **argv
   /* Is this option an alias (or an ignored option, marked as an alias
      of OPT_SPECIAL_ignore)?  */
   if (option->alias_target != N_OPTS
-      && (!(option->flags & CL_SEPARATE_ALIAS) || have_separate_arg))
+      && (!option->cl_separate_alias || have_separate_arg))
     {
       size_t new_opt_index = option->alias_target;
 
@@ -501,13 +500,13 @@  decode_cmdline_option (const char **argv
 
 	  /* The new option must not be an alias itself.  */
 	  gcc_assert (new_option->alias_target == N_OPTS
-		      || (new_option->flags & CL_SEPARATE_ALIAS));
+		      || new_option->cl_separate_alias);
 
 	  if (option->neg_alias_arg)
 	    {
 	      gcc_assert (option->alias_arg != NULL);
 	      gcc_assert (arg == NULL);
-	      gcc_assert (!(option->flags & CL_NEGATIVE_ALIAS));
+	      gcc_assert (!option->cl_negative_alias);
 	      if (value)
 		arg = option->alias_arg;
 	      else
@@ -518,35 +517,34 @@  decode_cmdline_option (const char **argv
 	    {
 	      gcc_assert (value == 1);
 	      gcc_assert (arg == NULL);
-	      gcc_assert (!(option->flags & CL_NEGATIVE_ALIAS));
+	      gcc_assert (!option->cl_negative_alias);
 	      arg = option->alias_arg;
 	    }
 
-	  if (option->flags & CL_NEGATIVE_ALIAS)
+	  if (option->cl_negative_alias)
 	    value = !value;
 
 	  opt_index = new_opt_index;
 	  option = new_option;
 
 	  if (value == 0)
-	    gcc_assert (!(option->flags & CL_REJECT_NEGATIVE));
+	    gcc_assert (!option->cl_reject_negative);
 
 	  /* Recompute what arguments are allowed.  */
 	  separate_arg_flag = ((option->flags & CL_SEPARATE)
-			       && !((option->flags & CL_NO_DRIVER_ARG)
+			       && !(option->cl_no_driver_arg
 				    && (lang_mask & CL_DRIVER)));
 	  joined_arg_flag = (option->flags & CL_JOINED) != 0;
 
-	  if (separate_args > 1 || (option->flags & CL_SEPARATE_NARGS_MASK))
+	  if (separate_args > 1 || option->cl_separate_nargs)
 	    gcc_assert (separate_args
-			== ((option->flags & CL_SEPARATE_NARGS_MASK)
-			    >> CL_SEPARATE_NARGS_SHIFT) + 1);
+			== (unsigned int) option->cl_separate_nargs + 1);
 
 	  if (!(errors & CL_ERR_MISSING_ARG))
 	    {
 	      if (separate_arg_flag || joined_arg_flag)
 		{
-		  if ((option->flags & CL_MISSING_OK) && arg == NULL)
+		  if (option->cl_missing_ok && arg == NULL)
 		    arg = "";
 		  gcc_assert (arg != NULL);
 		}
@@ -560,7 +558,7 @@  decode_cmdline_option (const char **argv
 	      gcc_assert (warn_message == NULL);
 	      warn_message = option->warn_message;
 	    }
-	  if (option->flags & CL_DISABLED)
+	  if (option->cl_disabled)
 	    errors |= CL_ERR_DISABLED;
 	}
     }
@@ -570,7 +568,7 @@  decode_cmdline_option (const char **argv
     errors |= CL_ERR_WRONG_LANG;
 
   /* If the switch takes an integer, convert it.  */
-  if (arg && (option->flags & CL_UINTEGER))
+  if (arg && option->cl_uinteger)
     {
       value = integral_argument (arg);
       if (value == -1)
Index: gcc/gcc.c
===================================================================
--- gcc/gcc.c	(revision 171779)
+++ gcc/gcc.c	(working copy)
@@ -3115,7 +3115,7 @@  driver_wrong_lang_callback (const struct
      options.  */
   const struct cl_option *option = &cl_options[decoded->opt_index];
 
-  if (option->flags & CL_REJECT_DRIVER)
+  if (option->cl_reject_driver)
     error ("unrecognized command line option %qs",
 	   decoded->orig_option_with_args_text);
   else
Index: gcc/toplev.c
===================================================================
--- gcc/toplev.c	(revision 171779)
+++ gcc/toplev.c	(working copy)
@@ -891,7 +891,7 @@  print_switch_values (print_switch_fn_typ
 			     SWITCH_TYPE_DESCRIPTIVE, _("options enabled: "));
 
   for (j = 0; j < cl_options_count; j++)
-    if ((cl_options[j].flags & CL_REPORT)
+    if (cl_options[j].cl_report
 	&& option_enabled (j, &global_options) > 0)
       pos = print_single_switch (print_fn, pos,
 				 SWITCH_TYPE_ENABLED, cl_options[j].opt_text);
Index: gcc/opts.c
===================================================================
--- gcc/opts.c	(revision 171779)
+++ gcc/opts.c	(working copy)
@@ -382,7 +382,7 @@  maybe_default_option (struct gcc_options
 			     lang_mask, DK_UNSPECIFIED, loc,
 			     handlers, dc);
   else if (default_opt->arg == NULL
-	   && !(option->flags & CL_REJECT_NEGATIVE))
+	   && !option->cl_reject_negative)
     handle_generated_option (opts, opts_set, default_opt->opt_index,
 			     default_opt->arg, !default_opt->value,
 			     lang_mask, DK_UNSPECIFIED, loc,
Index: gcc/opts.h
===================================================================
--- gcc/opts.h	(revision 171779)
+++ gcc/opts.h	(working copy)
@@ -53,20 +53,60 @@  enum cl_var_type {
 
 struct cl_option
 {
+  /* Text of the option, including initial '-'.  */
   const char *opt_text;
+  /* Help text for --help, or NULL.  */
   const char *help;
+  /* Error message for missing argument, or NULL.  */
   const char *missing_argument_error;
+  /* Warning to give when this option is used, or NULL.  */
   const char *warn_message;
+  /* Argument of alias target when positive option given, or NULL.  */
   const char *alias_arg;
+  /* Argument of alias target when negative option given, or NULL.  */
   const char *neg_alias_arg;
+  /* Alias target, or N_OPTS if not an alias.  */
   unsigned short alias_target;
+  /* Previous option that is an initial substring of this one, or
+     N_OPTS if none.  */
   unsigned short back_chain;
+  /* Option length, not including initial '-'.  */
   unsigned char opt_len;
+  /* Next option in a sequence marked with Negative, or -1 if none.  */
   int neg_index;
+  /* CL_* flags for this option.  */
   unsigned int flags;
+  /* Disabled in this configuration.  */
+  BOOL_BITFIELD cl_disabled : 1;
+  /* Options marked with CL_SEPARATE take a number of separate
+     arguments (1 to 4) that is one more than the number in this
+     bit-field.  */
+  unsigned int cl_separate_nargs : 2;
+  /* Option is an alias when used with separate argument.  */
+  BOOL_BITFIELD cl_separate_alias : 1;
+  /* Alias to negative form of option.  */
+  BOOL_BITFIELD cl_negative_alias : 1;
+  /* Option takes no argument in the driver.  */
+  BOOL_BITFIELD cl_no_driver_arg : 1;
+  /* Reject this option in the driver.  */
+  BOOL_BITFIELD cl_reject_driver : 1;
+  /* Reject no- form.  */
+  BOOL_BITFIELD cl_reject_negative : 1;
+  /* Missing argument OK (joined).  */
+  BOOL_BITFIELD cl_missing_ok : 1;
+  /* Argument is an integer >=0.  */
+  BOOL_BITFIELD cl_uinteger : 1;
+  /* Report argument with -fverbose-asm  */
+  BOOL_BITFIELD cl_report : 1;
+  /* Offset of field for this option in struct gcc_options, or
+     (unsigned short) -1 if none.  */
   unsigned short flag_var_offset;
+  /* Index in cl_enums of enum used for this option's arguments, for
+     CLVC_ENUM options.  */
   unsigned short var_enum;
+  /* How this option's value is determined and sets a field.  */
   enum cl_var_type var_type;
+  /* Value or bit-mask with which to set a field.  */
   int var_value;
 };
 
@@ -98,24 +138,9 @@  extern const unsigned int cl_lang_count;
    This distinction is important because --help will not list options
    which only have these higher bits set.  */
 
-/* Options marked with CL_SEPARATE take a number of separate arguments
-   (1 to 4) that is one more than the number in this bit-field.  */
-#define CL_SEPARATE_NARGS_SHIFT	17
-#define CL_SEPARATE_NARGS_MASK	(3U << CL_SEPARATE_NARGS_SHIFT)
-
-#define CL_SEPARATE_ALIAS	(1U << 19) /* Option is an alias when used with separate argument.  */
-#define CL_NO_DRIVER_ARG	(1U << 20) /* Option takes no argument in the driver.  */
-#define CL_REJECT_DRIVER	(1U << 21) /* Reject this option in the driver.  */
-#define CL_SAVE			(1U << 22) /* Target-specific option for attribute.  */
-#define CL_DISABLED		(1U << 23) /* Disabled in this configuration.  */
-#define CL_REPORT		(1U << 24) /* Report argument with -fverbose-asm  */
-#define CL_JOINED		(1U << 25) /* If takes joined argument.  */
-#define CL_SEPARATE		(1U << 26) /* If takes a separate argument.  */
-#define CL_REJECT_NEGATIVE	(1U << 27) /* Reject no- form.  */
-#define CL_MISSING_OK		(1U << 28) /* Missing argument OK (joined).  */
-#define CL_UINTEGER		(1U << 29) /* Argument is an integer >=0.  */
-#define CL_UNDOCUMENTED		(1U << 30) /* Do not output with --help.  */
-#define CL_NEGATIVE_ALIAS	(1U << 31) /* Alias to negative form of option.  */
+#define CL_JOINED		(1U << 17) /* If takes joined argument.  */
+#define CL_SEPARATE		(1U << 18) /* If takes a separate argument.  */
+#define CL_UNDOCUMENTED		(1U << 19) /* Do not output with --help.  */
 
 /* Flags for an enumerated option argument.  */
 #define CL_ENUM_CANONICAL	(1 << 0) /* Canonical for this value.  */
Index: gcc/optc-gen.awk
===================================================================
--- gcc/optc-gen.awk	(revision 171779)
+++ gcc/optc-gen.awk	(working copy)
@@ -401,15 +401,21 @@  for (i = 0; i < n_opts; i++) {
 	printf(" %d,\n", idx)
 	condition = opt_args("Condition", flags[i])
 	cl_flags = switch_flags(flags[i])
+	cl_bit_fields = switch_bit_fields(flags[i])
+	cl_zero_bit_fields = switch_bit_fields("")
 	if (condition != "")
 		printf("#if %s\n" \
 		       "    %s,\n" \
+		       "    0, %s,\n" \
 		       "#else\n" \
-		       "    CL_DISABLED,\n" \
+		       "    0,\n" \
+		       "    1 /* Disabled.  */, %s,\n" \
 		       "#endif\n",
-		       condition, cl_flags, cl_flags)
+		       condition, cl_flags, cl_bit_fields, cl_zero_bit_fields)
 	else
-		printf("    %s,\n", cl_flags)
+		printf("    %s,\n" \
+		       "    0, %s,\n",
+		       cl_flags, cl_bit_fields)
 	printf("    %s, %s }%s\n", var_ref(opts[i], flags[i]),
 	       var_set(flags[i]), comma)
 }
Index: gcc/opt-functions.awk
===================================================================
--- gcc/opt-functions.awk	(revision 171779)
+++ gcc/opt-functions.awk	(working copy)
@@ -42,6 +42,16 @@  function test_flag(regex, flags, string)
 	return ""
 }
 
+# Return a field initializer, with trailing comma, for a field that is
+# 1 if FLAGS contains a flag matching REGEX and 0 otherwise.
+function flag_init(regex, flags)
+{
+	if (flag_set_p(regex, flags))
+		return "1 /* " regex " */, "
+	else
+		return "0, "
+}
+
 # If FLAGS contains a "NAME(...argument...)" flag, return the value
 # of the argument.  Return the empty string otherwise.
 function opt_args(name, flags)
@@ -87,27 +97,38 @@  function switch_flags (flags)
 	  test_flag("Common", flags, " | CL_COMMON") \
 	  test_flag("Target", flags, " | CL_TARGET") \
 	  test_flag("Driver", flags, " | CL_DRIVER") \
-	  test_flag("RejectDriver", flags, " | CL_REJECT_DRIVER") \
-	  test_flag("NoDriverArg", flags, " | CL_NO_DRIVER_ARG") \
-	  test_flag("SeparateAlias", flags, " | CL_SEPARATE_ALIAS") \
-	  test_flag("NegativeAlias", flags, " | CL_NEGATIVE_ALIAS") \
-	  test_flag("Save", flags, " | CL_SAVE") \
 	  test_flag("Joined", flags, " | CL_JOINED") \
-	  test_flag("JoinedOrMissing", flags, " | CL_JOINED | CL_MISSING_OK") \
+	  test_flag("JoinedOrMissing", flags, " | CL_JOINED") \
 	  test_flag("Separate", flags, " | CL_SEPARATE") \
-	  test_flag("RejectNegative", flags, " | CL_REJECT_NEGATIVE") \
-	  test_flag("UInteger", flags, " | CL_UINTEGER") \
 	  test_flag("Undocumented", flags,  " | CL_UNDOCUMENTED") \
 	  test_flag("Warning", flags,  " | CL_WARNING") \
-	  test_flag("Optimization", flags,  " | CL_OPTIMIZATION") \
-	  test_flag("Report", flags, " | CL_REPORT")
+	  test_flag("Optimization", flags,  " | CL_OPTIMIZATION")
+	sub( "^0 \\| ", "", result )
+	return result
+}
+
+# Return bit-field initializers for option flags FLAGS.
+function switch_bit_fields (flags)
+{
+	result = ""
 	sep_args = opt_args("Args", flags)
-	if (sep_args != "") {
+	if (sep_args == "")
+		sep_args = 0
+	else
 		sep_args--
-		result = result " | (" sep_args \
-		    " << CL_SEPARATE_NARGS_SHIFT)"
-	}
-	sub( "^0 \\| ", "", result )
+	result = result sep_args ", "
+
+	result = result \
+	  flag_init("SeparateAlias", flags) \
+	  flag_init("NegativeAlias", flags) \
+	  flag_init("NoDriverArg", flags) \
+	  flag_init("RejectDriver", flags) \
+	  flag_init("RejectNegative", flags) \
+	  flag_init("JoinedOrMissing", flags) \
+	  flag_init("UInteger", flags) \
+	  flag_init("Report", flags)
+
+	sub(", $", "", result)
 	return result
 }