ro updated this revision to Diff 554946.
ro marked an inline comment as done.
ro added a comment.

Move `isLinkerGnuLd` to `Solaris.{h,cpp}` and into `solaris` namespace to make 
it unambigously clear where to use it.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D85309/new/

https://reviews.llvm.org/D85309

Files:
  clang/lib/Driver/ToolChains/CommonArgs.cpp
  clang/lib/Driver/ToolChains/Solaris.cpp
  clang/lib/Driver/ToolChains/Solaris.h
  clang/test/Driver/hip-link-bundle-archive.hip
  clang/test/Driver/solaris-ld-sanitizer.c
  clang/test/Driver/solaris-ld.c
  compiler-rt/cmake/config-ix.cmake
  compiler-rt/test/asan/TestCases/global-location-nodebug.cpp
  flang/test/Driver/linker-flags.f90
  llvm/cmake/modules/AddLLVM.cmake

Index: llvm/cmake/modules/AddLLVM.cmake
===================================================================
--- llvm/cmake/modules/AddLLVM.cmake
+++ llvm/cmake/modules/AddLLVM.cmake
@@ -282,9 +282,9 @@
         # ld64's implementation of -dead_strip breaks tools that use plugins.
         set_property(TARGET ${target_name} APPEND_STRING PROPERTY
                      LINK_FLAGS " -Wl,-dead_strip")
