Commit 97b0656d by Andre Vieira Committed by Andre Vieira

Handling ARMv8-M Security Extension's cmse_nonsecure_entry attribute

    gcc/ChangeLog:
    2016-12-02  Andre Vieira  <andre.simoesdiasvieira@arm.com>
	    Thomas Preud'homme  <thomas.preudhomme@arm.com>

	* config/arm/arm.c (arm_handle_cmse_nonsecure_entry): New.
	(arm_attribute_table): Added cmse_nonsecure_entry
	(arm_compute_func_type): Handle cmse_nonsecure_entry.
	(cmse_func_args_or_return_in_stack): New.
	(arm_handle_cmse_nonsecure_entry): New.
	* config/arm/arm.h (ARM_FT_CMSE_ENTRY): New macro define.
	(IS_CMSE_ENTRY): Likewise.
	* doc/extend.texi (ARM ARMv8-M Security Extensions): New attribute.

    gcc/testsuite/ChangeLog:
    2016-12-02  Andre Vieira  <andre.simoesdiasvieira@arm.com>
	    Thomas Preud'homme  <thomas.preudhomme@arm.com>

	* gcc.target/arm/cmse/cmse-3.c: New.


Co-Authored-By: Thomas Preud'homme <thomas.preudhomme@arm.com>

