1 //===-- ARMTargetParser - Parser for ARM target 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 ARM hardware features 10 // such as FPU/CPU/ARCH/extensions and specific support such as HWDIV. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_SUPPORT_ARMTARGETPARSER_H 15 #define LLVM_SUPPORT_ARMTARGETPARSER_H 16 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/Support/ARMBuildAttributes.h" 20 #include <vector> 21 22 namespace llvm { 23 24 class Triple; 25 26 namespace ARM { 27 28 // Arch extension modifiers for CPUs. 29 // Note that this is not the same as the AArch64 list 30 enum ArchExtKind : uint64_t { 31 AEK_INVALID = 0, 32 AEK_NONE = 1, 33 AEK_CRC = 1 << 1, 34 AEK_CRYPTO = 1 << 2, 35 AEK_FP = 1 << 3, 36 AEK_HWDIVTHUMB = 1 << 4, 37 AEK_HWDIVARM = 1 << 5, 38 AEK_MP = 1 << 6, 39 AEK_SIMD = 1 << 7, 40 AEK_SEC = 1 << 8, 41 AEK_VIRT = 1 << 9, 42 AEK_DSP = 1 << 10, 43 AEK_FP16 = 1 << 11, 44 AEK_RAS = 1 << 12, 45 AEK_DOTPROD = 1 << 13, 46 AEK_SHA2 = 1 << 14, 47 AEK_AES = 1 << 15, 48 AEK_FP16FML = 1 << 16, 49 AEK_SB = 1 << 17, 50 AEK_FP_DP = 1 << 18, 51 AEK_LOB = 1 << 19, 52 AEK_BF16 = 1 << 20, 53 AEK_I8MM = 1 << 21, 54 AEK_CDECP0 = 1 << 22, 55 AEK_CDECP1 = 1 << 23, 56 AEK_CDECP2 = 1 << 24, 57 AEK_CDECP3 = 1 << 25, 58 AEK_CDECP4 = 1 << 26, 59 AEK_CDECP5 = 1 << 27, 60 AEK_CDECP6 = 1 << 28, 61 AEK_CDECP7 = 1 << 29, 62 63 // Unsupported extensions. 64 AEK_OS = 1ULL << 59, 65 AEK_IWMMXT = 1ULL << 60, 66 AEK_IWMMXT2 = 1ULL << 61, 67 AEK_MAVERICK = 1ULL << 62, 68 AEK_XSCALE = 1ULL << 63, 69 }; 70 71 // List of Arch Extension names. 72 // FIXME: TableGen this. 73 struct ExtName { 74 const char *NameCStr; 75 size_t NameLength; 76 uint64_t ID; 77 const char *Feature; 78 const char *NegFeature; 79 getNameExtName80 StringRef getName() const { return StringRef(NameCStr, NameLength); } 81 }; 82 83 const ExtName ARCHExtNames[] = { 84 #define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \ 85 {NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE}, 86 #include "ARMTargetParser.def" 87 }; 88 89 // List of HWDiv names (use getHWDivSynonym) and which architectural 90 // features they correspond to (use getHWDivFeatures). 91 // FIXME: TableGen this. 92 const struct { 93 const char *NameCStr; 94 size_t NameLength; 95 uint64_t ID; 96 getName__anone391688d010897 StringRef getName() const { return StringRef(NameCStr, NameLength); } 98 } HWDivNames[] = { 99 #define ARM_HW_DIV_NAME(NAME, ID) {NAME, sizeof(NAME) - 1, ID}, 100 #include "ARMTargetParser.def" 101 }; 102 103 // Arch names. 104 enum class ArchKind { 105 #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) ID, 106 #include "ARMTargetParser.def" 107 }; 108 109 // List of CPU names and their arches. 110 // The same CPU can have multiple arches and can be default on multiple arches. 111 // When finding the Arch for a CPU, first-found prevails. Sort them accordingly. 112 // When this becomes table-generated, we'd probably need two tables. 113 // FIXME: TableGen this. 114 template <typename T> struct CpuNames { 115 const char *NameCStr; 116 size_t NameLength; 117 T ArchID; 118 bool Default; // is $Name the default CPU for $ArchID ? 119 uint64_t DefaultExtensions; 120 getNameCpuNames121 StringRef getName() const { return StringRef(NameCStr, NameLength); } 122 }; 123 124 const CpuNames<ArchKind> CPUNames[] = { 125 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 126 {NAME, sizeof(NAME) - 1, ARM::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT}, 127 #include "ARMTargetParser.def" 128 }; 129 130 // FPU names. 131 enum FPUKind { 132 #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) KIND, 133 #include "ARMTargetParser.def" 134 FK_LAST 135 }; 136 137 // FPU Version 138 enum class FPUVersion { 139 NONE, 140 VFPV2, 141 VFPV3, 142 VFPV3_FP16, 143 VFPV4, 144 VFPV5, 145 VFPV5_FULLFP16, 146 }; 147 148 // An FPU name restricts the FPU in one of three ways: 149 enum class FPURestriction { 150 None = 0, ///< No restriction 151 D16, ///< Only 16 D registers 152 SP_D16 ///< Only single-precision instructions, with 16 D registers 153 }; 154 155 // An FPU name implies one of three levels of Neon support: 156 enum class NeonSupportLevel { 157 None = 0, ///< No Neon 158 Neon, ///< Neon 159 Crypto ///< Neon with Crypto 160 }; 161 162 // ISA kinds. 163 enum class ISAKind { INVALID = 0, ARM, THUMB, AARCH64 }; 164 165 // Endianness 166 // FIXME: BE8 vs. BE32? 167 enum class EndianKind { INVALID = 0, LITTLE, BIG }; 168 169 // v6/v7/v8 Profile 170 enum class ProfileKind { INVALID = 0, A, R, M }; 171 172 // List of canonical FPU names (use getFPUSynonym) and which architectural 173 // features they correspond to (use getFPUFeatures). 174 // FIXME: TableGen this. 175 // The entries must appear in the order listed in ARM::FPUKind for correct 176 // indexing 177 struct FPUName { 178 const char *NameCStr; 179 size_t NameLength; 180 FPUKind ID; 181 FPUVersion FPUVer; 182 NeonSupportLevel NeonSupport; 183 FPURestriction Restriction; 184 getNameFPUName185 StringRef getName() const { return StringRef(NameCStr, NameLength); } 186 }; 187 188 static const FPUName FPUNames[] = { 189 #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \ 190 {NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION}, 191 #include "llvm/Support/ARMTargetParser.def" 192 }; 193 194 // List of canonical arch names (use getArchSynonym). 195 // This table also provides the build attribute fields for CPU arch 196 // and Arch ID, according to the Addenda to the ARM ABI, chapters 197 // 2.4 and 2.3.5.2 respectively. 198 // FIXME: SubArch values were simplified to fit into the expectations 199 // of the triples and are not conforming with their official names. 200 // Check to see if the expectation should be changed. 201 // FIXME: TableGen this. 202 template <typename T> struct ArchNames { 203 const char *NameCStr; 204 size_t NameLength; 205 const char *CPUAttrCStr; 206 size_t CPUAttrLength; 207 const char *SubArchCStr; 208 size_t SubArchLength; 209 unsigned DefaultFPU; 210 uint64_t ArchBaseExtensions; 211 T ID; 212 ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes. 213 getNameArchNames214 StringRef getName() const { return StringRef(NameCStr, NameLength); } 215 216 // CPU class in build attributes. getCPUAttrArchNames217 StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); } 218 219 // Sub-Arch name. getSubArchArchNames220 StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); } 221 }; 222 223 static const ArchNames<ArchKind> ARCHNames[] = { 224 #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, \ 225 ARCH_BASE_EXT) \ 226 {NAME, sizeof(NAME) - 1, \ 227 CPU_ATTR, sizeof(CPU_ATTR) - 1, \ 228 SUB_ARCH, sizeof(SUB_ARCH) - 1, \ 229 ARCH_FPU, ARCH_BASE_EXT, \ 230 ArchKind::ID, ARCH_ATTR}, 231 #include "llvm/Support/ARMTargetParser.def" 232 }; 233 234 // Information by ID 235 StringRef getFPUName(unsigned FPUKind); 236 FPUVersion getFPUVersion(unsigned FPUKind); 237 NeonSupportLevel getFPUNeonSupportLevel(unsigned FPUKind); 238 FPURestriction getFPURestriction(unsigned FPUKind); 239 240 // FIXME: These should be moved to TargetTuple once it exists 241 bool getFPUFeatures(unsigned FPUKind, std::vector<StringRef> &Features); 242 bool getHWDivFeatures(uint64_t HWDivKind, std::vector<StringRef> &Features); 243 bool getExtensionFeatures(uint64_t Extensions, 244 std::vector<StringRef> &Features); 245 246 StringRef getArchName(ArchKind AK); 247 unsigned getArchAttr(ArchKind AK); 248 StringRef getCPUAttr(ArchKind AK); 249 StringRef getSubArch(ArchKind AK); 250 StringRef getArchExtName(uint64_t ArchExtKind); 251 StringRef getArchExtFeature(StringRef ArchExt); 252 bool appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK, StringRef ArchExt, 253 std::vector<StringRef> &Features, 254 unsigned &ArgFPUKind); 255 StringRef getHWDivName(uint64_t HWDivKind); 256 257 // Information by Name 258 unsigned getDefaultFPU(StringRef CPU, ArchKind AK); 259 uint64_t getDefaultExtensions(StringRef CPU, ArchKind AK); 260 StringRef getDefaultCPU(StringRef Arch); 261 StringRef getCanonicalArchName(StringRef Arch); 262 StringRef getFPUSynonym(StringRef FPU); 263 StringRef getArchSynonym(StringRef Arch); 264 265 // Parser 266 uint64_t parseHWDiv(StringRef HWDiv); 267 unsigned parseFPU(StringRef FPU); 268 ArchKind parseArch(StringRef Arch); 269 uint64_t parseArchExt(StringRef ArchExt); 270 ArchKind parseCPUArch(StringRef CPU); 271 ISAKind parseArchISA(StringRef Arch); 272 EndianKind parseArchEndian(StringRef Arch); 273 ProfileKind parseArchProfile(StringRef Arch); 274 unsigned parseArchVersion(StringRef Arch); 275 276 void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values); 277 StringRef computeDefaultTargetABI(const Triple &TT, StringRef CPU); 278 279 } // namespace ARM 280 } // namespace llvm 281 282 #endif 283