RISCVISAInfo.cpp 37 KB

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