1 //===-- TargetParser - Parser for target 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 hardware features such as
11 // FPU/CPU/ARCH names as well as specific support such as HDIV, etc.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Support/ARMBuildAttributes.h"
16 #include "llvm/Support/TargetParser.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/ADT/StringSwitch.h"
26 // List of canonical FPU names (use getFPUSynonym) and which architectural
27 // features they correspond to (use getFPUFeatures).
28 // FIXME: TableGen this.
29 // The entries must appear in the order listed in ARM::FPUKind for correct indexing
33 ARM::FPUVersion FPUVersion;
34 ARM::NeonSupportLevel NeonSupport;
35 ARM::FPURestriction Restriction;
37 #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \
38 { NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION },
39 #include "llvm/Support/ARMTargetParser.def"
42 // List of canonical arch names (use getArchSynonym).
43 // This table also provides the build attribute fields for CPU arch
44 // and Arch ID, according to the Addenda to the ARM ABI, chapters
45 // 2.4 and 2.3.5.2 respectively.
46 // FIXME: SubArch values were simplified to fit into the expectations
47 // of the triples and are not conforming with their official names.
48 // Check to see if the expectation should be changed.
49 // FIXME: TableGen this.
53 const char *CPUAttr; // CPU class in build attributes.
54 const char *SubArch; // Sub-Arch name.
55 ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
57 #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR) \
58 { NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR },
59 #include "llvm/Support/ARMTargetParser.def"
61 // List of Arch Extension names.
62 // FIXME: TableGen this.
67 #define ARM_ARCH_EXT_NAME(NAME, ID) { NAME, ID },
68 #include "llvm/Support/ARMTargetParser.def"
70 // List of HWDiv names (use getHWDivSynonym) and which architectural
71 // features they correspond to (use getHWDivFeatures).
72 // FIXME: TableGen this.
77 #define ARM_HW_DIV_NAME(NAME, ID) { NAME, ID },
78 #include "llvm/Support/ARMTargetParser.def"
80 // List of CPU names and their arches.
81 // The same CPU can have multiple arches and can be default on multiple arches.
82 // When finding the Arch for a CPU, first-found prevails. Sort them accordingly.
83 // When this becomes table-generated, we'd probably need two tables.
84 // FIXME: TableGen this.
88 ARM::FPUKind DefaultFPU;
89 bool Default; // is $Name the default CPU for $ArchID ?
91 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT) \
92 { NAME, ID, DEFAULT_FPU, IS_DEFAULT },
93 #include "llvm/Support/ARMTargetParser.def"
98 // ======================================================= //
100 // ======================================================= //
102 const char *llvm::ARM::getFPUName(unsigned FPUKind) {
103 if (FPUKind >= ARM::FK_LAST)
105 return FPUNames[FPUKind].Name;
108 unsigned llvm::ARM::getFPUVersion(unsigned FPUKind) {
109 if (FPUKind >= ARM::FK_LAST)
111 return FPUNames[FPUKind].FPUVersion;
114 unsigned llvm::ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
115 if (FPUKind >= ARM::FK_LAST)
117 return FPUNames[FPUKind].NeonSupport;
120 unsigned llvm::ARM::getFPURestriction(unsigned FPUKind) {
121 if (FPUKind >= ARM::FK_LAST)
123 return FPUNames[FPUKind].Restriction;
126 unsigned llvm::ARM::getDefaultFPU(StringRef CPU) {
127 for (const auto C : CPUNames) {
131 return ARM::FK_INVALID;
134 bool llvm::ARM::getHWDivFeatures(unsigned HWDivKind,
135 std::vector<const char *> &Features) {
137 if (HWDivKind == ARM::AEK_INVALID)
140 if (HWDivKind & ARM::AEK_HWDIVARM)
141 Features.push_back("+hwdiv-arm");
143 Features.push_back("-hwdiv-arm");
145 if (HWDivKind & ARM::AEK_HWDIV)
146 Features.push_back("+hwdiv");
148 Features.push_back("-hwdiv");
153 bool llvm::ARM::getFPUFeatures(unsigned FPUKind,
154 std::vector<const char *> &Features) {
156 if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID)
159 // fp-only-sp and d16 subtarget features are independent of each other, so we
160 // must enable/disable both.
161 switch (FPUNames[FPUKind].Restriction) {
163 Features.push_back("+fp-only-sp");
164 Features.push_back("+d16");
167 Features.push_back("-fp-only-sp");
168 Features.push_back("+d16");
171 Features.push_back("-fp-only-sp");
172 Features.push_back("-d16");
176 // FPU version subtarget features are inclusive of lower-numbered ones, so
177 // enable the one corresponding to this version and disable all that are
178 // higher. We also have to make sure to disable fp16 when vfp4 is disabled,
179 // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16.
180 switch (FPUNames[FPUKind].FPUVersion) {
182 Features.push_back("+fp-armv8");
185 Features.push_back("+vfp4");
186 Features.push_back("-fp-armv8");
188 case ARM::FV_VFPV3_FP16:
189 Features.push_back("+vfp3");
190 Features.push_back("+fp16");
191 Features.push_back("-vfp4");
192 Features.push_back("-fp-armv8");
195 Features.push_back("+vfp3");
196 Features.push_back("-fp16");
197 Features.push_back("-vfp4");
198 Features.push_back("-fp-armv8");
201 Features.push_back("+vfp2");
202 Features.push_back("-vfp3");
203 Features.push_back("-fp16");
204 Features.push_back("-vfp4");
205 Features.push_back("-fp-armv8");
208 Features.push_back("-vfp2");
209 Features.push_back("-vfp3");
210 Features.push_back("-fp16");
211 Features.push_back("-vfp4");
212 Features.push_back("-fp-armv8");
216 // crypto includes neon, so we handle this similarly to FPU version.
217 switch (FPUNames[FPUKind].NeonSupport) {
219 Features.push_back("+crypto");
222 Features.push_back("+neon");
223 Features.push_back("-crypto");
226 Features.push_back("-neon");
227 Features.push_back("-crypto");
234 const char *llvm::ARM::getArchName(unsigned ArchKind) {
235 if (ArchKind >= ARM::AK_LAST)
237 return ARCHNames[ArchKind].Name;
240 const char *llvm::ARM::getCPUAttr(unsigned ArchKind) {
241 if (ArchKind >= ARM::AK_LAST)
243 return ARCHNames[ArchKind].CPUAttr;
246 const char *llvm::ARM::getSubArch(unsigned ArchKind) {
247 if (ArchKind >= ARM::AK_LAST)
249 return ARCHNames[ArchKind].SubArch;
252 unsigned llvm::ARM::getArchAttr(unsigned ArchKind) {
253 if (ArchKind >= ARM::AK_LAST)
254 return ARMBuildAttrs::CPUArch::Pre_v4;
255 return ARCHNames[ArchKind].ArchAttr;
258 const char *llvm::ARM::getArchExtName(unsigned ArchExtKind) {
259 for (const auto AE : ARCHExtNames) {
260 if (ArchExtKind == AE.ID)
266 const char *llvm::ARM::getHWDivName(unsigned HWDivKind) {
267 for (const auto D : HWDivNames) {
268 if (HWDivKind == D.ID)
274 const char *llvm::ARM::getDefaultCPU(StringRef Arch) {
275 unsigned AK = parseArch(Arch);
276 if (AK == ARM::AK_INVALID)
279 // Look for multiple AKs to find the default for pair AK+Name.
280 for (const auto CPU : CPUNames) {
281 if (CPU.ArchID == AK && CPU.Default)
287 // ======================================================= //
289 // ======================================================= //
291 static StringRef getHWDivSynonym(StringRef HWDiv) {
292 return StringSwitch<StringRef>(HWDiv)
293 .Case("thumb,arm", "arm,thumb")
297 static StringRef getFPUSynonym(StringRef FPU) {
298 return StringSwitch<StringRef>(FPU)
299 .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
300 .Case("vfp2", "vfpv2")
301 .Case("vfp3", "vfpv3")
302 .Case("vfp4", "vfpv4")
303 .Case("vfp3-d16", "vfpv3-d16")
304 .Case("vfp4-d16", "vfpv4-d16")
305 .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
306 .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
307 .Case("fp5-sp-d16", "fpv5-sp-d16")
308 .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
309 // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
310 .Case("neon-vfpv3", "neon")
314 static StringRef getArchSynonym(StringRef Arch) {
315 return StringSwitch<StringRef>(Arch)
316 .Case("v6sm", "v6s-m")
321 .Case("v7em", "v7e-m")
322 .Cases("v8", "v8a", "aarch64", "arm64", "v8-a")
323 .Case("v8.1a", "v8.1-a")
327 // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
328 // (iwmmxt|xscale)(eb)? is also permitted. If the former, return
329 // "v.+", if the latter, return unmodified string, minus 'eb'.
330 // If invalid, return empty string.
331 StringRef llvm::ARM::getCanonicalArchName(StringRef Arch) {
332 size_t offset = StringRef::npos;
334 StringRef Error = "";
336 // Begins with "arm" / "thumb", move past it.
337 if (A.startswith("arm64"))
339 else if (A.startswith("arm"))
341 else if (A.startswith("thumb"))
343 else if (A.startswith("aarch64")) {
345 // AArch64 uses "_be", not "eb" suffix.
346 if (A.find("eb") != StringRef::npos)
348 if (A.substr(offset, 3) == "_be")
352 // Ex. "armebv7", move past the "eb".
353 if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
355 // Or, if it ends with eb ("armv7eb"), chop it off.
356 else if (A.endswith("eb"))
357 A = A.substr(0, A.size() - 2);
359 if (offset != StringRef::npos)
360 A = A.substr(offset);
362 // Empty string means offset reached the end, which means it's valid.
366 // Only match non-marketing names
367 if (offset != StringRef::npos) {
368 // Must start with 'vN'.
369 if (A[0] != 'v' || !std::isdigit(A[1]))
371 // Can't have an extra 'eb'.
372 if (A.find("eb") != StringRef::npos)
376 // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
380 unsigned llvm::ARM::parseHWDiv(StringRef HWDiv) {
381 StringRef Syn = getHWDivSynonym(HWDiv);
382 for (const auto D : HWDivNames) {
386 return ARM::AEK_INVALID;
389 unsigned llvm::ARM::parseFPU(StringRef FPU) {
390 StringRef Syn = getFPUSynonym(FPU);
391 for (const auto F : FPUNames) {
395 return ARM::FK_INVALID;
398 // Allows partial match, ex. "v7a" matches "armv7a".
399 unsigned llvm::ARM::parseArch(StringRef Arch) {
400 Arch = getCanonicalArchName(Arch);
401 StringRef Syn = getArchSynonym(Arch);
402 for (const auto A : ARCHNames) {
403 if (StringRef(A.Name).endswith(Syn))
406 return ARM::AK_INVALID;
409 unsigned llvm::ARM::parseArchExt(StringRef ArchExt) {
410 for (const auto A : ARCHExtNames) {
411 if (ArchExt == A.Name)
414 return ARM::AEK_INVALID;
417 unsigned llvm::ARM::parseCPUArch(StringRef CPU) {
418 for (const auto C : CPUNames) {
422 return ARM::AK_INVALID;
425 // ARM, Thumb, AArch64
426 unsigned llvm::ARM::parseArchISA(StringRef Arch) {
427 return StringSwitch<unsigned>(Arch)
428 .StartsWith("aarch64", ARM::IK_AARCH64)
429 .StartsWith("arm64", ARM::IK_AARCH64)
430 .StartsWith("thumb", ARM::IK_THUMB)
431 .StartsWith("arm", ARM::IK_ARM)
432 .Default(ARM::EK_INVALID);
436 unsigned llvm::ARM::parseArchEndian(StringRef Arch) {
437 if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
438 Arch.startswith("aarch64_be"))
441 if (Arch.startswith("arm") || Arch.startswith("thumb")) {
442 if (Arch.endswith("eb"))
445 return ARM::EK_LITTLE;
448 if (Arch.startswith("aarch64"))
449 return ARM::EK_LITTLE;
451 return ARM::EK_INVALID;
455 unsigned llvm::ARM::parseArchProfile(StringRef Arch) {
456 Arch = getCanonicalArchName(Arch);
457 switch (parseArch(Arch)) {
460 case ARM::AK_ARMV6SM:
461 case ARM::AK_ARMV7EM:
469 case ARM::AK_ARMV8_1A:
472 return ARM::PK_INVALID;
475 // Version number (ex. v7 = 7).
476 unsigned llvm::ARM::parseArchVersion(StringRef Arch) {
477 Arch = getCanonicalArchName(Arch);
478 switch (parseArch(Arch)) {
490 case ARM::AK_ARMV5TE:
492 case ARM::AK_IWMMXT2:
495 case ARM::AK_ARMV5TEJ:
500 case ARM::AK_ARMV6T2:
502 case ARM::AK_ARMV6ZK:
504 case ARM::AK_ARMV6SM:
505 case ARM::AK_ARMV6HL:
512 case ARM::AK_ARMV7HL:
514 case ARM::AK_ARMV7EM:
518 case ARM::AK_ARMV8_1A: