blob: e897137df680fcfc99f344223b3ecf31c152790f [file] [log] [blame]
David Spickette01718c2018-11-28 11:38:10 +00001//===-- 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}