OSDN Git Service

gcc/:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 8 Nov 2010 04:34:32 +0000 (04:34 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 8 Nov 2010 04:34:32 +0000 (04:34 +0000)
PR target/46089
* config/i386/i386.c (split_stack_fn_large): New static variable.
(ix86_expand_split_stack_prologue): Handle large model.
libgcc/:
* config/i386/morestack.S (__morestack_large_model): New
function.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166427 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/i386/i386.c
libgcc/ChangeLog
libgcc/config/i386/morestack.S

index ce49a50..4088046 100644 (file)
@@ -1,3 +1,9 @@
+2010-11-07  Ian Lance Taylor  <iant@google.com>
+
+       PR target/46089
+       * config/i386/i386.c (split_stack_fn_large): New static variable.
+       (ix86_expand_split_stack_prologue): Handle large model.
+
 2010-11-07  Andreas Schwab  <schwab@linux-m68k.org>
 
        * config/m68k/m68k.c (m68k_delegitimize_address): Update to handle
index 6e086bc..b4ba2c1 100644 (file)
@@ -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 ea864d3..21099ab 100644 (file)
@@ -1,3 +1,9 @@
+2010-11-07  Ian Lance Taylor  <iant@google.com>
+
+       PR target/46089
+       * config/i386/morestack.S (__morestack_large_model): New
+       function.
+
 2010-10-23  Nathan Froyd  <froydnj@codesourcery.com>
 
        * config/libbid/bid_gcc_intrinsics.h (LIBGCC2_WORDS_BIG_ENDIAN):
index 79abba3..10fa1fd 100644 (file)
@@ -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