1f5f373fcSRenato Golin //===-- TargetParser - Parser for target features ---------------*- C++ -*-===// 2f5f373fcSRenato Golin // 3f5f373fcSRenato Golin // The LLVM Compiler Infrastructure 4f5f373fcSRenato Golin // 5f5f373fcSRenato Golin // This file is distributed under the University of Illinois Open Source 6f5f373fcSRenato Golin // License. See LICENSE.TXT for details. 7f5f373fcSRenato Golin // 8f5f373fcSRenato Golin //===----------------------------------------------------------------------===// 9f5f373fcSRenato Golin // 10f5f373fcSRenato Golin // This file implements a target parser to recognise hardware features such as 11f5f373fcSRenato Golin // FPU/CPU/ARCH names as well as specific support such as HDIV, etc. 12f5f373fcSRenato Golin // 13f5f373fcSRenato Golin //===----------------------------------------------------------------------===// 14f5f373fcSRenato Golin 15f5f373fcSRenato Golin #include "llvm/Support/ARMBuildAttributes.h" 16f5f373fcSRenato Golin #include "llvm/Support/TargetParser.h" 17f5f373fcSRenato Golin #include "llvm/ADT/StringExtras.h" 18f5f373fcSRenato Golin #include "llvm/ADT/StringSwitch.h" 19ebdd12cbSRenato Golin #include <cctype> 20f5f373fcSRenato Golin 21f5f373fcSRenato Golin using namespace llvm; 22799e880eSChandler Carruth using namespace ARM; 23f5f373fcSRenato Golin 24f5f373fcSRenato Golin namespace { 25f5f373fcSRenato Golin 26d03d2292SJohn Brawn // List of canonical FPU names (use getFPUSynonym) and which architectural 27d03d2292SJohn Brawn // features they correspond to (use getFPUFeatures). 28f5f373fcSRenato Golin // FIXME: TableGen this. 29d5526303SJaved Absar // The entries must appear in the order listed in ARM::FPUKind for correct indexing 30f5f373fcSRenato Golin struct { 31*3309ef6fSChandler Carruth const char *NameCStr; 32*3309ef6fSChandler Carruth size_t NameLength; 33f5f373fcSRenato Golin ARM::FPUKind ID; 34d5526303SJaved Absar ARM::FPUVersion FPUVersion; 35d03d2292SJohn Brawn ARM::NeonSupportLevel NeonSupport; 36d03d2292SJohn Brawn ARM::FPURestriction Restriction; 37*3309ef6fSChandler Carruth 38*3309ef6fSChandler Carruth StringRef getName() const { return StringRef(NameCStr, NameLength); } 39f5f373fcSRenato Golin } FPUNames[] = { 40799e880eSChandler Carruth #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \ 41*3309ef6fSChandler Carruth { NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION }, 42799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def" 43f5f373fcSRenato Golin }; 44d03d2292SJohn Brawn 45f7c0d5f2SRenato Golin // List of canonical arch names (use getArchSynonym). 46f7c0d5f2SRenato Golin // This table also provides the build attribute fields for CPU arch 47f7c0d5f2SRenato Golin // and Arch ID, according to the Addenda to the ARM ABI, chapters 48f7c0d5f2SRenato Golin // 2.4 and 2.3.5.2 respectively. 4942dad647SRenato Golin // FIXME: SubArch values were simplified to fit into the expectations 5042dad647SRenato Golin // of the triples and are not conforming with their official names. 5142dad647SRenato Golin // Check to see if the expectation should be changed. 52f5f373fcSRenato Golin // FIXME: TableGen this. 53f5f373fcSRenato Golin struct { 54*3309ef6fSChandler Carruth const char *NameCStr; 55*3309ef6fSChandler Carruth size_t NameLength; 56f5f373fcSRenato Golin ARM::ArchKind ID; 57*3309ef6fSChandler Carruth const char *CPUAttrCStr; 58*3309ef6fSChandler Carruth size_t CPUAttrLength; 59*3309ef6fSChandler Carruth const char *SubArchCStr; 60*3309ef6fSChandler Carruth size_t SubArchLength; 61f7c0d5f2SRenato Golin ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes. 62*3309ef6fSChandler Carruth 63*3309ef6fSChandler Carruth StringRef getName() const { return StringRef(NameCStr, NameLength); } 64*3309ef6fSChandler Carruth 65*3309ef6fSChandler Carruth // CPU class in build attributes. 66*3309ef6fSChandler Carruth StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); } 67*3309ef6fSChandler Carruth 68*3309ef6fSChandler Carruth // Sub-Arch name. 69*3309ef6fSChandler Carruth StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); } 70f5f373fcSRenato Golin } ARCHNames[] = { 71799e880eSChandler Carruth #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR) \ 72*3309ef6fSChandler Carruth {NAME, sizeof(NAME) - 1, ID, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \ 73*3309ef6fSChandler Carruth sizeof(SUB_ARCH) - 1, ARCH_ATTR}, 74799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def" 75f5f373fcSRenato Golin }; 76*3309ef6fSChandler Carruth 77e1326cadSRenato Golin // List of Arch Extension names. 78f5f373fcSRenato Golin // FIXME: TableGen this. 79f5f373fcSRenato Golin struct { 80*3309ef6fSChandler Carruth const char *NameCStr; 81*3309ef6fSChandler Carruth size_t NameLength; 824ea70755SAlexandros Lamprineas unsigned ID; 83*3309ef6fSChandler Carruth 84*3309ef6fSChandler Carruth StringRef getName() const { return StringRef(NameCStr, NameLength); } 85f5f373fcSRenato Golin } ARCHExtNames[] = { 86*3309ef6fSChandler Carruth #define ARM_ARCH_EXT_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID }, 87799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def" 88f5f373fcSRenato Golin }; 89*3309ef6fSChandler Carruth 904ea70755SAlexandros Lamprineas // List of HWDiv names (use getHWDivSynonym) and which architectural 914ea70755SAlexandros Lamprineas // features they correspond to (use getHWDivFeatures). 924ea70755SAlexandros Lamprineas // FIXME: TableGen this. 934ea70755SAlexandros Lamprineas struct { 94*3309ef6fSChandler Carruth const char *NameCStr; 95*3309ef6fSChandler Carruth size_t NameLength; 964ea70755SAlexandros Lamprineas unsigned ID; 97*3309ef6fSChandler Carruth 98*3309ef6fSChandler Carruth StringRef getName() const { return StringRef(NameCStr, NameLength); } 994ea70755SAlexandros Lamprineas } HWDivNames[] = { 100*3309ef6fSChandler Carruth #define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID }, 101799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def" 1024ea70755SAlexandros Lamprineas }; 103*3309ef6fSChandler Carruth 104e8048f0dSRenato Golin // List of CPU names and their arches. 105e8048f0dSRenato Golin // The same CPU can have multiple arches and can be default on multiple arches. 106e8048f0dSRenato Golin // When finding the Arch for a CPU, first-found prevails. Sort them accordingly. 1077374fcdbSRenato Golin // When this becomes table-generated, we'd probably need two tables. 108e8048f0dSRenato Golin // FIXME: TableGen this. 109e8048f0dSRenato Golin struct { 110*3309ef6fSChandler Carruth const char *NameCStr; 111*3309ef6fSChandler Carruth size_t NameLength; 112e8048f0dSRenato Golin ARM::ArchKind ArchID; 113fcd93d53SAlexandros Lamprineas ARM::FPUKind DefaultFPU; 114fcd93d53SAlexandros Lamprineas bool Default; // is $Name the default CPU for $ArchID ? 115*3309ef6fSChandler Carruth 116*3309ef6fSChandler Carruth StringRef getName() const { return StringRef(NameCStr, NameLength); } 117e8048f0dSRenato Golin } CPUNames[] = { 118799e880eSChandler Carruth #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT) \ 119*3309ef6fSChandler Carruth { NAME, sizeof(NAME) - 1, ID, DEFAULT_FPU, IS_DEFAULT }, 120799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def" 121e8048f0dSRenato Golin }; 122f5f373fcSRenato Golin 123f5f373fcSRenato Golin } // namespace 124f5f373fcSRenato Golin 125f5f373fcSRenato Golin // ======================================================= // 126f5f373fcSRenato Golin // Information by ID 127f5f373fcSRenato Golin // ======================================================= // 128f5f373fcSRenato Golin 129*3309ef6fSChandler Carruth StringRef llvm::ARM::getFPUName(unsigned FPUKind) { 130e8048f0dSRenato Golin if (FPUKind >= ARM::FK_LAST) 131*3309ef6fSChandler Carruth return StringRef(); 132*3309ef6fSChandler Carruth return FPUNames[FPUKind].getName(); 133f5f373fcSRenato Golin } 134f5f373fcSRenato Golin 135bb47b9a3SChandler Carruth unsigned llvm::ARM::getFPUVersion(unsigned FPUKind) { 136d03d2292SJohn Brawn if (FPUKind >= ARM::FK_LAST) 137d03d2292SJohn Brawn return 0; 138d03d2292SJohn Brawn return FPUNames[FPUKind].FPUVersion; 139d03d2292SJohn Brawn } 140d03d2292SJohn Brawn 141bb47b9a3SChandler Carruth unsigned llvm::ARM::getFPUNeonSupportLevel(unsigned FPUKind) { 142d03d2292SJohn Brawn if (FPUKind >= ARM::FK_LAST) 143d03d2292SJohn Brawn return 0; 144d03d2292SJohn Brawn return FPUNames[FPUKind].NeonSupport; 145d03d2292SJohn Brawn } 146d03d2292SJohn Brawn 147bb47b9a3SChandler Carruth unsigned llvm::ARM::getFPURestriction(unsigned FPUKind) { 148d03d2292SJohn Brawn if (FPUKind >= ARM::FK_LAST) 149d03d2292SJohn Brawn return 0; 150d03d2292SJohn Brawn return FPUNames[FPUKind].Restriction; 151d03d2292SJohn Brawn } 152d03d2292SJohn Brawn 153bb47b9a3SChandler Carruth unsigned llvm::ARM::getDefaultFPU(StringRef CPU) { 154fcd93d53SAlexandros Lamprineas for (const auto C : CPUNames) { 155*3309ef6fSChandler Carruth if (CPU == C.getName()) 156fcd93d53SAlexandros Lamprineas return C.DefaultFPU; 157fcd93d53SAlexandros Lamprineas } 158fcd93d53SAlexandros Lamprineas return ARM::FK_INVALID; 159fcd93d53SAlexandros Lamprineas } 160fcd93d53SAlexandros Lamprineas 161bb47b9a3SChandler Carruth bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind, 1624ea70755SAlexandros Lamprineas std::vector<const char *> &Features) { 1634ea70755SAlexandros Lamprineas 1644ea70755SAlexandros Lamprineas if (HWDivKind == ARM::AEK_INVALID) 1654ea70755SAlexandros Lamprineas return false; 1664ea70755SAlexandros Lamprineas 1674ea70755SAlexandros Lamprineas if (HWDivKind & ARM::AEK_HWDIVARM) 1684ea70755SAlexandros Lamprineas Features.push_back("+hwdiv-arm"); 1694ea70755SAlexandros Lamprineas else 1704ea70755SAlexandros Lamprineas Features.push_back("-hwdiv-arm"); 1714ea70755SAlexandros Lamprineas 1724ea70755SAlexandros Lamprineas if (HWDivKind & ARM::AEK_HWDIV) 1734ea70755SAlexandros Lamprineas Features.push_back("+hwdiv"); 1744ea70755SAlexandros Lamprineas else 1754ea70755SAlexandros Lamprineas Features.push_back("-hwdiv"); 1764ea70755SAlexandros Lamprineas 1774ea70755SAlexandros Lamprineas return true; 1784ea70755SAlexandros Lamprineas } 1794ea70755SAlexandros Lamprineas 180bb47b9a3SChandler Carruth bool llvm::ARM::getFPUFeatures(unsigned FPUKind, 181d03d2292SJohn Brawn std::vector<const char *> &Features) { 182d03d2292SJohn Brawn 183d03d2292SJohn Brawn if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID) 184d03d2292SJohn Brawn return false; 185d03d2292SJohn Brawn 186d03d2292SJohn Brawn // fp-only-sp and d16 subtarget features are independent of each other, so we 187d03d2292SJohn Brawn // must enable/disable both. 188d03d2292SJohn Brawn switch (FPUNames[FPUKind].Restriction) { 189d03d2292SJohn Brawn case ARM::FR_SP_D16: 190d03d2292SJohn Brawn Features.push_back("+fp-only-sp"); 191d03d2292SJohn Brawn Features.push_back("+d16"); 192d03d2292SJohn Brawn break; 193d03d2292SJohn Brawn case ARM::FR_D16: 194d03d2292SJohn Brawn Features.push_back("-fp-only-sp"); 195d03d2292SJohn Brawn Features.push_back("+d16"); 196d03d2292SJohn Brawn break; 197d03d2292SJohn Brawn case ARM::FR_None: 198d03d2292SJohn Brawn Features.push_back("-fp-only-sp"); 199d03d2292SJohn Brawn Features.push_back("-d16"); 200d03d2292SJohn Brawn break; 201d03d2292SJohn Brawn } 202d03d2292SJohn Brawn 203d03d2292SJohn Brawn // FPU version subtarget features are inclusive of lower-numbered ones, so 204d03d2292SJohn Brawn // enable the one corresponding to this version and disable all that are 205d9e39d53SJohn Brawn // higher. We also have to make sure to disable fp16 when vfp4 is disabled, 206d9e39d53SJohn Brawn // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16. 207d03d2292SJohn Brawn switch (FPUNames[FPUKind].FPUVersion) { 208d5526303SJaved Absar case ARM::FV_VFPV5: 209d03d2292SJohn Brawn Features.push_back("+fp-armv8"); 210d03d2292SJohn Brawn break; 211d5526303SJaved Absar case ARM::FV_VFPV4: 212d03d2292SJohn Brawn Features.push_back("+vfp4"); 213d03d2292SJohn Brawn Features.push_back("-fp-armv8"); 214d03d2292SJohn Brawn break; 215d5526303SJaved Absar case ARM::FV_VFPV3_FP16: 216d5526303SJaved Absar Features.push_back("+vfp3"); 217d5526303SJaved Absar Features.push_back("+fp16"); 218d5526303SJaved Absar Features.push_back("-vfp4"); 219d5526303SJaved Absar Features.push_back("-fp-armv8"); 220d5526303SJaved Absar break; 221d5526303SJaved Absar case ARM::FV_VFPV3: 222d03d2292SJohn Brawn Features.push_back("+vfp3"); 223d9e39d53SJohn Brawn Features.push_back("-fp16"); 224d03d2292SJohn Brawn Features.push_back("-vfp4"); 225d03d2292SJohn Brawn Features.push_back("-fp-armv8"); 226d03d2292SJohn Brawn break; 227d5526303SJaved Absar case ARM::FV_VFPV2: 228d03d2292SJohn Brawn Features.push_back("+vfp2"); 229d03d2292SJohn Brawn Features.push_back("-vfp3"); 230d9e39d53SJohn Brawn Features.push_back("-fp16"); 231d03d2292SJohn Brawn Features.push_back("-vfp4"); 232d03d2292SJohn Brawn Features.push_back("-fp-armv8"); 233d03d2292SJohn Brawn break; 234d5526303SJaved Absar case ARM::FV_NONE: 235d03d2292SJohn Brawn Features.push_back("-vfp2"); 236d03d2292SJohn Brawn Features.push_back("-vfp3"); 237d9e39d53SJohn Brawn Features.push_back("-fp16"); 238d03d2292SJohn Brawn Features.push_back("-vfp4"); 239d03d2292SJohn Brawn Features.push_back("-fp-armv8"); 240d03d2292SJohn Brawn break; 241d03d2292SJohn Brawn } 242d03d2292SJohn Brawn 243d03d2292SJohn Brawn // crypto includes neon, so we handle this similarly to FPU version. 244d03d2292SJohn Brawn switch (FPUNames[FPUKind].NeonSupport) { 245d03d2292SJohn Brawn case ARM::NS_Crypto: 246d03d2292SJohn Brawn Features.push_back("+crypto"); 247d03d2292SJohn Brawn break; 248d03d2292SJohn Brawn case ARM::NS_Neon: 249d03d2292SJohn Brawn Features.push_back("+neon"); 250d03d2292SJohn Brawn Features.push_back("-crypto"); 251d03d2292SJohn Brawn break; 252d03d2292SJohn Brawn case ARM::NS_None: 253d03d2292SJohn Brawn Features.push_back("-neon"); 254d03d2292SJohn Brawn Features.push_back("-crypto"); 255d03d2292SJohn Brawn break; 256d03d2292SJohn Brawn } 257d03d2292SJohn Brawn 258d03d2292SJohn Brawn return true; 259d03d2292SJohn Brawn } 260d03d2292SJohn Brawn 261*3309ef6fSChandler Carruth StringRef llvm::ARM::getArchName(unsigned ArchKind) { 262e8048f0dSRenato Golin if (ArchKind >= ARM::AK_LAST) 263*3309ef6fSChandler Carruth return StringRef(); 264*3309ef6fSChandler Carruth return ARCHNames[ArchKind].getName(); 265f5f373fcSRenato Golin } 266f5f373fcSRenato Golin 267*3309ef6fSChandler Carruth StringRef llvm::ARM::getCPUAttr(unsigned ArchKind) { 268e8048f0dSRenato Golin if (ArchKind >= ARM::AK_LAST) 269*3309ef6fSChandler Carruth return StringRef(); 270*3309ef6fSChandler Carruth return ARCHNames[ArchKind].getCPUAttr(); 271f5f373fcSRenato Golin } 272f5f373fcSRenato Golin 273*3309ef6fSChandler Carruth StringRef llvm::ARM::getSubArch(unsigned ArchKind) { 27442dad647SRenato Golin if (ArchKind >= ARM::AK_LAST) 275*3309ef6fSChandler Carruth return StringRef(); 276*3309ef6fSChandler Carruth return ARCHNames[ArchKind].getSubArch(); 27742dad647SRenato Golin } 27842dad647SRenato Golin 279bb47b9a3SChandler Carruth unsigned llvm::ARM::getArchAttr(unsigned ArchKind) { 280e8048f0dSRenato Golin if (ArchKind >= ARM::AK_LAST) 281e8048f0dSRenato Golin return ARMBuildAttrs::CPUArch::Pre_v4; 282f7c0d5f2SRenato Golin return ARCHNames[ArchKind].ArchAttr; 283f5f373fcSRenato Golin } 284f5f373fcSRenato Golin 285*3309ef6fSChandler Carruth StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) { 2864ea70755SAlexandros Lamprineas for (const auto AE : ARCHExtNames) { 2874ea70755SAlexandros Lamprineas if (ArchExtKind == AE.ID) 288*3309ef6fSChandler Carruth return AE.getName(); 2894ea70755SAlexandros Lamprineas } 290*3309ef6fSChandler Carruth return StringRef(); 2914ea70755SAlexandros Lamprineas } 2924ea70755SAlexandros Lamprineas 293*3309ef6fSChandler Carruth StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) { 2944ea70755SAlexandros Lamprineas for (const auto D : HWDivNames) { 2954ea70755SAlexandros Lamprineas if (HWDivKind == D.ID) 296*3309ef6fSChandler Carruth return D.getName(); 2974ea70755SAlexandros Lamprineas } 298*3309ef6fSChandler Carruth return StringRef(); 299e8048f0dSRenato Golin } 300e8048f0dSRenato Golin 301*3309ef6fSChandler Carruth StringRef llvm::ARM::getDefaultCPU(StringRef Arch) { 302e8048f0dSRenato Golin unsigned AK = parseArch(Arch); 303e8048f0dSRenato Golin if (AK == ARM::AK_INVALID) 304*3309ef6fSChandler Carruth return StringRef(); 305e8048f0dSRenato Golin 306e8048f0dSRenato Golin // Look for multiple AKs to find the default for pair AK+Name. 307e8048f0dSRenato Golin for (const auto CPU : CPUNames) { 308e8048f0dSRenato Golin if (CPU.ArchID == AK && CPU.Default) 309*3309ef6fSChandler Carruth return CPU.getName(); 310e8048f0dSRenato Golin } 311*3309ef6fSChandler Carruth return StringRef(); 312f5f373fcSRenato Golin } 313f5f373fcSRenato Golin 314f5f373fcSRenato Golin // ======================================================= // 315f5f373fcSRenato Golin // Parsers 316f5f373fcSRenato Golin // ======================================================= // 317f5f373fcSRenato Golin 318bb47b9a3SChandler Carruth static StringRef getHWDivSynonym(StringRef HWDiv) { 3194ea70755SAlexandros Lamprineas return StringSwitch<StringRef>(HWDiv) 3204ea70755SAlexandros Lamprineas .Case("thumb,arm", "arm,thumb") 3214ea70755SAlexandros Lamprineas .Default(HWDiv); 3224ea70755SAlexandros Lamprineas } 3234ea70755SAlexandros Lamprineas 324bb47b9a3SChandler Carruth static StringRef getFPUSynonym(StringRef FPU) { 325f5f373fcSRenato Golin return StringSwitch<StringRef>(FPU) 326f5f373fcSRenato Golin .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported 327f5f373fcSRenato Golin .Case("vfp2", "vfpv2") 328f5f373fcSRenato Golin .Case("vfp3", "vfpv3") 329f5f373fcSRenato Golin .Case("vfp4", "vfpv4") 330f5f373fcSRenato Golin .Case("vfp3-d16", "vfpv3-d16") 331f5f373fcSRenato Golin .Case("vfp4-d16", "vfpv4-d16") 332985c04e8SJohn Brawn .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16") 333f5f373fcSRenato Golin .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16") 334985c04e8SJohn Brawn .Case("fp5-sp-d16", "fpv5-sp-d16") 335f5f373fcSRenato Golin .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16") 336f5f373fcSRenato Golin // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3. 337f5f373fcSRenato Golin .Case("neon-vfpv3", "neon") 338f5f373fcSRenato Golin .Default(FPU); 339f5f373fcSRenato Golin } 340f5f373fcSRenato Golin 341bb47b9a3SChandler Carruth static StringRef getArchSynonym(StringRef Arch) { 342f5f373fcSRenato Golin return StringSwitch<StringRef>(Arch) 34385aebc8cSArtyom Skrobov .Case("v6sm", "v6s-m") 34485aebc8cSArtyom Skrobov .Case("v6m", "v6-m") 34585aebc8cSArtyom Skrobov .Case("v7a", "v7-a") 34685aebc8cSArtyom Skrobov .Case("v7r", "v7-r") 34785aebc8cSArtyom Skrobov .Case("v7m", "v7-m") 34885aebc8cSArtyom Skrobov .Case("v7em", "v7e-m") 349acd1cd66SArtyom Skrobov .Cases("v8", "v8a", "aarch64", "arm64", "v8-a") 35085aebc8cSArtyom Skrobov .Case("v8.1a", "v8.1-a") 351f5f373fcSRenato Golin .Default(Arch); 352f5f373fcSRenato Golin } 353f5f373fcSRenato Golin 354e8048f0dSRenato Golin // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but 355e8048f0dSRenato Golin // (iwmmxt|xscale)(eb)? is also permitted. If the former, return 356ebdd12cbSRenato Golin // "v.+", if the latter, return unmodified string, minus 'eb'. 357ebdd12cbSRenato Golin // If invalid, return empty string. 358bb47b9a3SChandler Carruth StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) { 359e8048f0dSRenato Golin size_t offset = StringRef::npos; 360e8048f0dSRenato Golin StringRef A = Arch; 361b6b9e056SRenato Golin StringRef Error = ""; 362e8048f0dSRenato Golin 363e8048f0dSRenato Golin // Begins with "arm" / "thumb", move past it. 364ebdd12cbSRenato Golin if (A.startswith("arm64")) 365ebdd12cbSRenato Golin offset = 5; 366ebdd12cbSRenato Golin else if (A.startswith("arm")) 367e8048f0dSRenato Golin offset = 3; 368e8048f0dSRenato Golin else if (A.startswith("thumb")) 369e8048f0dSRenato Golin offset = 5; 370b6b9e056SRenato Golin else if (A.startswith("aarch64")) { 371b6b9e056SRenato Golin offset = 7; 372b6b9e056SRenato Golin // AArch64 uses "_be", not "eb" suffix. 373b6b9e056SRenato Golin if (A.find("eb") != StringRef::npos) 374b6b9e056SRenato Golin return Error; 375b6b9e056SRenato Golin if (A.substr(offset, 3) == "_be") 376b6b9e056SRenato Golin offset += 3; 377b6b9e056SRenato Golin } 378b6b9e056SRenato Golin 379e8048f0dSRenato Golin // Ex. "armebv7", move past the "eb". 380e8048f0dSRenato Golin if (offset != StringRef::npos && A.substr(offset, 2) == "eb") 381e8048f0dSRenato Golin offset += 2; 382e8048f0dSRenato Golin // Or, if it ends with eb ("armv7eb"), chop it off. 383e8048f0dSRenato Golin else if (A.endswith("eb")) 384e8048f0dSRenato Golin A = A.substr(0, A.size() - 2); 385ebdd12cbSRenato Golin // Trim the head 386ebdd12cbSRenato Golin if (offset != StringRef::npos) 387e8048f0dSRenato Golin A = A.substr(offset); 388e8048f0dSRenato Golin 389ebdd12cbSRenato Golin // Empty string means offset reached the end, which means it's valid. 390e8048f0dSRenato Golin if (A.empty()) 391e8048f0dSRenato Golin return Arch; 392e8048f0dSRenato Golin 393ebdd12cbSRenato Golin // Only match non-marketing names 394ebdd12cbSRenato Golin if (offset != StringRef::npos) { 395ebdd12cbSRenato Golin // Must start with 'vN'. 396ebdd12cbSRenato Golin if (A[0] != 'v' || !std::isdigit(A[1])) 397b6b9e056SRenato Golin return Error; 398ebdd12cbSRenato Golin // Can't have an extra 'eb'. 399ebdd12cbSRenato Golin if (A.find("eb") != StringRef::npos) 400ebdd12cbSRenato Golin return Error; 401ebdd12cbSRenato Golin } 402e8048f0dSRenato Golin 403ebdd12cbSRenato Golin // Arch will either be a 'v' name (v7a) or a marketing name (xscale). 404e8048f0dSRenato Golin return A; 405e8048f0dSRenato Golin } 406e8048f0dSRenato Golin 407bb47b9a3SChandler Carruth unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) { 4084ea70755SAlexandros Lamprineas StringRef Syn = getHWDivSynonym(HWDiv); 4094ea70755SAlexandros Lamprineas for (const auto D : HWDivNames) { 410*3309ef6fSChandler Carruth if (Syn == D.getName()) 4114ea70755SAlexandros Lamprineas return D.ID; 4124ea70755SAlexandros Lamprineas } 4134ea70755SAlexandros Lamprineas return ARM::AEK_INVALID; 4144ea70755SAlexandros Lamprineas } 4154ea70755SAlexandros Lamprineas 416bb47b9a3SChandler Carruth unsigned llvm::ARM::parseFPU(StringRef FPU) { 417f5f373fcSRenato Golin StringRef Syn = getFPUSynonym(FPU); 418f5f373fcSRenato Golin for (const auto F : FPUNames) { 419*3309ef6fSChandler Carruth if (Syn == F.getName()) 420f5f373fcSRenato Golin return F.ID; 421f5f373fcSRenato Golin } 42235de35d0SRenato Golin return ARM::FK_INVALID; 423f5f373fcSRenato Golin } 424f5f373fcSRenato Golin 425e8048f0dSRenato Golin // Allows partial match, ex. "v7a" matches "armv7a". 426bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArch(StringRef Arch) { 42785aebc8cSArtyom Skrobov Arch = getCanonicalArchName(Arch); 428f5f373fcSRenato Golin StringRef Syn = getArchSynonym(Arch); 429f5f373fcSRenato Golin for (const auto A : ARCHNames) { 430*3309ef6fSChandler Carruth if (A.getName().endswith(Syn)) 431f5f373fcSRenato Golin return A.ID; 432f5f373fcSRenato Golin } 43335de35d0SRenato Golin return ARM::AK_INVALID; 434f5f373fcSRenato Golin } 435f5f373fcSRenato Golin 436bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchExt(StringRef ArchExt) { 437f5f373fcSRenato Golin for (const auto A : ARCHExtNames) { 438*3309ef6fSChandler Carruth if (ArchExt == A.getName()) 439f5f373fcSRenato Golin return A.ID; 440f5f373fcSRenato Golin } 44135de35d0SRenato Golin return ARM::AEK_INVALID; 442f5f373fcSRenato Golin } 443f5f373fcSRenato Golin 444bb47b9a3SChandler Carruth unsigned llvm::ARM::parseCPUArch(StringRef CPU) { 445e8048f0dSRenato Golin for (const auto C : CPUNames) { 446*3309ef6fSChandler Carruth if (CPU == C.getName()) 447e8048f0dSRenato Golin return C.ArchID; 448e8048f0dSRenato Golin } 449e8048f0dSRenato Golin return ARM::AK_INVALID; 450e8048f0dSRenato Golin } 451e8048f0dSRenato Golin 452b6b9e056SRenato Golin // ARM, Thumb, AArch64 453bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchISA(StringRef Arch) { 454b6b9e056SRenato Golin return StringSwitch<unsigned>(Arch) 455b6b9e056SRenato Golin .StartsWith("aarch64", ARM::IK_AARCH64) 456b6b9e056SRenato Golin .StartsWith("arm64", ARM::IK_AARCH64) 457b6b9e056SRenato Golin .StartsWith("thumb", ARM::IK_THUMB) 458b6b9e056SRenato Golin .StartsWith("arm", ARM::IK_ARM) 459b6b9e056SRenato Golin .Default(ARM::EK_INVALID); 460b6b9e056SRenato Golin } 461b6b9e056SRenato Golin 462b6b9e056SRenato Golin // Little/Big endian 463bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchEndian(StringRef Arch) { 4644fc3a986SChandler Carruth if (Arch.startswith("armeb") || Arch.startswith("thumbeb") || 465b6b9e056SRenato Golin Arch.startswith("aarch64_be")) 466b6b9e056SRenato Golin return ARM::EK_BIG; 467b6b9e056SRenato Golin 468b6b9e056SRenato Golin if (Arch.startswith("arm") || Arch.startswith("thumb")) { 469b6b9e056SRenato Golin if (Arch.endswith("eb")) 470b6b9e056SRenato Golin return ARM::EK_BIG; 471b6b9e056SRenato Golin else 472b6b9e056SRenato Golin return ARM::EK_LITTLE; 473b6b9e056SRenato Golin } 474b6b9e056SRenato Golin 475b6b9e056SRenato Golin if (Arch.startswith("aarch64")) 476b6b9e056SRenato Golin return ARM::EK_LITTLE; 477b6b9e056SRenato Golin 478b6b9e056SRenato Golin return ARM::EK_INVALID; 479b6b9e056SRenato Golin } 480b6b9e056SRenato Golin 481fadc2108SRenato Golin // Profile A/R/M 482bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchProfile(StringRef Arch) { 483fadc2108SRenato Golin Arch = getCanonicalArchName(Arch); 484fadc2108SRenato Golin switch (parseArch(Arch)) { 485fadc2108SRenato Golin case ARM::AK_ARMV6M: 486fadc2108SRenato Golin case ARM::AK_ARMV7M: 487fadc2108SRenato Golin case ARM::AK_ARMV6SM: 488fadc2108SRenato Golin case ARM::AK_ARMV7EM: 489fadc2108SRenato Golin return ARM::PK_M; 490fadc2108SRenato Golin case ARM::AK_ARMV7R: 491fadc2108SRenato Golin return ARM::PK_R; 492fadc2108SRenato Golin case ARM::AK_ARMV7: 493fadc2108SRenato Golin case ARM::AK_ARMV7A: 4940e20b8dcSAlexandros Lamprineas case ARM::AK_ARMV7L: 495fadc2108SRenato Golin case ARM::AK_ARMV8A: 496fadc2108SRenato Golin case ARM::AK_ARMV8_1A: 497fadc2108SRenato Golin return ARM::PK_A; 498fadc2108SRenato Golin } 499fadc2108SRenato Golin return ARM::PK_INVALID; 500fadc2108SRenato Golin } 501fadc2108SRenato Golin 502ebdd12cbSRenato Golin // Version number (ex. v7 = 7). 503bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchVersion(StringRef Arch) { 504fadc2108SRenato Golin Arch = getCanonicalArchName(Arch); 505fadc2108SRenato Golin switch (parseArch(Arch)) { 506fadc2108SRenato Golin case ARM::AK_ARMV2: 507fadc2108SRenato Golin case ARM::AK_ARMV2A: 508fadc2108SRenato Golin return 2; 509fadc2108SRenato Golin case ARM::AK_ARMV3: 510fadc2108SRenato Golin case ARM::AK_ARMV3M: 511fadc2108SRenato Golin return 3; 512fadc2108SRenato Golin case ARM::AK_ARMV4: 513fadc2108SRenato Golin case ARM::AK_ARMV4T: 514fadc2108SRenato Golin return 4; 515fadc2108SRenato Golin case ARM::AK_ARMV5: 516fadc2108SRenato Golin case ARM::AK_ARMV5T: 517fadc2108SRenato Golin case ARM::AK_ARMV5TE: 518fadc2108SRenato Golin case ARM::AK_IWMMXT: 519fadc2108SRenato Golin case ARM::AK_IWMMXT2: 520fadc2108SRenato Golin case ARM::AK_XSCALE: 521fadc2108SRenato Golin case ARM::AK_ARMV5E: 522fadc2108SRenato Golin case ARM::AK_ARMV5TEJ: 523fadc2108SRenato Golin return 5; 524fadc2108SRenato Golin case ARM::AK_ARMV6: 525fadc2108SRenato Golin case ARM::AK_ARMV6J: 526fadc2108SRenato Golin case ARM::AK_ARMV6K: 527fadc2108SRenato Golin case ARM::AK_ARMV6T2: 528fadc2108SRenato Golin case ARM::AK_ARMV6Z: 529fadc2108SRenato Golin case ARM::AK_ARMV6ZK: 530fadc2108SRenato Golin case ARM::AK_ARMV6M: 531fadc2108SRenato Golin case ARM::AK_ARMV6SM: 532fadc2108SRenato Golin case ARM::AK_ARMV6HL: 533fadc2108SRenato Golin return 6; 534fadc2108SRenato Golin case ARM::AK_ARMV7: 535fadc2108SRenato Golin case ARM::AK_ARMV7A: 536fadc2108SRenato Golin case ARM::AK_ARMV7R: 537fadc2108SRenato Golin case ARM::AK_ARMV7M: 538fadc2108SRenato Golin case ARM::AK_ARMV7L: 539fadc2108SRenato Golin case ARM::AK_ARMV7HL: 540fadc2108SRenato Golin case ARM::AK_ARMV7S: 541fadc2108SRenato Golin case ARM::AK_ARMV7EM: 542366dd9fdSVedant Kumar case ARM::AK_ARMV7K: 543fadc2108SRenato Golin return 7; 544fadc2108SRenato Golin case ARM::AK_ARMV8A: 545fadc2108SRenato Golin case ARM::AK_ARMV8_1A: 546fadc2108SRenato Golin return 8; 547fadc2108SRenato Golin } 548fadc2108SRenato Golin return 0; 549fadc2108SRenato Golin } 550