summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td2
-rw-r--r--include/clang/Driver/Options.td2
-rw-r--r--include/clang/Driver/ToolChain.h4
-rw-r--r--lib/Driver/ToolChain.cpp25
-rw-r--r--lib/Driver/ToolChains.cpp2
-rw-r--r--lib/Driver/Tools.cpp18
-rw-r--r--test/Driver/Inputs/basic_android_tree/arm-linux-androideabi/bin/ld0
-rw-r--r--test/Driver/Inputs/basic_android_tree/arm-linux-androideabi/bin/ld.bfd0
-rw-r--r--test/Driver/Inputs/basic_android_tree/arm-linux-androideabi/bin/ld.gold0
-rw-r--r--test/Driver/Inputs/basic_android_tree/bin/arm-linux-androideabi-ld0
-rw-r--r--test/Driver/Inputs/basic_android_tree/bin/arm-linux-androideabi-ld.bfd0
-rw-r--r--test/Driver/Inputs/basic_android_tree/bin/arm-linux-androideabi-ld.gold0
-rw-r--r--test/Driver/Inputs/basic_freebsd_tree/usr/bin/ld.bfd0
-rw-r--r--test/Driver/Inputs/basic_freebsd_tree/usr/bin/ld.gold0
-rw-r--r--test/Driver/fuse-ld.c63
15 files changed, 105 insertions, 11 deletions
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index 7de2250134..957019ee62 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -22,6 +22,8 @@ def err_drv_unknown_stdin_type_clang_cl : Error<
def err_drv_unknown_language : Error<"language not recognized: '%0'">;
def err_drv_invalid_arch_name : Error<
"invalid arch name '%0'">;
+def err_drv_invalid_linker_name : Error<
+ "invalid linker name in argument '%0'">;
def err_drv_invalid_rtlib_name : Error<
"invalid runtime library name in argument '%0'">;
def err_drv_unsupported_rtlib_for_platform : Error<
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index dd8722e1b4..95f13cc384 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -1542,7 +1542,7 @@ def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group<clang_ignored_f_Group>;
defm profile_use : BooleanFFlag<"profile-use">, Group<clang_ignored_f_Group>;
def fprofile_use_EQ : Joined<["-"], "fprofile-use=">, Group<clang_ignored_f_Group>;
-def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group<clang_ignored_f_Group>;
+def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group<f_Group>;
defm align_functions : BooleanFFlag<"align-functions">, Group<clang_ignored_f_Group>;
def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group<clang_ignored_f_Group>;
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index f3db2c1c90..c9a6c4b57f 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -158,6 +158,10 @@ public:
std::string GetFilePath(const char *Name) const;
std::string GetProgramPath(const char *Name) const;
+ /// Returns the linker path, respecting the -fuse-ld= argument to determine
+ /// the linker suffix or name.
+ std::string GetLinkerPath() const;
+
/// \brief Dispatch to the specific toolchain for verbose printing.
///
/// This is used when handling the verbose option to print detailed,
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index eefe487b32..4f90d083c7 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -15,6 +15,7 @@
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/ToolChain.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
@@ -147,6 +148,30 @@ std::string ToolChain::GetProgramPath(const char *Name) const {
return D.GetProgramPath(Name, *this);
}
+std::string ToolChain::GetLinkerPath() const {
+ if (Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
+ StringRef Suffix = A->getValue();
+
+ // If we're passed -fuse-ld= with no argument, or with the argument ld,
+ // then use whatever the default system linker is.
+ if (Suffix.empty() || Suffix == "ld")
+ return GetProgramPath("ld");
+
+ llvm::SmallString<8> LinkerName("ld.");
+ LinkerName.append(Suffix);
+
+ std::string LinkerPath(GetProgramPath(LinkerName.c_str()));
+ if (llvm::sys::fs::exists(LinkerPath))
+ return LinkerPath;
+
+ getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);
+ return "";
+ }
+
+ return GetProgramPath("ld");
+}
+
+
types::ID ToolChain::LookupTypeForExtension(const char *Ext) const {
return types::lookupTypeForExtension(Ext);
}
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index 640cb92a93..d02c84d315 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -3001,7 +3001,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
GCCInstallation.getTriple().str() + "/bin").str());
- Linker = GetProgramPath("ld");
+ Linker = GetLinkerPath();
Distro Distro = DetectDistro(Arch);
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 76b9890ec0..843177414d 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -5614,7 +5614,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_F);
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5804,7 +5804,7 @@ void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA,
addProfileRT(getToolChain(), Args, CmdArgs);
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5912,7 +5912,7 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
addProfileRT(getToolChain(), Args, CmdArgs);
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -6114,7 +6114,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -6250,7 +6250,7 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -6514,7 +6514,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
addProfileRT(ToolChain, Args, CmdArgs);
const char *Exec =
- Args.MakeArgString(ToolChain.GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -6767,7 +6767,7 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
addProfileRT(getToolChain(), Args, CmdArgs);
- const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -7325,7 +7325,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
}
- const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -7503,7 +7503,7 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
addProfileRT(getToolChain(), Args, CmdArgs);
- const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
diff --git a/test/Driver/Inputs/basic_android_tree/arm-linux-androideabi/bin/ld b/test/Driver/Inputs/basic_android_tree/arm-linux-androideabi/bin/ld
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_tree/arm-linux-androideabi/bin/ld
diff --git a/test/Driver/Inputs/basic_android_tree/arm-linux-androideabi/bin/ld.bfd b/test/Driver/Inputs/basic_android_tree/arm-linux-androideabi/bin/ld.bfd
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_tree/arm-linux-androideabi/bin/ld.bfd
diff --git a/test/Driver/Inputs/basic_android_tree/arm-linux-androideabi/bin/ld.gold b/test/Driver/Inputs/basic_android_tree/arm-linux-androideabi/bin/ld.gold
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_tree/arm-linux-androideabi/bin/ld.gold
diff --git a/test/Driver/Inputs/basic_android_tree/bin/arm-linux-androideabi-ld b/test/Driver/Inputs/basic_android_tree/bin/arm-linux-androideabi-ld
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_tree/bin/arm-linux-androideabi-ld
diff --git a/test/Driver/Inputs/basic_android_tree/bin/arm-linux-androideabi-ld.bfd b/test/Driver/Inputs/basic_android_tree/bin/arm-linux-androideabi-ld.bfd
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_tree/bin/arm-linux-androideabi-ld.bfd
diff --git a/test/Driver/Inputs/basic_android_tree/bin/arm-linux-androideabi-ld.gold b/test/Driver/Inputs/basic_android_tree/bin/arm-linux-androideabi-ld.gold
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/Driver/Inputs/basic_android_tree/bin/arm-linux-androideabi-ld.gold
diff --git a/test/Driver/Inputs/basic_freebsd_tree/usr/bin/ld.bfd b/test/Driver/Inputs/basic_freebsd_tree/usr/bin/ld.bfd
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/Driver/Inputs/basic_freebsd_tree/usr/bin/ld.bfd
diff --git a/test/Driver/Inputs/basic_freebsd_tree/usr/bin/ld.gold b/test/Driver/Inputs/basic_freebsd_tree/usr/bin/ld.gold
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/Driver/Inputs/basic_freebsd_tree/usr/bin/ld.gold
diff --git a/test/Driver/fuse-ld.c b/test/Driver/fuse-ld.c
new file mode 100644
index 0000000000..ce7ef182ef
--- /dev/null
+++ b/test/Driver/fuse-ld.c
@@ -0,0 +1,63 @@
+// RUN: %clang %s -### \
+// RUN: -target x86_64-unknown-freebsd 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-FREEBSD-LD
+// CHECK-FREEBSD-LD: ld
+
+// RUN: %clang %s -### -fuse-ld=bfd \
+// RUN: --sysroot=%S/Inputs/basic_freebsd_tree \
+// RUN: -target x86_64-unknown-freebsd \
+// RUN: -B%S/Inputs/basic_freebsd_tree/usr/bin 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-FREEBSD-BFD
+// CHECK-FREEBSD-BFD: Inputs/basic_freebsd_tree/usr/bin/ld.bfd
+
+// RUN: %clang %s -### -fuse-ld=gold \
+// RUN: --sysroot=%S/Inputs/basic_freebsd_tree \
+// RUN: -target x86_64-unknown-freebsd \
+// RUN: -B%S/Inputs/basic_freebsd_tree/usr/bin 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-FREEBSD-GOLD
+// CHECK-FREEBSD-GOLD: Inputs/basic_freebsd_tree/usr/bin/ld.gold
+
+// RUN: %clang %s -### -fuse-ld=plib \
+// RUN: --sysroot=%S/Inputs/basic_freebsd_tree \
+// RUN: -target x86_64-unknown-freebsd \
+// RUN: -B%S/Inputs/basic_freebsd_tree/usr/bin 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-FREEBSD-PLIB
+// CHECK-FREEBSD-PLIB: error: invalid linker name
+
+
+
+// RUN: %clang %s -### \
+// RUN: -target arm-linux-androideabi \
+// RUN: -B%S/Inputs/basic_android_tree/bin 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-ANDROID-ARM-LD
+// CHECK-ANDROID-ARM-LD: Inputs/basic_android_tree/bin/arm-linux-androideabi-ld
+
+// RUN: %clang %s -### -fuse-ld=bfd \
+// RUN: -target arm-linux-androideabi \
+// RUN: -B%S/Inputs/basic_android_tree/bin 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-ANDROID-ARM-BFD
+// CHECK-ANDROID-ARM-BFD: Inputs/basic_android_tree/bin/arm-linux-androideabi-ld.bfd
+
+// RUN: %clang %s -### -fuse-ld=gold \
+// RUN: -target arm-linux-androideabi \
+// RUN: -B%S/Inputs/basic_android_tree/bin 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-ANDROID-ARM-GOLD
+// CHECK-ANDROID-ARM-GOLD: Inputs/basic_android_tree/bin/arm-linux-androideabi-ld.gold
+
+// RUN: %clang %s -### \
+// RUN: -target arm-linux-androideabi \
+// RUN: -gcc-toolchain %S/Inputs/basic_android_tree 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-ANDROID-ARM-LD-TC
+// CHECK-ANDROID-ARM-LD-TC: Inputs/basic_android_tree/lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld
+
+// RUN: %clang %s -### -fuse-ld=bfd \
+// RUN: -target arm-linux-androideabi \
+// RUN: -gcc-toolchain %S/Inputs/basic_android_tree 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-ANDROID-ARM-BFD-TC
+// CHECK-ANDROID-ARM-BFD-TC: Inputs/basic_android_tree/lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld.bfd
+
+// RUN: %clang %s -### -fuse-ld=gold \
+// RUN: -target arm-linux-androideabi \
+// RUN: -gcc-toolchain %S/Inputs/basic_android_tree 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CHECK-ANDROID-ARM-GOLD-TC
+// CHECK-ANDROID-ARM-GOLD-TC: Inputs/basic_android_tree/lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld.gold