xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Targets/RISCV.cpp (revision e64bea71c21eb42e97aa615188ba91f6cce0d36d)
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