This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Alpha] Fix stack checking
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 10 Sep 2010 20:47:12 +0200
- Subject: [Alpha] Fix stack checking
The Tru64 ABI requires stack checking to be performed unconditionally so the
support has been present in the Alpha back-end since the beginning. However
there is no protection area mandated by the ABI because it is implemented by
the system (yellow and red zones) so the back-end doesn't implement one. As
a consequence, -fstack-check doesn't make it possible to recover from a stack
overflow condition by means of an exception like on other platforms.
This adjusts the prologue expander to implement the protection area and fixes
the couple of Ada testcases gnat.dg/stack_check[12].adb on Alpha platforms.
Tested on alphaev56-dec-osf5.1, OK for mainline?
2010-09-10 Eric Botcazou <ebotcazou@adacore.com>
* config/alpha/alpha.c (alpha_expand_prologue): If stack checking
is enabled, probe up to frame_size + STACK_CHECK_PROTECT bytes.
--
Eric Botcazou
Index: config/alpha/alpha.c
===================================================================
--- config/alpha/alpha.c (revision 163921)
+++ config/alpha/alpha.c (working copy)
@@ -7814,6 +7814,9 @@ alpha_expand_prologue (void)
HOST_WIDE_INT sa_size;
/* Complete stack size needed. */
HOST_WIDE_INT frame_size;
+ /* Probed stack size; it additionally includes the size of
+ the "reserve region" if any. */
+ HOST_WIDE_INT probed_size;
/* Offset from base reg to register save area. */
HOST_WIDE_INT reg_offset;
rtx sa_reg;
@@ -7859,20 +7862,26 @@ alpha_expand_prologue (void)
Note that we are only allowed to adjust sp once in the prologue. */
- if (frame_size <= 32768)
+ probed_size = frame_size;
+ if (flag_stack_check)
+ probed_size += STACK_CHECK_PROTECT;
+
+ if (probed_size <= 32768)
{
- if (frame_size > 4096)
+ if (probed_size > 4096)
{
int probed;
- for (probed = 4096; probed < frame_size; probed += 8192)
+ for (probed = 4096; probed < probed_size; probed += 8192)
emit_insn (gen_probe_stack (GEN_INT (TARGET_ABI_UNICOSMK
? -probed + 64
: -probed)));
- /* We only have to do this probe if we aren't saving registers. */
- if (sa_size == 0 && frame_size > probed - 4096)
- emit_insn (gen_probe_stack (GEN_INT (-frame_size)));
+ /* We only have to do this probe if we aren't saving registers or
+ if we are probing beyond the frame because of -fstack-check. */
+ if ((sa_size == 0 && probed_size > probed - 4096)
+ || flag_stack_check)
+ emit_insn (gen_probe_stack (GEN_INT (-probed_size)));
}
if (frame_size != 0)
@@ -7887,10 +7896,11 @@ alpha_expand_prologue (void)
number of 8192 byte blocks to probe. We then probe each block
in the loop and then set SP to the proper location. If the
amount remaining is > 4096, we have to do one more probe if we
- are not saving any registers. */
+ are not saving any registers or if we are probing beyond the
+ frame because of -fstack-check. */
- HOST_WIDE_INT blocks = (frame_size + 4096) / 8192;
- HOST_WIDE_INT leftover = frame_size + 4096 - blocks * 8192;
+ HOST_WIDE_INT blocks = (probed_size + 4096) / 8192;
+ HOST_WIDE_INT leftover = probed_size + 4096 - blocks * 8192;
rtx ptr = gen_rtx_REG (DImode, 22);
rtx count = gen_rtx_REG (DImode, 23);
rtx seq;
@@ -7903,20 +7913,23 @@ alpha_expand_prologue (void)
late in the compilation, generate the loop as a single insn. */
emit_insn (gen_prologue_stack_probe_loop (count, ptr));
- if (leftover > 4096 && sa_size == 0)
+ if ((leftover > 4096 && sa_size == 0) || flag_stack_check)
{
rtx last = gen_rtx_MEM (DImode, plus_constant (ptr, -leftover));
MEM_VOLATILE_P (last) = 1;
emit_move_insn (last, const0_rtx);
}
- if (TARGET_ABI_WINDOWS_NT)
+ if (TARGET_ABI_WINDOWS_NT || flag_stack_check)
{
/* For NT stack unwind (done by 'reverse execution'), it's
not OK to take the result of a loop, even though the value
is already in ptr, so we reload it via a single operation
and subtract it to sp.
+ Same if -fstack-check is specified, because the probed stack
+ size is not equal to the frame size.
+
Yes, that's correct -- we have to reload the whole constant
into a temporary via ldah+lda then subtract from sp. */