1 //===-- RISCVISAInfo.cpp - RISCV Arch String Parser --------------===//
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 #include "llvm/Support/RISCVISAInfo.h"
10 #include "llvm/ADT/None.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/SetVector.h"
13 #include "llvm/ADT/StringExtras.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/Support/Errc.h"
16 #include "llvm/Support/Error.h"
17 #include "llvm/Support/raw_ostream.h"
18
19 #include <array>
20 #include <string>
21 #include <vector>
22
23 using namespace llvm;
24
25 namespace {
26 /// Represents the major and version number components of a RISC-V extension
27 struct RISCVExtensionVersion {
28 unsigned Major;
29 unsigned Minor;
30 };
31
32 struct RISCVSupportedExtension {
33 const char *Name;
34 /// Supported version.
35 RISCVExtensionVersion Version;
36 };
37
38 } // end anonymous namespace
39
40 static constexpr StringLiteral AllStdExts = "mafdqlcbkjtpvn";
41
42 static const RISCVSupportedExtension SupportedExtensions[] = {
43 {"i", RISCVExtensionVersion{2, 0}},
44 {"e", RISCVExtensionVersion{1, 9}},
45 {"m", RISCVExtensionVersion{2, 0}},
46 {"a", RISCVExtensionVersion{2, 0}},
47 {"f", RISCVExtensionVersion{2, 0}},
48 {"d", RISCVExtensionVersion{2, 0}},
49 {"c", RISCVExtensionVersion{2, 0}},
50
51 {"zihintpause", RISCVExtensionVersion{2, 0}},
52
53 {"zfhmin", RISCVExtensionVersion{1, 0}},
54 {"zfh", RISCVExtensionVersion{1, 0}},
55
56 {"zfinx", RISCVExtensionVersion{1, 0}},
57 {"zdinx", RISCVExtensionVersion{1, 0}},
58 {"zhinxmin", RISCVExtensionVersion{1, 0}},
59 {"zhinx", RISCVExtensionVersion{1, 0}},
60
61 {"zba", RISCVExtensionVersion{1, 0}},
62 {"zbb", RISCVExtensionVersion{1, 0}},
63 {"zbc", RISCVExtensionVersion{1, 0}},
64 {"zbs", RISCVExtensionVersion{1, 0}},
65
66 {"zbkb", RISCVExtensionVersion{1, 0}},
67 {"zbkc", RISCVExtensionVersion{1, 0}},
68 {"zbkx", RISCVExtensionVersion{1, 0}},
69 {"zknd", RISCVExtensionVersion{1, 0}},
70 {"zkne", RISCVExtensionVersion{1, 0}},
71 {"zknh", RISCVExtensionVersion{1, 0}},
72 {"zksed", RISCVExtensionVersion{1, 0}},
73 {"zksh", RISCVExtensionVersion{1, 0}},
74 {"zkr", RISCVExtensionVersion{1, 0}},
75 {"zkn", RISCVExtensionVersion{1, 0}},
76 {"zks", RISCVExtensionVersion{1, 0}},
77 {"zkt", RISCVExtensionVersion{1, 0}},
78 {"zk", RISCVExtensionVersion{1, 0}},
79
80 {"zmmul", RISCVExtensionVersion{1, 0}},
81
82 {"v", RISCVExtensionVersion{1, 0}},
83 {"zvl32b", RISCVExtensionVersion{1, 0}},
84 {"zvl64b", RISCVExtensionVersion{1, 0}},
85 {"zvl128b", RISCVExtensionVersion{1, 0}},
86 {"zvl256b", RISCVExtensionVersion{1, 0}},
87 {"zvl512b", RISCVExtensionVersion{1, 0}},
88 {"zvl1024b", RISCVExtensionVersion{1, 0}},
89 {"zvl2048b", RISCVExtensionVersion{1, 0}},
90 {"zvl4096b", RISCVExtensionVersion{1, 0}},
91 {"zvl8192b", RISCVExtensionVersion{1, 0}},
92 {"zvl16384b", RISCVExtensionVersion{1, 0}},
93 {"zvl32768b", RISCVExtensionVersion{1, 0}},
94 {"zvl65536b", RISCVExtensionVersion{1, 0}},
95 {"zve32x", RISCVExtensionVersion{1, 0}},
96 {"zve32f", RISCVExtensionVersion{1, 0}},
97 {"zve64x", RISCVExtensionVersion{1, 0}},
98 {"zve64f", RISCVExtensionVersion{1, 0}},
99 {"zve64d", RISCVExtensionVersion{1, 0}},
100
101 {"zicbom", RISCVExtensionVersion{1, 0}},
102 {"zicboz", RISCVExtensionVersion{1, 0}},
103 {"zicbop", RISCVExtensionVersion{1, 0}},
104 };
105
106 static const RISCVSupportedExtension SupportedExperimentalExtensions[] = {
107 {"zbe", RISCVExtensionVersion{0, 93}},
108 {"zbf", RISCVExtensionVersion{0, 93}},
109 {"zbm", RISCVExtensionVersion{0, 93}},
110 {"zbp", RISCVExtensionVersion{0, 93}},
111 {"zbr", RISCVExtensionVersion{0, 93}},
112 {"zbt", RISCVExtensionVersion{0, 93}},
113 {"zvfh", RISCVExtensionVersion{0, 1}},
114 };
115
stripExperimentalPrefix(StringRef & Ext)116 static bool stripExperimentalPrefix(StringRef &Ext) {
117 return Ext.consume_front("experimental-");
118 }
119
120 // This function finds the first character that doesn't belong to a version
121 // (e.g. zbe0p93 is extension 'zbe' of version '0p93'). So the function will
122 // consume [0-9]*p[0-9]* starting from the backward. An extension name will not
123 // end with a digit or the letter 'p', so this function will parse correctly.
124 // NOTE: This function is NOT able to take empty strings or strings that only
125 // have version numbers and no extension name. It assumes the extension name
126 // will be at least more than one character.
findFirstNonVersionCharacter(StringRef Ext)127 static size_t findFirstNonVersionCharacter(StringRef Ext) {
128 assert(!Ext.empty() &&
129 "Already guarded by if-statement in ::parseArchString");
130
131 int Pos = Ext.size() - 1;
132 while (Pos > 0 && isDigit(Ext[Pos]))
133 Pos--;
134 if (Pos > 0 && Ext[Pos] == 'p' && isDigit(Ext[Pos - 1])) {
135 Pos--;
136 while (Pos > 0 && isDigit(Ext[Pos]))
137 Pos--;
138 }
139 return Pos;
140 }
141
142 struct FindByName {
FindByNameFindByName143 FindByName(StringRef Ext) : Ext(Ext){};
144 StringRef Ext;
operator ()FindByName145 bool operator()(const RISCVSupportedExtension &ExtInfo) {
146 return ExtInfo.Name == Ext;
147 }
148 };
149
findDefaultVersion(StringRef ExtName)150 static Optional<RISCVExtensionVersion> findDefaultVersion(StringRef ExtName) {
151 // Find default version of an extension.
152 // TODO: We might set default version based on profile or ISA spec.
153 for (auto &ExtInfo : {makeArrayRef(SupportedExtensions),
154 makeArrayRef(SupportedExperimentalExtensions)}) {
155 auto ExtensionInfoIterator = llvm::find_if(ExtInfo, FindByName(ExtName));
156
157 if (ExtensionInfoIterator == ExtInfo.end()) {
158 continue;
159 }
160 return ExtensionInfoIterator->Version;
161 }
162 return None;
163 }
164
addExtension(StringRef ExtName,unsigned MajorVersion,unsigned MinorVersion)165 void RISCVISAInfo::addExtension(StringRef ExtName, unsigned MajorVersion,
166 unsigned MinorVersion) {
167 RISCVExtensionInfo Ext;
168 Ext.ExtName = ExtName.str();
169 Ext.MajorVersion = MajorVersion;
170 Ext.MinorVersion = MinorVersion;
171 Exts[ExtName.str()] = Ext;
172 }
173
getExtensionTypeDesc(StringRef Ext)174 static StringRef getExtensionTypeDesc(StringRef Ext) {
175 if (Ext.startswith("sx"))
176 return "non-standard supervisor-level extension";
177 if (Ext.startswith("s"))
178 return "standard supervisor-level extension";
179 if (Ext.startswith("x"))
180 return "non-standard user-level extension";
181 if (Ext.startswith("z"))
182 return "standard user-level extension";
183 return StringRef();
184 }
185
getExtensionType(StringRef Ext)186 static StringRef getExtensionType(StringRef Ext) {
187 if (Ext.startswith("sx"))
188 return "sx";
189 if (Ext.startswith("s"))
190 return "s";
191 if (Ext.startswith("x"))
192 return "x";
193 if (Ext.startswith("z"))
194 return "z";
195 return StringRef();
196 }
197
isExperimentalExtension(StringRef Ext)198 static Optional<RISCVExtensionVersion> isExperimentalExtension(StringRef Ext) {
199 auto ExtIterator =
200 llvm::find_if(SupportedExperimentalExtensions, FindByName(Ext));
201 if (ExtIterator == std::end(SupportedExperimentalExtensions))
202 return None;
203
204 return ExtIterator->Version;
205 }
206
isSupportedExtensionFeature(StringRef Ext)207 bool RISCVISAInfo::isSupportedExtensionFeature(StringRef Ext) {
208 bool IsExperimental = stripExperimentalPrefix(Ext);
209
210 if (IsExperimental)
211 return llvm::any_of(SupportedExperimentalExtensions, FindByName(Ext));
212 else
213 return llvm::any_of(SupportedExtensions, FindByName(Ext));
214 }
215
isSupportedExtension(StringRef Ext)216 bool RISCVISAInfo::isSupportedExtension(StringRef Ext) {
217 return llvm::any_of(SupportedExtensions, FindByName(Ext)) ||
218 llvm::any_of(SupportedExperimentalExtensions, FindByName(Ext));
219 }
220
isSupportedExtension(StringRef Ext,unsigned MajorVersion,unsigned MinorVersion)221 bool RISCVISAInfo::isSupportedExtension(StringRef Ext, unsigned MajorVersion,
222 unsigned MinorVersion) {
223 auto FindByNameAndVersion = [=](const RISCVSupportedExtension &ExtInfo) {
224 return ExtInfo.Name == Ext && (MajorVersion == ExtInfo.Version.Major) &&
225 (MinorVersion == ExtInfo.Version.Minor);
226 };
227 return llvm::any_of(SupportedExtensions, FindByNameAndVersion) ||
228 llvm::any_of(SupportedExperimentalExtensions, FindByNameAndVersion);
229 }
230
hasExtension(StringRef Ext) const231 bool RISCVISAInfo::hasExtension(StringRef Ext) const {
232 stripExperimentalPrefix(Ext);
233
234 if (!isSupportedExtension(Ext))
235 return false;
236
237 return Exts.count(Ext.str()) != 0;
238 }
239
240 // Get the rank for single-letter extension, lower value meaning higher
241 // priority.
singleLetterExtensionRank(char Ext)242 static int singleLetterExtensionRank(char Ext) {
243 switch (Ext) {
244 case 'i':
245 return -2;
246 case 'e':
247 return -1;
248 default:
249 break;
250 }
251
252 size_t Pos = AllStdExts.find(Ext);
253 int Rank;
254 if (Pos == StringRef::npos)
255 // If we got an unknown extension letter, then give it an alphabetical
256 // order, but after all known standard extensions.
257 Rank = AllStdExts.size() + (Ext - 'a');
258 else
259 Rank = Pos;
260
261 return Rank;
262 }
263
264 // Get the rank for multi-letter extension, lower value meaning higher
265 // priority/order in canonical order.
multiLetterExtensionRank(const std::string & ExtName)266 static int multiLetterExtensionRank(const std::string &ExtName) {
267 assert(ExtName.length() >= 2);
268 int HighOrder;
269 int LowOrder = 0;
270 // The order between multi-char extensions: s -> h -> z -> x.
271 char ExtClass = ExtName[0];
272 switch (ExtClass) {
273 case 's':
274 HighOrder = 0;
275 break;
276 case 'h':
277 HighOrder = 1;
278 break;
279 case 'z':
280 HighOrder = 2;
281 // `z` extension must be sorted by canonical order of second letter.
282 // e.g. zmx has higher rank than zax.
283 LowOrder = singleLetterExtensionRank(ExtName[1]);
284 break;
285 case 'x':
286 HighOrder = 3;
287 break;
288 default:
289 llvm_unreachable("Unknown prefix for multi-char extension");
290 return -1;
291 }
292
293 return (HighOrder << 8) + LowOrder;
294 }
295
296 // Compare function for extension.
297 // Only compare the extension name, ignore version comparison.
compareExtension(const std::string & LHS,const std::string & RHS)298 bool RISCVISAInfo::compareExtension(const std::string &LHS,
299 const std::string &RHS) {
300 size_t LHSLen = LHS.length();
301 size_t RHSLen = RHS.length();
302 if (LHSLen == 1 && RHSLen != 1)
303 return true;
304
305 if (LHSLen != 1 && RHSLen == 1)
306 return false;
307
308 if (LHSLen == 1 && RHSLen == 1)
309 return singleLetterExtensionRank(LHS[0]) <
310 singleLetterExtensionRank(RHS[0]);
311
312 // Both are multi-char ext here.
313 int LHSRank = multiLetterExtensionRank(LHS);
314 int RHSRank = multiLetterExtensionRank(RHS);
315 if (LHSRank != RHSRank)
316 return LHSRank < RHSRank;
317
318 // If the rank is same, it must be sorted by lexicographic order.
319 return LHS < RHS;
320 }
321
toFeatures(std::vector<StringRef> & Features,std::function<StringRef (const Twine &)> StrAlloc) const322 void RISCVISAInfo::toFeatures(
323 std::vector<StringRef> &Features,
324 std::function<StringRef(const Twine &)> StrAlloc) const {
325 for (auto const &Ext : Exts) {
326 StringRef ExtName = Ext.first;
327
328 if (ExtName == "i")
329 continue;
330
331 if (isExperimentalExtension(ExtName)) {
332 Features.push_back(StrAlloc("+experimental-" + ExtName));
333 } else {
334 Features.push_back(StrAlloc("+" + ExtName));
335 }
336 }
337 }
338
339 // Extensions may have a version number, and may be separated by
340 // an underscore '_' e.g.: rv32i2_m2.
341 // Version number is divided into major and minor version numbers,
342 // separated by a 'p'. If the minor version is 0 then 'p0' can be
343 // omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1.
getExtensionVersion(StringRef Ext,StringRef In,unsigned & Major,unsigned & Minor,unsigned & ConsumeLength,bool EnableExperimentalExtension,bool ExperimentalExtensionVersionCheck)344 static Error getExtensionVersion(StringRef Ext, StringRef In, unsigned &Major,
345 unsigned &Minor, unsigned &ConsumeLength,
346 bool EnableExperimentalExtension,
347 bool ExperimentalExtensionVersionCheck) {
348 StringRef MajorStr, MinorStr;
349 Major = 0;
350 Minor = 0;
351 ConsumeLength = 0;
352 MajorStr = In.take_while(isDigit);
353 In = In.substr(MajorStr.size());
354
355 if (!MajorStr.empty() && In.consume_front("p")) {
356 MinorStr = In.take_while(isDigit);
357 In = In.substr(MajorStr.size() + MinorStr.size() - 1);
358
359 // Expected 'p' to be followed by minor version number.
360 if (MinorStr.empty()) {
361 return createStringError(
362 errc::invalid_argument,
363 "minor version number missing after 'p' for extension '" + Ext + "'");
364 }
365 }
366
367 if (!MajorStr.empty() && MajorStr.getAsInteger(10, Major))
368 return createStringError(
369 errc::invalid_argument,
370 "Failed to parse major version number for extension '" + Ext + "'");
371
372 if (!MinorStr.empty() && MinorStr.getAsInteger(10, Minor))
373 return createStringError(
374 errc::invalid_argument,
375 "Failed to parse minor version number for extension '" + Ext + "'");
376
377 ConsumeLength = MajorStr.size();
378
379 if (!MinorStr.empty())
380 ConsumeLength += MinorStr.size() + 1 /*'p'*/;
381
382 // Expected multi-character extension with version number to have no
383 // subsequent characters (i.e. must either end string or be followed by
384 // an underscore).
385 if (Ext.size() > 1 && In.size()) {
386 std::string Error =
387 "multi-character extensions must be separated by underscores";
388 return createStringError(errc::invalid_argument, Error);
389 }
390
391 // If experimental extension, require use of current version number number
392 if (auto ExperimentalExtension = isExperimentalExtension(Ext)) {
393 if (!EnableExperimentalExtension) {
394 std::string Error = "requires '-menable-experimental-extensions' for "
395 "experimental extension '" +
396 Ext.str() + "'";
397 return createStringError(errc::invalid_argument, Error);
398 }
399
400 if (ExperimentalExtensionVersionCheck &&
401 (MajorStr.empty() && MinorStr.empty())) {
402 std::string Error =
403 "experimental extension requires explicit version number `" +
404 Ext.str() + "`";
405 return createStringError(errc::invalid_argument, Error);
406 }
407
408 auto SupportedVers = *ExperimentalExtension;
409 if (ExperimentalExtensionVersionCheck &&
410 (Major != SupportedVers.Major || Minor != SupportedVers.Minor)) {
411 std::string Error = "unsupported version number " + MajorStr.str();
412 if (!MinorStr.empty())
413 Error += "." + MinorStr.str();
414 Error += " for experimental extension '" + Ext.str() +
415 "' (this compiler supports " + utostr(SupportedVers.Major) +
416 "." + utostr(SupportedVers.Minor) + ")";
417 return createStringError(errc::invalid_argument, Error);
418 }
419 return Error::success();
420 }
421
422 // Exception rule for `g`, we don't have clear version scheme for that on
423 // ISA spec.
424 if (Ext == "g")
425 return Error::success();
426
427 if (MajorStr.empty() && MinorStr.empty()) {
428 if (auto DefaultVersion = findDefaultVersion(Ext)) {
429 Major = DefaultVersion->Major;
430 Minor = DefaultVersion->Minor;
431 }
432 // No matter found or not, return success, assume other place will
433 // verify.
434 return Error::success();
435 }
436
437 if (RISCVISAInfo::isSupportedExtension(Ext, Major, Minor))
438 return Error::success();
439
440 std::string Error = "unsupported version number " + std::string(MajorStr);
441 if (!MinorStr.empty())
442 Error += "." + MinorStr.str();
443 Error += " for extension '" + Ext.str() + "'";
444 return createStringError(errc::invalid_argument, Error);
445 }
446
447 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
parseFeatures(unsigned XLen,const std::vector<std::string> & Features)448 RISCVISAInfo::parseFeatures(unsigned XLen,
449 const std::vector<std::string> &Features) {
450 assert(XLen == 32 || XLen == 64);
451 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
452
453 for (auto &Feature : Features) {
454 StringRef ExtName = Feature;
455 bool Experimental = false;
456 assert(ExtName.size() > 1 && (ExtName[0] == '+' || ExtName[0] == '-'));
457 bool Add = ExtName[0] == '+';
458 ExtName = ExtName.drop_front(1); // Drop '+' or '-'
459 Experimental = stripExperimentalPrefix(ExtName);
460 auto ExtensionInfos = Experimental
461 ? makeArrayRef(SupportedExperimentalExtensions)
462 : makeArrayRef(SupportedExtensions);
463 auto ExtensionInfoIterator =
464 llvm::find_if(ExtensionInfos, FindByName(ExtName));
465
466 // Not all features is related to ISA extension, like `relax` or
467 // `save-restore`, skip those feature.
468 if (ExtensionInfoIterator == ExtensionInfos.end())
469 continue;
470
471 if (Add)
472 ISAInfo->addExtension(ExtName, ExtensionInfoIterator->Version.Major,
473 ExtensionInfoIterator->Version.Minor);
474 else
475 ISAInfo->Exts.erase(ExtName.str());
476 }
477
478 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
479 }
480
481 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
parseArchString(StringRef Arch,bool EnableExperimentalExtension,bool ExperimentalExtensionVersionCheck)482 RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
483 bool ExperimentalExtensionVersionCheck) {
484 // RISC-V ISA strings must be lowercase.
485 if (llvm::any_of(Arch, isupper)) {
486 return createStringError(errc::invalid_argument,
487 "string must be lowercase");
488 }
489
490 bool HasRV64 = Arch.startswith("rv64");
491 // ISA string must begin with rv32 or rv64.
492 if (!(Arch.startswith("rv32") || HasRV64) || (Arch.size() < 5)) {
493 return createStringError(errc::invalid_argument,
494 "string must begin with rv32{i,e,g} or rv64{i,g}");
495 }
496
497 unsigned XLen = HasRV64 ? 64 : 32;
498 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
499
500 // The canonical order specified in ISA manual.
501 // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
502 StringRef StdExts = AllStdExts;
503 char Baseline = Arch[4];
504
505 // First letter should be 'e', 'i' or 'g'.
506 switch (Baseline) {
507 default:
508 return createStringError(errc::invalid_argument,
509 "first letter should be 'e', 'i' or 'g'");
510 case 'e': {
511 // Extension 'e' is not allowed in rv64.
512 if (HasRV64)
513 return createStringError(
514 errc::invalid_argument,
515 "standard user-level extension 'e' requires 'rv32'");
516 break;
517 }
518 case 'i':
519 break;
520 case 'g':
521 // g = imafd
522 StdExts = StdExts.drop_front(4);
523 break;
524 }
525
526 // Skip rvxxx
527 StringRef Exts = Arch.substr(5);
528
529 // Remove multi-letter standard extensions, non-standard extensions and
530 // supervisor-level extensions. They have 'z', 'x', 's', 'sx' prefixes.
531 // Parse them at the end.
532 // Find the very first occurrence of 's', 'x' or 'z'.
533 StringRef OtherExts;
534 size_t Pos = Exts.find_first_of("zsx");
535 if (Pos != StringRef::npos) {
536 OtherExts = Exts.substr(Pos);
537 Exts = Exts.substr(0, Pos);
538 }
539
540 unsigned Major, Minor, ConsumeLength;
541 if (auto E = getExtensionVersion(std::string(1, Baseline), Exts, Major, Minor,
542 ConsumeLength, EnableExperimentalExtension,
543 ExperimentalExtensionVersionCheck))
544 return std::move(E);
545
546 if (Baseline == 'g') {
547 // No matter which version is given to `g`, we always set imafd to default
548 // version since the we don't have clear version scheme for that on
549 // ISA spec.
550 for (auto Ext : {"i", "m", "a", "f", "d"})
551 if (auto Version = findDefaultVersion(Ext))
552 ISAInfo->addExtension(Ext, Version->Major, Version->Minor);
553 else
554 llvm_unreachable("Default extension version not found?");
555 } else
556 // Baseline is `i` or `e`
557 ISAInfo->addExtension(std::string(1, Baseline), Major, Minor);
558
559 // Consume the base ISA version number and any '_' between rvxxx and the
560 // first extension
561 Exts = Exts.drop_front(ConsumeLength);
562 Exts.consume_front("_");
563
564 // TODO: Use version number when setting target features
565
566 auto StdExtsItr = StdExts.begin();
567 auto StdExtsEnd = StdExts.end();
568 for (auto I = Exts.begin(), E = Exts.end(); I != E;) {
569 char C = *I;
570
571 // Check ISA extensions are specified in the canonical order.
572 while (StdExtsItr != StdExtsEnd && *StdExtsItr != C)
573 ++StdExtsItr;
574
575 if (StdExtsItr == StdExtsEnd) {
576 // Either c contains a valid extension but it was not given in
577 // canonical order or it is an invalid extension.
578 if (StdExts.contains(C)) {
579 return createStringError(
580 errc::invalid_argument,
581 "standard user-level extension not given in canonical order '%c'",
582 C);
583 }
584
585 return createStringError(errc::invalid_argument,
586 "invalid standard user-level extension '%c'", C);
587 }
588
589 // Move to next char to prevent repeated letter.
590 ++StdExtsItr;
591
592 std::string Next;
593 unsigned Major, Minor, ConsumeLength;
594 if (std::next(I) != E)
595 Next = std::string(std::next(I), E);
596 if (auto E = getExtensionVersion(std::string(1, C), Next, Major, Minor,
597 ConsumeLength, EnableExperimentalExtension,
598 ExperimentalExtensionVersionCheck))
599 return std::move(E);
600
601 // The order is OK, then push it into features.
602 // TODO: Use version number when setting target features
603 // Currently LLVM supports only "mafdcbv".
604 StringRef SupportedStandardExtension = "mafdcbv";
605 if (!SupportedStandardExtension.contains(C))
606 return createStringError(errc::invalid_argument,
607 "unsupported standard user-level extension '%c'",
608 C);
609 ISAInfo->addExtension(std::string(1, C), Major, Minor);
610
611 // Consume full extension name and version, including any optional '_'
612 // between this extension and the next
613 ++I;
614 I += ConsumeLength;
615 if (*I == '_')
616 ++I;
617 }
618
619 // Handle other types of extensions other than the standard
620 // general purpose and standard user-level extensions.
621 // Parse the ISA string containing non-standard user-level
622 // extensions, standard supervisor-level extensions and
623 // non-standard supervisor-level extensions.
624 // These extensions start with 'z', 'x', 's', 'sx' prefixes, follow a
625 // canonical order, might have a version number (major, minor)
626 // and are separated by a single underscore '_'.
627 // Set the hardware features for the extensions that are supported.
628
629 // Multi-letter extensions are seperated by a single underscore
630 // as described in RISC-V User-Level ISA V2.2.
631 SmallVector<StringRef, 8> Split;
632 OtherExts.split(Split, '_');
633
634 SmallVector<StringRef, 8> AllExts;
635 std::array<StringRef, 4> Prefix{"z", "x", "s", "sx"};
636 auto I = Prefix.begin();
637 auto E = Prefix.end();
638 if (Split.size() > 1 || Split[0] != "") {
639 for (StringRef Ext : Split) {
640 if (Ext.empty())
641 return createStringError(errc::invalid_argument,
642 "extension name missing after separator '_'");
643
644 StringRef Type = getExtensionType(Ext);
645 StringRef Desc = getExtensionTypeDesc(Ext);
646 auto Pos = findFirstNonVersionCharacter(Ext) + 1;
647 StringRef Name(Ext.substr(0, Pos));
648 StringRef Vers(Ext.substr(Pos));
649
650 if (Type.empty())
651 return createStringError(errc::invalid_argument,
652 "invalid extension prefix '" + Ext + "'");
653
654 // Check ISA extensions are specified in the canonical order.
655 while (I != E && *I != Type)
656 ++I;
657
658 if (I == E)
659 return createStringError(errc::invalid_argument,
660 "%s not given in canonical order '%s'",
661 Desc.str().c_str(), Ext.str().c_str());
662
663 if (Name.size() == Type.size()) {
664 return createStringError(errc::invalid_argument,
665 "%s name missing after '%s'",
666 Desc.str().c_str(), Type.str().c_str());
667 }
668
669 unsigned Major, Minor, ConsumeLength;
670 if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
671 EnableExperimentalExtension,
672 ExperimentalExtensionVersionCheck))
673 return std::move(E);
674
675 // Check if duplicated extension.
676 if (llvm::is_contained(AllExts, Name))
677 return createStringError(errc::invalid_argument, "duplicated %s '%s'",
678 Desc.str().c_str(), Name.str().c_str());
679
680 ISAInfo->addExtension(Name, Major, Minor);
681 // Extension format is correct, keep parsing the extensions.
682 // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
683 AllExts.push_back(Name);
684 }
685 }
686
687 for (auto Ext : AllExts) {
688 if (!isSupportedExtension(Ext)) {
689 StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext));
690 return createStringError(errc::invalid_argument, "unsupported %s '%s'",
691 Desc.str().c_str(), Ext.str().c_str());
692 }
693 }
694
695 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
696 }
697
checkDependency()698 Error RISCVISAInfo::checkDependency() {
699 bool IsRv32 = XLen == 32;
700 bool HasE = Exts.count("e") != 0;
701 bool HasD = Exts.count("d") != 0;
702 bool HasF = Exts.count("f") != 0;
703 bool HasZfinx = Exts.count("zfinx") != 0;
704 bool HasZdinx = Exts.count("zdinx") != 0;
705 bool HasVector = Exts.count("zve32x") != 0;
706 bool HasZve32f = Exts.count("zve32f") != 0;
707 bool HasZve64d = Exts.count("zve64d") != 0;
708 bool HasZvl = MinVLen != 0;
709
710 if (HasE && !IsRv32)
711 return createStringError(
712 errc::invalid_argument,
713 "standard user-level extension 'e' requires 'rv32'");
714
715 // It's illegal to specify the 'd' (double-precision floating point)
716 // extension without also specifying the 'f' (single precision
717 // floating-point) extension.
718 // TODO: This has been removed in later specs, which specify that D implies F
719 if (HasD && !HasF)
720 return createStringError(errc::invalid_argument,
721 "d requires f extension to also be specified");
722
723 if (HasZve32f && !HasF && !HasZfinx)
724 return createStringError(
725 errc::invalid_argument,
726 "zve32f requires f or zfinx extension to also be specified");
727
728 if (HasZve64d && !HasD && !HasZdinx)
729 return createStringError(
730 errc::invalid_argument,
731 "zve64d requires d or zdinx extension to also be specified");
732
733 if (Exts.count("zvfh") && !Exts.count("zfh") && !Exts.count("zfhmin") &&
734 !Exts.count("zhinx") && !Exts.count("zhinxmin"))
735 return createStringError(
736 errc::invalid_argument,
737 "zvfh requires zfh, zfhmin, zhinx or zhinxmin extension to also be "
738 "specified");
739
740 if (HasZvl && !HasVector)
741 return createStringError(
742 errc::invalid_argument,
743 "zvl*b requires v or zve* extension to also be specified");
744
745 // Additional dependency checks.
746 // TODO: The 'q' extension requires rv64.
747 // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.
748
749 return Error::success();
750 }
751
752 static const char *ImpliedExtsV[] = {"zvl128b", "zve64d", "f", "d"};
753 static const char *ImpliedExtsZfhmin[] = {"f"};
754 static const char *ImpliedExtsZfh[] = {"f"};
755 static const char *ImpliedExtsZdinx[] = {"zfinx"};
756 static const char *ImpliedExtsZhinxmin[] = {"zfinx"};
757 static const char *ImpliedExtsZhinx[] = {"zfinx"};
758 static const char *ImpliedExtsZve64d[] = {"zve64f"};
759 static const char *ImpliedExtsZve64f[] = {"zve64x", "zve32f"};
760 static const char *ImpliedExtsZve64x[] = {"zve32x", "zvl64b"};
761 static const char *ImpliedExtsZve32f[] = {"zve32x"};
762 static const char *ImpliedExtsZve32x[] = {"zvl32b"};
763 static const char *ImpliedExtsZvl65536b[] = {"zvl32768b"};
764 static const char *ImpliedExtsZvl32768b[] = {"zvl16384b"};
765 static const char *ImpliedExtsZvl16384b[] = {"zvl8192b"};
766 static const char *ImpliedExtsZvl8192b[] = {"zvl4096b"};
767 static const char *ImpliedExtsZvl4096b[] = {"zvl2048b"};
768 static const char *ImpliedExtsZvl2048b[] = {"zvl1024b"};
769 static const char *ImpliedExtsZvl1024b[] = {"zvl512b"};
770 static const char *ImpliedExtsZvl512b[] = {"zvl256b"};
771 static const char *ImpliedExtsZvl256b[] = {"zvl128b"};
772 static const char *ImpliedExtsZvl128b[] = {"zvl64b"};
773 static const char *ImpliedExtsZvl64b[] = {"zvl32b"};
774 static const char *ImpliedExtsZk[] = {"zkn", "zkt", "zkr"};
775 static const char *ImpliedExtsZkn[] = {"zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"};
776 static const char *ImpliedExtsZks[] = {"zbkb", "zbkc", "zbkx", "zksed", "zksh"};
777 static const char *ImpliedExtsZvfh[] = {"zve32f"};
778
779 struct ImpliedExtsEntry {
780 StringLiteral Name;
781 ArrayRef<const char *> Exts;
782
operator <ImpliedExtsEntry783 bool operator<(const ImpliedExtsEntry &Other) const {
784 return Name < Other.Name;
785 }
786
operator <ImpliedExtsEntry787 bool operator<(StringRef Other) const { return Name < Other; }
788 };
789
790 // Note: The table needs to be sorted by name.
791 static constexpr ImpliedExtsEntry ImpliedExts[] = {
792 {{"v"}, {ImpliedExtsV}},
793 {{"zdinx"}, {ImpliedExtsZdinx}},
794 {{"zfh"}, {ImpliedExtsZfh}},
795 {{"zfhmin"}, {ImpliedExtsZfhmin}},
796 {{"zhinx"}, {ImpliedExtsZhinx}},
797 {{"zhinxmin"}, {ImpliedExtsZhinxmin}},
798 {{"zk"}, {ImpliedExtsZk}},
799 {{"zkn"}, {ImpliedExtsZkn}},
800 {{"zks"}, {ImpliedExtsZks}},
801 {{"zve32f"}, {ImpliedExtsZve32f}},
802 {{"zve32x"}, {ImpliedExtsZve32x}},
803 {{"zve64d"}, {ImpliedExtsZve64d}},
804 {{"zve64f"}, {ImpliedExtsZve64f}},
805 {{"zve64x"}, {ImpliedExtsZve64x}},
806 {{"zvfh"}, {ImpliedExtsZvfh}},
807 {{"zvl1024b"}, {ImpliedExtsZvl1024b}},
808 {{"zvl128b"}, {ImpliedExtsZvl128b}},
809 {{"zvl16384b"}, {ImpliedExtsZvl16384b}},
810 {{"zvl2048b"}, {ImpliedExtsZvl2048b}},
811 {{"zvl256b"}, {ImpliedExtsZvl256b}},
812 {{"zvl32768b"}, {ImpliedExtsZvl32768b}},
813 {{"zvl4096b"}, {ImpliedExtsZvl4096b}},
814 {{"zvl512b"}, {ImpliedExtsZvl512b}},
815 {{"zvl64b"}, {ImpliedExtsZvl64b}},
816 {{"zvl65536b"}, {ImpliedExtsZvl65536b}},
817 {{"zvl8192b"}, {ImpliedExtsZvl8192b}},
818 };
819
updateImplication()820 void RISCVISAInfo::updateImplication() {
821 bool HasE = Exts.count("e") != 0;
822 bool HasI = Exts.count("i") != 0;
823
824 // If not in e extension and i extension does not exist, i extension is
825 // implied
826 if (!HasE && !HasI) {
827 auto Version = findDefaultVersion("i");
828 addExtension("i", Version->Major, Version->Minor);
829 }
830
831 assert(llvm::is_sorted(ImpliedExts) && "Table not sorted by Name");
832
833 // This loop may execute over 1 iteration since implication can be layered
834 // Exits loop if no more implication is applied
835 SmallSetVector<StringRef, 16> WorkList;
836 for (auto const &Ext : Exts)
837 WorkList.insert(Ext.first);
838
839 while (!WorkList.empty()) {
840 StringRef ExtName = WorkList.pop_back_val();
841 auto I = llvm::lower_bound(ImpliedExts, ExtName);
842 if (I != std::end(ImpliedExts) && I->Name == ExtName) {
843 for (const char *ImpliedExt : I->Exts) {
844 if (WorkList.count(ImpliedExt))
845 continue;
846 if (Exts.count(ImpliedExt))
847 continue;
848 auto Version = findDefaultVersion(ImpliedExt);
849 addExtension(ImpliedExt, Version->Major, Version->Minor);
850 WorkList.insert(ImpliedExt);
851 }
852 }
853 }
854 }
855
856 struct CombinedExtsEntry {
857 StringLiteral CombineExt;
858 ArrayRef<const char *> RequiredExts;
859 };
860
861 static constexpr CombinedExtsEntry CombineIntoExts[] = {
862 {{"zk"}, {ImpliedExtsZk}},
863 {{"zkn"}, {ImpliedExtsZkn}},
864 {{"zks"}, {ImpliedExtsZks}},
865 };
866
updateCombination()867 void RISCVISAInfo::updateCombination() {
868 bool IsNewCombine = false;
869 do {
870 IsNewCombine = false;
871 for (CombinedExtsEntry CombineIntoExt : CombineIntoExts) {
872 auto CombineExt = CombineIntoExt.CombineExt;
873 auto RequiredExts = CombineIntoExt.RequiredExts;
874 if (hasExtension(CombineExt))
875 continue;
876 bool IsAllRequiredFeatureExist = true;
877 for (const char *Ext : RequiredExts)
878 IsAllRequiredFeatureExist &= hasExtension(Ext);
879 if (IsAllRequiredFeatureExist) {
880 auto Version = findDefaultVersion(CombineExt);
881 addExtension(CombineExt, Version->Major, Version->Minor);
882 IsNewCombine = true;
883 }
884 }
885 } while (IsNewCombine);
886 }
887
updateFLen()888 void RISCVISAInfo::updateFLen() {
889 FLen = 0;
890 // TODO: Handle q extension.
891 if (Exts.count("d"))
892 FLen = 64;
893 else if (Exts.count("f"))
894 FLen = 32;
895 }
896
updateMinVLen()897 void RISCVISAInfo::updateMinVLen() {
898 for (auto const &Ext : Exts) {
899 StringRef ExtName = Ext.first;
900 bool IsZvlExt = ExtName.consume_front("zvl") && ExtName.consume_back("b");
901 if (IsZvlExt) {
902 unsigned ZvlLen;
903 if (!ExtName.getAsInteger(10, ZvlLen))
904 MinVLen = std::max(MinVLen, ZvlLen);
905 }
906 }
907 }
908
updateMaxELen()909 void RISCVISAInfo::updateMaxELen() {
910 // handles EEW restriction by sub-extension zve
911 for (auto const &Ext : Exts) {
912 StringRef ExtName = Ext.first;
913 bool IsZveExt = ExtName.consume_front("zve");
914 if (IsZveExt) {
915 if (ExtName.back() == 'f')
916 MaxELenFp = std::max(MaxELenFp, 32u);
917 if (ExtName.back() == 'd')
918 MaxELenFp = std::max(MaxELenFp, 64u);
919 ExtName = ExtName.drop_back();
920 unsigned ZveELen;
921 ExtName.getAsInteger(10, ZveELen);
922 MaxELen = std::max(MaxELen, ZveELen);
923 }
924 }
925 }
926
toString() const927 std::string RISCVISAInfo::toString() const {
928 std::string Buffer;
929 raw_string_ostream Arch(Buffer);
930
931 Arch << "rv" << XLen;
932
933 ListSeparator LS("_");
934 for (auto const &Ext : Exts) {
935 StringRef ExtName = Ext.first;
936 auto ExtInfo = Ext.second;
937 Arch << LS << ExtName;
938 Arch << ExtInfo.MajorVersion << "p" << ExtInfo.MinorVersion;
939 }
940
941 return Arch.str();
942 }
943
toFeatureVector() const944 std::vector<std::string> RISCVISAInfo::toFeatureVector() const {
945 std::vector<std::string> FeatureVector;
946 for (auto const &Ext : Exts) {
947 std::string ExtName = Ext.first;
948 if (ExtName == "i") // i is not recognized in clang -cc1
949 continue;
950 std::string Feature = isExperimentalExtension(ExtName)
951 ? "+experimental-" + ExtName
952 : "+" + ExtName;
953 FeatureVector.push_back(Feature);
954 }
955 return FeatureVector;
956 }
957
958 llvm::Expected<std::unique_ptr<RISCVISAInfo>>
postProcessAndChecking(std::unique_ptr<RISCVISAInfo> && ISAInfo)959 RISCVISAInfo::postProcessAndChecking(std::unique_ptr<RISCVISAInfo> &&ISAInfo) {
960 ISAInfo->updateImplication();
961 ISAInfo->updateCombination();
962 ISAInfo->updateFLen();
963 ISAInfo->updateMinVLen();
964 ISAInfo->updateMaxELen();
965
966 if (Error Result = ISAInfo->checkDependency())
967 return std::move(Result);
968 return std::move(ISAInfo);
969 }
970
computeDefaultABI() const971 StringRef RISCVISAInfo::computeDefaultABI() const {
972 if (XLen == 32) {
973 if (hasExtension("d"))
974 return "ilp32d";
975 if (hasExtension("e"))
976 return "ilp32e";
977 return "ilp32";
978 } else if (XLen == 64) {
979 if (hasExtension("d"))
980 return "lp64d";
981 return "lp64";
982 }
983 llvm_unreachable("Invalid XLEN");
984 }
985