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.slice(Idx, StringRef::npos); 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.slice(VersionStart, StringRef::npos); 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.slice(Idx, StringRef::npos); 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 Error RISCVISAInfo::checkDependency() { 725 bool HasE = Exts.count("e") != 0; 726 bool HasI = Exts.count("i") != 0; 727 bool HasC = Exts.count("c") != 0; 728 bool HasF = Exts.count("f") != 0; 729 bool HasD = Exts.count("d") != 0; 730 bool HasZfinx = Exts.count("zfinx") != 0; 731 bool HasVector = Exts.count("zve32x") != 0; 732 bool HasZvl = MinVLen != 0; 733 bool HasZcmt = Exts.count("zcmt") != 0; 734 735 if (HasI && HasE) 736 return getError("'I' and 'E' extensions are incompatible"); 737 738 if (HasF && HasZfinx) 739 return getError("'f' and 'zfinx' extensions are incompatible"); 740 741 if (HasZvl && !HasVector) 742 return getError( 743 "'zvl*b' requires 'v' or 'zve*' extension to also be specified"); 744 745 if (Exts.count("zvbb") && !HasVector) 746 return getError( 747 "'zvbb' requires 'v' or 'zve*' extension to also be specified"); 748 749 if (Exts.count("zvbc") && !Exts.count("zve64x")) 750 return getError( 751 "'zvbc' requires 'v' or 'zve64*' extension to also be specified"); 752 753 if ((Exts.count("zvkb") || Exts.count("zvkg") || Exts.count("zvkned") || 754 Exts.count("zvknha") || Exts.count("zvksed") || Exts.count("zvksh")) && 755 !HasVector) 756 return getError( 757 "'zvk*' requires 'v' or 'zve*' extension to also be specified"); 758 759 if (Exts.count("zvknhb") && !Exts.count("zve64x")) 760 return getError( 761 "'zvknhb' requires 'v' or 'zve64*' extension to also be specified"); 762 763 if ((HasZcmt || Exts.count("zcmp")) && HasD && (HasC || Exts.count("zcd"))) 764 return getError(Twine("'") + (HasZcmt ? "zcmt" : "zcmp") + 765 "' extension is incompatible with '" + 766 (HasC ? "c" : "zcd") + 767 "' extension when 'd' extension is enabled"); 768 769 if (XLen != 32 && Exts.count("zcf")) 770 return getError("'zcf' is only supported for 'rv32'"); 771 772 if (Exts.count("zacas") && !(Exts.count("a") || Exts.count("zaamo"))) 773 return getError( 774 "'zacas' requires 'a' or 'zaamo' extension to also be specified"); 775 776 if (Exts.count("zabha") && !(Exts.count("a") || Exts.count("zaamo"))) 777 return getError( 778 "'zabha' requires 'a' or 'zaamo' extension to also be specified"); 779 780 if (Exts.count("xwchc") != 0) { 781 if (XLen != 32) 782 return getError("'Xwchc' is only supported for 'rv32'"); 783 784 if (HasD) 785 return getError("'D' and 'Xwchc' extensions are incompatible"); 786 787 if (Exts.count("zcb") != 0) 788 return getError("'Xwchc' and 'Zcb' extensions are incompatible"); 789 } 790 791 return Error::success(); 792 } 793 794 struct ImpliedExtsEntry { 795 StringLiteral Name; 796 const char *ImpliedExt; 797 798 bool operator<(const ImpliedExtsEntry &Other) const { 799 return Name < Other.Name; 800 } 801 }; 802 803 static bool operator<(const ImpliedExtsEntry &LHS, StringRef RHS) { 804 return LHS.Name < RHS; 805 } 806 807 static bool operator<(StringRef LHS, const ImpliedExtsEntry &RHS) { 808 return LHS < RHS.Name; 809 } 810 811 #define GET_IMPLIED_EXTENSIONS 812 #include "llvm/TargetParser/RISCVTargetParserDef.inc" 813 814 void RISCVISAInfo::updateImplication() { 815 bool HasE = Exts.count("e") != 0; 816 bool HasI = Exts.count("i") != 0; 817 818 // If not in e extension and i extension does not exist, i extension is 819 // implied 820 if (!HasE && !HasI) { 821 auto Version = findDefaultVersion("i"); 822 Exts["i"] = *Version; 823 } 824 825 if (HasE && HasI) 826 Exts.erase("i"); 827 828 assert(llvm::is_sorted(ImpliedExts) && "Table not sorted by Name"); 829 830 // This loop may execute over 1 iteration since implication can be layered 831 // Exits loop if no more implication is applied 832 SmallVector<StringRef, 16> WorkList; 833 for (auto const &Ext : Exts) 834 WorkList.push_back(Ext.first); 835 836 while (!WorkList.empty()) { 837 StringRef ExtName = WorkList.pop_back_val(); 838 auto Range = std::equal_range(std::begin(ImpliedExts), 839 std::end(ImpliedExts), ExtName); 840 std::for_each(Range.first, Range.second, 841 [&](const ImpliedExtsEntry &Implied) { 842 const char *ImpliedExt = Implied.ImpliedExt; 843 if (Exts.count(ImpliedExt)) 844 return; 845 auto Version = findDefaultVersion(ImpliedExt); 846 Exts[ImpliedExt] = *Version; 847 WorkList.push_back(ImpliedExt); 848 }); 849 } 850 851 // Add Zcf if Zce and F are enabled on RV32. 852 if (XLen == 32 && Exts.count("zce") && Exts.count("f") && 853 !Exts.count("zcf")) { 854 auto Version = findDefaultVersion("zcf"); 855 Exts["zcf"] = *Version; 856 } 857 } 858 859 static constexpr StringLiteral CombineIntoExts[] = { 860 {"zk"}, {"zkn"}, {"zks"}, {"zvkn"}, {"zvknc"}, 861 {"zvkng"}, {"zvks"}, {"zvksc"}, {"zvksg"}, 862 }; 863 864 void RISCVISAInfo::updateCombination() { 865 bool MadeChange = false; 866 do { 867 MadeChange = false; 868 for (StringRef CombineExt : CombineIntoExts) { 869 if (Exts.count(CombineExt.str())) 870 continue; 871 872 // Look up the extension in the ImpliesExt table to find everything it 873 // depends on. 874 auto Range = std::equal_range(std::begin(ImpliedExts), 875 std::end(ImpliedExts), CombineExt); 876 bool HasAllRequiredFeatures = std::all_of( 877 Range.first, Range.second, [&](const ImpliedExtsEntry &Implied) { 878 return Exts.count(Implied.ImpliedExt); 879 }); 880 if (HasAllRequiredFeatures) { 881 auto Version = findDefaultVersion(CombineExt); 882 Exts[CombineExt.str()] = *Version; 883 MadeChange = true; 884 } 885 } 886 } while (MadeChange); 887 } 888 889 void RISCVISAInfo::updateImpliedLengths() { 890 assert(FLen == 0 && MaxELenFp == 0 && MaxELen == 0 && MinVLen == 0 && 891 "Expected lengths to be initialied to zero"); 892 893 // TODO: Handle q extension. 894 if (Exts.count("d")) 895 FLen = 64; 896 else if (Exts.count("f")) 897 FLen = 32; 898 899 if (Exts.count("v")) { 900 MaxELenFp = std::max(MaxELenFp, 64u); 901 MaxELen = std::max(MaxELen, 64u); 902 } 903 904 for (auto const &Ext : Exts) { 905 StringRef ExtName = Ext.first; 906 // Infer MaxELen and MaxELenFp from Zve(32/64)(x/f/d) 907 if (ExtName.consume_front("zve")) { 908 unsigned ZveELen; 909 if (ExtName.consumeInteger(10, ZveELen)) 910 continue; 911 912 if (ExtName == "f") 913 MaxELenFp = std::max(MaxELenFp, 32u); 914 else if (ExtName == "d") 915 MaxELenFp = std::max(MaxELenFp, 64u); 916 else if (ExtName != "x") 917 continue; 918 919 MaxELen = std::max(MaxELen, ZveELen); 920 continue; 921 } 922 923 // Infer MinVLen from zvl*b. 924 if (ExtName.consume_front("zvl")) { 925 unsigned ZvlLen; 926 if (ExtName.consumeInteger(10, ZvlLen)) 927 continue; 928 929 if (ExtName != "b") 930 continue; 931 932 MinVLen = std::max(MinVLen, ZvlLen); 933 continue; 934 } 935 } 936 } 937 938 std::string RISCVISAInfo::toString() const { 939 std::string Buffer; 940 raw_string_ostream Arch(Buffer); 941 942 Arch << "rv" << XLen; 943 944 ListSeparator LS("_"); 945 for (auto const &Ext : Exts) { 946 StringRef ExtName = Ext.first; 947 auto ExtInfo = Ext.second; 948 Arch << LS << ExtName; 949 Arch << ExtInfo.Major << "p" << ExtInfo.Minor; 950 } 951 952 return Arch.str(); 953 } 954 955 llvm::Expected<std::unique_ptr<RISCVISAInfo>> 956 RISCVISAInfo::postProcessAndChecking(std::unique_ptr<RISCVISAInfo> &&ISAInfo) { 957 ISAInfo->updateImplication(); 958 ISAInfo->updateCombination(); 959 ISAInfo->updateImpliedLengths(); 960 961 if (Error Result = ISAInfo->checkDependency()) 962 return std::move(Result); 963 return std::move(ISAInfo); 964 } 965 966 StringRef RISCVISAInfo::computeDefaultABI() const { 967 if (XLen == 32) { 968 if (Exts.count("e")) 969 return "ilp32e"; 970 if (Exts.count("d")) 971 return "ilp32d"; 972 if (Exts.count("f")) 973 return "ilp32f"; 974 return "ilp32"; 975 } else if (XLen == 64) { 976 if (Exts.count("e")) 977 return "lp64e"; 978 if (Exts.count("d")) 979 return "lp64d"; 980 if (Exts.count("f")) 981 return "lp64f"; 982 return "lp64"; 983 } 984 llvm_unreachable("Invalid XLEN"); 985 } 986 987 bool RISCVISAInfo::isSupportedExtensionWithVersion(StringRef Ext) { 988 if (Ext.empty()) 989 return false; 990 991 auto Pos = findLastNonVersionCharacter(Ext) + 1; 992 StringRef Name = Ext.substr(0, Pos); 993 StringRef Vers = Ext.substr(Pos); 994 if (Vers.empty()) 995 return false; 996 997 unsigned Major, Minor, ConsumeLength; 998 if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength, 999 true, true)) { 1000 consumeError(std::move(E)); 1001 return false; 1002 } 1003 1004 return true; 1005 } 1006 1007 std::string RISCVISAInfo::getTargetFeatureForExtension(StringRef Ext) { 1008 if (Ext.empty()) 1009 return std::string(); 1010 1011 auto Pos = findLastNonVersionCharacter(Ext) + 1; 1012 StringRef Name = Ext.substr(0, Pos); 1013 1014 if (Pos != Ext.size() && !isSupportedExtensionWithVersion(Ext)) 1015 return std::string(); 1016 1017 if (!isSupportedExtension(Name)) 1018 return std::string(); 1019 1020 return isExperimentalExtension(Name) ? "experimental-" + Name.str() 1021 : Name.str(); 1022 } 1023