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