1 //===-- ARMTargetParser - Parser for ARM target features --------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements a target parser to recognise ARM hardware features
10 // such as FPU/CPU/ARCH/extensions and specific support such as HWDIV.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/TargetParser/ARMTargetParser.h"
15 #include "llvm/ADT/StringSwitch.h"
16 #include "llvm/TargetParser/ARMTargetParserCommon.h"
17 #include "llvm/TargetParser/Triple.h"
18 #include <cctype>
19
20 using namespace llvm;
21
getHWDivSynonym(StringRef HWDiv)22 static StringRef getHWDivSynonym(StringRef HWDiv) {
23 return StringSwitch<StringRef>(HWDiv)
24 .Case("thumb,arm", "arm,thumb")
25 .Default(HWDiv);
26 }
27
28 // Allows partial match, ex. "v7a" matches "armv7a".
parseArch(StringRef Arch)29 ARM::ArchKind ARM::parseArch(StringRef Arch) {
30 Arch = getCanonicalArchName(Arch);
31 StringRef Syn = getArchSynonym(Arch);
32 for (const auto &A : ARMArchNames) {
33 if (A.Name.endswith(Syn))
34 return A.ID;
35 }
36 return ArchKind::INVALID;
37 }
38
39 // Version number (ex. v7 = 7).
parseArchVersion(StringRef Arch)40 unsigned ARM::parseArchVersion(StringRef Arch) {
41 Arch = getCanonicalArchName(Arch);
42 switch (parseArch(Arch)) {
43 case ArchKind::ARMV4:
44 case ArchKind::ARMV4T:
45 return 4;
46 case ArchKind::ARMV5T:
47 case ArchKind::ARMV5TE:
48 case ArchKind::IWMMXT:
49 case ArchKind::IWMMXT2:
50 case ArchKind::XSCALE:
51 case ArchKind::ARMV5TEJ:
52 return 5;
53 case ArchKind::ARMV6:
54 case ArchKind::ARMV6K:
55 case ArchKind::ARMV6T2:
56 case ArchKind::ARMV6KZ:
57 case ArchKind::ARMV6M:
58 return 6;
59 case ArchKind::ARMV7A:
60 case ArchKind::ARMV7VE:
61 case ArchKind::ARMV7R:
62 case ArchKind::ARMV7M:
63 case ArchKind::ARMV7S:
64 case ArchKind::ARMV7EM:
65 case ArchKind::ARMV7K:
66 return 7;
67 case ArchKind::ARMV8A:
68 case ArchKind::ARMV8_1A:
69 case ArchKind::ARMV8_2A:
70 case ArchKind::ARMV8_3A:
71 case ArchKind::ARMV8_4A:
72 case ArchKind::ARMV8_5A:
73 case ArchKind::ARMV8_6A:
74 case ArchKind::ARMV8_7A:
75 case ArchKind::ARMV8_8A:
76 case ArchKind::ARMV8_9A:
77 case ArchKind::ARMV8R:
78 case ArchKind::ARMV8MBaseline:
79 case ArchKind::ARMV8MMainline:
80 case ArchKind::ARMV8_1MMainline:
81 return 8;
82 case ArchKind::ARMV9A:
83 case ArchKind::ARMV9_1A:
84 case ArchKind::ARMV9_2A:
85 case ArchKind::ARMV9_3A:
86 case ArchKind::ARMV9_4A:
87 return 9;
88 case ArchKind::INVALID:
89 return 0;
90 }
91 llvm_unreachable("Unhandled architecture");
92 }
93
getProfileKind(ARM::ArchKind AK)94 static ARM::ProfileKind getProfileKind(ARM::ArchKind AK) {
95 switch (AK) {
96 case ARM::ArchKind::ARMV6M:
97 case ARM::ArchKind::ARMV7M:
98 case ARM::ArchKind::ARMV7EM:
99 case ARM::ArchKind::ARMV8MMainline:
100 case ARM::ArchKind::ARMV8MBaseline:
101 case ARM::ArchKind::ARMV8_1MMainline:
102 return ARM::ProfileKind::M;
103 case ARM::ArchKind::ARMV7R:
104 case ARM::ArchKind::ARMV8R:
105 return ARM::ProfileKind::R;
106 case ARM::ArchKind::ARMV7A:
107 case ARM::ArchKind::ARMV7VE:
108 case ARM::ArchKind::ARMV7K:
109 case ARM::ArchKind::ARMV8A:
110 case ARM::ArchKind::ARMV8_1A:
111 case ARM::ArchKind::ARMV8_2A:
112 case ARM::ArchKind::ARMV8_3A:
113 case ARM::ArchKind::ARMV8_4A:
114 case ARM::ArchKind::ARMV8_5A:
115 case ARM::ArchKind::ARMV8_6A:
116 case ARM::ArchKind::ARMV8_7A:
117 case ARM::ArchKind::ARMV8_8A:
118 case ARM::ArchKind::ARMV8_9A:
119 case ARM::ArchKind::ARMV9A:
120 case ARM::ArchKind::ARMV9_1A:
121 case ARM::ArchKind::ARMV9_2A:
122 case ARM::ArchKind::ARMV9_3A:
123 case ARM::ArchKind::ARMV9_4A:
124 return ARM::ProfileKind::A;
125 case ARM::ArchKind::ARMV4:
126 case ARM::ArchKind::ARMV4T:
127 case ARM::ArchKind::ARMV5T:
128 case ARM::ArchKind::ARMV5TE:
129 case ARM::ArchKind::ARMV5TEJ:
130 case ARM::ArchKind::ARMV6:
131 case ARM::ArchKind::ARMV6K:
132 case ARM::ArchKind::ARMV6T2:
133 case ARM::ArchKind::ARMV6KZ:
134 case ARM::ArchKind::ARMV7S:
135 case ARM::ArchKind::IWMMXT:
136 case ARM::ArchKind::IWMMXT2:
137 case ARM::ArchKind::XSCALE:
138 case ARM::ArchKind::INVALID:
139 return ARM::ProfileKind::INVALID;
140 }
141 llvm_unreachable("Unhandled architecture");
142 }
143
144 // Profile A/R/M
parseArchProfile(StringRef Arch)145 ARM::ProfileKind ARM::parseArchProfile(StringRef Arch) {
146 Arch = getCanonicalArchName(Arch);
147 return getProfileKind(parseArch(Arch));
148 }
149
getFPUFeatures(unsigned FPUKind,std::vector<StringRef> & Features)150 bool ARM::getFPUFeatures(unsigned FPUKind, std::vector<StringRef> &Features) {
151
152 if (FPUKind >= FK_LAST || FPUKind == FK_INVALID)
153 return false;
154
155 static const struct FPUFeatureNameInfo {
156 const char *PlusName, *MinusName;
157 FPUVersion MinVersion;
158 FPURestriction MaxRestriction;
159 } FPUFeatureInfoList[] = {
160 // We have to specify the + and - versions of the name in full so
161 // that we can return them as static StringRefs.
162 //
163 // Also, the SubtargetFeatures ending in just "sp" are listed here
164 // under FPURestriction::None, which is the only FPURestriction in
165 // which they would be valid (since FPURestriction::SP doesn't
166 // exist).
167 {"+vfp2", "-vfp2", FPUVersion::VFPV2, FPURestriction::D16},
168 {"+vfp2sp", "-vfp2sp", FPUVersion::VFPV2, FPURestriction::SP_D16},
169 {"+vfp3", "-vfp3", FPUVersion::VFPV3, FPURestriction::None},
170 {"+vfp3d16", "-vfp3d16", FPUVersion::VFPV3, FPURestriction::D16},
171 {"+vfp3d16sp", "-vfp3d16sp", FPUVersion::VFPV3, FPURestriction::SP_D16},
172 {"+vfp3sp", "-vfp3sp", FPUVersion::VFPV3, FPURestriction::None},
173 {"+fp16", "-fp16", FPUVersion::VFPV3_FP16, FPURestriction::SP_D16},
174 {"+vfp4", "-vfp4", FPUVersion::VFPV4, FPURestriction::None},
175 {"+vfp4d16", "-vfp4d16", FPUVersion::VFPV4, FPURestriction::D16},
176 {"+vfp4d16sp", "-vfp4d16sp", FPUVersion::VFPV4, FPURestriction::SP_D16},
177 {"+vfp4sp", "-vfp4sp", FPUVersion::VFPV4, FPURestriction::None},
178 {"+fp-armv8", "-fp-armv8", FPUVersion::VFPV5, FPURestriction::None},
179 {"+fp-armv8d16", "-fp-armv8d16", FPUVersion::VFPV5, FPURestriction::D16},
180 {"+fp-armv8d16sp", "-fp-armv8d16sp", FPUVersion::VFPV5, FPURestriction::SP_D16},
181 {"+fp-armv8sp", "-fp-armv8sp", FPUVersion::VFPV5, FPURestriction::None},
182 {"+fullfp16", "-fullfp16", FPUVersion::VFPV5_FULLFP16, FPURestriction::SP_D16},
183 {"+fp64", "-fp64", FPUVersion::VFPV2, FPURestriction::D16},
184 {"+d32", "-d32", FPUVersion::VFPV3, FPURestriction::None},
185 };
186
187 for (const auto &Info: FPUFeatureInfoList) {
188 if (FPUNames[FPUKind].FPUVer >= Info.MinVersion &&
189 FPUNames[FPUKind].Restriction <= Info.MaxRestriction)
190 Features.push_back(Info.PlusName);
191 else
192 Features.push_back(Info.MinusName);
193 }
194
195 static const struct NeonFeatureNameInfo {
196 const char *PlusName, *MinusName;
197 NeonSupportLevel MinSupportLevel;
198 } NeonFeatureInfoList[] = {
199 {"+neon", "-neon", NeonSupportLevel::Neon},
200 {"+sha2", "-sha2", NeonSupportLevel::Crypto},
201 {"+aes", "-aes", NeonSupportLevel::Crypto},
202 };
203
204 for (const auto &Info: NeonFeatureInfoList) {
205 if (FPUNames[FPUKind].NeonSupport >= Info.MinSupportLevel)
206 Features.push_back(Info.PlusName);
207 else
208 Features.push_back(Info.MinusName);
209 }
210
211 return true;
212 }
213
parseFPU(StringRef FPU)214 unsigned ARM::parseFPU(StringRef FPU) {
215 StringRef Syn = getFPUSynonym(FPU);
216 for (const auto &F : FPUNames) {
217 if (Syn == F.Name)
218 return F.ID;
219 }
220 return FK_INVALID;
221 }
222
getFPUNeonSupportLevel(unsigned FPUKind)223 ARM::NeonSupportLevel ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
224 if (FPUKind >= FK_LAST)
225 return NeonSupportLevel::None;
226 return FPUNames[FPUKind].NeonSupport;
227 }
228
getFPUSynonym(StringRef FPU)229 StringRef ARM::getFPUSynonym(StringRef FPU) {
230 return StringSwitch<StringRef>(FPU)
231 .Cases("fpa", "fpe2", "fpe3", "maverick", "invalid") // Unsupported
232 .Case("vfp2", "vfpv2")
233 .Case("vfp3", "vfpv3")
234 .Case("vfp4", "vfpv4")
235 .Case("vfp3-d16", "vfpv3-d16")
236 .Case("vfp4-d16", "vfpv4-d16")
237 .Cases("fp4-sp-d16", "vfpv4-sp-d16", "fpv4-sp-d16")
238 .Cases("fp4-dp-d16", "fpv4-dp-d16", "vfpv4-d16")
239 .Case("fp5-sp-d16", "fpv5-sp-d16")
240 .Cases("fp5-dp-d16", "fpv5-dp-d16", "fpv5-d16")
241 // FIXME: Clang uses it, but it's bogus, since neon defaults to vfpv3.
242 .Case("neon-vfpv3", "neon")
243 .Default(FPU);
244 }
245
getFPUName(unsigned FPUKind)246 StringRef ARM::getFPUName(unsigned FPUKind) {
247 if (FPUKind >= FK_LAST)
248 return StringRef();
249 return FPUNames[FPUKind].Name;
250 }
251
getFPUVersion(unsigned FPUKind)252 ARM::FPUVersion ARM::getFPUVersion(unsigned FPUKind) {
253 if (FPUKind >= FK_LAST)
254 return FPUVersion::NONE;
255 return FPUNames[FPUKind].FPUVer;
256 }
257
getFPURestriction(unsigned FPUKind)258 ARM::FPURestriction ARM::getFPURestriction(unsigned FPUKind) {
259 if (FPUKind >= FK_LAST)
260 return FPURestriction::None;
261 return FPUNames[FPUKind].Restriction;
262 }
263
getDefaultFPU(StringRef CPU,ARM::ArchKind AK)264 unsigned ARM::getDefaultFPU(StringRef CPU, ARM::ArchKind AK) {
265 if (CPU == "generic")
266 return ARM::ARMArchNames[static_cast<unsigned>(AK)].DefaultFPU;
267
268 return StringSwitch<unsigned>(CPU)
269 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
270 .Case(NAME, DEFAULT_FPU)
271 #include "llvm/TargetParser/ARMTargetParser.def"
272 .Default(ARM::FK_INVALID);
273 }
274
getDefaultExtensions(StringRef CPU,ARM::ArchKind AK)275 uint64_t ARM::getDefaultExtensions(StringRef CPU, ARM::ArchKind AK) {
276 if (CPU == "generic")
277 return ARM::ARMArchNames[static_cast<unsigned>(AK)].ArchBaseExtensions;
278
279 return StringSwitch<uint64_t>(CPU)
280 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) \
281 .Case(NAME, \
282 ARMArchNames[static_cast<unsigned>(ArchKind::ID)].ArchBaseExtensions | \
283 DEFAULT_EXT)
284 #include "llvm/TargetParser/ARMTargetParser.def"
285 .Default(ARM::AEK_INVALID);
286 }
287
getHWDivFeatures(uint64_t HWDivKind,std::vector<StringRef> & Features)288 bool ARM::getHWDivFeatures(uint64_t HWDivKind,
289 std::vector<StringRef> &Features) {
290
291 if (HWDivKind == AEK_INVALID)
292 return false;
293
294 if (HWDivKind & AEK_HWDIVARM)
295 Features.push_back("+hwdiv-arm");
296 else
297 Features.push_back("-hwdiv-arm");
298
299 if (HWDivKind & AEK_HWDIVTHUMB)
300 Features.push_back("+hwdiv");
301 else
302 Features.push_back("-hwdiv");
303
304 return true;
305 }
306
getExtensionFeatures(uint64_t Extensions,std::vector<StringRef> & Features)307 bool ARM::getExtensionFeatures(uint64_t Extensions,
308 std::vector<StringRef> &Features) {
309
310 if (Extensions == AEK_INVALID)
311 return false;
312
313 for (const auto &AE : ARCHExtNames) {
314 if ((Extensions & AE.ID) == AE.ID && !AE.Feature.empty())
315 Features.push_back(AE.Feature);
316 else if (!AE.NegFeature.empty())
317 Features.push_back(AE.NegFeature);
318 }
319
320 return getHWDivFeatures(Extensions, Features);
321 }
322
getArchName(ARM::ArchKind AK)323 StringRef ARM::getArchName(ARM::ArchKind AK) {
324 return ARMArchNames[static_cast<unsigned>(AK)].Name;
325 }
326
getCPUAttr(ARM::ArchKind AK)327 StringRef ARM::getCPUAttr(ARM::ArchKind AK) {
328 return ARMArchNames[static_cast<unsigned>(AK)].CPUAttr;
329 }
330
getSubArch(ARM::ArchKind AK)331 StringRef ARM::getSubArch(ARM::ArchKind AK) {
332 return ARMArchNames[static_cast<unsigned>(AK)].getSubArch();
333 }
334
getArchAttr(ARM::ArchKind AK)335 unsigned ARM::getArchAttr(ARM::ArchKind AK) {
336 return ARMArchNames[static_cast<unsigned>(AK)].ArchAttr;
337 }
338
getArchExtName(uint64_t ArchExtKind)339 StringRef ARM::getArchExtName(uint64_t ArchExtKind) {
340 for (const auto &AE : ARCHExtNames) {
341 if (ArchExtKind == AE.ID)
342 return AE.Name;
343 }
344 return StringRef();
345 }
346
stripNegationPrefix(StringRef & Name)347 static bool stripNegationPrefix(StringRef &Name) {
348 if (Name.startswith("no")) {
349 Name = Name.substr(2);
350 return true;
351 }
352 return false;
353 }
354
getArchExtFeature(StringRef ArchExt)355 StringRef ARM::getArchExtFeature(StringRef ArchExt) {
356 bool Negated = stripNegationPrefix(ArchExt);
357 for (const auto &AE : ARCHExtNames) {
358 if (!AE.Feature.empty() && ArchExt == AE.Name)
359 return StringRef(Negated ? AE.NegFeature : AE.Feature);
360 }
361
362 return StringRef();
363 }
364
findDoublePrecisionFPU(unsigned InputFPUKind)365 static unsigned findDoublePrecisionFPU(unsigned InputFPUKind) {
366 const ARM::FPUName &InputFPU = ARM::FPUNames[InputFPUKind];
367
368 // If the input FPU already supports double-precision, then there
369 // isn't any different FPU we can return here.
370 //
371 // The current available FPURestriction values are None (no
372 // restriction), D16 (only 16 d-regs) and SP_D16 (16 d-regs
373 // and single precision only); there's no value representing
374 // SP restriction without D16. So this test just means 'is it
375 // SP only?'.
376 if (InputFPU.Restriction != ARM::FPURestriction::SP_D16)
377 return ARM::FK_INVALID;
378
379 // Otherwise, look for an FPU entry with all the same fields, except
380 // that SP_D16 has been replaced with just D16, representing adding
381 // double precision and not changing anything else.
382 for (const ARM::FPUName &CandidateFPU : ARM::FPUNames) {
383 if (CandidateFPU.FPUVer == InputFPU.FPUVer &&
384 CandidateFPU.NeonSupport == InputFPU.NeonSupport &&
385 CandidateFPU.Restriction == ARM::FPURestriction::D16) {
386 return CandidateFPU.ID;
387 }
388 }
389
390 // nothing found
391 return ARM::FK_INVALID;
392 }
393
appendArchExtFeatures(StringRef CPU,ARM::ArchKind AK,StringRef ArchExt,std::vector<StringRef> & Features,unsigned & ArgFPUID)394 bool ARM::appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK,
395 StringRef ArchExt,
396 std::vector<StringRef> &Features,
397 unsigned &ArgFPUID) {
398
399 size_t StartingNumFeatures = Features.size();
400 const bool Negated = stripNegationPrefix(ArchExt);
401 uint64_t ID = parseArchExt(ArchExt);
402
403 if (ID == AEK_INVALID)
404 return false;
405
406 for (const auto &AE : ARCHExtNames) {
407 if (Negated) {
408 if ((AE.ID & ID) == ID && !AE.NegFeature.empty())
409 Features.push_back(AE.NegFeature);
410 } else {
411 if ((AE.ID & ID) == AE.ID && !AE.Feature.empty())
412 Features.push_back(AE.Feature);
413 }
414 }
415
416 if (CPU == "")
417 CPU = "generic";
418
419 if (ArchExt == "fp" || ArchExt == "fp.dp") {
420 unsigned FPUKind;
421 if (ArchExt == "fp.dp") {
422 if (Negated) {
423 Features.push_back("-fp64");
424 return true;
425 }
426 FPUKind = findDoublePrecisionFPU(getDefaultFPU(CPU, AK));
427 } else if (Negated) {
428 FPUKind = ARM::FK_NONE;
429 } else {
430 FPUKind = getDefaultFPU(CPU, AK);
431 }
432 ArgFPUID = FPUKind;
433 return ARM::getFPUFeatures(FPUKind, Features);
434 }
435 return StartingNumFeatures != Features.size();
436 }
437
convertV9toV8(ARM::ArchKind AK)438 ARM::ArchKind ARM::convertV9toV8(ARM::ArchKind AK) {
439 if (getProfileKind(AK) != ProfileKind::A)
440 return ARM::ArchKind::INVALID;
441 if (AK < ARM::ArchKind::ARMV9A || AK > ARM::ArchKind::ARMV9_3A)
442 return ARM::ArchKind::INVALID;
443 unsigned AK_v8 = static_cast<unsigned>(ARM::ArchKind::ARMV8_5A);
444 AK_v8 += static_cast<unsigned>(AK) -
445 static_cast<unsigned>(ARM::ArchKind::ARMV9A);
446 return static_cast<ARM::ArchKind>(AK_v8);
447 }
448
getDefaultCPU(StringRef Arch)449 StringRef ARM::getDefaultCPU(StringRef Arch) {
450 ArchKind AK = parseArch(Arch);
451 if (AK == ArchKind::INVALID)
452 return StringRef();
453
454 // Look for multiple AKs to find the default for pair AK+Name.
455 for (const auto &CPU : CPUNames) {
456 if (CPU.ArchID == AK && CPU.Default)
457 return CPU.Name;
458 }
459
460 // If we can't find a default then target the architecture instead
461 return "generic";
462 }
463
parseHWDiv(StringRef HWDiv)464 uint64_t ARM::parseHWDiv(StringRef HWDiv) {
465 StringRef Syn = getHWDivSynonym(HWDiv);
466 for (const auto &D : HWDivNames) {
467 if (Syn == D.Name)
468 return D.ID;
469 }
470 return AEK_INVALID;
471 }
472
parseArchExt(StringRef ArchExt)473 uint64_t ARM::parseArchExt(StringRef ArchExt) {
474 for (const auto &A : ARCHExtNames) {
475 if (ArchExt == A.Name)
476 return A.ID;
477 }
478 return AEK_INVALID;
479 }
480
parseCPUArch(StringRef CPU)481 ARM::ArchKind ARM::parseCPUArch(StringRef CPU) {
482 for (const auto &C : CPUNames) {
483 if (CPU == C.Name)
484 return C.ArchID;
485 }
486 return ArchKind::INVALID;
487 }
488
fillValidCPUArchList(SmallVectorImpl<StringRef> & Values)489 void ARM::fillValidCPUArchList(SmallVectorImpl<StringRef> &Values) {
490 for (const auto &Arch : CPUNames) {
491 if (Arch.ArchID != ArchKind::INVALID)
492 Values.push_back(Arch.Name);
493 }
494 }
495
computeDefaultTargetABI(const Triple & TT,StringRef CPU)496 StringRef ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) {
497 StringRef ArchName =
498 CPU.empty() ? TT.getArchName() : getArchName(parseCPUArch(CPU));
499
500 if (TT.isOSBinFormatMachO()) {
501 if (TT.getEnvironment() == Triple::EABI ||
502 TT.getOS() == Triple::UnknownOS ||
503 parseArchProfile(ArchName) == ProfileKind::M)
504 return "aapcs";
505 if (TT.isWatchABI())
506 return "aapcs16";
507 return "apcs-gnu";
508 } else if (TT.isOSWindows())
509 // FIXME: this is invalid for WindowsCE.
510 return "aapcs";
511
512 // Select the default based on the platform.
513 switch (TT.getEnvironment()) {
514 case Triple::Android:
515 case Triple::GNUEABI:
516 case Triple::GNUEABIHF:
517 case Triple::MuslEABI:
518 case Triple::MuslEABIHF:
519 return "aapcs-linux";
520 case Triple::EABIHF:
521 case Triple::EABI:
522 return "aapcs";
523 default:
524 if (TT.isOSNetBSD())
525 return "apcs-gnu";
526 if (TT.isOSFreeBSD() || TT.isOSOpenBSD())
527 return "aapcs-linux";
528 return "aapcs";
529 }
530 }
531
getARMCPUForArch(const llvm::Triple & Triple,StringRef MArch)532 StringRef ARM::getARMCPUForArch(const llvm::Triple &Triple, StringRef MArch) {
533 if (MArch.empty())
534 MArch = Triple.getArchName();
535 MArch = llvm::ARM::getCanonicalArchName(MArch);
536
537 // Some defaults are forced.
538 switch (Triple.getOS()) {
539 case llvm::Triple::FreeBSD:
540 case llvm::Triple::NetBSD:
541 case llvm::Triple::OpenBSD:
542 if (!MArch.empty() && MArch == "v6")
543 return "arm1176jzf-s";
544 if (!MArch.empty() && MArch == "v7")
545 return "cortex-a8";
546 break;
547 case llvm::Triple::Win32:
548 // FIXME: this is invalid for WindowsCE
549 if (llvm::ARM::parseArchVersion(MArch) <= 7)
550 return "cortex-a9";
551 break;
552 case llvm::Triple::IOS:
553 case llvm::Triple::MacOSX:
554 case llvm::Triple::TvOS:
555 case llvm::Triple::WatchOS:
556 case llvm::Triple::DriverKit:
557 if (MArch == "v7k")
558 return "cortex-a7";
559 break;
560 default:
561 break;
562 }
563
564 if (MArch.empty())
565 return StringRef();
566
567 StringRef CPU = llvm::ARM::getDefaultCPU(MArch);
568 if (!CPU.empty() && !CPU.equals("invalid"))
569 return CPU;
570
571 // If no specific architecture version is requested, return the minimum CPU
572 // required by the OS and environment.
573 switch (Triple.getOS()) {
574 case llvm::Triple::NetBSD:
575 switch (Triple.getEnvironment()) {
576 case llvm::Triple::EABI:
577 case llvm::Triple::EABIHF:
578 case llvm::Triple::GNUEABI:
579 case llvm::Triple::GNUEABIHF:
580 return "arm926ej-s";
581 default:
582 return "strongarm";
583 }
584 case llvm::Triple::NaCl:
585 case llvm::Triple::OpenBSD:
586 return "cortex-a8";
587 default:
588 switch (Triple.getEnvironment()) {
589 case llvm::Triple::EABIHF:
590 case llvm::Triple::GNUEABIHF:
591 case llvm::Triple::MuslEABIHF:
592 return "arm1176jzf-s";
593 default:
594 return "arm7tdmi";
595 }
596 }
597
598 llvm_unreachable("invalid arch name");
599 }
600