gollvm: add check for '-fsplit-stack' option

On some platforms such as linux arm64, gcc and ld.gold don't support
'-fsplit-stack' option at present, but currently gollvm doesn't check this,
and enters the normal compilation process, then fails when linking. This CL
adds a check for this option when parsing command line options, so that if
'-fsplit-stack' is not supported, the program can exit earlier and report
the corresponding error message.

Change-Id: I41f74435f790375c4dedd0c5e544124e67d62087
Reviewed-on: https://go-review.googlesource.com/c/gollvm/+/210323
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 241fad3..4baae8a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,6 +15,7 @@
 include(LLVMExternalProjectUtils)
 
 list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
+set(GOLLVM_USE_SPLIT_STACK ON CACHE BOOL "use split stack by default")
 
 include(CmakeUtils)
 include(AddGollvm)
@@ -22,8 +23,6 @@
 # So that we can issue "make -jN" cmds in externalproject_add
 processorcount(PROCESSOR_COUNT)
 
-set(GOLLVM_USE_SPLIT_STACK ON CACHE BOOL "use split stack by default")
-
 set(EXTINSTALLDIR ${CMAKE_CURRENT_BINARY_DIR}/external/install)
 set(EXTLIBDIR "${EXTINSTALLDIR}/lib")
 set(EXTINCLUDEDIR "${EXTINSTALLDIR}/include")
diff --git a/cmake/modules/AddGollvm.cmake b/cmake/modules/AddGollvm.cmake
index c6185bf..80e602e 100644
--- a/cmake/modules/AddGollvm.cmake
+++ b/cmake/modules/AddGollvm.cmake
@@ -21,9 +21,27 @@
 set(GOLLVM_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}")
 set(GOLLVM_INSTALL_LIBDIR "${CMAKE_INSTALL_PREFIX}/${libsubdir}")
 
+# We need to check if '-fsplit-stack' is supported with 'USING_SPLIT_STACK'
+# at compile time. So define this macro in GollvmConfig.h if it's supported.
+if(GOLLVM_USE_SPLIT_STACK)
+  # For amd64, as gcc, clang, ld and ld.gold all support -fsplit-stack, so all
+  # going well. For arm64, the situation is very complicated, none of gcc, ld
+  # and ld.gold support this option, but clang does. When using clang compiler
+  # and ld linker, the test passes, but in fact ld does not support stack
+  # splitting. So here we do this test with ld.gold linker.
+  # FIXME: update here once one day there is a linker that supports '-fsplit-stack'
+  # on arm64.
+  SET(CMAKE_REQUIRED_FLAGS "-fuse-ld=gold -fsplit-stack")
+  check_c_source_compiles("#include<stdio.h>\nint main(){printf(\"hello\");\nreturn 0;}" C_SUPPORTS_SPLIT_STACK)
+  if(NOT C_SUPPORTS_SPLIT_STACK)
+    message(SEND_ERROR "C compiler does not support -fsplit-stack")
+  else()
+    set(USING_SPLIT_STACK 1)
+  endif()
+endif()
+
 macro(add_gollvm_library name)
   llvm_add_library(${name} ${ARGN})
-
   # Configure for install.
   install(TARGETS ${name}
     COMPONENT ${name}
diff --git a/cmake/modules/ConfigSetup.cmake b/cmake/modules/ConfigSetup.cmake
index 0baeac3..dc271ed 100644
--- a/cmake/modules/ConfigSetup.cmake
+++ b/cmake/modules/ConfigSetup.cmake
@@ -136,11 +136,9 @@
 # Issue an error if the C compiler doesn't support -fsplit-stack
 # (in theory you can build libgo without it, so I suppose this could
 # be changed to a warning).
-if(GOLLVM_USE_SPLIT_STACK)
-  check_c_compiler_flag("-fsplit-stack" C_SUPPORTS_SPLIT_STACK)
-  if(NOT C_SUPPORTS_SPLIT_STACK)
-    message(SEND_ERROR "C compiler does not support -fsplit-stack")
-  endif()
+if(NOT C_SUPPORTS_SPLIT_STACK)
+  message(SEND_ERROR "C compiler does not support -fsplit-stack")
+else()
   set(USING_SPLIT_STACK 1)
 endif()
 set(USE_LIBFFI 1)
diff --git a/driver-main/llvm-goc.cpp b/driver-main/llvm-goc.cpp
index 411083d..1299be9 100644
--- a/driver-main/llvm-goc.cpp
+++ b/driver-main/llvm-goc.cpp
@@ -176,6 +176,16 @@
     return false;
   }
 
+  // Check if '-fsplit-stack' is supported by this compiler configuration.
+#ifndef USING_SPLIT_STACK
+  if (args_.hasArg(gollvm::options::OPT_fsplit_stack)) {
+    errs() << progname
+           << ": '-fsplit-stack' is not supported by this compiler "
+              "configuration\n";
+    return false;
+  }
+#endif
+
   return true;
 }
 
diff --git a/driver/GollvmConfig.h.cmake b/driver/GollvmConfig.h.cmake
index 963d279..debf707 100644
--- a/driver/GollvmConfig.h.cmake
+++ b/driver/GollvmConfig.h.cmake
@@ -15,6 +15,9 @@
 // Library version (e.g. 7, 4.5, 8.0.1)
 #cmakedefine GOLLVM_LIBVERSION "@GOLLVM_LIBVERSION@"
 
+// Define if the compiler supports -fsplit-stack
+#cmakedefine USING_SPLIT_STACK
+
 // Compiler version. Same as library version currently.
 #define GOLLVM_COMPILERVERSION GOLLVM_LIBVERSION