This patch fixes PR49437 with a single line change in ARM backend and a regression test case for ARM target
ChangeLog: 2011-08-02 Matthew Gretton-Dann <matthew.gretton-d...@arm.com> PR target/49437 * config/arm/arm.c (arm_output_epilogue): Properly handle epilogue when stack was realigned in interrupt handler prologue. 2011-08-02 Joey Ye <joey...@arm.com> PR target/49437 * gcc.target/arm/handler-align.c: New test. * lib/target-supports.exp (check_effective_target_arm_cortex_m): New Function. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index d9763d2..427c58d 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -14878,6 +14878,7 @@ arm_output_epilogue (rtx sibling) && !crtl->calls_eh_return && bit_count(saved_regs_mask) * 4 == count && !IS_INTERRUPT (func_type) + && !IS_STACKALIGN (func_type) && !crtl->tail_call_emit) { unsigned long mask; diff --git a/gcc/testsuite/gcc.target/arm/handler-align.c b/gcc/testsuite/gcc.target/arm/handler-align.c new file mode 100644 index 0000000..6c5187b --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/handler-align.c @@ -0,0 +1,42 @@ +/* Test epilogue of a realigned interrupt handler. */ +/* { dg-do run } */ +/* { dg-options "-mthumb -Os" } */ +/* { dg-skip-if "" { ! { arm_thumb1_ok || arm_thumb2_ok } } } */ +/* { dg-require-effective-target arm_cortex_m } */ +/* { dg-require-effective-target arm_eabi } */ + +extern __attribute__((noreturn)) void abort(void); +extern int snprintf(char *, int, const char *, ...); + +#define BUFF_LEN 256 +char buff[BUFF_LEN]; + +char *get_buffer(void) +{ + return buff; +} + +void __attribute__((interrupt)) foo(void) +{ + char *msg = get_buffer(); + snprintf(msg, BUFF_LEN, "%d %p", 1, buff+BUFF_LEN); +} + +volatile void * save_sp; +int main() +{ + register volatile void * sp asm("sp"); + /* Check stack pointer before/after calling the interrupt + * handler. Not equal means that handler doesn't restore + * stack correctly. */ + save_sp = sp; + foo(); + /* Abort here instead of return non-zero. Due to wrong sp, lr value, + * returning from main may not work. */ + if (save_sp != sp) + { + sp = save_sp; + abort(); + } + return 0; +} diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index cf44f1e..10cfcb4 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -2108,6 +2108,19 @@ proc check_effective_target_arm_thumb2 { } { } ""] } +# Return 1 if this is an ARM cortex-M profile cpu + +proc check_effective_target_arm_cortex_m { } { + return [check_no_compiler_messages arm_cortex_m assembly { + #if !defined(__ARM_ARCH_7M__) \ + && !defined (__ARM_ARCH_7EM__) \ + && !defined (__ARM_ARCH_6M__) + #error FOO + #endif + int i; + } "-mthumb"] +} + # Return 1 if the target supports executing NEON instructions, 0 # otherwise. Cache the result.