Commit c7887347 by Martin Liska Committed by Martin Liska

Provide extension hint for aarch64 target (PR driver/83193).

2018-10-31  Martin Liska  <mliska@suse.cz>

	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  <mliska@suse.cz>

	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
parent ff65e980
2018-10-31 Martin Liska <mliska@suse.cz>
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 <rguenther@suse.de> 2018-10-31 Richard Biener <rguenther@suse.de>
PR middle-end/70359 PR middle-end/70359
...@@ -220,10 +220,13 @@ static const struct arch_to_arch_name all_architectures[] = ...@@ -220,10 +220,13 @@ static const struct arch_to_arch_name all_architectures[] =
/* Parse the architecture extension string STR and update ISA_FLAGS /* Parse the architecture extension string STR and update ISA_FLAGS
with the architecture features turned on or off. Return a 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 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. */ /* The extension string is parsed left to right. */
const struct aarch64_option_extension *opt = NULL; const struct aarch64_option_extension *opt = NULL;
...@@ -274,6 +277,8 @@ aarch64_parse_extension (const char *str, unsigned long *isa_flags) ...@@ -274,6 +277,8 @@ aarch64_parse_extension (const char *str, unsigned long *isa_flags)
if (opt->name == NULL) if (opt->name == NULL)
{ {
/* Extension not found in list. */ /* Extension not found in list. */
if (invalid_extension)
*invalid_extension = std::string (str, len);
return AARCH64_PARSE_INVALID_FEATURE; return AARCH64_PARSE_INVALID_FEATURE;
} }
...@@ -283,6 +288,16 @@ aarch64_parse_extension (const char *str, unsigned long *isa_flags) ...@@ -283,6 +288,16 @@ aarch64_parse_extension (const char *str, unsigned long *isa_flags)
return AARCH64_PARSE_OK; return AARCH64_PARSE_OK;
} }
/* Append all architecture extension candidates to the CANDIDATES vector. */
void
aarch64_get_all_extension_candidates (auto_vec<const char *> *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 /* Return a string representation of ISA_FLAGS. DEFAULT_ARCH_FLAGS
gives the default set of flags which are implied by whatever -march 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 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) ...@@ -370,7 +385,7 @@ aarch64_rewrite_selected_cpu (const char *name)
fatal_error (input_location, "unknown value %qs for -mcpu", name); fatal_error (input_location, "unknown value %qs for -mcpu", name);
unsigned long extensions = p_to_a->flags; 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 std::string outstr = a_to_an->arch_name
+ aarch64_get_extension_string_for_isa_flags (extensions, + aarch64_get_extension_string_for_isa_flags (extensions,
......
...@@ -613,7 +613,9 @@ bool aarch64_handle_option (struct gcc_options *, struct gcc_options *, ...@@ -613,7 +613,9 @@ bool aarch64_handle_option (struct gcc_options *, struct gcc_options *,
const struct cl_decoded_option *, location_t); const struct cl_decoded_option *, location_t);
const char *aarch64_rewrite_selected_cpu (const char *name); const char *aarch64_rewrite_selected_cpu (const char *name);
enum aarch64_parse_opt_result aarch64_parse_extension (const char *, enum aarch64_parse_opt_result aarch64_parse_extension (const char *,
unsigned long *); unsigned long *,
std::string *);
void aarch64_get_all_extension_candidates (auto_vec<const char *> *candidates);
std::string aarch64_get_extension_string_for_isa_flags (unsigned long, std::string aarch64_get_extension_string_for_isa_flags (unsigned long,
unsigned long); unsigned long);
......
...@@ -10545,11 +10545,13 @@ static void initialize_aarch64_code_model (struct gcc_options *); ...@@ -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 /* Parse the TO_PARSE string and put the architecture struct that it
selects into RES and the architectural features into ISA_FLAGS. selects into RES and the architectural features into ISA_FLAGS.
Return an aarch64_parse_opt_result describing the parse result. 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 static enum aarch64_parse_opt_result
aarch64_parse_arch (const char *to_parse, const struct processor **res, 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; char *ext;
const struct processor *arch; const struct processor *arch;
...@@ -10580,7 +10582,7 @@ aarch64_parse_arch (const char *to_parse, const struct processor **res, ...@@ -10580,7 +10582,7 @@ aarch64_parse_arch (const char *to_parse, const struct processor **res,
{ {
/* TO_PARSE string contains at least one extension. */ /* TO_PARSE string contains at least one extension. */
enum aarch64_parse_opt_result ext_res 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) if (ext_res != AARCH64_PARSE_OK)
return ext_res; return ext_res;
...@@ -10600,11 +10602,13 @@ aarch64_parse_arch (const char *to_parse, const struct processor **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 /* 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 architecture flags in ISA_FLAGS. Return an aarch64_parse_opt_result
describing the parse result. If there is an error parsing, RES and 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 static enum aarch64_parse_opt_result
aarch64_parse_cpu (const char *to_parse, const struct processor **res, 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; char *ext;
const struct processor *cpu; const struct processor *cpu;
...@@ -10636,7 +10640,7 @@ aarch64_parse_cpu (const char *to_parse, const struct processor **res, ...@@ -10636,7 +10640,7 @@ aarch64_parse_cpu (const char *to_parse, const struct processor **res,
{ {
/* TO_PARSE string contains at least one extension. */ /* TO_PARSE string contains at least one extension. */
enum aarch64_parse_opt_result ext_res 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) if (ext_res != AARCH64_PARSE_OK)
return ext_res; return ext_res;
...@@ -11118,6 +11122,26 @@ aarch64_print_hint_for_arch (const char *str) ...@@ -11118,6 +11122,26 @@ aarch64_print_hint_for_arch (const char *str)
aarch64_print_hint_for_core_or_arch (str, true); 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<const char *> 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) /* 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 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 they are valid in RES and ISA_FLAGS. Return whether the option is
...@@ -11127,8 +11151,9 @@ static bool ...@@ -11127,8 +11151,9 @@ static bool
aarch64_validate_mcpu (const char *str, const struct processor **res, aarch64_validate_mcpu (const char *str, const struct processor **res,
unsigned long *isa_flags) unsigned long *isa_flags)
{ {
std::string invalid_extension;
enum aarch64_parse_opt_result parse_res 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) if (parse_res == AARCH64_PARSE_OK)
return true; return true;
...@@ -11143,7 +11168,9 @@ aarch64_validate_mcpu (const char *str, const struct processor **res, ...@@ -11143,7 +11168,9 @@ aarch64_validate_mcpu (const char *str, const struct processor **res,
aarch64_print_hint_for_core (str); aarch64_print_hint_for_core (str);
break; break;
case AARCH64_PARSE_INVALID_FEATURE: 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; break;
default: default:
gcc_unreachable (); gcc_unreachable ();
...@@ -11161,8 +11188,9 @@ static bool ...@@ -11161,8 +11188,9 @@ static bool
aarch64_validate_march (const char *str, const struct processor **res, aarch64_validate_march (const char *str, const struct processor **res,
unsigned long *isa_flags) unsigned long *isa_flags)
{ {
std::string invalid_extension;
enum aarch64_parse_opt_result parse_res 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) if (parse_res == AARCH64_PARSE_OK)
return true; return true;
...@@ -11177,7 +11205,9 @@ aarch64_validate_march (const char *str, const struct processor **res, ...@@ -11177,7 +11205,9 @@ aarch64_validate_march (const char *str, const struct processor **res,
aarch64_print_hint_for_arch (str); aarch64_print_hint_for_arch (str);
break; break;
case AARCH64_PARSE_INVALID_FEATURE: 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; break;
default: default:
gcc_unreachable (); gcc_unreachable ();
...@@ -11577,8 +11607,9 @@ static bool ...@@ -11577,8 +11607,9 @@ static bool
aarch64_handle_attr_arch (const char *str) aarch64_handle_attr_arch (const char *str)
{ {
const struct processor *tmp_arch = NULL; const struct processor *tmp_arch = NULL;
std::string invalid_extension;
enum aarch64_parse_opt_result parse_res 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) if (parse_res == AARCH64_PARSE_OK)
{ {
...@@ -11598,7 +11629,9 @@ aarch64_handle_attr_arch (const char *str) ...@@ -11598,7 +11629,9 @@ aarch64_handle_attr_arch (const char *str)
aarch64_print_hint_for_arch (str); aarch64_print_hint_for_arch (str);
break; break;
case AARCH64_PARSE_INVALID_FEATURE: case AARCH64_PARSE_INVALID_FEATURE:
error ("invalid value (\"%s\") in %<target()%> pragma or attribute", str); error ("invalid feature modifier %s of value (\"%s\") in "
"%<target()%> pragma or attribute", invalid_extension.c_str (), str);
aarch64_print_hint_for_extensions (invalid_extension);
break; break;
default: default:
gcc_unreachable (); gcc_unreachable ();
...@@ -11613,8 +11646,9 @@ static bool ...@@ -11613,8 +11646,9 @@ static bool
aarch64_handle_attr_cpu (const char *str) aarch64_handle_attr_cpu (const char *str)
{ {
const struct processor *tmp_cpu = NULL; const struct processor *tmp_cpu = NULL;
std::string invalid_extension;
enum aarch64_parse_opt_result parse_res 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) if (parse_res == AARCH64_PARSE_OK)
{ {
...@@ -11637,7 +11671,9 @@ aarch64_handle_attr_cpu (const char *str) ...@@ -11637,7 +11671,9 @@ aarch64_handle_attr_cpu (const char *str)
aarch64_print_hint_for_core (str); aarch64_print_hint_for_core (str);
break; break;
case AARCH64_PARSE_INVALID_FEATURE: case AARCH64_PARSE_INVALID_FEATURE:
error ("invalid value (\"%s\") in %<target()%> pragma or attribute", str); error ("invalid feature modifier %s of value (\"%s\") in "
"%<target()%> pragma or attribute", invalid_extension.c_str (), str);
aarch64_print_hint_for_extensions (invalid_extension);
break; break;
default: default:
gcc_unreachable (); gcc_unreachable ();
...@@ -11695,7 +11731,8 @@ aarch64_handle_attr_isa_flags (char *str) ...@@ -11695,7 +11731,8 @@ aarch64_handle_attr_isa_flags (char *str)
str += 8; 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) if (parse_res == AARCH64_PARSE_OK)
{ {
...@@ -11710,7 +11747,8 @@ aarch64_handle_attr_isa_flags (char *str) ...@@ -11710,7 +11747,8 @@ aarch64_handle_attr_isa_flags (char *str)
break; break;
case AARCH64_PARSE_INVALID_FEATURE: case AARCH64_PARSE_INVALID_FEATURE:
error ("invalid value (\"%s\") in %<target()%> pragma or attribute", str); error ("invalid feature modifier %s of value (\"%s\") in "
"%<target()%> pragma or attribute", invalid_extension.c_str (), str);
break; break;
default: default:
......
2018-10-31 Martin Liska <mliska@suse.cz>
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 <nathan@acm.org> 2018-10-31 Nathan Sidwell <nathan@acm.org>
* g++.dg/lookup/using60.C: New. * g++.dg/lookup/using60.C: New.
......
/* { 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 } */
/* { 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 } */
/* { 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 } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment