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