-      elseif(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
+      elseif(${CMAKE_SYSTEM_NAME} MATCHES "SunOS" AND LLVM_LINKER_IS_SOLARISLD)
         # Support for ld -z discard-unused=sections was only added in
-        # Solaris 11.4.
+        # Solaris 11.4.  GNU ld ignores it, but warns every time.
         include(LLVMCheckLinkerFlag)
         llvm_check_linker_flag(CXX "-Wl,-z,discard-unused=sections" LINKER_SUPPORTS_Z_DISCARD_UNUSED)
         if (LINKER_SUPPORTS_Z_DISCARD_UNUSED)
@@ -1288,7 +1288,10 @@
     # the size of the exported symbol table, but on other platforms we can do
     # it without any trouble.
     set_target_properties(${target} PROPERTIES ENABLE_EXPORTS 1)
-    if (APPLE)
+    # CMake doesn't set CMAKE_EXE_EXPORTS_${lang}_FLAG on Solaris, so
+    # ENABLE_EXPORTS has no effect.  While Solaris ld defaults to -rdynamic
+    # behaviour, GNU ld needs it.
+    if (APPLE OR ${CMAKE_SYSTEM_NAME} STREQUAL "SunOS")
       set_property(TARGET ${target} APPEND_STRING PROPERTY
         LINK_FLAGS " -rdynamic")
     endif()
Index: flang/test/Driver/linker-flags.f90
===================================================================
--- flang/test/Driver/linker-flags.f90
+++ flang/test/Driver/linker-flags.f90
@@ -10,7 +10,7 @@
 !       'oldnames' on Windows, but they are not needed when compiling
 !       Fortran code and they might bring in additional dependencies.
 !       Make sure they're not added.
-! RUN: %flang -### -target aarch64-windows-msvc %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MSVC --implicit-check-not libcmt --implicit-check-not oldnames
+! RUN: %flang -### -target aarch64-windows-msvc -fuse-ld= %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MSVC --implicit-check-not libcmt --implicit-check-not oldnames
 
 ! Compiler invocation to generate the object file
 ! CHECK-LABEL: {{.*}} "-emit-obj"
Index: compiler-rt/test/asan/TestCases/global-location-nodebug.cpp
===================================================================
--- compiler-rt/test/asan/TestCases/global-location-nodebug.cpp
+++ compiler-rt/test/asan/TestCases/global-location-nodebug.cpp
@@ -2,13 +2,14 @@
 /// allow this test to also run on Windows (which can't be done for the
 /// debuginfo variant).
 
-// RUN: %clangxx_asan -O2 %S/global-location.cpp -o %t %if target={{.*-windows-msvc.*}} %{ -Wl,/DEBUG:NONE %} %else %{ -Wl,-S %}
+// RUN: %clangxx_asan -O2 %S/global-location.cpp -o %t %if target={{.*-windows-msvc.*}} %{ -Wl,/DEBUG:NONE %} %else %{ -Wl,-S %} %if target={{.*-solaris.*}} %{ -fuse-ld= %}
 // RUN: not %run %t g 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=GLOB-NO-G
 // RUN: not %run %t c 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CLASS_STATIC-NO-G
 // RUN: not %run %t f 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=FUNC_STATIC-NO-G
 // RUN: not %run %t l 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=LITERAL-NO-G
 
-/// Solaris ld -S has different semantics.
+/// Solaris ld -S has different semantics, so enforce -fuse-ld= for
+/// configurations that default to GNU ld.
 // XFAIL: target={{.*solaris.*}}
 
 // CHECK: AddressSanitizer: global-buffer-overflow
Index: compiler-rt/cmake/config-ix.cmake
===================================================================
--- compiler-rt/cmake/config-ix.cmake
+++ compiler-rt/cmake/config-ix.cmake
@@ -1,4 +1,5 @@
 include(CMakePushCheckState)
+include(AddLLVM)
 include(LLVMCheckCompilerLinkerFlag)
 include(CheckCCompilerFlag)
 include(CheckCXXCompilerFlag)
@@ -196,7 +197,7 @@
 llvm_check_compiler_linker_flag(C "-Wl,-z,text" COMPILER_RT_HAS_Z_TEXT)
 llvm_check_compiler_linker_flag(C "-fuse-ld=lld" COMPILER_RT_HAS_FUSE_LD_LLD_FLAG)
 
-if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
+if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS" AND LLVM_LINKER_IS_SOLARISLD)
   set(VERS_COMPAT_OPTION "-Wl,-z,gnu-version-script-compat")
   llvm_check_compiler_linker_flag(C "${VERS_COMPAT_OPTION}" COMPILER_RT_HAS_GNU_VERSION_SCRIPT_COMPAT)
 endif()
Index: clang/test/Driver/solaris-ld.c
===================================================================
--- clang/test/Driver/solaris-ld.c
+++ clang/test/Driver/solaris-ld.c
@@ -2,10 +2,14 @@
 // sysroot to make these tests independent of the host system.
 
 // Check sparc-sun-solaris2.11, 32bit
-// RUN: %clang -### %s 2>&1 --target=sparc-sun-solaris2.11 \
+// RUN: %clang -### %s --target=sparc-sun-solaris2.11 -fuse-ld= \
 // RUN:     --gcc-toolchain="" \
-// RUN:     --sysroot=%S/Inputs/solaris_sparc_tree \
-// RUN:   | FileCheck --check-prefix=CHECK-LD-SPARC32 %s
+// RUN:     --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \
+// RUN:   | FileCheck --check-prefixes=CHECK-LD-SPARC32,CHECK-LD %s
+// RUN: %clang -### %s --target=sparc-sun-solaris2.11 -fuse-ld=gld \
+// RUN:     --gcc-toolchain="" \
+// RUN:     --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \
+// RUN:   | FileCheck --check-prefixes=CHECK-LD-SPARC32,CHECK-GLD %s
 // CHECK-LD-SPARC32-NOT: warning:
 // CHECK-LD-SPARC32: "-cc1" "-triple" "sparc-sun-solaris2.11"
 // CHECK-LD-SPARC32-SAME: "-isysroot" "[[SYSROOT:[^"]+]]"
@@ -16,7 +20,8 @@
 // CHECK-LD-SPARC32-SAME: "-L[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2"
 // CHECK-LD-SPARC32-SAME: "-L[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/../../.."
 // CHECK-LD-SPARC32-SAME: "-L[[SYSROOT]]/usr/lib"
-// CHECK-LD-SPARC32-SAME: "-z" "ignore" "-latomic" "-z" "record"
+// CHECK-LD: "-z" "ignore" "-latomic" "-z" "record"
+// CHECK-GLD: "--as-needed" "-latomic" "--no-as-needed"
 // CHECK-LD-SPARC32-SAME: "-lgcc_s"
 // CHECK-LD-SPARC32-SAME: "-lc"
 // CHECK-LD-SPARC32-SAME: "-lgcc"
@@ -107,31 +112,53 @@
 // CHECK-SPARC32-SHARED-NOT: "-lm"
 
 // Check the right ld flags are present with -pie.
-// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -pie \
+// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -pie -fuse-ld= \
+// RUN:     --gcc-toolchain="" \
+// RUN:     --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-PIE-LD %s
+// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -pie -fuse-ld=gld \
 // RUN:     --gcc-toolchain="" \
 // RUN:     --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \
-// RUN:   | FileCheck --check-prefix=CHECK-PIE %s
-// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -nopie \
+// RUN:   | FileCheck --check-prefix=CHECK-PIE-GLD %s
+// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -nopie -fuse-ld= \
 // RUN:     --gcc-toolchain="" \
 // RUN:     --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \
-// RUN:   | FileCheck --check-prefix=CHECK-NOPIE %s
+// RUN:   | FileCheck --check-prefix=CHECK-NOPIE-LD %s
+// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -nopie -fuse-ld=gld \
+// RUN:     --gcc-toolchain="" \
+// RUN:     --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-NOPIE-GLD %s
 
 // Check that -shared/-r/-static disable PIE.
-// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -shared -pie \
+// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -shared -pie -fuse-ld= \
 // RUN:     --gcc-toolchain="" \
 // RUN:     --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \
-// RUN:   | FileCheck --check-prefix=CHECK-NOPIE %s
-// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -r -pie \
+// RUN:   | FileCheck --check-prefix=CHECK-NOPIE-LD %s
+// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -shared -pie -fuse-ld=gld \
+// RUN:     --gcc-toolchain="" \
+// RUN:     --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-NOPIE-GLD %s
+// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -r -pie -fuse-ld= \
+// RUN:     --gcc-toolchain="" \
+// RUN:     --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-NOPIE-LD %s
+// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -r -pie -fuse-ld=gld \
 // RUN:     --gcc-toolchain="" \
 // RUN:     --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \
-// RUN:   | FileCheck --check-prefix=CHECK-NOPIE %s
-// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -static -pie \
+// RUN:   | FileCheck --check-prefix=CHECK-NOPIE-GLD %s
+// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -static -pie -fuse-ld= \
 // RUN:     --gcc-toolchain="" \
 // RUN:     --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \
-// RUN:   | FileCheck --check-prefix=CHECK-NOPIE %s
+// RUN:   | FileCheck --check-prefix=CHECK-NOPIE-LD %s
+// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -static -pie -fuse-ld=gld \
+// RUN:     --gcc-toolchain="" \
+// RUN:     --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-NOPIE-GLD %s
 
-// CHECK-PIE: "-z" "type=pie"
-// CHECK-NOPIE-NOT: "-z" "type=pie"
+// CHECK-PIE-LD: "-z" "type=pie"
+// CHECK-PIE-GLD: "-pie"
+// CHECK-NOPIE-LD-NOT: "-z" "type=pie"
+// CHECK-NOPIE-GLD-NOT: "-pie"
 
 // -r suppresses default -l and crt*.o, values-*.o like -nostdlib.
 // RUN: %clang -### %s --target=sparc-sun-solaris2.11 -r 2>&1 \
Index: clang/test/Driver/solaris-ld-sanitizer.c
===================================================================
--- clang/test/Driver/solaris-ld-sanitizer.c
+++ clang/test/Driver/solaris-ld-sanitizer.c
@@ -3,55 +3,55 @@
 /// independent of the host system.
 
 /// Check sparc-sun-solaris2.11, 32bit
-// RUN: %clang --target=sparc-sun-solaris2.11 %s -### 2>&1 \
-// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree \
-// RUN:   | FileCheck --check-prefix=CHECK-LD-SPARC32 %s
-// CHECK-LD-SPARC32-NOT: "-z" "relax=transtls"
+// RUN: %clang --target=sparc-sun-solaris2.11 %s -### -fuse-ld= \
+// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-LD %s
 
 /// Check sparc-sun-solaris2.11, 32bit
-// RUN: %clang -fsanitize=undefined --target=sparc-sun-solaris2.11 %s -### 2>&1 \
-// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree \
-// RUN:   | FileCheck --check-prefix=CHECK-LD-SPARC32 %s
-// CHECK-LD-SPARC32-NOT: "-z" "relax=transtls"
+// RUN: %clang -fsanitize=undefined --target=sparc-sun-solaris2.11 %s -### -fuse-ld= \
+// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-LD %s
 
 /// Check sparc-sun-solaris2.11, 64bit
-// RUN: %clang -m64 --target=sparc-sun-solaris2.11 %s -### 2>&1 \
-// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree \
-// RUN:   | FileCheck --check-prefix=CHECK-LD-SPARC64 %s
-// CHECK-LD-SPARC64-NOT: "-z" "relax=transtls"
+// RUN: %clang -m64 --target=sparc-sun-solaris2.11 %s -### -fuse-ld= \
+// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-LD %s
 
 /// Check sparc-sun-solaris2.11, 64bit
-// RUN: %clang -m64 -fsanitize=undefined --target=sparc-sun-solaris2.11 %s -### 2>&1 \
-// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree \
-// RUN:   | FileCheck --check-prefix=CHECK-LD-SPARC64 %s
-// CHECK-LD-SPARC64-NOT: "-z" "relax=transtls"
+// RUN: %clang -m64 -fsanitize=undefined --target=sparc-sun-solaris2.11 %s -### -fuse-ld= \
+// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-LD %s
+
+/// Check i386-pc-solaris2.11, 32bit
+// RUN: %clang --target=i386-pc-solaris2.11 %s -### -fuse-ld= \
+// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-LD %s
 
 /// Check i386-pc-solaris2.11, 32bit
-// RUN: %clang --target=i386-pc-solaris2.11 %s -### 2>&1 \
-// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree \
-// RUN:   | FileCheck --check-prefix=CHECK-LD-X32 %s
-// CHECK-LD-X32-NOT: "-z" "relax=transtls"
+// RUN: %clang -fsanitize=undefined --target=i386-pc-solaris2.11 %s -### -fuse-ld= \
+// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-LD %s
 
-/// Check i386-pc-solaris2.11, 32bit
-// RUN: %clang -fsanitize=undefined --target=i386-pc-solaris2.11 %s -### 2>&1 \
-// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree \
-// RUN:   | FileCheck --check-prefix=CHECK-LD-X32 %s
-// CHECK-LD-X32-NOT: "-z" "relax=transtls"
+/// Check i386-pc-solaris2.11, 64bit
+// RUN: %clang -m64 --target=i386-pc-solaris2.11 %s -### -fuse-ld= \
+// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-LD %s
+
+// CHECK-LD-NOT: "-z" "relax=transtls"
 
 /// Check i386-pc-solaris2.11, 64bit
-// RUN: %clang -m64 --target=i386-pc-solaris2.11 %s -### 2>&1 \
-// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree \
-// RUN:   | FileCheck --check-prefix=CHECK-LD-X64 %s
-// CHECK-LD-X64-NOT: "-z" "relax=transtls"
+// RUN: %clang -m64 -fsanitize=undefined --target=i386-pc-solaris2.11 %s -### -fuse-ld= \
+// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-LD-X64-UBSAN %s
+// RUN: %clang -m64 -fsanitize=undefined --target=i386-pc-solaris2.11 %s -### -fuse-ld=gld \
+// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-GLD-X64-UBSAN %s
 
-/// Check i386-pc-solaris2.11, 64bit
-// RUN: %clang -m64 -fsanitize=undefined --target=i386-pc-solaris2.11 %s -### 2>&1 \
-// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree \
-// RUN:   | FileCheck --check-prefix=CHECK-LD-X64-UBSAN %s
 // CHECK-LD-X64-UBSAN: "-z" "relax=transtls"
+// CHECK-GLD-X64-UBSAN-NOT: "-z" "relax=transtls"
 
 /// General tests that the ld -z now workaround is only applied on
-/// Solaris/i386 with shared libclang_rt.asan.. Note that we use sysroot to
+/// Solaris/i386 with shared libclang_rt.asan. Note that we use sysroot to
 /// make these tests independent of the host system.
 
 /// Check i386-pc-solaris2.11, 32bit, shared libclang_rt.asan
Index: clang/test/Driver/hip-link-bundle-archive.hip
===================================================================
--- clang/test/Driver/hip-link-bundle-archive.hip
+++ clang/test/Driver/hip-link-bundle-archive.hip
@@ -56,17 +56,17 @@
 
 // RUN: llvm-ar cr %t/hipBundled2.lib %t/dummy.bc
 // RUN: %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \
-// RUN:   --target=x86_64-pc-windows-msvc \
+// RUN:   --target=x86_64-pc-windows-msvc -fuse-ld= \
 // RUN:   -nogpuinc -nogpulib %s -fgpu-rdc -L%t -lhipBundled2 \
 // RUN:   2>&1 | FileCheck -check-prefix=MSVC %s
 
 // RUN: %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \
-// RUN:   --target=x86_64-pc-windows-msvc \
+// RUN:   --target=x86_64-pc-windows-msvc -fuse-ld= \
 // RUN:   -nogpuinc -nogpulib %s -fgpu-rdc -L%t -l:hipBundled2.lib \
 // RUN:   2>&1 | FileCheck -check-prefix=MSVC %s
 
 // RUN: %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \
-// RUN:   --target=x86_64-pc-windows-msvc \
+// RUN:   --target=x86_64-pc-windows-msvc -fuse-ld= \
 // RUN:   -nogpuinc -nogpulib %s -fgpu-rdc %t/hipBundled2.lib \
 // RUN:   2>&1 | FileCheck -check-prefix=MSVC %s
 
Index: clang/lib/Driver/ToolChains/Solaris.h
===================================================================
--- clang/lib/Driver/ToolChains/Solaris.h
+++ clang/lib/Driver/ToolChains/Solaris.h
@@ -32,12 +32,15 @@
                     const char *LinkingOutput) const override;
 };
 
