1ff0cc061SDimitry Andric //===-- TargetParser - Parser for target features ---------------*- C++ -*-===// 2ff0cc061SDimitry Andric // 3ff0cc061SDimitry Andric // The LLVM Compiler Infrastructure 4ff0cc061SDimitry Andric // 5ff0cc061SDimitry Andric // This file is distributed under the University of Illinois Open Source 6ff0cc061SDimitry Andric // License. See LICENSE.TXT for details. 7ff0cc061SDimitry Andric // 8ff0cc061SDimitry Andric //===----------------------------------------------------------------------===// 9ff0cc061SDimitry Andric // 10ff0cc061SDimitry Andric // This file implements a target parser to recognise hardware features such as 11ff0cc061SDimitry Andric // FPU/CPU/ARCH names as well as specific support such as HDIV, etc. 12ff0cc061SDimitry Andric // 13ff0cc061SDimitry Andric //===----------------------------------------------------------------------===// 14ff0cc061SDimitry Andric 15ff0cc061SDimitry Andric #include "llvm/Support/ARMBuildAttributes.h" 16ff0cc061SDimitry Andric #include "llvm/Support/TargetParser.h" 17ff0cc061SDimitry Andric #include "llvm/ADT/StringExtras.h" 18ff0cc061SDimitry Andric #include "llvm/ADT/StringSwitch.h" 197d523365SDimitry Andric #include "llvm/ADT/Twine.h" 20ff0cc061SDimitry Andric #include <cctype> 21ff0cc061SDimitry Andric 22ff0cc061SDimitry Andric using namespace llvm; 237d523365SDimitry Andric using namespace ARM; 243ca95b02SDimitry Andric using namespace AArch64; 25ff0cc061SDimitry Andric 26ff0cc061SDimitry Andric namespace { 27ff0cc061SDimitry Andric 2897bc6c73SDimitry Andric // List of canonical FPU names (use getFPUSynonym) and which architectural 2997bc6c73SDimitry Andric // features they correspond to (use getFPUFeatures). 30ff0cc061SDimitry Andric // FIXME: TableGen this. 313dac3a9bSDimitry Andric // The entries must appear in the order listed in ARM::FPUKind for correct indexing 327d523365SDimitry Andric static const struct { 337d523365SDimitry Andric const char *NameCStr; 347d523365SDimitry Andric size_t NameLength; 35ff0cc061SDimitry Andric ARM::FPUKind ID; 363dac3a9bSDimitry Andric ARM::FPUVersion FPUVersion; 3797bc6c73SDimitry Andric ARM::NeonSupportLevel NeonSupport; 3897bc6c73SDimitry Andric ARM::FPURestriction Restriction; 397d523365SDimitry Andric 407d523365SDimitry Andric StringRef getName() const { return StringRef(NameCStr, NameLength); } 41ff0cc061SDimitry Andric } FPUNames[] = { 427d523365SDimitry Andric #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \ 437d523365SDimitry Andric { NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION }, 447d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def" 45ff0cc061SDimitry Andric }; 4697bc6c73SDimitry Andric 4797bc6c73SDimitry Andric // List of canonical arch names (use getArchSynonym). 4897bc6c73SDimitry Andric // This table also provides the build attribute fields for CPU arch 4997bc6c73SDimitry Andric // and Arch ID, according to the Addenda to the ARM ABI, chapters 5097bc6c73SDimitry Andric // 2.4 and 2.3.5.2 respectively. 5197bc6c73SDimitry Andric // FIXME: SubArch values were simplified to fit into the expectations 5297bc6c73SDimitry Andric // of the triples and are not conforming with their official names. 5397bc6c73SDimitry Andric // Check to see if the expectation should be changed. 54ff0cc061SDimitry Andric // FIXME: TableGen this. 55d88c1a5aSDimitry Andric template <typename T> struct ArchNames { 567d523365SDimitry Andric const char *NameCStr; 577d523365SDimitry Andric size_t NameLength; 587d523365SDimitry Andric const char *CPUAttrCStr; 597d523365SDimitry Andric size_t CPUAttrLength; 607d523365SDimitry Andric const char *SubArchCStr; 617d523365SDimitry Andric size_t SubArchLength; 627d523365SDimitry Andric unsigned DefaultFPU; 637d523365SDimitry Andric unsigned ArchBaseExtensions; 64d88c1a5aSDimitry Andric T ID; 6597bc6c73SDimitry Andric ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes. 667d523365SDimitry Andric 677d523365SDimitry Andric StringRef getName() const { return StringRef(NameCStr, NameLength); } 687d523365SDimitry Andric 697d523365SDimitry Andric // CPU class in build attributes. 707d523365SDimitry Andric StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); } 717d523365SDimitry Andric 727d523365SDimitry Andric // Sub-Arch name. 737d523365SDimitry Andric StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); } 74d88c1a5aSDimitry Andric }; 75d88c1a5aSDimitry Andric ArchNames<ARM::ArchKind> ARCHNames[] = { 767d523365SDimitry Andric #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \ 777d523365SDimitry Andric {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \ 787d523365SDimitry Andric sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ID, ARCH_ATTR}, 797d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def" 80d88c1a5aSDimitry Andric }; 81d88c1a5aSDimitry Andric 82d88c1a5aSDimitry Andric ArchNames<AArch64::ArchKind> AArch64ARCHNames[] = { 833ca95b02SDimitry Andric #define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \ 843ca95b02SDimitry Andric {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \ 85d88c1a5aSDimitry Andric sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, AArch64::ArchKind::ID, ARCH_ATTR}, 863ca95b02SDimitry Andric #include "llvm/Support/AArch64TargetParser.def" 87ff0cc061SDimitry Andric }; 887d523365SDimitry Andric 89d88c1a5aSDimitry Andric 9097bc6c73SDimitry Andric // List of Arch Extension names. 91ff0cc061SDimitry Andric // FIXME: TableGen this. 927d523365SDimitry Andric static const struct { 937d523365SDimitry Andric const char *NameCStr; 947d523365SDimitry Andric size_t NameLength; 957d523365SDimitry Andric unsigned ID; 967d523365SDimitry Andric const char *Feature; 977d523365SDimitry Andric const char *NegFeature; 987d523365SDimitry Andric 997d523365SDimitry Andric StringRef getName() const { return StringRef(NameCStr, NameLength); } 100ff0cc061SDimitry Andric } ARCHExtNames[] = { 1017d523365SDimitry Andric #define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \ 1027d523365SDimitry Andric { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE }, 1037d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def" 1043ca95b02SDimitry Andric },AArch64ARCHExtNames[] = { 1053ca95b02SDimitry Andric #define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \ 1063ca95b02SDimitry Andric { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE }, 1073ca95b02SDimitry Andric #include "llvm/Support/AArch64TargetParser.def" 108ff0cc061SDimitry Andric }; 1097d523365SDimitry Andric 1107d523365SDimitry Andric // List of HWDiv names (use getHWDivSynonym) and which architectural 1117d523365SDimitry Andric // features they correspond to (use getHWDivFeatures). 1127d523365SDimitry Andric // FIXME: TableGen this. 1137d523365SDimitry Andric static const struct { 1147d523365SDimitry Andric const char *NameCStr; 1157d523365SDimitry Andric size_t NameLength; 1167d523365SDimitry Andric unsigned ID; 1177d523365SDimitry Andric 1187d523365SDimitry Andric StringRef getName() const { return StringRef(NameCStr, NameLength); } 1197d523365SDimitry Andric } HWDivNames[] = { 1207d523365SDimitry Andric #define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID }, 1217d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def" 1227d523365SDimitry Andric }; 1237d523365SDimitry Andric 124ff0cc061SDimitry Andric // List of CPU names and their arches. 125ff0cc061SDimitry Andric // The same CPU can have multiple arches and can be default on multiple arches. 126ff0cc061SDimitry Andric // When finding the Arch for a CPU, first-found prevails. Sort them accordingly. 12797bc6c73SDimitry Andric // When this becomes table-generated, we'd probably need two tables. 128ff0cc061SDimitry Andric // FIXME: TableGen this. 129d88c1a5aSDimitry Andric template <typename T> struct CpuNames { 1307d523365SDimitry Andric const char *NameCStr; 1317d523365SDimitry Andric size_t NameLength; 132d88c1a5aSDimitry Andric T ArchID; 1337d523365SDimitry Andric bool Default; // is $Name the default CPU for $ArchID ? 1347d523365SDimitry Andric unsigned DefaultExtensions; 1357d523365SDimitry Andric 1367d523365SDimitry Andric StringRef getName() const { return StringRef(NameCStr, NameLength); } 137d88c1a5aSDimitry Andric }; 138d88c1a5aSDimitry Andric CpuNames<ARM::ArchKind> CPUNames[] = { 1397d523365SDimitry Andric #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 1407d523365SDimitry Andric { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT }, 1417d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def" 142d88c1a5aSDimitry Andric }; 143d88c1a5aSDimitry Andric 144d88c1a5aSDimitry Andric CpuNames<AArch64::ArchKind> AArch64CPUNames[] = { 1453ca95b02SDimitry Andric #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 146d88c1a5aSDimitry Andric { NAME, sizeof(NAME) - 1, AArch64::ArchKind::ID, IS_DEFAULT, DEFAULT_EXT }, 1473ca95b02SDimitry Andric #include "llvm/Support/AArch64TargetParser.def" 148ff0cc061SDimitry Andric }; 149ff0cc061SDimitry Andric 150ff0cc061SDimitry Andric } // namespace 151ff0cc061SDimitry Andric 152ff0cc061SDimitry Andric // ======================================================= // 153ff0cc061SDimitry Andric // Information by ID 154ff0cc061SDimitry Andric // ======================================================= // 155ff0cc061SDimitry Andric 1567d523365SDimitry Andric StringRef llvm::ARM::getFPUName(unsigned FPUKind) { 157ff0cc061SDimitry Andric if (FPUKind >= ARM::FK_LAST) 1587d523365SDimitry Andric return StringRef(); 1597d523365SDimitry Andric return FPUNames[FPUKind].getName(); 160ff0cc061SDimitry Andric } 161ff0cc061SDimitry Andric 1627d523365SDimitry Andric unsigned llvm::ARM::getFPUVersion(unsigned FPUKind) { 16397bc6c73SDimitry Andric if (FPUKind >= ARM::FK_LAST) 16497bc6c73SDimitry Andric return 0; 16597bc6c73SDimitry Andric return FPUNames[FPUKind].FPUVersion; 16697bc6c73SDimitry Andric } 16797bc6c73SDimitry Andric 1687d523365SDimitry Andric unsigned llvm::ARM::getFPUNeonSupportLevel(unsigned FPUKind) { 16997bc6c73SDimitry Andric if (FPUKind >= ARM::FK_LAST) 17097bc6c73SDimitry Andric return 0; 17197bc6c73SDimitry Andric return FPUNames[FPUKind].NeonSupport; 17297bc6c73SDimitry Andric } 17397bc6c73SDimitry Andric 1747d523365SDimitry Andric unsigned llvm::ARM::getFPURestriction(unsigned FPUKind) { 17597bc6c73SDimitry Andric if (FPUKind >= ARM::FK_LAST) 17697bc6c73SDimitry Andric return 0; 17797bc6c73SDimitry Andric return FPUNames[FPUKind].Restriction; 17897bc6c73SDimitry Andric } 17997bc6c73SDimitry Andric 1807d523365SDimitry Andric unsigned llvm::ARM::getDefaultFPU(StringRef CPU, unsigned ArchKind) { 1817d523365SDimitry Andric if (CPU == "generic") 1827d523365SDimitry Andric return ARCHNames[ArchKind].DefaultFPU; 1837d523365SDimitry Andric 1847d523365SDimitry Andric return StringSwitch<unsigned>(CPU) 1857d523365SDimitry Andric #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 1867d523365SDimitry Andric .Case(NAME, DEFAULT_FPU) 1877d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def" 1887d523365SDimitry Andric .Default(ARM::FK_INVALID); 1897d523365SDimitry Andric } 1907d523365SDimitry Andric 1917d523365SDimitry Andric unsigned llvm::ARM::getDefaultExtensions(StringRef CPU, unsigned ArchKind) { 1927d523365SDimitry Andric if (CPU == "generic") 1937d523365SDimitry Andric return ARCHNames[ArchKind].ArchBaseExtensions; 1947d523365SDimitry Andric 1957d523365SDimitry Andric return StringSwitch<unsigned>(CPU) 1967d523365SDimitry Andric #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 1977d523365SDimitry Andric .Case(NAME, ARCHNames[ID].ArchBaseExtensions | DEFAULT_EXT) 1987d523365SDimitry Andric #include "llvm/Support/ARMTargetParser.def" 1997d523365SDimitry Andric .Default(ARM::AEK_INVALID); 2007d523365SDimitry Andric } 2017d523365SDimitry Andric 2027d523365SDimitry Andric bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind, 203d88c1a5aSDimitry Andric std::vector<StringRef> &Features) { 2047d523365SDimitry Andric 2057d523365SDimitry Andric if (HWDivKind == ARM::AEK_INVALID) 2067d523365SDimitry Andric return false; 2077d523365SDimitry Andric 2087d523365SDimitry Andric if (HWDivKind & ARM::AEK_HWDIVARM) 2097d523365SDimitry Andric Features.push_back("+hwdiv-arm"); 2107d523365SDimitry Andric else 2117d523365SDimitry Andric Features.push_back("-hwdiv-arm"); 2127d523365SDimitry Andric 2137d523365SDimitry Andric if (HWDivKind & ARM::AEK_HWDIV) 2147d523365SDimitry Andric Features.push_back("+hwdiv"); 2157d523365SDimitry Andric else 2167d523365SDimitry Andric Features.push_back("-hwdiv"); 2177d523365SDimitry Andric 2187d523365SDimitry Andric return true; 2197d523365SDimitry Andric } 2207d523365SDimitry Andric 2217d523365SDimitry Andric bool llvm::ARM::getExtensionFeatures(unsigned Extensions, 222d88c1a5aSDimitry Andric std::vector<StringRef> &Features) { 2237d523365SDimitry Andric 2247d523365SDimitry Andric if (Extensions == ARM::AEK_INVALID) 2257d523365SDimitry Andric return false; 2267d523365SDimitry Andric 2277d523365SDimitry Andric if (Extensions & ARM::AEK_CRC) 2287d523365SDimitry Andric Features.push_back("+crc"); 2297d523365SDimitry Andric else 2307d523365SDimitry Andric Features.push_back("-crc"); 2317d523365SDimitry Andric 2327d523365SDimitry Andric if (Extensions & ARM::AEK_DSP) 2337d523365SDimitry Andric Features.push_back("+dsp"); 2347d523365SDimitry Andric else 2357d523365SDimitry Andric Features.push_back("-dsp"); 2367d523365SDimitry Andric 2377d523365SDimitry Andric return getHWDivFeatures(Extensions, Features); 2387d523365SDimitry Andric } 2397d523365SDimitry Andric 2407d523365SDimitry Andric bool llvm::ARM::getFPUFeatures(unsigned FPUKind, 241d88c1a5aSDimitry Andric std::vector<StringRef> &Features) { 24297bc6c73SDimitry Andric 24397bc6c73SDimitry Andric if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID) 24497bc6c73SDimitry Andric return false; 24597bc6c73SDimitry Andric 24697bc6c73SDimitry Andric // fp-only-sp and d16 subtarget features are independent of each other, so we 24797bc6c73SDimitry Andric // must enable/disable both. 24897bc6c73SDimitry Andric switch (FPUNames[FPUKind].Restriction) { 24997bc6c73SDimitry Andric case ARM::FR_SP_D16: 25097bc6c73SDimitry Andric Features.push_back("+fp-only-sp"); 25197bc6c73SDimitry Andric Features.push_back("+d16"); 25297bc6c73SDimitry Andric break; 25397bc6c73SDimitry Andric case ARM::FR_D16: 25497bc6c73SDimitry Andric Features.push_back("-fp-only-sp"); 25597bc6c73SDimitry Andric Features.push_back("+d16"); 25697bc6c73SDimitry Andric break; 25797bc6c73SDimitry Andric case ARM::FR_None: 25897bc6c73SDimitry Andric Features.push_back("-fp-only-sp"); 25997bc6c73SDimitry Andric Features.push_back("-d16"); 26097bc6c73SDimitry Andric break; 26197bc6c73SDimitry Andric } 26297bc6c73SDimitry Andric 26397bc6c73SDimitry Andric // FPU version subtarget features are inclusive of lower-numbered ones, so 26497bc6c73SDimitry Andric // enable the one corresponding to this version and disable all that are 2658f0fd8f6SDimitry Andric // higher. We also have to make sure to disable fp16 when vfp4 is disabled, 2668f0fd8f6SDimitry Andric // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16. 26797bc6c73SDimitry Andric switch (FPUNames[FPUKind].FPUVersion) { 2683dac3a9bSDimitry Andric case ARM::FV_VFPV5: 26997bc6c73SDimitry Andric Features.push_back("+fp-armv8"); 27097bc6c73SDimitry Andric break; 2713dac3a9bSDimitry Andric case ARM::FV_VFPV4: 27297bc6c73SDimitry Andric Features.push_back("+vfp4"); 27397bc6c73SDimitry Andric Features.push_back("-fp-armv8"); 27497bc6c73SDimitry Andric break; 2753dac3a9bSDimitry Andric case ARM::FV_VFPV3_FP16: 2763dac3a9bSDimitry Andric Features.push_back("+vfp3"); 2773dac3a9bSDimitry Andric Features.push_back("+fp16"); 2783dac3a9bSDimitry Andric Features.push_back("-vfp4"); 2793dac3a9bSDimitry Andric Features.push_back("-fp-armv8"); 2803dac3a9bSDimitry Andric break; 2813dac3a9bSDimitry Andric case ARM::FV_VFPV3: 28297bc6c73SDimitry Andric Features.push_back("+vfp3"); 2838f0fd8f6SDimitry Andric Features.push_back("-fp16"); 28497bc6c73SDimitry Andric Features.push_back("-vfp4"); 28597bc6c73SDimitry Andric Features.push_back("-fp-armv8"); 28697bc6c73SDimitry Andric break; 2873dac3a9bSDimitry Andric case ARM::FV_VFPV2: 28897bc6c73SDimitry Andric Features.push_back("+vfp2"); 28997bc6c73SDimitry Andric Features.push_back("-vfp3"); 2908f0fd8f6SDimitry Andric Features.push_back("-fp16"); 29197bc6c73SDimitry Andric Features.push_back("-vfp4"); 29297bc6c73SDimitry Andric Features.push_back("-fp-armv8"); 29397bc6c73SDimitry Andric break; 2943dac3a9bSDimitry Andric case ARM::FV_NONE: 29597bc6c73SDimitry Andric Features.push_back("-vfp2"); 29697bc6c73SDimitry Andric Features.push_back("-vfp3"); 2978f0fd8f6SDimitry Andric Features.push_back("-fp16"); 29897bc6c73SDimitry Andric Features.push_back("-vfp4"); 29997bc6c73SDimitry Andric Features.push_back("-fp-armv8"); 30097bc6c73SDimitry Andric break; 30197bc6c73SDimitry Andric } 30297bc6c73SDimitry Andric 30397bc6c73SDimitry Andric // crypto includes neon, so we handle this similarly to FPU version. 30497bc6c73SDimitry Andric switch (FPUNames[FPUKind].NeonSupport) { 30597bc6c73SDimitry Andric case ARM::NS_Crypto: 3067d523365SDimitry Andric Features.push_back("+neon"); 30797bc6c73SDimitry Andric Features.push_back("+crypto"); 30897bc6c73SDimitry Andric break; 30997bc6c73SDimitry Andric case ARM::NS_Neon: 31097bc6c73SDimitry Andric Features.push_back("+neon"); 31197bc6c73SDimitry Andric Features.push_back("-crypto"); 31297bc6c73SDimitry Andric break; 31397bc6c73SDimitry Andric case ARM::NS_None: 31497bc6c73SDimitry Andric Features.push_back("-neon"); 31597bc6c73SDimitry Andric Features.push_back("-crypto"); 31697bc6c73SDimitry Andric break; 31797bc6c73SDimitry Andric } 31897bc6c73SDimitry Andric 31997bc6c73SDimitry Andric return true; 32097bc6c73SDimitry Andric } 32197bc6c73SDimitry Andric 3227d523365SDimitry Andric StringRef llvm::ARM::getArchName(unsigned ArchKind) { 323ff0cc061SDimitry Andric if (ArchKind >= ARM::AK_LAST) 3247d523365SDimitry Andric return StringRef(); 3257d523365SDimitry Andric return ARCHNames[ArchKind].getName(); 326ff0cc061SDimitry Andric } 327ff0cc061SDimitry Andric 3287d523365SDimitry Andric StringRef llvm::ARM::getCPUAttr(unsigned ArchKind) { 3293ca95b02SDimitry Andric if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST) 3307d523365SDimitry Andric return StringRef(); 3317d523365SDimitry Andric return ARCHNames[ArchKind].getCPUAttr(); 332ff0cc061SDimitry Andric } 333ff0cc061SDimitry Andric 3347d523365SDimitry Andric StringRef llvm::ARM::getSubArch(unsigned ArchKind) { 3353ca95b02SDimitry Andric if (ArchKind == ARM::AK_INVALID || ArchKind >= ARM::AK_LAST) 3367d523365SDimitry Andric return StringRef(); 3377d523365SDimitry Andric return ARCHNames[ArchKind].getSubArch(); 33897bc6c73SDimitry Andric } 33997bc6c73SDimitry Andric 3407d523365SDimitry Andric unsigned llvm::ARM::getArchAttr(unsigned ArchKind) { 341ff0cc061SDimitry Andric if (ArchKind >= ARM::AK_LAST) 342ff0cc061SDimitry Andric return ARMBuildAttrs::CPUArch::Pre_v4; 34397bc6c73SDimitry Andric return ARCHNames[ArchKind].ArchAttr; 344ff0cc061SDimitry Andric } 345ff0cc061SDimitry Andric 3467d523365SDimitry Andric StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) { 3477d523365SDimitry Andric for (const auto AE : ARCHExtNames) { 3487d523365SDimitry Andric if (ArchExtKind == AE.ID) 3497d523365SDimitry Andric return AE.getName(); 3507d523365SDimitry Andric } 3517d523365SDimitry Andric return StringRef(); 352ff0cc061SDimitry Andric } 353ff0cc061SDimitry Andric 354d88c1a5aSDimitry Andric StringRef llvm::ARM::getArchExtFeature(StringRef ArchExt) { 3557d523365SDimitry Andric if (ArchExt.startswith("no")) { 3567d523365SDimitry Andric StringRef ArchExtBase(ArchExt.substr(2)); 3577d523365SDimitry Andric for (const auto AE : ARCHExtNames) { 3587d523365SDimitry Andric if (AE.NegFeature && ArchExtBase == AE.getName()) 359d88c1a5aSDimitry Andric return StringRef(AE.NegFeature); 3607d523365SDimitry Andric } 3617d523365SDimitry Andric } 3627d523365SDimitry Andric for (const auto AE : ARCHExtNames) { 3637d523365SDimitry Andric if (AE.Feature && ArchExt == AE.getName()) 364d88c1a5aSDimitry Andric return StringRef(AE.Feature); 3657d523365SDimitry Andric } 3667d523365SDimitry Andric 367d88c1a5aSDimitry Andric return StringRef(); 3687d523365SDimitry Andric } 3697d523365SDimitry Andric 3707d523365SDimitry Andric StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) { 3717d523365SDimitry Andric for (const auto D : HWDivNames) { 3727d523365SDimitry Andric if (HWDivKind == D.ID) 3737d523365SDimitry Andric return D.getName(); 3747d523365SDimitry Andric } 3757d523365SDimitry Andric return StringRef(); 3767d523365SDimitry Andric } 3777d523365SDimitry Andric 3787d523365SDimitry Andric StringRef llvm::ARM::getDefaultCPU(StringRef Arch) { 379ff0cc061SDimitry Andric unsigned AK = parseArch(Arch); 380ff0cc061SDimitry Andric if (AK == ARM::AK_INVALID) 3817d523365SDimitry Andric return StringRef(); 382ff0cc061SDimitry Andric 383ff0cc061SDimitry Andric // Look for multiple AKs to find the default for pair AK+Name. 384ff0cc061SDimitry Andric for (const auto CPU : CPUNames) { 385ff0cc061SDimitry Andric if (CPU.ArchID == AK && CPU.Default) 3867d523365SDimitry Andric return CPU.getName(); 387ff0cc061SDimitry Andric } 3887d523365SDimitry Andric 3897d523365SDimitry Andric // If we can't find a default then target the architecture instead 3907d523365SDimitry Andric return "generic"; 391ff0cc061SDimitry Andric } 392ff0cc061SDimitry Andric 3933ca95b02SDimitry Andric StringRef llvm::AArch64::getFPUName(unsigned FPUKind) { 3943ca95b02SDimitry Andric return ARM::getFPUName(FPUKind); 3953ca95b02SDimitry Andric } 3963ca95b02SDimitry Andric 3973ca95b02SDimitry Andric unsigned llvm::AArch64::getFPUVersion(unsigned FPUKind) { 3983ca95b02SDimitry Andric return ARM::getFPUVersion(FPUKind); 3993ca95b02SDimitry Andric } 4003ca95b02SDimitry Andric 4013ca95b02SDimitry Andric unsigned llvm::AArch64::getFPUNeonSupportLevel(unsigned FPUKind) { 4023ca95b02SDimitry Andric return ARM::getFPUNeonSupportLevel( FPUKind); 4033ca95b02SDimitry Andric } 4043ca95b02SDimitry Andric 4053ca95b02SDimitry Andric unsigned llvm::AArch64::getFPURestriction(unsigned FPUKind) { 4063ca95b02SDimitry Andric return ARM::getFPURestriction(FPUKind); 4073ca95b02SDimitry Andric } 4083ca95b02SDimitry Andric 4093ca95b02SDimitry Andric unsigned llvm::AArch64::getDefaultFPU(StringRef CPU, unsigned ArchKind) { 4103ca95b02SDimitry Andric if (CPU == "generic") 4113ca95b02SDimitry Andric return AArch64ARCHNames[ArchKind].DefaultFPU; 4123ca95b02SDimitry Andric 4133ca95b02SDimitry Andric return StringSwitch<unsigned>(CPU) 4143ca95b02SDimitry Andric #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 4153ca95b02SDimitry Andric .Case(NAME, DEFAULT_FPU) 4163ca95b02SDimitry Andric #include "llvm/Support/AArch64TargetParser.def" 4173ca95b02SDimitry Andric .Default(ARM::FK_INVALID); 4183ca95b02SDimitry Andric } 4193ca95b02SDimitry Andric 4203ca95b02SDimitry Andric unsigned llvm::AArch64::getDefaultExtensions(StringRef CPU, unsigned ArchKind) { 4213ca95b02SDimitry Andric if (CPU == "generic") 4223ca95b02SDimitry Andric return AArch64ARCHNames[ArchKind].ArchBaseExtensions; 4233ca95b02SDimitry Andric 4243ca95b02SDimitry Andric return StringSwitch<unsigned>(CPU) 4253ca95b02SDimitry Andric #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 426d88c1a5aSDimitry Andric .Case(NAME, DEFAULT_EXT) 4273ca95b02SDimitry Andric #include "llvm/Support/AArch64TargetParser.def" 4283ca95b02SDimitry Andric .Default(AArch64::AEK_INVALID); 4293ca95b02SDimitry Andric } 4303ca95b02SDimitry Andric 4313ca95b02SDimitry Andric bool llvm::AArch64::getExtensionFeatures(unsigned Extensions, 432d88c1a5aSDimitry Andric std::vector<StringRef> &Features) { 4333ca95b02SDimitry Andric 4343ca95b02SDimitry Andric if (Extensions == AArch64::AEK_INVALID) 4353ca95b02SDimitry Andric return false; 4363ca95b02SDimitry Andric 4373ca95b02SDimitry Andric if (Extensions & AArch64::AEK_FP) 4383ca95b02SDimitry Andric Features.push_back("+fp-armv8"); 4393ca95b02SDimitry Andric if (Extensions & AArch64::AEK_SIMD) 4403ca95b02SDimitry Andric Features.push_back("+neon"); 4413ca95b02SDimitry Andric if (Extensions & AArch64::AEK_CRC) 4423ca95b02SDimitry Andric Features.push_back("+crc"); 4433ca95b02SDimitry Andric if (Extensions & AArch64::AEK_CRYPTO) 4443ca95b02SDimitry Andric Features.push_back("+crypto"); 4453ca95b02SDimitry Andric if (Extensions & AArch64::AEK_FP16) 4463ca95b02SDimitry Andric Features.push_back("+fullfp16"); 4473ca95b02SDimitry Andric if (Extensions & AArch64::AEK_PROFILE) 4483ca95b02SDimitry Andric Features.push_back("+spe"); 4493ca95b02SDimitry Andric if (Extensions & AArch64::AEK_RAS) 4503ca95b02SDimitry Andric Features.push_back("+ras"); 4513ca95b02SDimitry Andric 4523ca95b02SDimitry Andric return true; 4533ca95b02SDimitry Andric } 4543ca95b02SDimitry Andric 4553ca95b02SDimitry Andric bool llvm::AArch64::getFPUFeatures(unsigned FPUKind, 456d88c1a5aSDimitry Andric std::vector<StringRef> &Features) { 4573ca95b02SDimitry Andric return ARM::getFPUFeatures(FPUKind, Features); 4583ca95b02SDimitry Andric } 4593ca95b02SDimitry Andric 4603ca95b02SDimitry Andric bool llvm::AArch64::getArchFeatures(unsigned ArchKind, 461d88c1a5aSDimitry Andric std::vector<StringRef> &Features) { 462d88c1a5aSDimitry Andric if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_ARMV8_1A)) 4633ca95b02SDimitry Andric Features.push_back("+v8.1a"); 464d88c1a5aSDimitry Andric if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_ARMV8_2A)) 4653ca95b02SDimitry Andric Features.push_back("+v8.2a"); 4663ca95b02SDimitry Andric 467d88c1a5aSDimitry Andric return ArchKind > static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) && 468d88c1a5aSDimitry Andric ArchKind < static_cast<unsigned>(AArch64::ArchKind::AK_LAST); 4693ca95b02SDimitry Andric } 4703ca95b02SDimitry Andric 4713ca95b02SDimitry Andric StringRef llvm::AArch64::getArchName(unsigned ArchKind) { 472d88c1a5aSDimitry Andric if (ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST)) 4733ca95b02SDimitry Andric return StringRef(); 474d88c1a5aSDimitry Andric return AArch64ARCHNames[ArchKind].getName(); 4753ca95b02SDimitry Andric } 4763ca95b02SDimitry Andric 4773ca95b02SDimitry Andric StringRef llvm::AArch64::getCPUAttr(unsigned ArchKind) { 478d88c1a5aSDimitry Andric if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) || 479d88c1a5aSDimitry Andric ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST)) 4803ca95b02SDimitry Andric return StringRef(); 481d88c1a5aSDimitry Andric return AArch64ARCHNames[ArchKind].getCPUAttr(); 4823ca95b02SDimitry Andric } 4833ca95b02SDimitry Andric 4843ca95b02SDimitry Andric StringRef llvm::AArch64::getSubArch(unsigned ArchKind) { 485d88c1a5aSDimitry Andric if (ArchKind == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) || 486d88c1a5aSDimitry Andric ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST)) 4873ca95b02SDimitry Andric return StringRef(); 488d88c1a5aSDimitry Andric return AArch64ARCHNames[ArchKind].getSubArch(); 4893ca95b02SDimitry Andric } 4903ca95b02SDimitry Andric 4913ca95b02SDimitry Andric unsigned llvm::AArch64::getArchAttr(unsigned ArchKind) { 492d88c1a5aSDimitry Andric if (ArchKind >= static_cast<unsigned>(AArch64::ArchKind::AK_LAST)) 4933ca95b02SDimitry Andric return ARMBuildAttrs::CPUArch::v8_A; 494d88c1a5aSDimitry Andric return AArch64ARCHNames[ArchKind].ArchAttr; 4953ca95b02SDimitry Andric } 4963ca95b02SDimitry Andric 497d88c1a5aSDimitry Andric StringRef llvm::AArch64::getArchExtName(unsigned ArchExtKind) { 4983ca95b02SDimitry Andric for (const auto &AE : AArch64ARCHExtNames) 499d88c1a5aSDimitry Andric if (ArchExtKind == AE.ID) 5003ca95b02SDimitry Andric return AE.getName(); 5013ca95b02SDimitry Andric return StringRef(); 5023ca95b02SDimitry Andric } 5033ca95b02SDimitry Andric 504d88c1a5aSDimitry Andric StringRef llvm::AArch64::getArchExtFeature(StringRef ArchExt) { 5053ca95b02SDimitry Andric if (ArchExt.startswith("no")) { 5063ca95b02SDimitry Andric StringRef ArchExtBase(ArchExt.substr(2)); 5073ca95b02SDimitry Andric for (const auto &AE : AArch64ARCHExtNames) { 5083ca95b02SDimitry Andric if (AE.NegFeature && ArchExtBase == AE.getName()) 509d88c1a5aSDimitry Andric return StringRef(AE.NegFeature); 5103ca95b02SDimitry Andric } 5113ca95b02SDimitry Andric } 5123ca95b02SDimitry Andric 5133ca95b02SDimitry Andric for (const auto &AE : AArch64ARCHExtNames) 5143ca95b02SDimitry Andric if (AE.Feature && ArchExt == AE.getName()) 515d88c1a5aSDimitry Andric return StringRef(AE.Feature); 516d88c1a5aSDimitry Andric return StringRef(); 5173ca95b02SDimitry Andric } 5183ca95b02SDimitry Andric 5193ca95b02SDimitry Andric StringRef llvm::AArch64::getDefaultCPU(StringRef Arch) { 5203ca95b02SDimitry Andric unsigned AK = parseArch(Arch); 521d88c1a5aSDimitry Andric if (AK == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID)) 5223ca95b02SDimitry Andric return StringRef(); 5233ca95b02SDimitry Andric 5243ca95b02SDimitry Andric // Look for multiple AKs to find the default for pair AK+Name. 5253ca95b02SDimitry Andric for (const auto &CPU : AArch64CPUNames) 526d88c1a5aSDimitry Andric if (static_cast<unsigned>(CPU.ArchID) == AK && CPU.Default) 5273ca95b02SDimitry Andric return CPU.getName(); 5283ca95b02SDimitry Andric 5293ca95b02SDimitry Andric // If we can't find a default then target the architecture instead 5303ca95b02SDimitry Andric return "generic"; 5313ca95b02SDimitry Andric } 5323ca95b02SDimitry Andric 5333ca95b02SDimitry Andric unsigned llvm::AArch64::checkArchVersion(StringRef Arch) { 5343ca95b02SDimitry Andric if (Arch[0] == 'v' && std::isdigit(Arch[1])) 5353ca95b02SDimitry Andric return (Arch[1] - 48); 5363ca95b02SDimitry Andric return 0; 5373ca95b02SDimitry Andric } 5383ca95b02SDimitry Andric 539ff0cc061SDimitry Andric // ======================================================= // 540ff0cc061SDimitry Andric // Parsers 541ff0cc061SDimitry Andric // ======================================================= // 542ff0cc061SDimitry Andric 5437d523365SDimitry Andric static StringRef getHWDivSynonym(StringRef HWDiv) { 5447d523365SDimitry Andric return StringSwitch<StringRef>(HWDiv) 5457d523365SDimitry Andric .Case("thumb,arm", "arm,thumb") 5467d523365SDimitry Andric .Default(HWDiv); 5477d523365SDimitry Andric } 5487d523365SDimitry Andric 5497d523365SDimitry Andric static StringRef getFPUSynonym(StringRef FPU) { 550ff0cc061SDimitry Andric return StringSwitch<StringRef>(FPU) 551ff0cc061SDimitry Andric .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported 552ff0cc061SDimitry Andric .Case("vfp2", "vfpv2") 553ff0cc061SDimitry Andric .Case("vfp3", "vfpv3") 554ff0cc061SDimitry Andric .Case("vfp4", "vfpv4") 555ff0cc061SDimitry Andric .Case("vfp3-d16", "vfpv3-d16") 556ff0cc061SDimitry Andric .Case("vfp4-d16", "vfpv4-d16") 55797bc6c73SDimitry Andric .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16") 558ff0cc061SDimitry Andric .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16") 55997bc6c73SDimitry Andric .Case("fp5-sp-d16", "fpv5-sp-d16") 560ff0cc061SDimitry Andric .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16") 561ff0cc061SDimitry Andric // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3. 562ff0cc061SDimitry Andric .Case("neon-vfpv3", "neon") 563ff0cc061SDimitry Andric .Default(FPU); 564ff0cc061SDimitry Andric } 565ff0cc061SDimitry Andric 5667d523365SDimitry Andric static StringRef getArchSynonym(StringRef Arch) { 567ff0cc061SDimitry Andric return StringSwitch<StringRef>(Arch) 5687d523365SDimitry Andric .Case("v5", "v5t") 5697d523365SDimitry Andric .Case("v5e", "v5te") 5707d523365SDimitry Andric .Case("v6j", "v6") 5717d523365SDimitry Andric .Case("v6hl", "v6k") 5727d523365SDimitry Andric .Cases("v6m", "v6sm", "v6s-m", "v6-m") 5737d523365SDimitry Andric .Cases("v6z", "v6zk", "v6kz") 5747d523365SDimitry Andric .Cases("v7", "v7a", "v7hl", "v7l", "v7-a") 57597bc6c73SDimitry Andric .Case("v7r", "v7-r") 57697bc6c73SDimitry Andric .Case("v7m", "v7-m") 57797bc6c73SDimitry Andric .Case("v7em", "v7e-m") 57897bc6c73SDimitry Andric .Cases("v8", "v8a", "aarch64", "arm64", "v8-a") 57997bc6c73SDimitry Andric .Case("v8.1a", "v8.1-a") 5807d523365SDimitry Andric .Case("v8.2a", "v8.2-a") 581d88c1a5aSDimitry Andric .Case("v8r", "v8-r") 5823ca95b02SDimitry Andric .Case("v8m.base", "v8-m.base") 5833ca95b02SDimitry Andric .Case("v8m.main", "v8-m.main") 584ff0cc061SDimitry Andric .Default(Arch); 585ff0cc061SDimitry Andric } 586ff0cc061SDimitry Andric 587ff0cc061SDimitry Andric // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but 588ff0cc061SDimitry Andric // (iwmmxt|xscale)(eb)? is also permitted. If the former, return 589ff0cc061SDimitry Andric // "v.+", if the latter, return unmodified string, minus 'eb'. 590ff0cc061SDimitry Andric // If invalid, return empty string. 5917d523365SDimitry Andric StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) { 592ff0cc061SDimitry Andric size_t offset = StringRef::npos; 593ff0cc061SDimitry Andric StringRef A = Arch; 594ff0cc061SDimitry Andric StringRef Error = ""; 595ff0cc061SDimitry Andric 596ff0cc061SDimitry Andric // Begins with "arm" / "thumb", move past it. 597ff0cc061SDimitry Andric if (A.startswith("arm64")) 598ff0cc061SDimitry Andric offset = 5; 599ff0cc061SDimitry Andric else if (A.startswith("arm")) 600ff0cc061SDimitry Andric offset = 3; 601ff0cc061SDimitry Andric else if (A.startswith("thumb")) 602ff0cc061SDimitry Andric offset = 5; 603ff0cc061SDimitry Andric else if (A.startswith("aarch64")) { 604ff0cc061SDimitry Andric offset = 7; 605ff0cc061SDimitry Andric // AArch64 uses "_be", not "eb" suffix. 606ff0cc061SDimitry Andric if (A.find("eb") != StringRef::npos) 607ff0cc061SDimitry Andric return Error; 608ff0cc061SDimitry Andric if (A.substr(offset, 3) == "_be") 609ff0cc061SDimitry Andric offset += 3; 610ff0cc061SDimitry Andric } 611ff0cc061SDimitry Andric 612ff0cc061SDimitry Andric // Ex. "armebv7", move past the "eb". 613ff0cc061SDimitry Andric if (offset != StringRef::npos && A.substr(offset, 2) == "eb") 614ff0cc061SDimitry Andric offset += 2; 615ff0cc061SDimitry Andric // Or, if it ends with eb ("armv7eb"), chop it off. 616ff0cc061SDimitry Andric else if (A.endswith("eb")) 617ff0cc061SDimitry Andric A = A.substr(0, A.size() - 2); 618ff0cc061SDimitry Andric // Trim the head 619ff0cc061SDimitry Andric if (offset != StringRef::npos) 620ff0cc061SDimitry Andric A = A.substr(offset); 621ff0cc061SDimitry Andric 622ff0cc061SDimitry Andric // Empty string means offset reached the end, which means it's valid. 623ff0cc061SDimitry Andric if (A.empty()) 624ff0cc061SDimitry Andric return Arch; 625ff0cc061SDimitry Andric 626ff0cc061SDimitry Andric // Only match non-marketing names 627ff0cc061SDimitry Andric if (offset != StringRef::npos) { 628ff0cc061SDimitry Andric // Must start with 'vN'. 629ff0cc061SDimitry Andric if (A[0] != 'v' || !std::isdigit(A[1])) 630ff0cc061SDimitry Andric return Error; 631ff0cc061SDimitry Andric // Can't have an extra 'eb'. 632ff0cc061SDimitry Andric if (A.find("eb") != StringRef::npos) 633ff0cc061SDimitry Andric return Error; 634ff0cc061SDimitry Andric } 635ff0cc061SDimitry Andric 636ff0cc061SDimitry Andric // Arch will either be a 'v' name (v7a) or a marketing name (xscale). 637ff0cc061SDimitry Andric return A; 638ff0cc061SDimitry Andric } 639ff0cc061SDimitry Andric 6407d523365SDimitry Andric unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) { 6417d523365SDimitry Andric StringRef Syn = getHWDivSynonym(HWDiv); 6427d523365SDimitry Andric for (const auto D : HWDivNames) { 6437d523365SDimitry Andric if (Syn == D.getName()) 6447d523365SDimitry Andric return D.ID; 6457d523365SDimitry Andric } 6467d523365SDimitry Andric return ARM::AEK_INVALID; 6477d523365SDimitry Andric } 6487d523365SDimitry Andric 6497d523365SDimitry Andric unsigned llvm::ARM::parseFPU(StringRef FPU) { 650ff0cc061SDimitry Andric StringRef Syn = getFPUSynonym(FPU); 651ff0cc061SDimitry Andric for (const auto F : FPUNames) { 6527d523365SDimitry Andric if (Syn == F.getName()) 653ff0cc061SDimitry Andric return F.ID; 654ff0cc061SDimitry Andric } 655ff0cc061SDimitry Andric return ARM::FK_INVALID; 656ff0cc061SDimitry Andric } 657ff0cc061SDimitry Andric 658ff0cc061SDimitry Andric // Allows partial match, ex. "v7a" matches "armv7a". 6597d523365SDimitry Andric unsigned llvm::ARM::parseArch(StringRef Arch) { 66097bc6c73SDimitry Andric Arch = getCanonicalArchName(Arch); 661ff0cc061SDimitry Andric StringRef Syn = getArchSynonym(Arch); 662ff0cc061SDimitry Andric for (const auto A : ARCHNames) { 6637d523365SDimitry Andric if (A.getName().endswith(Syn)) 664ff0cc061SDimitry Andric return A.ID; 665ff0cc061SDimitry Andric } 666ff0cc061SDimitry Andric return ARM::AK_INVALID; 667ff0cc061SDimitry Andric } 668ff0cc061SDimitry Andric 6697d523365SDimitry Andric unsigned llvm::ARM::parseArchExt(StringRef ArchExt) { 670ff0cc061SDimitry Andric for (const auto A : ARCHExtNames) { 6717d523365SDimitry Andric if (ArchExt == A.getName()) 672ff0cc061SDimitry Andric return A.ID; 673ff0cc061SDimitry Andric } 674ff0cc061SDimitry Andric return ARM::AEK_INVALID; 675ff0cc061SDimitry Andric } 676ff0cc061SDimitry Andric 6777d523365SDimitry Andric unsigned llvm::ARM::parseCPUArch(StringRef CPU) { 678ff0cc061SDimitry Andric for (const auto C : CPUNames) { 6797d523365SDimitry Andric if (CPU == C.getName()) 680ff0cc061SDimitry Andric return C.ArchID; 681ff0cc061SDimitry Andric } 682ff0cc061SDimitry Andric return ARM::AK_INVALID; 683ff0cc061SDimitry Andric } 684ff0cc061SDimitry Andric 685ff0cc061SDimitry Andric // ARM, Thumb, AArch64 6867d523365SDimitry Andric unsigned llvm::ARM::parseArchISA(StringRef Arch) { 687ff0cc061SDimitry Andric return StringSwitch<unsigned>(Arch) 688ff0cc061SDimitry Andric .StartsWith("aarch64", ARM::IK_AARCH64) 689ff0cc061SDimitry Andric .StartsWith("arm64", ARM::IK_AARCH64) 690ff0cc061SDimitry Andric .StartsWith("thumb", ARM::IK_THUMB) 691ff0cc061SDimitry Andric .StartsWith("arm", ARM::IK_ARM) 692d88c1a5aSDimitry Andric .Default(ARM::IK_INVALID); 693ff0cc061SDimitry Andric } 694ff0cc061SDimitry Andric 695ff0cc061SDimitry Andric // Little/Big endian 6967d523365SDimitry Andric unsigned llvm::ARM::parseArchEndian(StringRef Arch) { 6977d523365SDimitry Andric if (Arch.startswith("armeb") || Arch.startswith("thumbeb") || 698ff0cc061SDimitry Andric Arch.startswith("aarch64_be")) 699ff0cc061SDimitry Andric return ARM::EK_BIG; 700ff0cc061SDimitry Andric 701ff0cc061SDimitry Andric if (Arch.startswith("arm") || Arch.startswith("thumb")) { 702ff0cc061SDimitry Andric if (Arch.endswith("eb")) 703ff0cc061SDimitry Andric return ARM::EK_BIG; 704ff0cc061SDimitry Andric else 705ff0cc061SDimitry Andric return ARM::EK_LITTLE; 706ff0cc061SDimitry Andric } 707ff0cc061SDimitry Andric 708ff0cc061SDimitry Andric if (Arch.startswith("aarch64")) 709ff0cc061SDimitry Andric return ARM::EK_LITTLE; 710ff0cc061SDimitry Andric 711ff0cc061SDimitry Andric return ARM::EK_INVALID; 712ff0cc061SDimitry Andric } 713ff0cc061SDimitry Andric 714ff0cc061SDimitry Andric // Profile A/R/M 7157d523365SDimitry Andric unsigned llvm::ARM::parseArchProfile(StringRef Arch) { 716ff0cc061SDimitry Andric Arch = getCanonicalArchName(Arch); 717ff0cc061SDimitry Andric switch (parseArch(Arch)) { 718ff0cc061SDimitry Andric case ARM::AK_ARMV6M: 719ff0cc061SDimitry Andric case ARM::AK_ARMV7M: 720ff0cc061SDimitry Andric case ARM::AK_ARMV7EM: 7213ca95b02SDimitry Andric case ARM::AK_ARMV8MMainline: 7223ca95b02SDimitry Andric case ARM::AK_ARMV8MBaseline: 723ff0cc061SDimitry Andric return ARM::PK_M; 724ff0cc061SDimitry Andric case ARM::AK_ARMV7R: 725d88c1a5aSDimitry Andric case ARM::AK_ARMV8R: 726ff0cc061SDimitry Andric return ARM::PK_R; 727ff0cc061SDimitry Andric case ARM::AK_ARMV7A: 7287d523365SDimitry Andric case ARM::AK_ARMV7K: 729ff0cc061SDimitry Andric case ARM::AK_ARMV8A: 730ff0cc061SDimitry Andric case ARM::AK_ARMV8_1A: 7317d523365SDimitry Andric case ARM::AK_ARMV8_2A: 732ff0cc061SDimitry Andric return ARM::PK_A; 733ff0cc061SDimitry Andric } 734ff0cc061SDimitry Andric return ARM::PK_INVALID; 735ff0cc061SDimitry Andric } 736ff0cc061SDimitry Andric 737ff0cc061SDimitry Andric // Version number (ex. v7 = 7). 7387d523365SDimitry Andric unsigned llvm::ARM::parseArchVersion(StringRef Arch) { 739ff0cc061SDimitry Andric Arch = getCanonicalArchName(Arch); 740ff0cc061SDimitry Andric switch (parseArch(Arch)) { 741ff0cc061SDimitry Andric case ARM::AK_ARMV2: 742ff0cc061SDimitry Andric case ARM::AK_ARMV2A: 743ff0cc061SDimitry Andric return 2; 744ff0cc061SDimitry Andric case ARM::AK_ARMV3: 745ff0cc061SDimitry Andric case ARM::AK_ARMV3M: 746ff0cc061SDimitry Andric return 3; 747ff0cc061SDimitry Andric case ARM::AK_ARMV4: 748ff0cc061SDimitry Andric case ARM::AK_ARMV4T: 749ff0cc061SDimitry Andric return 4; 750ff0cc061SDimitry Andric case ARM::AK_ARMV5T: 751ff0cc061SDimitry Andric case ARM::AK_ARMV5TE: 752ff0cc061SDimitry Andric case ARM::AK_IWMMXT: 753ff0cc061SDimitry Andric case ARM::AK_IWMMXT2: 754ff0cc061SDimitry Andric case ARM::AK_XSCALE: 755ff0cc061SDimitry Andric case ARM::AK_ARMV5TEJ: 756ff0cc061SDimitry Andric return 5; 757ff0cc061SDimitry Andric case ARM::AK_ARMV6: 758ff0cc061SDimitry Andric case ARM::AK_ARMV6K: 759ff0cc061SDimitry Andric case ARM::AK_ARMV6T2: 7607d523365SDimitry Andric case ARM::AK_ARMV6KZ: 761ff0cc061SDimitry Andric case ARM::AK_ARMV6M: 762ff0cc061SDimitry Andric return 6; 763ff0cc061SDimitry Andric case ARM::AK_ARMV7A: 764ff0cc061SDimitry Andric case ARM::AK_ARMV7R: 765ff0cc061SDimitry Andric case ARM::AK_ARMV7M: 766ff0cc061SDimitry Andric case ARM::AK_ARMV7S: 767ff0cc061SDimitry Andric case ARM::AK_ARMV7EM: 7687d523365SDimitry Andric case ARM::AK_ARMV7K: 769ff0cc061SDimitry Andric return 7; 770ff0cc061SDimitry Andric case ARM::AK_ARMV8A: 771ff0cc061SDimitry Andric case ARM::AK_ARMV8_1A: 7727d523365SDimitry Andric case ARM::AK_ARMV8_2A: 773d88c1a5aSDimitry Andric case ARM::AK_ARMV8R: 7743ca95b02SDimitry Andric case ARM::AK_ARMV8MBaseline: 7753ca95b02SDimitry Andric case ARM::AK_ARMV8MMainline: 776ff0cc061SDimitry Andric return 8; 777ff0cc061SDimitry Andric } 778ff0cc061SDimitry Andric return 0; 779ff0cc061SDimitry Andric } 7803ca95b02SDimitry Andric 7813ca95b02SDimitry Andric StringRef llvm::AArch64::getCanonicalArchName(StringRef Arch) { 7823ca95b02SDimitry Andric return ARM::getCanonicalArchName(Arch); 7833ca95b02SDimitry Andric } 7843ca95b02SDimitry Andric 7853ca95b02SDimitry Andric unsigned llvm::AArch64::parseFPU(StringRef FPU) { 7863ca95b02SDimitry Andric return ARM::parseFPU(FPU); 7873ca95b02SDimitry Andric } 7883ca95b02SDimitry Andric 7893ca95b02SDimitry Andric // Allows partial match, ex. "v8a" matches "armv8a". 7903ca95b02SDimitry Andric unsigned llvm::AArch64::parseArch(StringRef Arch) { 7913ca95b02SDimitry Andric Arch = getCanonicalArchName(Arch); 7923ca95b02SDimitry Andric if (checkArchVersion(Arch) < 8) 793d88c1a5aSDimitry Andric return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID); 7943ca95b02SDimitry Andric 7953ca95b02SDimitry Andric StringRef Syn = getArchSynonym(Arch); 7963ca95b02SDimitry Andric for (const auto A : AArch64ARCHNames) { 7973ca95b02SDimitry Andric if (A.getName().endswith(Syn)) 798d88c1a5aSDimitry Andric return static_cast<unsigned>(A.ID); 7993ca95b02SDimitry Andric } 800d88c1a5aSDimitry Andric return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID); 8013ca95b02SDimitry Andric } 8023ca95b02SDimitry Andric 8033ca95b02SDimitry Andric unsigned llvm::AArch64::parseArchExt(StringRef ArchExt) { 8043ca95b02SDimitry Andric for (const auto A : AArch64ARCHExtNames) { 8053ca95b02SDimitry Andric if (ArchExt == A.getName()) 8063ca95b02SDimitry Andric return A.ID; 8073ca95b02SDimitry Andric } 8083ca95b02SDimitry Andric return AArch64::AEK_INVALID; 8093ca95b02SDimitry Andric } 8103ca95b02SDimitry Andric 8113ca95b02SDimitry Andric unsigned llvm::AArch64::parseCPUArch(StringRef CPU) { 8123ca95b02SDimitry Andric for (const auto C : AArch64CPUNames) { 8133ca95b02SDimitry Andric if (CPU == C.getName()) 814d88c1a5aSDimitry Andric return static_cast<unsigned>(C.ArchID); 8153ca95b02SDimitry Andric } 816d88c1a5aSDimitry Andric return static_cast<unsigned>(AArch64::ArchKind::AK_INVALID); 8173ca95b02SDimitry Andric } 8183ca95b02SDimitry Andric 8193ca95b02SDimitry Andric // ARM, Thumb, AArch64 8203ca95b02SDimitry Andric unsigned llvm::AArch64::parseArchISA(StringRef Arch) { 8213ca95b02SDimitry Andric return ARM::parseArchISA(Arch); 8223ca95b02SDimitry Andric } 8233ca95b02SDimitry Andric 8243ca95b02SDimitry Andric // Little/Big endian 8253ca95b02SDimitry Andric unsigned llvm::AArch64::parseArchEndian(StringRef Arch) { 8263ca95b02SDimitry Andric return ARM::parseArchEndian(Arch); 8273ca95b02SDimitry Andric } 8283ca95b02SDimitry Andric 8293ca95b02SDimitry Andric // Profile A/R/M 8303ca95b02SDimitry Andric unsigned llvm::AArch64::parseArchProfile(StringRef Arch) { 8313ca95b02SDimitry Andric return ARM::parseArchProfile(Arch); 8323ca95b02SDimitry Andric } 8333ca95b02SDimitry Andric 8343ca95b02SDimitry Andric // Version number (ex. v8 = 8). 8353ca95b02SDimitry Andric unsigned llvm::AArch64::parseArchVersion(StringRef Arch) { 8363ca95b02SDimitry Andric return ARM::parseArchVersion(Arch); 8373ca95b02SDimitry Andric } 838