1e01718cdSDavid Spickett //===-- ARMTargetParser - Parser for ARM target features --------*- C++ -*-===//
2e01718cdSDavid Spickett //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e01718cdSDavid Spickett //
7e01718cdSDavid Spickett //===----------------------------------------------------------------------===//
8e01718cdSDavid Spickett //
9e01718cdSDavid Spickett // This file implements a target parser to recognise ARM hardware features
10e01718cdSDavid Spickett // such as FPU/CPU/ARCH/extensions and specific support such as HWDIV.
11e01718cdSDavid Spickett //
12e01718cdSDavid Spickett //===----------------------------------------------------------------------===//
13e01718cdSDavid Spickett
14e01718cdSDavid Spickett #include "llvm/Support/ARMTargetParser.h"
15e01718cdSDavid Spickett #include "llvm/ADT/StringSwitch.h"
16ffd9cfa7SSimon Pilgrim #include "llvm/ADT/Triple.h"
17cc3fa397SDavid Spickett #include <cctype>
18e01718cdSDavid Spickett
19e01718cdSDavid Spickett using namespace llvm;
20e01718cdSDavid Spickett
getHWDivSynonym(StringRef HWDiv)21e01718cdSDavid Spickett static StringRef getHWDivSynonym(StringRef HWDiv) {
22e01718cdSDavid Spickett return StringSwitch<StringRef>(HWDiv)
23e01718cdSDavid Spickett .Case("thumb,arm", "arm,thumb")
24e01718cdSDavid Spickett .Default(HWDiv);
25e01718cdSDavid Spickett }
26e01718cdSDavid Spickett
27e01718cdSDavid Spickett // Allows partial match, ex. "v7a" matches "armv7a".
parseArch(StringRef Arch)28e01718cdSDavid Spickett ARM::ArchKind ARM::parseArch(StringRef Arch) {
29e01718cdSDavid Spickett Arch = getCanonicalArchName(Arch);
30e01718cdSDavid Spickett StringRef Syn = getArchSynonym(Arch);
317982db5dSReid Kleckner for (const auto &A : ARCHNames) {
32e01718cdSDavid Spickett if (A.getName().endswith(Syn))
33e01718cdSDavid Spickett return A.ID;
34e01718cdSDavid Spickett }
35e01718cdSDavid Spickett return ArchKind::INVALID;
36e01718cdSDavid Spickett }
37e01718cdSDavid Spickett
38e01718cdSDavid Spickett // Version number (ex. v7 = 7).
parseArchVersion(StringRef Arch)39e01718cdSDavid Spickett unsigned ARM::parseArchVersion(StringRef Arch) {
40e01718cdSDavid Spickett Arch = getCanonicalArchName(Arch);
41e01718cdSDavid Spickett switch (parseArch(Arch)) {
42e01718cdSDavid Spickett case ArchKind::ARMV2:
43e01718cdSDavid Spickett case ArchKind::ARMV2A:
44e01718cdSDavid Spickett return 2;
45e01718cdSDavid Spickett case ArchKind::ARMV3:
46e01718cdSDavid Spickett case ArchKind::ARMV3M:
47e01718cdSDavid Spickett return 3;
48e01718cdSDavid Spickett case ArchKind::ARMV4:
49e01718cdSDavid Spickett case ArchKind::ARMV4T:
50e01718cdSDavid Spickett return 4;
51e01718cdSDavid Spickett case ArchKind::ARMV5T:
52e01718cdSDavid Spickett case ArchKind::ARMV5TE:
53e01718cdSDavid Spickett case ArchKind::IWMMXT:
54e01718cdSDavid Spickett case ArchKind::IWMMXT2:
55e01718cdSDavid Spickett case ArchKind::XSCALE:
56e01718cdSDavid Spickett case ArchKind::ARMV5TEJ:
57e01718cdSDavid Spickett return 5;
58e01718cdSDavid Spickett case ArchKind::ARMV6:
59e01718cdSDavid Spickett case ArchKind::ARMV6K:
60e01718cdSDavid Spickett case ArchKind::ARMV6T2:
61e01718cdSDavid Spickett case ArchKind::ARMV6KZ:
62e01718cdSDavid Spickett case ArchKind::ARMV6M:
63e01718cdSDavid Spickett return 6;
64e01718cdSDavid Spickett case ArchKind::ARMV7A:
65e01718cdSDavid Spickett case ArchKind::ARMV7VE:
66e01718cdSDavid Spickett case ArchKind::ARMV7R:
67e01718cdSDavid Spickett case ArchKind::ARMV7M:
68e01718cdSDavid Spickett case ArchKind::ARMV7S:
69e01718cdSDavid Spickett case ArchKind::ARMV7EM:
70e01718cdSDavid Spickett case ArchKind::ARMV7K:
71e01718cdSDavid Spickett return 7;
72e01718cdSDavid Spickett case ArchKind::ARMV8A:
73e01718cdSDavid Spickett case ArchKind::ARMV8_1A:
74e01718cdSDavid Spickett case ArchKind::ARMV8_2A:
75e01718cdSDavid Spickett case ArchKind::ARMV8_3A:
76e01718cdSDavid Spickett case ArchKind::ARMV8_4A:
77e01718cdSDavid Spickett case ArchKind::ARMV8_5A:
7871ae267dSTies Stuij case ArchKind::ARMV8_6A:
79c5046ebdSLucas Prates case ArchKind::ARMV8_7A:
80d50072f7SSimon Tatham case ArchKind::ARMV8_8A:
81e01718cdSDavid Spickett case ArchKind::ARMV8R:
82e01718cdSDavid Spickett case ArchKind::ARMV8MBaseline:
83e01718cdSDavid Spickett case ArchKind::ARMV8MMainline:
84930dee2cSSjoerd Meijer case ArchKind::ARMV8_1MMainline:
85e01718cdSDavid Spickett return 8;
863550e242SVictor Campos case ArchKind::ARMV9A:
873550e242SVictor Campos case ArchKind::ARMV9_1A:
883550e242SVictor Campos case ArchKind::ARMV9_2A:
89*cd7f621aSLucas Prates case ArchKind::ARMV9_3A:
903550e242SVictor Campos return 9;
91e01718cdSDavid Spickett case ArchKind::INVALID:
92e01718cdSDavid Spickett return 0;
93e01718cdSDavid Spickett }
94e01718cdSDavid Spickett llvm_unreachable("Unhandled architecture");
95e01718cdSDavid Spickett }
96e01718cdSDavid Spickett
97e01718cdSDavid Spickett // Profile A/R/M
parseArchProfile(StringRef Arch)98e01718cdSDavid Spickett ARM::ProfileKind ARM::parseArchProfile(StringRef Arch) {
99e01718cdSDavid Spickett Arch = getCanonicalArchName(Arch);
100e01718cdSDavid Spickett switch (parseArch(Arch)) {
101e01718cdSDavid Spickett case ArchKind::ARMV6M:
102e01718cdSDavid Spickett case ArchKind::ARMV7M:
103e01718cdSDavid Spickett case ArchKind::ARMV7EM:
104e01718cdSDavid Spickett case ArchKind::ARMV8MMainline:
105e01718cdSDavid Spickett case ArchKind::ARMV8MBaseline:
106930dee2cSSjoerd Meijer case ArchKind::ARMV8_1MMainline:
107e01718cdSDavid Spickett return ProfileKind::M;
108e01718cdSDavid Spickett case ArchKind::ARMV7R:
109e01718cdSDavid Spickett case ArchKind::ARMV8R:
110e01718cdSDavid Spickett return ProfileKind::R;
111e01718cdSDavid Spickett case ArchKind::ARMV7A:
112e01718cdSDavid Spickett case ArchKind::ARMV7VE:
113e01718cdSDavid Spickett case ArchKind::ARMV7K:
114e01718cdSDavid Spickett case ArchKind::ARMV8A:
115e01718cdSDavid Spickett case ArchKind::ARMV8_1A:
116e01718cdSDavid Spickett case ArchKind::ARMV8_2A:
117e01718cdSDavid Spickett case ArchKind::ARMV8_3A:
118e01718cdSDavid Spickett case ArchKind::ARMV8_4A:
119e01718cdSDavid Spickett case ArchKind::ARMV8_5A:
12071ae267dSTies Stuij case ArchKind::ARMV8_6A:
121c5046ebdSLucas Prates case ArchKind::ARMV8_7A:
122d50072f7SSimon Tatham case ArchKind::ARMV8_8A:
1233550e242SVictor Campos case ArchKind::ARMV9A:
1243550e242SVictor Campos case ArchKind::ARMV9_1A:
1253550e242SVictor Campos case ArchKind::ARMV9_2A:
126*cd7f621aSLucas Prates case ArchKind::ARMV9_3A:
127e01718cdSDavid Spickett return ProfileKind::A;
128e01718cdSDavid Spickett case ArchKind::ARMV2:
129e01718cdSDavid Spickett case ArchKind::ARMV2A:
130e01718cdSDavid Spickett case ArchKind::ARMV3:
131e01718cdSDavid Spickett case ArchKind::ARMV3M:
132e01718cdSDavid Spickett case ArchKind::ARMV4:
133e01718cdSDavid Spickett case ArchKind::ARMV4T:
134e01718cdSDavid Spickett case ArchKind::ARMV5T:
135e01718cdSDavid Spickett case ArchKind::ARMV5TE:
136e01718cdSDavid Spickett case ArchKind::ARMV5TEJ:
137e01718cdSDavid Spickett case ArchKind::ARMV6:
138e01718cdSDavid Spickett case ArchKind::ARMV6K:
139e01718cdSDavid Spickett case ArchKind::ARMV6T2:
140e01718cdSDavid Spickett case ArchKind::ARMV6KZ:
141e01718cdSDavid Spickett case ArchKind::ARMV7S:
142e01718cdSDavid Spickett case ArchKind::IWMMXT:
143e01718cdSDavid Spickett case ArchKind::IWMMXT2:
144e01718cdSDavid Spickett case ArchKind::XSCALE:
145e01718cdSDavid Spickett case ArchKind::INVALID:
146e01718cdSDavid Spickett return ProfileKind::INVALID;
147e01718cdSDavid Spickett }
148e01718cdSDavid Spickett llvm_unreachable("Unhandled architecture");
149e01718cdSDavid Spickett }
150e01718cdSDavid Spickett
getArchSynonym(StringRef Arch)151e01718cdSDavid Spickett StringRef ARM::getArchSynonym(StringRef Arch) {
152e01718cdSDavid Spickett return StringSwitch<StringRef>(Arch)
153e01718cdSDavid Spickett .Case("v5", "v5t")
154e01718cdSDavid Spickett .Case("v5e", "v5te")
155e01718cdSDavid Spickett .Case("v6j", "v6")
156e01718cdSDavid Spickett .Case("v6hl", "v6k")
157e01718cdSDavid Spickett .Cases("v6m", "v6sm", "v6s-m", "v6-m")
158e01718cdSDavid Spickett .Cases("v6z", "v6zk", "v6kz")
159e01718cdSDavid Spickett .Cases("v7", "v7a", "v7hl", "v7l", "v7-a")
160e01718cdSDavid Spickett .Case("v7r", "v7-r")
161e01718cdSDavid Spickett .Case("v7m", "v7-m")
162e01718cdSDavid Spickett .Case("v7em", "v7e-m")
163e01718cdSDavid Spickett .Cases("v8", "v8a", "v8l", "aarch64", "arm64", "v8-a")
164e01718cdSDavid Spickett .Case("v8.1a", "v8.1-a")
165e01718cdSDavid Spickett .Case("v8.2a", "v8.2-a")
166e01718cdSDavid Spickett .Case("v8.3a", "v8.3-a")
167e01718cdSDavid Spickett .Case("v8.4a", "v8.4-a")
168e01718cdSDavid Spickett .Case("v8.5a", "v8.5-a")
16971ae267dSTies Stuij .Case("v8.6a", "v8.6-a")
170c4d851b0SLucas Prates .Case("v8.7a", "v8.7-a")
171d50072f7SSimon Tatham .Case("v8.8a", "v8.8-a")
172e01718cdSDavid Spickett .Case("v8r", "v8-r")
1733550e242SVictor Campos .Cases("v9", "v9a", "v9-a")
1743550e242SVictor Campos .Case("v9.1a", "v9.1-a")
1753550e242SVictor Campos .Case("v9.2a", "v9.2-a")
176*cd7f621aSLucas Prates .Case("v9.3a", "v9.3-a")
177e01718cdSDavid Spickett .Case("v8m.base", "v8-m.base")
178e01718cdSDavid Spickett .Case("v8m.main", "v8-m.main")
179930dee2cSSjoerd Meijer .Case("v8.1m.main", "v8.1-m.main")
180e01718cdSDavid Spickett .Default(Arch);
181e01718cdSDavid Spickett }
182e01718cdSDavid Spickett
getFPUFeatures(unsigned FPUKind,std::vector<StringRef> & Features)183e01718cdSDavid Spickett bool ARM::getFPUFeatures(unsigned FPUKind, std::vector<StringRef> &Features) {
184e01718cdSDavid Spickett
185e01718cdSDavid Spickett if (FPUKind >= FK_LAST || FPUKind == FK_INVALID)
186e01718cdSDavid Spickett return false;
187e01718cdSDavid Spickett
1885d66f2b0SSimon Tatham static const struct FPUFeatureNameInfo {
1895d66f2b0SSimon Tatham const char *PlusName, *MinusName;
1905d66f2b0SSimon Tatham FPUVersion MinVersion;
1915d66f2b0SSimon Tatham FPURestriction MaxRestriction;
1925d66f2b0SSimon Tatham } FPUFeatureInfoList[] = {
1935d66f2b0SSimon Tatham // We have to specify the + and - versions of the name in full so
1945d66f2b0SSimon Tatham // that we can return them as static StringRefs.
1955d66f2b0SSimon Tatham //
1965d66f2b0SSimon Tatham // Also, the SubtargetFeatures ending in just "sp" are listed here
1975d66f2b0SSimon Tatham // under FPURestriction::None, which is the only FPURestriction in
1985d66f2b0SSimon Tatham // which they would be valid (since FPURestriction::SP doesn't
1995d66f2b0SSimon Tatham // exist).
200ddf5e86cSEli Friedman {"+vfp2", "-vfp2", FPUVersion::VFPV2, FPURestriction::D16},
201ddf5e86cSEli Friedman {"+vfp2sp", "-vfp2sp", FPUVersion::VFPV2, FPURestriction::SP_D16},
2025d66f2b0SSimon Tatham {"+vfp3", "-vfp3", FPUVersion::VFPV3, FPURestriction::None},
2035d66f2b0SSimon Tatham {"+vfp3d16", "-vfp3d16", FPUVersion::VFPV3, FPURestriction::D16},
2045d66f2b0SSimon Tatham {"+vfp3d16sp", "-vfp3d16sp", FPUVersion::VFPV3, FPURestriction::SP_D16},
2055d66f2b0SSimon Tatham {"+vfp3sp", "-vfp3sp", FPUVersion::VFPV3, FPURestriction::None},
2065d66f2b0SSimon Tatham {"+fp16", "-fp16", FPUVersion::VFPV3_FP16, FPURestriction::SP_D16},
2075d66f2b0SSimon Tatham {"+vfp4", "-vfp4", FPUVersion::VFPV4, FPURestriction::None},
2085d66f2b0SSimon Tatham {"+vfp4d16", "-vfp4d16", FPUVersion::VFPV4, FPURestriction::D16},
2095d66f2b0SSimon Tatham {"+vfp4d16sp", "-vfp4d16sp", FPUVersion::VFPV4, FPURestriction::SP_D16},
2105d66f2b0SSimon Tatham {"+vfp4sp", "-vfp4sp", FPUVersion::VFPV4, FPURestriction::None},
2115d66f2b0SSimon Tatham {"+fp-armv8", "-fp-armv8", FPUVersion::VFPV5, FPURestriction::None},
2125d66f2b0SSimon Tatham {"+fp-armv8d16", "-fp-armv8d16", FPUVersion::VFPV5, FPURestriction::D16},
2135d66f2b0SSimon Tatham {"+fp-armv8d16sp", "-fp-armv8d16sp", FPUVersion::VFPV5, FPURestriction::SP_D16},
2145d66f2b0SSimon Tatham {"+fp-armv8sp", "-fp-armv8sp", FPUVersion::VFPV5, FPURestriction::None},
2155d66f2b0SSimon Tatham {"+fullfp16", "-fullfp16", FPUVersion::VFPV5_FULLFP16, FPURestriction::SP_D16},
2165d66f2b0SSimon Tatham {"+fp64", "-fp64", FPUVersion::VFPV2, FPURestriction::D16},
217ddf5e86cSEli Friedman {"+d32", "-d32", FPUVersion::VFPV3, FPURestriction::None},
2185d66f2b0SSimon Tatham };
2195d66f2b0SSimon Tatham
2205d66f2b0SSimon Tatham for (const auto &Info: FPUFeatureInfoList) {
2215d66f2b0SSimon Tatham if (FPUNames[FPUKind].FPUVer >= Info.MinVersion &&
2225d66f2b0SSimon Tatham FPUNames[FPUKind].Restriction <= Info.MaxRestriction)
2235d66f2b0SSimon Tatham Features.push_back(Info.PlusName);
2245d66f2b0SSimon Tatham else
2255d66f2b0SSimon Tatham Features.push_back(Info.MinusName);
226e01718cdSDavid Spickett }
227e01718cdSDavid Spickett
2285d66f2b0SSimon Tatham static const struct NeonFeatureNameInfo {
2295d66f2b0SSimon Tatham const char *PlusName, *MinusName;
2305d66f2b0SSimon Tatham NeonSupportLevel MinSupportLevel;
2315d66f2b0SSimon Tatham } NeonFeatureInfoList[] = {
2325d66f2b0SSimon Tatham {"+neon", "-neon", NeonSupportLevel::Neon},
233b8baa2a9SDavid Candler {"+sha2", "-sha2", NeonSupportLevel::Crypto},
234b8baa2a9SDavid Candler {"+aes", "-aes", NeonSupportLevel::Crypto},
2355d66f2b0SSimon Tatham };
236760df47bSSimon Tatham
2375d66f2b0SSimon Tatham for (const auto &Info: NeonFeatureInfoList) {
2385d66f2b0SSimon Tatham if (FPUNames[FPUKind].NeonSupport >= Info.MinSupportLevel)
2395d66f2b0SSimon Tatham Features.push_back(Info.PlusName);
2405d66f2b0SSimon Tatham else
2415d66f2b0SSimon Tatham Features.push_back(Info.MinusName);
242e01718cdSDavid Spickett }
243e01718cdSDavid Spickett
244e01718cdSDavid Spickett return true;
245e01718cdSDavid Spickett }
246e01718cdSDavid Spickett
247e01718cdSDavid Spickett // Little/Big endian
parseArchEndian(StringRef Arch)248e01718cdSDavid Spickett ARM::EndianKind ARM::parseArchEndian(StringRef Arch) {
249e01718cdSDavid Spickett if (Arch.startswith("armeb") || Arch.startswith("thumbeb") ||
250e01718cdSDavid Spickett Arch.startswith("aarch64_be"))
251e01718cdSDavid Spickett return EndianKind::BIG;
252e01718cdSDavid Spickett
253e01718cdSDavid Spickett if (Arch.startswith("arm") || Arch.startswith("thumb")) {
254e01718cdSDavid Spickett if (Arch.endswith("eb"))
255e01718cdSDavid Spickett return EndianKind::BIG;
256e01718cdSDavid Spickett else
257e01718cdSDavid Spickett return EndianKind::LITTLE;
258e01718cdSDavid Spickett }
259e01718cdSDavid Spickett
260ff6875acSTim Northover if (Arch.startswith("aarch64") || Arch.startswith("aarch64_32"))
261e01718cdSDavid Spickett return EndianKind::LITTLE;
262e01718cdSDavid Spickett
263e01718cdSDavid Spickett return EndianKind::INVALID;
264e01718cdSDavid Spickett }
265e01718cdSDavid Spickett
266e01718cdSDavid Spickett // ARM, Thumb, AArch64
parseArchISA(StringRef Arch)267e01718cdSDavid Spickett ARM::ISAKind ARM::parseArchISA(StringRef Arch) {
268e01718cdSDavid Spickett return StringSwitch<ISAKind>(Arch)
269e01718cdSDavid Spickett .StartsWith("aarch64", ISAKind::AARCH64)
270e01718cdSDavid Spickett .StartsWith("arm64", ISAKind::AARCH64)
271e01718cdSDavid Spickett .StartsWith("thumb", ISAKind::THUMB)
272e01718cdSDavid Spickett .StartsWith("arm", ISAKind::ARM)
273e01718cdSDavid Spickett .Default(ISAKind::INVALID);
274e01718cdSDavid Spickett }
275e01718cdSDavid Spickett
parseFPU(StringRef FPU)276e01718cdSDavid Spickett unsigned ARM::parseFPU(StringRef FPU) {
277e01718cdSDavid Spickett StringRef Syn = getFPUSynonym(FPU);
278f16b2d83SSimon Pilgrim for (const auto &F : FPUNames) {
279e01718cdSDavid Spickett if (Syn == F.getName())
280e01718cdSDavid Spickett return F.ID;
281e01718cdSDavid Spickett }
282e01718cdSDavid Spickett return FK_INVALID;
283e01718cdSDavid Spickett }
284e01718cdSDavid Spickett
getFPUNeonSupportLevel(unsigned FPUKind)285e01718cdSDavid Spickett ARM::NeonSupportLevel ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
286e01718cdSDavid Spickett if (FPUKind >= FK_LAST)
287e01718cdSDavid Spickett return NeonSupportLevel::None;
288e01718cdSDavid Spickett return FPUNames[FPUKind].NeonSupport;
289e01718cdSDavid Spickett }
290e01718cdSDavid Spickett
291e01718cdSDavid Spickett // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
292e01718cdSDavid Spickett // (iwmmxt|xscale)(eb)? is also permitted. If the former, return
293e01718cdSDavid Spickett // "v.+", if the latter, return unmodified string, minus 'eb'.
294e01718cdSDavid Spickett // If invalid, return empty string.
getCanonicalArchName(StringRef Arch)295e01718cdSDavid Spickett StringRef ARM::getCanonicalArchName(StringRef Arch) {
296e01718cdSDavid Spickett size_t offset = StringRef::npos;
297e01718cdSDavid Spickett StringRef A = Arch;
298e01718cdSDavid Spickett StringRef Error = "";
299e01718cdSDavid Spickett
300e01718cdSDavid Spickett // Begins with "arm" / "thumb", move past it.
301ff6875acSTim Northover if (A.startswith("arm64_32"))
302ff6875acSTim Northover offset = 8;
303f77c948dSAhmed Bougacha else if (A.startswith("arm64e"))
304f77c948dSAhmed Bougacha offset = 6;
305ff6875acSTim Northover else if (A.startswith("arm64"))
306e01718cdSDavid Spickett offset = 5;
307ff6875acSTim Northover else if (A.startswith("aarch64_32"))
308ff6875acSTim Northover offset = 10;
309e01718cdSDavid Spickett else if (A.startswith("arm"))
310e01718cdSDavid Spickett offset = 3;
311e01718cdSDavid Spickett else if (A.startswith("thumb"))
312e01718cdSDavid Spickett offset = 5;
313e01718cdSDavid Spickett else if (A.startswith("aarch64")) {
314e01718cdSDavid Spickett offset = 7;
315e01718cdSDavid Spickett // AArch64 uses "_be", not "eb" suffix.
316d14d7068SKazu Hirata if (A.contains("eb"))
317e01718cdSDavid Spickett return Error;
318e01718cdSDavid Spickett if (A.substr(offset, 3) == "_be")
319e01718cdSDavid Spickett offset += 3;
320e01718cdSDavid Spickett }
321e01718cdSDavid Spickett
322e01718cdSDavid Spickett // Ex. "armebv7", move past the "eb".
323e01718cdSDavid Spickett if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
324e01718cdSDavid Spickett offset += 2;
325e01718cdSDavid Spickett // Or, if it ends with eb ("armv7eb"), chop it off.
326e01718cdSDavid Spickett else if (A.endswith("eb"))
327e01718cdSDavid Spickett A = A.substr(0, A.size() - 2);
328e01718cdSDavid Spickett // Trim the head
329e01718cdSDavid Spickett if (offset != StringRef::npos)
330e01718cdSDavid Spickett A = A.substr(offset);
331e01718cdSDavid Spickett
332e01718cdSDavid Spickett // Empty string means offset reached the end, which means it's valid.
333e01718cdSDavid Spickett if (A.empty())
334e01718cdSDavid Spickett return Arch;
335e01718cdSDavid Spickett
336e01718cdSDavid Spickett // Only match non-marketing names
337e01718cdSDavid Spickett if (offset != StringRef::npos) {
338e01718cdSDavid Spickett // Must start with 'vN'.
339e01718cdSDavid Spickett if (A.size() >= 2 && (A[0] != 'v' || !std::isdigit(A[1])))
340e01718cdSDavid Spickett return Error;
341e01718cdSDavid Spickett // Can't have an extra 'eb'.
342d14d7068SKazu Hirata if (A.contains("eb"))
343e01718cdSDavid Spickett return Error;
344e01718cdSDavid Spickett }
345e01718cdSDavid Spickett
346e01718cdSDavid Spickett // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
347e01718cdSDavid Spickett return A;
348e01718cdSDavid Spickett }
349e01718cdSDavid Spickett
getFPUSynonym(StringRef FPU)350e01718cdSDavid Spickett StringRef ARM::getFPUSynonym(StringRef FPU) {
351e01718cdSDavid Spickett return StringSwitch<StringRef>(FPU)
352e01718cdSDavid Spickett .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
353e01718cdSDavid Spickett .Case("vfp2", "vfpv2")
354e01718cdSDavid Spickett .Case("vfp3", "vfpv3")
355e01718cdSDavid Spickett .Case("vfp4", "vfpv4")
356e01718cdSDavid Spickett .Case("vfp3-d16", "vfpv3-d16")
357e01718cdSDavid Spickett .Case("vfp4-d16", "vfpv4-d16")
358e01718cdSDavid Spickett .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
359e01718cdSDavid Spickett .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
360e01718cdSDavid Spickett .Case("fp5-sp-d16", "fpv5-sp-d16")
361e01718cdSDavid Spickett .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
362e01718cdSDavid Spickett // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
363e01718cdSDavid Spickett .Case("neon-vfpv3", "neon")
364e01718cdSDavid Spickett .Default(FPU);
365e01718cdSDavid Spickett }
366e01718cdSDavid Spickett
getFPUName(unsigned FPUKind)367e01718cdSDavid Spickett StringRef ARM::getFPUName(unsigned FPUKind) {
368e01718cdSDavid Spickett if (FPUKind >= FK_LAST)
369e01718cdSDavid Spickett return StringRef();
370e01718cdSDavid Spickett return FPUNames[FPUKind].getName();
371e01718cdSDavid Spickett }
372e01718cdSDavid Spickett
getFPUVersion(unsigned FPUKind)373e01718cdSDavid Spickett ARM::FPUVersion ARM::getFPUVersion(unsigned FPUKind) {
374e01718cdSDavid Spickett if (FPUKind >= FK_LAST)
375e01718cdSDavid Spickett return FPUVersion::NONE;
376e01718cdSDavid Spickett return FPUNames[FPUKind].FPUVer;
377e01718cdSDavid Spickett }
378e01718cdSDavid Spickett
getFPURestriction(unsigned FPUKind)379e01718cdSDavid Spickett ARM::FPURestriction ARM::getFPURestriction(unsigned FPUKind) {
380e01718cdSDavid Spickett if (FPUKind >= FK_LAST)
381e01718cdSDavid Spickett return FPURestriction::None;
382e01718cdSDavid Spickett return FPUNames[FPUKind].Restriction;
383e01718cdSDavid Spickett }
384e01718cdSDavid Spickett
getDefaultFPU(StringRef CPU,ARM::ArchKind AK)385e01718cdSDavid Spickett unsigned ARM::getDefaultFPU(StringRef CPU, ARM::ArchKind AK) {
386e01718cdSDavid Spickett if (CPU == "generic")
387e01718cdSDavid Spickett return ARM::ARCHNames[static_cast<unsigned>(AK)].DefaultFPU;
388e01718cdSDavid Spickett
389e01718cdSDavid Spickett return StringSwitch<unsigned>(CPU)
390e01718cdSDavid Spickett #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
391e01718cdSDavid Spickett .Case(NAME, DEFAULT_FPU)
392e01718cdSDavid Spickett #include "llvm/Support/ARMTargetParser.def"
393e01718cdSDavid Spickett .Default(ARM::FK_INVALID);
394e01718cdSDavid Spickett }
395e01718cdSDavid Spickett
getDefaultExtensions(StringRef CPU,ARM::ArchKind AK)3967128aaceSMikhail Maltsev uint64_t ARM::getDefaultExtensions(StringRef CPU, ARM::ArchKind AK) {
397e01718cdSDavid Spickett if (CPU == "generic")
398e01718cdSDavid Spickett return ARM::ARCHNames[static_cast<unsigned>(AK)].ArchBaseExtensions;
399e01718cdSDavid Spickett
4007128aaceSMikhail Maltsev return StringSwitch<uint64_t>(CPU)
401e01718cdSDavid Spickett #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
402e01718cdSDavid Spickett .Case(NAME, \
403e01718cdSDavid Spickett ARCHNames[static_cast<unsigned>(ArchKind::ID)].ArchBaseExtensions | \
404e01718cdSDavid Spickett DEFAULT_EXT)
405e01718cdSDavid Spickett #include "llvm/Support/ARMTargetParser.def"
406e01718cdSDavid Spickett .Default(ARM::AEK_INVALID);
407e01718cdSDavid Spickett }
408e01718cdSDavid Spickett
getHWDivFeatures(uint64_t HWDivKind,std::vector<StringRef> & Features)4097128aaceSMikhail Maltsev bool ARM::getHWDivFeatures(uint64_t HWDivKind,
410e01718cdSDavid Spickett std::vector<StringRef> &Features) {
411e01718cdSDavid Spickett
412e01718cdSDavid Spickett if (HWDivKind == AEK_INVALID)
413e01718cdSDavid Spickett return false;
414e01718cdSDavid Spickett
415e01718cdSDavid Spickett if (HWDivKind & AEK_HWDIVARM)
416e01718cdSDavid Spickett Features.push_back("+hwdiv-arm");
417e01718cdSDavid Spickett else
418e01718cdSDavid Spickett Features.push_back("-hwdiv-arm");
419e01718cdSDavid Spickett
420e01718cdSDavid Spickett if (HWDivKind & AEK_HWDIVTHUMB)
421e01718cdSDavid Spickett Features.push_back("+hwdiv");
422e01718cdSDavid Spickett else
423e01718cdSDavid Spickett Features.push_back("-hwdiv");
424e01718cdSDavid Spickett
425e01718cdSDavid Spickett return true;
426e01718cdSDavid Spickett }
427e01718cdSDavid Spickett
getExtensionFeatures(uint64_t Extensions,std::vector<StringRef> & Features)4287128aaceSMikhail Maltsev bool ARM::getExtensionFeatures(uint64_t Extensions,
429e01718cdSDavid Spickett std::vector<StringRef> &Features) {
430e01718cdSDavid Spickett
431e01718cdSDavid Spickett if (Extensions == AEK_INVALID)
432e01718cdSDavid Spickett return false;
433e01718cdSDavid Spickett
434f16b2d83SSimon Pilgrim for (const auto &AE : ARCHExtNames) {
43524cacf9cSAlexandros Lamprineas if ((Extensions & AE.ID) == AE.ID && AE.Feature)
43624cacf9cSAlexandros Lamprineas Features.push_back(AE.Feature);
43724cacf9cSAlexandros Lamprineas else if (AE.NegFeature)
43824cacf9cSAlexandros Lamprineas Features.push_back(AE.NegFeature);
43924cacf9cSAlexandros Lamprineas }
440e01718cdSDavid Spickett
441e01718cdSDavid Spickett return getHWDivFeatures(Extensions, Features);
442e01718cdSDavid Spickett }
443e01718cdSDavid Spickett
getArchName(ARM::ArchKind AK)444e01718cdSDavid Spickett StringRef ARM::getArchName(ARM::ArchKind AK) {
445e01718cdSDavid Spickett return ARCHNames[static_cast<unsigned>(AK)].getName();
446e01718cdSDavid Spickett }
447e01718cdSDavid Spickett
getCPUAttr(ARM::ArchKind AK)448e01718cdSDavid Spickett StringRef ARM::getCPUAttr(ARM::ArchKind AK) {
449e01718cdSDavid Spickett return ARCHNames[static_cast<unsigned>(AK)].getCPUAttr();
450e01718cdSDavid Spickett }
451e01718cdSDavid Spickett
getSubArch(ARM::ArchKind AK)452e01718cdSDavid Spickett StringRef ARM::getSubArch(ARM::ArchKind AK) {
453e01718cdSDavid Spickett return ARCHNames[static_cast<unsigned>(AK)].getSubArch();
454e01718cdSDavid Spickett }
455e01718cdSDavid Spickett
getArchAttr(ARM::ArchKind AK)456e01718cdSDavid Spickett unsigned ARM::getArchAttr(ARM::ArchKind AK) {
457e01718cdSDavid Spickett return ARCHNames[static_cast<unsigned>(AK)].ArchAttr;
458e01718cdSDavid Spickett }
459e01718cdSDavid Spickett
getArchExtName(uint64_t ArchExtKind)4607128aaceSMikhail Maltsev StringRef ARM::getArchExtName(uint64_t ArchExtKind) {
461f16b2d83SSimon Pilgrim for (const auto &AE : ARCHExtNames) {
462e01718cdSDavid Spickett if (ArchExtKind == AE.ID)
463e01718cdSDavid Spickett return AE.getName();
464e01718cdSDavid Spickett }
465e01718cdSDavid Spickett return StringRef();
466e01718cdSDavid Spickett }
467e01718cdSDavid Spickett
stripNegationPrefix(StringRef & Name)468a1bb4fb7SSjoerd Meijer static bool stripNegationPrefix(StringRef &Name) {
469a1bb4fb7SSjoerd Meijer if (Name.startswith("no")) {
470a1bb4fb7SSjoerd Meijer Name = Name.substr(2);
471a1bb4fb7SSjoerd Meijer return true;
472a1bb4fb7SSjoerd Meijer }
473a1bb4fb7SSjoerd Meijer return false;
474a1bb4fb7SSjoerd Meijer }
475a1bb4fb7SSjoerd Meijer
getArchExtFeature(StringRef ArchExt)476e01718cdSDavid Spickett StringRef ARM::getArchExtFeature(StringRef ArchExt) {
477a1bb4fb7SSjoerd Meijer bool Negated = stripNegationPrefix(ArchExt);
478f16b2d83SSimon Pilgrim for (const auto &AE : ARCHExtNames) {
479e01718cdSDavid Spickett if (AE.Feature && ArchExt == AE.getName())
480a1bb4fb7SSjoerd Meijer return StringRef(Negated ? AE.NegFeature : AE.Feature);
481e01718cdSDavid Spickett }
482e01718cdSDavid Spickett
483e01718cdSDavid Spickett return StringRef();
484e01718cdSDavid Spickett }
485e01718cdSDavid Spickett
findDoublePrecisionFPU(unsigned InputFPUKind)486a1bb4fb7SSjoerd Meijer static unsigned findDoublePrecisionFPU(unsigned InputFPUKind) {
487a1bb4fb7SSjoerd Meijer const ARM::FPUName &InputFPU = ARM::FPUNames[InputFPUKind];
488a1bb4fb7SSjoerd Meijer
489a1bb4fb7SSjoerd Meijer // If the input FPU already supports double-precision, then there
490a1bb4fb7SSjoerd Meijer // isn't any different FPU we can return here.
491a1bb4fb7SSjoerd Meijer //
492a1bb4fb7SSjoerd Meijer // The current available FPURestriction values are None (no
493a1bb4fb7SSjoerd Meijer // restriction), D16 (only 16 d-regs) and SP_D16 (16 d-regs
494a1bb4fb7SSjoerd Meijer // and single precision only); there's no value representing
495a1bb4fb7SSjoerd Meijer // SP restriction without D16. So this test just means 'is it
496a1bb4fb7SSjoerd Meijer // SP only?'.
497a1bb4fb7SSjoerd Meijer if (InputFPU.Restriction != ARM::FPURestriction::SP_D16)
498a1bb4fb7SSjoerd Meijer return ARM::FK_INVALID;
499a1bb4fb7SSjoerd Meijer
500a1bb4fb7SSjoerd Meijer // Otherwise, look for an FPU entry with all the same fields, except
501a1bb4fb7SSjoerd Meijer // that SP_D16 has been replaced with just D16, representing adding
502a1bb4fb7SSjoerd Meijer // double precision and not changing anything else.
503a1bb4fb7SSjoerd Meijer for (const ARM::FPUName &CandidateFPU : ARM::FPUNames) {
504a1bb4fb7SSjoerd Meijer if (CandidateFPU.FPUVer == InputFPU.FPUVer &&
505a1bb4fb7SSjoerd Meijer CandidateFPU.NeonSupport == InputFPU.NeonSupport &&
506a1bb4fb7SSjoerd Meijer CandidateFPU.Restriction == ARM::FPURestriction::D16) {
507a1bb4fb7SSjoerd Meijer return CandidateFPU.ID;
508a1bb4fb7SSjoerd Meijer }
509a1bb4fb7SSjoerd Meijer }
510a1bb4fb7SSjoerd Meijer
511a1bb4fb7SSjoerd Meijer // nothing found
512a1bb4fb7SSjoerd Meijer return ARM::FK_INVALID;
513a1bb4fb7SSjoerd Meijer }
514a1bb4fb7SSjoerd Meijer
appendArchExtFeatures(StringRef CPU,ARM::ArchKind AK,StringRef ArchExt,std::vector<StringRef> & Features,unsigned & ArgFPUID)515d1a3396bSVictor Campos bool ARM::appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK,
516d1a3396bSVictor Campos StringRef ArchExt,
517d1a3396bSVictor Campos std::vector<StringRef> &Features,
518d1a3396bSVictor Campos unsigned &ArgFPUID) {
519a1bb4fb7SSjoerd Meijer
520951bb68cSAlexandros Lamprineas size_t StartingNumFeatures = Features.size();
521a1bb4fb7SSjoerd Meijer const bool Negated = stripNegationPrefix(ArchExt);
5227128aaceSMikhail Maltsev uint64_t ID = parseArchExt(ArchExt);
523951bb68cSAlexandros Lamprineas
524951bb68cSAlexandros Lamprineas if (ID == AEK_INVALID)
525951bb68cSAlexandros Lamprineas return false;
526951bb68cSAlexandros Lamprineas
527f16b2d83SSimon Pilgrim for (const auto &AE : ARCHExtNames) {
5283627c91eSMomchil Velikov if (Negated) {
5293627c91eSMomchil Velikov if ((AE.ID & ID) == ID && AE.NegFeature)
530951bb68cSAlexandros Lamprineas Features.push_back(AE.NegFeature);
5313627c91eSMomchil Velikov } else {
5323627c91eSMomchil Velikov if ((AE.ID & ID) == AE.ID && AE.Feature)
533951bb68cSAlexandros Lamprineas Features.push_back(AE.Feature);
534951bb68cSAlexandros Lamprineas }
5353627c91eSMomchil Velikov }
536a1bb4fb7SSjoerd Meijer
537a1bb4fb7SSjoerd Meijer if (CPU == "")
538a1bb4fb7SSjoerd Meijer CPU = "generic";
539a1bb4fb7SSjoerd Meijer
540a1bb4fb7SSjoerd Meijer if (ArchExt == "fp" || ArchExt == "fp.dp") {
541a1bb4fb7SSjoerd Meijer unsigned FPUKind;
542a1bb4fb7SSjoerd Meijer if (ArchExt == "fp.dp") {
543a1bb4fb7SSjoerd Meijer if (Negated) {
544a1bb4fb7SSjoerd Meijer Features.push_back("-fp64");
545a1bb4fb7SSjoerd Meijer return true;
546a1bb4fb7SSjoerd Meijer }
547a1bb4fb7SSjoerd Meijer FPUKind = findDoublePrecisionFPU(getDefaultFPU(CPU, AK));
548a1bb4fb7SSjoerd Meijer } else if (Negated) {
549a1bb4fb7SSjoerd Meijer FPUKind = ARM::FK_NONE;
550a1bb4fb7SSjoerd Meijer } else {
551a1bb4fb7SSjoerd Meijer FPUKind = getDefaultFPU(CPU, AK);
552a1bb4fb7SSjoerd Meijer }
553d1a3396bSVictor Campos ArgFPUID = FPUKind;
554a1bb4fb7SSjoerd Meijer return ARM::getFPUFeatures(FPUKind, Features);
555a1bb4fb7SSjoerd Meijer }
556951bb68cSAlexandros Lamprineas return StartingNumFeatures != Features.size();
557a1bb4fb7SSjoerd Meijer }
558a1bb4fb7SSjoerd Meijer
getDefaultCPU(StringRef Arch)559e01718cdSDavid Spickett StringRef ARM::getDefaultCPU(StringRef Arch) {
560e01718cdSDavid Spickett ArchKind AK = parseArch(Arch);
561e01718cdSDavid Spickett if (AK == ArchKind::INVALID)
562e01718cdSDavid Spickett return StringRef();
563e01718cdSDavid Spickett
564e01718cdSDavid Spickett // Look for multiple AKs to find the default for pair AK+Name.
565f16b2d83SSimon Pilgrim for (const auto &CPU : CPUNames) {
566e01718cdSDavid Spickett if (CPU.ArchID == AK && CPU.Default)
567e01718cdSDavid Spickett return CPU.getName();
568e01718cdSDavid Spickett }
569e01718cdSDavid Spickett
570e01718cdSDavid Spickett // If we can't find a default then target the architecture instead
571e01718cdSDavid Spickett return "generic";
572e01718cdSDavid Spickett }
573e01718cdSDavid Spickett
parseHWDiv(StringRef HWDiv)5747128aaceSMikhail Maltsev uint64_t ARM::parseHWDiv(StringRef HWDiv) {
575e01718cdSDavid Spickett StringRef Syn = getHWDivSynonym(HWDiv);
576f16b2d83SSimon Pilgrim for (const auto &D : HWDivNames) {
577e01718cdSDavid Spickett if (Syn == D.getName())
578e01718cdSDavid Spickett return D.ID;
579e01718cdSDavid Spickett }
580e01718cdSDavid Spickett return AEK_INVALID;
581e01718cdSDavid Spickett }
582e01718cdSDavid Spickett
parseArchExt(StringRef ArchExt)5837128aaceSMikhail Maltsev uint64_t ARM::parseArchExt(StringRef ArchExt) {
584f16b2d83SSimon Pilgrim for (const auto &A : ARCHExtNames) {
585e01718cdSDavid Spickett if (ArchExt == A.getName())
586e01718cdSDavid Spickett return A.ID;
587e01718cdSDavid Spickett }
588e01718cdSDavid Spickett return AEK_INVALID;
589e01718cdSDavid Spickett }
590e01718cdSDavid Spickett
parseCPUArch(StringRef CPU)591e01718cdSDavid Spickett ARM::ArchKind ARM::parseCPUArch(StringRef CPU) {
592f16b2d83SSimon Pilgrim for (const auto &C : CPUNames) {
593e01718cdSDavid Spickett if (CPU == C.getName())
594e01718cdSDavid Spickett return C.ArchID;
595e01718cdSDavid Spickett }
596e01718cdSDavid Spickett return ArchKind::INVALID;
597e01718cdSDavid Spickett }
598e01718cdSDavid Spickett
fillValidCPUArchList(SmallVectorImpl<StringRef> & Values)599e01718cdSDavid Spickett void ARM::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
600e01718cdSDavid Spickett for (const CpuNames<ArchKind> &Arch : CPUNames) {
601e01718cdSDavid Spickett if (Arch.ArchID != ArchKind::INVALID)
602e01718cdSDavid Spickett Values.push_back(Arch.getName());
603e01718cdSDavid Spickett }
604e01718cdSDavid Spickett }
605e01718cdSDavid Spickett
computeDefaultTargetABI(const Triple & TT,StringRef CPU)606e01718cdSDavid Spickett StringRef ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) {
607e01718cdSDavid Spickett StringRef ArchName =
608e01718cdSDavid Spickett CPU.empty() ? TT.getArchName() : getArchName(parseCPUArch(CPU));
609e01718cdSDavid Spickett
610e01718cdSDavid Spickett if (TT.isOSBinFormatMachO()) {
611e01718cdSDavid Spickett if (TT.getEnvironment() == Triple::EABI ||
612e01718cdSDavid Spickett TT.getOS() == Triple::UnknownOS ||
613e01718cdSDavid Spickett parseArchProfile(ArchName) == ProfileKind::M)
614e01718cdSDavid Spickett return "aapcs";
615e01718cdSDavid Spickett if (TT.isWatchABI())
616e01718cdSDavid Spickett return "aapcs16";
617e01718cdSDavid Spickett return "apcs-gnu";
618e01718cdSDavid Spickett } else if (TT.isOSWindows())
619e01718cdSDavid Spickett // FIXME: this is invalid for WindowsCE.
620e01718cdSDavid Spickett return "aapcs";
621e01718cdSDavid Spickett
622e01718cdSDavid Spickett // Select the default based on the platform.
623e01718cdSDavid Spickett switch (TT.getEnvironment()) {
624e01718cdSDavid Spickett case Triple::Android:
625e01718cdSDavid Spickett case Triple::GNUEABI:
626e01718cdSDavid Spickett case Triple::GNUEABIHF:
627e01718cdSDavid Spickett case Triple::MuslEABI:
628e01718cdSDavid Spickett case Triple::MuslEABIHF:
629e01718cdSDavid Spickett return "aapcs-linux";
630e01718cdSDavid Spickett case Triple::EABIHF:
631e01718cdSDavid Spickett case Triple::EABI:
632e01718cdSDavid Spickett return "aapcs";
633e01718cdSDavid Spickett default:
634e01718cdSDavid Spickett if (TT.isOSNetBSD())
635e01718cdSDavid Spickett return "apcs-gnu";
636e01718cdSDavid Spickett if (TT.isOSOpenBSD())
637e01718cdSDavid Spickett return "aapcs-linux";
638e01718cdSDavid Spickett return "aapcs";
639e01718cdSDavid Spickett }
640e01718cdSDavid Spickett }
641