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