diff options
Diffstat (limited to 'gcc/opts.c')
-rw-r--r-- | gcc/opts.c | 108 |
1 files changed, 88 insertions, 20 deletions
@@ -1039,26 +1039,6 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, if ((opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS) && opts->x_flag_tm) sorry ("transactional memory is not supported with " "%<-fsanitize=kernel-address%>"); - - /* Comes from final.c -- no real reason to change it. */ -#define MAX_CODE_ALIGN 16 -#define MAX_CODE_ALIGN_VALUE (1 << MAX_CODE_ALIGN) - - if (opts->x_align_loops > MAX_CODE_ALIGN_VALUE) - error_at (loc, "-falign-loops=%d is not between 0 and %d", - opts->x_align_loops, MAX_CODE_ALIGN_VALUE); - - if (opts->x_align_jumps > MAX_CODE_ALIGN_VALUE) - error_at (loc, "-falign-jumps=%d is not between 0 and %d", - opts->x_align_jumps, MAX_CODE_ALIGN_VALUE); - - if (opts->x_align_functions > MAX_CODE_ALIGN_VALUE) - error_at (loc, "-falign-functions=%d is not between 0 and %d", - opts->x_align_functions, MAX_CODE_ALIGN_VALUE); - - if (opts->x_align_labels > MAX_CODE_ALIGN_VALUE) - error_at (loc, "-falign-labels=%d is not between 0 and %d", - opts->x_align_labels, MAX_CODE_ALIGN_VALUE); } #define LEFT_COLUMN 27 @@ -1779,6 +1759,78 @@ parse_no_sanitize_attribute (char *value) return flags; } +/* Parse -falign-NAME format for a FLAG value. Return individual + parsed integer values into RESULT_VALUES array. If REPORT_ERROR is + set, print error message at LOC location. */ + +bool +parse_and_check_align_values (const char *flag, + const char *name, + auto_vec<unsigned> &result_values, + bool report_error, + location_t loc) +{ + char *str = xstrdup (flag); + for (char *p = strtok (str, ":"); p; p = strtok (NULL, ":")) + { + char *end; + int v = strtol (p, &end, 10); + if (*end != '\0' || v < 0) + { + if (report_error) + error_at (loc, "invalid arguments for %<-falign-%s%> option: %qs", + name, flag); + + return false; + } + + result_values.safe_push ((unsigned)v); + } + + free (str); + + /* Check that we have a correct number of values. */ +#ifdef SUBALIGN_LOG + unsigned max_valid_values = 4; +#else + unsigned max_valid_values = 2; +#endif + + if (result_values.is_empty () + || result_values.length () > max_valid_values) + { + if (report_error) + error_at (loc, "invalid number of arguments for %<-falign-%s%> " + "option: %qs", name, flag); + return false; + } + + /* Comes from final.c -- no real reason to change it. */ +#define MAX_CODE_ALIGN 16 +#define MAX_CODE_ALIGN_VALUE (1 << MAX_CODE_ALIGN) + + for (unsigned i = 0; i < result_values.length (); i++) + if (result_values[i] > MAX_CODE_ALIGN_VALUE) + { + if (report_error) + error_at (loc, "%<-falign-%s%> is not between 0 and %d", + name, MAX_CODE_ALIGN_VALUE); + return false; + } + + return true; +} + +/* Check that alignment value FLAG for -falign-NAME is valid at a given + location LOC. */ + +static void +check_alignment_argument (location_t loc, const char *flag, const char *name) +{ + auto_vec<unsigned> align_result; + parse_and_check_align_values (flag, name, align_result, true, loc); +} + /* Handle target- and language-independent options. Return zero to generate an "unknown option" message. Only options that need extra handling need to be listed here; if you simply want @@ -2501,6 +2553,22 @@ common_handle_option (struct gcc_options *opts, opts->x_flag_ipa_icf_variables = value; break; + case OPT_falign_loops_: + check_alignment_argument (loc, arg, "loops"); + break; + + case OPT_falign_jumps_: + check_alignment_argument (loc, arg, "jumps"); + break; + + case OPT_falign_labels_: + check_alignment_argument (loc, arg, "labels"); + break; + + case OPT_falign_functions_: + check_alignment_argument (loc, arg, "functions"); + break; + default: /* If the flag was handled in a standard way, assume the lack of processing here is intentional. */ |