From-SVN: r243188
parent de7b5723
2016-12-02 Andre Vieira <andre.simoesdiasvieira@arm.com> 2016-12-02 Andre Vieira <andre.simoesdiasvieira@arm.com>
Thomas Preud'homme <thomas.preudhomme@arm.com> Thomas Preud'homme <thomas.preudhomme@arm.com>
* config/arm/arm.c (arm_handle_cmse_nonsecure_entry): New.
(arm_attribute_table): Added cmse_nonsecure_entry
(arm_compute_func_type): Handle cmse_nonsecure_entry.
(cmse_func_args_or_return_in_stack): New.
(arm_handle_cmse_nonsecure_entry): New.
* config/arm/arm.h (ARM_FT_CMSE_ENTRY): New macro define.
(IS_CMSE_ENTRY): Likewise.
* doc/extend.texi (ARM ARMv8-M Security Extensions): New attribute.
2016-12-02 Andre Vieira <andre.simoesdiasvieira@arm.com>
Thomas Preud'homme <thomas.preudhomme@arm.com>
* config.gcc (extra_headers): Added arm_cmse.h. * config.gcc (extra_headers): Added arm_cmse.h.
* config/arm/arm-arches.def (ARM_ARCH): * config/arm/arm-arches.def (ARM_ARCH):
(armv8-m): Add FL2_CMSE. (armv8-m): Add FL2_CMSE.
...@@ -136,6 +136,7 @@ static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *); ...@@ -136,6 +136,7 @@ static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *);
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
static tree arm_handle_notshared_attribute (tree *, tree, tree, int, bool *); static tree arm_handle_notshared_attribute (tree *, tree, tree, int, bool *);
#endif #endif
static tree arm_handle_cmse_nonsecure_entry (tree *, tree, tree, int, bool *);
static void arm_output_function_epilogue (FILE *, HOST_WIDE_INT); static void arm_output_function_epilogue (FILE *, HOST_WIDE_INT);
static void arm_output_function_prologue (FILE *, HOST_WIDE_INT); static void arm_output_function_prologue (FILE *, HOST_WIDE_INT);
static int arm_comp_type_attributes (const_tree, const_tree); static int arm_comp_type_attributes (const_tree, const_tree);
...@@ -344,6 +345,9 @@ static const struct attribute_spec arm_attribute_table[] = ...@@ -344,6 +345,9 @@ static const struct attribute_spec arm_attribute_table[] =
{ "notshared", 0, 0, false, true, false, arm_handle_notshared_attribute, { "notshared", 0, 0, false, true, false, arm_handle_notshared_attribute,
false }, false },
#endif #endif
/* ARMv8-M Security Extensions support. */
{ "cmse_nonsecure_entry", 0, 0, true, false, false,
arm_handle_cmse_nonsecure_entry, false },
{ NULL, 0, 0, false, false, false, NULL, false } { NULL, 0, 0, false, false, false, NULL, false }
}; };
...@@ -3633,6 +3637,9 @@ arm_compute_func_type (void) ...@@ -3633,6 +3637,9 @@ arm_compute_func_type (void)
else else
type |= arm_isr_value (TREE_VALUE (a)); type |= arm_isr_value (TREE_VALUE (a));
if (lookup_attribute ("cmse_nonsecure_entry", attr))
type |= ARM_FT_CMSE_ENTRY;
return type; return type;
} }
...@@ -6634,6 +6641,113 @@ arm_handle_notshared_attribute (tree *node, ...@@ -6634,6 +6641,113 @@ arm_handle_notshared_attribute (tree *node,
} }
#endif #endif
/* This function returns true if a function with declaration FNDECL and type
FNTYPE uses the stack to pass arguments or return variables and false
otherwise. This is used for functions with the attributes
'cmse_nonsecure_call' or 'cmse_nonsecure_entry' and this function will issue
diagnostic messages if the stack is used. NAME is the name of the attribute
used. */
static bool
cmse_func_args_or_return_in_stack (tree fndecl, tree name, tree fntype)
{
function_args_iterator args_iter;
CUMULATIVE_ARGS args_so_far_v;
cumulative_args_t args_so_far;
bool first_param = true;
tree arg_type, prev_arg_type = NULL_TREE, ret_type;
/* Error out if any argument is passed on the stack. */
arm_init_cumulative_args (&args_so_far_v, fntype, NULL_RTX, fndecl);
args_so_far = pack_cumulative_args (&args_so_far_v);
FOREACH_FUNCTION_ARGS (fntype, arg_type, args_iter)
{
rtx arg_rtx;
machine_mode arg_mode = TYPE_MODE (arg_type);
prev_arg_type = arg_type;
if (VOID_TYPE_P (arg_type))
continue;
if (!first_param)
arm_function_arg_advance (args_so_far, arg_mode, arg_type, true);
arg_rtx = arm_function_arg (args_so_far, arg_mode, arg_type, true);
if (!arg_rtx
|| arm_arg_partial_bytes (args_so_far, arg_mode, arg_type, true))
{
error ("%qE attribute not available to functions with arguments "
"passed on the stack", name);
return true;
}
first_param = false;
}
/* Error out for variadic functions since we cannot control how many
arguments will be passed and thus stack could be used. stdarg_p () is not
used for the checking to avoid browsing arguments twice. */
if (prev_arg_type != NULL_TREE && !VOID_TYPE_P (prev_arg_type))
{
error ("%qE attribute not available to functions with variable number "
"of arguments", name);
return true;
}
/* Error out if return value is passed on the stack. */
ret_type = TREE_TYPE (fntype);
if (arm_return_in_memory (ret_type, fntype))
{
error ("%qE attribute not available to functions that return value on "
"the stack", name);
return true;
}
return false;
}
/* Called upon detection of the use of the cmse_nonsecure_entry attribute, this
function will check whether the attribute is allowed here and will add the
attribute to the function declaration tree or otherwise issue a warning. */
static tree
arm_handle_cmse_nonsecure_entry (tree *node, tree name,
tree /* args */,
int /* flags */,
bool *no_add_attrs)
{
tree fndecl;
if (!use_cmse)
{
*no_add_attrs = true;
warning (OPT_Wattributes, "%qE attribute ignored without -mcmse option.",
name);
return NULL_TREE;
}
/* Ignore attribute for function types. */
if (TREE_CODE (*node) != FUNCTION_DECL)
{
warning (OPT_Wattributes, "%qE attribute only applies to functions",
name);
*no_add_attrs = true;
return NULL_TREE;
}
fndecl = *node;
/* Warn for static linkage functions. */
if (!TREE_PUBLIC (fndecl))
{
warning (OPT_Wattributes, "%qE attribute has no effect on functions "
"with static linkage", name);
*no_add_attrs = true;
return NULL_TREE;
}
*no_add_attrs |= cmse_func_args_or_return_in_stack (fndecl, name,
TREE_TYPE (fndecl));
return NULL_TREE;
}
/* Return 0 if the attributes for two types are incompatible, 1 if they /* Return 0 if the attributes for two types are incompatible, 1 if they
are compatible, and 2 if they are nearly compatible (which causes a are compatible, and 2 if they are nearly compatible (which causes a
warning to be generated). */ warning to be generated). */
......
...@@ -1385,6 +1385,7 @@ enum reg_class ...@@ -1385,6 +1385,7 @@ enum reg_class
#define ARM_FT_VOLATILE (1 << 4) /* Does not return. */ #define ARM_FT_VOLATILE (1 << 4) /* Does not return. */
#define ARM_FT_NESTED (1 << 5) /* Embedded inside another func. */ #define ARM_FT_NESTED (1 << 5) /* Embedded inside another func. */
#define ARM_FT_STACKALIGN (1 << 6) /* Called with misaligned stack. */ #define ARM_FT_STACKALIGN (1 << 6) /* Called with misaligned stack. */
#define ARM_FT_CMSE_ENTRY (1 << 7) /* ARMv8-M non-secure entry function. */
/* Some macros to test these flags. */ /* Some macros to test these flags. */
#define ARM_FUNC_TYPE(t) (t & ARM_FT_TYPE_MASK) #define ARM_FUNC_TYPE(t) (t & ARM_FT_TYPE_MASK)
...@@ -1393,6 +1394,7 @@ enum reg_class ...@@ -1393,6 +1394,7 @@ enum reg_class
#define IS_NAKED(t) (t & ARM_FT_NAKED) #define IS_NAKED(t) (t & ARM_FT_NAKED)
#define IS_NESTED(t) (t & ARM_FT_NESTED) #define IS_NESTED(t) (t & ARM_FT_NESTED)
#define IS_STACKALIGN(t) (t & ARM_FT_STACKALIGN) #define IS_STACKALIGN(t) (t & ARM_FT_STACKALIGN)
#define IS_CMSE_ENTRY(t) (t & ARM_FT_CMSE_ENTRY)
/* Structure used to hold the function stack frame layout. Offsets are /* Structure used to hold the function stack frame layout. Offsets are
......
...@@ -12648,6 +12648,9 @@ Security Extensions: Requiremenets on Development Tools Engineering ...@@ -12648,6 +12648,9 @@ Security Extensions: Requiremenets on Development Tools Engineering
Specification, which can be found at Specification, which can be found at
@uref{http://infocenter.arm.com/help/topic/com.arm.doc.ecm0359818/ECM0359818_armv8m_security_extensions_reqs_on_dev_tools_1_0.pdf}. @uref{http://infocenter.arm.com/help/topic/com.arm.doc.ecm0359818/ECM0359818_armv8m_security_extensions_reqs_on_dev_tools_1_0.pdf}.
As part of the Security Extensions GCC implements a new function attribute
@code{cmse_nonsecure_entry}.
As part of the Security Extensions GCC implements the intrinsics below. FPTR As part of the Security Extensions GCC implements the intrinsics below. FPTR
is used here to mean any function pointer type. is used here to mean any function pointer type.
......
2016-12-02 Andre Vieira <andre.simoesdiasvieira@arm.com> 2016-12-02 Andre Vieira <andre.simoesdiasvieira@arm.com>
Thomas Preud'homme <thomas.preudhomme@arm.com> Thomas Preud'homme <thomas.preudhomme@arm.com>
* gcc.target/arm/cmse/cmse-3.c: New.
2016-12-02 Andre Vieira <andre.simoesdiasvieira@arm.com>
Thomas Preud'homme <thomas.preudhomme@arm.com>
* gcc.target/arm/cmse/cmse.exp: New. * gcc.target/arm/cmse/cmse.exp: New.
* gcc.target/arm/cmse/cmse-1.c: New. * gcc.target/arm/cmse/cmse-1.c: New.
* gcc.target/arm/cmse/cmse-12.c: New. * gcc.target/arm/cmse/cmse-12.c: New.
......
/* { dg-do compile } */
/* { dg-options "-mcmse" } */
struct span {
int a, b;
};
struct span2 {
float a, b, c, d;
};
union test_union
{
long long a;
int b;
struct span2 c;
} test_union;
void __attribute__ ((cmse_nonsecure_entry))
foo (long long a, int b, long long c) {} /* { dg-error "not available to functions with arguments passed on the stack" } */
void __attribute__ ((cmse_nonsecure_entry))
bar (long long a, int b, struct span c) {} /* { dg-error "not available to functions with arguments passed on the stack" } */
void __attribute__ ((cmse_nonsecure_entry))
baz (int a, ...) {} /* { dg-error "not available to functions with variable number of arguments" } */
struct span __attribute__ ((cmse_nonsecure_entry))
qux (void) { /* { dg-error "not available to functions that return value on the stack" } */
struct span ret = {0, 0};
return ret;
}
void __attribute__ ((cmse_nonsecure_entry))
norf (struct span2 a) {}
void __attribute__ ((cmse_nonsecure_entry))
foo2 (long long a, int b, union test_union c) {} /* { dg-error "not available to functions with arguments passed on the stack" } */
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