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_RCPC
)
92 Features
.push_back("+rcpc");
97 bool AArch64::getArchFeatures(AArch64::ArchKind AK
,
98 std::vector
<StringRef
> &Features
) {
99 if (AK
== ArchKind::ARMV8_1A
)
100 Features
.push_back("+v8.1a");
101 if (AK
== ArchKind::ARMV8_2A
)
102 Features
.push_back("+v8.2a");
103 if (AK
== ArchKind::ARMV8_3A
)
104 Features
.push_back("+v8.3a");
105 if (AK
== ArchKind::ARMV8_4A
)
106 Features
.push_back("+v8.4a");
107 if (AK
== ArchKind::ARMV8_5A
)
108 Features
.push_back("+v8.5a");
110 return AK
!= ArchKind::INVALID
;
113 StringRef
AArch64::getArchName(AArch64::ArchKind AK
) {
114 return AArch64ARCHNames
[static_cast<unsigned>(AK
)].getName();
117 StringRef
AArch64::getCPUAttr(AArch64::ArchKind AK
) {
118 return AArch64ARCHNames
[static_cast<unsigned>(AK
)].getCPUAttr();
121 StringRef
AArch64::getSubArch(AArch64::ArchKind AK
) {
122 return AArch64ARCHNames
[static_cast<unsigned>(AK
)].getSubArch();
125 unsigned AArch64::getArchAttr(AArch64::ArchKind AK
) {
126 return AArch64ARCHNames
[static_cast<unsigned>(AK
)].ArchAttr
;
129 StringRef
AArch64::getArchExtName(unsigned ArchExtKind
) {
130 for (const auto &AE
: AArch64ARCHExtNames
)
131 if (ArchExtKind
== AE
.ID
)
136 StringRef
AArch64::getArchExtFeature(StringRef ArchExt
) {
137 if (ArchExt
.startswith("no")) {
138 StringRef
ArchExtBase(ArchExt
.substr(2));
139 for (const auto &AE
: AArch64ARCHExtNames
) {
140 if (AE
.NegFeature
&& ArchExtBase
== AE
.getName())
141 return StringRef(AE
.NegFeature
);
145 for (const auto &AE
: AArch64ARCHExtNames
)
146 if (AE
.Feature
&& ArchExt
== AE
.getName())
147 return StringRef(AE
.Feature
);
151 StringRef
AArch64::getDefaultCPU(StringRef Arch
) {
152 ArchKind AK
= parseArch(Arch
);
153 if (AK
== ArchKind::INVALID
)
156 // Look for multiple AKs to find the default for pair AK+Name.
157 for (const auto &CPU
: AArch64CPUNames
)
158 if (CPU
.ArchID
== AK
&& CPU
.Default
)
159 return CPU
.getName();
161 // If we can't find a default then target the architecture instead
165 void AArch64::fillValidCPUArchList(SmallVectorImpl
<StringRef
> &Values
) {
166 for (const auto &Arch
: AArch64CPUNames
) {
167 if (Arch
.ArchID
!= ArchKind::INVALID
)
168 Values
.push_back(Arch
.getName());
172 bool AArch64::isX18ReservedByDefault(const Triple
&TT
) {
173 return TT
.isAndroid() || TT
.isOSDarwin() || TT
.isOSFuchsia() ||
177 // Allows partial match, ex. "v8a" matches "armv8a".
178 AArch64::ArchKind
AArch64::parseArch(StringRef Arch
) {
179 Arch
= ARM::getCanonicalArchName(Arch
);
180 if (checkArchVersion(Arch
) < 8)
181 return ArchKind::INVALID
;
183 StringRef Syn
= ARM::getArchSynonym(Arch
);
184 for (const auto A
: AArch64ARCHNames
) {
185 if (A
.getName().endswith(Syn
))
188 return ArchKind::INVALID
;
191 AArch64::ArchExtKind
AArch64::parseArchExt(StringRef ArchExt
) {
192 for (const auto A
: AArch64ARCHExtNames
) {
193 if (ArchExt
== A
.getName())
194 return static_cast<ArchExtKind
>(A
.ID
);
196 return AArch64::AEK_INVALID
;
199 AArch64::ArchKind
AArch64::parseCPUArch(StringRef CPU
) {
200 for (const auto C
: AArch64CPUNames
) {
201 if (CPU
== C
.getName())
204 return ArchKind::INVALID
;