diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp | 1582 |
1 files changed, 1149 insertions, 433 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp index 15e36a1..b02430e 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 -------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,6 +10,7 @@ #include "ToolChains.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Version.h" +#include "clang/Basic/VirtualFileSystem.h" #include "clang/Config/config.h" // for GCC_INSTALL_PREFIX #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" @@ -24,6 +25,7 @@ #include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" +#include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" @@ -65,6 +67,8 @@ bool MachO::HasNativeLLVMSupport() const { return true; } /// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0. ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const { + if (isTargetWatchOSBased()) + return ObjCRuntime(ObjCRuntime::WatchOS, TargetVersion); if (isTargetIOSBased()) return ObjCRuntime(ObjCRuntime::iOS, TargetVersion); if (isNonFragile) @@ -74,7 +78,9 @@ ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const { /// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2. bool Darwin::hasBlocksRuntime() const { - if (isTargetIOSBased()) + if (isTargetWatchOSBased()) + return true; + else if (isTargetIOSBased()) return !isIPhoneOSVersionLT(3, 2); else { assert(isTargetMacOS() && "unexpected darwin target"); @@ -104,10 +110,10 @@ static const char *ArmMachOArchName(StringRef Arch) { } static const char *ArmMachOArchNameCPU(StringRef CPU) { - unsigned ArchKind = llvm::ARMTargetParser::parseCPUArch(CPU); + unsigned ArchKind = llvm::ARM::parseCPUArch(CPU); if (ArchKind == llvm::ARM::AK_INVALID) return nullptr; - StringRef Arch = llvm::ARMTargetParser::getArchName(ArchKind); + StringRef Arch = llvm::ARM::getArchName(ArchKind); // FIXME: Make sure this MachO triple mangling is really necessary. // ARMv5* normalises to ARMv5. @@ -142,7 +148,7 @@ StringRef MachO::getMachOArchName(const ArgList &Args) const { return "arm64"; case llvm::Triple::thumb: - case llvm::Triple::arm: { + case llvm::Triple::arm: if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) if (const char *Arch = ArmMachOArchName(A->getValue())) return Arch; @@ -153,7 +159,6 @@ StringRef MachO::getMachOArchName(const ArgList &Args) const { return "arm"; } - } } Darwin::~Darwin() {} @@ -177,7 +182,14 @@ std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args, return Triple.getTriple(); SmallString<16> Str; - Str += isTargetIOSBased() ? "ios" : "macosx"; + if (isTargetWatchOSBased()) + Str += "watchos"; + else if (isTargetTvOSBased()) + Str += "tvos"; + else if (isTargetIOSBased()) + Str += "ios"; + else + Str += "macosx"; Str += getTargetVersion().getAsString(); Triple.setOSName(Str); @@ -216,16 +228,17 @@ DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple, : Darwin(D, Triple, Args) {} void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const { - // For iOS, 64-bit, promote certain warnings to errors. - if (!isTargetMacOS() && getTriple().isArch64Bit()) { + // For modern targets, promote certain warnings to errors. + if (isTargetWatchOSBased() || getTriple().isArch64Bit()) { // Always enable -Wdeprecated-objc-isa-usage and promote it // to an error. CC1Args.push_back("-Wdeprecated-objc-isa-usage"); CC1Args.push_back("-Werror=deprecated-objc-isa-usage"); - // Also error about implicit function declarations, as that - // can impact calling conventions. - CC1Args.push_back("-Werror=implicit-function-declaration"); + // For iOS and watchOS, also error about implicit function declarations, + // as that can impact calling conventions. + if (!isTargetMacOS()) + CC1Args.push_back("-Werror=implicit-function-declaration"); } } @@ -253,7 +266,15 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args, llvm::sys::path::remove_filename(P); // 'bin' llvm::sys::path::append(P, "lib", "arc", "libarclite_"); // Mash in the platform. - if (isTargetIOSSimulator()) + if (isTargetWatchOSSimulator()) + P += "watchsimulator"; + else if (isTargetWatchOS()) + P += "watchos"; + else if (isTargetTvOSSimulator()) + P += "appletvsimulator"; + else if (isTargetTvOS()) + P += "appletvos"; + else if (isTargetIOSSimulator()) P += "iphonesimulator"; else if (isTargetIPhoneOS()) P += "iphoneos"; @@ -276,7 +297,7 @@ void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs, // For now, allow missing resource libraries to support developers who may // not have compiler-rt checked out or integrated into their build (unless // we explicitly force linking with this library). - if (AlwaysLink || llvm::sys::fs::exists(P)) + if (AlwaysLink || getVFS().exists(P)) CmdArgs.push_back(Args.MakeArgString(P)); // Adding the rpaths might negatively interact when other rpaths are involved, @@ -300,23 +321,38 @@ void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs, void Darwin::addProfileRTLibs(const ArgList &Args, ArgStringList &CmdArgs) const { - if (!(Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, - false) || - Args.hasArg(options::OPT_fprofile_generate) || - Args.hasArg(options::OPT_fprofile_generate_EQ) || - Args.hasArg(options::OPT_fprofile_instr_generate) || - Args.hasArg(options::OPT_fprofile_instr_generate_EQ) || - Args.hasArg(options::OPT_fcreate_profile) || - Args.hasArg(options::OPT_coverage))) - return; + 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 (isTargetIOSBased()) - AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_ios.a", - /*AlwaysLink*/ true); - else - AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_osx.a", - /*AlwaysLink*/ true); + 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, + /*AlwaysLink*/ true); + return; } void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args, @@ -327,6 +363,7 @@ void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args, // Sanitizer runtime libraries requires C++. AddCXXStdlibLibArgs(Args, CmdArgs); } + // ASan is not supported on watchOS. assert(isTargetMacOS() || isTargetIOSSimulator()); StringRef OS = isTargetMacOS() ? "osx" : "iossim"; AddLinkRuntimeLib( @@ -374,13 +411,21 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, AddLinkSanitizerLibArgs(Args, CmdArgs, "asan"); if (Sanitize.needsUbsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan"); + if (Sanitize.needsTsanRt()) + AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan"); // Otherwise link libSystem, then the dynamic runtime library, and finally any // target specific static runtime library. CmdArgs.push_back("-lSystem"); // Select the dynamic runtime library and the target specific static library. - if (isTargetIOSBased()) { + if (isTargetWatchOSBased()) { + // We currently always need a static runtime library for watchOS. + AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.watchos.a"); + } else if (isTargetTvOSBased()) { + // We currently always need a static runtime library for tvOS. + AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.tvos.a"); + } else if (isTargetIOSBased()) { // If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1, // it never went into the SDK. // Linking against libgcc_s.1 isn't needed for iOS 5.0+ @@ -425,13 +470,13 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { // isysroot. if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { // Warn if the path does not exist. - if (!llvm::sys::fs::exists(A->getValue())) + if (!getVFS().exists(A->getValue())) getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue(); } else { if (char *env = ::getenv("SDKROOT")) { // We only use this value as the default if it is an absolute path, // exists, and it is not the root path. - if (llvm::sys::path::is_absolute(env) && llvm::sys::fs::exists(env) && + if (llvm::sys::path::is_absolute(env) && getVFS().exists(env) && StringRef(env) != "/") { Args.append(Args.MakeSeparateArg( nullptr, Opts.getOption(options::OPT_isysroot), env)); @@ -441,25 +486,46 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ); Arg *iOSVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ); + Arg *TvOSVersion = Args.getLastArg(options::OPT_mtvos_version_min_EQ); + Arg *WatchOSVersion = Args.getLastArg(options::OPT_mwatchos_version_min_EQ); - if (OSXVersion && iOSVersion) { + if (OSXVersion && (iOSVersion || TvOSVersion || WatchOSVersion)) { + getDriver().Diag(diag::err_drv_argument_not_allowed_with) + << OSXVersion->getAsString(Args) + << (iOSVersion ? iOSVersion : + TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args); + iOSVersion = TvOSVersion = WatchOSVersion = nullptr; + } else if (iOSVersion && (TvOSVersion || WatchOSVersion)) { getDriver().Diag(diag::err_drv_argument_not_allowed_with) - << OSXVersion->getAsString(Args) << iOSVersion->getAsString(Args); - iOSVersion = nullptr; - } else if (!OSXVersion && !iOSVersion) { + << iOSVersion->getAsString(Args) + << (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args); + TvOSVersion = WatchOSVersion = nullptr; + } else if (TvOSVersion && WatchOSVersion) { + getDriver().Diag(diag::err_drv_argument_not_allowed_with) + << TvOSVersion->getAsString(Args) + << WatchOSVersion->getAsString(Args); + WatchOSVersion = nullptr; + } else if (!OSXVersion && !iOSVersion && !TvOSVersion && !WatchOSVersion) { // If no deployment target was specified on the command line, check for // environment defines. std::string OSXTarget; std::string iOSTarget; + std::string TvOSTarget; + std::string WatchOSTarget; + if (char *env = ::getenv("MACOSX_DEPLOYMENT_TARGET")) OSXTarget = env; if (char *env = ::getenv("IPHONEOS_DEPLOYMENT_TARGET")) iOSTarget = env; + if (char *env = ::getenv("TVOS_DEPLOYMENT_TARGET")) + TvOSTarget = env; + if (char *env = ::getenv("WATCHOS_DEPLOYMENT_TARGET")) + WatchOSTarget = env; // If there is no command-line argument to specify the Target version and // no environment variable defined, see if we can set the default based // on -isysroot. - if (iOSTarget.empty() && OSXTarget.empty() && + if (OSXTarget.empty() && iOSTarget.empty() && WatchOSTarget.empty() && Args.hasArg(options::OPT_isysroot)) { if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { StringRef isysroot = A->getValue(); @@ -479,6 +545,12 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { iOSTarget = Version; else if (SDK.startswith("MacOSX")) OSXTarget = Version; + else if (SDK.startswith("WatchOS") || + SDK.startswith("WatchSimulator")) + WatchOSTarget = Version; + else if (SDK.startswith("AppleTVOS") || + SDK.startswith("AppleTVSimulator")) + TvOSTarget = Version; } } } @@ -486,7 +558,8 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { // If no OSX or iOS target has been specified, try to guess platform // from arch name and compute the version from the triple. - if (OSXTarget.empty() && iOSTarget.empty()) { + if (OSXTarget.empty() && iOSTarget.empty() && TvOSTarget.empty() && + WatchOSTarget.empty()) { StringRef MachOArchName = getMachOArchName(Args); unsigned Major, Minor, Micro; if (MachOArchName == "armv7" || MachOArchName == "armv7s" || @@ -494,6 +567,10 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { getTriple().getiOSVersion(Major, Minor, Micro); llvm::raw_string_ostream(iOSTarget) << Major << '.' << Minor << '.' << Micro; + } else if (MachOArchName == "armv7k") { + getTriple().getWatchOSVersion(Major, Minor, Micro); + llvm::raw_string_ostream(WatchOSTarget) << Major << '.' << Minor << '.' + << Micro; } else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" && MachOArchName != "armv7em") { if (!getTriple().getMacOSXVersion(Major, Minor, Micro)) { @@ -505,15 +582,32 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { } } + // Do not allow conflicts with the watchOS target. + if (!WatchOSTarget.empty() && (!iOSTarget.empty() || !TvOSTarget.empty())) { + getDriver().Diag(diag::err_drv_conflicting_deployment_targets) + << "WATCHOS_DEPLOYMENT_TARGET" + << (!iOSTarget.empty() ? "IPHONEOS_DEPLOYMENT_TARGET" : + "TVOS_DEPLOYMENT_TARGET"); + } + + // Do not allow conflicts with the tvOS target. + if (!TvOSTarget.empty() && !iOSTarget.empty()) { + getDriver().Diag(diag::err_drv_conflicting_deployment_targets) + << "TVOS_DEPLOYMENT_TARGET" + << "IPHONEOS_DEPLOYMENT_TARGET"; + } + // Allow conflicts among OSX and iOS for historical reasons, but choose the // default platform. - if (!OSXTarget.empty() && !iOSTarget.empty()) { + if (!OSXTarget.empty() && (!iOSTarget.empty() || + !WatchOSTarget.empty() || + !TvOSTarget.empty())) { if (getTriple().getArch() == llvm::Triple::arm || getTriple().getArch() == llvm::Triple::aarch64 || getTriple().getArch() == llvm::Triple::thumb) OSXTarget = ""; else - iOSTarget = ""; + iOSTarget = WatchOSTarget = TvOSTarget = ""; } if (!OSXTarget.empty()) { @@ -524,6 +618,14 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { const Option O = Opts.getOption(options::OPT_miphoneos_version_min_EQ); iOSVersion = Args.MakeJoinedArg(nullptr, O, iOSTarget); Args.append(iOSVersion); + } else if (!TvOSTarget.empty()) { + const Option O = Opts.getOption(options::OPT_mtvos_version_min_EQ); + TvOSVersion = Args.MakeJoinedArg(nullptr, O, TvOSTarget); + Args.append(TvOSVersion); + } else if (!WatchOSTarget.empty()) { + const Option O = Opts.getOption(options::OPT_mwatchos_version_min_EQ); + WatchOSVersion = Args.MakeJoinedArg(nullptr, O, WatchOSTarget); + Args.append(WatchOSVersion); } } @@ -532,6 +634,10 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { Platform = MacOS; else if (iOSVersion) Platform = IPhoneOS; + else if (TvOSVersion) + Platform = TvOS; + else if (WatchOSVersion) + Platform = WatchOS; else llvm_unreachable("Unable to infer Darwin variant"); @@ -539,7 +645,8 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { unsigned Major, Minor, Micro; bool HadExtra; if (Platform == MacOS) { - assert(!iOSVersion && "Unknown target platform!"); + assert((!iOSVersion && !TvOSVersion && !WatchOSVersion) && + "Unknown target platform!"); if (!Driver::GetReleaseVersion(OSXVersion->getValue(), Major, Minor, Micro, HadExtra) || HadExtra || Major != 10 || Minor >= 100 || Micro >= 100) @@ -552,6 +659,18 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { HadExtra || Major >= 10 || 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) + getDriver().Diag(diag::err_drv_invalid_version_number) + << TvOSVersion->getAsString(Args); + } else if (Platform == WatchOS) { + if (!Driver::GetReleaseVersion(WatchOSVersion->getValue(), Major, Minor, + Micro, HadExtra) || HadExtra || + Major >= 10 || Minor >= 100 || Micro >= 100) + getDriver().Diag(diag::err_drv_invalid_version_number) + << WatchOSVersion->getAsString(Args); } else llvm_unreachable("unknown kind of Darwin platform"); @@ -559,6 +678,12 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { if (iOSVersion && (getTriple().getArch() == llvm::Triple::x86 || getTriple().getArch() == llvm::Triple::x86_64)) Platform = IPhoneOSSimulator; + if (TvOSVersion && (getTriple().getArch() == llvm::Triple::x86 || + getTriple().getArch() == llvm::Triple::x86_64)) + Platform = TvOSSimulator; + if (WatchOSVersion && (getTriple().getArch() == llvm::Triple::x86 || + getTriple().getArch() == llvm::Triple::x86_64)) + Platform = WatchOSSimulator; setTarget(Platform, Major, Minor, Micro); } @@ -572,7 +697,7 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args, CmdArgs.push_back("-lc++"); break; - case ToolChain::CST_Libstdcxx: { + 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 @@ -583,10 +708,10 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args, SmallString<128> P(A->getValue()); llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib"); - if (!llvm::sys::fs::exists(P)) { + if (!getVFS().exists(P)) { llvm::sys::path::remove_filename(P); llvm::sys::path::append(P, "libstdc++.6.dylib"); - if (llvm::sys::fs::exists(P)) { + if (getVFS().exists(P)) { CmdArgs.push_back(Args.MakeArgString(P)); return; } @@ -596,8 +721,8 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args, // Otherwise, look in the root. // FIXME: This should be removed someday when we don't have to care about // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist. - if (!llvm::sys::fs::exists("/usr/lib/libstdc++.dylib") && - llvm::sys::fs::exists("/usr/lib/libstdc++.6.dylib")) { + if (!getVFS().exists("/usr/lib/libstdc++.dylib") && + getVFS().exists("/usr/lib/libstdc++.6.dylib")) { CmdArgs.push_back("/usr/lib/libstdc++.6.dylib"); return; } @@ -606,7 +731,6 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args, CmdArgs.push_back("-lstdc++"); break; } - } } void DarwinClang::AddCCKextLibArgs(const ArgList &Args, @@ -620,17 +744,19 @@ void DarwinClang::AddCCKextLibArgs(const ArgList &Args, llvm::sys::path::append(P, "lib", "darwin"); // Use the newer cc_kext for iOS ARM after 6.0. - if (!isTargetIPhoneOS() || isTargetIOSSimulator() || - getTriple().getArch() == llvm::Triple::aarch64 || - !isIPhoneOSVersionLT(6, 0)) { - llvm::sys::path::append(P, "libclang_rt.cc_kext.a"); + if (isTargetWatchOS()) { + llvm::sys::path::append(P, "libclang_rt.cc_kext_watchos.a"); + } else if (isTargetTvOS()) { + llvm::sys::path::append(P, "libclang_rt.cc_kext_tvos.a"); + } else if (isTargetIPhoneOS()) { + llvm::sys::path::append(P, "libclang_rt.cc_kext_ios.a"); } else { - llvm::sys::path::append(P, "libclang_rt.cc_kext_ios5.a"); + llvm::sys::path::append(P, "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. - if (llvm::sys::fs::exists(P)) + if (getVFS().exists(P)) CmdArgs.push_back(Args.MakeArgString(P)); } @@ -856,7 +982,7 @@ void MachO::AddLinkRuntimeLibArgs(const ArgList &Args, // { hard-float, soft-float } llvm::SmallString<32> CompilerRT = StringRef("libclang_rt."); CompilerRT += - tools::arm::getARMFloatABI(getDriver(), Args, getTriple()) == "hard" + (tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard) ? "hard" : "soft"; CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic.a" : "_static.a"; @@ -883,8 +1009,9 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, // FIXME: It would be far better to avoid inserting those -static arguments, // but we can't check the deployment target in the translation code until // it is set here. - if (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0)) { - for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie;) { + if (isTargetWatchOSBased() || + (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0))) { + for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) { Arg *A = *it; ++it; if (A->getOption().getID() != options::OPT_mkernel && @@ -900,7 +1027,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))) && + (isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0)) || + isTargetWatchOSBased()) && !Args.getLastArg(options::OPT_stdlib_EQ)) DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_stdlib_EQ), "libc++"); @@ -933,10 +1061,14 @@ bool MachO::UseDwarfDebugFlags() const { return false; } -bool Darwin::UseSjLjExceptions() const { +bool Darwin::UseSjLjExceptions(const ArgList &Args) const { // Darwin uses SjLj exceptions on ARM. - return (getTriple().getArch() == llvm::Triple::arm || - getTriple().getArch() == llvm::Triple::thumb); + if (getTriple().getArch() != llvm::Triple::arm && + getTriple().getArch() != llvm::Triple::thumb) + return false; + + // Only watchOS uses the new DWARF/Compact unwinding method. + return !isTargetWatchOS(); } bool MachO::isPICDefault() const { return true; } @@ -957,7 +1089,15 @@ void Darwin::addMinVersionArgs(const ArgList &Args, ArgStringList &CmdArgs) const { VersionTuple TargetVersion = getTargetVersion(); - if (isTargetIOSSimulator()) + if (isTargetWatchOS()) + CmdArgs.push_back("-watchos_version_min"); + else if (isTargetWatchOSSimulator()) + CmdArgs.push_back("-watchos_simulator_version_min"); + else if (isTargetTvOS()) + CmdArgs.push_back("-tvos_version_min"); + else if (isTargetTvOSSimulator()) + CmdArgs.push_back("-tvos_simulator_version_min"); + else if (isTargetIOSSimulator()) CmdArgs.push_back("-ios_simulator_version_min"); else if (isTargetIOSBased()) CmdArgs.push_back("-iphoneos_version_min"); @@ -974,7 +1114,9 @@ void Darwin::addStartObjectFileArgs(const ArgList &Args, // Derived from startfile spec. if (Args.hasArg(options::OPT_dynamiclib)) { // Derived from darwin_dylib1 spec. - if (isTargetIOSSimulator()) { + if (isTargetWatchOSBased()) { + ; // watchOS does not need dylib1.o. + } else if (isTargetIOSSimulator()) { ; // iOS simulator does not need dylib1.o. } else if (isTargetIPhoneOS()) { if (isIPhoneOSVersionLT(3, 1)) @@ -989,7 +1131,9 @@ void Darwin::addStartObjectFileArgs(const ArgList &Args, if (Args.hasArg(options::OPT_bundle)) { if (!Args.hasArg(options::OPT_static)) { // Derived from darwin_bundle1 spec. - if (isTargetIOSSimulator()) { + if (isTargetWatchOSBased()) { + ; // watchOS does not need bundle1.o. + } else if (isTargetIOSSimulator()) { ; // iOS simulator does not need bundle1.o. } else if (isTargetIPhoneOS()) { if (isIPhoneOSVersionLT(3, 1)) @@ -1024,7 +1168,9 @@ void Darwin::addStartObjectFileArgs(const ArgList &Args, CmdArgs.push_back("-lcrt0.o"); } else { // Derived from darwin_crt1 spec. - if (isTargetIOSSimulator()) { + if (isTargetWatchOSBased()) { + ; // watchOS does not need crt1.o. + } else if (isTargetIOSSimulator()) { ; // iOS simulator does not need crt1.o. } else if (isTargetIPhoneOS()) { if (getArch() == llvm::Triple::aarch64) @@ -1049,6 +1195,7 @@ void Darwin::addStartObjectFileArgs(const ArgList &Args, } if (!isTargetIPhoneOS() && Args.hasArg(options::OPT_shared_libgcc) && + !isTargetWatchOS() && isMacosxVersionLT(10, 5)) { const char *Str = Args.MakeArgString(GetFilePath("crt3.o")); CmdArgs.push_back(Str); @@ -1058,7 +1205,8 @@ void Darwin::addStartObjectFileArgs(const ArgList &Args, bool Darwin::SupportsObjCGC() const { return isTargetMacOS(); } void Darwin::CheckObjCARC() const { - if (isTargetIOSBased() || (isTargetMacOS() && !isMacosxVersionLT(10, 6))) + if (isTargetIOSBased() || isTargetWatchOSBased() || + (isTargetMacOS() && !isMacosxVersionLT(10, 6))) return; getDriver().Diag(diag::err_arc_unsupported_on_toolchain); } @@ -1071,6 +1219,7 @@ SanitizerMask Darwin::getSupportedSanitizers() const { if (!isMacosxVersionLT(10, 9)) Res |= SanitizerKind::Vptr; Res |= SanitizerKind::SafeStack; + Res |= SanitizerKind::Thread; } return Res; } @@ -1170,7 +1319,8 @@ static llvm::StringRef getGCCToolchainDir(const ArgList &Args) { /// necessary because the driver doesn't store the final version of the target /// triple. void Generic_GCC::GCCInstallationDetector::init( - const Driver &D, const llvm::Triple &TargetTriple, const ArgList &Args) { + const llvm::Triple &TargetTriple, const ArgList &Args, + ArrayRef<std::string> ExtraTripleAliases) { llvm::Triple BiarchVariantTriple = TargetTriple.isArch32Bit() ? TargetTriple.get64BitArchVariant() : TargetTriple.get32BitArchVariant(); @@ -1212,20 +1362,22 @@ void Generic_GCC::GCCInstallationDetector::init( // installation available. GCC installs are ranked by version number. Version = GCCVersion::Parse("0.0.0"); for (const std::string &Prefix : Prefixes) { - if (!llvm::sys::fs::exists(Prefix)) + if (!D.getVFS().exists(Prefix)) continue; - for (const StringRef Suffix : CandidateLibDirs) { + for (StringRef Suffix : CandidateLibDirs) { const std::string LibDir = Prefix + Suffix.str(); - if (!llvm::sys::fs::exists(LibDir)) + if (!D.getVFS().exists(LibDir)) continue; - for (const StringRef Candidate : CandidateTripleAliases) + for (StringRef Candidate : ExtraTripleAliases) // Try these first. + ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate); + for (StringRef Candidate : CandidateTripleAliases) ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate); } - for (const StringRef Suffix : CandidateBiarchLibDirs) { + for (StringRef Suffix : CandidateBiarchLibDirs) { const std::string LibDir = Prefix + Suffix.str(); - if (!llvm::sys::fs::exists(LibDir)) + if (!D.getVFS().exists(LibDir)) continue; - for (const StringRef Candidate : CandidateBiarchTripleAliases) + for (StringRef Candidate : CandidateBiarchTripleAliases) ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate, /*NeedsBiarchSuffix=*/ true); } @@ -1300,8 +1452,9 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { "i586-linux-gnu"}; static const char *const MIPSLibDirs[] = {"/lib"}; - static const char *const MIPSTriples[] = { - "mips-linux-gnu", "mips-mti-linux-gnu", "mips-img-linux-gnu"}; + static const char *const MIPSTriples[] = {"mips-linux-gnu", "mips-mti-linux", + "mips-mti-linux-gnu", + "mips-img-linux-gnu"}; static const char *const MIPSELLibDirs[] = {"/lib"}; static const char *const MIPSELTriples[] = { "mipsel-linux-gnu", "mipsel-linux-android", "mips-img-linux-gnu"}; @@ -1340,9 +1493,20 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { "s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu", "s390x-suse-linux", "s390x-redhat-linux"}; + // Solaris. + static const char *const SolarisSPARCLibDirs[] = {"/gcc"}; + static const char *const SolarisSPARCTriples[] = {"sparc-sun-solaris2.11", + "i386-pc-solaris2.11"}; + using std::begin; using std::end; + if (TargetTriple.getOS() == llvm::Triple::Solaris) { + LibDirs.append(begin(SolarisSPARCLibDirs), end(SolarisSPARCLibDirs)); + TripleAliases.append(begin(SolarisSPARCTriples), end(SolarisSPARCTriples)); + return; + } + switch (TargetTriple.getArch()) { case llvm::Triple::aarch64: LibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs)); @@ -1436,6 +1600,7 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { TripleAliases.append(begin(PPC64LETriples), end(PPC64LETriples)); break; case llvm::Triple::sparc: + case llvm::Triple::sparcel: LibDirs.append(begin(SPARCv8LibDirs), end(SPARCv8LibDirs)); TripleAliases.append(begin(SPARCv8Triples), end(SPARCv8Triples)); BiarchLibDirs.append(begin(SPARCv9LibDirs), end(SPARCv9LibDirs)); @@ -1451,7 +1616,6 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { LibDirs.append(begin(SystemZLibDirs), end(SystemZLibDirs)); TripleAliases.append(begin(SystemZTriples), end(SystemZTriples)); break; - default: // By default, just rely on the standard lib directories and the original // triple. @@ -1467,15 +1631,83 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { BiarchTripleAliases.push_back(BiarchTriple.str()); } +// \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; + + if (Args.hasArg(options::OPT_cuda_path_EQ)) + CudaPathCandidates.push_back( + Args.getLastArgValue(options::OPT_cuda_path_EQ)); + else { + CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda"); + CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda-7.5"); + CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda-7.0"); + } + + for (const auto &CudaPath : CudaPathCandidates) { + if (CudaPath.empty() || !D.getVFS().exists(CudaPath)) + continue; + + CudaInstallPath = CudaPath; + CudaIncludePath = CudaInstallPath + "/include"; + CudaLibDevicePath = CudaInstallPath + "/nvvm/libdevice"; + CudaLibPath = + CudaInstallPath + (TargetTriple.isArch64Bit() ? "/lib64" : "/lib"); + + if (!(D.getVFS().exists(CudaIncludePath) && + D.getVFS().exists(CudaLibPath) && + D.getVFS().exists(CudaLibDevicePath))) + continue; + + std::error_code EC; + for (llvm::sys::fs::directory_iterator LI(CudaLibDevicePath, EC), LE; + !EC && LI != LE; LI = LI.increment(EC)) { + StringRef FilePath = LI->path(); + StringRef FileName = llvm::sys::path::filename(FilePath); + // Process all bitcode filenames that look like libdevice.compute_XX.YY.bc + const StringRef LibDeviceName = "libdevice."; + if (!(FileName.startswith(LibDeviceName) && FileName.endswith(".bc"))) + continue; + StringRef GpuArch = FileName.slice( + LibDeviceName.size(), FileName.find('.', LibDeviceName.size())); + CudaLibDeviceMap[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; + } else if (GpuArch == "compute_30") { + CudaLibDeviceMap["sm_30"] = FilePath; + CudaLibDeviceMap["sm_32"] = FilePath; + } else if (GpuArch == "compute_35") { + CudaLibDeviceMap["sm_35"] = FilePath; + CudaLibDeviceMap["sm_37"] = FilePath; + } + } + + IsValid = true; + break; + } +} + +void Generic_GCC::CudaInstallationDetector::print(raw_ostream &OS) const { + if (isValid()) + OS << "Found CUDA installation: " << CudaInstallPath << "\n"; +} + namespace { // Filter to remove Multilibs that don't exist as a suffix to Path class FilterNonExistent { StringRef Base; + vfs::FileSystem &VFS; public: - FilterNonExistent(StringRef Base) : Base(Base) {} + FilterNonExistent(StringRef Base, vfs::FileSystem &VFS) + : Base(Base), VFS(VFS) {} bool operator()(const Multilib &M) { - return !llvm::sys::fs::exists(Base + M.gccSuffix() + "/crtbegin.o"); + return !VFS.exists(Base + M.gccSuffix() + "/crtbegin.o"); } }; } // end anonymous namespace @@ -1515,6 +1747,7 @@ static bool isMicroMips(const ArgList &Args) { return A && A->getOption().matches(options::OPT_mmicromips); } +namespace { struct DetectedMultilibs { /// The set of multilibs that the detected installation supports. MultilibSet Multilibs; @@ -1526,13 +1759,15 @@ struct DetectedMultilibs { /// targeting the non-default multilib. Otherwise, it is empty. llvm::Optional<Multilib> BiarchSibling; }; +} // end anonymous namespace static Multilib makeMultilib(StringRef commonSuffix) { return Multilib(commonSuffix, commonSuffix, commonSuffix); } -static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path, - const ArgList &Args, DetectedMultilibs &Result) { +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 @@ -1558,7 +1793,7 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path, // /usr // /lib <= crt*.o files compiled with '-mips32' - FilterNonExistent NonExistent(Path); + FilterNonExistent NonExistent(Path, D.getVFS()); // Check for FSF toolchain multilibs MultilibSet FSFMipsMultilibs; @@ -1636,6 +1871,32 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path, }); } + // 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; { @@ -1754,7 +2015,7 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path, addMultilibFlag(isMips16(Args), "mips16", Flags); addMultilibFlag(CPUName == "mips32", "march=mips32", Flags); addMultilibFlag(CPUName == "mips32r2" || CPUName == "mips32r3" || - CPUName == "mips32r5", + CPUName == "mips32r5" || CPUName == "p5600", "march=mips32r2", Flags); addMultilibFlag(CPUName == "mips32r6", "march=mips32r6", Flags); addMultilibFlag(CPUName == "mips64", "march=mips64", Flags); @@ -1772,7 +2033,7 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path, addMultilibFlag(isMipsEL(TargetArch), "EL", Flags); addMultilibFlag(!isMipsEL(TargetArch), "EB", Flags); - if (TargetTriple.getEnvironment() == llvm::Triple::Android) { + if (TargetTriple.isAndroid()) { // Select Android toolchain. It's the only choice in that case. if (AndroidMipsMultilibs.select(Flags, Result.SelectedMultilib)) { Result.Multilibs = AndroidMipsMultilibs; @@ -1781,6 +2042,16 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path, return false; } + 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; + } + if (TargetTriple.getVendor() == llvm::Triple::ImaginationTechnologies && TargetTriple.getOS() == llvm::Triple::Linux && TargetTriple.getEnvironment() == llvm::Triple::GNU) { @@ -1823,11 +2094,11 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path, return false; } -static bool findBiarchMultilibs(const llvm::Triple &TargetTriple, +static bool findBiarchMultilibs(const Driver &D, + const llvm::Triple &TargetTriple, StringRef Path, const ArgList &Args, bool NeedsBiarchSuffix, DetectedMultilibs &Result) { - // Some versions of SUSE and Fedora on ppc64 put 32-bit libs // in what would normally be GCCInstallPath and put the 64-bit // libs in a subdirectory named 64. The simple logic we follow is that @@ -1855,7 +2126,7 @@ static bool findBiarchMultilibs(const llvm::Triple &TargetTriple, .flag("-m64") .flag("+mx32"); - FilterNonExistent NonExistent(Path); + FilterNonExistent NonExistent(Path, D.getVFS()); // Determine default multilib from: 32, 64, x32 // Also handle cases such as 64 on 32, 32 on 64, etc. @@ -1907,6 +2178,56 @@ static bool findBiarchMultilibs(const llvm::Triple &TargetTriple, return true; } +void Generic_GCC::GCCInstallationDetector::scanLibDirForGCCTripleSolaris( + const llvm::Triple &TargetArch, const llvm::opt::ArgList &Args, + const std::string &LibDir, StringRef CandidateTriple, + bool NeedsBiarchSuffix) { + // Solaris is a special case. The GCC installation is under + // /usr/gcc/<major>.<minor>/lib/gcc/<triple>/<major>.<minor>.<patch>/, so we + // need to iterate twice. + std::error_code EC; + for (vfs::directory_iterator LI = D.getVFS().dir_begin(LibDir, EC), LE; + !EC && LI != LE; LI = LI.increment(EC)) { + StringRef VersionText = llvm::sys::path::filename(LI->getName()); + GCCVersion CandidateVersion = GCCVersion::Parse(VersionText); + + if (CandidateVersion.Major != -1) // Filter obviously bad entries. + if (!CandidateGCCInstallPaths.insert(LI->getName()).second) + continue; // Saw this path before; no need to look at it again. + if (CandidateVersion.isOlderThan(4, 1, 1)) + continue; + if (CandidateVersion <= Version) + continue; + + GCCInstallPath = + LibDir + "/" + VersionText.str() + "/lib/gcc/" + CandidateTriple.str(); + if (!D.getVFS().exists(GCCInstallPath)) + continue; + + // If we make it here there has to be at least one GCC version, let's just + // use the latest one. + std::error_code EEC; + for (vfs::directory_iterator + LLI = D.getVFS().dir_begin(GCCInstallPath, EEC), + LLE; + !EEC && LLI != LLE; LLI = LLI.increment(EEC)) { + + StringRef SubVersionText = llvm::sys::path::filename(LLI->getName()); + GCCVersion CandidateSubVersion = GCCVersion::Parse(SubVersionText); + + if (CandidateSubVersion > Version) + Version = CandidateSubVersion; + } + + GCCTriple.setTriple(CandidateTriple); + + GCCInstallPath += "/" + Version.Text; + GCCParentLibPath = GCCInstallPath + "/../../../../"; + + IsValid = true; + } +} + void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( const llvm::Triple &TargetTriple, const ArgList &Args, const std::string &LibDir, StringRef CandidateTriple, @@ -1914,41 +2235,48 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( llvm::Triple::ArchType TargetArch = TargetTriple.getArch(); // There are various different suffixes involving the triple we // check for. We also record what is necessary to walk from each back - // up to the lib directory. - const std::string LibSuffixes[] = { - "/gcc/" + CandidateTriple.str(), + // up to the lib directory. Specifically, the number of "up" steps + // in the second half of each row is 1 + the number of path separators + // in the first half. + const std::string LibAndInstallSuffixes[][2] = { + {"/gcc/" + CandidateTriple.str(), "/../../.."}, + // Debian puts cross-compilers in gcc-cross - "/gcc-cross/" + CandidateTriple.str(), - "/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(), + {"/gcc-cross/" + CandidateTriple.str(), "/../../.."}, + + {"/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(), + "/../../../.."}, // The Freescale PPC SDK has the gcc libraries in // <sysroot>/usr/lib/<triple>/x.y.z so have a look there as well. - "/" + CandidateTriple.str(), + {"/" + CandidateTriple.str(), "/../.."}, // Ubuntu has a strange mis-matched pair of triples that this happens to // match. // FIXME: It may be worthwhile to generalize this and look for a second // triple. - "/i386-linux-gnu/gcc/" + CandidateTriple.str()}; - const std::string InstallSuffixes[] = { - "/../../..", // gcc/ - "/../../..", // gcc-cross/ - "/../../../..", // <triple>/gcc/ - "/../..", // <triple>/ - "/../../../.." // i386-linux-gnu/gcc/<triple>/ - }; + {"/i386-linux-gnu/gcc/" + CandidateTriple.str(), "/../../../.."}}; + + if (TargetTriple.getOS() == llvm::Triple::Solaris) { + scanLibDirForGCCTripleSolaris(TargetTriple, Args, LibDir, CandidateTriple, + NeedsBiarchSuffix); + return; + } + // Only look at the final, weird Ubuntu suffix for i386-linux-gnu. - const unsigned NumLibSuffixes = - (llvm::array_lengthof(LibSuffixes) - (TargetArch != llvm::Triple::x86)); + const unsigned NumLibSuffixes = (llvm::array_lengthof(LibAndInstallSuffixes) - + (TargetArch != llvm::Triple::x86)); for (unsigned i = 0; i < NumLibSuffixes; ++i) { - StringRef LibSuffix = LibSuffixes[i]; + StringRef LibSuffix = LibAndInstallSuffixes[i][0]; std::error_code EC; - for (llvm::sys::fs::directory_iterator LI(LibDir + LibSuffix, EC), LE; + for (vfs::directory_iterator + LI = D.getVFS().dir_begin(LibDir + LibSuffix, EC), + LE; !EC && LI != LE; LI = LI.increment(EC)) { - StringRef VersionText = llvm::sys::path::filename(LI->path()); + StringRef VersionText = llvm::sys::path::filename(LI->getName()); GCCVersion CandidateVersion = GCCVersion::Parse(VersionText); if (CandidateVersion.Major != -1) // Filter obviously bad entries. - if (!CandidateGCCInstallPaths.insert(LI->path()).second) + if (!CandidateGCCInstallPaths.insert(LI->getName()).second) continue; // Saw this path before; no need to look at it again. if (CandidateVersion.isOlderThan(4, 1, 1)) continue; @@ -1960,9 +2288,9 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( // Debian mips multilibs behave more like the rest of the biarch ones, // so handle them there if (isMipsArch(TargetArch)) { - if (!findMIPSMultilibs(TargetTriple, LI->path(), Args, Detected)) + if (!findMIPSMultilibs(D, TargetTriple, LI->getName(), Args, Detected)) continue; - } else if (!findBiarchMultilibs(TargetTriple, LI->path(), Args, + } else if (!findBiarchMultilibs(D, TargetTriple, LI->getName(), Args, NeedsBiarchSuffix, Detected)) { continue; } @@ -1975,8 +2303,9 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( // FIXME: We hack together the directory name here instead of // using LI to ensure stable path separators across Windows and // Linux. - GCCInstallPath = LibDir + LibSuffixes[i] + "/" + VersionText.str(); - GCCParentLibPath = GCCInstallPath + InstallSuffixes[i]; + GCCInstallPath = + LibDir + LibAndInstallSuffixes[i][0] + "/" + VersionText.str(); + GCCParentLibPath = GCCInstallPath + LibAndInstallSuffixes[i][1]; IsValid = true; } } @@ -1984,7 +2313,7 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) - : ToolChain(D, Triple, Args), GCCInstallation() { + : ToolChain(D, Triple, Args), GCCInstallation(D), CudaInstallation(D) { getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().getInstalledDir() != getDriver().Dir) getProgramPaths().push_back(getDriver().Dir); @@ -2016,6 +2345,7 @@ Tool *Generic_GCC::buildLinker() const { return new tools::gcc::Linker(*this); } void Generic_GCC::printVerboseInfo(raw_ostream &OS) const { // Print the information about how we detected the GCC installation. GCCInstallation.print(OS); + CudaInstallation.print(OS); } bool Generic_GCC::IsUnwindTablesDefault() const { @@ -2047,9 +2377,6 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const { case llvm::Triple::ppc: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: - case llvm::Triple::sparc: - case llvm::Triple::sparcel: - case llvm::Triple::sparcv9: case llvm::Triple::systemz: return true; default: @@ -2057,6 +2384,40 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const { } } +/// \brief Helper to add the variant paths of a libstdc++ installation. +bool Generic_GCC::addLibStdCXXIncludePaths( + Twine Base, Twine Suffix, StringRef GCCTriple, StringRef GCCMultiarchTriple, + StringRef TargetMultiarchTriple, Twine IncludeSuffix, + const ArgList &DriverArgs, ArgStringList &CC1Args) const { + if (!getVFS().exists(Base + Suffix)) + return false; + + addSystemInclude(DriverArgs, CC1Args, Base + Suffix); + + // The vanilla GCC layout of libstdc++ headers uses a triple subdirectory. If + // that path exists or we have neither a GCC nor target multiarch triple, use + // this vanilla search path. + if ((GCCMultiarchTriple.empty() && TargetMultiarchTriple.empty()) || + getVFS().exists(Base + Suffix + "/" + GCCTriple + IncludeSuffix)) { + addSystemInclude(DriverArgs, CC1Args, + Base + Suffix + "/" + GCCTriple + IncludeSuffix); + } else { + // Otherwise try to use multiarch naming schemes which have normalized the + // triples and put the triple before the suffix. + // + // GCC surprisingly uses *both* the GCC triple with a multilib suffix and + // the target triple, so we support that here. + addSystemInclude(DriverArgs, CC1Args, + Base + "/" + GCCMultiarchTriple + Suffix + IncludeSuffix); + addSystemInclude(DriverArgs, CC1Args, + Base + "/" + TargetMultiarchTriple + Suffix); + } + + addSystemInclude(DriverArgs, CC1Args, Base + Suffix + "/backward"); + return true; +} + + void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs, ArgStringList &CC1Args) const { const Generic_GCC::GCCVersion &V = GCCInstallation.getVersion(); @@ -2064,238 +2425,324 @@ void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs, getTriple().getArch() == llvm::Triple::aarch64 || getTriple().getArch() == llvm::Triple::aarch64_be || (getTriple().getOS() == llvm::Triple::Linux && - (!V.isOlderThan(4, 7, 0) || - getTriple().getEnvironment() == llvm::Triple::Android)) || - getTriple().getOS() == llvm::Triple::NaCl; + (!V.isOlderThan(4, 7, 0) || getTriple().isAndroid())) || + getTriple().getOS() == llvm::Triple::NaCl || + (getTriple().getVendor() == llvm::Triple::MipsTechnologies && + !getTriple().hasEnvironment()); if (DriverArgs.hasFlag(options::OPT_fuse_init_array, options::OPT_fno_use_init_array, UseInitArrayDefault)) CC1Args.push_back("-fuse-init-array"); } +/// Mips Toolchain +MipsLLVMToolChain::MipsLLVMToolChain(const Driver &D, + const llvm::Triple &Triple, + const ArgList &Args) + : Linux(D, Triple, Args) { + // Select the correct multilib according to the given arguments. + DetectedMultilibs Result; + findMIPSMultilibs(D, Triple, "", Args, Result); + Multilibs = Result.Multilibs; + SelectedMultilib = Result.SelectedMultilib; + + // Find out the library suffix based on the ABI. + LibSuffix = tools::mips::getMipsABILibSuffix(Args, Triple); + getFilePaths().clear(); + getFilePaths().push_back(computeSysRoot() + "/usr/lib" + LibSuffix); + + // Use LLD by default. + DefaultLinker = "lld"; +} + +void MipsLLVMToolChain::AddClangSystemIncludeArgs( + const ArgList &DriverArgs, ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdinc)) + return; + + const Driver &D = getDriver(); + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { + SmallString<128> P(D.ResourceDir); + llvm::sys::path::append(P, "include"); + addSystemInclude(DriverArgs, CC1Args, P); + } + + if (DriverArgs.hasArg(options::OPT_nostdlibinc)) + return; + + const auto &Callback = Multilibs.includeDirsCallback(); + if (Callback) { + const auto IncludePaths = + Callback(D.getInstalledDir(), getTripleString(), SelectedMultilib); + for (const auto &Path : IncludePaths) + addExternCSystemIncludeIfExists(DriverArgs, CC1Args, Path); + } +} + +Tool *MipsLLVMToolChain::buildLinker() const { + return new tools::gnutools::Linker(*this); +} + +std::string MipsLLVMToolChain::computeSysRoot() const { + if (!getDriver().SysRoot.empty()) + return getDriver().SysRoot + SelectedMultilib.osSuffix(); + + const std::string InstalledDir(getDriver().getInstalledDir()); + std::string SysRootPath = + InstalledDir + "/../sysroot" + SelectedMultilib.osSuffix(); + if (llvm::sys::fs::exists(SysRootPath)) + return SysRootPath; + + return std::string(); +} + +ToolChain::CXXStdlibType +MipsLLVMToolChain::GetCXXStdlibType(const ArgList &Args) const { + Arg *A = Args.getLastArg(options::OPT_stdlib_EQ); + if (A) { + StringRef Value = A->getValue(); + if (Value != "libc++") + getDriver().Diag(diag::err_drv_invalid_stdlib_name) + << A->getAsString(Args); + } + + return ToolChain::CST_Libcxx; +} + +void MipsLLVMToolChain::AddClangCXXStdlibIncludeArgs( + const ArgList &DriverArgs, ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdlibinc) || + DriverArgs.hasArg(options::OPT_nostdincxx)) + return; + + assert((GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) && + "Only -lc++ (aka libcxx) is suported in this toolchain."); + + 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"); + break; + } + } + } +} + +void MipsLLVMToolChain::AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + assert((GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) && + "Only -lc++ (aka libxx) is suported in this toolchain."); + + CmdArgs.push_back("-lc++"); + CmdArgs.push_back("-lc++abi"); + CmdArgs.push_back("-lunwind"); +} + +std::string MipsLLVMToolChain::getCompilerRT(const ArgList &Args, + StringRef Component, + bool Shared) const { + SmallString<128> Path(getDriver().ResourceDir); + llvm::sys::path::append(Path, SelectedMultilib.osSuffix(), "lib" + LibSuffix, + getOS()); + llvm::sys::path::append(Path, Twine("libclang_rt." + Component + "-" + + "mips" + (Shared ? ".so" : ".a"))); + return Path.str(); +} + /// Hexagon Toolchain -std::string Hexagon_TC::GetGnuDir(const std::string &InstalledDir, - const ArgList &Args) { +std::string HexagonToolChain::getHexagonTargetDir( + const std::string &InstalledDir, + const SmallVectorImpl<std::string> &PrefixDirs) const { + std::string InstallRelDir; + const Driver &D = getDriver(); // Locate the rest of the toolchain ... - std::string GccToolchain = getGCCToolchainDir(Args); - - if (!GccToolchain.empty()) - return GccToolchain; + for (auto &I : PrefixDirs) + if (D.getVFS().exists(I)) + return I; - std::string InstallRelDir = InstalledDir + "/../../gnu"; - if (llvm::sys::fs::exists(InstallRelDir)) + if (getVFS().exists(InstallRelDir = InstalledDir + "/../target")) return InstallRelDir; - std::string PrefixRelDir = std::string(LLVM_PREFIX) + "/../gnu"; - if (llvm::sys::fs::exists(PrefixRelDir)) + std::string PrefixRelDir = std::string(LLVM_PREFIX) + "/target"; + if (getVFS().exists(PrefixRelDir)) return PrefixRelDir; return InstallRelDir; } -const char *Hexagon_TC::GetSmallDataThreshold(const ArgList &Args) { - Arg *A; - A = Args.getLastArg(options::OPT_G, options::OPT_G_EQ, - options::OPT_msmall_data_threshold_EQ); - if (A) - return A->getValue(); +Optional<unsigned> HexagonToolChain::getSmallDataThreshold( + const ArgList &Args) { + StringRef Gn = ""; + if (Arg *A = Args.getLastArg(options::OPT_G, options::OPT_G_EQ, + options::OPT_msmall_data_threshold_EQ)) { + Gn = A->getValue(); + } else if (Args.getLastArg(options::OPT_shared, options::OPT_fpic, + options::OPT_fPIC)) { + Gn = "0"; + } - A = Args.getLastArg(options::OPT_shared, options::OPT_fpic, - options::OPT_fPIC); - if (A) - return "0"; + unsigned G; + if (!Gn.getAsInteger(10, G)) + return G; - return 0; + return None; } -bool Hexagon_TC::UsesG0(const char *smallDataThreshold) { - return smallDataThreshold && smallDataThreshold[0] == '0'; -} -static void GetHexagonLibraryPaths(const ArgList &Args, const std::string &Ver, - const std::string &MarchString, - const std::string &InstalledDir, - ToolChain::path_list *LibPaths) { - bool buildingLib = Args.hasArg(options::OPT_shared); +void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args, + ToolChain::path_list &LibPaths) const { + const Driver &D = getDriver(); //---------------------------------------------------------------------------- // -L Args //---------------------------------------------------------------------------- for (Arg *A : Args.filtered(options::OPT_L)) for (const char *Value : A->getValues()) - LibPaths->push_back(Value); + LibPaths.push_back(Value); //---------------------------------------------------------------------------- // Other standard paths //---------------------------------------------------------------------------- - const std::string MarchSuffix = "/" + MarchString; - const std::string G0Suffix = "/G0"; - const std::string MarchG0Suffix = MarchSuffix + G0Suffix; - const std::string RootDir = Hexagon_TC::GetGnuDir(InstalledDir, Args) + "/"; - - // lib/gcc/hexagon/... - std::string LibGCCHexagonDir = RootDir + "lib/gcc/hexagon/"; - if (buildingLib) { - LibPaths->push_back(LibGCCHexagonDir + Ver + MarchG0Suffix); - LibPaths->push_back(LibGCCHexagonDir + Ver + G0Suffix); - } - LibPaths->push_back(LibGCCHexagonDir + Ver + MarchSuffix); - LibPaths->push_back(LibGCCHexagonDir + Ver); - - // lib/gcc/... - LibPaths->push_back(RootDir + "lib/gcc"); - - // hexagon/lib/... - std::string HexagonLibDir = RootDir + "hexagon/lib"; - if (buildingLib) { - LibPaths->push_back(HexagonLibDir + MarchG0Suffix); - LibPaths->push_back(HexagonLibDir + G0Suffix); + std::vector<std::string> RootDirs; + std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(), RootDirs.begin()); + + std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(), + D.PrefixDirs); + if (std::find(RootDirs.begin(), RootDirs.end(), TargetDir) == RootDirs.end()) + RootDirs.push_back(TargetDir); + + bool HasPIC = Args.hasArg(options::OPT_fpic, options::OPT_fPIC); + // Assume G0 with -shared. + bool HasG0 = Args.hasArg(options::OPT_shared); + if (auto G = getSmallDataThreshold(Args)) + HasG0 = G.getValue() == 0; + + const std::string CpuVer = GetTargetCPUVersion(Args).str(); + for (auto &Dir : RootDirs) { + std::string LibDir = Dir + "/hexagon/lib"; + std::string LibDirCpu = LibDir + '/' + CpuVer; + if (HasG0) { + if (HasPIC) + LibPaths.push_back(LibDirCpu + "/G0/pic"); + LibPaths.push_back(LibDirCpu + "/G0"); + } + LibPaths.push_back(LibDirCpu); + LibPaths.push_back(LibDir); } - LibPaths->push_back(HexagonLibDir + MarchSuffix); - LibPaths->push_back(HexagonLibDir); } -Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple &Triple, - const ArgList &Args) +HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args) : Linux(D, Triple, Args) { - const std::string InstalledDir(getDriver().getInstalledDir()); - const std::string GnuDir = Hexagon_TC::GetGnuDir(InstalledDir, Args); + const std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(), + D.PrefixDirs); // Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to // program paths - const std::string BinDir(GnuDir + "/bin"); - if (llvm::sys::fs::exists(BinDir)) + const std::string BinDir(TargetDir + "/bin"); + if (D.getVFS().exists(BinDir)) getProgramPaths().push_back(BinDir); - // Determine version of GCC libraries and headers to use. - const std::string HexagonDir(GnuDir + "/lib/gcc/hexagon"); - std::error_code ec; - GCCVersion MaxVersion = GCCVersion::Parse("0.0.0"); - for (llvm::sys::fs::directory_iterator di(HexagonDir, ec), de; - !ec && di != de; di = di.increment(ec)) { - GCCVersion cv = GCCVersion::Parse(llvm::sys::path::filename(di->path())); - if (MaxVersion < cv) - MaxVersion = cv; - } - GCCLibAndIncVersion = MaxVersion; - - ToolChain::path_list *LibPaths = &getFilePaths(); + ToolChain::path_list &LibPaths = getFilePaths(); // Remove paths added by Linux toolchain. Currently Hexagon_TC really targets // 'elf' OS type, so the Linux paths are not appropriate. When we actually // support 'linux' we'll need to fix this up - LibPaths->clear(); - - GetHexagonLibraryPaths(Args, GetGCCLibAndIncVersion(), GetTargetCPU(Args), - InstalledDir, LibPaths); + LibPaths.clear(); + getHexagonLibraryPaths(Args, LibPaths); } -Hexagon_TC::~Hexagon_TC() {} +HexagonToolChain::~HexagonToolChain() {} -Tool *Hexagon_TC::buildAssembler() const { +Tool *HexagonToolChain::buildAssembler() const { return new tools::hexagon::Assembler(*this); } -Tool *Hexagon_TC::buildLinker() const { +Tool *HexagonToolChain::buildLinker() const { return new tools::hexagon::Linker(*this); } -void Hexagon_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs, - ArgStringList &CC1Args) const { - const Driver &D = getDriver(); - +void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { if (DriverArgs.hasArg(options::OPT_nostdinc) || DriverArgs.hasArg(options::OPT_nostdlibinc)) return; - std::string Ver(GetGCCLibAndIncVersion()); - std::string GnuDir = Hexagon_TC::GetGnuDir(D.InstalledDir, DriverArgs); - std::string HexagonDir(GnuDir + "/lib/gcc/hexagon/" + Ver); - addExternCSystemInclude(DriverArgs, CC1Args, HexagonDir + "/include"); - addExternCSystemInclude(DriverArgs, CC1Args, HexagonDir + "/include-fixed"); - addExternCSystemInclude(DriverArgs, CC1Args, GnuDir + "/hexagon/include"); + const Driver &D = getDriver(); + std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(), + D.PrefixDirs); + addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include"); } -void Hexagon_TC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, - ArgStringList &CC1Args) const { - +void HexagonToolChain::AddClangCXXStdlibIncludeArgs( + const ArgList &DriverArgs, ArgStringList &CC1Args) const { if (DriverArgs.hasArg(options::OPT_nostdlibinc) || DriverArgs.hasArg(options::OPT_nostdincxx)) return; const Driver &D = getDriver(); - std::string Ver(GetGCCLibAndIncVersion()); - SmallString<128> IncludeDir( - Hexagon_TC::GetGnuDir(D.InstalledDir, DriverArgs)); - - llvm::sys::path::append(IncludeDir, "hexagon/include/c++/"); - llvm::sys::path::append(IncludeDir, Ver); - addSystemInclude(DriverArgs, CC1Args, IncludeDir); + std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs); + addSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include/c++"); } ToolChain::CXXStdlibType -Hexagon_TC::GetCXXStdlibType(const ArgList &Args) const { +HexagonToolChain::GetCXXStdlibType(const ArgList &Args) const { Arg *A = Args.getLastArg(options::OPT_stdlib_EQ); if (!A) return ToolChain::CST_Libstdcxx; StringRef Value = A->getValue(); - if (Value != "libstdc++") { + if (Value != "libstdc++") getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args); - } return ToolChain::CST_Libstdcxx; } -static int getHexagonVersion(const ArgList &Args) { - Arg *A = Args.getLastArg(options::OPT_march_EQ, options::OPT_mcpu_EQ); - // Select the default CPU (v4) if none was given. - if (!A) - return 4; +// +// Returns the default CPU for Hexagon. This is the default compilation target +// if no Hexagon processor is selected at the command-line. +// +const StringRef HexagonToolChain::GetDefaultCPU() { + return "hexagonv60"; +} - // FIXME: produce errors if we cannot parse the version. - StringRef WhichHexagon = A->getValue(); - if (WhichHexagon.startswith("hexagonv")) { - int Val; - if (!WhichHexagon.substr(sizeof("hexagonv") - 1).getAsInteger(10, Val)) - return Val; - } - if (WhichHexagon.startswith("v")) { - int Val; - if (!WhichHexagon.substr(1).getAsInteger(10, Val)) - return Val; +const StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) { + Arg *CpuArg = nullptr; + + for (auto &A : Args) { + if (A->getOption().matches(options::OPT_mcpu_EQ)) { + CpuArg = A; + A->claim(); + } } - // FIXME: should probably be an error. - return 4; + StringRef CPU = CpuArg ? CpuArg->getValue() : GetDefaultCPU(); + if (CPU.startswith("hexagon")) + return CPU.substr(sizeof("hexagon") - 1); + return CPU; } +// End Hexagon -StringRef Hexagon_TC::GetTargetCPU(const ArgList &Args) { - int V = getHexagonVersion(Args); - // FIXME: We don't support versions < 4. We should error on them. - switch (V) { - default: - llvm_unreachable("Unexpected version"); - case 5: - return "v5"; - case 4: - return "v4"; - case 3: - return "v3"; - case 2: - return "v2"; - case 1: - return "v1"; - } +/// AMDGPU Toolchain +AMDGPUToolChain::AMDGPUToolChain(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : Generic_ELF(D, Triple, Args) { } + +Tool *AMDGPUToolChain::buildLinker() const { + return new tools::amdgpu::Linker(*this); } -// End Hexagon +// End AMDGPU /// NaCl Toolchain -NaCl_TC::NaCl_TC(const Driver &D, const llvm::Triple &Triple, - const ArgList &Args) +NaClToolChain::NaClToolChain(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) : Generic_ELF(D, Triple, Args) { // Remove paths added by Generic_GCC. NaCl Toolchain cannot use the @@ -2317,45 +2764,39 @@ NaCl_TC::NaCl_TC(const Driver &D, const llvm::Triple &Triple, std::string ToolPath(getDriver().ResourceDir + "/lib/"); switch (Triple.getArch()) { - case llvm::Triple::x86: { + case llvm::Triple::x86: file_paths.push_back(FilePath + "x86_64-nacl/lib32"); - file_paths.push_back(FilePath + "x86_64-nacl/usr/lib32"); + file_paths.push_back(FilePath + "i686-nacl/usr/lib"); prog_paths.push_back(ProgPath + "x86_64-nacl/bin"); file_paths.push_back(ToolPath + "i686-nacl"); break; - } - case llvm::Triple::x86_64: { + case llvm::Triple::x86_64: file_paths.push_back(FilePath + "x86_64-nacl/lib"); file_paths.push_back(FilePath + "x86_64-nacl/usr/lib"); prog_paths.push_back(ProgPath + "x86_64-nacl/bin"); file_paths.push_back(ToolPath + "x86_64-nacl"); break; - } - case llvm::Triple::arm: { + case llvm::Triple::arm: file_paths.push_back(FilePath + "arm-nacl/lib"); file_paths.push_back(FilePath + "arm-nacl/usr/lib"); prog_paths.push_back(ProgPath + "arm-nacl/bin"); file_paths.push_back(ToolPath + "arm-nacl"); break; - } - case llvm::Triple::mipsel: { + case llvm::Triple::mipsel: file_paths.push_back(FilePath + "mipsel-nacl/lib"); file_paths.push_back(FilePath + "mipsel-nacl/usr/lib"); prog_paths.push_back(ProgPath + "bin"); file_paths.push_back(ToolPath + "mipsel-nacl"); break; - } default: break; } - // Use provided linker, not system linker - Linker = GetProgramPath("ld"); NaClArmMacrosPath = GetFilePath("nacl-arm-macros.s"); } -void NaCl_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs, - ArgStringList &CC1Args) const { +void NaClToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { const Driver &D = getDriver(); if (DriverArgs.hasArg(options::OPT_nostdinc)) return; @@ -2371,12 +2812,21 @@ void NaCl_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs, SmallString<128> P(D.Dir + "/../"); switch (getTriple().getArch()) { + case llvm::Triple::x86: + // x86 is special because multilib style uses x86_64-nacl/include for libc + // headers but the SDK wants i686-nacl/usr/include. The other architectures + // have the same substring. + llvm::sys::path::append(P, "i686-nacl/usr/include"); + addSystemInclude(DriverArgs, CC1Args, P.str()); + llvm::sys::path::remove_filename(P); + llvm::sys::path::remove_filename(P); + llvm::sys::path::remove_filename(P); + llvm::sys::path::append(P, "x86_64-nacl/include"); + addSystemInclude(DriverArgs, CC1Args, P.str()); + return; case llvm::Triple::arm: llvm::sys::path::append(P, "arm-nacl/usr/include"); break; - case llvm::Triple::x86: - llvm::sys::path::append(P, "x86_64-nacl/usr/include"); - break; case llvm::Triple::x86_64: llvm::sys::path::append(P, "x86_64-nacl/usr/include"); break; @@ -2394,16 +2844,16 @@ void NaCl_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs, addSystemInclude(DriverArgs, CC1Args, P.str()); } -void NaCl_TC::AddCXXStdlibLibArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { +void NaClToolChain::AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { // Check for -stdlib= flags. We only support libc++ but this consumes the arg // if the value is libc++, and emits an error for other values. GetCXXStdlibType(Args); CmdArgs.push_back("-lc++"); } -void NaCl_TC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, - ArgStringList &CC1Args) const { +void NaClToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { const Driver &D = getDriver(); if (DriverArgs.hasArg(options::OPT_nostdlibinc) || DriverArgs.hasArg(options::OPT_nostdincxx)) @@ -2436,7 +2886,8 @@ void NaCl_TC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, } } -ToolChain::CXXStdlibType NaCl_TC::GetCXXStdlibType(const ArgList &Args) const { +ToolChain::CXXStdlibType +NaClToolChain::GetCXXStdlibType(const ArgList &Args) const { if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { StringRef Value = A->getValue(); if (Value == "libc++") @@ -2447,8 +2898,9 @@ ToolChain::CXXStdlibType NaCl_TC::GetCXXStdlibType(const ArgList &Args) const { return ToolChain::CST_Libcxx; } -std::string NaCl_TC::ComputeEffectiveClangTriple(const ArgList &Args, - types::ID InputType) const { +std::string +NaClToolChain::ComputeEffectiveClangTriple(const ArgList &Args, + types::ID InputType) const { llvm::Triple TheTriple(ComputeLLVMTriple(Args, InputType)); if (TheTriple.getArch() == llvm::Triple::arm && TheTriple.getEnvironment() == llvm::Triple::UnknownEnvironment) @@ -2456,11 +2908,11 @@ std::string NaCl_TC::ComputeEffectiveClangTriple(const ArgList &Args, return TheTriple.getTriple(); } -Tool *NaCl_TC::buildLinker() const { +Tool *NaClToolChain::buildLinker() const { return new tools::nacltools::Linker(*this); } -Tool *NaCl_TC::buildAssembler() const { +Tool *NaClToolChain::buildAssembler() const { if (getTriple().getArch() == llvm::Triple::arm) return new tools::nacltools::AssemblerARM(*this); return new tools::gnutools::Assembler(*this); @@ -2619,7 +3071,7 @@ FreeBSD::FreeBSD(const Driver &D, const llvm::Triple &Triple, // back to '/usr/lib' if it doesn't exist. if ((Triple.getArch() == llvm::Triple::x86 || Triple.getArch() == llvm::Triple::ppc) && - llvm::sys::fs::exists(getDriver().SysRoot + "/usr/lib32/crt1.o")) + D.getVFS().exists(getDriver().SysRoot + "/usr/lib32/crt1.o")) getFilePaths().push_back(getDriver().SysRoot + "/usr/lib32"); else getFilePaths().push_back(getDriver().SysRoot + "/usr/lib"); @@ -2666,7 +3118,7 @@ Tool *FreeBSD::buildAssembler() const { Tool *FreeBSD::buildLinker() const { return new tools::freebsd::Linker(*this); } -bool FreeBSD::UseSjLjExceptions() const { +bool FreeBSD::UseSjLjExceptions(const ArgList &Args) const { // FreeBSD uses SjLj exceptions on ARM oabi. switch (getTriple().getEnvironment()) { case llvm::Triple::GNUEABIHF: @@ -2829,18 +3281,46 @@ Tool *Minix::buildAssembler() const { Tool *Minix::buildLinker() const { return new tools::minix::Linker(*this); } +static void addPathIfExists(const Driver &D, const Twine &Path, + ToolChain::path_list &Paths) { + if (D.getVFS().exists(Path)) + Paths.push_back(Path.str()); +} + /// Solaris - Solaris tool chain which can call as(1) and ld(1) directly. Solaris::Solaris(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : Generic_GCC(D, Triple, Args) { - getProgramPaths().push_back(getDriver().getInstalledDir()); + GCCInstallation.init(Triple, Args); + + path_list &Paths = getFilePaths(); + if (GCCInstallation.isValid()) + addPathIfExists(D, GCCInstallation.getInstallPath(), Paths); + + addPathIfExists(D, getDriver().getInstalledDir(), Paths); if (getDriver().getInstalledDir() != getDriver().Dir) - getProgramPaths().push_back(getDriver().Dir); + addPathIfExists(D, getDriver().Dir, Paths); - getFilePaths().push_back(getDriver().Dir + "/../lib"); - getFilePaths().push_back("/usr/lib"); + addPathIfExists(D, getDriver().SysRoot + getDriver().Dir + "/../lib", Paths); + + std::string LibPath = "/usr/lib/"; + switch (Triple.getArch()) { + case llvm::Triple::x86: + case llvm::Triple::sparc: + break; + case llvm::Triple::x86_64: + LibPath += "amd64/"; + break; + case llvm::Triple::sparcv9: + LibPath += "sparcv9/"; + break; + default: + llvm_unreachable("Unsupported architecture"); + } + + addPathIfExists(D, getDriver().SysRoot + LibPath, Paths); } Tool *Solaris::buildAssembler() const { @@ -2849,6 +3329,31 @@ Tool *Solaris::buildAssembler() const { Tool *Solaris::buildLinker() const { return new tools::solaris::Linker(*this); } +void Solaris::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdlibinc) || + DriverArgs.hasArg(options::OPT_nostdincxx)) + return; + + // Include the support directory for things like xlocale and fudged system + // headers. + addSystemInclude(DriverArgs, CC1Args, "/usr/include/c++/v1/support/solaris"); + + if (GCCInstallation.isValid()) { + GCCVersion Version = GCCInstallation.getVersion(); + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/usr/gcc/" + + Version.MajorStr + "." + + Version.MinorStr + + "/include/c++/" + Version.Text); + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/usr/gcc/" + Version.MajorStr + + "." + Version.MinorStr + "/include/c++/" + + Version.Text + "/" + + GCCInstallation.getTriple().str()); + } +} + /// Distribution (very bare-bones at the moment). enum Distro { @@ -2884,6 +3389,7 @@ enum Distro { UbuntuUtopic, UbuntuVivid, UbuntuWily, + UbuntuXenial, UnknownDistro }; @@ -2898,10 +3404,10 @@ static bool IsDebian(enum Distro Distro) { } static bool IsUbuntu(enum Distro Distro) { - return Distro >= UbuntuHardy && Distro <= UbuntuWily; + return Distro >= UbuntuHardy && Distro <= UbuntuXenial; } -static Distro DetectDistro(llvm::Triple::ArchType Arch) { +static Distro DetectDistro(const Driver &D, llvm::Triple::ArchType Arch) { llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File = llvm::MemoryBuffer::getFile("/etc/lsb-release"); if (File) { @@ -2909,7 +3415,7 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) { SmallVector<StringRef, 16> Lines; Data.split(Lines, "\n"); Distro Version = UnknownDistro; - for (const StringRef Line : Lines) + for (StringRef Line : Lines) if (Version == UnknownDistro && Line.startswith("DISTRIB_CODENAME=")) Version = llvm::StringSwitch<Distro>(Line.substr(17)) .Case("hardy", UbuntuHardy) @@ -2928,6 +3434,7 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) { .Case("utopic", UbuntuUtopic) .Case("vivid", UbuntuVivid) .Case("wily", UbuntuWily) + .Case("xenial", UbuntuXenial) .Default(UnknownDistro); return Version; } @@ -2967,13 +3474,13 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) { return UnknownDistro; } - if (llvm::sys::fs::exists("/etc/SuSE-release")) + if (D.getVFS().exists("/etc/SuSE-release")) return OpenSUSE; - if (llvm::sys::fs::exists("/etc/exherbo-release")) + if (D.getVFS().exists("/etc/exherbo-release")) return Exherbo; - if (llvm::sys::fs::exists("/etc/arch-release")) + if (D.getVFS().exists("/etc/arch-release")) return ArchLinux; return UnknownDistro; @@ -2985,9 +3492,11 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) { /// a target-triple directory in the library and header search paths. /// Unfortunately, this triple does not align with the vanilla target triple, /// so we provide a rough mapping here. -static std::string getMultiarchTriple(const llvm::Triple &TargetTriple, +static std::string getMultiarchTriple(const Driver &D, + const llvm::Triple &TargetTriple, StringRef SysRoot) { - llvm::Triple::EnvironmentType TargetEnvironment = TargetTriple.getEnvironment(); + llvm::Triple::EnvironmentType TargetEnvironment = + TargetTriple.getEnvironment(); // For most architectures, just use whatever we have rather than trying to be // clever. @@ -3002,92 +3511,91 @@ static std::string getMultiarchTriple(const llvm::Triple &TargetTriple, case llvm::Triple::arm: case llvm::Triple::thumb: if (TargetEnvironment == llvm::Triple::GNUEABIHF) { - if (llvm::sys::fs::exists(SysRoot + "/lib/arm-linux-gnueabihf")) + if (D.getVFS().exists(SysRoot + "/lib/arm-linux-gnueabihf")) return "arm-linux-gnueabihf"; } else { - if (llvm::sys::fs::exists(SysRoot + "/lib/arm-linux-gnueabi")) + if (D.getVFS().exists(SysRoot + "/lib/arm-linux-gnueabi")) return "arm-linux-gnueabi"; } break; case llvm::Triple::armeb: case llvm::Triple::thumbeb: if (TargetEnvironment == llvm::Triple::GNUEABIHF) { - if (llvm::sys::fs::exists(SysRoot + "/lib/armeb-linux-gnueabihf")) + if (D.getVFS().exists(SysRoot + "/lib/armeb-linux-gnueabihf")) return "armeb-linux-gnueabihf"; } else { - if (llvm::sys::fs::exists(SysRoot + "/lib/armeb-linux-gnueabi")) + if (D.getVFS().exists(SysRoot + "/lib/armeb-linux-gnueabi")) return "armeb-linux-gnueabi"; } break; case llvm::Triple::x86: - if (llvm::sys::fs::exists(SysRoot + "/lib/i386-linux-gnu")) + if (D.getVFS().exists(SysRoot + "/lib/i386-linux-gnu")) return "i386-linux-gnu"; break; case llvm::Triple::x86_64: // We don't want this for x32, otherwise it will match x86_64 libs if (TargetEnvironment != llvm::Triple::GNUX32 && - llvm::sys::fs::exists(SysRoot + "/lib/x86_64-linux-gnu")) + D.getVFS().exists(SysRoot + "/lib/x86_64-linux-gnu")) return "x86_64-linux-gnu"; break; case llvm::Triple::aarch64: - if (llvm::sys::fs::exists(SysRoot + "/lib/aarch64-linux-gnu")) + if (D.getVFS().exists(SysRoot + "/lib/aarch64-linux-gnu")) return "aarch64-linux-gnu"; break; case llvm::Triple::aarch64_be: - if (llvm::sys::fs::exists(SysRoot + "/lib/aarch64_be-linux-gnu")) + if (D.getVFS().exists(SysRoot + "/lib/aarch64_be-linux-gnu")) return "aarch64_be-linux-gnu"; break; case llvm::Triple::mips: - if (llvm::sys::fs::exists(SysRoot + "/lib/mips-linux-gnu")) + if (D.getVFS().exists(SysRoot + "/lib/mips-linux-gnu")) return "mips-linux-gnu"; break; case llvm::Triple::mipsel: - if (llvm::sys::fs::exists(SysRoot + "/lib/mipsel-linux-gnu")) + if (D.getVFS().exists(SysRoot + "/lib/mipsel-linux-gnu")) return "mipsel-linux-gnu"; break; case llvm::Triple::mips64: - if (llvm::sys::fs::exists(SysRoot + "/lib/mips64-linux-gnu")) + if (D.getVFS().exists(SysRoot + "/lib/mips64-linux-gnu")) return "mips64-linux-gnu"; - if (llvm::sys::fs::exists(SysRoot + "/lib/mips64-linux-gnuabi64")) + if (D.getVFS().exists(SysRoot + "/lib/mips64-linux-gnuabi64")) return "mips64-linux-gnuabi64"; break; case llvm::Triple::mips64el: - if (llvm::sys::fs::exists(SysRoot + "/lib/mips64el-linux-gnu")) + if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnu")) return "mips64el-linux-gnu"; - if (llvm::sys::fs::exists(SysRoot + "/lib/mips64el-linux-gnuabi64")) + if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnuabi64")) return "mips64el-linux-gnuabi64"; break; case llvm::Triple::ppc: - if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc-linux-gnuspe")) + if (D.getVFS().exists(SysRoot + "/lib/powerpc-linux-gnuspe")) return "powerpc-linux-gnuspe"; - if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc-linux-gnu")) + if (D.getVFS().exists(SysRoot + "/lib/powerpc-linux-gnu")) return "powerpc-linux-gnu"; break; case llvm::Triple::ppc64: - if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc64-linux-gnu")) + if (D.getVFS().exists(SysRoot + "/lib/powerpc64-linux-gnu")) return "powerpc64-linux-gnu"; break; case llvm::Triple::ppc64le: - if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc64le-linux-gnu")) + if (D.getVFS().exists(SysRoot + "/lib/powerpc64le-linux-gnu")) return "powerpc64le-linux-gnu"; break; case llvm::Triple::sparc: - if (llvm::sys::fs::exists(SysRoot + "/lib/sparc-linux-gnu")) + if (D.getVFS().exists(SysRoot + "/lib/sparc-linux-gnu")) return "sparc-linux-gnu"; break; case llvm::Triple::sparcv9: - if (llvm::sys::fs::exists(SysRoot + "/lib/sparc64-linux-gnu")) + if (D.getVFS().exists(SysRoot + "/lib/sparc64-linux-gnu")) return "sparc64-linux-gnu"; break; + case llvm::Triple::systemz: + if (D.getVFS().exists(SysRoot + "/lib/s390x-linux-gnu")) + return "s390x-linux-gnu"; + break; } return TargetTriple.str(); } -static void addPathIfExists(Twine Path, ToolChain::path_list &Paths) { - if (llvm::sys::fs::exists(Path)) - Paths.push_back(Path.str()); -} - static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) { if (isMipsArch(Triple.getArch())) { // lib32 directory has a special meaning on MIPS targets. @@ -3120,7 +3628,8 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) { Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : Generic_ELF(D, Triple, Args) { - GCCInstallation.init(D, Triple, Args); + GCCInstallation.init(Triple, Args); + CudaInstallation.init(Triple, Args); Multilibs = GCCInstallation.getMultilibs(); llvm::Triple::ArchType Arch = Triple.getArch(); std::string SysRoot = computeSysRoot(); @@ -3138,9 +3647,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) GCCInstallation.getTriple().str() + "/bin") .str()); - Linker = GetLinkerPath(); - - Distro Distro = DetectDistro(Arch); + Distro Distro = DetectDistro(D, Arch); if (IsOpenSUSE(Distro) || IsUbuntu(Distro)) { ExtraOpts.push_back("-z"); @@ -3150,7 +3657,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) ExtraOpts.push_back("-X"); - const bool IsAndroid = Triple.getEnvironment() == llvm::Triple::Android; + const bool IsAndroid = Triple.isAndroid(); const bool IsMips = isMipsArch(Arch); if (IsMips && !SysRoot.empty()) @@ -3190,7 +3697,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) path_list &Paths = getFilePaths(); const std::string OSLibDir = getOSLibDir(Triple, Args); - const std::string MultiarchTriple = getMultiarchTriple(Triple, SysRoot); + const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot); // Add the multilib suffixed paths where they are available. if (GCCInstallation.isValid()) { @@ -3200,7 +3707,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // Sourcery CodeBench MIPS toolchain holds some libraries under // a biarch-like suffix of the GCC installation. - addPathIfExists((GCCInstallation.getInstallPath() + Multilib.gccSuffix()), + addPathIfExists(D, GCCInstallation.getInstallPath() + Multilib.gccSuffix(), Paths); // GCC cross compiling toolchains will install target libraries which ship @@ -3221,8 +3728,8 @@ 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(LibPath + "/../" + GCCTriple.str() + "/lib/../" + OSLibDir + - Multilib.osSuffix(), + addPathIfExists(D, LibPath + "/../" + GCCTriple.str() + "/lib/../" + + OSLibDir + Multilib.osSuffix(), Paths); // If the GCC installation we found is inside of the sysroot, we want to @@ -3235,8 +3742,8 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // configurations but this seems somewhere between questionable and simply // a bug. if (StringRef(LibPath).startswith(SysRoot)) { - addPathIfExists(LibPath + "/" + MultiarchTriple, Paths); - addPathIfExists(LibPath + "/../" + OSLibDir, Paths); + addPathIfExists(D, LibPath + "/" + MultiarchTriple, Paths); + addPathIfExists(D, LibPath + "/../" + OSLibDir, Paths); } } @@ -3246,27 +3753,29 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // FIXME: It's not clear whether we should use the driver's installed // directory ('Dir' below) or the ResourceDir. if (StringRef(D.Dir).startswith(SysRoot)) { - addPathIfExists(D.Dir + "/../lib/" + MultiarchTriple, Paths); - addPathIfExists(D.Dir + "/../" + OSLibDir, Paths); + addPathIfExists(D, D.Dir + "/../lib/" + MultiarchTriple, Paths); + addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths); } - addPathIfExists(SysRoot + "/lib/" + MultiarchTriple, Paths); - addPathIfExists(SysRoot + "/lib/../" + OSLibDir, Paths); - addPathIfExists(SysRoot + "/usr/lib/" + MultiarchTriple, Paths); - addPathIfExists(SysRoot + "/usr/lib/../" + OSLibDir, Paths); + addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths); + addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths); + addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths); + addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths); // Try walking via the GCC triple path in case of biarch or multiarch GCC // installations with strange symlinks. if (GCCInstallation.isValid()) { - addPathIfExists(SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() + + addPathIfExists(D, + SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() + "/../../" + OSLibDir, Paths); // Add the 'other' biarch variant path Multilib BiarchSibling; if (GCCInstallation.getBiarchSibling(BiarchSibling)) { - addPathIfExists( - GCCInstallation.getInstallPath() + BiarchSibling.gccSuffix(), Paths); + addPathIfExists(D, GCCInstallation.getInstallPath() + + BiarchSibling.gccSuffix(), + Paths); } // See comments above on the multilib variant for details of why this is @@ -3274,14 +3783,14 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) const std::string &LibPath = GCCInstallation.getParentLibPath(); const llvm::Triple &GCCTriple = GCCInstallation.getTriple(); const Multilib &Multilib = GCCInstallation.getMultilib(); - addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib" + - Multilib.osSuffix(), + addPathIfExists(D, LibPath + "/../" + GCCTriple.str() + "/lib" + + Multilib.osSuffix(), Paths); // See comments above on the multilib variant for details of why this is // only included from within the sysroot. if (StringRef(LibPath).startswith(SysRoot)) - addPathIfExists(LibPath, Paths); + addPathIfExists(D, LibPath, Paths); } // Similar to the logic for GCC above, if we are currently running Clang @@ -3290,10 +3799,10 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // FIXME: It's not clear whether we should use the driver's installed // directory ('Dir' below) or the ResourceDir. if (StringRef(D.Dir).startswith(SysRoot)) - addPathIfExists(D.Dir + "/../lib", Paths); + addPathIfExists(D, D.Dir + "/../lib", Paths); - addPathIfExists(SysRoot + "/lib", Paths); - addPathIfExists(SysRoot + "/usr/lib", Paths); + addPathIfExists(D, SysRoot + "/lib", Paths); + addPathIfExists(D, SysRoot + "/usr/lib", Paths); } bool Linux::HasNativeLLVMSupport() const { return true; } @@ -3323,12 +3832,12 @@ std::string Linux::computeSysRoot() const { (InstallDir + "/../../../../" + TripleStr + "/libc" + Multilib.osSuffix()) .str(); - if (llvm::sys::fs::exists(Path)) + if (getVFS().exists(Path)) return Path; Path = (InstallDir + "/../../../../sysroot" + Multilib.osSuffix()).str(); - if (llvm::sys::fs::exists(Path)) + if (getVFS().exists(Path)) return Path; return std::string(); @@ -3404,6 +3913,10 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, "/usr/include/arm-linux-gnueabi"}; const StringRef ARMHFMultiarchIncludeDirs[] = { "/usr/include/arm-linux-gnueabihf"}; + const StringRef ARMEBMultiarchIncludeDirs[] = { + "/usr/include/armeb-linux-gnueabi"}; + const StringRef ARMEBHFMultiarchIncludeDirs[] = { + "/usr/include/armeb-linux-gnueabihf"}; const StringRef MIPSMultiarchIncludeDirs[] = {"/usr/include/mips-linux-gnu"}; const StringRef MIPSELMultiarchIncludeDirs[] = { "/usr/include/mipsel-linux-gnu"}; @@ -3422,6 +3935,8 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, "/usr/include/sparc-linux-gnu"}; const StringRef Sparc64MultiarchIncludeDirs[] = { "/usr/include/sparc64-linux-gnu"}; + const StringRef SYSTEMZMultiarchIncludeDirs[] = { + "/usr/include/s390x-linux-gnu"}; ArrayRef<StringRef> MultiarchIncludeDirs; switch (getTriple().getArch()) { case llvm::Triple::x86_64: @@ -3435,11 +3950,19 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, MultiarchIncludeDirs = AArch64MultiarchIncludeDirs; break; case llvm::Triple::arm: + case llvm::Triple::thumb: if (getTriple().getEnvironment() == llvm::Triple::GNUEABIHF) MultiarchIncludeDirs = ARMHFMultiarchIncludeDirs; else MultiarchIncludeDirs = ARMMultiarchIncludeDirs; break; + case llvm::Triple::armeb: + case llvm::Triple::thumbeb: + if (getTriple().getEnvironment() == llvm::Triple::GNUEABIHF) + MultiarchIncludeDirs = ARMEBHFMultiarchIncludeDirs; + else + MultiarchIncludeDirs = ARMEBMultiarchIncludeDirs; + break; case llvm::Triple::mips: MultiarchIncludeDirs = MIPSMultiarchIncludeDirs; break; @@ -3467,11 +3990,14 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, case llvm::Triple::sparcv9: MultiarchIncludeDirs = Sparc64MultiarchIncludeDirs; break; + case llvm::Triple::systemz: + MultiarchIncludeDirs = SYSTEMZMultiarchIncludeDirs; + break; default: break; } for (StringRef Dir : MultiarchIncludeDirs) { - if (llvm::sys::fs::exists(SysRoot + Dir)) { + if (D.getVFS().exists(SysRoot + Dir)) { addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + Dir); break; } @@ -3488,37 +4014,24 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include"); } -/// \brief Helper to add the variant paths of a libstdc++ installation. -/*static*/ bool Linux::addLibStdCXXIncludePaths( - Twine Base, Twine Suffix, StringRef GCCTriple, StringRef GCCMultiarchTriple, - StringRef TargetMultiarchTriple, Twine IncludeSuffix, - const ArgList &DriverArgs, ArgStringList &CC1Args) { - if (!llvm::sys::fs::exists(Base + Suffix)) - return false; - - addSystemInclude(DriverArgs, CC1Args, Base + Suffix); - // The vanilla GCC layout of libstdc++ headers uses a triple subdirectory. If - // that path exists or we have neither a GCC nor target multiarch triple, use - // this vanilla search path. - if ((GCCMultiarchTriple.empty() && TargetMultiarchTriple.empty()) || - llvm::sys::fs::exists(Base + Suffix + "/" + GCCTriple + IncludeSuffix)) { - addSystemInclude(DriverArgs, CC1Args, - Base + Suffix + "/" + GCCTriple + IncludeSuffix); - } else { - // Otherwise try to use multiarch naming schemes which have normalized the - // triples and put the triple before the suffix. - // - // GCC surprisingly uses *both* the GCC triple with a multilib suffix and - // the target triple, so we support that here. - addSystemInclude(DriverArgs, CC1Args, - Base + "/" + GCCMultiarchTriple + Suffix + IncludeSuffix); - addSystemInclude(DriverArgs, CC1Args, - Base + "/" + TargetMultiarchTriple + Suffix); +static std::string DetectLibcxxIncludePath(StringRef base) { + std::error_code EC; + int MaxVersion = 0; + std::string MaxVersionString = ""; + for (llvm::sys::fs::directory_iterator LI(base, EC), LE; !EC && LI != LE; + LI = LI.increment(EC)) { + StringRef VersionText = llvm::sys::path::filename(LI->path()); + int Version; + if (VersionText[0] == 'v' && + !VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) { + if (Version > MaxVersion) { + MaxVersion = Version; + MaxVersionString = VersionText; + } + } } - - addSystemInclude(DriverArgs, CC1Args, Base + Suffix + "/backward"); - return true; + return MaxVersion ? (base + "/" + MaxVersionString).str() : ""; } void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, @@ -3530,17 +4043,14 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, // Check if libc++ has been enabled and provide its include paths if so. if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) { const std::string LibCXXIncludePathCandidates[] = { - // The primary location is within the Clang installation. - // FIXME: We shouldn't hard code 'v1' here to make Clang future proof to - // newer ABI versions. - getDriver().Dir + "/../include/c++/v1", + 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. - getDriver().SysRoot + "/usr/include/c++/v1"}; + DetectLibcxxIncludePath(getDriver().SysRoot + "/usr/include/c++")}; for (const auto &IncludePath : LibCXXIncludePathCandidates) { - if (!llvm::sys::fs::exists(IncludePath)) + if (IncludePath.empty() || !getVFS().exists(IncludePath)) continue; // Add the first candidate that exists. addSystemInclude(DriverArgs, CC1Args, IncludePath); @@ -3561,10 +4071,10 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, StringRef InstallDir = GCCInstallation.getInstallPath(); StringRef TripleStr = GCCInstallation.getTriple().str(); const Multilib &Multilib = GCCInstallation.getMultilib(); - const std::string GCCMultiarchTriple = - getMultiarchTriple(GCCInstallation.getTriple(), getDriver().SysRoot); + const std::string GCCMultiarchTriple = getMultiarchTriple( + getDriver(), GCCInstallation.getTriple(), getDriver().SysRoot); const std::string TargetMultiarchTriple = - getMultiarchTriple(getTriple(), getDriver().SysRoot); + getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot); const GCCVersion &Version = GCCInstallation.getVersion(); // The primary search for libstdc++ supports multiarch variants. @@ -3598,6 +4108,18 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, } } +void Linux::AddCudaIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + 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"); + } +} + bool Linux::isPIEDefault() const { return getSanitizerArgs().requiresPIE(); } SanitizerMask Linux::getSupportedSanitizers() const { @@ -3607,24 +4129,39 @@ SanitizerMask Linux::getSupportedSanitizers() const { getTriple().getArch() == llvm::Triple::mips64el; const bool IsPowerPC64 = getTriple().getArch() == llvm::Triple::ppc64 || getTriple().getArch() == llvm::Triple::ppc64le; + const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64 || + getTriple().getArch() == llvm::Triple::aarch64_be; SanitizerMask Res = ToolChain::getSupportedSanitizers(); Res |= SanitizerKind::Address; Res |= SanitizerKind::KernelAddress; Res |= SanitizerKind::Vptr; - if (IsX86_64 || IsMIPS64) { + Res |= SanitizerKind::SafeStack; + if (IsX86_64 || IsMIPS64 || IsAArch64) Res |= SanitizerKind::DataFlow; + if (IsX86_64 || IsMIPS64 || IsAArch64) Res |= SanitizerKind::Leak; + if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64) Res |= SanitizerKind::Thread; - } - if (IsX86_64 || IsMIPS64 || IsPowerPC64) + if (IsX86_64 || IsMIPS64 || IsPowerPC64 || IsAArch64) Res |= SanitizerKind::Memory; if (IsX86 || IsX86_64) { Res |= SanitizerKind::Function; - Res |= SanitizerKind::SafeStack; } return Res; } +void Linux::addProfileRTLibs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const { + if (!needsProfileRT(Args)) return; + + // Add linker option -u__llvm_runtime_variable to cause runtime + // initialization module to be linked in. + if (!Args.hasArg(options::OPT_coverage)) + CmdArgs.push_back(Args.MakeArgString( + Twine("-u", llvm::getInstrProfRuntimeHookVarName()))); + ToolChain::addProfileRTLibs(Args, CmdArgs); +} + /// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly. DragonFly::DragonFly(const Driver &D, const llvm::Triple &Triple, @@ -3638,10 +4175,7 @@ DragonFly::DragonFly(const Driver &D, const llvm::Triple &Triple, getFilePaths().push_back(getDriver().Dir + "/../lib"); getFilePaths().push_back("/usr/lib"); - if (llvm::sys::fs::exists("/usr/lib/gcc47")) - getFilePaths().push_back("/usr/lib/gcc47"); - else - getFilePaths().push_back("/usr/lib/gcc44"); + getFilePaths().push_back("/usr/lib/gcc50"); } Tool *DragonFly::buildAssembler() const { @@ -3665,6 +4199,22 @@ CudaToolChain::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const { Linux::addClangTargetOptions(DriverArgs, CC1Args); CC1Args.push_back("-fcuda-is-device"); + + if (DriverArgs.hasArg(options::OPT_nocudalib)) + return; + + std::string LibDeviceFile = CudaInstallation.getLibDeviceFile( + DriverArgs.getLastArgValue(options::OPT_march_EQ)); + if (!LibDeviceFile.empty()) { + CC1Args.push_back("-mlink-cuda-bitcode"); + CC1Args.push_back(DriverArgs.MakeArgString(LibDeviceFile)); + + // Libdevice in CUDA-7.0 requires PTX version that's more recent + // than LLVM defaults to. Use PTX4.2 which is the PTX version that + // came with CUDA-7.0. + CC1Args.push_back("-target-feature"); + CC1Args.push_back("+ptx42"); + } } llvm::opt::DerivedArgList * @@ -3712,29 +4262,32 @@ CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, } /// XCore tool chain -XCore::XCore(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) +XCoreToolChain::XCoreToolChain(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) : ToolChain(D, Triple, Args) { // ProgramPaths are found via 'PATH' environment variable. } -Tool *XCore::buildAssembler() const { +Tool *XCoreToolChain::buildAssembler() const { return new tools::XCore::Assembler(*this); } -Tool *XCore::buildLinker() const { return new tools::XCore::Linker(*this); } +Tool *XCoreToolChain::buildLinker() const { + return new tools::XCore::Linker(*this); +} -bool XCore::isPICDefault() const { return false; } +bool XCoreToolChain::isPICDefault() const { return false; } -bool XCore::isPIEDefault() const { return false; } +bool XCoreToolChain::isPIEDefault() const { return false; } -bool XCore::isPICDefaultForced() const { return false; } +bool XCoreToolChain::isPICDefaultForced() const { return false; } -bool XCore::SupportsProfiling() const { return false; } +bool XCoreToolChain::SupportsProfiling() const { return false; } -bool XCore::hasBlocksRuntime() const { return false; } +bool XCoreToolChain::hasBlocksRuntime() const { return false; } -void XCore::AddClangSystemIncludeArgs(const ArgList &DriverArgs, - ArgStringList &CC1Args) const { +void XCoreToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { if (DriverArgs.hasArg(options::OPT_nostdinc) || DriverArgs.hasArg(options::OPT_nostdlibinc)) return; @@ -3747,13 +4300,13 @@ void XCore::AddClangSystemIncludeArgs(const ArgList &DriverArgs, } } -void XCore::addClangTargetOptions(const ArgList &DriverArgs, - ArgStringList &CC1Args) const { +void XCoreToolChain::addClangTargetOptions(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { CC1Args.push_back("-nostdsysteminc"); } -void XCore::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, - ArgStringList &CC1Args) const { +void XCoreToolChain::AddClangCXXStdlibIncludeArgs( + const ArgList &DriverArgs, ArgStringList &CC1Args) const { if (DriverArgs.hasArg(options::OPT_nostdinc) || DriverArgs.hasArg(options::OPT_nostdlibinc) || DriverArgs.hasArg(options::OPT_nostdincxx)) @@ -3767,15 +4320,84 @@ void XCore::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, } } -void XCore::AddCXXStdlibLibArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { +void XCoreToolChain::AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { // We don't output any lib args. This is handled by xcc. } -// SHAVEToolChain does not call Clang's C compiler. -// We override SelectTool to avoid testing ShouldUseClangCompiler(). -Tool *SHAVEToolChain::SelectTool(const JobAction &JA) const { +MyriadToolChain::MyriadToolChain(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : Generic_GCC(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 + // extra triple, which is preferable to further hacks of the logic that at + // present is based solely on getArch(). In particular, it would be wrong to + // choose the myriad installation when targeting a non-myriad sparc install. + switch (Triple.getArch()) { + default: + D.Diag(diag::err_target_unsupported_arch) << Triple.getArchName() + << "myriad"; + case llvm::Triple::sparc: + case llvm::Triple::sparcel: + case llvm::Triple::shave: + GCCInstallation.init(Triple, Args, {"sparc-myriad-elf"}); + } + + if (GCCInstallation.isValid()) { + // The contents of LibDir are independent of the version of gcc. + // This contains libc, libg (a superset of libc), libm, libstdc++, libssp. + SmallString<128> LibDir(GCCInstallation.getParentLibPath()); + if (Triple.getArch() == llvm::Triple::sparcel) + llvm::sys::path::append(LibDir, "../sparc-myriad-elf/lib/le"); + else + llvm::sys::path::append(LibDir, "../sparc-myriad-elf/lib"); + addPathIfExists(D, LibDir, getFilePaths()); + + // This directory contains crt{i,n,begin,end}.o as well as libgcc. + // These files are tied to a particular version of gcc. + SmallString<128> CompilerSupportDir(GCCInstallation.getInstallPath()); + // There are actually 4 choices: {le,be} x {fpu,nofpu} + // but as this toolchain is for LEON sparc, it can assume FPU. + if (Triple.getArch() == llvm::Triple::sparcel) + llvm::sys::path::append(CompilerSupportDir, "le"); + addPathIfExists(D, CompilerSupportDir, getFilePaths()); + } +} + +MyriadToolChain::~MyriadToolChain() {} + +void MyriadToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (!DriverArgs.hasArg(options::OPT_nostdinc)) + addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include"); +} + +void MyriadToolChain::AddClangCXXStdlibIncludeArgs( + const ArgList &DriverArgs, ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdlibinc) || + DriverArgs.hasArg(options::OPT_nostdincxx)) + return; + + // Only libstdc++, for now. + StringRef LibDir = GCCInstallation.getParentLibPath(); + const GCCVersion &Version = GCCInstallation.getVersion(); + StringRef TripleStr = GCCInstallation.getTriple().str(); + const Multilib &Multilib = GCCInstallation.getMultilib(); + + addLibStdCXXIncludePaths( + LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text, + "", TripleStr, "", "", Multilib.includeSuffix(), DriverArgs, CC1Args); +} + +// MyriadToolChain handles several triples: +// {shave,sparc{,el}}-myriad-{rtems,unknown}-elf +Tool *MyriadToolChain::SelectTool(const JobAction &JA) const { + // The inherited method works fine if not targeting the SHAVE. + if (!isShaveCompilation(getTriple())) + return ToolChain::SelectTool(JA); switch (JA.getKind()) { + case Action::PreprocessJobClass: case Action::CompileJobClass: if (!Compiler) Compiler.reset(new tools::SHAVE::Compiler(*this)); @@ -3789,28 +4411,122 @@ Tool *SHAVEToolChain::SelectTool(const JobAction &JA) const { } } -SHAVEToolChain::SHAVEToolChain(const Driver &D, const llvm::Triple &Triple, - const ArgList &Args) - : Generic_GCC(D, Triple, Args) {} +Tool *MyriadToolChain::buildLinker() const { + return new tools::Myriad::Linker(*this); +} + +WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args) + : ToolChain(D, Triple, Args) { + // Use LLD by default. + DefaultLinker = "lld"; +} + +bool WebAssembly::IsMathErrnoDefault() const { return false; } + +bool WebAssembly::IsObjCNonFragileABIDefault() const { return true; } + +bool WebAssembly::UseObjCMixedDispatch() const { return true; } + +bool WebAssembly::isPICDefault() const { return false; } + +bool WebAssembly::isPIEDefault() const { return false; } + +bool WebAssembly::isPICDefaultForced() const { return false; } + +bool WebAssembly::IsIntegratedAssemblerDefault() const { return true; } + +// TODO: Support Objective C stuff. +bool WebAssembly::SupportsObjCGC() const { return false; } -SHAVEToolChain::~SHAVEToolChain() {} +bool WebAssembly::hasBlocksRuntime() const { return false; } -/// Following are methods necessary to avoid having moviClang be an abstract -/// class. +// TODO: Support profiling. +bool WebAssembly::SupportsProfiling() const { return false; } -Tool *SHAVEToolChain::getTool(Action::ActionClass AC) const { - // SelectTool() must find a tool using the method in the superclass. - // There's nothing we can do if that fails. - llvm_unreachable("SHAVEToolChain can't getTool"); +bool WebAssembly::HasNativeLLVMSupport() const { return true; } + +void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasFlag(options::OPT_fuse_init_array, + options::OPT_fno_use_init_array, true)) + CC1Args.push_back("-fuse-init-array"); } -Tool *SHAVEToolChain::buildLinker() const { - // SHAVEToolChain executables can not be linked except by the vendor tools. - llvm_unreachable("SHAVEToolChain can't buildLinker"); +Tool *WebAssembly::buildLinker() const { + return new tools::wasm::Linker(*this); } -Tool *SHAVEToolChain::buildAssembler() const { - // This one you'd think should be reachable since we expose an - // assembler to the driver, except not the way it expects. - llvm_unreachable("SHAVEToolChain can't buildAssembler"); +PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) + : Generic_ELF(D, Triple, 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 + // 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 (!llvm::sys::fs::exists(EnvValue)) + getDriver().Diag(clang::diag::warn_drv_ps4_sdk_dir) << EnvValue; + PS4SDKDir = EnvValue; + } else { + PS4SDKDir = getDriver().Dir; + llvm::sys::path::append(PS4SDKDir, "/../../"); + } + + // By default, the driver won't report a warning if it can't find + // PS4's include or lib directories. This behavior could be changed if + // -Weverything or -Winvalid-or-nonexistent-directory options are passed. + // If -isysroot was passed, use that as the SDK base path. + std::string PrefixDir; + if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { + PrefixDir = A->getValue(); + if (!llvm::sys::fs::exists(PrefixDir)) + getDriver().Diag(clang::diag::warn_missing_sysroot) << PrefixDir; + } else + PrefixDir = PS4SDKDir.str(); + + SmallString<512> PS4SDKIncludeDir(PrefixDir); + llvm::sys::path::append(PS4SDKIncludeDir, "target/include"); + if (!Args.hasArg(options::OPT_nostdinc) && + !Args.hasArg(options::OPT_nostdlibinc) && + !Args.hasArg(options::OPT_isysroot) && + !Args.hasArg(options::OPT__sysroot_EQ) && + !llvm::sys::fs::exists(PS4SDKIncludeDir)) { + getDriver().Diag(clang::diag::warn_drv_unable_to_find_directory_expected) + << "PS4 system headers" << PS4SDKIncludeDir; + } + + SmallString<512> PS4SDKLibDir(PS4SDKDir); + llvm::sys::path::append(PS4SDKLibDir, "target/lib"); + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs) && + !Args.hasArg(options::OPT__sysroot_EQ) && !Args.hasArg(options::OPT_E) && + !Args.hasArg(options::OPT_c) && !Args.hasArg(options::OPT_S) && + !Args.hasArg(options::OPT_emit_ast) && + !llvm::sys::fs::exists(PS4SDKLibDir)) { + getDriver().Diag(clang::diag::warn_drv_unable_to_find_directory_expected) + << "PS4 system libraries" << PS4SDKLibDir; + return; + } + getFilePaths().push_back(PS4SDKLibDir.str()); +} + +Tool *PS4CPU::buildAssembler() const { + return new tools::PS4cpu::Assemble(*this); +} + +Tool *PS4CPU::buildLinker() const { return new tools::PS4cpu::Link(*this); } + +bool PS4CPU::isPICDefault() const { return true; } + +bool PS4CPU::HasNativeLLVMSupport() const { return true; } + +SanitizerMask PS4CPU::getSupportedSanitizers() const { + SanitizerMask Res = ToolChain::getSupportedSanitizers(); + Res |= SanitizerKind::Address; + Res |= SanitizerKind::Vptr; + return Res; } |