aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/sh/sh.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/sh/sh.c')
-rw-r--r--gcc/config/sh/sh.c142
1 files changed, 96 insertions, 46 deletions
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 29a657b..684cff1 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -154,15 +154,18 @@ static int calc_live_regs PARAMS ((int *, int *));
static void mark_use PARAMS ((rtx, rtx *));
static HOST_WIDE_INT rounded_frame_size PARAMS ((int));
static rtx mark_constant_pool_use PARAMS ((rtx));
-static int sh_valid_decl_attribute PARAMS ((tree, tree, tree, tree));
+const struct attribute_spec sh_attribute_table[];
+static tree sh_handle_interrupt_handler_attribute PARAMS ((tree *, tree, tree, int, bool *));
+static tree sh_handle_sp_switch_attribute PARAMS ((tree *, tree, tree, int, bool *));
+static tree sh_handle_trap_exit_attribute PARAMS ((tree *, tree, tree, int, bool *));
static void sh_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
static void sh_insert_attributes PARAMS ((tree, tree *));
static void sh_asm_named_section PARAMS ((const char *, unsigned int));
static int sh_adjust_cost PARAMS ((rtx, rtx, rtx, int));
/* Initialize the GCC target structure. */
-#undef TARGET_VALID_DECL_ATTRIBUTE
-#define TARGET_VALID_DECL_ATTRIBUTE sh_valid_decl_attribute
+#undef TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE sh_attribute_table
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE sh_output_function_epilogue
@@ -269,7 +272,7 @@ print_operand (stream, x, code)
if ((lookup_attribute
("interrupt_handler",
- DECL_MACHINE_ATTRIBUTES (current_function_decl)))
+ DECL_ATTRIBUTES (current_function_decl)))
!= NULL_TREE)
interrupt_handler = 1;
else
@@ -3964,7 +3967,7 @@ calc_live_regs (count_ptr, live_regs_mask2)
if ((lookup_attribute
("interrupt_handler",
- DECL_MACHINE_ATTRIBUTES (current_function_decl)))
+ DECL_ATTRIBUTES (current_function_decl)))
!= NULL_TREE)
interrupt_handler = 1;
else
@@ -4058,7 +4061,7 @@ sh_expand_prologue ()
current_function_interrupt
= lookup_attribute ("interrupt_handler",
- DECL_MACHINE_ATTRIBUTES (current_function_decl))
+ DECL_ATTRIBUTES (current_function_decl))
!= NULL_TREE;
/* We have pretend args if we had an object sent partially in registers
@@ -4656,11 +4659,7 @@ sh_insert_attributes (node, attributes)
return;
}
-/* Return nonzero if ATTR is a valid attribute for DECL.
- ATTRIBUTES are any existing attributes and ARGS are the arguments
- supplied with ATTR.
-
- Supported attributes:
+/* Supported attributes:
interrupt_handler -- specifies this function is an interrupt handler.
@@ -4670,59 +4669,110 @@ sh_insert_attributes (node, attributes)
trap_exit -- use a trapa to exit an interrupt function instead of
an rte instruction. */
-static int
-sh_valid_decl_attribute (decl, attributes, attr, args)
- tree decl;
- tree attributes ATTRIBUTE_UNUSED;
- tree attr;
- tree args;
+const struct attribute_spec sh_attribute_table[] =
{
- if (TREE_CODE (decl) != FUNCTION_DECL)
- return 0;
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+ { "interrupt_handler", 0, 0, true, false, false, sh_handle_interrupt_handler_attribute },
+ { "sp_switch", 1, 1, true, false, false, sh_handle_sp_switch_attribute },
+ { "trap_exit", 1, 1, true, false, false, sh_handle_trap_exit_attribute },
+ { NULL, 0, 0, false, false, false, NULL }
+};
- if (is_attribute_p ("interrupt_handler", attr))
+/* Handle an "interrupt_handler" attribute; arguments as in
+ struct attribute_spec.handler. */
+static tree
+sh_handle_interrupt_handler_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
{
- return 1;
+ warning ("`%s' attribute only applies to functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
}
- if (is_attribute_p ("sp_switch", attr))
+ return NULL_TREE;
+}
+
+/* Handle an "sp_switch" attribute; arguments as in
+ struct attribute_spec.handler. */
+static tree
+sh_handle_sp_switch_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning ("`%s' attribute only applies to functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else if (!pragma_interrupt)
{
/* The sp_switch attribute only has meaning for interrupt functions. */
- if (!pragma_interrupt)
- return 0;
-
- /* sp_switch must have an argument. */
- if (!args || TREE_CODE (args) != TREE_LIST)
- return 0;
-
+ warning ("`%s' attribute only applies to interrupt functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
+ {
/* The argument must be a constant string. */
- if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
- return 0;
-
+ warning ("`%s' attribute argument not a string constant",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else
+ {
sp_switch = gen_rtx_SYMBOL_REF (VOIDmode,
TREE_STRING_POINTER (TREE_VALUE (args)));
- return 1;
}
- if (is_attribute_p ("trap_exit", attr))
+ return NULL_TREE;
+}
+
+/* Handle an "trap_exit" attribute; arguments as in
+ struct attribute_spec.handler. */
+static tree
+sh_handle_trap_exit_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning ("`%s' attribute only applies to functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else if (!pragma_interrupt)
{
/* The trap_exit attribute only has meaning for interrupt functions. */
- if (!pragma_interrupt)
- return 0;
-
- /* trap_exit must have an argument. */
- if (!args || TREE_CODE (args) != TREE_LIST)
- return 0;
-
+ warning ("`%s' attribute only applies to interrupt functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
+ {
/* The argument must be a constant integer. */
- if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
- return 0;
-
+ warning ("`%s' attribute argument not an integer constant",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else
+ {
trap_exit = TREE_INT_CST_LOW (TREE_VALUE (args));
- return 1;
}
- return 0;
+ return NULL_TREE;
}