1//===--- ARM.cpp - Implement ARM target feature support -------------------===//
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 ARM TargetInfo objects.
10//
11//===----------------------------------------------------------------------===//
12
13#include "ARM.h"
14#include "clang/Basic/Builtins.h"
15#include "clang/Basic/Diagnostic.h"
16#include "clang/Basic/TargetBuiltins.h"
17#include "llvm/ADT/StringRef.h"
18#include "llvm/ADT/StringSwitch.h"
19#include "llvm/TargetParser/ARMTargetParser.h"
20
21using namespace clang;
22using namespace clang::targets;
23
24void ARMTargetInfo::setABIAAPCS() {
25 IsAAPCS = true;
26
27 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
28 BFloat16Width = BFloat16Align = 16;
29 BFloat16Format = &llvm::APFloat::BFloat();
30
31 const llvm::Triple &T = getTriple();
32
33 bool IsNetBSD = T.isOSNetBSD();
34 bool IsOpenBSD = T.isOSOpenBSD();
35 if (!T.isOSWindows() && !IsNetBSD && !IsOpenBSD)
36 WCharType = UnsignedInt;
37
38 UseBitFieldTypeAlignment = true;
39
40 ZeroLengthBitfieldBoundary = 0;
41
42 resetDataLayout();
43
44 // FIXME: Enumerated types are variable width in straight AAPCS.
45}
46
47void ARMTargetInfo::setABIAPCS(bool IsAAPCS16) {
48 IsAAPCS = false;
49
50 if (IsAAPCS16)
51 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
52 else
53 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32;
54 BFloat16Width = BFloat16Align = 16;
55 BFloat16Format = &llvm::APFloat::BFloat();
56
57 WCharType = SignedInt;
58
59 // Do not respect the alignment of bit-field types when laying out
60 // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc.
61 UseBitFieldTypeAlignment = false;
62
63 /// gcc forces the alignment to 4 bytes, regardless of the type of the
64 /// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in
65 /// gcc.
66 ZeroLengthBitfieldBoundary = 32;
67
68 resetDataLayout();
69
70 // FIXME: Override "preferred align" for double and long long.
71}
72
73void ARMTargetInfo::setArchInfo() {
74 StringRef ArchName = getTriple().getArchName();
75
76 ArchISA = llvm::ARM::parseArchISA(Arch: ArchName);
77 CPU = std::string(llvm::ARM::getDefaultCPU(Arch: ArchName));
78 llvm::ARM::ArchKind AK = llvm::ARM::parseArch(Arch: ArchName);
79 if (AK != llvm::ARM::ArchKind::INVALID)
80 ArchKind = AK;
81 setArchInfo(ArchKind);
82}
83
84void ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) {
85 StringRef SubArch;
86
87 // cache TargetParser info
88 ArchKind = Kind;
89 SubArch = llvm::ARM::getSubArch(AK: ArchKind);
90 ArchProfile = llvm::ARM::parseArchProfile(Arch: SubArch);
91 ArchVersion = llvm::ARM::parseArchVersion(Arch: SubArch);
92
93 // cache CPU related strings
94 CPUAttr = getCPUAttr();
95 CPUProfile = getCPUProfile();
96}
97
98void ARMTargetInfo::setAtomic() {
99 if (ArchProfile == llvm::ARM::ProfileKind::M) {
100 // M-class only ever supports 32-bit atomics. Cortex-M0 doesn't have
101 // any atomics.
102 MaxAtomicPromoteWidth = 32;
103 if (ArchVersion >= 7)
104 MaxAtomicInlineWidth = 32;
105 } else {
106 // A-class targets have up to 64-bit atomics.
107 //
108 // On Linux, 64-bit atomics are always available through kernel helpers
109 // (which are lock-free). Otherwise, atomics are available on v6 or later.
110 //
111 // (Thumb doesn't matter; for Thumbv6, we just use a library call which
112 // switches out of Thumb mode.)
113 //
114 // This should match setMaxAtomicSizeInBitsSupported() in the backend.
115 MaxAtomicPromoteWidth = 64;
116 if (getTriple().getOS() == llvm::Triple::Linux || ArchVersion >= 6)
117 MaxAtomicInlineWidth = 64;
118 }
119}
120
121bool ARMTargetInfo::hasMVE() const {
122 return ArchKind == llvm::ARM::ArchKind::ARMV8_1MMainline && MVE != 0;
123}
124
125bool ARMTargetInfo::hasMVEFloat() const {
126 return hasMVE() && (MVE & MVE_FP);
127}
128
129bool ARMTargetInfo::hasCDE() const { return getARMCDECoprocMask() != 0; }
130
131bool ARMTargetInfo::isThumb() const {
132 return ArchISA == llvm::ARM::ISAKind::THUMB;
133}
134
135bool ARMTargetInfo::supportsThumb() const {
136 return CPUAttr.count(C: 'T') || ArchVersion >= 6;
137}
138
139bool ARMTargetInfo::supportsThumb2() const {
140 return CPUAttr == "6T2" || (ArchVersion >= 7 && CPUAttr != "8M_BASE");
141}
142
143StringRef ARMTargetInfo::getCPUAttr() const {
144 // For most sub-arches, the build attribute CPU name is enough.
145 // For Cortex variants, it's slightly different.
146 switch (ArchKind) {
147 default:
148 return llvm::ARM::getCPUAttr(AK: ArchKind);
149 case llvm::ARM::ArchKind::ARMV6M:
150 return "6M";
151 case llvm::ARM::ArchKind::ARMV7S:
152 return "7S";
153 case llvm::ARM::ArchKind::ARMV7A:
154 return "7A";
155 case llvm::ARM::ArchKind::ARMV7R:
156 return "7R";
157 case llvm::ARM::ArchKind::ARMV7M:
158 return "7M";
159 case llvm::ARM::ArchKind::ARMV7EM:
160 return "7EM";
161 case llvm::ARM::ArchKind::ARMV7VE:
162 return "7VE";
163 case llvm::ARM::ArchKind::ARMV8A:
164 return "8A";
165 case llvm::ARM::ArchKind::ARMV8_1A:
166 return "8_1A";
167 case llvm::ARM::ArchKind::ARMV8_2A:
168 return "8_2A";
169 case llvm::ARM::ArchKind::ARMV8_3A:
170 return "8_3A";
171 case llvm::ARM::ArchKind::ARMV8_4A:
172 return "8_4A";
173 case llvm::ARM::ArchKind::ARMV8_5A:
174 return "8_5A";
175 case llvm::ARM::ArchKind::ARMV8_6A:
176 return "8_6A";
177 case llvm::ARM::ArchKind::ARMV8_7A:
178 return "8_7A";
179 case llvm::ARM::ArchKind::ARMV8_8A:
180 return "8_8A";
181 case llvm::ARM::ArchKind::ARMV8_9A:
182 return "8_9A";
183 case llvm::ARM::ArchKind::ARMV9A:
184 return "9A";
185 case llvm::ARM::ArchKind::ARMV9_1A:
186 return "9_1A";
187 case llvm::ARM::ArchKind::ARMV9_2A:
188 return "9_2A";
189 case llvm::ARM::ArchKind::ARMV9_3A:
190 return "9_3A";
191 case llvm::ARM::ArchKind::ARMV9_4A:
192 return "9_4A";
193 case llvm::ARM::ArchKind::ARMV9_5A:
194 return "9_5A";
195 case llvm::ARM::ArchKind::ARMV9_6A:
196 return "9_6A";
197 case llvm::ARM::ArchKind::ARMV9_7A:
198 return "9_7A";
199 case llvm::ARM::ArchKind::ARMV8MBaseline:
200 return "8M_BASE";
201 case llvm::ARM::ArchKind::ARMV8MMainline:
202 return "8M_MAIN";
203 case llvm::ARM::ArchKind::ARMV8R:
204 return "8R";
205 case llvm::ARM::ArchKind::ARMV8_1MMainline:
206 return "8_1M_MAIN";
207 }
208}
209
210StringRef ARMTargetInfo::getCPUProfile() const {
211 switch (ArchProfile) {
212 case llvm::ARM::ProfileKind::A:
213 return "A";
214 case llvm::ARM::ProfileKind::R:
215 return "R";
216 case llvm::ARM::ProfileKind::M:
217 return "M";
218 default:
219 return "";
220 }
221}
222
223ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
224 const TargetOptions &Opts)
225 : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
226 HW_FP(0) {
227 bool IsFreeBSD = Triple.isOSFreeBSD();
228 bool IsFuchsia = Triple.isOSFuchsia();
229 bool IsOpenBSD = Triple.isOSOpenBSD();
230 bool IsNetBSD = Triple.isOSNetBSD();
231 bool IsHaiku = Triple.isOSHaiku();
232 bool IsOHOS = Triple.isOHOSFamily();
233
234 // FIXME: the isOSBinFormatMachO is a workaround for identifying a Darwin-like
235 // environment where size_t is `unsigned long` rather than `unsigned int`
236
237 PtrDiffType = IntPtrType =
238 (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
239 IsNetBSD)
240 ? SignedLong
241 : SignedInt;
242
243 SizeType = (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
244 IsNetBSD)
245 ? UnsignedLong
246 : UnsignedInt;
247
248 // ptrdiff_t is inconsistent on Darwin
249 if ((Triple.isOSDarwin() || Triple.isOSBinFormatMachO()) &&
250 !Triple.isWatchABI())
251 PtrDiffType = SignedInt;
252
253 // Cache arch related info.
254 setArchInfo();
255
256 // {} in inline assembly are neon specifiers, not assembly variant
257 // specifiers.
258 NoAsmVariants = true;
259
260 // FIXME: This duplicates code from the driver that sets the -target-abi
261 // option - this code is used if -target-abi isn't passed and should
262 // be unified in some way.
263 if (Triple.isOSBinFormatMachO()) {
264 // The backend is hardwired to assume AAPCS for M-class processors, ensure
265 // the frontend matches that.
266 if (Triple.getEnvironment() == llvm::Triple::EABI ||
267 Triple.getOS() == llvm::Triple::UnknownOS ||
268 ArchProfile == llvm::ARM::ProfileKind::M) {
269 setABI("aapcs");
270 } else if (Triple.isWatchABI()) {
271 setABI("aapcs16");
272 } else {
273 setABI("apcs-gnu");
274 }
275 } else if (Triple.isOSWindows()) {
276 // FIXME: this is invalid for WindowsCE
277 setABI("aapcs");
278 } else {
279 // Select the default based on the platform.
280 switch (Triple.getEnvironment()) {
281 case llvm::Triple::Android:
282 case llvm::Triple::GNUEABI:
283 case llvm::Triple::GNUEABIT64:
284 case llvm::Triple::GNUEABIHF:
285 case llvm::Triple::GNUEABIHFT64:
286 case llvm::Triple::MuslEABI:
287 case llvm::Triple::MuslEABIHF:
288 case llvm::Triple::OpenHOS:
289 setABI("aapcs-linux");
290 break;
291 case llvm::Triple::EABIHF:
292 case llvm::Triple::EABI:
293 setABI("aapcs");
294 break;
295 case llvm::Triple::GNU:
296 setABI("apcs-gnu");
297 break;
298 default:
299 if (IsNetBSD)
300 setABI("apcs-gnu");
301 else if (IsFreeBSD || IsFuchsia || IsOpenBSD || IsHaiku || IsOHOS)
302 setABI("aapcs-linux");
303 else
304 setABI("aapcs");
305 break;
306 }
307 }
308
309 // ARM targets default to using the ARM C++ ABI.
310 TheCXXABI.set(TargetCXXABI::GenericARM);
311
312 // ARM has atomics up to 8 bytes
313 setAtomic();
314
315 // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS)
316 // as well the default alignment
317 if (IsAAPCS && !Triple.isAndroid())
318 DefaultAlignForAttributeAligned = MaxVectorAlign = 64;
319
320 // Do force alignment of members that follow zero length bitfields. If
321 // the alignment of the zero-length bitfield is greater than the member
322 // that follows it, `bar', `bar' will be aligned as the type of the
323 // zero length bitfield.
324 UseZeroLengthBitfieldAlignment = true;
325
326 if (Triple.getOS() == llvm::Triple::Linux ||
327 Triple.getOS() == llvm::Triple::UnknownOS)
328 this->MCountName =
329 Triple.isGNUEnvironment() ? "llvm.arm.gnu.eabi.mcount" : "\01mcount";
330
331 SoftFloatABI = llvm::is_contained(Range: Opts.FeaturesAsWritten, Element: "+soft-float-abi");
332}
333
334StringRef ARMTargetInfo::getABI() const { return ABI; }
335
336bool ARMTargetInfo::setABI(const std::string &Name) {
337 ABI = Name;
338
339 // The defaults (above) are for AAPCS, check if we need to change them.
340 //
341 // FIXME: We need support for -meabi... we could just mangle it into the
342 // name.
343 if (Name == "apcs-gnu" || Name == "aapcs16") {
344 setABIAPCS(Name == "aapcs16");
345 return true;
346 }
347 if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") {
348 setABIAAPCS();
349 return true;
350 }
351 return false;
352}
353
354bool ARMTargetInfo::isBranchProtectionSupportedArch(StringRef Arch) const {
355 llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(CPU: Arch);
356 if (CPUArch == llvm::ARM::ArchKind::INVALID)
357 CPUArch = llvm::ARM::parseArch(Arch: getTriple().getArchName());
358
359 if (CPUArch == llvm::ARM::ArchKind::INVALID)
360 return false;
361
362 StringRef ArchFeature = llvm::ARM::getArchName(AK: CPUArch);
363 auto a =
364 llvm::Triple(ArchFeature, getTriple().getVendorName(),
365 getTriple().getOSName(), getTriple().getEnvironmentName());
366
367 StringRef SubArch = llvm::ARM::getSubArch(AK: CPUArch);
368 llvm::ARM::ProfileKind Profile = llvm::ARM::parseArchProfile(Arch: SubArch);
369 return a.isArmT32() && (Profile == llvm::ARM::ProfileKind::M);
370}
371
372bool ARMTargetInfo::validateBranchProtection(StringRef Spec, StringRef Arch,
373 BranchProtectionInfo &BPI,
374 const LangOptions &LO,
375 StringRef &Err) const {
376 llvm::ARM::ParsedBranchProtection PBP;
377 if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err, Triple: getTriple()))
378 return false;
379
380 if (!isBranchProtectionSupportedArch(Arch))
381 return false;
382
383 BPI.SignReturnAddr =
384 llvm::StringSwitch<LangOptions::SignReturnAddressScopeKind>(PBP.Scope)
385 .Case(S: "non-leaf", Value: LangOptions::SignReturnAddressScopeKind::NonLeaf)
386 .Case(S: "all", Value: LangOptions::SignReturnAddressScopeKind::All)
387 .Default(Value: LangOptions::SignReturnAddressScopeKind::None);
388
389 // Don't care for the sign key, beyond issuing a warning.
390 if (PBP.Key == "b_key")
391 Err = "b-key";
392 BPI.SignKey = LangOptions::SignReturnAddressKeyKind::AKey;
393
394 BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement;
395 BPI.BranchProtectionPAuthLR = PBP.BranchProtectionPAuthLR;
396 return true;
397}
398
399// FIXME: This should be based on Arch attributes, not CPU names.
400bool ARMTargetInfo::initFeatureMap(
401 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
402 const std::vector<std::string> &FeaturesVec) const {
403
404 std::string ArchFeature;
405 std::vector<StringRef> TargetFeatures;
406 llvm::ARM::ArchKind Arch = llvm::ARM::parseArch(Arch: getTriple().getArchName());
407
408 // Map the base architecture to an appropriate target feature, so we don't
409 // rely on the target triple.
410 llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(CPU);
411 if (CPUArch == llvm::ARM::ArchKind::INVALID)
412 CPUArch = Arch;
413 if (CPUArch != llvm::ARM::ArchKind::INVALID) {
414 ArchFeature = ("+" + llvm::ARM::getArchName(AK: CPUArch)).str();
415 TargetFeatures.push_back(x: ArchFeature);
416
417 // These features are added to allow arm_neon.h target(..) attributes to
418 // match with both arm and aarch64. We need to add all previous architecture
419 // versions, so that "8.6" also allows "8.1" functions. In case of v9.x the
420 // v8.x counterparts are added too. We only need these for anything > 8.0-A.
421 for (llvm::ARM::ArchKind I = llvm::ARM::convertV9toV8(AK: CPUArch);
422 I != llvm::ARM::ArchKind::INVALID; --I)
423 Features[llvm::ARM::getSubArch(AK: I)] = true;
424 if (CPUArch > llvm::ARM::ArchKind::ARMV8A &&
425 CPUArch <= llvm::ARM::ArchKind::ARMV9_3A)
426 for (llvm::ARM::ArchKind I = CPUArch; I != llvm::ARM::ArchKind::INVALID;
427 --I)
428 Features[llvm::ARM::getSubArch(AK: I)] = true;
429 }
430
431 // get default FPU features
432 llvm::ARM::FPUKind FPUKind = llvm::ARM::getDefaultFPU(CPU, AK: Arch);
433 llvm::ARM::getFPUFeatures(FPUKind, Features&: TargetFeatures);
434
435 // get default Extension features
436 uint64_t Extensions = llvm::ARM::getDefaultExtensions(CPU, AK: Arch);
437 llvm::ARM::getExtensionFeatures(Extensions, Features&: TargetFeatures);
438
439 for (auto Feature : TargetFeatures)
440 if (Feature[0] == '+')
441 Features[Feature.drop_front(N: 1)] = true;
442
443 // Enable or disable thumb-mode explicitly per function to enable mixed
444 // ARM and Thumb code generation.
445 if (isThumb())
446 Features["thumb-mode"] = true;
447 else
448 Features["thumb-mode"] = false;
449
450 // Convert user-provided arm and thumb GNU target attributes to
451 // [-|+]thumb-mode target features respectively.
452 std::vector<std::string> UpdatedFeaturesVec;
453 for (const auto &Feature : FeaturesVec) {
454 // Skip soft-float-abi; it's something we only use to initialize a bit of
455 // class state, and is otherwise unrecognized.
456 if (Feature == "+soft-float-abi")
457 continue;
458
459 StringRef FixedFeature;
460 if (Feature == "+arm")
461 FixedFeature = "-thumb-mode";
462 else if (Feature == "+thumb")
463 FixedFeature = "+thumb-mode";
464 else
465 FixedFeature = Feature;
466 UpdatedFeaturesVec.push_back(x: FixedFeature.str());
467 }
468
469 return TargetInfo::initFeatureMap(Features, Diags, CPU, FeatureVec: UpdatedFeaturesVec);
470}
471
472
473bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
474 DiagnosticsEngine &Diags) {
475 FPU = 0;
476 MVE = 0;
477 CRC = 0;
478 Crypto = 0;
479 SHA2 = 0;
480 AES = 0;
481 DSP = 0;
482 HasUnalignedAccess = true;
483 SoftFloat = false;
484 // Note that SoftFloatABI is initialized in our constructor.
485 HWDiv = 0;
486 DotProd = 0;
487 HasMatMul = 0;
488 HasPAC = 0;
489 HasBTI = 0;
490 HasFloat16 = true;
491 ARMCDECoprocMask = 0;
492 HasBFloat16 = false;
493 HasFullBFloat16 = false;
494 FPRegsDisabled = false;
495
496 // This does not diagnose illegal cases like having both
497 // "+vfpv2" and "+vfpv3" or having "+neon" and "-fp64".
498 for (const auto &Feature : Features) {
499 if (Feature == "+soft-float") {
500 SoftFloat = true;
501 } else if (Feature == "+vfp2sp" || Feature == "+vfp2") {
502 FPU |= VFP2FPU;
503 HW_FP |= HW_FP_SP;
504 if (Feature == "+vfp2")
505 HW_FP |= HW_FP_DP;
506 } else if (Feature == "+vfp3sp" || Feature == "+vfp3d16sp" ||
507 Feature == "+vfp3" || Feature == "+vfp3d16") {
508 FPU |= VFP3FPU;
509 HW_FP |= HW_FP_SP;
510 if (Feature == "+vfp3" || Feature == "+vfp3d16")
511 HW_FP |= HW_FP_DP;
512 } else if (Feature == "+vfp4sp" || Feature == "+vfp4d16sp" ||
513 Feature == "+vfp4" || Feature == "+vfp4d16") {
514 FPU |= VFP4FPU;
515 HW_FP |= HW_FP_SP | HW_FP_HP;
516 if (Feature == "+vfp4" || Feature == "+vfp4d16")
517 HW_FP |= HW_FP_DP;
518 } else if (Feature == "+fp-armv8sp" || Feature == "+fp-armv8d16sp" ||
519 Feature == "+fp-armv8" || Feature == "+fp-armv8d16") {
520 FPU |= FPARMV8;
521 HW_FP |= HW_FP_SP | HW_FP_HP;
522 if (Feature == "+fp-armv8" || Feature == "+fp-armv8d16")
523 HW_FP |= HW_FP_DP;
524 } else if (Feature == "+neon") {
525 FPU |= NeonFPU;
526 HW_FP |= HW_FP_SP;
527 } else if (Feature == "+hwdiv") {
528 HWDiv |= HWDivThumb;
529 } else if (Feature == "+hwdiv-arm") {
530 HWDiv |= HWDivARM;
531 } else if (Feature == "+crc") {
532 CRC = 1;
533 } else if (Feature == "+crypto") {
534 Crypto = 1;
535 } else if (Feature == "+sha2") {
536 SHA2 = 1;
537 } else if (Feature == "+aes") {
538 AES = 1;
539 } else if (Feature == "+dsp") {
540 DSP = 1;
541 } else if (Feature == "+fp64") {
542 HW_FP |= HW_FP_DP;
543 } else if (Feature == "+8msecext") {
544 if (CPUProfile != "M" || ArchVersion != 8) {
545 Diags.Report(DiagID: diag::err_target_unsupported_mcmse) << CPU;
546 return false;
547 }
548 } else if (Feature == "+strict-align") {
549 HasUnalignedAccess = false;
550 } else if (Feature == "+fp16") {
551 HW_FP |= HW_FP_HP;
552 } else if (Feature == "+fullfp16") {
553 HasFastHalfType = true;
554 } else if (Feature == "+dotprod") {
555 DotProd = true;
556 } else if (Feature == "+mve") {
557 MVE |= MVE_INT;
558 } else if (Feature == "+mve.fp") {
559 HasFastHalfType = true;
560 FPU |= FPARMV8;
561 MVE |= MVE_INT | MVE_FP;
562 HW_FP |= HW_FP_SP | HW_FP_HP;
563 } else if (Feature == "+i8mm") {
564 HasMatMul = 1;
565 } else if (Feature.size() == strlen(s: "+cdecp0") && Feature >= "+cdecp0" &&
566 Feature <= "+cdecp7") {
567 unsigned Coproc = Feature.back() - '0';
568 ARMCDECoprocMask |= (1U << Coproc);
569 } else if (Feature == "+bf16") {
570 HasBFloat16 = true;
571 } else if (Feature == "-fpregs") {
572 FPRegsDisabled = true;
573 } else if (Feature == "+pacbti") {
574 HasPAC = 1;
575 HasBTI = 1;
576 } else if (Feature == "+fullbf16") {
577 HasFullBFloat16 = true;
578 } else if (Feature == "+execute-only") {
579 TLSSupported = false;
580 }
581 }
582
583 HalfArgsAndReturns = true;
584
585 switch (ArchVersion) {
586 case 6:
587 if (ArchProfile == llvm::ARM::ProfileKind::M)
588 LDREX = 0;
589 else if (ArchKind == llvm::ARM::ArchKind::ARMV6K ||
590 ArchKind == llvm::ARM::ArchKind::ARMV6KZ)
591 LDREX = ARM_LDREX_D | ARM_LDREX_W | ARM_LDREX_H | ARM_LDREX_B;
592 else
593 LDREX = ARM_LDREX_W;
594 break;
595 case 7:
596 case 8:
597 if (ArchProfile == llvm::ARM::ProfileKind::M)
598 LDREX = ARM_LDREX_W | ARM_LDREX_H | ARM_LDREX_B;
599 else
600 LDREX = ARM_LDREX_D | ARM_LDREX_W | ARM_LDREX_H | ARM_LDREX_B;
601 break;
602 case 9:
603 assert(ArchProfile != llvm::ARM::ProfileKind::M &&
604 "No Armv9-M architectures defined");
605 LDREX = ARM_LDREX_D | ARM_LDREX_W | ARM_LDREX_H | ARM_LDREX_B;
606 }
607
608 if (!(FPU & NeonFPU) && FPMath == FP_Neon) {
609 Diags.Report(DiagID: diag::err_target_unsupported_fpmath) << "neon";
610 return false;
611 }
612
613 if (FPMath == FP_Neon)
614 Features.push_back(x: "+neonfp");
615 else if (FPMath == FP_VFP)
616 Features.push_back(x: "-neonfp");
617
618 return true;
619}
620
621bool ARMTargetInfo::hasFeature(StringRef Feature) const {
622 return llvm::StringSwitch<bool>(Feature)
623 .Case(S: "arm", Value: true)
624 .Case(S: "aarch32", Value: true)
625 .Case(S: "softfloat", Value: SoftFloat)
626 .Case(S: "thumb", Value: isThumb())
627 .Case(S: "neon", Value: (FPU & NeonFPU) && !SoftFloat)
628 .Case(S: "vfp", Value: FPU && !SoftFloat)
629 .Case(S: "hwdiv", Value: HWDiv & HWDivThumb)
630 .Case(S: "hwdiv-arm", Value: HWDiv & HWDivARM)
631 .Case(S: "mve", Value: hasMVE())
632 .Default(Value: false);
633}
634
635bool ARMTargetInfo::hasBFloat16Type() const {
636 // The __bf16 type is generally available so long as we have any fp registers.
637 return HasBFloat16 || (FPU && !SoftFloat);
638}
639
640bool ARMTargetInfo::isValidCPUName(StringRef Name) const {
641 return Name == "generic" ||
642 llvm::ARM::parseCPUArch(CPU: Name) != llvm::ARM::ArchKind::INVALID;
643}
644
645void ARMTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
646 llvm::ARM::fillValidCPUArchList(Values);
647}
648
649bool ARMTargetInfo::setCPU(StringRef Name) {
650 if (Name != "generic")
651 setArchInfo(llvm::ARM::parseCPUArch(CPU: Name));
652
653 if (ArchKind == llvm::ARM::ArchKind::INVALID)
654 return false;
655 setAtomic();
656 CPU = Name;
657 return true;
658}
659
660bool ARMTargetInfo::setFPMath(StringRef Name) {
661 if (Name == "neon") {
662 FPMath = FP_Neon;
663 return true;
664 } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" ||
665 Name == "vfp4") {
666 FPMath = FP_VFP;
667 return true;
668 }
669 return false;
670}
671
672void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
673 MacroBuilder &Builder) const {
674 Builder.defineMacro(Name: "__ARM_FEATURE_QRDMX", Value: "1");
675}
676
677void ARMTargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
678 MacroBuilder &Builder) const {
679 // Also include the ARMv8.1-A defines
680 getTargetDefinesARMV81A(Opts, Builder);
681}
682
683void ARMTargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts,
684 MacroBuilder &Builder) const {
685 // Also include the ARMv8.2-A defines
686 Builder.defineMacro(Name: "__ARM_FEATURE_COMPLEX", Value: "1");
687 getTargetDefinesARMV82A(Opts, Builder);
688}
689
690void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
691 MacroBuilder &Builder) const {
692 // Target identification.
693 Builder.defineMacro(Name: "__arm");
694 Builder.defineMacro(Name: "__arm__");
695 // For bare-metal none-eabi.
696 if (getTriple().getOS() == llvm::Triple::UnknownOS &&
697 (getTriple().getEnvironment() == llvm::Triple::EABI ||
698 getTriple().getEnvironment() == llvm::Triple::EABIHF) &&
699 Opts.CPlusPlus) {
700 Builder.defineMacro(Name: "_GNU_SOURCE");
701 }
702
703 // Target properties.
704 Builder.defineMacro(Name: "__REGISTER_PREFIX__", Value: "");
705
706 // Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU
707 // happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__.
708 if (getTriple().isWatchABI())
709 Builder.defineMacro(Name: "__ARM_ARCH_7K__", Value: "2");
710
711 if (!CPUAttr.empty())
712 Builder.defineMacro(Name: "__ARM_ARCH_" + CPUAttr + "__");
713
714 // ACLE 6.4.1 ARM/Thumb instruction set architecture
715 // __ARM_ARCH is defined as an integer value indicating the current ARM ISA
716 Builder.defineMacro(Name: "__ARM_ARCH", Value: Twine(ArchVersion));
717
718 if (ArchVersion >= 8) {
719 // ACLE 6.5.7 Crypto Extension
720 // The __ARM_FEATURE_CRYPTO is deprecated in favor of finer grained
721 // feature macros for AES and SHA2
722 if (SHA2 && AES)
723 Builder.defineMacro(Name: "__ARM_FEATURE_CRYPTO", Value: "1");
724 if (SHA2)
725 Builder.defineMacro(Name: "__ARM_FEATURE_SHA2", Value: "1");
726 if (AES)
727 Builder.defineMacro(Name: "__ARM_FEATURE_AES", Value: "1");
728 // ACLE 6.5.8 CRC32 Extension
729 if (CRC)
730 Builder.defineMacro(Name: "__ARM_FEATURE_CRC32", Value: "1");
731 // ACLE 6.5.10 Numeric Maximum and Minimum
732 Builder.defineMacro(Name: "__ARM_FEATURE_NUMERIC_MAXMIN", Value: "1");
733 // ACLE 6.5.9 Directed Rounding
734 Builder.defineMacro(Name: "__ARM_FEATURE_DIRECTED_ROUNDING", Value: "1");
735 }
736
737 // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA. It
738 // is not defined for the M-profile.
739 // NOTE that the default profile is assumed to be 'A'
740 if (CPUProfile.empty() || ArchProfile != llvm::ARM::ProfileKind::M)
741 Builder.defineMacro(Name: "__ARM_ARCH_ISA_ARM", Value: "1");
742
743 // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original
744 // Thumb ISA (including v6-M and v8-M Baseline). It is set to 2 if the
745 // core supports the Thumb-2 ISA as found in the v6T2 architecture and all
746 // v7 and v8 architectures excluding v8-M Baseline.
747 if (supportsThumb2())
748 Builder.defineMacro(Name: "__ARM_ARCH_ISA_THUMB", Value: "2");
749 else if (supportsThumb())
750 Builder.defineMacro(Name: "__ARM_ARCH_ISA_THUMB", Value: "1");
751
752 // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit
753 // instruction set such as ARM or Thumb.
754 Builder.defineMacro(Name: "__ARM_32BIT_STATE", Value: "1");
755
756 // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex)
757
758 // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset.
759 if (!CPUProfile.empty())
760 Builder.defineMacro(Name: "__ARM_ARCH_PROFILE", Value: "'" + CPUProfile + "'");
761
762 // ACLE 6.4.3 Unaligned access supported in hardware
763 if (HasUnalignedAccess)
764 Builder.defineMacro(Name: "__ARM_FEATURE_UNALIGNED", Value: "1");
765
766 // ACLE 6.4.4 LDREX/STREX
767 if (LDREX)
768 Builder.defineMacro(Name: "__ARM_FEATURE_LDREX", Value: "0x" + Twine::utohexstr(Val: LDREX));
769
770 // ACLE 6.4.5 CLZ
771 if (ArchVersion == 5 || (ArchVersion == 6 && CPUProfile != "M") ||
772 ArchVersion > 6)
773 Builder.defineMacro(Name: "__ARM_FEATURE_CLZ", Value: "1");
774
775 // ACLE 6.5.1 Hardware Floating Point
776 if (HW_FP)
777 Builder.defineMacro(Name: "__ARM_FP", Value: "0x" + Twine::utohexstr(Val: HW_FP));
778
779 // ACLE predefines.
780 Builder.defineMacro(Name: "__ARM_ACLE", Value: "200");
781
782 // FP16 support (we currently only support IEEE format).
783 Builder.defineMacro(Name: "__ARM_FP16_FORMAT_IEEE", Value: "1");
784 Builder.defineMacro(Name: "__ARM_FP16_ARGS", Value: "1");
785
786 // ACLE 6.5.3 Fused multiply-accumulate (FMA)
787 if (ArchVersion >= 7 && (FPU & VFP4FPU))
788 Builder.defineMacro(Name: "__ARM_FEATURE_FMA", Value: "1");
789
790 // Subtarget options.
791
792 // FIXME: It's more complicated than this and we don't really support
793 // interworking.
794 // Windows on ARM does not "support" interworking
795 if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows())
796 Builder.defineMacro(Name: "__THUMB_INTERWORK__");
797
798 if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {
799 // Embedded targets on Darwin follow AAPCS, but not EABI.
800 // Windows on ARM follows AAPCS VFP, but does not conform to EABI.
801 if (!getTriple().isOSBinFormatMachO() && !getTriple().isOSWindows())
802 Builder.defineMacro(Name: "__ARM_EABI__");
803 Builder.defineMacro(Name: "__ARM_PCS", Value: "1");
804 }
805
806 if ((!SoftFloat && !SoftFloatABI) || ABI == "aapcs-vfp" || ABI == "aapcs16")
807 Builder.defineMacro(Name: "__ARM_PCS_VFP", Value: "1");
808
809 if (SoftFloat || (SoftFloatABI && !FPU))
810 Builder.defineMacro(Name: "__SOFTFP__");
811
812 // ACLE position independent code macros.
813 if (Opts.ROPI)
814 Builder.defineMacro(Name: "__ARM_ROPI", Value: "1");
815 if (Opts.RWPI)
816 Builder.defineMacro(Name: "__ARM_RWPI", Value: "1");
817
818 // Macros for enabling co-proc intrinsics
819 uint64_t FeatureCoprocBF = 0;
820 switch (ArchKind) {
821 default:
822 break;
823 case llvm::ARM::ArchKind::ARMV4:
824 case llvm::ARM::ArchKind::ARMV4T:
825 // Filter __arm_ldcl and __arm_stcl in acle.h
826 FeatureCoprocBF = isThumb() ? 0 : FEATURE_COPROC_B1;
827 break;
828 case llvm::ARM::ArchKind::ARMV5T:
829 FeatureCoprocBF = isThumb() ? 0 : FEATURE_COPROC_B1 | FEATURE_COPROC_B2;
830 break;
831 case llvm::ARM::ArchKind::ARMV5TE:
832 case llvm::ARM::ArchKind::ARMV5TEJ:
833 if (!isThumb())
834 FeatureCoprocBF =
835 FEATURE_COPROC_B1 | FEATURE_COPROC_B2 | FEATURE_COPROC_B3;
836 break;
837 case llvm::ARM::ArchKind::ARMV6:
838 case llvm::ARM::ArchKind::ARMV6K:
839 case llvm::ARM::ArchKind::ARMV6KZ:
840 case llvm::ARM::ArchKind::ARMV6T2:
841 if (!isThumb() || ArchKind == llvm::ARM::ArchKind::ARMV6T2)
842 FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 |
843 FEATURE_COPROC_B3 | FEATURE_COPROC_B4;
844 break;
845 case llvm::ARM::ArchKind::ARMV7A:
846 case llvm::ARM::ArchKind::ARMV7R:
847 case llvm::ARM::ArchKind::ARMV7M:
848 case llvm::ARM::ArchKind::ARMV7S:
849 case llvm::ARM::ArchKind::ARMV7EM:
850 FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 |
851 FEATURE_COPROC_B3 | FEATURE_COPROC_B4;
852 break;
853 case llvm::ARM::ArchKind::ARMV8A:
854 case llvm::ARM::ArchKind::ARMV8R:
855 case llvm::ARM::ArchKind::ARMV8_1A:
856 case llvm::ARM::ArchKind::ARMV8_2A:
857 case llvm::ARM::ArchKind::ARMV8_3A:
858 case llvm::ARM::ArchKind::ARMV8_4A:
859 case llvm::ARM::ArchKind::ARMV8_5A:
860 case llvm::ARM::ArchKind::ARMV8_6A:
861 case llvm::ARM::ArchKind::ARMV8_7A:
862 case llvm::ARM::ArchKind::ARMV8_8A:
863 case llvm::ARM::ArchKind::ARMV8_9A:
864 case llvm::ARM::ArchKind::ARMV9A:
865 case llvm::ARM::ArchKind::ARMV9_1A:
866 case llvm::ARM::ArchKind::ARMV9_2A:
867 case llvm::ARM::ArchKind::ARMV9_3A:
868 case llvm::ARM::ArchKind::ARMV9_4A:
869 case llvm::ARM::ArchKind::ARMV9_5A:
870 case llvm::ARM::ArchKind::ARMV9_6A:
871 case llvm::ARM::ArchKind::ARMV9_7A:
872 // Filter __arm_cdp, __arm_ldcl, __arm_stcl in arm_acle.h
873 FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B3;
874 break;
875 case llvm::ARM::ArchKind::ARMV8MMainline:
876 case llvm::ARM::ArchKind::ARMV8_1MMainline:
877 FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 |
878 FEATURE_COPROC_B3 | FEATURE_COPROC_B4;
879 break;
880 }
881 Builder.defineMacro(Name: "__ARM_FEATURE_COPROC",
882 Value: "0x" + Twine::utohexstr(Val: FeatureCoprocBF));
883
884 if (ArchKind == llvm::ARM::ArchKind::XSCALE)
885 Builder.defineMacro(Name: "__XSCALE__");
886
887 if (isThumb()) {
888 Builder.defineMacro(Name: "__THUMBEL__");
889 Builder.defineMacro(Name: "__thumb__");
890 if (supportsThumb2())
891 Builder.defineMacro(Name: "__thumb2__");
892 }
893
894 // ACLE 6.4.9 32-bit SIMD instructions
895 if ((CPUProfile != "M" && ArchVersion >= 6) || (CPUProfile == "M" && DSP))
896 Builder.defineMacro(Name: "__ARM_FEATURE_SIMD32", Value: "1");
897
898 // ACLE 6.4.10 Hardware Integer Divide
899 if (((HWDiv & HWDivThumb) && isThumb()) ||
900 ((HWDiv & HWDivARM) && !isThumb())) {
901 Builder.defineMacro(Name: "__ARM_FEATURE_IDIV", Value: "1");
902 Builder.defineMacro(Name: "__ARM_ARCH_EXT_IDIV__", Value: "1");
903 }
904
905 // Note, this is always on in gcc, even though it doesn't make sense.
906 Builder.defineMacro(Name: "__APCS_32__");
907
908 // __VFP_FP__ means that the floating-point format is VFP, not that a hardware
909 // FPU is present. Moreover, the VFP format is the only one supported by
910 // clang. For these reasons, this macro is always defined.
911 Builder.defineMacro(Name: "__VFP_FP__");
912
913 if (FPUModeIsVFP(Mode: (FPUMode)FPU)) {
914 if (FPU & VFP2FPU)
915 Builder.defineMacro(Name: "__ARM_VFPV2__");
916 if (FPU & VFP3FPU)
917 Builder.defineMacro(Name: "__ARM_VFPV3__");
918 if (FPU & VFP4FPU)
919 Builder.defineMacro(Name: "__ARM_VFPV4__");
920 if (FPU & FPARMV8)
921 Builder.defineMacro(Name: "__ARM_FPV5__");
922 }
923
924 // This only gets set when Neon instructions are actually available, unlike
925 // the VFP define, hence the soft float and arch check. This is subtly
926 // different from gcc, we follow the intent which was that it should be set
927 // when Neon instructions are actually available.
928 if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) {
929 Builder.defineMacro(Name: "__ARM_NEON", Value: "1");
930 Builder.defineMacro(Name: "__ARM_NEON__");
931 // current AArch32 NEON implementations do not support double-precision
932 // floating-point even when it is present in VFP.
933 Builder.defineMacro(Name: "__ARM_NEON_FP",
934 Value: "0x" + Twine::utohexstr(Val: HW_FP & ~HW_FP_DP));
935 }
936
937 if (hasMVE()) {
938 Builder.defineMacro(Name: "__ARM_FEATURE_MVE", Value: hasMVEFloat() ? "3" : "1");
939 }
940
941 if (hasCDE()) {
942 Builder.defineMacro(Name: "__ARM_FEATURE_CDE", Value: "1");
943 Builder.defineMacro(Name: "__ARM_FEATURE_CDE_COPROC",
944 Value: "0x" + Twine::utohexstr(Val: getARMCDECoprocMask()));
945 }
946
947 Builder.defineMacro(Name: "__ARM_SIZEOF_WCHAR_T",
948 Value: Twine(Opts.WCharSize ? Opts.WCharSize : 4));
949
950 Builder.defineMacro(Name: "__ARM_SIZEOF_MINIMAL_ENUM", Value: Opts.ShortEnums ? "1" : "4");
951
952 // CMSE
953 if (ArchVersion == 8 && ArchProfile == llvm::ARM::ProfileKind::M)
954 Builder.defineMacro(Name: "__ARM_FEATURE_CMSE", Value: Opts.Cmse ? "3" : "1");
955
956 if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE") {
957 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
958 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
959 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
960 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
961 }
962
963 // ACLE 6.4.7 DSP instructions
964 if (DSP) {
965 Builder.defineMacro(Name: "__ARM_FEATURE_DSP", Value: "1");
966 }
967
968 // ACLE 6.4.8 Saturation instructions
969 bool SAT = false;
970 if ((ArchVersion == 6 && CPUProfile != "M") || ArchVersion > 6) {
971 Builder.defineMacro(Name: "__ARM_FEATURE_SAT", Value: "1");
972 SAT = true;
973 }
974
975 // ACLE 6.4.6 Q (saturation) flag
976 if (DSP || SAT)
977 Builder.defineMacro(Name: "__ARM_FEATURE_QBIT", Value: "1");
978
979 if (Opts.UnsafeFPMath)
980 Builder.defineMacro(Name: "__ARM_FP_FAST", Value: "1");
981
982 // Armv8.2-A FP16 vector intrinsic
983 if ((FPU & NeonFPU) && HasFastHalfType)
984 Builder.defineMacro(Name: "__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", Value: "1");
985
986 // Armv8.2-A FP16 scalar intrinsics
987 if (HasFastHalfType)
988 Builder.defineMacro(Name: "__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", Value: "1");
989
990 // Armv8.2-A dot product intrinsics
991 if (DotProd)
992 Builder.defineMacro(Name: "__ARM_FEATURE_DOTPROD", Value: "1");
993
994 if (HasMatMul)
995 Builder.defineMacro(Name: "__ARM_FEATURE_MATMUL_INT8", Value: "1");
996
997 if (HasPAC)
998 Builder.defineMacro(Name: "__ARM_FEATURE_PAUTH", Value: "1");
999
1000 if (HasBTI)
1001 Builder.defineMacro(Name: "__ARM_FEATURE_BTI", Value: "1");
1002
1003 if (HasBFloat16) {
1004 Builder.defineMacro(Name: "__ARM_FEATURE_BF16", Value: "1");
1005 Builder.defineMacro(Name: "__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", Value: "1");
1006 Builder.defineMacro(Name: "__ARM_BF16_FORMAT_ALTERNATIVE", Value: "1");
1007 }
1008
1009 if (Opts.BranchTargetEnforcement)
1010 Builder.defineMacro(Name: "__ARM_FEATURE_BTI_DEFAULT", Value: "1");
1011
1012 if (Opts.hasSignReturnAddress()) {
1013 unsigned Value = 1;
1014 if (Opts.isSignReturnAddressScopeAll())
1015 Value |= 1 << 2;
1016 Builder.defineMacro(Name: "__ARM_FEATURE_PAC_DEFAULT", Value: Twine(Value));
1017 }
1018
1019 switch (ArchKind) {
1020 default:
1021 break;
1022 case llvm::ARM::ArchKind::ARMV8_1A:
1023 getTargetDefinesARMV81A(Opts, Builder);
1024 break;
1025 case llvm::ARM::ArchKind::ARMV8_2A:
1026 getTargetDefinesARMV82A(Opts, Builder);
1027 break;
1028 case llvm::ARM::ArchKind::ARMV8_3A:
1029 case llvm::ARM::ArchKind::ARMV8_4A:
1030 case llvm::ARM::ArchKind::ARMV8_5A:
1031 case llvm::ARM::ArchKind::ARMV8_6A:
1032 case llvm::ARM::ArchKind::ARMV8_7A:
1033 case llvm::ARM::ArchKind::ARMV8_8A:
1034 case llvm::ARM::ArchKind::ARMV8_9A:
1035 case llvm::ARM::ArchKind::ARMV9A:
1036 case llvm::ARM::ArchKind::ARMV9_1A:
1037 case llvm::ARM::ArchKind::ARMV9_2A:
1038 case llvm::ARM::ArchKind::ARMV9_3A:
1039 case llvm::ARM::ArchKind::ARMV9_4A:
1040 case llvm::ARM::ArchKind::ARMV9_5A:
1041 case llvm::ARM::ArchKind::ARMV9_6A:
1042 case llvm::ARM::ArchKind::ARMV9_7A:
1043 getTargetDefinesARMV83A(Opts, Builder);
1044 break;
1045 }
1046}
1047
1048static constexpr int NumBuiltins = ARM::LastTSBuiltin - Builtin::FirstTSBuiltin;
1049static constexpr int NumNeonBuiltins =
1050 NEON::FirstFp16Builtin - Builtin::FirstTSBuiltin;
1051static constexpr int NumFp16Builtins =
1052 NEON::FirstTSBuiltin - NEON::FirstFp16Builtin;
1053static constexpr int NumMVEBuiltins =
1054 ARM::FirstCDEBuiltin - NEON::FirstTSBuiltin;
1055static constexpr int NumCDEBuiltins =
1056 ARM::FirstARMBuiltin - ARM::FirstCDEBuiltin;
1057static constexpr int NumARMBuiltins = ARM::LastTSBuiltin - ARM::FirstARMBuiltin;
1058static_assert(NumBuiltins ==
1059 (NumNeonBuiltins + NumFp16Builtins + NumMVEBuiltins +
1060 NumCDEBuiltins + NumARMBuiltins));
1061
1062namespace clang {
1063namespace NEON {
1064#define GET_NEON_BUILTIN_STR_TABLE
1065#include "clang/Basic/arm_neon.inc"
1066#undef GET_NEON_BUILTIN_STR_TABLE
1067
1068static constexpr std::array<Builtin::Info, NumNeonBuiltins> BuiltinInfos = {
1069#define GET_NEON_BUILTIN_INFOS
1070#include "clang/Basic/arm_neon.inc"
1071#undef GET_NEON_BUILTIN_INFOS
1072};
1073
1074namespace FP16 {
1075#define GET_NEON_BUILTIN_STR_TABLE
1076#include "clang/Basic/arm_fp16.inc"
1077#undef GET_NEON_BUILTIN_STR_TABLE
1078
1079static constexpr std::array<Builtin::Info, NumFp16Builtins> BuiltinInfos = {
1080#define GET_NEON_BUILTIN_INFOS
1081#include "clang/Basic/arm_fp16.inc"
1082#undef GET_NEON_BUILTIN_INFOS
1083};
1084} // namespace FP16
1085} // namespace NEON
1086} // namespace clang
1087
1088namespace {
1089namespace MVE {
1090#define GET_MVE_BUILTIN_STR_TABLE
1091#include "clang/Basic/arm_mve_builtins.inc"
1092#undef GET_MVE_BUILTIN_STR_TABLE
1093
1094static constexpr std::array<Builtin::Info, NumMVEBuiltins> BuiltinInfos = {
1095#define GET_MVE_BUILTIN_INFOS
1096#include "clang/Basic/arm_mve_builtins.inc"
1097#undef GET_MVE_BUILTIN_INFOS
1098};
1099} // namespace MVE
1100
1101namespace CDE {
1102#define GET_CDE_BUILTIN_STR_TABLE
1103#include "clang/Basic/arm_cde_builtins.inc"
1104#undef GET_CDE_BUILTIN_STR_TABLE
1105
1106static constexpr std::array<Builtin::Info, NumCDEBuiltins> BuiltinInfos = {
1107#define GET_CDE_BUILTIN_INFOS
1108#include "clang/Basic/arm_cde_builtins.inc"
1109#undef GET_CDE_BUILTIN_INFOS
1110};
1111} // namespace CDE
1112} // namespace
1113
1114namespace clang {
1115namespace ARM {
1116
1117#define GET_BUILTIN_STR_TABLE
1118#include "clang/Basic/BuiltinsARM.inc"
1119#undef GET_BUILTIN_STR_TABLE
1120
1121static constexpr Builtin::Info BuiltinInfos[] = {
1122#define GET_BUILTIN_INFOS
1123#include "clang/Basic/BuiltinsARM.inc"
1124#undef GET_BUILTIN_INFOS
1125};
1126
1127static constexpr Builtin::Info PrefixedBuiltinInfos[] = {
1128#define GET_BUILTIN_PREFIXED_INFOS
1129#include "clang/Basic/BuiltinsARM.inc"
1130#undef GET_BUILTIN_PREFIXED_INFOS
1131};
1132
1133static_assert((std::size(BuiltinInfos) + std::size(PrefixedBuiltinInfos)) ==
1134 NumARMBuiltins);
1135
1136} // namespace ARM
1137} // namespace clang
1138
1139llvm::SmallVector<Builtin::InfosShard>
1140ARMTargetInfo::getTargetBuiltins() const {
1141 return {
1142 {.Strings: &NEON::BuiltinStrings, .Infos: NEON::BuiltinInfos, .NamePrefix: "__builtin_neon_"},
1143 {.Strings: &NEON::FP16::BuiltinStrings, .Infos: NEON::FP16::BuiltinInfos,
1144 .NamePrefix: "__builtin_neon_"},
1145 {.Strings: &MVE::BuiltinStrings, .Infos: MVE::BuiltinInfos, .NamePrefix: "__builtin_arm_mve_"},
1146 {.Strings: &CDE::BuiltinStrings, .Infos: CDE::BuiltinInfos, .NamePrefix: "__builtin_arm_cde_"},
1147 {.Strings: &ARM::BuiltinStrings, .Infos: ARM::BuiltinInfos},
1148 {.Strings: &ARM::BuiltinStrings, .Infos: ARM::PrefixedBuiltinInfos, .NamePrefix: "__builtin_arm_"},
1149 };
1150}
1151
1152bool ARMTargetInfo::isCLZForZeroUndef() const { return false; }
1153TargetInfo::BuiltinVaListKind ARMTargetInfo::getBuiltinVaListKind() const {
1154 return IsAAPCS
1155 ? AAPCSABIBuiltinVaList
1156 : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList
1157 : TargetInfo::VoidPtrBuiltinVaList);
1158}
1159
1160const char *const ARMTargetInfo::GCCRegNames[] = {
1161 // Integer registers
1162 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
1163 "r12", "sp", "lr", "pc",
1164
1165 // Float registers
1166 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
1167 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
1168 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
1169
1170 // Double registers
1171 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
1172 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
1173 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
1174
1175 // Quad registers
1176 "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11",
1177 "q12", "q13", "q14", "q15"};
1178
1179ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const {
1180 return llvm::ArrayRef(GCCRegNames);
1181}
1182
1183const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
1184 {.Aliases: {"a1"}, .Register: "r0"}, {.Aliases: {"a2"}, .Register: "r1"}, {.Aliases: {"a3"}, .Register: "r2"}, {.Aliases: {"a4"}, .Register: "r3"},
1185 {.Aliases: {"v1"}, .Register: "r4"}, {.Aliases: {"v2"}, .Register: "r5"}, {.Aliases: {"v3"}, .Register: "r6"}, {.Aliases: {"v4"}, .Register: "r7"},
1186 {.Aliases: {"v5"}, .Register: "r8"}, {.Aliases: {"v6", "rfp"}, .Register: "r9"}, {.Aliases: {"sl"}, .Register: "r10"}, {.Aliases: {"fp"}, .Register: "r11"},
1187 {.Aliases: {"ip"}, .Register: "r12"}, {.Aliases: {"r13"}, .Register: "sp"}, {.Aliases: {"r14"}, .Register: "lr"}, {.Aliases: {"r15"}, .Register: "pc"},
1188 // The S, D and Q registers overlap, but aren't really aliases; we
1189 // don't want to substitute one of these for a different-sized one.
1190};
1191
1192ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const {
1193 return llvm::ArrayRef(GCCRegAliases);
1194}
1195
1196bool ARMTargetInfo::validateAsmConstraint(
1197 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
1198 switch (*Name) {
1199 default:
1200 break;
1201 case 'l': // r0-r7 if thumb, r0-r15 if ARM
1202 Info.setAllowsRegister();
1203 return true;
1204 case 'h': // r8-r15, thumb only
1205 if (isThumb()) {
1206 Info.setAllowsRegister();
1207 return true;
1208 }
1209 break;
1210 case 's': // An integer constant, but allowing only relocatable values.
1211 return true;
1212 case 't': // s0-s31, d0-d31, or q0-q15
1213 case 'w': // s0-s15, d0-d7, or q0-q3
1214 case 'x': // s0-s31, d0-d15, or q0-q7
1215 if (FPRegsDisabled)
1216 return false;
1217 Info.setAllowsRegister();
1218 return true;
1219 case 'j': // An immediate integer between 0 and 65535 (valid for MOVW)
1220 // only available in ARMv6T2 and above
1221 if (CPUAttr == "6T2" || ArchVersion >= 7) {
1222 Info.setRequiresImmediate(Min: 0, Max: 65535);
1223 return true;
1224 }
1225 break;
1226 case 'I':
1227 if (isThumb()) {
1228 if (!supportsThumb2())
1229 Info.setRequiresImmediate(Min: 0, Max: 255);
1230 else
1231 // FIXME: should check if immediate value would be valid for a Thumb2
1232 // data-processing instruction
1233 Info.setRequiresImmediate();
1234 } else
1235 // FIXME: should check if immediate value would be valid for an ARM
1236 // data-processing instruction
1237 Info.setRequiresImmediate();
1238 return true;
1239 case 'J':
1240 if (isThumb() && !supportsThumb2())
1241 Info.setRequiresImmediate(Min: -255, Max: -1);
1242 else
1243 Info.setRequiresImmediate(Min: -4095, Max: 4095);
1244 return true;
1245 case 'K':
1246 if (isThumb()) {
1247 if (!supportsThumb2())
1248 // FIXME: should check if immediate value can be obtained from shifting
1249 // a value between 0 and 255 left by any amount
1250 Info.setRequiresImmediate();
1251 else
1252 // FIXME: should check if immediate value would be valid for a Thumb2
1253 // data-processing instruction when inverted
1254 Info.setRequiresImmediate();
1255 } else
1256 // FIXME: should check if immediate value would be valid for an ARM
1257 // data-processing instruction when inverted
1258 Info.setRequiresImmediate();
1259 return true;
1260 case 'L':
1261 if (isThumb()) {
1262 if (!supportsThumb2())
1263 Info.setRequiresImmediate(Min: -7, Max: 7);
1264 else
1265 // FIXME: should check if immediate value would be valid for a Thumb2
1266 // data-processing instruction when negated
1267 Info.setRequiresImmediate();
1268 } else
1269 // FIXME: should check if immediate value would be valid for an ARM
1270 // data-processing instruction when negated
1271 Info.setRequiresImmediate();
1272 return true;
1273 case 'M':
1274 if (isThumb() && !supportsThumb2())
1275 // FIXME: should check if immediate value is a multiple of 4 between 0 and
1276 // 1020
1277 Info.setRequiresImmediate();
1278 else
1279 // FIXME: should check if immediate value is a power of two or a integer
1280 // between 0 and 32
1281 Info.setRequiresImmediate();
1282 return true;
1283 case 'N':
1284 // Thumb1 only
1285 if (isThumb() && !supportsThumb2()) {
1286 Info.setRequiresImmediate(Min: 0, Max: 31);
1287 return true;
1288 }
1289 break;
1290 case 'O':
1291 // Thumb1 only
1292 if (isThumb() && !supportsThumb2()) {
1293 // FIXME: should check if immediate value is a multiple of 4 between -508
1294 // and 508
1295 Info.setRequiresImmediate();
1296 return true;
1297 }
1298 break;
1299 case 'Q': // A memory address that is a single base register.
1300 Info.setAllowsMemory();
1301 return true;
1302 case 'T':
1303 switch (Name[1]) {
1304 default:
1305 break;
1306 case 'e': // Even general-purpose register
1307 case 'o': // Odd general-purpose register
1308 Info.setAllowsRegister();
1309 Name++;
1310 return true;
1311 }
1312 break;
1313 case 'U': // a memory reference...
1314 switch (Name[1]) {
1315 case 'q': // ...ARMV4 ldrsb
1316 case 'v': // ...VFP load/store (reg+constant offset)
1317 case 'y': // ...iWMMXt load/store
1318 case 't': // address valid for load/store opaque types wider
1319 // than 128-bits
1320 case 'n': // valid address for Neon doubleword vector load/store
1321 case 'm': // valid address for Neon element and structure load/store
1322 case 's': // valid address for non-offset loads/stores of quad-word
1323 // values in four ARM registers
1324 Info.setAllowsMemory();
1325 Name++;
1326 return true;
1327 }
1328 break;
1329 }
1330 return false;
1331}
1332
1333std::string ARMTargetInfo::convertConstraint(const char *&Constraint) const {
1334 std::string R;
1335 switch (*Constraint) {
1336 case 'U': // Two-character constraint; add "^" hint for later parsing.
1337 case 'T':
1338 R = std::string("^") + std::string(Constraint, 2);
1339 Constraint++;
1340 break;
1341 case 'p': // 'p' should be translated to 'r' by default.
1342 R = std::string("r");
1343 break;
1344 default:
1345 return std::string(1, *Constraint);
1346 }
1347 return R;
1348}
1349
1350bool ARMTargetInfo::validateConstraintModifier(
1351 StringRef Constraint, char Modifier, unsigned Size,
1352 std::string &SuggestedModifier) const {
1353 bool isOutput = (Constraint[0] == '=');
1354 bool isInOut = (Constraint[0] == '+');
1355
1356 // Strip off constraint modifiers.
1357 Constraint = Constraint.ltrim(Chars: "=+&");
1358
1359 switch (Constraint[0]) {
1360 default:
1361 break;
1362 case 'r': {
1363 switch (Modifier) {
1364 default:
1365 return (isInOut || isOutput || Size <= 64);
1366 case 'q':
1367 // A register of size 32 cannot fit a vector type.
1368 return false;
1369 }
1370 }
1371 }
1372
1373 return true;
1374}
1375std::string_view ARMTargetInfo::getClobbers() const {
1376 // FIXME: Is this really right?
1377 return "";
1378}
1379
1380TargetInfo::CallingConvCheckResult
1381ARMTargetInfo::checkCallingConvention(CallingConv CC) const {
1382 switch (CC) {
1383 case CC_AAPCS:
1384 case CC_AAPCS_VFP:
1385 case CC_Swift:
1386 case CC_SwiftAsync:
1387 case CC_DeviceKernel:
1388 return CCCR_OK;
1389 default:
1390 return CCCR_Warning;
1391 }
1392}
1393
1394int ARMTargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
1395 if (RegNo == 0)
1396 return 0;
1397 if (RegNo == 1)
1398 return 1;
1399 return -1;
1400}
1401
1402bool ARMTargetInfo::hasSjLjLowering() const { return true; }
1403
1404ARMleTargetInfo::ARMleTargetInfo(const llvm::Triple &Triple,
1405 const TargetOptions &Opts)
1406 : ARMTargetInfo(Triple, Opts) {}
1407
1408void ARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
1409 MacroBuilder &Builder) const {
1410 Builder.defineMacro(Name: "__ARMEL__");
1411 ARMTargetInfo::getTargetDefines(Opts, Builder);
1412}
1413
1414ARMbeTargetInfo::ARMbeTargetInfo(const llvm::Triple &Triple,
1415 const TargetOptions &Opts)
1416 : ARMTargetInfo(Triple, Opts) {}
1417
1418void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts,
1419 MacroBuilder &Builder) const {
1420 Builder.defineMacro(Name: "__ARMEB__");
1421 Builder.defineMacro(Name: "__ARM_BIG_ENDIAN");
1422 ARMTargetInfo::getTargetDefines(Opts, Builder);
1423}
1424
1425WindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple,
1426 const TargetOptions &Opts)
1427 : WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) {
1428}
1429
1430void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts,
1431 MacroBuilder &Builder) const {
1432 // FIXME: this is invalid for WindowsCE
1433 Builder.defineMacro(Name: "_M_ARM_NT", Value: "1");
1434 Builder.defineMacro(Name: "_M_ARMT", Value: "_M_ARM");
1435 Builder.defineMacro(Name: "_M_THUMB", Value: "_M_ARM");
1436
1437 assert((Triple.getArch() == llvm::Triple::arm ||
1438 Triple.getArch() == llvm::Triple::thumb) &&
1439 "invalid architecture for Windows ARM target info");
1440 unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
1441 Builder.defineMacro(Name: "_M_ARM", Value: Triple.getArchName().substr(Start: Offset));
1442
1443 // TODO map the complete set of values
1444 // 31: VFPv3 40: VFPv4
1445 Builder.defineMacro(Name: "_M_ARM_FP", Value: "31");
1446}
1447
1448TargetInfo::BuiltinVaListKind
1449WindowsARMTargetInfo::getBuiltinVaListKind() const {
1450 return TargetInfo::CharPtrBuiltinVaList;
1451}
1452
1453TargetInfo::CallingConvCheckResult
1454WindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const {
1455 switch (CC) {
1456 case CC_X86StdCall:
1457 case CC_X86ThisCall:
1458 case CC_X86FastCall:
1459 case CC_X86VectorCall:
1460 return CCCR_Ignore;
1461 case CC_C:
1462 case CC_DeviceKernel:
1463 case CC_PreserveMost:
1464 case CC_PreserveAll:
1465 case CC_Swift:
1466 case CC_SwiftAsync:
1467 return CCCR_OK;
1468 default:
1469 return CCCR_Warning;
1470 }
1471}
1472
1473// Windows ARM + Itanium C++ ABI Target
1474ItaniumWindowsARMleTargetInfo::ItaniumWindowsARMleTargetInfo(
1475 const llvm::Triple &Triple, const TargetOptions &Opts)
1476 : WindowsARMTargetInfo(Triple, Opts) {
1477 TheCXXABI.set(TargetCXXABI::GenericARM);
1478}
1479
1480void ItaniumWindowsARMleTargetInfo::getTargetDefines(
1481 const LangOptions &Opts, MacroBuilder &Builder) const {
1482 WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
1483
1484 if (Opts.MSVCCompat)
1485 WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
1486}
1487
1488// Windows ARM, MS (C++) ABI
1489MicrosoftARMleTargetInfo::MicrosoftARMleTargetInfo(const llvm::Triple &Triple,
1490 const TargetOptions &Opts)
1491 : WindowsARMTargetInfo(Triple, Opts) {
1492 TheCXXABI.set(TargetCXXABI::Microsoft);
1493}
1494
1495void MicrosoftARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
1496 MacroBuilder &Builder) const {
1497 WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
1498 WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
1499}
1500
1501MinGWARMTargetInfo::MinGWARMTargetInfo(const llvm::Triple &Triple,
1502 const TargetOptions &Opts)
1503 : WindowsARMTargetInfo(Triple, Opts) {
1504 TheCXXABI.set(TargetCXXABI::GenericARM);
1505}
1506
1507void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts,
1508 MacroBuilder &Builder) const {
1509 WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
1510 Builder.defineMacro(Name: "_ARM_");
1511}
1512
1513CygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple,
1514 const TargetOptions &Opts)
1515 : ARMleTargetInfo(Triple, Opts) {
1516 this->WCharType = TargetInfo::UnsignedShort;
1517 TLSSupported = false;
1518 DoubleAlign = LongLongAlign = 64;
1519 resetDataLayout();
1520}
1521
1522void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts,
1523 MacroBuilder &Builder) const {
1524 ARMleTargetInfo::getTargetDefines(Opts, Builder);
1525 Builder.defineMacro(Name: "_ARM_");
1526 Builder.defineMacro(Name: "__CYGWIN__");
1527 Builder.defineMacro(Name: "__CYGWIN32__");
1528 DefineStd(Builder, MacroName: "unix", Opts);
1529 if (Opts.CPlusPlus)
1530 Builder.defineMacro(Name: "_GNU_SOURCE");
1531}
1532
1533AppleMachOARMTargetInfo::AppleMachOARMTargetInfo(const llvm::Triple &Triple,
1534 const TargetOptions &Opts)
1535 : AppleMachOTargetInfo<ARMleTargetInfo>(Triple, Opts) {}
1536
1537void AppleMachOARMTargetInfo::getOSDefines(const LangOptions &Opts,
1538 const llvm::Triple &Triple,
1539 MacroBuilder &Builder) const {
1540 getAppleMachODefines(Builder, Opts, Triple);
1541}
1542
1543DarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple,
1544 const TargetOptions &Opts)
1545 : DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) {
1546 HasAlignMac68kSupport = true;
1547 if (Triple.isWatchABI()) {
1548 // Darwin on iOS uses a variant of the ARM C++ ABI.
1549 TheCXXABI.set(TargetCXXABI::WatchOS);
1550
1551 // BOOL should be a real boolean on the new ABI
1552 UseSignedCharForObjCBool = false;
1553 } else
1554 TheCXXABI.set(TargetCXXABI::iOS);
1555}
1556
1557void DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts,
1558 const llvm::Triple &Triple,
1559 MacroBuilder &Builder) const {
1560 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
1561}
1562