RISCVISAInfo.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. //===-- RISCVISAInfo.cpp - RISCV 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. #include "llvm/Support/RISCVISAInfo.h"
  9. #include "llvm/ADT/None.h"
  10. #include "llvm/ADT/STLExtras.h"
  11. #include "llvm/ADT/SetVector.h"
  12. #include "llvm/ADT/StringExtras.h"
  13. #include "llvm/ADT/StringRef.h"
  14. #include "llvm/Support/Errc.h"
  15. #include "llvm/Support/Error.h"
  16. #include "llvm/Support/raw_ostream.h"
  17. #include <array>
  18. #include <string>
  19. #include <vector>
  20. using namespace llvm;
  21. namespace {
  22. /// Represents the major and version number components of a RISC-V extension
  23. struct RISCVExtensionVersion {
  24. unsigned Major;
  25. unsigned Minor;
  26. };
  27. struct RISCVSupportedExtension {
  28. const char *Name;
  29. /// Supported version.
  30. RISCVExtensionVersion Version;
  31. };
  32. } // end anonymous namespace
  33. static constexpr StringLiteral AllStdExts = "mafdqlcbjtpvn";
  34. static const RISCVSupportedExtension SupportedExtensions[] = {
  35. {"i", RISCVExtensionVersion{2, 0}},
  36. {"e", RISCVExtensionVersion{1, 9}},
  37. {"m", RISCVExtensionVersion{2, 0}},
  38. {"a", RISCVExtensionVersion{2, 0}},
  39. {"f", RISCVExtensionVersion{2, 0}},
  40. {"d", RISCVExtensionVersion{2, 0}},
  41. {"c", RISCVExtensionVersion{2, 0}},
  42. {"zfhmin", RISCVExtensionVersion{1, 0}},
  43. {"zfh", RISCVExtensionVersion{1, 0}},
  44. {"zfinx", RISCVExtensionVersion{1, 0}},
  45. {"zdinx", RISCVExtensionVersion{1, 0}},
  46. {"zhinxmin", RISCVExtensionVersion{1, 0}},
  47. {"zhinx", RISCVExtensionVersion{1, 0}},
  48. {"zba", RISCVExtensionVersion{1, 0}},
  49. {"zbb", RISCVExtensionVersion{1, 0}},
  50. {"zbc", RISCVExtensionVersion{1, 0}},
  51. {"zbs", RISCVExtensionVersion{1, 0}},
  52. {"zbkb", RISCVExtensionVersion{1, 0}},
  53. {"zbkc", RISCVExtensionVersion{1, 0}},
  54. {"zbkx", RISCVExtensionVersion{1, 0}},
  55. {"zknd", RISCVExtensionVersion{1, 0}},
  56. {"zkne", RISCVExtensionVersion{1, 0}},
  57. {"zknh", RISCVExtensionVersion{1, 0}},
  58. {"zksed", RISCVExtensionVersion{1, 0}},
  59. {"zksh", RISCVExtensionVersion{1, 0}},
  60. {"zkr", RISCVExtensionVersion{1, 0}},
  61. {"zkn", RISCVExtensionVersion{1, 0}},
  62. {"zks", RISCVExtensionVersion{1, 0}},
  63. {"zkt", RISCVExtensionVersion{1, 0}},
  64. {"zk", RISCVExtensionVersion{1, 0}},
  65. {"v", RISCVExtensionVersion{1, 0}},
  66. {"zvl32b", RISCVExtensionVersion{1, 0}},
  67. {"zvl64b", RISCVExtensionVersion{1, 0}},
  68. {"zvl128b", RISCVExtensionVersion{1, 0}},
  69. {"zvl256b", RISCVExtensionVersion{1, 0}},
  70. {"zvl512b", RISCVExtensionVersion{1, 0}},
  71. {"zvl1024b", RISCVExtensionVersion{1, 0}},
  72. {"zvl2048b", RISCVExtensionVersion{1, 0}},
  73. {"zvl4096b", RISCVExtensionVersion{1, 0}},
  74. {"zvl8192b", RISCVExtensionVersion{1, 0}},
  75. {"zvl16384b", RISCVExtensionVersion{1, 0}},
  76. {"zvl32768b", RISCVExtensionVersion{1, 0}},
  77. {"zvl65536b", RISCVExtensionVersion{1, 0}},
  78. {"zve32x", RISCVExtensionVersion{1, 0}},
  79. {"zve32f", RISCVExtensionVersion{1, 0}},
  80. {"zve64x", RISCVExtensionVersion{1, 0}},
  81. {"zve64f", RISCVExtensionVersion{1, 0}},
  82. {"zve64d", RISCVExtensionVersion{1, 0}},
  83. };
  84. static const RISCVSupportedExtension SupportedExperimentalExtensions[] = {
  85. {"zbe", RISCVExtensionVersion{0, 93}},
  86. {"zbf", RISCVExtensionVersion{0, 93}},
  87. {"zbm", RISCVExtensionVersion{0, 93}},
  88. {"zbp", RISCVExtensionVersion{0, 93}},
  89. {"zbr", RISCVExtensionVersion{0, 93}},
  90. {"zbt", RISCVExtensionVersion{0, 93}},
  91. };
  92. static bool stripExperimentalPrefix(StringRef &Ext) {
  93. return Ext.consume_front("experimental-");
  94. }
  95. // This function finds the first character that doesn't belong to a version
  96. // (e.g. zbe0p93 is extension 'zbe' of version '0p93'). So the function will
  97. // consume [0-9]*p[0-9]* starting from the backward. An extension name will not
  98. // end with a digit or the letter 'p', so this function will parse correctly.
  99. // NOTE: This function is NOT able to take empty strings or strings that only
  100. // have version numbers and no extension name. It assumes the extension name
  101. // will be at least more than one character.
  102. static size_t findFirstNonVersionCharacter(StringRef Ext) {
  103. assert(!Ext.empty() &&
  104. "Already guarded by if-statement in ::parseArchString");
  105. int Pos = Ext.size() - 1;
  106. while (Pos > 0 && isDigit(Ext[Pos]))
  107. Pos--;
  108. if (Pos > 0 && Ext[Pos] == 'p' && isDigit(Ext[Pos - 1])) {
  109. Pos--;
  110. while (Pos > 0 && isDigit(Ext[Pos]))
  111. Pos--;
  112. }
  113. return Pos;
  114. }
  115. struct FindByName {
  116. FindByName(StringRef Ext) : Ext(Ext){};
  117. StringRef Ext;
  118. bool operator()(const RISCVSupportedExtension &ExtInfo) {
  119. return ExtInfo.Name == Ext;
  120. }
  121. };
  122. static Optional<RISCVExtensionVersion> findDefaultVersion(StringRef ExtName) {
  123. // Find default version of an extension.
  124. // TODO: We might set default version based on profile or ISA spec.
  125. for (auto &ExtInfo : {makeArrayRef(SupportedExtensions),
  126. makeArrayRef(SupportedExperimentalExtensions)}) {
  127. auto ExtensionInfoIterator = llvm::find_if(ExtInfo, FindByName(ExtName));
  128. if (ExtensionInfoIterator == ExtInfo.end()) {
  129. continue;
  130. }
  131. return ExtensionInfoIterator->Version;
  132. }
  133. return None;
  134. }
  135. void RISCVISAInfo::addExtension(StringRef ExtName, unsigned MajorVersion,
  136. unsigned MinorVersion) {
  137. RISCVExtensionInfo Ext;
  138. Ext.ExtName = ExtName.str();
  139. Ext.MajorVersion = MajorVersion;
  140. Ext.MinorVersion = MinorVersion;
  141. Exts[ExtName.str()] = Ext;
  142. }
  143. static StringRef getExtensionTypeDesc(StringRef Ext) {
  144. if (Ext.startswith("sx"))
  145. return "non-standard supervisor-level extension";
  146. if (Ext.startswith("s"))
  147. return "standard supervisor-level extension";
  148. if (Ext.startswith("x"))
  149. return "non-standard user-level extension";
  150. if (Ext.startswith("z"))
  151. return "standard user-level extension";
  152. return StringRef();
  153. }
  154. static StringRef getExtensionType(StringRef Ext) {
  155. if (Ext.startswith("sx"))
  156. return "sx";
  157. if (Ext.startswith("s"))
  158. return "s";
  159. if (Ext.startswith("x"))
  160. return "x";
  161. if (Ext.startswith("z"))
  162. return "z";
  163. return StringRef();
  164. }
  165. static Optional<RISCVExtensionVersion> isExperimentalExtension(StringRef Ext) {
  166. auto ExtIterator =
  167. llvm::find_if(SupportedExperimentalExtensions, FindByName(Ext));
  168. if (ExtIterator == std::end(SupportedExperimentalExtensions))
  169. return None;
  170. return ExtIterator->Version;
  171. }
  172. bool RISCVISAInfo::isSupportedExtensionFeature(StringRef Ext) {
  173. bool IsExperimental = stripExperimentalPrefix(Ext);
  174. if (IsExperimental)
  175. return llvm::any_of(SupportedExperimentalExtensions, FindByName(Ext));
  176. else
  177. return llvm::any_of(SupportedExtensions, FindByName(Ext));
  178. }
  179. bool RISCVISAInfo::isSupportedExtension(StringRef Ext) {
  180. return llvm::any_of(SupportedExtensions, FindByName(Ext)) ||
  181. llvm::any_of(SupportedExperimentalExtensions, FindByName(Ext));
  182. }
  183. bool RISCVISAInfo::isSupportedExtension(StringRef Ext, unsigned MajorVersion,
  184. unsigned MinorVersion) {
  185. auto FindByNameAndVersion = [=](const RISCVSupportedExtension &ExtInfo) {
  186. return ExtInfo.Name == Ext && (MajorVersion == ExtInfo.Version.Major) &&
  187. (MinorVersion == ExtInfo.Version.Minor);
  188. };
  189. return llvm::any_of(SupportedExtensions, FindByNameAndVersion) ||
  190. llvm::any_of(SupportedExperimentalExtensions, FindByNameAndVersion);
  191. }
  192. bool RISCVISAInfo::hasExtension(StringRef Ext) const {
  193. stripExperimentalPrefix(Ext);
  194. if (!isSupportedExtension(Ext))
  195. return false;
  196. return Exts.count(Ext.str()) != 0;
  197. }
  198. // Get the rank for single-letter extension, lower value meaning higher
  199. // priority.
  200. static int singleLetterExtensionRank(char Ext) {
  201. switch (Ext) {
  202. case 'i':
  203. return -2;
  204. case 'e':
  205. return -1;
  206. default:
  207. break;
  208. }
  209. size_t Pos = AllStdExts.find(Ext);
  210. int Rank;
  211. if (Pos == StringRef::npos)
  212. // If we got an unknown extension letter, then give it an alphabetical
  213. // order, but after all known standard extensions.
  214. Rank = AllStdExts.size() + (Ext - 'a');
  215. else
  216. Rank = Pos;
  217. return Rank;
  218. }
  219. // Get the rank for multi-letter extension, lower value meaning higher
  220. // priority/order in canonical order.
  221. static int multiLetterExtensionRank(const std::string &ExtName) {
  222. assert(ExtName.length() >= 2);
  223. int HighOrder;
  224. int LowOrder = 0;
  225. // The order between multi-char extensions: s -> h -> z -> x.
  226. char ExtClass = ExtName[0];
  227. switch (ExtClass) {
  228. case 's':
  229. HighOrder = 0;
  230. break;
  231. case 'h':
  232. HighOrder = 1;
  233. break;
  234. case 'z':
  235. HighOrder = 2;
  236. // `z` extension must be sorted by canonical order of second letter.
  237. // e.g. zmx has higher rank than zax.
  238. LowOrder = singleLetterExtensionRank(ExtName[1]);
  239. break;
  240. case 'x':
  241. HighOrder = 3;
  242. break;
  243. default:
  244. llvm_unreachable("Unknown prefix for multi-char extension");
  245. return -1;
  246. }
  247. return (HighOrder << 8) + LowOrder;
  248. }
  249. // Compare function for extension.
  250. // Only compare the extension name, ignore version comparison.
  251. bool RISCVISAInfo::compareExtension(const std::string &LHS,
  252. const std::string &RHS) {
  253. size_t LHSLen = LHS.length();
  254. size_t RHSLen = RHS.length();
  255. if (LHSLen == 1 && RHSLen != 1)
  256. return true;
  257. if (LHSLen != 1 && RHSLen == 1)
  258. return false;
  259. if (LHSLen == 1 && RHSLen == 1)
  260. return singleLetterExtensionRank(LHS[0]) <
  261. singleLetterExtensionRank(RHS[0]);
  262. // Both are multi-char ext here.
  263. int LHSRank = multiLetterExtensionRank(LHS);
  264. int RHSRank = multiLetterExtensionRank(RHS);
  265. if (LHSRank != RHSRank)
  266. return LHSRank < RHSRank;
  267. // If the rank is same, it must be sorted by lexicographic order.
  268. return LHS < RHS;
  269. }
  270. void RISCVISAInfo::toFeatures(
  271. std::vector<StringRef> &Features,
  272. std::function<StringRef(const Twine &)> StrAlloc) const {
  273. for (auto const &Ext : Exts) {
  274. StringRef ExtName = Ext.first;
  275. if (ExtName == "i")
  276. continue;
  277. if (isExperimentalExtension(ExtName)) {
  278. Features.push_back(StrAlloc("+experimental-" + ExtName));
  279. } else {
  280. Features.push_back(StrAlloc("+" + ExtName));
  281. }
  282. }
  283. }
  284. // Extensions may have a version number, and may be separated by
  285. // an underscore '_' e.g.: rv32i2_m2.
  286. // Version number is divided into major and minor version numbers,
  287. // separated by a 'p'. If the minor version is 0 then 'p0' can be
  288. // omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1.
  289. static Error getExtensionVersion(StringRef Ext, StringRef In, unsigned &Major,
  290. unsigned &Minor, unsigned &ConsumeLength,
  291. bool EnableExperimentalExtension,
  292. bool ExperimentalExtensionVersionCheck) {
  293. StringRef MajorStr, MinorStr;
  294. Major = 0;
  295. Minor = 0;
  296. ConsumeLength = 0;
  297. MajorStr = In.take_while(isDigit);
  298. In = In.substr(MajorStr.size());
  299. if (!MajorStr.empty() && In.consume_front("p")) {
  300. MinorStr = In.take_while(isDigit);
  301. In = In.substr(MajorStr.size() + 1);
  302. // Expected 'p' to be followed by minor version number.
  303. if (MinorStr.empty()) {
  304. return createStringError(
  305. errc::invalid_argument,
  306. "minor version number missing after 'p' for extension '" + Ext + "'");
  307. }
  308. }
  309. if (!MajorStr.empty() && MajorStr.getAsInteger(10, Major))
  310. return createStringError(
  311. errc::invalid_argument,
  312. "Failed to parse major version number for extension '" + Ext + "'");
  313. if (!MinorStr.empty() && MinorStr.getAsInteger(10, Minor))
  314. return createStringError(
  315. errc::invalid_argument,
  316. "Failed to parse minor version number for extension '" + Ext + "'");
  317. ConsumeLength = MajorStr.size();
  318. if (!MinorStr.empty())
  319. ConsumeLength += MinorStr.size() + 1 /*'p'*/;
  320. // Expected multi-character extension with version number to have no
  321. // subsequent characters (i.e. must either end string or be followed by
  322. // an underscore).
  323. if (Ext.size() > 1 && In.size()) {
  324. std::string Error =
  325. "multi-character extensions must be separated by underscores";
  326. return createStringError(errc::invalid_argument, Error);
  327. }
  328. // If experimental extension, require use of current version number number
  329. if (auto ExperimentalExtension = isExperimentalExtension(Ext)) {
  330. if (!EnableExperimentalExtension) {
  331. std::string Error = "requires '-menable-experimental-extensions' for "
  332. "experimental extension '" +
  333. Ext.str() + "'";
  334. return createStringError(errc::invalid_argument, Error);
  335. }
  336. if (ExperimentalExtensionVersionCheck &&
  337. (MajorStr.empty() && MinorStr.empty())) {
  338. std::string Error =
  339. "experimental extension requires explicit version number `" +
  340. Ext.str() + "`";
  341. return createStringError(errc::invalid_argument, Error);
  342. }
  343. auto SupportedVers = *ExperimentalExtension;
  344. if (ExperimentalExtensionVersionCheck &&
  345. (Major != SupportedVers.Major || Minor != SupportedVers.Minor)) {
  346. std::string Error = "unsupported version number " + MajorStr.str();
  347. if (!MinorStr.empty())
  348. Error += "." + MinorStr.str();
  349. Error += " for experimental extension '" + Ext.str() +
  350. "'(this compiler supports " + utostr(SupportedVers.Major) + "." +
  351. utostr(SupportedVers.Minor) + ")";
  352. return createStringError(errc::invalid_argument, Error);
  353. }
  354. return Error::success();
  355. }
  356. // Exception rule for `g`, we don't have clear version scheme for that on
  357. // ISA spec.
  358. if (Ext == "g")
  359. return Error::success();
  360. if (MajorStr.empty() && MinorStr.empty()) {
  361. if (auto DefaultVersion = findDefaultVersion(Ext)) {
  362. Major = DefaultVersion->Major;
  363. Minor = DefaultVersion->Minor;
  364. }
  365. // No matter found or not, return success, assume other place will
  366. // verify.
  367. return Error::success();
  368. }
  369. if (RISCVISAInfo::isSupportedExtension(Ext, Major, Minor))
  370. return Error::success();
  371. std::string Error = "unsupported version number " + std::string(MajorStr);
  372. if (!MinorStr.empty())
  373. Error += "." + MinorStr.str();
  374. Error += " for extension '" + Ext.str() + "'";
  375. return createStringError(errc::invalid_argument, Error);
  376. }
  377. llvm::Expected<std::unique_ptr<RISCVISAInfo>>
  378. RISCVISAInfo::parseFeatures(unsigned XLen,
  379. const std::vector<std::string> &Features) {
  380. assert(XLen == 32 || XLen == 64);
  381. std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
  382. for (auto &Feature : Features) {
  383. StringRef ExtName = Feature;
  384. bool Experimental = false;
  385. assert(ExtName.size() > 1 && (ExtName[0] == '+' || ExtName[0] == '-'));
  386. bool Add = ExtName[0] == '+';
  387. ExtName = ExtName.drop_front(1); // Drop '+' or '-'
  388. Experimental = stripExperimentalPrefix(ExtName);
  389. auto ExtensionInfos = Experimental
  390. ? makeArrayRef(SupportedExperimentalExtensions)
  391. : makeArrayRef(SupportedExtensions);
  392. auto ExtensionInfoIterator =
  393. llvm::find_if(ExtensionInfos, FindByName(ExtName));
  394. // Not all features is related to ISA extension, like `relax` or
  395. // `save-restore`, skip those feature.
  396. if (ExtensionInfoIterator == ExtensionInfos.end())
  397. continue;
  398. if (Add)
  399. ISAInfo->addExtension(ExtName, ExtensionInfoIterator->Version.Major,
  400. ExtensionInfoIterator->Version.Minor);
  401. else
  402. ISAInfo->Exts.erase(ExtName.str());
  403. }
  404. return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
  405. }
  406. llvm::Expected<std::unique_ptr<RISCVISAInfo>>
  407. RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension,
  408. bool ExperimentalExtensionVersionCheck) {
  409. // RISC-V ISA strings must be lowercase.
  410. if (llvm::any_of(Arch, isupper)) {
  411. return createStringError(errc::invalid_argument,
  412. "string must be lowercase");
  413. }
  414. bool HasRV64 = Arch.startswith("rv64");
  415. // ISA string must begin with rv32 or rv64.
  416. if (!(Arch.startswith("rv32") || HasRV64) || (Arch.size() < 5)) {
  417. return createStringError(errc::invalid_argument,
  418. "string must begin with rv32{i,e,g} or rv64{i,g}");
  419. }
  420. unsigned XLen = HasRV64 ? 64 : 32;
  421. std::unique_ptr<RISCVISAInfo> ISAInfo(new RISCVISAInfo(XLen));
  422. // The canonical order specified in ISA manual.
  423. // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
  424. StringRef StdExts = AllStdExts;
  425. char Baseline = Arch[4];
  426. // First letter should be 'e', 'i' or 'g'.
  427. switch (Baseline) {
  428. default:
  429. return createStringError(errc::invalid_argument,
  430. "first letter should be 'e', 'i' or 'g'");
  431. case 'e': {
  432. // Extension 'e' is not allowed in rv64.
  433. if (HasRV64)
  434. return createStringError(
  435. errc::invalid_argument,
  436. "standard user-level extension 'e' requires 'rv32'");
  437. break;
  438. }
  439. case 'i':
  440. break;
  441. case 'g':
  442. // g = imafd
  443. StdExts = StdExts.drop_front(4);
  444. break;
  445. }
  446. // Skip rvxxx
  447. StringRef Exts = Arch.substr(5);
  448. // Remove multi-letter standard extensions, non-standard extensions and
  449. // supervisor-level extensions. They have 'z', 'x', 's', 'sx' prefixes.
  450. // Parse them at the end.
  451. // Find the very first occurrence of 's', 'x' or 'z'.
  452. StringRef OtherExts;
  453. size_t Pos = Exts.find_first_of("zsx");
  454. if (Pos != StringRef::npos) {
  455. OtherExts = Exts.substr(Pos);
  456. Exts = Exts.substr(0, Pos);
  457. }
  458. unsigned Major, Minor, ConsumeLength;
  459. if (auto E = getExtensionVersion(std::string(1, Baseline), Exts, Major, Minor,
  460. ConsumeLength, EnableExperimentalExtension,
  461. ExperimentalExtensionVersionCheck))
  462. return std::move(E);
  463. if (Baseline == 'g') {
  464. // No matter which version is given to `g`, we always set imafd to default
  465. // version since the we don't have clear version scheme for that on
  466. // ISA spec.
  467. for (auto Ext : {"i", "m", "a", "f", "d"})
  468. if (auto Version = findDefaultVersion(Ext))
  469. ISAInfo->addExtension(Ext, Version->Major, Version->Minor);
  470. else
  471. llvm_unreachable("Default extension version not found?");
  472. } else
  473. // Baseline is `i` or `e`
  474. ISAInfo->addExtension(std::string(1, Baseline), Major, Minor);
  475. // Consume the base ISA version number and any '_' between rvxxx and the
  476. // first extension
  477. Exts = Exts.drop_front(ConsumeLength);
  478. Exts.consume_front("_");
  479. // TODO: Use version number when setting target features
  480. auto StdExtsItr = StdExts.begin();
  481. auto StdExtsEnd = StdExts.end();
  482. for (auto I = Exts.begin(), E = Exts.end(); I != E;) {
  483. char C = *I;
  484. // Check ISA extensions are specified in the canonical order.
  485. while (StdExtsItr != StdExtsEnd && *StdExtsItr != C)
  486. ++StdExtsItr;
  487. if (StdExtsItr == StdExtsEnd) {
  488. // Either c contains a valid extension but it was not given in
  489. // canonical order or it is an invalid extension.
  490. if (StdExts.contains(C)) {
  491. return createStringError(
  492. errc::invalid_argument,
  493. "standard user-level extension not given in canonical order '%c'",
  494. C);
  495. }
  496. return createStringError(errc::invalid_argument,
  497. "invalid standard user-level extension '%c'", C);
  498. }
  499. // Move to next char to prevent repeated letter.
  500. ++StdExtsItr;
  501. std::string Next;
  502. unsigned Major, Minor, ConsumeLength;
  503. if (std::next(I) != E)
  504. Next = std::string(std::next(I), E);
  505. if (auto E = getExtensionVersion(std::string(1, C), Next, Major, Minor,
  506. ConsumeLength, EnableExperimentalExtension,
  507. ExperimentalExtensionVersionCheck))
  508. return std::move(E);
  509. // The order is OK, then push it into features.
  510. // TODO: Use version number when setting target features
  511. // Currently LLVM supports only "mafdcbv".
  512. StringRef SupportedStandardExtension = "mafdcbv";
  513. if (!SupportedStandardExtension.contains(C))
  514. return createStringError(errc::invalid_argument,
  515. "unsupported standard user-level extension '%c'",
  516. C);
  517. ISAInfo->addExtension(std::string(1, C), Major, Minor);
  518. // Consume full extension name and version, including any optional '_'
  519. // between this extension and the next
  520. ++I;
  521. I += ConsumeLength;
  522. if (*I == '_')
  523. ++I;
  524. }
  525. // Handle other types of extensions other than the standard
  526. // general purpose and standard user-level extensions.
  527. // Parse the ISA string containing non-standard user-level
  528. // extensions, standard supervisor-level extensions and
  529. // non-standard supervisor-level extensions.
  530. // These extensions start with 'z', 'x', 's', 'sx' prefixes, follow a
  531. // canonical order, might have a version number (major, minor)
  532. // and are separated by a single underscore '_'.
  533. // Set the hardware features for the extensions that are supported.
  534. // Multi-letter extensions are seperated by a single underscore
  535. // as described in RISC-V User-Level ISA V2.2.
  536. SmallVector<StringRef, 8> Split;
  537. OtherExts.split(Split, '_');
  538. SmallVector<StringRef, 8> AllExts;
  539. std::array<StringRef, 4> Prefix{"z", "x", "s", "sx"};
  540. auto I = Prefix.begin();
  541. auto E = Prefix.end();
  542. if (Split.size() > 1 || Split[0] != "") {
  543. for (StringRef Ext : Split) {
  544. if (Ext.empty())
  545. return createStringError(errc::invalid_argument,
  546. "extension name missing after separator '_'");
  547. StringRef Type = getExtensionType(Ext);
  548. StringRef Desc = getExtensionTypeDesc(Ext);
  549. auto Pos = findFirstNonVersionCharacter(Ext) + 1;
  550. StringRef Name(Ext.substr(0, Pos));
  551. StringRef Vers(Ext.substr(Pos));
  552. if (Type.empty())
  553. return createStringError(errc::invalid_argument,
  554. "invalid extension prefix '" + Ext + "'");
  555. // Check ISA extensions are specified in the canonical order.
  556. while (I != E && *I != Type)
  557. ++I;
  558. if (I == E)
  559. return createStringError(errc::invalid_argument,
  560. "%s not given in canonical order '%s'",
  561. Desc.str().c_str(), Ext.str().c_str());
  562. if (Name.size() == Type.size()) {
  563. return createStringError(errc::invalid_argument,
  564. "%s name missing after '%s'",
  565. Desc.str().c_str(), Type.str().c_str());
  566. }
  567. unsigned Major, Minor, ConsumeLength;
  568. if (auto E = getExtensionVersion(Name, Vers, Major, Minor, ConsumeLength,
  569. EnableExperimentalExtension,
  570. ExperimentalExtensionVersionCheck))
  571. return std::move(E);
  572. // Check if duplicated extension.
  573. if (llvm::is_contained(AllExts, Name))
  574. return createStringError(errc::invalid_argument, "duplicated %s '%s'",
  575. Desc.str().c_str(), Name.str().c_str());
  576. ISAInfo->addExtension(Name, Major, Minor);
  577. // Extension format is correct, keep parsing the extensions.
  578. // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
  579. AllExts.push_back(Name);
  580. }
  581. }
  582. for (auto Ext : AllExts) {
  583. if (!isSupportedExtension(Ext)) {
  584. StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext));
  585. return createStringError(errc::invalid_argument, "unsupported %s '%s'",
  586. Desc.str().c_str(), Ext.str().c_str());
  587. }
  588. }
  589. return RISCVISAInfo::postProcessAndChecking(std::move(ISAInfo));
  590. }
  591. Error RISCVISAInfo::checkDependency() {
  592. bool IsRv32 = XLen == 32;
  593. bool HasE = Exts.count("e") != 0;
  594. bool HasD = Exts.count("d") != 0;
  595. bool HasF = Exts.count("f") != 0;
  596. bool HasZfinx = Exts.count("zfinx") != 0;
  597. bool HasZdinx = Exts.count("zdinx") != 0;
  598. bool HasZve32x = Exts.count("zve32x") != 0;
  599. bool HasZve32f = Exts.count("zve32f") != 0;
  600. bool HasZve64d = Exts.count("zve64d") != 0;
  601. bool HasV = Exts.count("v") != 0;
  602. bool HasVector = HasZve32x || HasV;
  603. bool HasZvl = MinVLen != 0;
  604. if (HasE && !IsRv32)
  605. return createStringError(
  606. errc::invalid_argument,
  607. "standard user-level extension 'e' requires 'rv32'");
  608. // It's illegal to specify the 'd' (double-precision floating point)
  609. // extension without also specifying the 'f' (single precision
  610. // floating-point) extension.
  611. // TODO: This has been removed in later specs, which specify that D implies F
  612. if (HasD && !HasF)
  613. return createStringError(errc::invalid_argument,
  614. "d requires f extension to also be specified");
  615. if (HasZve32f && !HasF && !HasZfinx)
  616. return createStringError(
  617. errc::invalid_argument,
  618. "zve32f requires f or zfinx extension to also be specified");
  619. if (HasZve64d && !HasD && !HasZdinx)
  620. return createStringError(
  621. errc::invalid_argument,
  622. "zve64d requires d or zdinx extension to also be specified");
  623. if (HasZvl && !HasVector)
  624. return createStringError(
  625. errc::invalid_argument,
  626. "zvl*b requires v or zve* extension to also be specified");
  627. // Additional dependency checks.
  628. // TODO: The 'q' extension requires rv64.
  629. // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.
  630. return Error::success();
  631. }
  632. static const char *ImpliedExtsV[] = {"zvl128b", "f", "d"};
  633. static const char *ImpliedExtsZfhmin[] = {"f"};
  634. static const char *ImpliedExtsZfh[] = {"f"};
  635. static const char *ImpliedExtsZdinx[] = {"zfinx"};
  636. static const char *ImpliedExtsZhinxmin[] = {"zfinx"};
  637. static const char *ImpliedExtsZhinx[] = {"zfinx"};
  638. static const char *ImpliedExtsZve64d[] = {"zve64f"};
  639. static const char *ImpliedExtsZve64f[] = {"zve64x", "zve32f"};
  640. static const char *ImpliedExtsZve64x[] = {"zve32x", "zvl64b"};
  641. static const char *ImpliedExtsZve32f[] = {"zve32x"};
  642. static const char *ImpliedExtsZve32x[] = {"zvl32b"};
  643. static const char *ImpliedExtsZvl65536b[] = {"zvl32768b"};
  644. static const char *ImpliedExtsZvl32768b[] = {"zvl16384b"};
  645. static const char *ImpliedExtsZvl16384b[] = {"zvl8192b"};
  646. static const char *ImpliedExtsZvl8192b[] = {"zvl4096b"};
  647. static const char *ImpliedExtsZvl4096b[] = {"zvl2048b"};
  648. static const char *ImpliedExtsZvl2048b[] = {"zvl1024b"};
  649. static const char *ImpliedExtsZvl1024b[] = {"zvl512b"};
  650. static const char *ImpliedExtsZvl512b[] = {"zvl256b"};
  651. static const char *ImpliedExtsZvl256b[] = {"zvl128b"};
  652. static const char *ImpliedExtsZvl128b[] = {"zvl64b"};
  653. static const char *ImpliedExtsZvl64b[] = {"zvl32b"};
  654. static const char *ImpliedExtsZk[] = {"zkn", "zkt", "zkr"};
  655. static const char *ImpliedExtsZkn[] = {"zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"};
  656. static const char *ImpliedExtsZks[] = {"zbkb", "zbkc", "zbkx", "zksed", "zksh"};
  657. struct ImpliedExtsEntry {
  658. StringLiteral Name;
  659. ArrayRef<const char *> Exts;
  660. bool operator<(const ImpliedExtsEntry &Other) const {
  661. return Name < Other.Name;
  662. }
  663. bool operator<(StringRef Other) const { return Name < Other; }
  664. };
  665. // Note: The table needs to be sorted by name.
  666. static constexpr ImpliedExtsEntry ImpliedExts[] = {
  667. {{"v"}, {ImpliedExtsV}},
  668. {{"zdinx"}, {ImpliedExtsZdinx}},
  669. {{"zfh"}, {ImpliedExtsZfh}},
  670. {{"zfhmin"}, {ImpliedExtsZfhmin}},
  671. {{"zhinx"}, {ImpliedExtsZhinx}},
  672. {{"zhinxmin"}, {ImpliedExtsZhinxmin}},
  673. {{"zk"}, {ImpliedExtsZk}},
  674. {{"zkn"}, {ImpliedExtsZkn}},
  675. {{"zks"}, {ImpliedExtsZks}},
  676. {{"zve32f"}, {ImpliedExtsZve32f}},
  677. {{"zve32x"}, {ImpliedExtsZve32x}},
  678. {{"zve64d"}, {ImpliedExtsZve64d}},
  679. {{"zve64f"}, {ImpliedExtsZve64f}},
  680. {{"zve64x"}, {ImpliedExtsZve64x}},
  681. {{"zvl1024b"}, {ImpliedExtsZvl1024b}},
  682. {{"zvl128b"}, {ImpliedExtsZvl128b}},
  683. {{"zvl16384b"}, {ImpliedExtsZvl16384b}},
  684. {{"zvl2048b"}, {ImpliedExtsZvl2048b}},
  685. {{"zvl256b"}, {ImpliedExtsZvl256b}},
  686. {{"zvl32768b"}, {ImpliedExtsZvl32768b}},
  687. {{"zvl4096b"}, {ImpliedExtsZvl4096b}},
  688. {{"zvl512b"}, {ImpliedExtsZvl512b}},
  689. {{"zvl64b"}, {ImpliedExtsZvl64b}},
  690. {{"zvl65536b"}, {ImpliedExtsZvl65536b}},
  691. {{"zvl8192b"}, {ImpliedExtsZvl8192b}},
  692. };
  693. void RISCVISAInfo::updateImplication() {
  694. bool HasE = Exts.count("e") != 0;
  695. bool HasI = Exts.count("i") != 0;
  696. // If not in e extension and i extension does not exist, i extension is
  697. // implied
  698. if (!HasE && !HasI) {
  699. auto Version = findDefaultVersion("i");
  700. addExtension("i", Version->Major, Version->Minor);
  701. }
  702. assert(llvm::is_sorted(ImpliedExts) && "Table not sorted by Name");
  703. // This loop may execute over 1 iteration since implication can be layered
  704. // Exits loop if no more implication is applied
  705. SmallSetVector<StringRef, 16> WorkList;
  706. for (auto const &Ext : Exts)
  707. WorkList.insert(Ext.first);
  708. while (!WorkList.empty()) {
  709. StringRef ExtName = WorkList.pop_back_val();
  710. auto I = llvm::lower_bound(ImpliedExts, ExtName);
  711. if (I != std::end(ImpliedExts) && I->Name == ExtName) {
  712. for (const char *ImpliedExt : I->Exts) {
  713. if (WorkList.count(ImpliedExt))
  714. continue;
  715. if (Exts.count(ImpliedExt))
  716. continue;
  717. auto Version = findDefaultVersion(ImpliedExt);
  718. addExtension(ImpliedExt, Version->Major, Version->Minor);
  719. WorkList.insert(ImpliedExt);
  720. }
  721. }
  722. }
  723. }
  724. void RISCVISAInfo::updateFLen() {
  725. FLen = 0;
  726. // TODO: Handle q extension.
  727. if (Exts.count("d"))
  728. FLen = 64;
  729. else if (Exts.count("f"))
  730. FLen = 32;
  731. }
  732. void RISCVISAInfo::updateMinVLen() {
  733. for (auto const &Ext : Exts) {
  734. StringRef ExtName = Ext.first;
  735. bool IsZvlExt = ExtName.consume_front("zvl") && ExtName.consume_back("b");
  736. if (IsZvlExt) {
  737. unsigned ZvlLen;
  738. if (!ExtName.getAsInteger(10, ZvlLen))
  739. MinVLen = std::max(MinVLen, ZvlLen);
  740. }
  741. }
  742. }
  743. void RISCVISAInfo::updateMaxELen() {
  744. // handles EEW restriction by sub-extension zve
  745. for (auto const &Ext : Exts) {
  746. StringRef ExtName = Ext.first;
  747. bool IsZveExt = ExtName.consume_front("zve");
  748. if (IsZveExt) {
  749. if (ExtName.back() == 'f')
  750. MaxELenFp = std::max(MaxELenFp, 32u);
  751. if (ExtName.back() == 'd')
  752. MaxELenFp = std::max(MaxELenFp, 64u);
  753. ExtName = ExtName.drop_back();
  754. unsigned ZveELen;
  755. ExtName.getAsInteger(10, ZveELen);
  756. MaxELen = std::max(MaxELen, ZveELen);
  757. }
  758. if (ExtName == "v") {
  759. MaxELenFp = 64;
  760. MaxELen = 64;
  761. return;
  762. }
  763. }
  764. }
  765. std::string RISCVISAInfo::toString() const {
  766. std::string Buffer;
  767. raw_string_ostream Arch(Buffer);
  768. Arch << "rv" << XLen;
  769. ListSeparator LS("_");
  770. for (auto const &Ext : Exts) {
  771. StringRef ExtName = Ext.first;
  772. auto ExtInfo = Ext.second;
  773. Arch << LS << ExtName;
  774. Arch << ExtInfo.MajorVersion << "p" << ExtInfo.MinorVersion;
  775. }
  776. return Arch.str();
  777. }
  778. std::vector<std::string> RISCVISAInfo::toFeatureVector() const {
  779. std::vector<std::string> FeatureVector;
  780. for (auto const &Ext : Exts) {
  781. std::string ExtName = Ext.first;
  782. if (ExtName == "i") // i is not recognized in clang -cc1
  783. continue;
  784. std::string Feature = isExperimentalExtension(ExtName)
  785. ? "+experimental-" + ExtName
  786. : "+" + ExtName;
  787. FeatureVector.push_back(Feature);
  788. }
  789. return FeatureVector;
  790. }
  791. llvm::Expected<std::unique_ptr<RISCVISAInfo>>
  792. RISCVISAInfo::postProcessAndChecking(std::unique_ptr<RISCVISAInfo> &&ISAInfo) {
  793. ISAInfo->updateImplication();
  794. ISAInfo->updateFLen();
  795. ISAInfo->updateMinVLen();
  796. ISAInfo->updateMaxELen();
  797. if (Error Result = ISAInfo->checkDependency())
  798. return std::move(Result);
  799. return std::move(ISAInfo);
  800. }