diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-10-23 17:52:09 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-10-23 17:52:09 +0000 |
commit | 519fc96c475680de2cc49e7811dbbfadb912cbcc (patch) | |
tree | 310ca684459b7e9ae13c9a3b9abf308b3a634afe /lib/Driver/ToolChains | |
parent | 2298981669bf3bd63335a4be179bc0f96823a8f4 (diff) |
Notes
Diffstat (limited to 'lib/Driver/ToolChains')
49 files changed, 1114 insertions, 748 deletions
diff --git a/lib/Driver/ToolChains/AMDGPU.cpp b/lib/Driver/ToolChains/AMDGPU.cpp index df4e7ee202bfd..71a2c68b4197b 100644 --- a/lib/Driver/ToolChains/AMDGPU.cpp +++ b/lib/Driver/ToolChains/AMDGPU.cpp @@ -31,7 +31,7 @@ void amdgpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-shared"); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), CmdArgs, Inputs)); } diff --git a/lib/Driver/ToolChains/AVR.cpp b/lib/Driver/ToolChains/AVR.cpp index 4a60d9ec589b7..e8a3a7b38c31f 100644 --- a/lib/Driver/ToolChains/AVR.cpp +++ b/lib/Driver/ToolChains/AVR.cpp @@ -144,7 +144,7 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName)); } - C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), CmdArgs, Inputs)); } diff --git a/lib/Driver/ToolChains/Ananas.cpp b/lib/Driver/ToolChains/Ananas.cpp index e3511198cb2d8..2f11c9739a0eb 100644 --- a/lib/Driver/ToolChains/Ananas.cpp +++ b/lib/Driver/ToolChains/Ananas.cpp @@ -39,7 +39,7 @@ void ananas::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -123,7 +123,7 @@ void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } // Ananas - Ananas tool chain which can call as(1) and ld(1) directly. diff --git a/lib/Driver/ToolChains/Arch/AArch64.cpp b/lib/Driver/ToolChains/Arch/AArch64.cpp index 35d11f4e2d3b3..3a5fe6ddeaed5 100644 --- a/lib/Driver/ToolChains/Arch/AArch64.cpp +++ b/lib/Driver/ToolChains/Arch/AArch64.cpp @@ -12,6 +12,7 @@ #include "clang/Driver/Options.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/TargetParser.h" +#include "llvm/Support/Host.h" using namespace clang::driver; using namespace clang::driver::tools; diff --git a/lib/Driver/ToolChains/Arch/ARM.cpp b/lib/Driver/ToolChains/Arch/ARM.cpp index d1db583e52802..68a57310ad402 100644 --- a/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/lib/Driver/ToolChains/Arch/ARM.cpp @@ -13,6 +13,7 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/TargetParser.h" +#include "llvm/Support/Host.h" using namespace clang::driver; using namespace clang::driver::tools; @@ -460,11 +461,12 @@ fp16_fml_fallthrough: // now just be explicit and disable all known dependent features // as well. for (std::string Feature : { - "vfp2", "vfp2sp", "vfp2d16", "vfp2d16sp", + "vfp2", "vfp2sp", "vfp3", "vfp3sp", "vfp3d16", "vfp3d16sp", "vfp4", "vfp4sp", "vfp4d16", "vfp4d16sp", "fp-armv8", "fp-armv8sp", "fp-armv8d16", "fp-armv8d16sp", "fullfp16", "neon", "crypto", "dotprod", "fp16fml", + "mve", "mve.fp", "fp64", "d32", "fpregs"}) Features.push_back(Args.MakeArgString("-" + Feature)); } @@ -477,23 +479,35 @@ fp16_fml_fallthrough: Features.push_back("-crc"); } - // For Arch >= ARMv8.0: crypto = sha2 + aes + // For Arch >= ARMv8.0 && A profile: 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"); + auto CryptoIt = llvm::find_if(llvm::reverse(Features), [](const StringRef F) { + return F.contains("crypto"); + }); + if (CryptoIt != Features.rend()) { + if (CryptoIt->take_front() == "+") { + StringRef ArchSuffix = arm::getLLVMArchSuffixForARM( + arm::getARMTargetCPU(CPUName, ArchName, Triple), ArchName, Triple); + if (llvm::ARM::parseArchVersion(ArchSuffix) >= 8 && + llvm::ARM::parseArchProfile(ArchSuffix) == + llvm::ARM::ProfileKind::A) { + if (ArchName.find_lower("+nosha2") == StringRef::npos && + CPUName.find_lower("+nosha2") == StringRef::npos) + Features.push_back("+sha2"); + if (ArchName.find_lower("+noaes") == StringRef::npos && + CPUName.find_lower("+noaes") == StringRef::npos) + Features.push_back("+aes"); + } else { + D.Diag(clang::diag::warn_target_unsupported_extension) + << "crypto" + << llvm::ARM::getArchName(llvm::ARM::parseArch(ArchSuffix)); + // With -fno-integrated-as -mfpu=crypto-neon-fp-armv8 some assemblers such as the GNU assembler + // will permit the use of crypto instructions as the fpu will override the architecture. + // We keep the crypto feature in this case to preserve compatibility. + // In all other cases we remove the crypto feature. + if (!Args.hasArg(options::OPT_fno_integrated_as)) + Features.push_back("-crypto"); + } } } @@ -655,7 +669,7 @@ std::string arm::getARMTargetCPU(StringRef CPU, StringRef Arch, llvm::ARM::ArchKind arm::getLLVMArchKindForARM(StringRef CPU, StringRef Arch, const llvm::Triple &Triple) { llvm::ARM::ArchKind ArchKind; - if (CPU == "generic") { + if (CPU == "generic" || CPU.empty()) { std::string ARMArch = tools::arm::getARMArch(Arch, Triple); ArchKind = llvm::ARM::parseArch(ARMArch); if (ArchKind == llvm::ARM::ArchKind::INVALID) diff --git a/lib/Driver/ToolChains/Arch/Mips.cpp b/lib/Driver/ToolChains/Arch/Mips.cpp index b512ff64b0c62..7b4dd703c0c7e 100644 --- a/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/lib/Driver/ToolChains/Arch/Mips.cpp @@ -149,7 +149,8 @@ StringRef mips::getGnuCompatibleMipsABIName(StringRef ABI) { // Select the MIPS float ABI as determined by -msoft-float, -mhard-float, // and -mfloat-abi=. -mips::FloatABI mips::getMipsFloatABI(const Driver &D, const ArgList &Args) { +mips::FloatABI mips::getMipsFloatABI(const Driver &D, const ArgList &Args, + const llvm::Triple &Triple) { mips::FloatABI ABI = mips::FloatABI::Invalid; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, @@ -172,10 +173,15 @@ mips::FloatABI mips::getMipsFloatABI(const Driver &D, const ArgList &Args) { // If unspecified, choose the default based on the platform. if (ABI == mips::FloatABI::Invalid) { - // Assume "hard", because it's a default value used by gcc. - // When we start to recognize specific target MIPS processors, - // we will be able to select the default more correctly. - ABI = mips::FloatABI::Hard; + if (Triple.isOSFreeBSD()) { + // For FreeBSD, assume "soft" on all flavors of MIPS. + ABI = mips::FloatABI::Soft; + } else { + // Assume "hard", because it's a default value used by gcc. + // When we start to recognize specific target MIPS processors, + // we will be able to select the default more correctly. + ABI = mips::FloatABI::Hard; + } } assert(ABI != mips::FloatABI::Invalid && "must select an ABI"); @@ -267,7 +273,14 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, D.Diag(diag::warn_drv_unsupported_longcalls) << (ABICallsArg ? 0 : 1); } - mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args); + if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) { + if (A->getOption().matches(options::OPT_mxgot)) + Features.push_back("+xgot"); + else + Features.push_back("-xgot"); + } + + mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args, Triple); if (FloatABI == mips::FloatABI::Soft) { // FIXME: Note, this is a hack. We need to pass the selected float // mode to the MipsTargetInfoBase to define appropriate macros there. diff --git a/lib/Driver/ToolChains/Arch/Mips.h b/lib/Driver/ToolChains/Arch/Mips.h index 23e0cf79e154f..074012f40fe58 100644 --- a/lib/Driver/ToolChains/Arch/Mips.h +++ b/lib/Driver/ToolChains/Arch/Mips.h @@ -38,7 +38,8 @@ void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args, std::vector<StringRef> &Features); StringRef getGnuCompatibleMipsABIName(StringRef ABI); -mips::FloatABI getMipsFloatABI(const Driver &D, const llvm::opt::ArgList &Args); +mips::FloatABI getMipsFloatABI(const Driver &D, const llvm::opt::ArgList &Args, + const llvm::Triple &Triple); std::string getMipsABILibSuffix(const llvm::opt::ArgList &Args, const llvm::Triple &Triple); bool hasMipsAbiArg(const llvm::opt::ArgList &Args, const char *Value); diff --git a/lib/Driver/ToolChains/Arch/PPC.cpp b/lib/Driver/ToolChains/Arch/PPC.cpp index 30f1a0d9022c2..3e02e57e0f6c7 100644 --- a/lib/Driver/ToolChains/Arch/PPC.cpp +++ b/lib/Driver/ToolChains/Arch/PPC.cpp @@ -13,6 +13,7 @@ #include "clang/Driver/Options.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Option/ArgList.h" +#include "llvm/Support/Host.h" using namespace clang::driver; using namespace clang::driver::tools; @@ -115,7 +116,8 @@ ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const llvm::Tripl const ArgList &Args) { if (Args.getLastArg(options::OPT_msecure_plt)) return ppc::ReadGOTPtrMode::SecurePlt; - if (Triple.isOSNetBSD() || Triple.isOSOpenBSD() || Triple.isMusl()) + if ((Triple.isOSFreeBSD() && Triple.getOSMajorVersion() >= 13) || + Triple.isOSNetBSD() || Triple.isOSOpenBSD() || Triple.isMusl()) return ppc::ReadGOTPtrMode::SecurePlt; else return ppc::ReadGOTPtrMode::Bss; diff --git a/lib/Driver/ToolChains/Arch/RISCV.cpp b/lib/Driver/ToolChains/Arch/RISCV.cpp index b6768de4d2991..624788a5874e3 100644 --- a/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -12,6 +12,7 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "llvm/Option/ArgList.h" +#include "llvm/ADT/Optional.h" #include "llvm/Support/TargetParser.h" #include "llvm/Support/raw_ostream.h" #include "ToolChains/CommonArgs.h" @@ -189,168 +190,182 @@ static void getExtensionFeatures(const Driver &D, } } -void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args, - std::vector<StringRef> &Features) { - if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - StringRef MArch = A->getValue(); +// Returns false if an error is diagnosed. +static bool getArchFeatures(const Driver &D, StringRef MArch, + std::vector<StringRef> &Features, + const ArgList &Args) { + // RISC-V ISA strings must be lowercase. + if (llvm::any_of(MArch, [](char c) { return isupper(c); })) { + D.Diag(diag::err_drv_invalid_riscv_arch_name) + << MArch << "string must be lowercase"; + return false; + } - // RISC-V ISA strings must be lowercase. - if (llvm::any_of(MArch, [](char c) { return isupper(c); })) { - D.Diag(diag::err_drv_invalid_riscv_arch_name) - << MArch << "string must be lowercase"; - return; - } + // ISA string must begin with rv32 or rv64. + if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) || + (MArch.size() < 5)) { + D.Diag(diag::err_drv_invalid_riscv_arch_name) + << MArch << "string must begin with rv32{i,e,g} or rv64{i,g}"; + return false; + } - // ISA string must begin with rv32 or rv64. - if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) || - (MArch.size() < 5)) { - D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch - << "string must begin with rv32{i,e,g} or rv64{i,g}"; - return; - } + bool HasRV64 = MArch.startswith("rv64"); + + // The canonical order specified in ISA manual. + // Ref: Table 22.1 in RISC-V User-Level ISA V2.2 + StringRef StdExts = "mafdqlcbjtpvn"; + bool HasF = false, HasD = false; + char Baseline = MArch[4]; + + // First letter should be 'e', 'i' or 'g'. + switch (Baseline) { + default: + D.Diag(diag::err_drv_invalid_riscv_arch_name) + << MArch << "first letter should be 'e', 'i' or 'g'"; + return false; + case 'e': { + StringRef Error; + // Currently LLVM does not support 'e'. + // Extension 'e' is not allowed in rv64. + if (HasRV64) + Error = "standard user-level extension 'e' requires 'rv32'"; + else + Error = "unsupported standard user-level extension 'e'"; + D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch << Error; + return false; + } + case 'i': + break; + case 'g': + // g = imafd + StdExts = StdExts.drop_front(4); + Features.push_back("+m"); + Features.push_back("+a"); + Features.push_back("+f"); + Features.push_back("+d"); + HasF = true; + HasD = true; + break; + } - bool HasRV64 = MArch.startswith("rv64"); + // Skip rvxxx + StringRef Exts = MArch.substr(5); + + // Remove non-standard extensions and supervisor-level extensions. + // They have 'x', 's', 'sx' prefixes. Parse them at the end. + // Find the very first occurrence of 's' or 'x'. + StringRef OtherExts; + size_t Pos = Exts.find_first_of("sx"); + if (Pos != StringRef::npos) { + OtherExts = Exts.substr(Pos); + Exts = Exts.substr(0, Pos); + } - // The canonical order specified in ISA manual. - // Ref: Table 22.1 in RISC-V User-Level ISA V2.2 - StringRef StdExts = "mafdqlcbjtpvn"; - bool HasF = false, HasD = false; - char Baseline = MArch[4]; + std::string Major, Minor; + if (!getExtensionVersion(D, MArch, std::string(1, Baseline), Exts, Major, + Minor)) + return false; - // First letter should be 'e', 'i' or 'g'. - switch (Baseline) { - default: - D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch - << "first letter should be 'e', 'i' or 'g'"; - return; - case 'e': { + // TODO: Use version number when setting target features + // and consume the underscore '_' that might follow. + + auto StdExtsItr = StdExts.begin(); + auto StdExtsEnd = StdExts.end(); + + for (auto I = Exts.begin(), E = Exts.end(); I != E; ++I) { + char c = *I; + + // Check ISA extensions are specified in the canonical order. + while (StdExtsItr != StdExtsEnd && *StdExtsItr != c) + ++StdExtsItr; + + if (StdExtsItr == StdExtsEnd) { + // Either c contains a valid extension but it was not given in + // canonical order or it is an invalid extension. StringRef Error; - // Currently LLVM does not support 'e'. - // Extension 'e' is not allowed in rv64. - if (HasRV64) - Error = "standard user-level extension 'e' requires 'rv32'"; + if (StdExts.contains(c)) + Error = "standard user-level extension not given in canonical order"; else - Error = "unsupported standard user-level extension 'e'"; - D.Diag(diag::err_drv_invalid_riscv_arch_name) - << MArch << Error; - return; + Error = "invalid standard user-level extension"; + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << Error << std::string(1, c); + return false; } - case 'i': - break; - case 'g': - // g = imafd - StdExts = StdExts.drop_front(4); + + // Move to next char to prevent repeated letter. + ++StdExtsItr; + + if (std::next(I) != E) { + // Skip c. + std::string Next = std::string(std::next(I), E); + std::string Major, Minor; + if (!getExtensionVersion(D, MArch, std::string(1, c), Next, Major, Minor)) + return false; + + // TODO: Use version number when setting target features + // and consume the underscore '_' that might follow. + } + + // The order is OK, then push it into features. + switch (c) { + default: + // Currently LLVM supports only "mafdc". + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << "unsupported standard user-level extension" + << std::string(1, c); + return false; + case 'm': Features.push_back("+m"); + break; + case 'a': Features.push_back("+a"); + break; + case 'f': Features.push_back("+f"); - Features.push_back("+d"); HasF = true; + break; + case 'd': + Features.push_back("+d"); HasD = true; break; + case 'c': + Features.push_back("+c"); + break; } + } - // Skip rvxxx - StringRef Exts = MArch.substr(5); - - // Remove non-standard extensions and supervisor-level extensions. - // They have 'x', 's', 'sx' prefixes. Parse them at the end. - // Find the very first occurrence of 's' or 'x'. - StringRef OtherExts; - size_t Pos = Exts.find_first_of("sx"); - if (Pos != StringRef::npos) { - OtherExts = Exts.substr(Pos); - Exts = Exts.substr(0, Pos); - } - - std::string Major, Minor; - if (!getExtensionVersion(D, MArch, std::string(1, Baseline), - Exts, Major, Minor)) - return; - - // TODO: Use version number when setting target features - // and consume the underscore '_' that might follow. - - auto StdExtsItr = StdExts.begin(); - auto StdExtsEnd = StdExts.end(); - - for (auto I = Exts.begin(), E = Exts.end(); I != E; ++I) { - char c = *I; - - // Check ISA extensions are specified in the canonical order. - while (StdExtsItr != StdExtsEnd && *StdExtsItr != c) - ++StdExtsItr; - - if (StdExtsItr == StdExtsEnd) { - // Either c contains a valid extension but it was not given in - // canonical order or it is an invalid extension. - StringRef Error; - if (StdExts.contains(c)) - Error = "standard user-level extension not given in canonical order"; - else - Error = "invalid standard user-level extension"; - D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) - << MArch << Error << std::string(1, c); - return; - } - - // Move to next char to prevent repeated letter. - ++StdExtsItr; + // Dependency check. + // It's illegal to specify the 'd' (double-precision floating point) + // extension without also specifying the 'f' (single precision + // floating-point) extension. + if (HasD && !HasF) { + D.Diag(diag::err_drv_invalid_riscv_arch_name) + << MArch << "d requires f extension to also be specified"; + return false; + } - if (std::next(I) != E) { - // Skip c. - std::string Next = std::string(std::next(I), E); - std::string Major, Minor; - if (!getExtensionVersion(D, MArch, std::string(1, c), - Next, Major, Minor)) - return; - - // TODO: Use version number when setting target features - // and consume the underscore '_' that might follow. - } - - // The order is OK, then push it into features. - switch (c) { - default: - // Currently LLVM supports only "mafdc". - D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) - << MArch << "unsupported standard user-level extension" - << std::string(1, c); - return; - case 'm': - Features.push_back("+m"); - break; - case 'a': - Features.push_back("+a"); - break; - case 'f': - Features.push_back("+f"); - HasF = true; - break; - case 'd': - Features.push_back("+d"); - HasD = true; - break; - case 'c': - Features.push_back("+c"); - break; - } - } + // Additional dependency checks. + // TODO: The 'q' extension requires rv64. + // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'. - // Dependency check. - // It's illegal to specify the 'd' (double-precision floating point) - // extension without also specifying the 'f' (single precision - // floating-point) extension. - if (HasD && !HasF) - D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch - << "d requires f extension to also be specified"; + // Handle all other types of extensions. + getExtensionFeatures(D, Args, Features, MArch, OtherExts); - // Additional dependency checks. - // TODO: The 'q' extension requires rv64. - // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'. + return true; +} - // Handle all other types of extensions. - getExtensionFeatures(D, Args, Features, MArch, OtherExts); - } +void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args, + std::vector<StringRef> &Features) { + llvm::Optional<StringRef> MArch; + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) + MArch = A->getValue(); + else if (Triple.getOS() == llvm::Triple::Linux) + // RISC-V Linux defaults to rv{32,64}gc. + MArch = Triple.getArch() == llvm::Triple::riscv32 ? "rv32gc" : "rv64gc"; + + if (MArch.hasValue() && !getArchFeatures(D, *MArch, Features, Args)) + return; // -mrelax is default, unless -mno-relax is specified. if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true)) @@ -372,8 +387,16 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args, } StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) { - if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) + assert((Triple.getArch() == llvm::Triple::riscv32 || + Triple.getArch() == llvm::Triple::riscv64) && + "Unexpected triple"); + + if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) return A->getValue(); - return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32" : "lp64"; + // RISC-V Linux defaults to ilp32d/lp64d + if (Triple.getOS() == llvm::Triple::Linux) + return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32d" : "lp64d"; + else + return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32" : "lp64"; } diff --git a/lib/Driver/ToolChains/Arch/RISCV.h b/lib/Driver/ToolChains/Arch/RISCV.h index 443526900aae0..10eaf3c897b68 100644 --- a/lib/Driver/ToolChains/Arch/RISCV.h +++ b/lib/Driver/ToolChains/Arch/RISCV.h @@ -19,7 +19,8 @@ namespace clang { namespace driver { namespace tools { namespace riscv { -void getRISCVTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args, +void getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args, std::vector<llvm::StringRef> &Features); StringRef getRISCVABI(const llvm::opt::ArgList &Args, const llvm::Triple &Triple); diff --git a/lib/Driver/ToolChains/Arch/X86.cpp b/lib/Driver/ToolChains/Arch/X86.cpp index 34be226b69e98..d2b97bf6ad719 100644 --- a/lib/Driver/ToolChains/Arch/X86.cpp +++ b/lib/Driver/ToolChains/Arch/X86.cpp @@ -13,6 +13,7 @@ #include "clang/Driver/Options.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Option/ArgList.h" +#include "llvm/Support/Host.h" using namespace clang::driver; using namespace clang::driver::tools; diff --git a/lib/Driver/ToolChains/BareMetal.cpp b/lib/Driver/ToolChains/BareMetal.cpp index 1544727050f4f..dff0e04183ef9 100644 --- a/lib/Driver/ToolChains/BareMetal.cpp +++ b/lib/Driver/ToolChains/BareMetal.cpp @@ -191,7 +191,7 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - C.addCommand(llvm::make_unique<Command>(JA, *this, + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(TC.GetLinkerPath()), CmdArgs, Inputs)); } diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index cb861f27aedab..55d631733add2 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -22,6 +22,7 @@ #include "InputInfo.h" #include "PS4CPU.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Version.h" @@ -301,95 +302,6 @@ static void ParseMPreferVectorWidth(const Driver &D, const ArgList &Args, } } -static void getWebAssemblyTargetFeatures(const ArgList &Args, - std::vector<StringRef> &Features) { - handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group); -} - -static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, - const ArgList &Args, ArgStringList &CmdArgs, - bool ForAS) { - const Driver &D = TC.getDriver(); - std::vector<StringRef> Features; - switch (Triple.getArch()) { - default: - break; - case llvm::Triple::mips: - case llvm::Triple::mipsel: - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - mips::getMIPSTargetFeatures(D, Triple, Args, Features); - break; - - case llvm::Triple::arm: - case llvm::Triple::armeb: - case llvm::Triple::thumb: - case llvm::Triple::thumbeb: - arm::getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS); - break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - case llvm::Triple::ppc64le: - ppc::getPPCTargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::riscv32: - case llvm::Triple::riscv64: - riscv::getRISCVTargetFeatures(D, Args, Features); - break; - case llvm::Triple::systemz: - systemz::getSystemZTargetFeatures(Args, Features); - break; - case llvm::Triple::aarch64: - case llvm::Triple::aarch64_be: - aarch64::getAArch64TargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::x86: - case llvm::Triple::x86_64: - x86::getX86TargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::hexagon: - hexagon::getHexagonTargetFeatures(D, Args, Features); - break; - case llvm::Triple::wasm32: - case llvm::Triple::wasm64: - getWebAssemblyTargetFeatures(Args, Features); - break; - case llvm::Triple::sparc: - case llvm::Triple::sparcel: - case llvm::Triple::sparcv9: - sparc::getSparcTargetFeatures(D, Args, Features); - break; - case llvm::Triple::r600: - 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. - llvm::StringMap<unsigned> LastOpt; - for (unsigned I = 0, N = Features.size(); I < N; ++I) { - StringRef Name = Features[I]; - assert(Name[0] == '-' || Name[0] == '+'); - LastOpt[Name.drop_front(1)] = I; - } - - for (unsigned I = 0, N = Features.size(); I < N; ++I) { - // If this feature was overridden, ignore it. - StringRef Name = Features[I]; - llvm::StringMap<unsigned>::iterator LastI = LastOpt.find(Name.drop_front(1)); - assert(LastI != LastOpt.end()); - unsigned Last = LastI->second; - if (Last != I) - continue; - - CmdArgs.push_back("-target-feature"); - CmdArgs.push_back(Name.data()); - } -} - static bool shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime, const llvm::Triple &Triple) { @@ -501,8 +413,6 @@ static codegenoptions::DebugInfoKind DebugLevelToInfoKind(const Arg &A) { return codegenoptions::LimitedDebugInfo; } -enum class FramePointerKind { None, NonLeaf, All }; - static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) { switch (Triple.getArch()){ default: @@ -579,22 +489,33 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args, return true; } -static FramePointerKind getFramePointerKind(const ArgList &Args, - const llvm::Triple &Triple) { +static CodeGenOptions::FramePointerKind +getFramePointerKind(const ArgList &Args, const llvm::Triple &Triple) { + // We have 4 states: + // + // 00) leaf retained, non-leaf retained + // 01) leaf retained, non-leaf omitted (this is invalid) + // 10) leaf omitted, non-leaf retained + // (what -momit-leaf-frame-pointer was designed for) + // 11) leaf omitted, non-leaf omitted + // + // "omit" options taking precedence over "no-omit" options is the only way + // to make 3 valid states representable Arg *A = Args.getLastArg(options::OPT_fomit_frame_pointer, options::OPT_fno_omit_frame_pointer); bool OmitFP = A && A->getOption().matches(options::OPT_fomit_frame_pointer); bool NoOmitFP = A && A->getOption().matches(options::OPT_fno_omit_frame_pointer); + bool KeepLeaf = + Args.hasFlag(options::OPT_momit_leaf_frame_pointer, + options::OPT_mno_omit_leaf_frame_pointer, Triple.isPS4CPU()); if (NoOmitFP || mustUseNonLeafFramePointerForTarget(Triple) || (!OmitFP && useFramePointerForTargetByDefault(Args, Triple))) { - if (Args.hasFlag(options::OPT_momit_leaf_frame_pointer, - options::OPT_mno_omit_leaf_frame_pointer, - Triple.isPS4CPU())) - return FramePointerKind::NonLeaf; - return FramePointerKind::All; + if (KeepLeaf) + return CodeGenOptions::FramePointerKind::NonLeaf; + return CodeGenOptions::FramePointerKind::All; } - return FramePointerKind::None; + return CodeGenOptions::FramePointerKind::None; } /// Add a CC1 option to specify the debug compilation directory. @@ -821,12 +742,14 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, } } - if (Args.hasArg(options::OPT_ftest_coverage) || - Args.hasArg(options::OPT_coverage)) + bool EmitCovNotes = Args.hasArg(options::OPT_ftest_coverage) || + Args.hasArg(options::OPT_coverage); + bool EmitCovData = Args.hasFlag(options::OPT_fprofile_arcs, + options::OPT_fno_profile_arcs, false) || + Args.hasArg(options::OPT_coverage); + if (EmitCovNotes) CmdArgs.push_back("-femit-coverage-notes"); - if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, - false) || - Args.hasArg(options::OPT_coverage)) + if (EmitCovData) CmdArgs.push_back("-femit-coverage-data"); if (Args.hasFlag(options::OPT_fcoverage_mapping, @@ -862,35 +785,43 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, 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()) { - CmdArgs.push_back("-coverage-notes-file"); - SmallString<128> OutputFilename; - if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) - OutputFilename = FinalOutput->getValue(); - else - OutputFilename = llvm::sys::path::filename(Output.getBaseInput()); - SmallString<128> CoverageFilename = OutputFilename; - if (llvm::sys::path::is_relative(CoverageFilename)) - (void)D.getVFS().makeAbsolute(CoverageFilename); - llvm::sys::path::replace_extension(CoverageFilename, "gcno"); - CmdArgs.push_back(Args.MakeArgString(CoverageFilename)); - - // Leave -fprofile-dir= an unused argument unless .gcda emission is - // enabled. To be polite, with '-fprofile-arcs -fno-profile-arcs' consider - // the flag used. There is no -fno-profile-dir, so the user has no - // targeted way to suppress the warning. - if (Args.hasArg(options::OPT_fprofile_arcs) || - Args.hasArg(options::OPT_coverage)) { - CmdArgs.push_back("-coverage-data-file"); - if (Arg *FProfileDir = Args.getLastArg(options::OPT_fprofile_dir)) { - CoverageFilename = FProfileDir->getValue(); - llvm::sys::path::append(CoverageFilename, OutputFilename); - } - llvm::sys::path::replace_extension(CoverageFilename, "gcda"); - CmdArgs.push_back(Args.MakeArgString(CoverageFilename)); + // Leave -fprofile-dir= an unused argument unless .gcda emission is + // enabled. To be polite, with '-fprofile-arcs -fno-profile-arcs' consider + // the flag used. There is no -fno-profile-dir, so the user has no + // targeted way to suppress the warning. + Arg *FProfileDir = nullptr; + if (Args.hasArg(options::OPT_fprofile_arcs) || + Args.hasArg(options::OPT_coverage)) + FProfileDir = Args.getLastArg(options::OPT_fprofile_dir); + + // Put the .gcno and .gcda files (if needed) next to the object file or + // bitcode file in the case of LTO. + // FIXME: There should be a simpler way to find the object file for this + // input, and this code probably does the wrong thing for commands that + // compile and link all at once. + if ((Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) && + (EmitCovNotes || EmitCovData) && Output.isFilename()) { + SmallString<128> OutputFilename; + if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) + OutputFilename = FinalOutput->getValue(); + else + OutputFilename = llvm::sys::path::filename(Output.getBaseInput()); + SmallString<128> CoverageFilename = OutputFilename; + if (llvm::sys::path::is_relative(CoverageFilename)) + (void)D.getVFS().makeAbsolute(CoverageFilename); + llvm::sys::path::replace_extension(CoverageFilename, "gcno"); + + CmdArgs.push_back("-coverage-notes-file"); + CmdArgs.push_back(Args.MakeArgString(CoverageFilename)); + + if (EmitCovData) { + if (FProfileDir) { + CoverageFilename = FProfileDir->getValue(); + llvm::sys::path::append(CoverageFilename, OutputFilename); } + llvm::sys::path::replace_extension(CoverageFilename, "gcda"); + CmdArgs.push_back("-coverage-data-file"); + CmdArgs.push_back(Args.MakeArgString(CoverageFilename)); } } } @@ -1045,7 +976,6 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, ArgStringList &CmdArgs, const InputInfo &Output, const InputInfoList &Inputs) const { - Arg *A; const bool IsIAMCU = getToolChain().getTriple().isOSIAMCU(); CheckPreprocessingOptions(D, Args); @@ -1054,9 +984,20 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_CC); // Handle dependency file generation. - if ((A = Args.getLastArg(options::OPT_M, options::OPT_MM)) || - (A = Args.getLastArg(options::OPT_MD)) || - (A = Args.getLastArg(options::OPT_MMD))) { + Arg *ArgM = Args.getLastArg(options::OPT_MM); + if (!ArgM) + ArgM = Args.getLastArg(options::OPT_M); + Arg *ArgMD = Args.getLastArg(options::OPT_MMD); + if (!ArgMD) + ArgMD = Args.getLastArg(options::OPT_MD); + + // -M and -MM imply -w. + if (ArgM) + CmdArgs.push_back("-w"); + else + ArgM = ArgMD; + + if (ArgM) { // Determine the output location. const char *DepFile; if (Arg *MF = Args.getLastArg(options::OPT_MF)) { @@ -1064,8 +1005,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, C.addFailureResultFile(DepFile, &JA); } else if (Output.getType() == types::TY_Dependencies) { DepFile = Output.getFilename(); - } else if (A->getOption().matches(options::OPT_M) || - A->getOption().matches(options::OPT_MM)) { + } else if (!ArgMD) { DepFile = "-"; } else { DepFile = getDependencyFileName(Args, Inputs); @@ -1074,8 +1014,22 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, CmdArgs.push_back("-dependency-file"); CmdArgs.push_back(DepFile); + bool HasTarget = false; + for (const Arg *A : Args.filtered(options::OPT_MT, options::OPT_MQ)) { + HasTarget = true; + A->claim(); + if (A->getOption().matches(options::OPT_MT)) { + A->render(Args, CmdArgs); + } else { + CmdArgs.push_back("-MT"); + SmallString<128> Quoted; + QuoteTarget(A->getValue(), Quoted); + CmdArgs.push_back(Args.MakeArgString(Quoted)); + } + } + // Add a default target if one wasn't specified. - if (!Args.hasArg(options::OPT_MT) && !Args.hasArg(options::OPT_MQ)) { + if (!HasTarget) { const char *DepTarget; // If user provided -o, that is the dependency target, except @@ -1092,17 +1046,14 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, DepTarget = Args.MakeArgString(llvm::sys::path::filename(P)); } - if (!A->getOption().matches(options::OPT_MD) && !A->getOption().matches(options::OPT_MMD)) { - CmdArgs.push_back("-w"); - } CmdArgs.push_back("-MT"); SmallString<128> Quoted; QuoteTarget(DepTarget, Quoted); CmdArgs.push_back(Args.MakeArgString(Quoted)); } - if (A->getOption().matches(options::OPT_M) || - A->getOption().matches(options::OPT_MD)) + if (ArgM->getOption().matches(options::OPT_M) || + ArgM->getOption().matches(options::OPT_MD)) CmdArgs.push_back("-sys-header-deps"); if ((isa<PrecompileJobAction>(JA) && !Args.hasArg(options::OPT_fno_module_file_deps)) || @@ -1111,8 +1062,8 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, } if (Args.hasArg(options::OPT_MG)) { - if (!A || A->getOption().matches(options::OPT_MD) || - A->getOption().matches(options::OPT_MMD)) + if (!ArgM || ArgM->getOption().matches(options::OPT_MD) || + ArgM->getOption().matches(options::OPT_MMD)) D.Diag(diag::err_drv_mg_requires_m_or_mm); CmdArgs.push_back("-MG"); } @@ -1120,22 +1071,6 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_MP); Args.AddLastArg(CmdArgs, options::OPT_MV); - // Convert all -MQ <target> args to -MT <quoted target> - for (const Arg *A : Args.filtered(options::OPT_MT, options::OPT_MQ)) { - A->claim(); - - if (A->getOption().matches(options::OPT_MQ)) { - CmdArgs.push_back("-MT"); - SmallString<128> Quoted; - QuoteTarget(A->getValue(), Quoted); - CmdArgs.push_back(Args.MakeArgString(Quoted)); - - // -MT flag - no change - } else { - A->render(Args, CmdArgs); - } - } - // Add offload include arguments specific for CUDA. This must happen before // we -I or -include anything else, because we must pick up the CUDA headers // from the particular CUDA installation, rather than from e.g. @@ -1236,6 +1171,9 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, // Do not claim the argument so that the use of the argument does not // silently go unnoticed on toolchains which do not honour the option. continue; + } else if (A->getOption().matches(options::OPT_stdlibxx_isystem)) { + // Translated to -internal-isystem by the driver, no need to pass to cc1. + continue; } // Not translated, render as usual. @@ -1290,11 +1228,15 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, // of an offloading programming model. // Add C++ include arguments, if needed. - if (types::isCXX(Inputs[0].getType())) - forAllAssociatedToolChains(C, JA, getToolChain(), - [&Args, &CmdArgs](const ToolChain &TC) { - TC.AddClangCXXStdlibIncludeArgs(Args, CmdArgs); - }); + if (types::isCXX(Inputs[0].getType())) { + bool HasStdlibxxIsystem = Args.hasArg(options::OPT_stdlibxx_isystem); + forAllAssociatedToolChains( + C, JA, getToolChain(), + [&Args, &CmdArgs, HasStdlibxxIsystem](const ToolChain &TC) { + HasStdlibxxIsystem ? TC.AddClangCXXStdlibIsystemArgs(Args, CmdArgs) + : TC.AddClangCXXStdlibIncludeArgs(Args, CmdArgs); + }); + } // Add system include arguments for all targets but IAMCU. if (!IsIAMCU) @@ -1635,7 +1577,7 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args, CmdArgs.push_back("-target-abi"); CmdArgs.push_back(ABIName.data()); - mips::FloatABI ABI = mips::getMipsFloatABI(D, Args); + mips::FloatABI ABI = mips::getMipsFloatABI(D, Args, Triple); if (ABI == mips::FloatABI::Soft) { // Floating point operations and argument passing are soft. CmdArgs.push_back("-msoft-float"); @@ -1648,13 +1590,6 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args, CmdArgs.push_back("hard"); } - if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) { - if (A->getOption().matches(options::OPT_mxgot)) { - CmdArgs.push_back("-mllvm"); - CmdArgs.push_back("-mxgot"); - } - } - if (Arg *A = Args.getLastArg(options::OPT_mldc1_sdc1, options::OPT_mno_ldc1_sdc1)) { if (A->getOption().matches(options::OPT_mno_ldc1_sdc1)) { @@ -1842,21 +1777,11 @@ void Clang::AddPPCTargetArgs(const ArgList &Args, void Clang::AddRISCVTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { - // FIXME: currently defaults to the soft-float ABIs. Will need to be - // expanded to select ilp32f, ilp32d, lp64f, lp64d when appropriate. - const char *ABIName = nullptr; const llvm::Triple &Triple = getToolChain().getTriple(); - if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) - ABIName = A->getValue(); - else if (Triple.getArch() == llvm::Triple::riscv32) - ABIName = "ilp32"; - else if (Triple.getArch() == llvm::Triple::riscv64) - ABIName = "lp64"; - else - llvm_unreachable("Unexpected triple!"); + StringRef ABIName = riscv::getRISCVABI(Args, Triple); CmdArgs.push_back("-target-abi"); - CmdArgs.push_back(ABIName); + CmdArgs.push_back(ABIName.data()); } void Clang::AddSparcTargetArgs(const ArgList &Args, @@ -1996,7 +1921,8 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename, if (!CompilationDatabase) { std::error_code EC; - auto File = llvm::make_unique<llvm::raw_fd_ostream>(Filename, EC, llvm::sys::fs::F_Text); + auto File = std::make_unique<llvm::raw_fd_ostream>(Filename, EC, + llvm::sys::fs::OF_Text); if (EC) { D.Diag(clang::diag::err_drv_compilationdatabase) << Filename << EC.message(); @@ -2005,13 +1931,14 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename, CompilationDatabase = std::move(File); } auto &CDB = *CompilationDatabase; - SmallString<128> Buf; - if (llvm::sys::fs::current_path(Buf)) - Buf = "."; - CDB << "{ \"directory\": \"" << escape(Buf) << "\""; + auto CWD = D.getVFS().getCurrentWorkingDirectory(); + if (!CWD) + CWD = "."; + CDB << "{ \"directory\": \"" << escape(*CWD) << "\""; CDB << ", \"file\": \"" << escape(Input.getFilename()) << "\""; CDB << ", \"output\": \"" << escape(Output.getFilename()) << "\""; CDB << ", \"arguments\": [\"" << escape(D.ClangExecutable) << "\""; + SmallString<128> Buf; Buf = "-x"; Buf += types::getTypeName(Input.getType()); CDB << ", \"" << escape(Buf) << "\""; @@ -2029,6 +1956,8 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename, // Skip writing dependency output and the compilation database itself. if (O.getGroup().isValid() && O.getGroup().getID() == options::OPT_M_Group) continue; + if (O.getID() == options::OPT_gen_cdb_fragment_path) + continue; // Skip inputs. if (O.getKind() == Option::InputClass) continue; @@ -2043,6 +1972,40 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename, CDB << ", \"" << escape(Buf) << "\"]},\n"; } +void Clang::DumpCompilationDatabaseFragmentToDir( + StringRef Dir, Compilation &C, StringRef Target, const InputInfo &Output, + const InputInfo &Input, const llvm::opt::ArgList &Args) const { + // If this is a dry run, do not create the compilation database file. + if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) + return; + + if (CompilationDatabase) + DumpCompilationDatabase(C, "", Target, Output, Input, Args); + + SmallString<256> Path = Dir; + const auto &Driver = C.getDriver(); + Driver.getVFS().makeAbsolute(Path); + auto Err = llvm::sys::fs::create_directory(Path, /*IgnoreExisting=*/true); + if (Err) { + Driver.Diag(diag::err_drv_compilationdatabase) << Dir << Err.message(); + return; + } + + llvm::sys::path::append( + Path, + Twine(llvm::sys::path::filename(Input.getFilename())) + ".%%%%.json"); + int FD; + SmallString<256> TempPath; + Err = llvm::sys::fs::createUniqueFile(Path, FD, TempPath); + if (Err) { + Driver.Diag(diag::err_drv_compilationdatabase) << Path << Err.message(); + return; + } + CompilationDatabase = + std::make_unique<llvm::raw_fd_ostream>(FD, /*shouldClose=*/true); + DumpCompilationDatabase(C, "", Target, Output, Input, Args); +} + static void CollectArgsForIntegratedAssembler(Compilation &C, const ArgList &Args, ArgStringList &CmdArgs, @@ -2080,6 +2043,9 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, break; } + // If you add more args here, also add them to the block below that + // starts with "// If CollectArgsForIntegratedAssembler() isn't called below". + // When passing -I arguments to the assembler we sometimes need to // unconditionally take the next argument. For example, when parsing // '-Wa,-I -Wa,foo' we need to accept the -Wa,foo arg after seeing the @@ -2169,6 +2135,8 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, CmdArgs.push_back("-msave-temp-labels"); } else if (Value == "--fatal-warnings") { CmdArgs.push_back("-massembler-fatal-warnings"); + } else if (Value == "--no-warn" || Value == "-W") { + CmdArgs.push_back("-massembler-no-warn"); } else if (Value == "--noexecstack") { UseNoExecStack = true; } else if (Value.startswith("-compress-debug-sections") || @@ -2804,6 +2772,10 @@ static void RenderModulesOptions(Compilation &C, const Driver &D, std::string("-fprebuilt-module-path=") + A->getValue())); A->claim(); } + if (Args.hasFlag(options::OPT_fmodules_validate_input_files_content, + options::OPT_fno_modules_validate_input_files_content, + false)) + CmdArgs.push_back("-fvalidate-ast-input-files-content"); } // -fmodule-name specifies the module that is currently being built (or @@ -3342,7 +3314,6 @@ static void RenderDebugOptions(const ToolChain &TC, const Driver &D, 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) && @@ -3482,6 +3453,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (const Arg *MJ = Args.getLastArg(options::OPT_MJ)) { DumpCompilationDatabase(C, MJ->getValue(), TripleStr, Output, Input, Args); Args.ClaimAllArgs(options::OPT_MJ); + } else if (const Arg *GenCDBFragment = + Args.getLastArg(options::OPT_gen_cdb_fragment_path)) { + DumpCompilationDatabaseFragmentToDir(GenCDBFragment->getValue(), C, + TripleStr, Output, Input, Args); + Args.ClaimAllArgs(options::OPT_gen_cdb_fragment_path); } if (IsCuda || IsHIP) { @@ -3544,6 +3520,36 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Select the appropriate action. RewriteKind rewriteKind = RK_None; + // If CollectArgsForIntegratedAssembler() isn't called below, claim the args + // it claims when not running an assembler. Otherwise, clang would emit + // "argument unused" warnings for assembler flags when e.g. adding "-E" to + // flags while debugging something. That'd be somewhat inconvenient, and it's + // also inconsistent with most other flags -- we don't warn on + // -ffunction-sections not being used in -E mode either for example, even + // though it's not really used either. + if (!isa<AssembleJobAction>(JA)) { + // The args claimed here should match the args used in + // CollectArgsForIntegratedAssembler(). + if (TC.useIntegratedAs()) { + Args.ClaimAllArgs(options::OPT_mrelax_all); + Args.ClaimAllArgs(options::OPT_mno_relax_all); + Args.ClaimAllArgs(options::OPT_mincremental_linker_compatible); + Args.ClaimAllArgs(options::OPT_mno_incremental_linker_compatible); + switch (C.getDefaultToolChain().getArch()) { + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + Args.ClaimAllArgs(options::OPT_mimplicit_it_EQ); + break; + default: + break; + } + } + Args.ClaimAllArgs(options::OPT_Wa_COMMA); + Args.ClaimAllArgs(options::OPT_Xassembler); + } + if (isa<AnalyzeJobAction>(JA)) { assert(JA.getType() == types::TY_Plist && "Invalid output type."); CmdArgs.push_back("-analyze"); @@ -3587,25 +3593,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } else if (JA.getType() == types::TY_LLVM_BC || JA.getType() == types::TY_LTO_BC) { CmdArgs.push_back("-emit-llvm-bc"); - } else if (JA.getType() == types::TY_IFS) { - StringRef StubFormat = - llvm::StringSwitch<StringRef>( - Args.hasArg(options::OPT_iterface_stub_version_EQ) - ? Args.getLastArgValue(options::OPT_iterface_stub_version_EQ) - : "") - .Case("experimental-yaml-elf-v1", "experimental-yaml-elf-v1") - .Case("experimental-tapi-elf-v1", "experimental-tapi-elf-v1") - .Default(""); - - if (StubFormat.empty()) - D.Diag(diag::err_drv_invalid_value) - << "Must specify a valid interface stub format type using " - << "-interface-stub-version=<experimental-tapi-elf-v1 | " - "experimental-yaml-elf-v1>"; - + } else if (JA.getType() == types::TY_IFS || + JA.getType() == types::TY_IFS_CPP) { + StringRef ArgStr = + Args.hasArg(options::OPT_interface_stub_version_EQ) + ? Args.getLastArgValue(options::OPT_interface_stub_version_EQ) + : "experimental-ifs-v1"; CmdArgs.push_back("-emit-interface-stubs"); CmdArgs.push_back( - Args.MakeArgString(Twine("-interface-stub-version=") + StubFormat)); + Args.MakeArgString(Twine("-interface-stub-version=") + ArgStr.str())); } else if (JA.getType() == types::TY_PP_Asm) { CmdArgs.push_back("-S"); } else if (JA.getType() == types::TY_AST) { @@ -3635,13 +3631,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (D.isUsingLTO() && !isDeviceOffloadAction) { Args.AddLastArg(CmdArgs, options::OPT_flto, options::OPT_flto_EQ); - - // The Darwin and PS4 linkers currently use the legacy LTO API, which - // does not support LTO unit features (CFI, whole program vtable opt) - // under ThinLTO. - if (!(RawTriple.isOSDarwin() || RawTriple.isPS4()) || - D.getLTOMode() == LTOK_Full) - CmdArgs.push_back("-flto-unit"); + CmdArgs.push_back("-flto-unit"); } } @@ -3761,7 +3751,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, II.getInputArg().renderAsInput(Args, CmdArgs); } - C.addCommand(llvm::make_unique<Command>(JA, *this, D.getClangProgramPath(), + C.addCommand(std::make_unique<Command>(JA, *this, D.getClangProgramPath(), CmdArgs, Inputs)); return; } @@ -3806,6 +3796,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (isa<AnalyzeJobAction>(JA)) RenderAnalyzerOptions(Args, CmdArgs, Triple, Input); + if (isa<AnalyzeJobAction>(JA) || + (isa<PreprocessJobAction>(JA) && Args.hasArg(options::OPT__analyze))) + CmdArgs.push_back("-setup-static-analyzer"); + // Enable compatilibily mode to avoid analyzer-config related errors. // Since we can't access frontend flags through hasArg, let's manually iterate // through them. @@ -3946,12 +3940,23 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false)) CmdArgs.push_back("-fdefault-calling-conv=stdcall"); - FramePointerKind FPKeepKind = getFramePointerKind(Args, RawTriple); - if (FPKeepKind != FramePointerKind::None) { - CmdArgs.push_back("-mdisable-fp-elim"); - if (FPKeepKind == FramePointerKind::NonLeaf) - CmdArgs.push_back("-momit-leaf-frame-pointer"); + CodeGenOptions::FramePointerKind FPKeepKind = + getFramePointerKind(Args, RawTriple); + const char *FPKeepKindStr = nullptr; + switch (FPKeepKind) { + case CodeGenOptions::FramePointerKind::None: + FPKeepKindStr = "-mframe-pointer=none"; + break; + case CodeGenOptions::FramePointerKind::NonLeaf: + FPKeepKindStr = "-mframe-pointer=non-leaf"; + break; + case CodeGenOptions::FramePointerKind::All: + FPKeepKindStr = "-mframe-pointer=all"; + break; } + assert(FPKeepKindStr && "unknown FramePointerKind"); + CmdArgs.push_back(FPKeepKindStr); + if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss, options::OPT_fno_zero_initialized_in_bss)) CmdArgs.push_back("-mno-zero-initialized-in-bss"); @@ -4003,11 +4008,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs); - if (Arg *A = Args.getLastArg(options::OPT_mlong_double_64, - options::OPT_mlong_double_128)) { + if (Arg *A = Args.getLastArg(options::OPT_LongDouble_Group)) { if (TC.getArch() == llvm::Triple::x86 || - TC.getArch() == llvm::Triple::x86_64 || - TC.getArch() == llvm::Triple::ppc || TC.getTriple().isPPC64()) + TC.getArch() == llvm::Triple::x86_64) + A->render(Args, CmdArgs); + else if ((TC.getArch() == llvm::Triple::ppc || TC.getTriple().isPPC64()) && + (A->getOption().getID() != options::OPT_mlong_double_80)) A->render(Args, CmdArgs); else D.Diag(diag::err_drv_unsupported_opt_for_target) @@ -4018,8 +4024,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // toolchains which have the integrated assembler on by default. bool IsIntegratedAssemblerDefault = TC.IsIntegratedAssemblerDefault(); if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm, - IsIntegratedAssemblerDefault) || - Args.hasArg(options::OPT_dA)) + IsIntegratedAssemblerDefault)) CmdArgs.push_back("-masm-verbose"); if (!TC.useIntegratedAs()) @@ -4386,6 +4391,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue()); } + if (Args.hasArg(options::OPT_fexperimental_new_constant_interpreter)) + CmdArgs.push_back("-fexperimental-new-constant-interpreter"); + + if (Args.hasArg(options::OPT_fforce_experimental_new_constant_interpreter)) + CmdArgs.push_back("-fforce-experimental-new-constant-interpreter"); + if (Arg *A = Args.getLastArg(options::OPT_fbracket_depth_EQ)) { CmdArgs.push_back("-fbracket-depth"); CmdArgs.push_back(A->getValue()); @@ -4571,20 +4582,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (TC.SupportsProfiling()) Args.AddLastArg(CmdArgs, options::OPT_mfentry); - // -flax-vector-conversions is default. - if (!Args.hasFlag(options::OPT_flax_vector_conversions, - options::OPT_fno_lax_vector_conversions)) - CmdArgs.push_back("-fno-lax-vector-conversions"); - if (Args.getLastArg(options::OPT_fapple_kext) || (Args.hasArg(options::OPT_mkernel) && types::isCXX(InputType))) CmdArgs.push_back("-fapple-kext"); + Args.AddLastArg(CmdArgs, options::OPT_flax_vector_conversions_EQ); Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch); Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info); Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_parseable_fixits); Args.AddLastArg(CmdArgs, options::OPT_ftime_report); Args.AddLastArg(CmdArgs, options::OPT_ftime_trace); + Args.AddLastArg(CmdArgs, options::OPT_ftime_trace_granularity_EQ); Args.AddLastArg(CmdArgs, options::OPT_ftrapv); Args.AddLastArg(CmdArgs, options::OPT_malign_double); @@ -4667,6 +4675,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Forward -cl options to -cc1 RenderOpenCLOptions(Args, CmdArgs); + if (Args.hasFlag(options::OPT_fhip_new_launch_api, + options::OPT_fno_hip_new_launch_api, false)) + CmdArgs.push_back("-fhip-new-launch-api"); + if (Arg *A = Args.getLastArg(options::OPT_fcf_protection_EQ)) { CmdArgs.push_back( Args.MakeArgString(Twine("-fcf-protection=") + A->getValue())); @@ -4771,13 +4783,36 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fuse-line-directives"); // -fms-compatibility=0 is default. - if (Args.hasFlag(options::OPT_fms_compatibility, - options::OPT_fno_ms_compatibility, - (IsWindowsMSVC && - Args.hasFlag(options::OPT_fms_extensions, - options::OPT_fno_ms_extensions, true)))) + bool IsMSVCCompat = Args.hasFlag( + options::OPT_fms_compatibility, options::OPT_fno_ms_compatibility, + (IsWindowsMSVC && Args.hasFlag(options::OPT_fms_extensions, + options::OPT_fno_ms_extensions, true))); + if (IsMSVCCompat) CmdArgs.push_back("-fms-compatibility"); + // Handle -fgcc-version, if present. + VersionTuple GNUCVer; + if (Arg *A = Args.getLastArg(options::OPT_fgnuc_version_EQ)) { + // Check that the version has 1 to 3 components and the minor and patch + // versions fit in two decimal digits. + StringRef Val = A->getValue(); + Val = Val.empty() ? "0" : Val; // Treat "" as 0 or disable. + bool Invalid = GNUCVer.tryParse(Val); + unsigned Minor = GNUCVer.getMinor().getValueOr(0); + unsigned Patch = GNUCVer.getSubminor().getValueOr(0); + if (Invalid || GNUCVer.getBuild() || Minor >= 100 || Patch >= 100) { + D.Diag(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(); + } + } else if (!IsMSVCCompat) { + // Imitate GCC 4.2.1 by default if -fms-compatibility is not in effect. + GNUCVer = VersionTuple(4, 2, 1); + } + if (!GNUCVer.empty()) { + CmdArgs.push_back( + Args.MakeArgString("-fgnuc-version=" + GNUCVer.getAsString())); + } + VersionTuple MSVT = TC.computeMSVCVersion(&D, Args); if (!MSVT.empty()) CmdArgs.push_back( @@ -4857,6 +4892,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Std && (Std->containsValue("c++2a") || Std->containsValue("c++latest")); RenderModulesOptions(C, D, Args, Input, Output, CmdArgs, HaveModules); + if (Args.hasFlag(options::OPT_fpch_validate_input_files_content, + options::OPT_fno_pch_validate_input_files_content, false)) + CmdArgs.push_back("-fvalidate-ast-input-files-content"); + Args.AddLastArg(CmdArgs, options::OPT_fexperimental_new_pass_manager, options::OPT_fno_experimental_new_pass_manager); @@ -4873,9 +4912,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, addExceptionArgs(Args, InputType, TC, KernelOrKext, Runtime, CmdArgs); // Handle exception personalities - Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions, - options::OPT_fseh_exceptions, - options::OPT_fdwarf_exceptions); + Arg *A = Args.getLastArg( + options::OPT_fsjlj_exceptions, options::OPT_fseh_exceptions, + options::OPT_fdwarf_exceptions, options::OPT_fwasm_exceptions); if (A) { const Option &Opt = A->getOption(); if (Opt.matches(options::OPT_fsjlj_exceptions)) @@ -4884,6 +4923,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fseh-exceptions"); if (Opt.matches(options::OPT_fdwarf_exceptions)) CmdArgs.push_back("-fdwarf-exceptions"); + if (Opt.matches(options::OPT_fwasm_exceptions)) + CmdArgs.push_back("-fwasm-exceptions"); } else { switch (TC.GetExceptionModel(Args)) { default: @@ -5322,9 +5363,30 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(TargetInfo.str())); } - bool WholeProgramVTables = - Args.hasFlag(options::OPT_fwhole_program_vtables, - options::OPT_fno_whole_program_vtables, false); + bool VirtualFunctionElimination = + Args.hasFlag(options::OPT_fvirtual_function_elimination, + options::OPT_fno_virtual_function_elimination, false); + if (VirtualFunctionElimination) { + // VFE requires full LTO (currently, this might be relaxed to allow ThinLTO + // in the future). + if (D.getLTOMode() != LTOK_Full) + D.Diag(diag::err_drv_argument_only_allowed_with) + << "-fvirtual-function-elimination" + << "-flto=full"; + + CmdArgs.push_back("-fvirtual-function-elimination"); + } + + // VFE requires whole-program-vtables, and enables it by default. + bool WholeProgramVTables = Args.hasFlag( + options::OPT_fwhole_program_vtables, + options::OPT_fno_whole_program_vtables, VirtualFunctionElimination); + if (VirtualFunctionElimination && !WholeProgramVTables) { + D.Diag(diag::err_drv_argument_not_allowed_with) + << "-fno-whole-program-vtables" + << "-fvirtual-function-elimination"; + } + if (WholeProgramVTables) { if (!D.isUsingLTO()) D.Diag(diag::err_drv_argument_only_allowed_with) @@ -5333,14 +5395,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fwhole-program-vtables"); } - bool RequiresSplitLTOUnit = WholeProgramVTables || Sanitize.needsLTO(); + bool DefaultsSplitLTOUnit = 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"); + options::OPT_fno_split_lto_unit, DefaultsSplitLTOUnit); + if (Sanitize.needsLTO() && !SplitLTOUnit) + D.Diag(diag::err_drv_argument_not_allowed_with) << "-fno-split-lto-unit" + << "-fsanitize=cfi"; if (SplitLTOUnit) CmdArgs.push_back("-fsplit-lto-unit"); @@ -5469,16 +5530,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, (InputType == types::TY_C || InputType == types::TY_CXX)) { auto CLCommand = getCLFallback()->GetCommand(C, JA, Output, Inputs, Args, LinkingOutput); - C.addCommand(llvm::make_unique<FallbackCommand>( + C.addCommand(std::make_unique<FallbackCommand>( JA, *this, Exec, CmdArgs, Inputs, std::move(CLCommand))); } else if (Args.hasArg(options::OPT__SLASH_fallback) && isa<PrecompileJobAction>(JA)) { // In /fallback builds, run the main compilation even if the pch generation // fails, so that the main compilation's fallback to cl.exe runs. - C.addCommand(llvm::make_unique<ForceSuccessCommand>(JA, *this, Exec, + C.addCommand(std::make_unique<ForceSuccessCommand>(JA, *this, Exec, CmdArgs, Inputs)); } else { - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } // Make the compile command echo its inputs for /showFilenames. @@ -5489,7 +5550,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } if (Arg *A = Args.getLastArg(options::OPT_pg)) - if (FPKeepKind == FramePointerKind::None) + if (FPKeepKind == CodeGenOptions::FramePointerKind::None) D.Diag(diag::err_drv_argument_not_allowed_with) << "-fomit-frame-pointer" << A->getAsString(Args); @@ -5954,15 +6015,14 @@ const char *Clang::getBaseInputStem(const ArgList &Args, const char *Clang::getDependencyFileName(const ArgList &Args, const InputInfoList &Inputs) { // FIXME: Think about this more. - std::string Res; if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) { - std::string Str(OutputOpt->getValue()); - Res = Str.substr(0, Str.rfind('.')); - } else { - Res = getBaseInputStem(Args, Inputs); + SmallString<128> OutputFilename(OutputOpt->getValue()); + llvm::sys::path::replace_extension(OutputFilename, llvm::Twine('d')); + return Args.MakeArgString(OutputFilename); } - return Args.MakeArgString(Res + ".d"); + + return Args.MakeArgString(Twine(getBaseInputStem(Args, Inputs)) + ".d"); } // Begin ClangAs @@ -6205,7 +6265,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Input.getFilename()); const char *Exec = getToolChain().getDriver().getClangProgramPath(); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } // Begin OffloadBundler @@ -6288,7 +6348,7 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(TCArgs.MakeArgString(UB)); // All the inputs are encoded as commands. - C.addCommand(llvm::make_unique<Command>( + C.addCommand(std::make_unique<Command>( JA, *this, TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())), CmdArgs, None)); @@ -6354,8 +6414,38 @@ void OffloadBundler::ConstructJobMultipleOutputs( CmdArgs.push_back("-unbundle"); // All the inputs are encoded as commands. - C.addCommand(llvm::make_unique<Command>( + C.addCommand(std::make_unique<Command>( JA, *this, TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())), CmdArgs, None)); } + +void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + ArgStringList CmdArgs; + + const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); + + // Add the "effective" target triple. + CmdArgs.push_back("-target"); + CmdArgs.push_back(Args.MakeArgString(Triple.getTriple())); + + // Add the output file name. + assert(Output.isFilename() && "Invalid output."); + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + + // Add inputs. + for (const InputInfo &I : Inputs) { + assert(I.isFilename() && "Invalid input."); + CmdArgs.push_back(I.getFilename()); + } + + C.addCommand(std::make_unique<Command>( + JA, *this, + Args.MakeArgString(getToolChain().GetProgramPath(getShortName())), + CmdArgs, Inputs)); +} diff --git a/lib/Driver/ToolChains/Clang.h b/lib/Driver/ToolChains/Clang.h index fc4f5ecdd28a4..b345c02489d4d 100644 --- a/lib/Driver/ToolChains/Clang.h +++ b/lib/Driver/ToolChains/Clang.h @@ -95,6 +95,10 @@ private: const InputInfo &Output, const InputInfo &Input, const llvm::opt::ArgList &Args) const; + void DumpCompilationDatabaseFragmentToDir( + StringRef Dir, Compilation &C, StringRef Target, const InputInfo &Output, + const InputInfo &Input, const llvm::opt::ArgList &Args) const; + public: Clang(const ToolChain &TC); ~Clang() override; @@ -148,6 +152,20 @@ public: const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override; }; + +/// Offload wrapper tool. +class LLVM_LIBRARY_VISIBILITY OffloadWrapper final : public Tool { +public: + OffloadWrapper(const ToolChain &TC) + : Tool("offload wrapper", "clang-offload-wrapper", TC) {} + + bool hasIntegratedCPP() const override { return false; } + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; + } // end namespace tools } // end namespace driver diff --git a/lib/Driver/ToolChains/CloudABI.cpp b/lib/Driver/ToolChains/CloudABI.cpp index cc1ac3ab7e790..cf1d0d551e570 100644 --- a/lib/Driver/ToolChains/CloudABI.cpp +++ b/lib/Driver/ToolChains/CloudABI.cpp @@ -92,7 +92,7 @@ void cloudabi::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } // CloudABI - CloudABI tool chain which can call ld(1) directly. diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp index 99691cb43dc42..10743559e0481 100644 --- a/lib/Driver/ToolChains/CommonArgs.cpp +++ b/lib/Driver/ToolChains/CommonArgs.cpp @@ -11,8 +11,12 @@ #include "Arch/ARM.h" #include "Arch/Mips.h" #include "Arch/PPC.h" +#include "Arch/RISCV.h" +#include "Arch/Sparc.h" #include "Arch/SystemZ.h" #include "Arch/X86.h" +#include "AMDGPU.h" +#include "MSP430.h" #include "HIP.h" #include "Hexagon.h" #include "InputInfo.h" @@ -145,6 +149,11 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, // (constructed via -Xarch_). Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input); + // LIBRARY_PATH are included before user inputs and only supported on native + // toolchains. + if (!TC.isCrossCompiling()) + addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); + for (const auto &II : Inputs) { // If the current tool chain refers to an OpenMP or HIP offloading host, we // should ignore inputs that refer to OpenMP or HIP offloading devices - @@ -182,12 +191,6 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, A.renderAsInput(Args, CmdArgs); } } - - // LIBRARY_PATH - included following the user specified library paths. - // and only supported on native toolchains. - if (!TC.isCrossCompiling()) { - addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); - } } void tools::AddTargetFeature(const ArgList &Args, @@ -485,6 +488,14 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args, if (!StatsFile.empty()) CmdArgs.push_back( Args.MakeArgString(Twine("-plugin-opt=stats-file=") + StatsFile)); + + getTargetFeatures(ToolChain, ToolChain.getTriple(), Args, CmdArgs, + /* ForAS= */ false, /* ForLTOPlugin= */ true); + + StringRef ABIName = tools::getTargetABI(Args, ToolChain.getTriple()); + if (!ABIName.empty()) + CmdArgs.push_back( + Args.MakeArgString(Twine("-plugin-opt=-target-abi=") + ABIName)); } void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, @@ -501,30 +512,41 @@ void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, } bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC, - const ArgList &Args, bool IsOffloadingHost, - bool GompNeedsRT) { + const ArgList &Args, bool ForceStaticHostRuntime, + bool IsOffloadingHost, bool GompNeedsRT) { if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, options::OPT_fno_openmp, false)) return false; - switch (TC.getDriver().getOpenMPRuntime(Args)) { + Driver::OpenMPRuntimeKind RTKind = TC.getDriver().getOpenMPRuntime(Args); + + if (RTKind == Driver::OMPRT_Unknown) + // Already diagnosed. + return false; + + if (ForceStaticHostRuntime) + CmdArgs.push_back("-Bstatic"); + + switch (RTKind) { case Driver::OMPRT_OMP: CmdArgs.push_back("-lomp"); break; case Driver::OMPRT_GOMP: CmdArgs.push_back("-lgomp"); - - if (GompNeedsRT) - CmdArgs.push_back("-lrt"); break; case Driver::OMPRT_IOMP5: CmdArgs.push_back("-liomp5"); break; case Driver::OMPRT_Unknown: - // Already diagnosed. - return false; + break; } + if (ForceStaticHostRuntime) + CmdArgs.push_back("-Bdynamic"); + + if (RTKind == Driver::OMPRT_GOMP && GompNeedsRT) + CmdArgs.push_back("-lrt"); + if (IsOffloadingHost) CmdArgs.push_back("-lomptarget"); @@ -605,29 +627,29 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); // Collect shared runtimes. if (SanArgs.needsSharedRt()) { - if (SanArgs.needsAsanRt()) { + if (SanArgs.needsAsanRt() && SanArgs.linkRuntimes()) { SharedRuntimes.push_back("asan"); if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid()) HelperStaticRuntimes.push_back("asan-preinit"); } - if (SanArgs.needsUbsanRt()) { + if (SanArgs.needsUbsanRt() && SanArgs.linkRuntimes()) { if (SanArgs.requiresMinimalRuntime()) SharedRuntimes.push_back("ubsan_minimal"); else SharedRuntimes.push_back("ubsan_standalone"); } - if (SanArgs.needsScudoRt()) { + if (SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) { if (SanArgs.requiresMinimalRuntime()) SharedRuntimes.push_back("scudo_minimal"); else SharedRuntimes.push_back("scudo"); } - if (SanArgs.needsHwasanRt()) + if (SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) SharedRuntimes.push_back("hwasan"); } // The stats_client library is also statically linked into DSOs. - if (SanArgs.needsStatsRt()) + if (SanArgs.needsStatsRt() && SanArgs.linkRuntimes()) StaticRuntimes.push_back("stats_client"); // Collect static runtimes. @@ -635,32 +657,32 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, // Don't link static runtimes into DSOs or if -shared-libasan. return; } - if (SanArgs.needsAsanRt()) { + if (SanArgs.needsAsanRt() && SanArgs.linkRuntimes()) { StaticRuntimes.push_back("asan"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("asan_cxx"); } - if (SanArgs.needsHwasanRt()) { + if (SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) { StaticRuntimes.push_back("hwasan"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("hwasan_cxx"); } - if (SanArgs.needsDfsanRt()) + if (SanArgs.needsDfsanRt() && SanArgs.linkRuntimes()) StaticRuntimes.push_back("dfsan"); - if (SanArgs.needsLsanRt()) + if (SanArgs.needsLsanRt() && SanArgs.linkRuntimes()) StaticRuntimes.push_back("lsan"); - if (SanArgs.needsMsanRt()) { + if (SanArgs.needsMsanRt() && SanArgs.linkRuntimes()) { StaticRuntimes.push_back("msan"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("msan_cxx"); } - if (SanArgs.needsTsanRt()) { + if (SanArgs.needsTsanRt() && SanArgs.linkRuntimes()) { StaticRuntimes.push_back("tsan"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("tsan_cxx"); } - if (SanArgs.needsUbsanRt()) { + if (SanArgs.needsUbsanRt() && SanArgs.linkRuntimes()) { if (SanArgs.requiresMinimalRuntime()) { StaticRuntimes.push_back("ubsan_minimal"); } else { @@ -669,22 +691,22 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, StaticRuntimes.push_back("ubsan_standalone_cxx"); } } - if (SanArgs.needsSafeStackRt()) { + if (SanArgs.needsSafeStackRt() && SanArgs.linkRuntimes()) { NonWholeStaticRuntimes.push_back("safestack"); RequiredSymbols.push_back("__safestack_init"); } - if (SanArgs.needsCfiRt()) + if (SanArgs.needsCfiRt() && SanArgs.linkRuntimes()) StaticRuntimes.push_back("cfi"); - if (SanArgs.needsCfiDiagRt()) { + if (SanArgs.needsCfiDiagRt() && SanArgs.linkRuntimes()) { StaticRuntimes.push_back("cfi_diag"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("ubsan_standalone_cxx"); } - if (SanArgs.needsStatsRt()) { + if (SanArgs.needsStatsRt() && SanArgs.linkRuntimes()) { NonWholeStaticRuntimes.push_back("stats"); RequiredSymbols.push_back("__sanitizer_stats_register"); } - if (SanArgs.needsScudoRt()) { + if (SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) { if (SanArgs.requiresMinimalRuntime()) { StaticRuntimes.push_back("scudo_minimal"); if (SanArgs.linkCXXRuntimes()) @@ -707,9 +729,10 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, NonWholeStaticRuntimes, HelperStaticRuntimes, RequiredSymbols); + const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); // Inject libfuzzer dependencies. - if (TC.getSanitizerArgs().needsFuzzer() - && !Args.hasArg(options::OPT_shared)) { + if (SanArgs.needsFuzzer() && SanArgs.linkRuntimes() && + !Args.hasArg(options::OPT_shared)) { addSanitizerRuntime(TC, Args, CmdArgs, "fuzzer", false, true); if (!Args.hasArg(clang::driver::options::OPT_nostdlibxx)) @@ -738,7 +761,6 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, if (AddExportDynamic) CmdArgs.push_back("--export-dynamic"); - const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic) CmdArgs.push_back("-export-dynamic-symbol=__cfi_check"); @@ -823,10 +845,10 @@ void tools::SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T, InputInfo II(types::TY_Object, Output.getFilename(), Output.getFilename()); // First extract the dwo sections. - C.addCommand(llvm::make_unique<Command>(JA, T, Exec, ExtractArgs, II)); + C.addCommand(std::make_unique<Command>(JA, T, Exec, ExtractArgs, II)); // Then remove them from the original .o file. - C.addCommand(llvm::make_unique<Command>(JA, T, Exec, StripArgs, II)); + C.addCommand(std::make_unique<Command>(JA, T, Exec, StripArgs, II)); } // Claim options we don't want to warn if they are unused. We do this for @@ -1176,7 +1198,6 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D, case ToolChain::UNW_None: return; case ToolChain::UNW_Libgcc: { - LibGccType LGT = getLibGccType(D, Args); if (LGT == LibGccType::StaticLibGcc) CmdArgs.push_back("-lgcc_eh"); else @@ -1235,131 +1256,6 @@ void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D, } } -/// Add OpenMP linker script arguments at the end of the argument list so that -/// the fat binary is built by embedding each of the device images into the -/// host. The linker script also defines a few symbols required by the code -/// generation so that the images can be easily retrieved at runtime by the -/// offloading library. This should be used only in tool chains that support -/// linker scripts. -void tools::AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C, - const InputInfo &Output, - const InputInfoList &Inputs, - const ArgList &Args, ArgStringList &CmdArgs, - const JobAction &JA) { - - // If this is not an OpenMP host toolchain, we don't need to do anything. - if (!JA.isHostOffloading(Action::OFK_OpenMP)) - return; - - // Create temporary linker script. Keep it if save-temps is enabled. - const char *LKS; - SmallString<256> Name = llvm::sys::path::filename(Output.getFilename()); - if (C.getDriver().isSaveTempsEnabled()) { - llvm::sys::path::replace_extension(Name, "lk"); - LKS = C.getArgs().MakeArgString(Name.c_str()); - } else { - llvm::sys::path::replace_extension(Name, ""); - Name = C.getDriver().GetTemporaryPath(Name, "lk"); - LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str())); - } - - // Add linker script option to the command. - CmdArgs.push_back("-T"); - CmdArgs.push_back(LKS); - - // Create a buffer to write the contents of the linker script. - std::string LksBuffer; - llvm::raw_string_ostream LksStream(LksBuffer); - - // Get the OpenMP offload tool chains so that we can extract the triple - // associated with each device input. - auto OpenMPToolChains = C.getOffloadToolChains<Action::OFK_OpenMP>(); - assert(OpenMPToolChains.first != OpenMPToolChains.second && - "No OpenMP toolchains??"); - - // Track the input file name and device triple in order to build the script, - // inserting binaries in the designated sections. - SmallVector<std::pair<std::string, const char *>, 8> InputBinaryInfo; - - // Add commands to embed target binaries. We ensure that each section and - // image is 16-byte aligned. This is not mandatory, but increases the - // likelihood of data to be aligned with a cache block in several main host - // machines. - LksStream << "/*\n"; - LksStream << " OpenMP Offload Linker Script\n"; - LksStream << " *** Automatically generated by Clang ***\n"; - LksStream << "*/\n"; - LksStream << "TARGET(binary)\n"; - auto DTC = OpenMPToolChains.first; - for (auto &II : Inputs) { - const Action *A = II.getAction(); - // Is this a device linking action? - if (A && isa<LinkJobAction>(A) && - A->isDeviceOffloading(Action::OFK_OpenMP)) { - assert(DTC != OpenMPToolChains.second && - "More device inputs than device toolchains??"); - InputBinaryInfo.push_back(std::make_pair( - DTC->second->getTriple().normalize(), II.getFilename())); - ++DTC; - LksStream << "INPUT(" << II.getFilename() << ")\n"; - } - } - - assert(DTC == OpenMPToolChains.second && - "Less device inputs than device toolchains??"); - - LksStream << "SECTIONS\n"; - LksStream << "{\n"; - - // Put each target binary into a separate section. - for (const auto &BI : InputBinaryInfo) { - LksStream << " .omp_offloading." << BI.first << " :\n"; - LksStream << " ALIGN(0x10)\n"; - LksStream << " {\n"; - LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_start." << BI.first - << " = .);\n"; - LksStream << " " << BI.second << "\n"; - LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_end." << BI.first - << " = .);\n"; - LksStream << " }\n"; - } - - // Add commands to define host entries begin and end. We use 1-byte subalign - // so that the linker does not add any padding and the elements in this - // section form an array. - LksStream << " .omp_offloading.entries :\n"; - LksStream << " ALIGN(0x10)\n"; - LksStream << " SUBALIGN(0x01)\n"; - LksStream << " {\n"; - LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_begin = .);\n"; - LksStream << " *(.omp_offloading.entries)\n"; - LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_end = .);\n"; - LksStream << " }\n"; - LksStream << "}\n"; - LksStream << "INSERT BEFORE .data\n"; - LksStream.flush(); - - // Dump the contents of the linker script if the user requested that. We - // support this option to enable testing of behavior with -###. - if (C.getArgs().hasArg(options::OPT_fopenmp_dump_offload_linker_script)) - llvm::errs() << LksBuffer; - - // If this is a dry run, do not create the linker script file. - if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) - return; - - // Open script file and write the contents. - std::error_code EC; - llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::F_None); - - if (EC) { - C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message(); - return; - } - - Lksf << LksBuffer; -} - /// Add HIP linker script arguments at the end of the argument list so that /// the fat binary is built by embedding the device images into the host. The /// linker script also defines a symbol required by the code generation so that @@ -1389,14 +1285,12 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C, // Create temporary linker script. Keep it if save-temps is enabled. const char *LKS; - SmallString<256> Name = llvm::sys::path::filename(Output.getFilename()); + std::string Name = llvm::sys::path::filename(Output.getFilename()); if (C.getDriver().isSaveTempsEnabled()) { - llvm::sys::path::replace_extension(Name, "lk"); - LKS = C.getArgs().MakeArgString(Name.c_str()); + LKS = C.getArgs().MakeArgString(Name + ".lk"); } else { - llvm::sys::path::replace_extension(Name, ""); - Name = C.getDriver().GetTemporaryPath(Name, "lk"); - LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str())); + auto TmpName = C.getDriver().GetTemporaryPath(Name, "lk"); + LKS = C.addTempFile(C.getArgs().MakeArgString(TmpName)); } // Add linker script option to the command. @@ -1414,11 +1308,13 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C, "Wrong platform"); (void)HIPTC; - // 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())); + const char *BundleFile; + if (C.getDriver().isSaveTempsEnabled()) { + BundleFile = C.getArgs().MakeArgString(Name + ".hipfb"); + } else { + auto TmpName = C.getDriver().GetTemporaryPath(Name, "hipfb"); + BundleFile = C.addTempFile(C.getArgs().MakeArgString(TmpName)); + } AMDGCN::constructHIPFatbinCommand(C, JA, BundleFile, DeviceInputs, Args, T); // Add commands to embed target binaries. We ensure that each section and @@ -1430,14 +1326,14 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C, LksStream << " *** Automatically generated by Clang ***\n"; LksStream << "*/\n"; LksStream << "TARGET(binary)\n"; - LksStream << "INPUT(" << BundleFileName << ")\n"; + LksStream << "INPUT(" << BundleFile << ")\n"; LksStream << "SECTIONS\n"; LksStream << "{\n"; LksStream << " .hip_fatbin :\n"; LksStream << " ALIGN(0x10)\n"; LksStream << " {\n"; LksStream << " PROVIDE_HIDDEN(__hip_fatbin = .);\n"; - LksStream << " " << BundleFileName << "\n"; + LksStream << " " << BundleFile << "\n"; LksStream << " }\n"; LksStream << " /DISCARD/ :\n"; LksStream << " {\n"; @@ -1458,7 +1354,7 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C, // Open script file and write the contents. std::error_code EC; - llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::F_None); + llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::OF_None); if (EC) { C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message(); @@ -1496,3 +1392,111 @@ void tools::addMultilibFlag(bool Enabled, const char *const Flag, Multilib::flags_list &Flags) { Flags.push_back(std::string(Enabled ? "+" : "-") + Flag); } + +static void getWebAssemblyTargetFeatures(const ArgList &Args, + std::vector<StringRef> &Features) { + handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group); +} + +void tools::getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, + const ArgList &Args, ArgStringList &CmdArgs, bool ForAS, + bool ForLTOPlugin) { + + const Driver &D = TC.getDriver(); + std::vector<StringRef> Features; + switch (Triple.getArch()) { + default: + break; + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + mips::getMIPSTargetFeatures(D, Triple, Args, Features); + break; + + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + arm::getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS); + break; + + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: + ppc::getPPCTargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::riscv32: + case llvm::Triple::riscv64: + riscv::getRISCVTargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::systemz: + systemz::getSystemZTargetFeatures(Args, Features); + break; + case llvm::Triple::aarch64: + case llvm::Triple::aarch64_be: + aarch64::getAArch64TargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::x86: + case llvm::Triple::x86_64: + x86::getX86TargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::hexagon: + hexagon::getHexagonTargetFeatures(D, Args, Features); + break; + case llvm::Triple::wasm32: + case llvm::Triple::wasm64: + getWebAssemblyTargetFeatures(Args, Features); + break; + case llvm::Triple::sparc: + case llvm::Triple::sparcel: + case llvm::Triple::sparcv9: + sparc::getSparcTargetFeatures(D, Args, Features); + break; + case llvm::Triple::r600: + 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. + llvm::StringMap<unsigned> LastOpt; + for (unsigned I = 0, N = Features.size(); I < N; ++I) { + StringRef Name = Features[I]; + assert(Name[0] == '-' || Name[0] == '+'); + LastOpt[Name.drop_front(1)] = I; + } + + for (unsigned I = 0, N = Features.size(); I < N; ++I) { + // If this feature was overridden, ignore it. + StringRef Name = Features[I]; + llvm::StringMap<unsigned>::iterator LastI = + LastOpt.find(Name.drop_front(1)); + assert(LastI != LastOpt.end()); + unsigned Last = LastI->second; + if (Last != I) + continue; + if (!ForLTOPlugin) { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back(Name.data()); + } else { + CmdArgs.push_back( + Args.MakeArgString(Twine("-plugin-opt=-mattr=") + Name)); + } + } +} + +StringRef tools::getTargetABI(const ArgList &Args, const llvm::Triple &Triple) { + // TODO: Support the other target ABI + switch (Triple.getArch()) { + default: + break; + case llvm::Triple::riscv32: + case llvm::Triple::riscv64: + return tools::riscv::getRISCVABI(Args, Triple); + break; + } + return StringRef(); +} diff --git a/lib/Driver/ToolChains/CommonArgs.h b/lib/Driver/ToolChains/CommonArgs.h index 9a311708f3ae3..79468e6b89262 100644 --- a/lib/Driver/ToolChains/CommonArgs.h +++ b/lib/Driver/ToolChains/CommonArgs.h @@ -45,13 +45,6 @@ void AddRunTimeLibs(const ToolChain &TC, const Driver &D, llvm::opt::ArgStringList &CmdArgs, const llvm::opt::ArgList &Args); -void AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C, - const InputInfo &Output, - const InputInfoList &Inputs, - const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs, - const JobAction &JA); - void AddHIPLinkerScript(const ToolChain &TC, Compilation &C, const InputInfo &Output, const InputInfoList &Inputs, const llvm::opt::ArgList &Args, @@ -84,6 +77,7 @@ void addArchSpecificRPath(const ToolChain &TC, const llvm::opt::ArgList &Args, /// Returns true, if an OpenMP runtime has been added. bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC, const llvm::opt::ArgList &Args, + bool ForceStaticHostRuntime = false, bool IsOffloadingHost = false, bool GompNeedsRT = false); llvm::opt::Arg *getLastProfileUseArg(const llvm::opt::ArgList &Args); @@ -124,6 +118,14 @@ SmallString<128> getStatsFileName(const llvm::opt::ArgList &Args, void addMultilibFlag(bool Enabled, const char *const Flag, Multilib::flags_list &Flags); +StringRef getTargetABI(const llvm::opt::ArgList &Args, + const llvm::Triple &Triple); + +void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs, bool ForAS, + bool ForLTOPlugin = false); + } // end namespace tools } // end namespace driver } // end namespace clang diff --git a/lib/Driver/ToolChains/CrossWindows.cpp b/lib/Driver/ToolChains/CrossWindows.cpp index bd3a6e11c9285..dbf6114eb2ecc 100644 --- a/lib/Driver/ToolChains/CrossWindows.cpp +++ b/lib/Driver/ToolChains/CrossWindows.cpp @@ -57,7 +57,7 @@ void tools::CrossWindows::Assembler::ConstructJob( const std::string Assembler = TC.GetProgramPath("as"); Exec = Args.MakeArgString(Assembler); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void tools::CrossWindows::Linker::ConstructJob( @@ -202,7 +202,7 @@ void tools::CrossWindows::Linker::ConstructJob( Exec = Args.MakeArgString(TC.GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } CrossWindowsToolChain::CrossWindowsToolChain(const Driver &D, diff --git a/lib/Driver/ToolChains/Cuda.cpp b/lib/Driver/ToolChains/Cuda.cpp index 96f8c513bb56b..8c704a3078adc 100644 --- a/lib/Driver/ToolChains/Cuda.cpp +++ b/lib/Driver/ToolChains/Cuda.cpp @@ -121,7 +121,7 @@ CudaInstallationDetector::CudaInstallationDetector( Candidates.emplace_back(D.SysRoot + "/usr/lib/cuda"); } - bool NoCudaLib = Args.hasArg(options::OPT_nocudalib); + bool NoCudaLib = Args.hasArg(options::OPT_nogpulib); for (const auto &Candidate : Candidates) { InstallPath = Candidate.Path; @@ -422,7 +422,7 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA, Exec = A->getValue(); else Exec = Args.MakeArgString(TC.GetProgramPath("ptxas")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } static bool shouldIncludePTX(const ArgList &Args, const char *gpu_arch) { @@ -488,7 +488,7 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(A)); const char *Exec = Args.MakeArgString(TC.GetProgramPath("fatbinary")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA, @@ -563,11 +563,9 @@ void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(CubinF); } - AddOpenMPLinkerScript(getToolChain(), C, Output, Inputs, Args, CmdArgs, JA); - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("nvlink")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } /// CUDA toolchain. Our assembler is ptxas, and our "linker" is fatbinary, @@ -628,7 +626,7 @@ void CudaToolChain::addClangTargetOptions( CC1Args.push_back("-fgpu-rdc"); } - if (DriverArgs.hasArg(options::OPT_nocudalib)) + if (DriverArgs.hasArg(options::OPT_nogpulib)) return; std::string LibDeviceFile = CudaInstallation.getLibDeviceFile(GpuArch); diff --git a/lib/Driver/ToolChains/Darwin.cpp b/lib/Driver/ToolChains/Darwin.cpp index 5de7d7132df81..ee08b8208d939 100644 --- a/lib/Driver/ToolChains/Darwin.cpp +++ b/lib/Driver/ToolChains/Darwin.cpp @@ -146,7 +146,7 @@ void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA, // asm_final spec is empty. const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void darwin::MachOTool::anchor() {} @@ -451,7 +451,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("touch")); CmdArgs.push_back(Output.getFilename()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, None)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, None)); return; } @@ -653,7 +653,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); std::unique_ptr<Command> Cmd = - llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs); + std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs); Cmd->setInputFileList(std::move(InputFileList)); C.addCommand(std::move(Cmd)); } @@ -677,7 +677,7 @@ void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA, @@ -697,7 +697,7 @@ void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("dsymutil")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, @@ -720,7 +720,7 @@ void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) @@ -1128,7 +1128,6 @@ void Darwin::addProfileRTLibs(const ArgList &Args, } else { addExportedSymbol(CmdArgs, "___llvm_profile_filename"); addExportedSymbol(CmdArgs, "___llvm_profile_raw_version"); - addExportedSymbol(CmdArgs, "_lprofCurFilename"); } addExportedSymbol(CmdArgs, "_lprofDirMode"); } @@ -1480,22 +1479,6 @@ getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver, Targets[I.index()] = Env; } - // Do not allow conflicts with the watchOS target. - if (!Targets[Darwin::WatchOS].empty() && - (!Targets[Darwin::IPhoneOS].empty() || !Targets[Darwin::TvOS].empty())) { - TheDriver.Diag(diag::err_drv_conflicting_deployment_targets) - << "WATCHOS_DEPLOYMENT_TARGET" - << (!Targets[Darwin::IPhoneOS].empty() ? "IPHONEOS_DEPLOYMENT_TARGET" - : "TVOS_DEPLOYMENT_TARGET"); - } - - // Do not allow conflicts with the tvOS target. - if (!Targets[Darwin::TvOS].empty() && !Targets[Darwin::IPhoneOS].empty()) { - TheDriver.Diag(diag::err_drv_conflicting_deployment_targets) - << "TVOS_DEPLOYMENT_TARGET" - << "IPHONEOS_DEPLOYMENT_TARGET"; - } - // Allow conflicts among OSX and iOS for historical reasons, but choose the // default platform. if (!Targets[Darwin::MacOS].empty() && @@ -1508,6 +1491,18 @@ getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver, else Targets[Darwin::IPhoneOS] = Targets[Darwin::WatchOS] = Targets[Darwin::TvOS] = ""; + } else { + // Don't allow conflicts in any other platform. + int FirstTarget = llvm::array_lengthof(Targets); + for (int I = 0; I != llvm::array_lengthof(Targets); ++I) { + if (Targets[I].empty()) + continue; + if (FirstTarget == llvm::array_lengthof(Targets)) + FirstTarget = I; + else + TheDriver.Diag(diag::err_drv_conflicting_deployment_targets) + << Targets[FirstTarget] << Targets[I]; + } } for (const auto &Target : llvm::enumerate(llvm::makeArrayRef(Targets))) { diff --git a/lib/Driver/ToolChains/DragonFly.cpp b/lib/Driver/ToolChains/DragonFly.cpp index 0a7c8b1615e79..424331fbc6fe0 100644 --- a/lib/Driver/ToolChains/DragonFly.cpp +++ b/lib/Driver/ToolChains/DragonFly.cpp @@ -45,7 +45,7 @@ void dragonfly::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -169,7 +169,7 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } /// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly. diff --git a/lib/Driver/ToolChains/FreeBSD.cpp b/lib/Driver/ToolChains/FreeBSD.cpp index 3a0bab8d07f52..7c891a24ba304 100644 --- a/lib/Driver/ToolChains/FreeBSD.cpp +++ b/lib/Driver/ToolChains/FreeBSD.cpp @@ -112,7 +112,7 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -197,6 +197,14 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, else CmdArgs.push_back("elf64ltsmip_fbsd"); break; + case llvm::Triple::riscv32: + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf32lriscv"); + break; + case llvm::Triple::riscv64: + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf64lriscv"); + break; default: break; } @@ -262,7 +270,11 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { - addOpenMPRuntime(CmdArgs, ToolChain, Args); + // Use the static OpenMP runtime with -static-openmp + bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && + !Args.hasArg(options::OPT_static); + addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); + if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); @@ -331,7 +343,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, ToolChain.addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } /// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly. @@ -356,6 +368,12 @@ ToolChain::CXXStdlibType FreeBSD::GetDefaultCXXStdlibType() const { return ToolChain::CST_Libstdcxx; } +unsigned FreeBSD::GetDefaultDwarfVersion() const { + if (getTriple().getOSMajorVersion() < 12) + return 2; + return 4; +} + void FreeBSD::addLibStdCxxIncludePaths( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const { diff --git a/lib/Driver/ToolChains/FreeBSD.h b/lib/Driver/ToolChains/FreeBSD.h index adfe21da372f3..d17b3808ffacc 100644 --- a/lib/Driver/ToolChains/FreeBSD.h +++ b/lib/Driver/ToolChains/FreeBSD.h @@ -69,7 +69,7 @@ public: const llvm::opt::ArgList &Args) const override; bool isPIEDefault() const override; SanitizerMask getSupportedSanitizers() const override; - unsigned GetDefaultDwarfVersion() const override { return 2; } + unsigned GetDefaultDwarfVersion() const override; // Until dtrace (via CTF) and LLDB can deal with distributed debug info, // FreeBSD defaults to standalone/full debug info. bool GetDefaultStandaloneDebug() const override { return true; } diff --git a/lib/Driver/ToolChains/Fuchsia.cpp b/lib/Driver/ToolChains/Fuchsia.cpp index 1f5ec9ebb16d5..e7d38ff9f227b 100644 --- a/lib/Driver/ToolChains/Fuchsia.cpp +++ b/lib/Driver/ToolChains/Fuchsia.cpp @@ -51,6 +51,8 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, llvm::sys::path::stem(Exec).equals_lower("ld.lld")) { CmdArgs.push_back("-z"); CmdArgs.push_back("rodynamic"); + CmdArgs.push_back("-z"); + CmdArgs.push_back("separate-loadable-segments"); } if (!D.SysRoot.empty()) @@ -154,7 +156,7 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-lc"); } - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } /// Fuchsia - Fuchsia tool chain which can call as(1) and ld(1) directly. diff --git a/lib/Driver/ToolChains/Fuchsia.h b/lib/Driver/ToolChains/Fuchsia.h index dd7c5c650352e..fee0e018f3ce3 100644 --- a/lib/Driver/ToolChains/Fuchsia.h +++ b/lib/Driver/ToolChains/Fuchsia.h @@ -17,9 +17,9 @@ namespace clang { namespace driver { namespace tools { namespace fuchsia { -class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool { +class LLVM_LIBRARY_VISIBILITY Linker : public Tool { public: - Linker(const ToolChain &TC) : GnuTool("fuchsia::Linker", "ld.lld", TC) {} + Linker(const ToolChain &TC) : Tool("fuchsia::Linker", "ld.lld", TC) {} bool hasIntegratedCPP() const override { return false; } bool isLinkJob() const override { return true; } diff --git a/lib/Driver/ToolChains/Gnu.cpp b/lib/Driver/ToolChains/Gnu.cpp index 33cdd3585c297..c302a31cd2e10 100644 --- a/lib/Driver/ToolChains/Gnu.cpp +++ b/lib/Driver/ToolChains/Gnu.cpp @@ -189,7 +189,7 @@ void tools::gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, GCCName = "gcc"; const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void tools::gcc::Preprocessor::RenderExtraToolArgs( @@ -499,7 +499,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, P = ToolChain.GetFilePath(crtbegin); } CmdArgs.push_back(Args.MakeArgString(P)); - } + } // Add crtfastmath.o if available and fast math is enabled. ToolChain.AddFastMathRuntimeIfAvailable(Args, CmdArgs); @@ -555,9 +555,13 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, bool WantPthread = Args.hasArg(options::OPT_pthread) || Args.hasArg(options::OPT_pthreads); + // Use the static OpenMP runtime with -static-openmp + bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && + !Args.hasArg(options::OPT_static); + // FIXME: Only pass GompNeedsRT = true for platforms with libgomp that // require librt. Most modern Linux platforms do, but some may not. - if (addOpenMPRuntime(CmdArgs, ToolChain, Args, + if (addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP, JA.isHostOffloading(Action::OFK_OpenMP), /* GompNeedsRT= */ true)) // OpenMP runtimes implies pthreads when using the GNU toolchain. @@ -619,15 +623,12 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, } } - // Add OpenMP offloading linker script args if required. - AddOpenMPLinkerScript(getToolChain(), C, Output, Inputs, Args, CmdArgs, JA); - // Add HIP offloading linker script args if required. 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)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void tools::gnutools::Assembler::ConstructJob(Compilation &C, @@ -819,7 +820,8 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C, A->render(Args, CmdArgs); } else if (mips::shouldUseFPXX( Args, getToolChain().getTriple(), CPUName, ABIName, - mips::getMipsFloatABI(getToolChain().getDriver(), Args))) + mips::getMipsFloatABI(getToolChain().getDriver(), Args, + getToolChain().getTriple()))) CmdArgs.push_back("-mfpxx"); // Pass on -mmips16 or -mno-mips16. However, the assembler equivalent of @@ -878,7 +880,7 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); // Handle the debug info splitting at object creation time if we're // creating an object. @@ -2017,7 +2019,8 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( static const char *const RISCV64LibDirs[] = {"/lib64", "/lib"}; static const char *const RISCV64Triples[] = {"riscv64-unknown-linux-gnu", "riscv64-linux-gnu", - "riscv64-unknown-elf"}; + "riscv64-unknown-elf", + "riscv64-suse-linux"}; static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"}; static const char *const SPARCv8Triples[] = {"sparc-linux-gnu", diff --git a/lib/Driver/ToolChains/HIP.cpp b/lib/Driver/ToolChains/HIP.cpp index 2ec97e798fd05..ad9384df6a242 100644 --- a/lib/Driver/ToolChains/HIP.cpp +++ b/lib/Driver/ToolChains/HIP.cpp @@ -23,7 +23,7 @@ using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; -#if _WIN32 || _WIN64 +#if defined(_WIN32) || defined(_WIN64) #define NULL_FILE "nul" #else #define NULL_FILE "/dev/null" @@ -48,6 +48,20 @@ static void addBCLib(const Driver &D, const ArgList &Args, D.Diag(diag::err_drv_no_such_file) << BCName; } +static const char *getOutputFileName(Compilation &C, StringRef Base, + const char *Postfix, + const char *Extension) { + const char *OutputFileName; + if (C.getDriver().isSaveTempsEnabled()) { + OutputFileName = + C.getArgs().MakeArgString(Base.str() + Postfix + "." + Extension); + } else { + std::string TmpName = + C.getDriver().GetTemporaryPath(Base.str() + Postfix, Extension); + OutputFileName = C.addTempFile(C.getArgs().MakeArgString(TmpName)); + } + return OutputFileName; +} } // namespace const char *AMDGCN::Linker::constructLLVMLinkCommand( @@ -61,15 +75,12 @@ const char *AMDGCN::Linker::constructLLVMLinkCommand( // Add an intermediate output file. CmdArgs.push_back("-o"); - std::string TmpName = - C.getDriver().GetTemporaryPath(OutputFilePrefix.str() + "-linked", "bc"); - const char *OutputFileName = - C.addTempFile(C.getArgs().MakeArgString(TmpName)); + auto OutputFileName = getOutputFileName(C, OutputFilePrefix, "-linked", "bc"); CmdArgs.push_back(OutputFileName); SmallString<128> ExecPath(C.getDriver().Dir); llvm::sys::path::append(ExecPath, "llvm-link"); const char *Exec = Args.MakeArgString(ExecPath); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); return OutputFileName; } @@ -109,26 +120,26 @@ const char *AMDGCN::Linker::constructOptCommand( } OptArgs.push_back("-o"); - std::string TmpFileName = C.getDriver().GetTemporaryPath( - OutputFilePrefix.str() + "-optimized", "bc"); - const char *OutputFileName = - C.addTempFile(C.getArgs().MakeArgString(TmpFileName)); + auto OutputFileName = + getOutputFileName(C, OutputFilePrefix, "-optimized", "bc"); OptArgs.push_back(OutputFileName); SmallString<128> OptPath(C.getDriver().Dir); llvm::sys::path::append(OptPath, "opt"); const char *OptExec = Args.MakeArgString(OptPath); - C.addCommand(llvm::make_unique<Command>(JA, *this, OptExec, OptArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, OptExec, OptArgs, Inputs)); return OutputFileName; } const char *AMDGCN::Linker::constructLlcCommand( Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const llvm::opt::ArgList &Args, llvm::StringRef SubArchName, - llvm::StringRef OutputFilePrefix, const char *InputFileName) const { + llvm::StringRef OutputFilePrefix, const char *InputFileName, + bool OutputIsAsm) const { // Construct llc command. - ArgStringList LlcArgs{InputFileName, "-mtriple=amdgcn-amd-amdhsa", - "-filetype=obj", - Args.MakeArgString("-mcpu=" + SubArchName)}; + ArgStringList LlcArgs{ + InputFileName, "-mtriple=amdgcn-amd-amdhsa", + Args.MakeArgString(Twine("-filetype=") + (OutputIsAsm ? "asm" : "obj")), + Args.MakeArgString("-mcpu=" + SubArchName)}; // Extract all the -m options std::vector<llvm::StringRef> Features; @@ -151,15 +162,13 @@ const char *AMDGCN::Linker::constructLlcCommand( // Add output filename LlcArgs.push_back("-o"); - std::string LlcOutputFileName = - C.getDriver().GetTemporaryPath(OutputFilePrefix, "o"); - const char *LlcOutputFile = - C.addTempFile(C.getArgs().MakeArgString(LlcOutputFileName)); + auto LlcOutputFile = + getOutputFileName(C, OutputFilePrefix, "", OutputIsAsm ? "s" : "o"); LlcArgs.push_back(LlcOutputFile); SmallString<128> LlcPath(C.getDriver().Dir); llvm::sys::path::append(LlcPath, "llc"); const char *Llc = Args.MakeArgString(LlcPath); - C.addCommand(llvm::make_unique<Command>(JA, *this, Llc, LlcArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Llc, LlcArgs, Inputs)); return LlcOutputFile; } @@ -175,7 +184,7 @@ void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA, SmallString<128> LldPath(C.getDriver().Dir); llvm::sys::path::append(LldPath, "lld"); const char *Lld = Args.MakeArgString(LldPath); - C.addCommand(llvm::make_unique<Command>(JA, *this, Lld, LldArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Lld, LldArgs, Inputs)); } // Construct a clang-offload-bundler command to bundle code objects for @@ -209,7 +218,7 @@ void AMDGCN::constructHIPFatbinCommand(Compilation &C, const JobAction &JA, 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)); + C.addCommand(std::make_unique<Command>(JA, T, Bundler, BundlerArgs, Inputs)); } // For amdgcn the inputs of the linker job are device bitcode and output is @@ -230,14 +239,18 @@ void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA, assert(StringRef(SubArchName).startswith("gfx") && "Unsupported sub arch"); // Prefix for temporary file name. - std::string Prefix = - llvm::sys::path::stem(Inputs[0].getFilename()).str() + "-" + SubArchName; + std::string Prefix = llvm::sys::path::stem(Inputs[0].getFilename()).str(); + if (!C.getDriver().isSaveTempsEnabled()) + Prefix += "-" + SubArchName; // Each command outputs different files. const char *LLVMLinkCommand = constructLLVMLinkCommand(C, JA, Inputs, Args, SubArchName, Prefix); const char *OptCommand = constructOptCommand(C, JA, Inputs, Args, SubArchName, Prefix, LLVMLinkCommand); + if (C.getDriver().isSaveTempsEnabled()) + constructLlcCommand(C, JA, Inputs, Args, SubArchName, Prefix, OptCommand, + /*OutputIsAsm=*/true); const char *LlcCommand = constructLlcCommand(C, JA, Inputs, Args, SubArchName, Prefix, OptCommand); constructLldCommand(C, JA, Inputs, Output, Args, LlcCommand); @@ -286,6 +299,9 @@ void HIPToolChain::addClangTargetOptions( CC1Args.append({"-fvisibility", "hidden"}); CC1Args.push_back("-fapply-global-visibility-to-externs"); } + + if (DriverArgs.hasArg(options::OPT_nogpulib)) + return; ArgStringList LibraryPaths; // Find in --hip-device-lib-path and HIP_LIBRARY_PATH. diff --git a/lib/Driver/ToolChains/HIP.h b/lib/Driver/ToolChains/HIP.h index a650095d054d7..2d146ce5cc6fd 100644 --- a/lib/Driver/ToolChains/HIP.h +++ b/lib/Driver/ToolChains/HIP.h @@ -58,7 +58,8 @@ private: const llvm::opt::ArgList &Args, llvm::StringRef SubArchName, llvm::StringRef OutputFilePrefix, - const char *InputFileName) const; + const char *InputFileName, + bool OutputIsAsm = false) const; void constructLldCommand(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const InputInfo &Output, diff --git a/lib/Driver/ToolChains/Hexagon.cpp b/lib/Driver/ToolChains/Hexagon.cpp index f2c3ea11a9f3f..96cc084e2821e 100644 --- a/lib/Driver/ToolChains/Hexagon.cpp +++ b/lib/Driver/ToolChains/Hexagon.cpp @@ -183,7 +183,7 @@ void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA, } auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName)); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA, @@ -370,7 +370,7 @@ void hexagon::Linker::ConstructJob(Compilation &C, const JobAction &JA, LinkingOutput); const char *Exec = Args.MakeArgString(HTC.GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } // Hexagon tools end. diff --git a/lib/Driver/ToolChains/InterfaceStubs.cpp b/lib/Driver/ToolChains/InterfaceStubs.cpp new file mode 100644 index 0000000000000..6677843b2c533 --- /dev/null +++ b/lib/Driver/ToolChains/InterfaceStubs.cpp @@ -0,0 +1,37 @@ +//===--- InterfaceStubs.cpp - Base InterfaceStubs Implementations C++ ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "InterfaceStubs.h" +#include "CommonArgs.h" +#include "clang/Driver/Compilation.h" + +namespace clang { +namespace driver { +namespace tools { +namespace ifstool { +void Merger::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &Args, + const char *LinkingOutput) const { + std::string Merger = getToolChain().GetProgramPath(getShortName()); + llvm::opt::ArgStringList CmdArgs; + CmdArgs.push_back("-action"); + CmdArgs.push_back(Args.getLastArg(options::OPT_emit_merged_ifs) + ? "write-ifs" + : "write-bin"); + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + for (const auto &Input : Inputs) + CmdArgs.push_back(Input.getFilename()); + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Merger), + CmdArgs, Inputs)); +} +} // namespace ifstool +} // namespace tools +} // namespace driver +} // namespace clang diff --git a/lib/Driver/ToolChains/InterfaceStubs.h b/lib/Driver/ToolChains/InterfaceStubs.h new file mode 100644 index 0000000000000..4afa73701a4c5 --- /dev/null +++ b/lib/Driver/ToolChains/InterfaceStubs.h @@ -0,0 +1,36 @@ +//===--- InterfaceStubs.cpp - Base InterfaceStubs Implementations C++ ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_IFS_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_IFS_H + +#include "clang/Driver/Tool.h" +#include "clang/Driver/ToolChain.h" + +namespace clang { +namespace driver { +namespace tools { +namespace ifstool { +class LLVM_LIBRARY_VISIBILITY Merger : public Tool { +public: + Merger(const ToolChain &TC) : Tool("IFS::Merger", "llvm-ifs", TC) {} + + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return false; } + + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; +} // end namespace ifstool +} // end namespace tools +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_IFS_H diff --git a/lib/Driver/ToolChains/Linux.cpp b/lib/Driver/ToolChains/Linux.cpp index d900508ad9385..087783875ffe2 100644 --- a/lib/Driver/ToolChains/Linux.cpp +++ b/lib/Driver/ToolChains/Linux.cpp @@ -658,11 +658,11 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 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); - } + SmallString<128> ResourceDirInclude(D.ResourceDir); + llvm::sys::path::append(ResourceDirInclude, "include"); + if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && + (!getTriple().isMusl() || DriverArgs.hasArg(options::OPT_nostdlibinc))) + addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude); if (DriverArgs.hasArg(options::OPT_nostdlibinc)) return; @@ -860,6 +860,9 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include"); addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include"); + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && getTriple().isMusl()) + addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude); } static std::string DetectLibcxxIncludePath(llvm::vfs::FileSystem &vfs, @@ -1026,8 +1029,6 @@ SanitizerMask Linux::getSupportedSanitizers() const { Res |= SanitizerKind::HWAddress; Res |= SanitizerKind::KernelHWAddress; } - if (IsAArch64) - Res |= SanitizerKind::MemTag; return Res; } diff --git a/lib/Driver/ToolChains/MSP430.cpp b/lib/Driver/ToolChains/MSP430.cpp index fc6048f17d785..bc77f015915dc 100644 --- a/lib/Driver/ToolChains/MSP430.cpp +++ b/lib/Driver/ToolChains/MSP430.cpp @@ -227,6 +227,6 @@ void msp430::Linker::ConstructJob(Compilation &C, const JobAction &JA, } CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), CmdArgs, Inputs)); } diff --git a/lib/Driver/ToolChains/MSVC.cpp b/lib/Driver/ToolChains/MSVC.cpp index 6ed80a8f47523..1d31844bfcc88 100644 --- a/lib/Driver/ToolChains/MSVC.cpp +++ b/lib/Driver/ToolChains/MSVC.cpp @@ -331,6 +331,11 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, TC.getSubDirectoryPath( toolchains::MSVCToolChain::SubDirectoryType::Lib))); + CmdArgs.push_back(Args.MakeArgString( + Twine("-libpath:") + + TC.getSubDirectoryPath(toolchains::MSVCToolChain::SubDirectoryType::Lib, + "atlmfc"))); + if (TC.useUniversalCRT()) { std::string UniversalCRTLibPath; if (TC.getUniversalCRTLibraryPath(UniversalCRTLibPath)) @@ -548,7 +553,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, EnvVar.substr(0, PrefixLen) + TC.getSubDirectoryPath(SubDirectoryType::Bin) + llvm::Twine(llvm::sys::EnvPathSeparator) + - TC.getSubDirectoryPath(SubDirectoryType::Bin, HostArch) + + TC.getSubDirectoryPath(SubDirectoryType::Bin, "", HostArch) + (EnvVar.size() > PrefixLen ? llvm::Twine(llvm::sys::EnvPathSeparator) + EnvVar.substr(PrefixLen) @@ -565,7 +570,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, linkPath = TC.GetProgramPath(Linker.str().c_str()); } - auto LinkCmd = llvm::make_unique<Command>( + auto LinkCmd = std::make_unique<Command>( JA, *this, Args.MakeArgString(linkPath), CmdArgs, Inputs); if (!Environment.empty()) LinkCmd->setEnvironment(Environment); @@ -695,7 +700,7 @@ std::unique_ptr<Command> visualstudio::Compiler::GetCommand( CmdArgs.push_back(Fo); std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe"); - return llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), + return std::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs, Inputs); } @@ -824,6 +829,7 @@ static const char *llvmArchToDevDivInternalArch(llvm::Triple::ArchType Arch) { // of hardcoding paths. std::string MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type, + llvm::StringRef SubdirParent, llvm::Triple::ArchType TargetArch) const { const char *SubdirName; const char *IncludeName; @@ -843,6 +849,9 @@ MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type, } llvm::SmallString<256> Path(VCToolChainPath); + if (!SubdirParent.empty()) + llvm::sys::path::append(Path, SubdirParent); + switch (Type) { case SubDirectoryType::Bin: if (VSLayout == ToolsetLayout::VS2017OrNewer) { @@ -1228,6 +1237,8 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, if (!VCToolChainPath.empty()) { addSystemInclude(DriverArgs, CC1Args, getSubDirectoryPath(SubDirectoryType::Include)); + addSystemInclude(DriverArgs, CC1Args, + getSubDirectoryPath(SubDirectoryType::Include, "atlmfc")); if (useUniversalCRT()) { std::string UniversalCRTSdkPath; diff --git a/lib/Driver/ToolChains/MSVC.h b/lib/Driver/ToolChains/MSVC.h index aba9417c97279..41a69a82fecfe 100644 --- a/lib/Driver/ToolChains/MSVC.h +++ b/lib/Driver/ToolChains/MSVC.h @@ -78,10 +78,12 @@ 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. + /// Set CodeView as the default debug info format for non-MachO binary + /// formats, and to DWARF otherwise. Users can use -gcodeview and -gdwarf to + /// override the default. codegenoptions::DebugInfoFormat getDefaultDebugFormat() const override { - return codegenoptions::DIF_CodeView; + return getTriple().isOSBinFormatMachO() ? codegenoptions::DIF_DWARF + : codegenoptions::DIF_CodeView; } /// Set the debugger tuning to "default", since we're definitely not tuning @@ -96,12 +98,14 @@ public: Lib, }; std::string getSubDirectoryPath(SubDirectoryType Type, + llvm::StringRef SubdirParent, llvm::Triple::ArchType TargetArch) const; // Convenience overload. // Uses the current target arch. - std::string getSubDirectoryPath(SubDirectoryType Type) const { - return getSubDirectoryPath(Type, getArch()); + std::string getSubDirectoryPath(SubDirectoryType Type, + llvm::StringRef SubdirParent = "") const { + return getSubDirectoryPath(Type, SubdirParent, getArch()); } enum class ToolsetLayout { diff --git a/lib/Driver/ToolChains/MinGW.cpp b/lib/Driver/ToolChains/MinGW.cpp index 0e1873cce25be..0d851114c225b 100644 --- a/lib/Driver/ToolChains/MinGW.cpp +++ b/lib/Driver/ToolChains/MinGW.cpp @@ -49,7 +49,7 @@ void tools::MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); if (Args.hasArg(options::OPT_gsplit_dwarf)) SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, @@ -294,7 +294,7 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, } } const char *Exec = Args.MakeArgString(TC.GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple. diff --git a/lib/Driver/ToolChains/MinGW.h b/lib/Driver/ToolChains/MinGW.h index 08298e910ebbd..6752a405be879 100644 --- a/lib/Driver/ToolChains/MinGW.h +++ b/lib/Driver/ToolChains/MinGW.h @@ -34,7 +34,8 @@ public: class LLVM_LIBRARY_VISIBILITY Linker : public Tool { public: - Linker(const ToolChain &TC) : Tool("MinGW::Linker", "linker", TC) {} + Linker(const ToolChain &TC) + : Tool("MinGW::Linker", "linker", TC, Tool::RF_Full) {} bool hasIntegratedCPP() const override { return false; } bool isLinkJob() const override { return true; } diff --git a/lib/Driver/ToolChains/Minix.cpp b/lib/Driver/ToolChains/Minix.cpp index dbcc1f8908c4b..6947049ea52ee 100644 --- a/lib/Driver/ToolChains/Minix.cpp +++ b/lib/Driver/ToolChains/Minix.cpp @@ -36,7 +36,7 @@ void tools::minix::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void tools::minix::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -88,7 +88,7 @@ void tools::minix::Linker::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } /// Minix - Minix tool chain which can call as(1) and ld(1) directly. diff --git a/lib/Driver/ToolChains/Myriad.cpp b/lib/Driver/ToolChains/Myriad.cpp index 16eea1f13b142..2ce0f13ce3d1a 100644 --- a/lib/Driver/ToolChains/Myriad.cpp +++ b/lib/Driver/ToolChains/Myriad.cpp @@ -77,7 +77,7 @@ void tools::SHAVE::Compiler::ConstructJob(Compilation &C, const JobAction &JA, std::string Exec = Args.MakeArgString(getToolChain().GetProgramPath("moviCompile")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs, Inputs)); } @@ -112,7 +112,7 @@ void tools::SHAVE::Assembler::ConstructJob(Compilation &C, const JobAction &JA, std::string Exec = Args.MakeArgString(getToolChain().GetProgramPath("moviAsm")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs, Inputs)); } @@ -198,7 +198,7 @@ void tools::Myriad::Linker::ConstructJob(Compilation &C, const JobAction &JA, std::string Exec = Args.MakeArgString(TC.GetProgramPath("sparc-myriad-rtems-ld")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs, Inputs)); } diff --git a/lib/Driver/ToolChains/NaCl.cpp b/lib/Driver/ToolChains/NaCl.cpp index 984afc1758b1a..97241c8840273 100644 --- a/lib/Driver/ToolChains/NaCl.cpp +++ b/lib/Driver/ToolChains/NaCl.cpp @@ -193,7 +193,7 @@ void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } /// NaCl Toolchain diff --git a/lib/Driver/ToolChains/NetBSD.cpp b/lib/Driver/ToolChains/NetBSD.cpp index 3219a5d1e4f4f..405142204199d 100644 --- a/lib/Driver/ToolChains/NetBSD.cpp +++ b/lib/Driver/ToolChains/NetBSD.cpp @@ -103,7 +103,7 @@ void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as"))); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -289,7 +289,11 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { - addOpenMPRuntime(CmdArgs, getToolChain(), Args); + // Use the static OpenMP runtime with -static-openmp + bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && + !Args.hasArg(options::OPT_static); + addOpenMPRuntime(CmdArgs, getToolChain(), Args, StaticOpenMP); + if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); @@ -333,7 +337,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, ToolChain.addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } /// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly. @@ -485,10 +489,23 @@ SanitizerMask NetBSD::getSupportedSanitizers() const { return Res; } -void NetBSD::addClangTargetOptions(const ArgList &, +void NetBSD::addClangTargetOptions(const ArgList &DriverArgs, ArgStringList &CC1Args, Action::OffloadKind) const { const SanitizerArgs &SanArgs = getSanitizerArgs(); if (SanArgs.hasAnySanitizer()) CC1Args.push_back("-D_REENTRANT"); + + unsigned Major, Minor, Micro; + getTriple().getOSVersion(Major, Minor, Micro); + bool UseInitArrayDefault = + Major >= 9 || Major == 0 || + getTriple().getArch() == llvm::Triple::aarch64 || + getTriple().getArch() == llvm::Triple::aarch64_be || + getTriple().getArch() == llvm::Triple::arm || + getTriple().getArch() == llvm::Triple::armeb; + + if (DriverArgs.hasFlag(options::OPT_fuse_init_array, + options::OPT_fno_use_init_array, UseInitArrayDefault)) + CC1Args.push_back("-fuse-init-array"); } diff --git a/lib/Driver/ToolChains/OpenBSD.cpp b/lib/Driver/ToolChains/OpenBSD.cpp index 8441b83c29a93..e93f5fcc3d819 100644 --- a/lib/Driver/ToolChains/OpenBSD.cpp +++ b/lib/Driver/ToolChains/OpenBSD.cpp @@ -89,7 +89,7 @@ void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -227,7 +227,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } SanitizerMask OpenBSD::getSupportedSanitizers() const { diff --git a/lib/Driver/ToolChains/PPCLinux.cpp b/lib/Driver/ToolChains/PPCLinux.cpp index 5221e5d0e22cb..af2e3a21a0af7 100644 --- a/lib/Driver/ToolChains/PPCLinux.cpp +++ b/lib/Driver/ToolChains/PPCLinux.cpp @@ -16,10 +16,7 @@ using namespace llvm::opt; void PPCLinuxToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { - // PPC wrapper headers are implementation of x86 intrinsics on PowerPC, which - // is not supported on PPC32 platform. - if (getArch() != llvm::Triple::ppc && - !DriverArgs.hasArg(clang::driver::options::OPT_nostdinc) && + if (!DriverArgs.hasArg(clang::driver::options::OPT_nostdinc) && !DriverArgs.hasArg(options::OPT_nobuiltininc)) { const Driver &D = getDriver(); SmallString<128> P(D.ResourceDir); diff --git a/lib/Driver/ToolChains/PS4CPU.cpp b/lib/Driver/ToolChains/PS4CPU.cpp index 7be471365668a..4e8840296205d 100644 --- a/lib/Driver/ToolChains/PS4CPU.cpp +++ b/lib/Driver/ToolChains/PS4CPU.cpp @@ -62,7 +62,7 @@ void tools::PS4cpu::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("orbis-as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } static void AddPS4SanitizerArgs(const ToolChain &TC, ArgStringList &CmdArgs) { @@ -141,7 +141,7 @@ static void ConstructPS4LinkJob(const Tool &T, Compilation &C, const char *Exec = Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld")); - C.addCommand(llvm::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs)); } static void ConstructGoldLinkJob(const Tool &T, Compilation &C, @@ -319,7 +319,7 @@ static void ConstructGoldLinkJob(const Tool &T, Compilation &C, Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld")); #endif - C.addCommand(llvm::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, T, Exec, CmdArgs, Inputs)); } void tools::PS4cpu::Link::ConstructJob(Compilation &C, const JobAction &JA, diff --git a/lib/Driver/ToolChains/RISCVToolchain.cpp b/lib/Driver/ToolChains/RISCVToolchain.cpp index c5fdd129c3a8d..22dc5117f1962 100644 --- a/lib/Driver/ToolChains/RISCVToolchain.cpp +++ b/lib/Driver/ToolChains/RISCVToolchain.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "RISCVToolchain.h" +#include "Arch/RISCV.h" #include "CommonArgs.h" #include "InputInfo.h" #include "clang/Driver/Compilation.h" @@ -100,6 +101,12 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA, std::string Linker = getToolChain().GetProgramPath(getShortName()); + if (D.isUsingLTO()) { + assert(!Inputs.empty() && "Must have at least one input."); + AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0], + D.getLTOMode() == LTOK_Thin); + } + bool WantCRTs = !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles); @@ -134,7 +141,7 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), + C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), CmdArgs, Inputs)); } // RISCV tools end. diff --git a/lib/Driver/ToolChains/RISCVToolchain.h b/lib/Driver/ToolChains/RISCVToolchain.h index b2b56b066efd2..673d749d76ff7 100644 --- a/lib/Driver/ToolChains/RISCVToolchain.h +++ b/lib/Driver/ToolChains/RISCVToolchain.h @@ -25,6 +25,7 @@ public: void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind) const override; + bool HasNativeLLVMSupport() const override { return true; } void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; diff --git a/lib/Driver/ToolChains/Solaris.cpp b/lib/Driver/ToolChains/Solaris.cpp index 38f24d4cf7e74..fc4e2cf151ef1 100644 --- a/lib/Driver/ToolChains/Solaris.cpp +++ b/lib/Driver/ToolChains/Solaris.cpp @@ -8,6 +8,7 @@ #include "Solaris.h" #include "CommonArgs.h" +#include "clang/Basic/LangStandard.h" #include "clang/Config/config.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" @@ -40,7 +41,7 @@ void solaris::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -86,8 +87,28 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, Args.MakeArgString(getToolChain().GetFilePath("crt1.o"))); CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o"))); + + const Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi); + bool HaveAnsi = false; + const LangStandard *LangStd = nullptr; + if (Std) { + HaveAnsi = Std->getOption().matches(options::OPT_ansi); + if (!HaveAnsi) + LangStd = LangStandard::getLangStandardForName(Std->getValue()); + } + + const char *values_X = "values-Xa.o"; + // Use values-Xc.o for -ansi, -std=c*, -std=iso9899:199409. + if (HaveAnsi || (LangStd && !LangStd->isGNUMode())) + values_X = "values-Xc.o"; + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(values_X))); + + const char *values_xpg = "values-xpg6.o"; + // Use values-xpg4.o for -std=c90, -std=gnu90, -std=iso9899:199409. + if (LangStd && LangStd->getLanguage() == Language::C && !LangStd->isC99()) + values_xpg = "values-xpg4.o"; CmdArgs.push_back( - Args.MakeArgString(getToolChain().GetFilePath("values-Xa.o"))); + Args.MakeArgString(getToolChain().GetFilePath(values_xpg))); CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o"))); } @@ -129,7 +150,7 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } static StringRef getSolarisLibSuffix(const llvm::Triple &Triple) { @@ -177,6 +198,7 @@ Solaris::Solaris(const Driver &D, const llvm::Triple &Triple, SanitizerMask Solaris::getSupportedSanitizers() const { const bool IsX86 = getTriple().getArch() == llvm::Triple::x86; + const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; SanitizerMask Res = ToolChain::getSupportedSanitizers(); // FIXME: Omit X86_64 until 64-bit support is figured out. if (IsX86) { @@ -184,6 +206,8 @@ SanitizerMask Solaris::getSupportedSanitizers() const { Res |= SanitizerKind::PointerCompare; Res |= SanitizerKind::PointerSubtract; } + if (IsX86 || IsX86_64) + Res |= SanitizerKind::Function; Res |= SanitizerKind::Vptr; return Res; } diff --git a/lib/Driver/ToolChains/WebAssembly.cpp b/lib/Driver/ToolChains/WebAssembly.cpp index 7a40c13c065a4..3add913b700fa 100644 --- a/lib/Driver/ToolChains/WebAssembly.cpp +++ b/lib/Driver/ToolChains/WebAssembly.cpp @@ -89,7 +89,7 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - C.addCommand(llvm::make_unique<Command>(JA, *this, Linker, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Linker, CmdArgs, Inputs)); } WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple, @@ -141,7 +141,7 @@ void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs, options::OPT_fno_use_init_array, true)) CC1Args.push_back("-fuse-init-array"); - // '-pthread' implies atomics, bulk-memory, and mutable-globals + // '-pthread' implies atomics, bulk-memory, mutable-globals, and sign-ext if (DriverArgs.hasFlag(options::OPT_pthread, options::OPT_no_pthread, false)) { if (DriverArgs.hasFlag(options::OPT_mno_atomics, options::OPT_matomics, @@ -159,12 +159,39 @@ void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs, getDriver().Diag(diag::err_drv_argument_not_allowed_with) << "-pthread" << "-mno-mutable-globals"; + if (DriverArgs.hasFlag(options::OPT_mno_sign_ext, options::OPT_msign_ext, + false)) + getDriver().Diag(diag::err_drv_argument_not_allowed_with) + << "-pthread" + << "-mno-sign-ext"; CC1Args.push_back("-target-feature"); CC1Args.push_back("+atomics"); CC1Args.push_back("-target-feature"); CC1Args.push_back("+bulk-memory"); CC1Args.push_back("-target-feature"); CC1Args.push_back("+mutable-globals"); + CC1Args.push_back("-target-feature"); + CC1Args.push_back("+sign-ext"); + } + + if (DriverArgs.getLastArg(options::OPT_fwasm_exceptions)) { + // '-fwasm-exceptions' is not compatible with '-mno-exception-handling' + if (DriverArgs.hasFlag(options::OPT_mno_exception_handing, + options::OPT_mexception_handing, false)) + getDriver().Diag(diag::err_drv_argument_not_allowed_with) + << "-fwasm-exceptions" + << "-mno-exception-handling"; + // '-fwasm-exceptions' is not compatible with + // '-mllvm -enable-emscripten-cxx-exceptions' + for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) { + if (StringRef(A->getValue(0)) == "-enable-emscripten-cxx-exceptions") + getDriver().Diag(diag::err_drv_argument_not_allowed_with) + << "-fwasm-exceptions" + << "-mllvm -enable-emscripten-cxx-exceptions"; + } + // '-fwasm-exceptions' implies exception-handling + CC1Args.push_back("-target-feature"); + CC1Args.push_back("+exception-handling"); } } diff --git a/lib/Driver/ToolChains/XCore.cpp b/lib/Driver/ToolChains/XCore.cpp index 477cdb7609149..ba3a6d44addaf 100644 --- a/lib/Driver/ToolChains/XCore.cpp +++ b/lib/Driver/ToolChains/XCore.cpp @@ -52,7 +52,7 @@ void tools::XCore::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } void tools::XCore::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -80,7 +80,7 @@ void tools::XCore::Linker::ConstructJob(Compilation &C, const JobAction &JA, AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); - C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); } /// XCore tool chain |