diff options
author | gjl <gjl@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-03-13 11:28:25 +0000 |
---|---|---|
committer | gjl <gjl@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-03-13 11:28:25 +0000 |
commit | 21467ee600d87518b5f07c6b56f6ea4fd600bac9 (patch) | |
tree | 3a117bbd43fed7de52223cdc601a30b781e4620d | |
parent | fa89c18dd67096cadc9c07de6245631beab568ab (diff) | |
download | gcc-21467ee600d87518b5f07c6b56f6ea4fd600bac9.tar.gz |
PR target/52488
* config/avr/avr.c (avr_prologue_setup_frame): Cut down stack
offset (size) to a value the insns can deal with.
(expand_epilogue): Ditto.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@185329 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/config/avr/avr.c | 42 |
2 files changed, 45 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c8de4f91245..34d49a2705a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2012-03-13 Georg-Johann Lay <avr@gjlay.de> + + PR target/52488 + * config/avr/avr.c (avr_prologue_setup_frame): Cut down stack + offset (size) to a value the insns can deal with. + (expand_epilogue): Ditto. + 2012-03-13 Matthew Gretton-Dann <matthew.gretton-dann@arm.com> * config/arm/neon.ml (ops): Fixup expected instructions for diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index d9f8651e8ef..d65dd4f0c24 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -827,7 +827,11 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal; int live_seq = sequent_regs_live (); + HOST_WIDE_INT size_max + = (HOST_WIDE_INT) GET_MODE_MASK (AVR_HAVE_8BIT_SP ? QImode : Pmode); + bool minimize = (TARGET_CALL_PROLOGUES + && size < size_max && live_seq && !isr_p && !cfun->machine->is_OS_task @@ -933,6 +937,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) leaf function and thus X has already been saved. */ int irq_state = -1; + HOST_WIDE_INT size_cfa = size; rtx fp_plus_insns, fp, my_fp; gcc_assert (frame_pointer_needed @@ -951,6 +956,27 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) my_fp = all_regs_rtx[FRAME_POINTER_REGNUM]; } + /* Cut down size and avoid size = 0 so that we don't run + into ICE like PR52488 in the remainder. */ + + if (size > size_max) + { + /* Don't error so that insane code from newlib still compiles + and does not break building newlib. As PR51345 is implemented + now, there are multilib variants with -mtiny-stack. + + If user wants sanity checks he can use -Wstack-usage= + or similar options. + + For CFA we emit the original, non-saturated size so that + the generic machinery is aware of the real stack usage and + will print the above diagnostic as expected. */ + + size = size_max; + } + + size = trunc_int_for_mode (size, GET_MODE (my_fp)); + /************ Method 1: Adjust frame pointer ************/ start_sequence (); @@ -975,7 +1001,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) RTX_FRAME_RELATED_P (insn) = 1; add_reg_note (insn, REG_CFA_ADJUST_CFA, gen_rtx_SET (VOIDmode, fp, - plus_constant (fp, -size))); + plus_constant (fp, -size_cfa))); } /* Copy to stack pointer. Note that since we've already @@ -1003,7 +1029,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) add_reg_note (insn, REG_CFA_ADJUST_CFA, gen_rtx_SET (VOIDmode, stack_pointer_rtx, plus_constant (stack_pointer_rtx, - -size))); + -size_cfa))); } fp_plus_insns = get_insns (); @@ -1026,7 +1052,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) add_reg_note (insn, REG_CFA_ADJUST_CFA, gen_rtx_SET (VOIDmode, stack_pointer_rtx, plus_constant (stack_pointer_rtx, - -size))); + -size_cfa))); if (frame_pointer_needed) { insn = emit_move_insn (fp, stack_pointer_rtx); @@ -1048,7 +1074,7 @@ avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set) emit_insn (fp_plus_insns); } - cfun->machine->stack_usage += size; + cfun->machine->stack_usage += size_cfa; } /* !minimize && size != 0 */ } /* !minimize */ } @@ -1261,6 +1287,7 @@ expand_epilogue (bool sibcall_p) int irq_state = -1; rtx fp, my_fp; rtx fp_plus_insns; + HOST_WIDE_INT size_max; gcc_assert (frame_pointer_needed || !isr_p @@ -1277,6 +1304,13 @@ expand_epilogue (bool sibcall_p) my_fp = all_regs_rtx[FRAME_POINTER_REGNUM]; } + + /* For rationale see comment in prologue generation. */ + + size_max = (HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (my_fp)); + if (size > size_max) + size = size_max; + size = trunc_int_for_mode (size, GET_MODE (my_fp)); /********** Method 1: Adjust fp register **********/ |