diff options
Diffstat (limited to 'lib/Driver/Tools.cpp')
-rw-r--r-- | lib/Driver/Tools.cpp | 1405 |
1 files changed, 1024 insertions, 381 deletions
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 75eef9e..527038f 100644 --- a/lib/Driver/Tools.cpp +++ b/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,6 +339,7 @@ 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, @@ -377,19 +385,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 +410,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 +497,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: @@ -536,75 +545,88 @@ static void getARMFPUFeatures(const Driver &D, const Arg *A, 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. + // FIXME: Why does "none" disable more than "invalid"? + 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 if (FPU == "vfp") { + return; + } + + // FIXME: Make sure we differentiate sp-only. + if (FPU.find("-sp-") != StringRef::npos) { + Features.push_back("+fp-only-sp"); + } + + // All other FPU types, valid or invalid. + switch(llvm::ARMTargetParser::parseFPU(FPU)) { + case llvm::ARM::FK_INVALID: + case llvm::ARM::FK_SOFTVFP: + Features.push_back("-vfp2"); + Features.push_back("-vfp3"); + Features.push_back("-neon"); + break; + case llvm::ARM::FK_VFP: + case llvm::ARM::FK_VFPV2: Features.push_back("+vfp2"); Features.push_back("-neon"); - } else if (FPU == "vfp3-d16" || FPU == "vfpv3-d16") { - Features.push_back("+vfp3"); + break; + case llvm::ARM::FK_VFPV3_D16: Features.push_back("+d16"); - Features.push_back("-neon"); - } else if (FPU == "vfp3" || FPU == "vfpv3") { + // fall-through + case llvm::ARM::FK_VFPV3: Features.push_back("+vfp3"); Features.push_back("-neon"); - } else if (FPU == "vfp4-d16" || FPU == "vfpv4-d16") { - Features.push_back("+vfp4"); + break; + case llvm::ARM::FK_VFPV4_D16: Features.push_back("+d16"); - Features.push_back("-neon"); - } else if (FPU == "vfp4" || FPU == "vfpv4") { + // fall-through + case llvm::ARM::FK_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"); + break; + case llvm::ARM::FK_FPV5_D16: 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") { + // fall-through + case llvm::ARM::FK_FP_ARMV8: 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") { + break; + case llvm::ARM::FK_NEON_FP_ARMV8: Features.push_back("+fp-armv8"); Features.push_back("+neon"); Features.push_back("-crypto"); - } else if (FPU == "crypto-neon-fp-armv8") { + break; + case llvm::ARM::FK_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"); + break; + case llvm::ARM::FK_NEON: Features.push_back("+neon"); - } else if (FPU == "neon-vfpv4") { + break; + case llvm::ARM::FK_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 + break; + default: 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 @@ -637,11 +659,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 +700,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 +753,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. 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::getCanonicalArchName(Arch).empty()) + 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)) { + StringRef 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 +780,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 +800,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 +813,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 +894,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 +992,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 +1138,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 +1151,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; } @@ -1322,9 +1363,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 +1464,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 +1519,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 +1590,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 +1630,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,7 +1655,7 @@ static void getX86TargetFeatures(const Driver & D, Features.push_back("-fsgsbase"); } - // Add features to comply with gcc on Android + // Add features to be compatible with gcc for Android. if (Triple.getEnvironment() == llvm::Triple::Android) { if (Triple.getArch() == llvm::Triple::x86_64) { Features.push_back("+sse4.2"); @@ -1575,7 +1664,7 @@ static void getX86TargetFeatures(const Driver & D, 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; @@ -1656,39 +1745,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 +1800,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 +1821,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 +1946,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 +2013,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 +2051,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; @@ -2135,8 +2231,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 +2270,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; @@ -2181,16 +2281,11 @@ static void addProfileRT(const ToolChain &TC, const ArgList &Args, 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 +2346,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 +2387,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 +2447,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 +2463,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 +2473,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 +2552,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 +2575,38 @@ 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()); +} + void Clang::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -2477,6 +2623,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 +2715,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 +2738,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 +2766,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. @@ -2680,6 +2834,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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" @@ -2781,6 +2936,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"); @@ -2961,6 +3118,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 +3222,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 +3234,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 +3267,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 +3297,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 +3396,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 +3441,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 +3459,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 +3545,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); @@ -3427,6 +3601,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 +3628,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,6 +3803,12 @@ 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.hasArg(options::OPT_fopenmp_EQ) || + Args.hasArg(options::OPT_fopenmp)) { + CmdArgs.push_back("-fopenmp"); + } + const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs(); Sanitize.addArgs(Args, CmdArgs); @@ -3739,6 +3920,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment)); } + 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().getTriple().getArch() == llvm::Triple::aarch64 || getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be) CmdArgs.push_back("-fallow-half-arguments-and-returns"); @@ -3845,6 +4035,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 +4068,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 +4108,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 +4136,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 +4151,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 +4176,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,9 +4189,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, true)))) CmdArgs.push_back("-fms-compatibility"); - // -fms-compatibility-version=17.00 is default. + // -fms-compatibility-version=18.00 is default. + VersionTuple MSVT; if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, - IsWindowsMSVC) || Args.hasArg(options::OPT_fmsc_version) || + 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 = @@ -4008,16 +4204,31 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, << 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()); + if (MSCompatibilityVersion) { + if (MSVT.tryParse(MSCompatibilityVersion->getValue())) + D.Diag(diag::err_drv_invalid_value) + << MSCompatibilityVersion->getAsString(Args) + << MSCompatibilityVersion->getValue(); + } else if (MSCVersion) { + unsigned Version = 0; + if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version)) + D.Diag(diag::err_drv_invalid_value) << MSCVersion->getAsString(Args) + << MSCVersion->getValue(); + MSVT = getMSCompatibilityVersion(Version); + } else { + MSVT = VersionTuple(18); + } + + 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 +4236,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, @@ -4130,9 +4348,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 +4365,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 +4554,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. @@ -4450,7 +4683,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // 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 +4725,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 +4737,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 +5005,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 +5015,19 @@ void Clang::AddClangCLArgs(const ArgList &Args, ArgStringList &CmdArgs) const { CmdArgs.push_back("-P"); } + unsigned VolatileOptionID; + if (getToolChain().getTriple().getArch() == llvm::Triple::x86_64 || + getToolChain().getTriple().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 +5072,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 +5119,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,11 +5185,24 @@ 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 @@ -4964,7 +5234,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() {} @@ -5095,16 +5365,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 +5418,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 +5462,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 +5482,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 +5516,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 +5534,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 @@ -5344,6 +5616,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 +5637,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,13 +5652,35 @@ 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. @@ -5394,13 +5701,24 @@ 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) { +// FIXME: Use ARMTargetParser. +const char *arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch) { + // FIXME: Use ARMTargetParser + if (CPU == "generic") { + if (Arch == "armv8.1a" || Arch == "armv8.1-a" || + Arch == "armebv8.1a" || Arch == "armebv8.1-a") { + return "v8.1a"; + } + } + + // FIXME: Use ARMTargetParser return llvm::StringSwitch<const char *>(CPU) - .Case("strongarm", "v4") + .Cases("arm8", "arm810", "v4") + .Cases("strongarm", "strongarm110", "strongarm1100", "strongarm1110", "v4") .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t") .Cases("arm720t", "arm9", "arm9tdmi", "v4t") .Cases("arm920", "arm920t", "arm922t", "v4t") @@ -5409,33 +5727,51 @@ const char *arm::getLLVMArchSuffixForARM(StringRef CPU) { .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("arm1136j-s", "arm1136jf-s", "v6") + .Cases("arm1176jz-s", "arm1176jzf-s", "v6k") + .Cases("mpcorenovfp", "mpcore", "v6k") .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-r4", "cortex-r4f", "cortex-r5", "cortex-r7", "v7r") + .Cases("sc000", "cortex-m0", "cortex-m0plus", "cortex-m1", "v6m") + .Cases("sc300", "cortex-m3", "v7m") .Cases("cortex-m4", "cortex-m7", "v7em") .Case("swift", "v7s") .Case("cyclone", "v8") - .Cases("cortex-a53", "cortex-a57", "v8") + .Cases("cortex-a53", "cortex-a57", "cortex-a72", "v8") .Default(""); } -void arm::appendEBLinkFlags(const ArgList &Args, ArgStringList &CmdArgs, const llvm::Triple &Triple) { +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 +5810,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); } @@ -5527,14 +5863,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 +5891,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 +6082,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); @@ -5832,6 +6244,27 @@ enum LibOpenMP { LibIOMP5 }; +/// Map a -fopenmp=<blah> macro to the corresponding library. +static LibOpenMP getOpenMPLibByName(StringRef Name) { + return llvm::StringSwitch<LibOpenMP>(Name).Case("libgomp", LibGOMP) + .Case("libiomp5", LibIOMP5) + .Default(LibUnknown); +} + +/// Get the default -l<blah> flag to use for -fopenmp, if no library is +/// specified. This can be overridden at configure time. +static const char *getDefaultOpenMPLibFlag() { +#ifndef OPENMP_DEFAULT_LIB +#define OPENMP_DEFAULT_LIB iomp5 +#endif + +#define STR2(lib) #lib +#define STR(lib) STR2(lib) + return "-l" STR(OPENMP_DEFAULT_LIB); +#undef STR +#undef STR2 +} + void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -5889,27 +6322,21 @@ 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) + if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) { + switch (getOpenMPLibByName(A->getValue())) { + case LibGOMP: + CmdArgs.push_back("-lgomp"); + break; + case LibIOMP5: + CmdArgs.push_back("-liomp5"); + break; + case 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; + break; + } + } else if (Args.hasArg(options::OPT_fopenmp)) { + CmdArgs.push_back(getDefaultOpenMPLibFlag()); } AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); @@ -5951,6 +6378,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 +6402,22 @@ 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 (auto it = Args.filtered_begin(options::OPT_iframework), + ie = Args.filtered_end(); it != ie; ++it) + CmdArgs.push_back(Args.MakeArgString(std::string("-F") + + (*it)->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 = @@ -6191,6 +6639,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; @@ -6569,6 +7018,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"); @@ -6697,7 +7147,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); @@ -6823,6 +7273,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; @@ -6901,7 +7352,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: @@ -7069,47 +7521,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); @@ -7124,10 +7595,12 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, 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); @@ -7211,11 +7684,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) @@ -7239,7 +7716,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, @@ -7283,7 +7760,8 @@ static std::string getLinuxDynamicLinker(const ArgList &Args, else return "/system/bin/linker"; } else if (ToolChain.getArch() == llvm::Triple::x86 || - ToolChain.getArch() == llvm::Triple::sparc) + ToolChain.getArch() == llvm::Triple::sparc || + ToolChain.getArch() == llvm::Triple::sparcel) return "/lib/ld-linux.so.2"; else if (ToolChain.getArch() == llvm::Triple::aarch64) return "/lib/ld-linux-aarch64.so.1"; @@ -7385,6 +7863,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"; @@ -7424,11 +7903,7 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, 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_pie) || ToolChain.isPIEDefault()); ArgStringList CmdArgs; @@ -7454,7 +7929,8 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (ToolChain.getArch() == llvm::Triple::armeb || ToolChain.getArch() == llvm::Triple::thumbeb) - arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getTriple()); + arm::appendEBLinkFlags(Args, CmdArgs, + llvm::Triple(getToolChain().ComputeEffectiveClangTriple(Args))); for (const auto &Opt : ToolChain.ExtraOpts) CmdArgs.push_back(Opt.c_str()); @@ -7533,7 +8009,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)) @@ -7556,6 +8032,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)) { @@ -7565,37 +8043,33 @@ 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) + bool WantPthread = true; + if (const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ)) { + switch (getOpenMPLibByName(A->getValue())) { + 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: D.Diag(diag::err_drv_unsupported_option_argument) - << A->getOption().getName() << A->getValue(); - } - 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; + << A->getOption().getName() << A->getValue(); + break; + } + } else if (Args.hasArg(options::OPT_fopenmp)) { + CmdArgs.push_back(getDefaultOpenMPLibFlag()); + } else { + WantPthread = Args.hasArg(options::OPT_pthread) || + Args.hasArg(options::OPT_pthreads); } 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"); @@ -7625,6 +8099,172 @@ 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 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 (ToolChain.getArch() == llvm::Triple::x86) + CmdArgs.push_back("elf_i386_nacl"); + else if (ToolChain.getArch() == llvm::Triple::arm) + CmdArgs.push_back("armelf_nacl"); + else if (ToolChain.getArch() == 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, @@ -7915,8 +8555,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)) { @@ -7950,14 +8590,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()) { @@ -8074,7 +8716,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, @@ -8094,7 +8736,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)); |