diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:04:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:04:05 +0000 |
commit | 676fbe8105eeb6ff4bb2ed261cb212fcfdbe7b63 (patch) | |
tree | 02a1ac369cb734d0abfa5000dd86e5b7797e6a74 /lib/Driver/ToolChains | |
parent | c7e70c433efc6953dc3888b9fbf9f3512d7da2b0 (diff) | |
download | src-676fbe8105eeb6ff4bb2ed261cb212fcfdbe7b63.tar.gz src-676fbe8105eeb6ff4bb2ed261cb212fcfdbe7b63.zip |
Vendor import of clang trunk r351319 (just before the release_80 branchvendor/clang/clang-trunk-r351319
Notes
Notes:
svn path=/vendor/clang/dist/; revision=343173
svn path=/vendor/clang/clang-trunk-r351319/; revision=343174; tag=vendor/clang/clang-trunk-r351319
Diffstat (limited to 'lib/Driver/ToolChains')
48 files changed, 2541 insertions, 681 deletions
diff --git a/lib/Driver/ToolChains/AMDGPU.cpp b/lib/Driver/ToolChains/AMDGPU.cpp index 6b673feeadfc..a421a09891cd 100644 --- a/lib/Driver/ToolChains/AMDGPU.cpp +++ b/lib/Driver/ToolChains/AMDGPU.cpp @@ -98,3 +98,16 @@ AMDGPUToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch, return DAL; } + +void AMDGPUToolChain::addClangTargetOptions( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args, + Action::OffloadKind DeviceOffloadingKind) const { + // Default to "hidden" visibility, as object level linking will not be + // supported for the foreseeable future. + if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ, + options::OPT_fvisibility_ms_compat)) { + CC1Args.push_back("-fvisibility"); + CC1Args.push_back("hidden"); + } +} diff --git a/lib/Driver/ToolChains/AMDGPU.h b/lib/Driver/ToolChains/AMDGPU.h index 36114d0dabc4..9d38eeedf59d 100644 --- a/lib/Driver/ToolChains/AMDGPU.h +++ b/lib/Driver/ToolChains/AMDGPU.h @@ -61,6 +61,10 @@ public: llvm::opt::DerivedArgList * TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const override; + + void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args, + Action::OffloadKind DeviceOffloadKind) const override; }; } // end namespace toolchains diff --git a/lib/Driver/ToolChains/Arch/AArch64.cpp b/lib/Driver/ToolChains/Arch/AArch64.cpp index 5114279b4b45..71e55fe79e27 100644 --- a/lib/Driver/ToolChains/Arch/AArch64.cpp +++ b/lib/Driver/ToolChains/Arch/AArch64.cpp @@ -19,10 +19,17 @@ using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; +/// \returns true if the given triple can determine the default CPU type even +/// if -arch is not specified. +static bool isCPUDeterminedByTriple(const llvm::Triple &Triple) { + return Triple.isOSDarwin(); +} + /// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are /// targeting. Set \p A to the Arg corresponding to the -mcpu argument if it is /// provided, or to nullptr otherwise. -std::string aarch64::getAArch64TargetCPU(const ArgList &Args, Arg *&A) { +std::string aarch64::getAArch64TargetCPU(const ArgList &Args, + const llvm::Triple &Triple, Arg *&A) { std::string CPU; // If we have -mcpu, use that. if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) { @@ -36,9 +43,9 @@ std::string aarch64::getAArch64TargetCPU(const ArgList &Args, Arg *&A) { else if (CPU.size()) return CPU; - // Make sure we pick "cyclone" if -arch is used. - // FIXME: Should this be picked by checking the target triple instead? - if (Args.getLastArg(options::OPT_arch)) + // Make sure we pick "cyclone" if -arch is used or when targetting a Darwin + // OS. + if (Args.getLastArg(options::OPT_arch) || Triple.isOSDarwin()) return "cyclone"; return "generic"; @@ -152,7 +159,9 @@ getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu, return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features); } -void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args, +void aarch64::getAArch64TargetFeatures(const Driver &D, + const llvm::Triple &Triple, + const ArgList &Args, std::vector<StringRef> &Features) { Arg *A; bool success = true; @@ -162,9 +171,9 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args, success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features); else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features); - else if (Args.hasArg(options::OPT_arch)) - success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args, A), - Args, Features); + else if (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple)) + success = getAArch64ArchFeaturesFromMcpu( + D, getAArch64TargetCPU(Args, Triple, A), Args, Features); if (success && (A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ))) success = @@ -172,9 +181,10 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args, else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ))) success = getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features); - else if (success && Args.hasArg(options::OPT_arch)) + else if (success && + (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple))) success = getAArch64MicroArchFeaturesFromMcpu( - D, getAArch64TargetCPU(Args, A), Args, Features); + D, getAArch64TargetCPU(Args, Triple, A), Args, Features); if (!success) D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); @@ -193,17 +203,172 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args, Features.push_back("-crc"); } + // Handle (arch-dependent) fp16fml/fullfp16 relationship. + // FIXME: this fp16fml option handling will be reimplemented after the + // TargetParser rewrite. + const auto ItRNoFullFP16 = std::find(Features.rbegin(), Features.rend(), "-fullfp16"); + const auto ItRFP16FML = std::find(Features.rbegin(), Features.rend(), "+fp16fml"); + if (std::find(Features.begin(), Features.end(), "+v8.4a") != Features.end()) { + const auto ItRFullFP16 = std::find(Features.rbegin(), Features.rend(), "+fullfp16"); + if (ItRFullFP16 < ItRNoFullFP16 && ItRFullFP16 < ItRFP16FML) { + // Only entangled feature that can be to the right of this +fullfp16 is -fp16fml. + // Only append the +fp16fml if there is no -fp16fml after the +fullfp16. + if (std::find(Features.rbegin(), ItRFullFP16, "-fp16fml") == ItRFullFP16) + Features.push_back("+fp16fml"); + } + else + goto fp16_fml_fallthrough; + } + else { +fp16_fml_fallthrough: + // In both of these cases, putting the 'other' feature on the end of the vector will + // result in the same effect as placing it immediately after the current feature. + if (ItRNoFullFP16 < ItRFP16FML) + Features.push_back("-fp16fml"); + else if (ItRNoFullFP16 > ItRFP16FML) + Features.push_back("+fullfp16"); + } + + // FIXME: this needs reimplementation too after the TargetParser rewrite + // + // Context sensitive meaning of Crypto: + // 1) For Arch >= ARMv8.4a: crypto = sm4 + sha3 + sha2 + aes + // 2) For Arch <= ARMv8.3a: crypto = sha2 + aes + const auto ItBegin = Features.begin(); + const auto ItEnd = Features.end(); + const auto ItRBegin = Features.rbegin(); + const auto ItREnd = Features.rend(); + const auto ItRCrypto = std::find(ItRBegin, ItREnd, "+crypto"); + const auto ItRNoCrypto = std::find(ItRBegin, ItREnd, "-crypto"); + const auto HasCrypto = ItRCrypto != ItREnd; + const auto HasNoCrypto = ItRNoCrypto != ItREnd; + const ptrdiff_t PosCrypto = ItRCrypto - ItRBegin; + const ptrdiff_t PosNoCrypto = ItRNoCrypto - ItRBegin; + + bool NoCrypto = false; + if (HasCrypto && HasNoCrypto) { + if (PosNoCrypto < PosCrypto) + NoCrypto = true; + } + + if (std::find(ItBegin, ItEnd, "+v8.4a") != ItEnd) { + if (HasCrypto && !NoCrypto) { + // Check if we have NOT disabled an algorithm with something like: + // +crypto, -algorithm + // And if "-algorithm" does not occur, we enable that crypto algorithm. + const bool HasSM4 = (std::find(ItBegin, ItEnd, "-sm4") == ItEnd); + const bool HasSHA3 = (std::find(ItBegin, ItEnd, "-sha3") == ItEnd); + const bool HasSHA2 = (std::find(ItBegin, ItEnd, "-sha2") == ItEnd); + const bool HasAES = (std::find(ItBegin, ItEnd, "-aes") == ItEnd); + if (HasSM4) + Features.push_back("+sm4"); + if (HasSHA3) + Features.push_back("+sha3"); + if (HasSHA2) + Features.push_back("+sha2"); + if (HasAES) + Features.push_back("+aes"); + } else if (HasNoCrypto) { + // Check if we have NOT enabled a crypto algorithm with something like: + // -crypto, +algorithm + // And if "+algorithm" does not occur, we disable that crypto algorithm. + const bool HasSM4 = (std::find(ItBegin, ItEnd, "+sm4") != ItEnd); + const bool HasSHA3 = (std::find(ItBegin, ItEnd, "+sha3") != ItEnd); + const bool HasSHA2 = (std::find(ItBegin, ItEnd, "+sha2") != ItEnd); + const bool HasAES = (std::find(ItBegin, ItEnd, "+aes") != ItEnd); + if (!HasSM4) + Features.push_back("-sm4"); + if (!HasSHA3) + Features.push_back("-sha3"); + if (!HasSHA2) + Features.push_back("-sha2"); + if (!HasAES) + Features.push_back("-aes"); + } + } else { + if (HasCrypto && !NoCrypto) { + const bool HasSHA2 = (std::find(ItBegin, ItEnd, "-sha2") == ItEnd); + const bool HasAES = (std::find(ItBegin, ItEnd, "-aes") == ItEnd); + if (HasSHA2) + Features.push_back("+sha2"); + if (HasAES) + Features.push_back("+aes"); + } else if (HasNoCrypto) { + const bool HasSHA2 = (std::find(ItBegin, ItEnd, "+sha2") != ItEnd); + const bool HasAES = (std::find(ItBegin, ItEnd, "+aes") != ItEnd); + const bool HasV82a = (std::find(ItBegin, ItEnd, "+v8.2a") != ItEnd); + const bool HasV83a = (std::find(ItBegin, ItEnd, "+v8.3a") != ItEnd); + const bool HasV84a = (std::find(ItBegin, ItEnd, "+v8.4a") != ItEnd); + if (!HasSHA2) + Features.push_back("-sha2"); + if (!HasAES) + Features.push_back("-aes"); + if (HasV82a || HasV83a || HasV84a) { + Features.push_back("-sm4"); + Features.push_back("-sha3"); + } + } + } + if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) if (A->getOption().matches(options::OPT_mno_unaligned_access)) Features.push_back("+strict-align"); + if (Args.hasArg(options::OPT_ffixed_x1)) + Features.push_back("+reserve-x1"); + + if (Args.hasArg(options::OPT_ffixed_x2)) + Features.push_back("+reserve-x2"); + + if (Args.hasArg(options::OPT_ffixed_x3)) + Features.push_back("+reserve-x3"); + + if (Args.hasArg(options::OPT_ffixed_x4)) + Features.push_back("+reserve-x4"); + + if (Args.hasArg(options::OPT_ffixed_x5)) + Features.push_back("+reserve-x5"); + + if (Args.hasArg(options::OPT_ffixed_x6)) + Features.push_back("+reserve-x6"); + + if (Args.hasArg(options::OPT_ffixed_x7)) + Features.push_back("+reserve-x7"); + if (Args.hasArg(options::OPT_ffixed_x18)) Features.push_back("+reserve-x18"); if (Args.hasArg(options::OPT_ffixed_x20)) Features.push_back("+reserve-x20"); + if (Args.hasArg(options::OPT_fcall_saved_x8)) + Features.push_back("+call-saved-x8"); + + if (Args.hasArg(options::OPT_fcall_saved_x9)) + Features.push_back("+call-saved-x9"); + + if (Args.hasArg(options::OPT_fcall_saved_x10)) + Features.push_back("+call-saved-x10"); + + if (Args.hasArg(options::OPT_fcall_saved_x11)) + Features.push_back("+call-saved-x11"); + + if (Args.hasArg(options::OPT_fcall_saved_x12)) + Features.push_back("+call-saved-x12"); + + if (Args.hasArg(options::OPT_fcall_saved_x13)) + Features.push_back("+call-saved-x13"); + + if (Args.hasArg(options::OPT_fcall_saved_x14)) + Features.push_back("+call-saved-x14"); + + if (Args.hasArg(options::OPT_fcall_saved_x15)) + Features.push_back("+call-saved-x15"); + + if (Args.hasArg(options::OPT_fcall_saved_x18)) + Features.push_back("+call-saved-x18"); + if (Args.hasArg(options::OPT_mno_neg_immediates)) Features.push_back("+no-neg-immediates"); } diff --git a/lib/Driver/ToolChains/Arch/AArch64.h b/lib/Driver/ToolChains/Arch/AArch64.h index 62e419cc19f7..5f6148ebd6c4 100644 --- a/lib/Driver/ToolChains/Arch/AArch64.h +++ b/lib/Driver/ToolChains/Arch/AArch64.h @@ -21,11 +21,12 @@ namespace driver { namespace tools { namespace aarch64 { -void getAArch64TargetFeatures(const Driver &D, const llvm::opt::ArgList &Args, +void getAArch64TargetFeatures(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args, std::vector<llvm::StringRef> &Features); std::string getAArch64TargetCPU(const llvm::opt::ArgList &Args, - llvm::opt::Arg *&A); + const llvm::Triple &Triple, llvm::opt::Arg *&A); } // end namespace aarch64 } // end namespace target diff --git a/lib/Driver/ToolChains/Arch/ARM.cpp b/lib/Driver/ToolChains/Arch/ARM.cpp index 886d947c586b..f55efc1a22e3 100644 --- a/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/lib/Driver/ToolChains/Arch/ARM.cpp @@ -378,6 +378,13 @@ void arm::getARMTargetFeatures(const ToolChain &TC, Features); } else if (FPUArg) { getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features); + } else if (Triple.isAndroid() && getARMSubArchVersionNumber(Triple) >= 7) { + // Android mandates minimum FPU requirements based on OS version. + const char *AndroidFPU = + Triple.isAndroidVersionLT(23) ? "vfpv3-d16" : "neon"; + if (!llvm::ARM::getFPUFeatures(llvm::ARM::parseFPU(AndroidFPU), Features)) + D.Diag(clang::diag::err_drv_clang_unsupported) + << std::string("-mfpu=") + AndroidFPU; } // Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=. @@ -391,6 +398,33 @@ void arm::getARMTargetFeatures(const ToolChain &TC, } else if (HDivArg) getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features); + // Handle (arch-dependent) fp16fml/fullfp16 relationship. + // Must happen before any features are disabled due to soft-float. + // FIXME: this fp16fml option handling will be reimplemented after the + // TargetParser rewrite. + const auto ItRNoFullFP16 = std::find(Features.rbegin(), Features.rend(), "-fullfp16"); + const auto ItRFP16FML = std::find(Features.rbegin(), Features.rend(), "+fp16fml"); + if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8_4a) { + const auto ItRFullFP16 = std::find(Features.rbegin(), Features.rend(), "+fullfp16"); + if (ItRFullFP16 < ItRNoFullFP16 && ItRFullFP16 < ItRFP16FML) { + // Only entangled feature that can be to the right of this +fullfp16 is -fp16fml. + // Only append the +fp16fml if there is no -fp16fml after the +fullfp16. + if (std::find(Features.rbegin(), ItRFullFP16, "-fp16fml") == ItRFullFP16) + Features.push_back("+fp16fml"); + } + else + goto fp16_fml_fallthrough; + } + else { +fp16_fml_fallthrough: + // In both of these cases, putting the 'other' feature on the end of the vector will + // result in the same effect as placing it immediately after the current feature. + if (ItRNoFullFP16 < ItRFP16FML) + Features.push_back("-fp16fml"); + else if (ItRNoFullFP16 > ItRFP16FML) + Features.push_back("+fullfp16"); + } + // Setting -msoft-float/-mfloat-abi=soft effectively disables the FPU (GCC // ignores the -mfpu options in this case). // Note that the ABI can also be set implicitly by the target selected. @@ -404,7 +438,7 @@ void arm::getARMTargetFeatures(const ToolChain &TC, // now just be explicit and disable all known dependent features // as well. for (std::string Feature : {"vfp2", "vfp3", "vfp4", "fp-armv8", "fullfp16", - "neon", "crypto", "dotprod"}) + "neon", "crypto", "dotprod", "fp16fml"}) if (std::find(std::begin(Features), std::end(Features), "+" + Feature) != std::end(Features)) Features.push_back(Args.MakeArgString("-" + Feature)); } @@ -417,6 +451,26 @@ void arm::getARMTargetFeatures(const ToolChain &TC, Features.push_back("-crc"); } + // For Arch >= ARMv8.0: crypto = sha2 + aes + // FIXME: this needs reimplementation after the TargetParser rewrite + if (ArchName.find_lower("armv8a") != StringRef::npos || + ArchName.find_lower("armv8.1a") != StringRef::npos || + ArchName.find_lower("armv8.2a") != StringRef::npos || + ArchName.find_lower("armv8.3a") != StringRef::npos || + ArchName.find_lower("armv8.4a") != StringRef::npos) { + if (ArchName.find_lower("+crypto") != StringRef::npos) { + if (ArchName.find_lower("+nosha2") == StringRef::npos) + Features.push_back("+sha2"); + if (ArchName.find_lower("+noaes") == StringRef::npos) + Features.push_back("+aes"); + } else if (ArchName.find_lower("-crypto") != StringRef::npos) { + if (ArchName.find_lower("+sha2") == StringRef::npos) + Features.push_back("-sha2"); + if (ArchName.find_lower("+aes") == StringRef::npos) + Features.push_back("-aes"); + } + } + // Look for the last occurrence of -mlong-calls or -mno-long-calls. If // neither options are specified, see if we are compiling for kernel/kext and // decide whether to pass "+long-calls" based on the OS and its version. @@ -589,7 +643,7 @@ StringRef arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch, return llvm::ARM::getSubArch(ArchKind); } -void arm::appendEBLinkFlags(const ArgList &Args, ArgStringList &CmdArgs, +void arm::appendBE8LinkFlag(const ArgList &Args, ArgStringList &CmdArgs, const llvm::Triple &Triple) { if (Args.hasArg(options::OPT_r)) return; diff --git a/lib/Driver/ToolChains/Arch/ARM.h b/lib/Driver/ToolChains/Arch/ARM.h index c1dc16884033..9f0dc4ea2e25 100644 --- a/lib/Driver/ToolChains/Arch/ARM.h +++ b/lib/Driver/ToolChains/Arch/ARM.h @@ -29,7 +29,7 @@ StringRef getARMCPUForMArch(llvm::StringRef Arch, const llvm::Triple &Triple); StringRef getLLVMArchSuffixForARM(llvm::StringRef CPU, llvm::StringRef Arch, const llvm::Triple &Triple); -void appendEBLinkFlags(const llvm::opt::ArgList &Args, +void appendBE8LinkFlag(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const llvm::Triple &Triple); enum class ReadTPMode { diff --git a/lib/Driver/ToolChains/Arch/Mips.cpp b/lib/Driver/ToolChains/Arch/Mips.cpp index 6d814631d05f..e10a5e1c773f 100644 --- a/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/lib/Driver/ToolChains/Arch/Mips.cpp @@ -35,6 +35,11 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple, DefMips64CPU = "mips64r6"; } + if (Triple.getSubArch() == llvm::Triple::MipsSubArch_r6) { + DefMips32CPU = "mips32r6"; + DefMips64CPU = "mips64r6"; + } + // MIPS64r6 is the default for Android MIPS64 (mips64el-linux-android). if (Triple.isAndroid()) { DefMips32CPU = "mips32"; @@ -42,12 +47,12 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple, } // MIPS3 is the default for mips64*-unknown-openbsd. - if (Triple.getOS() == llvm::Triple::OpenBSD) + if (Triple.isOSOpenBSD()) DefMips64CPU = "mips3"; // MIPS2 is the default for mips(el)?-unknown-freebsd. // MIPS3 is the default for mips64(el)?-unknown-freebsd. - if (Triple.getOS() == llvm::Triple::FreeBSD) { + if (Triple.isOSFreeBSD()) { DefMips32CPU = "mips2"; DefMips64CPU = "mips3"; } @@ -82,6 +87,9 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple, } } + if (ABIName.empty() && (Triple.getEnvironment() == llvm::Triple::GNUABIN32)) + ABIName = "n32"; + if (ABIName.empty() && (Triple.getVendor() == llvm::Triple::MipsTechnologies || Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) { diff --git a/lib/Driver/ToolChains/Arch/PPC.cpp b/lib/Driver/ToolChains/Arch/PPC.cpp index f6a95962ace3..791f1206cf25 100644 --- a/lib/Driver/ToolChains/Arch/PPC.cpp +++ b/lib/Driver/ToolChains/Arch/PPC.cpp @@ -107,15 +107,19 @@ void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple, if (FloatABI == ppc::FloatABI::Soft) Features.push_back("-hard-float"); - ppc::ReadGOTPtrMode ReadGOT = ppc::getPPCReadGOTPtrMode(D, Args); + ppc::ReadGOTPtrMode ReadGOT = ppc::getPPCReadGOTPtrMode(D, Triple, Args); if (ReadGOT == ppc::ReadGOTPtrMode::SecurePlt) Features.push_back("+secure-plt"); } -ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const ArgList &Args) { +ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) { if (Args.getLastArg(options::OPT_msecure_plt)) return ppc::ReadGOTPtrMode::SecurePlt; - return ppc::ReadGOTPtrMode::Bss; + if (Triple.isOSOpenBSD()) + return ppc::ReadGOTPtrMode::SecurePlt; + else + return ppc::ReadGOTPtrMode::Bss; } ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) { diff --git a/lib/Driver/ToolChains/Arch/PPC.h b/lib/Driver/ToolChains/Arch/PPC.h index 3acee91a2ac3..4f3cd688ca39 100644 --- a/lib/Driver/ToolChains/Arch/PPC.h +++ b/lib/Driver/ToolChains/Arch/PPC.h @@ -38,7 +38,7 @@ FloatABI getPPCFloatABI(const Driver &D, const llvm::opt::ArgList &Args); std::string getPPCTargetCPU(const llvm::opt::ArgList &Args); const char *getPPCAsmModeForCPU(StringRef Name); -ReadGOTPtrMode getPPCReadGOTPtrMode(const Driver &D, +ReadGOTPtrMode getPPCReadGOTPtrMode(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); void getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple, diff --git a/lib/Driver/ToolChains/Arch/X86.cpp b/lib/Driver/ToolChains/Arch/X86.cpp index 7a4f836d2e1a..45648945d5ef 100644 --- a/lib/Driver/ToolChains/Arch/X86.cpp +++ b/lib/Driver/ToolChains/Arch/X86.cpp @@ -23,12 +23,8 @@ using namespace llvm::opt; const char *x86::getX86TargetCPU(const ArgList &Args, const llvm::Triple &Triple) { if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) { - if (StringRef(A->getValue()) != "native") { - if (Triple.isOSDarwin() && Triple.getArchName() == "x86_64h") - return "core-avx2"; - + if (StringRef(A->getValue()) != "native") return A->getValue(); - } // FIXME: Reject attempts to use -march=native unless the target matches // the host. @@ -144,6 +140,34 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple, Features.push_back("+ssse3"); } + // Translate the high level `-mretpoline` flag to the specific target feature + // flags. We also detect if the user asked for retpoline external thunks but + // failed to ask for retpolines themselves (through any of the different + // flags). This is a bit hacky but keeps existing usages working. We should + // consider deprecating this and instead warn if the user requests external + // retpoline thunks and *doesn't* request some form of retpolines. + if (Args.hasArgNoClaim(options::OPT_mretpoline, options::OPT_mno_retpoline, + options::OPT_mspeculative_load_hardening, + options::OPT_mno_speculative_load_hardening)) { + if (Args.hasFlag(options::OPT_mretpoline, options::OPT_mno_retpoline, + false)) { + Features.push_back("+retpoline-indirect-calls"); + Features.push_back("+retpoline-indirect-branches"); + } else if (Args.hasFlag(options::OPT_mspeculative_load_hardening, + options::OPT_mno_speculative_load_hardening, + false)) { + // On x86, speculative load hardening relies on at least using retpolines + // for indirect calls. + Features.push_back("+retpoline-indirect-calls"); + } + } else if (Args.hasFlag(options::OPT_mretpoline_external_thunk, + options::OPT_mno_retpoline_external_thunk, false)) { + // FIXME: Add a warning about failing to specify `-mretpoline` and + // eventually switch to an error here. + Features.push_back("+retpoline-indirect-calls"); + Features.push_back("+retpoline-indirect-branches"); + } + // Now add any that the user explicitly requested on the command line, // which may override the defaults. handleTargetFeaturesGroup(Args, Features, options::OPT_m_x86_Features_Group); diff --git a/lib/Driver/ToolChains/BareMetal.cpp b/lib/Driver/ToolChains/BareMetal.cpp index c302d647b973..31d16922cc43 100644 --- a/lib/Driver/ToolChains/BareMetal.cpp +++ b/lib/Driver/ToolChains/BareMetal.cpp @@ -13,13 +13,13 @@ #include "InputInfo.h" #include "Gnu.h" -#include "clang/Basic/VirtualFileSystem.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/Path.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" using namespace llvm::opt; @@ -119,10 +119,11 @@ void BareMetal::AddClangCXXStdlibIncludeArgs( std::error_code EC; Generic_GCC::GCCVersion Version = {"", -1, -1, -1, "", "", ""}; // Walk the subdirs, and find the one with the newest gcc version: - for (vfs::directory_iterator LI = - getDriver().getVFS().dir_begin(Dir.str(), EC), LE; + for (llvm::vfs::directory_iterator + LI = getDriver().getVFS().dir_begin(Dir.str(), EC), + LE; !EC && LI != LE; LI = LI.increment(EC)) { - StringRef VersionText = llvm::sys::path::filename(LI->getName()); + StringRef VersionText = llvm::sys::path::filename(LI->path()); auto CandidateVersion = Generic_GCC::GCCVersion::Parse(VersionText); if (CandidateVersion.Major == -1) continue; diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index 8e9c4c6aecb8..75f16898dfaf 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -19,12 +19,14 @@ #include "AMDGPU.h" #include "CommonArgs.h" #include "Hexagon.h" +#include "MSP430.h" #include "InputInfo.h" #include "PS4CPU.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Version.h" +#include "clang/Driver/Distro.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Driver/SanitizerArgs.h" @@ -341,7 +343,7 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, break; case llvm::Triple::aarch64: case llvm::Triple::aarch64_be: - aarch64::getAArch64TargetFeatures(D, Args, Features); + aarch64::getAArch64TargetFeatures(D, Triple, Args, Features); break; case llvm::Triple::x86: case llvm::Triple::x86_64: @@ -363,6 +365,8 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, case llvm::Triple::amdgcn: amdgpu::getAMDGPUTargetFeatures(D, Args, Features); break; + case llvm::Triple::msp430: + msp430::getMSP430TargetFeatures(D, Args, Features); } // Find the last of each feature. @@ -493,6 +497,8 @@ static codegenoptions::DebugInfoKind DebugLevelToInfoKind(const Arg &A) { if (A.getOption().matches(options::OPT_gline_tables_only) || A.getOption().matches(options::OPT_ggdb1)) return codegenoptions::DebugLineTablesOnly; + if (A.getOption().matches(options::OPT_gline_directives_only)) + return codegenoptions::DebugDirectivesOnly; return codegenoptions::LimitedDebugInfo; } @@ -524,11 +530,12 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args, break; } - if (Triple.getOS() == llvm::Triple::NetBSD) { + if (Triple.isOSNetBSD()) { return !areOptimizationsEnabled(Args); } - if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI) { + if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI || + Triple.isOSHurd()) { switch (Triple.getArch()) { // Don't use a frame pointer on linux if optimizing for certain targets. case llvm::Triple::mips64: @@ -800,6 +807,29 @@ static void addPGOAndCoverageFlags(Compilation &C, const Driver &D, CmdArgs.push_back("-fcoverage-mapping"); } + if (Args.hasArg(options::OPT_fprofile_exclude_files_EQ)) { + auto *Arg = Args.getLastArg(options::OPT_fprofile_exclude_files_EQ); + if (!Args.hasArg(options::OPT_coverage)) + D.Diag(clang::diag::err_drv_argument_only_allowed_with) + << "-fprofile-exclude-files=" + << "--coverage"; + + StringRef v = Arg->getValue(); + CmdArgs.push_back( + Args.MakeArgString(Twine("-fprofile-exclude-files=" + v))); + } + + if (Args.hasArg(options::OPT_fprofile_filter_files_EQ)) { + auto *Arg = Args.getLastArg(options::OPT_fprofile_filter_files_EQ); + if (!Args.hasArg(options::OPT_coverage)) + D.Diag(clang::diag::err_drv_argument_only_allowed_with) + << "-fprofile-filter-files=" + << "--coverage"; + + StringRef v = Arg->getValue(); + CmdArgs.push_back(Args.MakeArgString(Twine("-fprofile-filter-files=" + v))); + } + if (C.getArgs().hasArg(options::OPT_c) || C.getArgs().hasArg(options::OPT_S)) { if (Output.isFilename()) { @@ -889,6 +919,9 @@ static void RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs, unsigned DwarfVersion, llvm::DebuggerKind DebuggerTuning) { switch (DebugInfoKind) { + case codegenoptions::DebugDirectivesOnly: + CmdArgs.push_back("-debug-info-kind=line-directives-only"); + break; case codegenoptions::DebugLineTablesOnly: CmdArgs.push_back("-debug-info-kind=line-tables-only"); break; @@ -1100,10 +1133,19 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, StringRef ThroughHeader = YcArg ? YcArg->getValue() : YuArg->getValue(); if (!isa<PrecompileJobAction>(JA)) { CmdArgs.push_back("-include-pch"); - CmdArgs.push_back(Args.MakeArgString(D.GetClPchPath(C, ThroughHeader))); + CmdArgs.push_back(Args.MakeArgString(D.GetClPchPath( + C, !ThroughHeader.empty() + ? ThroughHeader + : llvm::sys::path::filename(Inputs[0].getBaseInput())))); + } + + if (ThroughHeader.empty()) { + CmdArgs.push_back(Args.MakeArgString( + Twine("-pch-through-hdrstop-") + (YcArg ? "create" : "use"))); + } else { + CmdArgs.push_back( + Args.MakeArgString(Twine("-pch-through-header=") + ThroughHeader)); } - CmdArgs.push_back( - Args.MakeArgString(Twine("-pch-through-header=") + ThroughHeader)); } } @@ -1114,42 +1156,26 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, bool IsFirstImplicitInclude = !RenderedImplicitInclude; RenderedImplicitInclude = true; - // Use PCH if the user requested it. - bool UsePCH = D.CCCUsePCH; - - bool FoundPTH = false; bool FoundPCH = false; SmallString<128> P(A->getValue()); // We want the files to have a name like foo.h.pch. Add a dummy extension // so that replace_extension does the right thing. P += ".dummy"; - if (UsePCH) { - llvm::sys::path::replace_extension(P, "pch"); - if (llvm::sys::fs::exists(P)) - FoundPCH = true; - } + llvm::sys::path::replace_extension(P, "pch"); + if (llvm::sys::fs::exists(P)) + FoundPCH = true; if (!FoundPCH) { - llvm::sys::path::replace_extension(P, "pth"); - if (llvm::sys::fs::exists(P)) - FoundPTH = true; - } - - if (!FoundPCH && !FoundPTH) { llvm::sys::path::replace_extension(P, "gch"); if (llvm::sys::fs::exists(P)) { - FoundPCH = UsePCH; - FoundPTH = !UsePCH; + FoundPCH = true; } } - if (FoundPCH || FoundPTH) { + if (FoundPCH) { if (IsFirstImplicitInclude) { A->claim(); - if (UsePCH) - CmdArgs.push_back("-include-pch"); - else - CmdArgs.push_back("-include-pth"); + CmdArgs.push_back("-include-pch"); CmdArgs.push_back(Args.MakeArgString(P)); continue; } else { @@ -1283,21 +1309,28 @@ static bool isNoCommonDefault(const llvm::Triple &Triple) { } } -void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args, - ArgStringList &CmdArgs, bool KernelOrKext) const { +namespace { +void RenderARMABI(const llvm::Triple &Triple, const ArgList &Args, + ArgStringList &CmdArgs) { // Select the ABI to use. // FIXME: Support -meabi. // FIXME: Parts of this are duplicated in the backend, unify this somehow. const char *ABIName = nullptr; - if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) + if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { ABIName = A->getValue(); - else { + } else { std::string CPU = getCPUName(Args, Triple, /*FromAs*/ false); ABIName = llvm::ARM::computeDefaultTargetABI(Triple, CPU).data(); } CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName); +} +} + +void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args, + ArgStringList &CmdArgs, bool KernelOrKext) const { + RenderARMABI(Triple, Args, CmdArgs); // Determine floating point ABI from the options & target defaults. arm::FloatABI ABI = arm::getARMFloatABI(getToolChain(), Args); @@ -1409,19 +1442,59 @@ void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple, } } -void Clang::AddAArch64TargetArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { - const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); +// Parse -mbranch-protection=<protection>[+<protection>]* where +// <protection> ::= standard | none | [bti,pac-ret[+b-key,+leaf]*] +// Returns a triple of (return address signing Scope, signing key, require +// landing pads) +static std::tuple<StringRef, StringRef, bool> +ParseAArch64BranchProtection(const Driver &D, const ArgList &Args, + const Arg *A) { + StringRef Scope = "none"; + StringRef Key = "a_key"; + bool IndirectBranches = false; - if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) || - Args.hasArg(options::OPT_mkernel) || - Args.hasArg(options::OPT_fapple_kext)) - CmdArgs.push_back("-disable-red-zone"); + StringRef Value = A->getValue(); + // This maps onto -mbranch-protection=<scope>+<key> + + if (Value.equals("standard")) { + Scope = "non-leaf"; + Key = "a_key"; + IndirectBranches = true; + + } else if (!Value.equals("none")) { + SmallVector<StringRef, 4> BranchProtection; + StringRef(A->getValue()).split(BranchProtection, '+'); + + auto Protection = BranchProtection.begin(); + while (Protection != BranchProtection.end()) { + if (Protection->equals("bti")) + IndirectBranches = true; + else if (Protection->equals("pac-ret")) { + Scope = "non-leaf"; + while (++Protection != BranchProtection.end()) { + // Inner loop as "leaf" and "b-key" options must only appear attached + // to pac-ret. + if (Protection->equals("leaf")) + Scope = "all"; + else if (Protection->equals("b-key")) + Key = "b_key"; + else + break; + } + Protection--; + } else + D.Diag(diag::err_invalid_branch_protection) + << *Protection << A->getAsString(Args); + Protection++; + } + } - if (!Args.hasFlag(options::OPT_mimplicit_float, - options::OPT_mno_implicit_float, true)) - CmdArgs.push_back("-no-implicit-float"); + return std::make_tuple(Scope, Key, IndirectBranches); +} +namespace { +void RenderAArch64ABI(const llvm::Triple &Triple, const ArgList &Args, + ArgStringList &CmdArgs) { const char *ABIName = nullptr; if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) ABIName = A->getValue(); @@ -1432,6 +1505,23 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName); +} +} + +void Clang::AddAArch64TargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); + + if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) || + Args.hasArg(options::OPT_mkernel) || + Args.hasArg(options::OPT_fapple_kext)) + CmdArgs.push_back("-disable-red-zone"); + + if (!Args.hasFlag(options::OPT_mimplicit_float, + options::OPT_mno_implicit_float, true)) + CmdArgs.push_back("-no-implicit-float"); + + RenderAArch64ABI(Triple, Args, CmdArgs); if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769, options::OPT_mno_fix_cortex_a53_835769)) { @@ -1455,6 +1545,35 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, else CmdArgs.push_back("-aarch64-enable-global-merge=true"); } + + // Enable/disable return address signing and indirect branch targets. + if (Arg *A = Args.getLastArg(options::OPT_msign_return_address_EQ, + options::OPT_mbranch_protection_EQ)) { + + const Driver &D = getToolChain().getDriver(); + + StringRef Scope, Key; + bool IndirectBranches; + + if (A->getOption().matches(options::OPT_msign_return_address_EQ)) { + Scope = A->getValue(); + if (!Scope.equals("none") && !Scope.equals("non-leaf") && + !Scope.equals("all")) + D.Diag(diag::err_invalid_branch_protection) + << Scope << A->getAsString(Args); + Key = "a_key"; + IndirectBranches = false; + } else + std::tie(Scope, Key, IndirectBranches) = + ParseAArch64BranchProtection(D, Args, A); + + CmdArgs.push_back( + Args.MakeArgString(Twine("-msign-return-address=") + Scope)); + CmdArgs.push_back( + Args.MakeArgString(Twine("-msign-return-address-key=") + Key)); + if (IndirectBranches) + CmdArgs.push_back("-mbranch-target-enforce"); + } } void Clang::AddMIPSTargetArgs(const ArgList &Args, @@ -1706,6 +1825,10 @@ void Clang::AddX86TargetArgs(const ArgList &Args, Args.hasArg(options::OPT_fapple_kext)) CmdArgs.push_back("-disable-red-zone"); + if (!Args.hasFlag(options::OPT_mtls_direct_seg_refs, + options::OPT_mno_tls_direct_seg_refs, true)) + CmdArgs.push_back("-mno-tls-direct-seg-refs"); + // Default to avoid implicit floating-point for kernel/kext code, but allow // that to be overridden with -mno-soft-float. bool NoImplicitFloat = (Args.hasArg(options::OPT_mkernel) || @@ -2033,6 +2156,9 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, } CmdArgs.push_back(Value.data()); TakeNextArg = true; + } else if (Value == "-fdebug-compilation-dir") { + CmdArgs.push_back("-fdebug-compilation-dir"); + TakeNextArg = true; } else { D.Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Value; @@ -2045,6 +2171,11 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, CmdArgs.push_back("-target-feature"); CmdArgs.push_back(MipsTargetFeature); } + + // forward -fembed-bitcode to assmebler + if (C.getDriver().embedBitcodeEnabled() || + C.getDriver().embedBitcodeMarkerOnly()) + Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ); } static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, @@ -2066,6 +2197,11 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, StringRef DenormalFPMath = ""; StringRef FPContract = ""; + if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) { + CmdArgs.push_back("-mlimit-float-precision"); + CmdArgs.push_back(A->getValue()); + } + for (const Arg *A : Args) { switch (A->getOption().getID()) { // If this isn't an FP option skip the claim below @@ -2228,8 +2364,6 @@ static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs, // Treat blocks as analysis entry points. CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks"); - CmdArgs.push_back("-analyzer-eagerly-assume"); - // Add default argument set. if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) { CmdArgs.push_back("-analyzer-checker=core"); @@ -2339,6 +2473,50 @@ static void RenderSSPOptions(const ToolChain &TC, const ArgList &Args, } } +static void RenderTrivialAutoVarInitOptions(const Driver &D, + const ToolChain &TC, + const ArgList &Args, + ArgStringList &CmdArgs) { + auto DefaultTrivialAutoVarInit = TC.GetDefaultTrivialAutoVarInit(); + StringRef TrivialAutoVarInit = ""; + + for (const Arg *A : Args) { + switch (A->getOption().getID()) { + default: + continue; + case options::OPT_ftrivial_auto_var_init: { + A->claim(); + StringRef Val = A->getValue(); + if (Val == "uninitialized" || Val == "zero" || Val == "pattern") + TrivialAutoVarInit = Val; + else + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << Val; + break; + } + } + } + + if (TrivialAutoVarInit.empty()) + switch (DefaultTrivialAutoVarInit) { + case LangOptions::TrivialAutoVarInitKind::Uninitialized: + break; + case LangOptions::TrivialAutoVarInitKind::Pattern: + TrivialAutoVarInit = "pattern"; + break; + case LangOptions::TrivialAutoVarInitKind::Zero: + TrivialAutoVarInit = "zero"; + break; + } + + if (!TrivialAutoVarInit.empty()) { + if (TrivialAutoVarInit == "zero" && !Args.hasArg(options::OPT_enable_trivial_var_init_zero)) + D.Diag(diag::err_drv_trivial_auto_var_init_zero_disabled); + CmdArgs.push_back( + Args.MakeArgString("-ftrivial-auto-var-init=" + TrivialAutoVarInit)); + } +} + static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs) { const unsigned ForwardedArguments[] = { options::OPT_cl_opt_disable, @@ -2658,8 +2836,10 @@ static void RenderCharacterOptions(const ArgList &Args, const llvm::Triple &T, CmdArgs.push_back("-fno-signed-char"); } - if (Args.hasFlag(options::OPT_fchar8__t, options::OPT_fno_char8__t, false)) - CmdArgs.push_back("-fchar8_t"); + // The default depends on the language standard. + if (const Arg *A = + Args.getLastArg(options::OPT_fchar8__t, options::OPT_fno_char8__t)) + A->render(Args, CmdArgs); if (const Arg *A = Args.getLastArg(options::OPT_fshort_wchar, options::OPT_fno_short_wchar)) { @@ -2669,8 +2849,8 @@ static void RenderCharacterOptions(const ArgList &Args, const llvm::Triple &T, } else { bool IsARM = T.isARM() || T.isThumb() || T.isAArch64(); CmdArgs.push_back("-fwchar-type=int"); - if (IsARM && !(T.isOSWindows() || T.getOS() == llvm::Triple::NetBSD || - T.getOS() == llvm::Triple::OpenBSD)) + if (IsARM && !(T.isOSWindows() || T.isOSNetBSD() || + T.isOSOpenBSD())) CmdArgs.push_back("-fno-signed-wchar"); else CmdArgs.push_back("-fsigned-wchar"); @@ -2701,7 +2881,6 @@ static void RenderObjCOptions(const ToolChain &TC, const Driver &D, // When ObjectiveC legacy runtime is in effect on MacOSX, turn on the option // to do Array/Dictionary subscripting by default. if (Arch == llvm::Triple::x86 && T.isMacOSX() && - !T.isMacOSXVersionLT(10, 7) && Runtime.getKind() == ObjCRuntime::FragileMacOSX && Runtime.isNeXTFamily()) CmdArgs.push_back("-fobjc-subscripting-legacy-runtime"); @@ -2737,6 +2916,18 @@ static void RenderObjCOptions(const ToolChain &TC, const Driver &D, Args.ClaimAllArgs(options::OPT_fno_objc_arc_exceptions); } + // Allow the user to control whether messages can be converted to runtime + // functions. + if (types::isObjC(Input.getType())) { + auto *Arg = Args.getLastArg( + options::OPT_fobjc_convert_messages_to_runtime_calls, + options::OPT_fno_objc_convert_messages_to_runtime_calls); + if (Arg && + Arg->getOption().matches( + options::OPT_fno_objc_convert_messages_to_runtime_calls)) + CmdArgs.push_back("-fno-objc-convert-messages-to-runtime-calls"); + } + // -fobjc-infer-related-result-type is the default, except in the Objective-C // rewriter. if (InferCovariantReturns) @@ -2872,12 +3063,35 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args, CmdArgs.push_back("-fno-spell-checking"); } +enum class DwarfFissionKind { None, Split, Single }; + +static DwarfFissionKind getDebugFissionKind(const Driver &D, + const ArgList &Args, Arg *&Arg) { + Arg = + Args.getLastArg(options::OPT_gsplit_dwarf, options::OPT_gsplit_dwarf_EQ); + if (!Arg) + return DwarfFissionKind::None; + + if (Arg->getOption().matches(options::OPT_gsplit_dwarf)) + return DwarfFissionKind::Split; + + StringRef Value = Arg->getValue(); + if (Value == "split") + return DwarfFissionKind::Split; + if (Value == "single") + return DwarfFissionKind::Single; + + D.Diag(diag::err_drv_unsupported_option_argument) + << Arg->getOption().getName() << Arg->getValue(); + return DwarfFissionKind::None; +} + static void RenderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, const ArgList &Args, bool EmitCodeView, bool IsWindowsMSVC, ArgStringList &CmdArgs, codegenoptions::DebugInfoKind &DebugInfoKind, - const Arg *&SplitDWARFArg) { + DwarfFissionKind &DwarfFission) { if (Args.hasFlag(options::OPT_fdebug_info_for_profiling, options::OPT_fno_debug_info_for_profiling, false) && checkDebugInfoOption( @@ -2902,10 +3116,12 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, Args.ClaimAllArgs(options::OPT_g_Group); - SplitDWARFArg = Args.getLastArg(options::OPT_gsplit_dwarf); + Arg* SplitDWARFArg; + DwarfFission = getDebugFissionKind(D, Args, SplitDWARFArg); - if (SplitDWARFArg && !checkDebugInfoOption(SplitDWARFArg, Args, D, TC)) { - SplitDWARFArg = nullptr; + if (DwarfFission != DwarfFissionKind::None && + !checkDebugInfoOption(SplitDWARFArg, Args, D, TC)) { + DwarfFission = DwarfFissionKind::None; SplitDWARFInlining = false; } @@ -2922,12 +3138,13 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, // composing split-dwarf and line-tables-only, so let those compose // naturally in that case. And if you just turned off debug info, // (-gsplit-dwarf -g0) - do that. - if (SplitDWARFArg) { + if (DwarfFission != DwarfFissionKind::None) { if (A->getIndex() > SplitDWARFArg->getIndex()) { if (DebugInfoKind == codegenoptions::NoDebugInfo || + DebugInfoKind == codegenoptions::DebugDirectivesOnly || (DebugInfoKind == codegenoptions::DebugLineTablesOnly && SplitDWARFInlining)) - SplitDWARFArg = nullptr; + DwarfFission = DwarfFissionKind::None; } else if (SplitDWARFInlining) DebugInfoKind = codegenoptions::NoDebugInfo; } @@ -2960,21 +3177,28 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, if (checkDebugInfoOption(A, Args, D, TC)) DWARFVersion = DwarfVersionNum(A->getSpelling()); - // Forward -gcodeview. EmitCodeView might have been set by CL-compatibility - // argument parsing. - if (EmitCodeView) { - if (const Arg *A = Args.getLastArg(options::OPT_gcodeview)) { - EmitCodeView = checkDebugInfoOption(A, Args, D, TC); - if (EmitCodeView) { - // DWARFVersion remains at 0 if no explicit choice was made. - CmdArgs.push_back("-gcodeview"); - } - } + if (const Arg *A = Args.getLastArg(options::OPT_gcodeview)) { + if (checkDebugInfoOption(A, Args, D, TC)) + EmitCodeView = true; } + // If the user asked for debug info but did not explicitly specify -gcodeview + // or -gdwarf, ask the toolchain for the default format. if (!EmitCodeView && DWARFVersion == 0 && - DebugInfoKind != codegenoptions::NoDebugInfo) - DWARFVersion = TC.GetDefaultDwarfVersion(); + DebugInfoKind != codegenoptions::NoDebugInfo) { + switch (TC.getDefaultDebugFormat()) { + case codegenoptions::DIF_CodeView: + EmitCodeView = true; + break; + case codegenoptions::DIF_DWARF: + DWARFVersion = TC.GetDefaultDwarfVersion(); + break; + } + } + + // -gline-directives-only supported only for the DWARF debug info. + if (DWARFVersion == 0 && DebugInfoKind == codegenoptions::DebugDirectivesOnly) + DebugInfoKind = codegenoptions::NoDebugInfo; // We ignore flag -gstrict-dwarf for now. // And we handle flag -grecord-gcc-switches later with DWARFDebugFlags. @@ -2993,10 +3217,11 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, CmdArgs.push_back("-dwarf-column-info"); // FIXME: Move backend command line options to the module. - // If -gline-tables-only is the last option it wins. + // If -gline-tables-only or -gline-directives-only is the last option it wins. if (const Arg *A = Args.getLastArg(options::OPT_gmodules)) if (checkDebugInfoOption(A, Args, D, TC)) { - if (DebugInfoKind != codegenoptions::DebugLineTablesOnly) { + if (DebugInfoKind != codegenoptions::DebugLineTablesOnly && + DebugInfoKind != codegenoptions::DebugDirectivesOnly) { DebugInfoKind = codegenoptions::LimitedDebugInfo; CmdArgs.push_back("-dwarf-ext-refs"); CmdArgs.push_back("-fmodule-format=obj"); @@ -3005,15 +3230,19 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, // -gsplit-dwarf should turn on -g and enable the backend dwarf // splitting and extraction. - // FIXME: Currently only works on Linux. - if (T.isOSLinux()) { + // FIXME: Currently only works on Linux and Fuchsia. + if (T.isOSLinux() || T.isOSFuchsia()) { if (!SplitDWARFInlining) CmdArgs.push_back("-fno-split-dwarf-inlining"); - if (SplitDWARFArg) { + if (DwarfFission != DwarfFissionKind::None) { if (DebugInfoKind == codegenoptions::NoDebugInfo) DebugInfoKind = codegenoptions::LimitedDebugInfo; - CmdArgs.push_back("-enable-split-dwarf"); + + if (DwarfFission == DwarfFissionKind::Single) + CmdArgs.push_back("-enable-split-dwarf=single"); + else + CmdArgs.push_back("-enable-split-dwarf"); } } @@ -3044,6 +3273,19 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, CmdArgs.push_back("-gembed-source"); } + if (EmitCodeView) { + CmdArgs.push_back("-gcodeview"); + + // Emit codeview type hashes if requested. + if (Args.hasFlag(options::OPT_gcodeview_ghash, + options::OPT_gno_codeview_ghash, false)) { + CmdArgs.push_back("-gcodeview-ghash"); + } + } + + // Adjust the debug info kind for the given toolchain. + TC.adjustDebugInfoKind(DebugInfoKind, Args); + RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DWARFVersion, DebuggerTuning); @@ -3055,11 +3297,24 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, CmdArgs.push_back("-debug-info-macro"); // -ggnu-pubnames turns on gnu style pubnames in the backend. - if (Args.hasFlag(options::OPT_ggnu_pubnames, options::OPT_gno_gnu_pubnames, - false)) - if (checkDebugInfoOption(Args.getLastArg(options::OPT_ggnu_pubnames), Args, - D, TC)) - CmdArgs.push_back("-ggnu-pubnames"); + const auto *PubnamesArg = + Args.getLastArg(options::OPT_ggnu_pubnames, options::OPT_gno_gnu_pubnames, + options::OPT_gpubnames, options::OPT_gno_pubnames); + if (DwarfFission != DwarfFissionKind::None || + DebuggerTuning == llvm::DebuggerKind::LLDB || + (PubnamesArg && checkDebugInfoOption(PubnamesArg, Args, D, TC))) + if (!PubnamesArg || + (!PubnamesArg->getOption().matches(options::OPT_gno_gnu_pubnames) && + !PubnamesArg->getOption().matches(options::OPT_gno_pubnames))) + CmdArgs.push_back(PubnamesArg && PubnamesArg->getOption().matches( + options::OPT_gpubnames) + ? "-gpubnames" + : "-ggnu-pubnames"); + + if (Args.hasFlag(options::OPT_fdebug_ranges_base_address, + options::OPT_fno_debug_ranges_base_address, false)) { + CmdArgs.push_back("-fdebug-ranges-base-address"); + } // -gdwarf-aranges turns on the emission of the aranges section in the // backend. @@ -3103,32 +3358,64 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, void Clang::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { - const llvm::Triple &RawTriple = getToolChain().getTriple(); - const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); + const auto &TC = getToolChain(); + const llvm::Triple &RawTriple = TC.getTriple(); + const llvm::Triple &Triple = TC.getEffectiveTriple(); const std::string &TripleStr = Triple.getTriple(); bool KernelOrKext = Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext); - const Driver &D = getToolChain().getDriver(); + const Driver &D = TC.getDriver(); ArgStringList CmdArgs; // Check number of inputs for sanity. We need at least one input. assert(Inputs.size() >= 1 && "Must have at least one input."); - const InputInfo &Input = Inputs[0]; // CUDA/HIP compilation may have multiple inputs (source file + results of // device-side compilations). OpenMP device jobs also take the host IR as a - // second input. All other jobs are expected to have exactly one - // input. + // second input. Module precompilation accepts a list of header files to + // include as part of the module. All other jobs are expected to have exactly + // one input. bool IsCuda = JA.isOffloading(Action::OFK_Cuda); bool IsHIP = JA.isOffloading(Action::OFK_HIP); bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP); - assert((IsCuda || IsHIP || (IsOpenMPDevice && Inputs.size() == 2) || - Inputs.size() == 1) && - "Unable to handle multiple inputs."); - - const llvm::Triple *AuxTriple = - IsCuda ? getToolChain().getAuxTriple() : nullptr; + bool IsHeaderModulePrecompile = isa<HeaderModulePrecompileJobAction>(JA); + + // A header module compilation doesn't have a main input file, so invent a + // fake one as a placeholder. + const char *ModuleName = [&]{ + auto *ModuleNameArg = Args.getLastArg(options::OPT_fmodule_name_EQ); + return ModuleNameArg ? ModuleNameArg->getValue() : ""; + }(); + InputInfo HeaderModuleInput(Inputs[0].getType(), ModuleName, ModuleName); + + const InputInfo &Input = + IsHeaderModulePrecompile ? HeaderModuleInput : Inputs[0]; + + InputInfoList ModuleHeaderInputs; + const InputInfo *CudaDeviceInput = nullptr; + const InputInfo *OpenMPDeviceInput = nullptr; + for (const InputInfo &I : Inputs) { + if (&I == &Input) { + // This is the primary input. + } else if (IsHeaderModulePrecompile && + types::getPrecompiledType(I.getType()) == types::TY_PCH) { + types::ID Expected = HeaderModuleInput.getType(); + if (I.getType() != Expected) { + D.Diag(diag::err_drv_module_header_wrong_kind) + << I.getFilename() << types::getTypeName(I.getType()) + << types::getTypeName(Expected); + } + ModuleHeaderInputs.push_back(I); + } else if ((IsCuda || IsHIP) && !CudaDeviceInput) { + CudaDeviceInput = &I; + } else if (IsOpenMPDevice && !OpenMPDeviceInput) { + OpenMPDeviceInput = &I; + } else { + llvm_unreachable("unexpectedly given multiple inputs"); + } + } + const llvm::Triple *AuxTriple = IsCuda ? TC.getAuxTriple() : nullptr; bool IsWindowsGNU = RawTriple.isWindowsGNUEnvironment(); bool IsWindowsCygnus = RawTriple.isWindowsCygwinEnvironment(); bool IsWindowsMSVC = RawTriple.isWindowsMSVCEnvironment(); @@ -3204,7 +3491,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Push all default warning arguments that are specific to // the given target. These come before user provided warning options // are provided. - getToolChain().addClangWarningOptions(CmdArgs); + TC.addClangWarningOptions(CmdArgs); // Select the appropriate action. RewriteKind rewriteKind = RK_None; @@ -3231,17 +3518,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Also ignore explicit -force_cpusubtype_ALL option. (void)Args.hasArg(options::OPT_force__cpusubtype__ALL); } else if (isa<PrecompileJobAction>(JA)) { - // Use PCH if the user requested it. - bool UsePCH = D.CCCUsePCH; - if (JA.getType() == types::TY_Nothing) CmdArgs.push_back("-fsyntax-only"); else if (JA.getType() == types::TY_ModuleFile) - CmdArgs.push_back("-emit-module-interface"); - else if (UsePCH) - CmdArgs.push_back("-emit-pch"); + CmdArgs.push_back(IsHeaderModulePrecompile + ? "-emit-header-module" + : "-emit-module-interface"); else - CmdArgs.push_back("-emit-pth"); + CmdArgs.push_back("-emit-pch"); } else if (isa<VerifyPCHJobAction>(JA)) { CmdArgs.push_back("-verify-pch"); } else { @@ -3305,13 +3589,116 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_save_temps_EQ); // Embed-bitcode option. + // Only white-listed flags below are allowed to be embedded. if (C.getDriver().embedBitcodeInObject() && !C.getDriver().isUsingLTO() && (isa<BackendJobAction>(JA) || isa<AssembleJobAction>(JA))) { // Add flags implied by -fembed-bitcode. Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ); // Disable all llvm IR level optimizations. CmdArgs.push_back("-disable-llvm-passes"); + + // reject options that shouldn't be supported in bitcode + // also reject kernel/kext + static const constexpr unsigned kBitcodeOptionBlacklist[] = { + options::OPT_mkernel, + options::OPT_fapple_kext, + options::OPT_ffunction_sections, + options::OPT_fno_function_sections, + options::OPT_fdata_sections, + options::OPT_fno_data_sections, + options::OPT_funique_section_names, + options::OPT_fno_unique_section_names, + options::OPT_mrestrict_it, + options::OPT_mno_restrict_it, + options::OPT_mstackrealign, + options::OPT_mno_stackrealign, + options::OPT_mstack_alignment, + options::OPT_mcmodel_EQ, + options::OPT_mlong_calls, + options::OPT_mno_long_calls, + options::OPT_ggnu_pubnames, + options::OPT_gdwarf_aranges, + options::OPT_fdebug_types_section, + options::OPT_fno_debug_types_section, + options::OPT_fdwarf_directory_asm, + options::OPT_fno_dwarf_directory_asm, + options::OPT_mrelax_all, + options::OPT_mno_relax_all, + options::OPT_ftrap_function_EQ, + options::OPT_ffixed_r9, + options::OPT_mfix_cortex_a53_835769, + options::OPT_mno_fix_cortex_a53_835769, + options::OPT_ffixed_x18, + options::OPT_mglobal_merge, + options::OPT_mno_global_merge, + options::OPT_mred_zone, + options::OPT_mno_red_zone, + options::OPT_Wa_COMMA, + options::OPT_Xassembler, + options::OPT_mllvm, + }; + for (const auto &A : Args) + if (std::find(std::begin(kBitcodeOptionBlacklist), + std::end(kBitcodeOptionBlacklist), + A->getOption().getID()) != + std::end(kBitcodeOptionBlacklist)) + D.Diag(diag::err_drv_unsupported_embed_bitcode) << A->getSpelling(); + + // Render the CodeGen options that need to be passed. + if (!Args.hasFlag(options::OPT_foptimize_sibling_calls, + options::OPT_fno_optimize_sibling_calls)) + CmdArgs.push_back("-mdisable-tail-calls"); + + RenderFloatingPointOptions(TC, D, isOptimizationLevelFast(Args), Args, + CmdArgs); + + // Render ABI arguments + switch (TC.getArch()) { + default: break; + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumbeb: + RenderARMABI(Triple, Args, CmdArgs); + break; + case llvm::Triple::aarch64: + case llvm::Triple::aarch64_be: + RenderAArch64ABI(Triple, Args, CmdArgs); + break; + } + + // Optimization level for CodeGen. + if (const Arg *A = Args.getLastArg(options::OPT_O_Group)) { + if (A->getOption().matches(options::OPT_O4)) { + CmdArgs.push_back("-O3"); + D.Diag(diag::warn_O4_is_O3); + } else { + A->render(Args, CmdArgs); + } + } + + // Input/Output file. + if (Output.getType() == types::TY_Dependencies) { + // Handled with other dependency code. + } else if (Output.isFilename()) { + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + } else { + assert(Output.isNothing() && "Input output."); + } + + for (const auto &II : Inputs) { + addDashXForInput(Args, II, CmdArgs); + if (II.isFilename()) + CmdArgs.push_back(II.getFilename()); + else + II.getInputArg().renderAsInput(Args, CmdArgs); + } + + C.addCommand(llvm::make_unique<Command>(JA, *this, D.getClangProgramPath(), + CmdArgs, Inputs)); + return; } + if (C.getDriver().embedBitcodeMarkerOnly() && !C.getDriver().isUsingLTO()) CmdArgs.push_back("-fembed-bitcode=marker"); @@ -3346,12 +3733,33 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("-static-define"); + if (Args.hasArg(options::OPT_municode)) + CmdArgs.push_back("-DUNICODE"); + if (isa<AnalyzeJobAction>(JA)) RenderAnalyzerOptions(Args, CmdArgs, Triple, Input); + // Enable compatilibily mode to avoid analyzer-config related errors. + // Since we can't access frontend flags through hasArg, let's manually iterate + // through them. + bool FoundAnalyzerConfig = false; + for (auto Arg : Args.filtered(options::OPT_Xclang)) + if (StringRef(Arg->getValue()) == "-analyzer-config") { + FoundAnalyzerConfig = true; + break; + } + if (!FoundAnalyzerConfig) + for (auto Arg : Args.filtered(options::OPT_Xanalyzer)) + if (StringRef(Arg->getValue()) == "-analyzer-config") { + FoundAnalyzerConfig = true; + break; + } + if (FoundAnalyzerConfig) + CmdArgs.push_back("-analyzer-config-compatibility-mode=true"); + CheckCodeGenerationOptions(D, Args); - unsigned FunctionAlignment = ParseFunctionAlignment(getToolChain(), Args); + unsigned FunctionAlignment = ParseFunctionAlignment(TC, Args); assert(FunctionAlignment <= 31 && "function alignment will be truncated!"); if (FunctionAlignment) { CmdArgs.push_back("-function-alignment"); @@ -3361,8 +3769,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, llvm::Reloc::Model RelocationModel; unsigned PICLevel; bool IsPIE; - std::tie(RelocationModel, PICLevel, IsPIE) = - ParsePICArgs(getToolChain(), Args); + std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(TC, Args); const char *RMName = RelocationModelName(RelocationModel); @@ -3390,13 +3797,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-mthread-model"); if (Arg *A = Args.getLastArg(options::OPT_mthread_model)) { - if (!getToolChain().isThreadModelSupported(A->getValue())) + if (!TC.isThreadModelSupported(A->getValue())) D.Diag(diag::err_drv_invalid_thread_model_for_target) << A->getValue() << A->getAsString(Args); CmdArgs.push_back(A->getValue()); } else - CmdArgs.push_back(Args.MakeArgString(getToolChain().getThreadModel())); + CmdArgs.push_back(Args.MakeArgString(TC.getThreadModel())); Args.AddLastArg(CmdArgs, options::OPT_fveclib); @@ -3451,7 +3858,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_fpcc_struct_return, options::OPT_freg_struct_return)) { - if (getToolChain().getArch() != llvm::Triple::x86) { + if (TC.getArch() != llvm::Triple::x86) { D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getSpelling() << RawTriple.str(); } else if (A->getOption().matches(options::OPT_fpcc_struct_return)) { @@ -3516,18 +3923,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_fsplit_stack)) CmdArgs.push_back("-split-stacks"); - RenderFloatingPointOptions(getToolChain(), D, OFastEnabled, Args, CmdArgs); + RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs); // Decide whether to use verbose asm. Verbose assembly is the default on // toolchains which have the integrated assembler on by default. - bool IsIntegratedAssemblerDefault = - getToolChain().IsIntegratedAssemblerDefault(); + bool IsIntegratedAssemblerDefault = TC.IsIntegratedAssemblerDefault(); if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm, IsIntegratedAssemblerDefault) || Args.hasArg(options::OPT_dA)) CmdArgs.push_back("-masm-verbose"); - if (!getToolChain().useIntegratedAs()) + if (!TC.useIntegratedAs()) CmdArgs.push_back("-no-integrated-as"); if (Args.hasArg(options::OPT_fdebug_pass_structure)) { @@ -3580,20 +3986,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, bool AsynchronousUnwindTables = Args.hasFlag(options::OPT_fasynchronous_unwind_tables, options::OPT_fno_asynchronous_unwind_tables, - (getToolChain().IsUnwindTablesDefault(Args) || - getToolChain().getSanitizerArgs().needsUnwindTables()) && + (TC.IsUnwindTablesDefault(Args) || + TC.getSanitizerArgs().needsUnwindTables()) && !Freestanding); if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables, AsynchronousUnwindTables)) CmdArgs.push_back("-munwind-tables"); - getToolChain().addClangTargetOptions(Args, CmdArgs, - JA.getOffloadingDeviceKind()); - - if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) { - CmdArgs.push_back("-mlimit-float-precision"); - CmdArgs.push_back(A->getValue()); - } + TC.addClangTargetOptions(Args, CmdArgs, JA.getOffloadingDeviceKind()); // FIXME: Handle -mtune=. (void)Args.hasArg(options::OPT_mtune_EQ); @@ -3620,22 +4020,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, types::ID InputType = Input.getType(); if (D.IsCLMode()) AddClangCLArgs(Args, InputType, CmdArgs, &DebugInfoKind, &EmitCodeView); - else - EmitCodeView = Args.hasArg(options::OPT_gcodeview); - const Arg *SplitDWARFArg = nullptr; - RenderDebugOptions(getToolChain(), D, RawTriple, Args, EmitCodeView, - IsWindowsMSVC, CmdArgs, DebugInfoKind, SplitDWARFArg); + DwarfFissionKind DwarfFission; + RenderDebugOptions(TC, D, RawTriple, Args, EmitCodeView, IsWindowsMSVC, + CmdArgs, DebugInfoKind, DwarfFission); // Add the split debug info name to the command lines here so we // can propagate it to the backend. - bool SplitDWARF = SplitDWARFArg && RawTriple.isOSLinux() && + bool SplitDWARF = (DwarfFission != DwarfFissionKind::None) && + (RawTriple.isOSLinux() || RawTriple.isOSFuchsia()) && (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)); const char *SplitDWARFOut; if (SplitDWARF) { CmdArgs.push_back("-split-dwarf-file"); - SplitDWARFOut = SplitDebugName(Args, Input); + SplitDWARFOut = SplitDebugName(Args, Output); CmdArgs.push_back(SplitDWARFOut); } @@ -3653,7 +4052,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_fallow_unsupported)) { Arg *Unsupported; if (types::isCXX(InputType) && RawTriple.isOSDarwin() && - getToolChain().getArch() == llvm::Triple::x86) { + TC.getArch() == llvm::Triple::x86) { if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext)) || (Unsupported = Args.getLastArg(options::OPT_mkernel))) D.Diag(diag::err_drv_clang_unsupported_opt_cxx_darwin_i386) @@ -3717,9 +4116,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, ABICompatArg->render(Args, CmdArgs); // Add runtime flag for PS4 when PGO, coverage, or sanitizers are enabled. - if (RawTriple.isPS4CPU()) { - PS4cpu::addProfileRTArgs(getToolChain(), Args, CmdArgs); - PS4cpu::addSanitizerArgs(getToolChain(), CmdArgs); + if (RawTriple.isPS4CPU() && + !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { + PS4cpu::addProfileRTArgs(TC, Args, CmdArgs); + PS4cpu::addSanitizerArgs(TC, CmdArgs); } // Pass options for controlling the default header search paths. @@ -3867,10 +4267,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fno-gnu-keywords"); } - if (ShouldDisableDwarfDirectory(Args, getToolChain())) + if (ShouldDisableDwarfDirectory(Args, TC)) CmdArgs.push_back("-fno-dwarf-directory-asm"); - if (ShouldDisableAutolink(Args, getToolChain())) + if (ShouldDisableAutolink(Args, TC)) CmdArgs.push_back("-fno-autolink"); // Add in -fdebug-compilation-dir if necessary. @@ -3916,6 +4316,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_relocatable_pch)) CmdArgs.push_back("-relocatable-pch"); + if (const Arg *A = Args.getLastArg(options::OPT_fcf_runtime_abi_EQ)) { + static const char *kCFABIs[] = { + "standalone", "objc", "swift", "swift-5.0", "swift-4.2", "swift-4.1", + }; + + if (find(kCFABIs, StringRef(A->getValue())) == std::end(kCFABIs)) + D.Diag(diag::err_drv_invalid_cf_runtime_abi) << A->getValue(); + else + A->render(Args, CmdArgs); + } + if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) { CmdArgs.push_back("-fconstant-string-class"); CmdArgs.push_back(A->getValue()); @@ -3983,6 +4394,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden); + Args.AddLastArg(CmdArgs, options::OPT_fvisibility_global_new_delete_hidden); Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ); @@ -3993,6 +4405,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names); Args.AddLastArg(CmdArgs, options::OPT_femulated_tls, options::OPT_fno_emulated_tls); + Args.AddLastArg(CmdArgs, options::OPT_fkeep_static_consts); // AltiVec-like language extensions aren't relevant for assembling. if (!isa<PreprocessJobAction>(JA) || Output.getType() != types::TY_PP_Asm) @@ -4022,11 +4435,25 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd, options::OPT_fno_openmp_simd); Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ); + Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_number_of_sm_EQ); + Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_blocks_per_sm_EQ); + if (Args.hasFlag(options::OPT_fopenmp_optimistic_collapse, + options::OPT_fno_openmp_optimistic_collapse, + /*Default=*/false)) + CmdArgs.push_back("-fopenmp-optimistic-collapse"); // When in OpenMP offloading mode with NVPTX target, forward // cuda-mode flag - Args.AddLastArg(CmdArgs, options::OPT_fopenmp_cuda_mode, - options::OPT_fno_openmp_cuda_mode); + if (Args.hasFlag(options::OPT_fopenmp_cuda_mode, + options::OPT_fno_openmp_cuda_mode, /*Default=*/false)) + CmdArgs.push_back("-fopenmp-cuda-mode"); + + // When in OpenMP offloading mode with NVPTX target, check if full runtime + // is required. + if (Args.hasFlag(options::OPT_fopenmp_cuda_force_full_runtime, + options::OPT_fno_openmp_cuda_force_full_runtime, + /*Default=*/false)) + CmdArgs.push_back("-fopenmp-cuda-force-full-runtime"); break; default: // By default, if Clang doesn't know how to generate useful OpenMP code @@ -4043,16 +4470,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ); } - const SanitizerArgs &Sanitize = getToolChain().getSanitizerArgs(); - Sanitize.addArgs(getToolChain(), Args, CmdArgs, InputType); + const SanitizerArgs &Sanitize = TC.getSanitizerArgs(); + Sanitize.addArgs(TC, Args, CmdArgs, InputType); - const XRayArgs &XRay = getToolChain().getXRayArgs(); - XRay.addArgs(getToolChain(), Args, CmdArgs, InputType); + const XRayArgs &XRay = TC.getXRayArgs(); + XRay.addArgs(TC, Args, CmdArgs, InputType); - if (getToolChain().SupportsProfiling()) + if (TC.SupportsProfiling()) Args.AddLastArg(CmdArgs, options::OPT_pg); - if (getToolChain().SupportsProfiling()) + if (TC.SupportsProfiling()) Args.AddLastArg(CmdArgs, options::OPT_mfentry); // -flax-vector-conversions is default. @@ -4099,7 +4526,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_pthread); - RenderSSPOptions(getToolChain(), Args, CmdArgs, KernelOrKext); + if (Args.hasFlag(options::OPT_mspeculative_load_hardening, options::OPT_mno_speculative_load_hardening, + false)) + CmdArgs.push_back(Args.MakeArgString("-mspeculative-load-hardening")); + + RenderSSPOptions(TC, Args, CmdArgs, KernelOrKext); + RenderTrivialAutoVarInitOptions(D, TC, Args, CmdArgs); // Translate -mstackrealign if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign, @@ -4158,8 +4590,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, else A->render(Args, CmdArgs); } + Args.AddLastArg(CmdArgs, options::OPT_fprofile_remapping_file_EQ); - RenderBuiltinOptions(getToolChain(), RawTriple, Args, CmdArgs); + RenderBuiltinOptions(TC, RawTriple, Args, CmdArgs); if (!Args.hasFlag(options::OPT_fassume_sane_operator_new, options::OPT_fno_assume_sane_operator_new)) @@ -4167,19 +4600,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fblocks=0 is default. if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks, - getToolChain().IsBlocksDefault()) || + TC.IsBlocksDefault()) || (Args.hasArg(options::OPT_fgnu_runtime) && Args.hasArg(options::OPT_fobjc_nonfragile_abi) && !Args.hasArg(options::OPT_fno_blocks))) { CmdArgs.push_back("-fblocks"); - if (!Args.hasArg(options::OPT_fgnu_runtime) && - !getToolChain().hasBlocksRuntime()) + if (!Args.hasArg(options::OPT_fgnu_runtime) && !TC.hasBlocksRuntime()) CmdArgs.push_back("-fblocks-runtime-optional"); } // -fencode-extended-block-signature=1 is default. - if (getToolChain().IsEncodeExtendedBlockSignatureDefault()) + if (TC.IsEncodeExtendedBlockSignatureDefault()) CmdArgs.push_back("-fencode-extended-block-signature"); if (Args.hasFlag(options::OPT_fcoroutines_ts, options::OPT_fno_coroutines_ts, @@ -4204,7 +4636,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_felide_constructors, false)) CmdArgs.push_back("-fno-elide-constructors"); - ToolChain::RTTIMode RTTIMode = getToolChain().getRTTIMode(); + ToolChain::RTTIMode RTTIMode = TC.getRTTIMode(); if (KernelOrKext || (types::isCXX(InputType) && (RTTIMode == ToolChain::RM_Disabled))) @@ -4212,7 +4644,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fshort-enums=0 is default for all architectures except Hexagon. if (Args.hasFlag(options::OPT_fshort_enums, options::OPT_fno_short_enums, - getToolChain().getArch() == llvm::Triple::hexagon)) + TC.getArch() == llvm::Triple::hexagon)) CmdArgs.push_back("-fshort-enums"); RenderCharacterOptions(Args, AuxTriple ? *AuxTriple : RawTriple, CmdArgs); @@ -4222,8 +4654,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit, !RawTriple.isOSWindows() && RawTriple.getOS() != llvm::Triple::Solaris && - getToolChain().getArch() != llvm::Triple::hexagon && - getToolChain().getArch() != llvm::Triple::xcore && + TC.getArch() != llvm::Triple::xcore && ((RawTriple.getVendor() != llvm::Triple::MipsTechnologies) || RawTriple.hasEnvironment())) || KernelOrKext) @@ -4252,7 +4683,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_ms_extensions, true)))) CmdArgs.push_back("-fms-compatibility"); - VersionTuple MSVT = getToolChain().computeMSVCVersion(&D, Args); + VersionTuple MSVT = TC.computeMSVCVersion(&D, Args); if (!MSVT.empty()) CmdArgs.push_back( Args.MakeArgString("-fms-compatibility-version=" + MSVT.getAsString())); @@ -4330,8 +4761,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_experimental_new_pass_manager); ObjCRuntime Runtime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind); - RenderObjCOptions(getToolChain(), D, RawTriple, Args, Runtime, - rewriteKind != RK_None, Input, CmdArgs); + RenderObjCOptions(TC, D, RawTriple, Args, Runtime, rewriteKind != RK_None, + Input, CmdArgs); if (Args.hasFlag(options::OPT_fapplication_extension, options::OPT_fno_application_extension, false)) @@ -4339,8 +4770,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Handle GCC-style exception args. if (!C.getDriver().IsCLMode()) - addExceptionArgs(Args, InputType, getToolChain(), KernelOrKext, Runtime, - CmdArgs); + addExceptionArgs(Args, InputType, TC, KernelOrKext, Runtime, CmdArgs); // Handle exception personalities Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions, @@ -4355,7 +4785,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Opt.matches(options::OPT_fdwarf_exceptions)) CmdArgs.push_back("-fdwarf-exceptions"); } else { - switch (getToolChain().GetExceptionModel(Args)) { + switch (TC.GetExceptionModel(Args)) { default: break; case llvm::ExceptionHandling::DwarfCFI: @@ -4592,7 +5022,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // nice to enable this when doing a crashdump for modules as well. if (Args.hasFlag(options::OPT_frewrite_includes, options::OPT_fno_rewrite_includes, false) || - (C.isForDiagnostics() && (RewriteImports || !HaveModules))) + (C.isForDiagnostics() && !HaveModules)) CmdArgs.push_back("-frewrite-includes"); // Only allow -traditional or -traditional-cpp outside in preprocessing modes. @@ -4685,23 +5115,39 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, addDashXForInput(Args, Input, CmdArgs); - if (Input.isFilename()) - CmdArgs.push_back(Input.getFilename()); - else - Input.getInputArg().renderAsInput(Args, CmdArgs); + ArrayRef<InputInfo> FrontendInputs = Input; + if (IsHeaderModulePrecompile) + FrontendInputs = ModuleHeaderInputs; + else if (Input.isNothing()) + FrontendInputs = {}; + + for (const InputInfo &Input : FrontendInputs) { + if (Input.isFilename()) + CmdArgs.push_back(Input.getFilename()); + else + Input.getInputArg().renderAsInput(Args, CmdArgs); + } Args.AddAllArgs(CmdArgs, options::OPT_undef); const char *Exec = D.getClangProgramPath(); - // Optionally embed the -cc1 level arguments into the debug info, for build - // analysis. + // Optionally embed the -cc1 level arguments into the debug info or a + // section, for build analysis. // Also record command line arguments into the debug info if // -grecord-gcc-switches options is set on. // By default, -gno-record-gcc-switches is set on and no recording. - if (getToolChain().UseDwarfDebugFlags() || - Args.hasFlag(options::OPT_grecord_gcc_switches, - options::OPT_gno_record_gcc_switches, false)) { + auto GRecordSwitches = + Args.hasFlag(options::OPT_grecord_command_line, + options::OPT_gno_record_command_line, false); + auto FRecordSwitches = + Args.hasFlag(options::OPT_frecord_command_line, + options::OPT_fno_record_command_line, false); + if (FRecordSwitches && !Triple.isOSBinFormatELF()) + D.Diag(diag::err_drv_unsupported_opt_for_target) + << Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args) + << TripleStr; + if (TC.UseDwarfDebugFlags() || GRecordSwitches || FRecordSwitches) { ArgStringList OriginalArgs; for (const auto &Arg : Args) Arg->render(Args, OriginalArgs); @@ -4714,21 +5160,27 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Flags += " "; Flags += EscapedArg; } - CmdArgs.push_back("-dwarf-debug-flags"); - CmdArgs.push_back(Args.MakeArgString(Flags)); + auto FlagsArgString = Args.MakeArgString(Flags); + if (TC.UseDwarfDebugFlags() || GRecordSwitches) { + CmdArgs.push_back("-dwarf-debug-flags"); + CmdArgs.push_back(FlagsArgString); + } + if (FRecordSwitches) { + CmdArgs.push_back("-record-command-line"); + CmdArgs.push_back(FlagsArgString); + } } - if (IsCuda) { - // Host-side cuda compilation receives all device-side outputs in a single - // fatbin as Inputs[1]. Include the binary with -fcuda-include-gpubinary. - if (Inputs.size() > 1) { - assert(Inputs.size() == 2 && "More than one GPU binary!"); + // Host-side cuda compilation receives all device-side outputs in a single + // fatbin as Inputs[1]. Include the binary with -fcuda-include-gpubinary. + if ((IsCuda || IsHIP) && CudaDeviceInput) { CmdArgs.push_back("-fcuda-include-gpubinary"); - CmdArgs.push_back(Inputs[1].getFilename()); - } + CmdArgs.push_back(CudaDeviceInput->getFilename()); + if (Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false)) + CmdArgs.push_back("-fgpu-rdc"); + } - if (Args.hasFlag(options::OPT_fcuda_rdc, options::OPT_fno_cuda_rdc, false)) - CmdArgs.push_back("-fcuda-rdc"); + if (IsCuda) { if (Args.hasFlag(options::OPT_fcuda_short_ptr, options::OPT_fno_cuda_short_ptr, false)) CmdArgs.push_back("-fcuda-short-ptr"); @@ -4741,9 +5193,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // only the relevant declarations are emitted. if (IsOpenMPDevice) { CmdArgs.push_back("-fopenmp-is-device"); - if (Inputs.size() == 2) { + if (OpenMPDeviceInput) { CmdArgs.push_back("-fopenmp-host-ir-file-path"); - CmdArgs.push_back(Args.MakeArgString(Inputs.back().getFilename())); + CmdArgs.push_back(Args.MakeArgString(OpenMPDeviceInput->getFilename())); } } @@ -4777,6 +5229,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fwhole-program-vtables"); } + bool RequiresSplitLTOUnit = WholeProgramVTables || Sanitize.needsLTO(); + bool SplitLTOUnit = + Args.hasFlag(options::OPT_fsplit_lto_unit, + options::OPT_fno_split_lto_unit, RequiresSplitLTOUnit); + if (RequiresSplitLTOUnit && !SplitLTOUnit) + D.Diag(diag::err_drv_argument_not_allowed_with) + << "-fno-split-lto-unit" + << (WholeProgramVTables ? "-fwhole-program-vtables" : "-fsanitize=cfi"); + if (SplitLTOUnit) + CmdArgs.push_back("-fsplit-lto-unit"); + if (Arg *A = Args.getLastArg(options::OPT_fexperimental_isel, options::OPT_fno_experimental_isel)) { CmdArgs.push_back("-mllvm"); @@ -4818,6 +5281,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_complete_member_pointers, false)) CmdArgs.push_back("-fcomplete-member-pointers"); + if (!Args.hasFlag(options::OPT_fcxx_static_destructors, + options::OPT_fno_cxx_static_destructors, true)) + CmdArgs.push_back("-fno-c++-static-destructors"); + if (Arg *A = Args.getLastArg(options::OPT_moutline, options::OPT_mno_outline)) { if (A->getOption().matches(options::OPT_moutline)) { @@ -4838,8 +5305,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } if (Args.hasFlag(options::OPT_faddrsig, options::OPT_fno_addrsig, - getToolChain().getTriple().isOSBinFormatELF() && - getToolChain().useIntegratedAs())) + (TC.getTriple().isOSBinFormatELF() || + TC.getTriple().isOSBinFormatCOFF()) && + !TC.getTriple().isPS4() && + !TC.getTriple().isOSNetBSD() && + !Distro(D.getVFS()).IsGentoo() && + !TC.getTriple().isAndroid() && + TC.useIntegratedAs())) CmdArgs.push_back("-faddrsig"); // Finally add the compile command to the compilation. @@ -4860,16 +5332,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } + // Make the compile command echo its inputs for /showFilenames. + if (Output.getType() == types::TY_Object && + Args.hasFlag(options::OPT__SLASH_showFilenames, + options::OPT__SLASH_showFilenames_, false)) { + C.getJobs().getJobs().back()->setPrintInputFilenames(true); + } + if (Arg *A = Args.getLastArg(options::OPT_pg)) - if (Args.hasArg(options::OPT_fomit_frame_pointer)) + if (!shouldUseFramePointer(Args, Triple)) D.Diag(diag::err_drv_argument_not_allowed_with) << "-fomit-frame-pointer" << A->getAsString(Args); // Claim some arguments which clang supports automatically. // -fpch-preprocess is used with gcc to add a special marker in the output to - // include the PCH file. Clang's PTH solution is completely transparent, so we - // do not need to deal with it at all. + // include the PCH file. Args.ClaimAllArgs(options::OPT_fpch_preprocess); // Claim some arguments which clang doesn't support, but we don't @@ -4912,7 +5390,8 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args, } if ((runtime.getKind() == ObjCRuntime::GNUstep) && (runtime.getVersion() >= VersionTuple(2, 0))) - if (!getToolChain().getTriple().isOSBinFormatELF()) { + if (!getToolChain().getTriple().isOSBinFormatELF() && + !getToolChain().getTriple().isOSBinFormatCOFF()) { getToolChain().getDriver().Diag( diag::err_drv_gnustep_objc_runtime_incompatible_binary) << runtime.getVersion().getMajor(); @@ -5163,7 +5642,6 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, *DebugInfoKind = codegenoptions::LimitedDebugInfo; else *DebugInfoKind = codegenoptions::DebugLineTablesOnly; - CmdArgs.push_back("-gcodeview"); } else { *EmitCodeView = false; } @@ -5197,6 +5675,16 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, if (VolatileOptionID == options::OPT__SLASH_volatile_ms) CmdArgs.push_back("-fms-volatile"); + if (Args.hasFlag(options::OPT__SLASH_Zc_dllexportInlines_, + options::OPT__SLASH_Zc_dllexportInlines, + false)) { + if (Args.hasArg(options::OPT__SLASH_fallback)) { + D.Diag(clang::diag::err_drv_dllexport_inlines_and_fallback); + } else { + CmdArgs.push_back("-fno-dllexport-inlines"); + } + } + Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg); Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb); if (MostGeneralArg && BestCaseArg) @@ -5270,9 +5758,28 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, CmdArgs.push_back("msvc"); } - if (Args.hasArg(options::OPT__SLASH_Guard) && - Args.getLastArgValue(options::OPT__SLASH_Guard).equals_lower("cf")) - CmdArgs.push_back("-cfguard"); + if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) { + SmallVector<StringRef, 1> SplitArgs; + StringRef(A->getValue()).split(SplitArgs, ","); + bool Instrument = false; + bool NoChecks = false; + for (StringRef Arg : SplitArgs) { + if (Arg.equals_lower("cf")) + Instrument = true; + else if (Arg.equals_lower("cf-")) + Instrument = false; + else if (Arg.equals_lower("nochecks")) + NoChecks = true; + else if (Arg.equals_lower("nochecks-")) + NoChecks = false; + else + D.Diag(diag::err_drv_invalid_value) << A->getSpelling() << Arg; + } + // Currently there's no support emitting CFG instrumentation; the flag only + // emits the table of address-taken functions. + if (Instrument || NoChecks) + CmdArgs.push_back("-cfguard"); + } } visualstudio::Compiler *Clang::getCLFallback() const { @@ -5525,10 +6032,12 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - if (Args.hasArg(options::OPT_gsplit_dwarf) && - getToolChain().getTriple().isOSLinux()) { + const llvm::Triple &T = getToolChain().getTriple(); + Arg *A; + if ((getDebugFissionKind(D, Args, A) == DwarfFissionKind::Split) && + (T.isOSLinux() || T.isOSFuchsia())) { CmdArgs.push_back("-split-dwarf-file"); - CmdArgs.push_back(SplitDebugName(Args, Input)); + CmdArgs.push_back(SplitDebugName(Args, Output)); } assert(Input.isFilename() && "Invalid input."); diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp index 1e093b25b909..d7e316befa61 100644 --- a/lib/Driver/ToolChains/CommonArgs.cpp +++ b/lib/Driver/ToolChains/CommonArgs.cpp @@ -14,13 +14,13 @@ #include "Arch/PPC.h" #include "Arch/SystemZ.h" #include "Arch/X86.h" +#include "HIP.h" #include "Hexagon.h" #include "InputInfo.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Version.h" -#include "clang/Basic/VirtualFileSystem.h" #include "clang/Config/config.h" #include "clang/Driver/Action.h" #include "clang/Driver/Compilation.h" @@ -51,6 +51,7 @@ #include "llvm/Support/Program.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/TargetParser.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/YAMLParser.h" using namespace clang::driver; @@ -219,21 +220,6 @@ static std::string getR600TargetGPU(const ArgList &Args) { return ""; } -static std::string getNios2TargetCPU(const ArgList &Args) { - Arg *A = Args.getLastArg(options::OPT_mcpu_EQ); - if (!A) - A = Args.getLastArg(options::OPT_march_EQ); - - if (!A) - return ""; - - const char *name = A->getValue(); - return llvm::StringSwitch<const char *>(name) - .Case("r1", "nios2r1") - .Case("r2", "nios2r2") - .Default(name); -} - static std::string getLanaiTargetCPU(const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { return A->getValue(); @@ -270,7 +256,7 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T, case llvm::Triple::aarch64: case llvm::Triple::aarch64_be: - return aarch64::getAArch64TargetCPU(Args, A); + return aarch64::getAArch64TargetCPU(Args, T, A); case llvm::Triple::arm: case llvm::Triple::armeb: @@ -286,10 +272,6 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T, return A->getValue(); return ""; - case llvm::Triple::nios2: { - return getNios2TargetCPU(Args); - } - case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::mips64: @@ -559,6 +541,40 @@ static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args, return false; } +static void addSanitizerLibPath(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs, StringRef Name) { + for (const auto &LibPath : TC.getLibraryPaths()) { + if (!LibPath.empty()) { + SmallString<128> P(LibPath); + llvm::sys::path::append(P, Name); + if (TC.getVFS().exists(P)) + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + P)); + } + } +} + +void tools::addSanitizerPathLibArgs(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { + const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); + if (SanArgs.needsAsanRt()) { + addSanitizerLibPath(TC, Args, CmdArgs, "asan"); + } + if (SanArgs.needsHwasanRt()) { + addSanitizerLibPath(TC, Args, CmdArgs, "hwasan"); + } + if (SanArgs.needsLsanRt()) { + addSanitizerLibPath(TC, Args, CmdArgs, "lsan"); + } + if (SanArgs.needsMsanRt()) { + addSanitizerLibPath(TC, Args, CmdArgs, "msan"); + } + if (SanArgs.needsTsanRt()) { + addSanitizerLibPath(TC, Args, CmdArgs, "tsan"); + } +} + + + void tools::linkSanitizerRuntimeDeps(const ToolChain &TC, ArgStringList &CmdArgs) { // Force linking against the system libraries sanitizers depends on @@ -568,19 +584,19 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC, if (TC.getTriple().getOS() != llvm::Triple::RTEMS && !TC.getTriple().isAndroid()) { CmdArgs.push_back("-lpthread"); - if (TC.getTriple().getOS() != llvm::Triple::OpenBSD) + if (!TC.getTriple().isOSOpenBSD()) CmdArgs.push_back("-lrt"); } CmdArgs.push_back("-lm"); // There's no libdl on all OSes. - if (TC.getTriple().getOS() != llvm::Triple::FreeBSD && - TC.getTriple().getOS() != llvm::Triple::NetBSD && - TC.getTriple().getOS() != llvm::Triple::OpenBSD && - TC.getTriple().getOS() != llvm::Triple::RTEMS) + if (!TC.getTriple().isOSFreeBSD() && + !TC.getTriple().isOSNetBSD() && + !TC.getTriple().isOSOpenBSD() && + TC.getTriple().getOS() != llvm::Triple::RTEMS) CmdArgs.push_back("-ldl"); // Required for backtrace on some OSes - if (TC.getTriple().getOS() == llvm::Triple::NetBSD || - TC.getTriple().getOS() == llvm::Triple::FreeBSD) + if (TC.getTriple().isOSFreeBSD() || + TC.getTriple().isOSNetBSD()) CmdArgs.push_back("-lexecinfo"); } @@ -755,13 +771,13 @@ bool tools::addXRayRuntime(const ToolChain&TC, const ArgList &Args, ArgStringLis void tools::linkXRayRuntimeDeps(const ToolChain &TC, ArgStringList &CmdArgs) { CmdArgs.push_back("--no-as-needed"); CmdArgs.push_back("-lpthread"); - if (TC.getTriple().getOS() != llvm::Triple::OpenBSD) + if (!TC.getTriple().isOSOpenBSD()) CmdArgs.push_back("-lrt"); CmdArgs.push_back("-lm"); - if (TC.getTriple().getOS() != llvm::Triple::FreeBSD && - TC.getTriple().getOS() != llvm::Triple::NetBSD && - TC.getTriple().getOS() != llvm::Triple::OpenBSD) + if (!TC.getTriple().isOSFreeBSD() && + !TC.getTriple().isOSNetBSD() && + !TC.getTriple().isOSOpenBSD()) CmdArgs.push_back("-ldl"); } @@ -773,21 +789,18 @@ bool tools::areOptimizationsEnabled(const ArgList &Args) { return false; } -const char *tools::SplitDebugName(const ArgList &Args, const InputInfo &Input) { - Arg *FinalOutput = Args.getLastArg(options::OPT_o); - if (FinalOutput && Args.hasArg(options::OPT_c)) { - SmallString<128> T(FinalOutput->getValue()); - llvm::sys::path::replace_extension(T, "dwo"); - return Args.MakeArgString(T); - } else { - // Use the compilation dir. - SmallString<128> T( - Args.getLastArgValue(options::OPT_fdebug_compilation_dir)); - SmallString<128> F(llvm::sys::path::stem(Input.getBaseInput())); - llvm::sys::path::replace_extension(F, "dwo"); - T += F; - return Args.MakeArgString(F); - } +const char *tools::SplitDebugName(const ArgList &Args, + const InputInfo &Output) { + SmallString<128> F(Output.isFilename() + ? Output.getFilename() + : llvm::sys::path::stem(Output.getBaseInput())); + + if (Arg *A = Args.getLastArg(options::OPT_gsplit_dwarf_EQ)) + if (StringRef(A->getValue()) == "single") + return Args.MakeArgString(F); + + llvm::sys::path::replace_extension(F, "dwo"); + return Args.MakeArgString(F); } void tools::SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T, @@ -901,7 +914,7 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) { } // OpenBSD-specific defaults for PIE - if (Triple.getOS() == llvm::Triple::OpenBSD) { + if (Triple.isOSOpenBSD()) { switch (ToolChain.getArch()) { case llvm::Triple::arm: case llvm::Triple::aarch64: @@ -1126,23 +1139,39 @@ static void AddLibgcc(const llvm::Triple &Triple, const Driver &D, bool IsIAMCU = Triple.isOSIAMCU(); bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) || Args.hasArg(options::OPT_static); - if (!D.CCCIsCXX()) + + bool SharedLibgcc = Args.hasArg(options::OPT_shared_libgcc); + bool UnspecifiedLibgcc = !StaticLibgcc && !SharedLibgcc; + + // Gcc adds libgcc arguments in various ways: + // + // gcc <none>: -lgcc --as-needed -lgcc_s --no-as-needed + // g++ <none>: -lgcc_s -lgcc + // gcc shared: -lgcc_s -lgcc + // g++ shared: -lgcc_s -lgcc + // gcc static: -lgcc -lgcc_eh + // g++ static: -lgcc -lgcc_eh + // + // Also, certain targets need additional adjustments. + + bool LibGccFirst = (D.CCCIsCC() && UnspecifiedLibgcc) || StaticLibgcc; + if (LibGccFirst) CmdArgs.push_back("-lgcc"); - if (StaticLibgcc || isAndroid) { - if (D.CCCIsCXX()) - CmdArgs.push_back("-lgcc"); - } else { - if (!D.CCCIsCXX() && !isCygMing) - CmdArgs.push_back("--as-needed"); + bool AsNeeded = D.CCCIsCC() && UnspecifiedLibgcc && !isAndroid && !isCygMing; + if (AsNeeded) + CmdArgs.push_back("--as-needed"); + + if ((UnspecifiedLibgcc || SharedLibgcc) && !isAndroid) CmdArgs.push_back("-lgcc_s"); - if (!D.CCCIsCXX() && !isCygMing) - CmdArgs.push_back("--no-as-needed"); - } - if (StaticLibgcc && !isAndroid && !IsIAMCU) + else if (StaticLibgcc && !isAndroid && !IsIAMCU) CmdArgs.push_back("-lgcc_eh"); - else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX()) + + if (AsNeeded) + CmdArgs.push_back("--no-as-needed"); + + if (!LibGccFirst) CmdArgs.push_back("-lgcc"); // According to Android ABI, we have to link with libdl if we are @@ -1318,6 +1347,18 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C, if (!JA.isHostOffloading(Action::OFK_HIP)) return; + InputInfoList DeviceInputs; + for (const auto &II : Inputs) { + const Action *A = II.getAction(); + // Is this a device linking action? + if (A && isa<LinkJobAction>(A) && A->isDeviceOffloading(Action::OFK_HIP)) { + DeviceInputs.push_back(II); + } + } + + if (DeviceInputs.empty()) + return; + // Create temporary linker script. Keep it if save-temps is enabled. const char *LKS; SmallString<256> Name = llvm::sys::path::filename(Output.getFilename()); @@ -1345,39 +1386,12 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C, "Wrong platform"); (void)HIPTC; - // Construct clang-offload-bundler command to bundle object files for - // for different GPU archs. - ArgStringList BundlerArgs; - BundlerArgs.push_back(Args.MakeArgString("-type=o")); - - // ToDo: Remove the dummy host binary entry which is required by - // clang-offload-bundler. - std::string BundlerTargetArg = "-targets=host-x86_64-unknown-linux"; - std::string BundlerInputArg = "-inputs=/dev/null"; - - for (const auto &II : Inputs) { - const Action *A = II.getAction(); - // Is this a device linking action? - if (A && isa<LinkJobAction>(A) && A->isDeviceOffloading(Action::OFK_HIP)) { - BundlerTargetArg = BundlerTargetArg + ",hip-amdgcn-amd-amdhsa-" + - StringRef(A->getOffloadingArch()).str(); - BundlerInputArg = BundlerInputArg + "," + II.getFilename(); - } - } - BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg)); - BundlerArgs.push_back(Args.MakeArgString(BundlerInputArg)); - - std::string BundleFileName = C.getDriver().GetTemporaryPath("BUNDLE", "o"); + // The output file name needs to persist through the compilation, therefore + // it needs to be created through MakeArgString. + std::string BundleFileName = C.getDriver().GetTemporaryPath("BUNDLE", "hipfb"); const char *BundleFile = C.addTempFile(C.getArgs().MakeArgString(BundleFileName.c_str())); - auto BundlerOutputArg = - Args.MakeArgString(std::string("-outputs=").append(BundleFile)); - BundlerArgs.push_back(BundlerOutputArg); - - SmallString<128> BundlerPath(C.getDriver().Dir); - llvm::sys::path::append(BundlerPath, "clang-offload-bundler"); - const char *Bundler = Args.MakeArgString(BundlerPath); - C.addCommand(llvm::make_unique<Command>(JA, T, Bundler, BundlerArgs, Inputs)); + AMDGCN::constructHIPFatbinCommand(C, JA, BundleFile, DeviceInputs, Args, T); // Add commands to embed target binaries. We ensure that each section and // image is 16-byte aligned. This is not mandatory, but increases the @@ -1397,6 +1411,10 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C, LksStream << " PROVIDE_HIDDEN(__hip_fatbin = .);\n"; LksStream << " " << BundleFileName << "\n"; LksStream << " }\n"; + LksStream << " /DISCARD/ :\n"; + LksStream << " {\n"; + LksStream << " * ( __CLANG_OFFLOAD_BUNDLE__* )\n"; + LksStream << " }\n"; LksStream << "}\n"; LksStream << "INSERT BEFORE .data\n"; LksStream.flush(); diff --git a/lib/Driver/ToolChains/CommonArgs.h b/lib/Driver/ToolChains/CommonArgs.h index e8ebe2225e1c..3704b2e01b54 100644 --- a/lib/Driver/ToolChains/CommonArgs.h +++ b/lib/Driver/ToolChains/CommonArgs.h @@ -32,6 +32,10 @@ void claimNoWarnArgs(const llvm::opt::ArgList &Args); bool addSanitizerRuntimes(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs); +void addSanitizerPathLibArgs(const ToolChain &TC, + const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs); + void linkSanitizerRuntimeDeps(const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs); @@ -59,7 +63,7 @@ void AddHIPLinkerScript(const ToolChain &TC, Compilation &C, const Tool &T); const char *SplitDebugName(const llvm::opt::ArgList &Args, - const InputInfo &Input); + const InputInfo &Output); void SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T, const JobAction &JA, const llvm::opt::ArgList &Args, diff --git a/lib/Driver/ToolChains/CrossWindows.cpp b/lib/Driver/ToolChains/CrossWindows.cpp index 6ca04a8a3abb..795356026fbe 100644 --- a/lib/Driver/ToolChains/CrossWindows.cpp +++ b/lib/Driver/ToolChains/CrossWindows.cpp @@ -20,6 +20,7 @@ using namespace clang::driver; using namespace clang::driver::toolchains; using llvm::opt::ArgList; +using llvm::opt::ArgStringList; void tools::CrossWindows::Assembler::ConstructJob( Compilation &C, const JobAction &JA, const InputInfo &Output, diff --git a/lib/Driver/ToolChains/Cuda.cpp b/lib/Driver/ToolChains/Cuda.cpp index 7fb4ae4ea9cf..57b8d4340e3b 100644 --- a/lib/Driver/ToolChains/Cuda.cpp +++ b/lib/Driver/ToolChains/Cuda.cpp @@ -11,7 +11,6 @@ #include "CommonArgs.h" #include "InputInfo.h" #include "clang/Basic/Cuda.h" -#include "clang/Basic/VirtualFileSystem.h" #include "clang/Config/config.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Distro.h" @@ -23,6 +22,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" +#include "llvm/Support/VirtualFileSystem.h" #include <system_error> using namespace clang::driver; @@ -59,6 +59,8 @@ static CudaVersion ParseCudaVersionFile(llvm::StringRef V) { return CudaVersion::CUDA_91; if (Major == 9 && Minor == 2) return CudaVersion::CUDA_92; + if (Major == 10 && Minor == 0) + return CudaVersion::CUDA_100; return CudaVersion::UNKNOWN; } @@ -112,7 +114,7 @@ CudaInstallationDetector::CudaInstallationDetector( for (const char *Ver : Versions) Candidates.emplace_back(D.SysRoot + "/usr/local/cuda-" + Ver); - if (Distro(D.getVFS()).IsDebian()) + if (Distro(D.getVFS()).IsDebian() || Distro(D.getVFS()).IsUbuntu()) // Special case for Debian to have nvidia-cuda-toolkit work // out of the box. More info on http://bugs.debian.org/882505 Candidates.emplace_back(D.SysRoot + "/usr/lib/cuda"); @@ -165,7 +167,7 @@ CudaInstallationDetector::CudaInstallationDetector( if (FS.exists(FilePath)) { for (const char *GpuArchName : {"sm_30", "sm_32", "sm_35", "sm_37", "sm_50", "sm_52", "sm_53", - "sm_60", "sm_61", "sm_62", "sm_70", "sm_72"}) { + "sm_60", "sm_61", "sm_62", "sm_70", "sm_72", "sm_75"}) { const CudaArch GpuArch = StringToCudaArch(GpuArchName); if (Version >= MinVersionForCudaArch(GpuArch) && Version <= MaxVersionForCudaArch(GpuArch)) @@ -276,32 +278,44 @@ void CudaInstallationDetector::print(raw_ostream &OS) const { } namespace { - /// Debug info kind. -enum DebugInfoKind { - NoDebug, /// No debug info. - LineTableOnly, /// Line tables only. - FullDebug /// Full debug info. +/// Debug info level for the NVPTX devices. We may need to emit different debug +/// info level for the host and for the device itselfi. This type controls +/// emission of the debug info for the devices. It either prohibits disable info +/// emission completely, or emits debug directives only, or emits same debug +/// info as for the host. +enum DeviceDebugInfoLevel { + DisableDebugInfo, /// Do not emit debug info for the devices. + DebugDirectivesOnly, /// Emit only debug directives. + EmitSameDebugInfoAsHost, /// Use the same debug info level just like for the + /// host. }; } // anonymous namespace -static DebugInfoKind mustEmitDebugInfo(const ArgList &Args) { - Arg *A = Args.getLastArg(options::OPT_O_Group); - if (Args.hasFlag(options::OPT_cuda_noopt_device_debug, - options::OPT_no_cuda_noopt_device_debug, - !A || A->getOption().matches(options::OPT_O0))) { - if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) { - const Option &Opt = A->getOption(); - if (Opt.matches(options::OPT_gN_Group)) { - if (Opt.matches(options::OPT_g0) || Opt.matches(options::OPT_ggdb0)) - return NoDebug; - if (Opt.matches(options::OPT_gline_tables_only) || - Opt.matches(options::OPT_ggdb1)) - return LineTableOnly; - } - return FullDebug; +/// Define debug info level for the NVPTX devices. If the debug info for both +/// the host and device are disabled (-g0/-ggdb0 or no debug options at all). If +/// only debug directives are requested for the both host and device +/// (-gline-directvies-only), or the debug info only for the device is disabled +/// (optimization is on and --cuda-noopt-device-debug was not specified), the +/// debug directves only must be emitted for the device. Otherwise, use the same +/// debug info level just like for the host (with the limitations of only +/// supported DWARF2 standard). +static DeviceDebugInfoLevel mustEmitDebugInfo(const ArgList &Args) { + const Arg *A = Args.getLastArg(options::OPT_O_Group); + bool IsDebugEnabled = !A || A->getOption().matches(options::OPT_O0) || + Args.hasFlag(options::OPT_cuda_noopt_device_debug, + options::OPT_no_cuda_noopt_device_debug, + /*Default=*/false); + if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) { + const Option &Opt = A->getOption(); + if (Opt.matches(options::OPT_gN_Group)) { + if (Opt.matches(options::OPT_g0) || Opt.matches(options::OPT_ggdb0)) + return DisableDebugInfo; + if (Opt.matches(options::OPT_gline_directives_only)) + return DebugDirectivesOnly; } + return IsDebugEnabled ? EmitSameDebugInfoAsHost : DebugDirectivesOnly; } - return NoDebug; + return DisableDebugInfo; } void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA, @@ -335,8 +349,8 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA, ArgStringList CmdArgs; CmdArgs.push_back(TC.getTriple().isArch64Bit() ? "-m64" : "-m32"); - DebugInfoKind DIKind = mustEmitDebugInfo(Args); - if (DIKind == FullDebug) { + DeviceDebugInfoLevel DIKind = mustEmitDebugInfo(Args); + if (DIKind == EmitSameDebugInfoAsHost) { // ptxas does not accept -g option if optimization is enabled, so // we ignore the compiler's -O* options if we want debug info. CmdArgs.push_back("-g"); @@ -372,7 +386,7 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA, // to no optimizations, but ptxas's default is -O3. CmdArgs.push_back("-O0"); } - if (DIKind == LineTableOnly) + if (DIKind == DebugDirectivesOnly) CmdArgs.push_back("-lineinfo"); // Pass -v to ptxas if it was passed to the driver. @@ -396,8 +410,8 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fnoopenmp_relocatable_target, /*Default=*/true); else if (JA.isOffloading(Action::OFK_Cuda)) - Relocatable = Args.hasFlag(options::OPT_fcuda_rdc, - options::OPT_fno_cuda_rdc, /*Default=*/false); + Relocatable = Args.hasFlag(options::OPT_fgpu_rdc, + options::OPT_fno_gpu_rdc, /*Default=*/false); if (Relocatable) CmdArgs.push_back("-c"); @@ -443,7 +457,7 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(TC.getTriple().isArch64Bit() ? "-64" : "-32"); CmdArgs.push_back(Args.MakeArgString("--create")); CmdArgs.push_back(Args.MakeArgString(Output.getFilename())); - if (mustEmitDebugInfo(Args) == FullDebug) + if (mustEmitDebugInfo(Args) == EmitSameDebugInfoAsHost) CmdArgs.push_back("-g"); for (const auto& II : Inputs) { @@ -496,7 +510,7 @@ void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Output.getFilename()); } else assert(Output.isNothing() && "Invalid output."); - if (mustEmitDebugInfo(Args) == FullDebug) + if (mustEmitDebugInfo(Args) == EmitSameDebugInfoAsHost) CmdArgs.push_back("-g"); if (Args.hasArg(options::OPT_v)) @@ -509,6 +523,11 @@ void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-arch"); CmdArgs.push_back(Args.MakeArgString(GPUArch)); + // Assume that the directory specified with --libomptarget_nvptx_path + // contains the static library libomptarget-nvptx.a. + if (const Arg *A = Args.getLastArg(options::OPT_libomptarget_nvptx_path_EQ)) + CmdArgs.push_back(Args.MakeArgString(Twine("-L") + A->getValue())); + // Add paths specified in LIBRARY_PATH environment variable as -L options. addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); @@ -602,9 +621,9 @@ void CudaToolChain::addClangTargetOptions( options::OPT_fno_cuda_approx_transcendentals, false)) CC1Args.push_back("-fcuda-approx-transcendentals"); - if (DriverArgs.hasFlag(options::OPT_fcuda_rdc, options::OPT_fno_cuda_rdc, + if (DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false)) - CC1Args.push_back("-fcuda-rdc"); + CC1Args.push_back("-fgpu-rdc"); } if (DriverArgs.hasArg(options::OPT_nocudalib)) @@ -621,13 +640,16 @@ void CudaToolChain::addClangTargetOptions( return; } - CC1Args.push_back("-mlink-cuda-bitcode"); + CC1Args.push_back("-mlink-builtin-bitcode"); CC1Args.push_back(DriverArgs.MakeArgString(LibDeviceFile)); // Libdevice in CUDA-7.0 requires PTX version that's more recent than LLVM // defaults to. Use PTX4.2 by default, which is the PTX version that came with // CUDA-7.0. const char *PtxFeature = "+ptx42"; + // TODO(tra): CUDA-10+ needs PTX 6.3 to support new features. However that + // requires fair amount of work on LLVM side. We'll keep using PTX 6.1 until + // all prerequisites are in place. if (CudaInstallation.version() >= CudaVersion::CUDA_91) { // CUDA-9.1 uses new instructions that are only available in PTX6.1+ PtxFeature = "+ptx61"; @@ -642,12 +664,9 @@ void CudaToolChain::addClangTargetOptions( if (DeviceOffloadingKind == Action::OFK_OpenMP) { SmallVector<StringRef, 8> LibraryPaths; - // Add path to lib and/or lib64 folders. - SmallString<256> DefaultLibPath = - llvm::sys::path::parent_path(getDriver().Dir); - llvm::sys::path::append(DefaultLibPath, - Twine("lib") + CLANG_LIBDIR_SUFFIX); - LibraryPaths.emplace_back(DefaultLibPath.c_str()); + + if (const Arg *A = DriverArgs.getLastArg(options::OPT_libomptarget_nvptx_path_EQ)) + LibraryPaths.push_back(A->getValue()); // Add user defined library paths from LIBRARY_PATH. llvm::Optional<std::string> LibPath = @@ -660,6 +679,12 @@ void CudaToolChain::addClangTargetOptions( LibraryPaths.emplace_back(Path.trim()); } + // Add path to lib / lib64 folder. + SmallString<256> DefaultLibPath = + llvm::sys::path::parent_path(getDriver().Dir); + llvm::sys::path::append(DefaultLibPath, Twine("lib") + CLANG_LIBDIR_SUFFIX); + LibraryPaths.emplace_back(DefaultLibPath.c_str()); + std::string LibOmpTargetName = "libomptarget-nvptx-" + GpuArch.str() + ".bc"; bool FoundBCLibrary = false; @@ -667,7 +692,7 @@ void CudaToolChain::addClangTargetOptions( SmallString<128> LibOmpTargetFile(LibraryPath); llvm::sys::path::append(LibOmpTargetFile, LibOmpTargetName); if (llvm::sys::fs::exists(LibOmpTargetFile)) { - CC1Args.push_back("-mlink-cuda-bitcode"); + CC1Args.push_back("-mlink-builtin-bitcode"); CC1Args.push_back(DriverArgs.MakeArgString(LibOmpTargetFile)); FoundBCLibrary = true; break; @@ -691,6 +716,21 @@ bool CudaToolChain::supportsDebugInfoOption(const llvm::opt::Arg *A) const { O.matches(options::OPT_gcolumn_info); } +void CudaToolChain::adjustDebugInfoKind( + codegenoptions::DebugInfoKind &DebugInfoKind, const ArgList &Args) const { + switch (mustEmitDebugInfo(Args)) { + case DisableDebugInfo: + DebugInfoKind = codegenoptions::NoDebugInfo; + break; + case DebugDirectivesOnly: + DebugInfoKind = codegenoptions::DebugDirectivesOnly; + break; + case EmitSameDebugInfoAsHost: + // Use same debug info level as the host. + break; + } +} + void CudaToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { // Check our CUDA version if we're going to include the CUDA headers. diff --git a/lib/Driver/ToolChains/Cuda.h b/lib/Driver/ToolChains/Cuda.h index 01580cb66920..1d63ede41155 100644 --- a/lib/Driver/ToolChains/Cuda.h +++ b/lib/Driver/ToolChains/Cuda.h @@ -159,6 +159,8 @@ public: bool isPICDefaultForced() const override { return false; } bool SupportsProfiling() const override { return false; } bool supportsDebugInfoOption(const llvm::opt::Arg *A) const override; + void adjustDebugInfoKind(codegenoptions::DebugInfoKind &DebugInfoKind, + const llvm::opt::ArgList &Args) const override; bool IsMathErrnoDefault() const override { return false; } void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, diff --git a/lib/Driver/ToolChains/Darwin.cpp b/lib/Driver/ToolChains/Darwin.cpp index 9205dd52de0b..c395c9a4430e 100644 --- a/lib/Driver/ToolChains/Darwin.cpp +++ b/lib/Driver/ToolChains/Darwin.cpp @@ -12,7 +12,6 @@ #include "CommonArgs.h" #include "clang/Basic/AlignedAllocation.h" #include "clang/Basic/ObjCRuntime.h" -#include "clang/Basic/VirtualFileSystem.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" @@ -23,6 +22,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/TargetParser.h" +#include "llvm/Support/VirtualFileSystem.h" #include <cstdlib> // ::getenv using namespace clang::driver; @@ -98,7 +98,7 @@ void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA, SourceAction = SourceAction->getInputs()[0]; } - // If -fno-integrated-as is used add -Q to the darwin assember driver to make + // If -fno-integrated-as is used add -Q to the darwin assembler driver to make // sure it runs its system assembler not clang's integrated assembler. // Applicable to darwin11+ and Xcode 4+. darwin<10 lacked integrated-as. // FIXME: at run-time detect assembler capabilities or rely on version @@ -224,13 +224,20 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args, options::OPT_fno_application_extension, false)) CmdArgs.push_back("-application_extension"); - if (D.isUsingLTO()) { - // 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 && NeedsTempPath(Inputs)) { - const char *TmpPath = C.getArgs().MakeArgString( - D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object))); + if (D.isUsingLTO() && Version[0] >= 116 && NeedsTempPath(Inputs)) { + std::string TmpPathName; + if (D.getLTOMode() == LTOK_Full) { + // If we are using full 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. + TmpPathName = + D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)); + } else if (D.getLTOMode() == LTOK_Thin) + // If we are using thin LTO, then create a directory instead. + TmpPathName = D.GetTemporaryDirectory("thinlto"); + + if (!TmpPathName.empty()) { + auto *TmpPath = C.getArgs().MakeArgString(TmpPathName); C.addTempFile(TmpPath); CmdArgs.push_back("-object_path_lto"); CmdArgs.push_back(TmpPath); @@ -509,15 +516,6 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs); - // SafeStack requires its own runtime libraries - // These libraries should be linked first, to make sure the - // __safestack_init constructor executes before everything else - if (getToolChain().getSanitizerArgs().needsSafeStackRt()) { - getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs, - "libclang_rt.safestack_osx.a", - toolchains::Darwin::RLO_AlwaysLink); - } - Args.AddAllArgs(CmdArgs, options::OPT_L); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); @@ -917,8 +915,19 @@ unsigned DarwinClang::GetDefaultDwarfVersion() const { } void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs, - StringRef DarwinLibName, - RuntimeLinkOptions Opts) const { + StringRef Component, RuntimeLinkOptions Opts, + bool IsShared) const { + SmallString<64> DarwinLibName = StringRef("libclang_rt."); + // an Darwin the builtins compomnent is not in the library name + if (Component != "builtins") { + DarwinLibName += Component; + if (!(Opts & RLO_IsEmbedded)) + DarwinLibName += "_"; + DarwinLibName += getOSLibraryNameSuffix(); + } else + DarwinLibName += getOSLibraryNameSuffix(true); + + DarwinLibName += IsShared ? "_dynamic.dylib" : ".a"; SmallString<128> Dir(getDriver().ResourceDir); llvm::sys::path::append( Dir, "lib", (Opts & RLO_IsEmbedded) ? "macho_embedded" : "darwin"); @@ -983,16 +992,19 @@ StringRef Darwin::getSDKName(StringRef isysroot) { return ""; } -StringRef Darwin::getOSLibraryNameSuffix() const { - switch(TargetPlatform) { +StringRef Darwin::getOSLibraryNameSuffix(bool IgnoreSim) const { + switch (TargetPlatform) { case DarwinPlatformKind::MacOS: return "osx"; case DarwinPlatformKind::IPhoneOS: - return TargetEnvironment == NativeEnvironment ? "ios" : "iossim"; + return TargetEnvironment == NativeEnvironment || IgnoreSim ? "ios" + : "iossim"; case DarwinPlatformKind::TvOS: - return TargetEnvironment == NativeEnvironment ? "tvos" : "tvossim"; + return TargetEnvironment == NativeEnvironment || IgnoreSim ? "tvos" + : "tvossim"; case DarwinPlatformKind::WatchOS: - return TargetEnvironment == NativeEnvironment ? "watchos" : "watchossim"; + return TargetEnvironment == NativeEnvironment || IgnoreSim ? "watchos" + : "watchossim"; } llvm_unreachable("Unsupported platform"); } @@ -1022,18 +1034,24 @@ void Darwin::addProfileRTLibs(const ArgList &Args, ArgStringList &CmdArgs) const { if (!needsProfileRT(Args)) return; - AddLinkRuntimeLib( - Args, CmdArgs, - (Twine("libclang_rt.profile_") + getOSLibraryNameSuffix() + ".a").str(), - RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink)); + AddLinkRuntimeLib(Args, CmdArgs, "profile", + RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink)); // If we have a symbol export directive and we're linking in the profile // runtime, automatically export symbols necessary to implement some of the // runtime's functionality. if (hasExportSymbolDirective(Args)) { - addExportedSymbol(CmdArgs, "___llvm_profile_filename"); - addExportedSymbol(CmdArgs, "___llvm_profile_raw_version"); - addExportedSymbol(CmdArgs, "_lprofCurFilename"); + if (needsGCovInstrumentation(Args)) { + addExportedSymbol(CmdArgs, "___gcov_flush"); + addExportedSymbol(CmdArgs, "_flush_fn_list"); + addExportedSymbol(CmdArgs, "_writeout_fn_list"); + } else { + addExportedSymbol(CmdArgs, "___llvm_profile_filename"); + addExportedSymbol(CmdArgs, "___llvm_profile_raw_version"); + addExportedSymbol(CmdArgs, "_lprofCurFilename"); + addExportedSymbol(CmdArgs, "_lprofMergeValueProfData"); + } + addExportedSymbol(CmdArgs, "_lprofDirMode"); } } @@ -1042,12 +1060,7 @@ void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args, StringRef Sanitizer, bool Shared) const { auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U)); - AddLinkRuntimeLib(Args, CmdArgs, - (Twine("libclang_rt.") + Sanitizer + "_" + - getOSLibraryNameSuffix() + - (Shared ? "_dynamic.dylib" : ".a")) - .str(), - RLO); + AddLinkRuntimeLib(Args, CmdArgs, Sanitizer, RLO, Shared); } ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType( @@ -1101,66 +1114,33 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, AddCXXStdlibLibArgs(Args, CmdArgs); } if (Sanitize.needsStatsRt()) { - StringRef OS = isTargetMacOS() ? "osx" : "iossim"; - AddLinkRuntimeLib(Args, CmdArgs, - (Twine("libclang_rt.stats_client_") + OS + ".a").str(), - RLO_AlwaysLink); + AddLinkRuntimeLib(Args, CmdArgs, "stats_client", RLO_AlwaysLink); AddLinkSanitizerLibArgs(Args, CmdArgs, "stats"); } if (Sanitize.needsEsanRt()) AddLinkSanitizerLibArgs(Args, CmdArgs, "esan"); + const XRayArgs &XRay = getXRayArgs(); + if (XRay.needsXRayRt()) { + AddLinkRuntimeLib(Args, CmdArgs, "xray"); + AddLinkRuntimeLib(Args, CmdArgs, "xray-basic"); + AddLinkRuntimeLib(Args, CmdArgs, "xray-fdr"); + } + // Otherwise link libSystem, then the dynamic runtime library, and finally any // target specific static runtime library. CmdArgs.push_back("-lSystem"); // Select the dynamic runtime library and the target specific static library. - if (isTargetWatchOSBased()) { - // We currently always need a static runtime library for watchOS. - AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.watchos.a"); - } else if (isTargetTvOSBased()) { - // We currently always need a static runtime library for tvOS. - AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.tvos.a"); - } else if (isTargetIOSBased()) { + if (isTargetIOSBased()) { // If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1, // it never went into the SDK. // Linking against libgcc_s.1 isn't needed for iOS 5.0+ if (isIPhoneOSVersionLT(5, 0) && !isTargetIOSSimulator() && getTriple().getArch() != llvm::Triple::aarch64) CmdArgs.push_back("-lgcc_s.1"); - - // We currently always need a static runtime library for iOS. - AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.ios.a"); - } else { - assert(isTargetMacOS() && "unexpected non MacOS platform"); - // The dynamic runtime library was merged with libSystem for 10.6 and - // beyond; only 10.4 and 10.5 need an additional runtime library. - if (isMacosxVersionLT(10, 5)) - CmdArgs.push_back("-lgcc_s.10.4"); - else if (isMacosxVersionLT(10, 6)) - CmdArgs.push_back("-lgcc_s.10.5"); - - // Originally for OS X, we thought we would only need a static runtime - // library when targeting 10.4, to provide versions of the static functions - // which were omitted from 10.4.dylib. This led to the creation of the 10.4 - // builtins library. - // - // Unfortunately, that turned out to not be true, because Darwin system - // headers can still use eprintf on i386, and it is not exported from - // libSystem. Therefore, we still must provide a runtime library just for - // the tiny tiny handful of projects that *might* use that symbol. - // - // Then over time, we figured out it was useful to add more things to the - // runtime so we created libclang_rt.osx.a to provide new functions when - // deploying to old OS builds, and for a long time we had both eprintf and - // osx builtin libraries. Which just seems excessive. So with PR 28855, we - // are removing the eprintf library and expecting eprintf to be provided by - // the OS X builtins library. - if (isMacosxVersionLT(10, 5)) - AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.10.4.a"); - else - AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.osx.a"); } + AddLinkRuntimeLib(Args, CmdArgs, "builtins"); } /// Returns the most appropriate macOS target version for the current process. @@ -1314,6 +1294,18 @@ struct DarwinPlatform { return DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Value); } + /// Constructs an inferred SDKInfo value based on the version inferred from + /// the SDK path itself. Only works for values that were created by inferring + /// the platform from the SDKPath. + DarwinSDKInfo inferSDKInfo() { + assert(Kind == InferredFromSDK && "can infer SDK info only"); + llvm::VersionTuple Version; + bool IsValid = !Version.tryParse(OSVersion); + (void)IsValid; + assert(IsValid && "invalid SDK version"); + return DarwinSDKInfo(Version); + } + private: DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument) : Kind(Kind), Platform(Platform), Argument(Argument) {} @@ -1447,8 +1439,11 @@ getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver, } /// Tries to infer the deployment target from the SDK specified by -isysroot -/// (or SDKROOT). -Optional<DarwinPlatform> inferDeploymentTargetFromSDK(DerivedArgList &Args) { +/// (or SDKROOT). Uses the version specified in the SDKSettings.json file if +/// it's available. +Optional<DarwinPlatform> +inferDeploymentTargetFromSDK(DerivedArgList &Args, + const Optional<DarwinSDKInfo> &SDKInfo) { const Arg *A = Args.getLastArg(options::OPT_isysroot); if (!A) return None; @@ -1456,28 +1451,37 @@ Optional<DarwinPlatform> inferDeploymentTargetFromSDK(DerivedArgList &Args) { StringRef SDK = Darwin::getSDKName(isysroot); if (!SDK.size()) return None; - // Slice the version number out. - // Version number is between the first and the last number. - size_t StartVer = SDK.find_first_of("0123456789"); - size_t EndVer = SDK.find_last_of("0123456789"); - if (StartVer != StringRef::npos && EndVer > StartVer) { - StringRef Version = SDK.slice(StartVer, EndVer + 1); - if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator")) - return DarwinPlatform::createFromSDK( - Darwin::IPhoneOS, Version, - /*IsSimulator=*/SDK.startswith("iPhoneSimulator")); - else if (SDK.startswith("MacOSX")) - return DarwinPlatform::createFromSDK(Darwin::MacOS, - getSystemOrSDKMacOSVersion(Version)); - else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator")) - return DarwinPlatform::createFromSDK( - Darwin::WatchOS, Version, - /*IsSimulator=*/SDK.startswith("WatchSimulator")); - else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator")) - return DarwinPlatform::createFromSDK( - Darwin::TvOS, Version, - /*IsSimulator=*/SDK.startswith("AppleTVSimulator")); - } + + std::string Version; + if (SDKInfo) { + // Get the version from the SDKSettings.json if it's available. + Version = SDKInfo->getVersion().getAsString(); + } else { + // Slice the version number out. + // Version number is between the first and the last number. + size_t StartVer = SDK.find_first_of("0123456789"); + size_t EndVer = SDK.find_last_of("0123456789"); + if (StartVer != StringRef::npos && EndVer > StartVer) + Version = SDK.slice(StartVer, EndVer + 1); + } + if (Version.empty()) + return None; + + if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator")) + return DarwinPlatform::createFromSDK( + Darwin::IPhoneOS, Version, + /*IsSimulator=*/SDK.startswith("iPhoneSimulator")); + else if (SDK.startswith("MacOSX")) + return DarwinPlatform::createFromSDK(Darwin::MacOS, + getSystemOrSDKMacOSVersion(Version)); + else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator")) + return DarwinPlatform::createFromSDK( + Darwin::WatchOS, Version, + /*IsSimulator=*/SDK.startswith("WatchSimulator")); + else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator")) + return DarwinPlatform::createFromSDK( + Darwin::TvOS, Version, + /*IsSimulator=*/SDK.startswith("AppleTVSimulator")); return None; } @@ -1552,6 +1556,22 @@ Optional<DarwinPlatform> getDeploymentTargetFromTargetArg( Args.getLastArg(options::OPT_target)); } +Optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS, + const ArgList &Args, + const Driver &TheDriver) { + const Arg *A = Args.getLastArg(options::OPT_isysroot); + if (!A) + return None; + StringRef isysroot = A->getValue(); + auto SDKInfoOrErr = driver::parseDarwinSDKInfo(VFS, isysroot); + if (!SDKInfoOrErr) { + llvm::consumeError(SDKInfoOrErr.takeError()); + TheDriver.Diag(diag::warn_drv_darwin_sdk_invalid_settings); + return None; + } + return *SDKInfoOrErr; +} + } // namespace void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { @@ -1576,6 +1596,10 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { } } + // Read the SDKSettings.json file for more information, like the SDK version + // that we can pass down to the compiler. + SDKInfo = parseSDKSettings(getVFS(), Args, getDriver()); + // The OS and the version can be specified using the -target argument. Optional<DarwinPlatform> OSTarget = getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver()); @@ -1621,16 +1645,22 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple()); if (OSTarget) { // Don't infer simulator from the arch when the SDK is also specified. - Optional<DarwinPlatform> SDKTarget = inferDeploymentTargetFromSDK(Args); + Optional<DarwinPlatform> SDKTarget = + inferDeploymentTargetFromSDK(Args, SDKInfo); if (SDKTarget) OSTarget->setEnvironment(SDKTarget->getEnvironment()); } } // If there is no command-line argument to specify the Target version and // no environment variable defined, see if we can set the default based - // on -isysroot. - if (!OSTarget) - OSTarget = inferDeploymentTargetFromSDK(Args); + // on -isysroot using SDKSettings.json if it exists. + if (!OSTarget) { + OSTarget = inferDeploymentTargetFromSDK(Args, SDKInfo); + /// If the target was successfully constructed from the SDK path, try to + /// infer the SDK info if the SDK doesn't have it. + if (OSTarget && !SDKInfo) + SDKInfo = OSTarget->inferSDKInfo(); + } // If no OS targets have been specified, try to guess platform from -target // or arch name and compute the version from the triple. if (!OSTarget) @@ -1709,6 +1739,39 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { } } +void DarwinClang::AddClangCXXStdlibIncludeArgs( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + // The implementation from a base class will pass through the -stdlib to + // CC1Args. + // FIXME: this should not be necessary, remove usages in the frontend + // (e.g. HeaderSearchOptions::UseLibcxx) and don't pipe -stdlib. + ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args); + + if (DriverArgs.hasArg(options::OPT_nostdlibinc) || + DriverArgs.hasArg(options::OPT_nostdincxx)) + return; + + switch (GetCXXStdlibType(DriverArgs)) { + case ToolChain::CST_Libcxx: { + llvm::StringRef InstallDir = getDriver().getInstalledDir(); + if (InstallDir.empty()) + break; + // On Darwin, libc++ may be installed alongside the compiler in + // include/c++/v1. + // Get from 'foo/bin' to 'foo/include/c++/v1'. + SmallString<128> P = InstallDir; + // Note that InstallDir can be relative, so we have to '..' and not + // parent_path. + llvm::sys::path::append(P, "..", "include", "c++", "v1"); + addSystemInclude(DriverArgs, CC1Args, P); + break; + } + case ToolChain::CST_Libstdcxx: + // FIXME: should we do something about it? + break; + } +} void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args, ArgStringList &CmdArgs) const { CXXStdlibType Type = GetCXXStdlibType(Args); @@ -1962,12 +2025,8 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args, else if (Name == "pentIIm3") DAL->AddJoinedArg(nullptr, MArch, "pentium2"); - else if (Name == "x86_64") - DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64)); - else if (Name == "x86_64h") { + else if (Name == "x86_64" || Name == "x86_64h") DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64)); - DAL->AddJoinedArg(nullptr, MArch, "x86_64h"); - } else if (Name == "arm") DAL->AddJoinedArg(nullptr, MArch, "armv4t"); @@ -2001,12 +2060,12 @@ void MachO::AddLinkRuntimeLibArgs(const ArgList &Args, // Embedded targets are simple at the moment, not supporting sanitizers and // with different libraries for each member of the product { static, PIC } x // { hard-float, soft-float } - llvm::SmallString<32> CompilerRT = StringRef("libclang_rt."); + llvm::SmallString<32> CompilerRT = StringRef(""); CompilerRT += (tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard) ? "hard" : "soft"; - CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic.a" : "_static.a"; + CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic" : "_static"; AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, RLO_IsEmbedded); } @@ -2035,8 +2094,21 @@ bool Darwin::isAlignedAllocationUnavailable() const { void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind DeviceOffloadKind) const { - if (isAlignedAllocationUnavailable()) + // Pass "-faligned-alloc-unavailable" only when the user hasn't manually + // enabled or disabled aligned allocations. + if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation, + options::OPT_fno_aligned_allocation) && + isAlignedAllocationUnavailable()) CC1Args.push_back("-faligned-alloc-unavailable"); + + if (SDKInfo) { + /// Pass the SDK version to the compiler when the SDK information is + /// available. + std::string Arg; + llvm::raw_string_ostream OS(Arg); + OS << "-target-sdk-version=" << SDKInfo->getVersion(); + CC1Args.push_back(DriverArgs.MakeArgString(OS.str())); + } } DerivedArgList * @@ -2131,7 +2203,7 @@ llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const { // Only watchOS uses the new DWARF/Compact unwinding method. llvm::Triple Triple(ComputeLLVMTriple(Args)); - if(Triple.isWatchABI()) + if (Triple.isWatchABI()) return llvm::ExceptionHandling::DwarfCFI; return llvm::ExceptionHandling::SjLj; @@ -2268,8 +2340,7 @@ void Darwin::addStartObjectFileArgs(const ArgList &Args, } if (!isTargetIPhoneOS() && Args.hasArg(options::OPT_shared_libgcc) && - !isTargetWatchOS() && - isMacosxVersionLT(10, 5)) { + !isTargetWatchOS() && isMacosxVersionLT(10, 5)) { const char *Str = Args.MakeArgString(GetFilePath("crt3.o")); CmdArgs.push_back(Str); } @@ -2290,10 +2361,15 @@ SanitizerMask Darwin::getSupportedSanitizers() const { Res |= SanitizerKind::Fuzzer; Res |= SanitizerKind::FuzzerNoLink; Res |= SanitizerKind::Function; + + // Prior to 10.9, macOS shipped a version of the C++ standard library without + // C++11 support. The same is true of iOS prior to version 5. These OS'es are + // incompatible with -fsanitize=vptr. + if (!(isTargetMacOS() && isMacosxVersionLT(10, 9)) + && !(isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0))) + Res |= SanitizerKind::Vptr; + if (isTargetMacOS()) { - if (!isMacosxVersionLT(10, 9)) - Res |= SanitizerKind::Vptr; - Res |= SanitizerKind::SafeStack; if (IsX86_64) Res |= SanitizerKind::Thread; } else if (isTargetIOSSimulator() || isTargetTvOSSimulator()) { diff --git a/lib/Driver/ToolChains/Darwin.h b/lib/Driver/ToolChains/Darwin.h index 87d553bd7e0b..d753f8967a61 100644 --- a/lib/Driver/ToolChains/Darwin.h +++ b/lib/Driver/ToolChains/Darwin.h @@ -11,8 +11,10 @@ #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H #include "Cuda.h" +#include "clang/Driver/DarwinSDKInfo.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" +#include "clang/Driver/XRayArgs.h" namespace clang { namespace driver { @@ -189,9 +191,9 @@ public: /// Add a runtime library to the list of items to link. void AddLinkRuntimeLib(const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs, - StringRef DarwinLibName, - RuntimeLinkOptions Opts = RuntimeLinkOptions()) const; + llvm::opt::ArgStringList &CmdArgs, StringRef Component, + RuntimeLinkOptions Opts = RuntimeLinkOptions(), + bool IsShared = false) const; /// Add any profiling runtime libraries that are needed. This is essentially a /// MachO specific version of addProfileRT in Tools.cpp. @@ -252,6 +254,10 @@ public: return llvm::ExceptionHandling::None; } + virtual StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const { + return ""; + } + /// } }; @@ -283,6 +289,9 @@ public: /// The OS version we are targeting. mutable VersionTuple TargetVersion; + /// The information about the darwin SDK that was used. + mutable Optional<DarwinSDKInfo> SDKInfo; + CudaInstallationDetector CudaInstallation; private: @@ -418,7 +427,7 @@ protected: Action::OffloadKind DeviceOffloadKind) const override; StringRef getPlatformFamily() const; - StringRef getOSLibraryNameSuffix() const; + StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const override; public: static StringRef getSDKName(StringRef isysroot); @@ -489,6 +498,10 @@ public: void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override; + void AddClangCXXStdlibIncludeArgs( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override; diff --git a/lib/Driver/ToolChains/FreeBSD.cpp b/lib/Driver/ToolChains/FreeBSD.cpp index c16eabf06961..7a176d260aee 100644 --- a/lib/Driver/ToolChains/FreeBSD.cpp +++ b/lib/Driver/ToolChains/FreeBSD.cpp @@ -12,11 +12,11 @@ #include "Arch/Mips.h" #include "Arch/Sparc.h" #include "CommonArgs.h" -#include "clang/Basic/VirtualFileSystem.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Options.h" #include "clang/Driver/SanitizerArgs.h" #include "llvm/Option/ArgList.h" +#include "llvm/Support/VirtualFileSystem.h" using namespace clang::driver; using namespace clang::driver::tools; diff --git a/lib/Driver/ToolChains/Fuchsia.cpp b/lib/Driver/ToolChains/Fuchsia.cpp index 54c34ff159b1..de2c7411c5e4 100644 --- a/lib/Driver/ToolChains/Fuchsia.cpp +++ b/lib/Driver/ToolChains/Fuchsia.cpp @@ -76,10 +76,11 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, else if (Args.hasArg(options::OPT_shared)) CmdArgs.push_back("-shared"); + const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(); + if (!Args.hasArg(options::OPT_shared)) { std::string Dyld = D.DyldPrefix; - if (ToolChain.getSanitizerArgs().needsAsanRt() && - ToolChain.getSanitizerArgs().needsSharedRt()) + if (SanArgs.needsAsanRt() && SanArgs.needsSharedRt()) Dyld += "asan/"; Dyld += "ld.so.1"; CmdArgs.push_back("-dynamic-linker"); @@ -98,6 +99,8 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_u); + addSanitizerPathLibArgs(ToolChain, Args, CmdArgs); + ToolChain.AddFilePathLibArgs(Args, CmdArgs); if (D.isUsingLTO()) { @@ -106,8 +109,8 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, D.getLTOMode() == LTOK_Thin); } - addSanitizerRuntimes(ToolChain, Args, CmdArgs); - + bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs); + bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); ToolChain.addProfileRTLibs(Args, CmdArgs); @@ -119,15 +122,24 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (ToolChain.ShouldLinkCXXStdlib(Args)) { bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && !Args.hasArg(options::OPT_static); + CmdArgs.push_back("--push-state"); + CmdArgs.push_back("--as-needed"); if (OnlyLibstdcxxStatic) CmdArgs.push_back("-Bstatic"); ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); if (OnlyLibstdcxxStatic) CmdArgs.push_back("-Bdynamic"); + CmdArgs.push_back("-lm"); + CmdArgs.push_back("--pop-state"); } - CmdArgs.push_back("-lm"); } + if (NeedsSanitizerDeps) + linkSanitizerRuntimeDeps(ToolChain, CmdArgs); + + if (NeedsXRayDeps) + linkXRayRuntimeDeps(ToolChain, CmdArgs); + AddRunTimeLibs(ToolChain, D, CmdArgs, Args); if (Args.hasArg(options::OPT_pthread) || diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp index 3755673250b2..2ad45097dce8 100644 --- a/lib/Driver/ToolChains/Gnu.cpp +++ b/lib/Driver/ToolChains/Gnu.cpp @@ -16,7 +16,6 @@ #include "Arch/SystemZ.h" #include "CommonArgs.h" #include "Linux.h" -#include "clang/Basic/VirtualFileSystem.h" #include "clang/Config/config.h" // for GCC_INSTALL_PREFIX #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" @@ -27,6 +26,7 @@ #include "llvm/Support/CodeGen.h" #include "llvm/Support/Path.h" #include "llvm/Support/TargetParser.h" +#include "llvm/Support/VirtualFileSystem.h" #include <system_error> using namespace clang::driver; @@ -228,6 +228,30 @@ void tools::gcc::Linker::RenderExtraToolArgs(const JobAction &JA, // The types are (hopefully) good enough. } +// On Arm the endianness of the output file is determined by the target and +// can be overridden by the pseudo-target flags '-mlittle-endian'/'-EL' and +// '-mbig-endian'/'-EB'. Unlike other targets the flag does not result in a +// normalized triple so we must handle the flag here. +static bool isArmBigEndian(const llvm::Triple &Triple, + const ArgList &Args) { + bool IsBigEndian = false; + switch (Triple.getArch()) { + case llvm::Triple::armeb: + case llvm::Triple::thumbeb: + IsBigEndian = true; + LLVM_FALLTHROUGH; + case llvm::Triple::arm: + case llvm::Triple::thumb: + if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian, + options::OPT_mbig_endian)) + IsBigEndian = !A->getOption().matches(options::OPT_mlittle_endian); + break; + default: + break; + } + return IsBigEndian; +} + static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) { switch (T.getArch()) { case llvm::Triple::x86: @@ -237,13 +261,12 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) { case llvm::Triple::aarch64: return "aarch64linux"; case llvm::Triple::aarch64_be: - return "aarch64_be_linux"; + return "aarch64linuxb"; case llvm::Triple::arm: case llvm::Triple::thumb: - return "armelf_linux_eabi"; case llvm::Triple::armeb: case llvm::Triple::thumbeb: - return "armelfb_linux_eabi"; + return isArmBigEndian(T, Args) ? "armelfb_linux_eabi" : "armelf_linux_eabi"; case llvm::Triple::ppc: return "elf32ppclinux"; case llvm::Triple::ppc64: @@ -264,11 +287,13 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) { case llvm::Triple::mipsel: return "elf32ltsmip"; case llvm::Triple::mips64: - if (tools::mips::hasMipsAbiArg(Args, "n32")) + if (tools::mips::hasMipsAbiArg(Args, "n32") || + T.getEnvironment() == llvm::Triple::GNUABIN32) return "elf32btsmipn32"; return "elf64btsmip"; case llvm::Triple::mips64el: - if (tools::mips::hasMipsAbiArg(Args, "n32")) + if (tools::mips::hasMipsAbiArg(Args, "n32") || + T.getEnvironment() == llvm::Triple::GNUABIN32) return "elf32ltsmipn32"; return "elf64ltsmip"; case llvm::Triple::systemz: @@ -323,14 +348,6 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, // handled somewhere else. Args.ClaimAllArgs(options::OPT_w); - const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - if (llvm::sys::path::stem(Exec) == "lld") { - CmdArgs.push_back("-flavor"); - CmdArgs.push_back("old-gnu"); - CmdArgs.push_back("-target"); - CmdArgs.push_back(Args.MakeArgString(getToolChain().getTripleString())); - } - if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); @@ -343,8 +360,13 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_s)) CmdArgs.push_back("-s"); - if (Arch == llvm::Triple::armeb || Arch == llvm::Triple::thumbeb) - arm::appendEBLinkFlags(Args, CmdArgs, Triple); + if (Triple.isARM() || Triple.isThumb() || Triple.isAArch64()) { + bool IsBigEndian = isArmBigEndian(Triple, Args); + if (IsBigEndian) + arm::appendBE8LinkFlag(Args, CmdArgs, Triple); + IsBigEndian = IsBigEndian || Arch == llvm::Triple::aarch64_be; + CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL"); + } // Most Android ARM64 targets should enable the linker fix for erratum // 843419. Only non-Cortex-A53 devices are allowed to skip this flag. @@ -539,6 +561,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, AddHIPLinkerScript(getToolChain(), C, Output, Inputs, Args, CmdArgs, JA, *this); + const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } @@ -645,6 +668,7 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C, case llvm::Triple::thumb: case llvm::Triple::thumbeb: { const llvm::Triple &Triple2 = getToolChain().getTriple(); + CmdArgs.push_back(isArmBigEndian(Triple2, Args) ? "-EB" : "-EL"); switch (Triple2.getSubArch()) { case llvm::Triple::ARMSubArch_v7: CmdArgs.push_back("-mfpu=neon"); @@ -677,6 +701,8 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C, } case llvm::Triple::aarch64: case llvm::Triple::aarch64_be: { + CmdArgs.push_back( + getToolChain().getArch() == llvm::Triple::aarch64_be ? "-EB" : "-EL"); Args.AddLastArg(CmdArgs, options::OPT_march_EQ); normalizeCPUNamesForAssembler(Args, CmdArgs); @@ -791,17 +817,17 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C, if (Args.hasArg(options::OPT_gsplit_dwarf) && getToolChain().getTriple().isOSLinux()) SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, - SplitDebugName(Args, Inputs[0])); + SplitDebugName(Args, Output)); } namespace { // Filter to remove Multilibs that don't exist as a suffix to Path class FilterNonExistent { StringRef Base, File; - vfs::FileSystem &VFS; + llvm::vfs::FileSystem &VFS; public: - FilterNonExistent(StringRef Base, StringRef File, vfs::FileSystem &VFS) + FilterNonExistent(StringRef Base, StringRef File, llvm::vfs::FileSystem &VFS) : Base(Base), File(File), VFS(VFS) {} bool operator()(const Multilib &M) { return !VFS.exists(Base + M.gccSuffix() + File); @@ -852,6 +878,10 @@ static bool isRISCV(llvm::Triple::ArchType Arch) { return Arch == llvm::Triple::riscv32 || Arch == llvm::Triple::riscv64; } +static bool isMSP430(llvm::Triple::ArchType Arch) { + return Arch == llvm::Triple::msp430; +} + static Multilib makeMultilib(StringRef commonSuffix) { return Multilib(commonSuffix, commonSuffix, commonSuffix); } @@ -947,7 +977,7 @@ static bool findMipsCsMultilibs(const Multilib::flags_list &Flags, return false; } -static bool findMipsAndroidMultilibs(vfs::FileSystem &VFS, StringRef Path, +static bool findMipsAndroidMultilibs(llvm::vfs::FileSystem &VFS, StringRef Path, const Multilib::flags_list &Flags, FilterNonExistent &NonExistent, DetectedMultilibs &Result) { @@ -1397,6 +1427,26 @@ static void findAndroidArmMultilibs(const Driver &D, Result.Multilibs = AndroidArmMultilibs; } +static bool findMSP430Multilibs(const Driver &D, + const llvm::Triple &TargetTriple, + StringRef Path, const ArgList &Args, + DetectedMultilibs &Result) { + FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS()); + Multilib MSP430Multilib = makeMultilib("/430"); + // FIXME: when clang starts to support msp430x ISA additional logic + // to select between multilib must be implemented + // Multilib MSP430xMultilib = makeMultilib("/large"); + + Result.Multilibs.push_back(MSP430Multilib); + Result.Multilibs.FilterOut(NonExistent); + + Multilib::flags_list Flags; + if (Result.Multilibs.select(Flags, Result.SelectedMultilib)) + return true; + + return false; +} + static void findRISCVMultilibs(const Driver &D, const llvm::Triple &TargetTriple, StringRef Path, const ArgList &Args, DetectedMultilibs &Result) { @@ -1625,10 +1675,18 @@ Generic_GCC::GCCVersion Generic_GCC::GCCVersion::Parse(StringRef VersionText) { return GoodVersion; } -static llvm::StringRef getGCCToolchainDir(const ArgList &Args) { +static llvm::StringRef getGCCToolchainDir(const ArgList &Args, + llvm::StringRef SysRoot) { const Arg *A = Args.getLastArg(clang::driver::options::OPT_gcc_toolchain); if (A) return A->getValue(); + + // If we have a SysRoot, ignore GCC_INSTALL_PREFIX. + // GCC_INSTALL_PREFIX specifies the gcc installation for the default + // sysroot and is likely not valid with a different sysroot. + if (!SysRoot.empty()) + return ""; + return GCC_INSTALL_PREFIX; } @@ -1660,7 +1718,7 @@ void Generic_GCC::GCCInstallationDetector::init( SmallVector<std::string, 8> Prefixes(D.PrefixDirs.begin(), D.PrefixDirs.end()); - StringRef GCCToolchainDir = getGCCToolchainDir(Args); + StringRef GCCToolchainDir = getGCCToolchainDir(Args, D.SysRoot); if (GCCToolchainDir != "") { if (GCCToolchainDir.back() == '/') GCCToolchainDir = GCCToolchainDir.drop_back(); // remove the / @@ -1769,9 +1827,10 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( std::string PrefixDir = SysRoot.str() + "/usr/gcc"; std::error_code EC; - for (vfs::directory_iterator LI = D.getVFS().dir_begin(PrefixDir, EC), LE; + for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(PrefixDir, EC), + LE; !EC && LI != LE; LI = LI.increment(EC)) { - StringRef VersionText = llvm::sys::path::filename(LI->getName()); + StringRef VersionText = llvm::sys::path::filename(LI->path()); GCCVersion CandidateVersion = GCCVersion::Parse(VersionText); // Filter out obviously bad entries. @@ -1812,19 +1871,21 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( static const char *const AArch64LibDirs[] = {"/lib64", "/lib"}; static const char *const AArch64Triples[] = { "aarch64-none-linux-gnu", "aarch64-linux-gnu", "aarch64-redhat-linux", - "aarch64-suse-linux"}; + "aarch64-suse-linux", "aarch64-linux-android"}; static const char *const AArch64beLibDirs[] = {"/lib"}; static const char *const AArch64beTriples[] = {"aarch64_be-none-linux-gnu", "aarch64_be-linux-gnu"}; static const char *const ARMLibDirs[] = {"/lib"}; - static const char *const ARMTriples[] = {"arm-linux-gnueabi"}; + static const char *const ARMTriples[] = {"arm-linux-gnueabi", + "arm-linux-androideabi"}; static const char *const ARMHFTriples[] = {"arm-linux-gnueabihf", "armv7hl-redhat-linux-gnueabi", "armv6hl-suse-linux-gnueabi", "armv7hl-suse-linux-gnueabi"}; static const char *const ARMebLibDirs[] = {"/lib"}; - static const char *const ARMebTriples[] = {"armeb-linux-gnueabi"}; + static const char *const ARMebTriples[] = {"armeb-linux-gnueabi", + "armeb-linux-androideabi"}; static const char *const ARMebHFTriples[] = { "armeb-linux-gnueabihf", "armebv7hl-redhat-linux-gnueabi"}; @@ -1835,32 +1896,47 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( "x86_64-redhat-linux", "x86_64-suse-linux", "x86_64-manbo-linux-gnu", "x86_64-linux-gnu", "x86_64-slackware-linux", "x86_64-unknown-linux", - "x86_64-amazon-linux"}; + "x86_64-amazon-linux", "x86_64-linux-android"}; static const char *const X32LibDirs[] = {"/libx32"}; static const char *const X86LibDirs[] = {"/lib32", "/lib"}; static const char *const X86Triples[] = { "i686-linux-gnu", "i686-pc-linux-gnu", "i486-linux-gnu", "i386-linux-gnu", "i386-redhat-linux6E", "i686-redhat-linux", "i586-redhat-linux", "i386-redhat-linux", "i586-suse-linux", - "i486-slackware-linux", "i686-montavista-linux", "i586-linux-gnu"}; + "i486-slackware-linux", "i686-montavista-linux", "i586-linux-gnu", + "i686-linux-android", "i386-gnu", "i486-gnu", + "i586-gnu", "i686-gnu"}; static const char *const MIPSLibDirs[] = {"/lib"}; - static const char *const MIPSTriples[] = {"mips-linux-gnu", "mips-mti-linux", - "mips-mti-linux-gnu", - "mips-img-linux-gnu"}; + static const char *const MIPSTriples[] = { + "mips-linux-gnu", "mips-mti-linux", "mips-mti-linux-gnu", + "mips-img-linux-gnu", "mipsisa32r6-linux-gnu"}; static const char *const MIPSELLibDirs[] = {"/lib"}; - static const char *const MIPSELTriples[] = {"mipsel-linux-gnu", - "mips-img-linux-gnu"}; + static const char *const MIPSELTriples[] = { + "mipsel-linux-gnu", "mips-img-linux-gnu", "mipsisa32r6el-linux-gnu", + "mipsel-linux-android"}; static const char *const MIPS64LibDirs[] = {"/lib64", "/lib"}; static const char *const MIPS64Triples[] = { - "mips64-linux-gnu", "mips-mti-linux-gnu", "mips-img-linux-gnu", - "mips64-linux-gnuabi64"}; + "mips64-linux-gnu", "mips-mti-linux-gnu", + "mips-img-linux-gnu", "mips64-linux-gnuabi64", + "mipsisa64r6-linux-gnu", "mipsisa64r6-linux-gnuabi64"}; static const char *const MIPS64ELLibDirs[] = {"/lib64", "/lib"}; static const char *const MIPS64ELTriples[] = { - "mips64el-linux-gnu", "mips-mti-linux-gnu", "mips-img-linux-gnu", - "mips64el-linux-gnuabi64"}; + "mips64el-linux-gnu", "mips-mti-linux-gnu", + "mips-img-linux-gnu", "mips64el-linux-gnuabi64", + "mipsisa64r6el-linux-gnu", "mipsisa64r6el-linux-gnuabi64", + "mips64el-linux-android"}; + + static const char *const MIPSN32LibDirs[] = {"/lib32"}; + static const char *const MIPSN32Triples[] = {"mips64-linux-gnuabin32", + "mipsisa64r6-linux-gnuabin32"}; + static const char *const MIPSN32ELLibDirs[] = {"/lib32"}; + static const char *const MIPSN32ELTriples[] = { + "mips64el-linux-gnuabin32", "mipsisa64r6el-linux-gnuabin32"}; + static const char *const MSP430LibDirs[] = {"/lib"}; + static const char *const MSP430Triples[] = {"msp430-elf"}; static const char *const PPCLibDirs[] = {"/lib32", "/lib"}; static const char *const PPCTriples[] = { @@ -2057,6 +2133,8 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( TripleAliases.append(begin(MIPSTriples), end(MIPSTriples)); BiarchLibDirs.append(begin(MIPS64LibDirs), end(MIPS64LibDirs)); BiarchTripleAliases.append(begin(MIPS64Triples), end(MIPS64Triples)); + BiarchLibDirs.append(begin(MIPSN32LibDirs), end(MIPSN32LibDirs)); + BiarchTripleAliases.append(begin(MIPSN32Triples), end(MIPSN32Triples)); break; case llvm::Triple::mipsel: LibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs)); @@ -2064,20 +2142,30 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( TripleAliases.append(begin(MIPSTriples), end(MIPSTriples)); BiarchLibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs)); BiarchTripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples)); + BiarchLibDirs.append(begin(MIPSN32ELLibDirs), end(MIPSN32ELLibDirs)); + BiarchTripleAliases.append(begin(MIPSN32ELTriples), end(MIPSN32ELTriples)); break; case llvm::Triple::mips64: LibDirs.append(begin(MIPS64LibDirs), end(MIPS64LibDirs)); TripleAliases.append(begin(MIPS64Triples), end(MIPS64Triples)); BiarchLibDirs.append(begin(MIPSLibDirs), end(MIPSLibDirs)); BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples)); + BiarchLibDirs.append(begin(MIPSN32LibDirs), end(MIPSN32LibDirs)); + BiarchTripleAliases.append(begin(MIPSN32Triples), end(MIPSN32Triples)); break; case llvm::Triple::mips64el: LibDirs.append(begin(MIPS64ELLibDirs), end(MIPS64ELLibDirs)); TripleAliases.append(begin(MIPS64ELTriples), end(MIPS64ELTriples)); BiarchLibDirs.append(begin(MIPSELLibDirs), end(MIPSELLibDirs)); BiarchTripleAliases.append(begin(MIPSELTriples), end(MIPSELTriples)); + BiarchLibDirs.append(begin(MIPSN32ELLibDirs), end(MIPSN32ELLibDirs)); + BiarchTripleAliases.append(begin(MIPSN32ELTriples), end(MIPSN32ELTriples)); BiarchTripleAliases.append(begin(MIPSTriples), end(MIPSTriples)); break; + case llvm::Triple::msp430: + LibDirs.append(begin(MSP430LibDirs), end(MSP430LibDirs)); + TripleAliases.append(begin(MSP430Triples), end(MSP430Triples)); + break; case llvm::Triple::ppc: LibDirs.append(begin(PPCLibDirs), end(PPCLibDirs)); TripleAliases.append(begin(PPCTriples), end(PPCTriples)); @@ -2149,6 +2237,8 @@ bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs( return false; } else if (isRISCV(TargetArch)) { findRISCVMultilibs(D, TargetTriple, Path, Args, Detected); + } else if (isMSP430(TargetArch)) { + findMSP430Multilibs(D, TargetTriple, Path, Args, Detected); } else if (!findBiarchMultilibs(D, TargetTriple, Path, Args, NeedsBiarchSuffix, Detected)) { return false; @@ -2204,6 +2294,9 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( // triple. {"i386-linux-gnu/gcc/" + CandidateTriple.str(), "../../..", (TargetArch == llvm::Triple::x86 && + TargetTriple.getOS() != llvm::Triple::Solaris)}, + {"i386-gnu/gcc/" + CandidateTriple.str(), "../../..", + (TargetArch == llvm::Triple::x86 && TargetTriple.getOS() != llvm::Triple::Solaris)}}; for (auto &Suffix : Suffixes) { @@ -2212,21 +2305,21 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( StringRef LibSuffix = Suffix.LibSuffix; std::error_code EC; - for (vfs::directory_iterator + for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(LibDir + "/" + LibSuffix, EC), LE; !EC && LI != LE; LI = LI.increment(EC)) { - StringRef VersionText = llvm::sys::path::filename(LI->getName()); + StringRef VersionText = llvm::sys::path::filename(LI->path()); GCCVersion CandidateVersion = GCCVersion::Parse(VersionText); if (CandidateVersion.Major != -1) // Filter obviously bad entries. - if (!CandidateGCCInstallPaths.insert(LI->getName()).second) + if (!CandidateGCCInstallPaths.insert(LI->path()).second) continue; // Saw this path before; no need to look at it again. if (CandidateVersion.isOlderThan(4, 1, 1)) continue; if (CandidateVersion <= Version) continue; - if (!ScanGCCForMultilibs(TargetTriple, Args, LI->getName(), + if (!ScanGCCForMultilibs(TargetTriple, Args, LI->path(), NeedsBiarchSuffix)) continue; @@ -2375,7 +2468,7 @@ bool Generic_GCC::isPICDefault() const { case llvm::Triple::x86_64: return getTriple().isOSWindows(); case llvm::Triple::ppc64: - case llvm::Triple::ppc64le: + // Big endian PPC is PIC by default return !getTriple().isOSBinFormatMachO() && !getTriple().isMacOSX(); case llvm::Triple::mips64: case llvm::Triple::mips64el: @@ -2412,16 +2505,14 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const { case llvm::Triple::systemz: case llvm::Triple::mips: case llvm::Triple::mipsel: - return true; case llvm::Triple::mips64: case llvm::Triple::mips64el: - // Enabled for Debian, Android, FreeBSD and OpenBSD mips64/mipsel, as they - // can precisely identify the ABI in use (Debian) or only use N64 for MIPS64 - // (Android). Other targets are unable to distinguish N32 from N64. - if (getTriple().getEnvironment() == llvm::Triple::GNUABI64 || - getTriple().isAndroid() || - getTriple().isOSFreeBSD() || - getTriple().isOSOpenBSD()) + case llvm::Triple::msp430: + return true; + case llvm::Triple::sparc: + case llvm::Triple::sparcel: + case llvm::Triple::sparcv9: + if (getTriple().isOSSolaris() || getTriple().isOSOpenBSD()) return true; return false; default: @@ -2546,7 +2637,7 @@ void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs, bool UseInitArrayDefault = getTriple().getArch() == llvm::Triple::aarch64 || getTriple().getArch() == llvm::Triple::aarch64_be || - (getTriple().getOS() == llvm::Triple::FreeBSD && + (getTriple().isOSFreeBSD() && getTriple().getOSMajorVersion() >= 12) || (getTriple().getOS() == llvm::Triple::Linux && ((!GCCInstallation.isValid() || !V.isOlderThan(4, 7, 0)) || @@ -2554,7 +2645,9 @@ void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs, getTriple().getOS() == llvm::Triple::NaCl || (getTriple().getVendor() == llvm::Triple::MipsTechnologies && !getTriple().hasEnvironment()) || - getTriple().getOS() == llvm::Triple::Solaris; + getTriple().getOS() == llvm::Triple::Solaris || + getTriple().getArch() == llvm::Triple::riscv32 || + getTriple().getArch() == llvm::Triple::riscv64; if (DriverArgs.hasFlag(options::OPT_fuse_init_array, options::OPT_fno_use_init_array, UseInitArrayDefault)) diff --git a/lib/Driver/ToolChains/HIP.cpp b/lib/Driver/ToolChains/HIP.cpp index 03acf45a9b31..868765cf88e5 100644 --- a/lib/Driver/ToolChains/HIP.cpp +++ b/lib/Driver/ToolChains/HIP.cpp @@ -24,6 +24,12 @@ using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; +#if _WIN32 || _WIN64 +#define NULL_FILE "nul" +#else +#define NULL_FILE "/dev/null" +#endif + namespace { static void addBCLib(Compilation &C, const ArgList &Args, @@ -81,8 +87,8 @@ const char *AMDGCN::Linker::constructLLVMLinkCommand( else FlushDenormalControlBC = "oclc_daz_opt_off.amdgcn.bc"; - BCLibs.append({"opencl.amdgcn.bc", - "ocml.amdgcn.bc", "ockl.amdgcn.bc", "irif.amdgcn.bc", + BCLibs.append({"hip.amdgcn.bc", "opencl.amdgcn.bc", + "ocml.amdgcn.bc", "ockl.amdgcn.bc", "oclc_finite_only_off.amdgcn.bc", FlushDenormalControlBC, "oclc_correctly_rounded_sqrt_on.amdgcn.bc", @@ -154,7 +160,7 @@ const char *AMDGCN::Linker::constructLlcCommand( llvm::StringRef OutputFilePrefix, const char *InputFileName) const { // Construct llc command. ArgStringList LlcArgs{InputFileName, "-mtriple=amdgcn-amd-amdhsa", - "-filetype=obj", + "-filetype=obj", "-mattr=-code-object-v3", Args.MakeArgString("-mcpu=" + SubArchName), "-o"}; std::string LlcOutputFileName = C.getDriver().GetTemporaryPath(OutputFilePrefix, "o"); @@ -184,6 +190,40 @@ void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA, C.addCommand(llvm::make_unique<Command>(JA, *this, Lld, LldArgs, Inputs)); } +// Construct a clang-offload-bundler command to bundle code objects for +// different GPU's into a HIP fat binary. +void AMDGCN::constructHIPFatbinCommand(Compilation &C, const JobAction &JA, + StringRef OutputFileName, const InputInfoList &Inputs, + const llvm::opt::ArgList &Args, const Tool& T) { + // Construct clang-offload-bundler command to bundle object files for + // for different GPU archs. + ArgStringList BundlerArgs; + BundlerArgs.push_back(Args.MakeArgString("-type=o")); + + // ToDo: Remove the dummy host binary entry which is required by + // clang-offload-bundler. + std::string BundlerTargetArg = "-targets=host-x86_64-unknown-linux"; + std::string BundlerInputArg = "-inputs=" NULL_FILE; + + for (const auto &II : Inputs) { + const auto* A = II.getAction(); + BundlerTargetArg = BundlerTargetArg + ",hip-amdgcn-amd-amdhsa-" + + StringRef(A->getOffloadingArch()).str(); + BundlerInputArg = BundlerInputArg + "," + II.getFilename(); + } + BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg)); + BundlerArgs.push_back(Args.MakeArgString(BundlerInputArg)); + + auto BundlerOutputArg = + Args.MakeArgString(std::string("-outputs=").append(OutputFileName)); + BundlerArgs.push_back(BundlerOutputArg); + + SmallString<128> BundlerPath(C.getDriver().Dir); + llvm::sys::path::append(BundlerPath, "clang-offload-bundler"); + const char *Bundler = Args.MakeArgString(BundlerPath); + C.addCommand(llvm::make_unique<Command>(JA, T, Bundler, BundlerArgs, Inputs)); +} + // For amdgcn the inputs of the linker job are device bitcode and output is // object file. It calls llvm-link, opt, llc, then lld steps. void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -192,6 +232,9 @@ void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA, const ArgList &Args, const char *LinkingOutput) const { + if (JA.getType() == types::TY_HIP_FATBIN) + return constructHIPFatbinCommand(C, JA, Output.getFilename(), Inputs, Args, *this); + assert(getToolChain().getTriple().getArch() == llvm::Triple::amdgcn && "Unsupported target"); @@ -244,9 +287,15 @@ void HIPToolChain::addClangTargetOptions( options::OPT_fno_cuda_approx_transcendentals, false)) CC1Args.push_back("-fcuda-approx-transcendentals"); - if (DriverArgs.hasFlag(options::OPT_fcuda_rdc, options::OPT_fno_cuda_rdc, + if (DriverArgs.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false)) - CC1Args.push_back("-fcuda-rdc"); + CC1Args.push_back("-fgpu-rdc"); + + // Default to "hidden" visibility, as object level linking will not be + // supported for the foreseeable future. + if (!DriverArgs.hasArg(options::OPT_fvisibility_EQ, + options::OPT_fvisibility_ms_compat)) + CC1Args.append({"-fvisibility", "hidden"}); } llvm::opt::DerivedArgList * diff --git a/lib/Driver/ToolChains/HIP.h b/lib/Driver/ToolChains/HIP.h index 40c9128e2f59..3af19d44dae0 100644 --- a/lib/Driver/ToolChains/HIP.h +++ b/lib/Driver/ToolChains/HIP.h @@ -19,6 +19,11 @@ namespace driver { namespace tools { namespace AMDGCN { + // Construct command for creating HIP fatbin. + void constructHIPFatbinCommand(Compilation &C, const JobAction &JA, + StringRef OutputFileName, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, const Tool& T); + // Runs llvm-link/opt/llc/lld, which links multiple LLVM bitcode, together with // device library, then compiles it to ISA in a shared object. class LLVM_LIBRARY_VISIBILITY Linker : public Tool { diff --git a/lib/Driver/ToolChains/Hexagon.cpp b/lib/Driver/ToolChains/Hexagon.cpp index c2b27b6d9ac6..d302a3e24d8b 100644 --- a/lib/Driver/ToolChains/Hexagon.cpp +++ b/lib/Driver/ToolChains/Hexagon.cpp @@ -8,9 +8,8 @@ //===----------------------------------------------------------------------===// #include "Hexagon.h" -#include "InputInfo.h" #include "CommonArgs.h" -#include "clang/Basic/VirtualFileSystem.h" +#include "InputInfo.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" @@ -19,6 +18,7 @@ #include "llvm/Option/ArgList.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" +#include "llvm/Support/VirtualFileSystem.h" using namespace clang::driver; using namespace clang::driver::tools; @@ -32,6 +32,7 @@ static StringRef getDefaultHvxLength(StringRef Cpu) { .Case("v60", "64b") .Case("v62", "64b") .Case("v65", "64b") + .Case("v66", "128b") .Default("128b"); } @@ -75,7 +76,7 @@ static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args, // Handle -mhvx-length=. if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx_length_EQ)) { - // These falgs are valid only if HVX in enabled. + // These flags are valid only if HVX in enabled. if (!HasHVX) D.Diag(diag::err_drv_invalid_hvx_length); else if (A->getOption().matches(options::OPT_mhexagon_hvx_length_EQ)) @@ -369,9 +370,8 @@ void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA, constructHexagonLinkArgs(C, JA, HTC, Output, Inputs, Args, CmdArgs, LinkingOutput); - std::string Linker = HTC.GetProgramPath("hexagon-link"); - C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), - CmdArgs, Inputs)); + const char *Exec = Args.MakeArgString(HTC.GetLinkerPath()); + C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } // Hexagon tools end. @@ -513,11 +513,6 @@ unsigned HexagonToolChain::getOptimizationLevel( void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs, ArgStringList &CC1Args, Action::OffloadKind) const { - if (!DriverArgs.hasArg(options::OPT_ffp_contract)) { - unsigned OptLevel = getOptimizationLevel(DriverArgs); - if (OptLevel >= 3) - CC1Args.push_back("-ffp-contract=fast"); - } if (DriverArgs.hasArg(options::OPT_ffixed_r19)) { CC1Args.push_back("-target-feature"); CC1Args.push_back("+reserved-r19"); diff --git a/lib/Driver/ToolChains/Hexagon.h b/lib/Driver/ToolChains/Hexagon.h index e43b8a5b8800..a9e599de7ae5 100644 --- a/lib/Driver/ToolChains/Hexagon.h +++ b/lib/Driver/ToolChains/Hexagon.h @@ -81,6 +81,9 @@ public: void addLibStdCxxIncludePaths( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; + + const char *getDefaultLinker() const override { return "hexagon-link"; } + CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override; StringRef GetGCCLibAndIncVersion() const { return GCCLibAndIncVersion.Text; } diff --git a/lib/Driver/ToolChains/Hurd.cpp b/lib/Driver/ToolChains/Hurd.cpp new file mode 100644 index 000000000000..ff7b685dae3f --- /dev/null +++ b/lib/Driver/ToolChains/Hurd.cpp @@ -0,0 +1,169 @@ +//===--- Hurd.cpp - Hurd ToolChain Implementations --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Hurd.h" +#include "CommonArgs.h" +#include "clang/Config/config.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/Options.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/VirtualFileSystem.h" + +using namespace clang::driver; +using namespace clang::driver::toolchains; +using namespace clang; +using namespace llvm::opt; + +using tools::addPathIfExists; + +/// Get our best guess at the multiarch triple for a target. +/// +/// Debian-based systems are starting to use a multiarch setup where they use +/// a target-triple directory in the library and header search paths. +/// Unfortunately, this triple does not align with the vanilla target triple, +/// so we provide a rough mapping here. +static std::string getMultiarchTriple(const Driver &D, + const llvm::Triple &TargetTriple, + StringRef SysRoot) { + if (TargetTriple.getArch() == llvm::Triple::x86) { + // We use the existence of '/lib/<triple>' as a directory to detect some + // common hurd triples that don't quite match the Clang triple for both + // 32-bit and 64-bit targets. Multiarch fixes its install triples to these + // regardless of what the actual target triple is. + if (D.getVFS().exists(SysRoot + "/lib/i386-gnu")) + return "i386-gnu"; + } + + // For most architectures, just use whatever we have rather than trying to be + // clever. + return TargetTriple.str(); +} + +static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) { + // It happens that only x86 and PPC use the 'lib32' variant of oslibdir, and + // using that variant while targeting other architectures causes problems + // because the libraries are laid out in shared system roots that can't cope + // with a 'lib32' library search path being considered. So we only enable + // them when we know we may need it. + // + // FIXME: This is a bit of a hack. We should really unify this code for + // reasoning about oslibdir spellings with the lib dir spellings in the + // GCCInstallationDetector, but that is a more significant refactoring. + + if (Triple.getArch() == llvm::Triple::x86) + return "lib32"; + + return Triple.isArch32Bit() ? "lib" : "lib64"; +} + +Hurd::Hurd(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : Generic_ELF(D, Triple, Args) { + std::string SysRoot = computeSysRoot(); + path_list &Paths = getFilePaths(); + + const std::string OSLibDir = getOSLibDir(Triple, Args); + const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot); + + // If we are currently running Clang inside of the requested system root, add + // its parent library paths to those searched. + // FIXME: It's not clear whether we should use the driver's installed + // directory ('Dir' below) or the ResourceDir. + if (StringRef(D.Dir).startswith(SysRoot)) { + addPathIfExists(D, D.Dir + "/../lib/" + MultiarchTriple, Paths); + addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths); + } + + addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths); + addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths); + + addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths); + addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths); + + // If we are currently running Clang inside of the requested system root, add + // its parent library path to those searched. + // FIXME: It's not clear whether we should use the driver's installed + // directory ('Dir' below) or the ResourceDir. + if (StringRef(D.Dir).startswith(SysRoot)) + addPathIfExists(D, D.Dir + "/../lib", Paths); + + addPathIfExists(D, SysRoot + "/lib", Paths); + addPathIfExists(D, SysRoot + "/usr/lib", Paths); +} + +bool Hurd::HasNativeLLVMSupport() const { return true; } + +Tool *Hurd::buildLinker() const { return new tools::gnutools::Linker(*this); } + +Tool *Hurd::buildAssembler() const { + return new tools::gnutools::Assembler(*this); +} + +std::string Hurd::computeSysRoot() const { + if (!getDriver().SysRoot.empty()) + return getDriver().SysRoot; + + return std::string(); +} + +std::string Hurd::getDynamicLinker(const ArgList &Args) const { + if (getArch() == llvm::Triple::x86) + return "/lib/ld.so"; + + llvm_unreachable("unsupported architecture"); +} + +void Hurd::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + const Driver &D = getDriver(); + std::string SysRoot = computeSysRoot(); + + if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc)) + return; + + if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) + addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include"); + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { + SmallString<128> P(D.ResourceDir); + llvm::sys::path::append(P, "include"); + addSystemInclude(DriverArgs, CC1Args, P); + } + + if (DriverArgs.hasArg(options::OPT_nostdlibinc)) + return; + + // Check for configure-time C include directories. + StringRef CIncludeDirs(C_INCLUDE_DIRS); + if (CIncludeDirs != "") { + SmallVector<StringRef, 5> Dirs; + CIncludeDirs.split(Dirs, ":"); + for (StringRef Dir : Dirs) { + StringRef Prefix = + llvm::sys::path::is_absolute(Dir) ? StringRef(SysRoot) : ""; + addExternCSystemInclude(DriverArgs, CC1Args, Prefix + Dir); + } + return; + } + + // Lacking those, try to detect the correct set of system includes for the + // target triple. + if (getTriple().getArch() == llvm::Triple::x86) { + std::string Path = SysRoot + "/usr/include/i386-gnu"; + if (D.getVFS().exists(Path)) + addExternCSystemInclude(DriverArgs, CC1Args, Path); + } + + // Add an include of '/include' directly. This isn't provided by default by + // system GCCs, but is often used with cross-compiling GCCs, and harmless to + // add even when Clang is acting as-if it were a system compiler. + addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include"); + + addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include"); +} diff --git a/lib/Driver/ToolChains/Hurd.h b/lib/Driver/ToolChains/Hurd.h new file mode 100644 index 000000000000..d14619f0e2ce --- /dev/null +++ b/lib/Driver/ToolChains/Hurd.h @@ -0,0 +1,46 @@ +//===--- Hurd.h - Hurd ToolChain Implementations ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Hurd_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Hurd_H + +#include "Gnu.h" +#include "clang/Driver/ToolChain.h" + +namespace clang { +namespace driver { +namespace toolchains { + +class LLVM_LIBRARY_VISIBILITY Hurd : public Generic_ELF { +public: + Hurd(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + + bool HasNativeLLVMSupport() const override; + + void + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + + virtual std::string computeSysRoot() const; + + virtual std::string getDynamicLinker(const llvm::opt::ArgList &Args) const; + + std::vector<std::string> ExtraOpts; + +protected: + Tool *buildAssembler() const override; + Tool *buildLinker() const override; +}; + +} // end namespace toolchains +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Hurd_H diff --git a/lib/Driver/ToolChains/Linux.cpp b/lib/Driver/ToolChains/Linux.cpp index f8f36239180c..65ab9b2daf54 100644 --- a/lib/Driver/ToolChains/Linux.cpp +++ b/lib/Driver/ToolChains/Linux.cpp @@ -13,7 +13,6 @@ #include "Arch/PPC.h" #include "Arch/RISCV.h" #include "CommonArgs.h" -#include "clang/Basic/VirtualFileSystem.h" #include "clang/Config/config.h" #include "clang/Driver/Distro.h" #include "clang/Driver/Driver.h" @@ -23,6 +22,7 @@ #include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/Path.h" #include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/VirtualFileSystem.h" #include <system_error> using namespace clang::driver; @@ -44,6 +44,7 @@ static std::string getMultiarchTriple(const Driver &D, llvm::Triple::EnvironmentType TargetEnvironment = TargetTriple.getEnvironment(); bool IsAndroid = TargetTriple.isAndroid(); + bool IsMipsR6 = TargetTriple.getSubArch() == llvm::Triple::MipsSubArch_r6; // For most architectures, just use whatever we have rather than trying to be // clever. @@ -101,30 +102,36 @@ static std::string getMultiarchTriple(const Driver &D, if (D.getVFS().exists(SysRoot + "/lib/aarch64_be-linux-gnu")) return "aarch64_be-linux-gnu"; break; - case llvm::Triple::mips: - if (D.getVFS().exists(SysRoot + "/lib/mips-linux-gnu")) - return "mips-linux-gnu"; + case llvm::Triple::mips: { + std::string Arch = IsMipsR6 ? "mipsisa32r6" : "mips"; + if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-gnu")) + return Arch + "-linux-gnu"; break; - case llvm::Triple::mipsel: + } + case llvm::Triple::mipsel: { if (IsAndroid) return "mipsel-linux-android"; - if (D.getVFS().exists(SysRoot + "/lib/mipsel-linux-gnu")) - return "mipsel-linux-gnu"; + std::string Arch = IsMipsR6 ? "mipsisa32r6el" : "mipsel"; + if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-gnu")) + return Arch + "-linux-gnu"; break; - case llvm::Triple::mips64: - if (D.getVFS().exists(SysRoot + "/lib/mips64-linux-gnu")) - return "mips64-linux-gnu"; - if (D.getVFS().exists(SysRoot + "/lib/mips64-linux-gnuabi64")) - return "mips64-linux-gnuabi64"; + } + case llvm::Triple::mips64: { + std::string Arch = IsMipsR6 ? "mipsisa64r6" : "mips64"; + std::string ABI = llvm::Triple::getEnvironmentTypeName(TargetEnvironment); + if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-" + ABI)) + return Arch + "-linux-" + ABI; break; - case llvm::Triple::mips64el: + } + case llvm::Triple::mips64el: { if (IsAndroid) return "mips64el-linux-android"; - if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnu")) - return "mips64el-linux-gnu"; - if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnuabi64")) - return "mips64el-linux-gnuabi64"; + std::string Arch = IsMipsR6 ? "mipsisa64r6el" : "mips64el"; + std::string ABI = llvm::Triple::getEnvironmentTypeName(TargetEnvironment); + if (D.getVFS().exists(SysRoot + "/lib/" + Arch + "-linux-" + ABI)) + return Arch + "-linux-" + ABI; break; + } case llvm::Triple::ppc: if (D.getVFS().exists(SysRoot + "/lib/powerpc-linux-gnuspe")) return "powerpc-linux-gnuspe"; @@ -210,6 +217,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : Generic_ELF(D, Triple, Args) { GCCInstallation.init(Triple, Args); Multilibs = GCCInstallation.getMultilibs(); + SelectedMultilib = GCCInstallation.getMultilib(); llvm::Triple::ArchType Arch = Triple.getArch(); std::string SysRoot = computeSysRoot(); @@ -228,16 +236,25 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) Distro Distro(D.getVFS()); - if (Distro.IsAlpineLinux()) { + if (Distro.IsAlpineLinux() || Triple.isAndroid()) { ExtraOpts.push_back("-z"); ExtraOpts.push_back("now"); } - if (Distro.IsOpenSUSE() || Distro.IsUbuntu() || Distro.IsAlpineLinux()) { + if (Distro.IsOpenSUSE() || Distro.IsUbuntu() || Distro.IsAlpineLinux() || + Triple.isAndroid()) { ExtraOpts.push_back("-z"); ExtraOpts.push_back("relro"); } + // The lld default page size is too large for Aarch64, which produces much + // larger .so files and images for arm64 device targets. Use 4KB page size + // for Android arm64 targets instead. + if (Triple.isAArch64() && Triple.isAndroid()) { + ExtraOpts.push_back("-z"); + ExtraOpts.push_back("max-page-size=4096"); + } + if (GCCInstallation.getParentLibPath().find("opt/rh/devtoolset") != StringRef::npos) // With devtoolset on RHEL, we want to add a bin directory that is relative @@ -263,15 +280,18 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // and the MIPS ABI require .dynsym to be sorted in different ways. // .gnu.hash needs symbols to be grouped by hash code whereas the MIPS // ABI requires a mapping between the GOT and the symbol table. - // Android loader does not support .gnu.hash. + // Android loader does not support .gnu.hash until API 23. // Hexagon linker/loader does not support .gnu.hash - if (!IsMips && !IsAndroid && !IsHexagon) { + if (!IsMips && !IsHexagon) { if (Distro.IsRedhat() || Distro.IsOpenSUSE() || Distro.IsAlpineLinux() || - (Distro.IsUbuntu() && Distro >= Distro::UbuntuMaverick)) + (Distro.IsUbuntu() && Distro >= Distro::UbuntuMaverick) || + (IsAndroid && !Triple.isAndroidVersionLT(23))) ExtraOpts.push_back("--hash-style=gnu"); - if (Distro.IsDebian() || Distro.IsOpenSUSE() || Distro == Distro::UbuntuLucid || - Distro == Distro::UbuntuJaunty || Distro == Distro::UbuntuKarmic) + if (Distro.IsDebian() || Distro.IsOpenSUSE() || + Distro == Distro::UbuntuLucid || Distro == Distro::UbuntuJaunty || + Distro == Distro::UbuntuKarmic || + (IsAndroid && Triple.isAndroidVersionLT(23))) ExtraOpts.push_back("--hash-style=both"); } @@ -299,16 +319,14 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) if (GCCInstallation.isValid()) { const llvm::Triple &GCCTriple = GCCInstallation.getTriple(); const std::string &LibPath = GCCInstallation.getParentLibPath(); - const Multilib &Multilib = GCCInstallation.getMultilib(); - const MultilibSet &Multilibs = GCCInstallation.getMultilibs(); // Add toolchain / multilib specific file paths. - addMultilibsFilePaths(D, Multilibs, Multilib, + addMultilibsFilePaths(D, Multilibs, SelectedMultilib, GCCInstallation.getInstallPath(), Paths); // Sourcery CodeBench MIPS toolchain holds some libraries under // a biarch-like suffix of the GCC installation. - addPathIfExists(D, GCCInstallation.getInstallPath() + Multilib.gccSuffix(), + addPathIfExists(D, GCCInstallation.getInstallPath() + SelectedMultilib.gccSuffix(), Paths); // GCC cross compiling toolchains will install target libraries which ship @@ -330,7 +348,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) // Note that this matches the GCC behavior. See the below comment for where // Clang diverges from GCC's behavior. addPathIfExists(D, LibPath + "/../" + GCCTriple.str() + "/lib/../" + - OSLibDir + Multilib.osSuffix(), + OSLibDir + SelectedMultilib.osSuffix(), Paths); // If the GCC installation we found is inside of the sysroot, we want to @@ -433,6 +451,12 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) addPathIfExists(D, SysRoot + "/usr/lib", Paths); } +ToolChain::CXXStdlibType Linux::GetDefaultCXXStdlibType() const { + if (getTriple().isAndroid()) + return ToolChain::CST_Libcxx; + return ToolChain::CST_Libstdcxx; +} + bool Linux::HasNativeLLVMSupport() const { return true; } Tool *Linux::buildLinker() const { return new tools::gnutools::Linker(*this); } @@ -695,12 +719,28 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, const StringRef MIPSELMultiarchIncludeDirs[] = { "/usr/include/mipsel-linux-gnu"}; const StringRef MIPS64MultiarchIncludeDirs[] = { - "/usr/include/mips64-linux-gnu", "/usr/include/mips64-linux-gnuabi64"}; + "/usr/include/mips64-linux-gnuabi64"}; const StringRef MIPS64ELMultiarchIncludeDirs[] = { - "/usr/include/mips64el-linux-gnu", "/usr/include/mips64el-linux-gnuabi64"}; + const StringRef MIPSN32MultiarchIncludeDirs[] = { + "/usr/include/mips64-linux-gnuabin32"}; + const StringRef MIPSN32ELMultiarchIncludeDirs[] = { + "/usr/include/mips64el-linux-gnuabin32"}; + const StringRef MIPSR6MultiarchIncludeDirs[] = { + "/usr/include/mipsisa32-linux-gnu"}; + const StringRef MIPSR6ELMultiarchIncludeDirs[] = { + "/usr/include/mipsisa32r6el-linux-gnu"}; + const StringRef MIPS64R6MultiarchIncludeDirs[] = { + "/usr/include/mipsisa64r6-linux-gnuabi64"}; + const StringRef MIPS64R6ELMultiarchIncludeDirs[] = { + "/usr/include/mipsisa64r6el-linux-gnuabi64"}; + const StringRef MIPSN32R6MultiarchIncludeDirs[] = { + "/usr/include/mipsisa64r6-linux-gnuabin32"}; + const StringRef MIPSN32R6ELMultiarchIncludeDirs[] = { + "/usr/include/mipsisa64r6el-linux-gnuabin32"}; const StringRef PPCMultiarchIncludeDirs[] = { - "/usr/include/powerpc-linux-gnu"}; + "/usr/include/powerpc-linux-gnu", + "/usr/include/powerpc-linux-gnuspe"}; const StringRef PPC64MultiarchIncludeDirs[] = { "/usr/include/powerpc64-linux-gnu"}; const StringRef PPC64LEMultiarchIncludeDirs[] = { @@ -738,16 +778,38 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, MultiarchIncludeDirs = ARMEBMultiarchIncludeDirs; break; case llvm::Triple::mips: - MultiarchIncludeDirs = MIPSMultiarchIncludeDirs; + if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6) + MultiarchIncludeDirs = MIPSR6MultiarchIncludeDirs; + else + MultiarchIncludeDirs = MIPSMultiarchIncludeDirs; break; case llvm::Triple::mipsel: - MultiarchIncludeDirs = MIPSELMultiarchIncludeDirs; + if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6) + MultiarchIncludeDirs = MIPSR6ELMultiarchIncludeDirs; + else + MultiarchIncludeDirs = MIPSELMultiarchIncludeDirs; break; case llvm::Triple::mips64: - MultiarchIncludeDirs = MIPS64MultiarchIncludeDirs; + if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6) + if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32) + MultiarchIncludeDirs = MIPSN32R6MultiarchIncludeDirs; + else + MultiarchIncludeDirs = MIPS64R6MultiarchIncludeDirs; + else if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32) + MultiarchIncludeDirs = MIPSN32MultiarchIncludeDirs; + else + MultiarchIncludeDirs = MIPS64MultiarchIncludeDirs; break; case llvm::Triple::mips64el: - MultiarchIncludeDirs = MIPS64ELMultiarchIncludeDirs; + if (getTriple().getSubArch() == llvm::Triple::MipsSubArch_r6) + if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32) + MultiarchIncludeDirs = MIPSN32R6ELMultiarchIncludeDirs; + else + MultiarchIncludeDirs = MIPS64R6ELMultiarchIncludeDirs; + else if (getTriple().getEnvironment() == llvm::Triple::GNUABIN32) + MultiarchIncludeDirs = MIPSN32ELMultiarchIncludeDirs; + else + MultiarchIncludeDirs = MIPS64ELMultiarchIncludeDirs; break; case llvm::Triple::ppc: MultiarchIncludeDirs = PPCMultiarchIncludeDirs; @@ -876,6 +938,9 @@ void Linux::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, // Freescale SDK C++ headers are directly in <sysroot>/usr/include/c++, // without a subdirectory corresponding to the gcc version. LibDir.str() + "/../include/c++", + // Cray's gcc installation puts headers under "g++" without a + // version suffix. + LibDir.str() + "/../include/g++", }; for (const auto &IncludePath : LibStdCXXIncludePathCandidates) { @@ -907,6 +972,12 @@ bool Linux::isPIEDefault() const { getTriple().isMusl() || getSanitizerArgs().requiresPIE(); } +bool Linux::IsMathErrnoDefault() const { + if (getTriple().isAndroid()) + return false; + return Generic_ELF::IsMathErrnoDefault(); +} + SanitizerMask Linux::getSupportedSanitizers() const { const bool IsX86 = getTriple().getArch() == llvm::Triple::x86; const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; @@ -934,6 +1005,8 @@ SanitizerMask Linux::getSupportedSanitizers() const { Res |= SanitizerKind::Leak; if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64) Res |= SanitizerKind::Thread; + if (IsX86_64) + Res |= SanitizerKind::KernelMemory; if (IsX86_64 || IsMIPS64) Res |= SanitizerKind::Efficiency; if (IsX86 || IsX86_64) @@ -954,7 +1027,7 @@ void Linux::addProfileRTLibs(const llvm::opt::ArgList &Args, // Add linker option -u__llvm_runtime_variable to cause runtime // initialization module to be linked in. - if (!Args.hasArg(options::OPT_coverage)) + if ((!Args.hasArg(options::OPT_coverage)) && (!Args.hasArg(options::OPT_ftest_coverage))) CmdArgs.push_back(Args.MakeArgString( Twine("-u", llvm::getInstrProfRuntimeHookVarName()))); ToolChain::addProfileRTLibs(Args, CmdArgs); diff --git a/lib/Driver/ToolChains/Linux.h b/lib/Driver/ToolChains/Linux.h index 22dbbecf6b96..4a662cb4b427 100644 --- a/lib/Driver/ToolChains/Linux.h +++ b/lib/Driver/ToolChains/Linux.h @@ -37,7 +37,9 @@ public: llvm::opt::ArgStringList &CC1Args) const override; void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; + CXXStdlibType GetDefaultCXXStdlibType() const override; bool isPIEDefault() const override; + bool IsMathErrnoDefault() const override; SanitizerMask getSupportedSanitizers() const override; void addProfileRTLibs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override; diff --git a/lib/Driver/ToolChains/MSP430.cpp b/lib/Driver/ToolChains/MSP430.cpp new file mode 100644 index 000000000000..b2ff88dbd021 --- /dev/null +++ b/lib/Driver/ToolChains/MSP430.cpp @@ -0,0 +1,233 @@ +//===--- MSP430.cpp - MSP430 Helpers for Tools ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MSP430.h" +#include "CommonArgs.h" +#include "Gnu.h" +#include "InputInfo.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Multilib.h" +#include "clang/Driver/Options.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" + +using namespace clang::driver; +using namespace clang::driver::toolchains; +using namespace clang::driver::tools; +using namespace clang; +using namespace llvm::opt; + +static bool isSupportedMCU(const StringRef MCU) { + return llvm::StringSwitch<bool>(MCU) +#define MSP430_MCU(NAME) .Case(NAME, true) +#include "clang/Basic/MSP430Target.def" + .Default(false); +} + +static StringRef getSupportedHWMult(const Arg *MCU) { + if (!MCU) + return "none"; + + return llvm::StringSwitch<StringRef>(MCU->getValue()) +#define MSP430_MCU_FEAT(NAME, HWMULT) .Case(NAME, HWMULT) +#include "clang/Basic/MSP430Target.def" + .Default("none"); +} + +static StringRef getHWMultLib(const ArgList &Args) { + StringRef HWMult = Args.getLastArgValue(options::OPT_mhwmult_EQ, "auto"); + if (HWMult == "auto") { + HWMult = getSupportedHWMult(Args.getLastArg(options::OPT_mmcu_EQ)); + } + + return llvm::StringSwitch<StringRef>(HWMult) + .Case("16bit", "-lmul_16") + .Case("32bit", "-lmul_32") + .Case("f5series", "-lmul_f5") + .Default("-lmul_none"); +} + +void msp430::getMSP430TargetFeatures(const Driver &D, const ArgList &Args, + std::vector<StringRef> &Features) { + const Arg *MCU = Args.getLastArg(options::OPT_mmcu_EQ); + if (MCU && !isSupportedMCU(MCU->getValue())) { + D.Diag(diag::err_drv_clang_unsupported) << MCU->getValue(); + return; + } + + const Arg *HWMultArg = Args.getLastArg(options::OPT_mhwmult_EQ); + if (!MCU && !HWMultArg) + return; + + StringRef HWMult = HWMultArg ? HWMultArg->getValue() : "auto"; + StringRef SupportedHWMult = getSupportedHWMult(MCU); + + if (HWMult == "auto") { + // 'auto' - deduce hw multiplier support based on mcu name provided. + // If no mcu name is provided, assume no hw multiplier is supported. + if (!MCU) + D.Diag(clang::diag::warn_drv_msp430_hwmult_no_device); + HWMult = SupportedHWMult; + } + + if (HWMult == "none") { + // 'none' - disable hw multiplier. + Features.push_back("-hwmult16"); + Features.push_back("-hwmult32"); + Features.push_back("-hwmultf5"); + return; + } + + if (MCU && SupportedHWMult == "none") + D.Diag(clang::diag::warn_drv_msp430_hwmult_unsupported) << HWMult; + if (MCU && HWMult != SupportedHWMult) + D.Diag(clang::diag::warn_drv_msp430_hwmult_mismatch) + << SupportedHWMult << HWMult; + + if (HWMult == "16bit") { + // '16bit' - for 16-bit only hw multiplier. + Features.push_back("+hwmult16"); + } else if (HWMult == "32bit") { + // '32bit' - for 16/32-bit hw multiplier. + Features.push_back("+hwmult32"); + } else if (HWMult == "f5series") { + // 'f5series' - for 16/32-bit hw multiplier supported by F5 series mcus. + Features.push_back("+hwmultf5"); + } else { + D.Diag(clang::diag::err_drv_unsupported_option_argument) + << HWMultArg->getAsString(Args) << HWMult; + } +} + +/// MSP430 Toolchain +MSP430ToolChain::MSP430ToolChain(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : Generic_ELF(D, Triple, Args) { + + StringRef MultilibSuf = ""; + + GCCInstallation.init(Triple, Args); + if (GCCInstallation.isValid()) { + MultilibSuf = GCCInstallation.getMultilib().gccSuffix(); + + SmallString<128> GCCBinPath; + llvm::sys::path::append(GCCBinPath, + GCCInstallation.getParentLibPath(), "..", "bin"); + addPathIfExists(D, GCCBinPath, getProgramPaths()); + + SmallString<128> GCCRtPath; + llvm::sys::path::append(GCCRtPath, + GCCInstallation.getInstallPath(), MultilibSuf); + addPathIfExists(D, GCCRtPath, getFilePaths()); + } + + SmallString<128> SysRootDir(computeSysRoot()); + llvm::sys::path::append(SysRootDir, "lib", MultilibSuf); + addPathIfExists(D, SysRootDir, getFilePaths()); +} + +std::string MSP430ToolChain::computeSysRoot() const { + if (!getDriver().SysRoot.empty()) + return getDriver().SysRoot; + + SmallString<128> Dir; + if (GCCInstallation.isValid()) + llvm::sys::path::append(Dir, GCCInstallation.getParentLibPath(), "..", + GCCInstallation.getTriple().str()); + else + llvm::sys::path::append(Dir, getDriver().Dir, "..", getTriple().str()); + + return Dir.str(); +} + +void MSP430ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdinc) || + DriverArgs.hasArg(options::OPT_nostdlibinc)) + return; + + SmallString<128> Dir(computeSysRoot()); + llvm::sys::path::append(Dir, "include"); + addSystemInclude(DriverArgs, CC1Args, Dir.str()); +} + +void MSP430ToolChain::addClangTargetOptions(const ArgList &DriverArgs, + ArgStringList &CC1Args, + Action::OffloadKind) const { + CC1Args.push_back("-nostdsysteminc"); + + const auto *MCUArg = DriverArgs.getLastArg(options::OPT_mmcu_EQ); + if (!MCUArg) + return; + + const StringRef MCU = MCUArg->getValue(); + if (MCU.startswith("msp430i")) { + // 'i' should be in lower case as it's defined in TI MSP430-GCC headers + CC1Args.push_back(DriverArgs.MakeArgString( + "-D__MSP430i" + MCU.drop_front(7).upper() + "__")); + } else { + CC1Args.push_back(DriverArgs.MakeArgString("-D__" + MCU.upper() + "__")); + } +} + +Tool *MSP430ToolChain::buildLinker() const { + return new tools::msp430::Linker(*this); +} + +void msp430::Linker::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(); + std::string Linker = ToolChain.GetProgramPath(getShortName()); + ArgStringList CmdArgs; + + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + + Args.AddAllArgs(CmdArgs, options::OPT_L); + ToolChain.AddFilePathLibArgs(Args, CmdArgs); + + if (!Args.hasArg(options::OPT_T)) { + if (const Arg *MCUArg = Args.getLastArg(options::OPT_mmcu_EQ)) + CmdArgs.push_back( + Args.MakeArgString("-T" + StringRef(MCUArg->getValue()) + ".ld")); + } else { + Args.AddAllArgs(CmdArgs, options::OPT_T); + } + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o"))); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o"))); + } + + AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); + + CmdArgs.push_back("--start-group"); + CmdArgs.push_back(Args.MakeArgString(getHWMultLib(Args))); + CmdArgs.push_back("-lgcc"); + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { + CmdArgs.push_back("-lc"); + CmdArgs.push_back("-lcrt"); + CmdArgs.push_back("-lnosys"); + } + CmdArgs.push_back("--end-group"); + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); + } + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), + CmdArgs, Inputs)); +} diff --git a/lib/Driver/ToolChains/MSP430.h b/lib/Driver/ToolChains/MSP430.h new file mode 100644 index 000000000000..0fdceb75b963 --- /dev/null +++ b/lib/Driver/ToolChains/MSP430.h @@ -0,0 +1,71 @@ +//===--- MSP430.h - MSP430-specific Tool Helpers ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSP430_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSP430_H + +#include "Gnu.h" +#include "InputInfo.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Tool.h" +#include "clang/Driver/ToolChain.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Option/Option.h" + +#include <string> +#include <vector> + +namespace clang { +namespace driver { +namespace toolchains { + +class LLVM_LIBRARY_VISIBILITY MSP430ToolChain : public Generic_ELF { +public: + MSP430ToolChain(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + void + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args, + Action::OffloadKind) const override; + +protected: + Tool *buildLinker() const override; + +private: + std::string computeSysRoot() const; +}; + +} // end namespace toolchains + +namespace tools { +namespace msp430 { + +class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool { +public: + Linker(const ToolChain &TC) + : GnuTool("MSP430::Linker", "msp430-elf-ld", TC) {} + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; + +void getMSP430TargetFeatures(const Driver &D, const llvm::opt::ArgList &Args, + std::vector<llvm::StringRef> &Features); +} // end namespace msp430 +} // end namespace tools +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSP430_H diff --git a/lib/Driver/ToolChains/MSVC.cpp b/lib/Driver/ToolChains/MSVC.cpp index d062c6abc955..7e34b0df5c8c 100644 --- a/lib/Driver/ToolChains/MSVC.cpp +++ b/lib/Driver/ToolChains/MSVC.cpp @@ -355,6 +355,15 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, options::OPT__SLASH_Zd)) CmdArgs.push_back("-debug"); + // Pass on /Brepro if it was passed to the compiler. + // Note that /Brepro maps to -mno-incremental-linker-compatible. + bool DefaultIncrementalLinkerCompatible = + C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment(); + if (!Args.hasFlag(options::OPT_mincremental_linker_compatible, + options::OPT_mno_incremental_linker_compatible, + DefaultIncrementalLinkerCompatible)) + CmdArgs.push_back("-Brepro"); + bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd, options::OPT_shared); if (DLL) { @@ -365,6 +374,17 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName)); } + if (TC.getSanitizerArgs().needsFuzzer()) { + if (!Args.hasArg(options::OPT_shared)) + CmdArgs.push_back( + Args.MakeArgString(std::string("-wholearchive:") + + TC.getCompilerRTArgString(Args, "fuzzer", false))); + CmdArgs.push_back(Args.MakeArgString("-debug")); + // Prevent the linker from padding sections we use for instrumentation + // arrays. + CmdArgs.push_back(Args.MakeArgString("-incremental:no")); + } + if (TC.getSanitizerArgs().needsAsanRt()) { CmdArgs.push_back(Args.MakeArgString("-debug")); CmdArgs.push_back(Args.MakeArgString("-incremental:no")); @@ -702,15 +722,15 @@ bool MSVCToolChain::IsIntegratedAssemblerDefault() const { } bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const { - // Emit unwind tables by default on Win64. All non-x86_32 Windows platforms - // such as ARM and PPC actually require unwind tables, but LLVM doesn't know - // how to generate them yet. - // Don't emit unwind tables by default for MachO targets. if (getTriple().isOSBinFormatMachO()) return false; - return getArch() == llvm::Triple::x86_64; + // All non-x86_32 Windows targets require unwind tables. However, LLVM + // doesn't know how to generate them for all targets, so only enable + // the ones that are actually implemented. + return getArch() == llvm::Triple::x86_64 || + getArch() == llvm::Triple::aarch64; } bool MSVCToolChain::isPICDefault() const { @@ -1266,7 +1286,7 @@ VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D, if (MSVT.empty() && Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, IsWindowsMSVC)) { - // -fms-compatibility-version=19.11 is default, aka 2017 + // -fms-compatibility-version=19.11 is default, aka 2017, 15.3 MSVT = VersionTuple(19, 11); } return MSVT; @@ -1298,6 +1318,8 @@ MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args, SanitizerMask MSVCToolChain::getSupportedSanitizers() const { SanitizerMask Res = ToolChain::getSupportedSanitizers(); Res |= SanitizerKind::Address; + Res |= SanitizerKind::Fuzzer; + Res |= SanitizerKind::FuzzerNoLink; Res &= ~SanitizerKind::CFIMFCall; return Res; } @@ -1356,6 +1378,7 @@ static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL, } break; case 'g': + A->claim(); break; case 'i': if (I + 1 != E && OptStr[I + 1] == '-') { diff --git a/lib/Driver/ToolChains/MSVC.h b/lib/Driver/ToolChains/MSVC.h index 1db589ec9706..ebca0018bb85 100644 --- a/lib/Driver/ToolChains/MSVC.h +++ b/lib/Driver/ToolChains/MSVC.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSVC_H #include "Cuda.h" +#include "clang/Basic/DebugInfoOptions.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" @@ -78,6 +79,18 @@ public: bool isPIEDefault() const override; bool isPICDefaultForced() const override; + /// Set CodeView as the default debug info format. Users can use -gcodeview + /// and -gdwarf to override the default. + codegenoptions::DebugInfoFormat getDefaultDebugFormat() const override { + return codegenoptions::DIF_CodeView; + } + + /// Set the debugger tuning to "default", since we're definitely not tuning + /// for GDB. + llvm::DebuggerKind getDefaultDebuggerTuning() const override { + return llvm::DebuggerKind::Default; + } + enum class SubDirectoryType { Bin, Include, diff --git a/lib/Driver/ToolChains/MinGW.cpp b/lib/Driver/ToolChains/MinGW.cpp index a88e00f0c8e8..2d5217d03d3a 100644 --- a/lib/Driver/ToolChains/MinGW.cpp +++ b/lib/Driver/ToolChains/MinGW.cpp @@ -10,10 +10,12 @@ #include "MinGW.h" #include "InputInfo.h" #include "CommonArgs.h" +#include "clang/Config/config.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -52,7 +54,7 @@ void tools::MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_gsplit_dwarf)) SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, - SplitDebugName(Args, Inputs[0])); + SplitDebugName(Args, Output)); } void tools::MinGW::Linker::AddLibGCC(const ArgList &Args, @@ -95,7 +97,7 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, const char *LinkingOutput) const { const ToolChain &TC = getToolChain(); const Driver &D = TC.getDriver(); - // const SanitizerArgs &Sanitize = TC.getSanitizerArgs(); + const SanitizerArgs &Sanitize = TC.getSanitizerArgs(); ArgStringList CmdArgs; @@ -187,8 +189,6 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, TC.AddFilePathLibArgs(Args, CmdArgs); AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); - // TODO: Add ASan stuff here - // TODO: Add profile stuff here if (TC.ShouldLinkCXXStdlib(Args)) { @@ -220,8 +220,24 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-lssp_nonshared"); CmdArgs.push_back("-lssp"); } - if (Args.hasArg(options::OPT_fopenmp)) - CmdArgs.push_back("-lgomp"); + + if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, + options::OPT_fno_openmp, false)) { + switch (TC.getDriver().getOpenMPRuntime(Args)) { + case Driver::OMPRT_OMP: + CmdArgs.push_back("-lomp"); + break; + case Driver::OMPRT_IOMP5: + CmdArgs.push_back("-liomp5md"); + break; + case Driver::OMPRT_GOMP: + CmdArgs.push_back("-lgomp"); + break; + case Driver::OMPRT_Unknown: + // Already diagnosed. + break; + } + } AddLibGCC(Args, CmdArgs); @@ -231,6 +247,24 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_pthread)) CmdArgs.push_back("-lpthread"); + if (Sanitize.needsAsanRt()) { + // MinGW always links against a shared MSVCRT. + CmdArgs.push_back( + TC.getCompilerRTArgString(Args, "asan_dynamic", true)); + CmdArgs.push_back( + TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); + CmdArgs.push_back(Args.MakeArgString("--require-defined")); + CmdArgs.push_back(Args.MakeArgString(TC.getArch() == llvm::Triple::x86 + ? "___asan_seh_interceptor" + : "__asan_seh_interceptor")); + // Make sure the linker consider all object files from the dynamic + // runtime thunk. + CmdArgs.push_back(Args.MakeArgString("--whole-archive")); + CmdArgs.push_back(Args.MakeArgString( + TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk"))); + CmdArgs.push_back(Args.MakeArgString("--no-whole-archive")); + } + if (!HasWindowsApp) { // Add system libraries. If linking to libwindowsapp.a, that import // library replaces all these and we shouldn't accidentally try to @@ -359,6 +393,10 @@ toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, getFilePaths().push_back(Base + "lib"); // openSUSE getFilePaths().push_back(Base + Arch + "/sys-root/mingw/lib"); + + NativeLLVMSupport = + Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER) + .equals_lower("lld"); } bool toolchains::MinGW::IsIntegratedAssemblerDefault() const { return true; } @@ -386,7 +424,17 @@ Tool *toolchains::MinGW::buildLinker() const { return new tools::MinGW::Linker(*this); } +bool toolchains::MinGW::HasNativeLLVMSupport() const { + return NativeLLVMSupport; +} + bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList &Args) const { + Arg *ExceptionArg = Args.getLastArg(options::OPT_fsjlj_exceptions, + options::OPT_fseh_exceptions, + options::OPT_fdwarf_exceptions); + if (ExceptionArg && + ExceptionArg->getOption().matches(options::OPT_fseh_exceptions)) + return true; return getArch() == llvm::Triple::x86_64; } @@ -407,6 +455,12 @@ toolchains::MinGW::GetExceptionModel(const ArgList &Args) const { return llvm::ExceptionHandling::DwarfCFI; } +SanitizerMask toolchains::MinGW::getSupportedSanitizers() const { + SanitizerMask Res = ToolChain::getSupportedSanitizers(); + Res |= SanitizerKind::Address; + return Res; +} + void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); diff --git a/lib/Driver/ToolChains/MinGW.h b/lib/Driver/ToolChains/MinGW.h index 0c3919d29f77..04d23006ee75 100644 --- a/lib/Driver/ToolChains/MinGW.h +++ b/lib/Driver/ToolChains/MinGW.h @@ -59,12 +59,16 @@ public: MinGW(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); + bool HasNativeLLVMSupport() const override; + bool IsIntegratedAssemblerDefault() const override; bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override; bool isPICDefault() const override; bool isPIEDefault() const override; bool isPICDefaultForced() const override; + SanitizerMask getSupportedSanitizers() const override; + llvm::ExceptionHandling GetExceptionModel( const llvm::opt::ArgList &Args) const override; @@ -97,6 +101,8 @@ private: void findGccLibDir(); llvm::ErrorOr<std::string> findGcc(); llvm::ErrorOr<std::string> findClangRelativeSysroot(); + + bool NativeLLVMSupport; }; } // end namespace toolchains diff --git a/lib/Driver/ToolChains/Minix.cpp b/lib/Driver/ToolChains/Minix.cpp index 39e6f90b6ef0..7fadcb129d46 100644 --- a/lib/Driver/ToolChains/Minix.cpp +++ b/lib/Driver/ToolChains/Minix.cpp @@ -8,13 +8,13 @@ //===----------------------------------------------------------------------===// #include "Minix.h" -#include "InputInfo.h" #include "CommonArgs.h" -#include "clang/Basic/VirtualFileSystem.h" +#include "InputInfo.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" #include "clang/Driver/Options.h" #include "llvm/Option/ArgList.h" +#include "llvm/Support/VirtualFileSystem.h" using namespace clang::driver; using namespace clang; diff --git a/lib/Driver/ToolChains/MipsLinux.h b/lib/Driver/ToolChains/MipsLinux.h index d4b476d883e6..edf58a62b95c 100644 --- a/lib/Driver/ToolChains/MipsLinux.h +++ b/lib/Driver/ToolChains/MipsLinux.h @@ -49,7 +49,7 @@ public: } const char *getDefaultLinker() const override { - return "lld"; + return "ld.lld"; } private: diff --git a/lib/Driver/ToolChains/NetBSD.cpp b/lib/Driver/ToolChains/NetBSD.cpp index 02caafda1657..b1321cacaf7a 100644 --- a/lib/Driver/ToolChains/NetBSD.cpp +++ b/lib/Driver/ToolChains/NetBSD.cpp @@ -164,7 +164,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, break; case llvm::Triple::armeb: case llvm::Triple::thumbeb: - arm::appendEBLinkFlags(Args, CmdArgs, ToolChain.getEffectiveTriple()); + arm::appendBE8LinkFlag(Args, CmdArgs, ToolChain.getEffectiveTriple()); CmdArgs.push_back("-m"); switch (ToolChain.getTriple().getEnvironment()) { case llvm::Triple::EABI: @@ -448,12 +448,24 @@ SanitizerMask NetBSD::getSupportedSanitizers() const { Res |= SanitizerKind::Vptr; } if (IsX86_64) { + Res |= SanitizerKind::DataFlow; Res |= SanitizerKind::Efficiency; Res |= SanitizerKind::Fuzzer; Res |= SanitizerKind::FuzzerNoLink; + Res |= SanitizerKind::HWAddress; Res |= SanitizerKind::KernelAddress; + Res |= SanitizerKind::KernelHWAddress; + Res |= SanitizerKind::KernelMemory; Res |= SanitizerKind::Memory; Res |= SanitizerKind::Thread; } return Res; } + +void NetBSD::addClangTargetOptions(const ArgList &, + ArgStringList &CC1Args, + Action::OffloadKind) const { + const SanitizerArgs &SanArgs = getSanitizerArgs(); + if (SanArgs.hasAnySanitizer()) + CC1Args.push_back("-D_REENTRANT"); +} diff --git a/lib/Driver/ToolChains/NetBSD.h b/lib/Driver/ToolChains/NetBSD.h index 49e3a58d02c3..ae0865fd6573 100644 --- a/lib/Driver/ToolChains/NetBSD.h +++ b/lib/Driver/ToolChains/NetBSD.h @@ -76,6 +76,10 @@ public: SanitizerMask getSupportedSanitizers() const override; + void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args, + Action::OffloadKind DeviceOffloadKind) const override; + protected: Tool *buildAssembler() const override; Tool *buildLinker() const override; diff --git a/lib/Driver/ToolChains/OpenBSD.cpp b/lib/Driver/ToolChains/OpenBSD.cpp index 7b98cd62bbfc..3d35d37b7db3 100644 --- a/lib/Driver/ToolChains/OpenBSD.cpp +++ b/lib/Driver/ToolChains/OpenBSD.cpp @@ -111,9 +111,9 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, // handled somewhere else. Args.ClaimAllArgs(options::OPT_w); - if (getToolChain().getArch() == llvm::Triple::mips64) + if (ToolChain.getArch() == llvm::Triple::mips64) CmdArgs.push_back("-EB"); - else if (getToolChain().getArch() == llvm::Triple::mips64el) + else if (ToolChain.getArch() == llvm::Triple::mips64el) CmdArgs.push_back("-EL"); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) { @@ -138,7 +138,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_pie)) CmdArgs.push_back("-pie"); - if (Args.hasArg(options::OPT_nopie)) + if (Args.hasArg(options::OPT_nopie) || Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-nopie"); if (Output.isFilename()) { @@ -149,44 +149,40 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { + const char *crt0 = nullptr; + const char *crtbegin = nullptr; if (!Args.hasArg(options::OPT_shared)) { if (Args.hasArg(options::OPT_pg)) - CmdArgs.push_back( - Args.MakeArgString(getToolChain().GetFilePath("gcrt0.o"))); + crt0 = "gcrt0.o"; else if (Args.hasArg(options::OPT_static) && !Args.hasArg(options::OPT_nopie)) - CmdArgs.push_back( - Args.MakeArgString(getToolChain().GetFilePath("rcrt0.o"))); + crt0 = "rcrt0.o"; else - CmdArgs.push_back( - Args.MakeArgString(getToolChain().GetFilePath("crt0.o"))); - CmdArgs.push_back( - Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o"))); + crt0 = "crt0.o"; + crtbegin = "crtbegin.o"; } else { - CmdArgs.push_back( - Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o"))); + crtbegin = "crtbeginS.o"; } - } - std::string Triple = getToolChain().getTripleString(); - if (Triple.substr(0, 6) == "x86_64") - Triple.replace(0, 6, "amd64"); - CmdArgs.push_back( - Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple + "/4.2.1")); - CmdArgs.push_back(Args.MakeArgString("-L/usr/lib")); + if (crt0) + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt0))); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); + } - Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, - options::OPT_e, options::OPT_s, options::OPT_t, + Args.AddAllArgs(CmdArgs, options::OPT_L); + ToolChain.AddFilePathLibArgs(Args, CmdArgs); + Args.AddAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_e, + options::OPT_s, options::OPT_t, options::OPT_Z_Flag, options::OPT_r}); bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs); bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); - AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { if (D.CCCIsCXX()) { - if (getToolChain().ShouldLinkCXXStdlib(Args)) - getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); + if (ToolChain.ShouldLinkCXXStdlib(Args)) + ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lm_p"); else @@ -202,7 +198,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, } // FIXME: For some reason GCC passes -lgcc before adding // the default system libraries. Just mimic this for now. - CmdArgs.push_back("-lgcc"); + CmdArgs.push_back("-lcompiler_rt"); if (Args.hasArg(options::OPT_pthread)) { if (!Args.hasArg(options::OPT_shared) && Args.hasArg(options::OPT_pg)) @@ -218,21 +214,22 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-lc"); } - CmdArgs.push_back("-lgcc"); + CmdArgs.push_back("-lcompiler_rt"); } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { + const char *crtend = nullptr; if (!Args.hasArg(options::OPT_shared)) - CmdArgs.push_back( - Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); + crtend = "crtend.o"; else - CmdArgs.push_back( - Args.MakeArgString(getToolChain().GetFilePath("crtendS.o"))); + crtend = "crtendS.o"; + + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend))); } const char *Exec = Args.MakeArgString( - !NeedsSanitizerDeps ? getToolChain().GetLinkerPath() - : getToolChain().GetProgramPath("ld.lld")); + !NeedsSanitizerDeps ? ToolChain.GetLinkerPath() + : ToolChain.GetProgramPath("ld.lld")); C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } @@ -257,8 +254,7 @@ SanitizerMask OpenBSD::getSupportedSanitizers() const { OpenBSD::OpenBSD(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : Generic_ELF(D, Triple, Args) { - getFilePaths().push_back(getDriver().Dir + "/../lib"); - getFilePaths().push_back("/usr/lib"); + getFilePaths().push_back(getDriver().SysRoot + "/usr/lib"); } void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args, diff --git a/lib/Driver/ToolChains/OpenBSD.h b/lib/Driver/ToolChains/OpenBSD.h index bf8dfa4653cb..1912abdb95bc 100644 --- a/lib/Driver/ToolChains/OpenBSD.h +++ b/lib/Driver/ToolChains/OpenBSD.h @@ -58,6 +58,14 @@ public: bool IsMathErrnoDefault() const override { return false; } bool IsObjCNonFragileABIDefault() const override { return true; } bool isPIEDefault() const override { return true; } + + RuntimeLibType GetDefaultRuntimeLibType() const override { + return ToolChain::RLT_CompilerRT; + } + CXXStdlibType GetDefaultCXXStdlibType() const override { + return ToolChain::CST_Libcxx; + } + void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override; diff --git a/lib/Driver/ToolChains/PS4CPU.cpp b/lib/Driver/ToolChains/PS4CPU.cpp index a4b74d492331..0708d25fe45c 100644 --- a/lib/Driver/ToolChains/PS4CPU.cpp +++ b/lib/Driver/ToolChains/PS4CPU.cpp @@ -121,7 +121,8 @@ static void ConstructPS4LinkJob(const Tool &T, Compilation &C, assert(Output.isNothing() && "Invalid output."); } - AddPS4SanitizerArgs(ToolChain, CmdArgs); + if(!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) + AddPS4SanitizerArgs(ToolChain, CmdArgs); Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); @@ -190,7 +191,8 @@ static void ConstructGoldLinkJob(const Tool &T, Compilation &C, assert(Output.isNothing() && "Invalid output."); } - AddPS4SanitizerArgs(ToolChain, CmdArgs); + if(!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) + AddPS4SanitizerArgs(ToolChain, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { const char *crt1 = nullptr; diff --git a/lib/Driver/ToolChains/RISCV.cpp b/lib/Driver/ToolChains/RISCVToolchain.cpp index 31996fc588f1..e787c82b28a8 100644 --- a/lib/Driver/ToolChains/RISCV.cpp +++ b/lib/Driver/ToolChains/RISCVToolchain.cpp @@ -1,4 +1,4 @@ -//===--- RISCV.cpp - RISCV ToolChain Implementations ------------*- C++ -*-===// +//===--- RISCVToolchain.cpp - RISCV ToolChain Implementations ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,12 +7,13 @@ // //===----------------------------------------------------------------------===// -#include "RISCV.h" +#include "RISCVToolchain.h" #include "CommonArgs.h" #include "InputInfo.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Options.h" #include "llvm/Option/ArgList.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -27,7 +28,7 @@ RISCVToolChain::RISCVToolChain(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : Generic_ELF(D, Triple, Args) { GCCInstallation.init(Triple, Args); - getFilePaths().push_back(D.SysRoot + "/lib"); + getFilePaths().push_back(computeSysRoot() + "/lib"); if (GCCInstallation.isValid()) { getFilePaths().push_back(GCCInstallation.getInstallPath().str()); getProgramPaths().push_back( @@ -39,13 +40,21 @@ Tool *RISCVToolChain::buildLinker() const { return new tools::RISCV::Linker(*this); } +void RISCVToolChain::addClangTargetOptions( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args, + Action::OffloadKind) const { + CC1Args.push_back("-nostdsysteminc"); + CC1Args.push_back("-fuse-init-array"); +} + void RISCVToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { if (DriverArgs.hasArg(options::OPT_nostdinc)) return; if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) { - SmallString<128> Dir(getDriver().SysRoot); + SmallString<128> Dir(computeSysRoot()); llvm::sys::path::append(Dir, "include"); addSystemInclude(DriverArgs, CC1Args, Dir.str()); } @@ -54,15 +63,30 @@ void RISCVToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, void RISCVToolChain::addLibStdCxxIncludePaths( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const { - StringRef LibDir = GCCInstallation.getParentLibPath(); const GCCVersion &Version = GCCInstallation.getVersion(); StringRef TripleStr = GCCInstallation.getTriple().str(); const Multilib &Multilib = GCCInstallation.getMultilib(); - addLibStdCXXIncludePaths( - LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text, + addLibStdCXXIncludePaths(computeSysRoot() + "/include/c++/" + Version.Text, "", TripleStr, "", "", Multilib.includeSuffix(), DriverArgs, CC1Args); } +std::string RISCVToolChain::computeSysRoot() const { + if (!getDriver().SysRoot.empty()) + return getDriver().SysRoot; + + if (!GCCInstallation.isValid()) + return std::string(); + + StringRef LibDir = GCCInstallation.getParentLibPath(); + StringRef TripleStr = GCCInstallation.getTriple().str(); + std::string SysRootDir = LibDir.str() + "/../" + TripleStr.str(); + + if (!llvm::sys::fs::exists(SysRootDir)) + return std::string(); + + return SysRootDir; +} + void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, diff --git a/lib/Driver/ToolChains/RISCV.h b/lib/Driver/ToolChains/RISCVToolchain.h index 6f59d84020d8..4b38690b1b61 100644 --- a/lib/Driver/ToolChains/RISCV.h +++ b/lib/Driver/ToolChains/RISCVToolchain.h @@ -1,4 +1,4 @@ -//===--- RISCV.h - RISCV ToolChain Implementations --------------*- C++ -*-===// +//===--- RISCVToolchain.h - RISCV ToolChain Implementations -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCV_H -#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCV_H +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCVTOOLCHAIN_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCVTOOLCHAIN_H #include "Gnu.h" #include "clang/Driver/ToolChain.h" @@ -23,6 +23,9 @@ public: const llvm::opt::ArgList &Args); bool IsIntegratedAssemblerDefault() const override { return true; } + void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args, + Action::OffloadKind) const override; void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; @@ -32,6 +35,9 @@ public: protected: Tool *buildLinker() const override; + +private: + std::string computeSysRoot() const; }; } // end namespace toolchains @@ -54,4 +60,4 @@ public: } // end namespace driver } // end namespace clang -#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCV_H +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_RISCVTOOLCHAIN_H diff --git a/lib/Driver/ToolChains/Solaris.h b/lib/Driver/ToolChains/Solaris.h index 9e14269b393e..4d9c828b5c6b 100644 --- a/lib/Driver/ToolChains/Solaris.h +++ b/lib/Driver/ToolChains/Solaris.h @@ -55,8 +55,6 @@ public: Solaris(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); - bool IsIntegratedAssemblerDefault() const override { return true; } - void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; diff --git a/lib/Driver/ToolChains/WebAssembly.cpp b/lib/Driver/ToolChains/WebAssembly.cpp index 94f7279bbdba..6310d5fabaec 100644 --- a/lib/Driver/ToolChains/WebAssembly.cpp +++ b/lib/Driver/ToolChains/WebAssembly.cpp @@ -22,15 +22,20 @@ using namespace clang; using namespace llvm::opt; wasm::Linker::Linker(const ToolChain &TC) - : GnuTool("wasm::Linker", "lld", TC) {} - -bool wasm::Linker::isLinkJob() const { - return true; + : GnuTool("wasm::Linker", "lld", TC) {} + +/// Following the conventions in https://wiki.debian.org/Multiarch/Tuples, +/// we remove the vendor field to form the multiarch triple. +static std::string getMultiarchTriple(const Driver &D, + const llvm::Triple &TargetTriple, + StringRef SysRoot) { + return (TargetTriple.getArchName() + "-" + + TargetTriple.getOSAndEnvironmentName()).str(); } -bool wasm::Linker::hasIntegratedCPP() const { - return false; -} +bool wasm::Linker::isLinkJob() const { return true; } + +bool wasm::Linker::hasIntegratedCPP() const { return false; } void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, @@ -41,8 +46,6 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA, const ToolChain &ToolChain = getToolChain(); const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath()); ArgStringList CmdArgs; - CmdArgs.push_back("-flavor"); - CmdArgs.push_back("wasm"); if (Args.hasArg(options::OPT_s)) CmdArgs.push_back("--strip-all"); @@ -75,13 +78,23 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA, WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args) - : ToolChain(D, Triple, Args) { + : ToolChain(D, Triple, Args) { assert(Triple.isArch32Bit() != Triple.isArch64Bit()); getProgramPaths().push_back(getDriver().getInstalledDir()); - getFilePaths().push_back(getDriver().SysRoot + "/lib"); + if (getTriple().getOS() == llvm::Triple::UnknownOS) { + // Theoretically an "unknown" OS should mean no standard libraries, however + // it could also mean that a custom set of libraries is in use, so just add + // /lib to the search path. Disable multiarch in this case, to discourage + // paths containing "unknown" from acquiring meanings. + getFilePaths().push_back(getDriver().SysRoot + "/lib"); + } else { + const std::string MultiarchTriple = + getMultiarchTriple(getDriver(), Triple, getDriver().SysRoot); + getFilePaths().push_back(getDriver().SysRoot + "/lib/" + MultiarchTriple); + } } bool WebAssembly::IsMathErrnoDefault() const { return false; } @@ -117,7 +130,8 @@ ToolChain::RuntimeLibType WebAssembly::GetDefaultRuntimeLibType() const { return ToolChain::RLT_CompilerRT; } -ToolChain::CXXStdlibType WebAssembly::GetCXXStdlibType(const ArgList &Args) const { +ToolChain::CXXStdlibType +WebAssembly::GetCXXStdlibType(const ArgList &Args) const { if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { StringRef Value = A->getValue(); if (Value != "libc++") @@ -129,16 +143,29 @@ ToolChain::CXXStdlibType WebAssembly::GetCXXStdlibType(const ArgList &Args) cons void WebAssembly::AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { - if (!DriverArgs.hasArg(options::OPT_nostdinc)) + if (!DriverArgs.hasArg(options::OPT_nostdinc)) { + if (getTriple().getOS() != llvm::Triple::UnknownOS) { + const std::string MultiarchTriple = + getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot); + addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include/" + MultiarchTriple); + } addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include"); + } } void WebAssembly::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { if (!DriverArgs.hasArg(options::OPT_nostdlibinc) && - !DriverArgs.hasArg(options::OPT_nostdincxx)) + !DriverArgs.hasArg(options::OPT_nostdincxx)) { + if (getTriple().getOS() != llvm::Triple::UnknownOS) { + const std::string MultiarchTriple = + getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot); + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/include/" + MultiarchTriple + "/c++/v1"); + } addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include/c++/v1"); + } } void WebAssembly::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, diff --git a/lib/Driver/ToolChains/WebAssembly.h b/lib/Driver/ToolChains/WebAssembly.h index cdbb34ff919f..d795bad90020 100644 --- a/lib/Driver/ToolChains/WebAssembly.h +++ b/lib/Driver/ToolChains/WebAssembly.h @@ -51,14 +51,15 @@ private: bool hasBlocksRuntime() const override; bool SupportsProfiling() const override; bool HasNativeLLVMSupport() const override; - void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args, - Action::OffloadKind DeviceOffloadKind) const override; + void + addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args, + Action::OffloadKind DeviceOffloadKind) const override; RuntimeLibType GetDefaultRuntimeLibType() const override; CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override; - void AddClangSystemIncludeArgs( - const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const override; + void + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; void AddClangCXXStdlibIncludeArgs( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; @@ -66,9 +67,7 @@ private: llvm::opt::ArgStringList &CmdArgs) const override; std::string getThreadModel() const override; - const char *getDefaultLinker() const override { - return "lld"; - } + const char *getDefaultLinker() const override { return "wasm-ld"; } Tool *buildLinker() const override; }; |