aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/arm/arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r--gcc/config/arm/arm.c233
1 files changed, 113 insertions, 120 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 1ad558e..fcd90dd 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -103,10 +103,9 @@ static int current_file_function_operand PARAMS ((rtx));
static Ulong arm_compute_save_reg_mask PARAMS ((void));
static Ulong arm_isr_value PARAMS ((tree));
static Ulong arm_compute_func_type PARAMS ((void));
-static int arm_valid_type_attribute_p PARAMS ((tree, tree,
- tree, tree));
-static int arm_valid_decl_attribute_p PARAMS ((tree, tree,
- tree, tree));
+static tree arm_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
+static tree arm_handle_isr_attribute PARAMS ((tree *, tree, tree, int, bool *));
+const struct attribute_spec arm_attribute_table[];
static void arm_output_function_epilogue PARAMS ((FILE *,
HOST_WIDE_INT));
static void arm_output_function_prologue PARAMS ((FILE *,
@@ -130,16 +129,8 @@ static int arm_adjust_cost PARAMS ((rtx, rtx, rtx, int));
#define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
#endif
-#undef TARGET_VALID_TYPE_ATTRIBUTE
-#define TARGET_VALID_TYPE_ATTRIBUTE arm_valid_type_attribute_p
-
-#undef TARGET_VALID_DECL_ATTRIBUTE
-#ifdef ARM_PE
- static int arm_pe_valid_decl_attribute_p PARAMS ((tree, tree, tree, tree));
-# define TARGET_VALID_DECL_ATTRIBUTE arm_pe_valid_decl_attribute_p
-#else
-# define TARGET_VALID_DECL_ATTRIBUTE arm_valid_decl_attribute_p
-#endif
+#undef TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE arm_attribute_table
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE arm_output_function_prologue
@@ -845,7 +836,7 @@ arm_compute_func_type ()
if (current_function_needs_context)
type |= ARM_FT_NESTED;
- attr = DECL_MACHINE_ATTRIBUTES (current_function_decl);
+ attr = DECL_ATTRIBUTES (current_function_decl);
a = lookup_attribute ("naked", attr);
if (a != NULL_TREE)
@@ -1909,39 +1900,120 @@ arm_pr_long_calls_off (pfile)
}
-/* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine
- specific attribute for TYPE. The attributes in ATTRIBUTES have
- previously been assigned to TYPE. */
-static int
-arm_valid_type_attribute_p (type, attributes, identifier, args)
- tree type;
- tree attributes ATTRIBUTE_UNUSED;
- tree identifier;
- tree args;
+/* Table of machine attributes. */
+const struct attribute_spec arm_attribute_table[] =
{
- if ( TREE_CODE (type) != FUNCTION_TYPE
- && TREE_CODE (type) != METHOD_TYPE
- && TREE_CODE (type) != FIELD_DECL
- && TREE_CODE (type) != TYPE_DECL)
- return 0;
-
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
/* Function calls made to this symbol must be done indirectly, because
it may lie outside of the 26 bit addressing range of a normal function
call. */
- if (is_attribute_p ("long_call", identifier))
- return (args == NULL_TREE);
-
+ { "long_call", 0, 0, false, true, true, NULL },
/* Whereas these functions are always known to reside within the 26 bit
addressing range. */
- if (is_attribute_p ("short_call", identifier))
- return (args == NULL_TREE);
-
+ { "short_call", 0, 0, false, true, true, NULL },
/* Interrupt Service Routines have special prologue and epilogue requirements. */
- if (is_attribute_p ("isr", identifier)
- || is_attribute_p ("interrupt", identifier))
- return arm_isr_value (args);
+ { "isr", 0, 1, false, false, false, arm_handle_isr_attribute },
+ { "interrupt", 0, 1, false, false, false, arm_handle_isr_attribute },
+ { "naked", 0, 0, true, false, false, arm_handle_fndecl_attribute },
+#ifdef ARM_PE
+ /* ARM/PE has three new attributes:
+ interfacearm - ?
+ dllexport - for exporting a function/variable that will live in a dll
+ dllimport - for importing a function/variable from a dll
+
+ Microsoft allows multiple declspecs in one __declspec, separating
+ them with spaces. We do NOT support this. Instead, use __declspec
+ multiple times.
+ */
+ { "dllimport", 0, 0, true, false, false, NULL },
+ { "dllexport", 0, 0, true, false, false, NULL },
+ { "interfacearm", 0, 0, true, false, false, arm_handle_fndecl_attribute },
+#endif
+ { NULL, 0, 0, false, false, false, NULL }
+};
- return 0;
+/* Handle an attribute requiring a FUNCTION_DECL;
+ arguments as in struct attribute_spec.handler. */
+static tree
+arm_handle_fndecl_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)
+ {
+ warning ("`%s' attribute only applies to functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle an "interrupt" or "isr" attribute;
+ arguments as in struct attribute_spec.handler. */
+static tree
+arm_handle_isr_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args;
+ int flags;
+ bool *no_add_attrs;
+{
+ if (DECL_P (*node))
+ {
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning ("`%s' attribute only applies to functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ /* FIXME: the argument if any is checked for type attributes;
+ should it be checked for decl ones? */
+ }
+ else
+ {
+ if (TREE_CODE (*node) == FUNCTION_TYPE
+ || TREE_CODE (*node) == METHOD_TYPE)
+ {
+ if (arm_isr_value (args) == ARM_FT_UNKNOWN)
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ }
+ else if (TREE_CODE (*node) == POINTER_TYPE
+ && (TREE_CODE (TREE_TYPE (*node)) == FUNCTION_TYPE
+ || TREE_CODE (TREE_TYPE (*node)) == METHOD_TYPE)
+ && arm_isr_value (args) != ARM_FT_UNKNOWN)
+ {
+ *node = build_type_copy (*node);
+ TREE_TYPE (*node) = build_type_attribute_variant (TREE_TYPE (*node),
+ tree_cons (name,
+ args,
+ TYPE_ATTRIBUTES (TREE_TYPE (*node))));
+ *no_add_attrs = true;
+ }
+ else
+ {
+ /* Possibly pass this attribute on from the type to a decl. */
+ if (flags & ((int) ATTR_FLAG_DECL_NEXT
+ | (int) ATTR_FLAG_FUNCTION_NEXT
+ | (int) ATTR_FLAG_ARRAY_NEXT))
+ {
+ *no_add_attrs = true;
+ return tree_cons (name, args, NULL_TREE);
+ }
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ }
+ }
+ }
+
+ return NULL_TREE;
}
/* Return 0 if the attributes for two types are incompatible, 1 if they
@@ -4132,85 +4204,6 @@ multi_register_push (op, mode)
return 1;
}
-/* Routines for use with attributes. */
-
-/* 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:
-
- naked:
- don't output any prologue or epilogue code, the user is assumed
- to do the right thing.
-
- isr or interrupt:
- Interrupt Service Routine.
-
- interfacearm:
- Always assume that this function will be entered in ARM mode,
- not Thumb mode, and that the caller wishes to be returned to in
- ARM mode. */
-static int
-arm_valid_decl_attribute_p (decl, attributes, attr, args)
- tree decl;
- tree attributes ATTRIBUTE_UNUSED;
- tree attr;
- tree args;
-{
- /* The interrupt attribute can take args, so check for it before
- rejecting other attributes on the grounds that they did have args. */
- if (is_attribute_p ("isr", attr)
- || is_attribute_p ("interrupt", attr))
- return TREE_CODE (decl) == FUNCTION_DECL;
-
- if (args != NULL_TREE)
- return 0;
-
- if (is_attribute_p ("naked", attr))
- return TREE_CODE (decl) == FUNCTION_DECL;
-
-#ifdef ARM_PE
- if (is_attribute_p ("interfacearm", attr))
- return TREE_CODE (decl) == FUNCTION_DECL;
-#endif /* ARM_PE */
-
- return 0;
-}
-
-#ifdef ARM_PE
-
-/* ARM/PE has three new attributes:
- naked - for interrupt functions
- dllexport - for exporting a function/variable that will live in a dll
- dllimport - for importing a function/variable from a dll
-
- Microsoft allows multiple declspecs in one __declspec, separating
- them with spaces. We do NOT support this. Instead, use __declspec
- multiple times.
-*/
-
-static int
-arm_pe_valid_decl_attribute_p (decl, attributes, attr, args)
- tree decl;
- tree attributes;
- tree attr;
- tree args;
-{
- if (args != NULL_TREE)
- return 0;
-
- if (is_attribute_p ("dllexport", attr))
- return 1;
-
- if (is_attribute_p ("dllimport", attr))
- return 1;
-
- return arm_valid_decl_attribute_p (decl, attributes, attr, args);
-}
-
-#endif /* ARM_PE */
-
/* Routines for use in generating RTL. */
rtx
arm_gen_load_multiple (base_regno, count, from, up, write_back, unchanging_p,
@@ -9742,7 +9735,7 @@ is_called_in_ARM_mode (func)
return TRUE;
#ifdef ARM_PE
- return lookup_attribute ("interfacearm", DECL_MACHINE_ATTRIBUTES (func)) != NULL_TREE;
+ return lookup_attribute ("interfacearm", DECL_ATTRIBUTES (func)) != NULL_TREE;
#else
return FALSE;
#endif