[PATCH 1/15] arm: Make mbranch-protection opts parsing common to AArch32/64

Hi all,

This change refactors all the mbranch-protection option parsing code and
types to make it common to both AArch32 and AArch64 backends.

This change also pulls in some supporting types from AArch64 to make
it common (aarch_parse_opt_result).

The significant changes in this patch are the movement of all branch
protection parsing routines from aarch64.c to aarch-common.c and
supporting data types and static data structures.

This patch also pre-declares variables and types required in the
aarch32 back-end for moved variables for function sign scope and key
to prepare for the impending series of patches that support parsing
the feature mbranch-protection in the aarch32 back-end.

gcc/ChangeLog:

	* common/config/aarch64/aarch64-common.cc: Include aarch-common.h.
	(all_architectures): Fix comment.
	(aarch64_parse_extension): Rename return type, enum value names.
	* config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): Rename
	factored out aarch_ra_sign_scope and aarch_ra_sign_key variables.
	Also rename corresponding enum values.
	* config/aarch64/aarch64-opts.h (aarch64_function_type): Factor
	out aarch64_function_type and move it to common code as
	aarch_function_type in aarch-common.h.
	* config/aarch64/aarch64-protos.h: Include common types header,
	move out types aarch64_parse_opt_result and aarch64_key_type to
	aarch-common.h
	* config/aarch64/aarch64.cc: Move mbranch-protection parsing types
	and functions out into aarch-common.h and aarch-common.cc.  Fix up
	all the name changes resulting from the move.
	* config/aarch64/aarch64.md: Fix up aarch64_ra_sign_key type name change
	and enum value.
	* config/aarch64/aarch64.opt: Include aarch-common.h to import
	type move.  Fix up name changes from factoring out common code and
	data.
	* config/arm/aarch-common-protos.h: Export factored out routines to both
	backends.
	* config/arm/aarch-common.cc: Include newly factored out types.
	Move all mbranch-protection code and data structures from
	aarch64.cc.
	* config/arm/aarch-common.h: New header that declares types shared
	between aarch32 and aarch64 backends.
	* config/arm/arm-protos.h: Declare types and variables that are
	made common to aarch64 and aarch32 backends - aarch_ra_sign_key,
	aarch_ra_sign_scope and aarch_enable_bti.
	* config/arm/arm.opt (config/arm/aarch-common.h): Include header.
	(aarch_ra_sign_scope, aarch_enable_bti): Declare variable.
	* config/arm/arm.cc: Add missing includes.

Co-Authored-By: Tejas Belagod  <tbelagod@arm.com>
This commit is contained in:
Andrea Corallo 2021-12-06 11:34:35 +01:00
parent 47465fff97
commit d8dadbc9a5
13 changed files with 390 additions and 321 deletions

View File

@ -31,6 +31,7 @@
#include "flags.h"
#include "diagnostic.h"
#include "config/aarch64/aarch64-feature-deps.h"
#include "config/arm/aarch-common.h"
#ifdef TARGET_BIG_ENDIAN_DEFAULT
#undef TARGET_DEFAULT_TARGET_FLAGS
@ -191,13 +192,13 @@ static constexpr 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.
aarch_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 aarch_parse_opt_result
aarch64_parse_extension (const char *str, aarch64_feature_flags *isa_flags,
std::string *invalid_extension)
std::string *invalid_extension)
{
/* The extension string is parsed left to right. */
const struct aarch64_option_extension *opt = NULL;
@ -228,7 +229,7 @@ aarch64_parse_extension (const char *str, aarch64_feature_flags *isa_flags,
adding_ext = 1;
if (len == 0)
return AARCH64_PARSE_MISSING_ARG;
return AARCH_PARSE_MISSING_ARG;
/* Scan over the extensions table trying to find an exact match. */
@ -250,13 +251,13 @@ aarch64_parse_extension (const char *str, aarch64_feature_flags *isa_flags,
/* Extension not found in list. */
if (invalid_extension)
*invalid_extension = std::string (str, len);
return AARCH64_PARSE_INVALID_FEATURE;
return AARCH_PARSE_INVALID_FEATURE;
}
str = ext;
};
return AARCH64_PARSE_OK;
return AARCH_PARSE_OK;
}
/* Append all architecture extension candidates to the CANDIDATES vector. */

View File