+bool isLinkerGnuLd(const ToolChain &TC, const llvm::opt::ArgList &Args);
+
 class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
 public:
   Linker(const ToolChain &TC) : Tool("solaris::Linker", "linker", TC) {}
 
   bool hasIntegratedCPP() const override { return false; }
   bool isLinkJob() const override { return true; }
+  std::string getLinkerPath(const llvm::opt::ArgList &Args) const;
 
   void ConstructJob(Compilation &C, const JobAction &JA,
                     const InputInfo &Output, const InputInfoList &Inputs,
@@ -65,10 +68,7 @@
   SanitizerMask getSupportedSanitizers() const override;
   unsigned GetDefaultDwarfVersion() const override { return 2; }
 
-  const char *getDefaultLinker() const override {
-    // clang currently uses Solaris ld-only options.
-    return "/usr/bin/ld";
-  }
+  const char *getDefaultLinker() const override;
 
 protected:
   Tool *buildAssembler() const override;
Index: clang/lib/Driver/ToolChains/Solaris.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Solaris.cpp
+++ clang/lib/Driver/ToolChains/Solaris.cpp
@@ -16,6 +16,7 @@
 #include "clang/Driver/Options.h"
 #include "clang/Driver/SanitizerArgs.h"
 #include "clang/Driver/ToolChain.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
@@ -47,6 +48,14 @@
                                          Exec, CmdArgs, Inputs, Output));
 }
 
