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