diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/Tools.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Tools.cpp | 1701 |
1 files changed, 1138 insertions, 563 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp index 5161ddf..f4eca44 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp @@ -10,6 +10,7 @@ #include "Tools.h" #include "InputInfo.h" #include "ToolChains.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Version.h" @@ -23,6 +24,7 @@ #include "clang/Driver/SanitizerArgs.h" #include "clang/Driver/ToolChain.h" #include "clang/Driver/Util.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" @@ -30,16 +32,20 @@ #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" +#include "llvm/Support/TargetParser.h" #include "llvm/Support/Compression.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" -#include "llvm/Support/Format.h" #include "llvm/Support/Host.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" #include "llvm/Support/raw_ostream.h" +#ifdef LLVM_ON_UNIX +#include <unistd.h> // For getuid(). +#endif + using namespace clang::driver; using namespace clang::driver::tools; using namespace clang; @@ -319,8 +325,9 @@ void Clang::AddPreprocessingOptions(Compilation &C, if (A->getOption().matches(options::OPT_M) || A->getOption().matches(options::OPT_MD)) CmdArgs.push_back("-sys-header-deps"); - - if (isa<PrecompileJobAction>(JA)) + if ((isa<PrecompileJobAction>(JA) && + !Args.hasArg(options::OPT_fno_module_file_deps)) || + Args.hasArg(options::OPT_fmodule_file_deps)) CmdArgs.push_back("-module-file-deps"); } @@ -332,12 +339,10 @@ void Clang::AddPreprocessingOptions(Compilation &C, } Args.AddLastArg(CmdArgs, options::OPT_MP); + Args.AddLastArg(CmdArgs, options::OPT_MV); // Convert all -MQ <target> args to -MT <quoted target> - for (arg_iterator it = Args.filtered_begin(options::OPT_MT, - options::OPT_MQ), - ie = Args.filtered_end(); it != ie; ++it) { - const Arg *A = *it; + for (const Arg *A : Args.filtered(options::OPT_MT, options::OPT_MQ)) { A->claim(); if (A->getOption().matches(options::OPT_MQ)) { @@ -358,10 +363,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, // replacement into a build system already set up to be generating // .gch files. bool RenderedImplicitInclude = false; - for (arg_iterator it = Args.filtered_begin(options::OPT_clang_i_Group), - ie = Args.filtered_end(); it != ie; ++it) { - const Arg *A = it; - + for (const Arg *A : Args.filtered(options::OPT_clang_i_Group)) { if (A->getOption().matches(options::OPT_include)) { bool IsFirstImplicitInclude = !RenderedImplicitInclude; RenderedImplicitInclude = true; @@ -377,19 +379,19 @@ void Clang::AddPreprocessingOptions(Compilation &C, P += ".dummy"; if (UsePCH) { llvm::sys::path::replace_extension(P, "pch"); - if (llvm::sys::fs::exists(P.str())) + if (llvm::sys::fs::exists(P)) FoundPCH = true; } if (!FoundPCH) { llvm::sys::path::replace_extension(P, "pth"); - if (llvm::sys::fs::exists(P.str())) + if (llvm::sys::fs::exists(P)) FoundPTH = true; } if (!FoundPCH && !FoundPTH) { llvm::sys::path::replace_extension(P, "gch"); - if (llvm::sys::fs::exists(P.str())) { + if (llvm::sys::fs::exists(P)) { FoundPCH = UsePCH; FoundPTH = !UsePCH; } @@ -402,12 +404,12 @@ void Clang::AddPreprocessingOptions(Compilation &C, CmdArgs.push_back("-include-pch"); else CmdArgs.push_back("-include-pth"); - CmdArgs.push_back(Args.MakeArgString(P.str())); + CmdArgs.push_back(Args.MakeArgString(P)); continue; } else { // Ignore the PCH if not first on command line and emit warning. D.Diag(diag::warn_drv_pch_not_first_include) - << P.str() << A->getAsString(Args); + << P << A->getAsString(Args); } } } @@ -489,6 +491,7 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) { return true; return false; + case llvm::Triple::hexagon: case llvm::Triple::ppc64le: case llvm::Triple::systemz: case llvm::Triple::xcore: @@ -528,85 +531,26 @@ static void getARMHWDivFeatures(const Driver &D, const Arg *A, } // Handle -mfpu=. -// -// FIXME: Centralize feature selection, defaulting shouldn't be also in the -// frontend target. static void getARMFPUFeatures(const Driver &D, const Arg *A, const ArgList &Args, std::vector<const char *> &Features) { StringRef FPU = A->getValue(); - - // Set the target features based on the FPU. - if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") { - // Disable any default FPU support. - Features.push_back("-vfp2"); - Features.push_back("-vfp3"); - Features.push_back("-neon"); - } else if (FPU == "vfp") { - Features.push_back("+vfp2"); - Features.push_back("-neon"); - } else if (FPU == "vfp3-d16" || FPU == "vfpv3-d16") { - Features.push_back("+vfp3"); - Features.push_back("+d16"); - Features.push_back("-neon"); - } else if (FPU == "vfp3" || FPU == "vfpv3") { - Features.push_back("+vfp3"); - Features.push_back("-neon"); - } else if (FPU == "vfp4-d16" || FPU == "vfpv4-d16") { - Features.push_back("+vfp4"); - Features.push_back("+d16"); - Features.push_back("-neon"); - } else if (FPU == "vfp4" || FPU == "vfpv4") { - Features.push_back("+vfp4"); - Features.push_back("-neon"); - } else if (FPU == "fp4-sp-d16" || FPU == "fpv4-sp-d16") { - Features.push_back("+vfp4"); - Features.push_back("+d16"); - Features.push_back("+fp-only-sp"); - Features.push_back("-neon"); - } else if (FPU == "fp5-sp-d16" || FPU == "fpv5-sp-d16") { - Features.push_back("+fp-armv8"); - Features.push_back("+fp-only-sp"); - Features.push_back("+d16"); - Features.push_back("-neon"); - Features.push_back("-crypto"); - } else if (FPU == "fp5-dp-d16" || FPU == "fpv5-dp-d16" || - FPU == "fp5-d16" || FPU == "fpv5-d16") { - Features.push_back("+fp-armv8"); - Features.push_back("+d16"); - Features.push_back("-neon"); - Features.push_back("-crypto"); - } else if (FPU == "fp-armv8") { - Features.push_back("+fp-armv8"); - Features.push_back("-neon"); - Features.push_back("-crypto"); - } else if (FPU == "neon-fp-armv8") { - Features.push_back("+fp-armv8"); - Features.push_back("+neon"); - Features.push_back("-crypto"); - } else if (FPU == "crypto-neon-fp-armv8") { - Features.push_back("+fp-armv8"); - Features.push_back("+neon"); - Features.push_back("+crypto"); - } else if (FPU == "neon") { - Features.push_back("+neon"); - } else if (FPU == "neon-vfpv3") { - Features.push_back("+vfp3"); - Features.push_back("+neon"); - } else if (FPU == "neon-vfpv4") { - Features.push_back("+neon"); - Features.push_back("+vfp4"); - } else if (FPU == "none") { - Features.push_back("-vfp2"); - Features.push_back("-vfp3"); - Features.push_back("-vfp4"); - Features.push_back("-fp-armv8"); - Features.push_back("-crypto"); - Features.push_back("-neon"); - } else + unsigned FPUID = llvm::ARMTargetParser::parseFPU(FPU); + if (!llvm::ARMTargetParser::getFPUFeatures(FPUID, Features)) D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); } +static int getARMSubArchVersionNumber(const llvm::Triple &Triple) { + llvm::StringRef Arch = Triple.getArchName(); + return llvm::ARMTargetParser::parseArchVersion(Arch); +} + +static bool isARMMProfile(const llvm::Triple &Triple) { + llvm::StringRef Arch = Triple.getArchName(); + unsigned Profile = llvm::ARMTargetParser::parseArchProfile(Arch); + return Profile == llvm::ARM::PK_M; +} + // Select the float ABI as determined by -msoft-float, -mhard-float, and // -mfloat-abi=. StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args, @@ -637,11 +581,8 @@ StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args, case llvm::Triple::IOS: { // Darwin defaults to "softfp" for v6 and v7. // - // FIXME: Factor out an ARM class so we can cache the arch somewhere. - std::string ArchName = - arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple)); - if (StringRef(ArchName).startswith("v6") || - StringRef(ArchName).startswith("v7")) + if (getARMSubArchVersionNumber(Triple) == 6 || + getARMSubArchVersionNumber(Triple) == 7) FloatABI = "softfp"; else FloatABI = "soft"; @@ -681,9 +622,7 @@ StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args, FloatABI = "softfp"; break; case llvm::Triple::Android: { - std::string ArchName = - arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple)); - if (StringRef(ArchName).startswith("v7")) + if (getARMSubArchVersionNumber(Triple) == 7) FloatABI = "softfp"; else FloatABI = "soft"; @@ -736,6 +675,25 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple, if (const Arg *A = Args.getLastArg(options::OPT_mhwdiv_EQ)) getARMHWDivFeatures(D, A, Args, Features); + // Check if -march is valid by checking if it can be canonicalised and parsed. + // getARMArch is used here instead of just checking the -march value in order + // to handle -march=native correctly. + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { + StringRef Arch = arm::getARMArch(Args, Triple); + if (llvm::ARMTargetParser::parseArch(Arch) == llvm::ARM::AK_INVALID) + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); + } + + // We do a similar thing with -mcpu, but here things are complicated because + // the only function we have to check if a cpu is valid is + // getLLVMArchSuffixForARM which also needs an architecture. + if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { + std::string CPU = arm::getARMTargetCPU(Args, Triple); + StringRef Arch = arm::getARMArch(Args, Triple); + if (strcmp(arm::getLLVMArchSuffixForARM(CPU, Arch), "") == 0) + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); + } + // Setting -msoft-float effectively disables NEON because of the GCC // implementation, although the same isn't true of VFP or VFP3. if (FloatABI == "soft") { @@ -744,14 +702,17 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple, Features.push_back("-crypto"); } - // En/disable crc - if (Arg *A = Args.getLastArg(options::OPT_mcrc, - options::OPT_mnocrc)) { + // En/disable crc code generation. + if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) { if (A->getOption().matches(options::OPT_mcrc)) Features.push_back("+crc"); else Features.push_back("-crc"); } + + if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8_1a) { + Features.insert(Features.begin(), "+v8.1a"); + } } void Clang::AddARMTargetArgs(const ArgList &Args, @@ -761,7 +722,6 @@ void Clang::AddARMTargetArgs(const ArgList &Args, // Get the effective triple, which takes into account the deployment target. std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args); llvm::Triple Triple(TripleStr); - std::string CPUName = arm::getARMTargetCPU(Args, Triple); // Select the ABI to use. // @@ -775,7 +735,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, // the frontend matches that. if (Triple.getEnvironment() == llvm::Triple::EABI || Triple.getOS() == llvm::Triple::UnknownOS || - StringRef(CPUName).startswith("cortex-m")) { + isARMMProfile(Triple)) { ABIName = "aapcs"; } else { ABIName = "apcs-gnu"; @@ -856,12 +816,14 @@ void Clang::AddARMTargetArgs(const ArgList &Args, } } - // Setting -mno-global-merge disables the codegen global merge pass. Setting - // -mglobal-merge has no effect as the pass is enabled by default. + // Forward the -mglobal-merge option for explicit control over the pass. if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge, options::OPT_mno_global_merge)) { + CmdArgs.push_back("-backend-option"); if (A->getOption().matches(options::OPT_mno_global_merge)) - CmdArgs.push_back("-mno-global-merge"); + CmdArgs.push_back("-arm-global-merge=false"); + else + CmdArgs.push_back("-arm-global-merge=true"); } if (!Args.hasFlag(options::OPT_mimplicit_float, @@ -952,12 +914,14 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1"); } - // Setting -mno-global-merge disables the codegen global merge pass. Setting - // -mglobal-merge has no effect as the pass is enabled by default. + // Forward the -mglobal-merge option for explicit control over the pass. if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge, options::OPT_mno_global_merge)) { + CmdArgs.push_back("-backend-option"); if (A->getOption().matches(options::OPT_mno_global_merge)) - CmdArgs.push_back("-mno-global-merge"); + CmdArgs.push_back("-aarch64-global-merge=false"); + else + CmdArgs.push_back("-aarch64-global-merge=true"); } if (Args.hasArg(options::OPT_ffixed_x18)) { @@ -1096,17 +1060,6 @@ static void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); ABIName = getGnuCompatibleMipsABIName(ABIName); - // Always override the backend's default ABI. - std::string ABIFeature = llvm::StringSwitch<StringRef>(ABIName) - .Case("32", "+o32") - .Case("n32", "+n32") - .Case("64", "+n64") - .Case("eabi", "+eabi") - .Default(("+" + ABIName).str()); - Features.push_back("-o32"); - Features.push_back("-n64"); - Features.push_back(Args.MakeArgString(ABIFeature)); - AddTargetFeature(Args, Features, options::OPT_mno_abicalls, options::OPT_mabicalls, "noabicalls"); @@ -1120,11 +1073,21 @@ static void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) { StringRef Val = StringRef(A->getValue()); - if (Val == "2008") - Features.push_back("+nan2008"); - else if (Val == "legacy") - Features.push_back("-nan2008"); - else + if (Val == "2008") { + if (mips::getSupportedNanEncoding(CPUName) & mips::Nan2008) + Features.push_back("+nan2008"); + else { + Features.push_back("-nan2008"); + D.Diag(diag::warn_target_unsupported_nan2008) << CPUName; + } + } else if (Val == "legacy") { + if (mips::getSupportedNanEncoding(CPUName) & mips::NanLegacy) + Features.push_back("-nan2008"); + else { + Features.push_back("+nan2008"); + D.Diag(diag::warn_target_unsupported_nanlegacy) << CPUName; + } + } else D.Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Val; } @@ -1285,11 +1248,9 @@ static std::string getPPCTargetCPU(const ArgList &Args) { static void getPPCTargetFeatures(const ArgList &Args, std::vector<const char *> &Features) { - for (arg_iterator it = Args.filtered_begin(options::OPT_m_ppc_Features_Group), - ie = Args.filtered_end(); - it != ie; ++it) { - StringRef Name = (*it)->getOption().getName(); - (*it)->claim(); + for (const Arg *A : Args.filtered(options::OPT_m_ppc_Features_Group)) { + StringRef Name = A->getOption().getName(); + A->claim(); // Skip over "-m". assert(Name.startswith("m") && "Invalid feature name."); @@ -1322,9 +1283,22 @@ void Clang::AddPPCTargetArgs(const ArgList &Args, ABIName = A->getValue(); } else if (getToolChain().getTriple().isOSLinux()) switch(getToolChain().getArch()) { - case llvm::Triple::ppc64: + case llvm::Triple::ppc64: { + // When targeting a processor that supports QPX, or if QPX is + // specifically enabled, default to using the ABI that supports QPX (so + // long as it is not specifically disabled). + bool HasQPX = false; + if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) + HasQPX = A->getValue() == StringRef("a2q"); + HasQPX = Args.hasFlag(options::OPT_mqpx, options::OPT_mno_qpx, HasQPX); + if (HasQPX) { + ABIName = "elfv1-qpx"; + break; + } + ABIName = "elfv1"; break; + } case llvm::Triple::ppc64le: ABIName = "elfv2"; break; @@ -1410,6 +1384,26 @@ static const char *getSystemZTargetCPU(const ArgList &Args) { return "z10"; } +static void getSystemZTargetFeatures(const ArgList &Args, + std::vector<const char *> &Features) { + // -m(no-)htm overrides use of the transactional-execution facility. + if (Arg *A = Args.getLastArg(options::OPT_mhtm, + options::OPT_mno_htm)) { + if (A->getOption().matches(options::OPT_mhtm)) + Features.push_back("+transactional-execution"); + else + Features.push_back("-transactional-execution"); + } + // -m(no-)vx overrides use of the vector facility. + if (Arg *A = Args.getLastArg(options::OPT_mvx, + options::OPT_mno_vx)) { + if (A->getOption().matches(options::OPT_mvx)) + Features.push_back("+vector"); + else + Features.push_back("-vector"); + } +} + static const char *getX86TargetCPU(const ArgList &Args, const llvm::Triple &Triple) { if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { @@ -1445,6 +1439,10 @@ static const char *getX86TargetCPU(const ArgList &Args, return Is64Bit ? "core2" : "yonah"; } + // Set up default CPU name for PS4 compilers. + if (Triple.isPS4CPU()) + return "btver2"; + // On Android use targets compatible with gcc if (Triple.getEnvironment() == llvm::Triple::Android) return Is64Bit ? "x86-64" : "i686"; @@ -1512,6 +1510,7 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) { } case llvm::Triple::sparc: + case llvm::Triple::sparcel: case llvm::Triple::sparcv9: if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) return A->getValue(); @@ -1551,10 +1550,20 @@ static void AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args, CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU)); } -static void getX86TargetFeatures(const Driver & D, - const llvm::Triple &Triple, +static void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple, const ArgList &Args, std::vector<const char *> &Features) { + // If -march=native, autodetect the feature list. + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { + if (StringRef(A->getValue()) == "native") { + llvm::StringMap<bool> HostFeatures; + if (llvm::sys::getHostCPUFeatures(HostFeatures)) + for (auto &F : HostFeatures) + Features.push_back(Args.MakeArgString((F.second ? "+" : "-") + + F.first())); + } + } + if (Triple.getArchName() == "x86_64h") { // x86_64h implies quite a few of the more modern subtarget features // for Haswell class CPUs, but not all of them. Opt-out of a few. @@ -1566,29 +1575,29 @@ static void getX86TargetFeatures(const Driver & D, Features.push_back("-fsgsbase"); } - // Add features to comply with gcc on Android + const llvm::Triple::ArchType ArchType = Triple.getArch(); + // Add features to be compatible with gcc for Android. if (Triple.getEnvironment() == llvm::Triple::Android) { - if (Triple.getArch() == llvm::Triple::x86_64) { + if (ArchType == llvm::Triple::x86_64) { Features.push_back("+sse4.2"); Features.push_back("+popcnt"); } else Features.push_back("+ssse3"); } - // Set features according to the -arch flag on MSVC + // Set features according to the -arch flag on MSVC. if (Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) { StringRef Arch = A->getValue(); bool ArchUsed = false; // First, look for flags that are shared in x86 and x86-64. - if (Triple.getArch() == llvm::Triple::x86_64 || - Triple.getArch() == llvm::Triple::x86) { + if (ArchType == llvm::Triple::x86_64 || ArchType == llvm::Triple::x86) { if (Arch == "AVX" || Arch == "AVX2") { ArchUsed = true; Features.push_back(Args.MakeArgString("+" + Arch.lower())); } } // Then, look for x86-specific flags. - if (Triple.getArch() == llvm::Triple::x86) { + if (ArchType == llvm::Triple::x86) { if (Arch == "IA32") { ArchUsed = true; } else if (Arch == "SSE" || Arch == "SSE2") { @@ -1602,11 +1611,9 @@ static void getX86TargetFeatures(const Driver & D, // Now add any that the user explicitly requested on the command line, // which may override the defaults. - for (arg_iterator it = Args.filtered_begin(options::OPT_m_x86_Features_Group), - ie = Args.filtered_end(); - it != ie; ++it) { - StringRef Name = (*it)->getOption().getName(); - (*it)->claim(); + for (const Arg *A : Args.filtered(options::OPT_m_x86_Features_Group)) { + StringRef Name = A->getOption().getName(); + A->claim(); // Skip over "-m". assert(Name.startswith("m") && "Invalid feature name."); @@ -1656,39 +1663,16 @@ void Clang::AddX86TargetArgs(const ArgList &Args, } } -static inline bool HasPICArg(const ArgList &Args) { - return Args.hasArg(options::OPT_fPIC) - || Args.hasArg(options::OPT_fpic); -} - -static Arg *GetLastSmallDataThresholdArg(const ArgList &Args) { - return Args.getLastArg(options::OPT_G, - options::OPT_G_EQ, - options::OPT_msmall_data_threshold_EQ); -} - -static std::string GetHexagonSmallDataThresholdValue(const ArgList &Args) { - std::string value; - if (HasPICArg(Args)) - value = "0"; - else if (Arg *A = GetLastSmallDataThresholdArg(Args)) { - value = A->getValue(); - A->claim(); - } - return value; -} - void Clang::AddHexagonTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { - CmdArgs.push_back("-fno-signed-char"); CmdArgs.push_back("-mqdsp6-compat"); CmdArgs.push_back("-Wreturn-type"); - std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args); - if (!SmallDataThreshold.empty()) { + if (const char* v = toolchains::Hexagon_TC::GetSmallDataThreshold(Args)) { + std::string SmallDataThreshold="-hexagon-small-data-threshold="; + SmallDataThreshold += v; CmdArgs.push_back ("-mllvm"); - CmdArgs.push_back(Args.MakeArgString( - "-hexagon-small-data-threshold=" + SmallDataThreshold)); + CmdArgs.push_back(Args.MakeArgString(SmallDataThreshold)); } if (!Args.hasArg(options::OPT_fno_short_enums)) @@ -1734,7 +1718,7 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU, std::vector<const char *> &Features) { std::pair<StringRef, StringRef> Split = Mcpu.split("+"); CPU = Split.first; - if (CPU == "cyclone" || CPU == "cortex-a53" || CPU == "cortex-a57") { + if (CPU == "cyclone" || CPU == "cortex-a53" || CPU == "cortex-a57" || CPU == "cortex-a72") { Features.push_back("+neon"); Features.push_back("+crc"); Features.push_back("+crypto"); @@ -1755,8 +1739,17 @@ getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March, const ArgList &Args, std::vector<const char *> &Features) { std::pair<StringRef, StringRef> Split = March.split("+"); - if (Split.first != "armv8-a") + + if (Split.first == "armv8-a" || + Split.first == "armv8a") { + // ok, no additional features. + } else if ( + Split.first == "armv8.1-a" || + Split.first == "armv8.1a" ) { + Features.push_back("+v8.1a"); + } else { return false; + } if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features)) return false; @@ -1871,9 +1864,13 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple, getPPCTargetFeatures(Args, Features); break; case llvm::Triple::sparc: + case llvm::Triple::sparcel: case llvm::Triple::sparcv9: getSparcTargetFeatures(Args, Features); break; + case llvm::Triple::systemz: + getSystemZTargetFeatures(Args, Features); + break; case llvm::Triple::aarch64: case llvm::Triple::aarch64_be: getAArch64TargetFeatures(D, Args, Features); @@ -1934,16 +1931,17 @@ static bool exceptionSettings(const ArgList &Args, const llvm::Triple &Triple) { return false; } -/// addExceptionArgs - Adds exception related arguments to the driver command -/// arguments. There's a master flag, -fexceptions and also language specific -/// flags to enable/disable C++ and Objective-C exceptions. -/// This makes it possible to for example disable C++ exceptions but enable -/// Objective-C exceptions. +/// Adds exception related arguments to the driver command arguments. There's a +/// master flag, -fexceptions and also language specific flags to enable/disable +/// C++ and Objective-C exceptions. This makes it possible to for example +/// disable C++ exceptions but enable Objective-C exceptions. static void addExceptionArgs(const ArgList &Args, types::ID InputType, - const llvm::Triple &Triple, - bool KernelOrKext, + const ToolChain &TC, bool KernelOrKext, const ObjCRuntime &objcRuntime, ArgStringList &CmdArgs) { + const Driver &D = TC.getDriver(); + const llvm::Triple &Triple = TC.getTriple(); + if (KernelOrKext) { // -mkernel and -fapple-kext imply no exceptions, so claim exception related // arguments now to avoid warnings about unused arguments. @@ -1971,16 +1969,32 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType, } if (types::isCXX(InputType)) { - bool CXXExceptionsEnabled = Triple.getArch() != llvm::Triple::xcore; - if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions, - options::OPT_fno_cxx_exceptions, - options::OPT_fexceptions, - options::OPT_fno_exceptions)) + bool CXXExceptionsEnabled = + Triple.getArch() != llvm::Triple::xcore && !Triple.isPS4CPU(); + Arg *ExceptionArg = Args.getLastArg( + options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions, + options::OPT_fexceptions, options::OPT_fno_exceptions); + if (ExceptionArg) CXXExceptionsEnabled = - A->getOption().matches(options::OPT_fcxx_exceptions) || - A->getOption().matches(options::OPT_fexceptions); + ExceptionArg->getOption().matches(options::OPT_fcxx_exceptions) || + ExceptionArg->getOption().matches(options::OPT_fexceptions); if (CXXExceptionsEnabled) { + if (Triple.isPS4CPU()) { + ToolChain::RTTIMode RTTIMode = TC.getRTTIMode(); + assert(ExceptionArg && + "On the PS4 exceptions should only be enabled if passing " + "an argument"); + if (RTTIMode == ToolChain::RM_DisabledExplicitly) { + const Arg *RTTIArg = TC.getRTTIArg(); + assert(RTTIArg && "RTTI disabled explicitly but no RTTIArg!"); + D.Diag(diag::err_drv_argument_not_allowed_with) + << RTTIArg->getAsString(Args) << ExceptionArg->getAsString(Args); + } else if (RTTIMode == ToolChain::RM_EnabledImplicitly) + D.Diag(diag::warn_drv_enabling_rtti_with_exceptions); + } else + assert(TC.getRTTIMode() != ToolChain::RM_DisabledImplicitly); + CmdArgs.push_back("-fcxx-exceptions"); EH = true; @@ -2062,10 +2076,8 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, // When using an integrated assembler, translate -Wa, and -Xassembler // options. bool CompressDebugSections = false; - for (arg_iterator it = Args.filtered_begin(options::OPT_Wa_COMMA, - options::OPT_Xassembler), - ie = Args.filtered_end(); it != ie; ++it) { - const Arg *A = *it; + for (const Arg *A : + Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { A->claim(); for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) { @@ -2135,8 +2147,11 @@ static SmallString<128> getCompilerRTLibDir(const ToolChain &TC) { } static SmallString<128> getCompilerRT(const ToolChain &TC, StringRef Component, - bool Shared = false, - const char *Env = "") { + bool Shared = false) { + const char *Env = TC.getTriple().getEnvironment() == llvm::Triple::Android + ? "-android" + : ""; + bool IsOSWindows = TC.getTriple().isOSWindows(); StringRef Arch = getArchNameForCompilerRTLib(TC); const char *Prefix = IsOSWindows ? "" : "lib"; @@ -2171,6 +2186,7 @@ static void addProfileRT(const ToolChain &TC, const ArgList &Args, false) || Args.hasArg(options::OPT_fprofile_generate) || 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; @@ -2178,19 +2194,63 @@ static void addProfileRT(const ToolChain &TC, const ArgList &Args, CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "profile"))); } +namespace { +enum OpenMPRuntimeKind { + /// An unknown OpenMP runtime. We can't generate effective OpenMP code + /// without knowing what runtime to target. + OMPRT_Unknown, + + /// The LLVM OpenMP runtime. When completed and integrated, this will become + /// the default for Clang. + OMPRT_OMP, + + /// The GNU OpenMP runtime. Clang doesn't support generating OpenMP code for + /// this runtime but can swallow the pragmas, and find and link against the + /// runtime library itself. + OMPRT_GOMP, + + /// The legacy name for the LLVM OpenMP runtime from when it was the Intel + /// OpenMP runtime. We support this mode for users with existing dependencies + /// on this runtime library name. + OMPRT_IOMP5 +}; +} + +/// Compute the desired OpenMP runtime from the flag provided. +static OpenMPRuntimeKind getOpenMPRuntime(const ToolChain &TC, + const ArgList &Args) { + StringRef RuntimeName(CLANG_DEFAULT_OPENMP_RUNTIME); + + const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ); + if (A) + RuntimeName = A->getValue(); + + auto RT = llvm::StringSwitch<OpenMPRuntimeKind>(RuntimeName) + .Case("libomp", OMPRT_OMP) + .Case("libgomp", OMPRT_GOMP) + .Case("libiomp5", OMPRT_IOMP5) + .Default(OMPRT_Unknown); + + if (RT == OMPRT_Unknown) { + if (A) + TC.getDriver().Diag(diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << A->getValue(); + else + // FIXME: We could use a nicer diagnostic here. + TC.getDriver().Diag(diag::err_drv_unsupported_opt) << "-fopenmp"; + } + + return RT; +} + static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs, StringRef Sanitizer, bool IsShared) { - const char *Env = TC.getTriple().getEnvironment() == llvm::Triple::Android - ? "-android" - : ""; - // Static runtimes must be forced into executable, so we wrap them in // whole-archive. if (!IsShared) CmdArgs.push_back("-whole-archive"); - CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Sanitizer, IsShared, - Env))); + CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Sanitizer, IsShared))); if (!IsShared) CmdArgs.push_back("-no-whole-archive"); } @@ -2251,19 +2311,20 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, StaticRuntimes.push_back("dfsan"); if (SanArgs.needsLsanRt()) StaticRuntimes.push_back("lsan"); - if (SanArgs.needsMsanRt()) + if (SanArgs.needsMsanRt()) { StaticRuntimes.push_back("msan"); - if (SanArgs.needsTsanRt()) + if (SanArgs.linkCXXRuntimes()) + StaticRuntimes.push_back("msan_cxx"); + } + if (SanArgs.needsTsanRt()) { StaticRuntimes.push_back("tsan"); - // WARNING: UBSan should always go last. + if (SanArgs.linkCXXRuntimes()) + StaticRuntimes.push_back("tsan_cxx"); + } if (SanArgs.needsUbsanRt()) { - // If UBSan is not combined with another sanitizer, we need to pull in - // sanitizer_common explicitly. - if (StaticRuntimes.empty()) - HelperStaticRuntimes.push_back("san"); - StaticRuntimes.push_back("ubsan"); + StaticRuntimes.push_back("ubsan_standalone"); if (SanArgs.linkCXXRuntimes()) - StaticRuntimes.push_back("ubsan_cxx"); + StaticRuntimes.push_back("ubsan_standalone_cxx"); } } @@ -2291,27 +2352,49 @@ static bool addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, return !StaticRuntimes.empty(); } +static bool areOptimizationsEnabled(const ArgList &Args) { + // Find the last -O arg and see if it is non-zero. + if (Arg *A = Args.getLastArg(options::OPT_O_Group)) + return !A->getOption().matches(options::OPT_O0); + // Defaults to -O0. + return false; +} + static bool shouldUseFramePointerForTarget(const ArgList &Args, const llvm::Triple &Triple) { - switch (Triple.getArch()) { - // Don't use a frame pointer on linux if optimizing for certain targets. - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - case llvm::Triple::mips: - case llvm::Triple::mipsel: - case llvm::Triple::systemz: - case llvm::Triple::x86: - case llvm::Triple::x86_64: - if (Triple.isOSLinux()) - if (Arg *A = Args.getLastArg(options::OPT_O_Group)) - if (!A->getOption().matches(options::OPT_O0)) - return false; - return true; - case llvm::Triple::xcore: + // XCore never wants frame pointers, regardless of OS. + if (Triple.getArch() == llvm::Triple::xcore) { return false; - default: - return true; } + + if (Triple.isOSLinux()) { + switch (Triple.getArch()) { + // Don't use a frame pointer on linux if optimizing for certain targets. + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::systemz: + case llvm::Triple::x86: + case llvm::Triple::x86_64: + return !areOptimizationsEnabled(Args); + default: + return true; + } + } + + if (Triple.isOSWindows()) { + switch (Triple.getArch()) { + case llvm::Triple::x86: + return !areOptimizationsEnabled(Args); + default: + // All other supported Windows ISAs use xdata unwind information, so frame + // pointers are not generally useful. + return false; + } + } + + return true; } static bool shouldUseFramePointer(const ArgList &Args, @@ -2329,6 +2412,9 @@ static bool shouldUseLeafFramePointer(const ArgList &Args, options::OPT_momit_leaf_frame_pointer)) return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer); + if (Triple.isPS4CPU()) + return false; + return shouldUseFramePointerForTarget(Args, Triple); } @@ -2342,7 +2428,7 @@ static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) { } static const char *SplitDebugName(const ArgList &Args, - const InputInfoList &Inputs) { + const InputInfo &Input) { Arg *FinalOutput = Args.getLastArg(options::OPT_o); if (FinalOutput && Args.hasArg(options::OPT_c)) { SmallString<128> T(FinalOutput->getValue()); @@ -2352,7 +2438,7 @@ static const char *SplitDebugName(const ArgList &Args, // Use the compilation dir. SmallString<128> T( Args.getLastArgValue(options::OPT_fdebug_compilation_dir)); - SmallString<128> F(llvm::sys::path::stem(Inputs[0].getBaseInput())); + SmallString<128> F(llvm::sys::path::stem(Input.getBaseInput())); llvm::sys::path::replace_extension(F, "dwo"); T += F; return Args.MakeArgString(F); @@ -2431,24 +2517,17 @@ static void addDashXForInput(const ArgList &Args, const InputInfo &Input, CmdArgs.push_back(types::getTypeName(Input.getType())); } -static std::string getMSCompatibilityVersion(const char *VersionStr) { - unsigned Version; - if (StringRef(VersionStr).getAsInteger(10, Version)) - return "0"; - +static VersionTuple getMSCompatibilityVersion(unsigned Version) { if (Version < 100) - return llvm::utostr_32(Version) + ".0"; + return VersionTuple(Version); if (Version < 10000) - return llvm::utostr_32(Version / 100) + "." + - llvm::utostr_32(Version % 100); + return VersionTuple(Version / 100, Version % 100); unsigned Build = 0, Factor = 1; for ( ; Version > 10000; Version = Version / 10, Factor = Factor * 10) Build = Build + (Version % 10) * Factor; - return llvm::utostr_32(Version / 100) + "." + - llvm::utostr_32(Version % 100) + "." + - llvm::utostr_32(Build); + return VersionTuple(Version / 100, Version % 100, Build); } // Claim options we don't want to warn if they are unused. We do this for @@ -2461,6 +2540,85 @@ static void claimNoWarnArgs(const ArgList &Args) { Args.ClaimAllArgs(options::OPT_fno_lto); } +static void appendUserToPath(SmallVectorImpl<char> &Result) { +#ifdef LLVM_ON_UNIX + const char *Username = getenv("LOGNAME"); +#else + const char *Username = getenv("USERNAME"); +#endif + if (Username) { + // Validate that LoginName can be used in a path, and get its length. + size_t Len = 0; + for (const char *P = Username; *P; ++P, ++Len) { + if (!isAlphanumeric(*P) && *P != '_') { + Username = nullptr; + break; + } + } + + if (Username && Len > 0) { + Result.append(Username, Username + Len); + return; + } + } + + // Fallback to user id. +#ifdef LLVM_ON_UNIX + std::string UID = llvm::utostr(getuid()); +#else + // FIXME: Windows seems to have an 'SID' that might work. + std::string UID = "9999"; +#endif + Result.append(UID.begin(), UID.end()); +} + +VersionTuple visualstudio::getMSVCVersion(const Driver *D, + const llvm::Triple &Triple, + const llvm::opt::ArgList &Args, + bool IsWindowsMSVC) { + if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, + IsWindowsMSVC) || + Args.hasArg(options::OPT_fmsc_version) || + Args.hasArg(options::OPT_fms_compatibility_version)) { + const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version); + const Arg *MSCompatibilityVersion = + Args.getLastArg(options::OPT_fms_compatibility_version); + + if (MSCVersion && MSCompatibilityVersion) { + if (D) + D->Diag(diag::err_drv_argument_not_allowed_with) + << MSCVersion->getAsString(Args) + << MSCompatibilityVersion->getAsString(Args); + return VersionTuple(); + } + + if (MSCompatibilityVersion) { + VersionTuple MSVT; + if (MSVT.tryParse(MSCompatibilityVersion->getValue()) && D) + D->Diag(diag::err_drv_invalid_value) + << MSCompatibilityVersion->getAsString(Args) + << MSCompatibilityVersion->getValue(); + return MSVT; + } + + if (MSCVersion) { + unsigned Version = 0; + if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version) && D) + D->Diag(diag::err_drv_invalid_value) << MSCVersion->getAsString(Args) + << MSCVersion->getValue(); + return getMSCompatibilityVersion(Version); + } + + unsigned Major, Minor, Micro; + Triple.getEnvironmentVersion(Major, Minor, Micro); + if (Major || Minor || Micro) + return VersionTuple(Major, Minor, Micro); + + return VersionTuple(18); + } + return VersionTuple(); +} + void Clang::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -2477,6 +2635,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, bool IsWindowsMSVC = getToolChain().getTriple().isWindowsMSVCEnvironment(); assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); + const InputInfo &Input = Inputs[0]; // Invoke ourselves in -cc1 mode. // @@ -2568,6 +2727,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, assert(JA.getType() == types::TY_PP_Asm && "Unexpected output type!"); } + + // Preserve use-list order by default when emitting bitcode, so that + // loading the bitcode up in 'opt' or 'llc' and running passes gives the + // same result as running passes here. For LTO, we don't need to preserve + // the use-list order, since serialization to bitcode is part of the flow. + if (JA.getType() == types::TY_LLVM_BC) + CmdArgs.push_back("-emit-llvm-uselists"); } // We normally speed up the clang process a bit by skipping destructors at @@ -2584,7 +2750,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Set the main file name, so that debug info works even with // -save-temps. CmdArgs.push_back("-main-file-name"); - CmdArgs.push_back(getBaseInputName(Args, Inputs)); + CmdArgs.push_back(getBaseInputName(Args, Input)); // Some flags which affect the language (via preprocessor // defines). @@ -2612,7 +2778,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-analyzer-checker=deadcode"); - if (types::isCXX(Inputs[0].getType())) + if (types::isCXX(Input.getType())) CmdArgs.push_back("-analyzer-checker=cplusplus"); // Enable the following experimental checkers for testing. @@ -2650,7 +2816,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Android-specific defaults for PIC/PIE if (getToolChain().getTriple().getEnvironment() == llvm::Triple::Android) { - switch (getToolChain().getTriple().getArch()) { + switch (getToolChain().getArch()) { case llvm::Triple::arm: case llvm::Triple::armeb: case llvm::Triple::thumb: @@ -2676,16 +2842,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // OpenBSD-specific defaults for PIE if (getToolChain().getTriple().getOS() == llvm::Triple::OpenBSD) { - switch (getToolChain().getTriple().getArch()) { + switch (getToolChain().getArch()) { case llvm::Triple::mips64: case llvm::Triple::mips64el: - case llvm::Triple::sparc: + case llvm::Triple::sparcel: case llvm::Triple::x86: case llvm::Triple::x86_64: IsPICLevelTwo = false; // "-fpie" break; case llvm::Triple::ppc: + case llvm::Triple::sparc: case llvm::Triple::sparcv9: IsPICLevelTwo = true; // "-fPIE" break; @@ -2781,6 +2948,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, else CmdArgs.push_back(Args.MakeArgString(getToolChain().getThreadModel())); + Args.AddLastArg(CmdArgs, options::OPT_fveclib); + if (!Args.hasFlag(options::OPT_fmerge_all_constants, options::OPT_fno_merge_all_constants)) CmdArgs.push_back("-fno-merge-all-constants"); @@ -2789,14 +2958,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_frewrite_map_file) || Args.hasArg(options::OPT_frewrite_map_file_EQ)) { - for (arg_iterator - MFI = Args.filtered_begin(options::OPT_frewrite_map_file, - options::OPT_frewrite_map_file_EQ), - MFE = Args.filtered_end(); - MFI != MFE; ++MFI) { + for (const Arg *A : Args.filtered(options::OPT_frewrite_map_file, + options::OPT_frewrite_map_file_EQ)) { CmdArgs.push_back("-frewrite-map-file"); - CmdArgs.push_back((*MFI)->getValue()); - (*MFI)->claim(); + CmdArgs.push_back(A->getValue()); + A->claim(); } } @@ -2961,6 +3127,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, !TrappingMath) CmdArgs.push_back("-menable-unsafe-fp-math"); + if (!SignedZeros) + CmdArgs.push_back("-fno-signed-zeros"); + + if (ReciprocalMath) + CmdArgs.push_back("-freciprocal-math"); // Validate and pass through -fp-contract option. if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption, @@ -3060,9 +3231,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } // Add the target cpu - std::string ETripleStr = getToolChain().ComputeEffectiveClangTriple(Args); - llvm::Triple ETriple(ETripleStr); - std::string CPU = getCPUName(Args, ETriple); + std::string CPU = getCPUName(Args, Triple); if (!CPU.empty()) { CmdArgs.push_back("-target-cpu"); CmdArgs.push_back(Args.MakeArgString(CPU)); @@ -3074,7 +3243,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } // Add the target features - getTargetFeatures(D, ETriple, Args, CmdArgs, false); + getTargetFeatures(D, Triple, Args, CmdArgs, false); // Add target specific flags. switch(getToolChain().getArch()) { @@ -3107,6 +3276,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, break; case llvm::Triple::sparc: + case llvm::Triple::sparcel: case llvm::Triple::sparcv9: AddSparcTargetArgs(Args, CmdArgs); break; @@ -3136,7 +3306,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Explicitly error on some things we know we don't support and can't just // ignore. - types::ID InputType = Inputs[0].getType(); + types::ID InputType = Input.getType(); if (!Args.hasArg(options::OPT_fallow_unsupported)) { Arg *Unsupported; if (types::isCXX(InputType) && @@ -3235,25 +3405,36 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-generate-type-units"); } + // CloudABI uses -ffunction-sections and -fdata-sections by default. + bool UseSeparateSections = Triple.getOS() == llvm::Triple::CloudABI; + if (Args.hasFlag(options::OPT_ffunction_sections, - options::OPT_fno_function_sections, false)) { + options::OPT_fno_function_sections, UseSeparateSections)) { CmdArgs.push_back("-ffunction-sections"); } if (Args.hasFlag(options::OPT_fdata_sections, - options::OPT_fno_data_sections, false)) { + options::OPT_fno_data_sections, UseSeparateSections)) { CmdArgs.push_back("-fdata-sections"); } + if (!Args.hasFlag(options::OPT_funique_section_names, + options::OPT_fno_unique_section_names, true)) + CmdArgs.push_back("-fno-unique-section-names"); + Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions); - if (Args.hasArg(options::OPT_fprofile_instr_generate) && + if ((Args.hasArg(options::OPT_fprofile_instr_generate) || + Args.hasArg(options::OPT_fprofile_instr_generate_EQ)) && (Args.hasArg(options::OPT_fprofile_instr_use) || Args.hasArg(options::OPT_fprofile_instr_use_EQ))) D.Diag(diag::err_drv_argument_not_allowed_with) << "-fprofile-instr-generate" << "-fprofile-instr-use"; - Args.AddAllArgs(CmdArgs, options::OPT_fprofile_instr_generate); + if (Arg *A = Args.getLastArg(options::OPT_fprofile_instr_generate_EQ)) + A->render(Args, CmdArgs); + else + Args.AddAllArgs(CmdArgs, options::OPT_fprofile_instr_generate); if (Arg *A = Args.getLastArg(options::OPT_fprofile_instr_use_EQ)) A->render(Args, CmdArgs); @@ -3269,7 +3450,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-femit-coverage-data"); if (Args.hasArg(options::OPT_fcoverage_mapping) && - !Args.hasArg(options::OPT_fprofile_instr_generate)) + !(Args.hasArg(options::OPT_fprofile_instr_generate) || + Args.hasArg(options::OPT_fprofile_instr_generate_EQ))) D.Diag(diag::err_drv_argument_only_allowed_with) << "-fcoverage-mapping" << "-fprofile-instr-generate"; @@ -3286,10 +3468,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } else { CoverageFilename = llvm::sys::path::filename(Output.getBaseInput()); } - if (llvm::sys::path::is_relative(CoverageFilename.str())) { + if (llvm::sys::path::is_relative(CoverageFilename)) { SmallString<128> Pwd; if (!llvm::sys::fs::current_path(Pwd)) { - llvm::sys::path::append(Pwd, CoverageFilename.str()); + llvm::sys::path::append(Pwd, CoverageFilename); CoverageFilename.swap(Pwd); } } @@ -3372,6 +3554,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_all); Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readonly_property); Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readwrite_property); + Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property_dot_syntax); Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_annotation); Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_instancetype); Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_nsmacros); @@ -3407,10 +3590,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } // Warn about ignored options to clang. - for (arg_iterator it = Args.filtered_begin( - options::OPT_clang_ignored_gcc_optimization_f_Group), - ie = Args.filtered_end(); it != ie; ++it) { - D.Diag(diag::warn_ignored_gcc_optimization) << (*it)->getAsString(Args); + for (const Arg *A : + Args.filtered(options::OPT_clang_ignored_gcc_optimization_f_Group)) { + D.Diag(diag::warn_ignored_gcc_optimization) << A->getAsString(Args); } claimNoWarnArgs(Args); @@ -3427,6 +3609,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // // If a std is supplied, only add -trigraphs if it follows the // option. + bool ImplyVCPPCXXVer = false; if (Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) { if (Std->getOption().matches(options::OPT_ansi)) if (types::isCXX(InputType)) @@ -3453,7 +3636,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ, "-std=", /*Joined=*/true); else if (IsWindowsMSVC) - CmdArgs.push_back("-std=c++11"); + ImplyVCPPCXXVer = true; Args.AddLastArg(CmdArgs, options::OPT_ftrigraphs, options::OPT_fno_trigraphs); @@ -3628,16 +3811,36 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_show_template_tree); Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type); + // Forward flags for OpenMP + if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, + options::OPT_fno_openmp, false)) + switch (getOpenMPRuntime(getToolChain(), Args)) { + case OMPRT_OMP: + case OMPRT_IOMP5: + // Clang can generate useful OpenMP code for these two runtime libraries. + CmdArgs.push_back("-fopenmp"); + break; + default: + // By default, if Clang doesn't know how to generate useful OpenMP code + // for a specific runtime library, we just don't pass the '-fopenmp' flag + // down to the actual compilation. + // FIXME: It would be better to have a mode which *only* omits IR + // generation based on the OpenMP support so that we get consistent + // semantic analysis, etc. + break; + } + const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs(); Sanitize.addArgs(Args, CmdArgs); // Report an error for -faltivec on anything other than PowerPC. - if (const Arg *A = Args.getLastArg(options::OPT_faltivec)) - if (!(getToolChain().getArch() == llvm::Triple::ppc || - getToolChain().getArch() == llvm::Triple::ppc64 || - getToolChain().getArch() == llvm::Triple::ppc64le)) - D.Diag(diag::err_drv_argument_only_allowed_with) - << A->getAsString(Args) << "ppc/ppc64/ppc64le"; + if (const Arg *A = Args.getLastArg(options::OPT_faltivec)) { + const llvm::Triple::ArchType Arch = getToolChain().getArch(); + if (!(Arch == llvm::Triple::ppc || Arch == llvm::Triple::ppc64 || + Arch == llvm::Triple::ppc64le)) + D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args) + << "ppc/ppc64/ppc64le"; + } if (getToolChain().SupportsProfiling()) Args.AddLastArg(CmdArgs, options::OPT_pg); @@ -3710,16 +3913,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } // --param ssp-buffer-size= - for (arg_iterator it = Args.filtered_begin(options::OPT__param), - ie = Args.filtered_end(); it != ie; ++it) { - StringRef Str((*it)->getValue()); + for (const Arg *A : Args.filtered(options::OPT__param)) { + StringRef Str(A->getValue()); if (Str.startswith("ssp-buffer-size=")) { if (StackProtectorLevel) { CmdArgs.push_back("-stack-protector-buffer-size"); // FIXME: Verify the argument is a valid integer. CmdArgs.push_back(Args.MakeArgString(Str.drop_front(16))); } - (*it)->claim(); + A->claim(); } } @@ -3739,8 +3941,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment)); } - if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 || - getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be) + if (Args.hasArg(options::OPT_mstack_probe_size)) { + StringRef Size = Args.getLastArgValue(options::OPT_mstack_probe_size); + + if (!Size.empty()) + CmdArgs.push_back(Args.MakeArgString("-mstack-probe-size=" + Size)); + else + CmdArgs.push_back("-mstack-probe-size=0"); + } + + if (getToolChain().getArch() == llvm::Triple::aarch64 || + getToolChain().getArch() == llvm::Triple::aarch64_be) CmdArgs.push_back("-fallow-half-arguments-and-returns"); if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it, @@ -3845,6 +4056,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fmodules-strict-decluse"); } + // -fno-implicit-modules turns off implicitly compiling modules on demand. + if (!Args.hasFlag(options::OPT_fimplicit_modules, + options::OPT_fno_implicit_modules)) { + CmdArgs.push_back("-fno-implicit-modules"); + } + // -fmodule-name specifies the module that is currently being built (or // used for header checking by -fmodule-maps). Args.AddLastArg(CmdArgs, options::OPT_fmodule_name); @@ -3872,7 +4089,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // No module path was provided: use the default. llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, ModuleCachePath); - llvm::sys::path::append(ModuleCachePath, "org.llvm.clang"); + llvm::sys::path::append(ModuleCachePath, "org.llvm.clang."); + appendUserToPath(ModuleCachePath); llvm::sys::path::append(ModuleCachePath, "ModuleCache"); } const char Arg[] = "-fmodules-cache-path="; @@ -3911,10 +4129,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, llvm::sys::fs::file_status Status; if (llvm::sys::fs::status(A->getValue(), Status)) D.Diag(diag::err_drv_no_such_file) << A->getValue(); - char TimeStamp[48]; - snprintf(TimeStamp, sizeof(TimeStamp), "-fbuild-session-timestamp=%" PRIu64, - (uint64_t)Status.getLastModificationTime().toEpochTime()); - CmdArgs.push_back(Args.MakeArgString(TimeStamp)); + CmdArgs.push_back(Args.MakeArgString( + "-fbuild-session-timestamp=" + + Twine((uint64_t)Status.getLastModificationTime().toEpochTime()))); } if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) { @@ -3940,21 +4157,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, false)) CmdArgs.push_back("-fno-elide-constructors"); - // -frtti is default. - if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti) || - KernelOrKext) { - CmdArgs.push_back("-fno-rtti"); + ToolChain::RTTIMode RTTIMode = getToolChain().getRTTIMode(); - // -fno-rtti cannot usefully be combined with -fsanitize=vptr. - if (Sanitize.sanitizesVptr()) { - std::string NoRttiArg = - Args.getLastArg(options::OPT_mkernel, - options::OPT_fapple_kext, - options::OPT_fno_rtti)->getAsString(Args); - D.Diag(diag::err_drv_argument_not_allowed_with) - << "-fsanitize=vptr" << NoRttiArg; - } - } + if (KernelOrKext || (types::isCXX(InputType) && + (RTTIMode == ToolChain::RM_DisabledExplicitly || + RTTIMode == ToolChain::RM_DisabledImplicitly))) + CmdArgs.push_back("-fno-rtti"); // -fshort-enums=0 is default for all architectures except Hexagon. if (Args.hasFlag(options::OPT_fshort_enums, @@ -3964,14 +4172,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fshort-enums"); // -fsigned-char is default. - if (!Args.hasFlag(options::OPT_fsigned_char, options::OPT_funsigned_char, - isSignedCharDefault(getToolChain().getTriple()))) + if (Arg *A = Args.getLastArg( + options::OPT_fsigned_char, options::OPT_fno_signed_char, + options::OPT_funsigned_char, options::OPT_fno_unsigned_char)) { + if (A->getOption().matches(options::OPT_funsigned_char) || + A->getOption().matches(options::OPT_fno_signed_char)) { + CmdArgs.push_back("-fno-signed-char"); + } + } else if (!isSignedCharDefault(getToolChain().getTriple())) { CmdArgs.push_back("-fno-signed-char"); - - // -fthreadsafe-static is default. - if (!Args.hasFlag(options::OPT_fthreadsafe_statics, - options::OPT_fno_threadsafe_statics)) - CmdArgs.push_back("-fno-threadsafe-statics"); + } // -fuse-cxa-atexit is default. if (!Args.hasFlag(options::OPT_fuse_cxa_atexit, @@ -3987,6 +4197,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, IsWindowsMSVC)) CmdArgs.push_back("-fms-extensions"); + // -fno-use-line-directives is default. + if (Args.hasFlag(options::OPT_fuse_line_directives, + options::OPT_fno_use_line_directives, false)) + CmdArgs.push_back("-fuse-line-directives"); + // -fms-compatibility=0 is default. if (Args.hasFlag(options::OPT_fms_compatibility, options::OPT_fno_ms_compatibility, @@ -3995,29 +4210,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, true)))) CmdArgs.push_back("-fms-compatibility"); - // -fms-compatibility-version=17.00 is default. - if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, - IsWindowsMSVC) || Args.hasArg(options::OPT_fmsc_version) || - Args.hasArg(options::OPT_fms_compatibility_version)) { - const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version); - const Arg *MSCompatibilityVersion = - Args.getLastArg(options::OPT_fms_compatibility_version); - - if (MSCVersion && MSCompatibilityVersion) - D.Diag(diag::err_drv_argument_not_allowed_with) - << MSCVersion->getAsString(Args) - << MSCompatibilityVersion->getAsString(Args); - - std::string Ver; - if (MSCompatibilityVersion) - Ver = Args.getLastArgValue(options::OPT_fms_compatibility_version); - else if (MSCVersion) - Ver = getMSCompatibilityVersion(MSCVersion->getValue()); + // -fms-compatibility-version=18.00 is default. + VersionTuple MSVT = visualstudio::getMSVCVersion( + &D, getToolChain().getTriple(), Args, IsWindowsMSVC); + if (!MSVT.empty()) + CmdArgs.push_back( + Args.MakeArgString("-fms-compatibility-version=" + MSVT.getAsString())); - if (Ver.empty()) - CmdArgs.push_back("-fms-compatibility-version=17.00"); + bool IsMSVC2015Compatible = MSVT.getMajor() >= 19; + if (ImplyVCPPCXXVer) { + if (IsMSVC2015Compatible) + CmdArgs.push_back("-std=c++14"); else - CmdArgs.push_back(Args.MakeArgString("-fms-compatibility-version=" + Ver)); + CmdArgs.push_back("-std=c++11"); } // -fno-borland-extensions is default. @@ -4025,6 +4230,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_borland_extensions, false)) CmdArgs.push_back("-fborland-extensions"); + // -fthreadsafe-static is default, except for MSVC compatibility versions less + // than 19. + if (!Args.hasFlag(options::OPT_fthreadsafe_statics, + options::OPT_fno_threadsafe_statics, + !IsWindowsMSVC || IsMSVC2015Compatible)) + CmdArgs.push_back("-fno-threadsafe-statics"); + // -fno-delayed-template-parsing is default, except for Windows where MSVC STL // needs it. if (Args.hasFlag(options::OPT_fdelayed_template_parsing, @@ -4069,7 +4281,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // When ObjectiveC legacy runtime is in effect on MacOSX, // turn on the option to do Array/Dictionary subscripting // by default. - if (getToolChain().getTriple().getArch() == llvm::Triple::x86 && + if (getToolChain().getArch() == llvm::Triple::x86 && getToolChain().getTriple().isMacOSX() && !getToolChain().getTriple().isMacOSXVersionLT(10, 7) && objcRuntime.getKind() == ObjCRuntime::FragileMacOSX && @@ -4130,9 +4342,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } + if (Args.hasFlag(options::OPT_fapplication_extension, + options::OPT_fno_application_extension, false)) + CmdArgs.push_back("-fapplication-extension"); + // Handle GCC-style exception args. if (!C.getDriver().IsCLMode()) - addExceptionArgs(Args, InputType, getToolChain().getTriple(), KernelOrKext, + addExceptionArgs(Args, InputType, getToolChain(), KernelOrKext, objcRuntime, CmdArgs); if (getToolChain().UseSjLjExceptions()) @@ -4143,6 +4359,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_assume_sane_operator_new)) CmdArgs.push_back("-fno-assume-sane-operator-new"); + // -fsized-deallocation is off by default, as it is an ABI-breaking change for + // most platforms. + if (Args.hasFlag(options::OPT_fsized_deallocation, + options::OPT_fno_sized_deallocation, false)) + CmdArgs.push_back("-fsized-deallocation"); + // -fconstant-cfstrings is default, and may be subject to argument translation // on Darwin. if (!Args.hasFlag(options::OPT_fconstant_cfstrings, @@ -4326,6 +4548,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, false)) CmdArgs.push_back("-fasm-blocks"); + // -fgnu-inline-asm is default. + if (!Args.hasFlag(options::OPT_fgnu_inline_asm, + options::OPT_fno_gnu_inline_asm, true)) + CmdArgs.push_back("-fno-gnu-inline-asm"); + // Enable vectorization per default according to the optimization level // selected. For optimization levels that want vectorization we use the alias // option to simplify the hasFlag logic. @@ -4434,23 +4661,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // parser. Args.AddAllArgValues(CmdArgs, options::OPT_Xclang); bool OptDisabled = false; - for (arg_iterator it = Args.filtered_begin(options::OPT_mllvm), - ie = Args.filtered_end(); it != ie; ++it) { - (*it)->claim(); + for (const Arg *A : Args.filtered(options::OPT_mllvm)) { + A->claim(); // We translate this by hand to the -cc1 argument, since nightly test uses // it and developers have been trained to spell it with -mllvm. - if (StringRef((*it)->getValue(0)) == "-disable-llvm-optzns") { + if (StringRef(A->getValue(0)) == "-disable-llvm-optzns") { CmdArgs.push_back("-disable-llvm-optzns"); OptDisabled = true; } else - (*it)->render(Args, CmdArgs); + A->render(Args, CmdArgs); } // With -save-temps, we want to save the unoptimized bitcode output from the // CompileJobAction, so disable optimizations if they are not already // disabled. - if (Args.hasArg(options::OPT_save_temps) && !OptDisabled && + if (C.getDriver().isSaveTempsEnabled() && !OptDisabled && isa<CompileJobAction>(JA)) CmdArgs.push_back("-disable-llvm-optzns"); @@ -4492,7 +4718,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Flags += EscapedArg; } CmdArgs.push_back("-dwarf-debug-flags"); - CmdArgs.push_back(Args.MakeArgString(Flags.str())); + CmdArgs.push_back(Args.MakeArgString(Flags)); } // Add the split debug info name to the command lines here so we @@ -4504,7 +4730,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, const char *SplitDwarfOut; if (SplitDwarf) { CmdArgs.push_back("-split-dwarf-file"); - SplitDwarfOut = SplitDebugName(Args, Inputs); + SplitDwarfOut = SplitDebugName(Args, Input); CmdArgs.push_back(SplitDwarfOut); } @@ -4772,8 +4998,8 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const { EHFlags EH = parseClangCLEHFlags(D, Args); // FIXME: Do something with NoExceptC. if (EH.Synch || EH.Asynch) { - CmdArgs.push_back("-fexceptions"); CmdArgs.push_back("-fcxx-exceptions"); + CmdArgs.push_back("-fexceptions"); } // /EP should expand to -E -P. @@ -4782,6 +5008,19 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const { CmdArgs.push_back("-P"); } + unsigned VolatileOptionID; + if (getToolChain().getArch() == llvm::Triple::x86_64 || + getToolChain().getArch() == llvm::Triple::x86) + VolatileOptionID = options::OPT__SLASH_volatile_ms; + else + VolatileOptionID = options::OPT__SLASH_volatile_iso; + + if (Arg *A = Args.getLastArg(options::OPT__SLASH_volatile_Group)) + VolatileOptionID = A->getOption().getID(); + + if (VolatileOptionID == options::OPT__SLASH_volatile_ms) + CmdArgs.push_back("-fms-volatile"); + Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg); Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb); if (MostGeneralArg && BestCaseArg) @@ -4826,6 +5065,17 @@ visualstudio::Compile *Clang::getCLFallback() const { return CLFallback.get(); } +void ClangAs::AddMIPSTargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + StringRef CPUName; + StringRef ABIName; + const llvm::Triple &Triple = getToolChain().getTriple(); + mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); + + CmdArgs.push_back("-target-abi"); + CmdArgs.push_back(ABIName.data()); +} + void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -4862,10 +5112,10 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, // Set the main file name, so that debug info works even with // -save-temps or preprocessed assembly. CmdArgs.push_back("-main-file-name"); - CmdArgs.push_back(Clang::getBaseInputName(Args, Inputs)); + CmdArgs.push_back(Clang::getBaseInputName(Args, Input)); // Add the target cpu - const llvm::Triple &Triple = getToolChain().getTriple(); + const llvm::Triple Triple(TripleStr); std::string CPU = getCPUName(Args, Triple); if (!CPU.empty()) { CmdArgs.push_back("-target-cpu"); @@ -4928,20 +5178,31 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, Flags += EscapedArg; } CmdArgs.push_back("-dwarf-debug-flags"); - CmdArgs.push_back(Args.MakeArgString(Flags.str())); + CmdArgs.push_back(Args.MakeArgString(Flags)); } // FIXME: Add -static support, once we have it. + // Add target specific flags. + switch(getToolChain().getArch()) { + default: + break; + + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + AddMIPSTargetArgs(Args, CmdArgs); + break; + } + // Consume all the warning flags. Usually this would be handled more // gracefully by -cc1 (warning about unknown warning flags, etc) but -cc1as // doesn't handle that so rather than warning about unused flags that are // actually used, we'll lie by omission instead. // FIXME: Stop lying and consume only the appropriate driver flags - for (arg_iterator it = Args.filtered_begin(options::OPT_W_Group), - ie = Args.filtered_end(); - it != ie; ++it) - (*it)->claim(); + for (const Arg *A : Args.filtered(options::OPT_W_Group)) + A->claim(); CollectArgsForIntegratedAssembler(C, Args, CmdArgs, getToolChain().getDriver()); @@ -4964,7 +5225,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_gsplit_dwarf) && getToolChain().getTriple().isOSLinux()) SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, - SplitDebugName(Args, Inputs)); + SplitDebugName(Args, Input)); } void GnuTool::anchor() {} @@ -5012,7 +5273,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, // // FIXME: The triple class should directly provide the information we want // here. - llvm::Triple::ArchType Arch = getToolChain().getArch(); + const llvm::Triple::ArchType Arch = getToolChain().getArch(); if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc) CmdArgs.push_back("-m32"); else if (Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::ppc64 || @@ -5095,16 +5356,22 @@ void gcc::Compile::RenderExtraToolArgs(const JobAction &JA, ArgStringList &CmdArgs) const { const Driver &D = getToolChain().getDriver(); + switch (JA.getType()) { // If -flto, etc. are present then make sure not to force assembly output. - if (JA.getType() == types::TY_LLVM_IR || JA.getType() == types::TY_LTO_IR || - JA.getType() == types::TY_LLVM_BC || JA.getType() == types::TY_LTO_BC) + case types::TY_LLVM_IR: + case types::TY_LTO_IR: + case types::TY_LLVM_BC: + case types::TY_LTO_BC: CmdArgs.push_back("-c"); - else { - if (JA.getType() != types::TY_PP_Asm) - D.Diag(diag::err_drv_invalid_gcc_output_type) - << getTypeName(JA.getType()); - + break; + case types::TY_PP_Asm: CmdArgs.push_back("-S"); + break; + case types::TY_Nothing: + CmdArgs.push_back("-fsyntax-only"); + break; + default: + D.Diag(diag::err_drv_invalid_gcc_output_type) << getTypeName(JA.getType()); } } @@ -5142,10 +5409,8 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fsyntax-only"); } - std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args); - if (!SmallDataThreshold.empty()) - CmdArgs.push_back( - Args.MakeArgString(std::string("-G") + SmallDataThreshold)); + if (const char* v = toolchains::Hexagon_TC::GetSmallDataThreshold(Args)) + CmdArgs.push_back(Args.MakeArgString(std::string("-G") + v)); Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); @@ -5188,17 +5453,16 @@ void hexagon::Link::RenderExtraToolArgs(const JobAction &JA, // The types are (hopefully) good enough. } -void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const ArgList &Args, - const char *LinkingOutput) const { +static void constructHexagonLinkArgs(Compilation &C, const JobAction &JA, + const toolchains::Hexagon_TC& ToolChain, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + ArgStringList &CmdArgs, + const char *LinkingOutput) { - const toolchains::Hexagon_TC& ToolChain = - static_cast<const toolchains::Hexagon_TC&>(getToolChain()); const Driver &D = ToolChain.getDriver(); - ArgStringList CmdArgs; //---------------------------------------------------------------------------- // @@ -5209,6 +5473,7 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, bool incStdLib = !Args.hasArg(options::OPT_nostdlib); bool incStartFiles = !Args.hasArg(options::OPT_nostartfiles); bool incDefLibs = !Args.hasArg(options::OPT_nodefaultlibs); + bool useG0 = false; bool useShared = buildingLib && !hasStaticArg; //---------------------------------------------------------------------------- @@ -5242,10 +5507,9 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, if (buildPIE && !buildingLib) CmdArgs.push_back("-pie"); - std::string SmallDataThreshold = GetHexagonSmallDataThresholdValue(Args); - if (!SmallDataThreshold.empty()) { - CmdArgs.push_back( - Args.MakeArgString(std::string("-G") + SmallDataThreshold)); + if (const char* v = toolchains::Hexagon_TC::GetSmallDataThreshold(Args)) { + CmdArgs.push_back(Args.MakeArgString(std::string("-G") + v)); + useG0 = toolchains::Hexagon_TC::UsesG0(v); } //---------------------------------------------------------------------------- @@ -5261,8 +5525,7 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, toolchains::Hexagon_TC::GetGnuDir(D.InstalledDir, Args) + "/"; const std::string StartFilesDir = RootDir + "hexagon/lib" - + (buildingLib - ? MarchG0Suffix : MarchSuffix); + + (useG0 ? MarchG0Suffix : MarchSuffix); //---------------------------------------------------------------------------- // moslib @@ -5270,10 +5533,9 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, std::vector<std::string> oslibs; bool hasStandalone= false; - for (arg_iterator it = Args.filtered_begin(options::OPT_moslib_EQ), - ie = Args.filtered_end(); it != ie; ++it) { - (*it)->claim(); - oslibs.push_back((*it)->getValue()); + for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) { + A->claim(); + oslibs.emplace_back(A->getValue()); hasStandalone = hasStandalone || (oslibs.back() == "standalone"); } if (oslibs.empty()) { @@ -5344,6 +5606,20 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, std::string finiObj = useShared ? "/finiS.o" : "/fini.o"; CmdArgs.push_back(Args.MakeArgString(StartFilesDir + finiObj)); } +} + +void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + + const toolchains::Hexagon_TC& ToolChain = + static_cast<const toolchains::Hexagon_TC&>(getToolChain()); + + ArgStringList CmdArgs; + constructHexagonLinkArgs(C, JA, ToolChain, Output, Inputs, Args, CmdArgs, + LinkingOutput); std::string Linker = ToolChain.GetProgramPath("hexagon-ld"); C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), @@ -5351,9 +5627,8 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, } // Hexagon tools end. -/// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting. -const char *arm::getARMCPUForMArch(const ArgList &Args, - const llvm::Triple &Triple) { +const StringRef arm::getARMArch(const ArgList &Args, + const llvm::Triple &Triple) { StringRef MArch; if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) { // Otherwise, if we have -march= choose the base CPU for that arch. @@ -5367,22 +5642,44 @@ const char *arm::getARMCPUForMArch(const ArgList &Args, if (MArch == "native") { std::string CPU = llvm::sys::getHostCPUName(); if (CPU != "generic") { - // Translate the native cpu into the architecture. The switch below will - // then chose the minimum cpu for that arch. - MArch = std::string("arm") + arm::getLLVMArchSuffixForARM(CPU); + // Translate the native cpu into the architecture suffix for that CPU. + const char *Suffix = arm::getLLVMArchSuffixForARM(CPU, MArch); + // If there is no valid architecture suffix for this CPU we don't know how + // to handle it, so return no architecture. + if (strcmp(Suffix,"") == 0) + MArch = ""; + else + MArch = std::string("arm") + Suffix; } } - return Triple.getARMCPUForArch(MArch); + return MArch; +} +/// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting. +const char *arm::getARMCPUForMArch(const ArgList &Args, + const llvm::Triple &Triple) { + StringRef MArch = getARMArch(Args, Triple); + // getARMCPUForArch defaults to the triple if MArch is empty, but empty MArch + // here means an -march=native that we can't handle, so instead return no CPU. + if (MArch.empty()) + return ""; + + // We need to return an empty string here on invalid MArch values as the + // various places that call this function can't cope with a null result. + const char *result = Triple.getARMCPUForArch(MArch); + if (result) + return result; + else + return ""; } /// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. -StringRef arm::getARMTargetCPU(const ArgList &Args, +std::string arm::getARMTargetCPU(const ArgList &Args, const llvm::Triple &Triple) { // FIXME: Warn on inconsistent use of -mcpu and -march. // If we have -mcpu=, use that. if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { - StringRef MCPU = A->getValue(); + std::string MCPU = StringRef(A->getValue()).lower(); // Handle -mcpu=native. if (MCPU == "native") return llvm::sys::getHostCPUName(); @@ -5394,48 +5691,48 @@ StringRef arm::getARMTargetCPU(const ArgList &Args, } /// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular -/// CPU. -// +/// CPU (or Arch, if CPU is generic). // FIXME: This is redundant with -mcpu, why does LLVM use this. -// FIXME: tblgen this, or kill it! -const char *arm::getLLVMArchSuffixForARM(StringRef CPU) { - return llvm::StringSwitch<const char *>(CPU) - .Case("strongarm", "v4") - .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t") - .Cases("arm720t", "arm9", "arm9tdmi", "v4t") - .Cases("arm920", "arm920t", "arm922t", "v4t") - .Cases("arm940t", "ep9312","v4t") - .Cases("arm10tdmi", "arm1020t", "v5") - .Cases("arm9e", "arm926ej-s", "arm946e-s", "v5e") - .Cases("arm966e-s", "arm968e-s", "arm10e", "v5e") - .Cases("arm1020e", "arm1022e", "xscale", "iwmmxt", "v5e") - .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "v6") - .Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6") - .Cases("arm1156t2-s", "arm1156t2f-s", "v6t2") - .Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7") - .Cases("cortex-a9", "cortex-a12", "cortex-a15", "cortex-a17", "krait", "v7") - .Cases("cortex-r4", "cortex-r5", "v7r") - .Case("cortex-m0", "v6m") - .Case("cortex-m3", "v7m") - .Cases("cortex-m4", "cortex-m7", "v7em") - .Case("swift", "v7s") - .Case("cyclone", "v8") - .Cases("cortex-a53", "cortex-a57", "v8") - .Default(""); -} - -void arm::appendEBLinkFlags(const ArgList &Args, ArgStringList &CmdArgs, const llvm::Triple &Triple) { +const char *arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch) { + if (CPU == "generic" && + llvm::ARMTargetParser::parseArch(Arch) == llvm::ARM::AK_ARMV8_1A) + return "v8.1a"; + + unsigned ArchKind = llvm::ARMTargetParser::parseCPUArch(CPU); + if (ArchKind == llvm::ARM::AK_INVALID) + return ""; + return llvm::ARMTargetParser::getSubArch(ArchKind); +} + +void arm::appendEBLinkFlags(const ArgList &Args, ArgStringList &CmdArgs, + const llvm::Triple &Triple) { if (Args.hasArg(options::OPT_r)) return; - StringRef Suffix = getLLVMArchSuffixForARM(getARMCPUForMArch(Args, Triple)); - const char *LinkFlag = llvm::StringSwitch<const char *>(Suffix) - .Cases("v4", "v4t", "v5", "v5e", nullptr) - .Cases("v6", "v6t2", nullptr) - .Default("--be8"); - - if (LinkFlag) - CmdArgs.push_back(LinkFlag); + // ARMv7 (and later) and ARMv6-M do not support BE-32, so instruct the linker + // to generate BE-8 executables. + if (getARMSubArchVersionNumber(Triple) >= 7 || isARMMProfile(Triple)) + CmdArgs.push_back("--be8"); +} + +mips::NanEncoding mips::getSupportedNanEncoding(StringRef &CPU) { + return (NanEncoding)llvm::StringSwitch<int>(CPU) + .Case("mips1", NanLegacy) + .Case("mips2", NanLegacy) + .Case("mips3", NanLegacy) + .Case("mips4", NanLegacy) + .Case("mips5", NanLegacy) + .Case("mips32", NanLegacy) + .Case("mips32r2", NanLegacy) + .Case("mips32r3", NanLegacy | Nan2008) + .Case("mips32r5", NanLegacy | Nan2008) + .Case("mips32r6", Nan2008) + .Case("mips64", NanLegacy) + .Case("mips64r2", NanLegacy) + .Case("mips64r3", NanLegacy | Nan2008) + .Case("mips64r5", NanLegacy | Nan2008) + .Case("mips64r6", Nan2008) + .Default(NanLegacy); } bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) { @@ -5474,8 +5771,8 @@ bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName, return llvm::StringSwitch<bool>(CPUName) .Cases("mips2", "mips3", "mips4", "mips5", true) - .Cases("mips32", "mips32r2", true) - .Cases("mips64", "mips64r2", true) + .Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true) + .Cases("mips64", "mips64r2", "mips64r3", "mips64r5", true) .Default(false); } @@ -5515,7 +5812,7 @@ llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) { } void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str) { - llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str); + const llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str); T.setArch(Arch); if (Str == "x86_64h") @@ -5527,14 +5824,13 @@ void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str) { } const char *Clang::getBaseInputName(const ArgList &Args, - const InputInfoList &Inputs) { - return Args.MakeArgString( - llvm::sys::path::filename(Inputs[0].getBaseInput())); + const InputInfo &Input) { + return Args.MakeArgString(llvm::sys::path::filename(Input.getBaseInput())); } const char *Clang::getBaseInputStem(const ArgList &Args, const InputInfoList &Inputs) { - const char *Str = getBaseInputName(Args, Inputs); + const char *Str = getBaseInputName(Args, Inputs[0]); if (const char *End = strrchr(Str, '.')) return Args.MakeArgString(std::string(Str, End)); @@ -5556,6 +5852,76 @@ const char *Clang::getDependencyFileName(const ArgList &Args, return Args.MakeArgString(Res + ".d"); } +void cloudabi::Link::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + const ToolChain &ToolChain = getToolChain(); + const Driver &D = ToolChain.getDriver(); + ArgStringList CmdArgs; + + // Silence warning for "clang -g foo.o -o foo" + Args.ClaimAllArgs(options::OPT_g_Group); + // and "clang -emit-llvm foo.o -o foo" + Args.ClaimAllArgs(options::OPT_emit_llvm); + // and for "clang -w foo.o -o foo". Other warning options are already + // handled somewhere else. + Args.ClaimAllArgs(options::OPT_w); + + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + + // CloudABI only supports static linkage. + CmdArgs.push_back("-Bstatic"); + CmdArgs.push_back("--eh-frame-hdr"); + CmdArgs.push_back("--gc-sections"); + + if (Output.isFilename()) { + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + } else { + assert(Output.isNothing() && "Invalid output."); + } + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o"))); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o"))); + } + + Args.AddAllArgs(CmdArgs, options::OPT_L); + const ToolChain::path_list &Paths = ToolChain.getFilePaths(); + for (const auto &Path : Paths) + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path)); + Args.AddAllArgs(CmdArgs, options::OPT_T_Group); + Args.AddAllArgs(CmdArgs, options::OPT_e); + Args.AddAllArgs(CmdArgs, options::OPT_s); + Args.AddAllArgs(CmdArgs, options::OPT_t); + Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); + Args.AddAllArgs(CmdArgs, options::OPT_r); + + if (D.IsUsingLTO(ToolChain, Args)) + AddGoldPlugin(ToolChain, Args, CmdArgs); + + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + if (D.CCCIsCXX()) + ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); + CmdArgs.push_back("-lc"); + CmdArgs.push_back("-lcompiler_rt"); + } + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); + + const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs)); +} + void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -5677,10 +6043,17 @@ void darwin::Link::AddLinkArgs(Compilation &C, if (Args.hasArg(options::OPT_rdynamic) && Version[0] >= 137) CmdArgs.push_back("-export_dynamic"); + // If we are using App Extension restrictions, pass a flag to the linker + // telling it that the compiled code has been audited. + if (Args.hasFlag(options::OPT_fapplication_extension, + options::OPT_fno_application_extension, false)) + CmdArgs.push_back("-application_extension"); + // If we are using LTO, then automatically create a temporary file path for // the linker to use, so that it's lifetime will extend past a possible // dsymutil step. - if (Version[0] >= 116 && D.IsUsingLTO(Args) && NeedsTempPath(Inputs)) { + if (Version[0] >= 116 && D.IsUsingLTO(getToolChain(), Args) && + NeedsTempPath(Inputs)) { const char *TmpPath = C.getArgs().MakeArgString( D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object))); C.addTempFile(TmpPath); @@ -5826,12 +6199,6 @@ void darwin::Link::AddLinkArgs(Compilation &C, Args.AddLastArg(CmdArgs, options::OPT_Mach); } -enum LibOpenMP { - LibUnknown, - LibGOMP, - LibIOMP5 -}; - void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -5889,27 +6256,22 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_L); - LibOpenMP UsedOpenMPLib = LibUnknown; - if (Args.hasArg(options::OPT_fopenmp)) { - UsedOpenMPLib = LibGOMP; - } else if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) { - UsedOpenMPLib = llvm::StringSwitch<LibOpenMP>(A->getValue()) - .Case("libgomp", LibGOMP) - .Case("libiomp5", LibIOMP5) - .Default(LibUnknown); - if (UsedOpenMPLib == LibUnknown) - getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument) - << A->getOption().getName() << A->getValue(); - } - switch (UsedOpenMPLib) { - case LibGOMP: - CmdArgs.push_back("-lgomp"); - break; - case LibIOMP5: - CmdArgs.push_back("-liomp5"); - break; - case LibUnknown: - break; + if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, + options::OPT_fno_openmp, false)) { + switch (getOpenMPRuntime(getToolChain(), Args)) { + case OMPRT_OMP: + CmdArgs.push_back("-lomp"); + break; + case OMPRT_GOMP: + CmdArgs.push_back("-lgomp"); + break; + case OMPRT_IOMP5: + CmdArgs.push_back("-liomp5"); + break; + case OMPRT_Unknown: + // Already diagnosed. + break; + } } AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); @@ -5951,6 +6313,11 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_fnested_functions)) CmdArgs.push_back("-allow_stack_execute"); + // TODO: It would be nice to use addProfileRT() here, but darwin's compiler-rt + // paths are different enough from other toolchains that this needs a fair + // amount of refactoring done first. + getMachOToolChain().addProfileRTLibs(Args, CmdArgs); + if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { if (getToolChain().getDriver().CCCIsCXX()) @@ -5970,6 +6337,20 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_F); + // -iframework should be forwarded as -F. + for (const Arg *A : Args.filtered(options::OPT_iframework)) + CmdArgs.push_back(Args.MakeArgString(std::string("-F") + A->getValue())); + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + if (Arg *A = Args.getLastArg(options::OPT_fveclib)) { + if (A->getValue() == StringRef("Accelerate")) { + CmdArgs.push_back("-framework"); + CmdArgs.push_back("Accelerate"); + } + } + } + const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); std::unique_ptr<Command> Cmd = @@ -6073,7 +6454,7 @@ void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA, std::string GCCLibPath = "/usr/gcc/4.5/lib/gcc/"; const llvm::Triple &T = getToolChain().getTriple(); std::string LibPath = "/usr/lib/"; - llvm::Triple::ArchType Arch = T.getArch(); + const llvm::Triple::ArchType Arch = T.getArch(); switch (Arch) { case llvm::Triple::x86: GCCLibPath += @@ -6191,6 +6572,7 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, break; case llvm::Triple::sparc: + case llvm::Triple::sparcel: CmdArgs.push_back("-32"); NeedsKPIC = true; break; @@ -6478,7 +6860,7 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA, } StringRef MyArch; - switch (getToolChain().getTriple().getArch()) { + switch (getToolChain().getArch()) { case llvm::Triple::arm: MyArch = "arm"; break; @@ -6569,6 +6951,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-matpcs"); } } else if (getToolChain().getArch() == llvm::Triple::sparc || + getToolChain().getArch() == llvm::Triple::sparcel || getToolChain().getArch() == llvm::Triple::sparcv9) { if (getToolChain().getArch() == llvm::Triple::sparc) CmdArgs.push_back("-Av8plusa"); @@ -6596,12 +6979,13 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { - const toolchains::FreeBSD& ToolChain = - static_cast<const toolchains::FreeBSD&>(getToolChain()); + const toolchains::FreeBSD &ToolChain = + static_cast<const toolchains::FreeBSD &>(getToolChain()); const Driver &D = ToolChain.getDriver(); + const llvm::Triple::ArchType Arch = ToolChain.getArch(); const bool IsPIE = - !Args.hasArg(options::OPT_shared) && - (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault()); + !Args.hasArg(options::OPT_shared) && + (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault()); ArgStringList CmdArgs; // Silence warning for "clang -g foo.o -o foo" @@ -6631,7 +7015,6 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("/libexec/ld-elf.so.1"); } if (ToolChain.getTriple().getOSMajorVersion() >= 9) { - llvm::Triple::ArchType Arch = ToolChain.getArch(); if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc || Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) { CmdArgs.push_back("--hash-style=both"); @@ -6642,12 +7025,12 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, // When building 32-bit code on FreeBSD/amd64, we have to explicitly // instruct ld in the base system to link 32-bit code. - if (ToolChain.getArch() == llvm::Triple::x86) { + if (Arch == llvm::Triple::x86) { CmdArgs.push_back("-m"); CmdArgs.push_back("elf_i386_fbsd"); } - if (ToolChain.getArch() == llvm::Triple::ppc) { + if (Arch == llvm::Triple::ppc) { CmdArgs.push_back("-m"); CmdArgs.push_back("elf32ppc_fbsd"); } @@ -6708,7 +7091,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); Args.AddAllArgs(CmdArgs, options::OPT_r); - if (D.IsUsingLTO(Args)) + if (D.IsUsingLTO(getToolChain(), Args)) AddGoldPlugin(ToolChain, Args, CmdArgs); bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs); @@ -6804,7 +7187,7 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, case llvm::Triple::armeb: case llvm::Triple::thumb: case llvm::Triple::thumbeb: { - std::string MArch(arm::getARMTargetCPU(Args, getToolChain().getTriple())); + std::string MArch = arm::getARMTargetCPU(Args, getToolChain().getTriple()); CmdArgs.push_back(Args.MakeArgString("-mcpu=" + MArch)); break; } @@ -6834,6 +7217,7 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, } case llvm::Triple::sparc: + case llvm::Triple::sparcel: CmdArgs.push_back("-32"); addAssemblerKPIC(Args, CmdArgs); break; @@ -6912,7 +7296,8 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, break; case llvm::Triple::armeb: case llvm::Triple::thumbeb: - arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getTriple()); + arm::appendEBLinkFlags(Args, CmdArgs, + llvm::Triple(getToolChain().ComputeEffectiveClangTriple(Args))); CmdArgs.push_back("-m"); switch (getToolChain().getTriple().getEnvironment()) { case llvm::Triple::EABI: @@ -7080,47 +7465,66 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, ArgStringList CmdArgs; bool NeedsKPIC = false; + switch (getToolChain().getArch()) { + default: + break; // Add --32/--64 to make sure we get the format we want. // This is incomplete - if (getToolChain().getArch() == llvm::Triple::x86) { + case llvm::Triple::x86: CmdArgs.push_back("--32"); - } else if (getToolChain().getArch() == llvm::Triple::x86_64) { + break; + case llvm::Triple::x86_64: if (getToolChain().getTriple().getEnvironment() == llvm::Triple::GNUX32) CmdArgs.push_back("--x32"); else CmdArgs.push_back("--64"); - } else if (getToolChain().getArch() == llvm::Triple::ppc) { + break; + case llvm::Triple::ppc: CmdArgs.push_back("-a32"); CmdArgs.push_back("-mppc"); CmdArgs.push_back("-many"); - } else if (getToolChain().getArch() == llvm::Triple::ppc64) { + break; + case llvm::Triple::ppc64: CmdArgs.push_back("-a64"); CmdArgs.push_back("-mppc64"); CmdArgs.push_back("-many"); - } else if (getToolChain().getArch() == llvm::Triple::ppc64le) { + break; + case llvm::Triple::ppc64le: CmdArgs.push_back("-a64"); CmdArgs.push_back("-mppc64"); CmdArgs.push_back("-many"); CmdArgs.push_back("-mlittle-endian"); - } else if (getToolChain().getArch() == llvm::Triple::sparc) { + break; + case llvm::Triple::sparc: + case llvm::Triple::sparcel: CmdArgs.push_back("-32"); CmdArgs.push_back("-Av8plusa"); NeedsKPIC = true; - } else if (getToolChain().getArch() == llvm::Triple::sparcv9) { + break; + case llvm::Triple::sparcv9: CmdArgs.push_back("-64"); CmdArgs.push_back("-Av9a"); NeedsKPIC = true; - } else if (getToolChain().getArch() == llvm::Triple::arm || - getToolChain().getArch() == llvm::Triple::armeb) { - StringRef MArch = getToolChain().getArchName(); - if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a") + break; + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: { + const llvm::Triple &Triple = getToolChain().getTriple(); + switch (Triple.getSubArch()) { + case llvm::Triple::ARMSubArch_v7: CmdArgs.push_back("-mfpu=neon"); - if (MArch == "armv8" || MArch == "armv8a" || MArch == "armv8-a" || - MArch == "armebv8" || MArch == "armebv8a" || MArch == "armebv8-a") + break; + case llvm::Triple::ARMSubArch_v8: CmdArgs.push_back("-mfpu=crypto-neon-fp-armv8"); + break; + default: + break; + } StringRef ARMFloatABI = tools::arm::getARMFloatABI( - getToolChain().getDriver(), Args, getToolChain().getTriple()); + getToolChain().getDriver(), Args, + llvm::Triple(getToolChain().ComputeEffectiveClangTriple(Args))); CmdArgs.push_back(Args.MakeArgString("-mfloat-abi=" + ARMFloatABI)); Args.AddLastArg(CmdArgs, options::OPT_march_EQ); @@ -7130,15 +7534,17 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, // march from being picked in the absence of a cpu flag. Arg *A; if ((A = Args.getLastArg(options::OPT_mcpu_EQ)) && - StringRef(A->getValue()) == "krait") + StringRef(A->getValue()).lower() == "krait") CmdArgs.push_back("-march=armv7-a"); else Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ); Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ); - } else if (getToolChain().getArch() == llvm::Triple::mips || - getToolChain().getArch() == llvm::Triple::mipsel || - getToolChain().getArch() == llvm::Triple::mips64 || - getToolChain().getArch() == llvm::Triple::mips64el) { + break; + } + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: { StringRef CPUName; StringRef ABIName; mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); @@ -7222,11 +7628,15 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_mno_odd_spreg); NeedsKPIC = true; - } else if (getToolChain().getArch() == llvm::Triple::systemz) { + break; + } + case llvm::Triple::systemz: { // Always pass an -march option, since our default of z10 is later // than the GNU assembler's default. StringRef CPUName = getSystemZTargetCPU(Args); CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName)); + break; + } } if (NeedsKPIC) @@ -7250,7 +7660,7 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_gsplit_dwarf) && getToolChain().getTriple().isOSLinux()) SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, - SplitDebugName(Args, Inputs)); + SplitDebugName(Args, Inputs[0])); } static void AddLibgcc(const llvm::Triple &Triple, const Driver &D, @@ -7288,34 +7698,33 @@ static void AddLibgcc(const llvm::Triple &Triple, const Driver &D, static std::string getLinuxDynamicLinker(const ArgList &Args, const toolchains::Linux &ToolChain) { + const llvm::Triple::ArchType Arch = ToolChain.getArch(); + if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android) { if (ToolChain.getTriple().isArch64Bit()) return "/system/bin/linker64"; else return "/system/bin/linker"; - } else if (ToolChain.getArch() == llvm::Triple::x86 || - ToolChain.getArch() == llvm::Triple::sparc) + } else if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::sparc || + Arch == llvm::Triple::sparcel) return "/lib/ld-linux.so.2"; - else if (ToolChain.getArch() == llvm::Triple::aarch64) + else if (Arch == llvm::Triple::aarch64) return "/lib/ld-linux-aarch64.so.1"; - else if (ToolChain.getArch() == llvm::Triple::aarch64_be) + else if (Arch == llvm::Triple::aarch64_be) return "/lib/ld-linux-aarch64_be.so.1"; - else if (ToolChain.getArch() == llvm::Triple::arm || - ToolChain.getArch() == llvm::Triple::thumb) { + else if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) { if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF) return "/lib/ld-linux-armhf.so.3"; else return "/lib/ld-linux.so.3"; - } else if (ToolChain.getArch() == llvm::Triple::armeb || - ToolChain.getArch() == llvm::Triple::thumbeb) { + } else if (Arch == llvm::Triple::armeb || Arch == llvm::Triple::thumbeb) { + // TODO: check which dynamic linker name. if (ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUEABIHF) - return "/lib/ld-linux-armhf.so.3"; /* TODO: check which dynamic linker name. */ + return "/lib/ld-linux-armhf.so.3"; else - return "/lib/ld-linux.so.3"; /* TODO: check which dynamic linker name. */ - } else if (ToolChain.getArch() == llvm::Triple::mips || - ToolChain.getArch() == llvm::Triple::mipsel || - ToolChain.getArch() == llvm::Triple::mips64 || - ToolChain.getArch() == llvm::Triple::mips64el) { + return "/lib/ld-linux.so.3"; + } else if (Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel || + Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el) { StringRef CPUName; StringRef ABIName; mips::getMipsCPUAndABI(Args, ToolChain.getTriple(), CPUName, ABIName); @@ -7333,21 +7742,21 @@ static std::string getLinuxDynamicLinker(const ArgList &Args, LibName = IsNaN2008 ? "ld-linux-mipsn8.so.1" : "ld.so.1"; return (LibDir + "/" + LibName).str(); - } else if (ToolChain.getArch() == llvm::Triple::ppc) + } else if (Arch == llvm::Triple::ppc) return "/lib/ld.so.1"; - else if (ToolChain.getArch() == llvm::Triple::ppc64) { + else if (Arch == llvm::Triple::ppc64) { if (ppc::hasPPCAbiArg(Args, "elfv2")) return "/lib64/ld64.so.2"; return "/lib64/ld64.so.1"; - } else if (ToolChain.getArch() == llvm::Triple::ppc64le) { + } else if (Arch == llvm::Triple::ppc64le) { if (ppc::hasPPCAbiArg(Args, "elfv1")) return "/lib64/ld64.so.1"; return "/lib64/ld64.so.2"; - } else if (ToolChain.getArch() == llvm::Triple::systemz) + } else if (Arch == llvm::Triple::systemz) return "/lib64/ld64.so.1"; - else if (ToolChain.getArch() == llvm::Triple::sparcv9) + else if (Arch == llvm::Triple::sparcv9) return "/lib64/ld-linux.so.2"; - else if (ToolChain.getArch() == llvm::Triple::x86_64 && + else if (Arch == llvm::Triple::x86_64 && ToolChain.getTriple().getEnvironment() == llvm::Triple::GNUX32) return "/libx32/ld-linux-x32.so.2"; else @@ -7396,6 +7805,7 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) { case llvm::Triple::ppc64le: return "elf64lppc"; case llvm::Triple::sparc: + case llvm::Triple::sparcel: return "elf32_sparc"; case llvm::Triple::sparcv9: return "elf64_sparc"; @@ -7427,19 +7837,15 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { - const toolchains::Linux& ToolChain = - static_cast<const toolchains::Linux&>(getToolChain()); + const toolchains::Linux &ToolChain = + static_cast<const toolchains::Linux &>(getToolChain()); const Driver &D = ToolChain.getDriver(); + const llvm::Triple::ArchType Arch = ToolChain.getArch(); const bool isAndroid = - ToolChain.getTriple().getEnvironment() == llvm::Triple::Android; + ToolChain.getTriple().getEnvironment() == llvm::Triple::Android; const bool IsPIE = - !Args.hasArg(options::OPT_shared) && - !Args.hasArg(options::OPT_static) && - (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault() || - // On Android every code is PIC so every executable is PIE - // Cannot use isPIEDefault here since otherwise - // PIE only logic will be enabled during compilation - isAndroid); + !Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_static) && + (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault()); ArgStringList CmdArgs; @@ -7463,9 +7869,10 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_s)) CmdArgs.push_back("-s"); - if (ToolChain.getArch() == llvm::Triple::armeb || - ToolChain.getArch() == llvm::Triple::thumbeb) - arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getTriple()); + if (Arch == llvm::Triple::armeb || Arch == llvm::Triple::thumbeb) + arm::appendEBLinkFlags( + Args, CmdArgs, + llvm::Triple(getToolChain().ComputeEffectiveClangTriple(Args))); for (const auto &Opt : ToolChain.ExtraOpts) CmdArgs.push_back(Opt.c_str()); @@ -7478,10 +7885,8 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(getLDMOption(ToolChain.getTriple(), Args)); if (Args.hasArg(options::OPT_static)) { - if (ToolChain.getArch() == llvm::Triple::arm || - ToolChain.getArch() == llvm::Triple::armeb || - ToolChain.getArch() == llvm::Triple::thumb || - ToolChain.getArch() == llvm::Triple::thumbeb) + if (Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb || + Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb) CmdArgs.push_back("-Bstatic"); else CmdArgs.push_back("-static"); @@ -7489,10 +7894,8 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-shared"); } - if (ToolChain.getArch() == llvm::Triple::arm || - ToolChain.getArch() == llvm::Triple::armeb || - ToolChain.getArch() == llvm::Triple::thumb || - ToolChain.getArch() == llvm::Triple::thumbeb || + if (Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb || + Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb || (!Args.hasArg(options::OPT_static) && !Args.hasArg(options::OPT_shared))) { CmdArgs.push_back("-dynamic-linker"); @@ -7544,7 +7947,7 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, for (const auto &Path : Paths) CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path)); - if (D.IsUsingLTO(Args)) + if (D.IsUsingLTO(getToolChain(), Args)) AddGoldPlugin(ToolChain, Args, CmdArgs); if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) @@ -7567,6 +7970,8 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-Bdynamic"); CmdArgs.push_back("-lm"); } + // Silence warnings when linking C code with a C++ '-stdlib' argument. + Args.ClaimAllArgs(options::OPT_stdlib_EQ); if (!Args.hasArg(options::OPT_nostdlib)) { if (!Args.hasArg(options::OPT_nodefaultlibs)) { @@ -7576,37 +7981,39 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (NeedsSanitizerDeps) linkSanitizerRuntimeDeps(ToolChain, CmdArgs); - LibOpenMP UsedOpenMPLib = LibUnknown; - if (Args.hasArg(options::OPT_fopenmp)) { - UsedOpenMPLib = LibGOMP; - } else if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) { - UsedOpenMPLib = llvm::StringSwitch<LibOpenMP>(A->getValue()) - .Case("libgomp", LibGOMP) - .Case("libiomp5", LibIOMP5) - .Default(LibUnknown); - if (UsedOpenMPLib == LibUnknown) - D.Diag(diag::err_drv_unsupported_option_argument) - << A->getOption().getName() << A->getValue(); + bool WantPthread = Args.hasArg(options::OPT_pthread) || + Args.hasArg(options::OPT_pthreads); + + if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, + options::OPT_fno_openmp, false)) { + // OpenMP runtimes implies pthreads when using the GNU toolchain. + // FIXME: Does this really make sense for all GNU toolchains? + WantPthread = true; + + // Also link the particular OpenMP runtimes. + switch (getOpenMPRuntime(ToolChain, Args)) { + case OMPRT_OMP: + CmdArgs.push_back("-lomp"); + break; + case OMPRT_GOMP: + CmdArgs.push_back("-lgomp"); + + // FIXME: Exclude this for platforms with libgomp that don't require + // librt. Most modern Linux platforms require it, but some may not. + CmdArgs.push_back("-lrt"); + break; + case OMPRT_IOMP5: + CmdArgs.push_back("-liomp5"); + break; + case OMPRT_Unknown: + // Already diagnosed. + break; + } } - switch (UsedOpenMPLib) { - case LibGOMP: - CmdArgs.push_back("-lgomp"); - // FIXME: Exclude this for platforms with libgomp that don't require - // librt. Most modern Linux platforms require it, but some may not. - CmdArgs.push_back("-lrt"); - break; - case LibIOMP5: - CmdArgs.push_back("-liomp5"); - break; - case LibUnknown: - break; - } AddRunTimeLibs(ToolChain, D, CmdArgs, Args); - if ((Args.hasArg(options::OPT_pthread) || - Args.hasArg(options::OPT_pthreads) || UsedOpenMPLib != LibUnknown) && - !isAndroid) + if (WantPthread && !isAndroid) CmdArgs.push_back("-lpthread"); CmdArgs.push_back("-lc"); @@ -7636,6 +8043,171 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, llvm::make_unique<Command>(JA, *this, ToolChain.Linker.c_str(), CmdArgs)); } + +// NaCl ARM assembly (inline or standalone) can be written with a set of macros +// for the various SFI requirements like register masking. The assembly tool +// inserts the file containing the macros as an input into all the assembly +// jobs. +void nacltools::AssembleARM::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + const toolchains::NaCl_TC& ToolChain = + static_cast<const toolchains::NaCl_TC&>(getToolChain()); + InputInfo NaClMacros(ToolChain.GetNaClArmMacrosPath(), types::TY_PP_Asm, + "nacl-arm-macros.s"); + InputInfoList NewInputs; + NewInputs.push_back(NaClMacros); + NewInputs.append(Inputs.begin(), Inputs.end()); + gnutools::Assemble::ConstructJob(C, JA, Output, NewInputs, Args, + LinkingOutput); +} + + +// This is quite similar to gnutools::link::ConstructJob with changes that +// we use static by default, do not yet support sanitizers or LTO, and a few +// others. Eventually we can support more of that and hopefully migrate back +// to gnutools::link. +void nacltools::Link::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + + const toolchains::NaCl_TC &ToolChain = + static_cast<const toolchains::NaCl_TC &>(getToolChain()); + const Driver &D = ToolChain.getDriver(); + const llvm::Triple::ArchType Arch = ToolChain.getArch(); + const bool IsStatic = + !Args.hasArg(options::OPT_dynamic) && !Args.hasArg(options::OPT_shared); + + ArgStringList CmdArgs; + + // Silence warning for "clang -g foo.o -o foo" + Args.ClaimAllArgs(options::OPT_g_Group); + // and "clang -emit-llvm foo.o -o foo" + Args.ClaimAllArgs(options::OPT_emit_llvm); + // and for "clang -w foo.o -o foo". Other warning options are already + // handled somewhere else. + Args.ClaimAllArgs(options::OPT_w); + + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + + if (Args.hasArg(options::OPT_rdynamic)) + CmdArgs.push_back("-export-dynamic"); + + if (Args.hasArg(options::OPT_s)) + CmdArgs.push_back("-s"); + + // NaCl_TC doesn't have ExtraOpts like Linux; the only relevant flag from + // there is --build-id, which we do want. + CmdArgs.push_back("--build-id"); + + if (!IsStatic) + CmdArgs.push_back("--eh-frame-hdr"); + + CmdArgs.push_back("-m"); + if (Arch == llvm::Triple::x86) + CmdArgs.push_back("elf_i386_nacl"); + else if (Arch == llvm::Triple::arm) + CmdArgs.push_back("armelf_nacl"); + else if (Arch == llvm::Triple::x86_64) + CmdArgs.push_back("elf_x86_64_nacl"); + else + D.Diag(diag::err_target_unsupported_arch) << ToolChain.getArchName() + << "Native Client"; + + if (IsStatic) + CmdArgs.push_back("-static"); + else if (Args.hasArg(options::OPT_shared)) + CmdArgs.push_back("-shared"); + + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + if (!Args.hasArg(options::OPT_shared)) + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o"))); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); + + const char *crtbegin; + if (IsStatic) + crtbegin = "crtbeginT.o"; + else if (Args.hasArg(options::OPT_shared)) + crtbegin = "crtbeginS.o"; + else + crtbegin = "crtbegin.o"; + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); + } + + Args.AddAllArgs(CmdArgs, options::OPT_L); + Args.AddAllArgs(CmdArgs, options::OPT_u); + + const ToolChain::path_list &Paths = ToolChain.getFilePaths(); + + for (const auto &Path : Paths) + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path)); + + if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) + CmdArgs.push_back("--no-demangle"); + + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); + + if (D.CCCIsCXX() && + !Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && + !IsStatic; + if (OnlyLibstdcxxStatic) + CmdArgs.push_back("-Bstatic"); + ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); + if (OnlyLibstdcxxStatic) + CmdArgs.push_back("-Bdynamic"); + CmdArgs.push_back("-lm"); + } + + if (!Args.hasArg(options::OPT_nostdlib)) { + if (!Args.hasArg(options::OPT_nodefaultlibs)) { + // Always use groups, since it has no effect on dynamic libraries. + CmdArgs.push_back("--start-group"); + CmdArgs.push_back("-lc"); + // NaCl's libc++ currently requires libpthread, so just always include it + // in the group for C++. + if (Args.hasArg(options::OPT_pthread) || + Args.hasArg(options::OPT_pthreads) || + D.CCCIsCXX()) { + CmdArgs.push_back("-lpthread"); + } + + CmdArgs.push_back("-lgcc"); + CmdArgs.push_back("--as-needed"); + if (IsStatic) + CmdArgs.push_back("-lgcc_eh"); + else + CmdArgs.push_back("-lgcc_s"); + CmdArgs.push_back("--no-as-needed"); + CmdArgs.push_back("--end-group"); + } + + if (!Args.hasArg(options::OPT_nostartfiles)) { + const char *crtend; + if (Args.hasArg(options::OPT_shared)) + crtend = "crtendS.o"; + else + crtend = "crtend.o"; + + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend))); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); + } + } + + C.addCommand(llvm::make_unique<Command>(JA, *this, + ToolChain.Linker.c_str(), CmdArgs)); +} + + void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -7926,8 +8498,8 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!llvm::sys::Process::GetEnv("LIB")) { // If the VC environment hasn't been configured (perhaps because the user // did not run vcvarsall), try to build a consistent link environment. If - // the environment variable is set however, assume the user knows what he's - // doing. + // the environment variable is set however, assume the user knows what + // they're doing. std::string VisualStudioDir; const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC); if (MSVC.getVisualStudioInstallDir(VisualStudioDir)) { @@ -7961,14 +8533,16 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_g_Group)) CmdArgs.push_back("-debug"); - bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd); + bool DLL = Args.hasArg(options::OPT__SLASH_LD, + options::OPT__SLASH_LDd, + options::OPT_shared); if (DLL) { CmdArgs.push_back(Args.MakeArgString("-dll")); SmallString<128> ImplibName(Output.getFilename()); llvm::sys::path::replace_extension(ImplibName, "lib"); CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + - ImplibName.str())); + ImplibName)); } if (TC.getSanitizerArgs().needsAsanRt()) { @@ -8085,7 +8659,7 @@ std::unique_ptr<Command> visualstudio::Compile::GetCommand( } } - // Flags for which clang-cl have an alias. + // Flags for which clang-cl has an alias. // FIXME: How can we ensure this stays in sync with relevant clang-cl options? if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR, @@ -8105,7 +8679,8 @@ std::unique_ptr<Command> visualstudio::Compile::GetCommand( if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only)) CmdArgs.push_back("/Z7"); - std::vector<std::string> Includes = Args.getAllArgValues(options::OPT_include); + std::vector<std::string> Includes = + Args.getAllArgValues(options::OPT_include); for (const auto &Include : Includes) CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Include)); |