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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

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