aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2007-08-29 03:53:41 +0000
committerKazu Hirata <kazu@gcc.gnu.org>2007-08-29 03:53:41 +0000
commitfa157b28ca73804e8ac9196c4898c2e542d98a35 (patch)
treed2833806f032a2079955aeaeb53b1ee366295d5f /gcc
parentbdf57c4096fd8cd0bfdadade196c8ac7a87ddf5a (diff)
downloadgcc-fa157b28ca73804e8ac9196c4898c2e542d98a35.zip
gcc-fa157b28ca73804e8ac9196c4898c2e542d98a35.tar.gz
gcc-fa157b28ca73804e8ac9196c4898c2e542d98a35.tar.bz2
m68k.c (m68k_get_function_kind): Assert we're never given a non-function.
gcc/ * config/m68k/m68k.c (m68k_get_function_kind): Assert we're never given a non-function. (m68k_ok_for_sibcall_p): Only sibcall functions of the same kind. gcc/testsuite/ * gcc.target/m68k/interrupt-1.c: New. Co-Authored-By: Kazu Hirata <kazu@codesourcery.com> From-SVN: r127880
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/m68k/m68k.c31
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/m68k/interrupt-1.c24
4 files changed, 58 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 223b65a..9e2f445 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2007-08-28 Nathan Sidwell <nathan@codesourcery.com>
+
+ * config/m68k/m68k.c (m68k_get_function_kind): Assert we're never
+ given a non-function.
+ (m68k_ok_for_sibcall_p): Only sibcall functions of the same kind.
+
2007-08-28 DJ Delorie <dj@redhat.com>
* config/sh/sh.c (sh_gimplify_va_arg_expr): Fix sh2a support.
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 2b06b6c..f1f09bc 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -639,9 +639,8 @@ m68k_get_function_kind (tree func)
{
tree a;
- if (TREE_CODE (func) != FUNCTION_DECL)
- return false;
-
+ gcc_assert (TREE_CODE (func) == FUNCTION_DECL);
+
a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
if (a != NULL_TREE)
return m68k_fk_interrupt_handler;
@@ -1258,14 +1257,30 @@ flags_in_68881 (void)
return cc_status.flags & CC_IN_68881;
}
-/* Implement TARGET_FUNCTION_OK_FOR_SIBCALL_P. We cannot use sibcalls
- for nested functions because we use the static chain register for
- indirect calls. */
+/* Implement TARGET_FUNCTION_OK_FOR_SIBCALL_P. */
static bool
-m68k_ok_for_sibcall_p (tree decl ATTRIBUTE_UNUSED, tree exp)
+m68k_ok_for_sibcall_p (tree decl, tree exp)
{
- return TREE_OPERAND (exp, 2) == NULL;
+ enum m68k_function_kind kind;
+
+ /* We cannot use sibcalls for nested functions because we use the
+ static chain register for indirect calls. */
+ if (CALL_EXPR_STATIC_CHAIN (exp))
+ return false;
+
+ kind = m68k_get_function_kind (current_function_decl);
+ if (kind == m68k_fk_normal_function)
+ /* We can always sibcall from a normal function, because it's
+ undefined if it is calling an interrupt function. */
+ return true;
+
+ /* Otherwise we can only sibcall if the function kind is known to be
+ the same. */
+ if (decl && m68k_get_function_kind (decl) == kind)
+ return true;
+
+ return false;
}
/* Convert X to a legitimate function call memory reference and return the
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d9dc83e..36dd47a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2007-08-28 Nathan Sidwell <nathan@codesourcery.com>
+ Kazu Hirata <kazu@codesourcery.com>
+
+ * gcc.target/m68k/interrupt-1.c: New.
+
2007-08-28 Rask Ingemann Lambertsen <rask@sygehus.dk>
* gcc.c-torture/compile/limits-blockid.c: Reduce testcase size to
diff --git a/gcc/testsuite/gcc.target/m68k/interrupt-1.c b/gcc/testsuite/gcc.target/m68k/interrupt-1.c
new file mode 100644
index 0000000..443c13b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/interrupt-1.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "j(ra|mp)\[ \t\]*interrupt_sibcall" } } */
+/* { dg-final { scan-assembler "j(b|)sr\[ \t\]*interrupt_call" } } */
+/* { dg-final { scan-assembler "j(ra|mp)\[ \t\]*normal_sibcall" } } */
+
+void normal_sibcall (void);
+void interrupt_call (void);
+void __attribute ((interrupt)) interrupt_sibcall (void);
+
+void normal (void)
+{
+ normal_sibcall ();
+}
+
+void __attribute ((interrupt)) interrupt (void)
+{
+ interrupt_call ();
+}
+
+void __attribute ((interrupt)) interrupt_2 (void)
+{
+ interrupt_sibcall ();
+}