+bool solaris::isLinkerGnuLd(const ToolChain &TC, const ArgList &Args) {
+  // Only used if targetting Solaris.
+  const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ);
+  StringRef UseLinker = A ? A->getValue() : CLANG_DEFAULT_LINKER;
+  // FIXME: What about -fuse-ld=<path>?
+  return UseLinker == "bfd" || UseLinker == "gld";
+}
+
 static bool getPIE(const ArgList &Args, const ToolChain &TC) {
   if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_static) ||
       Args.hasArg(options::OPT_r))
@@ -59,6 +68,32 @@
   return A->getOption().matches(options::OPT_pie);
 }
 
+// FIXME: Need to handle CLANG_DEFAULT_LINKER here?
+std::string solaris::Linker::getLinkerPath(const ArgList &Args) const {
+  const ToolChain &ToolChain = getToolChain();
+  if (const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
+    StringRef UseLinker = A->getValue();
+    if (!UseLinker.empty()) {
+      if (llvm::sys::path::is_absolute(UseLinker) &&
+          llvm::sys::fs::can_execute(UseLinker))
+        return std::string(UseLinker);
+
+      // Accept 'bfd' and 'gld' as aliases for the GNU linker.
+      if (UseLinker == "bfd" || UseLinker == "gld")
+        // FIXME: Could also use /usr/bin/gld here.
+        return std::string("/usr/gnu/bin/ld");
+
+      // Accept 'ld' as alias for the default linker
+      if (UseLinker != "ld")
+        ToolChain.getDriver().Diag(diag::err_drv_invalid_linker_name)
+            << A->getAsString(Args);
+    }
+  }
+
+  // getDefaultLinker() always returns an absolute path.
+  return ToolChain.getDefaultLinker();
+}
+
 void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs,