@ -183,14 +183,14 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
"__ARM_FEATURE_BTI_DEFAULT", pfile);
cpp_undef (pfile, "__ARM_FEATURE_PAC_DEFAULT");
if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE)
if (aarch_ra_sign_scope != AARCH_FUNCTION_NONE)
{
int v = 0;
if (aarch64_ra_sign_key == AARCH64_KEY_A)
if (aarch_ra_sign_key == AARCH_KEY_A)
v |= 1;
if (aarch64_ra_sign_key == AARCH64_KEY_B)
if (aarch_ra_sign_key == AARCH_KEY_B)
v |= 2;
if (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL)
if (aarch_ra_sign_scope == AARCH_FUNCTION_ALL)
v |= 4;
builtin_define_with_int_value ("__ARM_FEATURE_PAC_DEFAULT", v);
}

View File

@ -75,16 +75,6 @@ enum aarch64_code_model {
AARCH64_CMODEL_LARGE
};
/* Function types -msign-return-address should sign. */
enum aarch64_function_type {
/* Don't sign any function. */
AARCH64_FUNCTION_NONE,
/* Non-leaf functions. */
AARCH64_FUNCTION_NON_LEAF,
/* All functions. */
AARCH64_FUNCTION_ALL
};
/* SVE vector register sizes. */
enum aarch64_sve_vector_bits_enum {
SVE_SCALABLE,

View File

@ -23,6 +23,7 @@
#define GCC_AARCH64_PROTOS_H
#include "input.h"
#include "config/arm/aarch-common.h"
/* SYMBOL_SMALL_ABSOLUTE: Generate symbol accesses through
high and lo relocs that calculate the base address using a PC
@ -651,18 +652,6 @@ enum aarch64_extra_tuning_flags
AARCH64_EXTRA_TUNE_ALL = (1u << AARCH64_EXTRA_TUNE_index_END) - 1
};
/* Enum describing the various ways that the
aarch64_parse_{arch,tune,cpu,extension} functions can fail.
This way their callers can choose what kind of error to give. */
enum aarch64_parse_opt_result
{
AARCH64_PARSE_OK, /* Parsing was successful. */
AARCH64_PARSE_MISSING_ARG, /* Missing argument. */
AARCH64_PARSE_INVALID_FEATURE, /* Invalid feature modifier. */
AARCH64_PARSE_INVALID_ARG /* Invalid arch, tune, cpu arg. */
};
/* Enum to distinguish which type of check is to be done in
aarch64_simd_valid_immediate. This is used as a bitmask where
AARCH64_CHECK_MOV has both bits set. Thus AARCH64_CHECK_MOV will
@ -673,6 +662,8 @@ enum simd_immediate_check {
AARCH64_CHECK_MOV = AARCH64_CHECK_ORR | AARCH64_CHECK_BIC
};
extern enum aarch_key_type aarch_ra_sign_key;
extern struct tune_params aarch64_tune_params;
/* The available SVE predicate patterns, known in the ACLE as "svpattern". */
@ -1038,9 +1029,9 @@ void aarch64_set_asm_isa_flags (gcc_options *, aarch64_feature_flags);
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 *,
aarch64_feature_flags *,
std::string *);
enum aarch_parse_opt_result aarch64_parse_extension (const char *,
aarch64_feature_flags *,
std::string *);
void aarch64_get_all_extension_candidates (auto_vec<const char *> *candidates);
std::string aarch64_get_extension_string_for_isa_flags (aarch64_feature_flags,
aarch64_feature_flags);

View File

