===================================================================
@@ -3664,6 +3664,15 @@ proc check_effective_target_lto { } {
return [info exists ENABLE_LTO]
}
+# Return 1 if this target supports the -fsplit-stack option, 0
+# otherwise.
+
+proc check_effective_target_split_stack {} {
+ return [check_no_compiler_messages split_stack object {
+ void foo (void) { }
+ } "-fsplit-stack"]
+}
+
# Return 1 if the language for the compiler under test is C.
proc check_effective_target_c { } {
===================================================================
@@ -0,0 +1,49 @@
+/* This test needs to use setrlimit to set the stack size, so it can
+ only run on Unix. */
+/* { dg-do run { target *-*-linux* *-*-solaris* *-*-darwin* } } */
+/* { dg-require-effective-target split_stack } */
+/* { dg-options "-fsplit-stack" } */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/resource.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';
+}
+
+/* Each recursive call uses 10,000 bytes. We call it 1000 times,
+ using a total of 10,000,000 bytes. If -fsplit-stack is not
+ working, that will overflow our stack limit. */
+
+static void
+down (int i)
+{
+ char buf[10000];
+
+ if (i > 0)
+ {
+ use_buffer (buf);
+ down (i - 1);
+ }
+}
+
+int
+main (void)
+{
+ struct rlimit r;
+
+ /* We set a stack limit because we are usually invoked via make, and
+ make sets the stack limit to be as large as possible. */
+ r.rlim_cur = 8192 * 1024;
+ r.rlim_max = 8192 * 1024;
+ if (setrlimit (RLIMIT_STACK, &r) != 0)
+ abort ();
+ down (1000);
+ return 0;
+}
===================================================================
@@ -0,0 +1,55 @@
+/* { dg-do run } */
+/* { dg-require-effective-target split_stack } */
+/* { dg-require-effective-target pthread_h } */
+/* { dg-options "-pthread -fsplit-stack" } */
+
+#include <stdlib.h>
+#include <pthread.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';
+}
+
+/* Each recursive call uses 10,000 bytes. We call it 1000 times,
+ using a total of 10,000,000 bytes. If -fsplit-stack is not
+ working, that will overflow our stack limit. */
+
+static void
+down (int i)
+{
+ char buf[10000];
+
+ if (i > 0)
+ {
+ use_buffer (buf);
+ down (i - 1);
+ }
+}
+
+static void *
+thread_routine (void *arg __attribute__ ((unused)))
+{
+ down (1000);
+ return NULL;
+}
+
+int
+main (void)
+{
+ int i;
+ pthread_t tid;
+ void *dummy;
+
+ i = pthread_create (&tid, NULL, thread_routine, NULL);
+ if (i != 0)
+ abort ();
+ i = pthread_join (tid, &dummy);
+ if (i != 0)
+ abort ();
+ return 0;
+}
===================================================================
@@ -0,0 +1,64 @@
+/* This test needs to use setrlimit to set the stack size, so it can
+ only run on Unix. */
+/* { dg-do run { target *-*-linux* *-*-solaris* *-*-darwin* } } */
+/* { dg-require-effective-target split_stack } */
+/* { dg-options "-fsplit-stack" } */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/resource.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';
+}
+
+/* Each recursive call uses 10,000 bytes. We call it 1000 times,
+ using a total of 10,000,000 bytes. If -fsplit-stack is not
+ working, that will overflow our stack limit. */
+
+static void
+down (int i, ...)
+{
+ char buf[10000];
+ 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)
+{
+ struct rlimit r;
+
+ /* We set a stack limit because we are usually invoked via make, and
+ make sets the stack limit to be as large as possible. */
+ r.rlim_cur = 8192 * 1024;
+ r.rlim_max = 8192 * 1024;
+ if (setrlimit (RLIMIT_STACK, &r) != 0)
+ abort ();
+ down (1000, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ return 0;
+}
===================================================================
@@ -0,0 +1,68 @@
+/* This test needs to use setrlimit to set the stack size, so it can
+ only run on Unix. */
+/* { dg-do run { target *-*-linux* *-*-solaris* *-*-darwin* } } */
+/* { dg-require-effective-target split_stack } */
+/* { dg-options "-fsplit-stack" } */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/resource.h>
+
+/* Use a noinline function to ensure that the buffer is not removed
+ from the stack. */
+static void use_buffer (char *buf, size_t) __attribute__ ((noinline));
+static void
+use_buffer (char *buf, size_t c)
+{
+ size_t i;
+
+ for (i = 0; i < c; ++i)
+ buf[i] = (char) i;
+}
+
+/* Each recursive call uses 10 * i bytes. We call it 1000 times,
+ using a total of 5,000,000 bytes. If -fsplit-stack is not working,
+ that will overflow our stack limit. */
+
+static void
+down1 (int i)
+{
+ char buf[10 * i];
+
+ if (i > 0)
+ {
+ use_buffer (buf, 10 * i);
+ down1 (i - 1);
+ }
+}
+
+/* Same thing, using alloca. */
+
+static void
+down2 (int i)
+{
+ char *buf = alloca (10 * i);
+
+ if (i > 0)
+ {
+ use_buffer (buf, 10 * i);
+ down2 (i - 1);
+ }
+}
+
+int
+main (void)
+{
+ struct rlimit r;
+
+ /* We set a stack limit because we are usually invoked via make, and
+ make sets the stack limit to be as large as possible. */
+ r.rlim_cur = 8192 * 1024;
+ r.rlim_max = 8192 * 1024;
+ if (setrlimit (RLIMIT_STACK, &r) != 0)
+ abort ();
+ down1 (1000);
+ down2 (1000);
+ return 0;
+}