gollvm: rework handling of default linker

Revise the recipe for setting the default linker, setting the default
of "gold" in the cmake code instead of the tools code. As before with
no explicit setting of GOLLVM_DEFAULT_LINKER we'll target gold, but
GOLLVM_DEFAULT_LINKER can be set to "bfd" or "lld" (to select those
variants) or set to the empty string to just invoke "ld".

Change-Id: Ie8cca9244067b84d0841b01edb938b63ebc47053
Reviewed-on: https://go-review.googlesource.com/c/gollvm/+/239957
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4baae8a..e461235 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,6 +16,7 @@
 
 list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
 set(GOLLVM_USE_SPLIT_STACK ON CACHE BOOL "use split stack by default")
+set(GOLLVM_DEFAULT_LINKER gold CACHE STRING "default linker for Go links")
 
 include(CmakeUtils)
 include(AddGollvm)
diff --git a/README.md b/README.md
index b9881fa..0d5785f 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
 
+
 # Gollvm
 
 Gollvm is an LLVM-based Go compiler. It incorporates "gofrontend" (a Go language front end written in C++ and shared with GCCGO), a bridge component (which translates from gofrontend IR to LLVM IR), and a driver that sends the resulting IR through the LLVM back end.
@@ -80,7 +81,9 @@
 %
 ```
 
-This will build the various tools and libraries needed for Gollvm. To select a specific C/C++ compiler for the build, you can use the "-DCMAKE_C_COMPILER" and "-DCMAKE_CXX_COMPILER" options to select your desired C/C++ compiler when invoking cmake (details [here](https://gitlab.kitware.com/cmake/community/wikis/FAQ#how-do-i-use-a-different-compiler)).
+This will build the various tools and libraries needed for Gollvm. To select a specific C/C++ compiler for the build, you can use the "-DCMAKE_C_COMPILER" and "-DCMAKE_CXX_COMPILER" options to select your desired C/C++ compiler when invoking cmake (details [here](https://gitlab.kitware.com/cmake/community/wikis/FAQ#how-do-i-use-a-different-compiler)). Use the "-DLLVM_USE_LINKER=<variant>" cmake variable to control which linker is selected to link the Gollvm compiler and tools (where variant is one of "bfd", "gold", "lld", etc).
+
+The Gollvm compiler driver defaults to using the gold linker when linking Go programs.  If some other linker is desired, this can be accomplished by passing "-DGOLLVM_DEFAULT_LINKER=<variant>" when running cmake. Note that this default can still be overridden on the command line using the "-fuse-ld" option.
 
 ## Installing gollvm <a name="installing"></a>
 
diff --git a/cmake/modules/AddGollvm.cmake b/cmake/modules/AddGollvm.cmake
index f5dd868..16c6e4f 100644
--- a/cmake/modules/AddGollvm.cmake
+++ b/cmake/modules/AddGollvm.cmake
@@ -20,7 +20,8 @@
 set(GOLLVM_LIBVERSION "${libversion}")
 set(GOLLVM_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}")
 set(GOLLVM_INSTALL_LIBDIR "${CMAKE_INSTALL_PREFIX}/${libsubdir}")
-set(GOLLVM_DEFAULT_LINKER "${LLVM_USE_LINKER}")
+
+message(STATUS "default linker set to \"${GOLLVM_DEFAULT_LINKER}\"")
 
 # Check to see whether the build compiler supports -fcf-protection=branch
 set(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
@@ -39,7 +40,11 @@
   # FIXME: update here once one day there is a linker that supports '-fsplit-stack'
   # on arm64.
   set(C_SUPPORTS_SPLIT_STACK 0)
-  set(CMAKE_REQUIRED_FLAGS "-fuse-ld=gold -fsplit-stack")
+  set(LVARIANT "")
+  if(GOLLVM_DEFAULT_LINKER)
+  set(LVARIANT "-fuse-ld=${GOLLVM_DEFAULT_LINKER}")
+  endif()
+  set(CMAKE_REQUIRED_FLAGS "${LVARIANT} -fsplit-stack")
   check_c_source_compiles("#include<stdio.h>\nint main(){printf(\"hello\");\nreturn 0;}" SPLIT_STACK_FUNCTIONAL)
   if(NOT SPLIT_STACK_FUNCTIONAL)
     if(C_SUPPORTS_CF_PROTECTION_BRANCH)
@@ -47,7 +52,7 @@
       # can cause unpleasant interactions with gold (see
       # https://sourceware.org/bugzilla/show_bug.cgi?id=25921 for details).
       message(STATUS "trying -fcf-protection=none workaround")
-      SET(CMAKE_REQUIRED_FLAGS "-fuse-ld=gold -fsplit-stack -fcf-protection=none")
+      SET(CMAKE_REQUIRED_FLAGS "${LVARIANT} -fsplit-stack -fcf-protection=none")
       check_c_source_compiles("#include<stdio.h>\nint main(){printf(\"hello\");\nreturn 0;}" SPLIT_STACK_WORKAROUND)
       if(SPLIT_STACK_WORKAROUND)
         message(STATUS "applying -fcf-protection=none workaround")
diff --git a/driver/GnuTools.cpp b/driver/GnuTools.cpp
index 2fb63a1..ea148f5 100644
--- a/driver/GnuTools.cpp
+++ b/driver/GnuTools.cpp
@@ -339,11 +339,7 @@
   // will always look for "ld.ABC" on the path. With clang, however,
   // you can supply a full path (e.g. "-fuse-ld=/my/path/to/ld"). This
   // code is intended to be consistent with clang.
-#ifdef GOLLVM_DEFAULT_LINKER
   const char *variant = GOLLVM_DEFAULT_LINKER;
-#else
-  const char *variant = "gold";
-#endif
   const char *linker = nullptr;
   llvm::opt::Arg *ldarg = args.getLastArg(gollvm::options::OPT_fuse_ld_EQ);
   const char *executable = nullptr;
@@ -353,8 +349,13 @@
     else
       variant = args.MakeArgString(ldarg->getValue());
   }
-  if (linker == nullptr)
-    linker = args.MakeArgString(llvm::StringRef("ld.") + variant);
+  if (linker == nullptr) {
+    if (strlen(variant) != 0) {
+      linker = args.MakeArgString(llvm::StringRef("ld.") + variant);
+    } else {
+      linker = args.MakeArgString(llvm::StringRef("ld"));
+    }
+  }
   if (executable == nullptr)
     executable = args.MakeArgString(toolchain().getProgramPath(linker));
   if (! executable) {
diff --git a/driver/GollvmConfig.h.cmake b/driver/GollvmConfig.h.cmake
index b22caca..0b53513 100644
--- a/driver/GollvmConfig.h.cmake
+++ b/driver/GollvmConfig.h.cmake
@@ -22,6 +22,6 @@
 #define GOLLVM_COMPILERVERSION GOLLVM_LIBVERSION
 
 // Gollvm default linker
-#cmakedefine GOLLVM_DEFAULT_LINKER "@GOLLVM_DEFAULT_LINKER@"
+#define GOLLVM_DEFAULT_LINKER "@GOLLVM_DEFAULT_LINKER@"
 
 #endif // GOLLVM_CONFIG_H