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/StringExtras.h" 13 #include "llvm/ADT/StringRef.h" 14 #include "llvm/Support/Errc.h" 15 #include "llvm/Support/Error.h" 16 #include "llvm/Support/raw_ostream.h" 17 18 #include <array> 19 #include <string> 20 #include <vector> 21 22 using namespace llvm; 23 24 namespace { 25 /// Represents the major and version number components of a RISC-V extension 26 struct RISCVExtensionVersion { 27 unsigned Major; 28 unsigned Minor; 29 }; 30 31 struct RISCVSupportedExtension { 32 const char *Name; 33 /// Supported version. 34 RISCVExtensionVersion Version; 35 }; 36 37 } // end anonymous namespace 38 39 static constexpr StringLiteral AllStdExts = "mafdqlcbjtpvn"; 40 41 static const RISCVSupportedExtension SupportedExtensions[] = { 42 {"i", RISCVExtensionVersion{2, 0}}, 43 {"e", RISCVExtensionVersion{1, 9}}, 44 {"m", RISCVExtensionVersion{2, 0}}, 45 {"a", RISCVExtensionVersion{2, 0}}, 46 {"f", RISCVExtensionVersion{2, 0}}, 47 {"d", RISCVExtensionVersion{2, 0}}, 48 {"c", RISCVExtensionVersion{2, 0}}, 49 }; 50 51 static const RISCVSupportedExtension SupportedExperimentalExtensions[] = { 52 {"v", RISCVExtensionVersion{0, 10}}, 53 {"zba", RISCVExtensionVersion{1, 0}}, 54 {"zbb", RISCVExtensionVersion{1, 0}}, 55 {"zbc", RISCVExtensionVersion{1, 0}}, 56 {"zbe", RISCVExtensionVersion{0, 93}}, 57 {"zbf", RISCVExtensionVersion{0, 93}}, 58 {"zbm", RISCVExtensionVersion{0, 93}}, 59 {"zbp", RISCVExtensionVersion{0, 93}}, 60 {"zbr", RISCVExtensionVersion{0, 93}}, 61 {"zbs", RISCVExtensionVersion{1, 0}}, 62 {"zbt", RISCVExtensionVersion{0, 93}}, 63 64 {"zvamo", RISCVExtensionVersion{0, 10}}, 65 {"zvlsseg", RISCVExtensionVersion{0, 10}}, 66 67 {"zfh", RISCVExtensionVersion{0, 1}}, 68 }; 69 70 static bool stripExperimentalPrefix(StringRef &Ext) { 71 return Ext.consume_front("experimental-"); 72 } 73 74 struct FindByName { 75 FindByName(StringRef Ext) : Ext(Ext){}; 76 StringRef Ext; 77 bool operator()(const RISCVSupportedExtension &ExtInfo) { 78 return ExtInfo.Name == Ext; 79 } 80 }; 81 82 static Optional<RISCVExtensionVersion> findDefaultVersion(StringRef ExtName) { 83 // Find default version of an extension. 84 // TODO: We might set default version based on profile or ISA spec. 85 for (auto &ExtInfo : {makeArrayRef(SupportedExtensions), 86 makeArrayRef(SupportedExperimentalExtensions)}) { 87 auto ExtensionInfoIterator = llvm::find_if(ExtInfo, FindByName(ExtName)); 88 89 if (ExtensionInfoIterator == ExtInfo.end()) { 90 continue; 91 } 92 return ExtensionInfoIterator->Version; 93 } 94 return None; 95 } 96 97 void RISCVISAInfo::addExtension(StringRef ExtName, unsigned MajorVersion, 98 unsigned MinorVersion) { 99 RISCVExtensionInfo Ext; 100 Ext.ExtName = ExtName.str(); 101 Ext.MajorVersion = MajorVersion; 102 Ext.MinorVersion = MinorVersion; 103 Exts[ExtName.str()] = Ext; 104 } 105 106 static StringRef getExtensionTypeDesc(StringRef Ext) { 107 if (Ext.startswith("sx")) 108 return "non-standard supervisor-level extension"; 109 if (Ext.startswith("s")) 110 return "standard supervisor-level extension"; 111 if (Ext.startswith("x")) 112 return "non-standard user-level extension"; 113 if (Ext.startswith("z")) 114 return "standard user-level extension"; 115 return StringRef(); 116 } 117 118 static StringRef getExtensionType(StringRef Ext) { 119 if (Ext.startswith("sx")) 120 return "sx"; 121 if (Ext.startswith("s")) 122 return "s"; 123 if (Ext.startswith("x")) 124 return "x"; 125 if (Ext.startswith("z")) 126 return "z"; 127 return StringRef(); 128 } 129 130 static Optional<RISCVExtensionVersion> isExperimentalExtension(StringRef Ext) { 131 auto ExtIterator = 132 llvm::find_if(SupportedExperimentalExtensions, FindByName(Ext)); 133 if (ExtIterator == std::end(SupportedExperimentalExtensions)) 134 return None; 135 136 return ExtIterator->Version; 137 } 138 139 bool RISCVISAInfo::isSupportedExtensionFeature(StringRef Ext) { 140 bool IsExperimental = stripExperimentalPrefix(Ext); 141 142 if (IsExperimental) 143 return llvm::any_of(SupportedExperimentalExtensions, FindByName(Ext)); 144 else 145 return llvm::any_of(SupportedExtensions, FindByName(Ext)); 146 } 147 148 bool RISCVISAInfo::isSupportedExtension(StringRef Ext) { 149 return llvm::any_of(SupportedExtensions, FindByName(Ext)) || 150 llvm::any_of(SupportedExperimentalExtensions, FindByName(Ext)); 151 } 152 153 bool RISCVISAInfo::isSupportedExtension(StringRef Ext, unsigned MajorVersion, 154 unsigned MinorVersion) { 155 auto FindByNameAndVersion = [=](const RISCVSupportedExtension &ExtInfo) { 156 return ExtInfo.Name == Ext && (MajorVersion == ExtInfo.Version.Major) && 157 (MinorVersion == ExtInfo.Version.Minor); 158 }; 159 return llvm::any_of(SupportedExtensions, FindByNameAndVersion) || 160 llvm::any_of(SupportedExperimentalExtensions, FindByNameAndVersion); 161 } 162 163 bool RISCVISAInfo::hasExtension(StringRef Ext) const { 164 stripExperimentalPrefix(Ext); 165 166 if (!isSupportedExtension(Ext)) 167 return false; 168 169 return Exts.count(Ext.str()) != 0; 170 } 171 172 // Get the rank for single-letter extension, lower value meaning higher 173 // priority. 174 static int singleLetterExtensionRank(char Ext) { 175 switch (Ext) { 176 case 'i': 177 return -2; 178 case 'e': 179 return -1; 180 default: 181 break; 182 } 183 184 size_t Pos = AllStdExts.find(Ext); 185 int Rank; 186 if (Pos == StringRef::npos) 187 // If we got an unknown extension letter, then give it an alphabetical 188 // order, but after all known standard extensions. 189 Rank = AllStdExts.size() + (Ext - 'a'); 190 else 191 Rank = Pos; 192 193 return Rank; 194 } 195 196 // Get the rank for multi-letter extension, lower value meaning higher 197 // priority/order in canonical order. 198 static int multiLetterExtensionRank(const std::string &ExtName) { 199 assert(ExtName.length() >= 2); 200 int HighOrder; 201 int LowOrder = 0; 202 // The order between multi-char extensions: s -> h -> z -> x. 203 char ExtClass = ExtName[0]; 204 switch (ExtClass) { 205 case 's': 206 HighOrder = 0; 207 break; 208 case 'h': 209 HighOrder = 1; 210 break; 211 case 'z': 212 HighOrder = 2; 213 // `z` extension must be sorted by canonical order of second letter. 214 // e.g. zmx has higher rank than zax. 215 LowOrder = singleLetterExtensionRank(ExtName[1]); 216 break; 217 case 'x': 218 HighOrder = 3; 219 break; 220 default: 221 llvm_unreachable("Unknown prefix for multi-char extension"); 222 return -1; 223 } 224 225 return (HighOrder << 8) + LowOrder; 226 } 227 228 // Compare function for extension. 229 // Only compare the extension name, ignore version comparison. 230 bool RISCVISAInfo::compareExtension(const std::string &LHS, 231 const std::string &RHS) { 232 size_t LHSLen = LHS.length(); 233 size_t RHSLen = RHS.length(); 234 if (LHSLen == 1 && RHSLen != 1) 235 return true; 236 237 if (LHSLen != 1 && RHSLen == 1) 238 return false; 239 240 if (LHSLen == 1 && RHSLen == 1) 241 return singleLetterExtensionRank(LHS[0]) < 242 singleLetterExtensionRank(RHS[0]); 243 244 // Both are multi-char ext here. 245 int LHSRank = multiLetterExtensionRank(LHS); 246 int RHSRank = multiLetterExtensionRank(RHS); 247 if (LHSRank != RHSRank) 248 return LHSRank < RHSRank; 249 250 // If the rank is same, it must be sorted by lexicographic order. 251 return LHS < RHS; 252 } 253 254 void RISCVISAInfo::toFeatures( 255 std::vector<StringRef> &Features, 256 std::function<StringRef(const Twine &)> StrAlloc) const { 257 for (auto &Ext : Exts) { 258 StringRef ExtName = Ext.first; 259 260 if (ExtName == "i") 261 continue; 262 263 if (ExtName == "zvlsseg") { 264 Features.push_back("+experimental-v"); 265 Features.push_back("+experimental-zvlsseg"); 266 } else if (ExtName == "zvamo") { 267 Features.push_back("+experimental-v"); 268 Features.push_back("+experimental-zvlsseg"); 269 Features.push_back("+experimental-zvamo"); 270 } else if (isExperimentalExtension(ExtName)) { 271 Features.push_back(StrAlloc("+experimental-" + ExtName)); 272 } else { 273 Features.push_back(StrAlloc("+" + ExtName)); 274 } 275 } 276 } 277 278 // Extensions may have a version number, and may be separated by 279 // an underscore '_' e.g.: rv32i2_m2. 280 // Version number is divided into major and minor version numbers, 281 // separated by a 'p'. If the minor version is 0 then 'p0' can be 282 // omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1. 283 static Error getExtensionVersion(StringRef Ext, StringRef In, unsigned &Major, 284 unsigned &Minor, unsigned &ConsumeLength, 285 bool EnableExperimentalExtension, 286 bool ExperimentalExtensionVersionCheck) { 287 StringRef MajorStr, MinorStr; 288 Major = 0; 289 Minor = 0; 290 ConsumeLength = 0; 291 MajorStr = In.take_while(isDigit); 292 In = In.substr(MajorStr.size()); 293 294 if (!MajorStr.empty() && In.consume_front("p")) { 295 MinorStr = In.take_while(isDigit); 296 In = In.substr(MajorStr.size() + 1); 297 298 // Expected 'p' to be followed by minor version number. 299 if (MinorStr.empty()) { 300 return createStringError( 301 errc::invalid_argument, 302 "minor version number missing after 'p' for extension '" + Ext + "'"); 303 } 304 } 305 306 if (!MajorStr.empty() && MajorStr.getAsInteger(10, Major)) 307 return createStringError( 308 errc::invalid_argument, 309 "Failed to parse major version number for extension '" + Ext + "'"); 310 311 if (!MinorStr.empty() && MinorStr.getAsInteger(10, Minor)) 312 return createStringError( 313 errc::invalid_argument, 314 "Failed to parse minor version number for extension '" + Ext + "'"); 315 316 ConsumeLength = MajorStr.size(); 317 318 if (!MinorStr.empty()) 319 ConsumeLength += MinorStr.size() + 1 /*'p'*/; 320 321 // Expected multi-character extension with version number to have no 322 // subsequent characters (i.e. must either end string or be followed by 323 // an underscore). 324 if (Ext.size() > 1 && In.size()) { 325 std::string Error = 326 "multi-character extensions must be separated by underscores"; 327 return createStringError(errc::invalid_argument, Error); 328 } 329 330 // If experimental extension, require use of current version number number 331 if (auto ExperimentalExtension = isExperimentalExtension(Ext)) { 332 if (!EnableExperimentalExtension) { 333 std::string Error = "requires '-menable-experimental-extensions' for " 334 "experimental extension '" + 335 Ext.str() + "'"; 336 return createStringError(errc::invalid_argument, Error); 337 } 338 339 if (ExperimentalExtensionVersionCheck && 340 (MajorStr.empty() && MinorStr.empty())) { 341 std::string Error = 342 "experimental extension requires explicit version number `" + 343 Ext.str() + "`"; 344 return createStringError(errc::invalid_argument, Error); 345 } 346 347 auto SupportedVers = *ExperimentalExtension; 348 if (ExperimentalExtensionVersionCheck && 349 (Major != SupportedVers.Major || Minor != SupportedVers.Minor)) { 350 std::string Error = "unsupported version number " + MajorStr.str(); 351 if (!MinorStr.empty()) 352 Error += "." + MinorStr.str(); 353 Error += " for experimental extension '" + Ext.str() + 354 "'(this compiler supports " + utostr(SupportedVers.Major) + "." + 355 utostr(SupportedVers.Minor) + ")"; 356 return createStringError(errc::invalid_argument, Error); 357 } 358 return Error::success(); 359 } 360 361 // Exception rule for `g`, we don't have clear version scheme for that on 362 // ISA spec. 363 if (Ext == "g") 364 return Error::success(); 365 366 if (MajorStr.empty() && MinorStr.empty()) { 367 if (auto DefaultVersion = findDefaultVersion(Ext)) { 368 Major = DefaultVersion->Major; 369 Minor = DefaultVersion->Minor; 370 } 371 // No matter found or not, return success, assume other place will 372 // verify. 373 return Error::success(); 374 } 375 376 if (RISCVISAInfo::isSupportedExtension(Ext, Major, Minor)) 377 return Error::success(); 378 379 std::string Error = "unsupported version number " + std::string(MajorStr); 380 if (!MinorStr.empty()) 381 Error += "." + MinorStr.str(); 382 Error += " for extension '" + Ext.str() + "'"; 383 return createStringError(errc::invalid_argument, Error); 384 } 385 386 llvm::Expected<std::unique_ptr<RISCVISAInfo>> 387 RISCVISAInfo::parseFeatures(unsigned XLen, 388 const std::vector<std::string> &Features) { 389 assert(XLen == 32 || XLen == 64); 390 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen)); 391 392 bool HasE = false; 393 for (auto &Feature : Features) { 394 StringRef ExtName = Feature; 395 bool Experimental = false; 396 assert(ExtName.size() > 1 && (ExtName[0] == '+' || ExtName[0] == '-')); 397 bool Add = ExtName[0] == '+'; 398 ExtName = ExtName.drop_front(1); // Drop '+' or '-' 399 Experimental = stripExperimentalPrefix(ExtName); 400 auto ExtensionInfos = Experimental 401 ? makeArrayRef(SupportedExperimentalExtensions) 402 : makeArrayRef(SupportedExtensions); 403 auto ExtensionInfoIterator = 404 llvm::find_if(ExtensionInfos, FindByName(ExtName)); 405 406 // Not all features is related to ISA extension, like `relax` or 407 // `save-restore`, skip those feature. 408 if (ExtensionInfoIterator == ExtensionInfos.end()) 409 continue; 410 411 if (Add) { 412 if (ExtName == "e") { 413 if (XLen != 32) 414 return createStringError( 415 errc::invalid_argument, 416 "standard user-level extension 'e' requires 'rv32'"); 417 HasE = true; 418 } 419 420 ISAInfo->addExtension(ExtName, ExtensionInfoIterator->Version.Major, 421 ExtensionInfoIterator->Version.Minor); 422 } else 423 ISAInfo->Exts.erase(ExtName.str()); 424 } 425 if (!HasE) { 426 if (auto Version = findDefaultVersion("i")) 427 ISAInfo->addExtension("i", Version->Major, Version->Minor); 428 else 429 llvm_unreachable("Default extension version for 'i' not found?"); 430 } 431 432 ISAInfo->updateFLen(); 433 434 return std::move(ISAInfo); 435 } 436 437 llvm::Expected<std::unique_ptr<RISCVISAInfo>> 438 RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension, 439 bool ExperimentalExtensionVersionCheck) { 440 // RISC-V ISA strings must be lowercase. 441 if (llvm::any_of(Arch, isupper)) { 442 return createStringError(errc::invalid_argument, 443 "string must be lowercase"); 444 } 445 446 bool HasRV64 = Arch.startswith("rv64"); 447 // ISA string must begin with rv32 or rv64. 448 if (!(Arch.startswith("rv32") || HasRV64) || (Arch.size() < 5)) { 449 return createStringError(errc::invalid_argument, 450 "string must begin with rv32{i,e,g} or rv64{i,g}"); 451 } 452 453 unsigned XLen = HasRV64 ? 64 : 32; 454 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen)); 455 456 // The canonical order specified in ISA manual. 457 // Ref: Table 22.1 in RISC-V User-Level ISA V2.2 458 StringRef StdExts = AllStdExts; 459 bool HasF = false, HasD = false; 460 char Baseline = Arch[4]; 461 462 // First letter should be 'e', 'i' or 'g'. 463 switch (Baseline) { 464 default: 465 return createStringError(errc::invalid_argument, 466 "first letter should be 'e', 'i' or 'g'"); 467 case 'e': { 468 // Extension 'e' is not allowed in rv64. 469 if (HasRV64) 470 return createStringError( 471 errc::invalid_argument, 472 "standard user-level extension 'e' requires 'rv32'"); 473 break; 474 } 475 case 'i': 476 break; 477 case 'g': 478 // g = imafd 479 StdExts = StdExts.drop_front(4); 480 HasF = true; 481 HasD = true; 482 break; 483 } 484 485 // Skip rvxxx 486 StringRef Exts = Arch.substr(5); 487 488 // Remove multi-letter standard extensions, non-standard extensions and 489 // supervisor-level extensions. They have 'z', 'x', 's', 'sx' prefixes. 490 // Parse them at the end. 491 // Find the very first occurrence of 's', 'x' or 'z'. 492 StringRef OtherExts; 493 size_t Pos = Exts.find_first_of("zsx"); 494 if (Pos != StringRef::npos) { 495 OtherExts = Exts.substr(Pos); 496 Exts = Exts.substr(0, Pos); 497 } 498 499 unsigned Major, Minor, ConsumeLength; 500 if (auto E = getExtensionVersion(std::string(1, Baseline), Exts, Major, Minor, 501 ConsumeLength, EnableExperimentalExtension, 502 ExperimentalExtensionVersionCheck)) 503 return std::move(E); 504 505 if (Baseline == 'g') { 506 // No matter which version is given to `g`, we always set imafd to default 507 // version since the we don't have clear version scheme for that on 508 // ISA spec. 509 for (auto Ext : {"i", "m", "a", "f", "d"}) 510 if (auto Version = findDefaultVersion(Ext)) 511 ISAInfo->addExtension(Ext, Version->Major, Version->Minor); 512 else 513 llvm_unreachable("Default extension version not found?"); 514 } else 515 // Baseline is `i` or `e` 516 ISAInfo->addExtension(std::string(1, Baseline), Major, Minor); 517 518 // Consume the base ISA version number and any '_' between rvxxx and the 519 // first extension 520 Exts = Exts.drop_front(ConsumeLength); 521 Exts.consume_front("_"); 522 523 // TODO: Use version number when setting target features 524 525 auto StdExtsItr = StdExts.begin(); 526 auto StdExtsEnd = StdExts.end(); 527 for (auto I = Exts.begin(), E = Exts.end(); I != E;) { 528 char C = *I; 529 530 // Check ISA extensions are specified in the canonical order. 531 while (StdExtsItr != StdExtsEnd && *StdExtsItr != C) 532 ++StdExtsItr; 533 534 if (StdExtsItr == StdExtsEnd) { 535 // Either c contains a valid extension but it was not given in 536 // canonical order or it is an invalid extension. 537 if (StdExts.contains(C)) { 538 return createStringError( 539 errc::invalid_argument, 540 "standard user-level extension not given in canonical order '%c'", 541 C); 542 } 543 544 return createStringError(errc::invalid_argument, 545 "invalid standard user-level extension '%c'", C); 546 } 547 548 // Move to next char to prevent repeated letter. 549 ++StdExtsItr; 550 551 std::string Next; 552 unsigned Major, Minor, ConsumeLength; 553 if (std::next(I) != E) 554 Next = std::string(std::next(I), E); 555 if (auto E = getExtensionVersion(std::string(1, C), Next, Major, Minor, 556 ConsumeLength, EnableExperimentalExtension, 557 ExperimentalExtensionVersionCheck)) 558 return std::move(E); 559 560 // The order is OK, then push it into features. 561 // TODO: Use version number when setting target features 562 switch (C) { 563 default: 564 // Currently LLVM supports only "mafdcbv". 565 return createStringError(errc::invalid_argument, 566 "unsupported standard user-level extension '%c'", 567 C); 568 case 'm': 569 ISAInfo->addExtension("m", Major, Minor); 570 break; 571 case 'a': 572 ISAInfo->addExtension("a", Major, Minor); 573 break; 574 case 'f': 575 ISAInfo->addExtension("f", Major, Minor); 576 HasF = true; 577 break; 578 case 'd': 579 ISAInfo->addExtension("d", Major, Minor); 580 HasD = true; 581 break; 582 case 'c': 583 ISAInfo->addExtension("c", Major, Minor); 584 break; 585 case 'v': 586 ISAInfo->addExtension("v", Major, Minor); 587 ISAInfo->addExtension("zvlsseg", Major, Minor); 588 break; 589 } 590 // Consume full extension name and version, including any optional '_' 591 // between this extension and the next 592 ++I; 593 I += ConsumeLength; 594 if (*I == '_') 595 ++I; 596 } 597 // Dependency check. 598 // It's illegal to specify the 'd' (double-precision floating point) 599 // extension without also specifying the 'f' (single precision 600 // floating-point) extension. 601 // TODO: This has been removed in later specs, which specify that D implies F 602 if (HasD && !HasF) 603 return createStringError(errc::invalid_argument, 604 "d requires f extension to also be specified"); 605 606 // Additional dependency checks. 607 // TODO: The 'q' extension requires rv64. 608 // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'. 609 610 if (OtherExts.empty()) 611 return std::move(ISAInfo); 612 613 // Handle other types of extensions other than the standard 614 // general purpose and standard user-level extensions. 615 // Parse the ISA string containing non-standard user-level 616 // extensions, standard supervisor-level extensions and 617 // non-standard supervisor-level extensions. 618 // These extensions start with 'z', 'x', 's', 'sx' prefixes, follow a 619 // canonical order, might have a version number (major, minor) 620 // and are separated by a single underscore '_'. 621 // Set the hardware features for the extensions that are supported. 622 623 // Multi-letter extensions are seperated by a single underscore 624 // as described in RISC-V User-Level ISA V2.2. 625 SmallVector<StringRef, 8> Split; 626 OtherExts.split(Split, '_'); 627 628 SmallVector<StringRef, 8> AllExts; 629 std::array<StringRef, 4> Prefix{"z", "x", "s", "sx"}; 630 auto I = Prefix.begin(); 631 auto E = Prefix.end(); 632 633 for (StringRef Ext : Split) { 634 if (Ext.empty()) 635 return createStringError(errc::invalid_argument, 636 "extension name missing after separator '_'"); 637 638 StringRef Type = getExtensionType(Ext); 639 StringRef Desc = getExtensionTypeDesc(Ext); 640 auto Pos = Ext.find_if(isDigit); 641 StringRef Name(Ext.substr(0, Pos)); 642 StringRef Vers(Ext.substr(Pos)); 643 644 if (Type.empty()) 645 return createStringError(errc::invalid_argument, 646 "invalid extension prefix '" + Ext + "'"); 647 648 // Check ISA extensions are specified in the canonical order. 649 while (I != E && *I != Type) 650 ++I; 651 652 if (I == E) 653 return createStringError(errc::invalid_argument, 654 "%s not given in canonical order '%s'", 655 Desc.str().c_str(), Ext.str().c_str()); 656 657 if (Name.size() == Type.size()) { 658 return createStringError(errc::invalid_argument, 659 "%s name missing after '%s'", Desc.str().c_str(), 660 Type.str().c_str()); 661 } 662 663 unsigned Major, Minor, ConsumeLength; 664 if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength, 665 EnableExperimentalExtension, 666 ExperimentalExtensionVersionCheck)) 667 return std::move(E); 668 669 // Check if duplicated extension. 670 if (llvm::is_contained(AllExts, Name)) 671 return createStringError(errc::invalid_argument, "duplicated %s '%s'", 672 Desc.str().c_str(), Name.str().c_str()); 673 674 ISAInfo->addExtension(Name, Major, Minor); 675 // Extension format is correct, keep parsing the extensions. 676 // TODO: Save Type, Name, Major, Minor to avoid parsing them later. 677 AllExts.push_back(Name); 678 } 679 680 for (auto Ext : AllExts) { 681 if (!isSupportedExtension(Ext)) { 682 StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext)); 683 return createStringError(errc::invalid_argument, "unsupported %s '%s'", 684 Desc.str().c_str(), Ext.str().c_str()); 685 } 686 } 687 688 ISAInfo->updateFLen(); 689 690 return std::move(ISAInfo); 691 } 692 693 void RISCVISAInfo::updateFLen() { 694 FLen = 0; 695 // TODO: Handle q extension. 696 if (Exts.count("d")) 697 FLen = 64; 698 else if (Exts.count("f")) 699 FLen = 32; 700 } 701 702 std::string RISCVISAInfo::toString() const { 703 std::string Buffer; 704 raw_string_ostream Arch(Buffer); 705 706 Arch << "rv" << XLen; 707 708 ListSeparator LS("_"); 709 for (auto &Ext : Exts) { 710 StringRef ExtName = Ext.first; 711 auto ExtInfo = Ext.second; 712 Arch << LS << ExtName; 713 Arch << ExtInfo.MajorVersion << "p" << ExtInfo.MinorVersion; 714 } 715 716 return Arch.str(); 717 } 718