From patchwork Fri Sep 10 18:47:12 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Botcazou X-Patchwork-Id: 64445 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 5D688B6EF2 for ; Sat, 11 Sep 2010 04:47:12 +1000 (EST) Received: (qmail 24347 invoked by alias); 10 Sep 2010 18:47:10 -0000 Received: (qmail 24339 invoked by uid 22791); 10 Sep 2010 18:47:08 -0000 X-SWARE-Spam-Status: No, hits=-2.1 required=5.0 tests=AWL,BAYES_00 X-Spam-Check-By: sourceware.org Received: from mel.act-europe.fr (HELO mel.act-europe.fr) (212.99.106.210) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 10 Sep 2010 18:47:03 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id 419D9CB022E for ; Fri, 10 Sep 2010 20:47:01 +0200 (CEST) Received: from mel.act-europe.fr ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id H0IZbBDqlTjh for ; Fri, 10 Sep 2010 20:47:01 +0200 (CEST) Received: from [192.168.1.2] (bon31-9-83-155-120-49.fbx.proxad.net [83.155.120.49]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mel.act-europe.fr (Postfix) with ESMTP id 1448ACB01EA for ; Fri, 10 Sep 2010 20:47:01 +0200 (CEST) From: Eric Botcazou To: gcc-patches@gcc.gnu.org Subject: [Alpha] Fix stack checking Date: Fri, 10 Sep 2010 20:47:12 +0200 User-Agent: KMail/1.9.9 MIME-Version: 1.0 Message-Id: <201009102047.12845.ebotcazou@adacore.com> Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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 * config/alpha/alpha.c (alpha_expand_prologue): If stack checking is enabled, probe up to frame_size + STACK_CHECK_PROTECT bytes. 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. */