brintos

brintos / llvm-project-archived public Read only

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