diff options
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/split-6.c | 53 | ||||
-rw-r--r-- | libgcc/ChangeLog | 11 | ||||
-rw-r--r-- | libgcc/config/i386/morestack.S | 42 |
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. |