diff options
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Driver/ToolChains.cpp')
| -rw-r--r-- | gnu/llvm/tools/clang/lib/Driver/ToolChains.cpp | 1305 |
1 files changed, 926 insertions, 379 deletions
diff --git a/gnu/llvm/tools/clang/lib/Driver/ToolChains.cpp b/gnu/llvm/tools/clang/lib/Driver/ToolChains.cpp index 7ba8f25efdd..cebf3363a92 100644 --- a/gnu/llvm/tools/clang/lib/Driver/ToolChains.cpp +++ b/gnu/llvm/tools/clang/lib/Driver/ToolChains.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "ToolChains.h" +#include "clang/Basic/Cuda.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Version.h" #include "clang/Basic/VirtualFileSystem.h" @@ -65,6 +66,16 @@ types::ID MachO::LookupTypeForExtension(const char *Ext) const { bool MachO::HasNativeLLVMSupport() const { return true; } +ToolChain::CXXStdlibType Darwin::GetDefaultCXXStdlibType() const { + // Default to use libc++ on OS X 10.9+ and iOS 7+. + if ((isTargetMacOS() && !isMacosxVersionLT(10, 9)) || + (isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0)) || + isTargetWatchOSBased()) + return ToolChain::CST_Libcxx; + + return ToolChain::CST_Libstdcxx; +} + /// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0. ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const { if (isTargetWatchOSBased()) @@ -319,64 +330,74 @@ void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs, } } +StringRef Darwin::getPlatformFamily() const { + switch (TargetPlatform) { + case DarwinPlatformKind::MacOS: + return "MacOSX"; + case DarwinPlatformKind::IPhoneOS: + case DarwinPlatformKind::IPhoneOSSimulator: + return "iPhone"; + case DarwinPlatformKind::TvOS: + case DarwinPlatformKind::TvOSSimulator: + return "AppleTV"; + case DarwinPlatformKind::WatchOS: + case DarwinPlatformKind::WatchOSSimulator: + return "Watch"; + } + llvm_unreachable("Unsupported platform"); +} + +StringRef Darwin::getSDKName(StringRef isysroot) { + // Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk + llvm::sys::path::const_iterator SDKDir; + auto BeginSDK = llvm::sys::path::begin(isysroot); + auto EndSDK = llvm::sys::path::end(isysroot); + for (auto IT = BeginSDK; IT != EndSDK; ++IT) { + StringRef SDK = *IT; + if (SDK.endswith(".sdk")) + return SDK.slice(0, SDK.size() - 4); + } + return ""; +} + +StringRef Darwin::getOSLibraryNameSuffix() const { + switch(TargetPlatform) { + case DarwinPlatformKind::MacOS: + return "osx"; + case DarwinPlatformKind::IPhoneOS: + return "ios"; + case DarwinPlatformKind::IPhoneOSSimulator: + return "iossim"; + case DarwinPlatformKind::TvOS: + return "tvos"; + case DarwinPlatformKind::TvOSSimulator: + return "tvossim"; + case DarwinPlatformKind::WatchOS: + return "watchos"; + case DarwinPlatformKind::WatchOSSimulator: + return "watchossim"; + } + llvm_unreachable("Unsupported platform"); +} + void Darwin::addProfileRTLibs(const ArgList &Args, ArgStringList &CmdArgs) const { if (!needsProfileRT(Args)) return; - // TODO: Clean this up once autoconf is gone - SmallString<128> P(getDriver().ResourceDir); - llvm::sys::path::append(P, "lib", "darwin"); - const char *Library = "libclang_rt.profile_osx.a"; - - // Select the appropriate runtime library for the target. - if (isTargetWatchOS()) { - Library = "libclang_rt.profile_watchos.a"; - } else if (isTargetWatchOSSimulator()) { - llvm::sys::path::append(P, "libclang_rt.profile_watchossim.a"); - Library = getVFS().exists(P) ? "libclang_rt.profile_watchossim.a" - : "libclang_rt.profile_watchos.a"; - } else if (isTargetTvOS()) { - Library = "libclang_rt.profile_tvos.a"; - } else if (isTargetTvOSSimulator()) { - llvm::sys::path::append(P, "libclang_rt.profile_tvossim.a"); - Library = getVFS().exists(P) ? "libclang_rt.profile_tvossim.a" - : "libclang_rt.profile_tvos.a"; - } else if (isTargetIPhoneOS()) { - Library = "libclang_rt.profile_ios.a"; - } else if (isTargetIOSSimulator()) { - llvm::sys::path::append(P, "libclang_rt.profile_iossim.a"); - Library = getVFS().exists(P) ? "libclang_rt.profile_iossim.a" - : "libclang_rt.profile_ios.a"; - } else { - assert(isTargetMacOS() && "unexpected non MacOS platform"); - } - AddLinkRuntimeLib(Args, CmdArgs, Library, + AddLinkRuntimeLib(Args, CmdArgs, (Twine("libclang_rt.profile_") + + getOSLibraryNameSuffix() + ".a").str(), /*AlwaysLink*/ true); - return; } void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args, ArgStringList &CmdArgs, StringRef Sanitizer) const { - if (!Args.hasArg(options::OPT_dynamiclib) && - !Args.hasArg(options::OPT_bundle)) { - // Sanitizer runtime libraries requires C++. - AddCXXStdlibLibArgs(Args, CmdArgs); - } - // ASan is not supported on watchOS. - assert(isTargetMacOS() || isTargetIOSSimulator()); - StringRef OS = isTargetMacOS() ? "osx" : "iossim"; AddLinkRuntimeLib( Args, CmdArgs, - (Twine("libclang_rt.") + Sanitizer + "_" + OS + "_dynamic.dylib").str(), + (Twine("libclang_rt.") + Sanitizer + "_" + + getOSLibraryNameSuffix() + "_dynamic.dylib").str(), /*AlwaysLink*/ true, /*IsEmbedded*/ false, /*AddRPath*/ true); - - if (GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) { - // Add explicit dependcy on -lc++abi, as -lc++ doesn't re-export - // all RTTI-related symbols that UBSan uses. - CmdArgs.push_back("-lc++abi"); - } } void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, @@ -413,6 +434,15 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan"); if (Sanitize.needsTsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan"); + if (Sanitize.needsStatsRt()) { + StringRef OS = isTargetMacOS() ? "osx" : "iossim"; + AddLinkRuntimeLib(Args, CmdArgs, + (Twine("libclang_rt.stats_client_") + OS + ".a").str(), + /*AlwaysLink=*/true); + AddLinkSanitizerLibArgs(Args, CmdArgs, "stats"); + } + if (Sanitize.needsEsanRt()) + AddLinkSanitizerLibArgs(Args, CmdArgs, "esan"); // Otherwise link libSystem, then the dynamic runtime library, and finally any // target specific static runtime library. @@ -444,21 +474,26 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, else if (isMacosxVersionLT(10, 6)) CmdArgs.push_back("-lgcc_s.10.5"); - // For OS X, we thought we would only need a static runtime library when - // targeting 10.4, to provide versions of the static functions which were - // omitted from 10.4.dylib. + // Originally for OS X, we thought we would only need a static runtime + // library when targeting 10.4, to provide versions of the static functions + // which were omitted from 10.4.dylib. This led to the creation of the 10.4 + // builtins library. // // 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)) { + // + // Then over time, we figured out it was useful to add more things to the + // runtime so we created libclang_rt.osx.a to provide new functions when + // deploying to old OS builds, and for a long time we had both eprintf and + // osx builtin libraries. Which just seems excessive. So with PR 28855, we + // are removing the eprintf library and expecting eprintf to be provided by + // the OS X builtins library. + if (isMacosxVersionLT(10, 5)) AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.10.4.a"); - } else { - if (getTriple().getArch() == llvm::Triple::x86) - AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.eprintf.a"); + else AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.osx.a"); - } } } @@ -529,11 +564,8 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { TvOSTarget.empty() && Args.hasArg(options::OPT_isysroot)) { if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { StringRef isysroot = A->getValue(); - // Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk - size_t BeginSDK = isysroot.rfind("SDKs/"); - size_t EndSDK = isysroot.rfind(".sdk"); - if (BeginSDK != StringRef::npos && EndSDK != StringRef::npos) { - StringRef SDK = isysroot.slice(BeginSDK + 5, EndSDK); + StringRef SDK = getSDKName(isysroot); + if (SDK.size() > 0) { // Slice the version number out. // Version number is between the first and the last number. size_t StartVer = SDK.find_first_of("0123456789"); @@ -656,13 +688,13 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { assert(iOSVersion && "Unknown target platform!"); if (!Driver::GetReleaseVersion(iOSVersion->getValue(), Major, Minor, Micro, HadExtra) || - HadExtra || Major >= 10 || Minor >= 100 || Micro >= 100) + HadExtra || Major >= 100 || Minor >= 100 || Micro >= 100) getDriver().Diag(diag::err_drv_invalid_version_number) << iOSVersion->getAsString(Args); } else if (Platform == TvOS) { if (!Driver::GetReleaseVersion(TvOSVersion->getValue(), Major, Minor, Micro, HadExtra) || HadExtra || - Major >= 10 || Minor >= 100 || Micro >= 100) + Major >= 100 || Minor >= 100 || Micro >= 100) getDriver().Diag(diag::err_drv_invalid_version_number) << TvOSVersion->getAsString(Args); } else if (Platform == WatchOS) { @@ -686,6 +718,17 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { Platform = WatchOSSimulator; setTarget(Platform, Major, Minor, Micro); + + if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { + StringRef SDK = getSDKName(A->getValue()); + if (SDK.size() > 0) { + size_t StartVer = SDK.find_first_of("0123456789"); + StringRef SDKName = SDK.slice(0, StartVer); + if (!SDKName.startswith(getPlatformFamily())) + getDriver().Diag(diag::warn_incompatible_sysroot) + << SDKName << getPlatformFamily(); + } + } } void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args, @@ -735,7 +778,6 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args, 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). @@ -1025,11 +1067,8 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, } } - // Default to use libc++ on OS X 10.9+ and iOS 7+. - if (((isTargetMacOS() && !isMacosxVersionLT(10, 9)) || - (isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0)) || - isTargetWatchOSBased()) && - !Args.getLastArg(options::OPT_stdlib_EQ)) + if (!Args.getLastArg(options::OPT_stdlib_EQ) && + GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_stdlib_EQ), "libc++"); @@ -1068,7 +1107,15 @@ bool Darwin::UseSjLjExceptions(const ArgList &Args) const { return false; // Only watchOS uses the new DWARF/Compact unwinding method. - return !isTargetWatchOS(); + llvm::Triple Triple(ComputeLLVMTriple(Args)); + return !Triple.isWatchABI(); +} + +bool Darwin::SupportsEmbeddedBitcode() const { + assert(TargetInitialized && "Target not initialized!"); + if (isTargetIPhoneOS() && isIPhoneOSVersionLT(6, 0)) + return false; + return true; } bool MachO::isPICDefault() const { return true; } @@ -1212,14 +1259,18 @@ void Darwin::CheckObjCARC() const { } SanitizerMask Darwin::getSupportedSanitizers() const { + const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; SanitizerMask Res = ToolChain::getSupportedSanitizers(); - if (isTargetMacOS() || isTargetIOSSimulator()) - Res |= SanitizerKind::Address; + Res |= SanitizerKind::Address; if (isTargetMacOS()) { if (!isMacosxVersionLT(10, 9)) Res |= SanitizerKind::Vptr; Res |= SanitizerKind::SafeStack; - Res |= SanitizerKind::Thread; + if (IsX86_64) + Res |= SanitizerKind::Thread; + } else if (isTargetIOSSimulator() || isTargetTvOSSimulator()) { + if (IsX86_64) + Res |= SanitizerKind::Thread; } return Res; } @@ -1241,6 +1292,8 @@ Generic_GCC::GCCVersion Linux::GCCVersion::Parse(StringRef VersionText) { if (First.first.getAsInteger(10, GoodVersion.Major) || GoodVersion.Major < 0) return BadVersion; GoodVersion.MajorStr = First.first.str(); + if (First.second.empty()) + return GoodVersion; if (Second.first.getAsInteger(10, GoodVersion.Minor) || GoodVersion.Minor < 0) return BadVersion; GoodVersion.MinorStr = Second.first.str(); @@ -1248,6 +1301,7 @@ Generic_GCC::GCCVersion Linux::GCCVersion::Parse(StringRef VersionText) { // First look for a number prefix and parse that if present. Otherwise just // stash the entire patch string in the suffix, and leave the number // unspecified. This covers versions strings such as: + // 5 (handled above) // 4.4 // 4.4.0 // 4.4.x @@ -1353,9 +1407,17 @@ void Generic_GCC::GCCInstallationDetector::init( // Then look for gcc installed alongside clang. Prefixes.push_back(D.InstalledDir + "/.."); - // And finally in /usr. - if (D.SysRoot.empty()) + // Then look for distribution supplied gcc installations. + if (D.SysRoot.empty()) { + // Look for RHEL devtoolsets. + Prefixes.push_back("/opt/rh/devtoolset-4/root/usr"); + Prefixes.push_back("/opt/rh/devtoolset-3/root/usr"); + Prefixes.push_back("/opt/rh/devtoolset-2/root/usr"); + Prefixes.push_back("/opt/rh/devtoolset-1.1/root/usr"); + Prefixes.push_back("/opt/rh/devtoolset-1.0/root/usr"); + // And finally in /usr. Prefixes.push_back("/usr"); + } } // Loop over the various components which exist and select the best GCC @@ -1553,9 +1615,13 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { break; case llvm::Triple::x86: LibDirs.append(begin(X86LibDirs), end(X86LibDirs)); - TripleAliases.append(begin(X86Triples), end(X86Triples)); - BiarchLibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs)); - BiarchTripleAliases.append(begin(X86_64Triples), end(X86_64Triples)); + // MCU toolchain is 32 bit only and its triple alias is TargetTriple + // itself, which will be appended below. + if (!TargetTriple.isOSIAMCU()) { + TripleAliases.append(begin(X86Triples), end(X86Triples)); + BiarchLibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs)); + BiarchTripleAliases.append(begin(X86_64Triples), end(X86_64Triples)); + } break; case llvm::Triple::mips: LibDirs.append(begin(MIPSLibDirs), end(MIPSLibDirs)); @@ -1631,9 +1697,33 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { BiarchTripleAliases.push_back(BiarchTriple.str()); } +// Parses the contents of version.txt in an CUDA installation. It should +// contain one line of the from e.g. "CUDA Version 7.5.2". +static CudaVersion ParseCudaVersionFile(llvm::StringRef V) { + if (!V.startswith("CUDA Version ")) + return CudaVersion::UNKNOWN; + V = V.substr(strlen("CUDA Version ")); + int Major = -1, Minor = -1; + auto First = V.split('.'); + auto Second = First.second.split('.'); + if (!First.first.getAsInteger(10, Major) || + !Second.first.getAsInteger(10, Minor)) + return CudaVersion::UNKNOWN; + + if (Major == 7 && Minor == 0) { + // This doesn't appear to ever happen -- version.txt doesn't exist in the + // CUDA 7 installs I've seen. But no harm in checking. + return CudaVersion::CUDA_70; + } + if (Major == 7 && Minor == 5) + return CudaVersion::CUDA_75; + if (Major == 8 && Minor == 0) + return CudaVersion::CUDA_80; + return CudaVersion::UNKNOWN; +} + // \brief -- try common CUDA installation paths looking for files we need for // CUDA compilation. - void Generic_GCC::CudaInstallationDetector::init( const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args) { SmallVector<std::string, 4> CudaPathCandidates; @@ -1643,6 +1733,8 @@ void Generic_GCC::CudaInstallationDetector::init( Args.getLastArgValue(options::OPT_cuda_path_EQ)); else { CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda"); + // FIXME: Uncomment this once we can compile the cuda 8 headers. + // CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda-8.0"); CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda-7.5"); CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda-7.0"); } @@ -1651,19 +1743,19 @@ void Generic_GCC::CudaInstallationDetector::init( if (CudaPath.empty() || !D.getVFS().exists(CudaPath)) continue; - CudaInstallPath = CudaPath; - CudaIncludePath = CudaInstallPath + "/include"; - CudaLibDevicePath = CudaInstallPath + "/nvvm/libdevice"; - CudaLibPath = - CudaInstallPath + (TargetTriple.isArch64Bit() ? "/lib64" : "/lib"); + InstallPath = CudaPath; + BinPath = CudaPath + "/bin"; + IncludePath = InstallPath + "/include"; + LibDevicePath = InstallPath + "/nvvm/libdevice"; + LibPath = InstallPath + (TargetTriple.isArch64Bit() ? "/lib64" : "/lib"); - if (!(D.getVFS().exists(CudaIncludePath) && - D.getVFS().exists(CudaLibPath) && - D.getVFS().exists(CudaLibDevicePath))) + auto &FS = D.getVFS(); + if (!(FS.exists(IncludePath) && FS.exists(BinPath) && FS.exists(LibPath) && + FS.exists(LibDevicePath))) continue; std::error_code EC; - for (llvm::sys::fs::directory_iterator LI(CudaLibDevicePath, EC), LE; + for (llvm::sys::fs::directory_iterator LI(LibDevicePath, EC), LE; !EC && LI != LE; LI = LI.increment(EC)) { StringRef FilePath = LI->path(); StringRef FileName = llvm::sys::path::filename(FilePath); @@ -1673,41 +1765,74 @@ void Generic_GCC::CudaInstallationDetector::init( continue; StringRef GpuArch = FileName.slice( LibDeviceName.size(), FileName.find('.', LibDeviceName.size())); - CudaLibDeviceMap[GpuArch] = FilePath.str(); + LibDeviceMap[GpuArch] = FilePath.str(); // Insert map entries for specifc devices with this compute capability. if (GpuArch == "compute_20") { - CudaLibDeviceMap["sm_20"] = FilePath; - CudaLibDeviceMap["sm_21"] = FilePath; + LibDeviceMap["sm_20"] = FilePath; + LibDeviceMap["sm_21"] = FilePath; } else if (GpuArch == "compute_30") { - CudaLibDeviceMap["sm_30"] = FilePath; - CudaLibDeviceMap["sm_32"] = FilePath; + LibDeviceMap["sm_30"] = FilePath; + LibDeviceMap["sm_32"] = FilePath; } else if (GpuArch == "compute_35") { - CudaLibDeviceMap["sm_35"] = FilePath; - CudaLibDeviceMap["sm_37"] = FilePath; + LibDeviceMap["sm_35"] = FilePath; + LibDeviceMap["sm_37"] = FilePath; + } else if (GpuArch == "compute_50") { + LibDeviceMap["sm_50"] = FilePath; + LibDeviceMap["sm_52"] = FilePath; + LibDeviceMap["sm_53"] = FilePath; + LibDeviceMap["sm_60"] = FilePath; + LibDeviceMap["sm_61"] = FilePath; + LibDeviceMap["sm_62"] = FilePath; } } + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile = + FS.getBufferForFile(InstallPath + "/version.txt"); + if (!VersionFile) { + // CUDA 7.0 doesn't have a version.txt, so guess that's our version if + // version.txt isn't present. + Version = CudaVersion::CUDA_70; + } else { + Version = ParseCudaVersionFile((*VersionFile)->getBuffer()); + } + IsValid = true; break; } } +void Generic_GCC::CudaInstallationDetector::CheckCudaVersionSupportsArch( + CudaArch Arch) const { + if (Arch == CudaArch::UNKNOWN || Version == CudaVersion::UNKNOWN || + ArchsWithVersionTooLowErrors.count(Arch) > 0) + return; + + auto RequiredVersion = MinVersionForCudaArch(Arch); + if (Version < RequiredVersion) { + ArchsWithVersionTooLowErrors.insert(Arch); + D.Diag(diag::err_drv_cuda_version_too_low) + << InstallPath << CudaArchToString(Arch) << CudaVersionToString(Version) + << CudaVersionToString(RequiredVersion); + } +} + void Generic_GCC::CudaInstallationDetector::print(raw_ostream &OS) const { if (isValid()) - OS << "Found CUDA installation: " << CudaInstallPath << "\n"; + OS << "Found CUDA installation: " << InstallPath << ", version " + << CudaVersionToString(Version) << "\n"; } namespace { // Filter to remove Multilibs that don't exist as a suffix to Path class FilterNonExistent { - StringRef Base; + StringRef Base, File; vfs::FileSystem &VFS; public: - FilterNonExistent(StringRef Base, vfs::FileSystem &VFS) - : Base(Base), VFS(VFS) {} + FilterNonExistent(StringRef Base, StringRef File, vfs::FileSystem &VFS) + : Base(Base), File(File), VFS(VFS) {} bool operator()(const Multilib &M) { - return !VFS.exists(Base + M.gccSuffix() + "/crtbegin.o"); + return !VFS.exists(Base + M.gccSuffix() + File); } }; } // end anonymous namespace @@ -1720,6 +1845,10 @@ static void addMultilibFlag(bool Enabled, const char *const Flag, Flags.push_back(std::string("-") + Flag); } +static bool isArmOrThumbArch(llvm::Triple::ArchType Arch) { + return Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb; +} + static bool isMipsArch(llvm::Triple::ArchType Arch) { return Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel || Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el; @@ -1765,38 +1894,151 @@ static Multilib makeMultilib(StringRef commonSuffix) { return Multilib(commonSuffix, commonSuffix, commonSuffix); } -static bool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple, - StringRef Path, const ArgList &Args, - DetectedMultilibs &Result) { - // Some MIPS toolchains put libraries and object files compiled - // using different options in to the sub-directoris which names - // reflects the flags used for compilation. For example sysroot - // directory might looks like the following examples: - // - // /usr - // /lib <= crt*.o files compiled with '-mips32' - // /mips16 - // /usr - // /lib <= crt*.o files compiled with '-mips16' - // /el - // /usr - // /lib <= crt*.o files compiled with '-mips16 -EL' - // - // or - // - // /usr - // /lib <= crt*.o files compiled with '-mips32r2' - // /mips16 - // /usr - // /lib <= crt*.o files compiled with '-mips32r2 -mips16' - // /mips32 - // /usr - // /lib <= crt*.o files compiled with '-mips32' - - FilterNonExistent NonExistent(Path, D.getVFS()); - - // Check for FSF toolchain multilibs - MultilibSet FSFMipsMultilibs; +static bool findMipsCsMultilibs(const Multilib::flags_list &Flags, + FilterNonExistent &NonExistent, + DetectedMultilibs &Result) { + // Check for Code Sourcery toolchain multilibs + MultilibSet CSMipsMultilibs; + { + auto MArchMips16 = makeMultilib("/mips16").flag("+m32").flag("+mips16"); + + auto MArchMicroMips = + makeMultilib("/micromips").flag("+m32").flag("+mmicromips"); + + auto MArchDefault = makeMultilib("").flag("-mips16").flag("-mmicromips"); + + auto UCLibc = makeMultilib("/uclibc").flag("+muclibc"); + + auto SoftFloat = makeMultilib("/soft-float").flag("+msoft-float"); + + auto Nan2008 = makeMultilib("/nan2008").flag("+mnan=2008"); + + auto DefaultFloat = + makeMultilib("").flag("-msoft-float").flag("-mnan=2008"); + + auto BigEndian = makeMultilib("").flag("+EB").flag("-EL"); + + auto LittleEndian = makeMultilib("/el").flag("+EL").flag("-EB"); + + // Note that this one's osSuffix is "" + auto MAbi64 = makeMultilib("") + .gccSuffix("/64") + .includeSuffix("/64") + .flag("+mabi=n64") + .flag("-mabi=n32") + .flag("-m32"); + + CSMipsMultilibs = + MultilibSet() + .Either(MArchMips16, MArchMicroMips, MArchDefault) + .Maybe(UCLibc) + .Either(SoftFloat, Nan2008, DefaultFloat) + .FilterOut("/micromips/nan2008") + .FilterOut("/mips16/nan2008") + .Either(BigEndian, LittleEndian) + .Maybe(MAbi64) + .FilterOut("/mips16.*/64") + .FilterOut("/micromips.*/64") + .FilterOut(NonExistent) + .setIncludeDirsCallback([](const Multilib &M) { + std::vector<std::string> Dirs({"/include"}); + if (StringRef(M.includeSuffix()).startswith("/uclibc")) + Dirs.push_back( + "/../../../../mips-linux-gnu/libc/uclibc/usr/include"); + else + Dirs.push_back("/../../../../mips-linux-gnu/libc/usr/include"); + return Dirs; + }); + } + + MultilibSet DebianMipsMultilibs; + { + Multilib MAbiN32 = + Multilib().gccSuffix("/n32").includeSuffix("/n32").flag("+mabi=n32"); + + Multilib M64 = Multilib() + .gccSuffix("/64") + .includeSuffix("/64") + .flag("+m64") + .flag("-m32") + .flag("-mabi=n32"); + + Multilib M32 = Multilib().flag("-m64").flag("+m32").flag("-mabi=n32"); + + DebianMipsMultilibs = + MultilibSet().Either(M32, M64, MAbiN32).FilterOut(NonExistent); + } + + // Sort candidates. Toolchain that best meets the directories tree goes first. + // Then select the first toolchains matches command line flags. + MultilibSet *Candidates[] = {&CSMipsMultilibs, &DebianMipsMultilibs}; + if (CSMipsMultilibs.size() < DebianMipsMultilibs.size()) + std::iter_swap(Candidates, Candidates + 1); + for (const MultilibSet *Candidate : Candidates) { + if (Candidate->select(Flags, Result.SelectedMultilib)) { + if (Candidate == &DebianMipsMultilibs) + Result.BiarchSibling = Multilib(); + Result.Multilibs = *Candidate; + return true; + } + } + return false; +} + +static bool findMipsAndroidMultilibs(const Multilib::flags_list &Flags, + FilterNonExistent &NonExistent, + DetectedMultilibs &Result) { + + MultilibSet AndroidMipsMultilibs = + MultilibSet() + .Maybe(Multilib("/mips-r2").flag("+march=mips32r2")) + .Maybe(Multilib("/mips-r6").flag("+march=mips32r6")) + .FilterOut(NonExistent); + + if (AndroidMipsMultilibs.select(Flags, Result.SelectedMultilib)) { + Result.Multilibs = AndroidMipsMultilibs; + return true; + } + return false; +} + +static bool findMipsMuslMultilibs(const Multilib::flags_list &Flags, + FilterNonExistent &NonExistent, + DetectedMultilibs &Result) { + // Musl toolchain multilibs + MultilibSet MuslMipsMultilibs; + { + auto MArchMipsR2 = makeMultilib("") + .osSuffix("/mips-r2-hard-musl") + .flag("+EB") + .flag("-EL") + .flag("+march=mips32r2"); + + auto MArchMipselR2 = makeMultilib("/mipsel-r2-hard-musl") + .flag("-EB") + .flag("+EL") + .flag("+march=mips32r2"); + + MuslMipsMultilibs = MultilibSet().Either(MArchMipsR2, MArchMipselR2); + + // Specify the callback that computes the include directories. + MuslMipsMultilibs.setIncludeDirsCallback([](const Multilib &M) { + return std::vector<std::string>( + {"/../sysroot" + M.osSuffix() + "/usr/include"}); + }); + } + if (MuslMipsMultilibs.select(Flags, Result.SelectedMultilib)) { + Result.Multilibs = MuslMipsMultilibs; + return true; + } + return false; +} + +static bool findMipsMtiMultilibs(const Multilib::flags_list &Flags, + FilterNonExistent &NonExistent, + DetectedMultilibs &Result) { + // CodeScape MTI toolchain v1.2 and early. + MultilibSet MtiMipsMultilibsV1; { auto MArchMips32 = makeMultilib("/mips32") .flag("+m32") @@ -1838,7 +2080,7 @@ static bool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple, auto Nan2008 = makeMultilib("/nan2008").flag("+mnan=2008"); - FSFMipsMultilibs = + MtiMipsMultilibsV1 = MultilibSet() .Either(MArchMips32, MArchMicroMips, MArchMips64r2, MArchMips64, MArchDefault) @@ -1857,128 +2099,118 @@ static bool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple, .Maybe(Nan2008) .FilterOut(".*sof/nan2008") .FilterOut(NonExistent) - .setIncludeDirsCallback([](StringRef InstallDir, - StringRef TripleStr, const Multilib &M) { - std::vector<std::string> Dirs; - Dirs.push_back((InstallDir + "/include").str()); - std::string SysRootInc = - InstallDir.str() + "/../../../../sysroot"; + .setIncludeDirsCallback([](const Multilib &M) { + std::vector<std::string> Dirs({"/include"}); if (StringRef(M.includeSuffix()).startswith("/uclibc")) - Dirs.push_back(SysRootInc + "/uclibc/usr/include"); + Dirs.push_back("/../../../../sysroot/uclibc/usr/include"); else - Dirs.push_back(SysRootInc + "/usr/include"); + Dirs.push_back("/../../../../sysroot/usr/include"); return Dirs; }); } - // Check for Musl toolchain multilibs - MultilibSet MuslMipsMultilibs; - { - auto MArchMipsR2 = makeMultilib("") - .osSuffix("/mips-r2-hard-musl") - .flag("+EB") - .flag("-EL") - .flag("+march=mips32r2"); - - auto MArchMipselR2 = makeMultilib("/mipsel-r2-hard-musl") - .flag("-EB") - .flag("+EL") - .flag("+march=mips32r2"); - - MuslMipsMultilibs = MultilibSet().Either(MArchMipsR2, MArchMipselR2); - - // Specify the callback that computes the include directories. - MuslMipsMultilibs.setIncludeDirsCallback([]( - StringRef InstallDir, StringRef TripleStr, const Multilib &M) { - std::vector<std::string> Dirs; - Dirs.push_back( - (InstallDir + "/../sysroot" + M.osSuffix() + "/usr/include").str()); - return Dirs; - }); - } - - // Check for Code Sourcery toolchain multilibs - MultilibSet CSMipsMultilibs; + // CodeScape IMG toolchain starting from v1.3. + MultilibSet MtiMipsMultilibsV2; { - auto MArchMips16 = makeMultilib("/mips16").flag("+m32").flag("+mips16"); - - auto MArchMicroMips = - makeMultilib("/micromips").flag("+m32").flag("+mmicromips"); - - auto MArchDefault = makeMultilib("").flag("-mips16").flag("-mmicromips"); - - auto UCLibc = makeMultilib("/uclibc").flag("+muclibc"); - - auto SoftFloat = makeMultilib("/soft-float").flag("+msoft-float"); - - auto Nan2008 = makeMultilib("/nan2008").flag("+mnan=2008"); - - auto DefaultFloat = - makeMultilib("").flag("-msoft-float").flag("-mnan=2008"); - - auto BigEndian = makeMultilib("").flag("+EB").flag("-EL"); - - auto LittleEndian = makeMultilib("/el").flag("+EL").flag("-EB"); - - // Note that this one's osSuffix is "" - auto MAbi64 = makeMultilib("") - .gccSuffix("/64") - .includeSuffix("/64") - .flag("+mabi=n64") - .flag("-mabi=n32") - .flag("-m32"); - - CSMipsMultilibs = + auto BeHard = makeMultilib("/mips-r2-hard") + .flag("+EB") + .flag("-msoft-float") + .flag("-mnan=2008") + .flag("-muclibc"); + auto BeSoft = makeMultilib("/mips-r2-soft") + .flag("+EB") + .flag("+msoft-float") + .flag("-mnan=2008"); + auto ElHard = makeMultilib("/mipsel-r2-hard") + .flag("+EL") + .flag("-msoft-float") + .flag("-mnan=2008") + .flag("-muclibc"); + auto ElSoft = makeMultilib("/mipsel-r2-soft") + .flag("+EL") + .flag("+msoft-float") + .flag("-mnan=2008") + .flag("-mmicromips"); + auto BeHardNan = makeMultilib("/mips-r2-hard-nan2008") + .flag("+EB") + .flag("-msoft-float") + .flag("+mnan=2008") + .flag("-muclibc"); + auto ElHardNan = makeMultilib("/mipsel-r2-hard-nan2008") + .flag("+EL") + .flag("-msoft-float") + .flag("+mnan=2008") + .flag("-muclibc") + .flag("-mmicromips"); + auto BeHardNanUclibc = makeMultilib("/mips-r2-hard-nan2008-uclibc") + .flag("+EB") + .flag("-msoft-float") + .flag("+mnan=2008") + .flag("+muclibc"); + auto ElHardNanUclibc = makeMultilib("/mipsel-r2-hard-nan2008-uclibc") + .flag("+EL") + .flag("-msoft-float") + .flag("+mnan=2008") + .flag("+muclibc"); + auto BeHardUclibc = makeMultilib("/mips-r2-hard-uclibc") + .flag("+EB") + .flag("-msoft-float") + .flag("-mnan=2008") + .flag("+muclibc"); + auto ElHardUclibc = makeMultilib("/mipsel-r2-hard-uclibc") + .flag("+EL") + .flag("-msoft-float") + .flag("-mnan=2008") + .flag("+muclibc"); + auto ElMicroHardNan = makeMultilib("/micromipsel-r2-hard-nan2008") + .flag("+EL") + .flag("-msoft-float") + .flag("+mnan=2008") + .flag("+mmicromips"); + auto ElMicroSoft = makeMultilib("/micromipsel-r2-soft") + .flag("+EL") + .flag("+msoft-float") + .flag("-mnan=2008") + .flag("+mmicromips"); + + auto O32 = + makeMultilib("/lib").osSuffix("").flag("-mabi=n32").flag("-mabi=n64"); + auto N32 = + makeMultilib("/lib32").osSuffix("").flag("+mabi=n32").flag("-mabi=n64"); + auto N64 = + makeMultilib("/lib64").osSuffix("").flag("-mabi=n32").flag("+mabi=n64"); + + MtiMipsMultilibsV2 = MultilibSet() - .Either(MArchMips16, MArchMicroMips, MArchDefault) - .Maybe(UCLibc) - .Either(SoftFloat, Nan2008, DefaultFloat) - .FilterOut("/micromips/nan2008") - .FilterOut("/mips16/nan2008") - .Either(BigEndian, LittleEndian) - .Maybe(MAbi64) - .FilterOut("/mips16.*/64") - .FilterOut("/micromips.*/64") + .Either({BeHard, BeSoft, ElHard, ElSoft, BeHardNan, ElHardNan, + BeHardNanUclibc, ElHardNanUclibc, BeHardUclibc, + ElHardUclibc, ElMicroHardNan, ElMicroSoft}) + .Either(O32, N32, N64) .FilterOut(NonExistent) - .setIncludeDirsCallback([](StringRef InstallDir, - StringRef TripleStr, const Multilib &M) { - std::vector<std::string> Dirs; - Dirs.push_back((InstallDir + "/include").str()); - std::string SysRootInc = - InstallDir.str() + "/../../../../" + TripleStr.str(); - if (StringRef(M.includeSuffix()).startswith("/uclibc")) - Dirs.push_back(SysRootInc + "/libc/uclibc/usr/include"); - else - Dirs.push_back(SysRootInc + "/libc/usr/include"); - return Dirs; + .setIncludeDirsCallback([](const Multilib &M) { + return std::vector<std::string>({"/../../../../sysroot" + + M.includeSuffix() + + "/../usr/include"}); + }) + .setFilePathsCallback([](const Multilib &M) { + return std::vector<std::string>( + {"/../../../../mips-mti-linux-gnu/lib" + M.gccSuffix()}); }); } - - MultilibSet AndroidMipsMultilibs = - MultilibSet() - .Maybe(Multilib("/mips-r2").flag("+march=mips32r2")) - .Maybe(Multilib("/mips-r6").flag("+march=mips32r6")) - .FilterOut(NonExistent); - - MultilibSet DebianMipsMultilibs; - { - Multilib MAbiN32 = - Multilib().gccSuffix("/n32").includeSuffix("/n32").flag("+mabi=n32"); - - Multilib M64 = Multilib() - .gccSuffix("/64") - .includeSuffix("/64") - .flag("+m64") - .flag("-m32") - .flag("-mabi=n32"); - - Multilib M32 = Multilib().flag("-m64").flag("+m32").flag("-mabi=n32"); - - DebianMipsMultilibs = - MultilibSet().Either(M32, M64, MAbiN32).FilterOut(NonExistent); + for (auto Candidate : {&MtiMipsMultilibsV1, &MtiMipsMultilibsV2}) { + if (Candidate->select(Flags, Result.SelectedMultilib)) { + Result.Multilibs = *Candidate; + return true; + } } + return false; +} - MultilibSet ImgMultilibs; +static bool findMipsImgMultilibs(const Multilib::flags_list &Flags, + FilterNonExistent &NonExistent, + DetectedMultilibs &Result) { + // CodeScape IMG toolchain v1.2 and early. + MultilibSet ImgMultilibsV1; { auto Mips64r6 = makeMultilib("/mips64r6").flag("+m64").flag("-m32"); @@ -1987,21 +2219,90 @@ static bool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple, auto MAbi64 = makeMultilib("/64").flag("+mabi=n64").flag("-mabi=n32").flag("-m32"); - ImgMultilibs = + ImgMultilibsV1 = MultilibSet() .Maybe(Mips64r6) .Maybe(MAbi64) .Maybe(LittleEndian) .FilterOut(NonExistent) - .setIncludeDirsCallback([](StringRef InstallDir, - StringRef TripleStr, const Multilib &M) { - std::vector<std::string> Dirs; - Dirs.push_back((InstallDir + "/include").str()); - Dirs.push_back( - (InstallDir + "/../../../../sysroot/usr/include").str()); - return Dirs; + .setIncludeDirsCallback([](const Multilib &M) { + return std::vector<std::string>( + {"/include", "/../../../../sysroot/usr/include"}); + }); + } + + // CodeScape IMG toolchain starting from v1.3. + MultilibSet ImgMultilibsV2; + { + auto BeHard = makeMultilib("/mips-r6-hard") + .flag("+EB") + .flag("-msoft-float") + .flag("-mmicromips"); + auto BeSoft = makeMultilib("/mips-r6-soft") + .flag("+EB") + .flag("+msoft-float") + .flag("-mmicromips"); + auto ElHard = makeMultilib("/mipsel-r6-hard") + .flag("+EL") + .flag("-msoft-float") + .flag("-mmicromips"); + auto ElSoft = makeMultilib("/mipsel-r6-soft") + .flag("+EL") + .flag("+msoft-float") + .flag("-mmicromips"); + auto BeMicroHard = makeMultilib("/micromips-r6-hard") + .flag("+EB") + .flag("-msoft-float") + .flag("+mmicromips"); + auto BeMicroSoft = makeMultilib("/micromips-r6-soft") + .flag("+EB") + .flag("+msoft-float") + .flag("+mmicromips"); + auto ElMicroHard = makeMultilib("/micromipsel-r6-hard") + .flag("+EL") + .flag("-msoft-float") + .flag("+mmicromips"); + auto ElMicroSoft = makeMultilib("/micromipsel-r6-soft") + .flag("+EL") + .flag("+msoft-float") + .flag("+mmicromips"); + + auto O32 = + makeMultilib("/lib").osSuffix("").flag("-mabi=n32").flag("-mabi=n64"); + auto N32 = + makeMultilib("/lib32").osSuffix("").flag("+mabi=n32").flag("-mabi=n64"); + auto N64 = + makeMultilib("/lib64").osSuffix("").flag("-mabi=n32").flag("+mabi=n64"); + + ImgMultilibsV2 = + MultilibSet() + .Either({BeHard, BeSoft, ElHard, ElSoft, BeMicroHard, BeMicroSoft, + ElMicroHard, ElMicroSoft}) + .Either(O32, N32, N64) + .FilterOut(NonExistent) + .setIncludeDirsCallback([](const Multilib &M) { + return std::vector<std::string>({"/../../../../sysroot" + + M.includeSuffix() + + "/../usr/include"}); + }) + .setFilePathsCallback([](const Multilib &M) { + return std::vector<std::string>( + {"/../../../../mips-img-linux-gnu/lib" + M.gccSuffix()}); }); } + for (auto Candidate : {&ImgMultilibsV1, &ImgMultilibsV2}) { + if (Candidate->select(Flags, Result.SelectedMultilib)) { + Result.Multilibs = *Candidate; + return true; + } + } + return false; +} + +static bool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple, + StringRef Path, const ArgList &Args, + DetectedMultilibs &Result) { + FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS()); StringRef CPUName; StringRef ABIName; @@ -2033,67 +2334,82 @@ static bool findMIPSMultilibs(const Driver &D, const llvm::Triple &TargetTriple, addMultilibFlag(isMipsEL(TargetArch), "EL", Flags); addMultilibFlag(!isMipsEL(TargetArch), "EB", Flags); - if (TargetTriple.isAndroid()) { - // Select Android toolchain. It's the only choice in that case. - if (AndroidMipsMultilibs.select(Flags, Result.SelectedMultilib)) { - Result.Multilibs = AndroidMipsMultilibs; - return true; - } - return false; - } + if (TargetTriple.isAndroid()) + return findMipsAndroidMultilibs(Flags, NonExistent, Result); if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies && TargetTriple.getOS() == llvm::Triple::Linux && - TargetTriple.getEnvironment() == llvm::Triple::UnknownEnvironment) { - if (MuslMipsMultilibs.select(Flags, Result.SelectedMultilib)) { - Result.Multilibs = MuslMipsMultilibs; - return true; - } - return false; - } + TargetTriple.getEnvironment() == llvm::Triple::UnknownEnvironment) + return findMipsMuslMultilibs(Flags, NonExistent, Result); + + if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies && + TargetTriple.getOS() == llvm::Triple::Linux && + TargetTriple.getEnvironment() == llvm::Triple::GNU) + return findMipsMtiMultilibs(Flags, NonExistent, Result); if (TargetTriple.getVendor() == llvm::Triple::ImaginationTechnologies && TargetTriple.getOS() == llvm::Triple::Linux && - TargetTriple.getEnvironment() == llvm::Triple::GNU) { - // Select mips-img-linux-gnu toolchain. - if (ImgMultilibs.select(Flags, Result.SelectedMultilib)) { - Result.Multilibs = ImgMultilibs; - return true; - } - return false; - } + TargetTriple.getEnvironment() == llvm::Triple::GNU) + return findMipsImgMultilibs(Flags, NonExistent, Result); - // Sort candidates. Toolchain that best meets the directories goes first. - // Then select the first toolchains matches command line flags. - MultilibSet *candidates[] = {&DebianMipsMultilibs, &FSFMipsMultilibs, - &CSMipsMultilibs}; - std::sort( - std::begin(candidates), std::end(candidates), - [](MultilibSet *a, MultilibSet *b) { return a->size() > b->size(); }); - for (const auto &candidate : candidates) { - if (candidate->select(Flags, Result.SelectedMultilib)) { - if (candidate == &DebianMipsMultilibs) - Result.BiarchSibling = Multilib(); - Result.Multilibs = *candidate; - return true; - } - } + if (findMipsCsMultilibs(Flags, NonExistent, Result)) + return true; - { - // Fallback to the regular toolchain-tree structure. - Multilib Default; - Result.Multilibs.push_back(Default); - Result.Multilibs.FilterOut(NonExistent); + // Fallback to the regular toolchain-tree structure. + Multilib Default; + Result.Multilibs.push_back(Default); + Result.Multilibs.FilterOut(NonExistent); - if (Result.Multilibs.select(Flags, Result.SelectedMultilib)) { - Result.BiarchSibling = Multilib(); - return true; - } + if (Result.Multilibs.select(Flags, Result.SelectedMultilib)) { + Result.BiarchSibling = Multilib(); + return true; } return false; } +static void findAndroidArmMultilibs(const Driver &D, + const llvm::Triple &TargetTriple, + StringRef Path, const ArgList &Args, + DetectedMultilibs &Result) { + // Find multilibs with subdirectories like armv7-a, thumb, armv7-a/thumb. + FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS()); + Multilib ArmV7Multilib = makeMultilib("/armv7-a") + .flag("+armv7") + .flag("-thumb"); + Multilib ThumbMultilib = makeMultilib("/thumb") + .flag("-armv7") + .flag("+thumb"); + Multilib ArmV7ThumbMultilib = makeMultilib("/armv7-a/thumb") + .flag("+armv7") + .flag("+thumb"); + Multilib DefaultMultilib = makeMultilib("") + .flag("-armv7") + .flag("-thumb"); + MultilibSet AndroidArmMultilibs = + MultilibSet() + .Either(ThumbMultilib, ArmV7Multilib, + ArmV7ThumbMultilib, DefaultMultilib) + .FilterOut(NonExistent); + + Multilib::flags_list Flags; + llvm::StringRef Arch = Args.getLastArgValue(options::OPT_march_EQ); + bool IsArmArch = TargetTriple.getArch() == llvm::Triple::arm; + bool IsThumbArch = TargetTriple.getArch() == llvm::Triple::thumb; + bool IsV7SubArch = TargetTriple.getSubArch() == llvm::Triple::ARMSubArch_v7; + bool IsThumbMode = IsThumbArch || + Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, false) || + (IsArmArch && llvm::ARM::parseArchISA(Arch) == llvm::ARM::IK_THUMB); + bool IsArmV7Mode = (IsArmArch || IsThumbArch) && + (llvm::ARM::parseArchVersion(Arch) == 7 || + (IsArmArch && Arch == "" && IsV7SubArch)); + addMultilibFlag(IsArmV7Mode, "armv7", Flags); + addMultilibFlag(IsThumbMode, "thumb", Flags); + + if (AndroidArmMultilibs.select(Flags, Result.SelectedMultilib)) + Result.Multilibs = AndroidArmMultilibs; +} + static bool findBiarchMultilibs(const Driver &D, const llvm::Triple &TargetTriple, StringRef Path, const ArgList &Args, @@ -2126,7 +2442,9 @@ static bool findBiarchMultilibs(const Driver &D, .flag("-m64") .flag("+mx32"); - FilterNonExistent NonExistent(Path, D.getVFS()); + // GCC toolchain for IAMCU doesn't have crtbegin.o, so look for libgcc.a. + FilterNonExistent NonExistent( + Path, TargetTriple.isOSIAMCU() ? "/libgcc.a" : "/crtbegin.o", D.getVFS()); // Determine default multilib from: 32, 64, x32 // Also handle cases such as 64 on 32, 32 on 64, etc. @@ -2285,9 +2603,13 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( DetectedMultilibs Detected; + // Android standalone toolchain could have multilibs for ARM and Thumb. // Debian mips multilibs behave more like the rest of the biarch ones, // so handle them there - if (isMipsArch(TargetArch)) { + if (isArmOrThumbArch(TargetArch) && TargetTriple.isAndroid()) { + // It should also work without multilibs in a simplified toolchain. + findAndroidArmMultilibs(D, TargetTriple, LI->getName(), Args, Detected); + } else if (isMipsArch(TargetArch)) { if (!findMIPSMultilibs(D, TargetTriple, LI->getName(), Args, Detected)) continue; } else if (!findBiarchMultilibs(D, TargetTriple, LI->getName(), Args, @@ -2378,6 +2700,8 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const { case llvm::Triple::ppc64: case llvm::Triple::ppc64le: case llvm::Triple::systemz: + case llvm::Triple::mips: + case llvm::Triple::mipsel: return true; default: return false; @@ -2417,7 +2741,6 @@ bool Generic_GCC::addLibStdCXXIncludePaths( return true; } - void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs, ArgStringList &CC1Args) const { const Generic_GCC::GCCVersion &V = GCCInstallation.getVersion(); @@ -2473,10 +2796,9 @@ void MipsLLVMToolChain::AddClangSystemIncludeArgs( const auto &Callback = Multilibs.includeDirsCallback(); if (Callback) { - const auto IncludePaths = - Callback(D.getInstalledDir(), getTripleString(), SelectedMultilib); - for (const auto &Path : IncludePaths) - addExternCSystemIncludeIfExists(DriverArgs, CC1Args, Path); + for (const auto &Path : Callback(SelectedMultilib)) + addExternCSystemIncludeIfExists(DriverArgs, CC1Args, + D.getInstalledDir() + Path); } } @@ -2521,11 +2843,10 @@ void MipsLLVMToolChain::AddClangCXXStdlibIncludeArgs( const auto &Callback = Multilibs.includeDirsCallback(); if (Callback) { - const auto IncludePaths = Callback(getDriver().getInstalledDir(), - getTripleString(), SelectedMultilib); - for (const auto &Path : IncludePaths) { - if (llvm::sys::fs::exists(Path + "/c++/v1")) { - addSystemInclude(DriverArgs, CC1Args, Path + "/c++/v1"); + for (std::string Path : Callback(SelectedMultilib)) { + Path = getDriver().getInstalledDir() + Path + "/c++/v1"; + if (llvm::sys::fs::exists(Path)) { + addSystemInclude(DriverArgs, CC1Args, Path); break; } } @@ -2569,14 +2890,9 @@ std::string HexagonToolChain::getHexagonTargetDir( if (getVFS().exists(InstallRelDir = InstalledDir + "/../target")) return InstallRelDir; - std::string PrefixRelDir = std::string(LLVM_PREFIX) + "/target"; - if (getVFS().exists(PrefixRelDir)) - return PrefixRelDir; - return InstallRelDir; } - Optional<unsigned> HexagonToolChain::getSmallDataThreshold( const ArgList &Args) { StringRef Gn = ""; @@ -2595,7 +2911,6 @@ Optional<unsigned> HexagonToolChain::getSmallDataThreshold( return None; } - void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args, ToolChain::path_list &LibPaths) const { const Driver &D = getDriver(); @@ -2971,6 +3286,61 @@ Tool *CloudABI::buildLinker() const { return new tools::cloudabi::Linker(*this); } +bool CloudABI::isPIEDefault() const { + // Only enable PIE on architectures that support PC-relative + // addressing. PC-relative addressing is required, as the process + // startup code must be able to relocate itself. + switch (getTriple().getArch()) { + case llvm::Triple::aarch64: + case llvm::Triple::x86_64: + return true; + default: + return false; + } +} + +SanitizerMask CloudABI::getSupportedSanitizers() const { + SanitizerMask Res = ToolChain::getSupportedSanitizers(); + Res |= SanitizerKind::SafeStack; + return Res; +} + +SanitizerMask CloudABI::getDefaultSanitizers() const { + return SanitizerKind::SafeStack; +} + +/// Haiku - Haiku tool chain which can call as(1) and ld(1) directly. + +Haiku::Haiku(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) + : Generic_ELF(D, Triple, Args) { + +} + +void Haiku::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdlibinc) || + DriverArgs.hasArg(options::OPT_nostdincxx)) + return; + + switch (GetCXXStdlibType(DriverArgs)) { + case ToolChain::CST_Libcxx: + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/system/develop/headers/c++/v1"); + break; + case ToolChain::CST_Libstdcxx: + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/system/develop/headers/c++"); + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/system/develop/headers/c++/backward"); + + StringRef Triple = getTriple().str(); + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/system/develop/headers/c++/" + + Triple); + break; + } +} + /// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly. OpenBSD::OpenBSD(const Driver &D, const llvm::Triple &Triple, @@ -3052,16 +3422,7 @@ Tool *Bitrig::buildAssembler() const { Tool *Bitrig::buildLinker() const { return new tools::bitrig::Linker(*this); } -ToolChain::CXXStdlibType Bitrig::GetCXXStdlibType(const ArgList &Args) const { - if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { - StringRef Value = A->getValue(); - if (Value == "libstdc++") - return ToolChain::CST_Libstdcxx; - if (Value == "libc++") - return ToolChain::CST_Libcxx; - - getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args); - } +ToolChain::CXXStdlibType Bitrig::GetDefaultCXXStdlibType() const { return ToolChain::CST_Libcxx; } @@ -3125,16 +3486,7 @@ FreeBSD::FreeBSD(const Driver &D, const llvm::Triple &Triple, getFilePaths().push_back(getDriver().SysRoot + "/usr/lib"); } -ToolChain::CXXStdlibType FreeBSD::GetCXXStdlibType(const ArgList &Args) const { - if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { - StringRef Value = A->getValue(); - if (Value == "libstdc++") - return ToolChain::CST_Libstdcxx; - if (Value == "libc++") - return ToolChain::CST_Libcxx; - - getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args); - } +ToolChain::CXXStdlibType FreeBSD::GetDefaultCXXStdlibType() const { if (getTriple().getOSMajorVersion() >= 10) return ToolChain::CST_Libcxx; return ToolChain::CST_Libstdcxx; @@ -3222,7 +3574,6 @@ SanitizerMask FreeBSD::getSupportedSanitizers() const { NetBSD::NetBSD(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : Generic_ELF(D, Triple, Args) { - if (getDriver().UseStdLib) { // When targeting a 32-bit platform, try the special directory used on // 64-bit hosts, and only fall back to the main library directory if that @@ -3278,20 +3629,10 @@ Tool *NetBSD::buildAssembler() const { Tool *NetBSD::buildLinker() const { return new tools::netbsd::Linker(*this); } -ToolChain::CXXStdlibType NetBSD::GetCXXStdlibType(const ArgList &Args) const { - if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { - StringRef Value = A->getValue(); - if (Value == "libstdc++") - return ToolChain::CST_Libstdcxx; - if (Value == "libc++") - return ToolChain::CST_Libcxx; - - getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args); - } - +ToolChain::CXXStdlibType NetBSD::GetDefaultCXXStdlibType() const { unsigned Major, Minor, Micro; getTriple().getOSVersion(Major, Minor, Micro); - if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 49) || Major == 0) { + if (Major >= 7 || Major == 0) { switch (getArch()) { case llvm::Triple::aarch64: case llvm::Triple::arm: @@ -3433,7 +3774,6 @@ enum Distro { DebianJessie, DebianStretch, Exherbo, - RHEL4, RHEL5, RHEL6, RHEL7, @@ -3460,7 +3800,7 @@ enum Distro { }; static bool IsRedhat(enum Distro Distro) { - return Distro == Fedora || (Distro >= RHEL4 && Distro <= RHEL7); + return Distro == Fedora || (Distro >= RHEL5 && Distro <= RHEL7); } static bool IsOpenSUSE(enum Distro Distro) { return Distro == OpenSUSE; } @@ -3502,7 +3842,8 @@ static Distro DetectDistro(const Driver &D, llvm::Triple::ArchType Arch) { .Case("wily", UbuntuWily) .Case("xenial", UbuntuXenial) .Default(UnknownDistro); - return Version; + if (Version != UnknownDistro) + return Version; } File = llvm::MemoryBuffer::getFile("/etc/redhat-release"); @@ -3511,15 +3852,14 @@ static Distro DetectDistro(const Driver &D, llvm::Triple::ArchType Arch) { if (Data.startswith("Fedora release")) return Fedora; if (Data.startswith("Red Hat Enterprise Linux") || - Data.startswith("CentOS")) { + Data.startswith("CentOS") || + Data.startswith("Scientific Linux")) { if (Data.find("release 7") != StringRef::npos) return RHEL7; else if (Data.find("release 6") != StringRef::npos) return RHEL6; else if (Data.find("release 5") != StringRef::npos) return RHEL5; - else if (Data.find("release 4") != StringRef::npos) - return RHEL4; } return UnknownDistro; } @@ -3692,6 +4032,15 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) { return Triple.isArch32Bit() ? "lib" : "lib64"; } +static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs, + const Multilib &Multilib, + StringRef InstallPath, + ToolChain::path_list &Paths) { + if (const auto &PathsCallback = Multilibs.filePathsCallback()) + for (const auto &Path : PathsCallback(Multilib)) + addPathIfExists(D, InstallPath + Path, Paths); +} + Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : Generic_ELF(D, Triple, Args) { GCCInstallation.init(Triple, Args); @@ -3744,13 +4093,12 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) ExtraOpts.push_back("--hash-style=both"); } - if (IsRedhat(Distro)) + if (IsRedhat(Distro) && Distro != RHEL5 && Distro != RHEL6) ExtraOpts.push_back("--no-add-needed"); - if ((IsDebian(Distro) && Distro >= DebianSqueeze) || IsOpenSUSE(Distro) || - (IsRedhat(Distro) && Distro != RHEL4 && Distro != RHEL5) || - (IsUbuntu(Distro) && Distro >= UbuntuKarmic)) - ExtraOpts.push_back("--build-id"); +#ifdef ENABLE_LINKER_BUILD_ID + ExtraOpts.push_back("--build-id"); +#endif if (IsOpenSUSE(Distro)) ExtraOpts.push_back("--enable-new-dtags"); @@ -3770,6 +4118,11 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) 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, + GCCInstallation.getInstallPath(), Paths); // Sourcery CodeBench MIPS toolchain holds some libraries under // a biarch-like suffix of the GCC installation. @@ -3909,6 +4262,125 @@ std::string Linux::computeSysRoot() const { return std::string(); } +std::string Linux::getDynamicLinker(const ArgList &Args) const { + const llvm::Triple::ArchType Arch = getArch(); + const llvm::Triple &Triple = getTriple(); + + const enum Distro Distro = DetectDistro(getDriver(), Arch); + + if (Triple.isAndroid()) + return Triple.isArch64Bit() ? "/system/bin/linker64" : "/system/bin/linker"; + else if (Triple.isMusl()) { + std::string ArchName; + switch (Arch) { + case llvm::Triple::thumb: + ArchName = "arm"; + break; + case llvm::Triple::thumbeb: + ArchName = "armeb"; + break; + default: + ArchName = Triple.getArchName().str(); + } + if (Triple.getEnvironment() == llvm::Triple::MuslEABIHF) + ArchName += "hf"; + + return "/lib/ld-musl-" + ArchName + ".so.1"; + } + + std::string LibDir; + std::string Loader; + + switch (Arch) { + default: + llvm_unreachable("unsupported architecture"); + + case llvm::Triple::aarch64: + LibDir = "lib"; + Loader = "ld-linux-aarch64.so.1"; + break; + case llvm::Triple::aarch64_be: + LibDir = "lib"; + Loader = "ld-linux-aarch64_be.so.1"; + break; + case llvm::Triple::arm: + case llvm::Triple::thumb: + case llvm::Triple::armeb: + case llvm::Triple::thumbeb: { + const bool HF = + Triple.getEnvironment() == llvm::Triple::GNUEABIHF || + tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard; + + LibDir = "lib"; + Loader = HF ? "ld-linux-armhf.so.3" : "ld-linux.so.3"; + break; + } + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: { + bool LE = (Triple.getArch() == llvm::Triple::mipsel) || + (Triple.getArch() == llvm::Triple::mips64el); + bool IsNaN2008 = tools::mips::isNaN2008(Args, Triple); + + LibDir = "lib" + tools::mips::getMipsABILibSuffix(Args, Triple); + + if (tools::mips::isUCLibc(Args)) + Loader = IsNaN2008 ? "ld-uClibc-mipsn8.so.0" : "ld-uClibc.so.0"; + else if (!Triple.hasEnvironment() && + Triple.getVendor() == llvm::Triple::VendorType::MipsTechnologies) + Loader = LE ? "ld-musl-mipsel.so.1" : "ld-musl-mips.so.1"; + else + Loader = IsNaN2008 ? "ld-linux-mipsn8.so.1" : "ld.so.1"; + + break; + } + case llvm::Triple::ppc: + LibDir = "lib"; + Loader = "ld.so.1"; + break; + case llvm::Triple::ppc64: + LibDir = "lib64"; + Loader = + (tools::ppc::hasPPCAbiArg(Args, "elfv2")) ? "ld64.so.2" : "ld64.so.1"; + break; + case llvm::Triple::ppc64le: + LibDir = "lib64"; + Loader = + (tools::ppc::hasPPCAbiArg(Args, "elfv1")) ? "ld64.so.1" : "ld64.so.2"; + break; + case llvm::Triple::sparc: + case llvm::Triple::sparcel: + LibDir = "lib"; + Loader = "ld-linux.so.2"; + break; + case llvm::Triple::sparcv9: + LibDir = "lib64"; + Loader = "ld-linux.so.2"; + break; + case llvm::Triple::systemz: + LibDir = "lib"; + Loader = "ld64.so.1"; + break; + case llvm::Triple::x86: + LibDir = "lib"; + Loader = "ld-linux.so.2"; + break; + case llvm::Triple::x86_64: { + bool X32 = Triple.getEnvironment() == llvm::Triple::GNUX32; + + LibDir = X32 ? "libx32" : "lib64"; + Loader = X32 ? "ld-linux-x32.so.2" : "ld-linux-x86-64.so.2"; + break; + } + } + + if (Distro == Exherbo && (Triple.getVendor() == llvm::Triple::UnknownVendor || + Triple.getVendor() == llvm::Triple::PC)) + return "/usr/" + Triple.str() + "/lib/" + Loader; + return "/" + LibDir + "/" + Loader; +} + void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { const Driver &D = getDriver(); @@ -3949,11 +4421,9 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, if (GCCInstallation.isValid()) { const auto &Callback = Multilibs.includeDirsCallback(); if (Callback) { - const auto IncludePaths = Callback(GCCInstallation.getInstallPath(), - GCCInstallation.getTriple().str(), - GCCInstallation.getMultilib()); - for (const auto &Path : IncludePaths) - addExternCSystemIncludeIfExists(DriverArgs, CC1Args, Path); + for (const auto &Path : Callback(GCCInstallation.getMultilib())) + addExternCSystemIncludeIfExists( + DriverArgs, CC1Args, GCCInstallation.getInstallPath() + Path); } } @@ -4080,7 +4550,6 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include"); } - static std::string DetectLibcxxIncludePath(StringRef base) { std::error_code EC; int MaxVersion = 0; @@ -4110,11 +4579,11 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) { const std::string LibCXXIncludePathCandidates[] = { DetectLibcxxIncludePath(getDriver().Dir + "/../include/c++"), - - // We also check the system as for a long time this is the only place - // Clang looked. - // FIXME: We should really remove this. It doesn't make any sense. - DetectLibcxxIncludePath(getDriver().SysRoot + "/usr/include/c++")}; + // If this is a development, non-installed, clang, libcxx will + // not be found at ../include/c++ but it likely to be found at + // one of the following two locations: + DetectLibcxxIncludePath(getDriver().SysRoot + "/usr/local/include/c++"), + DetectLibcxxIncludePath(getDriver().SysRoot + "/usr/include/c++") }; for (const auto &IncludePath : LibCXXIncludePathCandidates) { if (IncludePath.empty() || !getVFS().exists(IncludePath)) continue; @@ -4155,6 +4624,7 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, const std::string LibStdCXXIncludePathCandidates[] = { // Gentoo is weird and places its headers inside the GCC install, // so if the first attempt to find the headers fails, try these patterns. + InstallDir.str() + "/include/g++-v" + Version.Text, InstallDir.str() + "/include/g++-v" + Version.MajorStr + "." + Version.MinorStr, InstallDir.str() + "/include/g++-v" + Version.MajorStr, @@ -4179,10 +4649,23 @@ void Linux::AddCudaIncludeArgs(const ArgList &DriverArgs, if (DriverArgs.hasArg(options::OPT_nocudainc)) return; - if (CudaInstallation.isValid()) { - addSystemInclude(DriverArgs, CC1Args, CudaInstallation.getIncludePath()); - CC1Args.push_back("-include"); - CC1Args.push_back("__clang_cuda_runtime_wrapper.h"); + if (!CudaInstallation.isValid()) { + getDriver().Diag(diag::err_drv_no_cuda_installation); + return; + } + + addSystemInclude(DriverArgs, CC1Args, CudaInstallation.getIncludePath()); + CC1Args.push_back("-include"); + CC1Args.push_back("__clang_cuda_runtime_wrapper.h"); +} + +void Linux::AddIAMCUIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (GCCInstallation.isValid()) { + CC1Args.push_back("-isystem"); + CC1Args.push_back(DriverArgs.MakeArgString( + GCCInstallation.getParentLibPath() + "/../" + + GCCInstallation.getTriple().str() + "/include")); } } @@ -4210,6 +4693,8 @@ SanitizerMask Linux::getSupportedSanitizers() const { Res |= SanitizerKind::Thread; if (IsX86_64 || IsMIPS64 || IsPowerPC64 || IsAArch64) Res |= SanitizerKind::Memory; + if (IsX86_64) + Res |= SanitizerKind::Efficiency; if (IsX86 || IsX86_64) { Res |= SanitizerKind::Function; } @@ -4252,13 +4737,16 @@ Tool *DragonFly::buildLinker() const { return new tools::dragonfly::Linker(*this); } -/// Stub for CUDA toolchain. At the moment we don't have assembler or -/// linker and need toolchain mainly to propagate device-side options -/// to CC1. +/// CUDA toolchain. Our assembler is ptxas, and our "linker" is fatbinary, +/// which isn't properly a linker but nonetheless performs the step of stitching +/// together object files from the assembler into a single blob. CudaToolChain::CudaToolChain(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) - : Linux(D, Triple, Args) {} + : Linux(D, Triple, Args) { + if (CudaInstallation.isValid()) + getProgramPaths().push_back(CudaInstallation.getBinPath()); +} void CudaToolChain::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, @@ -4266,6 +4754,14 @@ CudaToolChain::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, Linux::addClangTargetOptions(DriverArgs, CC1Args); CC1Args.push_back("-fcuda-is-device"); + if (DriverArgs.hasFlag(options::OPT_fcuda_flush_denormals_to_zero, + options::OPT_fno_cuda_flush_denormals_to_zero, false)) + CC1Args.push_back("-fcuda-flush-denormals-to-zero"); + + if (DriverArgs.hasFlag(options::OPT_fcuda_approx_transcendentals, + options::OPT_fno_cuda_approx_transcendentals, false)) + CC1Args.push_back("-fcuda-approx-transcendentals"); + if (DriverArgs.hasArg(options::OPT_nocudalib)) return; @@ -4283,6 +4779,18 @@ CudaToolChain::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, } } +void CudaToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + // Check our CUDA version if we're going to include the CUDA headers. + if (!DriverArgs.hasArg(options::OPT_nocudainc) && + !DriverArgs.hasArg(options::OPT_no_cuda_version_check)) { + StringRef Arch = DriverArgs.getLastArgValue(options::OPT_march_EQ); + assert(!Arch.empty() && "Must have an explicit GPU arch."); + CudaInstallation.CheckCudaVersionSupportsArch(StringToCudaArch(Arch)); + } + Linux::AddCudaIncludeArgs(DriverArgs, CC1Args); +} + llvm::opt::DerivedArgList * CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, const char *BoundArch) const { @@ -4292,7 +4800,7 @@ CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, for (Arg *A : Args) { if (A->getOption().matches(options::OPT_Xarch__)) { // Skip this argument unless the architecture matches BoundArch - if (A->getValue(0) != StringRef(BoundArch)) + if (!BoundArch || A->getValue(0) != StringRef(BoundArch)) continue; unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1)); @@ -4323,10 +4831,21 @@ CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, DAL->append(A); } - DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), BoundArch); + if (BoundArch) { + DAL->eraseArg(options::OPT_march_EQ); + DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), BoundArch); + } return DAL; } +Tool *CudaToolChain::buildAssembler() const { + return new tools::NVPTX::Assembler(*this); +} + +Tool *CudaToolChain::buildLinker() const { + return new tools::NVPTX::Linker(*this); +} + /// XCore tool chain XCoreToolChain::XCoreToolChain(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) @@ -4393,7 +4912,7 @@ void XCoreToolChain::AddCXXStdlibLibArgs(const ArgList &Args, MyriadToolChain::MyriadToolChain(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) - : Generic_GCC(D, Triple, Args) { + : Generic_ELF(D, Triple, Args) { // If a target of 'sparc-myriad-elf' is specified to clang, it wants to use // 'sparc-myriad--elf' (note the unknown OS) as the canonical triple. // This won't work to find gcc. Instead we give the installation detector an @@ -4484,6 +5003,11 @@ Tool *MyriadToolChain::buildLinker() const { WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args) : ToolChain(D, Triple, Args) { + + assert(Triple.isArch32Bit() != Triple.isArch64Bit()); + getFilePaths().push_back( + getDriver().SysRoot + "/lib" + (Triple.isArch32Bit() ? "32" : "64")); + // Use LLD by default. DefaultLinker = "lld"; } @@ -4519,6 +5043,29 @@ void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs, CC1Args.push_back("-fuse-init-array"); } +ToolChain::RuntimeLibType WebAssembly::GetDefaultRuntimeLibType() const { + return ToolChain::RLT_CompilerRT; +} + +ToolChain::CXXStdlibType WebAssembly::GetCXXStdlibType(const ArgList &Args) const { + return ToolChain::CST_Libcxx; +} + +void WebAssembly::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (!DriverArgs.hasArg(options::OPT_nostdinc)) + addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include"); +} + +void WebAssembly::AddClangCXXStdlibIncludeArgs( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + if (!DriverArgs.hasArg(options::OPT_nostdlibinc) && + !DriverArgs.hasArg(options::OPT_nostdincxx)) + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/include/c++/v1"); +} + Tool *WebAssembly::buildLinker() const { return new tools::wasm::Linker(*this); } @@ -4528,12 +5075,12 @@ PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) if (Args.hasArg(options::OPT_static)) D.Diag(diag::err_drv_unsupported_opt_for_target) << "-static" << "PS4"; - // Determine where to find the PS4 libraries. We use SCE_PS4_SDK_DIR + // Determine where to find the PS4 libraries. We use SCE_ORBIS_SDK_DIR // if it exists; otherwise use the driver's installation path, which // should be <SDK_DIR>/host_tools/bin. SmallString<512> PS4SDKDir; - if (const char *EnvValue = getenv("SCE_PS4_SDK_DIR")) { + if (const char *EnvValue = getenv("SCE_ORBIS_SDK_DIR")) { if (!llvm::sys::fs::exists(EnvValue)) getDriver().Diag(clang::diag::warn_drv_ps4_sdk_dir) << EnvValue; PS4SDKDir = EnvValue; |
