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