AArch64TargetParser.cpp revision 343171
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
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}
207