summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/split-6.c53
-rw-r--r--libgcc/ChangeLog11
-rw-r--r--libgcc/config/i386/morestack.S42
4 files changed, 102 insertions, 8 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 22a29b83a21..285ae9cce7c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2012-05-25 Ian Lance Taylor <iant@google.com>
+
+ * gcc.dg/split-6.c: New test.
+
2012-05-25 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/lto14.adb: New test.
diff --git a/gcc/testsuite/gcc.dg/split-6.c b/gcc/testsuite/gcc.dg/split-6.c
new file mode 100644
index 00000000000..b32cf8de20a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/split-6.c
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-require-effective-target split_stack } */
+/* { dg-options "-fsplit-stack" } */
+
+/* This test is like split-3.c, but tests with a smaller stack frame,
+ since that uses a different prologue. */
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+/* Use a noinline function to ensure that the buffer is not removed
+ from the stack. */
+static void use_buffer (char *buf) __attribute__ ((noinline));
+static void
+use_buffer (char *buf)
+{
+ buf[0] = '\0';
+}
+
+/* When using gold, the call to abort will force a stack split. */
+
+static void
+down (int i, ...)
+{
+ char buf[1];
+ va_list ap;
+
+ va_start (ap, i);
+ if (va_arg (ap, int) != 1
+ || va_arg (ap, int) != 2
+ || va_arg (ap, int) != 3
+ || va_arg (ap, int) != 4
+ || va_arg (ap, int) != 5
+ || va_arg (ap, int) != 6
+ || va_arg (ap, int) != 7
+ || va_arg (ap, int) != 8
+ || va_arg (ap, int) != 9
+ || va_arg (ap, int) != 10)
+ abort ();
+
+ if (i > 0)
+ {
+ use_buffer (buf);
+ down (i - 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ }
+}
+
+int
+main (void)
+{
+ down (1000, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ return 0;
+}
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index db4c801580e..5c048f53149 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,8 @@
+2012-05-25 Ian Lance Taylor <iant@google.com>
+
+ * config/i386/morestack.S (__morestack_non_split): Check whether
+ caller is varargs and needs %bp to hold the stack frame on return.
+
2012-05-25 Olivier Hainque <hainque@adacore.com>
* config/rs6000/vxworks/tramp.S (trampoline_setup): Use a longcall
@@ -80,9 +85,9 @@
2012-04-28 Aurelien Jarno <aurelien@aurel32.net>
- * config.host (mips64*-*-linux*, mipsisa64*-*-linux*): Remove.
- (mips*-*-linux*): Include mips/t-tpbit when long double is
- 16 bytes long.
+ * config.host (mips64*-*-linux*, mipsisa64*-*-linux*): Remove.
+ (mips*-*-linux*): Include mips/t-tpbit when long double is
+ 16 bytes long.
2012-04-25 Sriraman Tallam <tmsriram@google.com>
diff --git a/libgcc/config/i386/morestack.S b/libgcc/config/i386/morestack.S
index 62f7ce1c0f7..228d6901abd 100644
--- a/libgcc/config/i386/morestack.S
+++ b/libgcc/config/i386/morestack.S
@@ -1,5 +1,5 @@
# x86/x86_64 support for -fsplit-stack.
-# Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+# Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
# Contributed by Ian Lance Taylor <iant@google.com>.
# This file is part of GCC.
@@ -138,6 +138,24 @@ __morestack_non_split:
je 1f # see above.
addl $2,%eax
1: inc %eax
+
+ # If the instruction that we return to is
+ # leal 20(%ebp),{%eax,%ecx,%edx}
+ # then we have been called by a varargs function that expects
+ # %ebp to hold a real value. That can only work if we do the
+ # full stack split routine. FIXME: This is fragile.
+ cmpb $0x8d,(%eax)
+ jne 3f
+ cmpb $0x14,2(%eax)
+ jne 3f
+ cmpb $0x45,1(%eax)
+ je 2f
+ cmpb $0x4d,1(%eax)
+ je 2f
+ cmpb $0x55,1(%eax)
+ je 2f
+
+3:
movl %eax,4(%esp) # Update return address.
popl %eax # Restore %eax and stack.
@@ -175,18 +193,32 @@ __morestack_non_split:
#else
cmpl %fs:0x40,%eax
#endif
- popq %rax # Restore register.
-
- .cfi_adjust_cfa_offset -8 # Adjust for popped register.
jb 2f # Get more space if we need it.
# This breaks call/return prediction, as described above.
- incq (%rsp) # Increment the return address.
+ incq 8(%rsp) # Increment the return address.
+
+ # If the instruction that we return to is
+ # leaq 24(%rbp), %r11n
+ # then we have been called by a varargs function that expects
+ # %ebp to hold a real value. That can only work if we do the
+ # full stack split routine. FIXME: This is fragile.
+ movq 8(%rsp),%rax
+ cmpl $0x185d8d4c,(%rax)
+ je 2f
+
+ popq %rax # Restore register.
+
+ .cfi_adjust_cfa_offset -8 # Adjust for popped register.
ret # Return to caller.
2:
+ popq %rax # Restore register.
+
+ .cfi_adjust_cfa_offset -8 # Adjust for popped register.
+
addq $0x5000+BACKOFF,%r10 # Increment space we request.
# Fall through into morestack.