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