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::parseNormalizedArchString(StringRef Arch) { 507 if (llvm::any_of(Arch, isupper)) { 508 return createStringError(errc::invalid_argument, 509 "string must be lowercase"); 510 } 511 // Must start with a valid base ISA name. 512 unsigned XLen; 513 if (Arch.startswith("rv32i") || Arch.startswith("rv32e")) 514 XLen = 32; 515 else if (Arch.startswith("rv64i") || Arch.startswith("rv64e")) 516 XLen = 64; 517 else 518 return createStringError(errc::invalid_argument, 519 "arch string must begin with valid base ISA"); 520 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen)); 521 // Discard rv32/rv64 prefix. 522 Arch = Arch.substr(4); 523 524 // Each extension is of the form ${name}${major_version}p${minor_version} 525 // and separated by _. Split by _ and then extract the name and version 526 // information for each extension. 527 SmallVector<StringRef, 8> Split; 528 Arch.split(Split, '_'); 529 for (StringRef Ext : Split) { 530 StringRef Prefix, MinorVersionStr; 531 std::tie(Prefix, MinorVersionStr) = Ext.rsplit('p'); 532 if (MinorVersionStr.empty()) 533 return createStringError(errc::invalid_argument, 534 "extension lacks version in expected format"); 535 unsigned MajorVersion, MinorVersion; 536 if (MinorVersionStr.getAsInteger(10, MinorVersion)) 537 return createStringError(errc::invalid_argument, 538 "failed to parse minor version number"); 539 540 // Split Prefix into the extension name and the major version number 541 // (the trailing digits of Prefix). 542 int TrailingDigits = 0; 543 StringRef ExtName = Prefix; 544 while (!ExtName.empty()) { 545 if (!isDigit(ExtName.back())) 546 break; 547 ExtName = ExtName.drop_back(1); 548 TrailingDigits++; 549 } 550 if (!TrailingDigits) 551 return createStringError(errc::invalid_argument, 552 "extension lacks version in expected format"); 553 554 StringRef MajorVersionStr = Prefix.take_back(TrailingDigits); 555 if (MajorVersionStr.getAsInteger(10, MajorVersion)) 556 return createStringError(errc::invalid_argument, 557 "failed to parse major version number"); 558 ISAInfo->addExtension(ExtName, MajorVersion, MinorVersion); 559 } 560 ISAInfo->updateFLen(); 561 ISAInfo->updateMinVLen(); 562 ISAInfo->updateMaxELen(); 563 return std::move(ISAInfo); 564 } 565 566 llvm::Expected<std::unique_ptr<RISCVISAInfo>> 567 RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension, 568 bool ExperimentalExtensionVersionCheck, 569 bool IgnoreUnknown) { 570 // RISC-V ISA strings must be lowercase. 571 if (llvm::any_of(Arch, isupper)) { 572 return createStringError(errc::invalid_argument, 573 "string must be lowercase"); 574 } 575 576 bool HasRV64 = Arch.startswith("rv64"); 577 // ISA string must begin with rv32 or rv64. 578 if (!(Arch.startswith("rv32") || HasRV64) || (Arch.size() < 5)) { 579 return createStringError(errc::invalid_argument, 580 "string must begin with rv32{i,e,g} or rv64{i,g}"); 581 } 582 583 unsigned XLen = HasRV64 ? 64 : 32; 584 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen)); 585 586 // The canonical order specified in ISA manual. 587 // Ref: Table 22.1 in RISC-V User-Level ISA V2.2 588 StringRef StdExts = AllStdExts; 589 char Baseline = Arch[4]; 590 591 // First letter should be 'e', 'i' or 'g'. 592 switch (Baseline) { 593 default: 594 return createStringError(errc::invalid_argument, 595 "first letter should be 'e', 'i' or 'g'"); 596 case 'e': { 597 // Extension 'e' is not allowed in rv64. 598 if (HasRV64) 599 return createStringError( 600 errc::invalid_argument, 601 "standard user-level extension 'e' requires 'rv32'"); 602 break; 603 } 604 case 'i': 605 break; 606 case 'g': 607 // g = imafd 608 StdExts = StdExts.drop_front(4); 609 break; 610 } 611 612 // Skip rvxxx 613 StringRef Exts = Arch.substr(5); 614 615 // Remove multi-letter standard extensions, non-standard extensions and 616 // supervisor-level extensions. They have 'z', 'x', 's', 'sx' prefixes. 617 // Parse them at the end. 618 // Find the very first occurrence of 's', 'x' or 'z'. 619 StringRef OtherExts; 620 size_t Pos = Exts.find_first_of("zsx"); 621 if (Pos != StringRef::npos) { 622 OtherExts = Exts.substr(Pos); 623 Exts = Exts.substr(0, Pos); 624 } 625 626 unsigned Major, Minor, ConsumeLength; 627 if (auto E = getExtensionVersion(std::string(1, Baseline), Exts, Major, Minor, 628 ConsumeLength, EnableExperimentalExtension, 629 ExperimentalExtensionVersionCheck)) 630 return std::move(E); 631 632 if (Baseline == 'g') { 633 // No matter which version is given to `g`, we always set imafd to default 634 // version since the we don't have clear version scheme for that on 635 // ISA spec. 636 for (const auto *Ext : {"i", "m", "a", "f", "d"}) 637 if (auto Version = findDefaultVersion(Ext)) 638 ISAInfo->addExtension(Ext, Version->Major, Version->Minor); 639 else 640 llvm_unreachable("Default extension version not found?"); 641 } else 642 // Baseline is `i` or `e` 643 ISAInfo->addExtension(std::string(1, Baseline), Major, Minor); 644 645 // Consume the base ISA version number and any '_' between rvxxx and the 646 // first extension 647 Exts = Exts.drop_front(ConsumeLength); 648 Exts.consume_front("_"); 649 650 // TODO: Use version number when setting target features 651 652 auto StdExtsItr = StdExts.begin(); 653 auto StdExtsEnd = StdExts.end(); 654 auto GoToNextExt = [](StringRef::iterator &I, unsigned ConsumeLength) { 655 I += 1 + ConsumeLength; 656 if (*I == '_') 657 ++I; 658 }; 659 for (auto I = Exts.begin(), E = Exts.end(); I != E;) { 660 char C = *I; 661 662 // Check ISA extensions are specified in the canonical order. 663 while (StdExtsItr != StdExtsEnd && *StdExtsItr != C) 664 ++StdExtsItr; 665 666 if (StdExtsItr == StdExtsEnd) { 667 // Either c contains a valid extension but it was not given in 668 // canonical order or it is an invalid extension. 669 if (StdExts.contains(C)) { 670 return createStringError( 671 errc::invalid_argument, 672 "standard user-level extension not given in canonical order '%c'", 673 C); 674 } 675 676 return createStringError(errc::invalid_argument, 677 "invalid standard user-level extension '%c'", C); 678 } 679 680 // Move to next char to prevent repeated letter. 681 ++StdExtsItr; 682 683 std::string Next; 684 unsigned Major, Minor, ConsumeLength; 685 if (std::next(I) != E) 686 Next = std::string(std::next(I), E); 687 if (auto E = getExtensionVersion(std::string(1, C), Next, Major, Minor, 688 ConsumeLength, EnableExperimentalExtension, 689 ExperimentalExtensionVersionCheck)) { 690 if (IgnoreUnknown) { 691 consumeError(std::move(E)); 692 GoToNextExt(I, ConsumeLength); 693 continue; 694 } 695 return std::move(E); 696 } 697 698 // The order is OK, then push it into features. 699 // TODO: Use version number when setting target features 700 // Currently LLVM supports only "mafdcvh". 701 if (!isSupportedExtension(StringRef(&C, 1))) { 702 if (IgnoreUnknown) { 703 GoToNextExt(I, ConsumeLength); 704 continue; 705 } 706 return createStringError(errc::invalid_argument, 707 "unsupported standard user-level extension '%c'", 708 C); 709 } 710 ISAInfo->addExtension(std::string(1, C), Major, Minor); 711 712 // Consume full extension name and version, including any optional '_' 713 // between this extension and the next 714 GoToNextExt(I, ConsumeLength); 715 } 716 717 // Handle other types of extensions other than the standard 718 // general purpose and standard user-level extensions. 719 // Parse the ISA string containing non-standard user-level 720 // extensions, standard supervisor-level extensions and 721 // non-standard supervisor-level extensions. 722 // These extensions start with 'z', 'x', 's', 'sx' prefixes, follow a 723 // canonical order, might have a version number (major, minor) 724 // and are separated by a single underscore '_'. 725 // Set the hardware features for the extensions that are supported. 726 727 // Multi-letter extensions are seperated by a single underscore 728 // as described in RISC-V User-Level ISA V2.2. 729 SmallVector<StringRef, 8> Split; 730 OtherExts.split(Split, '_'); 731 732 SmallVector<StringRef, 8> AllExts; 733 std::array<StringRef, 4> Prefix{"z", "x", "s", "sx"}; 734 auto I = Prefix.begin(); 735 auto E = Prefix.end(); 736 if (Split.size() > 1 || Split[0] != "") { 737 for (StringRef Ext : Split) { 738 if (Ext.empty()) 739 return createStringError(errc::invalid_argument, 740 "extension name missing after separator '_'"); 741 742 StringRef Type = getExtensionType(Ext); 743 StringRef Desc = getExtensionTypeDesc(Ext); 744 auto Pos = findFirstNonVersionCharacter(Ext) + 1; 745 StringRef Name(Ext.substr(0, Pos)); 746 StringRef Vers(Ext.substr(Pos)); 747 748 if (Type.empty()) { 749 if (IgnoreUnknown) 750 continue; 751 return createStringError(errc::invalid_argument, 752 "invalid extension prefix '" + Ext + "'"); 753 } 754 755 // Check ISA extensions are specified in the canonical order. 756 while (I != E && *I != Type) 757 ++I; 758 759 if (I == E) { 760 if (IgnoreUnknown) 761 continue; 762 return createStringError(errc::invalid_argument, 763 "%s not given in canonical order '%s'", 764 Desc.str().c_str(), Ext.str().c_str()); 765 } 766 767 if (!IgnoreUnknown && Name.size() == Type.size()) { 768 return createStringError(errc::invalid_argument, 769 "%s name missing after '%s'", 770 Desc.str().c_str(), Type.str().c_str()); 771 } 772 773 unsigned Major, Minor, ConsumeLength; 774 if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength, 775 EnableExperimentalExtension, 776 ExperimentalExtensionVersionCheck)) { 777 if (IgnoreUnknown) { 778 consumeError(std::move(E)); 779 continue; 780 } 781 return std::move(E); 782 } 783 784 // Check if duplicated extension. 785 if (!IgnoreUnknown && llvm::is_contained(AllExts, Name)) { 786 return createStringError(errc::invalid_argument, "duplicated %s '%s'", 787 Desc.str().c_str(), Name.str().c_str()); 788 } 789 790 ISAInfo->addExtension(Name, Major, Minor); 791 // Extension format is correct, keep parsing the extensions. 792 // TODO: Save Type, Name, Major, Minor to avoid parsing them later. 793 AllExts.push_back(Name); 794 } 795 } 796 797 for (auto Ext : AllExts) { 798 if (!isSupportedExtension(Ext)) { 799 StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext)); 800 return createStringError(errc::invalid_argument, "unsupported %s '%s'", 801 Desc.str().c_str(), Ext.str().c_str()); 802 } 803 } 804 805 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo)); 806 } 807 808 Error RISCVISAInfo::checkDependency() { 809 bool IsRv32 = XLen == 32; 810 bool HasE = Exts.count("e") != 0; 811 bool HasD = Exts.count("d") != 0; 812 bool HasF = Exts.count("f") != 0; 813 bool HasZfinx = Exts.count("zfinx") != 0; 814 bool HasZdinx = Exts.count("zdinx") != 0; 815 bool HasVector = Exts.count("zve32x") != 0; 816 bool HasZve32f = Exts.count("zve32f") != 0; 817 bool HasZve64d = Exts.count("zve64d") != 0; 818 bool HasZvl = MinVLen != 0; 819 820 if (HasE && !IsRv32) 821 return createStringError( 822 errc::invalid_argument, 823 "standard user-level extension 'e' requires 'rv32'"); 824 825 // It's illegal to specify the 'd' (double-precision floating point) 826 // extension without also specifying the 'f' (single precision 827 // floating-point) extension. 828 // TODO: This has been removed in later specs, which specify that D implies F 829 if (HasD && !HasF) 830 return createStringError(errc::invalid_argument, 831 "d requires f extension to also be specified"); 832 833 if (HasZve32f && !HasF && !HasZfinx) 834 return createStringError( 835 errc::invalid_argument, 836 "zve32f requires f or zfinx extension to also be specified"); 837 838 if (HasZve64d && !HasD && !HasZdinx) 839 return createStringError( 840 errc::invalid_argument, 841 "zve64d requires d or zdinx extension to also be specified"); 842 843 if (Exts.count("zvfh") && !Exts.count("zfh") && !Exts.count("zfhmin") && 844 !Exts.count("zhinx") && !Exts.count("zhinxmin")) 845 return createStringError( 846 errc::invalid_argument, 847 "zvfh requires zfh, zfhmin, zhinx or zhinxmin extension to also be " 848 "specified"); 849 850 if (HasZvl && !HasVector) 851 return createStringError( 852 errc::invalid_argument, 853 "zvl*b requires v or zve* extension to also be specified"); 854 855 // Additional dependency checks. 856 // TODO: The 'q' extension requires rv64. 857 // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'. 858 859 return Error::success(); 860 } 861 862 static const char *ImpliedExtsV[] = {"zvl128b", "zve64d", "f", "d"}; 863 static const char *ImpliedExtsZfhmin[] = {"f"}; 864 static const char *ImpliedExtsZfh[] = {"f"}; 865 static const char *ImpliedExtsZdinx[] = {"zfinx"}; 866 static const char *ImpliedExtsZhinxmin[] = {"zfinx"}; 867 static const char *ImpliedExtsZhinx[] = {"zfinx"}; 868 static const char *ImpliedExtsZve64d[] = {"zve64f"}; 869 static const char *ImpliedExtsZve64f[] = {"zve64x", "zve32f"}; 870 static const char *ImpliedExtsZve64x[] = {"zve32x", "zvl64b"}; 871 static const char *ImpliedExtsZve32f[] = {"zve32x"}; 872 static const char *ImpliedExtsZve32x[] = {"zvl32b"}; 873 static const char *ImpliedExtsZvl65536b[] = {"zvl32768b"}; 874 static const char *ImpliedExtsZvl32768b[] = {"zvl16384b"}; 875 static const char *ImpliedExtsZvl16384b[] = {"zvl8192b"}; 876 static const char *ImpliedExtsZvl8192b[] = {"zvl4096b"}; 877 static const char *ImpliedExtsZvl4096b[] = {"zvl2048b"}; 878 static const char *ImpliedExtsZvl2048b[] = {"zvl1024b"}; 879 static const char *ImpliedExtsZvl1024b[] = {"zvl512b"}; 880 static const char *ImpliedExtsZvl512b[] = {"zvl256b"}; 881 static const char *ImpliedExtsZvl256b[] = {"zvl128b"}; 882 static const char *ImpliedExtsZvl128b[] = {"zvl64b"}; 883 static const char *ImpliedExtsZvl64b[] = {"zvl32b"}; 884 static const char *ImpliedExtsZk[] = {"zkn", "zkt", "zkr"}; 885 static const char *ImpliedExtsZkn[] = {"zbkb", "zbkc", "zbkx", 886 "zkne", "zknd", "zknh"}; 887 static const char *ImpliedExtsZks[] = {"zbkb", "zbkc", "zbkx", "zksed", "zksh"}; 888 static const char *ImpliedExtsZvfh[] = {"zve32f"}; 889 static const char *ImpliedExtsXTHeadVdot[] = {"v"}; 890 891 struct ImpliedExtsEntry { 892 StringLiteral Name; 893 ArrayRef<const char *> Exts; 894 895 bool operator<(const ImpliedExtsEntry &Other) const { 896 return Name < Other.Name; 897 } 898 899 bool operator<(StringRef Other) const { return Name < Other; } 900 }; 901 902 // Note: The table needs to be sorted by name. 903 static constexpr ImpliedExtsEntry ImpliedExts[] = { 904 {{"v"}, {ImpliedExtsV}}, 905 {{"xtheadvdot"}, {ImpliedExtsXTHeadVdot}}, 906 {{"zdinx"}, {ImpliedExtsZdinx}}, 907 {{"zfh"}, {ImpliedExtsZfh}}, 908 {{"zfhmin"}, {ImpliedExtsZfhmin}}, 909 {{"zhinx"}, {ImpliedExtsZhinx}}, 910 {{"zhinxmin"}, {ImpliedExtsZhinxmin}}, 911 {{"zk"}, {ImpliedExtsZk}}, 912 {{"zkn"}, {ImpliedExtsZkn}}, 913 {{"zks"}, {ImpliedExtsZks}}, 914 {{"zve32f"}, {ImpliedExtsZve32f}}, 915 {{"zve32x"}, {ImpliedExtsZve32x}}, 916 {{"zve64d"}, {ImpliedExtsZve64d}}, 917 {{"zve64f"}, {ImpliedExtsZve64f}}, 918 {{"zve64x"}, {ImpliedExtsZve64x}}, 919 {{"zvfh"}, {ImpliedExtsZvfh}}, 920 {{"zvl1024b"}, {ImpliedExtsZvl1024b}}, 921 {{"zvl128b"}, {ImpliedExtsZvl128b}}, 922 {{"zvl16384b"}, {ImpliedExtsZvl16384b}}, 923 {{"zvl2048b"}, {ImpliedExtsZvl2048b}}, 924 {{"zvl256b"}, {ImpliedExtsZvl256b}}, 925 {{"zvl32768b"}, {ImpliedExtsZvl32768b}}, 926 {{"zvl4096b"}, {ImpliedExtsZvl4096b}}, 927 {{"zvl512b"}, {ImpliedExtsZvl512b}}, 928 {{"zvl64b"}, {ImpliedExtsZvl64b}}, 929 {{"zvl65536b"}, {ImpliedExtsZvl65536b}}, 930 {{"zvl8192b"}, {ImpliedExtsZvl8192b}}, 931 }; 932 933 void RISCVISAInfo::updateImplication() { 934 bool HasE = Exts.count("e") != 0; 935 bool HasI = Exts.count("i") != 0; 936 937 // If not in e extension and i extension does not exist, i extension is 938 // implied 939 if (!HasE && !HasI) { 940 auto Version = findDefaultVersion("i"); 941 addExtension("i", Version->Major, Version->Minor); 942 } 943 944 assert(llvm::is_sorted(ImpliedExts) && "Table not sorted by Name"); 945 946 // This loop may execute over 1 iteration since implication can be layered 947 // Exits loop if no more implication is applied 948 SmallSetVector<StringRef, 16> WorkList; 949 for (auto const &Ext : Exts) 950 WorkList.insert(Ext.first); 951 952 while (!WorkList.empty()) { 953 StringRef ExtName = WorkList.pop_back_val(); 954 auto I = llvm::lower_bound(ImpliedExts, ExtName); 955 if (I != std::end(ImpliedExts) && I->Name == ExtName) { 956 for (const char *ImpliedExt : I->Exts) { 957 if (WorkList.count(ImpliedExt)) 958 continue; 959 if (Exts.count(ImpliedExt)) 960 continue; 961 auto Version = findDefaultVersion(ImpliedExt); 962 addExtension(ImpliedExt, Version->Major, Version->Minor); 963 WorkList.insert(ImpliedExt); 964 } 965 } 966 } 967 } 968 969 struct CombinedExtsEntry { 970 StringLiteral CombineExt; 971 ArrayRef<const char *> RequiredExts; 972 }; 973 974 static constexpr CombinedExtsEntry CombineIntoExts[] = { 975 {{"zk"}, {ImpliedExtsZk}}, 976 {{"zkn"}, {ImpliedExtsZkn}}, 977 {{"zks"}, {ImpliedExtsZks}}, 978 }; 979 980 void RISCVISAInfo::updateCombination() { 981 bool IsNewCombine = false; 982 do { 983 IsNewCombine = false; 984 for (CombinedExtsEntry CombineIntoExt : CombineIntoExts) { 985 auto CombineExt = CombineIntoExt.CombineExt; 986 auto RequiredExts = CombineIntoExt.RequiredExts; 987 if (hasExtension(CombineExt)) 988 continue; 989 bool IsAllRequiredFeatureExist = true; 990 for (const char *Ext : RequiredExts) 991 IsAllRequiredFeatureExist &= hasExtension(Ext); 992 if (IsAllRequiredFeatureExist) { 993 auto Version = findDefaultVersion(CombineExt); 994 addExtension(CombineExt, Version->Major, Version->Minor); 995 IsNewCombine = true; 996 } 997 } 998 } while (IsNewCombine); 999 } 1000 1001 void RISCVISAInfo::updateFLen() { 1002 FLen = 0; 1003 // TODO: Handle q extension. 1004 if (Exts.count("d")) 1005 FLen = 64; 1006 else if (Exts.count("f")) 1007 FLen = 32; 1008 } 1009 1010 void RISCVISAInfo::updateMinVLen() { 1011 for (auto const &Ext : Exts) { 1012 StringRef ExtName = Ext.first; 1013 bool IsZvlExt = ExtName.consume_front("zvl") && ExtName.consume_back("b"); 1014 if (IsZvlExt) { 1015 unsigned ZvlLen; 1016 if (!ExtName.getAsInteger(10, ZvlLen)) 1017 MinVLen = std::max(MinVLen, ZvlLen); 1018 } 1019 } 1020 } 1021 1022 void RISCVISAInfo::updateMaxELen() { 1023 // handles EEW restriction by sub-extension zve 1024 for (auto const &Ext : Exts) { 1025 StringRef ExtName = Ext.first; 1026 bool IsZveExt = ExtName.consume_front("zve"); 1027 if (IsZveExt) { 1028 if (ExtName.back() == 'f') 1029 MaxELenFp = std::max(MaxELenFp, 32u); 1030 if (ExtName.back() == 'd') 1031 MaxELenFp = std::max(MaxELenFp, 64u); 1032 ExtName = ExtName.drop_back(); 1033 unsigned ZveELen; 1034 ExtName.getAsInteger(10, ZveELen); 1035 MaxELen = std::max(MaxELen, ZveELen); 1036 } 1037 } 1038 } 1039 1040 std::string RISCVISAInfo::toString() const { 1041 std::string Buffer; 1042 raw_string_ostream Arch(Buffer); 1043 1044 Arch << "rv" << XLen; 1045 1046 ListSeparator LS("_"); 1047 for (auto const &Ext : Exts) { 1048 StringRef ExtName = Ext.first; 1049 auto ExtInfo = Ext.second; 1050 Arch << LS << ExtName; 1051 Arch << ExtInfo.MajorVersion << "p" << ExtInfo.MinorVersion; 1052 } 1053 1054 return Arch.str(); 1055 } 1056 1057 std::vector<std::string> RISCVISAInfo::toFeatureVector() const { 1058 std::vector<std::string> FeatureVector; 1059 for (auto const &Ext : Exts) { 1060 std::string ExtName = Ext.first; 1061 if (ExtName == "i") // i is not recognized in clang -cc1 1062 continue; 1063 if (!isSupportedExtension(ExtName)) 1064 continue; 1065 std::string Feature = isExperimentalExtension(ExtName) 1066 ? "+experimental-" + ExtName 1067 : "+" + ExtName; 1068 FeatureVector.push_back(Feature); 1069 } 1070 return FeatureVector; 1071 } 1072 1073 llvm::Expected<std::unique_ptr<RISCVISAInfo>> 1074 RISCVISAInfo::postProcessAndChecking(std::unique_ptr<RISCVISAInfo> &&ISAInfo) { 1075 ISAInfo->updateImplication(); 1076 ISAInfo->updateCombination(); 1077 ISAInfo->updateFLen(); 1078 ISAInfo->updateMinVLen(); 1079 ISAInfo->updateMaxELen(); 1080 1081 if (Error Result = ISAInfo->checkDependency()) 1082 return std::move(Result); 1083 return std::move(ISAInfo); 1084 } 1085 1086 StringRef RISCVISAInfo::computeDefaultABI() const { 1087 if (XLen == 32) { 1088 if (hasExtension("d")) 1089 return "ilp32d"; 1090 if (hasExtension("e")) 1091 return "ilp32e"; 1092 return "ilp32"; 1093 } else if (XLen == 64) { 1094 if (hasExtension("d")) 1095 return "lp64d"; 1096 return "lp64"; 1097 } 1098 llvm_unreachable("Invalid XLEN"); 1099 } 1100