diff options
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/opts.c | 34 | ||||
-rw-r--r-- | gcc/opts.h | 9 | ||||
-rw-r--r-- | gcc/toplev.c | 51 |
4 files changed, 95 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ab0bf7a8b70..045c42a969f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,17 @@ 2005-06-01 Richard Sandiford <rsandifo@redhat.com> + * 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. + +2005-06-01 Richard Sandiford <rsandifo@redhat.com> + * config/mips/mips-protos.h (mips_use_ins_ext_p): Remove parameter names. diff --git a/gcc/opts.c b/gcc/opts.c index 44ed37bad4c..6e73561496d 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -1442,3 +1442,37 @@ option_enabled (int opt_idx) } 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; +} diff --git a/gcc/opts.h b/gcc/opts.h index 1794f7b82cc..962b1caeb66 100644 --- a/gcc/opts.h +++ b/gcc/opts.h @@ -52,6 +52,14 @@ struct cl_option 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[]; @@ -77,6 +85,7 @@ extern unsigned num_in_fnames; 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 diff --git a/gcc/toplev.c b/gcc/toplev.c index 6cda6bba35b..550574fd154 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1434,6 +1434,21 @@ init_asm_output (const char *name) } } +/* 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. */ @@ -1441,9 +1456,8 @@ init_asm_output (const char *name) void * default_get_pch_validity (size_t *len) { -#ifdef TARGET_OPTIONS + struct cl_option_state state; size_t i; -#endif char *result, *r; *len = sizeof (target_flags) + 2; @@ -1455,6 +1469,9 @@ default_get_pch_validity (size_t *len) *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; @@ -1475,6 +1492,12 @@ default_get_pch_validity (size_t *len) 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; } @@ -1484,6 +1507,7 @@ default_get_pch_validity (size_t *len) 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; @@ -1504,9 +1528,9 @@ default_pch_valid_p (const void *data_p, size_t len) if (r != NULL) return r; } +#ifdef TARGET_SWITCHES else if (tf != target_flags) { -#ifdef TARGET_SWITCHES for (i = 0; i < ARRAY_SIZE (target_switches); i++) { int bits; @@ -1520,16 +1544,9 @@ default_pch_valid_p (const void *data_p, size_t len) 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 (); } +#endif data += sizeof (target_flags); len -= sizeof (target_flags); @@ -1552,6 +1569,18 @@ default_pch_valid_p (const void *data_p, size_t len) } #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: |