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