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