@@ -66,9 +101,11 @@
                                    const char *LinkingOutput) const {
   const bool IsPIE = getPIE(Args, getToolChain());
   ArgStringList CmdArgs;
+  bool LinkerIsGnuLd = isLinkerGnuLd(getToolChain(), Args);
 
-  // Demangle C++ names in errors
-  CmdArgs.push_back("-C");
+  // Demangle C++ names in errors.  GNU ld already defaults to --demangle.
+  if (!LinkerIsGnuLd)
+    CmdArgs.push_back("-C");
 
   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
     CmdArgs.push_back("-e");
@@ -76,8 +113,12 @@
   }
 
   if (IsPIE) {
-    CmdArgs.push_back("-z");
-    CmdArgs.push_back("type=pie");
+    if (LinkerIsGnuLd) {
+      CmdArgs.push_back("-pie");
+    } else {
+      CmdArgs.push_back("-z");
+      CmdArgs.push_back("type=pie");
+    }
   }
 
   if (Args.hasArg(options::OPT_static)) {
@@ -95,6 +136,42 @@
     Args.ClaimAllArgs(options::OPT_pthreads);
   }
 
+  if (LinkerIsGnuLd) {
+    // Set the correct linker emulation for 32- and 64-bit Solaris.
+    const toolchains::Solaris &ToolChain =
+        static_cast<const toolchains::Solaris &>(getToolChain());
+    const llvm::Triple::ArchType Arch = ToolChain.getArch();
+
+    switch (Arch) {
+    case llvm::Triple::x86:
+      CmdArgs.push_back("-m");
+      CmdArgs.push_back("elf_i386_sol2");
+      break;
+    case llvm::Triple::x86_64:
+      CmdArgs.push_back("-m");
+      CmdArgs.push_back("elf_x86_64_sol2");
+      break;
+    case llvm::Triple::sparc:
+      CmdArgs.push_back("-m");
+      CmdArgs.push_back("elf32_sparc_sol2");
+      break;
+    case llvm::Triple::sparcv9:
+      CmdArgs.push_back("-m");
+      CmdArgs.push_back("elf64_sparc_sol2");
+      break;
+    default:
+      break;
+    }
+
+    if (Args.hasArg(options::OPT_rdynamic))
+      CmdArgs.push_back("-export-dynamic");
+
+    CmdArgs.push_back("--eh-frame-hdr");
+  } else {
+    // -rdynamic is a no-op with Solaris ld.  Claim argument to avoid warning.
+    Args.ClaimAllArgs(options::OPT_rdynamic);
+  }
+
   if (Output.isFilename()) {
     CmdArgs.push_back("-o");
     CmdArgs.push_back(Output.getFilename());
@@ -183,7 +260,8 @@
       // in Illumos.
       if (getToolChain().getTriple().getArch() == llvm::Triple::x86_64 &&
           (SA.needsAsanRt() || SA.needsStatsRt() ||
-           (SA.needsUbsanRt() && !SA.requiresMinimalRuntime()))) {
+           (SA.needsUbsanRt() && !SA.requiresMinimalRuntime())) &&
+          !LinkerIsGnuLd) {
         CmdArgs.push_back("-z");
         CmdArgs.push_back("relax=transtls");
       }
