aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/ip2k/ip2k.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/ip2k/ip2k.c')
-rw-r--r--gcc/config/ip2k/ip2k.c111
1 files changed, 75 insertions, 36 deletions
diff --git a/gcc/config/ip2k/ip2k.c b/gcc/config/ip2k/ip2k.c
index c0a643ae1d1..fa543205fc9 100644
--- a/gcc/config/ip2k/ip2k.c
+++ b/gcc/config/ip2k/ip2k.c
@@ -1,6 +1,6 @@
/* Subroutines used for code generation on Ubicom IP2022
Communications Controller.
- Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Red Hat, Inc and Ubicom, Inc.
This file is part of GNU CC.
@@ -72,6 +72,11 @@ static void mdr_try_wreg_elim PARAMS ((rtx));
static int ip2k_check_can_adjust_stack_ref PARAMS ((rtx, int));
static void ip2k_adjust_stack_ref PARAMS ((rtx *, int));
static int ip2k_xexp_not_uses_reg_for_mem PARAMS ((rtx, unsigned int));
+static tree ip2k_handle_progmem_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+static tree ip2k_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+const struct attribute_spec ip2k_attribute_table[];
/* Initialize the GCC target structure. */
@@ -90,6 +95,9 @@ static int ip2k_xexp_not_uses_reg_for_mem PARAMS ((rtx, unsigned int));
#undef TARGET_ENCODE_SECTION_INFO
#define TARGET_ENCODE_SECTION_INFO encode_section_info
+#undef TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE ip2k_attribute_table
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Commands in the functions prologues in the compiled file. */
@@ -3143,51 +3151,82 @@ class_likely_spilled_p(c)
|| c == PTR_REGS);
}
-/* Only `progmem' attribute valid for type. */
+/* Valid attributes:
+ progmem - put data to program memory;
+ naked - don't generate function prologue/epilogue and `ret' command.
-int
-valid_machine_type_attribute(type, attributes, identifier, args)
- tree type ATTRIBUTE_UNUSED;
- tree attributes ATTRIBUTE_UNUSED;
- tree identifier;
- tree args ATTRIBUTE_UNUSED;
-{
- return is_attribute_p ("progmem", identifier);
-}
+ Only `progmem' attribute valid for type. */
-/* If IDENTIFIER with arguments ARGS is a valid machine specific
- attribute for DECL return 1.
- Valid attributes:
- progmem - put data to program memory;
- naked - don't generate function prologue/epilogue and `ret' command. */
+const struct attribute_spec ip2k_attribute_table[] =
+{
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+ { "progmem", 0, 0, false, false, false, ip2k_handle_progmem_attribute },
+ { "naked", 0, 0, true, false, false, ip2k_handle_fndecl_attribute },
+ { NULL, 0, 0, false, false, false, NULL }
+};
-int
-valid_machine_decl_attribute (decl, attributes, attr, args)
- tree decl;
- tree attributes ATTRIBUTE_UNUSED;
- tree attr;
+/* Handle a "progmem" attribute; arguments as in
+ struct attribute_spec.handler. */
+static tree
+ip2k_handle_progmem_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 (is_attribute_p ("naked", attr))
- return TREE_CODE (decl) == FUNCTION_DECL;
-
- if (is_attribute_p ("progmem", attr)
- && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+ if (DECL_P (*node))
{
- /* Data stored in program RAM or FLASH must be word aligned or
- it won't be directly addressable. */
- if (DECL_ALIGN (decl) < FUNCTION_BOUNDARY)
- DECL_ALIGN (decl) = FUNCTION_BOUNDARY;
+ if (TREE_CODE (*node) == TYPE_DECL)
+ {
+ /* This is really a decl attribute, not a type attribute,
+ but try to handle it for GCC 3.0 backwards compatibility. */
+
+ tree type = TREE_TYPE (*node);
+ tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
+ tree newtype = build_type_attribute_variant (type, attr);
- if (DECL_INITIAL (decl) == NULL_TREE)
+ TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
+ TREE_TYPE (*node) = newtype;
+ *no_add_attrs = true;
+ }
+ else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
{
- warning ("Only initialized variables can be placed into "
- "program memory area.");
- return 0;
+ if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
+ {
+ warning ("only initialized variables can be placed into "
+ "program memory area");
+ *no_add_attrs = true;
+ }
+ }
+ else
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
}
- return 1;
}
- return 0;
+
+ return NULL_TREE;
+}
+
+/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
+ struct attribute_spec.handler. */
+static tree
+ip2k_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;
}
/* Encode section information about tree DECL. */