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