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