Add support for -fuse-ld=.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@194328 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index ed49006..5d54642 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -20,6 +20,8 @@
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 faaaee1..45a46e2 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -1434,7 +1434,8 @@
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>,
+ HelpText<"The suffix of the linker to use (e.g. bfd for ld.bfd).">;
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 12bce28..a0d757c 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -126,6 +126,9 @@
path_list &getProgramPaths() { return ProgramPaths; }
const path_list &getProgramPaths() const { return ProgramPaths; }
+ /// Returns the linker path, respecting the -fuse-ld= argument to determine
+ /// the linker suffix or name.
+ std::string GetLinkerPath() const;
const SanitizerArgs& getSanitizerArgs() const;
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index 9fe0379..20e37ff 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -146,6 +146,28 @@
return D.GetProgramPath(Name, *this);
}
+std::string ToolChain::GetLinkerPath() const {
+ if (Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
+ StringRef Value = 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 (Value.empty() || Value == "ld")
+ return GetProgramPath("ld");
+ std::string LinkerName = Value.str();
+ std::string LD("ld.");
+ LD += LinkerName;
+ std::string LinkerPath = GetProgramPath(LD.c_str());
+ bool Exists;
+ if (!llvm::sys::fs::exists(LinkerPath, Exists) && Exists)
+ 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/Tools.cpp b/lib/Driver/Tools.cpp
index 7c98719..378cc4e 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -5184,7 +5184,7 @@
addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5296,7 +5296,7 @@
addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5447,7 +5447,7 @@
}
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5587,7 +5587,7 @@
}
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5838,7 +5838,7 @@
addProfileRT(ToolChain, Args, CmdArgs, ToolChain.getTriple());
const char *Exec =
- Args.MakeArgString(ToolChain.GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -5992,7 +5992,7 @@
addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());
- const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
@@ -6503,7 +6503,7 @@
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));
}
@@ -6687,7 +6687,7 @@
addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple());
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ Args.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
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 0000000..e69de29
--- /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 0000000..e69de29
--- /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 0000000..241047d
--- /dev/null
+++ b/test/Driver/fuse_ld.c
@@ -0,0 +1,14 @@
+// RUN: %clang %s -### 2>&1 | FileCheck %s
+// CHECK: ld
+// RUN: %clang -fuse-ld=bfd --sysroot=%S/Inputs/basic_freebsd_tree \
+// RUN: -B%S/Inputs/basic_freebsd_tree %s -### 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-BFD %s
+// CHECK-BFD: ld.bfd
+// RUN: %clang -fuse-ld=gold --sysroot=%S/Inputs/basic_freebsd_tree \
+// RUN: -B%S/Inputs/basic_freebsd_tree %s -### 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-GOLD %s
+// CHECK-GOLD: ld.gold
+// RUN: %clang -fuse-ld=plib --sysroot=%S/Inputs/basic_freebsd_tree \
+// RUN: -B%S/Inputs/basic_freebsd_tree %s -### 2>&1 | \
+// RUN: FileCheck -check-prefix=CHECK-PLIB %s
+// CHECK-PLIB: error: invalid linker name