diff options
author | Nathan Sidwell <nathan@codesourcery.com> | 2007-08-29 03:53:41 +0000 |
---|---|---|
committer | Kazu Hirata <kazu@gcc.gnu.org> | 2007-08-29 03:53:41 +0000 |
commit | fa157b28ca73804e8ac9196c4898c2e542d98a35 (patch) | |
tree | d2833806f032a2079955aeaeb53b1ee366295d5f | |
parent | bdf57c4096fd8cd0bfdadade196c8ac7a87ddf5a (diff) | |
download | gcc-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
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/config/m68k/m68k.c | 31 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/m68k/interrupt-1.c | 24 |
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 (); +} |