This patch from Peter Collingbourne tweaks libgo to work around a
deficiency in the LLVM split-stack implementation: it doesn't support
varargs functions.  This is a step toward making it possible to compile
libgo with LLVM.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu.  Committed to mainline.

Ian

diff -r 445501e362dd libgo/runtime/print.c
--- a/libgo/runtime/print.c	Wed May 28 16:10:26 2014 -0700
+++ b/libgo/runtime/print.c	Wed May 28 16:47:30 2014 -0700
@@ -11,7 +11,9 @@
 
 //static Lock debuglock;
 
-static void go_vprintf(const char*, va_list);
+// Clang requires this function to not be inlined (see below).
+static void go_vprintf(const char*, va_list)
+__attribute__((noinline));
 
 // write to goroutine-local buffer if diverting output,
 // or else standard error.
@@ -61,6 +63,24 @@
 	gwrite(s, runtime_findnull((const byte*)s));
 }
 
+#if defined (__clang__) && (defined (__i386__) || defined (__x86_64__))
+// LLVM's code generator does not currently support split stacks for vararg
+// functions, so we disable the feature for this function under Clang. This
+// appears to be OK as long as:
+// - this function only calls non-inlined, internal-linkage (hence no dynamic
+//   loader) functions compiled with split stacks (i.e. go_vprintf), which can
+//   allocate more stack space as required;
+// - this function itself does not occupy more than BACKOFF bytes of stack space
+//   (see libgcc/config/i386/morestack.S).
+// These conditions are currently known to be satisfied by Clang on x86-32 and
+// x86-64. Note that signal handlers receive slightly less stack space than they
+// would normally do if they happen to be called while this function is being
+// run. If this turns out to be a problem we could consider increasing BACKOFF.
+void
+runtime_printf(const char *s, ...)
+__attribute__((no_split_stack));
+#endif
+
 void
 runtime_printf(const char *s, ...)
 {

Reply via email to