]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Support/AArch64TargetParser.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Support / AArch64TargetParser.cpp
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
20 using namespace llvm;
21
22 static 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
28 unsigned 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
39 unsigned 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
52 AArch64::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
63 bool 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
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");
110
111   return AK != ArchKind::INVALID;
112 }
113
114 StringRef AArch64::getArchName(AArch64::ArchKind AK) {
115   return AArch64ARCHNames[static_cast<unsigned>(AK)].getName();
116 }
117
118 StringRef AArch64::getCPUAttr(AArch64::ArchKind AK) {
119   return AArch64ARCHNames[static_cast<unsigned>(AK)].getCPUAttr();
120 }
121
122 StringRef AArch64::getSubArch(AArch64::ArchKind AK) {
123   return AArch64ARCHNames[static_cast<unsigned>(AK)].getSubArch();
124 }
125
126 unsigned AArch64::getArchAttr(AArch64::ArchKind AK) {
127   return AArch64ARCHNames[static_cast<unsigned>(AK)].ArchAttr;
128 }
129
130 StringRef AArch64::getArchExtName(unsigned ArchExtKind) {
131   for (const auto &AE : AArch64ARCHExtNames)
132     if (ArchExtKind == AE.ID)
133       return AE.getName();
134   return StringRef();
135 }
136
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);
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
152 StringRef 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
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());
170   }
171 }
172
173 bool 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".
179 AArch64::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
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);
196   }
197   return AArch64::AEK_INVALID;
198 }
199
200 AArch64::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 }