Index: include/clang/Basic/TargetInfo.h =================================================================== --- include/clang/Basic/TargetInfo.h +++ include/clang/Basic/TargetInfo.h @@ -869,6 +869,11 @@ return false; } + /// brief Determine whether this TargetInfo supports the given CPU name. + virtual bool isValidCPUName(StringRef Name) const { + return false; + } + /// \brief Use the specified ABI. /// /// \return False on error (invalid ABI name). @@ -891,6 +896,11 @@ Features[Name] = Enabled; } + /// \brief Determine whether this TargetInfo supports the given feature. + virtual bool isValidFeatureName(StringRef Feature) const { + return false; + } + /// \brief Perform initialization based on the user configured /// set of features (e.g., +sse4). /// Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -963,8 +963,8 @@ // 401, 403, 405, 405fp, 440fp, 464, 464fp, 476, 476fp, 505, 740, 801, // 821, 823, 8540, 8548, e300c2, e300c3, e500mc64, e6500, 860, cell, // titan, rs64. - bool setCPU(const std::string &Name) override { - bool CPUKnown = llvm::StringSwitch(Name) + bool isValidCPUName(StringRef Name) const override { + return llvm::StringSwitch(Name) .Case("generic", true) .Case("440", true) .Case("450", true) @@ -1014,10 +1014,12 @@ .Case("powerpc64le", true) .Case("ppc64le", true) .Default(false); + } + bool setCPU(const std::string &Name) override { + bool CPUKnown = isValidCPUName(Name); if (CPUKnown) CPU = Name; - return CPUKnown; } @@ -2006,6 +2008,9 @@ // FIXME: implement return TargetInfo::CharPtrBuiltinVaList; } + bool isValidCPUName(StringRef Name) const override { + return StringToCudaArch(Name) != CudaArch::UNKNOWN; + } bool setCPU(const std::string &Name) override { GPU = StringToCudaArch(Name); return GPU != CudaArch::UNKNOWN; @@ -2367,6 +2372,13 @@ .Default(GK_NONE); } + bool isValidCPUName(StringRef Name) const override { + if (getTriple().getArch() == llvm::Triple::amdgcn) + return GK_NONE != parseAMDGCNName(Name); + else + return GK_NONE != parseR600Name(Name); + } + bool setCPU(const std::string &Name) override { if (getTriple().getArch() == llvm::Triple::amdgcn) GPU = parseAMDGCNName(Name); @@ -2873,6 +2885,87 @@ //@} } CPU = CK_Generic; + bool checkCPUKind(CPUKind Kind) const { + // Perform any per-CPU checks necessary to determine if this CPU is + // acceptable. + // FIXME: This results in terrible diagnostics. Clang just says the CPU is + // invalid without explaining *why*. + switch (Kind) { + case CK_Generic: + // No processor selected! + return false; + + case CK_i386: + case CK_i486: + case CK_WinChipC6: + case CK_WinChip2: + case CK_C3: + case CK_i586: + case CK_Pentium: + case CK_PentiumMMX: + case CK_i686: + case CK_PentiumPro: + case CK_Pentium2: + case CK_Pentium3: + case CK_Pentium3M: + case CK_PentiumM: + case CK_Yonah: + case CK_C3_2: + case CK_Pentium4: + case CK_Pentium4M: + case CK_Lakemont: + case CK_Prescott: + case CK_K6: + case CK_K6_2: + case CK_K6_3: + case CK_Athlon: + case CK_AthlonThunderbird: + case CK_Athlon4: + case CK_AthlonXP: + case CK_AthlonMP: + case CK_Geode: + // Only accept certain architectures when compiling in 32-bit mode. + if (getTriple().getArch() != llvm::Triple::x86) + return false; + + LLVM_FALLTHROUGH; + case CK_Nocona: + case CK_Core2: + case CK_Penryn: + case CK_Bonnell: + case CK_Silvermont: + case CK_Goldmont: + case CK_Nehalem: + case CK_Westmere: + case CK_SandyBridge: + case CK_IvyBridge: + case CK_Haswell: + case CK_Broadwell: + case CK_SkylakeClient: + case CK_SkylakeServer: + case CK_Cannonlake: + case CK_KNL: + case CK_Athlon64: + case CK_Athlon64SSE3: + case CK_AthlonFX: + case CK_K8: + case CK_K8SSE3: + case CK_Opteron: + case CK_OpteronSSE3: + case CK_AMDFAM10: + case CK_BTVER1: + case CK_BTVER2: + case CK_BDVER1: + case CK_BDVER2: + case CK_BDVER3: + case CK_BDVER4: + case CK_ZNVER1: + case CK_x86_64: + return true; + } + llvm_unreachable("Unhandled CPU kind"); + } + CPUKind getCPUKind(StringRef CPU) const { return llvm::StringSwitch(CPU) .Case("i386", CK_i386) @@ -3053,6 +3146,7 @@ initFeatureMap(llvm::StringMap &Features, DiagnosticsEngine &Diags, StringRef CPU, const std::vector &FeaturesVec) const override; + bool isValidFeatureName(StringRef Name) const override; bool hasFeature(StringRef Feature) const override; bool handleTargetFeatures(std::vector &Features, DiagnosticsEngine &Diags) override; @@ -3066,87 +3160,13 @@ return "no-mmx"; return ""; } - bool setCPU(const std::string &Name) override { - CPU = getCPUKind(Name); - // Perform any per-CPU checks necessary to determine if this CPU is - // acceptable. - // FIXME: This results in terrible diagnostics. Clang just says the CPU is - // invalid without explaining *why*. - switch (CPU) { - case CK_Generic: - // No processor selected! - return false; - - case CK_i386: - case CK_i486: - case CK_WinChipC6: - case CK_WinChip2: - case CK_C3: - case CK_i586: - case CK_Pentium: - case CK_PentiumMMX: - case CK_i686: - case CK_PentiumPro: - case CK_Pentium2: - case CK_Pentium3: - case CK_Pentium3M: - case CK_PentiumM: - case CK_Yonah: - case CK_C3_2: - case CK_Pentium4: - case CK_Pentium4M: - case CK_Lakemont: - case CK_Prescott: - case CK_K6: - case CK_K6_2: - case CK_K6_3: - case CK_Athlon: - case CK_AthlonThunderbird: - case CK_Athlon4: - case CK_AthlonXP: - case CK_AthlonMP: - case CK_Geode: - // Only accept certain architectures when compiling in 32-bit mode. - if (getTriple().getArch() != llvm::Triple::x86) - return false; + bool isValidCPUName(StringRef Name) const override { + return checkCPUKind(getCPUKind(Name)); + } - // Fallthrough - case CK_Nocona: - case CK_Core2: - case CK_Penryn: - case CK_Bonnell: - case CK_Silvermont: - case CK_Goldmont: - case CK_Nehalem: - case CK_Westmere: - case CK_SandyBridge: - case CK_IvyBridge: - case CK_Haswell: - case CK_Broadwell: - case CK_SkylakeClient: - case CK_SkylakeServer: - case CK_Cannonlake: - case CK_KNL: - case CK_Athlon64: - case CK_Athlon64SSE3: - case CK_AthlonFX: - case CK_K8: - case CK_K8SSE3: - case CK_Opteron: - case CK_OpteronSSE3: - case CK_AMDFAM10: - case CK_BTVER1: - case CK_BTVER2: - case CK_BDVER1: - case CK_BDVER2: - case CK_BDVER3: - case CK_BDVER4: - case CK_ZNVER1: - case CK_x86_64: - return true; - } - llvm_unreachable("Unhandled CPU kind"); + bool setCPU(const std::string &Name) override { + return checkCPUKind(CPU = getCPUKind(Name)); } bool setFPMath(StringRef Name) override; @@ -4239,6 +4259,68 @@ Builder.defineMacro("__SIZEOF_FLOAT128__", "16"); } +bool X86TargetInfo::isValidFeatureName(StringRef Name) const { + return llvm::StringSwitch(Name) + .Case("aes", true) + .Case("avx", true) + .Case("avx2", true) + .Case("avx512f", true) + .Case("avx512cd", true) + .Case("avx512vpopcntdq", true) + .Case("avx512er", true) + .Case("avx512pf", true) + .Case("avx512dq", true) + .Case("avx512bw", true) + .Case("avx512vl", true) + .Case("avx512vbmi", true) + .Case("avx512ifma", true) + .Case("bmi", true) + .Case("bmi2", true) + .Case("clflushopt", true) + .Case("clwb", true) + .Case("clzero", true) + .Case("cx16", true) + .Case("f16c", true) + .Case("fma", true) + .Case("fma4", true) + .Case("fsgsbase", true) + .Case("fxsr", true) + .Case("lwp", true) + .Case("lzcnt", true) + .Case("mm3dnow", true) + .Case("mm3dnowa", true) + .Case("mmx", true) + .Case("movbe", true) + .Case("mpx", true) + .Case("pclmul", true) + .Case("pku", true) + .Case("popcnt", true) + .Case("prefetchwt1", true) + .Case("prfchw", true) + .Case("rdrnd", true) + .Case("rdseed", true) + .Case("rtm", true) + .Case("sgx", true) + .Case("sha", true) + .Case("sse", true) + .Case("sse2", true) + .Case("sse3", true) + .Case("ssse3", true) + .Case("sse4.1", true) + .Case("sse4.2", true) + .Case("sse4a", true) + .Case("tbm", true) + .Case("x86", true) + .Case("x86_32", true) + .Case("x86_64", true) + .Case("xop", true) + .Case("xsave", true) + .Case("xsavec", true) + .Case("xsaves", true) + .Case("xsaveopt", true) + .Default(false); +} + bool X86TargetInfo::hasFeature(StringRef Feature) const { return llvm::StringSwitch(Feature) .Case("aes", HasAES) @@ -4265,6 +4347,7 @@ .Case("fma4", XOPLevel >= FMA4) .Case("fsgsbase", HasFSGSBASE) .Case("fxsr", HasFXSR) + .Case("lwp", HasLWP) .Case("lzcnt", HasLZCNT) .Case("mm3dnow", MMX3DNowLevel >= AMD3DNow) .Case("mm3dnowa", MMX3DNowLevel >= AMD3DNowAthlon) @@ -4289,7 +4372,6 @@ .Case("sse4.2", SSELevel >= SSE42) .Case("sse4a", XOPLevel >= SSE4A) .Case("tbm", HasTBM) - .Case("lwp", HasLWP) .Case("x86", true) .Case("x86_32", getTriple().getArch() == llvm::Triple::x86) .Case("x86_64", getTriple().getArch() == llvm::Triple::x86_64) @@ -5634,6 +5716,11 @@ .Default(false); } + bool isValidCPUName(StringRef Name) const override { + return Name == "generic" || + llvm::ARM::parseCPUArch(Name) != llvm::ARM::AK_INVALID; + } + bool setCPU(const std::string &Name) override { if (Name != "generic") setArchInfo(llvm::ARM::parseCPUArch(Name)); @@ -6322,12 +6409,16 @@ return true; } - bool setCPU(const std::string &Name) override { + bool isValidCPUName(StringRef Name) const override { return Name == "generic" || llvm::AArch64::parseCPUArch(Name) != static_cast(llvm::AArch64::ArchKind::AK_INVALID); } + bool setCPU(const std::string &Name) override { + return isValidCPUName(Name); + } + void getTargetDefinesARMV81A(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); @@ -6846,8 +6937,12 @@ .Default(nullptr); } + bool isValidCPUName(StringRef Name) const override { + return getHexagonCPUSuffix(Name); + } + bool setCPU(const std::string &Name) override { - if (!getHexagonCPUSuffix(Name)) + if (!isValidCPUName(Name)) return false; CPU = Name; return true; @@ -7027,6 +7122,12 @@ } } + bool isValidCPUName(StringRef Name) const override { + return llvm::StringSwitch(Name) + .Case("v11", true) + .Default(false); + } + bool setCPU(const std::string &Name) override { CPU = llvm::StringSwitch(Name) .Case("v11", CK_V11) @@ -7265,6 +7366,10 @@ .Default(CK_GENERIC); } + bool isValidCPUName(StringRef Name) const override { + return getCPUKind(Name) != CK_GENERIC; + } + bool setCPU(const std::string &Name) override { CPU = getCPUKind(Name); return CPU != CK_GENERIC; @@ -7441,6 +7546,10 @@ } } + bool isValidCPUName(StringRef Name) const override { + return getCPUGeneration(SparcTargetInfo::getCPUKind(Name)) == CG_V9; + } + bool setCPU(const std::string &Name) override { if (!SparcTargetInfo::setCPU(Name)) return false; @@ -7523,6 +7632,11 @@ .Cases("arch12", "z14", 12) .Default(-1); } + + bool isValidCPUName(StringRef Name) const override { + return getISARevision(Name) != -1; + } + bool setCPU(const std::string &Name) override { CPU = Name; ISARevision = getISARevision(CPU); @@ -7903,8 +8017,12 @@ return false; } + bool isValidCPUName(StringRef Name) const override { + return Name == "nios2r1" || Name == "nios2r2"; + } + bool setCPU(const std::string &Name) override { - if (Name == "nios2r1" || Name == "nios2r2") { + if (isValidCPUName(Name)) { CPU = Name; return true; } @@ -8171,8 +8289,7 @@ SizeType = UnsignedInt; } - bool setCPU(const std::string &Name) override { - CPU = Name; + bool isValidCPUName(StringRef Name) const override { return llvm::StringSwitch(Name) .Case("mips1", true) .Case("mips2", true) @@ -8193,6 +8310,12 @@ .Case("p5600", true) .Default(false); } + + bool setCPU(const std::string &Name) override { + CPU = Name; + return isValidCPUName(Name); + } + const std::string& getCPU() const { return CPU; } bool initFeatureMap(llvm::StringMap &Features, DiagnosticsEngine &Diags, @@ -8750,13 +8873,16 @@ } return true; } - bool setCPU(const std::string &Name) final { + bool isValidCPUName(StringRef Name) const final { return llvm::StringSwitch(Name) .Case("mvp", true) .Case("bleeding-edge", true) .Case("generic", true) .Default(false); } + bool setCPU(const std::string &Name) final { + return isValidCPUName(Name); + } ArrayRef getTargetBuiltins() const final { return llvm::makeArrayRef(BuiltinInfo, clang::WebAssembly::LastTSBuiltin - Builtin::FirstTSBuiltin); @@ -9476,7 +9602,7 @@ : TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned); } - bool setCPU(const std::string &Name) override { + bool isValidCPUName(StringRef Name) const override { bool IsFamily = llvm::StringSwitch(Name) .Case("avr1", true) .Case("avr2", true) @@ -9498,16 +9624,18 @@ .Case("avrtiny", true) .Default(false); - if (IsFamily) this->CPU = Name; - bool IsMCU = std::find_if(AVRMcus.begin(), AVRMcus.end(), [&](const MCUInfo &Info) { return Info.Name == Name; }) != AVRMcus.end(); - - if (IsMCU) this->CPU = Name; - return IsFamily || IsMCU; } + bool setCPU(const std::string &Name) override { + bool isValid = isValidCPUName(Name); + if (isValid) + CPU = Name; + return isValid; + } + protected: std::string CPU; };