[clang] d39a9e3 - [Driver] Support GNU ld on Solaris

Rainer Orth via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 1 12:42:55 PDT 2023


Author: Rainer Orth
Date: 2023-09-01T21:42:05+02:00
New Revision: d39a9e3b4d4afc0321fea72b9d6b8a3908c45fc1

URL: https://github.com/llvm/llvm-project/commit/d39a9e3b4d4afc0321fea72b9d6b8a3908c45fc1
DIFF: https://github.com/llvm/llvm-project/commit/d39a9e3b4d4afc0321fea72b9d6b8a3908c45fc1.diff

LOG: [Driver] Support GNU ld on Solaris

This patch supports GNU ld on Solaris in addition to Solaris ld, the
default.

- Linker selection is dynamic: one can switch between Solaris ld and GNU ld
  at runtime, with the default selectable with `-DCLANG_DEFAULT_LINKER`.

- Testcases have been adjusted to test both variants in case there are
  differences.

- The `compiler-rt/cmake/config-ix.cmake` and
  `llvm/cmake/modules/AddLLVM.cmake` changes to restrict the tests to
  Solaris ld are necessary because GNU accepts unknown `-z` options, but
  warns every time they are used, creating a lot of noise.  Since there
  seems to be no way to check for those warnings in
  `llvm_check_compiler_linker_flag` or `llvm_check_compiler_linker_flag`, I
  restrict the cmake tests to Solaris ld in the first place.

- The changes to `clang/test/Driver/hip-link-bundle-archive.hip` and
  `flang/test/Driver/linker-flags.f90` are required when LLVM is built with
  `-DCLANG_DEFAULT_LINKER=gld` on Solaris: `MSVC.cpp`
  `visualstudio::Linker::ConstructJob` ultimately calls
  `GetProgramPath("gld")`, resulting in a search for `gld`, which exists in
  `/usr/bin/gld` on Solaris.  With `-fuse-ld=`, this doesn't happen and the
  expected `link` is returned.

- `compiler-rt/test/asan/TestCases/global-location-nodebug.cpp` needs to
  enforce the Solaris ld, otherwise the test would `XPASS` with GNU ld
  which has the `-S` semantics expected by the test.

Tested on `amd64-pc-solaris2.11` and `sparcv9-sun-solaris2.11` with both
`-DCLANG_DEFAULT_LINKER=gld` and the default, and `x86_64-pc-linux-gnu`.
No regressions in either case.

Differential Revision: https://reviews.llvm.org/D85309

Added: 
    

Modified: 
    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

Removed: 
    


################################################################################
diff  --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 4daca7ba5fc9544..37db5a2740011d4 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/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"
@@ -993,9 +994,11 @@ static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
 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")) {
@@ -1011,11 +1014,14 @@ void tools::addAsNeededOption(const ToolChain &TC,
                               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 {

diff  --git a/clang/lib/Driver/ToolChains/Solaris.cpp b/clang/lib/Driver/ToolChains/Solaris.cpp
index 1a7839d739655d7..a22e4c2e47b87e6 100644
--- a/clang/lib/Driver/ToolChains/Solaris.cpp
+++ b/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,13 @@ void solaris::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
                                          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;
+  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 +67,32 @@ static bool getPIE(const ArgList &Args, const ToolChain &TC) {
   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 "/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 +100,11 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                    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 +112,12 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   }
 
   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 +135,42 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     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 +259,8 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
       // 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 +287,7 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
 
   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 +348,13 @@ SanitizerMask Solaris::getSupportedSanitizers() const {
   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);
 }

diff  --git a/clang/lib/Driver/ToolChains/Solaris.h b/clang/lib/Driver/ToolChains/Solaris.h
index 9023bf7c37c522e..fe3e7f3a1f1b994 100644
--- a/clang/lib/Driver/ToolChains/Solaris.h
+++ b/clang/lib/Driver/ToolChains/Solaris.h
@@ -32,12 +32,15 @@ class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
                     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,
@@ -64,10 +67,7 @@ class LLVM_LIBRARY_VISIBILITY Solaris : public Generic_ELF {
 
   SanitizerMask getSupportedSanitizers() const override;
 
-  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;

diff  --git a/clang/test/Driver/hip-link-bundle-archive.hip b/clang/test/Driver/hip-link-bundle-archive.hip
index 7da7b91d1e62510..dd1d779fe19a876 100644
--- a/clang/test/Driver/hip-link-bundle-archive.hip
+++ b/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
 

diff  --git a/clang/test/Driver/solaris-ld-sanitizer.c b/clang/test/Driver/solaris-ld-sanitizer.c
index af98f94b0de10ac..a59164787cada13 100644
--- a/clang/test/Driver/solaris-ld-sanitizer.c
+++ b/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 -### 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 --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"
+// 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, 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 --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 -fsanitize=undefined --target=i386-pc-solaris2.11 %s -### 2>&1 \
-// RUN:     --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree \
+// 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-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

diff  --git a/clang/test/Driver/solaris-ld.c b/clang/test/Driver/solaris-ld.c
index 3c1de12b16d1cd0..096ecadbbd60a6d 100644
--- a/clang/test/Driver/solaris-ld.c
+++ b/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 %s
-// RUN: %clang --target=sparc-sun-solaris2.11 -### %s -nopie \
+// 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-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-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 -r -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: %clang --target=sparc-sun-solaris2.11 -### %s -static -pie \
+// 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 %s
+// 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 \

diff  --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake
index 8d3dc8d208b25d1..09a9b62ce4cd37b 100644
--- a/compiler-rt/cmake/config-ix.cmake
+++ b/compiler-rt/cmake/config-ix.cmake
@@ -1,4 +1,5 @@
 include(CMakePushCheckState)
+include(AddLLVM)
 include(LLVMCheckCompilerLinkerFlag)
 include(CheckCCompilerFlag)
 include(CheckCXXCompilerFlag)
@@ -196,7 +197,7 @@ check_library_exists(stdc++ __cxa_throw "" COMPILER_RT_HAS_LIBSTDCXX)
 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()

diff  --git a/compiler-rt/test/asan/TestCases/global-location-nodebug.cpp b/compiler-rt/test/asan/TestCases/global-location-nodebug.cpp
index edbff7c303107aa..07c8e63f439da47 100644
--- a/compiler-rt/test/asan/TestCases/global-location-nodebug.cpp
+++ b/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 
diff erent semantics.
+/// Solaris ld -S has 
diff erent semantics, so enforce -fuse-ld= for
+/// configurations that default to GNU ld.
 // XFAIL: target={{.*solaris.*}}
 
 // CHECK: AddressSanitizer: global-buffer-overflow

diff  --git a/flang/test/Driver/linker-flags.f90 b/flang/test/Driver/linker-flags.f90
index 910d246237f7984..09b8a224df13828 100644
--- a/flang/test/Driver/linker-flags.f90
+++ b/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"

diff  --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake
index a9aed212e5678fa..77b4a51b13b8ca9 100644
--- a/llvm/cmake/modules/AddLLVM.cmake
+++ b/llvm/cmake/modules/AddLLVM.cmake
@@ -282,9 +282,9 @@ function(add_link_opts target_name)
         # 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)
@@ -1281,7 +1281,10 @@ function(export_executable_symbols target)
     # 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()


        


More information about the cfe-commits mailing list