/src/keystone/llvm/lib/Support/TargetParser.cpp
Line | Count | Source |
1 | | //===-- TargetParser - Parser for target 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 hardware features such as |
11 | | // FPU/CPU/ARCH names as well as specific support such as HDIV, etc. |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #include "llvm/Support/ARMBuildAttributes.h" |
16 | | #include "llvm/Support/TargetParser.h" |
17 | | #include "llvm/ADT/StringExtras.h" |
18 | | #include "llvm/ADT/StringSwitch.h" |
19 | | #include "llvm/ADT/Twine.h" |
20 | | #include <cctype> |
21 | | |
22 | | using namespace llvm_ks; |
23 | | using namespace ARM; |
24 | | |
25 | | namespace { |
26 | | |
27 | | // List of canonical FPU names (use getFPUSynonym) and which architectural |
28 | | // features they correspond to (use getFPUFeatures). |
29 | | // FIXME: TableGen this. |
30 | | // The entries must appear in the order listed in ARM::FPUKind for correct indexing |
31 | | static const struct { |
32 | | const char *NameCStr; |
33 | | size_t NameLength; |
34 | | ARM::FPUKind ID; |
35 | | ARM::FPUVersion FPUVersion; |
36 | | ARM::NeonSupportLevel NeonSupport; |
37 | | ARM::FPURestriction Restriction; |
38 | | |
39 | 515k | StringRef getName() const { return StringRef(NameCStr, NameLength); } |
40 | | } FPUNames[] = { |
41 | | #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \ |
42 | | { NAME, sizeof(NAME) - 1, KIND, VERSION, NEON_SUPPORT, RESTRICTION }, |
43 | | #include "llvm/Support/ARMTargetParser.def" |
44 | | }; |
45 | | |
46 | | // List of canonical arch names (use getArchSynonym). |
47 | | // This table also provides the build attribute fields for CPU arch |
48 | | // and Arch ID, according to the Addenda to the ARM ABI, chapters |
49 | | // 2.4 and 2.3.5.2 respectively. |
50 | | // FIXME: SubArch values were simplified to fit into the expectations |
51 | | // of the triples and are not conforming with their official names. |
52 | | // Check to see if the expectation should be changed. |
53 | | // FIXME: TableGen this. |
54 | | static const struct { |
55 | | const char *NameCStr; |
56 | | size_t NameLength; |
57 | | const char *CPUAttrCStr; |
58 | | size_t CPUAttrLength; |
59 | | const char *SubArchCStr; |
60 | | size_t SubArchLength; |
61 | | unsigned DefaultFPU; |
62 | | unsigned ArchBaseExtensions; |
63 | | ARM::ArchKind ID; |
64 | | ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes. |
65 | | |
66 | 47.4M | StringRef getName() const { return StringRef(NameCStr, NameLength); } |
67 | | |
68 | | // CPU class in build attributes. |
69 | 0 | StringRef getCPUAttr() const { return StringRef(CPUAttrCStr, CPUAttrLength); } |
70 | | |
71 | | // Sub-Arch name. |
72 | 0 | StringRef getSubArch() const { return StringRef(SubArchCStr, SubArchLength); } |
73 | | } ARCHNames[] = { |
74 | | #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) \ |
75 | | {NAME, sizeof(NAME) - 1, CPU_ATTR, sizeof(CPU_ATTR) - 1, SUB_ARCH, \ |
76 | | sizeof(SUB_ARCH) - 1, ARCH_FPU, ARCH_BASE_EXT, ID, ARCH_ATTR}, |
77 | | #include "llvm/Support/ARMTargetParser.def" |
78 | | }; |
79 | | |
80 | | // List of Arch Extension names. |
81 | | // FIXME: TableGen this. |
82 | | static const struct { |
83 | | const char *NameCStr; |
84 | | size_t NameLength; |
85 | | unsigned ID; |
86 | | const char *Feature; |
87 | | const char *NegFeature; |
88 | | |
89 | 36.1k | StringRef getName() const { return StringRef(NameCStr, NameLength); } |
90 | | } ARCHExtNames[] = { |
91 | | #define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) \ |
92 | | { NAME, sizeof(NAME) - 1, ID, FEATURE, NEGFEATURE }, |
93 | | #include "llvm/Support/ARMTargetParser.def" |
94 | | }; |
95 | | |
96 | | // List of HWDiv names (use getHWDivSynonym) and which architectural |
97 | | // features they correspond to (use getHWDivFeatures). |
98 | | // FIXME: TableGen this. |
99 | | static const struct { |
100 | | const char *NameCStr; |
101 | | size_t NameLength; |
102 | | unsigned ID; |
103 | | |
104 | 0 | StringRef getName() const { return StringRef(NameCStr, NameLength); } |
105 | | } HWDivNames[] = { |
106 | | #define ARM_HW_DIV_NAME(NAME, ID) { NAME, sizeof(NAME) - 1, ID }, |
107 | | #include "llvm/Support/ARMTargetParser.def" |
108 | | }; |
109 | | |
110 | | // List of CPU names and their arches. |
111 | | // The same CPU can have multiple arches and can be default on multiple arches. |
112 | | // When finding the Arch for a CPU, first-found prevails. Sort them accordingly. |
113 | | // When this becomes table-generated, we'd probably need two tables. |
114 | | // FIXME: TableGen this. |
115 | | static const struct { |
116 | | const char *NameCStr; |
117 | | size_t NameLength; |
118 | | ARM::ArchKind ArchID; |
119 | | bool Default; // is $Name the default CPU for $ArchID ? |
120 | | unsigned DefaultExtensions; |
121 | | |
122 | 0 | StringRef getName() const { return StringRef(NameCStr, NameLength); } |
123 | | } CPUNames[] = { |
124 | | #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ |
125 | | { NAME, sizeof(NAME) - 1, ID, IS_DEFAULT, DEFAULT_EXT }, |
126 | | #include "llvm/Support/ARMTargetParser.def" |
127 | | }; |
128 | | |
129 | | } // namespace |
130 | | |
131 | | // ======================================================= // |
132 | | // Information by ID |
133 | | // ======================================================= // |
134 | | |
135 | 0 | StringRef llvm_ks::ARM::getFPUName(unsigned FPUKind) { |
136 | 0 | if (FPUKind >= ARM::FK_LAST) |
137 | 0 | return StringRef(); |
138 | 0 | return FPUNames[FPUKind].getName(); |
139 | 0 | } |
140 | | |
141 | 0 | unsigned llvm_ks::ARM::getFPUVersion(unsigned FPUKind) { |
142 | 0 | if (FPUKind >= ARM::FK_LAST) |
143 | 0 | return 0; |
144 | 0 | return FPUNames[FPUKind].FPUVersion; |
145 | 0 | } |
146 | | |
147 | 0 | unsigned llvm_ks::ARM::getFPUNeonSupportLevel(unsigned FPUKind) { |
148 | 0 | if (FPUKind >= ARM::FK_LAST) |
149 | 0 | return 0; |
150 | 0 | return FPUNames[FPUKind].NeonSupport; |
151 | 0 | } |
152 | | |
153 | 0 | unsigned llvm_ks::ARM::getFPURestriction(unsigned FPUKind) { |
154 | 0 | if (FPUKind >= ARM::FK_LAST) |
155 | 0 | return 0; |
156 | 0 | return FPUNames[FPUKind].Restriction; |
157 | 0 | } |
158 | | |
159 | 0 | unsigned llvm_ks::ARM::getDefaultFPU(StringRef CPU, unsigned ArchKind) { |
160 | 0 | if (CPU == "generic") |
161 | 0 | return ARCHNames[ArchKind].DefaultFPU; |
162 | | |
163 | 0 | return StringSwitch<unsigned>(CPU) |
164 | 0 | #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ |
165 | 0 | .Case(NAME, DEFAULT_FPU) |
166 | 0 | #include "llvm/Support/ARMTargetParser.def" |
167 | 0 | .Default(ARM::FK_INVALID); |
168 | 0 | } |
169 | | |
170 | 0 | unsigned llvm_ks::ARM::getDefaultExtensions(StringRef CPU, unsigned ArchKind) { |
171 | 0 | if (CPU == "generic") |
172 | 0 | return ARCHNames[ArchKind].ArchBaseExtensions; |
173 | | |
174 | 0 | return StringSwitch<unsigned>(CPU) |
175 | 0 | #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \ |
176 | 0 | .Case(NAME, ARCHNames[ID].ArchBaseExtensions | DEFAULT_EXT) |
177 | 0 | #include "llvm/Support/ARMTargetParser.def" |
178 | 0 | .Default(ARM::AEK_INVALID); |
179 | 0 | } |
180 | | |
181 | | bool llvm_ks::ARM::getHWDivFeatures(unsigned HWDivKind, |
182 | 0 | std::vector<const char *> &Features) { |
183 | |
|
184 | 0 | if (HWDivKind == ARM::AEK_INVALID) |
185 | 0 | return false; |
186 | | |
187 | 0 | if (HWDivKind & ARM::AEK_HWDIVARM) |
188 | 0 | Features.push_back("+hwdiv-arm"); |
189 | 0 | else |
190 | 0 | Features.push_back("-hwdiv-arm"); |
191 | |
|
192 | 0 | if (HWDivKind & ARM::AEK_HWDIV) |
193 | 0 | Features.push_back("+hwdiv"); |
194 | 0 | else |
195 | 0 | Features.push_back("-hwdiv"); |
196 | |
|
197 | 0 | return true; |
198 | 0 | } |
199 | | |
200 | | bool llvm_ks::ARM::getExtensionFeatures(unsigned Extensions, |
201 | 0 | std::vector<const char *> &Features) { |
202 | |
|
203 | 0 | if (Extensions == ARM::AEK_INVALID) |
204 | 0 | return false; |
205 | | |
206 | 0 | if (Extensions & ARM::AEK_CRC) |
207 | 0 | Features.push_back("+crc"); |
208 | 0 | else |
209 | 0 | Features.push_back("-crc"); |
210 | |
|
211 | 0 | if (Extensions & ARM::AEK_DSP) |
212 | 0 | Features.push_back("+dsp"); |
213 | 0 | else |
214 | 0 | Features.push_back("-dsp"); |
215 | |
|
216 | 0 | return getHWDivFeatures(Extensions, Features); |
217 | 0 | } |
218 | | |
219 | | bool llvm_ks::ARM::getFPUFeatures(unsigned FPUKind, |
220 | 37.6k | std::vector<const char *> &Features) { |
221 | | |
222 | 37.6k | if (FPUKind >= ARM::FK_LAST || FPUKind == ARM::FK_INVALID) |
223 | 19.6k | return false; |
224 | | |
225 | | // fp-only-sp and d16 subtarget features are independent of each other, so we |
226 | | // must enable/disable both. |
227 | 18.0k | switch (FPUNames[FPUKind].Restriction) { |
228 | 262 | case ARM::FR_SP_D16: |
229 | 262 | Features.push_back("+fp-only-sp"); |
230 | 262 | Features.push_back("+d16"); |
231 | 262 | break; |
232 | 696 | case ARM::FR_D16: |
233 | 696 | Features.push_back("-fp-only-sp"); |
234 | 696 | Features.push_back("+d16"); |
235 | 696 | break; |
236 | 17.0k | case ARM::FR_None: |
237 | 17.0k | Features.push_back("-fp-only-sp"); |
238 | 17.0k | Features.push_back("-d16"); |
239 | 17.0k | break; |
240 | 18.0k | } |
241 | | |
242 | | // FPU version subtarget features are inclusive of lower-numbered ones, so |
243 | | // enable the one corresponding to this version and disable all that are |
244 | | // higher. We also have to make sure to disable fp16 when vfp4 is disabled, |
245 | | // as +vfp4 implies +fp16 but -vfp4 does not imply -fp16. |
246 | 18.0k | switch (FPUNames[FPUKind].FPUVersion) { |
247 | 243 | case ARM::FV_VFPV5: |
248 | 243 | Features.push_back("+fp-armv8"); |
249 | 243 | break; |
250 | 985 | case ARM::FV_VFPV4: |
251 | 985 | Features.push_back("+vfp4"); |
252 | 985 | Features.push_back("-fp-armv8"); |
253 | 985 | break; |
254 | 20 | case ARM::FV_VFPV3_FP16: |
255 | 20 | Features.push_back("+vfp3"); |
256 | 20 | Features.push_back("+fp16"); |
257 | 20 | Features.push_back("-vfp4"); |
258 | 20 | Features.push_back("-fp-armv8"); |
259 | 20 | break; |
260 | 1.85k | case ARM::FV_VFPV3: |
261 | 1.85k | Features.push_back("+vfp3"); |
262 | 1.85k | Features.push_back("-fp16"); |
263 | 1.85k | Features.push_back("-vfp4"); |
264 | 1.85k | Features.push_back("-fp-armv8"); |
265 | 1.85k | break; |
266 | 14.8k | case ARM::FV_VFPV2: |
267 | 14.8k | Features.push_back("+vfp2"); |
268 | 14.8k | Features.push_back("-vfp3"); |
269 | 14.8k | Features.push_back("-fp16"); |
270 | 14.8k | Features.push_back("-vfp4"); |
271 | 14.8k | Features.push_back("-fp-armv8"); |
272 | 14.8k | break; |
273 | 102 | case ARM::FV_NONE: |
274 | 102 | Features.push_back("-vfp2"); |
275 | 102 | Features.push_back("-vfp3"); |
276 | 102 | Features.push_back("-fp16"); |
277 | 102 | Features.push_back("-vfp4"); |
278 | 102 | Features.push_back("-fp-armv8"); |
279 | 102 | break; |
280 | 18.0k | } |
281 | | |
282 | | // crypto includes neon, so we handle this similarly to FPU version. |
283 | 18.0k | switch (FPUNames[FPUKind].NeonSupport) { |
284 | 0 | case ARM::NS_Crypto: |
285 | 0 | Features.push_back("+neon"); |
286 | 0 | Features.push_back("+crypto"); |
287 | 0 | break; |
288 | 67 | case ARM::NS_Neon: |
289 | 67 | Features.push_back("+neon"); |
290 | 67 | Features.push_back("-crypto"); |
291 | 67 | break; |
292 | 17.9k | case ARM::NS_None: |
293 | 17.9k | Features.push_back("-neon"); |
294 | 17.9k | Features.push_back("-crypto"); |
295 | 17.9k | break; |
296 | 18.0k | } |
297 | | |
298 | 18.0k | return true; |
299 | 18.0k | } |
300 | | |
301 | 188k | StringRef llvm_ks::ARM::getArchName(unsigned ArchKind) { |
302 | 188k | if (ArchKind >= ARM::AK_LAST) |
303 | 0 | return StringRef(); |
304 | 188k | return ARCHNames[ArchKind].getName(); |
305 | 188k | } |
306 | | |
307 | 0 | StringRef llvm_ks::ARM::getCPUAttr(unsigned ArchKind) { |
308 | 0 | if (ArchKind >= ARM::AK_LAST) |
309 | 0 | return StringRef(); |
310 | 0 | return ARCHNames[ArchKind].getCPUAttr(); |
311 | 0 | } |
312 | | |
313 | 0 | StringRef llvm_ks::ARM::getSubArch(unsigned ArchKind) { |
314 | 0 | if (ArchKind >= ARM::AK_LAST) |
315 | 0 | return StringRef(); |
316 | 0 | return ARCHNames[ArchKind].getSubArch(); |
317 | 0 | } |
318 | | |
319 | 0 | unsigned llvm_ks::ARM::getArchAttr(unsigned ArchKind) { |
320 | 0 | if (ArchKind >= ARM::AK_LAST) |
321 | 0 | return ARMBuildAttrs::CPUArch::Pre_v4; |
322 | 0 | return ARCHNames[ArchKind].ArchAttr; |
323 | 0 | } |
324 | | |
325 | 0 | StringRef llvm_ks::ARM::getArchExtName(unsigned ArchExtKind) { |
326 | 0 | for (const auto AE : ARCHExtNames) { |
327 | 0 | if (ArchExtKind == AE.ID) |
328 | 0 | return AE.getName(); |
329 | 0 | } |
330 | 0 | return StringRef(); |
331 | 0 | } |
332 | | |
333 | 0 | const char *llvm_ks::ARM::getArchExtFeature(StringRef ArchExt) { |
334 | 0 | if (ArchExt.startswith("no")) { |
335 | 0 | StringRef ArchExtBase(ArchExt.substr(2)); |
336 | 0 | for (const auto AE : ARCHExtNames) { |
337 | 0 | if (AE.NegFeature && ArchExtBase == AE.getName()) |
338 | 0 | return AE.NegFeature; |
339 | 0 | } |
340 | 0 | } |
341 | 0 | for (const auto AE : ARCHExtNames) { |
342 | 0 | if (AE.Feature && ArchExt == AE.getName()) |
343 | 0 | return AE.Feature; |
344 | 0 | } |
345 | | |
346 | 0 | return nullptr; |
347 | 0 | } |
348 | | |
349 | 0 | StringRef llvm_ks::ARM::getHWDivName(unsigned HWDivKind) { |
350 | 0 | for (const auto D : HWDivNames) { |
351 | 0 | if (HWDivKind == D.ID) |
352 | 0 | return D.getName(); |
353 | 0 | } |
354 | 0 | return StringRef(); |
355 | 0 | } |
356 | | |
357 | 0 | StringRef llvm_ks::ARM::getDefaultCPU(StringRef Arch) { |
358 | 0 | unsigned AK = parseArch(Arch); |
359 | 0 | if (AK == ARM::AK_INVALID) |
360 | 0 | return StringRef(); |
361 | | |
362 | | // Look for multiple AKs to find the default for pair AK+Name. |
363 | 0 | for (const auto CPU : CPUNames) { |
364 | 0 | if (CPU.ArchID == AK && CPU.Default) |
365 | 0 | return CPU.getName(); |
366 | 0 | } |
367 | | |
368 | | // If we can't find a default then target the architecture instead |
369 | 0 | return "generic"; |
370 | 0 | } |
371 | | |
372 | | // ======================================================= // |
373 | | // Parsers |
374 | | // ======================================================= // |
375 | | |
376 | 0 | static StringRef getHWDivSynonym(StringRef HWDiv) { |
377 | 0 | return StringSwitch<StringRef>(HWDiv) |
378 | 0 | .Case("thumb,arm", "arm,thumb") |
379 | 0 | .Default(HWDiv); |
380 | 0 | } |
381 | | |
382 | 37.6k | static StringRef getFPUSynonym(StringRef FPU) { |
383 | 37.6k | return StringSwitch<StringRef>(FPU) |
384 | 37.6k | .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported |
385 | 37.6k | .Case("vfp2", "vfpv2") |
386 | 37.6k | .Case("vfp3", "vfpv3") |
387 | 37.6k | .Case("vfp4", "vfpv4") |
388 | 37.6k | .Case("vfp3-d16", "vfpv3-d16") |
389 | 37.6k | .Case("vfp4-d16", "vfpv4-d16") |
390 | 37.6k | .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16") |
391 | 37.6k | .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16") |
392 | 37.6k | .Case("fp5-sp-d16", "fpv5-sp-d16") |
393 | 37.6k | .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16") |
394 | | // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3. |
395 | 37.6k | .Case("neon-vfpv3", "neon") |
396 | 37.6k | .Default(FPU); |
397 | 37.6k | } |
398 | | |
399 | 2.38M | static StringRef getArchSynonym(StringRef Arch) { |
400 | 2.38M | return StringSwitch<StringRef>(Arch) |
401 | 2.38M | .Case("v5", "v5t") |
402 | 2.38M | .Case("v5e", "v5te") |
403 | 2.38M | .Case("v6j", "v6") |
404 | 2.38M | .Case("v6hl", "v6k") |
405 | 2.38M | .Cases("v6m", "v6sm", "v6s-m", "v6-m") |
406 | 2.38M | .Cases("v6z", "v6zk", "v6kz") |
407 | 2.38M | .Cases("v7", "v7a", "v7hl", "v7l", "v7-a") |
408 | 2.38M | .Case("v7r", "v7-r") |
409 | 2.38M | .Case("v7m", "v7-m") |
410 | 2.38M | .Case("v7em", "v7e-m") |
411 | 2.38M | .Cases("v8", "v8a", "aarch64", "arm64", "v8-a") |
412 | 2.38M | .Case("v8.1a", "v8.1-a") |
413 | 2.38M | .Case("v8.2a", "v8.2-a") |
414 | 2.38M | .Case("v8m.base", "v8-m.base") |
415 | 2.38M | .Case("v8m.main", "v8-m.main") |
416 | 2.38M | .Default(Arch); |
417 | 2.38M | } |
418 | | |
419 | | // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but |
420 | | // (iwmmxt|xscale)(eb)? is also permitted. If the former, return |
421 | | // "v.+", if the latter, return unmodified string, minus 'eb'. |
422 | | // If invalid, return empty string. |
423 | 5.04M | StringRef llvm_ks::ARM::getCanonicalArchName(StringRef Arch) { |
424 | 5.04M | size_t offset = StringRef::npos; |
425 | 5.04M | StringRef A = Arch; |
426 | 5.04M | StringRef Error = ""; |
427 | | |
428 | | // Begins with "arm" / "thumb", move past it. |
429 | 5.04M | if (A.startswith("arm64")) |
430 | 70 | offset = 5; |
431 | 5.04M | else if (A.startswith("arm")) |
432 | 544k | offset = 3; |
433 | 4.50M | else if (A.startswith("thumb")) |
434 | 591k | offset = 5; |
435 | 3.91M | else if (A.startswith("aarch64")) { |
436 | 26.3k | offset = 7; |
437 | | // AArch64 uses "_be", not "eb" suffix. |
438 | 26.3k | if (A.find("eb") != StringRef::npos) |
439 | 132 | return Error; |
440 | 26.2k | if (A.substr(offset, 3) == "_be") |
441 | 14 | offset += 3; |
442 | 26.2k | } |
443 | | |
444 | | // Ex. "armebv7", move past the "eb". |
445 | 5.04M | if (offset != StringRef::npos && A.substr(offset, 2) == "eb") |
446 | 275k | offset += 2; |
447 | | // Or, if it ends with eb ("armv7eb"), chop it off. |
448 | 4.77M | else if (A.endswith("eb")) |
449 | 199k | A = A.substr(0, A.size() - 2); |
450 | | // Trim the head |
451 | 5.04M | if (offset != StringRef::npos) |
452 | 1.16M | A = A.substr(offset); |
453 | | |
454 | | // Empty string means offset reached the end, which means it's valid. |
455 | 5.04M | if (A.empty()) |
456 | 31.4k | return Arch; |
457 | | |
458 | | // Only match non-marketing names |
459 | 5.01M | if (offset != StringRef::npos) { |
460 | | // Must start with 'vN'. |
461 | 1.13M | if (A[0] != 'v' || !std::isdigit(A[1])) |
462 | 10.5k | return Error; |
463 | | // Can't have an extra 'eb'. |
464 | 1.12M | if (A.find("eb") != StringRef::npos) |
465 | 687 | return Error; |
466 | 1.12M | } |
467 | | |
468 | | // Arch will either be a 'v' name (v7a) or a marketing name (xscale). |
469 | 5.00M | return A; |
470 | 5.01M | } |
471 | | |
472 | 0 | unsigned llvm_ks::ARM::parseHWDiv(StringRef HWDiv) { |
473 | 0 | StringRef Syn = getHWDivSynonym(HWDiv); |
474 | 0 | for (const auto D : HWDivNames) { |
475 | 0 | if (Syn == D.getName()) |
476 | 0 | return D.ID; |
477 | 0 | } |
478 | 0 | return ARM::AEK_INVALID; |
479 | 0 | } |
480 | | |
481 | 37.6k | unsigned llvm_ks::ARM::parseFPU(StringRef FPU) { |
482 | 37.6k | StringRef Syn = getFPUSynonym(FPU); |
483 | 515k | for (const auto F : FPUNames) { |
484 | 515k | if (Syn == F.getName()) |
485 | 18.1k | return F.ID; |
486 | 515k | } |
487 | 19.5k | return ARM::FK_INVALID; |
488 | 37.6k | } |
489 | | |
490 | | // Allows partial match, ex. "v7a" matches "armv7a". |
491 | 2.38M | unsigned llvm_ks::ARM::parseArch(StringRef Arch) { |
492 | 2.38M | Arch = getCanonicalArchName(Arch); |
493 | 2.38M | StringRef Syn = getArchSynonym(Arch); |
494 | 47.2M | for (const auto A : ARCHNames) { |
495 | 47.2M | if (A.getName().endswith(Syn)) |
496 | 1.77M | return A.ID; |
497 | 47.2M | } |
498 | 619k | return ARM::AK_INVALID; |
499 | 2.38M | } |
500 | | |
501 | 3.62k | unsigned llvm_ks::ARM::parseArchExt(StringRef ArchExt) { |
502 | 36.1k | for (const auto A : ARCHExtNames) { |
503 | 36.1k | if (ArchExt == A.getName()) |
504 | 2.83k | return A.ID; |
505 | 36.1k | } |
506 | 789 | return ARM::AEK_INVALID; |
507 | 3.62k | } |
508 | | |
509 | 0 | unsigned llvm_ks::ARM::parseCPUArch(StringRef CPU) { |
510 | 0 | for (const auto C : CPUNames) { |
511 | 0 | if (CPU == C.getName()) |
512 | 0 | return C.ArchID; |
513 | 0 | } |
514 | 0 | return ARM::AK_INVALID; |
515 | 0 | } |
516 | | |
517 | | // ARM, Thumb, AArch64 |
518 | 535k | unsigned llvm_ks::ARM::parseArchISA(StringRef Arch) { |
519 | 535k | return StringSwitch<unsigned>(Arch) |
520 | 535k | .StartsWith("aarch64", ARM::IK_AARCH64) |
521 | 535k | .StartsWith("arm64", ARM::IK_AARCH64) |
522 | 535k | .StartsWith("thumb", ARM::IK_THUMB) |
523 | 535k | .StartsWith("arm", ARM::IK_ARM) |
524 | 535k | .Default(ARM::EK_INVALID); |
525 | 535k | } |
526 | | |
527 | | // Little/Big endian |
528 | 535k | unsigned llvm_ks::ARM::parseArchEndian(StringRef Arch) { |
529 | 535k | if (Arch.startswith("armeb") || Arch.startswith("thumbeb") || |
530 | 404k | Arch.startswith("aarch64_be")) |
531 | 131k | return ARM::EK_BIG; |
532 | | |
533 | 404k | if (Arch.startswith("arm") || Arch.startswith("thumb")) { |
534 | 404k | if (Arch.endswith("eb")) |
535 | 94.7k | return ARM::EK_BIG; |
536 | 309k | else |
537 | 309k | return ARM::EK_LITTLE; |
538 | 404k | } |
539 | | |
540 | 0 | if (Arch.startswith("aarch64")) |
541 | 0 | return ARM::EK_LITTLE; |
542 | | |
543 | 0 | return ARM::EK_INVALID; |
544 | 0 | } |
545 | | |
546 | | // Profile A/R/M |
547 | 535k | unsigned llvm_ks::ARM::parseArchProfile(StringRef Arch) { |
548 | 535k | Arch = getCanonicalArchName(Arch); |
549 | 535k | switch (parseArch(Arch)) { |
550 | 0 | case ARM::AK_ARMV6M: |
551 | 0 | case ARM::AK_ARMV7M: |
552 | 0 | case ARM::AK_ARMV7EM: |
553 | 0 | case ARM::AK_ARMV8MMainline: |
554 | 0 | case ARM::AK_ARMV8MBaseline: |
555 | 0 | return ARM::PK_M; |
556 | 0 | case ARM::AK_ARMV7R: |
557 | 0 | return ARM::PK_R; |
558 | 430k | case ARM::AK_ARMV7A: |
559 | 430k | case ARM::AK_ARMV7K: |
560 | 535k | case ARM::AK_ARMV8A: |
561 | 535k | case ARM::AK_ARMV8_1A: |
562 | 535k | case ARM::AK_ARMV8_2A: |
563 | 535k | return ARM::PK_A; |
564 | 535k | } |
565 | 0 | return ARM::PK_INVALID; |
566 | 535k | } |
567 | | |
568 | | // Version number (ex. v7 = 7). |
569 | 535k | unsigned llvm_ks::ARM::parseArchVersion(StringRef Arch) { |
570 | 535k | Arch = getCanonicalArchName(Arch); |
571 | 535k | switch (parseArch(Arch)) { |
572 | 0 | case ARM::AK_ARMV2: |
573 | 0 | case ARM::AK_ARMV2A: |
574 | 0 | return 2; |
575 | 0 | case ARM::AK_ARMV3: |
576 | 0 | case ARM::AK_ARMV3M: |
577 | 0 | return 3; |
578 | 0 | case ARM::AK_ARMV4: |
579 | 0 | case ARM::AK_ARMV4T: |
580 | 0 | return 4; |
581 | 0 | case ARM::AK_ARMV5T: |
582 | 0 | case ARM::AK_ARMV5TE: |
583 | 0 | case ARM::AK_IWMMXT: |
584 | 0 | case ARM::AK_IWMMXT2: |
585 | 0 | case ARM::AK_XSCALE: |
586 | 0 | case ARM::AK_ARMV5TEJ: |
587 | 0 | return 5; |
588 | 0 | case ARM::AK_ARMV6: |
589 | 0 | case ARM::AK_ARMV6K: |
590 | 0 | case ARM::AK_ARMV6T2: |
591 | 0 | case ARM::AK_ARMV6KZ: |
592 | 0 | case ARM::AK_ARMV6M: |
593 | 0 | return 6; |
594 | 430k | case ARM::AK_ARMV7A: |
595 | 430k | case ARM::AK_ARMV7R: |
596 | 430k | case ARM::AK_ARMV7M: |
597 | 430k | case ARM::AK_ARMV7S: |
598 | 430k | case ARM::AK_ARMV7EM: |
599 | 430k | case ARM::AK_ARMV7K: |
600 | 430k | return 7; |
601 | 104k | case ARM::AK_ARMV8A: |
602 | 104k | case ARM::AK_ARMV8_1A: |
603 | 104k | case ARM::AK_ARMV8_2A: |
604 | 104k | case ARM::AK_ARMV8MBaseline: |
605 | 104k | case ARM::AK_ARMV8MMainline: |
606 | 104k | return 8; |
607 | 535k | } |
608 | 0 | return 0; |
609 | 535k | } |