AArch64TargetParser.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. //===-- AArch64TargetParser - Parser for AArch64 features -------*- 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. //
  9. // This file implements a target parser to recognise AArch64 hardware features
  10. // such as FPU/CPU/ARCH and extension names.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/Support/AArch64TargetParser.h"
  14. #include "llvm/ADT/StringSwitch.h"
  15. #include "llvm/ADT/Triple.h"
  16. #include <cctype>
  17. using namespace llvm;
  18. static unsigned checkArchVersion(llvm::StringRef Arch) {
  19. if (Arch.size() >= 2 && Arch[0] == 'v' && std::isdigit(Arch[1]))
  20. return (Arch[1] - 48);
  21. return 0;
  22. }
  23. unsigned AArch64::getDefaultFPU(StringRef CPU, AArch64::ArchKind AK) {
  24. if (CPU == "generic")
  25. return AArch64ARCHNames[static_cast<unsigned>(AK)].DefaultFPU;
  26. return StringSwitch<unsigned>(CPU)
  27. #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
  28. .Case(NAME, ARM::DEFAULT_FPU)
  29. #include "../../include/llvm/Support/AArch64TargetParser.def"
  30. .Default(ARM::FK_INVALID);
  31. }
  32. uint64_t AArch64::getDefaultExtensions(StringRef CPU, AArch64::ArchKind AK) {
  33. if (CPU == "generic")
  34. return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions;
  35. return StringSwitch<uint64_t>(CPU)
  36. #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
  37. .Case(NAME, AArch64ARCHNames[static_cast<unsigned>(ArchKind::ID)] \
  38. .ArchBaseExtensions | \
  39. DEFAULT_EXT)
  40. #include "../../include/llvm/Support/AArch64TargetParser.def"
  41. .Default(AArch64::AEK_INVALID);
  42. }
  43. AArch64::ArchKind AArch64::getCPUArchKind(StringRef CPU) {
  44. if (CPU == "generic")
  45. return ArchKind::ARMV8A;
  46. return StringSwitch<AArch64::ArchKind>(CPU)
  47. #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
  48. .Case(NAME, ArchKind::ID)
  49. #include "../../include/llvm/Support/AArch64TargetParser.def"
  50. .Default(ArchKind::INVALID);
  51. }
  52. bool AArch64::getExtensionFeatures(uint64_t Extensions,
  53. std::vector<StringRef> &Features) {
  54. if (Extensions == AArch64::AEK_INVALID)
  55. return false;
  56. if (Extensions & AEK_FP)
  57. Features.push_back("+fp-armv8");
  58. if (Extensions & AEK_SIMD)
  59. Features.push_back("+neon");
  60. if (Extensions & AEK_CRC)
  61. Features.push_back("+crc");
  62. if (Extensions & AEK_CRYPTO)
  63. Features.push_back("+crypto");
  64. if (Extensions & AEK_DOTPROD)
  65. Features.push_back("+dotprod");
  66. if (Extensions & AEK_FP16FML)
  67. Features.push_back("+fp16fml");
  68. if (Extensions & AEK_FP16)
  69. Features.push_back("+fullfp16");
  70. if (Extensions & AEK_PROFILE)
  71. Features.push_back("+spe");
  72. if (Extensions & AEK_RAS)
  73. Features.push_back("+ras");
  74. if (Extensions & AEK_LSE)
  75. Features.push_back("+lse");
  76. if (Extensions & AEK_RDM)
  77. Features.push_back("+rdm");
  78. if (Extensions & AEK_SVE)
  79. Features.push_back("+sve");
  80. if (Extensions & AEK_SVE2)
  81. Features.push_back("+sve2");
  82. if (Extensions & AEK_SVE2AES)
  83. Features.push_back("+sve2-aes");
  84. if (Extensions & AEK_SVE2SM4)
  85. Features.push_back("+sve2-sm4");
  86. if (Extensions & AEK_SVE2SHA3)
  87. Features.push_back("+sve2-sha3");
  88. if (Extensions & AEK_SVE2BITPERM)
  89. Features.push_back("+sve2-bitperm");
  90. if (Extensions & AArch64::AEK_TME)
  91. Features.push_back("+tme");
  92. if (Extensions & AEK_RCPC)
  93. Features.push_back("+rcpc");
  94. if (Extensions & AEK_BRBE)
  95. Features.push_back("+brbe");
  96. if (Extensions & AEK_PAUTH)
  97. Features.push_back("+pauth");
  98. if (Extensions & AEK_FLAGM)
  99. Features.push_back("+flagm");
  100. if (Extensions & AArch64::AEK_SME)
  101. Features.push_back("+sme");
  102. if (Extensions & AArch64::AEK_SMEF64)
  103. Features.push_back("+sme-f64");
  104. if (Extensions & AArch64::AEK_SMEI64)
  105. Features.push_back("+sme-i64");
  106. if (Extensions & AArch64::AEK_HBC)
  107. Features.push_back("+hbc");
  108. if (Extensions & AArch64::AEK_MOPS)
  109. Features.push_back("+mops");
  110. if (Extensions & AArch64::AEK_PERFMON)
  111. Features.push_back("+perfmon");
  112. if (Extensions & AArch64::AEK_SSBS)
  113. Features.push_back("+ssbs");
  114. return true;
  115. }
  116. bool AArch64::getArchFeatures(AArch64::ArchKind AK,
  117. std::vector<StringRef> &Features) {
  118. if (AK == ArchKind::ARMV8A)
  119. Features.push_back("+v8a");
  120. if (AK == ArchKind::ARMV8_1A)
  121. Features.push_back("+v8.1a");
  122. if (AK == ArchKind::ARMV8_2A)
  123. Features.push_back("+v8.2a");
  124. if (AK == ArchKind::ARMV8_3A)
  125. Features.push_back("+v8.3a");
  126. if (AK == ArchKind::ARMV8_4A)
  127. Features.push_back("+v8.4a");
  128. if (AK == ArchKind::ARMV8_5A)
  129. Features.push_back("+v8.5a");
  130. if (AK == AArch64::ArchKind::ARMV8_6A)
  131. Features.push_back("+v8.6a");
  132. if (AK == AArch64::ArchKind::ARMV8_7A)
  133. Features.push_back("+v8.7a");
  134. if (AK == AArch64::ArchKind::ARMV8_8A)
  135. Features.push_back("+v8.8a");
  136. if (AK == AArch64::ArchKind::ARMV9A)
  137. Features.push_back("+v9a");
  138. if (AK == AArch64::ArchKind::ARMV9_1A)
  139. Features.push_back("+v9.1a");
  140. if (AK == AArch64::ArchKind::ARMV9_2A)
  141. Features.push_back("+v9.2a");
  142. if (AK == AArch64::ArchKind::ARMV9_3A)
  143. Features.push_back("+v9.3a");
  144. if(AK == AArch64::ArchKind::ARMV8R)
  145. Features.push_back("+v8r");
  146. return AK != ArchKind::INVALID;
  147. }
  148. StringRef AArch64::getArchName(AArch64::ArchKind AK) {
  149. return AArch64ARCHNames[static_cast<unsigned>(AK)].getName();
  150. }
  151. StringRef AArch64::getCPUAttr(AArch64::ArchKind AK) {
  152. return AArch64ARCHNames[static_cast<unsigned>(AK)].getCPUAttr();
  153. }
  154. StringRef AArch64::getSubArch(AArch64::ArchKind AK) {
  155. return AArch64ARCHNames[static_cast<unsigned>(AK)].getSubArch();
  156. }
  157. unsigned AArch64::getArchAttr(AArch64::ArchKind AK) {
  158. return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchAttr;
  159. }
  160. StringRef AArch64::getArchExtName(unsigned ArchExtKind) {
  161. for (const auto &AE : AArch64ARCHExtNames)
  162. if (ArchExtKind == AE.ID)
  163. return AE.getName();
  164. return StringRef();
  165. }
  166. StringRef AArch64::getArchExtFeature(StringRef ArchExt) {
  167. if (ArchExt.startswith("no")) {
  168. StringRef ArchExtBase(ArchExt.substr(2));
  169. for (const auto &AE : AArch64ARCHExtNames) {
  170. if (AE.NegFeature && ArchExtBase == AE.getName())
  171. return StringRef(AE.NegFeature);
  172. }
  173. }
  174. for (const auto &AE : AArch64ARCHExtNames)
  175. if (AE.Feature && ArchExt == AE.getName())
  176. return StringRef(AE.Feature);
  177. return StringRef();
  178. }
  179. StringRef AArch64::getDefaultCPU(StringRef Arch) {
  180. ArchKind AK = parseArch(Arch);
  181. if (AK == ArchKind::INVALID)
  182. return StringRef();
  183. // Look for multiple AKs to find the default for pair AK+Name.
  184. for (const auto &CPU : AArch64CPUNames)
  185. if (CPU.ArchID == AK && CPU.Default)
  186. return CPU.getName();
  187. // If we can't find a default then target the architecture instead
  188. return "generic";
  189. }
  190. void AArch64::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
  191. for (const auto &Arch : AArch64CPUNames) {
  192. if (Arch.ArchID != ArchKind::INVALID)
  193. Values.push_back(Arch.getName());
  194. }
  195. }
  196. bool AArch64::isX18ReservedByDefault(const Triple &TT) {
  197. return TT.isAndroid() || TT.isOSDarwin() || TT.isOSFuchsia() ||
  198. TT.isOSWindows();
  199. }
  200. // Allows partial match, ex. "v8a" matches "armv8a".
  201. AArch64::ArchKind AArch64::parseArch(StringRef Arch) {
  202. Arch = ARM::getCanonicalArchName(Arch);
  203. if (checkArchVersion(Arch) < 8)
  204. return ArchKind::INVALID;
  205. StringRef Syn = ARM::getArchSynonym(Arch);
  206. for (const auto &A : AArch64ARCHNames) {
  207. if (A.getName().endswith(Syn))
  208. return A.ID;
  209. }
  210. return ArchKind::INVALID;
  211. }
  212. AArch64::ArchExtKind AArch64::parseArchExt(StringRef ArchExt) {
  213. for (const auto &A : AArch64ARCHExtNames) {
  214. if (ArchExt == A.getName())
  215. return static_cast<ArchExtKind>(A.ID);
  216. }
  217. return AArch64::AEK_INVALID;
  218. }
  219. AArch64::ArchKind AArch64::parseCPUArch(StringRef CPU) {
  220. for (const auto &C : AArch64CPUNames) {
  221. if (CPU == C.getName())
  222. return C.ArchID;
  223. }
  224. return ArchKind::INVALID;
  225. }