1 //===-- AArch64TargetParser - Parser for AArch64 features -------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements a target parser to recognise AArch64 hardware features
11 // such as FPU/CPU/ARCH and extension names.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Support/AArch64TargetParser.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/StringSwitch.h"
22 static unsigned checkArchVersion(llvm::StringRef Arch) {
23 if (Arch.size() >= 2 && Arch[0] == 'v' && std::isdigit(Arch[1]))
24 return (Arch[1] - 48);
28 unsigned AArch64::getDefaultFPU(StringRef CPU, AArch64::ArchKind AK) {
30 return AArch64ARCHNames[static_cast<unsigned>(AK)].DefaultFPU;
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);
39 unsigned AArch64::getDefaultExtensions(StringRef CPU, AArch64::ArchKind AK) {
41 return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions;
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 | \
48 #include "../../include/llvm/Support/AArch64TargetParser.def"
49 .Default(AArch64::AEK_INVALID);
52 AArch64::ArchKind AArch64::getCPUArchKind(StringRef CPU) {
54 return ArchKind::ARMV8A;
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);
63 bool AArch64::getExtensionFeatures(unsigned Extensions,
64 std::vector<StringRef> &Features) {
65 if (Extensions == AArch64::AEK_INVALID)
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");
98 bool 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");
111 return AK != ArchKind::INVALID;
114 StringRef AArch64::getArchName(AArch64::ArchKind AK) {
115 return AArch64ARCHNames[static_cast<unsigned>(AK)].getName();
118 StringRef AArch64::getCPUAttr(AArch64::ArchKind AK) {
119 return AArch64ARCHNames[static_cast<unsigned>(AK)].getCPUAttr();
122 StringRef AArch64::getSubArch(AArch64::ArchKind AK) {
123 return AArch64ARCHNames[static_cast<unsigned>(AK)].getSubArch();
126 unsigned AArch64::getArchAttr(AArch64::ArchKind AK) {
127 return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchAttr;
130 StringRef AArch64::getArchExtName(unsigned ArchExtKind) {
131 for (const auto &AE : AArch64ARCHExtNames)
132 if (ArchExtKind == AE.ID)
137 StringRef 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);
146 for (const auto &AE : AArch64ARCHExtNames)
147 if (AE.Feature && ArchExt == AE.getName())
148 return StringRef(AE.Feature);
152 StringRef AArch64::getDefaultCPU(StringRef Arch) {
153 ArchKind AK = parseArch(Arch);
154 if (AK == ArchKind::INVALID)
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();
162 // If we can't find a default then target the architecture instead
166 void AArch64::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
167 for (const auto &Arch : AArch64CPUNames) {
168 if (Arch.ArchID != ArchKind::INVALID)
169 Values.push_back(Arch.getName());
173 bool AArch64::isX18ReservedByDefault(const Triple &TT) {
174 return TT.isAndroid() || TT.isOSDarwin() || TT.isOSFuchsia() ||
178 // Allows partial match, ex. "v8a" matches "armv8a".
179 AArch64::ArchKind AArch64::parseArch(StringRef Arch) {
180 Arch = ARM::getCanonicalArchName(Arch);
181 if (checkArchVersion(Arch) < 8)
182 return ArchKind::INVALID;
184 StringRef Syn = ARM::getArchSynonym(Arch);
185 for (const auto A : AArch64ARCHNames) {
186 if (A.getName().endswith(Syn))
189 return ArchKind::INVALID;
192 AArch64::ArchExtKind AArch64::parseArchExt(StringRef ArchExt) {
193 for (const auto A : AArch64ARCHExtNames) {
194 if (ArchExt == A.getName())
195 return static_cast<ArchExtKind>(A.ID);
197 return AArch64::AEK_INVALID;
200 AArch64::ArchKind AArch64::parseCPUArch(StringRef CPU) {
201 for (const auto C : AArch64CPUNames) {
202 if (CPU == C.getName())
205 return ArchKind::INVALID;