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" 19*7b0a7d8dSBradley Smith #include "llvm/ADT/Twine.h" 20ebdd12cbSRenato Golin #include <cctype> 21f5f373fcSRenato Golin 22f5f373fcSRenato Golin using namespace llvm; 23799e880eSChandler Carruth using namespace ARM; 24f5f373fcSRenato Golin 25f5f373fcSRenato Golin namespace { 26f5f373fcSRenato Golin 27d03d2292SJohn Brawn // List of canonical FPU names (use getFPUSynonym) and which architectural 28d03d2292SJohn Brawn // features they correspond to (use getFPUFeatures). 29f5f373fcSRenato Golin // FIXME: TableGen this. 30d5526303SJaved Absar // The entries must appear in the order listed in ARM::FPUKind for correct indexing 31bc09f394SArtyom Skrobov static const struct { 323309ef6fSChandler Carruth const char *NameCStr; 333309ef6fSChandler Carruth size_t NameLength; 34f5f373fcSRenato Golin ARM::FPUKind ID; 35d5526303SJaved Absar ARM::FPUVersion FPUVersion; 36d03d2292SJohn Brawn ARM::NeonSupportLevel NeonSupport; 37d03d2292SJohn Brawn ARM::FPURestriction Restriction; 383309ef6fSChandler Carruth 393309ef6fSChandler Carruth StringRef getName() const { return StringRef(NameCStr, NameLength); } 40f5f373fcSRenato Golin } FPUNames[] = { 41799e880eSChandler Carruth #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \ 423309ef6fSChandler Carruth { NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION }, 43799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def" 44f5f373fcSRenato Golin }; 45d03d2292SJohn Brawn 46f7c0d5f2SRenato Golin // List of canonical arch names (use getArchSynonym). 47f7c0d5f2SRenato Golin // This table also provides the build attribute fields for CPU arch 48f7c0d5f2SRenato Golin // and Arch ID, according to the Addenda to the ARM ABI, chapters 49f7c0d5f2SRenato Golin // 2.4 and 2.3.5.2 respectively. 5042dad647SRenato Golin // FIXME: SubArch values were simplified to fit into the expectations 5142dad647SRenato Golin // of the triples and are not conforming with their official names. 5242dad647SRenato Golin // Check to see if the expectation should be changed. 53f5f373fcSRenato Golin // FIXME: TableGen this. 54bc09f394SArtyom Skrobov static const struct { 553309ef6fSChandler Carruth const char *NameCStr; 563309ef6fSChandler Carruth size_t NameLength; 57f5f373fcSRenato Golin ARM::ArchKind ID; 583309ef6fSChandler Carruth const char *CPUAttrCStr; 593309ef6fSChandler Carruth size_t CPUAttrLength; 603309ef6fSChandler Carruth const char *SubArchCStr; 613309ef6fSChandler Carruth size_t SubArchLength; 62f7c0d5f2SRenato Golin ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes. 634adcb739SBradley Smith unsigned DefaultFPU; 64ea33e5e8SAlexandros Lamprineas unsigned ArchBaseExtensions; 653309ef6fSChandler Carruth 663309ef6fSChandler Carruth StringRef getName() const { return StringRef(NameCStr, NameLength); } 673309ef6fSChandler Carruth 683309ef6fSChandler Carruth // CPU class in build attributes. 693309ef6fSChandler Carruth StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); } 703309ef6fSChandler Carruth 713309ef6fSChandler Carruth // Sub-Arch name. 723309ef6fSChandler Carruth StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); } 73f5f373fcSRenato Golin } ARCHNames[] = { 744adcb739SBradley Smith #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \ 753309ef6fSChandler Carruth {NAME, sizeof(NAME) - 1, ID, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \ 764adcb739SBradley Smith sizeof(SUB_ARCH) - 1, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT}, 77799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def" 78f5f373fcSRenato Golin }; 793309ef6fSChandler Carruth 80e1326cadSRenato Golin // List of Arch Extension names. 81f5f373fcSRenato Golin // FIXME: TableGen this. 82bc09f394SArtyom Skrobov static const struct { 833309ef6fSChandler Carruth const char *NameCStr; 843309ef6fSChandler Carruth size_t NameLength; 854ea70755SAlexandros Lamprineas unsigned ID; 86*7b0a7d8dSBradley Smith const char *Feature; 87*7b0a7d8dSBradley Smith const char *NegFeature; 883309ef6fSChandler Carruth 893309ef6fSChandler Carruth StringRef getName() const { return StringRef(NameCStr, NameLength); } 90*7b0a7d8dSBradley Smith StringRef getNegName() const { return (Twine("no") + getName()).str(); } 91f5f373fcSRenato Golin } ARCHExtNames[] = { 92*7b0a7d8dSBradley Smith #define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \ 93*7b0a7d8dSBradley Smith { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE }, 94799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def" 95f5f373fcSRenato Golin }; 963309ef6fSChandler Carruth 974ea70755SAlexandros Lamprineas // List of HWDiv names (use getHWDivSynonym) and which architectural 984ea70755SAlexandros Lamprineas // features they correspond to (use getHWDivFeatures). 994ea70755SAlexandros Lamprineas // FIXME: TableGen this. 100bc09f394SArtyom Skrobov static const struct { 1013309ef6fSChandler Carruth const char *NameCStr; 1023309ef6fSChandler Carruth size_t NameLength; 1034ea70755SAlexandros Lamprineas unsigned ID; 1043309ef6fSChandler Carruth 1053309ef6fSChandler Carruth StringRef getName() const { return StringRef(NameCStr, NameLength); } 1064ea70755SAlexandros Lamprineas } HWDivNames[] = { 1073309ef6fSChandler Carruth #define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID }, 108799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def" 1094ea70755SAlexandros Lamprineas }; 1103309ef6fSChandler Carruth 111e8048f0dSRenato Golin // List of CPU names and their arches. 112e8048f0dSRenato Golin // The same CPU can have multiple arches and can be default on multiple arches. 113e8048f0dSRenato Golin // When finding the Arch for a CPU, first-found prevails. Sort them accordingly. 1147374fcdbSRenato Golin // When this becomes table-generated, we'd probably need two tables. 115e8048f0dSRenato Golin // FIXME: TableGen this. 116bc09f394SArtyom Skrobov static const struct { 1173309ef6fSChandler Carruth const char *NameCStr; 1183309ef6fSChandler Carruth size_t NameLength; 119e8048f0dSRenato Golin ARM::ArchKind ArchID; 120fcd93d53SAlexandros Lamprineas bool Default; // is $Name the default CPU for $ArchID ? 121ea33e5e8SAlexandros Lamprineas unsigned DefaultExtensions; 1223309ef6fSChandler Carruth 1233309ef6fSChandler Carruth StringRef getName() const { return StringRef(NameCStr, NameLength); } 124e8048f0dSRenato Golin } CPUNames[] = { 125ea33e5e8SAlexandros Lamprineas #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 126ea33e5e8SAlexandros Lamprineas { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT }, 127799e880eSChandler Carruth #include "llvm/Support/ARMTargetParser.def" 128e8048f0dSRenato Golin }; 129f5f373fcSRenato Golin 130f5f373fcSRenato Golin } // namespace 131f5f373fcSRenato Golin 132f5f373fcSRenato Golin // ======================================================= // 133f5f373fcSRenato Golin // Information by ID 134f5f373fcSRenato Golin // ======================================================= // 135f5f373fcSRenato Golin 1363309ef6fSChandler Carruth StringRef llvm::ARM::getFPUName(unsigned FPUKind) { 137e8048f0dSRenato Golin if (FPUKind >= ARM::FK_LAST) 1383309ef6fSChandler Carruth return StringRef(); 1393309ef6fSChandler Carruth return FPUNames[FPUKind].getName(); 140f5f373fcSRenato Golin } 141f5f373fcSRenato Golin 142bb47b9a3SChandler Carruth unsigned llvm::ARM::getFPUVersion(unsigned FPUKind) { 143d03d2292SJohn Brawn if (FPUKind >= ARM::FK_LAST) 144d03d2292SJohn Brawn return 0; 145d03d2292SJohn Brawn return FPUNames[FPUKind].FPUVersion; 146d03d2292SJohn Brawn } 147d03d2292SJohn Brawn 148bb47b9a3SChandler Carruth unsigned llvm::ARM::getFPUNeonSupportLevel(unsigned FPUKind) { 149d03d2292SJohn Brawn if (FPUKind >= ARM::FK_LAST) 150d03d2292SJohn Brawn return 0; 151d03d2292SJohn Brawn return FPUNames[FPUKind].NeonSupport; 152d03d2292SJohn Brawn } 153d03d2292SJohn Brawn 154bb47b9a3SChandler Carruth unsigned llvm::ARM::getFPURestriction(unsigned FPUKind) { 155d03d2292SJohn Brawn if (FPUKind >= ARM::FK_LAST) 156d03d2292SJohn Brawn return 0; 157d03d2292SJohn Brawn return FPUNames[FPUKind].Restriction; 158d03d2292SJohn Brawn } 159d03d2292SJohn Brawn 1604adcb739SBradley Smith unsigned llvm::ARM::getDefaultFPU(StringRef CPU, unsigned ArchKind) { 1614adcb739SBradley Smith if (CPU == "generic") 1624adcb739SBradley Smith return ARCHNames[ArchKind].DefaultFPU; 1634adcb739SBradley Smith 164822d54a2SChandler Carruth return StringSwitch<unsigned>(CPU) 165ea33e5e8SAlexandros Lamprineas #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 166822d54a2SChandler Carruth .Case(NAME, DEFAULT_FPU) 167822d54a2SChandler Carruth #include "llvm/Support/ARMTargetParser.def" 168822d54a2SChandler Carruth .Default(ARM::FK_INVALID); 169fcd93d53SAlexandros Lamprineas } 170fcd93d53SAlexandros Lamprineas 171bc09f394SArtyom Skrobov unsigned llvm::ARM::getDefaultExtensions(StringRef CPU, unsigned ArchKind) { 172bc09f394SArtyom Skrobov if (CPU == "generic") 173bc09f394SArtyom Skrobov return ARCHNames[ArchKind].ArchBaseExtensions; 174bc09f394SArtyom Skrobov 175bc09f394SArtyom Skrobov return StringSwitch<unsigned>(CPU) 176bc09f394SArtyom Skrobov #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 177bc09f394SArtyom Skrobov .Case(NAME, ARCHNames[ID].ArchBaseExtensions | DEFAULT_EXT) 178bc09f394SArtyom Skrobov #include "llvm/Support/ARMTargetParser.def" 179bc09f394SArtyom Skrobov .Default(ARM::AEK_INVALID); 180bc09f394SArtyom Skrobov } 181bc09f394SArtyom Skrobov 182bb47b9a3SChandler Carruth bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind, 1834ea70755SAlexandros Lamprineas std::vector<const char *> &Features) { 1844ea70755SAlexandros Lamprineas 1854ea70755SAlexandros Lamprineas if (HWDivKind == ARM::AEK_INVALID) 1864ea70755SAlexandros Lamprineas return false; 1874ea70755SAlexandros Lamprineas 1884ea70755SAlexandros Lamprineas if (HWDivKind & ARM::AEK_HWDIVARM) 1894ea70755SAlexandros Lamprineas Features.push_back("+hwdiv-arm"); 1904ea70755SAlexandros Lamprineas else 1914ea70755SAlexandros Lamprineas Features.push_back("-hwdiv-arm"); 1924ea70755SAlexandros Lamprineas 1934ea70755SAlexandros Lamprineas if (HWDivKind & ARM::AEK_HWDIV) 1944ea70755SAlexandros Lamprineas Features.push_back("+hwdiv"); 1954ea70755SAlexandros Lamprineas else 1964ea70755SAlexandros Lamprineas Features.push_back("-hwdiv"); 1974ea70755SAlexandros Lamprineas 1984ea70755SAlexandros Lamprineas return true; 1994ea70755SAlexandros Lamprineas } 2004ea70755SAlexandros Lamprineas 201ea33e5e8SAlexandros Lamprineas bool llvm::ARM::getExtensionFeatures(unsigned Extensions, 202ea33e5e8SAlexandros Lamprineas std::vector<const char *> &Features) { 203ea33e5e8SAlexandros Lamprineas 204ea33e5e8SAlexandros Lamprineas if (Extensions == ARM::AEK_INVALID) 205ea33e5e8SAlexandros Lamprineas return false; 206ea33e5e8SAlexandros Lamprineas 207ea33e5e8SAlexandros Lamprineas if (Extensions & ARM::AEK_CRC) 208ea33e5e8SAlexandros Lamprineas Features.push_back("+crc"); 209ea33e5e8SAlexandros Lamprineas else 210ea33e5e8SAlexandros Lamprineas Features.push_back("-crc"); 211ea33e5e8SAlexandros Lamprineas 212cf296444SArtyom Skrobov if (Extensions & ARM::AEK_DSP) 2135a6e3945SArtyom Skrobov Features.push_back("+dsp"); 214cf296444SArtyom Skrobov else 2155a6e3945SArtyom Skrobov Features.push_back("-dsp"); 216cf296444SArtyom Skrobov 217ea33e5e8SAlexandros Lamprineas return getHWDivFeatures(Extensions, Features); 218ea33e5e8SAlexandros Lamprineas } 219ea33e5e8SAlexandros Lamprineas 220bb47b9a3SChandler Carruth bool llvm::ARM::getFPUFeatures(unsigned FPUKind, 221d03d2292SJohn Brawn std::vector<const char *> &Features) { 222d03d2292SJohn Brawn 223d03d2292SJohn Brawn if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID) 224d03d2292SJohn Brawn return false; 225d03d2292SJohn Brawn 226d03d2292SJohn Brawn // fp-only-sp and d16 subtarget features are independent of each other, so we 227d03d2292SJohn Brawn // must enable/disable both. 228d03d2292SJohn Brawn switch (FPUNames[FPUKind].Restriction) { 229d03d2292SJohn Brawn case ARM::FR_SP_D16: 230d03d2292SJohn Brawn Features.push_back("+fp-only-sp"); 231d03d2292SJohn Brawn Features.push_back("+d16"); 232d03d2292SJohn Brawn break; 233d03d2292SJohn Brawn case ARM::FR_D16: 234d03d2292SJohn Brawn Features.push_back("-fp-only-sp"); 235d03d2292SJohn Brawn Features.push_back("+d16"); 236d03d2292SJohn Brawn break; 237d03d2292SJohn Brawn case ARM::FR_None: 238d03d2292SJohn Brawn Features.push_back("-fp-only-sp"); 239d03d2292SJohn Brawn Features.push_back("-d16"); 240d03d2292SJohn Brawn break; 241d03d2292SJohn Brawn } 242d03d2292SJohn Brawn 243d03d2292SJohn Brawn // FPU version subtarget features are inclusive of lower-numbered ones, so 244d03d2292SJohn Brawn // enable the one corresponding to this version and disable all that are 245d9e39d53SJohn Brawn // higher. We also have to make sure to disable fp16 when vfp4 is disabled, 246d9e39d53SJohn Brawn // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16. 247d03d2292SJohn Brawn switch (FPUNames[FPUKind].FPUVersion) { 248d5526303SJaved Absar case ARM::FV_VFPV5: 249d03d2292SJohn Brawn Features.push_back("+fp-armv8"); 250d03d2292SJohn Brawn break; 251d5526303SJaved Absar case ARM::FV_VFPV4: 252d03d2292SJohn Brawn Features.push_back("+vfp4"); 253d03d2292SJohn Brawn Features.push_back("-fp-armv8"); 254d03d2292SJohn Brawn break; 255d5526303SJaved Absar case ARM::FV_VFPV3_FP16: 256d5526303SJaved Absar Features.push_back("+vfp3"); 257d5526303SJaved Absar Features.push_back("+fp16"); 258d5526303SJaved Absar Features.push_back("-vfp4"); 259d5526303SJaved Absar Features.push_back("-fp-armv8"); 260d5526303SJaved Absar break; 261d5526303SJaved Absar case ARM::FV_VFPV3: 262d03d2292SJohn Brawn Features.push_back("+vfp3"); 263d9e39d53SJohn Brawn Features.push_back("-fp16"); 264d03d2292SJohn Brawn Features.push_back("-vfp4"); 265d03d2292SJohn Brawn Features.push_back("-fp-armv8"); 266d03d2292SJohn Brawn break; 267d5526303SJaved Absar case ARM::FV_VFPV2: 268d03d2292SJohn Brawn Features.push_back("+vfp2"); 269d03d2292SJohn Brawn Features.push_back("-vfp3"); 270d9e39d53SJohn Brawn Features.push_back("-fp16"); 271d03d2292SJohn Brawn Features.push_back("-vfp4"); 272d03d2292SJohn Brawn Features.push_back("-fp-armv8"); 273d03d2292SJohn Brawn break; 274d5526303SJaved Absar case ARM::FV_NONE: 275d03d2292SJohn Brawn Features.push_back("-vfp2"); 276d03d2292SJohn Brawn Features.push_back("-vfp3"); 277d9e39d53SJohn Brawn Features.push_back("-fp16"); 278d03d2292SJohn Brawn Features.push_back("-vfp4"); 279d03d2292SJohn Brawn Features.push_back("-fp-armv8"); 280d03d2292SJohn Brawn break; 281d03d2292SJohn Brawn } 282d03d2292SJohn Brawn 283d03d2292SJohn Brawn // crypto includes neon, so we handle this similarly to FPU version. 284d03d2292SJohn Brawn switch (FPUNames[FPUKind].NeonSupport) { 285d03d2292SJohn Brawn case ARM::NS_Crypto: 286ea33e5e8SAlexandros Lamprineas Features.push_back("+neon"); 287d03d2292SJohn Brawn Features.push_back("+crypto"); 288d03d2292SJohn Brawn break; 289d03d2292SJohn Brawn case ARM::NS_Neon: 290d03d2292SJohn Brawn Features.push_back("+neon"); 291d03d2292SJohn Brawn Features.push_back("-crypto"); 292d03d2292SJohn Brawn break; 293d03d2292SJohn Brawn case ARM::NS_None: 294d03d2292SJohn Brawn Features.push_back("-neon"); 295d03d2292SJohn Brawn Features.push_back("-crypto"); 296d03d2292SJohn Brawn break; 297d03d2292SJohn Brawn } 298d03d2292SJohn Brawn 299d03d2292SJohn Brawn return true; 300d03d2292SJohn Brawn } 301d03d2292SJohn Brawn 3023309ef6fSChandler Carruth StringRef llvm::ARM::getArchName(unsigned ArchKind) { 303e8048f0dSRenato Golin if (ArchKind >= ARM::AK_LAST) 3043309ef6fSChandler Carruth return StringRef(); 3053309ef6fSChandler Carruth return ARCHNames[ArchKind].getName(); 306f5f373fcSRenato Golin } 307f5f373fcSRenato Golin 3083309ef6fSChandler Carruth StringRef llvm::ARM::getCPUAttr(unsigned ArchKind) { 309e8048f0dSRenato Golin if (ArchKind >= ARM::AK_LAST) 3103309ef6fSChandler Carruth return StringRef(); 3113309ef6fSChandler Carruth return ARCHNames[ArchKind].getCPUAttr(); 312f5f373fcSRenato Golin } 313f5f373fcSRenato Golin 3143309ef6fSChandler Carruth StringRef llvm::ARM::getSubArch(unsigned ArchKind) { 31542dad647SRenato Golin if (ArchKind >= ARM::AK_LAST) 3163309ef6fSChandler Carruth return StringRef(); 3173309ef6fSChandler Carruth return ARCHNames[ArchKind].getSubArch(); 31842dad647SRenato Golin } 31942dad647SRenato Golin 320bb47b9a3SChandler Carruth unsigned llvm::ARM::getArchAttr(unsigned ArchKind) { 321e8048f0dSRenato Golin if (ArchKind >= ARM::AK_LAST) 322e8048f0dSRenato Golin return ARMBuildAttrs::CPUArch::Pre_v4; 323f7c0d5f2SRenato Golin return ARCHNames[ArchKind].ArchAttr; 324f5f373fcSRenato Golin } 325f5f373fcSRenato Golin 3263309ef6fSChandler Carruth StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) { 3274ea70755SAlexandros Lamprineas for (const auto AE : ARCHExtNames) { 3284ea70755SAlexandros Lamprineas if (ArchExtKind == AE.ID) 3293309ef6fSChandler Carruth return AE.getName(); 3304ea70755SAlexandros Lamprineas } 3313309ef6fSChandler Carruth return StringRef(); 3324ea70755SAlexandros Lamprineas } 3334ea70755SAlexandros Lamprineas 334*7b0a7d8dSBradley Smith const char *llvm::ARM::getArchExtFeature(StringRef ArchExt) { 335*7b0a7d8dSBradley Smith for (const auto AE : ARCHExtNames) { 336*7b0a7d8dSBradley Smith if (AE.Feature && ArchExt == AE.getName()) 337*7b0a7d8dSBradley Smith return AE.Feature; 338*7b0a7d8dSBradley Smith else if (AE.NegFeature && ArchExt == AE.getNegName()) 339*7b0a7d8dSBradley Smith return AE.NegFeature; 340*7b0a7d8dSBradley Smith } 341*7b0a7d8dSBradley Smith 342*7b0a7d8dSBradley Smith return nullptr; 343*7b0a7d8dSBradley Smith } 344*7b0a7d8dSBradley Smith 3453309ef6fSChandler Carruth StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) { 3464ea70755SAlexandros Lamprineas for (const auto D : HWDivNames) { 3474ea70755SAlexandros Lamprineas if (HWDivKind == D.ID) 3483309ef6fSChandler Carruth return D.getName(); 3494ea70755SAlexandros Lamprineas } 3503309ef6fSChandler Carruth return StringRef(); 351e8048f0dSRenato Golin } 352e8048f0dSRenato Golin 3533309ef6fSChandler Carruth StringRef llvm::ARM::getDefaultCPU(StringRef Arch) { 354e8048f0dSRenato Golin unsigned AK = parseArch(Arch); 355e8048f0dSRenato Golin if (AK == ARM::AK_INVALID) 3563309ef6fSChandler Carruth return StringRef(); 357e8048f0dSRenato Golin 358e8048f0dSRenato Golin // Look for multiple AKs to find the default for pair AK+Name. 359e8048f0dSRenato Golin for (const auto CPU : CPUNames) { 360e8048f0dSRenato Golin if (CPU.ArchID == AK && CPU.Default) 3613309ef6fSChandler Carruth return CPU.getName(); 362e8048f0dSRenato Golin } 3634adcb739SBradley Smith 3644adcb739SBradley Smith // If we can't find a default then target the architecture instead 3654adcb739SBradley Smith return "generic"; 366f5f373fcSRenato Golin } 367f5f373fcSRenato Golin 368f5f373fcSRenato Golin // ======================================================= // 369f5f373fcSRenato Golin // Parsers 370f5f373fcSRenato Golin // ======================================================= // 371f5f373fcSRenato Golin 372bb47b9a3SChandler Carruth static StringRef getHWDivSynonym(StringRef HWDiv) { 3734ea70755SAlexandros Lamprineas return StringSwitch<StringRef>(HWDiv) 3744ea70755SAlexandros Lamprineas .Case("thumb,arm", "arm,thumb") 3754ea70755SAlexandros Lamprineas .Default(HWDiv); 3764ea70755SAlexandros Lamprineas } 3774ea70755SAlexandros Lamprineas 378bb47b9a3SChandler Carruth static StringRef getFPUSynonym(StringRef FPU) { 379f5f373fcSRenato Golin return StringSwitch<StringRef>(FPU) 380f5f373fcSRenato Golin .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported 381f5f373fcSRenato Golin .Case("vfp2", "vfpv2") 382f5f373fcSRenato Golin .Case("vfp3", "vfpv3") 383f5f373fcSRenato Golin .Case("vfp4", "vfpv4") 384f5f373fcSRenato Golin .Case("vfp3-d16", "vfpv3-d16") 385f5f373fcSRenato Golin .Case("vfp4-d16", "vfpv4-d16") 386985c04e8SJohn Brawn .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16") 387f5f373fcSRenato Golin .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16") 388985c04e8SJohn Brawn .Case("fp5-sp-d16", "fpv5-sp-d16") 389f5f373fcSRenato Golin .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16") 390f5f373fcSRenato Golin // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3. 391f5f373fcSRenato Golin .Case("neon-vfpv3", "neon") 392f5f373fcSRenato Golin .Default(FPU); 393f5f373fcSRenato Golin } 394f5f373fcSRenato Golin 395bb47b9a3SChandler Carruth static StringRef getArchSynonym(StringRef Arch) { 396f5f373fcSRenato Golin return StringSwitch<StringRef>(Arch) 3972c2f378fSArtyom Skrobov .Case("v5", "v5t") 3982c2f378fSArtyom Skrobov .Case("v5e", "v5te") 3992c2f378fSArtyom Skrobov .Case("v6hl", "v6k") 4002c2f378fSArtyom Skrobov .Cases("v6m", "v6sm", "v6s-m", "v6-m") 401f187a65fSArtyom Skrobov .Cases("v6z", "v6zk", "v6kz") 4022c2f378fSArtyom Skrobov .Cases("v7", "v7a", "v7hl", "v7l", "v7-a") 40385aebc8cSArtyom Skrobov .Case("v7r", "v7-r") 40485aebc8cSArtyom Skrobov .Case("v7m", "v7-m") 40585aebc8cSArtyom Skrobov .Case("v7em", "v7e-m") 406acd1cd66SArtyom Skrobov .Cases("v8", "v8a", "aarch64", "arm64", "v8-a") 40785aebc8cSArtyom Skrobov .Case("v8.1a", "v8.1-a") 408f5f373fcSRenato Golin .Default(Arch); 409f5f373fcSRenato Golin } 410f5f373fcSRenato Golin 411e8048f0dSRenato Golin // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but 412e8048f0dSRenato Golin // (iwmmxt|xscale)(eb)? is also permitted. If the former, return 413ebdd12cbSRenato Golin // "v.+", if the latter, return unmodified string, minus 'eb'. 414ebdd12cbSRenato Golin // If invalid, return empty string. 415bb47b9a3SChandler Carruth StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) { 416e8048f0dSRenato Golin size_t offset = StringRef::npos; 417e8048f0dSRenato Golin StringRef A = Arch; 418b6b9e056SRenato Golin StringRef Error = ""; 419e8048f0dSRenato Golin 420e8048f0dSRenato Golin // Begins with "arm" / "thumb", move past it. 421ebdd12cbSRenato Golin if (A.startswith("arm64")) 422ebdd12cbSRenato Golin offset = 5; 423ebdd12cbSRenato Golin else if (A.startswith("arm")) 424e8048f0dSRenato Golin offset = 3; 425e8048f0dSRenato Golin else if (A.startswith("thumb")) 426e8048f0dSRenato Golin offset = 5; 427b6b9e056SRenato Golin else if (A.startswith("aarch64")) { 428b6b9e056SRenato Golin offset = 7; 429b6b9e056SRenato Golin // AArch64 uses "_be", not "eb" suffix. 430b6b9e056SRenato Golin if (A.find("eb") != StringRef::npos) 431b6b9e056SRenato Golin return Error; 432b6b9e056SRenato Golin if (A.substr(offset, 3) == "_be") 433b6b9e056SRenato Golin offset += 3; 434b6b9e056SRenato Golin } 435b6b9e056SRenato Golin 436e8048f0dSRenato Golin // Ex. "armebv7", move past the "eb". 437e8048f0dSRenato Golin if (offset != StringRef::npos && A.substr(offset, 2) == "eb") 438e8048f0dSRenato Golin offset += 2; 439e8048f0dSRenato Golin // Or, if it ends with eb ("armv7eb"), chop it off. 440e8048f0dSRenato Golin else if (A.endswith("eb")) 441e8048f0dSRenato Golin A = A.substr(0, A.size() - 2); 442ebdd12cbSRenato Golin // Trim the head 443ebdd12cbSRenato Golin if (offset != StringRef::npos) 444e8048f0dSRenato Golin A = A.substr(offset); 445e8048f0dSRenato Golin 446ebdd12cbSRenato Golin // Empty string means offset reached the end, which means it's valid. 447e8048f0dSRenato Golin if (A.empty()) 448e8048f0dSRenato Golin return Arch; 449e8048f0dSRenato Golin 450ebdd12cbSRenato Golin // Only match non-marketing names 451ebdd12cbSRenato Golin if (offset != StringRef::npos) { 452ebdd12cbSRenato Golin // Must start with 'vN'. 453ebdd12cbSRenato Golin if (A[0] != 'v' || !std::isdigit(A[1])) 454b6b9e056SRenato Golin return Error; 455ebdd12cbSRenato Golin // Can't have an extra 'eb'. 456ebdd12cbSRenato Golin if (A.find("eb") != StringRef::npos) 457ebdd12cbSRenato Golin return Error; 458ebdd12cbSRenato Golin } 459e8048f0dSRenato Golin 460ebdd12cbSRenato Golin // Arch will either be a 'v' name (v7a) or a marketing name (xscale). 461e8048f0dSRenato Golin return A; 462e8048f0dSRenato Golin } 463e8048f0dSRenato Golin 464bb47b9a3SChandler Carruth unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) { 4654ea70755SAlexandros Lamprineas StringRef Syn = getHWDivSynonym(HWDiv); 4664ea70755SAlexandros Lamprineas for (const auto D : HWDivNames) { 4673309ef6fSChandler Carruth if (Syn == D.getName()) 4684ea70755SAlexandros Lamprineas return D.ID; 4694ea70755SAlexandros Lamprineas } 4704ea70755SAlexandros Lamprineas return ARM::AEK_INVALID; 4714ea70755SAlexandros Lamprineas } 4724ea70755SAlexandros Lamprineas 473bb47b9a3SChandler Carruth unsigned llvm::ARM::parseFPU(StringRef FPU) { 474f5f373fcSRenato Golin StringRef Syn = getFPUSynonym(FPU); 475f5f373fcSRenato Golin for (const auto F : FPUNames) { 4763309ef6fSChandler Carruth if (Syn == F.getName()) 477f5f373fcSRenato Golin return F.ID; 478f5f373fcSRenato Golin } 47935de35d0SRenato Golin return ARM::FK_INVALID; 480f5f373fcSRenato Golin } 481f5f373fcSRenato Golin 482e8048f0dSRenato Golin // Allows partial match, ex. "v7a" matches "armv7a". 483bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArch(StringRef Arch) { 48485aebc8cSArtyom Skrobov Arch = getCanonicalArchName(Arch); 485f5f373fcSRenato Golin StringRef Syn = getArchSynonym(Arch); 486f5f373fcSRenato Golin for (const auto A : ARCHNames) { 4873309ef6fSChandler Carruth if (A.getName().endswith(Syn)) 488f5f373fcSRenato Golin return A.ID; 489f5f373fcSRenato Golin } 49035de35d0SRenato Golin return ARM::AK_INVALID; 491f5f373fcSRenato Golin } 492f5f373fcSRenato Golin 493bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchExt(StringRef ArchExt) { 494f5f373fcSRenato Golin for (const auto A : ARCHExtNames) { 4953309ef6fSChandler Carruth if (ArchExt == A.getName()) 496f5f373fcSRenato Golin return A.ID; 497f5f373fcSRenato Golin } 49835de35d0SRenato Golin return ARM::AEK_INVALID; 499f5f373fcSRenato Golin } 500f5f373fcSRenato Golin 501bb47b9a3SChandler Carruth unsigned llvm::ARM::parseCPUArch(StringRef CPU) { 502e8048f0dSRenato Golin for (const auto C : CPUNames) { 5033309ef6fSChandler Carruth if (CPU == C.getName()) 504e8048f0dSRenato Golin return C.ArchID; 505e8048f0dSRenato Golin } 506e8048f0dSRenato Golin return ARM::AK_INVALID; 507e8048f0dSRenato Golin } 508e8048f0dSRenato Golin 509b6b9e056SRenato Golin // ARM, Thumb, AArch64 510bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchISA(StringRef Arch) { 511b6b9e056SRenato Golin return StringSwitch<unsigned>(Arch) 512b6b9e056SRenato Golin .StartsWith("aarch64", ARM::IK_AARCH64) 513b6b9e056SRenato Golin .StartsWith("arm64", ARM::IK_AARCH64) 514b6b9e056SRenato Golin .StartsWith("thumb", ARM::IK_THUMB) 515b6b9e056SRenato Golin .StartsWith("arm", ARM::IK_ARM) 516b6b9e056SRenato Golin .Default(ARM::EK_INVALID); 517b6b9e056SRenato Golin } 518b6b9e056SRenato Golin 519b6b9e056SRenato Golin // Little/Big endian 520bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchEndian(StringRef Arch) { 5214fc3a986SChandler Carruth if (Arch.startswith("armeb") || Arch.startswith("thumbeb") || 522b6b9e056SRenato Golin Arch.startswith("aarch64_be")) 523b6b9e056SRenato Golin return ARM::EK_BIG; 524b6b9e056SRenato Golin 525b6b9e056SRenato Golin if (Arch.startswith("arm") || Arch.startswith("thumb")) { 526b6b9e056SRenato Golin if (Arch.endswith("eb")) 527b6b9e056SRenato Golin return ARM::EK_BIG; 528b6b9e056SRenato Golin else 529b6b9e056SRenato Golin return ARM::EK_LITTLE; 530b6b9e056SRenato Golin } 531b6b9e056SRenato Golin 532b6b9e056SRenato Golin if (Arch.startswith("aarch64")) 533b6b9e056SRenato Golin return ARM::EK_LITTLE; 534b6b9e056SRenato Golin 535b6b9e056SRenato Golin return ARM::EK_INVALID; 536b6b9e056SRenato Golin } 537b6b9e056SRenato Golin 538fadc2108SRenato Golin // Profile A/R/M 539bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchProfile(StringRef Arch) { 540fadc2108SRenato Golin Arch = getCanonicalArchName(Arch); 541fadc2108SRenato Golin switch (parseArch(Arch)) { 542fadc2108SRenato Golin case ARM::AK_ARMV6M: 543fadc2108SRenato Golin case ARM::AK_ARMV7M: 544fadc2108SRenato Golin case ARM::AK_ARMV7EM: 545fadc2108SRenato Golin return ARM::PK_M; 546fadc2108SRenato Golin case ARM::AK_ARMV7R: 547fadc2108SRenato Golin return ARM::PK_R; 548fadc2108SRenato Golin case ARM::AK_ARMV7A: 5492d4d1615STim Northover case ARM::AK_ARMV7K: 550fadc2108SRenato Golin case ARM::AK_ARMV8A: 551fadc2108SRenato Golin case ARM::AK_ARMV8_1A: 552fadc2108SRenato Golin return ARM::PK_A; 553fadc2108SRenato Golin } 554fadc2108SRenato Golin return ARM::PK_INVALID; 555fadc2108SRenato Golin } 556fadc2108SRenato Golin 557ebdd12cbSRenato Golin // Version number (ex. v7 = 7). 558bb47b9a3SChandler Carruth unsigned llvm::ARM::parseArchVersion(StringRef Arch) { 559fadc2108SRenato Golin Arch = getCanonicalArchName(Arch); 560fadc2108SRenato Golin switch (parseArch(Arch)) { 561fadc2108SRenato Golin case ARM::AK_ARMV2: 562fadc2108SRenato Golin case ARM::AK_ARMV2A: 563fadc2108SRenato Golin return 2; 564fadc2108SRenato Golin case ARM::AK_ARMV3: 565fadc2108SRenato Golin case ARM::AK_ARMV3M: 566fadc2108SRenato Golin return 3; 567fadc2108SRenato Golin case ARM::AK_ARMV4: 568fadc2108SRenato Golin case ARM::AK_ARMV4T: 569fadc2108SRenato Golin return 4; 570fadc2108SRenato Golin case ARM::AK_ARMV5T: 571fadc2108SRenato Golin case ARM::AK_ARMV5TE: 572fadc2108SRenato Golin case ARM::AK_IWMMXT: 573fadc2108SRenato Golin case ARM::AK_IWMMXT2: 574fadc2108SRenato Golin case ARM::AK_XSCALE: 575fadc2108SRenato Golin case ARM::AK_ARMV5TEJ: 576fadc2108SRenato Golin return 5; 577fadc2108SRenato Golin case ARM::AK_ARMV6: 578fadc2108SRenato Golin case ARM::AK_ARMV6J: 579fadc2108SRenato Golin case ARM::AK_ARMV6K: 580fadc2108SRenato Golin case ARM::AK_ARMV6T2: 581f187a65fSArtyom Skrobov case ARM::AK_ARMV6KZ: 582fadc2108SRenato Golin case ARM::AK_ARMV6M: 583fadc2108SRenato Golin return 6; 584fadc2108SRenato Golin case ARM::AK_ARMV7A: 585fadc2108SRenato Golin case ARM::AK_ARMV7R: 586fadc2108SRenato Golin case ARM::AK_ARMV7M: 587fadc2108SRenato Golin case ARM::AK_ARMV7S: 588fadc2108SRenato Golin case ARM::AK_ARMV7EM: 589366dd9fdSVedant Kumar case ARM::AK_ARMV7K: 590fadc2108SRenato Golin return 7; 591fadc2108SRenato Golin case ARM::AK_ARMV8A: 592fadc2108SRenato Golin case ARM::AK_ARMV8_1A: 593fadc2108SRenato Golin return 8; 594fadc2108SRenato Golin } 595fadc2108SRenato Golin return 0; 596fadc2108SRenato Golin } 597