https://gcc.gnu.org/g:6ffc1509faea719d0271d0123f0529c51bc7ee95
commit r14-12920-g6ffc1509faea719d0271d0123f0529c51bc7ee95 Author: Georg-Johann Lay <[email protected]> Date: Mon Oct 5 17:16:50 2026 +0200 AVR: target/127482 - Fix prologue_saves + noreturn wrong code This patch fixes wrong code when a noreturn function is compiled with -mcall-prologues and the function gets arguments on the stack. The bug is that prologue_saves saves more registers than calculated by avr_regs_to_save() so that the argument pointer is wrong. The fix is to behave like avr_regs_to_save(), i.e. don't save any regs in a noreturn function so that prologue_saves is not used. PR target/127482 gcc/ * config/avr/avr.cc (sequent_regs_live): Return 0 for noreturn functions, OS_task and OS_main. (avr_prologue_setup_frame, avr_expand_epilogue) <minimize>: Move OS_task and OS_main tests to sequent_regs_live. gcc/testsuite/ * gcc.target/avr/torture/pr127482.c: New test. (cherry picked from commit a3028a9ab546ca16147d927eeb765b35b6956c2f) Diff: --- gcc/config/avr/avr.cc | 10 ++++---- gcc/testsuite/gcc.target/avr/torture/pr127482.c | 31 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index 856bfe05ebfc..e246c5067f5a 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -1765,6 +1765,12 @@ avr_simple_epilogue (void) static int sequent_regs_live (void) { + // Behave according to avr_regs_to_save(). + if (TREE_THIS_VOLATILE (current_function_decl) + || cfun->machine->is_OS_task + || cfun->machine->is_OS_main) + return 0; + int live_seq = 0; int cur_seq = 0; @@ -2617,8 +2623,6 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) && size < size_max && live_seq && !isr_p - && !cfun->machine->is_OS_task - && !cfun->machine->is_OS_main && !AVR_TINY); if (minimize @@ -3079,8 +3083,6 @@ avr_expand_epilogue (bool sibcall_p) bool minimize = (TARGET_CALL_PROLOGUES && live_seq && !isr_p - && !cfun->machine->is_OS_task - && !cfun->machine->is_OS_main && !AVR_TINY); if (minimize diff --git a/gcc/testsuite/gcc.target/avr/torture/pr127482.c b/gcc/testsuite/gcc.target/avr/torture/pr127482.c new file mode 100644 index 000000000000..0c02d5c05c0c --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/pr127482.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ +/* { dg-additional-options "-mcall-prologues" } */ + +#include <stdarg.h> +#include <stdlib.h> + +#define NI __attribute((noipa)) + +NI void xx_fun (void) {} +NI void xx_vprintf (const char *fmt, va_list args) +{ + int i = va_arg (args, int); + if (i != 0x1234) + exit (10); +} + +void error (const char *msg, ...) +{ + va_list args; + xx_fun (); + va_start (args, msg); + xx_vprintf (msg, args); + va_end (args); + exit (0); +} + +int main (void) +{ + error ("bad %d\n", 0x1234); + return 0; +}
