diff options
Diffstat (limited to 'lib/Driver/ToolChains/Linux.cpp')
-rw-r--r-- | lib/Driver/ToolChains/Linux.cpp | 147 |
1 files changed, 110 insertions, 37 deletions
diff --git a/lib/Driver/ToolChains/Linux.cpp b/lib/Driver/ToolChains/Linux.cpp index f8f36239180c..65ab9b2daf54 100644 --- a/lib/Driver/ToolChains/Linux.cpp +++ b/lib/Driver/ToolChains/Linux.cpp @@ -13,7 +13,6 @@ #include "Arch/PPC.h" #include "Arch/RISCV.h" #include "CommonArgs.h" -#include "clang/Basic/VirtualFileSystem.h" #include "clang/Config/config.h" #include "clang/Driver/Distro.h" #include "clang/Driver/Driver.h" @@ -23,6 +22,7 @@ #include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/Path.h" #include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/VirtualFileSystem.h" #include <system_error> using namespace clang::driver; @@ -44,6 +44,7 @@ static std::string getMultiarchTriple(const Driver &D, llvm::Triple::EnvironmentType TargetEnvironment = TargetTriple.getEnvironment(); bool IsAndroid = TargetTriple.isAndroid(); + bool IsMipsR6 = TargetTriple.getSubArch() == llvm::Triple::MipsSubArch_r6; // For most architectures, just use whatever we have rather than trying to be // clever. @@ -101,30 +102,36 @@ static std::string getMultiarchTriple(const Driver &D, if (D.getVFS().exists(SysRoot + "/lib/aarch64_be-linux-gnu")) return "aarch64_be-linux-gnu"; break; - case llvm::Triple::mips: - if (D.getVFS().exists(SysRoot + "/lib/mips-linux-gnu")) - return "mips-linux-gnu"; + case llvm::Triple::mips: { + std::string Arch = IsMipsR6 ? "mipsisa32r6" : "mips"; + if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-gnu")) + return Arch + "-linux-gnu"; break; - case llvm::Triple::mipsel: + } + case llvm::Triple::mipsel: { if (IsAndroid) return "mipsel-linux-android"; - if (D.getVFS().exists(SysRoot + "/lib/mipsel-linux-gnu")) - return "mipsel-linux-gnu"; + std::string Arch = IsMipsR6 ? "mipsisa32r6el" : "mipsel"; + if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-gnu")) + return Arch + "-linux-gnu"; break; - case llvm::Triple::mips64: - if (D.getVFS().exists(SysRoot + "/lib/mips64-linux-gnu")) - return "mips64-linux-gnu"; - if (D.getVFS().exists(SysRoot + "/lib/mips64-linux-gnuabi64")) - return "mips64-linux-gnuabi64"; + } + case llvm::Triple::mips64: { + std::string Arch = IsMipsR6 ? "mipsisa64r6" : "mips64"; + std::string ABI = llvm::Triple::getEnvironmentTypeName(TargetEnvironment); + if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-" + ABI)) + return Arch + "-linux-" + ABI; break; - case llvm::Triple::mips64el: + } + case llvm::Triple::mips64el: { if (IsAndroid) return "mips64el-linux-android"; - if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnu")) - return "mips64el-linux-gnu"; - if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnuabi64")) - return "mips64el-linux-gnuabi64"; + std::string Arch = IsMipsR6 ? "mipsisa64r6el" : "mips64el"; + std::string ABI = llvm::Triple::getEnvironmentTypeName(TargetEnvironment); + if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-" + ABI)) + return Arch + "-linux-" + ABI; break; + } case llvm::Triple::ppc: if (D.getVFS().exists(SysRoot + "/lib/powerpc-linux-gnuspe")) return "powerpc-linux-gnuspe"; @@ -210,6 +217,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : Generic_ELF(D, Triple, Args) { GCCInstallation.init(Triple, Args); Multilibs = GCCInstallation.getMultilibs(); + SelectedMultilib = GCCInstallation.getMultilib(); llvm::Triple::ArchType Arch = Triple.getArch(); std::string SysRoot = computeSysRoot(); @@ -228,16 +236,25 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) Distro Distro(D.getVFS()); - if (Distro.IsAlpineLinux()) { + if (Distro.IsAlpineLinux() || Triple.isAndroid()) { ExtraOpts.push_back("-z"); ExtraOpts.push_back("now"); } - if (Distro.IsOpenSUSE() || Distro.IsUbuntu() || Distro.IsAlpineLinux()) { + if (Distro.IsOpenSUSE() || Distro.IsUbuntu() || Distro.IsAlpineLinux() || + Triple.isAndroid()) { ExtraOpts.push_back("-z"); ExtraOpts.push_back("relro"); } + // The lld default page size is too large for Aarch64, which produces much + // larger .so files and images for arm64 device targets. Use 4KB page size + // for Android arm64 targets instead. + if (Triple.isAArch64() && Triple.isAndroid()) { + ExtraOpts.push_back("-z"); + ExtraOpts.push_back("max-page-size=4096"); + } + if (GCCInstallation.getParentLibPath().find("opt/rh/devtoolset") != StringRef::npos) // With devtoolset on RHEL, we want to add a bin directory that is relative @@ -263,15 +280,18 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // and the MIPS ABI require .dynsym to be sorted in different ways. // .gnu.hash needs symbols to be grouped by hash code whereas the MIPS // ABI requires a mapping between the GOT and the symbol table. - // Android loader does not support .gnu.hash. + // Android loader does not support .gnu.hash until API 23. // Hexagon linker/loader does not support .gnu.hash - if (!IsMips && !IsAndroid && !IsHexagon) { + if (!IsMips && !IsHexagon) { if (Distro.IsRedhat() || Distro.IsOpenSUSE() || Distro.IsAlpineLinux() || - (Distro.IsUbuntu() && Distro >= Distro::UbuntuMaverick)) + (Distro.IsUbuntu() && Distro >= Distro::UbuntuMaverick) || + (IsAndroid && !Triple.isAndroidVersionLT(23))) ExtraOpts.push_back("--hash-style=gnu"); - if (Distro.IsDebian() || Distro.IsOpenSUSE() || Distro == Distro::UbuntuLucid || - Distro == Distro::UbuntuJaunty || Distro == Distro::UbuntuKarmic) + if (Distro.IsDebian() || Distro.IsOpenSUSE() || + Distro == Distro::UbuntuLucid || Distro == Distro::UbuntuJaunty || + Distro == Distro::UbuntuKarmic || + (IsAndroid && Triple.isAndroidVersionLT(23))) ExtraOpts.push_back("--hash-style=both"); } @@ -299,16 +319,14 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) if (GCCInstallation.isValid()) { const llvm::Triple &GCCTriple = GCCInstallation.getTriple(); const std::string &LibPath = GCCInstallation.getParentLibPath(); - const Multilib &Multilib = GCCInstallation.getMultilib(); - const MultilibSet &Multilibs = GCCInstallation.getMultilibs(); // Add toolchain / multilib specific file paths. - addMultilibsFilePaths(D, Multilibs, Multilib, + addMultilibsFilePaths(D, Multilibs, SelectedMultilib, GCCInstallation.getInstallPath(), Paths); // Sourcery CodeBench MIPS toolchain holds some libraries under // a biarch-like suffix of the GCC installation. - addPathIfExists(D, GCCInstallation.getInstallPath() + Multilib.gccSuffix(), + addPathIfExists(D, GCCInstallation.getInstallPath() + SelectedMultilib.gccSuffix(), Paths); // GCC cross compiling toolchains will install target libraries which ship @@ -330,7 +348,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // Note that this matches the GCC behavior. See the below comment for where // Clang diverges from GCC's behavior. addPathIfExists(D, LibPath + "/../" + GCCTriple.str() + "/lib/../" + - OSLibDir + Multilib.osSuffix(), + OSLibDir + SelectedMultilib.osSuffix(), Paths); // If the GCC installation we found is inside of the sysroot, we want to @@ -433,6 +451,12 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) addPathIfExists(D, SysRoot + "/usr/lib", Paths); } +ToolChain::CXXStdlibType Linux::GetDefaultCXXStdlibType() const { + if (getTriple().isAndroid()) + return ToolChain::CST_Libcxx; + return ToolChain::CST_Libstdcxx; +} + bool Linux::HasNativeLLVMSupport() const { return true; } Tool *Linux::buildLinker() const { return new tools::gnutools::Linker(*this); } @@ -695,12 +719,28 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, const StringRef MIPSELMultiarchIncludeDirs[] = { "/usr/include/mipsel-linux-gnu"}; const StringRef MIPS64MultiarchIncludeDirs[] = { - "/usr/include/mips64-linux-gnu", "/usr/include/mips64-linux-gnuabi64"}; + "/usr/include/mips64-linux-gnuabi64"}; const StringRef MIPS64ELMultiarchIncludeDirs[] = { - "/usr/include/mips64el-linux-gnu", "/usr/include/mips64el-linux-gnuabi64"}; + const StringRef MIPSN32MultiarchIncludeDirs[] = { + "/usr/include/mips64-linux-gnuabin32"}; + const StringRef MIPSN32ELMultiarchIncludeDirs[] = { + "/usr/include/mips64el-linux-gnuabin32"}; + const StringRef MIPSR6MultiarchIncludeDirs[] = { + "/usr/include/mipsisa32-linux-gnu"}; + const StringRef MIPSR6ELMultiarchIncludeDirs[] = { + "/usr/include/mipsisa32r6el-linux-gnu"}; + const StringRef MIPS64R6MultiarchIncludeDirs[] = { + "/usr/include/mipsisa64r6-linux-gnuabi64"}; + const StringRef MIPS64R6ELMultiarchIncludeDirs[] = { + "/usr/include/mipsisa64r6el-linux-gnuabi64"}; + const StringRef MIPSN32R6MultiarchIncludeDirs[] = { + "/usr/include/mipsisa64r6-linux-gnuabin32"}; + const StringRef MIPSN32R6ELMultiarchIncludeDirs[] = { + "/usr/include/mipsisa64r6el-linux-gnuabin32"}; const StringRef PPCMultiarchIncludeDirs[] = { - "/usr/include/powerpc-linux-gnu"}; + "/usr/include/powerpc-linux-gnu", + "/usr/include/powerpc-linux-gnuspe"}; const StringRef PPC64MultiarchIncludeDirs[] = { "/usr/include/powerpc64-linux-gnu"}; const StringRef PPC64LEMultiarchIncludeDirs[] = { @@ -738,16 +778,38 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, MultiarchIncludeDirs = ARMEBMultiarchIncludeDirs; break; case llvm::Triple::mips: - MultiarchIncludeDirs = MIPSMultiarchIncludeDirs; + if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6) + MultiarchIncludeDirs = MIPSR6MultiarchIncludeDirs; + else + MultiarchIncludeDirs = MIPSMultiarchIncludeDirs; break; case llvm::Triple::mipsel: - MultiarchIncludeDirs = MIPSELMultiarchIncludeDirs; + if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6) + MultiarchIncludeDirs = MIPSR6ELMultiarchIncludeDirs; + else + MultiarchIncludeDirs = MIPSELMultiarchIncludeDirs; break; case llvm::Triple::mips64: - MultiarchIncludeDirs = MIPS64MultiarchIncludeDirs; + if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6) + if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32) + MultiarchIncludeDirs = MIPSN32R6MultiarchIncludeDirs; + else + MultiarchIncludeDirs = MIPS64R6MultiarchIncludeDirs; + else if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32) + MultiarchIncludeDirs = MIPSN32MultiarchIncludeDirs; + else + MultiarchIncludeDirs = MIPS64MultiarchIncludeDirs; break; case llvm::Triple::mips64el: - MultiarchIncludeDirs = MIPS64ELMultiarchIncludeDirs; + if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6) + if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32) + MultiarchIncludeDirs = MIPSN32R6ELMultiarchIncludeDirs; + else + MultiarchIncludeDirs = MIPS64R6ELMultiarchIncludeDirs; + else if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32) + MultiarchIncludeDirs = MIPSN32ELMultiarchIncludeDirs; + else + MultiarchIncludeDirs = MIPS64ELMultiarchIncludeDirs; break; case llvm::Triple::ppc: MultiarchIncludeDirs = PPCMultiarchIncludeDirs; @@ -876,6 +938,9 @@ void Linux::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, // Freescale SDK C++ headers are directly in <sysroot>/usr/include/c++, // without a subdirectory corresponding to the gcc version. LibDir.str() + "/../include/c++", + // Cray's gcc installation puts headers under "g++" without a + // version suffix. + LibDir.str() + "/../include/g++", }; for (const auto &IncludePath : LibStdCXXIncludePathCandidates) { @@ -907,6 +972,12 @@ bool Linux::isPIEDefault() const { getTriple().isMusl() || getSanitizerArgs().requiresPIE(); } +bool Linux::IsMathErrnoDefault() const { + if (getTriple().isAndroid()) + return false; + return Generic_ELF::IsMathErrnoDefault(); +} + SanitizerMask Linux::getSupportedSanitizers() const { const bool IsX86 = getTriple().getArch() == llvm::Triple::x86; const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; @@ -934,6 +1005,8 @@ SanitizerMask Linux::getSupportedSanitizers() const { Res |= SanitizerKind::Leak; if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64) Res |= SanitizerKind::Thread; + if (IsX86_64) + Res |= SanitizerKind::KernelMemory; if (IsX86_64 || IsMIPS64) Res |= SanitizerKind::Efficiency; if (IsX86 || IsX86_64) @@ -954,7 +1027,7 @@ void Linux::addProfileRTLibs(const llvm::opt::ArgList &Args, // Add linker option -u__llvm_runtime_variable to cause runtime // initialization module to be linked in. - if (!Args.hasArg(options::OPT_coverage)) + if ((!Args.hasArg(options::OPT_coverage)) && (!Args.hasArg(options::OPT_ftest_coverage))) CmdArgs.push_back(Args.MakeArgString( Twine("-u", llvm::getInstrProfRuntimeHookVarName()))); ToolChain::addProfileRTLibs(Args, CmdArgs); |