@@ -210,7 +288,7 @@
 
   getToolChain().addProfileRTLibs(Args, CmdArgs);
 
-  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
+  const char *Exec = Args.MakeArgString(getLinkerPath(Args));
   C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
                                          Exec, CmdArgs, Inputs, Output));
 }
@@ -271,6 +349,13 @@
   return Res;
 }
 
+const char *Solaris::getDefaultLinker() const {
+  // FIXME: Only handle Solaris ld and GNU ld here.
+  return llvm::StringSwitch<const char *>(CLANG_DEFAULT_LINKER)
+      .Cases("bfd", "gld", "/usr/gnu/bin/ld")
+      .Default("/usr/bin/ld");
+}
+
 Tool *Solaris::buildAssembler() const {
   return new tools::solaris::Assembler(*this);
 }
Index: clang/lib/Driver/ToolChains/CommonArgs.cpp
===================================================================
--- clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -22,6 +22,7 @@
 #include "HIPAMD.h"
 #include "Hexagon.h"
 #include "MSP430.h"
+#include "Solaris.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/Basic/ObjCRuntime.h"
@@ -987,9 +988,11 @@
 static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
                                     ArgStringList &CmdArgs,
                                     StringRef Sanitizer) {
+  bool LinkerIsGnuLd = solaris::isLinkerGnuLd(TC, Args);
+
   // Solaris ld defaults to --export-dynamic behaviour but doesn't support
   // the option, so don't try to pass it.
-  if (TC.getTriple().getOS() == llvm::Triple::Solaris)
+  if (TC.getTriple().getOS() == llvm::Triple::Solaris && !LinkerIsGnuLd)
     return true;
   SmallString<128> SanRT(TC.getCompilerRT(Args, Sanitizer));
   if (llvm::sys::fs::exists(SanRT + ".syms")) {
@@ -1005,11 +1008,14 @@
                               bool as_needed) {
   assert(!TC.getTriple().isOSAIX() &&
          "AIX linker does not support any form of --as-needed option yet.");
+  bool LinkerIsGnuLd = solaris::isLinkerGnuLd(TC, Args);
 
   // While the Solaris 11.2 ld added --as-needed/--no-as-needed as aliases
   // for the native forms -z ignore/-z record, they are missing in Illumos,
   // so always use the native form.
-  if (TC.getTriple().isOSSolaris()) {
+  // GNU ld doesn't support -z ignore/-z record, so don't use them even on
+  // Solaris.
+  if (TC.getTriple().isOSSolaris() && !LinkerIsGnuLd) {
     CmdArgs.push_back("-z");
     CmdArgs.push_back(as_needed ? "ignore" : "record");
   } else {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to