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