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