summaryrefslogtreecommitdiffstats
path: root/lib/Driver/ToolChains.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver/ToolChains.cpp')
-rw-r--r--lib/Driver/ToolChains.cpp516
1 files changed, 469 insertions, 47 deletions
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index 471c47d..13b8b46 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -1,4 +1,4 @@
-//===--- ToolChains.cpp - ToolChain Implementations ---------------------*-===//
+//===--- ToolChains.cpp - ToolChain Implementations -----------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -23,8 +23,11 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/System/Path.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/system_error.h"
#include <cstdlib> // ::getenv
@@ -59,6 +62,10 @@ types::ID Darwin::LookupTypeForExtension(const char *Ext) const {
return Ty;
}
+bool Darwin::HasNativeLLVMSupport() const {
+ return true;
+}
+
// FIXME: Can we tablegen this?
static const char *GetArmArchForMArch(llvm::StringRef Value) {
if (Value == "armv6k")
@@ -142,7 +149,8 @@ DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple)
// Try the next major version if that tool chain dir is invalid.
std::string Tmp = "/usr/lib/gcc/" + ToolChainDir;
- if (!llvm::sys::Path(Tmp).exists()) {
+ bool Exists;
+ if (llvm::sys::fs::exists(Tmp, Exists) || Exists) {
std::string Next = "i686-apple-darwin";
Next += llvm::utostr(DarwinVersion[0] + 1);
Next += "/";
@@ -156,7 +164,7 @@ DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple)
//
// FIXME: Drop dependency on gcc's tool chain.
Tmp = "/usr/lib/gcc/" + Next;
- if (llvm::sys::Path(Tmp).exists())
+ if (!llvm::sys::fs::exists(Tmp, Exists) && Exists)
ToolChainDir = Next;
}
@@ -301,19 +309,20 @@ void DarwinGCC::AddLinkSearchPathArgs(const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/" + ToolChainDir));
Tmp = getDriver().Dir + "/../lib/gcc/" + ToolChainDir;
- if (llvm::sys::Path(Tmp).exists())
+ bool Exists;
+ if (!llvm::sys::fs::exists(Tmp, Exists) && Exists)
CmdArgs.push_back(Args.MakeArgString("-L" + Tmp));
Tmp = getDriver().Dir + "/../lib/gcc";
- if (llvm::sys::Path(Tmp).exists())
+ if (!llvm::sys::fs::exists(Tmp, Exists) && Exists)
CmdArgs.push_back(Args.MakeArgString("-L" + Tmp));
CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir));
// Intentionally duplicated for (temporary) gcc bug compatibility.
CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir));
Tmp = getDriver().Dir + "/../lib/" + ToolChainDir;
- if (llvm::sys::Path(Tmp).exists())
+ if (!llvm::sys::fs::exists(Tmp, Exists) && Exists)
CmdArgs.push_back(Args.MakeArgString("-L" + Tmp));
Tmp = getDriver().Dir + "/../lib";
- if (llvm::sys::Path(Tmp).exists())
+ if (!llvm::sys::fs::exists(Tmp, Exists) && Exists)
CmdArgs.push_back(Args.MakeArgString("-L" + Tmp));
CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir +
"/../../../" + ToolChainDir));
@@ -369,10 +378,30 @@ void DarwinGCC::AddLinkRuntimeLibArgs(const ArgList &Args,
DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple)
: Darwin(Host, Triple)
{
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
+
// We expect 'as', 'ld', etc. to be adjacent to our install dir.
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
+
+ // For fallback, we need to know how to find the GCC cc1 executables, so we
+ // also add the GCC libexec paths. This is legiy code that can be removed once
+ // fallback is no longer useful.
+ std::string ToolChainDir = "i686-apple-darwin";
+ ToolChainDir += llvm::utostr(DarwinVersion[0]);
+ ToolChainDir += "/4.2.1";
+
+ std::string Path = getDriver().Dir;
+ Path += "/../libexec/gcc/";
+ Path += ToolChainDir;
+ getProgramPaths().push_back(Path);
+
+ Path = "/usr/libexec/gcc/";
+ Path += ToolChainDir;
+ getProgramPaths().push_back(Path);
}
void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args,
@@ -431,12 +460,14 @@ void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args,
if (ArchSpecificDir) {
P.appendComponent(ArchSpecificDir);
- if (P.exists())
+ bool Exists;
+ if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
CmdArgs.push_back(Args.MakeArgString("-L" + P.str()));
P.eraseComponent();
}
- if (P.exists())
+ bool Exists;
+ if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
CmdArgs.push_back(Args.MakeArgString("-L" + P.str()));
}
@@ -477,11 +508,20 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
else if (isMacosxVersionLT(10, 6))
CmdArgs.push_back("-lgcc_s.10.5");
- // For OS X, we only need a static runtime library when targetting 10.4, to
- // provide versions of the static functions which were omitted from
- // 10.4.dylib.
- if (isMacosxVersionLT(10, 5))
+ // For OS X, we thought we would only need a static runtime library when
+ // targetting 10.4, to provide versions of the static functions which were
+ // omitted from 10.4.dylib.
+ //
+ // Unfortunately, that turned out to not be true, because Darwin system
+ // headers can still use eprintf on i386, and it is not exported from
+ // libSystem. Therefore, we still must provide a runtime library just for
+ // the tiny tiny handful of projects that *might* use that symbol.
+ if (isMacosxVersionLT(10, 5)) {
DarwinStaticLib = "libclang_rt.10.4.a";
+ } else {
+ if (getTriple().getArch() == llvm::Triple::x86)
+ DarwinStaticLib = "libclang_rt.eprintf.a";
+ }
}
/// Add the target specific static library, if needed.
@@ -493,10 +533,8 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
// For now, allow missing resource libraries to support developers who may
// not have compiler-rt checked out or integrated into their build.
- if (!P.exists())
- getDriver().Diag(clang::diag::warn_drv_missing_resource_library)
- << P.str();
- else
+ bool Exists;
+ if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
CmdArgs.push_back(Args.MakeArgString(P.str()));
}
}
@@ -574,6 +612,72 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
setTarget(iPhoneVersion, Major, Minor, Micro);
}
+void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ CXXStdlibType Type = GetCXXStdlibType(Args);
+
+ switch (Type) {
+ case ToolChain::CST_Libcxx:
+ CmdArgs.push_back("-lc++");
+ break;
+
+ case ToolChain::CST_Libstdcxx: {
+ // Unfortunately, -lstdc++ doesn't always exist in the standard search path;
+ // it was previously found in the gcc lib dir. However, for all the Darwin
+ // platforms we care about it was -lstdc++.6, so we search for that
+ // explicitly if we can't see an obvious -lstdc++ candidate.
+
+ // Check in the sysroot first.
+ bool Exists;
+ if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
+ llvm::sys::Path P(A->getValue(Args));
+ P.appendComponent("usr");
+ P.appendComponent("lib");
+ P.appendComponent("libstdc++.dylib");
+
+ if (llvm::sys::fs::exists(P.str(), Exists) || !Exists) {
+ P.eraseComponent();
+ P.appendComponent("libstdc++.6.dylib");
+ if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) {
+ CmdArgs.push_back(Args.MakeArgString(P.str()));
+ return;
+ }
+ }
+ }
+
+ // Otherwise, look in the root.
+ if ((llvm::sys::fs::exists("/usr/lib/libstdc++.dylib", Exists) || !Exists)&&
+ (!llvm::sys::fs::exists("/usr/lib/libstdc++.6.dylib", Exists) && Exists)){
+ CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");
+ return;
+ }
+
+ // Otherwise, let the linker search.
+ CmdArgs.push_back("-lstdc++");
+ break;
+ }
+ }
+}
+
+void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+
+ // For Darwin platforms, use the compiler-rt-based support library
+ // instead of the gcc-provided one (which is also incidentally
+ // only present in the gcc lib dir, which makes it hard to find).
+
+ llvm::sys::Path P(getDriver().ResourceDir);
+ P.appendComponent("lib");
+ P.appendComponent("darwin");
+ P.appendComponent("libclang_rt.cc_kext.a");
+
+ // For now, allow missing resource libraries to support developers who may
+ // not have compiler-rt checked out or integrated into their build.
+ bool Exists;
+ if (!llvm::sys::fs::exists(P.str(), Exists) && Exists)
+ CmdArgs.push_back(Args.MakeArgString(P.str()));
+}
+
DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
const char *BoundArch) const {
DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
@@ -595,6 +699,7 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
if (getArchName() != A->getValue(Args, 0))
continue;
+ Arg *OriginalArg = A;
unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(Args, 1));
unsigned Prev = Index;
Arg *XarchArg = Opts.ParseOneArg(Args, Index);
@@ -618,6 +723,20 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
A = XarchArg;
DAL->AddSynthesizedArg(A);
+
+ // Linker input arguments require custom handling. The problem is that we
+ // have already constructed the phase actions, so we can not treat them as
+ // "input arguments".
+ if (A->getOption().isLinkerInput()) {
+ // Convert the argument into individual Zlinker_input_args.
+ for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
+ DAL->AddSeparateArg(OriginalArg,
+ Opts.getOption(options::OPT_Zlinker_input),
+ A->getValue(Args, i));
+
+ }
+ continue;
+ }
}
// Sob. These is strictly gcc compatible for the time being. Apple
@@ -937,7 +1056,7 @@ Tool &TCEToolChain::SelectTool(const Compilation &C,
/// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly.
OpenBSD::OpenBSD(const HostInfo &Host, const llvm::Triple& Triple)
- : Generic_GCC(Host, Triple) {
+ : Generic_ELF(Host, Triple) {
getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
}
@@ -949,11 +1068,20 @@ Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
else
Key = JA.getKind();
+ bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as,
+ options::OPT_no_integrated_as,
+ IsIntegratedAssemblerDefault());
+
Tool *&T = Tools[Key];
if (!T) {
switch (Key) {
- case Action::AssembleJobClass:
- T = new tools::openbsd::Assemble(*this); break;
+ case Action::AssembleJobClass: {
+ if (UseIntegratedAs)
+ T = new tools::ClangAs(*this);
+ else
+ T = new tools::openbsd::Assemble(*this);
+ break;
+ }
case Action::LinkJobClass:
T = new tools::openbsd::Link(*this); break;
default:
@@ -967,7 +1095,7 @@ Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
/// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.
FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple)
- : Generic_GCC(Host, Triple) {
+ : Generic_ELF(Host, Triple) {
// Determine if we are compiling 32-bit code on an x86_64 platform.
bool Lib32 = false;
@@ -994,11 +1122,19 @@ Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
else
Key = JA.getKind();
+ bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as,
+ options::OPT_no_integrated_as,
+ IsIntegratedAssemblerDefault());
+
Tool *&T = Tools[Key];
if (!T) {
switch (Key) {
case Action::AssembleJobClass:
- T = new tools::freebsd::Assemble(*this); break;
+ if (UseIntegratedAs)
+ T = new tools::ClangAs(*this);
+ else
+ T = new tools::freebsd::Assemble(*this);
+ break;
case Action::LinkJobClass:
T = new tools::freebsd::Link(*this); break;
default:
@@ -1009,6 +1145,57 @@ Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
return *T;
}
+/// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly.
+
+NetBSD::NetBSD(const HostInfo &Host, const llvm::Triple& Triple)
+ : Generic_ELF(Host, Triple) {
+
+ // Determine if we are compiling 32-bit code on an x86_64 platform.
+ bool Lib32 = false;
+ if (Triple.getArch() == llvm::Triple::x86 &&
+ llvm::Triple(getDriver().DefaultHostTriple).getArch() ==
+ llvm::Triple::x86_64)
+ Lib32 = true;
+
+ getProgramPaths().push_back(getDriver().Dir + "/../libexec");
+ getProgramPaths().push_back("/usr/libexec");
+ if (Lib32) {
+ getFilePaths().push_back("/usr/lib/i386");
+ } else {
+ getFilePaths().push_back("/usr/lib");
+ }
+}
+
+Tool &NetBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
+ Action::ActionClass Key;
+ if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+ Key = Action::AnalyzeJobClass;
+ else
+ Key = JA.getKind();
+
+ bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as,
+ options::OPT_no_integrated_as,
+ IsIntegratedAssemblerDefault());
+
+ Tool *&T = Tools[Key];
+ if (!T) {
+ switch (Key) {
+ case Action::AssembleJobClass:
+ if (UseIntegratedAs)
+ T = new tools::ClangAs(*this);
+ else
+ T = new tools::netbsd::Assemble(*this);
+ break;
+ case Action::LinkJobClass:
+ T = new tools::netbsd::Link(*this); break;
+ default:
+ T = &Generic_GCC::SelectTool(C, JA);
+ }
+ }
+
+ return *T;
+}
+
/// Minix - Minix tool chain which can call as(1) and ld(1) directly.
Minix::Minix(const HostInfo &Host, const llvm::Triple& Triple)
@@ -1083,28 +1270,253 @@ 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) {
- getFilePaths().push_back(getDriver().Dir +
- "/../lib/clang/" CLANG_VERSION_STRING "/");
- getFilePaths().push_back("/lib/");
- getFilePaths().push_back("/usr/lib/");
-
- // Depending on the Linux distribution, any combination of lib{,32,64} is
- // possible. E.g. Debian uses lib and lib32 for mixed i386/x86-64 systems,
- // openSUSE uses lib and lib64 for the same purpose.
- getFilePaths().push_back("/lib32/");
- getFilePaths().push_back("/usr/lib32/");
- 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.
+enum LinuxDistro {
+ DebianLenny,
+ DebianSqueeze,
+ Exherbo,
+ Fedora13,
+ Fedora14,
+ OpenSuse11_3,
+ UbuntuJaunty,
+ UbuntuKarmic,
+ UbuntuLucid,
+ UbuntuMaverick,
+ UnknownDistro
+};
+
+static bool IsFedora(enum LinuxDistro Distro) {
+ return Distro == Fedora13 || Distro == Fedora14;
+}
+
+static bool IsOpenSuse(enum LinuxDistro Distro) {
+ return Distro == OpenSuse11_3;
+}
+
+static bool IsDebian(enum LinuxDistro Distro) {
+ return Distro == DebianLenny || Distro == DebianSqueeze;
+}
+
+static bool IsUbuntu(enum LinuxDistro Distro) {
+ return Distro == UbuntuLucid || Distro == UbuntuMaverick ||
+ Distro == UbuntuJaunty || Distro == UbuntuKarmic;
+}
+
+static bool IsDebianBased(enum LinuxDistro Distro) {
+ return IsDebian(Distro) || IsUbuntu(Distro);
+}
+
+static bool HasMultilib(llvm::Triple::ArchType Arch, enum LinuxDistro Distro) {
+ if (Arch == llvm::Triple::x86_64) {
+ bool Exists;
+ if (Distro == Exherbo &&
+ (llvm::sys::fs::exists("/usr/lib32/libc.so", Exists) || !Exists))
+ return false;
+
+ return true;
+ }
+ if (Arch == llvm::Triple::x86 && IsDebianBased(Distro))
+ return true;
+ return false;
+}
+
+static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) {
+ llvm::OwningPtr<llvm::MemoryBuffer> File;
+ if (!llvm::MemoryBuffer::getFile("/etc/lsb-release", File)) {
+ llvm::StringRef Data = File.get()->getBuffer();
+ llvm::SmallVector<llvm::StringRef, 8> Lines;
+ Data.split(Lines, "\n");
+ for (unsigned int i = 0, s = Lines.size(); i < s; ++ i) {
+ if (Lines[i] == "DISTRIB_CODENAME=maverick")
+ return UbuntuMaverick;
+ else if (Lines[i] == "DISTRIB_CODENAME=lucid")
+ return UbuntuLucid;
+ else if (Lines[i] == "DISTRIB_CODENAME=jaunty")
+ return UbuntuJaunty;
+ else if (Lines[i] == "DISTRIB_CODENAME=karmic")
+ return UbuntuKarmic;
+ }
+ return UnknownDistro;
+ }
+
+ if (!llvm::MemoryBuffer::getFile("/etc/redhat-release", File)) {
+ llvm::StringRef Data = File.get()->getBuffer();
+ if (Data.startswith("Fedora release 14 (Laughlin)"))
+ return Fedora14;
+ else if (Data.startswith("Fedora release 13 (Goddard)"))
+ return Fedora13;
+ return UnknownDistro;
+ }
+
+ if (!llvm::MemoryBuffer::getFile("/etc/debian_version", File)) {
+ llvm::StringRef Data = File.get()->getBuffer();
+ if (Data[0] == '5')
+ return DebianLenny;
+ else if (Data.startswith("squeeze/sid"))
+ return DebianSqueeze;
+ return UnknownDistro;
+ }
+
+ if (!llvm::MemoryBuffer::getFile("/etc/SuSE-release", File)) {
+ llvm::StringRef Data = File.get()->getBuffer();
+ if (Data.startswith("openSUSE 11.3"))
+ return OpenSuse11_3;
+ return UnknownDistro;
+ }
+
+ bool Exists;
+ if (!llvm::sys::fs::exists("/etc/exherbo-release", Exists) && Exists)
+ return Exherbo;
+
+ return UnknownDistro;
+}
+
+Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple)
+ : Generic_ELF(Host, Triple) {
+ llvm::Triple::ArchType Arch =
+ llvm::Triple(getDriver().DefaultHostTriple).getArch();
+
+ std::string Suffix32 = "";
+ if (Arch == llvm::Triple::x86_64)
+ Suffix32 = "/32";
+
+ std::string Suffix64 = "";
+ if (Arch == llvm::Triple::x86)
+ Suffix64 = "/64";
+
+ std::string Lib32 = "lib";
+
+ bool Exists;
+ if (!llvm::sys::fs::exists("/lib32", Exists) && Exists)
+ Lib32 = "lib32";
+
+ std::string Lib64 = "lib";
+ bool Symlink;
+ if (!llvm::sys::fs::exists("/lib64", Exists) && Exists &&
+ (llvm::sys::fs::is_symlink("/lib64", Symlink) || !Symlink))
+ Lib64 = "lib64";
+
+ std::string GccTriple = "";
+ if (Arch == llvm::Triple::arm) {
+ if (!llvm::sys::fs::exists("/usr/lib/gcc/arm-linux-gnueabi", Exists) &&
+ Exists)
+ GccTriple = "arm-linux-gnueabi";
+ } else if (Arch == llvm::Triple::x86_64) {
+ if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-linux-gnu", Exists) &&
+ Exists)
+ GccTriple = "x86_64-linux-gnu";
+ else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-unknown-linux-gnu",
+ Exists) && Exists)
+ GccTriple = "x86_64-unknown-linux-gnu";
+ else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-pc-linux-gnu",
+ Exists) && Exists)
+ GccTriple = "x86_64-pc-linux-gnu";
+ else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-redhat-linux",
+ Exists) && Exists)
+ GccTriple = "x86_64-redhat-linux";
+ else if (!llvm::sys::fs::exists("/usr/lib64/gcc/x86_64-suse-linux",
+ Exists) && Exists)
+ GccTriple = "x86_64-suse-linux";
+ else if (!llvm::sys::fs::exists("/usr/lib/gcc/x86_64-manbo-linux-gnu",
+ Exists) && Exists)
+ GccTriple = "x86_64-manbo-linux-gnu";
+ } else if (Arch == llvm::Triple::x86) {
+ if (!llvm::sys::fs::exists("/usr/lib/gcc/i686-linux-gnu", Exists) && Exists)
+ GccTriple = "i686-linux-gnu";
+ else if (!llvm::sys::fs::exists("/usr/lib/gcc/i686-pc-linux-gnu", Exists) &&
+ Exists)
+ GccTriple = "i686-pc-linux-gnu";
+ else if (!llvm::sys::fs::exists("/usr/lib/gcc/i486-linux-gnu", Exists) &&
+ Exists)
+ GccTriple = "i486-linux-gnu";
+ else if (!llvm::sys::fs::exists("/usr/lib/gcc/i686-redhat-linux", Exists) &&
+ Exists)
+ GccTriple = "i686-redhat-linux";
+ else if (!llvm::sys::fs::exists("/usr/lib/gcc/i586-suse-linux", Exists) &&
+ Exists)
+ GccTriple = "i586-suse-linux";
+ }
+
+ const char* GccVersions[] = {"4.5.1", "4.5", "4.4.5", "4.4.4", "4.4.3", "4.4",
+ "4.3.4", "4.3.3", "4.3.2"};
+ std::string Base = "";
+ for (unsigned i = 0; i < sizeof(GccVersions)/sizeof(char*); ++i) {
+ std::string Suffix = GccTriple + "/" + GccVersions[i];
+ std::string t1 = "/usr/lib/gcc/" + Suffix;
+ if (!llvm::sys::fs::exists(t1 + "/crtbegin.o", Exists) && Exists) {
+ Base = t1;
+ break;
+ }
+ std::string t2 = "/usr/lib64/gcc/" + Suffix;
+ if (!llvm::sys::fs::exists(t2 + "/crtbegin.o", Exists) && Exists) {
+ Base = t2;
+ break;
+ }
+ }
+
+ path_list &Paths = getFilePaths();
+ bool Is32Bits = getArch() == llvm::Triple::x86;
+
+ std::string Suffix;
+ std::string Lib;
+
+ if (Is32Bits) {
+ Suffix = Suffix32;
+ Lib = Lib32;
+ } else {
+ Suffix = Suffix64;
+ Lib = Lib64;
+ }
+
+ llvm::sys::Path LinkerPath(Base + "/../../../../" + GccTriple + "/bin/ld");
+ if (!llvm::sys::fs::exists(LinkerPath.str(), Exists) && Exists)
+ Linker = LinkerPath.str();
+ else
+ Linker = GetProgramPath("ld");
+
+ LinuxDistro Distro = DetectLinuxDistro(Arch);
+
+ if (IsUbuntu(Distro)) {
+ ExtraOpts.push_back("-z");
+ ExtraOpts.push_back("relro");
+ }
+
+ if (Arch == llvm::Triple::arm)
+ ExtraOpts.push_back("-X");
+
+ if (IsFedora(Distro) || Distro == UbuntuMaverick)
+ ExtraOpts.push_back("--hash-style=gnu");
+
+ if (IsDebian(Distro) || Distro == UbuntuLucid || Distro == UbuntuJaunty ||
+ Distro == UbuntuKarmic)
+ ExtraOpts.push_back("--hash-style=both");
+
+ if (IsFedora(Distro))
+ ExtraOpts.push_back("--no-add-needed");
+
+ if (Distro == DebianSqueeze || IsOpenSuse(Distro) ||
+ IsFedora(Distro) || Distro == UbuntuLucid || Distro == UbuntuMaverick ||
+ Distro == UbuntuKarmic)
+ ExtraOpts.push_back("--build-id");
+
+ Paths.push_back(Base + Suffix);
+ if (HasMultilib(Arch, Distro)) {
+ if (IsOpenSuse(Distro) && Is32Bits)
+ Paths.push_back(Base + "/../../../../" + GccTriple + "/lib/../lib");
+ Paths.push_back(Base + "/../../../../" + Lib);
+ Paths.push_back("/lib/../" + Lib);
+ Paths.push_back("/usr/lib/../" + Lib);
+ }
+ if (!Suffix.empty())
+ Paths.push_back(Base);
+ if (IsOpenSuse(Distro))
+ Paths.push_back(Base + "/../../../../" + GccTriple + "/lib");
+ Paths.push_back(Base + "/../../..");
+ if (Arch == getArch() && IsUbuntu(Distro))
+ Paths.push_back("/usr/lib/" + GccTriple);
+}
+
+bool Linux::HasNativeLLVMSupport() const {
+ return true;
}
Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA) const {
@@ -1114,11 +1526,21 @@ Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA) const {
else
Key = JA.getKind();
+ bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as,
+ options::OPT_no_integrated_as,
+ IsIntegratedAssemblerDefault());
+
Tool *&T = Tools[Key];
if (!T) {
switch (Key) {
case Action::AssembleJobClass:
- T = new tools::linuxtools::Assemble(*this); break;
+ if (UseIntegratedAs)
+ T = new tools::ClangAs(*this);
+ else
+ T = new tools::linuxtools::Assemble(*this);
+ break;
+ case Action::LinkJobClass:
+ T = new tools::linuxtools::Link(*this); break;
default:
T = &Generic_GCC::SelectTool(C, JA);
}
@@ -1130,7 +1552,7 @@ Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA) const {
/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
DragonFly::DragonFly(const HostInfo &Host, const llvm::Triple& Triple)
- : Generic_GCC(Host, Triple) {
+ : Generic_ELF(Host, Triple) {
// Path mangling to find libexec
getProgramPaths().push_back(getDriver().getInstalledDir());
OpenPOWER on IntegriCloud