diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /clang/lib/Driver/ToolChains/Arch | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) |
Notes
Diffstat (limited to 'clang/lib/Driver/ToolChains/Arch')
-rw-r--r-- | clang/lib/Driver/ToolChains/Arch/AArch64.cpp | 68 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Arch/ARM.cpp | 59 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Arch/ARM.h | 6 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Arch/PPC.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Arch/RISCV.cpp | 193 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Arch/SystemZ.cpp | 30 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Arch/SystemZ.h | 10 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Arch/VE.cpp | 26 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Arch/VE.h | 33 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Arch/X86.cpp | 44 |
10 files changed, 384 insertions, 107 deletions
diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp index 9c27504dccf5b..487c50dfc4663 100644 --- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp +++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp @@ -39,7 +39,7 @@ std::string aarch64::getAArch64TargetCPU(const ArgList &Args, // Handle CPU name is 'native'. if (CPU == "native") - return llvm::sys::getHostCPUName(); + return std::string(llvm::sys::getHostCPUName()); else if (CPU.size()) return CPU; @@ -54,7 +54,8 @@ std::string aarch64::getAArch64TargetCPU(const ArgList &Args, // Decode AArch64 features from string like +[no]featureA+[no]featureB+... static bool DecodeAArch64Features(const Driver &D, StringRef text, - std::vector<StringRef> &Features) { + std::vector<StringRef> &Features, + llvm::AArch64::ArchKind ArchKind) { SmallVector<StringRef, 8> Split; text.split(Split, StringRef("+"), -1, false); @@ -66,6 +67,11 @@ static bool DecodeAArch64Features(const Driver &D, StringRef text, D.Diag(clang::diag::err_drv_no_neon_modifier); else return false; + + // +sve implies +f32mm if the base architecture is v8.6A + // it isn't the case in general that sve implies both f64mm and f32mm + if ((ArchKind == llvm::AArch64::ArchKind::ARMV8_6A) && Feature == "sve") + Features.push_back("+f32mm"); } return true; } @@ -76,6 +82,7 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU, std::vector<StringRef> &Features) { std::pair<StringRef, StringRef> Split = Mcpu.split("+"); CPU = Split.first; + llvm::AArch64::ArchKind ArchKind = llvm::AArch64::ArchKind::ARMV8A; if (CPU == "native") CPU = llvm::sys::getHostCPUName(); @@ -83,7 +90,7 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU, if (CPU == "generic") { Features.push_back("+neon"); } else { - llvm::AArch64::ArchKind ArchKind = llvm::AArch64::parseCPUArch(CPU); + ArchKind = llvm::AArch64::parseCPUArch(CPU); if (!llvm::AArch64::getArchFeatures(ArchKind, Features)) return false; @@ -92,10 +99,11 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU, return false; } - if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features)) - return false; + if (Split.second.size() && + !DecodeAArch64Features(D, Split.second, Features, ArchKind)) + return false; - return true; + return true; } static bool @@ -108,7 +116,8 @@ getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March, llvm::AArch64::ArchKind ArchKind = llvm::AArch64::parseArch(Split.first); if (ArchKind == llvm::AArch64::ArchKind::INVALID || !llvm::AArch64::getArchFeatures(ArchKind, Features) || - (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))) + (Split.second.size() && + !DecodeAArch64Features(D, Split.second, Features, ArchKind))) return false; return true; @@ -139,8 +148,9 @@ getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune, // Handle CPU name is 'native'. if (MtuneLowerCase == "native") - MtuneLowerCase = llvm::sys::getHostCPUName(); - if (MtuneLowerCase == "cyclone" || MtuneLowerCase.find("apple") == 0) { + MtuneLowerCase = std::string(llvm::sys::getHostCPUName()); + if (MtuneLowerCase == "cyclone" || + StringRef(MtuneLowerCase).startswith("apple")) { Features.push_back("+zcm"); Features.push_back("+zcz"); } @@ -208,6 +218,39 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args); } + // Enable/disable straight line speculation hardening. + if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) { + StringRef Scope = A->getValue(); + bool EnableRetBr = false; + bool EnableBlr = false; + if (Scope != "none" && Scope != "all") { + SmallVector<StringRef, 4> Opts; + Scope.split(Opts, ","); + for (auto Opt : Opts) { + Opt = Opt.trim(); + if (Opt == "retbr") { + EnableRetBr = true; + continue; + } + if (Opt == "blr") { + EnableBlr = true; + continue; + } + D.Diag(diag::err_invalid_sls_hardening) + << Scope << A->getAsString(Args); + break; + } + } else if (Scope == "all") { + EnableRetBr = true; + EnableBlr = true; + } + + if (EnableRetBr) + Features.push_back("+harden-sls-retbr"); + if (EnableBlr) + Features.push_back("+harden-sls-blr"); + } + // En/disable crc if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) { if (A->getOption().matches(options::OPT_mcrc)) @@ -322,6 +365,10 @@ fp16_fml_fallthrough: } } + auto V8_6Pos = llvm::find(Features, "+v8.6a"); + if (V8_6Pos != std::end(Features)) + V8_6Pos = Features.insert(std::next(V8_6Pos), {"+i8mm", "+bf16"}); + if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) if (A->getOption().matches(options::OPT_mno_unaligned_access)) @@ -399,6 +446,9 @@ fp16_fml_fallthrough: if (Args.hasArg(options::OPT_ffixed_x28)) Features.push_back("+reserve-x28"); + if (Args.hasArg(options::OPT_ffixed_x30)) + Features.push_back("+reserve-x30"); + if (Args.hasArg(options::OPT_fcall_saved_x8)) Features.push_back("+call-saved-x8"); diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp index a1923e731489e..afe896b4a65bf 100644 --- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp @@ -57,7 +57,7 @@ void arm::getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch, static void getARMHWDivFeatures(const Driver &D, const Arg *A, const ArgList &Args, StringRef HWDiv, std::vector<StringRef> &Features) { - unsigned HWDivID = llvm::ARM::parseHWDiv(HWDiv); + uint64_t HWDivID = llvm::ARM::parseHWDiv(HWDiv); if (!llvm::ARM::getHWDivFeatures(HWDivID, Features)) D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); } @@ -91,7 +91,7 @@ static void DecodeARMFeaturesFromCPU(const Driver &D, StringRef CPU, CPU = CPU.split("+").first; if (CPU != "generic") { llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU); - unsigned Extension = llvm::ARM::getDefaultExtensions(CPU, ArchKind); + uint64_t Extension = llvm::ARM::getDefaultExtensions(CPU, ArchKind); llvm::ARM::getExtensionFeatures(Extension, Features); } } @@ -137,9 +137,8 @@ bool arm::useAAPCSForMachO(const llvm::Triple &T) { } // Select mode for reading thread pointer (-mtp=soft/cp15). -arm::ReadTPMode arm::getReadTPMode(const ToolChain &TC, const ArgList &Args) { +arm::ReadTPMode arm::getReadTPMode(const Driver &D, const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) { - const Driver &D = TC.getDriver(); arm::ReadTPMode ThreadPointer = llvm::StringSwitch<arm::ReadTPMode>(A->getValue()) .Case("cp15", ReadTPMode::Cp15) @@ -156,11 +155,14 @@ arm::ReadTPMode arm::getReadTPMode(const ToolChain &TC, const ArgList &Args) { return ReadTPMode::Soft; } +arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) { + return arm::getARMFloatABI(TC.getDriver(), TC.getEffectiveTriple(), Args); +} + // Select the float ABI as determined by -msoft-float, -mhard-float, and // -mfloat-abi=. -arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) { - const Driver &D = TC.getDriver(); - const llvm::Triple &Triple = TC.getEffectiveTriple(); +arm::FloatABI arm::getARMFloatABI(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) { auto SubArch = getARMSubArchVersionNumber(Triple); arm::FloatABI ABI = FloatABI::Invalid; if (Arg *A = @@ -276,18 +278,20 @@ arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) { return ABI; } -void arm::getARMTargetFeatures(const ToolChain &TC, - const llvm::Triple &Triple, - const ArgList &Args, - ArgStringList &CmdArgs, - std::vector<StringRef> &Features, - bool ForAS) { - const Driver &D = TC.getDriver(); +static bool hasIntegerMVE(const std::vector<StringRef> &F) { + auto MVE = llvm::find(llvm::reverse(F), "+mve"); + auto NoMVE = llvm::find(llvm::reverse(F), "-mve"); + return MVE != F.rend() && + (NoMVE == F.rend() || std::distance(MVE, NoMVE) > 0); +} +void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args, ArgStringList &CmdArgs, + std::vector<StringRef> &Features, bool ForAS) { bool KernelOrKext = Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext); - arm::FloatABI ABI = arm::getARMFloatABI(TC, Args); - arm::ReadTPMode ThreadPointer = arm::getReadTPMode(TC, Args); + arm::FloatABI ABI = arm::getARMFloatABI(D, Triple, Args); + arm::ReadTPMode ThreadPointer = arm::getReadTPMode(D, Args); const Arg *WaCPU = nullptr, *WaFPU = nullptr; const Arg *WaHDiv = nullptr, *WaArch = nullptr; @@ -459,18 +463,13 @@ fp16_fml_fallthrough: // Disable all features relating to hardware FP, not already disabled by the // above call. - Features.insert(Features.end(), {"-neon", "-crypto", "-dotprod", "-fp16fml", - "-mve", "-mve.fp", "-fpregs"}); + Features.insert(Features.end(), + {"-dotprod", "-fp16fml", "-mve", "-mve.fp", "-fpregs"}); } else if (FPUID == llvm::ARM::FK_NONE) { // -mfpu=none is *very* similar to -mfloat-abi=soft, only that it should not // disable MVE-I. - Features.insert(Features.end(), - {"-neon", "-crypto", "-dotprod", "-fp16fml", "-mve.fp"}); - // Even though we remove MVE-FP, we still need to check if it was originally - // present among the requested extensions, because it implies MVE-I, which - // should not be disabled by -mfpu-none. - if (!llvm::is_contained(Features, "+mve") && - !llvm::is_contained(Features, "+mve.fp")) + Features.insert(Features.end(), {"-dotprod", "-fp16fml", "-mve.fp"}); + if (!hasIntegerMVE(Features)) Features.emplace_back("-fpregs"); } @@ -612,14 +611,14 @@ fp16_fml_fallthrough: const std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) { std::string MArch; if (!Arch.empty()) - MArch = Arch; + MArch = std::string(Arch); else - MArch = Triple.getArchName(); + MArch = std::string(Triple.getArchName()); MArch = StringRef(MArch).split("+").first.lower(); // Handle -march=native. if (MArch == "native") { - std::string CPU = llvm::sys::getHostCPUName(); + std::string CPU = std::string(llvm::sys::getHostCPUName()); if (CPU != "generic") { // Translate the native cpu into the architecture suffix for that CPU. StringRef Suffix = arm::getLLVMArchSuffixForARM(CPU, MArch, Triple); @@ -657,12 +656,12 @@ std::string arm::getARMTargetCPU(StringRef CPU, StringRef Arch, std::string MCPU = StringRef(CPU).split("+").first.lower(); // Handle -mcpu=native. if (MCPU == "native") - return llvm::sys::getHostCPUName(); + return std::string(llvm::sys::getHostCPUName()); else return MCPU; } - return getARMCPUForMArch(Arch, Triple); + return std::string(getARMCPUForMArch(Arch, Triple)); } /// getLLVMArchSuffixForARM - Get the LLVM ArchKind value to use for a diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.h b/clang/lib/Driver/ToolChains/Arch/ARM.h index 5640f8371262a..0ba1a59852aa0 100644 --- a/clang/lib/Driver/ToolChains/Arch/ARM.h +++ b/clang/lib/Driver/ToolChains/Arch/ARM.h @@ -48,13 +48,15 @@ enum class FloatABI { }; FloatABI getARMFloatABI(const ToolChain &TC, const llvm::opt::ArgList &Args); -ReadTPMode getReadTPMode(const ToolChain &TC, const llvm::opt::ArgList &Args); +FloatABI getARMFloatABI(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); +ReadTPMode getReadTPMode(const Driver &D, const llvm::opt::ArgList &Args); bool useAAPCSForMachO(const llvm::Triple &T); void getARMArchCPUFromArgs(const llvm::opt::ArgList &Args, llvm::StringRef &Arch, llvm::StringRef &CPU, bool FromAs = false); -void getARMTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, +void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, std::vector<llvm::StringRef> &Features, bool ForAS); diff --git a/clang/lib/Driver/ToolChains/Arch/PPC.cpp b/clang/lib/Driver/ToolChains/Arch/PPC.cpp index f1baadaebf41b..144e276a6bd87 100644 --- a/clang/lib/Driver/ToolChains/Arch/PPC.cpp +++ b/clang/lib/Driver/ToolChains/Arch/PPC.cpp @@ -26,7 +26,7 @@ std::string ppc::getPPCTargetCPU(const ArgList &Args) { StringRef CPUName = A->getValue(); if (CPUName == "native") { - std::string CPU = llvm::sys::getHostCPUName(); + std::string CPU = std::string(llvm::sys::getHostCPUName()); if (!CPU.empty() && CPU != "generic") return CPU; else @@ -70,6 +70,7 @@ std::string ppc::getPPCTargetCPU(const ArgList &Args) { .Case("power7", "pwr7") .Case("power8", "pwr8") .Case("power9", "pwr9") + .Case("power10", "pwr10") .Case("future", "future") .Case("pwr3", "pwr3") .Case("pwr4", "pwr4") @@ -80,6 +81,7 @@ std::string ppc::getPPCTargetCPU(const ArgList &Args) { .Case("pwr7", "pwr7") .Case("pwr8", "pwr8") .Case("pwr9", "pwr9") + .Case("pwr10", "pwr10") .Case("powerpc", "ppc") .Case("powerpc64", "ppc64") .Case("powerpc64le", "ppc64le") @@ -91,14 +93,16 @@ std::string ppc::getPPCTargetCPU(const ArgList &Args) { const char *ppc::getPPCAsmModeForCPU(StringRef Name) { return llvm::StringSwitch<const char *>(Name) - .Case("pwr7", "-mpower7") - .Case("power7", "-mpower7") - .Case("pwr8", "-mpower8") - .Case("power8", "-mpower8") - .Case("ppc64le", "-mpower8") - .Case("pwr9", "-mpower9") - .Case("power9", "-mpower9") - .Default("-many"); + .Case("pwr7", "-mpower7") + .Case("power7", "-mpower7") + .Case("pwr8", "-mpower8") + .Case("power8", "-mpower8") + .Case("ppc64le", "-mpower8") + .Case("pwr9", "-mpower9") + .Case("power9", "-mpower9") + .Case("pwr10", "-mpower10") + .Case("power10", "-mpower10") + .Default("-many"); } void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple, diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp index 8c343b8693f32..80d12e5aa8daa 100644 --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -22,6 +22,14 @@ using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; +namespace { +// Represents the major and version number components of a RISC-V extension +struct RISCVExtensionVersion { + StringRef Major; + StringRef Minor; +}; +} // end anonymous namespace + static StringRef getExtensionTypeDesc(StringRef Ext) { if (Ext.startswith("sx")) return "non-standard supervisor-level extension"; @@ -29,6 +37,8 @@ static StringRef getExtensionTypeDesc(StringRef Ext) { return "standard supervisor-level extension"; if (Ext.startswith("x")) return "non-standard user-level extension"; + if (Ext.startswith("z")) + return "standard user-level extension"; return StringRef(); } @@ -39,10 +49,29 @@ static StringRef getExtensionType(StringRef Ext) { return "s"; if (Ext.startswith("x")) return "x"; + if (Ext.startswith("z")) + return "z"; return StringRef(); } +// If the extension is supported as experimental, return the version of that +// extension that the compiler currently supports. +static Optional<RISCVExtensionVersion> +isExperimentalExtension(StringRef Ext) { + if (Ext == "b" || Ext == "zbb" || Ext == "zbc" || Ext == "zbe" || + Ext == "zbf" || Ext == "zbm" || Ext == "zbp" || Ext == "zbr" || + Ext == "zbs" || Ext == "zbt" || Ext == "zbproposedc") + return RISCVExtensionVersion{"0", "92"}; + if (Ext == "v") + return RISCVExtensionVersion{"0", "8"}; + return None; +} + static bool isSupportedExtension(StringRef Ext) { + // LLVM supports "z" extensions which are marked as experimental. + if (isExperimentalExtension(Ext)) + return true; + // LLVM does not support "sx", "s" nor "x" extensions. return false; } @@ -52,17 +81,15 @@ static bool isSupportedExtension(StringRef Ext) { // Version number is divided into major and minor version numbers, // separated by a 'p'. If the minor version is 0 then 'p0' can be // omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1. -static bool getExtensionVersion(const Driver &D, StringRef MArch, - StringRef Ext, StringRef In, +static bool getExtensionVersion(const Driver &D, const ArgList &Args, + StringRef MArch, StringRef Ext, StringRef In, std::string &Major, std::string &Minor) { - Major = In.take_while(isDigit); + Major = std::string(In.take_while(isDigit)); In = In.substr(Major.size()); - if (Major.empty()) - return true; - if (In.consume_front("p")) { - Minor = In.take_while(isDigit); - In = In.substr(Major.size()); + if (Major.size() && In.consume_front("p")) { + Minor = std::string(In.take_while(isDigit)); + In = In.substr(Major.size() + 1); // Expected 'p' to be followed by minor version number. if (Minor.empty()) { @@ -74,7 +101,53 @@ static bool getExtensionVersion(const Driver &D, StringRef MArch, } } - // TODO: Handle extensions with version number. + // Expected multi-character extension with version number to have no + // subsequent characters (i.e. must either end string or be followed by + // an underscore). + if (Ext.size() > 1 && In.size()) { + std::string Error = + "multi-character extensions must be separated by underscores"; + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << In; + return false; + } + + // If experimental extension, require use of current version number number + if (auto ExperimentalExtension = isExperimentalExtension(Ext)) { + if (!Args.hasArg(options::OPT_menable_experimental_extensions)) { + std::string Error = + "requires '-menable-experimental-extensions' for experimental extension"; + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << Error << Ext; + return false; + } else if (Major.empty() && Minor.empty()) { + std::string Error = + "experimental extension requires explicit version number"; + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << Error << Ext; + return false; + } + auto SupportedVers = *ExperimentalExtension; + if (Major != SupportedVers.Major || Minor != SupportedVers.Minor) { + std::string Error = + "unsupported version number " + Major; + if (!Minor.empty()) + Error += "." + Minor; + Error += " for experimental extension (this compiler supports " + + SupportedVers.Major.str() + "." + + SupportedVers.Minor.str() + ")"; + + D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) + << MArch << Error << Ext; + return false; + } + return true; + } + + // Allow extensions to declare no version number + if (Major.empty() && Minor.empty()) + return true; + + // TODO: Handle supported extensions with version number. std::string Error = "unsupported version number " + Major; if (!Minor.empty()) Error += "." + Minor; @@ -89,7 +162,7 @@ static bool getExtensionVersion(const Driver &D, StringRef MArch, // Parse the ISA string containing non-standard user-level // extensions, standard supervisor-level extensions and // non-standard supervisor-level extensions. -// These extensions start with 'x', 's', 'sx' prefixes, follow a +// These extensions start with 'z', 'x', 's', 'sx' prefixes, follow a // canonical order, might have a version number (major, minor) // and are separated by a single underscore '_'. // Set the hardware features for the extensions that are supported. @@ -105,7 +178,7 @@ static void getExtensionFeatures(const Driver &D, SmallVector<StringRef, 8> Split; Exts.split(Split, StringRef("_")); - SmallVector<StringRef, 3> Prefix{"x", "s", "sx"}; + SmallVector<StringRef, 4> Prefix{"z", "x", "s", "sx"}; auto I = Prefix.begin(); auto E = Prefix.end(); @@ -119,8 +192,10 @@ static void getExtensionFeatures(const Driver &D, } StringRef Type = getExtensionType(Ext); - StringRef Name(Ext.substr(Type.size())); StringRef Desc = getExtensionTypeDesc(Ext); + auto Pos = Ext.find_if(isDigit); + StringRef Name(Ext.substr(0, Pos)); + StringRef Vers(Ext.substr(Pos)); if (Type.empty()) { D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) @@ -133,7 +208,7 @@ static void getExtensionFeatures(const Driver &D, ++I; if (I == E) { - std::string Error = Desc; + std::string Error = std::string(Desc); Error += " not given in canonical order"; D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << Ext; @@ -143,35 +218,30 @@ static void getExtensionFeatures(const Driver &D, // The order is OK, do not advance I to the next prefix // to allow repeated extension type, e.g.: rv32ixabc_xdef. - if (Name.empty()) { - std::string Error = Desc; + if (Name.size() == Type.size()) { + std::string Error = std::string(Desc); Error += " name missing after"; D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) - << MArch << Error << Ext; + << MArch << Error << Type; return; } std::string Major, Minor; - auto Pos = Name.find_if(isDigit); - if (Pos != StringRef::npos) { - auto Next = Name.substr(Pos); - Name = Name.substr(0, Pos); - if (!getExtensionVersion(D, MArch, Ext, Next, Major, Minor)) - return; - } + if (!getExtensionVersion(D, Args, MArch, Name, Vers, Major, Minor)) + return; // Check if duplicated extension. - if (llvm::is_contained(AllExts, Ext)) { + if (llvm::is_contained(AllExts, Name)) { std::string Error = "duplicated "; Error += Desc; D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) - << MArch << Error << Ext; + << MArch << Error << Name; return; } // Extension format is correct, keep parsing the extensions. // TODO: Save Type, Name, Major, Minor to avoid parsing them later. - AllExts.push_back(Ext); + AllExts.push_back(Name); } // Set target features. @@ -186,7 +256,10 @@ static void getExtensionFeatures(const Driver &D, << MArch << Error << Ext; return; } - Features.push_back(Args.MakeArgString("+" + Ext)); + if (isExperimentalExtension(Ext)) + Features.push_back(Args.MakeArgString("+experimental-" + Ext)); + else + Features.push_back(Args.MakeArgString("+" + Ext)); } } @@ -251,28 +324,35 @@ static bool getArchFeatures(const Driver &D, StringRef MArch, // 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'. + // Remove multi-letter standard extensions, non-standard extensions and + // supervisor-level extensions. They have 'z', 'x', 's', 'sx' prefixes. + // Parse them at the end. + // Find the very first occurrence of 's', 'x' or 'z'. StringRef OtherExts; - size_t Pos = Exts.find_first_of("sx"); + size_t Pos = Exts.find_first_of("zsx"); 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)) + if (!getExtensionVersion(D, Args, MArch, std::string(1, Baseline), Exts, + Major, Minor)) return false; + // Consume the base ISA version number and any '_' between rvxxx and the + // first extension + Exts = Exts.drop_front(Major.size()); + if (!Minor.empty()) + Exts = Exts.drop_front(Minor.size() + 1 /*'p'*/); + Exts.consume_front("_"); + // 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) { + for (auto I = Exts.begin(), E = Exts.end(); I != E; ) { char c = *I; // Check ISA extensions are specified in the canonical order. @@ -295,18 +375,15 @@ static bool getArchFeatures(const Driver &D, StringRef MArch, // 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. - } + std::string Next, Major, Minor; + if (std::next(I) != E) + Next = std::string(std::next(I), E); + if (!getExtensionVersion(D, Args, MArch, std::string(1, c), Next, Major, + Minor)) + return false; // The order is OK, then push it into features. + // TODO: Use version number when setting target features switch (c) { default: // Currently LLVM supports only "mafdc". @@ -331,7 +408,22 @@ static bool getArchFeatures(const Driver &D, StringRef MArch, case 'c': Features.push_back("+c"); break; + case 'b': + Features.push_back("+experimental-b"); + break; + case 'v': + Features.push_back("+experimental-v"); + break; } + + // Consume full extension name and version, including any optional '_' + // between this extension and the next + ++I; + I += Major.size(); + if (Minor.size()) + I += Minor.size() + 1 /*'p'*/; + if (*I == '_') + ++I; } // Dependency check. @@ -433,12 +525,11 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, Features.push_back("-relax"); // GCC Compatibility: -mno-save-restore is default, unless -msave-restore is - // specified... - if (Args.hasFlag(options::OPT_msave_restore, options::OPT_mno_save_restore, false)) { - // ... but we don't support -msave-restore, so issue a warning. - D.Diag(diag::warn_drv_clang_unsupported) - << Args.getLastArg(options::OPT_msave_restore)->getAsString(Args); - } + // specified. + if (Args.hasFlag(options::OPT_msave_restore, options::OPT_mno_save_restore, false)) + Features.push_back("+save-restore"); + else + Features.push_back("-save-restore"); // Now add any that the user explicitly requested on the command line, // which may override the defaults. diff --git a/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp b/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp index 2b77d59fdc66b..f81bf68172de1 100644 --- a/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp +++ b/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp @@ -7,6 +7,8 @@ //===----------------------------------------------------------------------===// #include "SystemZ.h" +#include "clang/Config/config.h" +#include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/Host.h" @@ -16,24 +18,40 @@ using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; +systemz::FloatABI systemz::getSystemZFloatABI(const Driver &D, + const ArgList &Args) { + // Hard float is the default. + systemz::FloatABI ABI = systemz::FloatABI::Hard; + if (Args.hasArg(options::OPT_mfloat_abi_EQ)) + D.Diag(diag::err_drv_unsupported_opt) + << Args.getLastArg(options::OPT_mfloat_abi_EQ)->getAsString(Args); + + if (Arg *A = Args.getLastArg(clang::driver::options::OPT_msoft_float, + options::OPT_mhard_float)) + if (A->getOption().matches(clang::driver::options::OPT_msoft_float)) + ABI = systemz::FloatABI::Soft; + + return ABI; +} + std::string systemz::getSystemZTargetCPU(const ArgList &Args) { if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) { llvm::StringRef CPUName = A->getValue(); if (CPUName == "native") { - std::string CPU = llvm::sys::getHostCPUName(); + std::string CPU = std::string(llvm::sys::getHostCPUName()); if (!CPU.empty() && CPU != "generic") return CPU; else return ""; } - return CPUName; + return std::string(CPUName); } - return "z10"; + return CLANG_SYSTEMZ_DEFAULT_ARCH; } -void systemz::getSystemZTargetFeatures(const ArgList &Args, +void systemz::getSystemZTargetFeatures(const Driver &D, const ArgList &Args, std::vector<llvm::StringRef> &Features) { // -m(no-)htm overrides use of the transactional-execution facility. if (Arg *A = Args.getLastArg(options::OPT_mhtm, options::OPT_mno_htm)) { @@ -49,4 +67,8 @@ void systemz::getSystemZTargetFeatures(const ArgList &Args, else Features.push_back("-vector"); } + + systemz::FloatABI FloatABI = systemz::getSystemZFloatABI(D, Args); + if (FloatABI == systemz::FloatABI::Soft) + Features.push_back("+soft-float"); } diff --git a/clang/lib/Driver/ToolChains/Arch/SystemZ.h b/clang/lib/Driver/ToolChains/Arch/SystemZ.h index 77dcbc47be5c0..1e42b68a8f3c2 100644 --- a/clang/lib/Driver/ToolChains/Arch/SystemZ.h +++ b/clang/lib/Driver/ToolChains/Arch/SystemZ.h @@ -9,6 +9,7 @@ #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_SYSTEMZ_H #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_SYSTEMZ_H +#include "clang/Driver/Driver.h" #include "llvm/ADT/StringRef.h" #include "llvm/Option/Option.h" #include <string> @@ -19,9 +20,16 @@ namespace driver { namespace tools { namespace systemz { +enum class FloatABI { + Soft, + Hard, +}; + +FloatABI getSystemZFloatABI(const Driver &D, const llvm::opt::ArgList &Args); + std::string getSystemZTargetCPU(const llvm::opt::ArgList &Args); -void getSystemZTargetFeatures(const llvm::opt::ArgList &Args, +void getSystemZTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args, std::vector<llvm::StringRef> &Features); } // end namespace systemz diff --git a/clang/lib/Driver/ToolChains/Arch/VE.cpp b/clang/lib/Driver/ToolChains/Arch/VE.cpp new file mode 100644 index 0000000000000..fa10e4810f1c9 --- /dev/null +++ b/clang/lib/Driver/ToolChains/Arch/VE.cpp @@ -0,0 +1,26 @@ +//===--- VE.cpp - Tools 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 "VE.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Options.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Option/ArgList.h" + +using namespace clang::driver; +using namespace clang::driver::tools; +using namespace clang; +using namespace llvm::opt; + +const char *ve::getVEAsmModeForCPU(StringRef Name, const llvm::Triple &Triple) { + return ""; +} + +void ve::getVETargetFeatures(const Driver &D, const ArgList &Args, + std::vector<StringRef> &Features) {} diff --git a/clang/lib/Driver/ToolChains/Arch/VE.h b/clang/lib/Driver/ToolChains/Arch/VE.h new file mode 100644 index 0000000000000..713e3e7d042f2 --- /dev/null +++ b/clang/lib/Driver/ToolChains/Arch/VE.h @@ -0,0 +1,33 @@ +//===--- VE.h - VE-specific Tool Helpers ------------------------*- 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_ARCH_VE_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_VE_H + +#include "clang/Driver/Driver.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Option/Option.h" +#include <string> +#include <vector> + +namespace clang { +namespace driver { +namespace tools { +namespace ve { + +void getVETargetFeatures(const Driver &D, const llvm::opt::ArgList &Args, + std::vector<llvm::StringRef> &Features); +const char *getVEAsmModeForCPU(llvm::StringRef Name, + const llvm::Triple &Triple); + +} // end namespace ve +} // namespace tools +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_VE_H diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp b/clang/lib/Driver/ToolChains/Arch/X86.cpp index d1e0c8253b799..2cc44c09917f5 100644 --- a/clang/lib/Driver/ToolChains/Arch/X86.cpp +++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp @@ -31,7 +31,7 @@ const char *x86::getX86TargetCPU(const ArgList &Args, // // FIXME: We should also incorporate the detected target features for use // with -native. - std::string CPU = llvm::sys::getHostCPUName(); + std::string CPU = std::string(llvm::sys::getHostCPUName()); if (!CPU.empty() && CPU != "generic") return Args.MakeArgString(CPU); } @@ -94,6 +94,7 @@ const char *x86::getX86TargetCPU(const ArgList &Args, switch (Triple.getOS()) { case llvm::Triple::FreeBSD: + return "i686"; case llvm::Triple::NetBSD: case llvm::Triple::OpenBSD: return "i486"; @@ -146,6 +147,7 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple, // flags). This is a bit hacky but keeps existing usages working. We should // consider deprecating this and instead warn if the user requests external // retpoline thunks and *doesn't* request some form of retpolines. + auto SpectreOpt = clang::driver::options::ID::OPT_INVALID; if (Args.hasArgNoClaim(options::OPT_mretpoline, options::OPT_mno_retpoline, options::OPT_mspeculative_load_hardening, options::OPT_mno_speculative_load_hardening)) { @@ -153,12 +155,14 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple, false)) { Features.push_back("+retpoline-indirect-calls"); Features.push_back("+retpoline-indirect-branches"); + SpectreOpt = options::OPT_mretpoline; } else if (Args.hasFlag(options::OPT_mspeculative_load_hardening, options::OPT_mno_speculative_load_hardening, false)) { // On x86, speculative load hardening relies on at least using retpolines // for indirect calls. Features.push_back("+retpoline-indirect-calls"); + SpectreOpt = options::OPT_mspeculative_load_hardening; } } else if (Args.hasFlag(options::OPT_mretpoline_external_thunk, options::OPT_mno_retpoline_external_thunk, false)) { @@ -166,6 +170,44 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple, // eventually switch to an error here. Features.push_back("+retpoline-indirect-calls"); Features.push_back("+retpoline-indirect-branches"); + SpectreOpt = options::OPT_mretpoline_external_thunk; + } + + auto LVIOpt = clang::driver::options::ID::OPT_INVALID; + if (Args.hasFlag(options::OPT_mlvi_hardening, options::OPT_mno_lvi_hardening, + false)) { + Features.push_back("+lvi-load-hardening"); + Features.push_back("+lvi-cfi"); // load hardening implies CFI protection + LVIOpt = options::OPT_mlvi_hardening; + } else if (Args.hasFlag(options::OPT_mlvi_cfi, options::OPT_mno_lvi_cfi, + false)) { + Features.push_back("+lvi-cfi"); + LVIOpt = options::OPT_mlvi_cfi; + } + + if (Args.hasFlag(options::OPT_m_seses, options::OPT_mno_seses, false)) { + if (LVIOpt == options::OPT_mlvi_hardening) + D.Diag(diag::err_drv_argument_not_allowed_with) + << D.getOpts().getOptionName(options::OPT_mlvi_hardening) + << D.getOpts().getOptionName(options::OPT_m_seses); + + if (SpectreOpt != clang::driver::options::ID::OPT_INVALID) + D.Diag(diag::err_drv_argument_not_allowed_with) + << D.getOpts().getOptionName(SpectreOpt) + << D.getOpts().getOptionName(options::OPT_m_seses); + + Features.push_back("+seses"); + if (!Args.hasArg(options::OPT_mno_lvi_cfi)) { + Features.push_back("+lvi-cfi"); + LVIOpt = options::OPT_mlvi_cfi; + } + } + + if (SpectreOpt != clang::driver::options::ID::OPT_INVALID && + LVIOpt != clang::driver::options::ID::OPT_INVALID) { + D.Diag(diag::err_drv_argument_not_allowed_with) + << D.getOpts().getOptionName(SpectreOpt) + << D.getOpts().getOptionName(LVIOpt); } // Now add any that the user explicitly requested on the command line, |