@ -82,6 +82,8 @@
#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"
@ -318,12 +320,8 @@ bool aarch64_pcrelative_literal_loads;
/* 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
@ -2761,6 +2759,8 @@ static const struct processor all_cores[] =
{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;
@ -2826,100 +2826,6 @@ aarch64_cc;
#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[] =
@ -9020,10 +8926,10 @@ aarch64_return_address_signing_enabled (void)
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)));
}
@ -9031,7 +8937,7 @@ aarch64_return_address_signing_enabled (void)
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
@ -10023,12 +9929,12 @@ aarch64_expand_prologue (void)
/* 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:
@ -10329,12 +10235,12 @@ aarch64_expand_epilogue (bool for_sibcall)
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:
@ -17359,12 +17265,12 @@ 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.
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)
@ -17381,7 +17287,7 @@ aarch64_parse_arch (const char *to_parse, const struct processor **res,
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. */
@ -17395,32 +17301,32 @@ aarch64_parse_arch (const char *to_parse, const struct processor **res,
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)
@ -17437,7 +17343,7 @@ aarch64_parse_cpu (const char *to_parse, const struct processor **res,
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. */
@ -17450,29 +17356,29 @@ aarch64_parse_cpu (const char *to_parse, const struct processor **res,
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;
@ -17483,12 +17389,12 @@ aarch64_parse_tune (const char *to_parse, const struct processor **res)
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
@ -18079,22 +17985,22 @@ aarch64_validate_mcpu (const char *str, const struct processor **res,
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);
@ -18179,110 +18085,6 @@ aarch64_validate_sls_mitigation (const char *const_str)
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
@ -18293,27 +18095,27 @@ aarch64_validate_march (const char *str, const struct processor **res,
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);
@ -18333,18 +18135,18 @@ aarch64_validate_march (const char *str, const struct processor **res,
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;
@ -18406,7 +18208,7 @@ aarch64_override_options (void)
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
@ -18459,12 +18261,12 @@ aarch64_override_options (void)
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
}
@ -18474,9 +18276,9 @@ aarch64_override_options (void)
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
}
@ -18490,7 +18292,7 @@ aarch64_override_options (void)
/* 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
@ -18705,10 +18507,10 @@ aarch64_handle_attr_arch (const char *str)
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;
@ -18718,14 +18520,14 @@ aarch64_handle_attr_arch (const char *str)
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);
@ -18745,10 +18547,10 @@ aarch64_handle_attr_cpu (const char *str)
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;
@ -18759,14 +18561,14 @@ aarch64_handle_attr_cpu (const char *str)
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);
@ -18784,23 +18586,23 @@ aarch64_handle_attr_cpu (const char *str)
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 ();
@ -18815,10 +18617,10 @@ static bool
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;
@ -18827,7 +18629,7 @@ aarch64_handle_attr_tune (const char *str)
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;
@ -18846,7 +18648,7 @@ aarch64_handle_attr_tune (const char *str)
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
@ -18860,7 +18662,7 @@ aarch64_handle_attr_isa_flags (char *str)
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;
@ -18868,11 +18670,11 @@ aarch64_handle_attr_isa_flags (char *str)
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;
@ -19121,10 +18923,10 @@ aarch64_process_target_attr (tree args)
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
@ -22896,7 +22698,7 @@ void
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");
}
@ -27308,7 +27110,7 @@ aarch64_file_end_indicate_exec_stack ()
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)

View File

@ -891,7 +891,7 @@
if (aarch64_return_address_signing_enabled ()
&& (TARGET_PAUTH))
{
if (aarch64_ra_sign_key == AARCH64_KEY_B)
if (aarch_ra_sign_key == AARCH_KEY_B)
ret = "retab";
else
ret = "retaa";

View File

@ -21,6 +21,9 @@
HeaderInclude
config/aarch64/aarch64-opts.h
HeaderInclude
config/arm/aarch-common.h
TargetVariable
enum aarch64_processor selected_tune = aarch64_none
@ -34,7 +37,7 @@ TargetVariable
aarch64_feature_flags aarch64_isa_flags = 0
TargetVariable
unsigned aarch64_enable_bti = 2
unsigned aarch_enable_bti = 2
TargetVariable
enum aarch64_key_type aarch64_ra_sign_key = AARCH64_KEY_A
@ -164,21 +167,21 @@ Target RejectNegative Joined Var(aarch64_branch_protection_string) Save
Use branch-protection features.
msign-return-address=
Target WarnRemoved RejectNegative Joined Enum(aarch64_ra_sign_scope_t) Var(aarch64_ra_sign_scope) Init(AARCH64_FUNCTION_NONE) Save
Target WarnRemoved RejectNegative Joined Enum(aarch_ra_sign_scope_t) Var(aarch_ra_sign_scope) Init(AARCH_FUNCTION_NONE) Save
Select return address signing scope.
Enum
Name(aarch64_ra_sign_scope_t) Type(enum aarch64_function_type)
Name(aarch_ra_sign_scope_t) Type(enum aarch_function_type)
Supported AArch64 return address signing scope (for use with -msign-return-address= option):
EnumValue
Enum(aarch64_ra_sign_scope_t) String(none) Value(AARCH64_FUNCTION_NONE)
Enum(aarch_ra_sign_scope_t) String(none) Value(AARCH_FUNCTION_NONE)
EnumValue
Enum(aarch64_ra_sign_scope_t) String(non-leaf) Value(AARCH64_FUNCTION_NON_LEAF)
Enum(aarch_ra_sign_scope_t) String(non-leaf) Value(AARCH_FUNCTION_NON_LEAF)
EnumValue
Enum(aarch64_ra_sign_scope_t) String(all) Value(AARCH64_FUNCTION_ALL)
Enum(aarch_ra_sign_scope_t) String(all) Value(AARCH_FUNCTION_ALL)
mlow-precision-recip-sqrt
Target Var(flag_mrecip_low_precision_sqrt) Optimization

View File

@ -153,4 +153,10 @@ rtx_insn *arm_md_asm_adjust (vec<rtx> &outputs, vec<rtx> & /*inputs*/,
vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs,
location_t loc);
/* Parsing routine for branch-protection common to AArch64 and Arm. */
enum aarch_parse_opt_result aarch_parse_branch_protection (const char*, char**);
/* Validation routine for branch-protection common to AArch64 and Arm. */
bool aarch_validate_mbranch_protection (const char *);
#endif /* GCC_AARCH_COMMON_PROTOS_H */

