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