From patchwork Mon Nov 8 04:34:46 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 70395 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 0CCDEB70F4 for ; Mon, 8 Nov 2010 15:35:37 +1100 (EST) Received: (qmail 22356 invoked by alias); 8 Nov 2010 04:35:31 -0000 Received: (qmail 22177 invoked by uid 22791); 8 Nov 2010 04:35:30 -0000 X-SWARE-Spam-Status: No, hits=-4.6 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, TW_OV, TW_RG, T_RP_MATCHES_RCVD, T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (74.125.121.35) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 08 Nov 2010 04:35:24 +0000 Received: from wpaz21.hot.corp.google.com (wpaz21.hot.corp.google.com [172.24.198.85]) by smtp-out.google.com with ESMTP id oA84ZLij011273 for ; Sun, 7 Nov 2010 20:35:21 -0800 Received: from gya6 (gya6.prod.google.com [10.243.49.6]) by wpaz21.hot.corp.google.com with ESMTP id oA84ZJT6030854 for ; Sun, 7 Nov 2010 20:35:20 -0800 Received: by gya6 with SMTP id 6so3336114gya.4 for ; Sun, 07 Nov 2010 20:35:19 -0800 (PST) Received: by 10.150.204.18 with SMTP id b18mr7799030ybg.318.1289190919739; Sun, 07 Nov 2010 20:35:19 -0800 (PST) Received: from coign.google.com (adsl-71-133-8-30.dsl.pltn13.pacbell.net [71.133.8.30]) by mx.google.com with ESMTPS id w5sm3344692ybe.10.2010.11.07.20.35.17 (version=TLSv1/SSLv3 cipher=RC4-MD5); Sun, 07 Nov 2010 20:35:18 -0800 (PST) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org Subject: Patch committed: Fix -fsplit-stack -mcmodel=large Date: Sun, 07 Nov 2010 20:34:46 -0800 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 X-System-Of-Record: true X-IsSubscribed: yes 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 PR 46089 points out that -fsplit-stack fails when using -mcmodel=large. This fixes it. Bootstrapped and tested on x86_64-unknown-linux-gnu. Committed to mainline. Ian gcc/: 2010-11-07 Ian Lance Taylor PR target/46089 * config/i386/i386.c (split_stack_fn_large): New static variable. (ix86_expand_split_stack_prologue): Handle large model. libgcc/: 2010-11-07 Ian Lance Taylor PR target/46089 * config/i386/morestack.S (__morestack_large_model): New function. Index: gcc/config/i386/i386.c =================================================================== --- gcc/config/i386/i386.c (revision 166300) +++ gcc/config/i386/i386.c (working copy) @@ -11050,6 +11050,11 @@ split_stack_prologue_scratch_regno (void static GTY(()) rtx split_stack_fn; +/* A SYMBOL_REF for the more stack function when using the large + model. */ + +static GTY(()) rtx split_stack_fn_large; + /* Handle -fsplit-stack. These are the first instructions in the function, even before the regular prologue. */ @@ -11062,6 +11067,7 @@ ix86_expand_split_stack_prologue (void) rtx label, limit, current, jump_insn, allocate_rtx, call_insn, call_fusage; rtx scratch_reg = NULL_RTX; rtx varargs_label = NULL_RTX; + rtx fn; gcc_assert (flag_split_stack && reload_completed); @@ -11125,6 +11131,10 @@ ix86_expand_split_stack_prologue (void) add_reg_note (jump_insn, REG_BR_PROB, GEN_INT (REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100)); + if (split_stack_fn == NULL_RTX) + split_stack_fn = gen_rtx_SYMBOL_REF (Pmode, "__morestack"); + fn = split_stack_fn; + /* Get more stack space. We pass in the desired stack space and the size of the arguments to copy to the new stack. In 32-bit mode we push the parameters; __morestack will return on a new stack @@ -11135,9 +11145,10 @@ ix86_expand_split_stack_prologue (void) call_fusage = NULL_RTX; if (TARGET_64BIT) { - rtx reg; + rtx reg10, reg11; - reg = gen_rtx_REG (Pmode, R10_REG); + reg10 = gen_rtx_REG (Pmode, R10_REG); + reg11 = gen_rtx_REG (Pmode, R11_REG); /* If this function uses a static chain, it will be in %r10. Preserve it across the call to __morestack. */ @@ -11146,24 +11157,69 @@ ix86_expand_split_stack_prologue (void) rtx rax; rax = gen_rtx_REG (Pmode, AX_REG); - emit_move_insn (rax, reg); + emit_move_insn (rax, reg10); use_reg (&call_fusage, rax); } - emit_move_insn (reg, allocate_rtx); - use_reg (&call_fusage, reg); - reg = gen_rtx_REG (Pmode, R11_REG); - emit_move_insn (reg, GEN_INT (args_size)); - use_reg (&call_fusage, reg); + if (ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC) + { + HOST_WIDE_INT argval; + + /* When using the large model we need to load the address + into a register, and we've run out of registers. So we + switch to a different calling convention, and we call a + different function: __morestack_large. We pass the + argument size in the upper 32 bits of r10 and pass the + frame size in the lower 32 bits. */ + gcc_assert ((allocate & 0xffffffff) == allocate); + gcc_assert (((HOST_WIDE_INT) args_size & 0xffffffff) + == (HOST_WIDE_INT) args_size); + + if (split_stack_fn_large == NULL_RTX) + split_stack_fn_large = + gen_rtx_SYMBOL_REF (Pmode, "__morestack_large_model"); + + if (ix86_cmodel == CM_LARGE_PIC) + { + rtx label, x; + + label = gen_label_rtx (); + emit_label (label); + LABEL_PRESERVE_P (label) = 1; + emit_insn (gen_set_rip_rex64 (reg10, label)); + emit_insn (gen_set_got_offset_rex64 (reg11, label)); + emit_insn (gen_adddi3 (reg10, reg10, reg11)); + x = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, split_stack_fn_large), + UNSPEC_GOT); + x = gen_rtx_CONST (Pmode, x); + emit_move_insn (reg11, x); + x = gen_rtx_PLUS (Pmode, reg10, reg11); + x = gen_const_mem (Pmode, x); + emit_move_insn (reg11, x); + } + else + emit_move_insn (reg11, split_stack_fn_large); + + fn = reg11; + + argval = ((HOST_WIDE_INT) args_size << 32) + allocate; + emit_move_insn (reg10, GEN_INT (argval)); + } + else + { + emit_move_insn (reg10, allocate_rtx); + emit_move_insn (reg11, GEN_INT (args_size)); + use_reg (&call_fusage, reg11); + } + + use_reg (&call_fusage, reg10); } else { emit_insn (gen_push (GEN_INT (args_size))); emit_insn (gen_push (allocate_rtx)); } - if (split_stack_fn == NULL_RTX) - split_stack_fn = gen_rtx_SYMBOL_REF (Pmode, "__morestack"); - call_insn = ix86_expand_call (NULL_RTX, gen_rtx_MEM (QImode, split_stack_fn), + call_insn = ix86_expand_call (NULL_RTX, gen_rtx_MEM (QImode, fn), GEN_INT (UNITS_PER_WORD), constm1_rtx, NULL_RTX, 0); add_function_usage_to (call_insn, call_fusage); Index: libgcc/config/i386/morestack.S =================================================================== --- libgcc/config/i386/morestack.S (revision 166300) +++ libgcc/config/i386/morestack.S (working copy) @@ -488,6 +488,40 @@ DW.ref.__gcc_personality_v0: #endif #endif +#ifdef __x86_64__ + +# This entry point is used for the large model. With this entry point +# the upper 32 bits of %r10 hold the argument size and the lower 32 +# bits hold the new stack frame size. There doesn't seem to be a way +# to know in the assembler code that we are assembling for the large +# model, and there doesn't seem to be a large model multilib anyhow. +# If one is developed, then the non-PIC code is probably OK since we +# will probably be close to the morestack code, but the PIC code +# almost certainly needs to be changed. FIXME. + + .text + .global __morestack_large_model + .hidden __morestack_large_model + +#ifdef __ELF__ + .type __morestack_large_model,@function +#endif + +__morestack_large_model: + + .cfi_startproc + + movq %r10, %r11 + andl $0xffffffff, %r10d + sarq $32, %r11 + jmp __morestack + + .cfi_endproc +#ifdef __ELF__ + .size __morestack_large_model, . - __morestack_large_model +#endif + +#endif /* __x86_64__ */ # Initialize the stack test value when the program starts or when a # new thread starts. We don't know how large the main stack is, so we