diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp | 1968 |
1 files changed, 1146 insertions, 822 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp index 8bd8298..15e36a1 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp @@ -29,6 +29,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" +#include "llvm/Support/TargetParser.h" #include "llvm/Support/raw_ostream.h" #include <cstdlib> // ::getenv #include <system_error> @@ -38,13 +39,8 @@ using namespace clang::driver::toolchains; using namespace clang; using namespace llvm::opt; -MachO::MachO(const Driver &D, const llvm::Triple &Triple, - const ArgList &Args) - : ToolChain(D, Triple, Args) { - getProgramPaths().push_back(getDriver().getInstalledDir()); - if (getDriver().getInstalledDir() != getDriver().Dir) - getProgramPaths().push_back(getDriver().Dir); - +MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) + : ToolChain(D, Triple, Args) { // We expect 'as', 'ld', etc. to be adjacent to our install dir. getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().getInstalledDir() != getDriver().Dir) @@ -52,28 +48,8 @@ MachO::MachO(const Driver &D, const llvm::Triple &Triple, } /// Darwin - Darwin tool chain for i386 and x86_64. -Darwin::Darwin(const Driver & D, const llvm::Triple & Triple, - const ArgList & Args) - : MachO(D, Triple, Args), TargetInitialized(false) { - // Compute the initial Darwin version from the triple - unsigned Major, Minor, Micro; - if (!Triple.getMacOSXVersion(Major, Minor, Micro)) - getDriver().Diag(diag::err_drv_invalid_darwin_version) << - Triple.getOSName(); - llvm::raw_string_ostream(MacosxVersionMin) - << Major << '.' << Minor << '.' << Micro; - - // FIXME: DarwinVersion is only used to find GCC's libexec directory. - // It should be removed when we stop supporting that. - DarwinVersion[0] = Minor + 4; - DarwinVersion[1] = Micro; - DarwinVersion[2] = 0; - - // Compute the initial iOS version from the triple - Triple.getiOSVersion(Major, Minor, Micro); - llvm::raw_string_ostream(iOSVersionMin) - << Major << '.' << Minor << '.' << Micro; -} +Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) + : MachO(D, Triple, Args), TargetInitialized(false) {} types::ID MachO::LookupTypeForExtension(const char *Ext) const { types::ID Ty = types::lookupTypeForExtension(Ext); @@ -85,9 +61,7 @@ types::ID MachO::LookupTypeForExtension(const char *Ext) const { return Ty; } -bool MachO::HasNativeLLVMSupport() const { - return true; -} +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 { @@ -108,38 +82,44 @@ bool Darwin::hasBlocksRuntime() const { } } -static const char *GetArmArchForMArch(StringRef Value) { - return llvm::StringSwitch<const char*>(Value) - .Case("armv6k", "armv6") - .Case("armv6m", "armv6m") - .Case("armv5tej", "armv5") - .Case("xscale", "xscale") - .Case("armv4t", "armv4t") - .Case("armv7", "armv7") - .Cases("armv7a", "armv7-a", "armv7") - .Cases("armv7r", "armv7-r", "armv7") - .Cases("armv7em", "armv7e-m", "armv7em") - .Cases("armv7k", "armv7-k", "armv7k") - .Cases("armv7m", "armv7-m", "armv7m") - .Cases("armv7s", "armv7-s", "armv7s") - .Default(nullptr); -} - -static const char *GetArmArchForMCpu(StringRef Value) { - return llvm::StringSwitch<const char *>(Value) - .Cases("arm9e", "arm946e-s", "arm966e-s", "arm968e-s", "arm926ej-s","armv5") - .Cases("arm10e", "arm10tdmi", "armv5") - .Cases("arm1020t", "arm1020e", "arm1022e", "arm1026ej-s", "armv5") - .Case("xscale", "xscale") - .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "arm1176jzf-s", "armv6") - .Case("cortex-m0", "armv6m") - .Cases("cortex-a5", "cortex-a7", "cortex-a8", "armv7") - .Cases("cortex-a9", "cortex-a12", "cortex-a15", "cortex-a17", "krait", "armv7") - .Cases("cortex-r4", "cortex-r5", "armv7r") - .Case("cortex-m3", "armv7m") - .Cases("cortex-m4", "cortex-m7", "armv7em") - .Case("swift", "armv7s") - .Default(nullptr); +// This is just a MachO name translation routine and there's no +// way to join this into ARMTargetParser without breaking all +// other assumptions. Maybe MachO should consider standardising +// their nomenclature. +static const char *ArmMachOArchName(StringRef Arch) { + return llvm::StringSwitch<const char *>(Arch) + .Case("armv6k", "armv6") + .Case("armv6m", "armv6m") + .Case("armv5tej", "armv5") + .Case("xscale", "xscale") + .Case("armv4t", "armv4t") + .Case("armv7", "armv7") + .Cases("armv7a", "armv7-a", "armv7") + .Cases("armv7r", "armv7-r", "armv7") + .Cases("armv7em", "armv7e-m", "armv7em") + .Cases("armv7k", "armv7-k", "armv7k") + .Cases("armv7m", "armv7-m", "armv7m") + .Cases("armv7s", "armv7-s", "armv7s") + .Default(nullptr); +} + +static const char *ArmMachOArchNameCPU(StringRef CPU) { + unsigned ArchKind = llvm::ARMTargetParser::parseCPUArch(CPU); + if (ArchKind == llvm::ARM::AK_INVALID) + return nullptr; + StringRef Arch = llvm::ARMTargetParser::getArchName(ArchKind); + + // FIXME: Make sure this MachO triple mangling is really necessary. + // ARMv5* normalises to ARMv5. + if (Arch.startswith("armv5")) + Arch = Arch.substr(0, 5); + // ARMv6*, except ARMv6M, normalises to ARMv6. + else if (Arch.startswith("armv6") && !Arch.endswith("6m")) + Arch = Arch.substr(0, 5); + // ARMv7A normalises to ARMv7. + else if (Arch.endswith("v7a")) + Arch = Arch.substr(0, 5); + return Arch.data(); } static bool isSoftFloatABI(const ArgList &Args) { @@ -164,11 +144,11 @@ StringRef MachO::getMachOArchName(const ArgList &Args) const { case llvm::Triple::thumb: case llvm::Triple::arm: { if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) - if (const char *Arch = GetArmArchForMArch(A->getValue())) + if (const char *Arch = ArmMachOArchName(A->getValue())) return Arch; if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) - if (const char *Arch = GetArmArchForMCpu(A->getValue())) + if (const char *Arch = ArmMachOArchNameCPU(A->getValue())) return Arch; return "arm"; @@ -176,15 +156,12 @@ StringRef MachO::getMachOArchName(const ArgList &Args) const { } } -Darwin::~Darwin() { -} - -MachO::~MachO() { -} +Darwin::~Darwin() {} +MachO::~MachO() {} std::string MachO::ComputeEffectiveClangTriple(const ArgList &Args, - types::ID InputType) const { + types::ID InputType) const { llvm::Triple Triple(ComputeLLVMTriple(Args, InputType)); return Triple.getTriple(); @@ -228,18 +205,15 @@ Tool *MachO::getTool(Action::ActionClass AC) const { } } -Tool *MachO::buildLinker() const { - return new tools::darwin::Link(*this); -} +Tool *MachO::buildLinker() const { return new tools::darwin::Linker(*this); } Tool *MachO::buildAssembler() const { - return new tools::darwin::Assemble(*this); + return new tools::darwin::Assembler(*this); } -DarwinClang::DarwinClang(const Driver &D, const llvm::Triple& Triple, +DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) - : Darwin(D, Triple, Args) { -} + : Darwin(D, Triple, Args) {} void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const { // For iOS, 64-bit, promote certain warnings to errors. @@ -302,8 +276,8 @@ 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.str())) - CmdArgs.push_back(Args.MakeArgString(P.str())); + if (AlwaysLink || llvm::sys::fs::exists(P)) + CmdArgs.push_back(Args.MakeArgString(P)); // Adding the rpaths might negatively interact when other rpaths are involved, // so we should make sure we add the rpaths last, after all user-specified @@ -320,7 +294,51 @@ void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs, // Add the path to the resource dir to rpath to support using the dylib // from the default location without copying. CmdArgs.push_back("-rpath"); - CmdArgs.push_back(Args.MakeArgString(Dir.str())); + CmdArgs.push_back(Args.MakeArgString(Dir)); + } +} + +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; + + // 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); +} + +void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args, + ArgStringList &CmdArgs, + StringRef Sanitizer) const { + if (!Args.hasArg(options::OPT_dynamiclib) && + !Args.hasArg(options::OPT_bundle)) { + // Sanitizer runtime libraries requires C++. + AddCXXStdlibLibArgs(Args, CmdArgs); + } + assert(isTargetMacOS() || isTargetIOSSimulator()); + StringRef OS = isTargetMacOS() ? "osx" : "iossim"; + AddLinkRuntimeLib( + Args, CmdArgs, + (Twine("libclang_rt.") + Sanitizer + "_" + OS + "_dynamic.dylib").str(), + /*AlwaysLink*/ true, /*IsEmbedded*/ false, + /*AddRPath*/ true); + + if (GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) { + // Add explicit dependcy on -lc++abi, as -lc++ doesn't re-export + // all RTTI-related symbols that UBSan uses. + CmdArgs.push_back("-lc++abi"); } } @@ -332,7 +350,7 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, break; default: getDriver().Diag(diag::err_drv_unsupported_rtlib_for_platform) - << Args.getLastArg(options::OPT_rtlib_EQ)->getValue() << "darwin"; + << Args.getLastArg(options::OPT_rtlib_EQ)->getValue() << "darwin"; return; } @@ -347,70 +365,15 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, // cares. This is useful in situations where someone wants to statically link // something like libstdc++, and needs its runtime support routines. if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) { - getDriver().Diag(diag::err_drv_unsupported_opt) - << A->getAsString(Args); + getDriver().Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args); return; } - // If we are building profile support, link that library in. - if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, - false) || - Args.hasArg(options::OPT_fprofile_generate) || - Args.hasArg(options::OPT_fprofile_instr_generate) || - Args.hasArg(options::OPT_fcreate_profile) || - Args.hasArg(options::OPT_coverage)) { - // Select the appropriate runtime library for the target. - if (isTargetIOSBased()) - AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_ios.a"); - else - AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_osx.a"); - } - const SanitizerArgs &Sanitize = getSanitizerArgs(); - - // Add Ubsan runtime library, if required. - if (Sanitize.needsUbsanRt()) { - // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds. - if (isTargetIOSBased()) { - getDriver().Diag(diag::err_drv_clang_unsupported_per_platform) - << "-fsanitize=undefined"; - } else { - assert(isTargetMacOS() && "unexpected non OS X target"); - AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.ubsan_osx.a", true); - - // The Ubsan runtime library requires C++. - AddCXXStdlibLibArgs(Args, CmdArgs); - } - } - - // Add ASAN runtime library, if required. Dynamic libraries and bundles - // should not be linked with the runtime library. - if (Sanitize.needsAsanRt()) { - // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds. - if (isTargetIPhoneOS()) { - getDriver().Diag(diag::err_drv_clang_unsupported_per_platform) - << "-fsanitize=address"; - } else { - if (!Args.hasArg(options::OPT_dynamiclib) && - !Args.hasArg(options::OPT_bundle)) { - // The ASAN runtime library requires C++. - AddCXXStdlibLibArgs(Args, CmdArgs); - } - if (isTargetMacOS()) { - AddLinkRuntimeLib(Args, CmdArgs, - "libclang_rt.asan_osx_dynamic.dylib", - /*AlwaysLink*/ true, /*IsEmbedded*/ false, - /*AddRPath*/ true); - } else { - if (isTargetIOSSimulator()) { - AddLinkRuntimeLib(Args, CmdArgs, - "libclang_rt.asan_iossim_dynamic.dylib", - /*AlwaysLink*/ true, /*IsEmbedded*/ false, - /*AddRPath*/ true); - } - } - } - } + if (Sanitize.needsAsanRt()) + AddLinkSanitizerLibArgs(Args, CmdArgs, "asan"); + if (Sanitize.needsUbsanRt()) + AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan"); // Otherwise link libSystem, then the dynamic runtime library, and finally any // target specific static runtime library. @@ -471,7 +434,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { if (llvm::sys::path::is_absolute(env) && llvm::sys::fs::exists(env) && StringRef(env) != "/") { Args.append(Args.MakeSeparateArg( - nullptr, Opts.getOption(options::OPT_isysroot), env)); + nullptr, Opts.getOption(options::OPT_isysroot), env)); } } } @@ -481,39 +444,66 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { if (OSXVersion && iOSVersion) { getDriver().Diag(diag::err_drv_argument_not_allowed_with) - << OSXVersion->getAsString(Args) - << iOSVersion->getAsString(Args); + << OSXVersion->getAsString(Args) << iOSVersion->getAsString(Args); iOSVersion = nullptr; } else if (!OSXVersion && !iOSVersion) { // If no deployment target was specified on the command line, check for // environment defines. - StringRef OSXTarget; - StringRef iOSTarget; + std::string OSXTarget; + std::string iOSTarget; if (char *env = ::getenv("MACOSX_DEPLOYMENT_TARGET")) OSXTarget = env; if (char *env = ::getenv("IPHONEOS_DEPLOYMENT_TARGET")) iOSTarget = env; - // If no '-miphoneos-version-min' specified on the command line and - // IPHONEOS_DEPLOYMENT_TARGET is not defined, see if we can set the default - // based on -isysroot. - if (iOSTarget.empty()) { + // 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() && + Args.hasArg(options::OPT_isysroot)) { if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { - StringRef first, second; StringRef isysroot = A->getValue(); - std::tie(first, second) = isysroot.split(StringRef("SDKs/iPhoneOS")); - if (second != "") - iOSTarget = second.substr(0,3); + // Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk + size_t BeginSDK = isysroot.rfind("SDKs/"); + size_t EndSDK = isysroot.rfind(".sdk"); + if (BeginSDK != StringRef::npos && EndSDK != StringRef::npos) { + StringRef SDK = isysroot.slice(BeginSDK + 5, EndSDK); + // Slice the version number out. + // Version number is between the first and the last number. + size_t StartVer = SDK.find_first_of("0123456789"); + size_t EndVer = SDK.find_last_of("0123456789"); + if (StartVer != StringRef::npos && EndVer > StartVer) { + StringRef Version = SDK.slice(StartVer, EndVer + 1); + if (SDK.startswith("iPhoneOS") || + SDK.startswith("iPhoneSimulator")) + iOSTarget = Version; + else if (SDK.startswith("MacOSX")) + OSXTarget = Version; + } + } } } - // If no OSX or iOS target has been specified and we're compiling for armv7, - // go ahead as assume we're targeting iOS. - StringRef MachOArchName = getMachOArchName(Args); - if (OSXTarget.empty() && iOSTarget.empty() && - (MachOArchName == "armv7" || MachOArchName == "armv7s" || - MachOArchName == "arm64")) - iOSTarget = iOSVersionMin; + // 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()) { + StringRef MachOArchName = getMachOArchName(Args); + unsigned Major, Minor, Micro; + if (MachOArchName == "armv7" || MachOArchName == "armv7s" || + MachOArchName == "arm64") { + getTriple().getiOSVersion(Major, Minor, Micro); + llvm::raw_string_ostream(iOSTarget) << Major << '.' << Minor << '.' + << Micro; + } else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" && + MachOArchName != "armv7em") { + if (!getTriple().getMacOSXVersion(Major, Minor, Micro)) { + getDriver().Diag(diag::err_drv_invalid_darwin_version) + << getTriple().getOSName(); + } + llvm::raw_string_ostream(OSXTarget) << Major << '.' << Minor << '.' + << Micro; + } + } // Allow conflicts among OSX and iOS for historical reasons, but choose the // default platform. @@ -534,12 +524,6 @@ 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 (MachOArchName != "armv6m" && MachOArchName != "armv7m" && - MachOArchName != "armv7em") { - // Otherwise, assume we are targeting OS X. - const Option O = Opts.getOption(options::OPT_mmacosx_version_min_EQ); - OSXVersion = Args.MakeJoinedArg(nullptr, O, MacosxVersionMin); - Args.append(OSXVersion); } } @@ -556,18 +540,18 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { bool HadExtra; if (Platform == MacOS) { assert(!iOSVersion && "Unknown target platform!"); - if (!Driver::GetReleaseVersion(OSXVersion->getValue(), Major, Minor, - Micro, HadExtra) || HadExtra || - Major != 10 || Minor >= 100 || Micro >= 100) + if (!Driver::GetReleaseVersion(OSXVersion->getValue(), Major, Minor, Micro, + HadExtra) || + HadExtra || Major != 10 || Minor >= 100 || Micro >= 100) getDriver().Diag(diag::err_drv_invalid_version_number) - << OSXVersion->getAsString(Args); + << OSXVersion->getAsString(Args); } else if (Platform == IPhoneOS) { assert(iOSVersion && "Unknown target platform!"); - if (!Driver::GetReleaseVersion(iOSVersion->getValue(), Major, Minor, - Micro, HadExtra) || HadExtra || - Major >= 10 || Minor >= 100 || Micro >= 100) + if (!Driver::GetReleaseVersion(iOSVersion->getValue(), Major, Minor, Micro, + HadExtra) || + HadExtra || Major >= 10 || Minor >= 100 || Micro >= 100) getDriver().Diag(diag::err_drv_invalid_version_number) - << iOSVersion->getAsString(Args); + << iOSVersion->getAsString(Args); } else llvm_unreachable("unknown kind of Darwin platform"); @@ -599,11 +583,11 @@ 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.str())) { + if (!llvm::sys::fs::exists(P)) { llvm::sys::path::remove_filename(P); llvm::sys::path::append(P, "libstdc++.6.dylib"); - if (llvm::sys::fs::exists(P.str())) { - CmdArgs.push_back(Args.MakeArgString(P.str())); + if (llvm::sys::fs::exists(P)) { + CmdArgs.push_back(Args.MakeArgString(P)); return; } } @@ -646,8 +630,8 @@ void DarwinClang::AddCCKextLibArgs(const ArgList &Args, // For now, allow missing resource libraries to support developers who may // not have compiler-rt checked out or integrated into their build. - if (llvm::sys::fs::exists(P.str())) - CmdArgs.push_back(Args.MakeArgString(P.str())); + if (llvm::sys::fs::exists(P)) + CmdArgs.push_back(Args.MakeArgString(P)); } DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args, @@ -667,10 +651,11 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args, // Skip this argument unless the architecture matches either the toolchain // triple arch, or the arch being bound. llvm::Triple::ArchType XarchArch = - tools::darwin::getArchTypeForMachOArchName(A->getValue(0)); - if (!(XarchArch == getArch() || - (BoundArch && XarchArch == - tools::darwin::getArchTypeForMachOArchName(BoundArch)))) + tools::darwin::getArchTypeForMachOArchName(A->getValue(0)); + if (!(XarchArch == getArch() || + (BoundArch && + XarchArch == + tools::darwin::getArchTypeForMachOArchName(BoundArch)))) continue; Arg *OriginalArg = A; @@ -688,11 +673,11 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args, // like -O4 are going to slip through. if (!XarchArg || Index > Prev + 1) { getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args) - << A->getAsString(Args); + << A->getAsString(Args); continue; } else if (XarchArg->getOption().hasFlag(options::DriverOption)) { getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver) - << A->getAsString(Args); + << A->getAsString(Args); continue; } @@ -706,11 +691,9 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args, // "input arguments". if (A->getOption().hasFlag(options::LinkerInput)) { // Convert the argument into individual Zlinker_input_args. - for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) { - DAL->AddSeparateArg(OriginalArg, - Opts.getOption(options::OPT_Zlinker_input), - A->getValue(i)); - + for (const char *Value : A->getValues()) { + DAL->AddSeparateArg( + OriginalArg, Opts.getOption(options::OPT_Zlinker_input), Value); } continue; } @@ -719,7 +702,7 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args, // Sob. These is strictly gcc compatible for the time being. Apple // gcc translates options twice, which means that self-expanding // options add duplicates. - switch ((options::ID) A->getOption().getID()) { + switch ((options::ID)A->getOption().getID()) { default: DAL->append(A); break; @@ -731,20 +714,19 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args, break; case options::OPT_dependency_file: - DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), - A->getValue()); + DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue()); break; case options::OPT_gfull: DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag)); - DAL->AddFlagArg(A, - Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols)); + DAL->AddFlagArg( + A, Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols)); break; case options::OPT_gused: DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag)); - DAL->AddFlagArg(A, - Opts.getOption(options::OPT_feliminate_unused_debug_symbols)); + DAL->AddFlagArg( + A, Opts.getOption(options::OPT_feliminate_unused_debug_symbols)); break; case options::OPT_shared: @@ -765,8 +747,8 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args, break; case options::OPT_Wno_nonportable_cfstrings: - DAL->AddFlagArg(A, - Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings)); + DAL->AddFlagArg( + A, Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings)); break; case options::OPT_fpascal_strings: @@ -867,8 +849,8 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args, return DAL; } -void MachO::AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const { +void MachO::AddLinkRuntimeLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { // Embedded targets are simple at the moment, not supporting sanitizers and // with different libraries for each member of the product { static, PIC } x // { hard-float, soft-float } @@ -882,7 +864,6 @@ void MachO::AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args, AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, false, true); } - DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, const char *BoundArch) const { // First get the generic Apple args, before moving onto Darwin-specific ones. @@ -903,7 +884,7 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, // 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; ) { + for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie;) { Arg *A = *it; ++it; if (A->getOption().getID() != options::OPT_mkernel && @@ -935,8 +916,7 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args, where = "iOS 5.0"; if (where != StringRef()) { - getDriver().Diag(clang::diag::err_drv_invalid_libcxx_deployment) - << where; + getDriver().Diag(clang::diag::err_drv_invalid_libcxx_deployment) << where; } } @@ -959,13 +939,9 @@ bool Darwin::UseSjLjExceptions() const { getTriple().getArch() == llvm::Triple::thumb); } -bool MachO::isPICDefault() const { - return true; -} +bool MachO::isPICDefault() const { return true; } -bool MachO::isPIEDefault() const { - return false; -} +bool MachO::isPIEDefault() const { return false; } bool MachO::isPICDefaultForced() const { return (getArch() == llvm::Triple::x86_64 || @@ -977,8 +953,8 @@ bool MachO::SupportsProfiling() const { return getArch() == llvm::Triple::x86 || getArch() == llvm::Triple::x86_64; } -void Darwin::addMinVersionArgs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const { +void Darwin::addMinVersionArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { VersionTuple TargetVersion = getTargetVersion(); if (isTargetIOSSimulator()) @@ -993,8 +969,8 @@ void Darwin::addMinVersionArgs(const llvm::opt::ArgList &Args, CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString())); } -void Darwin::addStartObjectFileArgs(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs) const { +void Darwin::addStartObjectFileArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { // Derived from startfile spec. if (Args.hasArg(options::OPT_dynamiclib)) { // Derived from darwin_dylib1 spec. @@ -1079,16 +1055,26 @@ void Darwin::addStartObjectFileArgs(const llvm::opt::ArgList &Args, } } -bool Darwin::SupportsObjCGC() const { - return isTargetMacOS(); -} +bool Darwin::SupportsObjCGC() const { return isTargetMacOS(); } void Darwin::CheckObjCARC() const { - if (isTargetIOSBased()|| (isTargetMacOS() && !isMacosxVersionLT(10, 6))) + if (isTargetIOSBased() || (isTargetMacOS() && !isMacosxVersionLT(10, 6))) return; getDriver().Diag(diag::err_arc_unsupported_on_toolchain); } +SanitizerMask Darwin::getSupportedSanitizers() const { + SanitizerMask Res = ToolChain::getSupportedSanitizers(); + if (isTargetMacOS() || isTargetIOSSimulator()) + Res |= SanitizerKind::Address; + if (isTargetMacOS()) { + if (!isMacosxVersionLT(10, 9)) + Res |= SanitizerKind::Vptr; + Res |= SanitizerKind::SafeStack; + } + return Res; +} + /// Generic_GCC - A tool chain using the 'gcc' command to perform /// all subcommands; this relies on gcc translating the majority of /// command line options. @@ -1098,17 +1084,15 @@ void Darwin::CheckObjCARC() const { /// This is the primary means of forming GCCVersion objects. /*static*/ Generic_GCC::GCCVersion Linux::GCCVersion::Parse(StringRef VersionText) { - const GCCVersion BadVersion = { VersionText.str(), -1, -1, -1, "", "", "" }; + const GCCVersion BadVersion = {VersionText.str(), -1, -1, -1, "", "", ""}; std::pair<StringRef, StringRef> First = VersionText.split('.'); std::pair<StringRef, StringRef> Second = First.second.split('.'); - GCCVersion GoodVersion = { VersionText.str(), -1, -1, -1, "", "", "" }; - if (First.first.getAsInteger(10, GoodVersion.Major) || - GoodVersion.Major < 0) + GCCVersion GoodVersion = {VersionText.str(), -1, -1, -1, "", "", ""}; + if (First.first.getAsInteger(10, GoodVersion.Major) || GoodVersion.Major < 0) return BadVersion; GoodVersion.MajorStr = First.first.str(); - if (Second.first.getAsInteger(10, GoodVersion.Minor) || - GoodVersion.Minor < 0) + if (Second.first.getAsInteger(10, GoodVersion.Minor) || GoodVersion.Minor < 0) return BadVersion; GoodVersion.MinorStr = Second.first.str(); @@ -1185,12 +1169,11 @@ static llvm::StringRef getGCCToolchainDir(const ArgList &Args) { /// should instead pull the target out of the driver. This is currently /// necessary because the driver doesn't store the final version of the target /// triple. -void -Generic_GCC::GCCInstallationDetector::init( +void Generic_GCC::GCCInstallationDetector::init( const Driver &D, const llvm::Triple &TargetTriple, const ArgList &Args) { - llvm::Triple BiarchVariantTriple = - TargetTriple.isArch32Bit() ? TargetTriple.get64BitArchVariant() - : TargetTriple.get32BitArchVariant(); + llvm::Triple BiarchVariantTriple = TargetTriple.isArch32Bit() + ? TargetTriple.get64BitArchVariant() + : TargetTriple.get32BitArchVariant(); // The library directories which may contain GCC installations. SmallVector<StringRef, 4> CandidateLibDirs, CandidateBiarchLibDirs; // The compatible GCC triples for this particular architecture. @@ -1228,25 +1211,22 @@ Generic_GCC::GCCInstallationDetector::init( // Loop over the various components which exist and select the best GCC // installation available. GCC installs are ranked by version number. Version = GCCVersion::Parse("0.0.0"); - for (unsigned i = 0, ie = Prefixes.size(); i < ie; ++i) { - if (!llvm::sys::fs::exists(Prefixes[i])) + for (const std::string &Prefix : Prefixes) { + if (!llvm::sys::fs::exists(Prefix)) continue; - for (unsigned j = 0, je = CandidateLibDirs.size(); j < je; ++j) { - const std::string LibDir = Prefixes[i] + CandidateLibDirs[j].str(); + for (const StringRef Suffix : CandidateLibDirs) { + const std::string LibDir = Prefix + Suffix.str(); if (!llvm::sys::fs::exists(LibDir)) continue; - for (unsigned k = 0, ke = CandidateTripleAliases.size(); k < ke; ++k) - ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, - CandidateTripleAliases[k]); + for (const StringRef Candidate : CandidateTripleAliases) + ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate); } - for (unsigned j = 0, je = CandidateBiarchLibDirs.size(); j < je; ++j) { - const std::string LibDir = Prefixes[i] + CandidateBiarchLibDirs[j].str(); + for (const StringRef Suffix : CandidateBiarchLibDirs) { + const std::string LibDir = Prefix + Suffix.str(); if (!llvm::sys::fs::exists(LibDir)) continue; - for (unsigned k = 0, ke = CandidateBiarchTripleAliases.size(); k < ke; - ++k) - ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, - CandidateBiarchTripleAliases[k], + for (const StringRef Candidate : CandidateBiarchTripleAliases) + ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate, /*NeedsBiarchSuffix=*/ true); } } @@ -1283,91 +1263,82 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { // Declare a bunch of static data sets that we'll select between below. These // are specifically designed to always refer to string literals to avoid any // lifetime or initialization issues. - static const char *const AArch64LibDirs[] = { "/lib64", "/lib" }; - static const char *const AArch64Triples[] = { "aarch64-none-linux-gnu", - "aarch64-linux-gnu", - "aarch64-linux-android", - "aarch64-redhat-linux" }; - static const char *const AArch64beLibDirs[] = { "/lib" }; - static const char *const AArch64beTriples[] = { "aarch64_be-none-linux-gnu", - "aarch64_be-linux-gnu" }; - - static const char *const ARMLibDirs[] = { "/lib" }; - static const char *const ARMTriples[] = { "arm-linux-gnueabi", - "arm-linux-androideabi" }; - static const char *const ARMHFTriples[] = { "arm-linux-gnueabihf", - "armv7hl-redhat-linux-gnueabi" }; - static const char *const ARMebLibDirs[] = { "/lib" }; - static const char *const ARMebTriples[] = { "armeb-linux-gnueabi", - "armeb-linux-androideabi" }; - static const char *const ARMebHFTriples[] = { "armeb-linux-gnueabihf", - "armebv7hl-redhat-linux-gnueabi" }; - - static const char *const X86_64LibDirs[] = { "/lib64", "/lib" }; + static const char *const AArch64LibDirs[] = {"/lib64", "/lib"}; + static const char *const AArch64Triples[] = { + "aarch64-none-linux-gnu", "aarch64-linux-gnu", "aarch64-linux-android", + "aarch64-redhat-linux"}; + static const char *const AArch64beLibDirs[] = {"/lib"}; + static const char *const AArch64beTriples[] = {"aarch64_be-none-linux-gnu", + "aarch64_be-linux-gnu"}; + + static const char *const ARMLibDirs[] = {"/lib"}; + static const char *const ARMTriples[] = {"arm-linux-gnueabi", + "arm-linux-androideabi"}; + static const char *const ARMHFTriples[] = {"arm-linux-gnueabihf", + "armv7hl-redhat-linux-gnueabi"}; + static const char *const ARMebLibDirs[] = {"/lib"}; + static const char *const ARMebTriples[] = {"armeb-linux-gnueabi", + "armeb-linux-androideabi"}; + static const char *const ARMebHFTriples[] = { + "armeb-linux-gnueabihf", "armebv7hl-redhat-linux-gnueabi"}; + + static const char *const X86_64LibDirs[] = {"/lib64", "/lib"}; static const char *const X86_64Triples[] = { - "x86_64-linux-gnu", "x86_64-unknown-linux-gnu", "x86_64-pc-linux-gnu", - "x86_64-redhat-linux6E", "x86_64-redhat-linux", "x86_64-suse-linux", - "x86_64-manbo-linux-gnu", "x86_64-linux-gnu", "x86_64-slackware-linux", - "x86_64-linux-android", "x86_64-unknown-linux" - }; - static const char *const X32LibDirs[] = { "/libx32" }; - static const char *const X86LibDirs[] = { "/lib32", "/lib" }; + "x86_64-linux-gnu", "x86_64-unknown-linux-gnu", + "x86_64-pc-linux-gnu", "x86_64-redhat-linux6E", + "x86_64-redhat-linux", "x86_64-suse-linux", + "x86_64-manbo-linux-gnu", "x86_64-linux-gnu", + "x86_64-slackware-linux", "x86_64-linux-android", + "x86_64-unknown-linux"}; + static const char *const X32LibDirs[] = {"/libx32"}; + static const char *const X86LibDirs[] = {"/lib32", "/lib"}; static const char *const X86Triples[] = { - "i686-linux-gnu", "i686-pc-linux-gnu", "i486-linux-gnu", "i386-linux-gnu", - "i386-redhat-linux6E", "i686-redhat-linux", "i586-redhat-linux", - "i386-redhat-linux", "i586-suse-linux", "i486-slackware-linux", - "i686-montavista-linux", "i686-linux-android", "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 MIPSELLibDirs[] = { "/lib" }; - static const char *const MIPSELTriples[] = { "mipsel-linux-gnu", - "mipsel-linux-android", - "mips-img-linux-gnu" }; - - static const char *const MIPS64LibDirs[] = { "/lib64", "/lib" }; - static const char *const MIPS64Triples[] = { "mips64-linux-gnu", - "mips-mti-linux-gnu", - "mips-img-linux-gnu", - "mips64-linux-gnuabi64" }; - static const char *const MIPS64ELLibDirs[] = { "/lib64", "/lib" }; - static const char *const MIPS64ELTriples[] = { "mips64el-linux-gnu", - "mips-mti-linux-gnu", - "mips-img-linux-gnu", - "mips64el-linux-android", - "mips64el-linux-gnuabi64" }; - - static const char *const PPCLibDirs[] = { "/lib32", "/lib" }; + "i686-linux-gnu", "i686-pc-linux-gnu", "i486-linux-gnu", + "i386-linux-gnu", "i386-redhat-linux6E", "i686-redhat-linux", + "i586-redhat-linux", "i386-redhat-linux", "i586-suse-linux", + "i486-slackware-linux", "i686-montavista-linux", "i686-linux-android", + "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 MIPSELLibDirs[] = {"/lib"}; + static const char *const MIPSELTriples[] = { + "mipsel-linux-gnu", "mipsel-linux-android", "mips-img-linux-gnu"}; + + static const char *const MIPS64LibDirs[] = {"/lib64", "/lib"}; + static const char *const MIPS64Triples[] = { + "mips64-linux-gnu", "mips-mti-linux-gnu", "mips-img-linux-gnu", + "mips64-linux-gnuabi64"}; + static const char *const MIPS64ELLibDirs[] = {"/lib64", "/lib"}; + static const char *const MIPS64ELTriples[] = { + "mips64el-linux-gnu", "mips-mti-linux-gnu", "mips-img-linux-gnu", + "mips64el-linux-android", "mips64el-linux-gnuabi64"}; + + static const char *const PPCLibDirs[] = {"/lib32", "/lib"}; static const char *const PPCTriples[] = { - "powerpc-linux-gnu", "powerpc-unknown-linux-gnu", "powerpc-linux-gnuspe", - "powerpc-suse-linux", "powerpc-montavista-linuxspe" - }; - static const char *const PPC64LibDirs[] = { "/lib64", "/lib" }; - static const char *const PPC64Triples[] = { "powerpc64-linux-gnu", - "powerpc64-unknown-linux-gnu", - "powerpc64-suse-linux", - "ppc64-redhat-linux" }; - static const char *const PPC64LELibDirs[] = { "/lib64", "/lib" }; - static const char *const PPC64LETriples[] = { "powerpc64le-linux-gnu", - "powerpc64le-unknown-linux-gnu", - "powerpc64le-suse-linux", - "ppc64le-redhat-linux" }; - - static const char *const SPARCv8LibDirs[] = { "/lib32", "/lib" }; - static const char *const SPARCv8Triples[] = { "sparc-linux-gnu", - "sparcv8-linux-gnu" }; - static const char *const SPARCv9LibDirs[] = { "/lib64", "/lib" }; - static const char *const SPARCv9Triples[] = { "sparc64-linux-gnu", - "sparcv9-linux-gnu" }; - - static const char *const SystemZLibDirs[] = { "/lib64", "/lib" }; + "powerpc-linux-gnu", "powerpc-unknown-linux-gnu", "powerpc-linux-gnuspe", + "powerpc-suse-linux", "powerpc-montavista-linuxspe"}; + static const char *const PPC64LibDirs[] = {"/lib64", "/lib"}; + static const char *const PPC64Triples[] = { + "powerpc64-linux-gnu", "powerpc64-unknown-linux-gnu", + "powerpc64-suse-linux", "ppc64-redhat-linux"}; + static const char *const PPC64LELibDirs[] = {"/lib64", "/lib"}; + static const char *const PPC64LETriples[] = { + "powerpc64le-linux-gnu", "powerpc64le-unknown-linux-gnu", + "powerpc64le-suse-linux", "ppc64le-redhat-linux"}; + + static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"}; + static const char *const SPARCv8Triples[] = {"sparc-linux-gnu", + "sparcv8-linux-gnu"}; + static const char *const SPARCv9LibDirs[] = {"/lib64", "/lib"}; + static const char *const SPARCv9Triples[] = {"sparc64-linux-gnu", + "sparcv9-linux-gnu"}; + + static const char *const SystemZLibDirs[] = {"/lib64", "/lib"}; static const char *const SystemZTriples[] = { - "s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu", - "s390x-suse-linux", "s390x-redhat-linux" - }; + "s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu", + "s390x-suse-linux", "s390x-redhat-linux"}; using std::begin; using std::end; @@ -1498,11 +1469,12 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { namespace { // Filter to remove Multilibs that don't exist as a suffix to Path -class FilterNonExistent : public MultilibSet::FilterCallback { - std::string Base; +class FilterNonExistent { + StringRef Base; + public: - FilterNonExistent(std::string Base) : Base(Base) {} - bool operator()(const Multilib &M) const override { + FilterNonExistent(StringRef Base) : Base(Base) {} + bool operator()(const Multilib &M) { return !llvm::sys::fs::exists(Base + M.gccSuffix() + "/crtbegin.o"); } }; @@ -1534,14 +1506,12 @@ static bool isMipsEL(llvm::Triple::ArchType Arch) { } static bool isMips16(const ArgList &Args) { - Arg *A = Args.getLastArg(options::OPT_mips16, - options::OPT_mno_mips16); + Arg *A = Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16); return A && A->getOption().matches(options::OPT_mips16); } static bool isMicroMips(const ArgList &Args) { - Arg *A = Args.getLastArg(options::OPT_mmicromips, - options::OPT_mno_micromips); + Arg *A = Args.getLastArg(options::OPT_mmicromips, options::OPT_mno_micromips); return A && A->getOption().matches(options::OPT_mmicromips); } @@ -1562,8 +1532,7 @@ static Multilib makeMultilib(StringRef commonSuffix) { } static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path, - const llvm::opt::ArgList &Args, - DetectedMultilibs &Result) { + 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 @@ -1595,181 +1564,182 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path, MultilibSet FSFMipsMultilibs; { auto MArchMips32 = makeMultilib("/mips32") - .flag("+m32").flag("-m64").flag("-mmicromips").flag("+march=mips32"); + .flag("+m32") + .flag("-m64") + .flag("-mmicromips") + .flag("+march=mips32"); auto MArchMicroMips = makeMultilib("/micromips") - .flag("+m32").flag("-m64").flag("+mmicromips"); + .flag("+m32") + .flag("-m64") + .flag("+mmicromips"); auto MArchMips64r2 = makeMultilib("/mips64r2") - .flag("-m32").flag("+m64").flag("+march=mips64r2"); + .flag("-m32") + .flag("+m64") + .flag("+march=mips64r2"); - auto MArchMips64 = makeMultilib("/mips64") - .flag("-m32").flag("+m64").flag("-march=mips64r2"); + auto MArchMips64 = makeMultilib("/mips64").flag("-m32").flag("+m64").flag( + "-march=mips64r2"); auto MArchDefault = makeMultilib("") - .flag("+m32").flag("-m64").flag("-mmicromips").flag("+march=mips32r2"); - - auto Mips16 = makeMultilib("/mips16") - .flag("+mips16"); - - auto UCLibc = makeMultilib("/uclibc") - .flag("+muclibc"); - - auto MAbi64 = makeMultilib("/64") - .flag("+mabi=n64").flag("-mabi=n32").flag("-m32"); - - auto BigEndian = makeMultilib("") - .flag("+EB").flag("-EL"); - - auto LittleEndian = makeMultilib("/el") - .flag("+EL").flag("-EB"); - - auto SoftFloat = makeMultilib("/sof") - .flag("+msoft-float"); - - auto Nan2008 = makeMultilib("/nan2008") - .flag("+mnan=2008"); - - FSFMipsMultilibs = MultilibSet() - .Either(MArchMips32, MArchMicroMips, - MArchMips64r2, MArchMips64, MArchDefault) - .Maybe(UCLibc) - .Maybe(Mips16) - .FilterOut("/mips64/mips16") - .FilterOut("/mips64r2/mips16") - .FilterOut("/micromips/mips16") - .Maybe(MAbi64) - .FilterOut("/micromips/64") - .FilterOut("/mips32/64") - .FilterOut("^/64") - .FilterOut("/mips16/64") - .Either(BigEndian, LittleEndian) - .Maybe(SoftFloat) - .Maybe(Nan2008) - .FilterOut(".*sof/nan2008") - .FilterOut(NonExistent) - .setIncludeDirsCallback([]( - StringRef InstallDir, StringRef TripleStr, const Multilib &M) { - std::vector<std::string> Dirs; - Dirs.push_back((InstallDir + "/include").str()); - std::string SysRootInc = InstallDir.str() + "/../../../../sysroot"; - if (StringRef(M.includeSuffix()).startswith("/uclibc")) - Dirs.push_back(SysRootInc + "/uclibc/usr/include"); - else - Dirs.push_back(SysRootInc + "/usr/include"); - return Dirs; - }); + .flag("+m32") + .flag("-m64") + .flag("-mmicromips") + .flag("+march=mips32r2"); + + auto Mips16 = makeMultilib("/mips16").flag("+mips16"); + + auto UCLibc = makeMultilib("/uclibc").flag("+muclibc"); + + auto MAbi64 = + makeMultilib("/64").flag("+mabi=n64").flag("-mabi=n32").flag("-m32"); + + auto BigEndian = makeMultilib("").flag("+EB").flag("-EL"); + + auto LittleEndian = makeMultilib("/el").flag("+EL").flag("-EB"); + + auto SoftFloat = makeMultilib("/sof").flag("+msoft-float"); + + auto Nan2008 = makeMultilib("/nan2008").flag("+mnan=2008"); + + FSFMipsMultilibs = + MultilibSet() + .Either(MArchMips32, MArchMicroMips, MArchMips64r2, MArchMips64, + MArchDefault) + .Maybe(UCLibc) + .Maybe(Mips16) + .FilterOut("/mips64/mips16") + .FilterOut("/mips64r2/mips16") + .FilterOut("/micromips/mips16") + .Maybe(MAbi64) + .FilterOut("/micromips/64") + .FilterOut("/mips32/64") + .FilterOut("^/64") + .FilterOut("/mips16/64") + .Either(BigEndian, LittleEndian) + .Maybe(SoftFloat) + .Maybe(Nan2008) + .FilterOut(".*sof/nan2008") + .FilterOut(NonExistent) + .setIncludeDirsCallback([](StringRef InstallDir, + StringRef TripleStr, const Multilib &M) { + std::vector<std::string> Dirs; + Dirs.push_back((InstallDir + "/include").str()); + std::string SysRootInc = + InstallDir.str() + "/../../../../sysroot"; + if (StringRef(M.includeSuffix()).startswith("/uclibc")) + Dirs.push_back(SysRootInc + "/uclibc/usr/include"); + else + Dirs.push_back(SysRootInc + "/usr/include"); + return Dirs; + }); } // Check for Code Sourcery toolchain multilibs MultilibSet CSMipsMultilibs; { - auto MArchMips16 = makeMultilib("/mips16") - .flag("+m32").flag("+mips16"); + auto MArchMips16 = makeMultilib("/mips16").flag("+m32").flag("+mips16"); - auto MArchMicroMips = makeMultilib("/micromips") - .flag("+m32").flag("+mmicromips"); + auto MArchMicroMips = + makeMultilib("/micromips").flag("+m32").flag("+mmicromips"); - auto MArchDefault = makeMultilib("") - .flag("-mips16").flag("-mmicromips"); + auto MArchDefault = makeMultilib("").flag("-mips16").flag("-mmicromips"); - auto UCLibc = makeMultilib("/uclibc") - .flag("+muclibc"); + auto UCLibc = makeMultilib("/uclibc").flag("+muclibc"); - auto SoftFloat = makeMultilib("/soft-float") - .flag("+msoft-float"); + auto SoftFloat = makeMultilib("/soft-float").flag("+msoft-float"); - auto Nan2008 = makeMultilib("/nan2008") - .flag("+mnan=2008"); + auto Nan2008 = makeMultilib("/nan2008").flag("+mnan=2008"); - auto DefaultFloat = makeMultilib("") - .flag("-msoft-float").flag("-mnan=2008"); + auto DefaultFloat = + makeMultilib("").flag("-msoft-float").flag("-mnan=2008"); - auto BigEndian = makeMultilib("") - .flag("+EB").flag("-EL"); + auto BigEndian = makeMultilib("").flag("+EB").flag("-EL"); - auto LittleEndian = makeMultilib("/el") - .flag("+EL").flag("-EB"); + auto LittleEndian = makeMultilib("/el").flag("+EL").flag("-EB"); // Note that this one's osSuffix is "" auto MAbi64 = makeMultilib("") - .gccSuffix("/64") - .includeSuffix("/64") - .flag("+mabi=n64").flag("-mabi=n32").flag("-m32"); - - CSMipsMultilibs = MultilibSet() - .Either(MArchMips16, MArchMicroMips, MArchDefault) - .Maybe(UCLibc) - .Either(SoftFloat, Nan2008, DefaultFloat) - .FilterOut("/micromips/nan2008") - .FilterOut("/mips16/nan2008") - .Either(BigEndian, LittleEndian) - .Maybe(MAbi64) - .FilterOut("/mips16.*/64") - .FilterOut("/micromips.*/64") - .FilterOut(NonExistent) - .setIncludeDirsCallback([]( - StringRef InstallDir, StringRef TripleStr, const Multilib &M) { - std::vector<std::string> Dirs; - Dirs.push_back((InstallDir + "/include").str()); - std::string SysRootInc = - InstallDir.str() + "/../../../../" + TripleStr.str(); - if (StringRef(M.includeSuffix()).startswith("/uclibc")) - Dirs.push_back(SysRootInc + "/libc/uclibc/usr/include"); - else - Dirs.push_back(SysRootInc + "/libc/usr/include"); - return Dirs; - }); - } - - MultilibSet AndroidMipsMultilibs = MultilibSet() - .Maybe(Multilib("/mips-r2").flag("+march=mips32r2")) - .Maybe(Multilib("/mips-r6").flag("+march=mips32r6")) - .FilterOut(NonExistent); + .gccSuffix("/64") + .includeSuffix("/64") + .flag("+mabi=n64") + .flag("-mabi=n32") + .flag("-m32"); + + CSMipsMultilibs = + MultilibSet() + .Either(MArchMips16, MArchMicroMips, MArchDefault) + .Maybe(UCLibc) + .Either(SoftFloat, Nan2008, DefaultFloat) + .FilterOut("/micromips/nan2008") + .FilterOut("/mips16/nan2008") + .Either(BigEndian, LittleEndian) + .Maybe(MAbi64) + .FilterOut("/mips16.*/64") + .FilterOut("/micromips.*/64") + .FilterOut(NonExistent) + .setIncludeDirsCallback([](StringRef InstallDir, + StringRef TripleStr, const Multilib &M) { + std::vector<std::string> Dirs; + Dirs.push_back((InstallDir + "/include").str()); + std::string SysRootInc = + InstallDir.str() + "/../../../../" + TripleStr.str(); + if (StringRef(M.includeSuffix()).startswith("/uclibc")) + Dirs.push_back(SysRootInc + "/libc/uclibc/usr/include"); + else + Dirs.push_back(SysRootInc + "/libc/usr/include"); + return Dirs; + }); + } + + MultilibSet AndroidMipsMultilibs = + MultilibSet() + .Maybe(Multilib("/mips-r2").flag("+march=mips32r2")) + .Maybe(Multilib("/mips-r6").flag("+march=mips32r6")) + .FilterOut(NonExistent); MultilibSet DebianMipsMultilibs; { - Multilib MAbiN32 = Multilib() - .gccSuffix("/n32") - .includeSuffix("/n32") - .flag("+mabi=n32"); + Multilib MAbiN32 = + Multilib().gccSuffix("/n32").includeSuffix("/n32").flag("+mabi=n32"); Multilib M64 = Multilib() - .gccSuffix("/64") - .includeSuffix("/64") - .flag("+m64").flag("-m32").flag("-mabi=n32"); + .gccSuffix("/64") + .includeSuffix("/64") + .flag("+m64") + .flag("-m32") + .flag("-mabi=n32"); - Multilib M32 = Multilib() - .flag("-m64").flag("+m32").flag("-mabi=n32"); + Multilib M32 = Multilib().flag("-m64").flag("+m32").flag("-mabi=n32"); - DebianMipsMultilibs = MultilibSet() - .Either(M32, M64, MAbiN32) - .FilterOut(NonExistent); + DebianMipsMultilibs = + MultilibSet().Either(M32, M64, MAbiN32).FilterOut(NonExistent); } MultilibSet ImgMultilibs; { - auto Mips64r6 = makeMultilib("/mips64r6") - .flag("+m64").flag("-m32"); + auto Mips64r6 = makeMultilib("/mips64r6").flag("+m64").flag("-m32"); - auto LittleEndian = makeMultilib("/el") - .flag("+EL").flag("-EB"); + auto LittleEndian = makeMultilib("/el").flag("+EL").flag("-EB"); - auto MAbi64 = makeMultilib("/64") - .flag("+mabi=n64").flag("-mabi=n32").flag("-m32"); + auto MAbi64 = + makeMultilib("/64").flag("+mabi=n64").flag("-mabi=n32").flag("-m32"); - ImgMultilibs = MultilibSet() - .Maybe(Mips64r6) - .Maybe(MAbi64) - .Maybe(LittleEndian) - .FilterOut(NonExistent) - .setIncludeDirsCallback([]( - StringRef InstallDir, StringRef TripleStr, const Multilib &M) { - std::vector<std::string> Dirs; - Dirs.push_back((InstallDir + "/include").str()); - Dirs.push_back((InstallDir + "/../../../../sysroot/usr/include").str()); - return Dirs; - }); + ImgMultilibs = + MultilibSet() + .Maybe(Mips64r6) + .Maybe(MAbi64) + .Maybe(LittleEndian) + .FilterOut(NonExistent) + .setIncludeDirsCallback([](StringRef InstallDir, + StringRef TripleStr, const Multilib &M) { + std::vector<std::string> Dirs; + Dirs.push_back((InstallDir + "/include").str()); + Dirs.push_back( + (InstallDir + "/../../../../sysroot/usr/include").str()); + return Dirs; + }); } StringRef CPUName; @@ -1783,10 +1753,13 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path, addMultilibFlag(isMips64(TargetArch), "m64", Flags); addMultilibFlag(isMips16(Args), "mips16", Flags); addMultilibFlag(CPUName == "mips32", "march=mips32", Flags); - addMultilibFlag(CPUName == "mips32r2", "march=mips32r2", Flags); + addMultilibFlag(CPUName == "mips32r2" || CPUName == "mips32r3" || + CPUName == "mips32r5", + "march=mips32r2", Flags); addMultilibFlag(CPUName == "mips32r6", "march=mips32r6", Flags); addMultilibFlag(CPUName == "mips64", "march=mips64", Flags); - addMultilibFlag(CPUName == "mips64r2" || CPUName == "octeon", + addMultilibFlag(CPUName == "mips64r2" || CPUName == "mips64r3" || + CPUName == "mips64r5" || CPUName == "octeon", "march=mips64r2", Flags); addMultilibFlag(isMicroMips(Args), "mmicromips", Flags); addMultilibFlag(tools::mips::isUCLibc(Args), "muclibc", Flags); @@ -1821,8 +1794,8 @@ static bool findMIPSMultilibs(const llvm::Triple &TargetTriple, StringRef Path, // Sort candidates. Toolchain that best meets the directories goes first. // Then select the first toolchains matches command line flags. - MultilibSet *candidates[] = { &DebianMipsMultilibs, &FSFMipsMultilibs, - &CSMipsMultilibs }; + MultilibSet *candidates[] = {&DebianMipsMultilibs, &FSFMipsMultilibs, + &CSMipsMultilibs}; std::sort( std::begin(candidates), std::end(candidates), [](MultilibSet *a, MultilibSet *b) { return a->size() > b->size(); }); @@ -1864,17 +1837,23 @@ static bool findBiarchMultilibs(const llvm::Triple &TargetTriple, Multilib Default; Multilib Alt64 = Multilib() - .gccSuffix("/64") - .includeSuffix("/64") - .flag("-m32").flag("+m64").flag("-mx32"); + .gccSuffix("/64") + .includeSuffix("/64") + .flag("-m32") + .flag("+m64") + .flag("-mx32"); Multilib Alt32 = Multilib() - .gccSuffix("/32") - .includeSuffix("/32") - .flag("+m32").flag("-m64").flag("-mx32"); + .gccSuffix("/32") + .includeSuffix("/32") + .flag("+m32") + .flag("-m64") + .flag("-mx32"); Multilib Altx32 = Multilib() - .gccSuffix("/x32") - .includeSuffix("/x32") - .flag("-m32").flag("-m64").flag("+mx32"); + .gccSuffix("/x32") + .includeSuffix("/x32") + .flag("-m32") + .flag("-m64") + .flag("+mx32"); FilterNonExistent NonExistent(Path); @@ -1921,8 +1900,7 @@ static bool findBiarchMultilibs(const llvm::Triple &TargetTriple, if (!Result.Multilibs.select(Flags, Result.SelectedMultilib)) return false; - if (Result.SelectedMultilib == Alt64 || - Result.SelectedMultilib == Alt32 || + if (Result.SelectedMultilib == Alt64 || Result.SelectedMultilib == Alt32 || Result.SelectedMultilib == Altx32) Result.BiarchSibling = Default; @@ -1938,27 +1916,26 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( // 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(), - // Debian puts cross-compilers in gcc-cross - "/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(), - - // 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() - }; + "/gcc/" + CandidateTriple.str(), + // Debian puts cross-compilers in gcc-cross + "/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(), + + // 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>/ + "/../../..", // gcc/ + "/../../..", // gcc-cross/ + "/../../../..", // <triple>/gcc/ + "/../..", // <triple>/ + "/../../../.." // i386-linux-gnu/gcc/<triple>/ }; // Only look at the final, weird Ubuntu suffix for i386-linux-gnu. const unsigned NumLibSuffixes = @@ -2005,26 +1982,25 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( } } -Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple& Triple, +Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) - : ToolChain(D, Triple, Args), GCCInstallation() { + : ToolChain(D, Triple, Args), GCCInstallation() { getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().getInstalledDir() != getDriver().Dir) getProgramPaths().push_back(getDriver().Dir); } -Generic_GCC::~Generic_GCC() { -} +Generic_GCC::~Generic_GCC() {} Tool *Generic_GCC::getTool(Action::ActionClass AC) const { switch (AC) { case Action::PreprocessJobClass: if (!Preprocess) - Preprocess.reset(new tools::gcc::Preprocess(*this)); + Preprocess.reset(new tools::gcc::Preprocessor(*this)); return Preprocess.get(); case Action::CompileJobClass: if (!Compile) - Compile.reset(new tools::gcc::Compile(*this)); + Compile.reset(new tools::gcc::Compiler(*this)); return Compile.get(); default: return ToolChain::getTool(AC); @@ -2032,12 +2008,10 @@ Tool *Generic_GCC::getTool(Action::ActionClass AC) const { } Tool *Generic_GCC::buildAssembler() const { - return new tools::gnutools::Assemble(*this); + return new tools::gnutools::Assembler(*this); } -Tool *Generic_GCC::buildLinker() const { - return new tools::gcc::Link(*this); -} +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. @@ -2049,32 +2023,38 @@ bool Generic_GCC::IsUnwindTablesDefault() const { } bool Generic_GCC::isPICDefault() const { - return false; + return getArch() == llvm::Triple::x86_64 && getTriple().isOSWindows(); } -bool Generic_GCC::isPIEDefault() const { - return false; -} +bool Generic_GCC::isPIEDefault() const { return false; } bool Generic_GCC::isPICDefaultForced() const { - return false; + return getArch() == llvm::Triple::x86_64 && getTriple().isOSWindows(); } bool Generic_GCC::IsIntegratedAssemblerDefault() const { - return getTriple().getArch() == llvm::Triple::x86 || - getTriple().getArch() == llvm::Triple::x86_64 || - getTriple().getArch() == llvm::Triple::aarch64 || - getTriple().getArch() == llvm::Triple::aarch64_be || - getTriple().getArch() == llvm::Triple::arm || - getTriple().getArch() == llvm::Triple::armeb || - getTriple().getArch() == llvm::Triple::thumb || - getTriple().getArch() == llvm::Triple::thumbeb || - getTriple().getArch() == llvm::Triple::ppc || - getTriple().getArch() == llvm::Triple::ppc64 || - getTriple().getArch() == llvm::Triple::ppc64le || - getTriple().getArch() == llvm::Triple::sparc || - getTriple().getArch() == llvm::Triple::sparcv9 || - getTriple().getArch() == llvm::Triple::systemz; + switch (getTriple().getArch()) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + case llvm::Triple::aarch64: + case llvm::Triple::aarch64_be: + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::bpfel: + case llvm::Triple::bpfeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + 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: + return false; + } } void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs, @@ -2085,11 +2065,11 @@ void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs, getTriple().getArch() == llvm::Triple::aarch64_be || (getTriple().getOS() == llvm::Triple::Linux && (!V.isOlderThan(4, 7, 0) || - getTriple().getEnvironment() == llvm::Triple::Android)); + getTriple().getEnvironment() == llvm::Triple::Android)) || + getTriple().getOS() == llvm::Triple::NaCl; if (DriverArgs.hasFlag(options::OPT_fuse_init_array, - options::OPT_fno_use_init_array, - UseInitArrayDefault)) + options::OPT_fno_use_init_array, UseInitArrayDefault)) CC1Args.push_back("-fuse-init-array"); } @@ -2115,26 +2095,38 @@ std::string Hexagon_TC::GetGnuDir(const std::string &InstalledDir, return InstallRelDir; } -static void GetHexagonLibraryPaths( - const ArgList &Args, - const std::string &Ver, - const std::string &MarchString, - const std::string &InstalledDir, - ToolChain::path_list *LibPaths) -{ +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(); + + A = Args.getLastArg(options::OPT_shared, options::OPT_fpic, + options::OPT_fPIC); + if (A) + return "0"; + + return 0; +} + +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); //---------------------------------------------------------------------------- // -L Args //---------------------------------------------------------------------------- - for (arg_iterator - it = Args.filtered_begin(options::OPT_L), - ie = Args.filtered_end(); - it != ie; - ++it) { - for (unsigned i = 0, e = (*it)->getNumValues(); i != e; ++i) - LibPaths->push_back((*it)->getValue(i)); - } + for (Arg *A : Args.filtered(options::OPT_L)) + for (const char *Value : A->getValues()) + LibPaths->push_back(Value); //---------------------------------------------------------------------------- // Other standard paths @@ -2168,7 +2160,7 @@ static void GetHexagonLibraryPaths( Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) - : Linux(D, Triple, Args) { + : Linux(D, Triple, Args) { const std::string InstalledDir(getDriver().getInstalledDir()); const std::string GnuDir = Hexagon_TC::GetGnuDir(InstalledDir, Args); @@ -2181,7 +2173,7 @@ Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple &Triple, // 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"); + 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())); @@ -2190,30 +2182,25 @@ Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple &Triple, } 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); + GetHexagonLibraryPaths(Args, GetGCCLibAndIncVersion(), GetTargetCPU(Args), + InstalledDir, LibPaths); } -Hexagon_TC::~Hexagon_TC() { -} +Hexagon_TC::~Hexagon_TC() {} Tool *Hexagon_TC::buildAssembler() const { - return new tools::hexagon::Assemble(*this); + return new tools::hexagon::Assembler(*this); } Tool *Hexagon_TC::buildLinker() const { - return new tools::hexagon::Link(*this); + return new tools::hexagon::Linker(*this); } void Hexagon_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs, @@ -2246,7 +2233,7 @@ void Hexagon_TC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, llvm::sys::path::append(IncludeDir, "hexagon/include/c++/"); llvm::sys::path::append(IncludeDir, Ver); - addSystemInclude(DriverArgs, CC1Args, IncludeDir.str()); + addSystemInclude(DriverArgs, CC1Args, IncludeDir); } ToolChain::CXXStdlibType @@ -2257,8 +2244,7 @@ Hexagon_TC::GetCXXStdlibType(const ArgList &Args) const { StringRef Value = A->getValue(); if (Value != "libstdc++") { - getDriver().Diag(diag::err_drv_invalid_stdlib_name) - << A->getAsString(Args); + getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args); } return ToolChain::CST_Libstdcxx; @@ -2287,8 +2273,7 @@ static int getHexagonVersion(const ArgList &Args) { return 4; } -StringRef Hexagon_TC::GetTargetCPU(const ArgList &Args) -{ +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) { @@ -2308,13 +2293,187 @@ StringRef Hexagon_TC::GetTargetCPU(const ArgList &Args) } // End Hexagon +/// NaCl Toolchain +NaCl_TC::NaCl_TC(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 + // default paths, and must instead only use the paths provided + // with this toolchain based on architecture. + path_list &file_paths = getFilePaths(); + path_list &prog_paths = getProgramPaths(); + + file_paths.clear(); + prog_paths.clear(); + + // Path for library files (libc.a, ...) + std::string FilePath(getDriver().Dir + "/../"); + + // Path for tools (clang, ld, etc..) + std::string ProgPath(getDriver().Dir + "/../"); + + // Path for toolchain libraries (libgcc.a, ...) + std::string ToolPath(getDriver().ResourceDir + "/lib/"); + + switch (Triple.getArch()) { + case llvm::Triple::x86: { + file_paths.push_back(FilePath + "x86_64-nacl/lib32"); + file_paths.push_back(FilePath + "x86_64-nacl/usr/lib32"); + prog_paths.push_back(ProgPath + "x86_64-nacl/bin"); + file_paths.push_back(ToolPath + "i686-nacl"); + break; + } + 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: { + 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: { + 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 { + const Driver &D = getDriver(); + if (DriverArgs.hasArg(options::OPT_nostdinc)) + return; + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { + SmallString<128> P(D.ResourceDir); + llvm::sys::path::append(P, "include"); + addSystemInclude(DriverArgs, CC1Args, P.str()); + } + + if (DriverArgs.hasArg(options::OPT_nostdlibinc)) + return; + + SmallString<128> P(D.Dir + "/../"); + switch (getTriple().getArch()) { + 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; + case llvm::Triple::mipsel: + llvm::sys::path::append(P, "mipsel-nacl/usr/include"); + break; + default: + return; + } + + addSystemInclude(DriverArgs, CC1Args, P.str()); + llvm::sys::path::remove_filename(P); + llvm::sys::path::remove_filename(P); + llvm::sys::path::append(P, "include"); + addSystemInclude(DriverArgs, CC1Args, P.str()); +} + +void NaCl_TC::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 { + const Driver &D = getDriver(); + if (DriverArgs.hasArg(options::OPT_nostdlibinc) || + DriverArgs.hasArg(options::OPT_nostdincxx)) + return; + + // 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(DriverArgs); + + SmallString<128> P(D.Dir + "/../"); + switch (getTriple().getArch()) { + case llvm::Triple::arm: + llvm::sys::path::append(P, "arm-nacl/include/c++/v1"); + addSystemInclude(DriverArgs, CC1Args, P.str()); + break; + case llvm::Triple::x86: + llvm::sys::path::append(P, "x86_64-nacl/include/c++/v1"); + addSystemInclude(DriverArgs, CC1Args, P.str()); + break; + case llvm::Triple::x86_64: + llvm::sys::path::append(P, "x86_64-nacl/include/c++/v1"); + addSystemInclude(DriverArgs, CC1Args, P.str()); + break; + case llvm::Triple::mipsel: + llvm::sys::path::append(P, "mipsel-nacl/include/c++/v1"); + addSystemInclude(DriverArgs, CC1Args, P.str()); + break; + default: + break; + } +} + +ToolChain::CXXStdlibType NaCl_TC::GetCXXStdlibType(const ArgList &Args) const { + if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { + StringRef Value = A->getValue(); + if (Value == "libc++") + return ToolChain::CST_Libcxx; + getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args); + } + + return ToolChain::CST_Libcxx; +} + +std::string NaCl_TC::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) + TheTriple.setEnvironment(llvm::Triple::GNUEABIHF); + return TheTriple.getTriple(); +} + +Tool *NaCl_TC::buildLinker() const { + return new tools::nacltools::Linker(*this); +} + +Tool *NaCl_TC::buildAssembler() const { + if (getTriple().getArch() == llvm::Triple::arm) + return new tools::nacltools::AssemblerARM(*this); + return new tools::gnutools::Assembler(*this); +} +// End NaCl + /// TCEToolChain - A tool chain using the llvm bitcode tools to perform /// all subcommands. See http://tce.cs.tut.fi for our peculiar target. /// Currently does not support anything else but compilation. -TCEToolChain::TCEToolChain(const Driver &D, const llvm::Triple& Triple, +TCEToolChain::TCEToolChain(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) - : ToolChain(D, Triple, Args) { + : ToolChain(D, Triple, Args) { // Path mangling to find libexec std::string Path(getDriver().Dir); @@ -2322,59 +2481,78 @@ TCEToolChain::TCEToolChain(const Driver &D, const llvm::Triple& Triple, getProgramPaths().push_back(Path); } -TCEToolChain::~TCEToolChain() { -} +TCEToolChain::~TCEToolChain() {} -bool TCEToolChain::IsMathErrnoDefault() const { - return true; +bool TCEToolChain::IsMathErrnoDefault() const { return true; } + +bool TCEToolChain::isPICDefault() const { return false; } + +bool TCEToolChain::isPIEDefault() const { return false; } + +bool TCEToolChain::isPICDefaultForced() const { return false; } + +// CloudABI - CloudABI tool chain which can call ld(1) directly. + +CloudABI::CloudABI(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : Generic_ELF(D, Triple, Args) { + SmallString<128> P(getDriver().Dir); + llvm::sys::path::append(P, "..", getTriple().str(), "lib"); + getFilePaths().push_back(P.str()); } -bool TCEToolChain::isPICDefault() const { - return false; +void CloudABI::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdlibinc) && + DriverArgs.hasArg(options::OPT_nostdincxx)) + return; + + SmallString<128> P(getDriver().Dir); + llvm::sys::path::append(P, "..", getTriple().str(), "include/c++/v1"); + addSystemInclude(DriverArgs, CC1Args, P.str()); } -bool TCEToolChain::isPIEDefault() const { - return false; +void CloudABI::AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + CmdArgs.push_back("-lc++"); + CmdArgs.push_back("-lc++abi"); + CmdArgs.push_back("-lunwind"); } -bool TCEToolChain::isPICDefaultForced() const { - return false; +Tool *CloudABI::buildLinker() const { + return new tools::cloudabi::Linker(*this); } /// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly. -OpenBSD::OpenBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) - : Generic_ELF(D, Triple, Args) { +OpenBSD::OpenBSD(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : Generic_ELF(D, Triple, Args) { getFilePaths().push_back(getDriver().Dir + "/../lib"); getFilePaths().push_back("/usr/lib"); } Tool *OpenBSD::buildAssembler() const { - return new tools::openbsd::Assemble(*this); + return new tools::openbsd::Assembler(*this); } -Tool *OpenBSD::buildLinker() const { - return new tools::openbsd::Link(*this); -} +Tool *OpenBSD::buildLinker() const { return new tools::openbsd::Linker(*this); } /// Bitrig - Bitrig tool chain which can call as(1) and ld(1) directly. -Bitrig::Bitrig(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) - : Generic_ELF(D, Triple, Args) { +Bitrig::Bitrig(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) + : Generic_ELF(D, Triple, Args) { getFilePaths().push_back(getDriver().Dir + "/../lib"); getFilePaths().push_back("/usr/lib"); } Tool *Bitrig::buildAssembler() const { - return new tools::bitrig::Assemble(*this); + return new tools::bitrig::Assembler(*this); } -Tool *Bitrig::buildLinker() const { - return new tools::bitrig::Link(*this); -} +Tool *Bitrig::buildLinker() const { return new tools::bitrig::Linker(*this); } -ToolChain::CXXStdlibType -Bitrig::GetCXXStdlibType(const ArgList &Args) const { +ToolChain::CXXStdlibType Bitrig::GetCXXStdlibType(const ArgList &Args) const { if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { StringRef Value = A->getValue(); if (Value == "libstdc++") @@ -2382,8 +2560,7 @@ Bitrig::GetCXXStdlibType(const ArgList &Args) const { if (Value == "libc++") return ToolChain::CST_Libcxx; - getDriver().Diag(diag::err_drv_invalid_stdlib_name) - << A->getAsString(Args); + getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args); } return ToolChain::CST_Libcxx; } @@ -2409,11 +2586,11 @@ void Bitrig::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, if (Triple.startswith("amd64")) addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/usr/include/c++/stdc++/x86_64" + - Triple.substr(5)); + Triple.substr(5)); else - addSystemInclude(DriverArgs, CC1Args, - getDriver().SysRoot + "/usr/include/c++/stdc++/" + - Triple); + addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + + "/usr/include/c++/stdc++/" + + Triple); break; } } @@ -2434,8 +2611,9 @@ void Bitrig::AddCXXStdlibLibArgs(const ArgList &Args, /// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly. -FreeBSD::FreeBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) - : Generic_ELF(D, Triple, Args) { +FreeBSD::FreeBSD(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : Generic_ELF(D, Triple, Args) { // When targeting 32-bit platforms, look for '/usr/lib32/crt1.o' and fall // back to '/usr/lib' if it doesn't exist. @@ -2447,8 +2625,7 @@ FreeBSD::FreeBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Arg getFilePaths().push_back(getDriver().SysRoot + "/usr/lib"); } -ToolChain::CXXStdlibType -FreeBSD::GetCXXStdlibType(const ArgList &Args) const { +ToolChain::CXXStdlibType FreeBSD::GetCXXStdlibType(const ArgList &Args) const { if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { StringRef Value = A->getValue(); if (Value == "libstdc++") @@ -2456,10 +2633,9 @@ FreeBSD::GetCXXStdlibType(const ArgList &Args) const { if (Value == "libc++") return ToolChain::CST_Libcxx; - getDriver().Diag(diag::err_drv_invalid_stdlib_name) - << A->getAsString(Args); + getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args); } - if (getTriple().getOSMajorVersion() >= 10) + if (getTriple().getOSMajorVersion() >= 10) return ToolChain::CST_Libcxx; return ToolChain::CST_Libstdcxx; } @@ -2485,12 +2661,10 @@ void FreeBSD::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, } Tool *FreeBSD::buildAssembler() const { - return new tools::freebsd::Assemble(*this); + return new tools::freebsd::Assembler(*this); } -Tool *FreeBSD::buildLinker() const { - return new tools::freebsd::Link(*this); -} +Tool *FreeBSD::buildLinker() const { return new tools::freebsd::Linker(*this); } bool FreeBSD::UseSjLjExceptions() const { // FreeBSD uses SjLj exceptions on ARM oabi. @@ -2506,18 +2680,32 @@ bool FreeBSD::UseSjLjExceptions() const { } } -bool FreeBSD::HasNativeLLVMSupport() const { - return true; -} +bool FreeBSD::HasNativeLLVMSupport() const { return true; } + +bool FreeBSD::isPIEDefault() const { return getSanitizerArgs().requiresPIE(); } -bool FreeBSD::isPIEDefault() const { - return getSanitizerArgs().requiresPIE(); +SanitizerMask FreeBSD::getSupportedSanitizers() const { + const bool IsX86 = getTriple().getArch() == llvm::Triple::x86; + const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; + const bool IsMIPS64 = getTriple().getArch() == llvm::Triple::mips64 || + getTriple().getArch() == llvm::Triple::mips64el; + SanitizerMask Res = ToolChain::getSupportedSanitizers(); + Res |= SanitizerKind::Address; + Res |= SanitizerKind::Vptr; + if (IsX86_64 || IsMIPS64) { + Res |= SanitizerKind::Leak; + Res |= SanitizerKind::Thread; + } + if (IsX86 || IsX86_64) { + Res |= SanitizerKind::SafeStack; + } + return Res; } /// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly. -NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) - : Generic_ELF(D, Triple, Args) { +NetBSD::NetBSD(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) + : Generic_ELF(D, Triple, Args) { if (getDriver().UseStdLib) { // When targeting a 32-bit platform, try the special directory used on @@ -2569,15 +2757,12 @@ NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) } Tool *NetBSD::buildAssembler() const { - return new tools::netbsd::Assemble(*this); + return new tools::netbsd::Assembler(*this); } -Tool *NetBSD::buildLinker() const { - return new tools::netbsd::Link(*this); -} +Tool *NetBSD::buildLinker() const { return new tools::netbsd::Linker(*this); } -ToolChain::CXXStdlibType -NetBSD::GetCXXStdlibType(const ArgList &Args) const { +ToolChain::CXXStdlibType NetBSD::GetCXXStdlibType(const ArgList &Args) const { if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { StringRef Value = A->getValue(); if (Value == "libstdc++") @@ -2585,8 +2770,7 @@ NetBSD::GetCXXStdlibType(const ArgList &Args) const { if (Value == "libc++") return ToolChain::CST_Libcxx; - getDriver().Diag(diag::err_drv_invalid_stdlib_name) - << A->getAsString(Args); + getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args); } unsigned Major, Minor, Micro; @@ -2633,25 +2817,23 @@ void NetBSD::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, /// Minix - Minix tool chain which can call as(1) and ld(1) directly. -Minix::Minix(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) - : Generic_ELF(D, Triple, Args) { +Minix::Minix(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) + : Generic_ELF(D, Triple, Args) { getFilePaths().push_back(getDriver().Dir + "/../lib"); getFilePaths().push_back("/usr/lib"); } Tool *Minix::buildAssembler() const { - return new tools::minix::Assemble(*this); + return new tools::minix::Assembler(*this); } -Tool *Minix::buildLinker() const { - return new tools::minix::Link(*this); -} +Tool *Minix::buildLinker() const { return new tools::minix::Linker(*this); } /// Solaris - Solaris tool chain which can call as(1) and ld(1) directly. -Solaris::Solaris(const Driver &D, const llvm::Triple& Triple, +Solaris::Solaris(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) - : Generic_GCC(D, Triple, Args) { + : Generic_GCC(D, Triple, Args) { getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().getInstalledDir() != getDriver().Dir) @@ -2662,25 +2844,28 @@ Solaris::Solaris(const Driver &D, const llvm::Triple& Triple, } Tool *Solaris::buildAssembler() const { - return new tools::solaris::Assemble(*this); + return new tools::solaris::Assembler(*this); } -Tool *Solaris::buildLinker() const { - return new tools::solaris::Link(*this); -} +Tool *Solaris::buildLinker() const { return new tools::solaris::Linker(*this); } /// Distribution (very bare-bones at the moment). enum Distro { + // NB: Releases of a particular Linux distro should be kept together + // in this enum, because some tests are done by integer comparison against + // the first and last known member in the family, e.g. IsRedHat(). ArchLinux, DebianLenny, DebianSqueeze, DebianWheezy, DebianJessie, + DebianStretch, Exherbo, RHEL4, RHEL5, RHEL6, + RHEL7, Fedora, OpenSUSE, UbuntuHardy, @@ -2696,23 +2881,24 @@ enum Distro { UbuntuRaring, UbuntuSaucy, UbuntuTrusty, + UbuntuUtopic, + UbuntuVivid, + UbuntuWily, UnknownDistro }; static bool IsRedhat(enum Distro Distro) { - return Distro == Fedora || (Distro >= RHEL4 && Distro <= RHEL6); + return Distro == Fedora || (Distro >= RHEL4 && Distro <= RHEL7); } -static bool IsOpenSUSE(enum Distro Distro) { - return Distro == OpenSUSE; -} +static bool IsOpenSUSE(enum Distro Distro) { return Distro == OpenSUSE; } static bool IsDebian(enum Distro Distro) { - return Distro >= DebianLenny && Distro <= DebianJessie; + return Distro >= DebianLenny && Distro <= DebianStretch; } static bool IsUbuntu(enum Distro Distro) { - return Distro >= UbuntuHardy && Distro <= UbuntuTrusty; + return Distro >= UbuntuHardy && Distro <= UbuntuWily; } static Distro DetectDistro(llvm::Triple::ArchType Arch) { @@ -2723,23 +2909,26 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) { SmallVector<StringRef, 16> Lines; Data.split(Lines, "\n"); Distro Version = UnknownDistro; - for (unsigned i = 0, s = Lines.size(); i != s; ++i) - if (Version == UnknownDistro && Lines[i].startswith("DISTRIB_CODENAME=")) - Version = llvm::StringSwitch<Distro>(Lines[i].substr(17)) - .Case("hardy", UbuntuHardy) - .Case("intrepid", UbuntuIntrepid) - .Case("jaunty", UbuntuJaunty) - .Case("karmic", UbuntuKarmic) - .Case("lucid", UbuntuLucid) - .Case("maverick", UbuntuMaverick) - .Case("natty", UbuntuNatty) - .Case("oneiric", UbuntuOneiric) - .Case("precise", UbuntuPrecise) - .Case("quantal", UbuntuQuantal) - .Case("raring", UbuntuRaring) - .Case("saucy", UbuntuSaucy) - .Case("trusty", UbuntuTrusty) - .Default(UnknownDistro); + for (const StringRef Line : Lines) + if (Version == UnknownDistro && Line.startswith("DISTRIB_CODENAME=")) + Version = llvm::StringSwitch<Distro>(Line.substr(17)) + .Case("hardy", UbuntuHardy) + .Case("intrepid", UbuntuIntrepid) + .Case("jaunty", UbuntuJaunty) + .Case("karmic", UbuntuKarmic) + .Case("lucid", UbuntuLucid) + .Case("maverick", UbuntuMaverick) + .Case("natty", UbuntuNatty) + .Case("oneiric", UbuntuOneiric) + .Case("precise", UbuntuPrecise) + .Case("quantal", UbuntuQuantal) + .Case("raring", UbuntuRaring) + .Case("saucy", UbuntuSaucy) + .Case("trusty", UbuntuTrusty) + .Case("utopic", UbuntuUtopic) + .Case("vivid", UbuntuVivid) + .Case("wily", UbuntuWily) + .Default(UnknownDistro); return Version; } @@ -2750,7 +2939,9 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) { return Fedora; if (Data.startswith("Red Hat Enterprise Linux") || Data.startswith("CentOS")) { - if (Data.find("release 6") != StringRef::npos) + if (Data.find("release 7") != StringRef::npos) + return RHEL7; + else if (Data.find("release 6") != StringRef::npos) return RHEL6; else if (Data.find("release 5") != StringRef::npos) return RHEL5; @@ -2767,10 +2958,12 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) { return DebianLenny; else if (Data.startswith("squeeze/sid") || Data[0] == '6') return DebianSqueeze; - else if (Data.startswith("wheezy/sid") || Data[0] == '7') + else if (Data.startswith("wheezy/sid") || Data[0] == '7') return DebianWheezy; - else if (Data.startswith("jessie/sid") || Data[0] == '8') + else if (Data.startswith("jessie/sid") || Data[0] == '8') return DebianJessie; + else if (Data.startswith("stretch/sid") || Data[0] == '9') + return DebianStretch; return UnknownDistro; } @@ -2794,92 +2987,105 @@ static Distro DetectDistro(llvm::Triple::ArchType Arch) { /// so we provide a rough mapping here. static std::string getMultiarchTriple(const llvm::Triple &TargetTriple, StringRef SysRoot) { + llvm::Triple::EnvironmentType TargetEnvironment = TargetTriple.getEnvironment(); + // For most architectures, just use whatever we have rather than trying to be // clever. switch (TargetTriple.getArch()) { default: - return TargetTriple.str(); + break; - // We use the existence of '/lib/<triple>' as a directory to detect some - // common linux triples that don't quite match the Clang triple for both - // 32-bit and 64-bit targets. Multiarch fixes its install triples to these - // regardless of what the actual target triple is. + // We use the existence of '/lib/<triple>' as a directory to detect some + // common linux triples that don't quite match the Clang triple for both + // 32-bit and 64-bit targets. Multiarch fixes its install triples to these + // regardless of what the actual target triple is. case llvm::Triple::arm: case llvm::Triple::thumb: - if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) { + if (TargetEnvironment == llvm::Triple::GNUEABIHF) { if (llvm::sys::fs::exists(SysRoot + "/lib/arm-linux-gnueabihf")) return "arm-linux-gnueabihf"; } else { if (llvm::sys::fs::exists(SysRoot + "/lib/arm-linux-gnueabi")) return "arm-linux-gnueabi"; } - return TargetTriple.str(); + break; case llvm::Triple::armeb: case llvm::Triple::thumbeb: - if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) { + if (TargetEnvironment == llvm::Triple::GNUEABIHF) { if (llvm::sys::fs::exists(SysRoot + "/lib/armeb-linux-gnueabihf")) return "armeb-linux-gnueabihf"; } else { if (llvm::sys::fs::exists(SysRoot + "/lib/armeb-linux-gnueabi")) return "armeb-linux-gnueabi"; } - return TargetTriple.str(); + break; case llvm::Triple::x86: if (llvm::sys::fs::exists(SysRoot + "/lib/i386-linux-gnu")) return "i386-linux-gnu"; - return TargetTriple.str(); + break; case llvm::Triple::x86_64: // We don't want this for x32, otherwise it will match x86_64 libs - if (TargetTriple.getEnvironment() != llvm::Triple::GNUX32 && + if (TargetEnvironment != llvm::Triple::GNUX32 && llvm::sys::fs::exists(SysRoot + "/lib/x86_64-linux-gnu")) return "x86_64-linux-gnu"; - return TargetTriple.str(); + break; case llvm::Triple::aarch64: if (llvm::sys::fs::exists(SysRoot + "/lib/aarch64-linux-gnu")) return "aarch64-linux-gnu"; - return TargetTriple.str(); + break; case llvm::Triple::aarch64_be: if (llvm::sys::fs::exists(SysRoot + "/lib/aarch64_be-linux-gnu")) return "aarch64_be-linux-gnu"; - return TargetTriple.str(); + break; case llvm::Triple::mips: if (llvm::sys::fs::exists(SysRoot + "/lib/mips-linux-gnu")) return "mips-linux-gnu"; - return TargetTriple.str(); + break; case llvm::Triple::mipsel: if (llvm::sys::fs::exists(SysRoot + "/lib/mipsel-linux-gnu")) return "mipsel-linux-gnu"; - return TargetTriple.str(); + break; case llvm::Triple::mips64: if (llvm::sys::fs::exists(SysRoot + "/lib/mips64-linux-gnu")) return "mips64-linux-gnu"; if (llvm::sys::fs::exists(SysRoot + "/lib/mips64-linux-gnuabi64")) return "mips64-linux-gnuabi64"; - return TargetTriple.str(); + break; case llvm::Triple::mips64el: if (llvm::sys::fs::exists(SysRoot + "/lib/mips64el-linux-gnu")) return "mips64el-linux-gnu"; if (llvm::sys::fs::exists(SysRoot + "/lib/mips64el-linux-gnuabi64")) return "mips64el-linux-gnuabi64"; - return TargetTriple.str(); + break; case llvm::Triple::ppc: if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc-linux-gnuspe")) return "powerpc-linux-gnuspe"; if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc-linux-gnu")) return "powerpc-linux-gnu"; - return TargetTriple.str(); + break; case llvm::Triple::ppc64: if (llvm::sys::fs::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")) return "powerpc64le-linux-gnu"; - return TargetTriple.str(); + break; + case llvm::Triple::sparc: + if (llvm::sys::fs::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")) + return "sparc64-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()); + if (llvm::sys::fs::exists(Path)) + Paths.push_back(Path.str()); } static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) { @@ -2913,7 +3119,7 @@ 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) { + : Generic_ELF(D, Triple, Args) { GCCInstallation.init(D, Triple, Args); Multilibs = GCCInstallation.getMultilibs(); llvm::Triple::ArchType Arch = Triple.getArch(); @@ -2929,7 +3135,8 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // FIXME: This seems unlikely to be Linux-specific. ToolChain::path_list &PPaths = getProgramPaths(); PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" + - GCCInstallation.getTriple().str() + "/bin").str()); + GCCInstallation.getTriple().str() + "/bin") + .str()); Linker = GetLinkerPath(); @@ -2967,8 +3174,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) if (IsRedhat(Distro)) ExtraOpts.push_back("--no-add-needed"); - if (Distro == DebianSqueeze || Distro == DebianWheezy || - Distro == DebianJessie || IsOpenSUSE(Distro) || + if ((IsDebian(Distro) && Distro >= DebianSqueeze) || IsOpenSUSE(Distro) || (IsRedhat(Distro) && Distro != RHEL4 && Distro != RHEL5) || (IsUbuntu(Distro) && Distro >= UbuntuKarmic)) ExtraOpts.push_back("--build-id"); @@ -2994,8 +3200,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((GCCInstallation.getInstallPath() + Multilib.gccSuffix()), Paths); // GCC cross compiling toolchains will install target libraries which ship @@ -3017,7 +3222,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // Note that this matches the GCC behavior. See the below comment for where // Clang diverges from GCC's behavior. addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib/../" + OSLibDir + - Multilib.osSuffix(), + Multilib.osSuffix(), Paths); // If the GCC installation we found is inside of the sysroot, we want to @@ -3054,13 +3259,14 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // installations with strange symlinks. if (GCCInstallation.isValid()) { addPathIfExists(SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() + - "/../../" + OSLibDir, Paths); + "/../../" + OSLibDir, + Paths); // Add the 'other' biarch variant path Multilib BiarchSibling; if (GCCInstallation.getBiarchSibling(BiarchSibling)) { - addPathIfExists(GCCInstallation.getInstallPath() + - BiarchSibling.gccSuffix(), Paths); + addPathIfExists( + GCCInstallation.getInstallPath() + BiarchSibling.gccSuffix(), Paths); } // See comments above on the multilib variant for details of why this is @@ -3068,8 +3274,9 @@ 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(), Paths); + addPathIfExists(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. @@ -3089,16 +3296,12 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) addPathIfExists(SysRoot + "/usr/lib", Paths); } -bool Linux::HasNativeLLVMSupport() const { - return true; -} +bool Linux::HasNativeLLVMSupport() const { return true; } -Tool *Linux::buildLinker() const { - return new tools::gnutools::Link(*this); -} +Tool *Linux::buildLinker() const { return new tools::gnutools::Linker(*this); } Tool *Linux::buildAssembler() const { - return new tools::gnutools::Assemble(*this); + return new tools::gnutools::Assembler(*this); } std::string Linux::computeSysRoot() const { @@ -3116,8 +3319,9 @@ std::string Linux::computeSysRoot() const { const StringRef TripleStr = GCCInstallation.getTriple().str(); const Multilib &Multilib = GCCInstallation.getMultilib(); - std::string Path = (InstallDir + "/../../../../" + TripleStr + "/libc" + - Multilib.osSuffix()).str(); + std::string Path = + (InstallDir + "/../../../../" + TripleStr + "/libc" + Multilib.osSuffix()) + .str(); if (llvm::sys::fs::exists(Path)) return Path; @@ -3144,7 +3348,7 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { SmallString<128> P(D.ResourceDir); llvm::sys::path::append(P, "include"); - addSystemInclude(DriverArgs, CC1Args, P.str()); + addSystemInclude(DriverArgs, CC1Args, P); } if (DriverArgs.hasArg(options::OPT_nostdlibinc)) @@ -3168,7 +3372,7 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, // Add include directories specific to the selected multilib set and multilib. if (GCCInstallation.isValid()) { - auto Callback = Multilibs.includeDirsCallback(); + const auto &Callback = Multilibs.includeDirsCallback(); if (Callback) { const auto IncludePaths = Callback(GCCInstallation.getInstallPath(), GCCInstallation.getTriple().str(), @@ -3180,81 +3384,91 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, // Implement generic Debian multiarch support. const StringRef X86_64MultiarchIncludeDirs[] = { - "/usr/include/x86_64-linux-gnu", + "/usr/include/x86_64-linux-gnu", - // FIXME: These are older forms of multiarch. It's not clear that they're - // in use in any released version of Debian, so we should consider - // removing them. - "/usr/include/i686-linux-gnu/64", "/usr/include/i486-linux-gnu/64" - }; + // FIXME: These are older forms of multiarch. It's not clear that they're + // in use in any released version of Debian, so we should consider + // removing them. + "/usr/include/i686-linux-gnu/64", "/usr/include/i486-linux-gnu/64"}; const StringRef X86MultiarchIncludeDirs[] = { - "/usr/include/i386-linux-gnu", + "/usr/include/i386-linux-gnu", - // FIXME: These are older forms of multiarch. It's not clear that they're - // in use in any released version of Debian, so we should consider - // removing them. - "/usr/include/x86_64-linux-gnu/32", "/usr/include/i686-linux-gnu", - "/usr/include/i486-linux-gnu" - }; + // FIXME: These are older forms of multiarch. It's not clear that they're + // in use in any released version of Debian, so we should consider + // removing them. + "/usr/include/x86_64-linux-gnu/32", "/usr/include/i686-linux-gnu", + "/usr/include/i486-linux-gnu"}; const StringRef AArch64MultiarchIncludeDirs[] = { - "/usr/include/aarch64-linux-gnu" - }; + "/usr/include/aarch64-linux-gnu"}; const StringRef ARMMultiarchIncludeDirs[] = { - "/usr/include/arm-linux-gnueabi" - }; + "/usr/include/arm-linux-gnueabi"}; const StringRef ARMHFMultiarchIncludeDirs[] = { - "/usr/include/arm-linux-gnueabihf" - }; - const StringRef MIPSMultiarchIncludeDirs[] = { - "/usr/include/mips-linux-gnu" - }; + "/usr/include/arm-linux-gnueabihf"}; + const StringRef MIPSMultiarchIncludeDirs[] = {"/usr/include/mips-linux-gnu"}; const StringRef MIPSELMultiarchIncludeDirs[] = { - "/usr/include/mipsel-linux-gnu" - }; + "/usr/include/mipsel-linux-gnu"}; const StringRef MIPS64MultiarchIncludeDirs[] = { - "/usr/include/mips64-linux-gnu", - "/usr/include/mips64-linux-gnuabi64" - }; + "/usr/include/mips64-linux-gnu", "/usr/include/mips64-linux-gnuabi64"}; const StringRef MIPS64ELMultiarchIncludeDirs[] = { - "/usr/include/mips64el-linux-gnu", - "/usr/include/mips64el-linux-gnuabi64" - }; + "/usr/include/mips64el-linux-gnu", + "/usr/include/mips64el-linux-gnuabi64"}; const StringRef PPCMultiarchIncludeDirs[] = { - "/usr/include/powerpc-linux-gnu" - }; + "/usr/include/powerpc-linux-gnu"}; const StringRef PPC64MultiarchIncludeDirs[] = { - "/usr/include/powerpc64-linux-gnu" - }; + "/usr/include/powerpc64-linux-gnu"}; const StringRef PPC64LEMultiarchIncludeDirs[] = { - "/usr/include/powerpc64le-linux-gnu" - }; + "/usr/include/powerpc64le-linux-gnu"}; + const StringRef SparcMultiarchIncludeDirs[] = { + "/usr/include/sparc-linux-gnu"}; + const StringRef Sparc64MultiarchIncludeDirs[] = { + "/usr/include/sparc64-linux-gnu"}; ArrayRef<StringRef> MultiarchIncludeDirs; - if (getTriple().getArch() == llvm::Triple::x86_64) { + switch (getTriple().getArch()) { + case llvm::Triple::x86_64: MultiarchIncludeDirs = X86_64MultiarchIncludeDirs; - } else if (getTriple().getArch() == llvm::Triple::x86) { + break; + case llvm::Triple::x86: MultiarchIncludeDirs = X86MultiarchIncludeDirs; - } else if (getTriple().getArch() == llvm::Triple::aarch64 || - getTriple().getArch() == llvm::Triple::aarch64_be) { + break; + case llvm::Triple::aarch64: + case llvm::Triple::aarch64_be: MultiarchIncludeDirs = AArch64MultiarchIncludeDirs; - } else if (getTriple().getArch() == llvm::Triple::arm) { + break; + case llvm::Triple::arm: if (getTriple().getEnvironment() == llvm::Triple::GNUEABIHF) MultiarchIncludeDirs = ARMHFMultiarchIncludeDirs; else MultiarchIncludeDirs = ARMMultiarchIncludeDirs; - } else if (getTriple().getArch() == llvm::Triple::mips) { + break; + case llvm::Triple::mips: MultiarchIncludeDirs = MIPSMultiarchIncludeDirs; - } else if (getTriple().getArch() == llvm::Triple::mipsel) { + break; + case llvm::Triple::mipsel: MultiarchIncludeDirs = MIPSELMultiarchIncludeDirs; - } else if (getTriple().getArch() == llvm::Triple::mips64) { + break; + case llvm::Triple::mips64: MultiarchIncludeDirs = MIPS64MultiarchIncludeDirs; - } else if (getTriple().getArch() == llvm::Triple::mips64el) { + break; + case llvm::Triple::mips64el: MultiarchIncludeDirs = MIPS64ELMultiarchIncludeDirs; - } else if (getTriple().getArch() == llvm::Triple::ppc) { + break; + case llvm::Triple::ppc: MultiarchIncludeDirs = PPCMultiarchIncludeDirs; - } else if (getTriple().getArch() == llvm::Triple::ppc64) { + break; + case llvm::Triple::ppc64: MultiarchIncludeDirs = PPC64MultiarchIncludeDirs; - } else if (getTriple().getArch() == llvm::Triple::ppc64le) { + break; + case llvm::Triple::ppc64le: MultiarchIncludeDirs = PPC64LEMultiarchIncludeDirs; + break; + case llvm::Triple::sparc: + MultiarchIncludeDirs = SparcMultiarchIncludeDirs; + break; + case llvm::Triple::sparcv9: + MultiarchIncludeDirs = Sparc64MultiarchIncludeDirs; + break; + default: + break; } for (StringRef Dir : MultiarchIncludeDirs) { if (llvm::sys::fs::exists(SysRoot + Dir)) { @@ -3275,13 +3489,10 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, } /// \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) { +/*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; @@ -3319,15 +3530,15 @@ 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", - - // 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" - }; + // 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", + + // 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"}; for (const auto &IncludePath : LibCXXIncludePathCandidates) { if (!llvm::sys::fs::exists(IncludePath)) continue; @@ -3358,24 +3569,24 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, // The primary search for libstdc++ supports multiarch variants. if (addLibStdCXXIncludePaths(LibDir.str() + "/../include", - "/c++/" + Version.Text, TripleStr, GCCMultiarchTriple, - TargetMultiarchTriple, + "/c++/" + Version.Text, TripleStr, + GCCMultiarchTriple, TargetMultiarchTriple, Multilib.includeSuffix(), DriverArgs, CC1Args)) return; // Otherwise, fall back on a bunch of options which don't use multiarch // layouts for simplicity. const std::string LibStdCXXIncludePathCandidates[] = { - // Gentoo is weird and places its headers inside the GCC install, so if the - // first attempt to find the headers fails, try these patterns. - InstallDir.str() + "/include/g++-v" + Version.MajorStr + "." + - Version.MinorStr, - InstallDir.str() + "/include/g++-v" + Version.MajorStr, - // Android standalone toolchain has C++ headers in yet another place. - LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text, - // Freescale SDK C++ headers are directly in <sysroot>/usr/include/c++, - // without a subdirectory corresponding to the gcc version. - LibDir.str() + "/../include/c++", + // Gentoo is weird and places its headers inside the GCC install, + // so if the first attempt to find the headers fails, try these patterns. + InstallDir.str() + "/include/g++-v" + Version.MajorStr + "." + + Version.MinorStr, + InstallDir.str() + "/include/g++-v" + Version.MajorStr, + // Android standalone toolchain has C++ headers in yet another place. + LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text, + // Freescale SDK C++ headers are directly in <sysroot>/usr/include/c++, + // without a subdirectory corresponding to the gcc version. + LibDir.str() + "/../include/c++", }; for (const auto &IncludePath : LibStdCXXIncludePathCandidates) { @@ -3387,14 +3598,38 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, } } -bool Linux::isPIEDefault() const { - return getSanitizerArgs().requiresPIE(); +bool Linux::isPIEDefault() const { return getSanitizerArgs().requiresPIE(); } + +SanitizerMask Linux::getSupportedSanitizers() const { + const bool IsX86 = getTriple().getArch() == llvm::Triple::x86; + const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; + const bool IsMIPS64 = getTriple().getArch() == llvm::Triple::mips64 || + getTriple().getArch() == llvm::Triple::mips64el; + const bool IsPowerPC64 = getTriple().getArch() == llvm::Triple::ppc64 || + getTriple().getArch() == llvm::Triple::ppc64le; + SanitizerMask Res = ToolChain::getSupportedSanitizers(); + Res |= SanitizerKind::Address; + Res |= SanitizerKind::KernelAddress; + Res |= SanitizerKind::Vptr; + if (IsX86_64 || IsMIPS64) { + Res |= SanitizerKind::DataFlow; + Res |= SanitizerKind::Leak; + Res |= SanitizerKind::Thread; + } + if (IsX86_64 || IsMIPS64 || IsPowerPC64) + Res |= SanitizerKind::Memory; + if (IsX86 || IsX86_64) { + Res |= SanitizerKind::Function; + Res |= SanitizerKind::SafeStack; + } + return Res; } /// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly. -DragonFly::DragonFly(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) - : Generic_ELF(D, Triple, Args) { +DragonFly::DragonFly(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : Generic_ELF(D, Triple, Args) { // Path mangling to find libexec getProgramPaths().push_back(getDriver().getInstalledDir()); @@ -3410,47 +3645,93 @@ DragonFly::DragonFly(const Driver &D, const llvm::Triple& Triple, const ArgList } Tool *DragonFly::buildAssembler() const { - return new tools::dragonfly::Assemble(*this); + return new tools::dragonfly::Assembler(*this); } Tool *DragonFly::buildLinker() const { - return new tools::dragonfly::Link(*this); + return new tools::dragonfly::Linker(*this); +} + +/// Stub for CUDA toolchain. At the moment we don't have assembler or +/// linker and need toolchain mainly to propagate device-side options +/// to CC1. + +CudaToolChain::CudaToolChain(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : Linux(D, Triple, Args) {} + +void +CudaToolChain::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + Linux::addClangTargetOptions(DriverArgs, CC1Args); + CC1Args.push_back("-fcuda-is-device"); } +llvm::opt::DerivedArgList * +CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, + const char *BoundArch) const { + DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); + const OptTable &Opts = getDriver().getOpts(); + + for (Arg *A : Args) { + if (A->getOption().matches(options::OPT_Xarch__)) { + // Skip this argument unless the architecture matches BoundArch + if (A->getValue(0) != StringRef(BoundArch)) + continue; + + unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1)); + unsigned Prev = Index; + std::unique_ptr<Arg> XarchArg(Opts.ParseOneArg(Args, Index)); + + // If the argument parsing failed or more than one argument was + // consumed, the -Xarch_ argument's parameter tried to consume + // extra arguments. Emit an error and ignore. + // + // We also want to disallow any options which would alter the + // driver behavior; that isn't going to work in our model. We + // use isDriverOption() as an approximation, although things + // like -O4 are going to slip through. + if (!XarchArg || Index > Prev + 1) { + getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args) + << A->getAsString(Args); + continue; + } else if (XarchArg->getOption().hasFlag(options::DriverOption)) { + getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver) + << A->getAsString(Args); + continue; + } + XarchArg->setBaseArg(A); + A = XarchArg.release(); + DAL->AddSynthesizedArg(A); + } + DAL->append(A); + } + + DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), BoundArch); + return DAL; +} /// XCore tool chain -XCore::XCore(const Driver &D, const llvm::Triple &Triple, - const ArgList &Args) : ToolChain(D, Triple, Args) { +XCore::XCore(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 { - return new tools::XCore::Assemble(*this); + return new tools::XCore::Assembler(*this); } -Tool *XCore::buildLinker() const { - return new tools::XCore::Link(*this); -} +Tool *XCore::buildLinker() const { return new tools::XCore::Linker(*this); } -bool XCore::isPICDefault() const { - return false; -} +bool XCore::isPICDefault() const { return false; } -bool XCore::isPIEDefault() const { - return false; -} +bool XCore::isPIEDefault() const { return false; } -bool XCore::isPICDefaultForced() const { - return false; -} +bool XCore::isPICDefaultForced() const { return false; } -bool XCore::SupportsProfiling() const { - return false; -} +bool XCore::SupportsProfiling() const { return false; } -bool XCore::hasBlocksRuntime() const { - return false; -} +bool XCore::hasBlocksRuntime() const { return false; } void XCore::AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { @@ -3459,15 +3740,15 @@ void XCore::AddClangSystemIncludeArgs(const ArgList &DriverArgs, return; if (const char *cl_include_dir = getenv("XCC_C_INCLUDE_PATH")) { SmallVector<StringRef, 4> Dirs; - const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator,'\0'}; + const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'}; StringRef(cl_include_dir).split(Dirs, StringRef(EnvPathSeparatorStr)); ArrayRef<StringRef> DirVec(Dirs); addSystemIncludes(DriverArgs, CC1Args, DirVec); } } -void XCore::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const { +void XCore::addClangTargetOptions(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { CC1Args.push_back("-nostdsysteminc"); } @@ -3479,7 +3760,7 @@ void XCore::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, return; if (const char *cl_include_dir = getenv("XCC_CPLUS_INCLUDE_PATH")) { SmallVector<StringRef, 4> Dirs; - const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator,'\0'}; + const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'}; StringRef(cl_include_dir).split(Dirs, StringRef(EnvPathSeparatorStr)); ArrayRef<StringRef> DirVec(Dirs); addSystemIncludes(DriverArgs, CC1Args, DirVec); @@ -3490,3 +3771,46 @@ void XCore::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 { + switch (JA.getKind()) { + case Action::CompileJobClass: + if (!Compiler) + Compiler.reset(new tools::SHAVE::Compiler(*this)); + return Compiler.get(); + case Action::AssembleJobClass: + if (!Assembler) + Assembler.reset(new tools::SHAVE::Assembler(*this)); + return Assembler.get(); + default: + return ToolChain::getTool(JA.getKind()); + } +} + +SHAVEToolChain::SHAVEToolChain(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : Generic_GCC(D, Triple, Args) {} + +SHAVEToolChain::~SHAVEToolChain() {} + +/// Following are methods necessary to avoid having moviClang be an abstract +/// class. + +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"); +} + +Tool *SHAVEToolChain::buildLinker() const { + // SHAVEToolChain executables can not be linked except by the vendor tools. + llvm_unreachable("SHAVEToolChain can't buildLinker"); +} + +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"); +} |