From c788734738f1afd93b5b78c0e22e013e9c9720eb Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Wed, 31 Oct 2018 15:46:17 +0100 Subject: [PATCH] Provide extension hint for aarch64 target (PR driver/83193). 2018-10-31 Martin Liska PR driver/83193 * common/config/aarch64/aarch64-common.c (aarch64_parse_extension): Add new argument invalid_extension. (aarch64_get_all_extension_candidates): New function. (aarch64_rewrite_selected_cpu): Add NULL to function call. * config/aarch64/aarch64-protos.h (aarch64_parse_extension): Add new argument. (aarch64_get_all_extension_candidates): New function. * config/aarch64/aarch64.c (aarch64_parse_arch): Add new argument invalid_extension. (aarch64_parse_cpu): Likewise. (aarch64_print_hint_for_extensions): New function. (aarch64_validate_mcpu): Provide hint about invalid extension. (aarch64_validate_march): Likewise. (aarch64_handle_attr_arch): Pass new argument. (aarch64_handle_attr_cpu): Provide hint about invalid extension. (aarch64_handle_attr_isa_flags): Likewise. 2018-10-31 Martin Liska PR driver/83193 * gcc.target/aarch64/spellcheck_7.c: New test. * gcc.target/aarch64/spellcheck_8.c: New test. * gcc.target/aarch64/spellcheck_9.c: New test. From-SVN: r265686 --- gcc/ChangeLog | 20 ++++++ gcc/common/config/aarch64/aarch64-common.c | 21 +++++- gcc/config/aarch64/aarch64-protos.h | 4 +- gcc/config/aarch64/aarch64.c | 70 ++++++++++++++----- gcc/testsuite/ChangeLog | 7 ++ .../gcc.target/aarch64/spellcheck_7.c | 12 ++++ .../gcc.target/aarch64/spellcheck_8.c | 13 ++++ .../gcc.target/aarch64/spellcheck_9.c | 13 ++++ 8 files changed, 140 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/spellcheck_7.c create mode 100644 gcc/testsuite/gcc.target/aarch64/spellcheck_8.c create mode 100644 gcc/testsuite/gcc.target/aarch64/spellcheck_9.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1f45354555a..26cfa87d6b8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2018-10-31 Martin Liska + + PR driver/83193 + * common/config/aarch64/aarch64-common.c (aarch64_parse_extension): + Add new argument invalid_extension. + (aarch64_get_all_extension_candidates): New function. + (aarch64_rewrite_selected_cpu): Add NULL to function call. + * config/aarch64/aarch64-protos.h (aarch64_parse_extension): Add + new argument. + (aarch64_get_all_extension_candidates): New function. + * config/aarch64/aarch64.c (aarch64_parse_arch): Add new + argument invalid_extension. + (aarch64_parse_cpu): Likewise. + (aarch64_print_hint_for_extensions): New function. + (aarch64_validate_mcpu): Provide hint about invalid extension. + (aarch64_validate_march): Likewise. + (aarch64_handle_attr_arch): Pass new argument. + (aarch64_handle_attr_cpu): Provide hint about invalid extension. + (aarch64_handle_attr_isa_flags): Likewise. + 2018-10-31 Richard Biener PR middle-end/70359 diff --git a/gcc/common/config/aarch64/aarch64-common.c b/gcc/common/config/aarch64/aarch64-common.c index ffddc4d16d8..dd7d4267340 100644 --- a/gcc/common/config/aarch64/aarch64-common.c +++ b/gcc/common/config/aarch64/aarch64-common.c @@ -220,10 +220,13 @@ static const struct arch_to_arch_name all_architectures[] = /* Parse the architecture extension string STR and update ISA_FLAGS with the architecture features turned on or off. Return a - aarch64_parse_opt_result describing the result. */ + aarch64_parse_opt_result describing the result. + When the STR string contains an invalid extension, + a copy of the string is created and stored to INVALID_EXTENSION. */ enum aarch64_parse_opt_result -aarch64_parse_extension (const char *str, unsigned long *isa_flags) +aarch64_parse_extension (const char *str, unsigned long *isa_flags, + std::string *invalid_extension) { /* The extension string is parsed left to right. */ const struct aarch64_option_extension *opt = NULL; @@ -274,6 +277,8 @@ aarch64_parse_extension (const char *str, unsigned long *isa_flags) if (opt->name == NULL) { /* Extension not found in list. */ + if (invalid_extension) + *invalid_extension = std::string (str, len); return AARCH64_PARSE_INVALID_FEATURE; } @@ -283,6 +288,16 @@ aarch64_parse_extension (const char *str, unsigned long *isa_flags) return AARCH64_PARSE_OK; } +/* Append all architecture extension candidates to the CANDIDATES vector. */ + +void +aarch64_get_all_extension_candidates (auto_vec *candidates) +{ + const struct aarch64_option_extension *opt; + for (opt = all_extensions; opt->name != NULL; opt++) + candidates->safe_push (opt->name); +} + /* Return a string representation of ISA_FLAGS. DEFAULT_ARCH_FLAGS gives the default set of flags which are implied by whatever -march we'd put out. Our job is to figure out the minimal set of "+" and @@ -370,7 +385,7 @@ aarch64_rewrite_selected_cpu (const char *name) fatal_error (input_location, "unknown value %qs for -mcpu", name); unsigned long extensions = p_to_a->flags; - aarch64_parse_extension (extension_str.c_str (), &extensions); + aarch64_parse_extension (extension_str.c_str (), &extensions, NULL); std::string outstr = a_to_an->arch_name + aarch64_get_extension_string_for_isa_flags (extensions, diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 288efe9fc67..1fe1a50d52a 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -613,7 +613,9 @@ bool aarch64_handle_option (struct gcc_options *, struct gcc_options *, const struct cl_decoded_option *, location_t); const char *aarch64_rewrite_selected_cpu (const char *name); enum aarch64_parse_opt_result aarch64_parse_extension (const char *, - unsigned long *); + unsigned long *, + std::string *); +void aarch64_get_all_extension_candidates (auto_vec *candidates); std::string aarch64_get_extension_string_for_isa_flags (unsigned long, unsigned long); diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 9813a9ded8f..b44ee40115d 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -10545,11 +10545,13 @@ static void initialize_aarch64_code_model (struct gcc_options *); /* Parse the TO_PARSE string and put the architecture struct that it selects into RES and the architectural features into ISA_FLAGS. Return an aarch64_parse_opt_result describing the parse result. - If there is an error parsing, RES and ISA_FLAGS are left unchanged. */ + If there is an error parsing, RES and ISA_FLAGS are left unchanged. + When the TO_PARSE string contains an invalid extension, + a copy of the string is created and stored to INVALID_EXTENSION. */ static enum aarch64_parse_opt_result aarch64_parse_arch (const char *to_parse, const struct processor **res, - unsigned long *isa_flags) + unsigned long *isa_flags, std::string *invalid_extension) { char *ext; const struct processor *arch; @@ -10580,7 +10582,7 @@ aarch64_parse_arch (const char *to_parse, const struct processor **res, { /* TO_PARSE string contains at least one extension. */ enum aarch64_parse_opt_result ext_res - = aarch64_parse_extension (ext, &isa_temp); + = aarch64_parse_extension (ext, &isa_temp, invalid_extension); if (ext_res != AARCH64_PARSE_OK) return ext_res; @@ -10600,11 +10602,13 @@ aarch64_parse_arch (const char *to_parse, const struct processor **res, /* Parse the TO_PARSE string and put the result tuning in RES and the architecture flags in ISA_FLAGS. Return an aarch64_parse_opt_result describing the parse result. If there is an error parsing, RES and - ISA_FLAGS are left unchanged. */ + ISA_FLAGS are left unchanged. + When the TO_PARSE string contains an invalid extension, + a copy of the string is created and stored to INVALID_EXTENSION. */ static enum aarch64_parse_opt_result aarch64_parse_cpu (const char *to_parse, const struct processor **res, - unsigned long *isa_flags) + unsigned long *isa_flags, std::string *invalid_extension) { char *ext; const struct processor *cpu; @@ -10636,7 +10640,7 @@ aarch64_parse_cpu (const char *to_parse, const struct processor **res, { /* TO_PARSE string contains at least one extension. */ enum aarch64_parse_opt_result ext_res - = aarch64_parse_extension (ext, &isa_temp); + = aarch64_parse_extension (ext, &isa_temp, invalid_extension); if (ext_res != AARCH64_PARSE_OK) return ext_res; @@ -11118,6 +11122,26 @@ aarch64_print_hint_for_arch (const char *str) aarch64_print_hint_for_core_or_arch (str, true); } + +/* Print a hint with a suggestion for an extension name + that most closely resembles what the user passed in STR. */ + +void +aarch64_print_hint_for_extensions (const std::string &str) +{ + auto_vec candidates; + aarch64_get_all_extension_candidates (&candidates); + char *s; + const char *hint = candidates_list_and_hint (str.c_str (), s, candidates); + if (hint) + inform (input_location, "valid arguments are: %s;" + " did you mean %qs?", s, hint); + else + inform (input_location, "valid arguments are: %s;", s); + + XDELETEVEC (s); +} + /* Validate a command-line -mcpu option. Parse the cpu and extensions (if any) specified in STR and throw errors if appropriate. Put the results if they are valid in RES and ISA_FLAGS. Return whether the option is @@ -11127,8 +11151,9 @@ static bool aarch64_validate_mcpu (const char *str, const struct processor **res, unsigned long *isa_flags) { + std::string invalid_extension; enum aarch64_parse_opt_result parse_res - = aarch64_parse_cpu (str, res, isa_flags); + = aarch64_parse_cpu (str, res, isa_flags, &invalid_extension); if (parse_res == AARCH64_PARSE_OK) return true; @@ -11143,7 +11168,9 @@ aarch64_validate_mcpu (const char *str, const struct processor **res, aarch64_print_hint_for_core (str); break; case AARCH64_PARSE_INVALID_FEATURE: - error ("invalid feature modifier in %<-mcpu=%s%>", str); + error ("invalid feature modifier %qs in %<-mcpu=%s%>", + invalid_extension.c_str (), str); + aarch64_print_hint_for_extensions (invalid_extension); break; default: gcc_unreachable (); @@ -11161,8 +11188,9 @@ static bool aarch64_validate_march (const char *str, const struct processor **res, unsigned long *isa_flags) { + std::string invalid_extension; enum aarch64_parse_opt_result parse_res - = aarch64_parse_arch (str, res, isa_flags); + = aarch64_parse_arch (str, res, isa_flags, &invalid_extension); if (parse_res == AARCH64_PARSE_OK) return true; @@ -11177,7 +11205,9 @@ aarch64_validate_march (const char *str, const struct processor **res, aarch64_print_hint_for_arch (str); break; case AARCH64_PARSE_INVALID_FEATURE: - error ("invalid feature modifier in %<-march=%s%>", str); + error ("invalid feature modifier %qs in %<-march=%s%>", + invalid_extension.c_str (), str); + aarch64_print_hint_for_extensions (invalid_extension); break; default: gcc_unreachable (); @@ -11577,8 +11607,9 @@ static bool aarch64_handle_attr_arch (const char *str) { const struct processor *tmp_arch = NULL; + std::string invalid_extension; enum aarch64_parse_opt_result parse_res - = aarch64_parse_arch (str, &tmp_arch, &aarch64_isa_flags); + = aarch64_parse_arch (str, &tmp_arch, &aarch64_isa_flags, &invalid_extension); if (parse_res == AARCH64_PARSE_OK) { @@ -11598,7 +11629,9 @@ aarch64_handle_attr_arch (const char *str) aarch64_print_hint_for_arch (str); break; case AARCH64_PARSE_INVALID_FEATURE: - error ("invalid value (\"%s\") in % pragma or attribute", str); + error ("invalid feature modifier %s of value (\"%s\") in " + "% pragma or attribute", invalid_extension.c_str (), str); + aarch64_print_hint_for_extensions (invalid_extension); break; default: gcc_unreachable (); @@ -11613,8 +11646,9 @@ static bool aarch64_handle_attr_cpu (const char *str) { const struct processor *tmp_cpu = NULL; + std::string invalid_extension; enum aarch64_parse_opt_result parse_res - = aarch64_parse_cpu (str, &tmp_cpu, &aarch64_isa_flags); + = aarch64_parse_cpu (str, &tmp_cpu, &aarch64_isa_flags, &invalid_extension); if (parse_res == AARCH64_PARSE_OK) { @@ -11637,7 +11671,9 @@ aarch64_handle_attr_cpu (const char *str) aarch64_print_hint_for_core (str); break; case AARCH64_PARSE_INVALID_FEATURE: - error ("invalid value (\"%s\") in % pragma or attribute", str); + error ("invalid feature modifier %s of value (\"%s\") in " + "% pragma or attribute", invalid_extension.c_str (), str); + aarch64_print_hint_for_extensions (invalid_extension); break; default: gcc_unreachable (); @@ -11695,7 +11731,8 @@ aarch64_handle_attr_isa_flags (char *str) str += 8; } - parse_res = aarch64_parse_extension (str, &isa_flags); + std::string invalid_extension; + parse_res = aarch64_parse_extension (str, &isa_flags, &invalid_extension); if (parse_res == AARCH64_PARSE_OK) { @@ -11710,7 +11747,8 @@ aarch64_handle_attr_isa_flags (char *str) break; case AARCH64_PARSE_INVALID_FEATURE: - error ("invalid value (\"%s\") in % pragma or attribute", str); + error ("invalid feature modifier %s of value (\"%s\") in " + "% pragma or attribute", invalid_extension.c_str (), str); break; default: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 18c3ac64478..d6b6780be13 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2018-10-31 Martin Liska + + PR driver/83193 + * gcc.target/aarch64/spellcheck_7.c: New test. + * gcc.target/aarch64/spellcheck_8.c: New test. + * gcc.target/aarch64/spellcheck_9.c: New test. + 2018-10-31 Nathan Sidwell * g++.dg/lookup/using60.C: New. diff --git a/gcc/testsuite/gcc.target/aarch64/spellcheck_7.c b/gcc/testsuite/gcc.target/aarch64/spellcheck_7.c new file mode 100644 index 00000000000..1d31950cb61 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/spellcheck_7.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-march=*" } { "" } } */ +/* { dg-skip-if "" { *-*-* } { "-mcpu=*" } { "" } } */ +/* { dg-options "-march=armv8-a+typo" } */ + +void +foo () +{ +} + +/* { dg-error "invalid feature modifier .typo. in .-march=armv8-a\\+typo." "" { target *-*-* } 0 } */ +/* { dg-message "valid arguments are: \[^\n\r]*;'?" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/gcc.target/aarch64/spellcheck_8.c b/gcc/testsuite/gcc.target/aarch64/spellcheck_8.c new file mode 100644 index 00000000000..1b8c5ebfeb1 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/spellcheck_8.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-march=*" } { "" } } */ +/* { dg-skip-if "" { *-*-* } { "-mcpu=*" } { "" } } */ +/* { dg-options "-march=armv8-a+cripto" } */ + +void +foo () +{ +} + +/* { dg-error "invalid feature modifier .cripto. in .-march=armv8-a\\+cripto." "" { target *-*-* } 0 } */ +/* { dg-message "valid arguments are: \[^\n\r]*; did you mean .crypto.?" "" { target *-*-* } 0 } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/spellcheck_9.c b/gcc/testsuite/gcc.target/aarch64/spellcheck_9.c new file mode 100644 index 00000000000..ad5b82589c1 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/spellcheck_9.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-march=*" } { "" } } */ +/* { dg-skip-if "" { *-*-* } { "-mcpu=*" } { "" } } */ +/* { dg-options "-mcpu=thunderx+cripto" } */ + +void +foo () +{ +} + +/* { dg-error "invalid feature modifier .cripto. in .-mcpu=thunderx\\+cripto." "" { target *-*-* } 0 } */ +/* { dg-message "valid arguments are: \[^\n\r]*; did you mean .crypto.?" "" { target *-*-* } 0 } */ + -- 2.30.2