m68k.c (m68k_get_function_kind): Assert we're never given a non-function.
authorNathan Sidwell <nathan@codesourcery.com>
Wed, 29 Aug 2007 03:53:41 +0000 (03:53 +0000)
committerKazu Hirata <kazu@gcc.gnu.org>
Wed, 29 Aug 2007 03:53:41 +0000 (03:53 +0000)
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

gcc/ChangeLog
gcc/config/m68k/m68k.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/m68k/interrupt-1.c [new file with mode: 0644]

index 223b65ab5664a7e8d0efcdcd293407279128d4fa..9e2f445e77b38102c8a0d3d3d229d697f5ccd326 100644 (file)
@@ -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.
index 2b06b6c01d9919fa3846506fe73a44378e2d1129..f1f09bc86c11657605882b627f6f2e89fa5968cc 100644 (file)
@@ -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
index d9dc83e8b6fd8638d45664bbe12a3ab621a7e3d5..36dd47a953ed5916f9e40c8c8820520fe7e49093 100644 (file)
@@ -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 (file)
index 0000000..443c13b
--- /dev/null
@@ -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 ();
+}