This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
RFA: Check PCH validity of (most) .opt target options
- From: Richard Sandiford <rsandifo at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 28 May 2005 08:15:33 +0100
- Subject: RFA: Check PCH validity of (most) .opt target options
This patch follows on from:
http://gcc.gnu.org/ml/gcc-patches/2005-05/msg02594.html
Before we started moving options to .opt files, the default PCH
validity routines would check every option in TARGET_OPTIONS and
TARGET_SWITCHES. Unfortunately, they only check .opt options if
their state is stored in target_flags.
This patch makes the PCH validity routines check every target .opt
option with a Var(), Mask() or InverseMask() flag. Once that's done,
the next step will be to make sure that every target option is treated
as if it had such a flag, with the options scripts attaching a static
variable to options that don't otherwise meet the criteria. We'll
then be back to where we were before the whole .opt thing started.
Once _that's_ done, it might be worth adding some sort of flag
to say whether an option affects PCH or not. But I'd like to
discuss that separately.
As it stands, I think this patch is a strict improvement on
the current situation and is enough for me to remove the final
use of TARGET_OPTIONS with a clear conscience. The patch to
do that will follow shortly...
The patch adds a new function, get_option_state, for getting the
current state of an option. Hopefully this function could be useful
for other things too, such as pragmas that push or pop an option's state.
The patch means that we no longer treat target_flags options as a
special case on most targets. However, the PCH routines will still
load and store target_flags separately. This is harmless but redundant.
I'll clean it up when removing TARGET_SWITCHES and TARGET_OPTIONS,
at which point there'll be less preprocessor hair to deal with.
The patch to do that will also follow shortly.
Tested by bootstrapping and regression testing on i686-pc-linux-gnu in
combination with the patch above. Also tested on sh-linux-gnu to test
the targetm.check_pch_target_flags case. For both targets, I checked
that -Winvalid-pch worked as expected for each type of CLVC_* option.
OK to install?
Richard
* opts.h (cl_option_state): New structure.
(get_option_state): Declare.
* opts.c (get_option_state): New function.
* toplev.c (option_affects_pch_p): New function.
(default_get_pch_validity): Store the state of all options for which
option_affects_pch_p returns true.
(default_pch_valid_p): Check the state of those options here.
Only check target_flags separately if targetm.check_pch_target_Flags
is nonnull or if TARGET_SWITCHES is defined.
*** gcc.1/opts.h 2005-05-26 19:09:12.000000000 +0100
--- gcc/opts.h 2005-05-27 11:28:44.000000000 +0100
*************** struct cl_option
*** 52,57 ****
--- 52,65 ----
int var_value;
};
+ /* Records that the state of an option consists of SIZE bytes starting
+ at DATA. DATA might point to CH in some cases. */
+ struct cl_option_state {
+ const void *data;
+ size_t size;
+ char ch;
+ };
+
extern const struct cl_option cl_options[];
extern const unsigned int cl_options_count;
extern const char *const lang_names[];
*************** extern unsigned num_in_fnames;
*** 77,82 ****
--- 85,91 ----
extern void decode_options (unsigned int argc, const char **argv);
extern int option_enabled (int opt_idx);
+ extern bool get_option_state (int, struct cl_option_state *);
extern void print_filtered_help (unsigned int);
#endif
*** gcc.1/opts.c 2005-05-26 19:09:12.000000000 +0100
--- gcc/opts.c 2005-05-27 11:19:24.000000000 +0100
*************** option_enabled (int opt_idx)
*** 1442,1444 ****
--- 1442,1478 ----
}
return -1;
}
+
+ /* Fill STATE with the current state of option OPTION. Return true if
+ there is some state to store. */
+
+ bool
+ get_option_state (int option, struct cl_option_state *state)
+ {
+ if (cl_options[option].flag_var == 0)
+ return false;
+
+ switch (cl_options[option].var_type)
+ {
+ case CLVC_BOOLEAN:
+ case CLVC_EQUAL:
+ state->data = cl_options[option].flag_var;
+ state->size = sizeof (int);
+ break;
+
+ case CLVC_BIT_CLEAR:
+ case CLVC_BIT_SET:
+ state->ch = option_enabled (option);
+ state->data = &state->ch;
+ state->size = 1;
+ break;
+
+ case CLVC_STRING:
+ state->data = *(const char **) cl_options[option].flag_var;
+ if (state->data == 0)
+ state->data = "";
+ state->size = strlen (state->data) + 1;
+ break;
+ }
+ return true;
+ }
*** gcc.1/toplev.c 2005-05-26 19:31:31.000000000 +0100
--- gcc/toplev.c 2005-05-27 11:21:57.000000000 +0100
*************** init_asm_output (const char *name)
*** 1434,1439 ****
--- 1434,1454 ----
}
}
+ /* Return true if the state of option OPTION should be stored in PCH files
+ and checked by default_pch_valid_p. Store the option's current state
+ in STATE if so. */
+
+ static inline bool
+ option_affects_pch_p (int option, struct cl_option_state *state)
+ {
+ if ((cl_options[option].flags & CL_TARGET) == 0)
+ return false;
+ if (cl_options[option].flag_var == &target_flags)
+ if (targetm.check_pch_target_flags)
+ return false;
+ return get_option_state (option, state);
+ }
+
/* Default version of get_pch_validity.
By default, every flag difference is fatal; that will be mostly right for
most targets, but completely right for very few. */
*************** init_asm_output (const char *name)
*** 1441,1449 ****
void *
default_get_pch_validity (size_t *len)
{
! #ifdef TARGET_OPTIONS
size_t i;
- #endif
char *result, *r;
*len = sizeof (target_flags) + 2;
--- 1456,1463 ----
void *
default_get_pch_validity (size_t *len)
{
! struct cl_option_state state;
size_t i;
char *result, *r;
*len = sizeof (target_flags) + 2;
*************** default_get_pch_validity (size_t *len)
*** 1455,1460 ****
--- 1469,1477 ----
*len += strlen (*target_options[i].variable);
}
#endif
+ for (i = 0; i < cl_options_count; i++)
+ if (option_affects_pch_p (i, &state))
+ *len += state.size;
result = r = xmalloc (*len);
r[0] = flag_pic;
*************** default_get_pch_validity (size_t *len)
*** 1475,1480 ****
--- 1492,1503 ----
r += l;
}
#endif
+ for (i = 0; i < cl_options_count; i++)
+ if (option_affects_pch_p (i, &state))
+ {
+ memcpy (r, state.data, state.size);
+ r += state.size;
+ }
return result;
}
*************** default_get_pch_validity (size_t *len)
*** 1484,1489 ****
--- 1507,1513 ----
const char *
default_pch_valid_p (const void *data_p, size_t len)
{
+ struct cl_option_state state;
const char *data = (const char *)data_p;
const char *flag_that_differs = NULL;
size_t i;
*************** default_pch_valid_p (const void *data_p,
*** 1504,1512 ****
if (r != NULL)
return r;
}
else if (tf != target_flags)
{
- #ifdef TARGET_SWITCHES
for (i = 0; i < ARRAY_SIZE (target_switches); i++)
{
int bits;
--- 1528,1536 ----
if (r != NULL)
return r;
}
+ #ifdef TARGET_SWITCHES
else if (tf != target_flags)
{
for (i = 0; i < ARRAY_SIZE (target_switches); i++)
{
int bits;
*************** default_pch_valid_p (const void *data_p,
*** 1520,1535 ****
goto make_message;
}
}
- #endif
- for (i = 0; i < cl_options_count; i++)
- if (cl_options[i].flag_var == &target_flags
- && (cl_options[i].var_value & (target_flags ^ tf)) != 0)
- {
- flag_that_differs = cl_options[i].opt_text + 2;
- goto make_message;
- }
gcc_unreachable ();
}
data += sizeof (target_flags);
len -= sizeof (target_flags);
--- 1544,1552 ----
goto make_message;
}
}
gcc_unreachable ();
}
+ #endif
data += sizeof (target_flags);
len -= sizeof (target_flags);
*************** default_pch_valid_p (const void *data_p,
*** 1552,1557 ****
--- 1569,1586 ----
}
#endif
+ for (i = 0; i < cl_options_count; i++)
+ if (option_affects_pch_p (i, &state))
+ {
+ if (memcmp (data, state.data, state.size) != 0)
+ {
+ flag_that_differs = cl_options[i].opt_text + 2;
+ goto make_message;
+ }
+ data += state.size;
+ len -= state.size;
+ }
+
return NULL;
make_message: