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