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-exception 6 // 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 22 using namespace clang; 23 using namespace clang::targets; 24 25 ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const { 26 // clang-format off 27 static const char *const GCCRegNames[] = { 28 // Integer registers 29 "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 registers 35 "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 registers 41 "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 // CSRs 47 "fflags", "frm", "vtype", "vl", "vxsat", "vxrm", "sf.vcix_state" 48 }; 49 // clang-format on 50 return llvm::ArrayRef(GCCRegNames); 51 } 52 53 ArrayRef<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 74 bool 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 offset 101 Info.setAllowsRegister(); 102 return true; 103 case 'c': 104 // A RVC register - GPR or FPR 105 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 pair 113 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 126 std::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 142 static unsigned getVersionValue(unsigned MajorVersion, unsigned MinorVersion) { 143 return MajorVersion * 1000000 + MinorVersion * 1000; 144 } 145 146 void 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 else 172 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 if (ISAInfo->hasExtension("a")) { 196 Builder.defineMacro("__riscv_atomic"); 197 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); 198 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); 199 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); 200 if (Is64Bit) 201 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); 202 } 203 204 if (FLen) { 205 Builder.defineMacro("__riscv_flen", Twine(FLen)); 206 Builder.defineMacro("__riscv_fdiv"); 207 Builder.defineMacro("__riscv_fsqrt"); 208 } 209 210 if (MinVLen) { 211 Builder.defineMacro("__riscv_v_min_vlen", Twine(MinVLen)); 212 Builder.defineMacro("__riscv_v_elen", Twine(MaxELen)); 213 Builder.defineMacro("__riscv_v_elen_fp", Twine(MaxELenFp)); 214 } 215 216 if (ISAInfo->hasExtension("c")) 217 Builder.defineMacro("__riscv_compressed"); 218 219 if (ISAInfo->hasExtension("zve32x")) 220 Builder.defineMacro("__riscv_vector"); 221 222 // Currently we support the v1.0 RISC-V V intrinsics. 223 Builder.defineMacro("__riscv_v_intrinsic", Twine(getVersionValue(1, 0))); 224 225 auto VScale = getVScaleRange(Opts, ArmStreamingKind::NotStreaming); 226 if (VScale && VScale->first && VScale->first == VScale->second) 227 Builder.defineMacro("__riscv_v_fixed_vlen", 228 Twine(VScale->first * llvm::RISCV::RVVBitsPerBlock)); 229 230 if (FastScalarUnalignedAccess) 231 Builder.defineMacro("__riscv_misaligned_fast"); 232 else 233 Builder.defineMacro("__riscv_misaligned_avoid"); 234 235 if (ISAInfo->hasExtension("e")) { 236 if (Is64Bit) 237 Builder.defineMacro("__riscv_64e"); 238 else 239 Builder.defineMacro("__riscv_32e"); 240 } 241 242 if (Opts.CFProtectionReturn && ISAInfo->hasExtension("zicfiss")) 243 Builder.defineMacro("__riscv_shadow_stack"); 244 245 if (Opts.CFProtectionBranch) { 246 auto Scheme = Opts.getCFBranchLabelScheme(); 247 if (Scheme == CFBranchLabelSchemeKind::Default) 248 Scheme = getDefaultCFBranchLabelScheme(); 249 250 Builder.defineMacro("__riscv_landing_pad"); 251 switch (Scheme) { 252 case CFBranchLabelSchemeKind::Unlabeled: 253 Builder.defineMacro("__riscv_landing_pad_unlabeled"); 254 break; 255 case CFBranchLabelSchemeKind::FuncSig: 256 // TODO: Define macros after the func-sig scheme is implemented 257 break; 258 case CFBranchLabelSchemeKind::Default: 259 llvm_unreachable("default cf-branch-label scheme should already be " 260 "transformed to other scheme"); 261 } 262 } 263 } 264 265 static constexpr int NumRVVBuiltins = 266 RISCVVector::FirstSiFiveBuiltin - Builtin::FirstTSBuiltin; 267 static constexpr int NumRVVSiFiveBuiltins = 268 RISCVVector::FirstAndesBuiltin - RISCVVector::FirstSiFiveBuiltin; 269 static constexpr int NumRVVAndesBuiltins = 270 RISCVVector::FirstTSBuiltin - RISCVVector::FirstAndesBuiltin; 271 static constexpr int NumRISCVBuiltins = 272 RISCV::LastTSBuiltin - RISCVVector::FirstTSBuiltin; 273 static constexpr int NumBuiltins = 274 RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin; 275 static_assert(NumBuiltins == (NumRVVBuiltins + NumRVVSiFiveBuiltins + 276 NumRVVAndesBuiltins + NumRISCVBuiltins)); 277 278 namespace RVV { 279 #define GET_RISCVV_BUILTIN_STR_TABLE 280 #include "clang/Basic/riscv_vector_builtins.inc" 281 #undef GET_RISCVV_BUILTIN_STR_TABLE 282 static_assert(BuiltinStrings.size() < 100'000); 283 284 static constexpr std::array<Builtin::Info, NumRVVBuiltins> BuiltinInfos = { 285 #define GET_RISCVV_BUILTIN_INFOS 286 #include "clang/Basic/riscv_vector_builtins.inc" 287 #undef GET_RISCVV_BUILTIN_INFOS 288 }; 289 } // namespace RVV 290 291 namespace RVVSiFive { 292 #define GET_RISCVV_BUILTIN_STR_TABLE 293 #include "clang/Basic/riscv_sifive_vector_builtins.inc" 294 #undef GET_RISCVV_BUILTIN_STR_TABLE 295 296 static constexpr std::array<Builtin::Info, NumRVVSiFiveBuiltins> BuiltinInfos = 297 { 298 #define GET_RISCVV_BUILTIN_INFOS 299 #include "clang/Basic/riscv_sifive_vector_builtins.inc" 300 #undef GET_RISCVV_BUILTIN_INFOS 301 }; 302 } // namespace RVVSiFive 303 304 namespace RVVAndes { 305 #define GET_RISCVV_BUILTIN_STR_TABLE 306 #include "clang/Basic/riscv_andes_vector_builtins.inc" 307 #undef GET_RISCVV_BUILTIN_STR_TABLE 308 309 static constexpr std::array<Builtin::Info, NumRVVAndesBuiltins> BuiltinInfos = 310 { 311 #define GET_RISCVV_BUILTIN_INFOS 312 #include "clang/Basic/riscv_andes_vector_builtins.inc" 313 #undef GET_RISCVV_BUILTIN_INFOS 314 }; 315 } // namespace RVVAndes 316 317 #define GET_BUILTIN_STR_TABLE 318 #include "clang/Basic/BuiltinsRISCV.inc" 319 #undef GET_BUILTIN_STR_TABLE 320 321 static constexpr Builtin::Info BuiltinInfos[] = { 322 #define GET_BUILTIN_INFOS 323 #include "clang/Basic/BuiltinsRISCV.inc" 324 #undef GET_BUILTIN_INFOS 325 }; 326 static_assert(std::size(BuiltinInfos) == NumRISCVBuiltins); 327 328 llvm::SmallVector<Builtin::InfosShard> 329 RISCVTargetInfo::getTargetBuiltins() const { 330 return { 331 {&RVV::BuiltinStrings, RVV::BuiltinInfos, "__builtin_rvv_"}, 332 {&RVVSiFive::BuiltinStrings, RVVSiFive::BuiltinInfos, "__builtin_rvv_"}, 333 {&RVVAndes::BuiltinStrings, RVVAndes::BuiltinInfos, "__builtin_rvv_"}, 334 {&BuiltinStrings, BuiltinInfos}, 335 }; 336 } 337 338 bool RISCVTargetInfo::initFeatureMap( 339 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, 340 const std::vector<std::string> &FeaturesVec) const { 341 342 unsigned XLen = 32; 343 344 if (getTriple().isRISCV64()) { 345 Features["64bit"] = true; 346 XLen = 64; 347 } else { 348 Features["32bit"] = true; 349 } 350 351 std::vector<std::string> AllFeatures = FeaturesVec; 352 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec); 353 if (!ParseResult) { 354 std::string Buffer; 355 llvm::raw_string_ostream OutputErrMsg(Buffer); 356 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) { 357 OutputErrMsg << ErrMsg.getMessage(); 358 }); 359 Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str(); 360 return false; 361 } 362 363 // Append all features, not just new ones, so we override any negatives. 364 llvm::append_range(AllFeatures, (*ParseResult)->toFeatures()); 365 return TargetInfo::initFeatureMap(Features, Diags, CPU, AllFeatures); 366 } 367 368 std::optional<std::pair<unsigned, unsigned>> 369 RISCVTargetInfo::getVScaleRange(const LangOptions &LangOpts, 370 ArmStreamingKind IsArmStreamingFunction, 371 llvm::StringMap<bool> *FeatureMap) const { 372 // RISCV::RVVBitsPerBlock is 64. 373 unsigned VScaleMin = ISAInfo->getMinVLen() / llvm::RISCV::RVVBitsPerBlock; 374 375 if (LangOpts.VScaleMin || LangOpts.VScaleMax) { 376 // Treat Zvl*b as a lower bound on vscale. 377 VScaleMin = std::max(VScaleMin, LangOpts.VScaleMin); 378 unsigned VScaleMax = LangOpts.VScaleMax; 379 if (VScaleMax != 0 && VScaleMax < VScaleMin) 380 VScaleMax = VScaleMin; 381 return std::pair<unsigned, unsigned>(VScaleMin ? VScaleMin : 1, VScaleMax); 382 } 383 384 if (VScaleMin > 0) { 385 unsigned VScaleMax = ISAInfo->getMaxVLen() / llvm::RISCV::RVVBitsPerBlock; 386 return std::make_pair(VScaleMin, VScaleMax); 387 } 388 389 return std::nullopt; 390 } 391 392 /// Return true if has this feature, need to sync with handleTargetFeatures. 393 bool RISCVTargetInfo::hasFeature(StringRef Feature) const { 394 bool Is64Bit = getTriple().isRISCV64(); 395 auto Result = llvm::StringSwitch<std::optional<bool>>(Feature) 396 .Case("riscv", true) 397 .Case("riscv32", !Is64Bit) 398 .Case("riscv64", Is64Bit) 399 .Case("32bit", !Is64Bit) 400 .Case("64bit", Is64Bit) 401 .Case("experimental", HasExperimental) 402 .Default(std::nullopt); 403 if (Result) 404 return *Result; 405 406 return ISAInfo->hasExtension(Feature); 407 } 408 409 /// Perform initialization based on the user configured set of features. 410 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, 411 DiagnosticsEngine &Diags) { 412 unsigned XLen = getTriple().isArch64Bit() ? 64 : 32; 413 auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features); 414 if (!ParseResult) { 415 std::string Buffer; 416 llvm::raw_string_ostream OutputErrMsg(Buffer); 417 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) { 418 OutputErrMsg << ErrMsg.getMessage(); 419 }); 420 Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str(); 421 return false; 422 } else { 423 ISAInfo = std::move(*ParseResult); 424 } 425 426 if (ABI.empty()) 427 ABI = ISAInfo->computeDefaultABI().str(); 428 429 if (ISAInfo->hasExtension("zfh") || ISAInfo->hasExtension("zhinx")) 430 HasLegalHalfType = true; 431 432 FastScalarUnalignedAccess = 433 llvm::is_contained(Features, "+unaligned-scalar-mem"); 434 435 if (llvm::is_contained(Features, "+experimental")) 436 HasExperimental = true; 437 438 if (ABI == "ilp32e" && ISAInfo->hasExtension("d")) { 439 Diags.Report(diag::err_invalid_feature_combination) 440 << "ILP32E cannot be used with the D ISA extension"; 441 return false; 442 } 443 return true; 444 } 445 446 bool RISCVTargetInfo::isValidCPUName(StringRef Name) const { 447 bool Is64Bit = getTriple().isArch64Bit(); 448 return llvm::RISCV::parseCPU(Name, Is64Bit); 449 } 450 451 void RISCVTargetInfo::fillValidCPUList( 452 SmallVectorImpl<StringRef> &Values) const { 453 bool Is64Bit = getTriple().isArch64Bit(); 454 llvm::RISCV::fillValidCPUArchList(Values, Is64Bit); 455 } 456 457 bool RISCVTargetInfo::isValidTuneCPUName(StringRef Name) const { 458 bool Is64Bit = getTriple().isArch64Bit(); 459 return llvm::RISCV::parseTuneCPU(Name, Is64Bit); 460 } 461 462 void RISCVTargetInfo::fillValidTuneCPUList( 463 SmallVectorImpl<StringRef> &Values) const { 464 bool Is64Bit = getTriple().isArch64Bit(); 465 llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit); 466 } 467 468 static void populateNegativeRISCVFeatures(std::vector<std::string> &Features) { 469 auto RII = llvm::RISCVISAInfo::parseArchString( 470 "rv64i", /* EnableExperimentalExtension */ true); 471 472 if (llvm::errorToBool(RII.takeError())) 473 llvm_unreachable("unsupport rv64i"); 474 475 std::vector<std::string> FeatStrings = 476 (*RII)->toFeatures(/* AddAllExtensions */ true); 477 llvm::append_range(Features, FeatStrings); 478 } 479 480 static void handleFullArchString(StringRef FullArchStr, 481 std::vector<std::string> &Features) { 482 auto RII = llvm::RISCVISAInfo::parseArchString( 483 FullArchStr, /* EnableExperimentalExtension */ true); 484 if (llvm::errorToBool(RII.takeError())) { 485 // Forward the invalid FullArchStr. 486 Features.push_back(FullArchStr.str()); 487 } else { 488 // Append a full list of features, including any negative extensions so that 489 // we override the CPU's features. 490 populateNegativeRISCVFeatures(Features); 491 std::vector<std::string> FeatStrings = 492 (*RII)->toFeatures(/* AddAllExtensions */ true); 493 llvm::append_range(Features, FeatStrings); 494 } 495 } 496 497 ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const { 498 ParsedTargetAttr Ret; 499 if (Features == "default") 500 return Ret; 501 SmallVector<StringRef, 1> AttrFeatures; 502 Features.split(AttrFeatures, ";"); 503 bool FoundArch = false; 504 505 auto handleArchExtension = [](StringRef AttrString, 506 std::vector<std::string> &Features) { 507 SmallVector<StringRef, 1> Exts; 508 AttrString.split(Exts, ","); 509 for (auto Ext : Exts) { 510 if (Ext.empty()) 511 continue; 512 513 StringRef ExtName = Ext.substr(1); 514 std::string TargetFeature = 515 llvm::RISCVISAInfo::getTargetFeatureForExtension(ExtName); 516 if (!TargetFeature.empty()) 517 Features.push_back(Ext.front() + TargetFeature); 518 else 519 Features.push_back(Ext.str()); 520 } 521 }; 522 523 for (auto &Feature : AttrFeatures) { 524 Feature = Feature.trim(); 525 StringRef AttrString = Feature.split("=").second.trim(); 526 527 if (Feature.starts_with("arch=")) { 528 // Override last features 529 Ret.Features.clear(); 530 if (FoundArch) 531 Ret.Duplicate = "arch="; 532 FoundArch = true; 533 534 if (AttrString.starts_with("+")) { 535 // EXTENSION like arch=+v,+zbb 536 handleArchExtension(AttrString, Ret.Features); 537 } else { 538 // full-arch-string like arch=rv64gcv 539 handleFullArchString(AttrString, Ret.Features); 540 } 541 } else if (Feature.starts_with("cpu=")) { 542 if (!Ret.CPU.empty()) 543 Ret.Duplicate = "cpu="; 544 545 Ret.CPU = AttrString; 546 547 if (!FoundArch) { 548 // Update Features with CPU's features 549 StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(Ret.CPU); 550 if (MarchFromCPU != "") { 551 Ret.Features.clear(); 552 handleFullArchString(MarchFromCPU, Ret.Features); 553 } 554 } 555 } else if (Feature.starts_with("tune=")) { 556 if (!Ret.Tune.empty()) 557 Ret.Duplicate = "tune="; 558 559 Ret.Tune = AttrString; 560 } else if (Feature.starts_with("priority")) { 561 // Skip because it only use for FMV. 562 } else if (Feature.starts_with("+")) { 563 // Handle target_version/target_clones attribute strings 564 // that are already delimited by ',' 565 handleArchExtension(Feature, Ret.Features); 566 } 567 } 568 return Ret; 569 } 570 571 uint64_t RISCVTargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const { 572 // Priority is explicitly specified on RISC-V unlike on other targets, where 573 // it is derived by all the features of a specific version. Therefore if a 574 // feature contains the priority string, then return it immediately. 575 for (StringRef Feature : Features) { 576 auto [LHS, RHS] = Feature.rsplit(';'); 577 if (LHS.consume_front("priority=")) 578 Feature = LHS; 579 else if (RHS.consume_front("priority=")) 580 Feature = RHS; 581 else 582 continue; 583 uint64_t Priority; 584 if (!Feature.getAsInteger(0, Priority)) 585 return Priority; 586 } 587 // Default Priority is zero. 588 return 0; 589 } 590 591 TargetInfo::CallingConvCheckResult 592 RISCVTargetInfo::checkCallingConvention(CallingConv CC) const { 593 switch (CC) { 594 default: 595 return CCCR_Warning; 596 case CC_C: 597 case CC_RISCVVectorCall: 598 case CC_RISCVVLSCall_32: 599 case CC_RISCVVLSCall_64: 600 case CC_RISCVVLSCall_128: 601 case CC_RISCVVLSCall_256: 602 case CC_RISCVVLSCall_512: 603 case CC_RISCVVLSCall_1024: 604 case CC_RISCVVLSCall_2048: 605 case CC_RISCVVLSCall_4096: 606 case CC_RISCVVLSCall_8192: 607 case CC_RISCVVLSCall_16384: 608 case CC_RISCVVLSCall_32768: 609 case CC_RISCVVLSCall_65536: 610 return CCCR_OK; 611 } 612 } 613 614 bool RISCVTargetInfo::validateCpuSupports(StringRef Feature) const { 615 // Only allow extensions we have a known bit position for in the 616 // __riscv_feature_bits structure. 617 return -1 != llvm::RISCVISAInfo::getRISCVFeaturesBitsInfo(Feature).second; 618 } 619 620 bool RISCVTargetInfo::isValidFeatureName(StringRef Name) const { 621 return llvm::RISCVISAInfo::isSupportedExtensionFeature(Name); 622 } 623 624 bool RISCVTargetInfo::validateGlobalRegisterVariable( 625 StringRef RegName, unsigned RegSize, bool &HasSizeMismatch) const { 626 if (RegName == "ra" || RegName == "sp" || RegName == "gp" || 627 RegName == "tp" || RegName.starts_with("x") || RegName.starts_with("a") || 628 RegName.starts_with("s") || RegName.starts_with("t")) { 629 unsigned XLen = getTriple().isArch64Bit() ? 64 : 32; 630 HasSizeMismatch = RegSize != XLen; 631 return true; 632 } 633 return false; 634 } 635 636 bool RISCVTargetInfo::validateCpuIs(StringRef CPUName) const { 637 assert(getTriple().isOSLinux() && 638 "__builtin_cpu_is() is only supported for Linux."); 639 640 return llvm::RISCV::hasValidCPUModel(CPUName); 641 } 642