diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp | 516 |
1 files changed, 469 insertions, 47 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp index 596173d..8028fe0 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp +++ b/contrib/llvm/tools/clang/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 @@ -63,6 +66,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") @@ -146,7 +153,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 += "/"; @@ -160,7 +168,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; } @@ -305,19 +313,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)); @@ -373,10 +382,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, @@ -435,12 +464,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())); } @@ -481,11 +512,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. @@ -497,10 +537,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())); } } @@ -578,6 +616,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()); @@ -599,6 +703,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); @@ -622,6 +727,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 @@ -941,7 +1060,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"); } @@ -953,11 +1072,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: @@ -971,7 +1099,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; @@ -996,11 +1124,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: @@ -1011,6 +1147,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) @@ -1085,28 +1272,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 { @@ -1116,11 +1528,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); } @@ -1132,7 +1554,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()); |