ARMTargetParser.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===-- ARMTargetParser - Parser for ARM target features --------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file implements a target parser to recognise ARM hardware features
  15. // such as FPU/CPU/ARCH/extensions and specific support such as HWDIV.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_TARGETPARSER_ARMTARGETPARSER_H
  19. #define LLVM_TARGETPARSER_ARMTARGETPARSER_H
  20. #include "llvm/ADT/StringRef.h"
  21. #include "llvm/Support/ARMBuildAttributes.h"
  22. #include "llvm/TargetParser/ARMTargetParserCommon.h"
  23. #include <vector>
  24. namespace llvm {
  25. class Triple;
  26. namespace ARM {
  27. // Arch extension modifiers for CPUs.
  28. // Note that this is not the same as the AArch64 list
  29. enum ArchExtKind : uint64_t {
  30. AEK_INVALID = 0,
  31. AEK_NONE = 1,
  32. AEK_CRC = 1 << 1,
  33. AEK_CRYPTO = 1 << 2,
  34. AEK_FP = 1 << 3,
  35. AEK_HWDIVTHUMB = 1 << 4,
  36. AEK_HWDIVARM = 1 << 5,
  37. AEK_MP = 1 << 6,
  38. AEK_SIMD = 1 << 7,
  39. AEK_SEC = 1 << 8,
  40. AEK_VIRT = 1 << 9,
  41. AEK_DSP = 1 << 10,
  42. AEK_FP16 = 1 << 11,
  43. AEK_RAS = 1 << 12,
  44. AEK_DOTPROD = 1 << 13,
  45. AEK_SHA2 = 1 << 14,
  46. AEK_AES = 1 << 15,
  47. AEK_FP16FML = 1 << 16,
  48. AEK_SB = 1 << 17,
  49. AEK_FP_DP = 1 << 18,
  50. AEK_LOB = 1 << 19,
  51. AEK_BF16 = 1 << 20,
  52. AEK_I8MM = 1 << 21,
  53. AEK_CDECP0 = 1 << 22,
  54. AEK_CDECP1 = 1 << 23,
  55. AEK_CDECP2 = 1 << 24,
  56. AEK_CDECP3 = 1 << 25,
  57. AEK_CDECP4 = 1 << 26,
  58. AEK_CDECP5 = 1 << 27,
  59. AEK_CDECP6 = 1 << 28,
  60. AEK_CDECP7 = 1 << 29,
  61. AEK_PACBTI = 1 << 30,
  62. // Unsupported extensions.
  63. AEK_OS = 1ULL << 59,
  64. AEK_IWMMXT = 1ULL << 60,
  65. AEK_IWMMXT2 = 1ULL << 61,
  66. AEK_MAVERICK = 1ULL << 62,
  67. AEK_XSCALE = 1ULL << 63,
  68. };
  69. // List of Arch Extension names.
  70. struct ExtName {
  71. StringRef Name;
  72. uint64_t ID;
  73. StringRef Feature;
  74. StringRef NegFeature;
  75. };
  76. const ExtName ARCHExtNames[] = {
  77. #define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
  78. {NAME, ID, FEATURE, NEGFEATURE},
  79. #include "ARMTargetParser.def"
  80. };
  81. // List of HWDiv names (use getHWDivSynonym) and which architectural
  82. // features they correspond to (use getHWDivFeatures).
  83. const struct {
  84. StringRef Name;
  85. uint64_t ID;
  86. } HWDivNames[] = {
  87. #define ARM_HW_DIV_NAME(NAME, ID) {NAME, ID},
  88. #include "ARMTargetParser.def"
  89. };
  90. // Arch names.
  91. enum class ArchKind {
  92. #define ARM_ARCH(NAME, ID, CPU_ATTR, ARCH_FEATURE, ARCH_ATTR, ARCH_FPU, \
  93. ARCH_BASE_EXT) \
  94. ID,
  95. #include "ARMTargetParser.def"
  96. };
  97. // List of CPU names and their arches.
  98. // The same CPU can have multiple arches and can be default on multiple arches.
  99. // When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
  100. // When this becomes table-generated, we'd probably need two tables.
  101. struct CpuNames {
  102. StringRef Name;
  103. ArchKind ArchID;
  104. bool Default; // is $Name the default CPU for $ArchID ?
  105. uint64_t DefaultExtensions;
  106. };
  107. const CpuNames CPUNames[] = {
  108. #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
  109. {NAME, ARM::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT},
  110. #include "ARMTargetParser.def"
  111. };
  112. // FPU names.
  113. enum FPUKind {
  114. #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) KIND,
  115. #include "ARMTargetParser.def"
  116. FK_LAST
  117. };
  118. // FPU Version
  119. enum class FPUVersion {
  120. NONE,
  121. VFPV2,
  122. VFPV3,
  123. VFPV3_FP16,
  124. VFPV4,
  125. VFPV5,
  126. VFPV5_FULLFP16,
  127. };
  128. // An FPU name restricts the FPU in one of three ways:
  129. enum class FPURestriction {
  130. None = 0, ///< No restriction
  131. D16, ///< Only 16 D registers
  132. SP_D16 ///< Only single-precision instructions, with 16 D registers
  133. };
  134. // An FPU name implies one of three levels of Neon support:
  135. enum class NeonSupportLevel {
  136. None = 0, ///< No Neon
  137. Neon, ///< Neon
  138. Crypto ///< Neon with Crypto
  139. };
  140. // v6/v7/v8 Profile
  141. enum class ProfileKind { INVALID = 0, A, R, M };
  142. // List of canonical FPU names (use getFPUSynonym) and which architectural
  143. // features they correspond to (use getFPUFeatures).
  144. // The entries must appear in the order listed in ARM::FPUKind for correct
  145. // indexing
  146. struct FPUName {
  147. StringRef Name;
  148. FPUKind ID;
  149. FPUVersion FPUVer;
  150. NeonSupportLevel NeonSupport;
  151. FPURestriction Restriction;
  152. };
  153. static const FPUName FPUNames[] = {
  154. #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \
  155. {NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION},
  156. #include "llvm/TargetParser/ARMTargetParser.def"
  157. };
  158. // List of canonical arch names (use getArchSynonym).
  159. // This table also provides the build attribute fields for CPU arch
  160. // and Arch ID, according to the Addenda to the ARM ABI, chapters
  161. // 2.4 and 2.3.5.2 respectively.
  162. // FIXME: SubArch values were simplified to fit into the expectations
  163. // of the triples and are not conforming with their official names.
  164. // Check to see if the expectation should be changed.
  165. struct ArchNames {
  166. StringRef Name;
  167. StringRef CPUAttr; // CPU class in build attributes.
  168. StringRef ArchFeature;
  169. unsigned DefaultFPU;
  170. uint64_t ArchBaseExtensions;
  171. ArchKind ID;
  172. ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
  173. // Return ArchFeature without the leading "+".
  174. StringRef getSubArch() const { return ArchFeature.substr(1); }
  175. };
  176. static const ArchNames ARMArchNames[] = {
  177. #define ARM_ARCH(NAME, ID, CPU_ATTR, ARCH_FEATURE, ARCH_ATTR, ARCH_FPU, \
  178. ARCH_BASE_EXT) \
  179. {NAME, CPU_ATTR, ARCH_FEATURE, ARCH_FPU, \
  180. ARCH_BASE_EXT, ArchKind::ID, ARCH_ATTR},
  181. #include "llvm/TargetParser/ARMTargetParser.def"
  182. };
  183. inline ArchKind &operator--(ArchKind &Kind) {
  184. assert((Kind >= ArchKind::ARMV8A && Kind <= ArchKind::ARMV9_3A) &&
  185. "We only expect operator-- to be called with ARMV8/V9");
  186. if (Kind == ArchKind::INVALID || Kind == ArchKind::ARMV8A ||
  187. Kind == ArchKind::ARMV8_1A || Kind == ArchKind::ARMV9A ||
  188. Kind == ArchKind::ARMV8R)
  189. Kind = ArchKind::INVALID;
  190. else {
  191. unsigned KindAsInteger = static_cast<unsigned>(Kind);
  192. Kind = static_cast<ArchKind>(--KindAsInteger);
  193. }
  194. return Kind;
  195. }
  196. // Information by ID
  197. StringRef getFPUName(unsigned FPUKind);
  198. FPUVersion getFPUVersion(unsigned FPUKind);
  199. NeonSupportLevel getFPUNeonSupportLevel(unsigned FPUKind);
  200. FPURestriction getFPURestriction(unsigned FPUKind);
  201. bool getFPUFeatures(unsigned FPUKind, std::vector<StringRef> &Features);
  202. bool getHWDivFeatures(uint64_t HWDivKind, std::vector<StringRef> &Features);
  203. bool getExtensionFeatures(uint64_t Extensions,
  204. std::vector<StringRef> &Features);
  205. StringRef getArchName(ArchKind AK);
  206. unsigned getArchAttr(ArchKind AK);
  207. StringRef getCPUAttr(ArchKind AK);
  208. StringRef getSubArch(ArchKind AK);
  209. StringRef getArchExtName(uint64_t ArchExtKind);
  210. StringRef getArchExtFeature(StringRef ArchExt);
  211. bool appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK, StringRef ArchExt,
  212. std::vector<StringRef> &Features,
  213. unsigned &ArgFPUKind);
  214. ArchKind convertV9toV8(ArchKind AK);
  215. // Information by Name
  216. unsigned getDefaultFPU(StringRef CPU, ArchKind AK);
  217. uint64_t getDefaultExtensions(StringRef CPU, ArchKind AK);
  218. StringRef getDefaultCPU(StringRef Arch);
  219. StringRef getCanonicalArchName(StringRef Arch);
  220. StringRef getFPUSynonym(StringRef FPU);
  221. // Parser
  222. uint64_t parseHWDiv(StringRef HWDiv);
  223. unsigned parseFPU(StringRef FPU);
  224. ArchKind parseArch(StringRef Arch);
  225. uint64_t parseArchExt(StringRef ArchExt);
  226. ArchKind parseCPUArch(StringRef CPU);
  227. ProfileKind parseArchProfile(StringRef Arch);
  228. unsigned parseArchVersion(StringRef Arch);
  229. void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values);
  230. StringRef computeDefaultTargetABI(const Triple &TT, StringRef CPU);
  231. /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
  232. ///
  233. /// \param Arch the architecture name (e.g., "armv7s"). If it is an empty
  234. /// string then the triple's arch name is used.
  235. StringRef getARMCPUForArch(const llvm::Triple &Triple, StringRef MArch = {});
  236. } // namespace ARM
  237. } // namespace llvm
  238. #endif
  239. #ifdef __GNUC__
  240. #pragma GCC diagnostic pop
  241. #endif