#include "tree-dfa.h"
#include "asan.h"
#include "aarch64-feature-deps.h"
+#include "config/arm/aarch-common.h"
+#include "config/arm/aarch-common-protos.h"
/* This file should be included last. */
#include "target-def.h"
/* Global flag for whether frame pointer is enabled. */
bool aarch64_use_frame_pointer;
-#define BRANCH_PROTECT_STR_MAX 255
char *accepted_branch_protection_string = NULL;
-static enum aarch64_parse_opt_result
-aarch64_parse_branch_protection (const char*, char**);
-
/* Support for command line parsing of boolean flags in the tuning
structures. */
struct aarch64_flag_desc
{NULL, aarch64_none, aarch64_none, aarch64_no_arch, 0, NULL}
};
+enum aarch_key_type aarch_ra_sign_key = AARCH_KEY_A;
+
/* The current tuning set. */
struct tune_params aarch64_tune_params = generic_tunings;
#define AARCH64_INVERSE_CONDITION_CODE(X) ((aarch64_cc) (((int) X) ^ 1))
-struct aarch64_branch_protect_type
-{
- /* The type's name that the user passes to the branch-protection option
- string. */
- const char* name;
- /* Function to handle the protection type and set global variables.
- First argument is the string token corresponding with this type and the
- second argument is the next token in the option string.
- Return values:
- * AARCH64_PARSE_OK: Handling was sucessful.
- * AARCH64_INVALID_ARG: The type is invalid in this context and the caller
- should print an error.
- * AARCH64_INVALID_FEATURE: The type is invalid and the handler prints its
- own error. */
- enum aarch64_parse_opt_result (*handler)(char*, char*);
- /* A list of types that can follow this type in the option string. */
- const aarch64_branch_protect_type* subtypes;
- unsigned int num_subtypes;
-};
-
-static enum aarch64_parse_opt_result
-aarch64_handle_no_branch_protection (char* str, char* rest)
-{
- aarch64_ra_sign_scope = AARCH64_FUNCTION_NONE;
- aarch64_enable_bti = 0;
- if (rest)
- {
- error ("unexpected %<%s%> after %<%s%>", rest, str);
- return AARCH64_PARSE_INVALID_FEATURE;
- }
- return AARCH64_PARSE_OK;
-}
-
-static enum aarch64_parse_opt_result
-aarch64_handle_standard_branch_protection (char* str, char* rest)
-{
- aarch64_ra_sign_scope = AARCH64_FUNCTION_NON_LEAF;
- aarch64_ra_sign_key = AARCH64_KEY_A;
- aarch64_enable_bti = 1;
- if (rest)
- {
- error ("unexpected %<%s%> after %<%s%>", rest, str);
- return AARCH64_PARSE_INVALID_FEATURE;
- }
- return AARCH64_PARSE_OK;
-}
-
-static enum aarch64_parse_opt_result
-aarch64_handle_pac_ret_protection (char* str ATTRIBUTE_UNUSED,
- char* rest ATTRIBUTE_UNUSED)
-{
- aarch64_ra_sign_scope = AARCH64_FUNCTION_NON_LEAF;
- aarch64_ra_sign_key = AARCH64_KEY_A;
- return AARCH64_PARSE_OK;
-}
-
-static enum aarch64_parse_opt_result
-aarch64_handle_pac_ret_leaf (char* str ATTRIBUTE_UNUSED,
- char* rest ATTRIBUTE_UNUSED)
-{
- aarch64_ra_sign_scope = AARCH64_FUNCTION_ALL;
- return AARCH64_PARSE_OK;
-}
-
-static enum aarch64_parse_opt_result
-aarch64_handle_pac_ret_b_key (char* str ATTRIBUTE_UNUSED,
- char* rest ATTRIBUTE_UNUSED)
-{
- aarch64_ra_sign_key = AARCH64_KEY_B;
- return AARCH64_PARSE_OK;
-}
-
-static enum aarch64_parse_opt_result
-aarch64_handle_bti_protection (char* str ATTRIBUTE_UNUSED,
- char* rest ATTRIBUTE_UNUSED)
-{
- aarch64_enable_bti = 1;
- return AARCH64_PARSE_OK;
-}
-
-static const struct aarch64_branch_protect_type aarch64_pac_ret_subtypes[] = {
- { "leaf", aarch64_handle_pac_ret_leaf, NULL, 0 },
- { "b-key", aarch64_handle_pac_ret_b_key, NULL, 0 },
- { NULL, NULL, NULL, 0 }
-};
-
-static const struct aarch64_branch_protect_type aarch64_branch_protect_types[] = {
- { "none", aarch64_handle_no_branch_protection, NULL, 0 },
- { "standard", aarch64_handle_standard_branch_protection, NULL, 0 },
- { "pac-ret", aarch64_handle_pac_ret_protection, aarch64_pac_ret_subtypes,
- ARRAY_SIZE (aarch64_pac_ret_subtypes) },
- { "bti", aarch64_handle_bti_protection, NULL, 0 },
- { NULL, NULL, NULL, 0 }
-};
/* The condition codes of the processor, and the inverse function. */
static const char * const aarch64_condition_codes[] =
if (crtl->calls_eh_return)
return false;
- /* If signing scope is AARCH64_FUNCTION_NON_LEAF, we only sign a leaf function
+ /* If signing scope is AARCH_FUNCTION_NON_LEAF, we only sign a leaf function
if its LR is pushed onto stack. */
- return (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL
- || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF
+ return (aarch_ra_sign_scope == AARCH_FUNCTION_ALL
+ || (aarch_ra_sign_scope == AARCH_FUNCTION_NON_LEAF
&& known_ge (cfun->machine->frame.reg_offset[LR_REGNUM], 0)));
}
bool
aarch64_bti_enabled (void)
{
- return (aarch64_enable_bti == 1);
+ return (aarch_enable_bti == 1);
}
/* The caller is going to use ST1D or LD1D to save or restore an SVE
/* Sign return address for functions. */
if (aarch64_return_address_signing_enabled ())
{
- switch (aarch64_ra_sign_key)
+ switch (aarch_ra_sign_key)
{
- case AARCH64_KEY_A:
+ case AARCH_KEY_A:
insn = emit_insn (gen_paciasp ());
break;
- case AARCH64_KEY_B:
+ case AARCH_KEY_B:
insn = emit_insn (gen_pacibsp ());
break;
default:
if (aarch64_return_address_signing_enabled ()
&& (for_sibcall || !TARGET_ARMV8_3))
{
- switch (aarch64_ra_sign_key)
+ switch (aarch_ra_sign_key)
{
- case AARCH64_KEY_A:
+ case AARCH_KEY_A:
insn = emit_insn (gen_autiasp ());
break;
- case AARCH64_KEY_B:
+ case AARCH_KEY_B:
insn = emit_insn (gen_autibsp ());
break;
default:
/* 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.
+ Return an aarch_parse_opt_result describing the parse result.
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 aarch_parse_opt_result
aarch64_parse_arch (const char *to_parse, const struct processor **res,
aarch64_feature_flags *isa_flags,
std::string *invalid_extension)
len = strlen (to_parse);
if (len == 0)
- return AARCH64_PARSE_MISSING_ARG;
+ return AARCH_PARSE_MISSING_ARG;
/* Loop through the list of supported ARCHes to find a match. */
if (ext != NULL)
{
/* TO_PARSE string contains at least one extension. */
- enum aarch64_parse_opt_result ext_res
+ enum aarch_parse_opt_result ext_res
= aarch64_parse_extension (ext, &isa_temp, invalid_extension);
- if (ext_res != AARCH64_PARSE_OK)
+ if (ext_res != AARCH_PARSE_OK)
return ext_res;
}
/* Extension parsing was successful. Confirm the result
arch and ISA flags. */
*res = arch;
*isa_flags = isa_temp;
- return AARCH64_PARSE_OK;
+ return AARCH_PARSE_OK;
}
}
/* ARCH name not found in list. */
- return AARCH64_PARSE_INVALID_ARG;
+ return AARCH_PARSE_INVALID_ARG;
}
/* 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 aarch_parse_opt_result
describing the parse result. 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 aarch_parse_opt_result
aarch64_parse_cpu (const char *to_parse, const struct processor **res,
aarch64_feature_flags *isa_flags,
std::string *invalid_extension)
len = strlen (to_parse);
if (len == 0)
- return AARCH64_PARSE_MISSING_ARG;
+ return AARCH_PARSE_MISSING_ARG;
/* Loop through the list of supported CPUs to find a match. */
if (ext != NULL)
{
/* TO_PARSE string contains at least one extension. */
- enum aarch64_parse_opt_result ext_res
+ enum aarch_parse_opt_result ext_res
= aarch64_parse_extension (ext, &isa_temp, invalid_extension);
- if (ext_res != AARCH64_PARSE_OK)
+ if (ext_res != AARCH_PARSE_OK)
return ext_res;
}
/* Extension parsing was successfull. Confirm the result
cpu and ISA flags. */
*res = cpu;
*isa_flags = isa_temp;
- return AARCH64_PARSE_OK;
+ return AARCH_PARSE_OK;
}
}
/* CPU name not found in list. */
- return AARCH64_PARSE_INVALID_ARG;
+ return AARCH_PARSE_INVALID_ARG;
}
/* Parse the TO_PARSE string and put the cpu it selects into RES.
- Return an aarch64_parse_opt_result describing the parse result.
+ Return an aarch_parse_opt_result describing the parse result.
If the parsing fails the RES does not change. */
-static enum aarch64_parse_opt_result
+static enum aarch_parse_opt_result
aarch64_parse_tune (const char *to_parse, const struct processor **res)
{
const struct processor *cpu;
if (strcmp (cpu->name, to_parse) == 0)
{
*res = cpu;
- return AARCH64_PARSE_OK;
+ return AARCH_PARSE_OK;
}
}
/* CPU name not found in list. */
- return AARCH64_PARSE_INVALID_ARG;
+ return AARCH_PARSE_INVALID_ARG;
}
/* Parse TOKEN, which has length LENGTH to see if it is an option
aarch64_feature_flags *isa_flags)
{
std::string invalid_extension;
- enum aarch64_parse_opt_result parse_res
+ enum aarch_parse_opt_result parse_res
= aarch64_parse_cpu (str, res, isa_flags, &invalid_extension);
- if (parse_res == AARCH64_PARSE_OK)
+ if (parse_res == AARCH_PARSE_OK)
return true;
switch (parse_res)
{
- case AARCH64_PARSE_MISSING_ARG:
+ case AARCH_PARSE_MISSING_ARG:
error ("missing cpu name in %<-mcpu=%s%>", str);
break;
- case AARCH64_PARSE_INVALID_ARG:
+ case AARCH_PARSE_INVALID_ARG:
error ("unknown value %qs for %<-mcpu%>", str);
aarch64_print_hint_for_core (str);
break;
- case AARCH64_PARSE_INVALID_FEATURE:
+ case AARCH_PARSE_INVALID_FEATURE:
error ("invalid feature modifier %qs in %<-mcpu=%s%>",
invalid_extension.c_str (), str);
aarch64_print_hint_for_extensions (invalid_extension);
free (str_root);
}
-/* Parses CONST_STR for branch protection features specified in
- aarch64_branch_protect_types, and set any global variables required. Returns
- the parsing result and assigns LAST_STR to the last processed token from
- CONST_STR so that it can be used for error reporting. */
-
-static enum
-aarch64_parse_opt_result aarch64_parse_branch_protection (const char *const_str,
- char** last_str)
-{
- char *str_root = xstrdup (const_str);
- char* token_save = NULL;
- char *str = strtok_r (str_root, "+", &token_save);
- enum aarch64_parse_opt_result res = AARCH64_PARSE_OK;
- if (!str)
- res = AARCH64_PARSE_MISSING_ARG;
- else
- {
- char *next_str = strtok_r (NULL, "+", &token_save);
- /* Reset the branch protection features to their defaults. */
- aarch64_handle_no_branch_protection (NULL, NULL);
-
- while (str && res == AARCH64_PARSE_OK)
- {
- const aarch64_branch_protect_type* type = aarch64_branch_protect_types;
- bool found = false;
- /* Search for this type. */
- while (type && type->name && !found && res == AARCH64_PARSE_OK)
- {
- if (strcmp (str, type->name) == 0)
- {
- found = true;
- res = type->handler (str, next_str);
- str = next_str;
- next_str = strtok_r (NULL, "+", &token_save);
- }
- else
- type++;
- }
- if (found && res == AARCH64_PARSE_OK)
- {
- bool found_subtype = true;
- /* Loop through each token until we find one that isn't a
- subtype. */
- while (found_subtype)
- {
- found_subtype = false;
- const aarch64_branch_protect_type *subtype = type->subtypes;
- /* Search for the subtype. */
- while (str && subtype && subtype->name && !found_subtype
- && res == AARCH64_PARSE_OK)
- {
- if (strcmp (str, subtype->name) == 0)
- {
- found_subtype = true;
- res = subtype->handler (str, next_str);
- str = next_str;
- next_str = strtok_r (NULL, "+", &token_save);
- }
- else
- subtype++;
- }
- }
- }
- else if (!found)
- res = AARCH64_PARSE_INVALID_ARG;
- }
- }
- /* Copy the last processed token into the argument to pass it back.
- Used by option and attribute validation to print the offending token. */
- if (last_str)
- {
- if (str) strcpy (*last_str, str);
- else *last_str = NULL;
- }
- if (res == AARCH64_PARSE_OK)
- {
- /* If needed, alloc the accepted string then copy in const_str.
- Used by override_option_after_change_1. */
- if (!accepted_branch_protection_string)
- accepted_branch_protection_string = (char *) xmalloc (
- BRANCH_PROTECT_STR_MAX
- + 1);
- strncpy (accepted_branch_protection_string, const_str,
- BRANCH_PROTECT_STR_MAX + 1);
- /* Forcibly null-terminate. */
- accepted_branch_protection_string[BRANCH_PROTECT_STR_MAX] = '\0';
- }
- return res;
-}
-
-static bool
-aarch64_validate_mbranch_protection (const char *const_str)
-{
- char *str = (char *) xmalloc (strlen (const_str));
- enum aarch64_parse_opt_result res =
- aarch64_parse_branch_protection (const_str, &str);
- if (res == AARCH64_PARSE_INVALID_ARG)
- error ("invalid argument %<%s%> for %<-mbranch-protection=%>", str);
- else if (res == AARCH64_PARSE_MISSING_ARG)
- error ("missing argument for %<-mbranch-protection=%>");
- free (str);
- return res == AARCH64_PARSE_OK;
-}
-
/* Validate a command-line -march option. Parse the arch 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
aarch64_feature_flags *isa_flags)
{
std::string invalid_extension;
- enum aarch64_parse_opt_result parse_res
+ enum aarch_parse_opt_result parse_res
= aarch64_parse_arch (str, res, isa_flags, &invalid_extension);
- if (parse_res == AARCH64_PARSE_OK)
+ if (parse_res == AARCH_PARSE_OK)
return true;
switch (parse_res)
{
- case AARCH64_PARSE_MISSING_ARG:
+ case AARCH_PARSE_MISSING_ARG:
error ("missing arch name in %<-march=%s%>", str);
break;
- case AARCH64_PARSE_INVALID_ARG:
+ case AARCH_PARSE_INVALID_ARG:
error ("unknown value %qs for %<-march%>", str);
aarch64_print_hint_for_arch (str);
/* A common user error is confusing -march and -mcpu.
If the -march string matches a known CPU suggest -mcpu. */
parse_res = aarch64_parse_cpu (str, res, isa_flags, &invalid_extension);
- if (parse_res == AARCH64_PARSE_OK)
+ if (parse_res == AARCH_PARSE_OK)
inform (input_location, "did you mean %<-mcpu=%s%>?", str);
break;
- case AARCH64_PARSE_INVALID_FEATURE:
+ case AARCH_PARSE_INVALID_FEATURE:
error ("invalid feature modifier %qs in %<-march=%s%>",
invalid_extension.c_str (), str);
aarch64_print_hint_for_extensions (invalid_extension);
static bool
aarch64_validate_mtune (const char *str, const struct processor **res)
{
- enum aarch64_parse_opt_result parse_res
+ enum aarch_parse_opt_result parse_res
= aarch64_parse_tune (str, res);
- if (parse_res == AARCH64_PARSE_OK)
+ if (parse_res == AARCH_PARSE_OK)
return true;
switch (parse_res)
{
- case AARCH64_PARSE_MISSING_ARG:
+ case AARCH_PARSE_MISSING_ARG:
error ("missing cpu name in %<-mtune=%s%>", str);
break;
- case AARCH64_PARSE_INVALID_ARG:
+ case AARCH_PARSE_INVALID_ARG:
error ("unknown value %qs for %<-mtune%>", str);
aarch64_print_hint_for_core (str);
break;
aarch64_validate_sls_mitigation (aarch64_harden_sls_string);
if (aarch64_branch_protection_string)
- aarch64_validate_mbranch_protection (aarch64_branch_protection_string);
+ aarch_validate_mbranch_protection (aarch64_branch_protection_string);
/* -mcpu=CPU is shorthand for -march=ARCH_FOR_CPU, -mtune=CPU.
If either of -march or -mtune is given, they override their
selected_tune = tune ? tune->ident : cpu->ident;
- if (aarch64_enable_bti == 2)
+ if (aarch_enable_bti == 2)
{
#ifdef TARGET_ENABLE_BTI
- aarch64_enable_bti = 1;
+ aarch_enable_bti = 1;
#else
- aarch64_enable_bti = 0;
+ aarch_enable_bti = 0;
#endif
}
if (!TARGET_ILP32 && accepted_branch_protection_string == NULL)
{
#ifdef TARGET_ENABLE_PAC_RET
- aarch64_ra_sign_scope = AARCH64_FUNCTION_NON_LEAF;
+ aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
#else
- aarch64_ra_sign_scope = AARCH64_FUNCTION_NONE;
+ aarch_ra_sign_scope = AARCH_FUNCTION_NONE;
#endif
}
/* Convert -msve-vector-bits to a VG count. */
aarch64_sve_vg = aarch64_convert_sve_vector_bits (aarch64_sve_vector_bits);
- if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32)
+ if (aarch_ra_sign_scope != AARCH_FUNCTION_NONE && TARGET_ILP32)
sorry ("return address signing is only supported for %<-mabi=lp64%>");
/* The pass to insert speculation tracking runs before
const struct processor *tmp_arch = NULL;
std::string invalid_extension;
aarch64_feature_flags tmp_flags;
- enum aarch64_parse_opt_result parse_res
+ enum aarch_parse_opt_result parse_res
= aarch64_parse_arch (str, &tmp_arch, &tmp_flags, &invalid_extension);
- if (parse_res == AARCH64_PARSE_OK)
+ if (parse_res == AARCH_PARSE_OK)
{
gcc_assert (tmp_arch);
selected_arch = tmp_arch->arch;
switch (parse_res)
{
- case AARCH64_PARSE_MISSING_ARG:
+ case AARCH_PARSE_MISSING_ARG:
error ("missing name in %<target(\"arch=\")%> pragma or attribute");
break;
- case AARCH64_PARSE_INVALID_ARG:
+ case AARCH_PARSE_INVALID_ARG:
error ("invalid name %qs in %<target(\"arch=\")%> pragma or attribute", str);
aarch64_print_hint_for_arch (str);
break;
- case AARCH64_PARSE_INVALID_FEATURE:
+ case AARCH_PARSE_INVALID_FEATURE:
error ("invalid feature modifier %s of value %qs in "
"%<target()%> pragma or attribute", invalid_extension.c_str (), str);
aarch64_print_hint_for_extensions (invalid_extension);
const struct processor *tmp_cpu = NULL;
std::string invalid_extension;
aarch64_feature_flags tmp_flags;
- enum aarch64_parse_opt_result parse_res
+ enum aarch_parse_opt_result parse_res
= aarch64_parse_cpu (str, &tmp_cpu, &tmp_flags, &invalid_extension);
- if (parse_res == AARCH64_PARSE_OK)
+ if (parse_res == AARCH_PARSE_OK)
{
gcc_assert (tmp_cpu);
selected_tune = tmp_cpu->ident;
switch (parse_res)
{
- case AARCH64_PARSE_MISSING_ARG:
+ case AARCH_PARSE_MISSING_ARG:
error ("missing name in %<target(\"cpu=\")%> pragma or attribute");
break;
- case AARCH64_PARSE_INVALID_ARG:
+ case AARCH_PARSE_INVALID_ARG:
error ("invalid name %qs in %<target(\"cpu=\")%> pragma or attribute", str);
aarch64_print_hint_for_core (str);
break;
- case AARCH64_PARSE_INVALID_FEATURE:
+ case AARCH_PARSE_INVALID_FEATURE:
error ("invalid feature modifier %qs of value %qs in "
"%<target()%> pragma or attribute", invalid_extension.c_str (), str);
aarch64_print_hint_for_extensions (invalid_extension);
aarch64_handle_attr_branch_protection (const char* str)
{
char *err_str = (char *) xmalloc (strlen (str) + 1);
- enum aarch64_parse_opt_result res = aarch64_parse_branch_protection (str,
- &err_str);
+ enum aarch_parse_opt_result res = aarch_parse_branch_protection (str,
+ &err_str);
bool success = false;
switch (res)
{
- case AARCH64_PARSE_MISSING_ARG:
+ case AARCH_PARSE_MISSING_ARG:
error ("missing argument to %<target(\"branch-protection=\")%> pragma or"
" attribute");
break;
- case AARCH64_PARSE_INVALID_ARG:
+ case AARCH_PARSE_INVALID_ARG:
error ("invalid protection type %qs in %<target(\"branch-protection"
"=\")%> pragma or attribute", err_str);
break;
- case AARCH64_PARSE_OK:
+ case AARCH_PARSE_OK:
success = true;
/* Fall through. */
- case AARCH64_PARSE_INVALID_FEATURE:
+ case AARCH_PARSE_INVALID_FEATURE:
break;
default:
gcc_unreachable ();
aarch64_handle_attr_tune (const char *str)
{
const struct processor *tmp_tune = NULL;
- enum aarch64_parse_opt_result parse_res
+ enum aarch_parse_opt_result parse_res
= aarch64_parse_tune (str, &tmp_tune);
- if (parse_res == AARCH64_PARSE_OK)
+ if (parse_res == AARCH_PARSE_OK)
{
gcc_assert (tmp_tune);
selected_tune = tmp_tune->ident;
switch (parse_res)
{
- case AARCH64_PARSE_INVALID_ARG:
+ case AARCH_PARSE_INVALID_ARG:
error ("invalid name %qs in %<target(\"tune=\")%> pragma or attribute", str);
aarch64_print_hint_for_core (str);
break;
static bool
aarch64_handle_attr_isa_flags (char *str)
{
- enum aarch64_parse_opt_result parse_res;
+ enum aarch_parse_opt_result parse_res;
auto isa_flags = aarch64_asm_isa_flags;
/* We allow "+nothing" in the beginning to clear out all architectural
std::string invalid_extension;
parse_res = aarch64_parse_extension (str, &isa_flags, &invalid_extension);
- if (parse_res == AARCH64_PARSE_OK)
+ if (parse_res == AARCH_PARSE_OK)
{
aarch64_set_asm_isa_flags (isa_flags);
return true;
switch (parse_res)
{
- case AARCH64_PARSE_MISSING_ARG:
+ case AARCH_PARSE_MISSING_ARG:
error ("missing value in %<target()%> pragma or attribute");
break;
- case AARCH64_PARSE_INVALID_FEATURE:
+ case AARCH_PARSE_INVALID_FEATURE:
error ("invalid feature modifier %qs of value %qs in "
"%<target()%> pragma or attribute", invalid_extension.c_str (), str);
break;
leading '+'. */
aarch64_feature_flags isa_temp = 0;
auto with_plus = std::string ("+") + token;
- enum aarch64_parse_opt_result ext_res
+ enum aarch_parse_opt_result ext_res
= aarch64_parse_extension (with_plus.c_str (), &isa_temp, nullptr);
- if (ext_res == AARCH64_PARSE_OK)
+ if (ext_res == AARCH_PARSE_OK)
error ("arch extension %<%s%> should be prefixed by %<+%>",
token);
else
aarch64_post_cfi_startproc (FILE *f, tree ignored ATTRIBUTE_UNUSED)
{
if (cfun->machine->frame.laid_out && aarch64_return_address_signing_enabled ()
- && aarch64_ra_sign_key == AARCH64_KEY_B)
+ && aarch_ra_sign_key == AARCH_KEY_B)
asm_fprintf (f, "\t.cfi_b_key_frame\n");
}
if (aarch64_bti_enabled ())
feature_1_and |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
- if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE)
+ if (aarch_ra_sign_scope != AARCH_FUNCTION_NONE)
feature_1_and |= GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
if (feature_1_and)
#include "expr.h"
#include "function.h"
#include "emit-rtl.h"
+#include "aarch-common.h"
/* Return TRUE if X is either an arithmetic shift left, or
is a multiplication by a power of two. */
return saw_asm_flag ? seq : NULL;
}
+
+#define BRANCH_PROTECT_STR_MAX 255
+extern char *accepted_branch_protection_string;
+extern enum aarch_key_type aarch_ra_sign_key;
+
+static enum aarch_parse_opt_result
+aarch_handle_no_branch_protection (char* str, char* rest)
+{
+ aarch_ra_sign_scope = AARCH_FUNCTION_NONE;
+ aarch_enable_bti = 0;
+ if (rest)
+ {
+ error ("unexpected %<%s%> after %<%s%>", rest, str);
+ return AARCH_PARSE_INVALID_FEATURE;
+ }
+ return AARCH_PARSE_OK;
+}
+
+static enum aarch_parse_opt_result
+aarch_handle_standard_branch_protection (char* str, char* rest)
+{
+ aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
+ aarch_ra_sign_key = AARCH_KEY_A;
+ aarch_enable_bti = 1;
+ if (rest)
+ {
+ error ("unexpected %<%s%> after %<%s%>", rest, str);
+ return AARCH_PARSE_INVALID_FEATURE;
+ }
+ return AARCH_PARSE_OK;
+}
+
+static enum aarch_parse_opt_result
+aarch_handle_pac_ret_protection (char* str ATTRIBUTE_UNUSED,
+ char* rest ATTRIBUTE_UNUSED)
+{
+ aarch_ra_sign_scope = AARCH_FUNCTION_NON_LEAF;
+ aarch_ra_sign_key = AARCH_KEY_A;
+ return AARCH_PARSE_OK;
+}
+
+static enum aarch_parse_opt_result
+aarch_handle_pac_ret_leaf (char* str ATTRIBUTE_UNUSED,
+ char* rest ATTRIBUTE_UNUSED)
+{
+ aarch_ra_sign_scope = AARCH_FUNCTION_ALL;
+ return AARCH_PARSE_OK;
+}
+
+static enum aarch_parse_opt_result
+aarch_handle_pac_ret_b_key (char* str ATTRIBUTE_UNUSED,
+ char* rest ATTRIBUTE_UNUSED)
+{
+ aarch_ra_sign_key = AARCH_KEY_B;
+ return AARCH_PARSE_OK;
+}
+
+static enum aarch_parse_opt_result
+aarch_handle_bti_protection (char* str ATTRIBUTE_UNUSED,
+ char* rest ATTRIBUTE_UNUSED)
+{
+ aarch_enable_bti = 1;
+ return AARCH_PARSE_OK;
+}
+
+static const struct aarch_branch_protect_type aarch_pac_ret_subtypes[] = {
+ { "leaf", aarch_handle_pac_ret_leaf, NULL, 0 },
+ { "b-key", aarch_handle_pac_ret_b_key, NULL, 0 },
+ { NULL, NULL, NULL, 0 }
+};
+
+static const struct aarch_branch_protect_type aarch_branch_protect_types[] = {
+ { "none", aarch_handle_no_branch_protection, NULL, 0 },
+ { "standard", aarch_handle_standard_branch_protection, NULL, 0 },
+ { "pac-ret", aarch_handle_pac_ret_protection, aarch_pac_ret_subtypes,
+ ARRAY_SIZE (aarch_pac_ret_subtypes) },
+ { "bti", aarch_handle_bti_protection, NULL, 0 },
+ { NULL, NULL, NULL, 0 }
+};
+
+/* Parses CONST_STR for branch protection features specified in
+ aarch64_branch_protect_types, and set any global variables required. Returns
+ the parsing result and assigns LAST_STR to the last processed token from
+ CONST_STR so that it can be used for error reporting. */
+
+enum aarch_parse_opt_result
+aarch_parse_branch_protection (const char *const_str, char** last_str)
+{
+ char *str_root = xstrdup (const_str);
+ char* token_save = NULL;
+ char *str = strtok_r (str_root, "+", &token_save);
+ enum aarch_parse_opt_result res = AARCH_PARSE_OK;
+ if (!str)
+ res = AARCH_PARSE_MISSING_ARG;
+ else
+ {
+ char *next_str = strtok_r (NULL, "+", &token_save);
+ /* Reset the branch protection features to their defaults. */
+ aarch_handle_no_branch_protection (NULL, NULL);
+
+ while (str && res == AARCH_PARSE_OK)
+ {
+ const aarch_branch_protect_type* type = aarch_branch_protect_types;
+ bool found = false;
+ /* Search for this type. */
+ while (type && type->name && !found && res == AARCH_PARSE_OK)
+ {
+ if (strcmp (str, type->name) == 0)
+ {
+ found = true;
+ res = type->handler (str, next_str);
+ str = next_str;
+ next_str = strtok_r (NULL, "+", &token_save);
+ }
+ else
+ type++;
+ }
+ if (found && res == AARCH_PARSE_OK)
+ {
+ bool found_subtype = true;
+ /* Loop through each token until we find one that isn't a
+ subtype. */
+ while (found_subtype)
+ {
+ found_subtype = false;
+ const aarch_branch_protect_type *subtype = type->subtypes;
+ /* Search for the subtype. */
+ while (str && subtype && subtype->name && !found_subtype
+ && res == AARCH_PARSE_OK)
+ {
+ if (strcmp (str, subtype->name) == 0)
+ {
+ found_subtype = true;
+ res = subtype->handler (str, next_str);
+ str = next_str;
+ next_str = strtok_r (NULL, "+", &token_save);
+ }
+ else
+ subtype++;
+ }
+ }
+ }
+ else if (!found)
+ res = AARCH_PARSE_INVALID_ARG;
+ }
+ }
+ /* Copy the last processed token into the argument to pass it back.
+ Used by option and attribute validation to print the offending token. */
+ if (last_str)
+ {
+ if (str)
+ strcpy (*last_str, str);
+ else
+ *last_str = NULL;
+ }
+
+ if (res == AARCH_PARSE_OK)
+ {
+ /* If needed, alloc the accepted string then copy in const_str.
+ Used by override_option_after_change_1. */
+ if (!accepted_branch_protection_string)
+ accepted_branch_protection_string
+ = (char *) xmalloc (BRANCH_PROTECT_STR_MAX + 1);
+ strncpy (accepted_branch_protection_string, const_str,
+ BRANCH_PROTECT_STR_MAX + 1);
+ /* Forcibly null-terminate. */
+ accepted_branch_protection_string[BRANCH_PROTECT_STR_MAX] = '\0';
+ }
+ return res;
+}
+
+bool
+aarch_validate_mbranch_protection (const char *const_str)
+{
+ char *str = (char *) xmalloc (strlen (const_str));
+ enum aarch_parse_opt_result res =
+ aarch_parse_branch_protection (const_str, &str);
+ if (res == AARCH_PARSE_INVALID_ARG)
+ error ("invalid argument %<%s%> for %<-mbranch-protection=%>", str);
+ else if (res == AARCH_PARSE_MISSING_ARG)
+ error ("missing argument for %<-mbranch-protection=%>");
+ free (str);
+ return res == AARCH_PARSE_OK;
+}