View File

@ -36,6 +36,7 @@
#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. */
@ -657,3 +658,187 @@ arm_md_asm_adjust (vec<rtx> &outputs, vec<rtx> & /*inputs*/,
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;
}

View File

@ -0,0 +1,73 @@
/* Types shared between arm and aarch64.
Copyright (C) 2009-2021 Free Software Foundation, Inc.
Contributed by Arm Ltd.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 3, or (at your
option) any later version.
GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_AARCH_COMMON_H
#define GCC_AARCH_COMMON_H
/* Enum describing the various ways that the
aarch*_parse_{arch,tune,cpu,extension} functions can fail.
This way their callers can choose what kind of error to give. */
enum aarch_parse_opt_result
{
AARCH_PARSE_OK, /* Parsing was successful. */
AARCH_PARSE_MISSING_ARG, /* Missing argument. */
AARCH_PARSE_INVALID_FEATURE, /* Invalid feature modifier. */
AARCH_PARSE_INVALID_ARG /* Invalid arch, tune, cpu arg. */
};
/* Function types -msign-return-address should sign. */
enum aarch_function_type {
/* Don't sign any function. */
AARCH_FUNCTION_NONE,
/* Non-leaf functions. */
AARCH_FUNCTION_NON_LEAF,
/* All functions. */
AARCH_FUNCTION_ALL
};
/* The key type that -msign-return-address should use. */
enum aarch_key_type {
AARCH_KEY_A,
AARCH_KEY_B
};
struct aarch_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:
* AARCH_PARSE_OK: Handling was sucessful.
* AARCH_INVALID_ARG: The type is invalid in this context and the caller
should print an error.
* AARCH_INVALID_FEATURE: The type is invalid and the handler prints its
own error. */
enum aarch_parse_opt_result (*handler)(char*, char*);
/* A list of types that can follow this type in the option string. */
const struct aarch_branch_protect_type* subtypes;
unsigned int num_subtypes;
};
#endif /* GCC_AARCH_COMMON_H */

View File

@ -582,6 +582,8 @@ struct cpu_option
extern const arch_option all_architectures[];
extern const cpu_option all_cores[];
extern enum aarch_key_type aarch_ra_sign_key;
const cpu_option *arm_parse_cpu_option_name (const cpu_option *, const char *,
const char *, bool = true);
const arch_option *arm_parse_arch_option_name (const arch_option *,

View File

@ -72,6 +72,8 @@
#include "selftest.h"
#include "tree-vectorizer.h"
#include "opts.h"
#include "aarch-common.h"
#include "aarch-common-protos.h"
/* This file should be included last. */
#include "target-def.h"
@ -2413,6 +2415,11 @@ const struct tune_params arm_fa726te_tune =
tune_params::SCHED_AUTOPREF_OFF
};
/* Key type for Pointer Authentication extension. */
enum aarch_key_type aarch_ra_sign_key = AARCH_KEY_A;
char *accepted_branch_protection_string = NULL;
/* Auto-generated CPU, FPU and architecture tables. */
#include "arm-cpu-data.h"

View File

@ -21,6 +21,15 @@
HeaderInclude
config/arm/arm-opts.h
HeaderInclude
config/arm/aarch-common.h
TargetVariable
enum aarch_function_type aarch_ra_sign_scope = AARCH_FUNCTION_NONE
TargetVariable
unsigned aarch_enable_bti = 0
Enum
Name(tls_type) Type(enum arm_tls_type)
TLS dialect to use: