AArch64TargetParser.cpp revision 343171
1//===-- AArch64TargetParser - Parser for AArch64 features -------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements a target parser to recognise AArch64 hardware features 11// such as FPU/CPU/ARCH and extension names. 12// 13//===----------------------------------------------------------------------===// 14 15#include "llvm/Support/AArch64TargetParser.h" 16#include "llvm/ADT/StringRef.h" 17#include "llvm/ADT/StringSwitch.h" 18#include <cctype> 19 20using namespace llvm; 21 22static unsigned checkArchVersion(llvm::StringRef Arch) { 23 if (Arch.size() >= 2 && Arch[0] == 'v' && std::isdigit(Arch[1])) 24 return (Arch[1] - 48); 25 return 0; 26} 27 28unsigned AArch64::getDefaultFPU(StringRef CPU, AArch64::ArchKind AK) { 29 if (CPU == "generic") 30 return AArch64ARCHNames[static_cast<unsigned>(AK)].DefaultFPU; 31 32 return StringSwitch<unsigned>(CPU) 33#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 34 .Case(NAME, ARM::DEFAULT_FPU) 35#include "../../include/llvm/Support/AArch64TargetParser.def" 36 .Default(ARM::FK_INVALID); 37} 38 39unsigned AArch64::getDefaultExtensions(StringRef CPU, AArch64::ArchKind AK) { 40 if (CPU == "generic") 41 return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions; 42 43 return StringSwitch<unsigned>(CPU) 44#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 45 .Case(NAME, AArch64ARCHNames[static_cast<unsigned>(ArchKind::ID)] \ 46 .ArchBaseExtensions | \ 47 DEFAULT_EXT) 48#include "../../include/llvm/Support/AArch64TargetParser.def" 49 .Default(AArch64::AEK_INVALID); 50} 51 52AArch64::ArchKind AArch64::getCPUArchKind(StringRef CPU) { 53 if (CPU == "generic") 54 return ArchKind::ARMV8A; 55 56 return StringSwitch<AArch64::ArchKind>(CPU) 57#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ 58 .Case(NAME, ArchKind::ID) 59#include "../../include/llvm/Support/AArch64TargetParser.def" 60 .Default(ArchKind::INVALID); 61} 62 63bool AArch64::getExtensionFeatures(unsigned Extensions, 64 std::vector<StringRef> &Features) { 65 if (Extensions == AArch64::AEK_INVALID) 66 return false; 67 68 if (Extensions & AEK_FP) 69 Features.push_back("+fp-armv8"); 70 if (Extensions & AEK_SIMD) 71 Features.push_back("+neon"); 72 if (Extensions & AEK_CRC) 73 Features.push_back("+crc"); 74 if (Extensions & AEK_CRYPTO) 75 Features.push_back("+crypto"); 76 if (Extensions & AEK_DOTPROD) 77 Features.push_back("+dotprod"); 78 if (Extensions & AEK_FP16FML) 79 Features.push_back("+fp16fml"); 80 if (Extensions & AEK_FP16) 81 Features.push_back("+fullfp16"); 82 if (Extensions & AEK_PROFILE) 83 Features.push_back("+spe"); 84 if (Extensions & AEK_RAS) 85 Features.push_back("+ras"); 86 if (Extensions & AEK_LSE) 87 Features.push_back("+lse"); 88 if (Extensions & AEK_RDM) 89 Features.push_back("+rdm"); 90 if (Extensions & AEK_SVE) 91 Features.push_back("+sve"); 92 if (Extensions & AEK_RCPC) 93 Features.push_back("+rcpc"); 94 95 return true; 96} 97 98bool AArch64::getArchFeatures(AArch64::ArchKind AK, 99 std::vector<StringRef> &Features) { 100 if (AK == ArchKind::ARMV8_1A) 101 Features.push_back("+v8.1a"); 102 if (AK == ArchKind::ARMV8_2A) 103 Features.push_back("+v8.2a"); 104 if (AK == ArchKind::ARMV8_3A) 105 Features.push_back("+v8.3a"); 106 if (AK == ArchKind::ARMV8_4A) 107 Features.push_back("+v8.4a"); 108 if (AK == ArchKind::ARMV8_5A) 109 Features.push_back("+v8.5a"); 110 111 return AK != ArchKind::INVALID; 112} 113 114StringRef AArch64::getArchName(AArch64::ArchKind AK) { 115 return AArch64ARCHNames[static_cast<unsigned>(AK)].getName(); 116} 117 118StringRef AArch64::getCPUAttr(AArch64::ArchKind AK) { 119 return AArch64ARCHNames[static_cast<unsigned>(AK)].getCPUAttr(); 120} 121 122StringRef AArch64::getSubArch(AArch64::ArchKind AK) { 123 return AArch64ARCHNames[static_cast<unsigned>(AK)].getSubArch(); 124} 125 126unsigned AArch64::getArchAttr(AArch64::ArchKind AK) { 127 return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchAttr; 128} 129 130StringRef AArch64::getArchExtName(unsigned ArchExtKind) { 131 for (const auto &AE : AArch64ARCHExtNames) 132 if (ArchExtKind == AE.ID) 133 return AE.getName(); 134 return StringRef(); 135} 136 137StringRef AArch64::getArchExtFeature(StringRef ArchExt) { 138 if (ArchExt.startswith("no")) { 139 StringRef ArchExtBase(ArchExt.substr(2)); 140 for (const auto &AE : AArch64ARCHExtNames) { 141 if (AE.NegFeature && ArchExtBase == AE.getName()) 142 return StringRef(AE.NegFeature); 143 } 144 } 145 146 for (const auto &AE : AArch64ARCHExtNames) 147 if (AE.Feature && ArchExt == AE.getName()) 148 return StringRef(AE.Feature); 149 return StringRef(); 150} 151 152StringRef AArch64::getDefaultCPU(StringRef Arch) { 153 ArchKind AK = parseArch(Arch); 154 if (AK == ArchKind::INVALID) 155 return StringRef(); 156 157 // Look for multiple AKs to find the default for pair AK+Name. 158 for (const auto &CPU : AArch64CPUNames) 159 if (CPU.ArchID == AK && CPU.Default) 160 return CPU.getName(); 161 162 // If we can't find a default then target the architecture instead 163 return "generic"; 164} 165 166void AArch64::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) { 167 for (const auto &Arch : AArch64CPUNames) { 168 if (Arch.ArchID != ArchKind::INVALID) 169 Values.push_back(Arch.getName()); 170 } 171} 172 173bool AArch64::isX18ReservedByDefault(const Triple &TT) { 174 return TT.isAndroid() || TT.isOSDarwin() || TT.isOSFuchsia() || 175 TT.isOSWindows(); 176} 177 178// Allows partial match, ex. "v8a" matches "armv8a". 179AArch64::ArchKind AArch64::parseArch(StringRef Arch) { 180 Arch = ARM::getCanonicalArchName(Arch); 181 if (checkArchVersion(Arch) < 8) 182 return ArchKind::INVALID; 183 184 StringRef Syn = ARM::getArchSynonym(Arch); 185 for (const auto A : AArch64ARCHNames) { 186 if (A.getName().endswith(Syn)) 187 return A.ID; 188 } 189 return ArchKind::INVALID; 190} 191 192AArch64::ArchExtKind AArch64::parseArchExt(StringRef ArchExt) { 193 for (const auto A : AArch64ARCHExtNames) { 194 if (ArchExt == A.getName()) 195 return static_cast<ArchExtKind>(A.ID); 196 } 197 return AArch64::AEK_INVALID; 198} 199 200AArch64::ArchKind AArch64::parseCPUArch(StringRef CPU) { 201 for (const auto C : AArch64CPUNames) { 202 if (CPU == C.getName()) 203 return C.ArchID; 204 } 205 return ArchKind::INVALID; 206} 207