The attached patch adds support for calling as and ld directly on
linux. The ld support is disable by default as it suffers from the
existence of many linux distributions with different paths and
different dynamic linkers.
I tested a bootstrap on a Fedora 13 64 bits using both as and ld
directly. I think I can make the assembler support work everywhere,
but for the linker we will need some refactoring. Should I just remove
the linker bits for now?
My idea is to first make sure that the assembler works on more linux
distributions and then slowly start working on the universal driver
design. Eventually the config should include thing like the dynamic
linker and the directory containing the startup files and we should be
able to support running ld directly on linux.
Cheers,
--
Rafael Ávila de Espíndola
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 73c8e6b..2f3b6e7 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -109,6 +109,9 @@ def ccc_print_phases : Flag<"-ccc-print-phases">, CCCDebugOpt,
HelpText<"Dump list of actions to perform">;
def ccc_print_bindings : Flag<"-ccc-print-bindings">, CCCDebugOpt,
HelpText<"Show bindings of tools to actions">;
+def ccc_linux_use_ld : Flag<"-ccc-linux-use-ld">, CCCDebugOpt,
+ HelpText<"On Linux, call ld directly instead of using gcc">;
+
// Make sure all other -ccc- options are rejected.
def ccc_ : Joined<"-ccc-">, Group<ccc_Group>, Flags<[Unsupported]>;
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index 11a153c..05bbf62 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -53,6 +53,7 @@ public:
const Driver &getDriver() const;
const llvm::Triple &getTriple() const { return Triple; }
+ llvm::Triple::ArchType getArch() const { return Triple.getArch(); }
llvm::StringRef getArchName() const { return Triple.getArchName(); }
llvm::StringRef getPlatform() const { return Triple.getVendorName(); }
llvm::StringRef getOS() const { return Triple.getOSName(); }
diff --git a/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp
index 0636d9e..7a7842a 100644
--- a/lib/Driver/HostInfo.cpp
+++ b/lib/Driver/HostInfo.cpp
@@ -585,7 +585,8 @@ ToolChain *LinuxHostInfo::CreateToolChain(const ArgList &Args,
llvm::Triple TCTriple(getTriple());
TCTriple.setArchName(ArchName);
- TC = new toolchains::Linux(*this, TCTriple);
+ TC = new toolchains::Linux(*this, TCTriple,
+ Args.hasArg(options::OPT_ccc_linux_use_ld));
}
return TC;
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index a78d153..7f34987 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -971,8 +971,9 @@ Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA) const {
/// Linux toolchain (very bare-bones at the moment).
-Linux::Linux(const HostInfo &Host, const llvm::Triple& Triple)
- : Generic_GCC(Host, Triple) {
+Linux::Linux(const HostInfo &Host, const llvm::Triple& Triple,
+ bool UseLD_)
+ : Generic_GCC(Host, Triple), UseLD(UseLD_) {
getFilePaths().push_back(getDriver().Dir + "/../lib/clang/1.0/");
getFilePaths().push_back("/lib/");
getFilePaths().push_back("/usr/lib/");
@@ -985,13 +986,39 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple& Triple)
getFilePaths().push_back("/lib64/");
getFilePaths().push_back("/usr/lib64/");
- // FIXME: Figure out some way to get gcc's libdir
- // (e.g. /usr/lib/gcc/i486-linux-gnu/4.3/ for Ubuntu 32-bit); we need
- // crtbegin.o/crtend.o/etc., and want static versions of various
- // libraries. If we had our own crtbegin.o/crtend.o/etc, we could probably
- // get away with using shared versions in /usr/lib, though.
- // We could fall back to the approach we used for includes (a massive
- // list), but that's messy at best.
+
+ // This is starting to look like the large list of include paths we have
+ // for the various linux distros. We have to factor all this in a
+ // per distro configuration.
+
+ // Fedora 13 64 bits
+ getFilePaths().push_back("/usr/lib/gcc/x86_64-redhat-linux/4.4.4/");
+}
+
+Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA) const {
+ Action::ActionClass Key;
+ if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+ Key = Action::AnalyzeJobClass;
+ else
+ Key = JA.getKind();
+
+ Tool *&T = Tools[Key];
+ if (!T) {
+ switch (Key) {
+ case Action::AssembleJobClass:
+ T = new tools::linuxtools::Assemble(*this); break;
+ case Action::LinkJobClass:
+ if (UseLD)
+ T = new tools::linuxtools::Link(*this);
+ else
+ T = &Generic_GCC::SelectTool(C, JA);
+ break;
+ default:
+ T = &Generic_GCC::SelectTool(C, JA);
+ }
+ }
+
+ return *T;
}
/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 4bdd00f..a543f8e 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -287,7 +287,13 @@ public:
class LLVM_LIBRARY_VISIBILITY Linux : public Generic_GCC {
public:
- Linux(const HostInfo &Host, const llvm::Triple& Triple);
+ Linux(const HostInfo &Host, const llvm::Triple& Triple, bool UseLD);
+
+ virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+private:
+
+ // Use ld directly instead of gcc.
+ bool UseLD;
};
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index f423d4e..35542ff 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -3056,6 +3056,149 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
+void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ Job &Dest, const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ // Add --32/--64 to make sure we get the format we want.
+ // This is incomplete
+ if (getToolChain().getArch() == llvm::Triple::x86)
+ CmdArgs.push_back("--32");
+ else if (getToolChain().getArch() == llvm::Triple::x86_64)
+ CmdArgs.push_back("--64");
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ if (Output.isPipe())
+ CmdArgs.push_back("-");
+ else
+ CmdArgs.push_back(Output.getFilename());
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+ if (II.isPipe())
+ CmdArgs.push_back("-");
+ else
+ CmdArgs.push_back(II.getFilename());
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ Job &Dest, const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ // FIXME: This should be shared with the BSD implementations.
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-shared");
+ } else {
+ CmdArgs.push_back("-dynamic-linker");
+
+ // FIXME: This has to come from some configuration. Different linux distros
+ // use different dynamic linkers.
+ CmdArgs.push_back("/lib64/ld-linux-x86-64.so.2");
+ }
+
+ if (Output.isPipe()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back("-");
+ } else if (Output.isFilename()) {
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crt1.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbegin.o")));
+ } else {
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crtbeginS.o")));
+ }
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
+ Args.AddAllArgs(CmdArgs, options::OPT_e);
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+
+ // Don't try to pass LLVM inputs to a generic ld.
+ if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR ||
+ II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC)
+ D.Diag(clang::diag::err_drv_no_linker_llvm_support)
+ << getToolChain().getTripleString();
+
+ if (II.isPipe())
+ CmdArgs.push_back("-");
+ else if (II.isFilename())
+ CmdArgs.push_back(II.getFilename());
+ else
+ II.getInputArg().renderAsInput(Args, CmdArgs);
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ // Fedora 13 64 bits
+ CmdArgs.push_back("-L/usr/lib/gcc/x86_64-redhat-linux/4.4.4");
+ if (D.CCCIsCXX) {
+ CmdArgs.push_back("-lstdc++");
+ CmdArgs.push_back("-lm");
+ }
+ if (!Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("--start-group");
+ CmdArgs.push_back("-lgcc");
+ CmdArgs.push_back("-lgcc_eh");
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("--end-group");
+ } else {
+ CmdArgs.push_back("-lgcc_s");
+ CmdArgs.push_back("-lc");
+ // Copying gcc, but this is redundant, no?
+ CmdArgs.push_back("-lgcc_s");
+ }
+
+ if (!Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
+ "crtend.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
+ "crtendS.o")));
+
+ CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(
+ "crtn.o")));
+
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("ld"));
+ Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
Job &Dest, const InputInfo &Output,
const InputInfoList &Inputs,
diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h
index 2a18103..ec3367b 100644
--- a/lib/Driver/Tools.h
+++ b/lib/Driver/Tools.h
@@ -377,6 +377,40 @@ namespace freebsd {
};
} // end namespace freebsd
+ /// linux -- Directly call GNU Binutils assembler and linker
+namespace linuxtools {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("linux::Assemble", "assembler",
+ TC) {}
+
+ virtual bool acceptsPipedInput() const { return true; }
+ virtual bool canPipeOutput() const { return true; }
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ Job &Dest,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("linux::Link", "linker", TC) {}
+
+ virtual bool acceptsPipedInput() const { return true; }
+ virtual bool canPipeOutput() const { return true; }
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ Job &Dest,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+}
/// minix -- Directly call GNU Binutils assembler and linker
namespace minix {
class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits