blob: 213275ab0096f5d47b3afca6739a14817c1ad29e [file] [log] [blame]
Renato Golinf5f373f2015-05-08 21:04:27 +00001//===-- TargetParser - Parser for target 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 hardware features such as
11// FPU/CPU/ARCH names as well as specific support such as HDIV, etc.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/Support/ARMBuildAttributes.h"
16#include "llvm/Support/TargetParser.h"
17#include "llvm/ADT/StringExtras.h"
18#include "llvm/ADT/StringSwitch.h"
Bradley Smith7b0a7d82015-11-18 16:32:12 +000019#include "llvm/ADT/Twine.h"
Renato Golinebdd12c2015-05-22 20:43:30 +000020#include <cctype>
Renato Golinf5f373f2015-05-08 21:04:27 +000021
22using namespace llvm;
Chandler Carruth799e8802015-08-30 05:27:31 +000023using namespace ARM;
Renato Golinf5f373f2015-05-08 21:04:27 +000024
25namespace {
26
John Brawnd03d2292015-06-05 13:29:24 +000027// List of canonical FPU names (use getFPUSynonym) and which architectural
28// features they correspond to (use getFPUFeatures).
Renato Golinf5f373f2015-05-08 21:04:27 +000029// FIXME: TableGen this.
Javed Absard5526302015-06-29 09:32:29 +000030// The entries must appear in the order listed in ARM::FPUKind for correct indexing
Artyom Skrobovbc09f392015-11-16 12:08:05 +000031static const struct {
Chandler Carruth3309ef62015-08-30 07:51:04 +000032 const char *NameCStr;
33 size_t NameLength;
Renato Golinf5f373f2015-05-08 21:04:27 +000034 ARM::FPUKind ID;
Javed Absard5526302015-06-29 09:32:29 +000035 ARM::FPUVersion FPUVersion;
John Brawnd03d2292015-06-05 13:29:24 +000036 ARM::NeonSupportLevel NeonSupport;
37 ARM::FPURestriction Restriction;
Chandler Carruth3309ef62015-08-30 07:51:04 +000038
39 StringRef getName() const { return StringRef(NameCStr, NameLength); }
Renato Golinf5f373f2015-05-08 21:04:27 +000040} FPUNames[] = {
Chandler Carruth799e8802015-08-30 05:27:31 +000041#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \
Chandler Carruth3309ef62015-08-30 07:51:04 +000042 { NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION },
Chandler Carruth799e8802015-08-30 05:27:31 +000043#include "llvm/Support/ARMTargetParser.def"
Renato Golinf5f373f2015-05-08 21:04:27 +000044};
John Brawnd03d2292015-06-05 13:29:24 +000045
Renato Golinf7c0d5f2015-05-27 18:15:37 +000046// List of canonical arch names (use getArchSynonym).
47// This table also provides the build attribute fields for CPU arch
48// and Arch ID, according to the Addenda to the ARM ABI, chapters
49// 2.4 and 2.3.5.2 respectively.
Renato Golin42dad642015-05-28 15:05:18 +000050// FIXME: SubArch values were simplified to fit into the expectations
51// of the triples and are not conforming with their official names.
52// Check to see if the expectation should be changed.
Renato Golinf5f373f2015-05-08 21:04:27 +000053// FIXME: TableGen this.
Artyom Skrobovbc09f392015-11-16 12:08:05 +000054static const struct {
Chandler Carruth3309ef62015-08-30 07:51:04 +000055 const char *NameCStr;
56 size_t NameLength;
Renato Golinf5f373f2015-05-08 21:04:27 +000057 ARM::ArchKind ID;
Chandler Carruth3309ef62015-08-30 07:51:04 +000058 const char *CPUAttrCStr;
59 size_t CPUAttrLength;
60 const char *SubArchCStr;
61 size_t SubArchLength;
Renato Golinf7c0d5f2015-05-27 18:15:37 +000062 ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
Bradley Smith4adcb732015-11-16 11:15:22 +000063 unsigned DefaultFPU;
Alexandros Lamprineasea33e5e2015-09-05 17:05:33 +000064 unsigned ArchBaseExtensions;
Chandler Carruth3309ef62015-08-30 07:51:04 +000065
66 StringRef getName() const { return StringRef(NameCStr, NameLength); }
67
68 // CPU class in build attributes.
69 StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); }
70
71 // Sub-Arch name.
72 StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); }
Renato Golinf5f373f2015-05-08 21:04:27 +000073} ARCHNames[] = {
Bradley Smith4adcb732015-11-16 11:15:22 +000074#define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \
Chandler Carruth3309ef62015-08-30 07:51:04 +000075 {NAME, sizeof(NAME) - 1, ID, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \
Bradley Smith4adcb732015-11-16 11:15:22 +000076 sizeof(SUB_ARCH) - 1, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT},
Chandler Carruth799e8802015-08-30 05:27:31 +000077#include "llvm/Support/ARMTargetParser.def"
Renato Golinf5f373f2015-05-08 21:04:27 +000078};
Chandler Carruth3309ef62015-08-30 07:51:04 +000079
Renato Goline1326ca2015-05-28 08:59:03 +000080// List of Arch Extension names.
Renato Golinf5f373f2015-05-08 21:04:27 +000081// FIXME: TableGen this.
Artyom Skrobovbc09f392015-11-16 12:08:05 +000082static const struct {
Chandler Carruth3309ef62015-08-30 07:51:04 +000083 const char *NameCStr;
84 size_t NameLength;
Alexandros Lamprineas4ea70752015-07-27 22:26:59 +000085 unsigned ID;
Bradley Smith7b0a7d82015-11-18 16:32:12 +000086 const char *Feature;
87 const char *NegFeature;
Chandler Carruth3309ef62015-08-30 07:51:04 +000088
89 StringRef getName() const { return StringRef(NameCStr, NameLength); }
Bradley Smith7b0a7d82015-11-18 16:32:12 +000090 StringRef getNegName() const { return (Twine("no") + getName()).str(); }
Renato Golinf5f373f2015-05-08 21:04:27 +000091} ARCHExtNames[] = {
Bradley Smith7b0a7d82015-11-18 16:32:12 +000092#define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \
93 { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE },
Chandler Carruth799e8802015-08-30 05:27:31 +000094#include "llvm/Support/ARMTargetParser.def"
Alexandros Lamprineas4ea70752015-07-27 22:26:59 +000095};
Chandler Carruth3309ef62015-08-30 07:51:04 +000096
Alexandros Lamprineas4ea70752015-07-27 22:26:59 +000097// List of HWDiv names (use getHWDivSynonym) and which architectural
98// features they correspond to (use getHWDivFeatures).
99// FIXME: TableGen this.
Artyom Skrobovbc09f392015-11-16 12:08:05 +0000100static const struct {
Chandler Carruth3309ef62015-08-30 07:51:04 +0000101 const char *NameCStr;
102 size_t NameLength;
Alexandros Lamprineas4ea70752015-07-27 22:26:59 +0000103 unsigned ID;
Chandler Carruth3309ef62015-08-30 07:51:04 +0000104
105 StringRef getName() const { return StringRef(NameCStr, NameLength); }
Alexandros Lamprineas4ea70752015-07-27 22:26:59 +0000106} HWDivNames[] = {
Chandler Carruth3309ef62015-08-30 07:51:04 +0000107#define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID },
Chandler Carruth799e8802015-08-30 05:27:31 +0000108#include "llvm/Support/ARMTargetParser.def"
Renato Golinf5f373f2015-05-08 21:04:27 +0000109};
Chandler Carruth3309ef62015-08-30 07:51:04 +0000110
Renato Goline8048f02015-05-20 15:05:07 +0000111// List of CPU names and their arches.
112// The same CPU can have multiple arches and can be default on multiple arches.
113// When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
Renato Golin7374fcd2015-05-28 12:10:37 +0000114// When this becomes table-generated, we'd probably need two tables.
Renato Goline8048f02015-05-20 15:05:07 +0000115// FIXME: TableGen this.
Artyom Skrobovbc09f392015-11-16 12:08:05 +0000116static const struct {
Chandler Carruth3309ef62015-08-30 07:51:04 +0000117 const char *NameCStr;
118 size_t NameLength;
Renato Goline8048f02015-05-20 15:05:07 +0000119 ARM::ArchKind ArchID;
Alexandros Lamprineasfcd93d52015-07-15 10:46:21 +0000120 bool Default; // is $Name the default CPU for $ArchID ?
Alexandros Lamprineasea33e5e2015-09-05 17:05:33 +0000121 unsigned DefaultExtensions;
Chandler Carruth3309ef62015-08-30 07:51:04 +0000122
123 StringRef getName() const { return StringRef(NameCStr, NameLength); }
Renato Goline8048f02015-05-20 15:05:07 +0000124} CPUNames[] = {
Alexandros Lamprineasea33e5e2015-09-05 17:05:33 +0000125#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
126 { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT },
Chandler Carruth799e8802015-08-30 05:27:31 +0000127#include "llvm/Support/ARMTargetParser.def"
Renato Goline8048f02015-05-20 15:05:07 +0000128};
Renato Golinf5f373f2015-05-08 21:04:27 +0000129
130} // namespace
131
Renato Golinf5f373f2015-05-08 21:04:27 +0000132// ======================================================= //
133// Information by ID
134// ======================================================= //
135
Chandler Carruth3309ef62015-08-30 07:51:04 +0000136StringRef llvm::ARM::getFPUName(unsigned FPUKind) {
Renato Goline8048f02015-05-20 15:05:07 +0000137 if (FPUKind >= ARM::FK_LAST)
Chandler Carruth3309ef62015-08-30 07:51:04 +0000138 return StringRef();
139 return FPUNames[FPUKind].getName();
Renato Golinf5f373f2015-05-08 21:04:27 +0000140}
141
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000142unsigned llvm::ARM::getFPUVersion(unsigned FPUKind) {
John Brawnd03d2292015-06-05 13:29:24 +0000143 if (FPUKind >= ARM::FK_LAST)
144 return 0;
145 return FPUNames[FPUKind].FPUVersion;
146}
147
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000148unsigned llvm::ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
John Brawnd03d2292015-06-05 13:29:24 +0000149 if (FPUKind >= ARM::FK_LAST)
150 return 0;
151 return FPUNames[FPUKind].NeonSupport;
152}
153
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000154unsigned llvm::ARM::getFPURestriction(unsigned FPUKind) {
John Brawnd03d2292015-06-05 13:29:24 +0000155 if (FPUKind >= ARM::FK_LAST)
156 return 0;
157 return FPUNames[FPUKind].Restriction;
158}
159
Bradley Smith4adcb732015-11-16 11:15:22 +0000160unsigned llvm::ARM::getDefaultFPU(StringRef CPU, unsigned ArchKind) {
161 if (CPU == "generic")
162 return ARCHNames[ArchKind].DefaultFPU;
163
Chandler Carruth822d54a2015-08-30 09:01:38 +0000164 return StringSwitch<unsigned>(CPU)
Alexandros Lamprineasea33e5e2015-09-05 17:05:33 +0000165#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
Chandler Carruth822d54a2015-08-30 09:01:38 +0000166 .Case(NAME, DEFAULT_FPU)
167#include "llvm/Support/ARMTargetParser.def"
168 .Default(ARM::FK_INVALID);
Alexandros Lamprineasfcd93d52015-07-15 10:46:21 +0000169}
170
Artyom Skrobovbc09f392015-11-16 12:08:05 +0000171unsigned llvm::ARM::getDefaultExtensions(StringRef CPU, unsigned ArchKind) {
172 if (CPU == "generic")
173 return ARCHNames[ArchKind].ArchBaseExtensions;
174
175 return StringSwitch<unsigned>(CPU)
176#define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
177 .Case(NAME, ARCHNames[ID].ArchBaseExtensions | DEFAULT_EXT)
178#include "llvm/Support/ARMTargetParser.def"
179 .Default(ARM::AEK_INVALID);
180}
181
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000182bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind,
Chandler Carruth4fc3a982015-08-30 02:17:15 +0000183 std::vector<const char *> &Features) {
Alexandros Lamprineas4ea70752015-07-27 22:26:59 +0000184
185 if (HWDivKind == ARM::AEK_INVALID)
186 return false;
187
Chandler Carruth4fc3a982015-08-30 02:17:15 +0000188 if (HWDivKind & ARM::AEK_HWDIVARM)
Alexandros Lamprineas4ea70752015-07-27 22:26:59 +0000189 Features.push_back("+hwdiv-arm");
190 else
191 Features.push_back("-hwdiv-arm");
192
193 if (HWDivKind & ARM::AEK_HWDIV)
194 Features.push_back("+hwdiv");
195 else
196 Features.push_back("-hwdiv");
197
198 return true;
199}
200
Alexandros Lamprineasea33e5e2015-09-05 17:05:33 +0000201bool llvm::ARM::getExtensionFeatures(unsigned Extensions,
202 std::vector<const char *> &Features) {
203
204 if (Extensions == ARM::AEK_INVALID)
205 return false;
206
207 if (Extensions & ARM::AEK_CRC)
208 Features.push_back("+crc");
209 else
210 Features.push_back("-crc");
211
Artyom Skrobovcf296442015-09-24 17:31:16 +0000212 if (Extensions & ARM::AEK_DSP)
Artyom Skrobov5a6e3942015-10-23 17:19:19 +0000213 Features.push_back("+dsp");
Artyom Skrobovcf296442015-09-24 17:31:16 +0000214 else
Artyom Skrobov5a6e3942015-10-23 17:19:19 +0000215 Features.push_back("-dsp");
Artyom Skrobovcf296442015-09-24 17:31:16 +0000216
Alexandros Lamprineasea33e5e2015-09-05 17:05:33 +0000217 return getHWDivFeatures(Extensions, Features);
218}
219
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000220bool llvm::ARM::getFPUFeatures(unsigned FPUKind,
Chandler Carruth4fc3a982015-08-30 02:17:15 +0000221 std::vector<const char *> &Features) {
John Brawnd03d2292015-06-05 13:29:24 +0000222
223 if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID)
224 return false;
225
226 // fp-only-sp and d16 subtarget features are independent of each other, so we
227 // must enable/disable both.
228 switch (FPUNames[FPUKind].Restriction) {
229 case ARM::FR_SP_D16:
230 Features.push_back("+fp-only-sp");
231 Features.push_back("+d16");
232 break;
233 case ARM::FR_D16:
234 Features.push_back("-fp-only-sp");
235 Features.push_back("+d16");
236 break;
237 case ARM::FR_None:
238 Features.push_back("-fp-only-sp");
239 Features.push_back("-d16");
240 break;
241 }
242
243 // FPU version subtarget features are inclusive of lower-numbered ones, so
244 // enable the one corresponding to this version and disable all that are
John Brawnd9e39d52015-06-12 09:38:51 +0000245 // higher. We also have to make sure to disable fp16 when vfp4 is disabled,
246 // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16.
John Brawnd03d2292015-06-05 13:29:24 +0000247 switch (FPUNames[FPUKind].FPUVersion) {
Javed Absard5526302015-06-29 09:32:29 +0000248 case ARM::FV_VFPV5:
John Brawnd03d2292015-06-05 13:29:24 +0000249 Features.push_back("+fp-armv8");
250 break;
Javed Absard5526302015-06-29 09:32:29 +0000251 case ARM::FV_VFPV4:
John Brawnd03d2292015-06-05 13:29:24 +0000252 Features.push_back("+vfp4");
253 Features.push_back("-fp-armv8");
254 break;
Javed Absard5526302015-06-29 09:32:29 +0000255 case ARM::FV_VFPV3_FP16:
256 Features.push_back("+vfp3");
257 Features.push_back("+fp16");
258 Features.push_back("-vfp4");
259 Features.push_back("-fp-armv8");
260 break;
261 case ARM::FV_VFPV3:
John Brawnd03d2292015-06-05 13:29:24 +0000262 Features.push_back("+vfp3");
John Brawnd9e39d52015-06-12 09:38:51 +0000263 Features.push_back("-fp16");
John Brawnd03d2292015-06-05 13:29:24 +0000264 Features.push_back("-vfp4");
265 Features.push_back("-fp-armv8");
266 break;
Javed Absard5526302015-06-29 09:32:29 +0000267 case ARM::FV_VFPV2:
John Brawnd03d2292015-06-05 13:29:24 +0000268 Features.push_back("+vfp2");
269 Features.push_back("-vfp3");
John Brawnd9e39d52015-06-12 09:38:51 +0000270 Features.push_back("-fp16");
John Brawnd03d2292015-06-05 13:29:24 +0000271 Features.push_back("-vfp4");
272 Features.push_back("-fp-armv8");
273 break;
Javed Absard5526302015-06-29 09:32:29 +0000274 case ARM::FV_NONE:
John Brawnd03d2292015-06-05 13:29:24 +0000275 Features.push_back("-vfp2");
276 Features.push_back("-vfp3");
John Brawnd9e39d52015-06-12 09:38:51 +0000277 Features.push_back("-fp16");
John Brawnd03d2292015-06-05 13:29:24 +0000278 Features.push_back("-vfp4");
279 Features.push_back("-fp-armv8");
280 break;
281 }
282
283 // crypto includes neon, so we handle this similarly to FPU version.
284 switch (FPUNames[FPUKind].NeonSupport) {
285 case ARM::NS_Crypto:
Alexandros Lamprineasea33e5e2015-09-05 17:05:33 +0000286 Features.push_back("+neon");
John Brawnd03d2292015-06-05 13:29:24 +0000287 Features.push_back("+crypto");
288 break;
289 case ARM::NS_Neon:
290 Features.push_back("+neon");
291 Features.push_back("-crypto");
292 break;
293 case ARM::NS_None:
294 Features.push_back("-neon");
295 Features.push_back("-crypto");
296 break;
297 }
298
299 return true;
300}
301
Chandler Carruth3309ef62015-08-30 07:51:04 +0000302StringRef llvm::ARM::getArchName(unsigned ArchKind) {
Renato Goline8048f02015-05-20 15:05:07 +0000303 if (ArchKind >= ARM::AK_LAST)
Chandler Carruth3309ef62015-08-30 07:51:04 +0000304 return StringRef();
305 return ARCHNames[ArchKind].getName();
Renato Golinf5f373f2015-05-08 21:04:27 +0000306}
307
Chandler Carruth3309ef62015-08-30 07:51:04 +0000308StringRef llvm::ARM::getCPUAttr(unsigned ArchKind) {
Renato Goline8048f02015-05-20 15:05:07 +0000309 if (ArchKind >= ARM::AK_LAST)
Chandler Carruth3309ef62015-08-30 07:51:04 +0000310 return StringRef();
311 return ARCHNames[ArchKind].getCPUAttr();
Renato Golinf5f373f2015-05-08 21:04:27 +0000312}
313
Chandler Carruth3309ef62015-08-30 07:51:04 +0000314StringRef llvm::ARM::getSubArch(unsigned ArchKind) {
Renato Golin42dad642015-05-28 15:05:18 +0000315 if (ArchKind >= ARM::AK_LAST)
Chandler Carruth3309ef62015-08-30 07:51:04 +0000316 return StringRef();
317 return ARCHNames[ArchKind].getSubArch();
Renato Golin42dad642015-05-28 15:05:18 +0000318}
319
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000320unsigned llvm::ARM::getArchAttr(unsigned ArchKind) {
Renato Goline8048f02015-05-20 15:05:07 +0000321 if (ArchKind >= ARM::AK_LAST)
322 return ARMBuildAttrs::CPUArch::Pre_v4;
Renato Golinf7c0d5f2015-05-27 18:15:37 +0000323 return ARCHNames[ArchKind].ArchAttr;
Renato Golinf5f373f2015-05-08 21:04:27 +0000324}
325
Chandler Carruth3309ef62015-08-30 07:51:04 +0000326StringRef llvm::ARM::getArchExtName(unsigned ArchExtKind) {
Alexandros Lamprineas4ea70752015-07-27 22:26:59 +0000327 for (const auto AE : ARCHExtNames) {
328 if (ArchExtKind == AE.ID)
Chandler Carruth3309ef62015-08-30 07:51:04 +0000329 return AE.getName();
Alexandros Lamprineas4ea70752015-07-27 22:26:59 +0000330 }
Chandler Carruth3309ef62015-08-30 07:51:04 +0000331 return StringRef();
Alexandros Lamprineas4ea70752015-07-27 22:26:59 +0000332}
333
Bradley Smith7b0a7d82015-11-18 16:32:12 +0000334const char *llvm::ARM::getArchExtFeature(StringRef ArchExt) {
335 for (const auto AE : ARCHExtNames) {
336 if (AE.Feature && ArchExt == AE.getName())
337 return AE.Feature;
338 else if (AE.NegFeature && ArchExt == AE.getNegName())
339 return AE.NegFeature;
340 }
341
342 return nullptr;
343}
344
Chandler Carruth3309ef62015-08-30 07:51:04 +0000345StringRef llvm::ARM::getHWDivName(unsigned HWDivKind) {
Alexandros Lamprineas4ea70752015-07-27 22:26:59 +0000346 for (const auto D : HWDivNames) {
347 if (HWDivKind == D.ID)
Chandler Carruth3309ef62015-08-30 07:51:04 +0000348 return D.getName();
Alexandros Lamprineas4ea70752015-07-27 22:26:59 +0000349 }
Chandler Carruth3309ef62015-08-30 07:51:04 +0000350 return StringRef();
Renato Goline8048f02015-05-20 15:05:07 +0000351}
352
Chandler Carruth3309ef62015-08-30 07:51:04 +0000353StringRef llvm::ARM::getDefaultCPU(StringRef Arch) {
Renato Goline8048f02015-05-20 15:05:07 +0000354 unsigned AK = parseArch(Arch);
355 if (AK == ARM::AK_INVALID)
Chandler Carruth3309ef62015-08-30 07:51:04 +0000356 return StringRef();
Renato Goline8048f02015-05-20 15:05:07 +0000357
358 // Look for multiple AKs to find the default for pair AK+Name.
359 for (const auto CPU : CPUNames) {
360 if (CPU.ArchID == AK && CPU.Default)
Chandler Carruth3309ef62015-08-30 07:51:04 +0000361 return CPU.getName();
Renato Goline8048f02015-05-20 15:05:07 +0000362 }
Bradley Smith4adcb732015-11-16 11:15:22 +0000363
364 // If we can't find a default then target the architecture instead
365 return "generic";
Renato Golinf5f373f2015-05-08 21:04:27 +0000366}
367
368// ======================================================= //
369// Parsers
370// ======================================================= //
371
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000372static StringRef getHWDivSynonym(StringRef HWDiv) {
Alexandros Lamprineas4ea70752015-07-27 22:26:59 +0000373 return StringSwitch<StringRef>(HWDiv)
Chandler Carruth4fc3a982015-08-30 02:17:15 +0000374 .Case("thumb,arm", "arm,thumb")
375 .Default(HWDiv);
Alexandros Lamprineas4ea70752015-07-27 22:26:59 +0000376}
377
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000378static StringRef getFPUSynonym(StringRef FPU) {
Renato Golinf5f373f2015-05-08 21:04:27 +0000379 return StringSwitch<StringRef>(FPU)
Chandler Carruth4fc3a982015-08-30 02:17:15 +0000380 .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
381 .Case("vfp2", "vfpv2")
382 .Case("vfp3", "vfpv3")
383 .Case("vfp4", "vfpv4")
384 .Case("vfp3-d16", "vfpv3-d16")
385 .Case("vfp4-d16", "vfpv4-d16")
386 .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
387 .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
388 .Case("fp5-sp-d16", "fpv5-sp-d16")
389 .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
390 // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
391 .Case("neon-vfpv3", "neon")
392 .Default(FPU);
Renato Golinf5f373f2015-05-08 21:04:27 +0000393}
394
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000395static StringRef getArchSynonym(StringRef Arch) {
Renato Golinf5f373f2015-05-08 21:04:27 +0000396 return StringSwitch<StringRef>(Arch)
Artyom Skrobov2c2f3782015-11-12 15:51:41 +0000397 .Case("v5", "v5t")
398 .Case("v5e", "v5te")
399 .Case("v6hl", "v6k")
400 .Cases("v6m", "v6sm", "v6s-m", "v6-m")
Artyom Skrobovf187a652015-11-16 14:05:32 +0000401 .Cases("v6z", "v6zk", "v6kz")
Artyom Skrobov2c2f3782015-11-12 15:51:41 +0000402 .Cases("v7", "v7a", "v7hl", "v7l", "v7-a")
Chandler Carruth4fc3a982015-08-30 02:17:15 +0000403 .Case("v7r", "v7-r")
404 .Case("v7m", "v7-m")
405 .Case("v7em", "v7e-m")
406 .Cases("v8", "v8a", "aarch64", "arm64", "v8-a")
407 .Case("v8.1a", "v8.1-a")
408 .Default(Arch);
Renato Golinf5f373f2015-05-08 21:04:27 +0000409}
410
Renato Goline8048f02015-05-20 15:05:07 +0000411// MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
412// (iwmmxt|xscale)(eb)? is also permitted. If the former, return
Renato Golinebdd12c2015-05-22 20:43:30 +0000413// "v.+", if the latter, return unmodified string, minus 'eb'.
414// If invalid, return empty string.
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000415StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) {
Renato Goline8048f02015-05-20 15:05:07 +0000416 size_t offset = StringRef::npos;
417 StringRef A = Arch;
Renato Golinb6b9e052015-05-21 13:52:20 +0000418 StringRef Error = "";
Renato Goline8048f02015-05-20 15:05:07 +0000419
420 // Begins with "arm" / "thumb", move past it.
Renato Golinebdd12c2015-05-22 20:43:30 +0000421 if (A.startswith("arm64"))
422 offset = 5;
423 else if (A.startswith("arm"))
Renato Goline8048f02015-05-20 15:05:07 +0000424 offset = 3;
425 else if (A.startswith("thumb"))
426 offset = 5;
Renato Golinb6b9e052015-05-21 13:52:20 +0000427 else if (A.startswith("aarch64")) {
428 offset = 7;
429 // AArch64 uses "_be", not "eb" suffix.
430 if (A.find("eb") != StringRef::npos)
431 return Error;
Chandler Carruth4fc3a982015-08-30 02:17:15 +0000432 if (A.substr(offset, 3) == "_be")
Renato Golinb6b9e052015-05-21 13:52:20 +0000433 offset += 3;
434 }
435
Renato Goline8048f02015-05-20 15:05:07 +0000436 // Ex. "armebv7", move past the "eb".
437 if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
438 offset += 2;
439 // Or, if it ends with eb ("armv7eb"), chop it off.
440 else if (A.endswith("eb"))
441 A = A.substr(0, A.size() - 2);
Renato Golinebdd12c2015-05-22 20:43:30 +0000442 // Trim the head
443 if (offset != StringRef::npos)
Renato Goline8048f02015-05-20 15:05:07 +0000444 A = A.substr(offset);
445
Renato Golinebdd12c2015-05-22 20:43:30 +0000446 // Empty string means offset reached the end, which means it's valid.
Renato Goline8048f02015-05-20 15:05:07 +0000447 if (A.empty())
448 return Arch;
449
Renato Golinebdd12c2015-05-22 20:43:30 +0000450 // Only match non-marketing names
451 if (offset != StringRef::npos) {
Chandler Carruth4fc3a982015-08-30 02:17:15 +0000452 // Must start with 'vN'.
Renato Golinebdd12c2015-05-22 20:43:30 +0000453 if (A[0] != 'v' || !std::isdigit(A[1]))
454 return Error;
455 // Can't have an extra 'eb'.
456 if (A.find("eb") != StringRef::npos)
457 return Error;
458 }
Renato Goline8048f02015-05-20 15:05:07 +0000459
Renato Golinebdd12c2015-05-22 20:43:30 +0000460 // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
Renato Goline8048f02015-05-20 15:05:07 +0000461 return A;
462}
463
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000464unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) {
Alexandros Lamprineas4ea70752015-07-27 22:26:59 +0000465 StringRef Syn = getHWDivSynonym(HWDiv);
466 for (const auto D : HWDivNames) {
Chandler Carruth3309ef62015-08-30 07:51:04 +0000467 if (Syn == D.getName())
Alexandros Lamprineas4ea70752015-07-27 22:26:59 +0000468 return D.ID;
469 }
470 return ARM::AEK_INVALID;
471}
472
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000473unsigned llvm::ARM::parseFPU(StringRef FPU) {
Renato Golinf5f373f2015-05-08 21:04:27 +0000474 StringRef Syn = getFPUSynonym(FPU);
475 for (const auto F : FPUNames) {
Chandler Carruth3309ef62015-08-30 07:51:04 +0000476 if (Syn == F.getName())
Renato Golinf5f373f2015-05-08 21:04:27 +0000477 return F.ID;
478 }
Renato Golin35de35d2015-05-12 10:33:58 +0000479 return ARM::FK_INVALID;
Renato Golinf5f373f2015-05-08 21:04:27 +0000480}
481
Renato Goline8048f02015-05-20 15:05:07 +0000482// Allows partial match, ex. "v7a" matches "armv7a".
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000483unsigned llvm::ARM::parseArch(StringRef Arch) {
Artyom Skrobov85aebc82015-06-04 21:26:58 +0000484 Arch = getCanonicalArchName(Arch);
Renato Golinf5f373f2015-05-08 21:04:27 +0000485 StringRef Syn = getArchSynonym(Arch);
486 for (const auto A : ARCHNames) {
Chandler Carruth3309ef62015-08-30 07:51:04 +0000487 if (A.getName().endswith(Syn))
Renato Golinf5f373f2015-05-08 21:04:27 +0000488 return A.ID;
489 }
Renato Golin35de35d2015-05-12 10:33:58 +0000490 return ARM::AK_INVALID;
Renato Golinf5f373f2015-05-08 21:04:27 +0000491}
492
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000493unsigned llvm::ARM::parseArchExt(StringRef ArchExt) {
Renato Golinf5f373f2015-05-08 21:04:27 +0000494 for (const auto A : ARCHExtNames) {
Chandler Carruth3309ef62015-08-30 07:51:04 +0000495 if (ArchExt == A.getName())
Renato Golinf5f373f2015-05-08 21:04:27 +0000496 return A.ID;
497 }
Renato Golin35de35d2015-05-12 10:33:58 +0000498 return ARM::AEK_INVALID;
Renato Golinf5f373f2015-05-08 21:04:27 +0000499}
500
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000501unsigned llvm::ARM::parseCPUArch(StringRef CPU) {
Renato Goline8048f02015-05-20 15:05:07 +0000502 for (const auto C : CPUNames) {
Chandler Carruth3309ef62015-08-30 07:51:04 +0000503 if (CPU == C.getName())
Renato Goline8048f02015-05-20 15:05:07 +0000504 return C.ArchID;
505 }
506 return ARM::AK_INVALID;
507}
508
Renato Golinb6b9e052015-05-21 13:52:20 +0000509// ARM, Thumb, AArch64
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000510unsigned llvm::ARM::parseArchISA(StringRef Arch) {
Renato Golinb6b9e052015-05-21 13:52:20 +0000511 return StringSwitch<unsigned>(Arch)
512 .StartsWith("aarch64", ARM::IK_AARCH64)
Chandler Carruth4fc3a982015-08-30 02:17:15 +0000513 .StartsWith("arm64", ARM::IK_AARCH64)
514 .StartsWith("thumb", ARM::IK_THUMB)
515 .StartsWith("arm", ARM::IK_ARM)
Renato Golinb6b9e052015-05-21 13:52:20 +0000516 .Default(ARM::EK_INVALID);
517}
518
519// Little/Big endian
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000520unsigned llvm::ARM::parseArchEndian(StringRef Arch) {
Chandler Carruth4fc3a982015-08-30 02:17:15 +0000521 if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
Renato Golinb6b9e052015-05-21 13:52:20 +0000522 Arch.startswith("aarch64_be"))
523 return ARM::EK_BIG;
524
525 if (Arch.startswith("arm") || Arch.startswith("thumb")) {
526 if (Arch.endswith("eb"))
527 return ARM::EK_BIG;
528 else
529 return ARM::EK_LITTLE;
530 }
531
532 if (Arch.startswith("aarch64"))
533 return ARM::EK_LITTLE;
534
535 return ARM::EK_INVALID;
536}
537
Renato Golinfadc2102015-05-22 18:17:55 +0000538// Profile A/R/M
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000539unsigned llvm::ARM::parseArchProfile(StringRef Arch) {
Renato Golinfadc2102015-05-22 18:17:55 +0000540 Arch = getCanonicalArchName(Arch);
Chandler Carruth4fc3a982015-08-30 02:17:15 +0000541 switch (parseArch(Arch)) {
Renato Golinfadc2102015-05-22 18:17:55 +0000542 case ARM::AK_ARMV6M:
543 case ARM::AK_ARMV7M:
Renato Golinfadc2102015-05-22 18:17:55 +0000544 case ARM::AK_ARMV7EM:
545 return ARM::PK_M;
546 case ARM::AK_ARMV7R:
547 return ARM::PK_R;
Renato Golinfadc2102015-05-22 18:17:55 +0000548 case ARM::AK_ARMV7A:
Tim Northover2d4d1612015-10-28 22:36:05 +0000549 case ARM::AK_ARMV7K:
Renato Golinfadc2102015-05-22 18:17:55 +0000550 case ARM::AK_ARMV8A:
551 case ARM::AK_ARMV8_1A:
552 return ARM::PK_A;
553 }
554 return ARM::PK_INVALID;
555}
556
Renato Golinebdd12c2015-05-22 20:43:30 +0000557// Version number (ex. v7 = 7).
Chandler Carruthbb47b9a2015-08-30 02:09:48 +0000558unsigned llvm::ARM::parseArchVersion(StringRef Arch) {
Renato Golinfadc2102015-05-22 18:17:55 +0000559 Arch = getCanonicalArchName(Arch);
Chandler Carruth4fc3a982015-08-30 02:17:15 +0000560 switch (parseArch(Arch)) {
Renato Golinfadc2102015-05-22 18:17:55 +0000561 case ARM::AK_ARMV2:
562 case ARM::AK_ARMV2A:
563 return 2;
564 case ARM::AK_ARMV3:
565 case ARM::AK_ARMV3M:
566 return 3;
567 case ARM::AK_ARMV4:
568 case ARM::AK_ARMV4T:
569 return 4;
Renato Golinfadc2102015-05-22 18:17:55 +0000570 case ARM::AK_ARMV5T:
571 case ARM::AK_ARMV5TE:
572 case ARM::AK_IWMMXT:
573 case ARM::AK_IWMMXT2:
574 case ARM::AK_XSCALE:
Renato Golinfadc2102015-05-22 18:17:55 +0000575 case ARM::AK_ARMV5TEJ:
576 return 5;
577 case ARM::AK_ARMV6:
578 case ARM::AK_ARMV6J:
579 case ARM::AK_ARMV6K:
580 case ARM::AK_ARMV6T2:
Artyom Skrobovf187a652015-11-16 14:05:32 +0000581 case ARM::AK_ARMV6KZ:
Renato Golinfadc2102015-05-22 18:17:55 +0000582 case ARM::AK_ARMV6M:
Renato Golinfadc2102015-05-22 18:17:55 +0000583 return 6;
Renato Golinfadc2102015-05-22 18:17:55 +0000584 case ARM::AK_ARMV7A:
585 case ARM::AK_ARMV7R:
586 case ARM::AK_ARMV7M:
Renato Golinfadc2102015-05-22 18:17:55 +0000587 case ARM::AK_ARMV7S:
588 case ARM::AK_ARMV7EM:
Vedant Kumar366dd9fd2015-08-21 21:52:48 +0000589 case ARM::AK_ARMV7K:
Renato Golinfadc2102015-05-22 18:17:55 +0000590 return 7;
591 case ARM::AK_ARMV8A:
592 case ARM::AK_ARMV8_1A:
593 return 8;
594 }
595 return 0;
596}