1 //===-- RISCVISAInfo.cpp - RISC-V Arch String Parser ----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/TargetParser/RISCVISAInfo.h" 10 #include "llvm/ADT/STLExtras.h" 11 #include "llvm/ADT/StringExtras.h" 12 #include "llvm/ADT/StringRef.h" 13 #include "llvm/Support/Errc.h" 14 #include "llvm/Support/Error.h" 15 #include "llvm/Support/raw_ostream.h" 16 17 #include <array> 18 #include <atomic> 19 #include <optional> 20 #include <string> 21 #include <vector> 22 23 using namespace llvm; 24 25 namespace { 26 27 struct RISCVSupportedExtension { 28 const char *Name; 29 /// Supported version. 30 RISCVISAUtils::ExtensionVersion Version; 31 32 bool operator<(const RISCVSupportedExtension &RHS) const { 33 return StringRef(Name) < StringRef(RHS.Name); 34 } 35 }; 36 37 struct RISCVProfile { 38 StringLiteral Name; 39 StringLiteral MArch; 40 41 bool operator<(const RISCVProfile &RHS) const { 42 return StringRef(Name) < StringRef(RHS.Name); 43 } 44 }; 45 46 } // end anonymous namespace 47 48 static const char *RISCVGImplications[] = {"i", "m", "a", "f", "d"}; 49 static const char *RISCVGImplicationsZi[] = {"zicsr", "zifencei"}; 50 51 #define GET_SUPPORTED_EXTENSIONS 52 #include "llvm/TargetParser/RISCVTargetParserDef.inc" 53 54 #define GET_SUPPORTED_PROFILES 55 #include "llvm/TargetParser/RISCVTargetParserDef.inc" 56 57 static void verifyTables() { 58 #ifndef NDEBUG 59 static std::atomic<bool> TableChecked(false); 60 if (!TableChecked.load(std::memory_order_relaxed)) { 61 assert(llvm::is_sorted(SupportedExtensions) && 62 "Extensions are not sorted by name"); 63 assert(llvm::is_sorted(SupportedExperimentalExtensions) && 64 "Experimental extensions are not sorted by name"); 65 assert(llvm::is_sorted(SupportedProfiles) && 66 "Profiles are not sorted by name"); 67 assert(llvm::is_sorted(SupportedExperimentalProfiles) && 68 "Experimental profiles are not sorted by name"); 69 TableChecked.store(true, std::memory_order_relaxed); 70 } 71 #endif 72 } 73 74 static void PrintExtension(StringRef Name, StringRef Version, 75 StringRef Description) { 76 outs().indent(4); 77 unsigned VersionWidth = Description.empty() ? 0 : 10; 78 outs() << left_justify(Name, 21) << left_justify(Version, VersionWidth) 79 << Description << "\n"; 80 } 81 82 void RISCVISAInfo::printSupportedExtensions(StringMap<StringRef> &DescMap) { 83 outs() << "All available -march extensions for RISC-V\n\n"; 84 PrintExtension("Name", "Version", (DescMap.empty() ? "" : "Description")); 85 86 RISCVISAUtils::OrderedExtensionMap ExtMap; 87 for (const auto &E : SupportedExtensions) 88 ExtMap[E.Name] = {E.Version.Major, E.Version.Minor}; 89 for (const auto &E : ExtMap) { 90 std::string Version = 91 std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor); 92 PrintExtension(E.first, Version, DescMap[E.first]); 93 } 94 95 outs() << "\nExperimental extensions\n"; 96 ExtMap.clear(); 97 for (const auto &E : SupportedExperimentalExtensions) 98 ExtMap[E.Name] = {E.Version.Major, E.Version.Minor}; 99 for (const auto &E : ExtMap) { 100 std::string Version = 101 std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor); 102 PrintExtension(E.first, Version, DescMap["experimental-" + E.first]); 103 } 104 105 outs() << "\nSupported Profiles\n"; 106 for (const auto &P : SupportedProfiles) 107 outs().indent(4) << P.Name << "\n"; 108 109 outs() << "\nExperimental Profiles\n"; 110 for (const auto &P : SupportedExperimentalProfiles) 111 outs().indent(4) << P.Name << "\n"; 112 113 outs() << "\nUse -march to specify the target's extension.\n" 114 "For example, clang -march=rv32i_v1p0\n"; 115 } 116 117 void RISCVISAInfo::printEnabledExtensions( 118 bool IsRV64, std::set<StringRef> &EnabledFeatureNames, 119 StringMap<StringRef> &DescMap) { 120 outs() << "Extensions enabled for the given RISC-V target\n\n"; 121 PrintExtension("Name", "Version", (DescMap.empty() ? "" : "Description")); 122 123 RISCVISAUtils::OrderedExtensionMap FullExtMap; 124 RISCVISAUtils::OrderedExtensionMap ExtMap; 125 for (const auto &E : SupportedExtensions) 126 if (EnabledFeatureNames.count(E.Name) != 0) { 127 FullExtMap[E.Name] = {E.Version.Major, E.Version.Minor}; 128 ExtMap[E.Name] = {E.Version.Major, E.Version.Minor}; 129 } 130 for (const auto &E : ExtMap) { 131 std::string Version = 132 std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor); 133 PrintExtension(E.first, Version, DescMap[E.first]); 134 } 135 136 outs() << "\nExperimental extensions\n"; 137 ExtMap.clear(); 138 for (const auto &E : SupportedExperimentalExtensions) { 139 StringRef Name(E.Name); 140 if (EnabledFeatureNames.count("experimental-" + Name.str()) != 0) { 141 FullExtMap[E.Name] = {E.Version.Major, E.Version.Minor}; 142 ExtMap[E.Name] = {E.Version.Major, E.Version.Minor}; 143 } 144 } 145 for (const auto &E : ExtMap) { 146 std::string Version = 147 std::to_string(E.second.Major) + "." + std::to_string(E.second.Minor); 148 PrintExtension(E.first, Version, DescMap["experimental-" + E.first]); 149 } 150 151 unsigned XLen = IsRV64 ? 64 : 32; 152 if (auto ISAString = RISCVISAInfo::createFromExtMap(XLen, FullExtMap)) 153 outs() << "\nISA String: " << ISAString.get()->toString() << "\n"; 154 } 155 156 static bool stripExperimentalPrefix(StringRef &Ext) { 157 return Ext.consume_front("experimental-"); 158 } 159 160 // This function finds the last character that doesn't belong to a version 161 // (e.g. zba1p0 is extension 'zba' of version '1p0'). So the function will 162 // consume [0-9]*p[0-9]* starting from the backward. An extension name will not 163 // end with a digit or the letter 'p', so this function will parse correctly. 164 // NOTE: This function is NOT able to take empty strings or strings that only 165 // have version numbers and no extension name. It assumes the extension name 166 // will be at least more than one character. 167 static size_t findLastNonVersionCharacter(StringRef Ext) { 168 assert(!Ext.empty() && 169 "Already guarded by if-statement in ::parseArchString"); 170 171 int Pos = Ext.size() - 1; 172 while (Pos > 0 && isDigit(Ext[Pos])) 173 Pos--; 174 if (Pos > 0 && Ext[Pos] == 'p' && isDigit(Ext[Pos - 1])) { 175 Pos--; 176 while (Pos > 0 && isDigit(Ext[Pos])) 177 Pos--; 178 } 179 return Pos; 180 } 181 182 namespace { 183 struct LessExtName { 184 bool operator()(const RISCVSupportedExtension &LHS, StringRef RHS) { 185 return StringRef(LHS.Name) < RHS; 186 } 187 bool operator()(StringRef LHS, const RISCVSupportedExtension &RHS) { 188 return LHS < StringRef(RHS.Name); 189 } 190 }; 191 } // namespace 192 193 static std::optional<RISCVISAUtils::ExtensionVersion> 194 findDefaultVersion(StringRef ExtName) { 195 // Find default version of an extension. 196 // TODO: We might set default version based on profile or ISA spec. 197 for (auto &ExtInfo : {ArrayRef(SupportedExtensions), 198 ArrayRef(SupportedExperimentalExtensions)}) { 199 auto I = llvm::lower_bound(ExtInfo, ExtName, LessExtName()); 200 201 if (I == ExtInfo.end() || I->Name != ExtName) 202 continue; 203 204 return I->Version; 205 } 206 return std::nullopt; 207 } 208 209 static StringRef getExtensionTypeDesc(StringRef Ext) { 210 if (Ext.starts_with('s')) 211 return "standard supervisor-level extension"; 212 if (Ext.starts_with('x')) 213 return "non-standard user-level extension"; 214 if (Ext.starts_with('z')) 215 return "standard user-level extension"; 216 return StringRef(); 217 } 218 219 static StringRef getExtensionType(StringRef Ext) { 220 if (Ext.starts_with('s')) 221 return "s"; 222 if (Ext.starts_with('x')) 223 return "x"; 224 if (Ext.starts_with('z')) 225 return "z"; 226 return StringRef(); 227 } 228 229 static std::optional<RISCVISAUtils::ExtensionVersion> 230 isExperimentalExtension(StringRef Ext) { 231 auto I = 232 llvm::lower_bound(SupportedExperimentalExtensions, Ext, LessExtName()); 233 if (I == std::end(SupportedExperimentalExtensions) || I->Name != Ext) 234 return std::nullopt; 235 236 return I->Version; 237 } 238 239 bool RISCVISAInfo::isSupportedExtensionFeature(StringRef Ext) { 240 bool IsExperimental = stripExperimentalPrefix(Ext); 241 242 ArrayRef<RISCVSupportedExtension> ExtInfo = 243 IsExperimental ? ArrayRef(SupportedExperimentalExtensions) 244 : ArrayRef(SupportedExtensions); 245 246 auto I = llvm::lower_bound(ExtInfo, Ext, LessExtName()); 247 return I != ExtInfo.end() && I->Name == Ext; 248 } 249 250 bool RISCVISAInfo::isSupportedExtension(StringRef Ext) { 251 verifyTables(); 252 253 for (auto ExtInfo : {ArrayRef(SupportedExtensions), 254 ArrayRef(SupportedExperimentalExtensions)}) { 255 auto I = llvm::lower_bound(ExtInfo, Ext, LessExtName()); 256 if (I != ExtInfo.end() && I->Name == Ext) 257 return true; 258 } 259 260 return false; 261 } 262 263 bool RISCVISAInfo::isSupportedExtension(StringRef Ext, unsigned MajorVersion, 264 unsigned MinorVersion) { 265 for (auto ExtInfo : {ArrayRef(SupportedExtensions), 266 ArrayRef(SupportedExperimentalExtensions)}) { 267 auto Range = 268 std::equal_range(ExtInfo.begin(), ExtInfo.end(), Ext, LessExtName()); 269 for (auto I = Range.first, E = Range.second; I != E; ++I) 270 if (I->Version.Major == MajorVersion && I->Version.Minor == MinorVersion) 271 return true; 272 } 273 274 return false; 275 } 276 277 bool RISCVISAInfo::hasExtension(StringRef Ext) const { 278 stripExperimentalPrefix(Ext); 279 280 if (!isSupportedExtension(Ext)) 281 return false; 282 283 return Exts.count(Ext.str()) != 0; 284 } 285 286 std::vector<std::string> RISCVISAInfo::toFeatures(bool AddAllExtensions, 287 bool IgnoreUnknown) const { 288 std::vector<std::string> Features; 289 for (const auto &[ExtName, _] : Exts) { 290 // i is a base instruction set, not an extension (see 291 // https://github.com/riscv/riscv-isa-manual/blob/main/src/naming.adoc#base-integer-isa) 292 // and is not recognized in clang -cc1 293 if (ExtName == "i") 294 continue; 295 if (IgnoreUnknown && !isSupportedExtension(ExtName)) 296 continue; 297 298 if (isExperimentalExtension(ExtName)) { 299 Features.push_back((llvm::Twine("+experimental-") + ExtName).str()); 300 } else { 301 Features.push_back((llvm::Twine("+") + ExtName).str()); 302 } 303 } 304 if (AddAllExtensions) { 305 for (const RISCVSupportedExtension &Ext : SupportedExtensions) { 306 if (Exts.count(Ext.Name)) 307 continue; 308 Features.push_back((llvm::Twine("-") + Ext.Name).str()); 309 } 310 311 for (const RISCVSupportedExtension &Ext : SupportedExperimentalExtensions) { 312 if (Exts.count(Ext.Name)) 313 continue; 314 Features.push_back((llvm::Twine("-experimental-") + Ext.Name).str()); 315 } 316 } 317 return Features; 318 } 319 320 static Error getError(const Twine &Message) { 321 return createStringError(errc::invalid_argument, Message); 322 } 323 324 static Error getErrorForInvalidExt(StringRef ExtName) { 325 if (ExtName.size() == 1) { 326 return getError("unsupported standard user-level extension '" + ExtName + 327 "'"); 328 } 329 return getError("unsupported " + getExtensionTypeDesc(ExtName) + " '" + 330 ExtName + "'"); 331 } 332 333 // Extensions may have a version number, and may be separated by 334 // an underscore '_' e.g.: rv32i2_m2. 335 // Version number is divided into major and minor version numbers, 336 // separated by a 'p'. If the minor version is 0 then 'p0' can be 337 // omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1. 338 static Error getExtensionVersion(StringRef Ext, StringRef In, unsigned &Major, 339 unsigned &Minor, unsigned &ConsumeLength, 340 bool EnableExperimentalExtension, 341 bool ExperimentalExtensionVersionCheck) { 342 StringRef MajorStr, MinorStr; 343 Major = 0; 344 Minor = 0; 345 ConsumeLength = 0; 346 MajorStr = In.take_while(isDigit); 347 In = In.substr(MajorStr.size()); 348 349 if (!MajorStr.empty() && In.consume_front("p")) { 350 MinorStr = In.take_while(isDigit); 351 In = In.substr(MajorStr.size() + MinorStr.size() - 1); 352 353 // Expected 'p' to be followed by minor version number. 354 if (MinorStr.empty()) { 355 return getError("minor version number missing after 'p' for extension '" + 356 Ext + "'"); 357 } 358 } 359 360 if (!MajorStr.empty() && MajorStr.getAsInteger(10, Major)) 361 return getError("Failed to parse major version number for extension '" + 362 Ext + "'"); 363 364 if (!MinorStr.empty() && MinorStr.getAsInteger(10, Minor)) 365 return getError("Failed to parse minor version number for extension '" + 366 Ext + "'"); 367 368 ConsumeLength = MajorStr.size(); 369 370 if (!MinorStr.empty()) 371 ConsumeLength += MinorStr.size() + 1 /*'p'*/; 372 373 // Expected multi-character extension with version number to have no 374 // subsequent characters (i.e. must either end string or be followed by 375 // an underscore). 376 if (Ext.size() > 1 && In.size()) 377 return getError( 378 "multi-character extensions must be separated by underscores"); 379 380 // If experimental extension, require use of current version number 381 if (auto ExperimentalExtension = isExperimentalExtension(Ext)) { 382 if (!EnableExperimentalExtension) 383 return getError("requires '-menable-experimental-extensions' " 384 "for experimental extension '" + 385 Ext + "'"); 386 387 if (ExperimentalExtensionVersionCheck && 388 (MajorStr.empty() && MinorStr.empty())) 389 return getError( 390 "experimental extension requires explicit version number `" + Ext + 391 "`"); 392 393 auto SupportedVers = *ExperimentalExtension; 394 if (ExperimentalExtensionVersionCheck && 395 (Major != SupportedVers.Major || Minor != SupportedVers.Minor)) { 396 std::string Error = "unsupported version number " + MajorStr.str(); 397 if (!MinorStr.empty()) 398 Error += "." + MinorStr.str(); 399 Error += " for experimental extension '" + Ext.str() + 400 "' (this compiler supports " + utostr(SupportedVers.Major) + 401 "." + utostr(SupportedVers.Minor) + ")"; 402 return getError(Error); 403 } 404 return Error::success(); 405 } 406 407 // Exception rule for `g`, we don't have clear version scheme for that on 408 // ISA spec. 409 if (Ext == "g") 410 return Error::success(); 411 412 if (MajorStr.empty() && MinorStr.empty()) { 413 if (auto DefaultVersion = findDefaultVersion(Ext)) { 414 Major = DefaultVersion->Major; 415 Minor = DefaultVersion->Minor; 416 } 417 // No matter found or not, return success, assume other place will 418 // verify. 419 return Error::success(); 420 } 421 422 if (RISCVISAInfo::isSupportedExtension(Ext, Major, Minor)) 423 return Error::success(); 424 425 if (!RISCVISAInfo::isSupportedExtension(Ext)) 426 return getErrorForInvalidExt(Ext); 427 428 std::string Error = "unsupported version number " + MajorStr.str(); 429 if (!MinorStr.empty()) 430 Error += "." + MinorStr.str(); 431 Error += " for extension '" + Ext.str() + "'"; 432 return getError(Error); 433 } 434 435 llvm::Expected<std::unique_ptr<RISCVISAInfo>> 436 RISCVISAInfo::createFromExtMap(unsigned XLen, 437 const RISCVISAUtils::OrderedExtensionMap &Exts) { 438 assert(XLen == 32 || XLen == 64); 439 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen)); 440 441 ISAInfo->Exts = Exts; 442 443 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo)); 444 } 445 446 llvm::Expected<std::unique_ptr<RISCVISAInfo>> 447 RISCVISAInfo::parseFeatures(unsigned XLen, 448 const std::vector<std::string> &Features) { 449 assert(XLen == 32 || XLen == 64); 450 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen)); 451 452 for (StringRef ExtName : Features) { 453 assert(ExtName.size() > 1 && (ExtName[0] == '+' || ExtName[0] == '-')); 454 bool Add = ExtName[0] == '+'; 455 ExtName = ExtName.drop_front(1); // Drop '+' or '-' 456 bool Experimental = stripExperimentalPrefix(ExtName); 457 auto ExtensionInfos = Experimental 458 ? ArrayRef(SupportedExperimentalExtensions) 459 : ArrayRef(SupportedExtensions); 460 auto ExtensionInfoIterator = 461 llvm::lower_bound(ExtensionInfos, ExtName, LessExtName()); 462 463 // Not all features is related to ISA extension, like `relax` or 464 // `save-restore`, skip those feature. 465 if (ExtensionInfoIterator == ExtensionInfos.end() || 466 ExtensionInfoIterator->Name != ExtName) 467 continue; 468 469 if (Add) 470 ISAInfo->Exts[ExtName.str()] = ExtensionInfoIterator->Version; 471 else 472 ISAInfo->Exts.erase(ExtName.str()); 473 } 474 475 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo)); 476 } 477 478 llvm::Expected<std::unique_ptr<RISCVISAInfo>> 479 RISCVISAInfo::parseNormalizedArchString(StringRef Arch) { 480 // RISC-V ISA strings must be [a-z0-9_] 481 if (!llvm::all_of( 482 Arch, [](char C) { return isDigit(C) || isLower(C) || C == '_'; })) 483 return getError("string may only contain [a-z0-9_]"); 484 485 // Must start with a valid base ISA name. 486 unsigned XLen = 0; 487 if (Arch.consume_front("rv32")) 488 XLen = 32; 489 else if (Arch.consume_front("rv64")) 490 XLen = 64; 491 492 if (XLen == 0 || Arch.empty() || (Arch[0] != 'i' && Arch[0] != 'e')) 493 return getError("arch string must begin with valid base ISA"); 494 495 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen)); 496 497 // Each extension is of the form ${name}${major_version}p${minor_version} 498 // and separated by _. Split by _ and then extract the name and version 499 // information for each extension. 500 while (!Arch.empty()) { 501 if (Arch[0] == '_') { 502 if (Arch.size() == 1 || Arch[1] == '_') 503 return getError("extension name missing after separator '_'"); 504 Arch = Arch.drop_front(); 505 } 506 507 size_t Idx = Arch.find('_'); 508 StringRef Ext = Arch.slice(0, Idx); 509 Arch = Arch.substr(Idx); 510 511 StringRef Prefix, MinorVersionStr; 512 std::tie(Prefix, MinorVersionStr) = Ext.rsplit('p'); 513 if (MinorVersionStr.empty()) 514 return getError("extension lacks version in expected format"); 515 unsigned MajorVersion, MinorVersion; 516 if (MinorVersionStr.getAsInteger(10, MinorVersion)) 517 return getError("failed to parse minor version number"); 518 519 // Split Prefix into the extension name and the major version number 520 // (the trailing digits of Prefix). 521 size_t VersionStart = Prefix.size(); 522 while (VersionStart != 0) { 523 if (!isDigit(Prefix[VersionStart - 1])) 524 break; 525 --VersionStart; 526 } 527 if (VersionStart == Prefix.size()) 528 return getError("extension lacks version in expected format"); 529 530 if (VersionStart == 0) 531 return getError("missing extension name"); 532 533 StringRef ExtName = Prefix.slice(0, VersionStart); 534 StringRef MajorVersionStr = Prefix.substr(VersionStart); 535 if (MajorVersionStr.getAsInteger(10, MajorVersion)) 536 return getError("failed to parse major version number"); 537 538 if ((ExtName[0] == 'z' || ExtName[0] == 's' || ExtName[0] == 'x') && 539 (ExtName.size() == 1 || isDigit(ExtName[1]))) 540 return getError("'" + Twine(ExtName[0]) + 541 "' must be followed by a letter"); 542 543 if (!ISAInfo->Exts 544 .emplace( 545 ExtName.str(), 546 RISCVISAUtils::ExtensionVersion{MajorVersion, MinorVersion}) 547 .second) 548 return getError("duplicate extension '" + ExtName + "'"); 549 } 550 ISAInfo->updateImpliedLengths(); 551 return std::move(ISAInfo); 552 } 553 554 llvm::Expected<std::unique_ptr<RISCVISAInfo>> 555 RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension, 556 bool ExperimentalExtensionVersionCheck) { 557 // RISC-V ISA strings must be [a-z0-9_] 558 if (!llvm::all_of( 559 Arch, [](char C) { return isDigit(C) || isLower(C) || C == '_'; })) 560 return getError("string may only contain [a-z0-9_]"); 561 562 // ISA string must begin with rv32, rv64, or a profile. 563 unsigned XLen = 0; 564 if (Arch.consume_front("rv32")) { 565 XLen = 32; 566 } else if (Arch.consume_front("rv64")) { 567 XLen = 64; 568 } else { 569 // Try parsing as a profile. 570 auto ProfileCmp = [](StringRef Arch, const RISCVProfile &Profile) { 571 return Arch < Profile.Name; 572 }; 573 auto I = llvm::upper_bound(SupportedProfiles, Arch, ProfileCmp); 574 bool FoundProfile = I != std::begin(SupportedProfiles) && 575 Arch.starts_with(std::prev(I)->Name); 576 if (!FoundProfile) { 577 I = llvm::upper_bound(SupportedExperimentalProfiles, Arch, ProfileCmp); 578 FoundProfile = (I != std::begin(SupportedExperimentalProfiles) && 579 Arch.starts_with(std::prev(I)->Name)); 580 if (FoundProfile && !EnableExperimentalExtension) { 581 return getError("requires '-menable-experimental-extensions' " 582 "for profile '" + 583 std::prev(I)->Name + "'"); 584 } 585 } 586 if (FoundProfile) { 587 --I; 588 std::string NewArch = I->MArch.str(); 589 StringRef ArchWithoutProfile = Arch.drop_front(I->Name.size()); 590 if (!ArchWithoutProfile.empty()) { 591 if (ArchWithoutProfile.front() != '_') 592 return getError("additional extensions must be after separator '_'"); 593 NewArch += ArchWithoutProfile.str(); 594 } 595 return parseArchString(NewArch, EnableExperimentalExtension, 596 ExperimentalExtensionVersionCheck); 597 } 598 } 599 600 if (XLen == 0 || Arch.empty()) 601 return getError( 602 "string must begin with rv32{i,e,g}, rv64{i,e,g}, or a supported " 603 "profile name"); 604 605 std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen)); 606 607 // The canonical order specified in ISA manual. 608 // Ref: Table 22.1 in RISC-V User-Level ISA V2.2 609 char Baseline = Arch.front(); 610 // Skip the baseline. 611 Arch = Arch.drop_front(); 612 613 unsigned Major, Minor, ConsumeLength; 614 615 // First letter should be 'e', 'i' or 'g'. 616 switch (Baseline) { 617 default: 618 return getError("first letter after \'rv" + Twine(XLen) + 619 "\' should be 'e', 'i' or 'g'"); 620 case 'e': 621 case 'i': 622 // Baseline is `i` or `e` 623 if (auto E = getExtensionVersion( 624 StringRef(&Baseline, 1), Arch, Major, Minor, ConsumeLength, 625 EnableExperimentalExtension, ExperimentalExtensionVersionCheck)) 626 return std::move(E); 627 628 ISAInfo->Exts[std::string(1, Baseline)] = {Major, Minor}; 629 break; 630 case 'g': 631 // g expands to extensions in RISCVGImplications. 632 if (!Arch.empty() && isDigit(Arch.front())) 633 return getError("version not supported for 'g'"); 634 635 // Versions for g are disallowed, and this was checked for previously. 636 ConsumeLength = 0; 637 638 // No matter which version is given to `g`, we always set imafd to default 639 // version since the we don't have clear version scheme for that on 640 // ISA spec. 641 for (const char *Ext : RISCVGImplications) { 642 auto Version = findDefaultVersion(Ext); 643 assert(Version && "Default extension version not found?"); 644 ISAInfo->Exts[std::string(Ext)] = {Version->Major, Version->Minor}; 645 } 646 break; 647 } 648 649 // Consume the base ISA version number and any '_' between rvxxx and the 650 // first extension 651 Arch = Arch.drop_front(ConsumeLength); 652 653 while (!Arch.empty()) { 654 if (Arch.front() == '_') { 655 if (Arch.size() == 1 || Arch[1] == '_') 656 return getError("extension name missing after separator '_'"); 657 Arch = Arch.drop_front(); 658 } 659 660 size_t Idx = Arch.find('_'); 661 StringRef Ext = Arch.slice(0, Idx); 662 Arch = Arch.substr(Idx); 663 664 do { 665 StringRef Name, Vers, Desc; 666 if (RISCVISAUtils::AllStdExts.contains(Ext.front())) { 667 Name = Ext.take_front(1); 668 Ext = Ext.drop_front(); 669 Vers = Ext; 670 Desc = "standard user-level extension"; 671 } else if (Ext.front() == 'z' || Ext.front() == 's' || 672 Ext.front() == 'x') { 673 // Handle other types of extensions other than the standard 674 // general purpose and standard user-level extensions. 675 // Parse the ISA string containing non-standard user-level 676 // extensions, standard supervisor-level extensions and 677 // non-standard supervisor-level extensions. 678 // These extensions start with 'z', 's', 'x' prefixes, might have a 679 // version number (major, minor) and are separated by a single 680 // underscore '_'. We do not enforce a canonical order for them. 681 StringRef Type = getExtensionType(Ext); 682 Desc = getExtensionTypeDesc(Ext); 683 auto Pos = findLastNonVersionCharacter(Ext) + 1; 684 Name = Ext.substr(0, Pos); 685 Vers = Ext.substr(Pos); 686 Ext = StringRef(); 687 688 assert(!Type.empty() && "Empty type?"); 689 if (Name.size() == Type.size()) 690 return getError(Desc + " name missing after '" + Type + "'"); 691 } else { 692 return getError("invalid standard user-level extension '" + 693 Twine(Ext.front()) + "'"); 694 } 695 696 unsigned Major, Minor, ConsumeLength; 697 if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength, 698 EnableExperimentalExtension, 699 ExperimentalExtensionVersionCheck)) 700 return E; 701 702 if (Name.size() == 1) 703 Ext = Ext.substr(ConsumeLength); 704 705 if (!RISCVISAInfo::isSupportedExtension(Name)) 706 return getErrorForInvalidExt(Name); 707 708 // Insert and error for duplicates. 709 if (!ISAInfo->Exts 710 .emplace(Name.str(), 711 RISCVISAUtils::ExtensionVersion{Major, Minor}) 712 .second) 713 return getError("duplicated " + Desc + " '" + Name + "'"); 714 715 } while (!Ext.empty()); 716 } 717 718 // We add Zicsr/Zifenci as final to allow duplicated "zicsr"/"zifencei" like 719 // "rv64g_zicsr_zifencei". 720 if (Baseline == 'g') { 721 for (const char *Ext : RISCVGImplicationsZi) { 722 if (ISAInfo->Exts.count(Ext)) 723 continue; 724 725 auto Version = findDefaultVersion(Ext); 726 assert(Version && "Default extension version not found?"); 727 ISAInfo->Exts[std::string(Ext)] = {Version->Major, Version->Minor}; 728 } 729 } 730 731 return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo)); 732 } 733 734 static Error getIncompatibleError(StringRef Ext1, StringRef Ext2) { 735 return getError("'" + Ext1 + "' and '" + Ext2 + 736 "' extensions are incompatible"); 737 } 738 739 static Error getExtensionRequiresError(StringRef Ext, StringRef ReqExt) { 740 return getError("'" + Ext + "' requires '" + ReqExt + 741 "' extension to also be specified"); 742 } 743 744 Error RISCVISAInfo::checkDependency() { 745 bool HasE = Exts.count("e") != 0; 746 bool HasI = Exts.count("i") != 0; 747 bool HasC = Exts.count("c") != 0; 748 bool HasF = Exts.count("f") != 0; 749 bool HasD = Exts.count("d") != 0; 750 bool HasZfinx = Exts.count("zfinx") != 0; 751 bool HasVector = Exts.count("zve32x") != 0; 752 bool HasZvl = MinVLen != 0; 753 bool HasZcmp = Exts.count("zcmp") != 0; 754 bool HasXqccmp = Exts.count("xqccmp") != 0; 755 756 static constexpr StringLiteral XqciExts[] = { 757 {"xqcia"}, {"xqciac"}, {"xqcibi"}, {"xqcibm"}, {"xqcicli"}, 758 {"xqcicm"}, {"xqcics"}, {"xqcicsr"}, {"xqciint"}, {"xqciio"}, 759 {"xqcilb"}, {"xqcili"}, {"xqcilia"}, {"xqcilo"}, {"xqcilsm"}, 760 {"xqcisim"}, {"xqcisls"}, {"xqcisync"}}; 761 static constexpr StringLiteral ZcdOverlaps[] = { 762 {"zcmt"}, {"zcmp"}, {"xqccmp"}, {"xqciac"}, {"xqcicm"}}; 763 764 if (HasI && HasE) 765 return getIncompatibleError("i", "e"); 766 767 if (HasF && HasZfinx) 768 return getIncompatibleError("f", "zfinx"); 769 770 if (HasZvl && !HasVector) 771 return getExtensionRequiresError("zvl*b", "v' or 'zve*"); 772 773 if (HasD && (HasC || Exts.count("zcd"))) 774 for (auto Ext : ZcdOverlaps) 775 if (Exts.count(Ext.str())) 776 return getError( 777 Twine("'") + Ext + "' extension is incompatible with '" + 778 (HasC ? "c" : "zcd") + "' extension when 'd' extension is enabled"); 779 780 if (XLen != 32 && Exts.count("zcf")) 781 return getError("'zcf' is only supported for 'rv32'"); 782 783 if (Exts.count("xwchc") != 0) { 784 if (XLen != 32) 785 return getError("'xwchc' is only supported for 'rv32'"); 786 787 if (HasD) 788 return getIncompatibleError("d", "xwchc"); 789 790 if (Exts.count("zcb") != 0) 791 return getIncompatibleError("xwchc", "zcb"); 792 } 793 794 if (Exts.count("zclsd") != 0) { 795 if (XLen != 32) 796 return getError("'zclsd' is only supported for 'rv32'"); 797 798 if (Exts.count("zcf") != 0) 799 return getIncompatibleError("zclsd", "zcf"); 800 } 801 802 if (XLen != 32 && Exts.count("zilsd") != 0) 803 return getError("'zilsd' is only supported for 'rv32'"); 804 805 for (auto Ext : XqciExts) 806 if (Exts.count(Ext.str()) && (XLen != 32)) 807 return getError("'" + Twine(Ext) + "'" + " is only supported for 'rv32'"); 808 809 if (HasZcmp && HasXqccmp) 810 return getIncompatibleError("zcmp", "xqccmp"); 811 812 return Error::success(); 813 } 814 815 struct ImpliedExtsEntry { 816 StringLiteral Name; 817 const char *ImpliedExt; 818 819 bool operator<(const ImpliedExtsEntry &Other) const { 820 return Name < Other.Name; 821 } 822 }; 823 824 static bool operator<(const ImpliedExtsEntry &LHS, StringRef RHS) { 825 return LHS.Name < RHS; 826 } 827 828 static bool operator<(StringRef LHS, const ImpliedExtsEntry &RHS) { 829 return LHS < RHS.Name; 830 } 831 832 #define GET_IMPLIED_EXTENSIONS 833 #include "llvm/TargetParser/RISCVTargetParserDef.inc" 834 835 void RISCVISAInfo::updateImplication() { 836 bool HasE = Exts.count("e") != 0; 837 bool HasI = Exts.count("i") != 0; 838 839 // If not in e extension and i extension does not exist, i extension is 840 // implied 841 if (!HasE && !HasI) { 842 auto Version = findDefaultVersion("i"); 843 Exts["i"] = *Version; 844 } 845 846 if (HasE && HasI) 847 Exts.erase("i"); 848 849 assert(llvm::is_sorted(ImpliedExts) && "Table not sorted by Name"); 850 851 // This loop may execute over 1 iteration since implication can be layered 852 // Exits loop if no more implication is applied 853 SmallVector<StringRef, 16> WorkList; 854 for (auto const &Ext : Exts) 855 WorkList.push_back(Ext.first); 856 857 while (!WorkList.empty()) { 858 StringRef ExtName = WorkList.pop_back_val(); 859 auto Range = std::equal_range(std::begin(ImpliedExts), 860 std::end(ImpliedExts), ExtName); 861 std::for_each(Range.first, Range.second, 862 [&](const ImpliedExtsEntry &Implied) { 863 const char *ImpliedExt = Implied.ImpliedExt; 864 auto [It, Inserted] = Exts.try_emplace(ImpliedExt); 865 if (!Inserted) 866 return; 867 auto Version = findDefaultVersion(ImpliedExt); 868 It->second = *Version; 869 WorkList.push_back(ImpliedExt); 870 }); 871 } 872 873 // Add Zcd if C and D are enabled. 874 if (Exts.count("c") && Exts.count("d") && !Exts.count("zcd")) { 875 auto Version = findDefaultVersion("zcd"); 876 Exts["zcd"] = *Version; 877 } 878 879 // Add Zcf if C and F are enabled on RV32. 880 if (XLen == 32 && Exts.count("c") && Exts.count("f") && !Exts.count("zcf")) { 881 auto Version = findDefaultVersion("zcf"); 882 Exts["zcf"] = *Version; 883 } 884 885 // Add Zcf if Zce and F are enabled on RV32. 886 if (XLen == 32 && Exts.count("zce") && Exts.count("f") && 887 !Exts.count("zcf")) { 888 auto Version = findDefaultVersion("zcf"); 889 Exts["zcf"] = *Version; 890 } 891 } 892 893 static constexpr StringLiteral CombineIntoExts[] = { 894 {"b"}, {"zk"}, {"zkn"}, {"zks"}, {"zvkn"}, 895 {"zvknc"}, {"zvkng"}, {"zvks"}, {"zvksc"}, {"zvksg"}, 896 }; 897 898 void RISCVISAInfo::updateCombination() { 899 bool MadeChange = false; 900 do { 901 MadeChange = false; 902 for (StringRef CombineExt : CombineIntoExts) { 903 if (Exts.count(CombineExt.str())) 904 continue; 905 906 // Look up the extension in the ImpliesExt table to find everything it 907 // depends on. 908 auto Range = std::equal_range(std::begin(ImpliedExts), 909 std::end(ImpliedExts), CombineExt); 910 bool HasAllRequiredFeatures = std::all_of( 911 Range.first, Range.second, [&](const ImpliedExtsEntry &Implied) { 912 return Exts.count(Implied.ImpliedExt); 913 }); 914 if (HasAllRequiredFeatures) { 915 auto Version = findDefaultVersion(CombineExt); 916 Exts[CombineExt.str()] = *Version; 917 MadeChange = true; 918 } 919 } 920 } while (MadeChange); 921 } 922 923 void RISCVISAInfo::updateImpliedLengths() { 924 assert(FLen == 0 && MaxELenFp == 0 && MaxELen == 0 && MinVLen == 0 && 925 "Expected lengths to be initialied to zero"); 926 927 if (Exts.count("q")) 928 FLen = 128; 929 else if (Exts.count("d")) 930 FLen = 64; 931 else if (Exts.count("f")) 932 FLen = 32; 933 934 if (Exts.count("v")) { 935 MaxELenFp = std::max(MaxELenFp, 64u); 936 MaxELen = std::max(MaxELen, 64u); 937 } 938 939 for (auto const &Ext : Exts) { 940 StringRef ExtName = Ext.first; 941 // Infer MaxELen and MaxELenFp from Zve(32/64)(x/f/d) 942 if (ExtName.consume_front("zve")) { 943 unsigned ZveELen; 944 if (ExtName.consumeInteger(10, ZveELen)) 945 continue; 946 947 if (ExtName == "f") 948 MaxELenFp = std::max(MaxELenFp, 32u); 949 else if (ExtName == "d") 950 MaxELenFp = std::max(MaxELenFp, 64u); 951 else if (ExtName != "x") 952 continue; 953 954 MaxELen = std::max(MaxELen, ZveELen); 955 continue; 956 } 957 958 // Infer MinVLen from zvl*b. 959 if (ExtName.consume_front("zvl")) { 960 unsigned ZvlLen; 961 if (ExtName.consumeInteger(10, ZvlLen)) 962 continue; 963 964 if (ExtName != "b") 965 continue; 966 967 MinVLen = std::max(MinVLen, ZvlLen); 968 continue; 969 } 970 } 971 } 972 973 std::string RISCVISAInfo::toString() const { 974 std::string Buffer; 975 raw_string_ostream Arch(Buffer); 976 977 Arch << "rv" << XLen; 978 979 ListSeparator LS("_"); 980 for (auto const &Ext : Exts) { 981 StringRef ExtName = Ext.first; 982 auto ExtInfo = Ext.second; 983 Arch << LS << ExtName; 984 Arch << ExtInfo.Major << "p" << ExtInfo.Minor; 985 } 986 987 return Arch.str(); 988 } 989 990 llvm::Expected<std::unique_ptr<RISCVISAInfo>> 991 RISCVISAInfo::postProcessAndChecking(std::unique_ptr<RISCVISAInfo> &&ISAInfo) { 992 ISAInfo->updateImplication(); 993 ISAInfo->updateCombination(); 994 ISAInfo->updateImpliedLengths(); 995 996 if (Error Result = ISAInfo->checkDependency()) 997 return std::move(Result); 998 return std::move(ISAInfo); 999 } 1000 1001 StringRef RISCVISAInfo::computeDefaultABI() const { 1002 if (XLen == 32) { 1003 if (Exts.count("e")) 1004 return "ilp32e"; 1005 if (Exts.count("d")) 1006 return "ilp32d"; 1007 if (Exts.count("f")) 1008 return "ilp32f"; 1009 return "ilp32"; 1010 } else if (XLen == 64) { 1011 if (Exts.count("e")) 1012 return "lp64e"; 1013 if (Exts.count("d")) 1014 return "lp64d"; 1015 if (Exts.count("f")) 1016 return "lp64f"; 1017 return "lp64"; 1018 } 1019 llvm_unreachable("Invalid XLEN"); 1020 } 1021 1022 bool RISCVISAInfo::isSupportedExtensionWithVersion(StringRef Ext) { 1023 if (Ext.empty()) 1024 return false; 1025 1026 auto Pos = findLastNonVersionCharacter(Ext) + 1; 1027 StringRef Name = Ext.substr(0, Pos); 1028 StringRef Vers = Ext.substr(Pos); 1029 if (Vers.empty()) 1030 return false; 1031 1032 unsigned Major, Minor, ConsumeLength; 1033 if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength, 1034 true, true)) { 1035 consumeError(std::move(E)); 1036 return false; 1037 } 1038 1039 return true; 1040 } 1041 1042 std::string RISCVISAInfo::getTargetFeatureForExtension(StringRef Ext) { 1043 if (Ext.empty()) 1044 return std::string(); 1045 1046 auto Pos = findLastNonVersionCharacter(Ext) + 1; 1047 StringRef Name = Ext.substr(0, Pos); 1048 1049 if (Pos != Ext.size() && !isSupportedExtensionWithVersion(Ext)) 1050 return std::string(); 1051 1052 if (!isSupportedExtension(Name)) 1053 return std::string(); 1054 1055 return isExperimentalExtension(Name) ? "experimental-" + Name.str() 1056 : Name.str(); 1057 } 1058 1059 struct RISCVExtBit { 1060 const StringLiteral ext; 1061 uint8_t groupid; 1062 uint8_t bitpos; 1063 }; 1064 1065 struct RISCVExtensionBitmask { 1066 const char *Name; 1067 unsigned GroupID; 1068 unsigned BitPosition; 1069 }; 1070 1071 #define GET_RISCVExtensionBitmaskTable_IMPL 1072 #include "llvm/TargetParser/RISCVTargetParserDef.inc" 1073 1074 std::pair<int, int> RISCVISAInfo::getRISCVFeaturesBitsInfo(StringRef Ext) { 1075 // Note that this code currently accepts mixed case extension names, but 1076 // does not handle extension versions at all. That's probably fine because 1077 // there's only one extension version in the __riscv_feature_bits vector. 1078 for (auto E : ExtensionBitmask) 1079 if (Ext.equals_insensitive(E.Name)) 1080 return std::make_pair(E.GroupID, E.BitPosition); 1081 return std::make_pair(-1, -1); 1082 } 1083