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

source code of clang/lib/Basic/Targets/ARM.cpp