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