106c3fb27SDimitry Andric //===--- RISCV.cpp - Implement RISC-V target feature support --------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 906c3fb27SDimitry Andric // This file implements RISC-V TargetInfo objects. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "RISCV.h" 14349cc55cSDimitry Andric #include "clang/Basic/Diagnostic.h" 150b57cec5SDimitry Andric #include "clang/Basic/MacroBuilder.h" 16fe6060f1SDimitry Andric #include "clang/Basic/TargetBuiltins.h" 170b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h" 18349cc55cSDimitry Andric #include "llvm/Support/raw_ostream.h" 19bdd1243dSDimitry Andric #include "llvm/TargetParser/RISCVTargetParser.h" 20bdd1243dSDimitry Andric #include <optional> 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric using namespace clang; 230b57cec5SDimitry Andric using namespace clang::targets; 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const { 265f757f3fSDimitry Andric // clang-format off 270b57cec5SDimitry Andric static const char *const GCCRegNames[] = { 28a7dea167SDimitry Andric // Integer registers 290b57cec5SDimitry Andric "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 300b57cec5SDimitry Andric "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 310b57cec5SDimitry Andric "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", 32a7dea167SDimitry Andric "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", 33a7dea167SDimitry Andric 34a7dea167SDimitry Andric // Floating point registers 35a7dea167SDimitry Andric "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", 36a7dea167SDimitry Andric "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", 37a7dea167SDimitry Andric "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", 38fe6060f1SDimitry Andric "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", 39fe6060f1SDimitry Andric 40fe6060f1SDimitry Andric // Vector registers 41fe6060f1SDimitry Andric "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", 42fe6060f1SDimitry Andric "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", 43fe6060f1SDimitry Andric "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", 445f757f3fSDimitry Andric "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", 455f757f3fSDimitry Andric 465f757f3fSDimitry Andric // CSRs 475f757f3fSDimitry Andric "fflags", "frm", "vtype", "vl", "vxsat", "vxrm" 485f757f3fSDimitry Andric }; 495f757f3fSDimitry Andric // clang-format on 50bdd1243dSDimitry Andric return llvm::ArrayRef(GCCRegNames); 510b57cec5SDimitry Andric } 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const { 540b57cec5SDimitry Andric static const TargetInfo::GCCRegAlias GCCRegAliases[] = { 550b57cec5SDimitry Andric {{"zero"}, "x0"}, {{"ra"}, "x1"}, {{"sp"}, "x2"}, {{"gp"}, "x3"}, 560b57cec5SDimitry Andric {{"tp"}, "x4"}, {{"t0"}, "x5"}, {{"t1"}, "x6"}, {{"t2"}, "x7"}, 570b57cec5SDimitry Andric {{"s0"}, "x8"}, {{"s1"}, "x9"}, {{"a0"}, "x10"}, {{"a1"}, "x11"}, 580b57cec5SDimitry Andric {{"a2"}, "x12"}, {{"a3"}, "x13"}, {{"a4"}, "x14"}, {{"a5"}, "x15"}, 590b57cec5SDimitry Andric {{"a6"}, "x16"}, {{"a7"}, "x17"}, {{"s2"}, "x18"}, {{"s3"}, "x19"}, 600b57cec5SDimitry Andric {{"s4"}, "x20"}, {{"s5"}, "x21"}, {{"s6"}, "x22"}, {{"s7"}, "x23"}, 610b57cec5SDimitry Andric {{"s8"}, "x24"}, {{"s9"}, "x25"}, {{"s10"}, "x26"}, {{"s11"}, "x27"}, 62a7dea167SDimitry Andric {{"t3"}, "x28"}, {{"t4"}, "x29"}, {{"t5"}, "x30"}, {{"t6"}, "x31"}, 63a7dea167SDimitry Andric {{"ft0"}, "f0"}, {{"ft1"}, "f1"}, {{"ft2"}, "f2"}, {{"ft3"}, "f3"}, 64a7dea167SDimitry Andric {{"ft4"}, "f4"}, {{"ft5"}, "f5"}, {{"ft6"}, "f6"}, {{"ft7"}, "f7"}, 65a7dea167SDimitry Andric {{"fs0"}, "f8"}, {{"fs1"}, "f9"}, {{"fa0"}, "f10"}, {{"fa1"}, "f11"}, 66a7dea167SDimitry Andric {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"}, {{"fa5"}, "f15"}, 67a7dea167SDimitry Andric {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"}, {{"fs3"}, "f19"}, 68a7dea167SDimitry Andric {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"}, {{"fs7"}, "f23"}, 69a7dea167SDimitry Andric {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"}, 70a7dea167SDimitry Andric {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}}; 71bdd1243dSDimitry Andric return llvm::ArrayRef(GCCRegAliases); 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric bool RISCVTargetInfo::validateAsmConstraint( 750b57cec5SDimitry Andric const char *&Name, TargetInfo::ConstraintInfo &Info) const { 760b57cec5SDimitry Andric switch (*Name) { 770b57cec5SDimitry Andric default: 780b57cec5SDimitry Andric return false; 790b57cec5SDimitry Andric case 'I': 800b57cec5SDimitry Andric // A 12-bit signed immediate. 810b57cec5SDimitry Andric Info.setRequiresImmediate(-2048, 2047); 820b57cec5SDimitry Andric return true; 830b57cec5SDimitry Andric case 'J': 840b57cec5SDimitry Andric // Integer zero. 850b57cec5SDimitry Andric Info.setRequiresImmediate(0); 860b57cec5SDimitry Andric return true; 870b57cec5SDimitry Andric case 'K': 880b57cec5SDimitry Andric // A 5-bit unsigned immediate for CSR access instructions. 890b57cec5SDimitry Andric Info.setRequiresImmediate(0, 31); 900b57cec5SDimitry Andric return true; 910b57cec5SDimitry Andric case 'f': 920b57cec5SDimitry Andric // A floating-point register. 930b57cec5SDimitry Andric Info.setAllowsRegister(); 940b57cec5SDimitry Andric return true; 950b57cec5SDimitry Andric case 'A': 960b57cec5SDimitry Andric // An address that is held in a general-purpose register. 970b57cec5SDimitry Andric Info.setAllowsMemory(); 980b57cec5SDimitry Andric return true; 99*0fca6ea1SDimitry Andric case 's': 100*0fca6ea1SDimitry Andric case 'S': // A symbol or label reference with a constant offset 101fe6060f1SDimitry Andric Info.setAllowsRegister(); 102fe6060f1SDimitry Andric return true; 103fe6060f1SDimitry Andric case 'v': 104fe6060f1SDimitry Andric // A vector register. 105fe6060f1SDimitry Andric if (Name[1] == 'r' || Name[1] == 'm') { 106fe6060f1SDimitry Andric Info.setAllowsRegister(); 107fe6060f1SDimitry Andric Name += 1; 108fe6060f1SDimitry Andric return true; 1090b57cec5SDimitry Andric } 110fe6060f1SDimitry Andric return false; 111fe6060f1SDimitry Andric } 112fe6060f1SDimitry Andric } 113fe6060f1SDimitry Andric 114fe6060f1SDimitry Andric std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const { 115fe6060f1SDimitry Andric std::string R; 116fe6060f1SDimitry Andric switch (*Constraint) { 117fe6060f1SDimitry Andric case 'v': 118349cc55cSDimitry Andric R = std::string("^") + std::string(Constraint, 2); 119fe6060f1SDimitry Andric Constraint += 1; 120fe6060f1SDimitry Andric break; 121fe6060f1SDimitry Andric default: 122fe6060f1SDimitry Andric R = TargetInfo::convertConstraint(Constraint); 123fe6060f1SDimitry Andric break; 124fe6060f1SDimitry Andric } 125fe6060f1SDimitry Andric return R; 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 128bdd1243dSDimitry Andric static unsigned getVersionValue(unsigned MajorVersion, unsigned MinorVersion) { 129bdd1243dSDimitry Andric return MajorVersion * 1000000 + MinorVersion * 1000; 130bdd1243dSDimitry Andric } 131bdd1243dSDimitry Andric 1320b57cec5SDimitry Andric void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, 1330b57cec5SDimitry Andric MacroBuilder &Builder) const { 1340b57cec5SDimitry Andric Builder.defineMacro("__riscv"); 1355f757f3fSDimitry Andric bool Is64Bit = getTriple().isRISCV64(); 1360b57cec5SDimitry Andric Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32"); 137a7dea167SDimitry Andric StringRef CodeModel = getTargetOpts().CodeModel; 138349cc55cSDimitry Andric unsigned FLen = ISAInfo->getFLen(); 13904eeddc0SDimitry Andric unsigned MinVLen = ISAInfo->getMinVLen(); 14004eeddc0SDimitry Andric unsigned MaxELen = ISAInfo->getMaxELen(); 14104eeddc0SDimitry Andric unsigned MaxELenFp = ISAInfo->getMaxELenFp(); 142a7dea167SDimitry Andric if (CodeModel == "default") 143a7dea167SDimitry Andric CodeModel = "small"; 144a7dea167SDimitry Andric 145a7dea167SDimitry Andric if (CodeModel == "small") 1460b57cec5SDimitry Andric Builder.defineMacro("__riscv_cmodel_medlow"); 147a7dea167SDimitry Andric else if (CodeModel == "medium") 148a7dea167SDimitry Andric Builder.defineMacro("__riscv_cmodel_medany"); 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric StringRef ABIName = getABI(); 1510b57cec5SDimitry Andric if (ABIName == "ilp32f" || ABIName == "lp64f") 1520b57cec5SDimitry Andric Builder.defineMacro("__riscv_float_abi_single"); 1530b57cec5SDimitry Andric else if (ABIName == "ilp32d" || ABIName == "lp64d") 1540b57cec5SDimitry Andric Builder.defineMacro("__riscv_float_abi_double"); 1550b57cec5SDimitry Andric else 1560b57cec5SDimitry Andric Builder.defineMacro("__riscv_float_abi_soft"); 1570b57cec5SDimitry Andric 1587a6dacacSDimitry Andric if (ABIName == "ilp32e" || ABIName == "lp64e") 159a7dea167SDimitry Andric Builder.defineMacro("__riscv_abi_rve"); 160a7dea167SDimitry Andric 161e8d8bef9SDimitry Andric Builder.defineMacro("__riscv_arch_test"); 162e8d8bef9SDimitry Andric 163349cc55cSDimitry Andric for (auto &Extension : ISAInfo->getExtensions()) { 164349cc55cSDimitry Andric auto ExtName = Extension.first; 165349cc55cSDimitry Andric auto ExtInfo = Extension.second; 166349cc55cSDimitry Andric 167297eecfbSDimitry Andric Builder.defineMacro(Twine("__riscv_", ExtName), 168297eecfbSDimitry Andric Twine(getVersionValue(ExtInfo.Major, ExtInfo.Minor))); 169349cc55cSDimitry Andric } 170349cc55cSDimitry Andric 171*0fca6ea1SDimitry Andric if (ISAInfo->hasExtension("zmmul")) 1720b57cec5SDimitry Andric Builder.defineMacro("__riscv_mul"); 173fcaf7f86SDimitry Andric 174fcaf7f86SDimitry Andric if (ISAInfo->hasExtension("m")) { 1750b57cec5SDimitry Andric Builder.defineMacro("__riscv_div"); 1760b57cec5SDimitry Andric Builder.defineMacro("__riscv_muldiv"); 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric 179349cc55cSDimitry Andric if (ISAInfo->hasExtension("a")) { 1800b57cec5SDimitry Andric Builder.defineMacro("__riscv_atomic"); 1816813f242SDimitry Andric Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 1826813f242SDimitry Andric Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 1836813f242SDimitry Andric Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 1846813f242SDimitry Andric if (Is64Bit) 1856813f242SDimitry Andric Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 1866813f242SDimitry Andric } 1870b57cec5SDimitry Andric 188349cc55cSDimitry Andric if (FLen) { 189349cc55cSDimitry Andric Builder.defineMacro("__riscv_flen", Twine(FLen)); 1900b57cec5SDimitry Andric Builder.defineMacro("__riscv_fdiv"); 1910b57cec5SDimitry Andric Builder.defineMacro("__riscv_fsqrt"); 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 19404eeddc0SDimitry Andric if (MinVLen) { 19504eeddc0SDimitry Andric Builder.defineMacro("__riscv_v_min_vlen", Twine(MinVLen)); 19604eeddc0SDimitry Andric Builder.defineMacro("__riscv_v_elen", Twine(MaxELen)); 19704eeddc0SDimitry Andric Builder.defineMacro("__riscv_v_elen_fp", Twine(MaxELenFp)); 19804eeddc0SDimitry Andric } 19904eeddc0SDimitry Andric 200349cc55cSDimitry Andric if (ISAInfo->hasExtension("c")) 201e8d8bef9SDimitry Andric Builder.defineMacro("__riscv_compressed"); 202e8d8bef9SDimitry Andric 203bdd1243dSDimitry Andric if (ISAInfo->hasExtension("zve32x")) { 204e8d8bef9SDimitry Andric Builder.defineMacro("__riscv_vector"); 2058a4dda33SDimitry Andric // Currently we support the v0.12 RISC-V V intrinsics. 2068a4dda33SDimitry Andric Builder.defineMacro("__riscv_v_intrinsic", Twine(getVersionValue(0, 12))); 207bdd1243dSDimitry Andric } 20806c3fb27SDimitry Andric 20906c3fb27SDimitry Andric auto VScale = getVScaleRange(Opts); 21006c3fb27SDimitry Andric if (VScale && VScale->first && VScale->first == VScale->second) 21106c3fb27SDimitry Andric Builder.defineMacro("__riscv_v_fixed_vlen", 21206c3fb27SDimitry Andric Twine(VScale->first * llvm::RISCV::RVVBitsPerBlock)); 2135f757f3fSDimitry Andric 214*0fca6ea1SDimitry Andric if (FastScalarUnalignedAccess) 2155f757f3fSDimitry Andric Builder.defineMacro("__riscv_misaligned_fast"); 2165f757f3fSDimitry Andric else 2175f757f3fSDimitry Andric Builder.defineMacro("__riscv_misaligned_avoid"); 2187a6dacacSDimitry Andric 2197a6dacacSDimitry Andric if (ISAInfo->hasExtension("e")) { 2207a6dacacSDimitry Andric if (Is64Bit) 2217a6dacacSDimitry Andric Builder.defineMacro("__riscv_64e"); 2227a6dacacSDimitry Andric else 2237a6dacacSDimitry Andric Builder.defineMacro("__riscv_32e"); 2247a6dacacSDimitry Andric } 225e8d8bef9SDimitry Andric } 226e8d8bef9SDimitry Andric 227bdd1243dSDimitry Andric static constexpr Builtin::Info BuiltinInfo[] = { 228fe6060f1SDimitry Andric #define BUILTIN(ID, TYPE, ATTRS) \ 229bdd1243dSDimitry Andric {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, 230fe6060f1SDimitry Andric #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ 231bdd1243dSDimitry Andric {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, 232349cc55cSDimitry Andric #include "clang/Basic/BuiltinsRISCVVector.def" 233349cc55cSDimitry Andric #define BUILTIN(ID, TYPE, ATTRS) \ 234bdd1243dSDimitry Andric {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, 235349cc55cSDimitry Andric #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ 236bdd1243dSDimitry Andric {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, 237*0fca6ea1SDimitry Andric #include "clang/Basic/BuiltinsRISCV.inc" 238fe6060f1SDimitry Andric }; 239fe6060f1SDimitry Andric 240fe6060f1SDimitry Andric ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const { 241bdd1243dSDimitry Andric return llvm::ArrayRef(BuiltinInfo, 242bdd1243dSDimitry Andric clang::RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin); 243fe6060f1SDimitry Andric } 244fe6060f1SDimitry Andric 245fe6060f1SDimitry Andric bool RISCVTargetInfo::initFeatureMap( 246fe6060f1SDimitry Andric llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, 247fe6060f1SDimitry Andric const std::vector<std::string> &FeaturesVec) const { 248fe6060f1SDimitry Andric 24904eeddc0SDimitry Andric unsigned XLen = 32; 250fe6060f1SDimitry Andric 2515f757f3fSDimitry Andric if (getTriple().isRISCV64()) { 25204eeddc0SDimitry Andric Features["64bit"] = true; 25304eeddc0SDimitry Andric XLen = 64; 254bdd1243dSDimitry Andric } else { 255bdd1243dSDimitry Andric Features["32bit"] = true; 25604eeddc0SDimitry Andric } 25704eeddc0SDimitry Andric 2587a6dacacSDimitry Andric // If a target attribute specified a full arch string, override all the ISA 2597a6dacacSDimitry Andric // extension target features. 2607a6dacacSDimitry Andric const auto I = llvm::find(FeaturesVec, "__RISCV_TargetAttrNeedOverride"); 2617a6dacacSDimitry Andric if (I != FeaturesVec.end()) { 2627a6dacacSDimitry Andric std::vector<std::string> OverrideFeatures(std::next(I), FeaturesVec.end()); 2635f757f3fSDimitry Andric 2647a6dacacSDimitry Andric // Add back any non ISA extension features, e.g. +relax. 2657a6dacacSDimitry Andric auto IsNonISAExtFeature = [](StringRef Feature) { 2667a6dacacSDimitry Andric assert(Feature.size() > 1 && (Feature[0] == '+' || Feature[0] == '-')); 2677a6dacacSDimitry Andric StringRef Ext = Feature.substr(1); // drop the +/- 2687a6dacacSDimitry Andric return !llvm::RISCVISAInfo::isSupportedExtensionFeature(Ext); 2697a6dacacSDimitry Andric }; 2707a6dacacSDimitry Andric llvm::copy_if(llvm::make_range(FeaturesVec.begin(), I), 2717a6dacacSDimitry Andric std::back_inserter(OverrideFeatures), IsNonISAExtFeature); 2727a6dacacSDimitry Andric 2737a6dacacSDimitry Andric return TargetInfo::initFeatureMap(Features, Diags, CPU, OverrideFeatures); 2747a6dacacSDimitry Andric } 2757a6dacacSDimitry Andric 2767a6dacacSDimitry Andric // Otherwise, parse the features and add any implied extensions. 2777a6dacacSDimitry Andric std::vector<std::string> AllFeatures = FeaturesVec; 2787a6dacacSDimitry Andric auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec); 27904eeddc0SDimitry Andric if (!ParseResult) { 28004eeddc0SDimitry Andric std::string Buffer; 28104eeddc0SDimitry Andric llvm::raw_string_ostream OutputErrMsg(Buffer); 28204eeddc0SDimitry Andric handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) { 28304eeddc0SDimitry Andric OutputErrMsg << ErrMsg.getMessage(); 28404eeddc0SDimitry Andric }); 28504eeddc0SDimitry Andric Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str(); 28604eeddc0SDimitry Andric return false; 28704eeddc0SDimitry Andric } 28804eeddc0SDimitry Andric 2897a6dacacSDimitry Andric // Append all features, not just new ones, so we override any negatives. 2907a6dacacSDimitry Andric llvm::append_range(AllFeatures, (*ParseResult)->toFeatures()); 2917a6dacacSDimitry Andric return TargetInfo::initFeatureMap(Features, Diags, CPU, AllFeatures); 292fe6060f1SDimitry Andric } 293fe6060f1SDimitry Andric 294bdd1243dSDimitry Andric std::optional<std::pair<unsigned, unsigned>> 295bdd1243dSDimitry Andric RISCVTargetInfo::getVScaleRange(const LangOptions &LangOpts) const { 296bdd1243dSDimitry Andric // RISCV::RVVBitsPerBlock is 64. 297bdd1243dSDimitry Andric unsigned VScaleMin = ISAInfo->getMinVLen() / llvm::RISCV::RVVBitsPerBlock; 298bdd1243dSDimitry Andric 299bdd1243dSDimitry Andric if (LangOpts.VScaleMin || LangOpts.VScaleMax) { 300bdd1243dSDimitry Andric // Treat Zvl*b as a lower bound on vscale. 301bdd1243dSDimitry Andric VScaleMin = std::max(VScaleMin, LangOpts.VScaleMin); 302bdd1243dSDimitry Andric unsigned VScaleMax = LangOpts.VScaleMax; 303bdd1243dSDimitry Andric if (VScaleMax != 0 && VScaleMax < VScaleMin) 304bdd1243dSDimitry Andric VScaleMax = VScaleMin; 305bdd1243dSDimitry Andric return std::pair<unsigned, unsigned>(VScaleMin ? VScaleMin : 1, VScaleMax); 306bdd1243dSDimitry Andric } 307bdd1243dSDimitry Andric 308bdd1243dSDimitry Andric if (VScaleMin > 0) { 309bdd1243dSDimitry Andric unsigned VScaleMax = ISAInfo->getMaxVLen() / llvm::RISCV::RVVBitsPerBlock; 310bdd1243dSDimitry Andric return std::make_pair(VScaleMin, VScaleMax); 311bdd1243dSDimitry Andric } 312bdd1243dSDimitry Andric 313bdd1243dSDimitry Andric return std::nullopt; 314bdd1243dSDimitry Andric } 315bdd1243dSDimitry Andric 3160b57cec5SDimitry Andric /// Return true if has this feature, need to sync with handleTargetFeatures. 3170b57cec5SDimitry Andric bool RISCVTargetInfo::hasFeature(StringRef Feature) const { 3185f757f3fSDimitry Andric bool Is64Bit = getTriple().isRISCV64(); 319bdd1243dSDimitry Andric auto Result = llvm::StringSwitch<std::optional<bool>>(Feature) 3200b57cec5SDimitry Andric .Case("riscv", true) 3210b57cec5SDimitry Andric .Case("riscv32", !Is64Bit) 3220b57cec5SDimitry Andric .Case("riscv64", Is64Bit) 323bdd1243dSDimitry Andric .Case("32bit", !Is64Bit) 324fe6060f1SDimitry Andric .Case("64bit", Is64Bit) 325cb14a3feSDimitry Andric .Case("experimental", HasExperimental) 326bdd1243dSDimitry Andric .Default(std::nullopt); 32781ad6265SDimitry Andric if (Result) 328bdd1243dSDimitry Andric return *Result; 329349cc55cSDimitry Andric 330349cc55cSDimitry Andric return ISAInfo->hasExtension(Feature); 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric /// Perform initialization based on the user configured set of features. 3340b57cec5SDimitry Andric bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 3350b57cec5SDimitry Andric DiagnosticsEngine &Diags) { 336349cc55cSDimitry Andric unsigned XLen = getTriple().isArch64Bit() ? 64 : 32; 337349cc55cSDimitry Andric auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features); 338349cc55cSDimitry Andric if (!ParseResult) { 339349cc55cSDimitry Andric std::string Buffer; 340349cc55cSDimitry Andric llvm::raw_string_ostream OutputErrMsg(Buffer); 341349cc55cSDimitry Andric handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) { 342349cc55cSDimitry Andric OutputErrMsg << ErrMsg.getMessage(); 343349cc55cSDimitry Andric }); 344349cc55cSDimitry Andric Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str(); 345349cc55cSDimitry Andric return false; 346349cc55cSDimitry Andric } else { 347349cc55cSDimitry Andric ISAInfo = std::move(*ParseResult); 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric 3500eae32dcSDimitry Andric if (ABI.empty()) 35181ad6265SDimitry Andric ABI = ISAInfo->computeDefaultABI().str(); 3520eae32dcSDimitry Andric 35306c3fb27SDimitry Andric if (ISAInfo->hasExtension("zfh") || ISAInfo->hasExtension("zhinx")) 35406c3fb27SDimitry Andric HasLegalHalfType = true; 35506c3fb27SDimitry Andric 356*0fca6ea1SDimitry Andric FastScalarUnalignedAccess = 357*0fca6ea1SDimitry Andric llvm::is_contained(Features, "+unaligned-scalar-mem"); 3585f757f3fSDimitry Andric 359cb14a3feSDimitry Andric if (llvm::is_contained(Features, "+experimental")) 360cb14a3feSDimitry Andric HasExperimental = true; 361cb14a3feSDimitry Andric 3627a6dacacSDimitry Andric if (ABI == "ilp32e" && ISAInfo->hasExtension("d")) { 3637a6dacacSDimitry Andric Diags.Report(diag::err_invalid_feature_combination) 3647a6dacacSDimitry Andric << "ILP32E cannot be used with the D ISA extension"; 3657a6dacacSDimitry Andric return false; 3667a6dacacSDimitry Andric } 3670b57cec5SDimitry Andric return true; 3680b57cec5SDimitry Andric } 369590d96feSDimitry Andric 370bdd1243dSDimitry Andric bool RISCVTargetInfo::isValidCPUName(StringRef Name) const { 371bdd1243dSDimitry Andric bool Is64Bit = getTriple().isArch64Bit(); 37206c3fb27SDimitry Andric return llvm::RISCV::parseCPU(Name, Is64Bit); 373590d96feSDimitry Andric } 374590d96feSDimitry Andric 375bdd1243dSDimitry Andric void RISCVTargetInfo::fillValidCPUList( 376590d96feSDimitry Andric SmallVectorImpl<StringRef> &Values) const { 377bdd1243dSDimitry Andric bool Is64Bit = getTriple().isArch64Bit(); 378bdd1243dSDimitry Andric llvm::RISCV::fillValidCPUArchList(Values, Is64Bit); 379590d96feSDimitry Andric } 380590d96feSDimitry Andric 381bdd1243dSDimitry Andric bool RISCVTargetInfo::isValidTuneCPUName(StringRef Name) const { 382bdd1243dSDimitry Andric bool Is64Bit = getTriple().isArch64Bit(); 38306c3fb27SDimitry Andric return llvm::RISCV::parseTuneCPU(Name, Is64Bit); 384e8d8bef9SDimitry Andric } 385e8d8bef9SDimitry Andric 386bdd1243dSDimitry Andric void RISCVTargetInfo::fillValidTuneCPUList( 387e8d8bef9SDimitry Andric SmallVectorImpl<StringRef> &Values) const { 388bdd1243dSDimitry Andric bool Is64Bit = getTriple().isArch64Bit(); 389bdd1243dSDimitry Andric llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit); 390e8d8bef9SDimitry Andric } 3915f757f3fSDimitry Andric 3925f757f3fSDimitry Andric static void handleFullArchString(StringRef FullArchStr, 3935f757f3fSDimitry Andric std::vector<std::string> &Features) { 3945f757f3fSDimitry Andric Features.push_back("__RISCV_TargetAttrNeedOverride"); 3955f757f3fSDimitry Andric auto RII = llvm::RISCVISAInfo::parseArchString( 3965f757f3fSDimitry Andric FullArchStr, /* EnableExperimentalExtension */ true); 397647cbc5dSDimitry Andric if (llvm::errorToBool(RII.takeError())) { 3985f757f3fSDimitry Andric // Forward the invalid FullArchStr. 3995f757f3fSDimitry Andric Features.push_back("+" + FullArchStr.str()); 4005f757f3fSDimitry Andric } else { 4017a6dacacSDimitry Andric // Append a full list of features, including any negative extensions so that 4027a6dacacSDimitry Andric // we override the CPU's features. 4037a6dacacSDimitry Andric std::vector<std::string> FeatStrings = 4047a6dacacSDimitry Andric (*RII)->toFeatures(/* AddAllExtensions */ true); 4055f757f3fSDimitry Andric Features.insert(Features.end(), FeatStrings.begin(), FeatStrings.end()); 4065f757f3fSDimitry Andric } 4075f757f3fSDimitry Andric } 4085f757f3fSDimitry Andric 4095f757f3fSDimitry Andric ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const { 4105f757f3fSDimitry Andric ParsedTargetAttr Ret; 4115f757f3fSDimitry Andric if (Features == "default") 4125f757f3fSDimitry Andric return Ret; 4135f757f3fSDimitry Andric SmallVector<StringRef, 1> AttrFeatures; 4145f757f3fSDimitry Andric Features.split(AttrFeatures, ";"); 4155f757f3fSDimitry Andric bool FoundArch = false; 4165f757f3fSDimitry Andric 4175f757f3fSDimitry Andric for (auto &Feature : AttrFeatures) { 4185f757f3fSDimitry Andric Feature = Feature.trim(); 4195f757f3fSDimitry Andric StringRef AttrString = Feature.split("=").second.trim(); 4205f757f3fSDimitry Andric 4215f757f3fSDimitry Andric if (Feature.starts_with("arch=")) { 4225f757f3fSDimitry Andric // Override last features 4235f757f3fSDimitry Andric Ret.Features.clear(); 4245f757f3fSDimitry Andric if (FoundArch) 4255f757f3fSDimitry Andric Ret.Duplicate = "arch="; 4265f757f3fSDimitry Andric FoundArch = true; 4275f757f3fSDimitry Andric 4285f757f3fSDimitry Andric if (AttrString.starts_with("+")) { 4295f757f3fSDimitry Andric // EXTENSION like arch=+v,+zbb 4305f757f3fSDimitry Andric SmallVector<StringRef, 1> Exts; 4315f757f3fSDimitry Andric AttrString.split(Exts, ","); 4325f757f3fSDimitry Andric for (auto Ext : Exts) { 4335f757f3fSDimitry Andric if (Ext.empty()) 4345f757f3fSDimitry Andric continue; 4355f757f3fSDimitry Andric 4365f757f3fSDimitry Andric StringRef ExtName = Ext.substr(1); 4375f757f3fSDimitry Andric std::string TargetFeature = 4385f757f3fSDimitry Andric llvm::RISCVISAInfo::getTargetFeatureForExtension(ExtName); 4395f757f3fSDimitry Andric if (!TargetFeature.empty()) 4405f757f3fSDimitry Andric Ret.Features.push_back(Ext.front() + TargetFeature); 4415f757f3fSDimitry Andric else 4425f757f3fSDimitry Andric Ret.Features.push_back(Ext.str()); 4435f757f3fSDimitry Andric } 4445f757f3fSDimitry Andric } else { 4455f757f3fSDimitry Andric // full-arch-string like arch=rv64gcv 4465f757f3fSDimitry Andric handleFullArchString(AttrString, Ret.Features); 4475f757f3fSDimitry Andric } 4485f757f3fSDimitry Andric } else if (Feature.starts_with("cpu=")) { 4495f757f3fSDimitry Andric if (!Ret.CPU.empty()) 4505f757f3fSDimitry Andric Ret.Duplicate = "cpu="; 4515f757f3fSDimitry Andric 4525f757f3fSDimitry Andric Ret.CPU = AttrString; 4535f757f3fSDimitry Andric 4545f757f3fSDimitry Andric if (!FoundArch) { 4555f757f3fSDimitry Andric // Update Features with CPU's features 4565f757f3fSDimitry Andric StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(Ret.CPU); 4575f757f3fSDimitry Andric if (MarchFromCPU != "") { 4585f757f3fSDimitry Andric Ret.Features.clear(); 4595f757f3fSDimitry Andric handleFullArchString(MarchFromCPU, Ret.Features); 4605f757f3fSDimitry Andric } 4615f757f3fSDimitry Andric } 4625f757f3fSDimitry Andric } else if (Feature.starts_with("tune=")) { 4635f757f3fSDimitry Andric if (!Ret.Tune.empty()) 4645f757f3fSDimitry Andric Ret.Duplicate = "tune="; 4655f757f3fSDimitry Andric 4665f757f3fSDimitry Andric Ret.Tune = AttrString; 4675f757f3fSDimitry Andric } 4685f757f3fSDimitry Andric } 4695f757f3fSDimitry Andric return Ret; 4705f757f3fSDimitry Andric } 471*0fca6ea1SDimitry Andric 472*0fca6ea1SDimitry Andric TargetInfo::CallingConvCheckResult 473*0fca6ea1SDimitry Andric RISCVTargetInfo::checkCallingConvention(CallingConv CC) const { 474*0fca6ea1SDimitry Andric switch (CC) { 475*0fca6ea1SDimitry Andric default: 476*0fca6ea1SDimitry Andric return CCCR_Warning; 477*0fca6ea1SDimitry Andric case CC_C: 478*0fca6ea1SDimitry Andric case CC_RISCVVectorCall: 479*0fca6ea1SDimitry Andric return CCCR_OK; 480*0fca6ea1SDimitry Andric } 481*0fca6ea1SDimitry Andric } 482