1 //===-- RISCVISAInfo.cpp - RISC-V Arch String Parser ------------*- C++ -*-===// 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/STLExtras.h" 11 #include "llvm/ADT/SetVector.h" 12 #include "llvm/ADT/StringExtras.h" 13 #include "llvm/ADT/StringRef.h" 14 #include "llvm/Support/Errc.h" 15 #include "llvm/Support/Error.h" 16 #include "llvm/Support/raw_ostream.h" 17 18 #include <array> 19 #include <atomic> 20 #include <optional> 21 #include <string> 22 #include <vector> 23 24 using namespace llvm; 25 26 namespace { 27 28 struct RISCVSupportedExtension { 29 const char *Name; 30 /// Supported version. 31 RISCVISAInfo::ExtensionVersion Version; 32 33 bool operator<(const RISCVSupportedExtension &RHS) const { 34 return StringRef(Name) < StringRef(RHS.Name); 35 } 36 }; 37 38 } // end anonymous namespace 39 40 static constexpr StringLiteral AllStdExts = "mafdqlcbkjtpvnh"; 41 42 static const char *RISCVGImplications[] = { 43 "i", "m", "a", "f", "d", "zicsr", "zifencei" 44 }; 45 46 // NOTE: This table should be sorted alphabetically by extension name. 47 static const RISCVSupportedExtension SupportedExtensions[] = { 48 {"a", {2, 1}}, 49 {"c", {2, 0}}, 50 {"d", {2, 2}}, 51 {"e", {2, 0}}, 52 {"f", {2, 2}}, 53 {"h", {1, 0}}, 54 {"i", {2, 1}}, 55 {"m", {2, 0}}, 56 57 {"smaia", {1, 0}}, 58 {"smepmp", {1, 0}}, 59 {"ssaia", {1, 0}}, 60 {"svinval", {1, 0}}, 61 {"svnapot", {1, 0}}, 62 {"svpbmt", {1, 0}}, 63 64 {"v", {1, 0}}, 65 66 // vendor-defined ('X') extensions 67 {"xcvalu", {1, 0}}, 68 {"xcvbi", {1, 0}}, 69 {"xcvbitmanip", {1, 0}}, 70 {"xcvelw", {1, 0}}, 71 {"xcvmac", {1, 0}}, 72 {"xcvmem", {1, 0}}, 73 {"xcvsimd", {1, 0}}, 74 {"xsfvcp", {1, 0}}, 75 {"xsfvfnrclipxfqf", {1, 0}}, 76 {"xsfvfwmaccqqq", {1, 0}}, 77 {"xsfvqmaccdod", {1, 0}}, 78 {"xsfvqmaccqoq", {1, 0}}, 79 {"xtheadba", {1, 0}}, 80 {"xtheadbb", {1, 0}}, 81 {"xtheadbs", {1, 0}}, 82 {"xtheadcmo", {1, 0}}, 83 {"xtheadcondmov", {1, 0}}, 84 {"xtheadfmemidx", {1, 0}}, 85 {"xtheadmac", {1, 0}}, 86 {"xtheadmemidx", {1, 0}}, 87 {"xtheadmempair", {1, 0}}, 88 {"xtheadsync", {1, 0}}, 89 {"xtheadvdot", {1, 0}}, 90 {"xventanacondops", {1, 0}}, 91 92 {"za128rs", {1, 0}}, 93 {"za64rs", {1, 0}}, 94 {"zawrs", {1, 0}}, 95 96 {"zba", {1, 0}}, 97 {"zbb", {1, 0}}, 98 {"zbc", {1, 0}}, 99 {"zbkb", {1, 0}}, 100 {"zbkc", {1, 0}}, 101 {"zbkx", {1, 0}}, 102 {"zbs", {1, 0}}, 103 104 {"zca", {1, 0}}, 105 {"zcb", {1, 0}}, 106 {"zcd", {1, 0}}, 107 {"zce", {1, 0}}, 108 {"zcf", {1, 0}}, 109 {"zcmp", {1, 0}}, 110 {"zcmt", {1, 0}}, 111 112 {"zdinx", {1, 0}}, 113 114 {"zfa", {1, 0}}, 115 {"zfh", {1, 0}}, 116 {"zfhmin", {1, 0}}, 117 {"zfinx", {1, 0}}, 118 119 {"zhinx", {1, 0}}, 120 {"zhinxmin", {1, 0}}, 121 122 {"zic64b", {1, 0}}, 123 {"zicbom", {1, 0}}, 124 {"zicbop", {1, 0}}, 125 {"zicboz", {1, 0}}, 126 {"ziccamoa", {1, 0}}, 127 {"ziccif", {1, 0}}, 128 {"zicclsm", {1, 0}}, 129 {"ziccrse", {1, 0}}, 130 {"zicntr", {2, 0}}, 131 {"zicond", {1, 0}}, 132 {"zicsr", {2, 0}}, 133 {"zifencei", {2, 0}}, 134 {"zihintntl", {1, 0}}, 135 {"zihintpause", {2, 0}}, 136 {"zihpm", {2, 0}}, 137 138 {"zk", {1, 0}}, 139 {"zkn", {1, 0}}, 140 {"zknd", {1, 0}}, 141 {"zkne", {1, 0}}, 142 {"zknh", {1, 0}}, 143 {"zkr", {1, 0}}, 144 {"zks", {1, 0}}, 145 {"zksed", {1, 0}}, 146 {"zksh", {1, 0}}, 147 {"zkt", {1, 0}}, 148 149 {"zmmul", {1, 0}}, 150 151 {"zvbb", {1, 0}}, 152 {"zvbc", {1, 0}}, 153 154 {"zve32f", {1, 0}}, 155 {"zve32x", {1, 0}}, 156 {"zve64d", {1, 0}}, 157 {"zve64f", {1, 0}}, 158 {"zve64x", {1, 0}}, 159 160 {"zvfh", {1, 0}}, 161 {"zvfhmin", {1, 0}}, 162 163 // vector crypto 164 {"zvkb", {1, 0}}, 165 {"zvkg", {1, 0}}, 166 {"zvkn", {1, 0}}, 167 {"zvknc", {1, 0}}, 168 {"zvkned", {1, 0}}, 169 {"zvkng", {1, 0}}, 170 {"zvknha", {1, 0}}, 171 {"zvknhb", {1, 0}}, 172 {"zvks", {1, 0}}, 173 {"zvksc", {1, 0}}, 174 {"zvksed", {1, 0}}, 175 {"zvksg", {1, 0}}, 176 {"zvksh", {1, 0}}, 177 {"zvkt", {1, 0}}, 178 179 {"zvl1024b", {1, 0}}, 180 {"zvl128b", {1, 0}}, 181 {"zvl16384b", {1, 0}}, 182 {"zvl2048b", {1, 0}}, 183 {"zvl256b", {1, 0}}, 184 {"zvl32768b", {1, 0}}, 185 {"zvl32b", {1, 0}}, 186 {"zvl4096b", {1, 0}}, 187 {"zvl512b", {1, 0}}, 188 {"zvl64b", {1, 0}}, 189 {"zvl65536b", {1, 0}}, 190 {"zvl8192b", {1, 0}}, 191 }; 192 193 // NOTE: This table should be sorted alphabetically by extension name. 194 static const RISCVSupportedExtension SupportedExperimentalExtensions[] = { 195 {"zacas", {1, 0}}, 196 197 {"zcmop", {0, 2}}, 198 199 {"zfbfmin", {1, 0}}, 200 201 {"zicfilp", {0, 4}}, 202 {"zicfiss", {0, 4}}, 203 204 {"zimop", {0, 1}}, 205 206 {"ztso", {0, 1}}, 207 208 {"zvfbfmin", {1, 0}}, 209 {"zvfbfwma", {1, 0}}, 210 }; 211 212 static void verifyTables() { 213 #ifndef NDEBUG 214 static std::atomic<bool> TableChecked(false); 215 if (!TableChecked.load(std::memory_order_relaxed)) { 216 assert(llvm::is_sorted(SupportedExtensions) && 217 "Extensions are not sorted by name"); 218 assert(llvm::is_sorted(SupportedExperimentalExtensions) && 219 "Experimental extensions are not sorted by name"); 220 TableChecked.store(true, std::memory_order_relaxed); 221 } 222 #endif 223 } 224 225 static void PrintExtension(StringRef Name, StringRef Version, 226 StringRef Description) { 227 outs().indent(4); 228 unsigned VersionWidth = Description.empty() ? 0 : 10; 229 outs() << left_justify(Name, 20) << left_justify(Version, VersionWidth) 230 << Description << "\n"; 231 } 232 233 void llvm::riscvExtensionsHelp(StringMap<StringRef> DescMap) { 234 235 outs() << "All available -march extensions for RISC-V\n\n"; 236 PrintExtension("Name", "Version", (DescMap.empty() ? "" : "Description")); 237 238 RISCVISAInfo::OrderedExtensionMap ExtMap; 239 for (const auto &E : SupportedExtensions) 240 ExtMap[E.Name] = {E.Version.Major, E.Version.Minor}; 241 for (const auto &E : ExtMap) { 242 std::string Version = 243 std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor); 244 PrintExtension(E.first, Version, DescMap[E.first]); 245 } 246 247 outs() << "\nExperimental extensions\n"; 248 ExtMap.clear(); 249 for (const auto &E : SupportedExperimentalExtensions) 250 ExtMap[E.Name] = {E.Version.Major, E.Version.Minor}; 251 for (const auto &E : ExtMap) { 252 std::string Version = 253 std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor); 254 PrintExtension(E.first, Version, DescMap["experimental-" + E.first]); 255 } 256 257 outs() << "\nUse -march to specify the target's extension.\n" 258 "For example, clang -march=rv32i_v1p0\n"; 259 } 260 261 static bool stripExperimentalPrefix(StringRef &Ext) { 262 return Ext.consume_front("experimental-"); 263 } 264 265 // This function finds the last character that doesn't belong to a version 266 // (e.g. zba1p0 is extension 'zba' of version '1p0'). So the function will 267 // consume [0-9]*p[0-9]* starting from the backward. An extension name will not 268 // end with a digit or the letter 'p', so this function will parse correctly. 269 // NOTE: This function is NOT able to take empty strings or strings that only 270 // have version numbers and no extension name. It assumes the extension name 271 // will be at least more than one character. 272 static size_t findLastNonVersionCharacter(StringRef Ext) { 273 assert(!Ext.empty() && 274 "Already guarded by if-statement in ::parseArchString"); 275 276 int Pos = Ext.size() - 1; 277 while (Pos > 0 && isDigit(Ext[Pos])) 278 Pos--; 279 if (Pos > 0 && Ext[Pos] == 'p' && isDigit(Ext[Pos - 1])) { 280 Pos--; 281 while (Pos > 0 && isDigit(Ext[Pos])) 282 Pos--; 283 } 284 return Pos; 285 } 286 287 namespace { 288 struct LessExtName { 289 bool operator()(const RISCVSupportedExtension &LHS, StringRef RHS) { 290 return StringRef(LHS.Name) < RHS; 291 } 292 bool operator()(StringRef LHS, const RISCVSupportedExtension &RHS) { 293 return LHS < StringRef(RHS.Name); 294 } 295 }; 296 } // namespace 297 298 static std::optional<RISCVISAInfo::ExtensionVersion> 299 findDefaultVersion(StringRef ExtName) { 300 // Find default version of an extension. 301 // TODO: We might set default version based on profile or ISA spec. 302 for (auto &ExtInfo : {ArrayRef(SupportedExtensions), 303 ArrayRef(SupportedExperimentalExtensions)}) { 304 auto I = llvm::lower_bound(ExtInfo, ExtName, LessExtName()); 305 306 if (I == ExtInfo.end() || I->Name != ExtName) 307 continue; 308 309 return I->Version; 310 } 311 return std::nullopt; 312 } 313 314 void RISCVISAInfo::addExtension(StringRef ExtName, 315 RISCVISAInfo::ExtensionVersion Version) { 316 Exts[ExtName.str()] = Version; 317 } 318 319 static StringRef getExtensionTypeDesc(StringRef Ext) { 320 if (Ext.starts_with("s")) 321 return "standard supervisor-level extension"; 322 if (Ext.starts_with("x")) 323 return "non-standard user-level extension"; 324 if (Ext.starts_with("z")) 325 return "standard user-level extension"; 326 return StringRef(); 327 } 328 329 static StringRef getExtensionType(StringRef Ext) { 330 if (Ext.starts_with("s")) 331 return "s"; 332 if (Ext.starts_with("x")) 333 return "x"; 334 if (Ext.starts_with("z")) 335 return "z"; 336 return StringRef(); 337 } 338 339 static std::optional<RISCVISAInfo::ExtensionVersion> 340 isExperimentalExtension(StringRef Ext) { 341 auto I = 342 llvm::lower_bound(SupportedExperimentalExtensions, Ext, LessExtName()); 343 if (I == std::end(SupportedExperimentalExtensions) || I->Name != Ext) 344 return std::nullopt; 345 346 return I->Version; 347 } 348 349 bool RISCVISAInfo::isSupportedExtensionFeature(StringRef Ext) { 350 bool IsExperimental = stripExperimentalPrefix(Ext); 351 352 ArrayRef<RISCVSupportedExtension> ExtInfo = 353 IsExperimental ? ArrayRef(SupportedExperimentalExtensions) 354 : ArrayRef(SupportedExtensions); 355 356 auto I = llvm::lower_bound(ExtInfo, Ext, LessExtName()); 357 return I != ExtInfo.end() && I->Name == Ext; 358 } 359 360 bool RISCVISAInfo::isSupportedExtension(StringRef Ext) { 361 verifyTables(); 362 363 for (auto ExtInfo : {ArrayRef(SupportedExtensions), 364 ArrayRef(SupportedExperimentalExtensions)}) { 365 auto I = llvm::lower_bound(ExtInfo, Ext, LessExtName()); 366 if (I != ExtInfo.end() && I->Name == Ext) 367 return true; 368 } 369 370 return false; 371 } 372 373 bool RISCVISAInfo::isSupportedExtension(StringRef Ext, unsigned MajorVersion, 374 unsigned MinorVersion) { 375 for (auto ExtInfo : {ArrayRef(SupportedExtensions), 376 ArrayRef(SupportedExperimentalExtensions)}) { 377 auto Range = 378 std::equal_range(ExtInfo.begin(), ExtInfo.end(), Ext, LessExtName()); 379 for (auto I = Range.first, E = Range.second; I != E; ++I) 380 if (I->Version.Major == MajorVersion && I->Version.Minor == MinorVersion) 381 return true; 382 } 383 384 return false; 385 } 386 387 bool RISCVISAInfo::hasExtension(StringRef Ext) const { 388 stripExperimentalPrefix(Ext); 389 390 if (!isSupportedExtension(Ext)) 391 return false; 392 393 return Exts.count(Ext.str()) != 0; 394 } 395 396 // We rank extensions in the following order: 397 // -Single letter extensions in canonical order. 398 // -Unknown single letter extensions in alphabetical order. 399 // -Multi-letter extensions starting with 'z' sorted by canonical order of 400 // the second letter then sorted alphabetically. 401 // -Multi-letter extensions starting with 's' in alphabetical order. 402 // -(TODO) Multi-letter extensions starting with 'zxm' in alphabetical order. 403 // -X extensions in alphabetical order. 404 // These flags are used to indicate the category. The first 6 bits store the 405 // single letter extension rank for single letter and multi-letter extensions 406 // starting with 'z'. 407 enum RankFlags { 408 RF_Z_EXTENSION = 1 << 6, 409 RF_S_EXTENSION = 1 << 7, 410 RF_X_EXTENSION = 1 << 8, 411 }; 412 413 // Get the rank for single-letter extension, lower value meaning higher 414 // priority. 415 static unsigned singleLetterExtensionRank(char Ext) { 416 assert(Ext >= 'a' && Ext <= 'z'); 417 switch (Ext) { 418 case 'i': 419 return 0; 420 case 'e': 421 return 1; 422 } 423 424 size_t Pos = AllStdExts.find(Ext); 425 if (Pos != StringRef::npos) 426 return Pos + 2; // Skip 'e' and 'i' from above. 427 428 // If we got an unknown extension letter, then give it an alphabetical 429 // order, but after all known standard extensions. 430 return 2 + AllStdExts.size() + (Ext - 'a'); 431 } 432 433 // Get the rank for multi-letter extension, lower value meaning higher 434 // priority/order in canonical order. 435 static unsigned getExtensionRank(const std::string &ExtName) { 436 assert(ExtName.size() >= 1); 437 switch (ExtName[0]) { 438 case 's': 439 return RF_S_EXTENSION; 440 case 'z': 441 assert(ExtName.size() >= 2); 442 // `z` extension must be sorted by canonical order of second letter. 443 // e.g. zmx has higher rank than zax. 444 return RF_Z_EXTENSION | singleLetterExtensionRank(ExtName[1]); 445 case 'x': 446 return RF_X_EXTENSION; 447 default: 448 assert(ExtName.size() == 1); 449 return singleLetterExtensionRank(ExtName[0]); 450 } 451 } 452 453 // Compare function for extension. 454 // Only compare the extension name, ignore version comparison. 455 bool RISCVISAInfo::compareExtension(const std::string &LHS, 456 const std::string &RHS) { 457 unsigned LHSRank = getExtensionRank(LHS); 458 unsigned RHSRank = getExtensionRank(RHS); 459 460 // If the ranks differ, pick the lower rank. 461 if (LHSRank != RHSRank) 462 return LHSRank < RHSRank; 463 464 // If the rank is same, it must be sorted by lexicographic order. 465 return LHS < RHS; 466 } 467 468 std::vector<std::string> RISCVISAInfo::toFeatures(bool AddAllExtensions, 469 bool IgnoreUnknown) const { 470 std::vector<std::string> Features; 471 for (const auto &[ExtName, _] : Exts) { 472 // i is a base instruction set, not an extension (see 473 // https://github.com/riscv/riscv-isa-manual/blob/main/src/naming.adoc#base-integer-isa) 474 // and is not recognized in clang -cc1 475 if (ExtName == "i") 476 continue; 477 if (IgnoreUnknown && !isSupportedExtension(ExtName)) 478 continue; 479 480 if (isExperimentalExtension(ExtName)) { 481 Features.push_back((llvm::Twine("+experimental-") + ExtName).str()); 482 } else { 483 Features.push_back((llvm::Twine("+") + ExtName).str()); 484 } 485 } 486 if (AddAllExtensions) { 487 for (const RISCVSupportedExtension &Ext : SupportedExtensions) { 488 if (Exts.count(Ext.Name)) 489 continue; 490 Features.push_back((llvm::Twine("-") + Ext.Name).str()); 491 } 492 493 for (const RISCVSupportedExtension &Ext : SupportedExperimentalExtensions) { 494 if (Exts.count(Ext.Name)) 495 continue; 496 Features.push_back((llvm::Twine("-experimental-") + Ext.Name).str()); 497 } 498 } 499 return Features; 500 } 501 502 // Extensions may have a version number, and may be separated by 503 // an underscore '_' e.g.: rv32i2_m2. 504 // Version number is divided into major and minor version numbers, 505 // separated by a 'p'. If the minor version is 0 then 'p0' can be 506 // omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1. 507 static Error getExtensionVersion(StringRef Ext, StringRef In, unsigned &Major, 508 unsigned &Minor, unsigned &ConsumeLength, 509 bool EnableExperimentalExtension, 510 bool ExperimentalExtensionVersionCheck) { 511 StringRef MajorStr, MinorStr; 512 Major = 0; 513 Minor = 0; 514 ConsumeLength = 0; 515 MajorStr = In.take_while(isDigit); 516 In = In.substr(MajorStr.size()); 517 518 if (!MajorStr.empty() && In.consume_front("p")) { 519 MinorStr = In.take_while(isDigit); 520 In = In.substr(MajorStr.size() + MinorStr.size() - 1); 521 522 // Expected 'p' to be followed by minor version number. 523 if (MinorStr.empty()) { 524 return createStringError( 525 errc::invalid_argument, 526 "minor version number missing after 'p' for extension '" + Ext + "'"); 527 } 528 } 529 530 if (!MajorStr.empty() && MajorStr.getAsInteger(10, Major)) 531 return createStringError( 532 errc::invalid_argument, 533 "Failed to parse major version number for extension '" + Ext + "'"); 534 535 if (!MinorStr.empty() && MinorStr.getAsInteger(10, Minor)) 536 return createStringError( 537 errc::invalid_argument, 538 "Failed to parse minor version number for extension '" + Ext + "'"); 539 540 ConsumeLength = MajorStr.size(); 541 542 if (!MinorStr.empty()) 543 ConsumeLength += MinorStr.size() + 1 /*'p'*/; 544 545 // Expected multi-character extension with version number to have no 546 // subsequent characters (i.e. must either end string or be followed by 547 // an underscore). 548 if (Ext.size() > 1 && In.size()) { 549 std::string Error = 550 "multi-character extensions must be separated by underscores"; 551 return createStringError(errc::invalid_argument, Error); 552 } 553 554 // If experimental extension, require use of current version number 555 if (auto ExperimentalExtension = isExperimentalExtension(Ext)) { 556 if (!EnableExperimentalExtension) { 557 std::string Error = "requires '-menable-experimental-extensions' for " 558 "experimental extension '" + 559 Ext.str() + "'"; 560 return createStringError(errc::invalid_argument, Error); 561 } 562 563 if (ExperimentalExtensionVersionCheck && 564 (MajorStr.empty() && MinorStr.empty())) { 565 std::string Error = 566 "experimental extension requires explicit version number `" + 567 Ext.str() + "`"; 568 return createStringError(errc::invalid_argument, Error); 569 } 570 571 auto SupportedVers = *ExperimentalExtension; 572 if (ExperimentalExtensionVersionCheck && 573 (Major != SupportedVers.Major || Minor != SupportedVers.Minor)) { 574 std::string Error = "unsupported version number " + MajorStr.str(); 575 if (!MinorStr.empty()) 576 Error += "." + MinorStr.str(); 577 Error += " for experimental extension '" + Ext.str() + 578 "' (this compiler supports " + utostr(SupportedVers.Major) + 579 "." + utostr(SupportedVers.Minor) + ")"; 580 return createStringError(errc::invalid_argument, Error); 581 } 582 return Error::success(); 583 } 584 585 // Exception rule for `g`, we don't have clear version scheme for that on 586 // ISA spec. 587 if (Ext == "g") 588 return Error::success(); 589 590 if (MajorStr.empty() && MinorStr.empty()) { 591 if (auto DefaultVersion = findDefaultVersion(Ext)) { 592 Major = DefaultVersion->Major; 593 Minor = DefaultVersion->Minor; 594 } 595 // No matter found or not, return success, assume other place will 596 // verify. 597 return Error::success(); 598 } 599 600 if (RISCVISAInfo::isSupportedExtension(Ext, Major, Minor)) 601 return Error::success(); 602 603 std::string Error = "unsupported version number " + std::string(MajorStr); 604 if (!MinorStr.empty()) 605 Error += "." + MinorStr.str(); 606 Error += " for extension '" + Ext.str() + "'"; 607 return createStringError(errc::invalid_argument, Error); 608 } 609 610 llvm::Expected<std::unique_ptr<RISCVISAInfo>> 611 RISCVISAInfo::parseFeatures(unsigned XLen, 612 const std::vector<std::string> &Features) { 613 assert(XLen == 32 || XLen == 64); 614 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen)); 615 616 for (auto &Feature : Features) { 617 StringRef ExtName = Feature; 618 bool Experimental = false; 619 assert(ExtName.size() > 1 && (ExtName[0] == '+' || ExtName[0] == '-')); 620 bool Add = ExtName[0] == '+'; 621 ExtName = ExtName.drop_front(1); // Drop '+' or '-' 622 Experimental = stripExperimentalPrefix(ExtName); 623 auto ExtensionInfos = Experimental 624 ? ArrayRef(SupportedExperimentalExtensions) 625 : ArrayRef(SupportedExtensions); 626 auto ExtensionInfoIterator = 627 llvm::lower_bound(ExtensionInfos, ExtName, LessExtName()); 628 629 // Not all features is related to ISA extension, like `relax` or 630 // `save-restore`, skip those feature. 631 if (ExtensionInfoIterator == ExtensionInfos.end() || 632 ExtensionInfoIterator->Name != ExtName) 633 continue; 634 635 if (Add) 636 ISAInfo->addExtension(ExtName, ExtensionInfoIterator->Version); 637 else 638 ISAInfo->Exts.erase(ExtName.str()); 639 } 640 641 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo)); 642 } 643 644 llvm::Expected<std::unique_ptr<RISCVISAInfo>> 645 RISCVISAInfo::parseNormalizedArchString(StringRef Arch) { 646 if (llvm::any_of(Arch, isupper)) { 647 return createStringError(errc::invalid_argument, 648 "string must be lowercase"); 649 } 650 // Must start with a valid base ISA name. 651 unsigned XLen; 652 if (Arch.starts_with("rv32i") || Arch.starts_with("rv32e")) 653 XLen = 32; 654 else if (Arch.starts_with("rv64i") || Arch.starts_with("rv64e")) 655 XLen = 64; 656 else 657 return createStringError(errc::invalid_argument, 658 "arch string must begin with valid base ISA"); 659 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen)); 660 // Discard rv32/rv64 prefix. 661 Arch = Arch.substr(4); 662 663 // Each extension is of the form ${name}${major_version}p${minor_version} 664 // and separated by _. Split by _ and then extract the name and version 665 // information for each extension. 666 SmallVector<StringRef, 8> Split; 667 Arch.split(Split, '_'); 668 for (StringRef Ext : Split) { 669 StringRef Prefix, MinorVersionStr; 670 std::tie(Prefix, MinorVersionStr) = Ext.rsplit('p'); 671 if (MinorVersionStr.empty()) 672 return createStringError(errc::invalid_argument, 673 "extension lacks version in expected format"); 674 unsigned MajorVersion, MinorVersion; 675 if (MinorVersionStr.getAsInteger(10, MinorVersion)) 676 return createStringError(errc::invalid_argument, 677 "failed to parse minor version number"); 678 679 // Split Prefix into the extension name and the major version number 680 // (the trailing digits of Prefix). 681 int TrailingDigits = 0; 682 StringRef ExtName = Prefix; 683 while (!ExtName.empty()) { 684 if (!isDigit(ExtName.back())) 685 break; 686 ExtName = ExtName.drop_back(1); 687 TrailingDigits++; 688 } 689 if (!TrailingDigits) 690 return createStringError(errc::invalid_argument, 691 "extension lacks version in expected format"); 692 693 StringRef MajorVersionStr = Prefix.take_back(TrailingDigits); 694 if (MajorVersionStr.getAsInteger(10, MajorVersion)) 695 return createStringError(errc::invalid_argument, 696 "failed to parse major version number"); 697 ISAInfo->addExtension(ExtName, {MajorVersion, MinorVersion}); 698 } 699 ISAInfo->updateFLen(); 700 ISAInfo->updateMinVLen(); 701 ISAInfo->updateMaxELen(); 702 return std::move(ISAInfo); 703 } 704 705 llvm::Expected<std::unique_ptr<RISCVISAInfo>> 706 RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension, 707 bool ExperimentalExtensionVersionCheck, 708 bool IgnoreUnknown) { 709 // RISC-V ISA strings must be lowercase. 710 if (llvm::any_of(Arch, isupper)) { 711 return createStringError(errc::invalid_argument, 712 "string must be lowercase"); 713 } 714 715 bool HasRV64 = Arch.starts_with("rv64"); 716 // ISA string must begin with rv32 or rv64. 717 if (!(Arch.starts_with("rv32") || HasRV64) || (Arch.size() < 5)) { 718 return createStringError( 719 errc::invalid_argument, 720 "string must begin with rv32{i,e,g} or rv64{i,e,g}"); 721 } 722 723 unsigned XLen = HasRV64 ? 64 : 32; 724 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen)); 725 726 // The canonical order specified in ISA manual. 727 // Ref: Table 22.1 in RISC-V User-Level ISA V2.2 728 StringRef StdExts = AllStdExts; 729 char Baseline = Arch[4]; 730 731 // First letter should be 'e', 'i' or 'g'. 732 switch (Baseline) { 733 default: 734 return createStringError(errc::invalid_argument, 735 "first letter should be 'e', 'i' or 'g'"); 736 case 'e': 737 case 'i': 738 break; 739 case 'g': 740 // g expands to extensions in RISCVGImplications. 741 if (Arch.size() > 5 && isDigit(Arch[5])) 742 return createStringError(errc::invalid_argument, 743 "version not supported for 'g'"); 744 StdExts = StdExts.drop_front(4); 745 break; 746 } 747 748 if (Arch.back() == '_') 749 return createStringError(errc::invalid_argument, 750 "extension name missing after separator '_'"); 751 752 // Skip rvxxx 753 StringRef Exts = Arch.substr(5); 754 755 // Remove multi-letter standard extensions, non-standard extensions and 756 // supervisor-level extensions. They have 'z', 'x', 's' prefixes. 757 // Parse them at the end. 758 // Find the very first occurrence of 's', 'x' or 'z'. 759 StringRef OtherExts; 760 size_t Pos = Exts.find_first_of("zsx"); 761 if (Pos != StringRef::npos) { 762 OtherExts = Exts.substr(Pos); 763 Exts = Exts.substr(0, Pos); 764 } 765 766 unsigned Major, Minor, ConsumeLength; 767 if (Baseline == 'g') { 768 // Versions for g are disallowed, and this was checked for previously. 769 ConsumeLength = 0; 770 771 // No matter which version is given to `g`, we always set imafd to default 772 // version since the we don't have clear version scheme for that on 773 // ISA spec. 774 for (const auto *Ext : RISCVGImplications) { 775 if (auto Version = findDefaultVersion(Ext)) 776 ISAInfo->addExtension(Ext, *Version); 777 else 778 llvm_unreachable("Default extension version not found?"); 779 } 780 } else { 781 // Baseline is `i` or `e` 782 if (auto E = getExtensionVersion( 783 StringRef(&Baseline, 1), Exts, Major, Minor, ConsumeLength, 784 EnableExperimentalExtension, ExperimentalExtensionVersionCheck)) { 785 if (!IgnoreUnknown) 786 return std::move(E); 787 // If IgnoreUnknown, then ignore an unrecognised version of the baseline 788 // ISA and just use the default supported version. 789 consumeError(std::move(E)); 790 auto Version = findDefaultVersion(StringRef(&Baseline, 1)); 791 Major = Version->Major; 792 Minor = Version->Minor; 793 } 794 795 ISAInfo->addExtension(StringRef(&Baseline, 1), {Major, Minor}); 796 } 797 798 // Consume the base ISA version number and any '_' between rvxxx and the 799 // first extension 800 Exts = Exts.drop_front(ConsumeLength); 801 Exts.consume_front("_"); 802 803 auto StdExtsItr = StdExts.begin(); 804 auto StdExtsEnd = StdExts.end(); 805 auto GoToNextExt = [](StringRef::iterator &I, unsigned ConsumeLength, 806 StringRef::iterator E) { 807 I += 1 + ConsumeLength; 808 if (I != E && *I == '_') 809 ++I; 810 }; 811 for (auto I = Exts.begin(), E = Exts.end(); I != E;) { 812 char C = *I; 813 814 // Check ISA extensions are specified in the canonical order. 815 while (StdExtsItr != StdExtsEnd && *StdExtsItr != C) 816 ++StdExtsItr; 817 818 if (StdExtsItr == StdExtsEnd) { 819 // Either c contains a valid extension but it was not given in 820 // canonical order or it is an invalid extension. 821 if (StdExts.contains(C)) { 822 return createStringError( 823 errc::invalid_argument, 824 "standard user-level extension not given in canonical order '%c'", 825 C); 826 } 827 828 return createStringError(errc::invalid_argument, 829 "invalid standard user-level extension '%c'", C); 830 } 831 832 // Move to next char to prevent repeated letter. 833 ++StdExtsItr; 834 835 StringRef Next; 836 unsigned Major, Minor, ConsumeLength; 837 if (std::next(I) != E) 838 Next = StringRef(std::next(I), E - std::next(I)); 839 if (auto E = getExtensionVersion(StringRef(&C, 1), Next, Major, Minor, 840 ConsumeLength, EnableExperimentalExtension, 841 ExperimentalExtensionVersionCheck)) { 842 if (IgnoreUnknown) { 843 consumeError(std::move(E)); 844 GoToNextExt(I, ConsumeLength, Exts.end()); 845 continue; 846 } 847 return std::move(E); 848 } 849 850 // The order is OK, then push it into features. 851 // Currently LLVM supports only "mafdcvh". 852 if (!isSupportedExtension(StringRef(&C, 1))) { 853 if (IgnoreUnknown) { 854 GoToNextExt(I, ConsumeLength, Exts.end()); 855 continue; 856 } 857 return createStringError(errc::invalid_argument, 858 "unsupported standard user-level extension '%c'", 859 C); 860 } 861 ISAInfo->addExtension(StringRef(&C, 1), {Major, Minor}); 862 863 // Consume full extension name and version, including any optional '_' 864 // between this extension and the next 865 GoToNextExt(I, ConsumeLength, Exts.end()); 866 } 867 868 // Handle other types of extensions other than the standard 869 // general purpose and standard user-level extensions. 870 // Parse the ISA string containing non-standard user-level 871 // extensions, standard supervisor-level extensions and 872 // non-standard supervisor-level extensions. 873 // These extensions start with 'z', 's', 'x' prefixes, might have a version 874 // number (major, minor) and are separated by a single underscore '_'. We do 875 // not enforce a canonical order for them. 876 // Set the hardware features for the extensions that are supported. 877 878 // Multi-letter extensions are seperated by a single underscore 879 // as described in RISC-V User-Level ISA V2.2. 880 SmallVector<StringRef, 8> Split; 881 OtherExts.split(Split, '_'); 882 883 SmallVector<StringRef, 8> AllExts; 884 if (Split.size() > 1 || Split[0] != "") { 885 for (StringRef Ext : Split) { 886 if (Ext.empty()) 887 return createStringError(errc::invalid_argument, 888 "extension name missing after separator '_'"); 889 890 StringRef Type = getExtensionType(Ext); 891 StringRef Desc = getExtensionTypeDesc(Ext); 892 auto Pos = findLastNonVersionCharacter(Ext) + 1; 893 StringRef Name(Ext.substr(0, Pos)); 894 StringRef Vers(Ext.substr(Pos)); 895 896 if (Type.empty()) { 897 if (IgnoreUnknown) 898 continue; 899 return createStringError(errc::invalid_argument, 900 "invalid extension prefix '" + Ext + "'"); 901 } 902 903 if (!IgnoreUnknown && Name.size() == Type.size()) { 904 return createStringError(errc::invalid_argument, 905 "%s name missing after '%s'", 906 Desc.str().c_str(), Type.str().c_str()); 907 } 908 909 unsigned Major, Minor, ConsumeLength; 910 if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength, 911 EnableExperimentalExtension, 912 ExperimentalExtensionVersionCheck)) { 913 if (IgnoreUnknown) { 914 consumeError(std::move(E)); 915 continue; 916 } 917 return std::move(E); 918 } 919 920 // Check if duplicated extension. 921 if (!IgnoreUnknown && llvm::is_contained(AllExts, Name)) { 922 return createStringError(errc::invalid_argument, "duplicated %s '%s'", 923 Desc.str().c_str(), Name.str().c_str()); 924 } 925 926 if (IgnoreUnknown && !isSupportedExtension(Name)) 927 continue; 928 929 ISAInfo->addExtension(Name, {Major, Minor}); 930 // Extension format is correct, keep parsing the extensions. 931 // TODO: Save Type, Name, Major, Minor to avoid parsing them later. 932 AllExts.push_back(Name); 933 } 934 } 935 936 for (auto Ext : AllExts) { 937 if (!isSupportedExtension(Ext)) { 938 StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext)); 939 return createStringError(errc::invalid_argument, "unsupported %s '%s'", 940 Desc.str().c_str(), Ext.str().c_str()); 941 } 942 } 943 944 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo)); 945 } 946 947 Error RISCVISAInfo::checkDependency() { 948 bool HasC = Exts.count("c") != 0; 949 bool HasF = Exts.count("f") != 0; 950 bool HasZfinx = Exts.count("zfinx") != 0; 951 bool HasVector = Exts.count("zve32x") != 0; 952 bool HasZvl = MinVLen != 0; 953 bool HasZcmt = Exts.count("zcmt") != 0; 954 955 if (HasF && HasZfinx) 956 return createStringError(errc::invalid_argument, 957 "'f' and 'zfinx' extensions are incompatible"); 958 959 if (HasZvl && !HasVector) 960 return createStringError( 961 errc::invalid_argument, 962 "'zvl*b' requires 'v' or 'zve*' extension to also be specified"); 963 964 if (Exts.count("zvbb") && !HasVector) 965 return createStringError( 966 errc::invalid_argument, 967 "'zvbb' requires 'v' or 'zve*' extension to also be specified"); 968 969 if (Exts.count("zvbc") && !Exts.count("zve64x")) 970 return createStringError( 971 errc::invalid_argument, 972 "'zvbc' requires 'v' or 'zve64*' extension to also be specified"); 973 974 if ((Exts.count("zvkg") || Exts.count("zvkned") || Exts.count("zvknha") || 975 Exts.count("zvksed") || Exts.count("zvksh")) && 976 !HasVector) 977 return createStringError( 978 errc::invalid_argument, 979 "'zvk*' requires 'v' or 'zve*' extension to also be specified"); 980 981 if (Exts.count("zvknhb") && !Exts.count("zve64x")) 982 return createStringError( 983 errc::invalid_argument, 984 "'zvknhb' requires 'v' or 'zve64*' extension to also be specified"); 985 986 if ((HasZcmt || Exts.count("zcmp")) && Exts.count("d") && 987 (HasC || Exts.count("zcd"))) 988 return createStringError( 989 errc::invalid_argument, 990 Twine("'") + (HasZcmt ? "zcmt" : "zcmp") + 991 "' extension is incompatible with '" + (HasC ? "c" : "zcd") + 992 "' extension when 'd' extension is enabled"); 993 994 if (XLen != 32 && Exts.count("zcf")) 995 return createStringError(errc::invalid_argument, 996 "'zcf' is only supported for 'rv32'"); 997 998 return Error::success(); 999 } 1000 1001 static const char *ImpliedExtsD[] = {"f"}; 1002 static const char *ImpliedExtsF[] = {"zicsr"}; 1003 static const char *ImpliedExtsV[] = {"zvl128b", "zve64d"}; 1004 static const char *ImpliedExtsXTHeadVdot[] = {"v"}; 1005 static const char *ImpliedExtsXSfvcp[] = {"zve32x"}; 1006 static const char *ImpliedExtsXSfvfnrclipxfqf[] = {"zve32f"}; 1007 static const char *ImpliedExtsXSfvfwmaccqqq[] = {"zvfbfmin"}; 1008 static const char *ImpliedExtsXSfvqmaccdod[] = {"zve32x"}; 1009 static const char *ImpliedExtsXSfvqmaccqoq[] = {"zve32x"}; 1010 static const char *ImpliedExtsZacas[] = {"a"}; 1011 static const char *ImpliedExtsZcb[] = {"zca"}; 1012 static const char *ImpliedExtsZcd[] = {"d", "zca"}; 1013 static const char *ImpliedExtsZce[] = {"zcb", "zcmp", "zcmt"}; 1014 static const char *ImpliedExtsZcf[] = {"f", "zca"}; 1015 static const char *ImpliedExtsZcmop[] = {"zca"}; 1016 static const char *ImpliedExtsZcmp[] = {"zca"}; 1017 static const char *ImpliedExtsZcmt[] = {"zca", "zicsr"}; 1018 static const char *ImpliedExtsZdinx[] = {"zfinx"}; 1019 static const char *ImpliedExtsZfa[] = {"f"}; 1020 static const char *ImpliedExtsZfbfmin[] = {"f"}; 1021 static const char *ImpliedExtsZfh[] = {"zfhmin"}; 1022 static const char *ImpliedExtsZfhmin[] = {"f"}; 1023 static const char *ImpliedExtsZfinx[] = {"zicsr"}; 1024 static const char *ImpliedExtsZhinx[] = {"zhinxmin"}; 1025 static const char *ImpliedExtsZhinxmin[] = {"zfinx"}; 1026 static const char *ImpliedExtsZicntr[] = {"zicsr"}; 1027 static const char *ImpliedExtsZicfiss[] = {"zicsr", "zimop"}; 1028 static const char *ImpliedExtsZihpm[] = {"zicsr"}; 1029 static const char *ImpliedExtsZk[] = {"zkn", "zkt", "zkr"}; 1030 static const char *ImpliedExtsZkn[] = {"zbkb", "zbkc", "zbkx", 1031 "zkne", "zknd", "zknh"}; 1032 static const char *ImpliedExtsZks[] = {"zbkb", "zbkc", "zbkx", "zksed", "zksh"}; 1033 static const char *ImpliedExtsZvbb[] = {"zvkb"}; 1034 static const char *ImpliedExtsZve32f[] = {"zve32x", "f"}; 1035 static const char *ImpliedExtsZve32x[] = {"zvl32b", "zicsr"}; 1036 static const char *ImpliedExtsZve64d[] = {"zve64f", "d"}; 1037 static const char *ImpliedExtsZve64f[] = {"zve64x", "zve32f"}; 1038 static const char *ImpliedExtsZve64x[] = {"zve32x", "zvl64b"}; 1039 static const char *ImpliedExtsZvfbfmin[] = {"zve32f"}; 1040 static const char *ImpliedExtsZvfbfwma[] = {"zvfbfmin", "zfbfmin"}; 1041 static const char *ImpliedExtsZvfh[] = {"zvfhmin", "zfhmin"}; 1042 static const char *ImpliedExtsZvfhmin[] = {"zve32f"}; 1043 static const char *ImpliedExtsZvkn[] = {"zvkb", "zvkned", "zvknhb", "zvkt"}; 1044 static const char *ImpliedExtsZvknc[] = {"zvbc", "zvkn"}; 1045 static const char *ImpliedExtsZvkng[] = {"zvkg", "zvkn"}; 1046 static const char *ImpliedExtsZvknhb[] = {"zve64x"}; 1047 static const char *ImpliedExtsZvks[] = {"zvkb", "zvksed", "zvksh", "zvkt"}; 1048 static const char *ImpliedExtsZvksc[] = {"zvbc", "zvks"}; 1049 static const char *ImpliedExtsZvksg[] = {"zvkg", "zvks"}; 1050 static const char *ImpliedExtsZvl1024b[] = {"zvl512b"}; 1051 static const char *ImpliedExtsZvl128b[] = {"zvl64b"}; 1052 static const char *ImpliedExtsZvl16384b[] = {"zvl8192b"}; 1053 static const char *ImpliedExtsZvl2048b[] = {"zvl1024b"}; 1054 static const char *ImpliedExtsZvl256b[] = {"zvl128b"}; 1055 static const char *ImpliedExtsZvl32768b[] = {"zvl16384b"}; 1056 static const char *ImpliedExtsZvl4096b[] = {"zvl2048b"}; 1057 static const char *ImpliedExtsZvl512b[] = {"zvl256b"}; 1058 static const char *ImpliedExtsZvl64b[] = {"zvl32b"}; 1059 static const char *ImpliedExtsZvl65536b[] = {"zvl32768b"}; 1060 static const char *ImpliedExtsZvl8192b[] = {"zvl4096b"}; 1061 1062 struct ImpliedExtsEntry { 1063 StringLiteral Name; 1064 ArrayRef<const char *> Exts; 1065 1066 bool operator<(const ImpliedExtsEntry &Other) const { 1067 return Name < Other.Name; 1068 } 1069 1070 bool operator<(StringRef Other) const { return Name < Other; } 1071 }; 1072 1073 // Note: The table needs to be sorted by name. 1074 static constexpr ImpliedExtsEntry ImpliedExts[] = { 1075 {{"d"}, {ImpliedExtsD}}, 1076 {{"f"}, {ImpliedExtsF}}, 1077 {{"v"}, {ImpliedExtsV}}, 1078 {{"xsfvcp"}, {ImpliedExtsXSfvcp}}, 1079 {{"xsfvfnrclipxfqf"}, {ImpliedExtsXSfvfnrclipxfqf}}, 1080 {{"xsfvfwmaccqqq"}, {ImpliedExtsXSfvfwmaccqqq}}, 1081 {{"xsfvqmaccdod"}, {ImpliedExtsXSfvqmaccdod}}, 1082 {{"xsfvqmaccqoq"}, {ImpliedExtsXSfvqmaccqoq}}, 1083 {{"xtheadvdot"}, {ImpliedExtsXTHeadVdot}}, 1084 {{"zacas"}, {ImpliedExtsZacas}}, 1085 {{"zcb"}, {ImpliedExtsZcb}}, 1086 {{"zcd"}, {ImpliedExtsZcd}}, 1087 {{"zce"}, {ImpliedExtsZce}}, 1088 {{"zcf"}, {ImpliedExtsZcf}}, 1089 {{"zcmop"}, {ImpliedExtsZcmop}}, 1090 {{"zcmp"}, {ImpliedExtsZcmp}}, 1091 {{"zcmt"}, {ImpliedExtsZcmt}}, 1092 {{"zdinx"}, {ImpliedExtsZdinx}}, 1093 {{"zfa"}, {ImpliedExtsZfa}}, 1094 {{"zfbfmin"}, {ImpliedExtsZfbfmin}}, 1095 {{"zfh"}, {ImpliedExtsZfh}}, 1096 {{"zfhmin"}, {ImpliedExtsZfhmin}}, 1097 {{"zfinx"}, {ImpliedExtsZfinx}}, 1098 {{"zhinx"}, {ImpliedExtsZhinx}}, 1099 {{"zhinxmin"}, {ImpliedExtsZhinxmin}}, 1100 {{"zicfiss"}, {ImpliedExtsZicfiss}}, 1101 {{"zicntr"}, {ImpliedExtsZicntr}}, 1102 {{"zihpm"}, {ImpliedExtsZihpm}}, 1103 {{"zk"}, {ImpliedExtsZk}}, 1104 {{"zkn"}, {ImpliedExtsZkn}}, 1105 {{"zks"}, {ImpliedExtsZks}}, 1106 {{"zvbb"}, {ImpliedExtsZvbb}}, 1107 {{"zve32f"}, {ImpliedExtsZve32f}}, 1108 {{"zve32x"}, {ImpliedExtsZve32x}}, 1109 {{"zve64d"}, {ImpliedExtsZve64d}}, 1110 {{"zve64f"}, {ImpliedExtsZve64f}}, 1111 {{"zve64x"}, {ImpliedExtsZve64x}}, 1112 {{"zvfbfmin"}, {ImpliedExtsZvfbfmin}}, 1113 {{"zvfbfwma"}, {ImpliedExtsZvfbfwma}}, 1114 {{"zvfh"}, {ImpliedExtsZvfh}}, 1115 {{"zvfhmin"}, {ImpliedExtsZvfhmin}}, 1116 {{"zvkn"}, {ImpliedExtsZvkn}}, 1117 {{"zvknc"}, {ImpliedExtsZvknc}}, 1118 {{"zvkng"}, {ImpliedExtsZvkng}}, 1119 {{"zvknhb"}, {ImpliedExtsZvknhb}}, 1120 {{"zvks"}, {ImpliedExtsZvks}}, 1121 {{"zvksc"}, {ImpliedExtsZvksc}}, 1122 {{"zvksg"}, {ImpliedExtsZvksg}}, 1123 {{"zvl1024b"}, {ImpliedExtsZvl1024b}}, 1124 {{"zvl128b"}, {ImpliedExtsZvl128b}}, 1125 {{"zvl16384b"}, {ImpliedExtsZvl16384b}}, 1126 {{"zvl2048b"}, {ImpliedExtsZvl2048b}}, 1127 {{"zvl256b"}, {ImpliedExtsZvl256b}}, 1128 {{"zvl32768b"}, {ImpliedExtsZvl32768b}}, 1129 {{"zvl4096b"}, {ImpliedExtsZvl4096b}}, 1130 {{"zvl512b"}, {ImpliedExtsZvl512b}}, 1131 {{"zvl64b"}, {ImpliedExtsZvl64b}}, 1132 {{"zvl65536b"}, {ImpliedExtsZvl65536b}}, 1133 {{"zvl8192b"}, {ImpliedExtsZvl8192b}}, 1134 }; 1135 1136 void RISCVISAInfo::updateImplication() { 1137 bool HasE = Exts.count("e") != 0; 1138 bool HasI = Exts.count("i") != 0; 1139 1140 // If not in e extension and i extension does not exist, i extension is 1141 // implied 1142 if (!HasE && !HasI) { 1143 auto Version = findDefaultVersion("i"); 1144 addExtension("i", Version.value()); 1145 } 1146 1147 assert(llvm::is_sorted(ImpliedExts) && "Table not sorted by Name"); 1148 1149 // This loop may execute over 1 iteration since implication can be layered 1150 // Exits loop if no more implication is applied 1151 SmallSetVector<StringRef, 16> WorkList; 1152 for (auto const &Ext : Exts) 1153 WorkList.insert(Ext.first); 1154 1155 while (!WorkList.empty()) { 1156 StringRef ExtName = WorkList.pop_back_val(); 1157 auto I = llvm::lower_bound(ImpliedExts, ExtName); 1158 if (I != std::end(ImpliedExts) && I->Name == ExtName) { 1159 for (const char *ImpliedExt : I->Exts) { 1160 if (WorkList.count(ImpliedExt)) 1161 continue; 1162 if (Exts.count(ImpliedExt)) 1163 continue; 1164 auto Version = findDefaultVersion(ImpliedExt); 1165 addExtension(ImpliedExt, Version.value()); 1166 WorkList.insert(ImpliedExt); 1167 } 1168 } 1169 } 1170 1171 // Add Zcf if Zce and F are enabled on RV32. 1172 if (XLen == 32 && Exts.count("zce") && Exts.count("f") && 1173 !Exts.count("zcf")) { 1174 auto Version = findDefaultVersion("zcf"); 1175 addExtension("zcf", Version.value()); 1176 } 1177 } 1178 1179 struct CombinedExtsEntry { 1180 StringLiteral CombineExt; 1181 ArrayRef<const char *> RequiredExts; 1182 }; 1183 1184 static constexpr CombinedExtsEntry CombineIntoExts[] = { 1185 {{"zk"}, {ImpliedExtsZk}}, 1186 {{"zkn"}, {ImpliedExtsZkn}}, 1187 {{"zks"}, {ImpliedExtsZks}}, 1188 {{"zvkn"}, {ImpliedExtsZvkn}}, 1189 {{"zvknc"}, {ImpliedExtsZvknc}}, 1190 {{"zvkng"}, {ImpliedExtsZvkng}}, 1191 {{"zvks"}, {ImpliedExtsZvks}}, 1192 {{"zvksc"}, {ImpliedExtsZvksc}}, 1193 {{"zvksg"}, {ImpliedExtsZvksg}}, 1194 }; 1195 1196 void RISCVISAInfo::updateCombination() { 1197 bool IsNewCombine = false; 1198 do { 1199 IsNewCombine = false; 1200 for (CombinedExtsEntry CombineIntoExt : CombineIntoExts) { 1201 auto CombineExt = CombineIntoExt.CombineExt; 1202 auto RequiredExts = CombineIntoExt.RequiredExts; 1203 if (hasExtension(CombineExt)) 1204 continue; 1205 bool IsAllRequiredFeatureExist = true; 1206 for (const char *Ext : RequiredExts) 1207 IsAllRequiredFeatureExist &= hasExtension(Ext); 1208 if (IsAllRequiredFeatureExist) { 1209 auto Version = findDefaultVersion(CombineExt); 1210 addExtension(CombineExt, Version.value()); 1211 IsNewCombine = true; 1212 } 1213 } 1214 } while (IsNewCombine); 1215 } 1216 1217 void RISCVISAInfo::updateFLen() { 1218 FLen = 0; 1219 // TODO: Handle q extension. 1220 if (Exts.count("d")) 1221 FLen = 64; 1222 else if (Exts.count("f")) 1223 FLen = 32; 1224 } 1225 1226 void RISCVISAInfo::updateMinVLen() { 1227 for (auto const &Ext : Exts) { 1228 StringRef ExtName = Ext.first; 1229 bool IsZvlExt = ExtName.consume_front("zvl") && ExtName.consume_back("b"); 1230 if (IsZvlExt) { 1231 unsigned ZvlLen; 1232 if (!ExtName.getAsInteger(10, ZvlLen)) 1233 MinVLen = std::max(MinVLen, ZvlLen); 1234 } 1235 } 1236 } 1237 1238 void RISCVISAInfo::updateMaxELen() { 1239 // handles EEW restriction by sub-extension zve 1240 for (auto const &Ext : Exts) { 1241 StringRef ExtName = Ext.first; 1242 bool IsZveExt = ExtName.consume_front("zve"); 1243 if (IsZveExt) { 1244 if (ExtName.back() == 'f') 1245 MaxELenFp = std::max(MaxELenFp, 32u); 1246 if (ExtName.back() == 'd') 1247 MaxELenFp = std::max(MaxELenFp, 64u); 1248 ExtName = ExtName.drop_back(); 1249 unsigned ZveELen; 1250 ExtName.getAsInteger(10, ZveELen); 1251 MaxELen = std::max(MaxELen, ZveELen); 1252 } 1253 } 1254 } 1255 1256 std::string RISCVISAInfo::toString() const { 1257 std::string Buffer; 1258 raw_string_ostream Arch(Buffer); 1259 1260 Arch << "rv" << XLen; 1261 1262 ListSeparator LS("_"); 1263 for (auto const &Ext : Exts) { 1264 StringRef ExtName = Ext.first; 1265 auto ExtInfo = Ext.second; 1266 Arch << LS << ExtName; 1267 Arch << ExtInfo.Major << "p" << ExtInfo.Minor; 1268 } 1269 1270 return Arch.str(); 1271 } 1272 1273 llvm::Expected<std::unique_ptr<RISCVISAInfo>> 1274 RISCVISAInfo::postProcessAndChecking(std::unique_ptr<RISCVISAInfo> &&ISAInfo) { 1275 ISAInfo->updateImplication(); 1276 ISAInfo->updateCombination(); 1277 ISAInfo->updateFLen(); 1278 ISAInfo->updateMinVLen(); 1279 ISAInfo->updateMaxELen(); 1280 1281 if (Error Result = ISAInfo->checkDependency()) 1282 return std::move(Result); 1283 return std::move(ISAInfo); 1284 } 1285 1286 StringRef RISCVISAInfo::computeDefaultABI() const { 1287 if (XLen == 32) { 1288 if (hasExtension("e")) 1289 return "ilp32e"; 1290 if (hasExtension("d")) 1291 return "ilp32d"; 1292 if (hasExtension("f")) 1293 return "ilp32f"; 1294 return "ilp32"; 1295 } else if (XLen == 64) { 1296 if (hasExtension("e")) 1297 return "lp64e"; 1298 if (hasExtension("d")) 1299 return "lp64d"; 1300 if (hasExtension("f")) 1301 return "lp64f"; 1302 return "lp64"; 1303 } 1304 llvm_unreachable("Invalid XLEN"); 1305 } 1306 1307 bool RISCVISAInfo::isSupportedExtensionWithVersion(StringRef Ext) { 1308 if (Ext.empty()) 1309 return false; 1310 1311 auto Pos = findLastNonVersionCharacter(Ext) + 1; 1312 StringRef Name = Ext.substr(0, Pos); 1313 StringRef Vers = Ext.substr(Pos); 1314 if (Vers.empty()) 1315 return false; 1316 1317 unsigned Major, Minor, ConsumeLength; 1318 if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength, 1319 true, true)) { 1320 consumeError(std::move(E)); 1321 return false; 1322 } 1323 1324 return true; 1325 } 1326 1327 std::string RISCVISAInfo::getTargetFeatureForExtension(StringRef Ext) { 1328 if (Ext.empty()) 1329 return std::string(); 1330 1331 auto Pos = findLastNonVersionCharacter(Ext) + 1; 1332 StringRef Name = Ext.substr(0, Pos); 1333 1334 if (Pos != Ext.size() && !isSupportedExtensionWithVersion(Ext)) 1335 return std::string(); 1336 1337 if (!isSupportedExtension(Name)) 1338 return std::string(); 1339 1340 return isExperimentalExtension(Name) ? "experimental-" + Name.str() 1341 : Name.str(); 1342 } 1343