1 //===-- AArch64TargetParser - Parser for AArch64 features -------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements a target parser to recognise AArch64 hardware features
10 // such as FPU/CPU/ARCH and extension names.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/Support/AArch64TargetParser.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/ADT/StringSwitch.h"
21 static unsigned checkArchVersion(llvm::StringRef Arch
) {
22 if (Arch
.size() >= 2 && Arch
[0] == 'v' && std::isdigit(Arch
[1]))
23 return (Arch
[1] - 48);
27 unsigned AArch64::getDefaultFPU(StringRef CPU
, AArch64::ArchKind AK
) {
29 return AArch64ARCHNames
[static_cast<unsigned>(AK
)].DefaultFPU
;
31 return StringSwitch
<unsigned>(CPU
)
32 #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
33 .Case(NAME, ARM::DEFAULT_FPU)
34 #include "../../include/llvm/Support/AArch64TargetParser.def"
35 .Default(ARM::FK_INVALID
);
38 unsigned AArch64::getDefaultExtensions(StringRef CPU
, AArch64::ArchKind AK
) {
40 return AArch64ARCHNames
[static_cast<unsigned>(AK
)].ArchBaseExtensions
;
42 return StringSwitch
<unsigned>(CPU
)
43 #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
44 .Case(NAME, AArch64ARCHNames[static_cast<unsigned>(ArchKind::ID)] \
45 .ArchBaseExtensions | \
47 #include "../../include/llvm/Support/AArch64TargetParser.def"
48 .Default(AArch64::AEK_INVALID
);
51 AArch64::ArchKind
AArch64::getCPUArchKind(StringRef CPU
) {
53 return ArchKind::ARMV8A
;
55 return StringSwitch
<AArch64::ArchKind
>(CPU
)
56 #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
57 .Case(NAME, ArchKind::ID)
58 #include "../../include/llvm/Support/AArch64TargetParser.def"
59 .Default(ArchKind::INVALID
);
62 bool AArch64::getExtensionFeatures(unsigned Extensions
,
63 std::vector
<StringRef
> &Features
) {
64 if (Extensions
== AArch64::AEK_INVALID
)
67 if (Extensions
& AEK_FP
)
68 Features
.push_back("+fp-armv8");
69 if (Extensions
& AEK_SIMD
)
70 Features
.push_back("+neon");
71 if (Extensions
& AEK_CRC
)
72 Features
.push_back("+crc");
73 if (Extensions
& AEK_CRYPTO
)
74 Features
.push_back("+crypto");
75 if (Extensions
& AEK_DOTPROD
)
76 Features
.push_back("+dotprod");
77 if (Extensions
& AEK_FP16FML
)
78 Features
.push_back("+fp16fml");
79 if (Extensions
& AEK_FP16
)
80 Features
.push_back("+fullfp16");
81 if (Extensions
& AEK_PROFILE
)
82 Features
.push_back("+spe");
83 if (Extensions
& AEK_RAS
)
84 Features
.push_back("+ras");
85 if (Extensions
& AEK_LSE
)
86 Features
.push_back("+lse");
87 if (Extensions
& AEK_RDM
)
88 Features
.push_back("+rdm");
89 if (Extensions
& AEK_SVE
)
90 Features
.push_back("+sve");
91 if (Extensions
& AEK_SVE2
)
92 Features
.push_back("+sve2");
93 if (Extensions
& AEK_SVE2AES
)
94 Features
.push_back("+sve2-aes");
95 if (Extensions
& AEK_SVE2SM4
)
96 Features
.push_back("+sve2-sm4");
97 if (Extensions
& AEK_SVE2SHA3
)
98 Features
.push_back("+sve2-sha3");
99 if (Extensions
& AEK_SVE2BITPERM
)
100 Features
.push_back("+sve2-bitperm");
101 if (Extensions
& AEK_RCPC
)
102 Features
.push_back("+rcpc");
107 bool AArch64::getArchFeatures(AArch64::ArchKind AK
,
108 std::vector
<StringRef
> &Features
) {
109 if (AK
== ArchKind::ARMV8_1A
)
110 Features
.push_back("+v8.1a");
111 if (AK
== ArchKind::ARMV8_2A
)
112 Features
.push_back("+v8.2a");
113 if (AK
== ArchKind::ARMV8_3A
)
114 Features
.push_back("+v8.3a");
115 if (AK
== ArchKind::ARMV8_4A
)
116 Features
.push_back("+v8.4a");
117 if (AK
== ArchKind::ARMV8_5A
)
118 Features
.push_back("+v8.5a");
120 return AK
!= ArchKind::INVALID
;
123 StringRef
AArch64::getArchName(AArch64::ArchKind AK
) {
124 return AArch64ARCHNames
[static_cast<unsigned>(AK
)].getName();
127 StringRef
AArch64::getCPUAttr(AArch64::ArchKind AK
) {
128 return AArch64ARCHNames
[static_cast<unsigned>(AK
)].getCPUAttr();
131 StringRef
AArch64::getSubArch(AArch64::ArchKind AK
) {
132 return AArch64ARCHNames
[static_cast<unsigned>(AK
)].getSubArch();
135 unsigned AArch64::getArchAttr(AArch64::ArchKind AK
) {
136 return AArch64ARCHNames
[static_cast<unsigned>(AK
)].ArchAttr
;
139 StringRef
AArch64::getArchExtName(unsigned ArchExtKind
) {
140 for (const auto &AE
: AArch64ARCHExtNames
)
141 if (ArchExtKind
== AE
.ID
)
146 StringRef
AArch64::getArchExtFeature(StringRef ArchExt
) {
147 if (ArchExt
.startswith("no")) {
148 StringRef
ArchExtBase(ArchExt
.substr(2));
149 for (const auto &AE
: AArch64ARCHExtNames
) {
150 if (AE
.NegFeature
&& ArchExtBase
== AE
.getName())
151 return StringRef(AE
.NegFeature
);
155 for (const auto &AE
: AArch64ARCHExtNames
)
156 if (AE
.Feature
&& ArchExt
== AE
.getName())
157 return StringRef(AE
.Feature
);
161 StringRef
AArch64::getDefaultCPU(StringRef Arch
) {
162 ArchKind AK
= parseArch(Arch
);
163 if (AK
== ArchKind::INVALID
)
166 // Look for multiple AKs to find the default for pair AK+Name.
167 for (const auto &CPU
: AArch64CPUNames
)
168 if (CPU
.ArchID
== AK
&& CPU
.Default
)
169 return CPU
.getName();
171 // If we can't find a default then target the architecture instead
175 void AArch64::fillValidCPUArchList(SmallVectorImpl
<StringRef
> &Values
) {
176 for (const auto &Arch
: AArch64CPUNames
) {
177 if (Arch
.ArchID
!= ArchKind::INVALID
)
178 Values
.push_back(Arch
.getName());
182 bool AArch64::isX18ReservedByDefault(const Triple
&TT
) {
183 return TT
.isAndroid() || TT
.isOSDarwin() || TT
.isOSFuchsia() ||
187 // Allows partial match, ex. "v8a" matches "armv8a".
188 AArch64::ArchKind
AArch64::parseArch(StringRef Arch
) {
189 Arch
= ARM::getCanonicalArchName(Arch
);
190 if (checkArchVersion(Arch
) < 8)
191 return ArchKind::INVALID
;
193 StringRef Syn
= ARM::getArchSynonym(Arch
);
194 for (const auto A
: AArch64ARCHNames
) {
195 if (A
.getName().endswith(Syn
))
198 return ArchKind::INVALID
;
201 AArch64::ArchExtKind
AArch64::parseArchExt(StringRef ArchExt
) {
202 for (const auto A
: AArch64ARCHExtNames
) {
203 if (ArchExt
== A
.getName())
204 return static_cast<ArchExtKind
>(A
.ID
);
206 return AArch64::AEK_INVALID
;
209 AArch64::ArchKind
AArch64::parseCPUArch(StringRef CPU
) {
210 for (const auto C
: AArch64CPUNames
) {
211 if (CPU
== C
.getName())
214 return ArchKind::INVALID
;