brintos

brintos / llvm-project-archived public Read only

0
0
Text · 21.6 KiB · 685925b Raw
646 lines · cpp
1//===--- RISCV.cpp - Implement RISC-V target feature support --------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements RISC-V TargetInfo objects.10//11//===----------------------------------------------------------------------===//12 13#include "RISCV.h"14#include "clang/Basic/Diagnostic.h"15#include "clang/Basic/MacroBuilder.h"16#include "clang/Basic/TargetBuiltins.h"17#include "llvm/ADT/StringSwitch.h"18#include "llvm/Support/raw_ostream.h"19#include "llvm/TargetParser/RISCVTargetParser.h"20#include <optional>21 22using namespace clang;23using namespace clang::targets;24 25ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const {26  // clang-format off27  static const char *const GCCRegNames[] = {28      // Integer registers29      "x0",  "x1",  "x2",  "x3",  "x4",  "x5",  "x6",  "x7",30      "x8",  "x9",  "x10", "x11", "x12", "x13", "x14", "x15",31      "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",32      "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",33 34      // Floating point registers35      "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",36      "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",37      "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",38      "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",39 40      // Vector registers41      "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",42      "v8",  "v9",  "v10", "v11", "v12", "v13", "v14", "v15",43      "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",44      "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",45 46      // CSRs47      "fflags", "frm", "vtype", "vl", "vxsat", "vxrm", "sf.vcix_state"48    };49  // clang-format on50  return llvm::ArrayRef(GCCRegNames);51}52 53ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const {54  static const TargetInfo::GCCRegAlias GCCRegAliases[] = {55      {{"zero"}, "x0"}, {{"ra"}, "x1"},   {{"sp"}, "x2"},    {{"gp"}, "x3"},56      {{"tp"}, "x4"},   {{"t0"}, "x5"},   {{"t1"}, "x6"},    {{"t2"}, "x7"},57      {{"s0"}, "x8"},   {{"s1"}, "x9"},   {{"a0"}, "x10"},   {{"a1"}, "x11"},58      {{"a2"}, "x12"},  {{"a3"}, "x13"},  {{"a4"}, "x14"},   {{"a5"}, "x15"},59      {{"a6"}, "x16"},  {{"a7"}, "x17"},  {{"s2"}, "x18"},   {{"s3"}, "x19"},60      {{"s4"}, "x20"},  {{"s5"}, "x21"},  {{"s6"}, "x22"},   {{"s7"}, "x23"},61      {{"s8"}, "x24"},  {{"s9"}, "x25"},  {{"s10"}, "x26"},  {{"s11"}, "x27"},62      {{"t3"}, "x28"},  {{"t4"}, "x29"},  {{"t5"}, "x30"},   {{"t6"}, "x31"},63      {{"ft0"}, "f0"},  {{"ft1"}, "f1"},  {{"ft2"}, "f2"},   {{"ft3"}, "f3"},64      {{"ft4"}, "f4"},  {{"ft5"}, "f5"},  {{"ft6"}, "f6"},   {{"ft7"}, "f7"},65      {{"fs0"}, "f8"},  {{"fs1"}, "f9"},  {{"fa0"}, "f10"},  {{"fa1"}, "f11"},66      {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"},  {{"fa5"}, "f15"},67      {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"},  {{"fs3"}, "f19"},68      {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"},  {{"fs7"}, "f23"},69      {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"},70      {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}};71  return llvm::ArrayRef(GCCRegAliases);72}73 74bool RISCVTargetInfo::validateAsmConstraint(75    const char *&Name, TargetInfo::ConstraintInfo &Info) const {76  switch (*Name) {77  default:78    return false;79  case 'I':80    // A 12-bit signed immediate.81    Info.setRequiresImmediate(-2048, 2047);82    return true;83  case 'J':84    // Integer zero.85    Info.setRequiresImmediate(0);86    return true;87  case 'K':88    // A 5-bit unsigned immediate for CSR access instructions.89    Info.setRequiresImmediate(0, 31);90    return true;91  case 'f':92    // A floating-point register.93    Info.setAllowsRegister();94    return true;95  case 'A':96    // An address that is held in a general-purpose register.97    Info.setAllowsMemory();98    return true;99  case 's':100  case 'S': // A symbol or label reference with a constant offset101    Info.setAllowsRegister();102    return true;103  case 'c':104    // A RVC register - GPR or FPR105    if (Name[1] == 'r' || Name[1] == 'R' || Name[1] == 'f') {106      Info.setAllowsRegister();107      Name += 1;108      return true;109    }110    return false;111  case 'R':112    // An even-odd GPR pair113    Info.setAllowsRegister();114    return true;115  case 'v':116    // A vector register.117    if (Name[1] == 'r' || Name[1] == 'd' || Name[1] == 'm') {118      Info.setAllowsRegister();119      Name += 1;120      return true;121    }122    return false;123  }124}125 126std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const {127  std::string R;128  switch (*Constraint) {129  // c* and v* are two-letter constraints on RISC-V.130  case 'c':131  case 'v':132    R = std::string("^") + std::string(Constraint, 2);133    Constraint += 1;134    break;135  default:136    R = TargetInfo::convertConstraint(Constraint);137    break;138  }139  return R;140}141 142static unsigned getVersionValue(unsigned MajorVersion, unsigned MinorVersion) {143  return MajorVersion * 1000000 + MinorVersion * 1000;144}145 146void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,147                                       MacroBuilder &Builder) const {148  Builder.defineMacro("__riscv");149  bool Is64Bit = getTriple().isRISCV64();150  Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32");151  StringRef CodeModel = getTargetOpts().CodeModel;152  unsigned FLen = ISAInfo->getFLen();153  unsigned MinVLen = ISAInfo->getMinVLen();154  unsigned MaxELen = ISAInfo->getMaxELen();155  unsigned MaxELenFp = ISAInfo->getMaxELenFp();156  if (CodeModel == "default")157    CodeModel = "small";158 159  if (CodeModel == "small")160    Builder.defineMacro("__riscv_cmodel_medlow");161  else if (CodeModel == "medium")162    Builder.defineMacro("__riscv_cmodel_medany");163  else if (CodeModel == "large")164    Builder.defineMacro("__riscv_cmodel_large");165 166  StringRef ABIName = getABI();167  if (ABIName == "ilp32f" || ABIName == "lp64f")168    Builder.defineMacro("__riscv_float_abi_single");169  else if (ABIName == "ilp32d" || ABIName == "lp64d")170    Builder.defineMacro("__riscv_float_abi_double");171  else172    Builder.defineMacro("__riscv_float_abi_soft");173 174  if (ABIName == "ilp32e" || ABIName == "lp64e")175    Builder.defineMacro("__riscv_abi_rve");176 177  Builder.defineMacro("__riscv_arch_test");178 179  for (auto &Extension : ISAInfo->getExtensions()) {180    auto ExtName = Extension.first;181    auto ExtInfo = Extension.second;182 183    Builder.defineMacro(Twine("__riscv_", ExtName),184                        Twine(getVersionValue(ExtInfo.Major, ExtInfo.Minor)));185  }186 187  if (ISAInfo->hasExtension("zmmul"))188    Builder.defineMacro("__riscv_mul");189 190  if (ISAInfo->hasExtension("m")) {191    Builder.defineMacro("__riscv_div");192    Builder.defineMacro("__riscv_muldiv");193  }194 195  // The "a" extension is composed of "zalrsc" and "zaamo"196  if (ISAInfo->hasExtension("a"))197    Builder.defineMacro("__riscv_atomic");198 199  if (ISAInfo->hasExtension("zalrsc")) {200    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");201    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");202    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");203    if (Is64Bit)204      Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");205  }206 207  if (FLen) {208    Builder.defineMacro("__riscv_flen", Twine(FLen));209    Builder.defineMacro("__riscv_fdiv");210    Builder.defineMacro("__riscv_fsqrt");211  }212 213  if (MinVLen) {214    Builder.defineMacro("__riscv_v_min_vlen", Twine(MinVLen));215    Builder.defineMacro("__riscv_v_elen", Twine(MaxELen));216    Builder.defineMacro("__riscv_v_elen_fp", Twine(MaxELenFp));217  }218 219  if (ISAInfo->hasExtension("c"))220    Builder.defineMacro("__riscv_compressed");221 222  if (ISAInfo->hasExtension("zve32x"))223    Builder.defineMacro("__riscv_vector");224 225  // Currently we support the v1.0 RISC-V V intrinsics.226  Builder.defineMacro("__riscv_v_intrinsic", Twine(getVersionValue(1, 0)));227 228  auto VScale = getVScaleRange(Opts, ArmStreamingKind::NotStreaming);229  if (VScale && VScale->first && VScale->first == VScale->second)230    Builder.defineMacro("__riscv_v_fixed_vlen",231                        Twine(VScale->first * llvm::RISCV::RVVBitsPerBlock));232 233  if (FastScalarUnalignedAccess)234    Builder.defineMacro("__riscv_misaligned_fast");235  else236    Builder.defineMacro("__riscv_misaligned_avoid");237 238  if (ISAInfo->hasExtension("e")) {239    if (Is64Bit)240      Builder.defineMacro("__riscv_64e");241    else242      Builder.defineMacro("__riscv_32e");243  }244 245  if (Opts.CFProtectionReturn && ISAInfo->hasExtension("zicfiss"))246    Builder.defineMacro("__riscv_shadow_stack");247 248  if (Opts.CFProtectionBranch) {249    auto Scheme = Opts.getCFBranchLabelScheme();250    if (Scheme == CFBranchLabelSchemeKind::Default)251      Scheme = getDefaultCFBranchLabelScheme();252 253    Builder.defineMacro("__riscv_landing_pad");254    switch (Scheme) {255    case CFBranchLabelSchemeKind::Unlabeled:256      Builder.defineMacro("__riscv_landing_pad_unlabeled");257      break;258    case CFBranchLabelSchemeKind::FuncSig:259      // TODO: Define macros after the func-sig scheme is implemented260      break;261    case CFBranchLabelSchemeKind::Default:262      llvm_unreachable("default cf-branch-label scheme should already be "263                       "transformed to other scheme");264    }265  }266}267 268static constexpr int NumRVVBuiltins =269    RISCVVector::FirstSiFiveBuiltin - Builtin::FirstTSBuiltin;270static constexpr int NumRVVSiFiveBuiltins =271    RISCVVector::FirstAndesBuiltin - RISCVVector::FirstSiFiveBuiltin;272static constexpr int NumRVVAndesBuiltins =273    RISCVVector::FirstTSBuiltin - RISCVVector::FirstAndesBuiltin;274static constexpr int NumRISCVBuiltins =275    RISCV::LastTSBuiltin - RISCVVector::FirstTSBuiltin;276static constexpr int NumBuiltins =277    RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin;278static_assert(NumBuiltins == (NumRVVBuiltins + NumRVVSiFiveBuiltins +279                              NumRVVAndesBuiltins + NumRISCVBuiltins));280 281namespace RVV {282#define GET_RISCVV_BUILTIN_STR_TABLE283#include "clang/Basic/riscv_vector_builtins.inc"284#undef GET_RISCVV_BUILTIN_STR_TABLE285static_assert(BuiltinStrings.size() < 100'000);286 287static constexpr std::array<Builtin::Info, NumRVVBuiltins> BuiltinInfos = {288#define GET_RISCVV_BUILTIN_INFOS289#include "clang/Basic/riscv_vector_builtins.inc"290#undef GET_RISCVV_BUILTIN_INFOS291};292} // namespace RVV293 294namespace RVVSiFive {295#define GET_RISCVV_BUILTIN_STR_TABLE296#include "clang/Basic/riscv_sifive_vector_builtins.inc"297#undef GET_RISCVV_BUILTIN_STR_TABLE298 299static constexpr std::array<Builtin::Info, NumRVVSiFiveBuiltins> BuiltinInfos =300    {301#define GET_RISCVV_BUILTIN_INFOS302#include "clang/Basic/riscv_sifive_vector_builtins.inc"303#undef GET_RISCVV_BUILTIN_INFOS304};305} // namespace RVVSiFive306 307namespace RVVAndes {308#define GET_RISCVV_BUILTIN_STR_TABLE309#include "clang/Basic/riscv_andes_vector_builtins.inc"310#undef GET_RISCVV_BUILTIN_STR_TABLE311 312static constexpr std::array<Builtin::Info, NumRVVAndesBuiltins> BuiltinInfos =313    {314#define GET_RISCVV_BUILTIN_INFOS315#include "clang/Basic/riscv_andes_vector_builtins.inc"316#undef GET_RISCVV_BUILTIN_INFOS317};318} // namespace RVVAndes319 320#define GET_BUILTIN_STR_TABLE321#include "clang/Basic/BuiltinsRISCV.inc"322#undef GET_BUILTIN_STR_TABLE323 324static constexpr Builtin::Info BuiltinInfos[] = {325#define GET_BUILTIN_INFOS326#include "clang/Basic/BuiltinsRISCV.inc"327#undef GET_BUILTIN_INFOS328};329static_assert(std::size(BuiltinInfos) == NumRISCVBuiltins);330 331llvm::SmallVector<Builtin::InfosShard>332RISCVTargetInfo::getTargetBuiltins() const {333  return {334      {&RVV::BuiltinStrings, RVV::BuiltinInfos, "__builtin_rvv_"},335      {&RVVSiFive::BuiltinStrings, RVVSiFive::BuiltinInfos, "__builtin_rvv_"},336      {&RVVAndes::BuiltinStrings, RVVAndes::BuiltinInfos, "__builtin_rvv_"},337      {&BuiltinStrings, BuiltinInfos},338  };339}340 341bool RISCVTargetInfo::initFeatureMap(342    llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,343    const std::vector<std::string> &FeaturesVec) const {344 345  unsigned XLen = 32;346 347  if (getTriple().isRISCV64()) {348    Features["64bit"] = true;349    XLen = 64;350  } else {351    Features["32bit"] = true;352  }353 354  std::vector<std::string> AllFeatures = FeaturesVec;355  auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec);356  if (!ParseResult) {357    std::string Buffer;358    llvm::raw_string_ostream OutputErrMsg(Buffer);359    handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {360      OutputErrMsg << ErrMsg.getMessage();361    });362    Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();363    return false;364  }365 366  // Append all features, not just new ones, so we override any negatives.367  llvm::append_range(AllFeatures, (*ParseResult)->toFeatures());368  return TargetInfo::initFeatureMap(Features, Diags, CPU, AllFeatures);369}370 371std::optional<std::pair<unsigned, unsigned>>372RISCVTargetInfo::getVScaleRange(const LangOptions &LangOpts,373                                ArmStreamingKind IsArmStreamingFunction,374                                llvm::StringMap<bool> *FeatureMap) const {375  // RISCV::RVVBitsPerBlock is 64.376  unsigned VScaleMin = ISAInfo->getMinVLen() / llvm::RISCV::RVVBitsPerBlock;377 378  if (LangOpts.VScaleMin || LangOpts.VScaleMax) {379    // Treat Zvl*b as a lower bound on vscale.380    VScaleMin = std::max(VScaleMin, LangOpts.VScaleMin);381    unsigned VScaleMax = LangOpts.VScaleMax;382    if (VScaleMax != 0 && VScaleMax < VScaleMin)383      VScaleMax = VScaleMin;384    return std::pair<unsigned, unsigned>(VScaleMin ? VScaleMin : 1, VScaleMax);385  }386 387  if (VScaleMin > 0) {388    unsigned VScaleMax = ISAInfo->getMaxVLen() / llvm::RISCV::RVVBitsPerBlock;389    return std::make_pair(VScaleMin, VScaleMax);390  }391 392  return std::nullopt;393}394 395/// Return true if has this feature, need to sync with handleTargetFeatures.396bool RISCVTargetInfo::hasFeature(StringRef Feature) const {397  bool Is64Bit = getTriple().isRISCV64();398  auto Result = llvm::StringSwitch<std::optional<bool>>(Feature)399                    .Case("riscv", true)400                    .Case("riscv32", !Is64Bit)401                    .Case("riscv64", Is64Bit)402                    .Case("32bit", !Is64Bit)403                    .Case("64bit", Is64Bit)404                    .Case("experimental", HasExperimental)405                    .Default(std::nullopt);406  if (Result)407    return *Result;408 409  return ISAInfo->hasExtension(Feature);410}411 412/// Perform initialization based on the user configured set of features.413bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,414                                           DiagnosticsEngine &Diags) {415  unsigned XLen = getTriple().isArch64Bit() ? 64 : 32;416  auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);417  if (!ParseResult) {418    std::string Buffer;419    llvm::raw_string_ostream OutputErrMsg(Buffer);420    handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {421      OutputErrMsg << ErrMsg.getMessage();422    });423    Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();424    return false;425  } else {426    ISAInfo = std::move(*ParseResult);427  }428 429  if (ABI.empty())430    ABI = ISAInfo->computeDefaultABI().str();431 432  if (ISAInfo->hasExtension("zfh") || ISAInfo->hasExtension("zhinx"))433    HasFastHalfType = true;434 435  FastScalarUnalignedAccess =436      llvm::is_contained(Features, "+unaligned-scalar-mem");437 438  if (llvm::is_contained(Features, "+experimental"))439    HasExperimental = true;440 441  if (ABI == "ilp32e" && ISAInfo->hasExtension("d")) {442    Diags.Report(diag::err_invalid_feature_combination)443        << "ILP32E cannot be used with the D ISA extension";444    return false;445  }446  return true;447}448 449bool RISCVTargetInfo::isValidCPUName(StringRef Name) const {450  bool Is64Bit = getTriple().isArch64Bit();451  return llvm::RISCV::parseCPU(Name, Is64Bit);452}453 454void RISCVTargetInfo::fillValidCPUList(455    SmallVectorImpl<StringRef> &Values) const {456  bool Is64Bit = getTriple().isArch64Bit();457  llvm::RISCV::fillValidCPUArchList(Values, Is64Bit);458}459 460bool RISCVTargetInfo::isValidTuneCPUName(StringRef Name) const {461  bool Is64Bit = getTriple().isArch64Bit();462  return llvm::RISCV::parseTuneCPU(Name, Is64Bit);463}464 465void RISCVTargetInfo::fillValidTuneCPUList(466    SmallVectorImpl<StringRef> &Values) const {467  bool Is64Bit = getTriple().isArch64Bit();468  llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit);469}470 471static void populateNegativeRISCVFeatures(std::vector<std::string> &Features) {472  auto RII = llvm::RISCVISAInfo::parseArchString(473      "rv64i", /* EnableExperimentalExtension */ true);474 475  if (llvm::errorToBool(RII.takeError()))476    llvm_unreachable("unsupport rv64i");477 478  std::vector<std::string> FeatStrings =479      (*RII)->toFeatures(/* AddAllExtensions */ true);480  llvm::append_range(Features, FeatStrings);481}482 483static void handleFullArchString(StringRef FullArchStr,484                                 std::vector<std::string> &Features) {485  auto RII = llvm::RISCVISAInfo::parseArchString(486      FullArchStr, /* EnableExperimentalExtension */ true);487  if (llvm::errorToBool(RII.takeError())) {488    // Forward the invalid FullArchStr.489    Features.push_back(FullArchStr.str());490  } else {491    // Append a full list of features, including any negative extensions so that492    // we override the CPU's features.493    populateNegativeRISCVFeatures(Features);494    std::vector<std::string> FeatStrings =495        (*RII)->toFeatures(/* AddAllExtensions */ true);496    llvm::append_range(Features, FeatStrings);497  }498}499 500ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const {501  ParsedTargetAttr Ret;502  if (Features == "default")503    return Ret;504  SmallVector<StringRef, 1> AttrFeatures;505  Features.split(AttrFeatures, ";");506  bool FoundArch = false;507 508  auto handleArchExtension = [](StringRef AttrString,509                                std::vector<std::string> &Features) {510    SmallVector<StringRef, 1> Exts;511    AttrString.split(Exts, ",");512    for (auto Ext : Exts) {513      if (Ext.empty())514        continue;515 516      StringRef ExtName = Ext.substr(1);517      std::string TargetFeature =518          llvm::RISCVISAInfo::getTargetFeatureForExtension(ExtName);519      if (!TargetFeature.empty())520        Features.push_back(Ext.front() + TargetFeature);521      else522        Features.push_back(Ext.str());523    }524  };525 526  for (auto &Feature : AttrFeatures) {527    Feature = Feature.trim();528    StringRef AttrString = Feature.split("=").second.trim();529 530    if (Feature.starts_with("arch=")) {531      // Override last features532      Ret.Features.clear();533      if (FoundArch)534        Ret.Duplicate = "arch=";535      FoundArch = true;536 537      if (AttrString.starts_with("+")) {538        // EXTENSION like arch=+v,+zbb539        handleArchExtension(AttrString, Ret.Features);540      } else {541        // full-arch-string like arch=rv64gcv542        handleFullArchString(AttrString, Ret.Features);543      }544    } else if (Feature.starts_with("cpu=")) {545      if (!Ret.CPU.empty())546        Ret.Duplicate = "cpu=";547 548      Ret.CPU = AttrString;549 550      if (!FoundArch) {551        // Update Features with CPU's features552        StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(Ret.CPU);553        if (MarchFromCPU != "") {554          Ret.Features.clear();555          handleFullArchString(MarchFromCPU, Ret.Features);556        }557      }558    } else if (Feature.starts_with("tune=")) {559      if (!Ret.Tune.empty())560        Ret.Duplicate = "tune=";561 562      Ret.Tune = AttrString;563    } else if (Feature.starts_with("priority")) {564      // Skip because it only use for FMV.565    } else if (Feature.starts_with("+")) {566      // Handle target_version/target_clones attribute strings567      // that are already delimited by ','568      handleArchExtension(Feature, Ret.Features);569    }570  }571  return Ret;572}573 574llvm::APInt575RISCVTargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const {576  // Priority is explicitly specified on RISC-V unlike on other targets, where577  // it is derived by all the features of a specific version. Therefore if a578  // feature contains the priority string, then return it immediately.579  for (StringRef Feature : Features) {580    auto [LHS, RHS] = Feature.rsplit(';');581    if (LHS.consume_front("priority="))582      Feature = LHS;583    else if (RHS.consume_front("priority="))584      Feature = RHS;585    else586      continue;587    unsigned Priority;588    if (!Feature.getAsInteger(0, Priority))589      return llvm::APInt(32, Priority);590  }591  // Default Priority is zero.592  return llvm::APInt::getZero(32);593}594 595TargetInfo::CallingConvCheckResult596RISCVTargetInfo::checkCallingConvention(CallingConv CC) const {597  switch (CC) {598  default:599    return CCCR_Warning;600  case CC_C:601  case CC_RISCVVectorCall:602  case CC_RISCVVLSCall_32:603  case CC_RISCVVLSCall_64:604  case CC_RISCVVLSCall_128:605  case CC_RISCVVLSCall_256:606  case CC_RISCVVLSCall_512:607  case CC_RISCVVLSCall_1024:608  case CC_RISCVVLSCall_2048:609  case CC_RISCVVLSCall_4096:610  case CC_RISCVVLSCall_8192:611  case CC_RISCVVLSCall_16384:612  case CC_RISCVVLSCall_32768:613  case CC_RISCVVLSCall_65536:614    return CCCR_OK;615  }616}617 618bool RISCVTargetInfo::validateCpuSupports(StringRef Feature) const {619  // Only allow extensions we have a known bit position for in the620  // __riscv_feature_bits structure.621  return -1 != llvm::RISCVISAInfo::getRISCVFeaturesBitsInfo(Feature).second;622}623 624bool RISCVTargetInfo::isValidFeatureName(StringRef Name) const {625  return llvm::RISCVISAInfo::isSupportedExtensionFeature(Name);626}627 628bool RISCVTargetInfo::validateGlobalRegisterVariable(629    StringRef RegName, unsigned RegSize, bool &HasSizeMismatch) const {630  if (RegName == "ra" || RegName == "sp" || RegName == "gp" ||631      RegName == "tp" || RegName.starts_with("x") || RegName.starts_with("a") ||632      RegName.starts_with("s") || RegName.starts_with("t")) {633    unsigned XLen = getTriple().isArch64Bit() ? 64 : 32;634    HasSizeMismatch = RegSize != XLen;635    return true;636  }637  return false;638}639 640bool RISCVTargetInfo::validateCpuIs(StringRef CPUName) const {641  assert(getTriple().isOSLinux() &&642         "__builtin_cpu_is() is only supported for Linux.");643 644  return llvm::RISCV::hasValidCPUModel(CPUName);645}646