1//===--- AArch64.cpp - Implement AArch64 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 AArch64 TargetInfo objects.
10//
11//===----------------------------------------------------------------------===//
12
13#include "AArch64.h"
14#include "clang/Basic/Diagnostic.h"
15#include "clang/Basic/LangOptions.h"
16#include "clang/Basic/TargetBuiltins.h"
17#include "clang/Basic/TargetInfo.h"
18#include "llvm/ADT/APSInt.h"
19#include "llvm/ADT/ArrayRef.h"
20#include "llvm/ADT/StringSwitch.h"
21#include "llvm/TargetParser/AArch64TargetParser.h"
22#include "llvm/TargetParser/ARMTargetParserCommon.h"
23#include <optional>
24
25using namespace clang;
26using namespace clang::targets;
27
28static constexpr int NumNeonBuiltins =
29 NEON::FirstFp16Builtin - Builtin::FirstTSBuiltin;
30static constexpr int NumFp16Builtins =
31 NEON::FirstTSBuiltin - NEON::FirstFp16Builtin;
32static constexpr int NumSVEBuiltins =
33 SVE::FirstNeonBridgeBuiltin - NEON::FirstTSBuiltin;
34static constexpr int NumSVENeonBridgeBuiltins =
35 SVE::FirstTSBuiltin - SVE::FirstNeonBridgeBuiltin;
36static constexpr int NumSMEBuiltins = SME::FirstTSBuiltin - SVE::FirstTSBuiltin;
37static constexpr int NumAArch64Builtins =
38 AArch64::LastTSBuiltin - SME::FirstTSBuiltin;
39static constexpr int NumBuiltins =
40 AArch64::LastTSBuiltin - Builtin::FirstTSBuiltin;
41static_assert(NumBuiltins ==
42 (NumNeonBuiltins + NumFp16Builtins + NumSVEBuiltins +
43 NumSVENeonBridgeBuiltins + NumSMEBuiltins + NumAArch64Builtins));
44
45namespace clang {
46namespace AArch64 {
47#define GET_BUILTIN_STR_TABLE
48#include "clang/Basic/BuiltinsAArch64.inc"
49#undef GET_BUILTIN_STR_TABLE
50
51static constexpr Builtin::Info BuiltinInfos[] = {
52#define GET_BUILTIN_INFOS
53#include "clang/Basic/BuiltinsAArch64.inc"
54#undef GET_BUILTIN_INFOS
55};
56
57static constexpr Builtin::Info PrefixedBuiltinInfos[] = {
58#define GET_BUILTIN_PREFIXED_INFOS
59#include "clang/Basic/BuiltinsAArch64.inc"
60#undef GET_BUILTIN_PREFIXED_INFOS
61};
62static_assert((std::size(BuiltinInfos) + std::size(PrefixedBuiltinInfos)) ==
63 NumAArch64Builtins);
64} // namespace AArch64
65
66namespace NEON {
67#define GET_NEON_BUILTIN_STR_TABLE
68#include "clang/Basic/arm_neon.inc"
69#undef GET_NEON_BUILTIN_STR_TABLE
70
71static constexpr std::array<Builtin::Info, NumNeonBuiltins> BuiltinInfos = {
72#define GET_NEON_BUILTIN_INFOS
73#include "clang/Basic/arm_neon.inc"
74#undef GET_NEON_BUILTIN_INFOS
75};
76
77namespace FP16 {
78#define GET_NEON_BUILTIN_STR_TABLE
79#include "clang/Basic/arm_fp16.inc"
80#undef GET_NEON_BUILTIN_STR_TABLE
81
82static constexpr std::array<Builtin::Info, NumFp16Builtins> BuiltinInfos = {
83#define GET_NEON_BUILTIN_INFOS
84#include "clang/Basic/arm_fp16.inc"
85#undef GET_NEON_BUILTIN_INFOS
86};
87} // namespace FP16
88} // namespace NEON
89
90namespace SVE {
91#define GET_SVE_BUILTIN_STR_TABLE
92#include "clang/Basic/arm_sve_builtins.inc"
93#undef GET_SVE_BUILTIN_STR_TABLE
94
95static constexpr std::array<Builtin::Info, NumSVEBuiltins> BuiltinInfos = {
96#define GET_SVE_BUILTIN_INFOS
97#include "clang/Basic/arm_sve_builtins.inc"
98#undef GET_SVE_BUILTIN_INFOS
99};
100} // namespace SVE
101
102namespace SME {
103#define GET_SME_BUILTIN_STR_TABLE
104#include "clang/Basic/arm_sme_builtins.inc"
105#undef GET_SME_BUILTIN_STR_TABLE
106
107static constexpr std::array<Builtin::Info, NumSMEBuiltins> BuiltinInfos = {
108#define GET_SME_BUILTIN_INFOS
109#include "clang/Basic/arm_sme_builtins.inc"
110#undef GET_SME_BUILTIN_INFOS
111};
112} // namespace SME
113} // namespace clang
114
115static constexpr llvm::StringTable BuiltinSVENeonBridgeStrings =
116 CLANG_BUILTIN_STR_TABLE_START
117#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_STR_TABLE
118#define GET_SVE_BUILTINS
119#include "clang/Basic/BuiltinsAArch64NeonSVEBridge.def"
120#undef GET_SVE_BUILTINS
121#undef TARGET_BUILTIN
122 ;
123
124static constexpr auto BuiltinSVENeonBridgeInfos =
125 Builtin::MakeInfos<NumSVENeonBridgeBuiltins>(Infos: {
126#define TARGET_BUILTIN CLANG_TARGET_BUILTIN_ENTRY
127#define GET_SVE_BUILTINS
128#include "clang/Basic/BuiltinsAArch64NeonSVEBridge.def"
129#undef GET_SVE_BUILTINS
130#undef TARGET_BUILTIN
131 });
132
133AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
134 const TargetOptions &Opts)
135 : TargetInfo(Triple), ABI("aapcs") {
136 if (getTriple().isOSOpenBSD()) {
137 Int64Type = SignedLongLong;
138 IntMaxType = SignedLongLong;
139 } else {
140 if (!getTriple().isOSDarwin() && !getTriple().isOSNetBSD())
141 WCharType = UnsignedInt;
142
143 Int64Type = SignedLong;
144 IntMaxType = SignedLong;
145 }
146
147 AddrSpaceMap = &ARM64AddrSpaceMap;
148
149 // All AArch64 implementations support ARMv8 FP, which makes half a legal type.
150 HasFastHalfType = true;
151 HalfArgsAndReturns = true;
152 HasFloat16 = true;
153 HasStrictFP = true;
154
155 if (Triple.isArch64Bit())
156 LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
157 else
158 LongWidth = LongAlign = PointerWidth = PointerAlign = 32;
159
160 BitIntMaxAlign = 128;
161 MaxVectorAlign = 128;
162 MaxAtomicInlineWidth = 128;
163 MaxAtomicPromoteWidth = 128;
164
165 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
166 LongDoubleFormat = &llvm::APFloat::IEEEquad();
167
168 BFloat16Width = BFloat16Align = 16;
169 BFloat16Format = &llvm::APFloat::BFloat();
170
171 // Make __builtin_ms_va_list available.
172 HasBuiltinMSVaList = true;
173
174 // Make the Neon ACLE and SVE types available. Note that this deliberately
175 // doesn't depend on SveMode, since in principle it should be possible to turn
176 // SVE on and off within a translation unit. It should also be possible
177 // to compile the global declaration:
178 //
179 // __SVInt8_t *ptr;
180 //
181 // even without SVE.
182 HasAArch64ACLETypes = true;
183
184 // {} in inline assembly are neon specifiers, not assembly variant
185 // specifiers.
186 NoAsmVariants = true;
187
188 // AAPCS gives rules for bitfields. 7.1.7 says: "The container type
189 // contributes to the alignment of the containing aggregate in the same way
190 // a plain (non bit-field) member of that type would, without exception for
191 // zero-sized or anonymous bit-fields."
192 assert(UseBitFieldTypeAlignment && "bitfields affect type alignment");
193 UseZeroLengthBitfieldAlignment = true;
194
195 // AAPCS64 allows any "fundamental integer data type" to be used for
196 // over-sized bitfields, which includes 128-bit integers.
197 LargestOverSizedBitfieldContainer = 128;
198
199 HasUnalignedAccess = true;
200
201 // AArch64 targets default to using the ARM C++ ABI.
202 TheCXXABI.set(TargetCXXABI::GenericAArch64);
203
204 if (Triple.getOS() == llvm::Triple::Linux)
205 this->MCountName = "\01_mcount";
206 else if (Triple.getOS() == llvm::Triple::UnknownOS)
207 this->MCountName =
208 Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
209}
210
211StringRef AArch64TargetInfo::getABI() const { return ABI; }
212
213bool AArch64TargetInfo::setABI(const std::string &Name) {
214 if (Name != "aapcs" && Name != "aapcs-soft" && Name != "darwinpcs")
215 return false;
216
217 ABI = Name;
218 return true;
219}
220
221bool AArch64TargetInfo::validateTarget(DiagnosticsEngine &Diags) const {
222 if (hasFeature(Feature: "fp") && ABI == "aapcs-soft") {
223 // aapcs-soft is not allowed for targets with an FPU, to avoid there being
224 // two incomatible ABIs.
225 Diags.Report(DiagID: diag::err_target_unsupported_abi_with_fpu) << ABI;
226 return false;
227 }
228 return true;
229}
230
231bool AArch64TargetInfo::validateGlobalRegisterVariable(
232 StringRef RegName, unsigned RegSize, bool &HasSizeMismatch) const {
233 if (RegName == "sp") {
234 HasSizeMismatch = RegSize != 64;
235 return true;
236 }
237 if (RegName.starts_with(Prefix: "w"))
238 HasSizeMismatch = RegSize != 32;
239 else if (RegName.starts_with(Prefix: "x"))
240 HasSizeMismatch = RegSize != 64;
241 else
242 return false;
243 StringRef RegNum = RegName.drop_front();
244 // Check if the register is reserved. See also
245 // AArch64TargetLowering::getRegisterByName().
246 return RegNum == "0" ||
247 (RegNum == "18" &&
248 llvm::AArch64::isX18ReservedByDefault(TT: getTriple())) ||
249 getTargetOpts().FeatureMap.lookup(Key: ("reserve-x" + RegNum).str());
250}
251
252bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef,
253 BranchProtectionInfo &BPI,
254 const LangOptions &LO,
255 StringRef &Err) const {
256 llvm::ARM::ParsedBranchProtection PBP;
257 if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err, EnablePAuthLR: HasPAuthLR))
258 return false;
259
260 // GCS is currently untested with ptrauth-returns, but enabling this could be
261 // allowed in future after testing with a suitable system.
262 if (LO.PointerAuthReturns &&
263 (PBP.Scope != "none" || PBP.BranchProtectionPAuthLR ||
264 PBP.GuardedControlStack))
265 return false;
266
267 BPI.SignReturnAddr =
268 llvm::StringSwitch<LangOptions::SignReturnAddressScopeKind>(PBP.Scope)
269 .Case(S: "non-leaf", Value: LangOptions::SignReturnAddressScopeKind::NonLeaf)
270 .Case(S: "all", Value: LangOptions::SignReturnAddressScopeKind::All)
271 .Default(Value: LangOptions::SignReturnAddressScopeKind::None);
272
273 if (PBP.Key == "a_key")
274 BPI.SignKey = LangOptions::SignReturnAddressKeyKind::AKey;
275 else
276 BPI.SignKey = LangOptions::SignReturnAddressKeyKind::BKey;
277
278 BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement;
279 BPI.BranchProtectionPAuthLR = PBP.BranchProtectionPAuthLR;
280 BPI.GuardedControlStack = PBP.GuardedControlStack;
281 return true;
282}
283
284bool AArch64TargetInfo::isValidCPUName(StringRef Name) const {
285 return llvm::AArch64::parseCpu(Name).has_value();
286}
287
288bool AArch64TargetInfo::setCPU(StringRef Name) { return isValidCPUName(Name); }
289
290void AArch64TargetInfo::fillValidCPUList(
291 SmallVectorImpl<StringRef> &Values) const {
292 llvm::AArch64::fillValidCPUArchList(Values);
293}
294
295void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
296 MacroBuilder &Builder) const {
297 Builder.defineMacro(Name: "__ARM_FEATURE_QRDMX", Value: "1");
298}
299
300void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
301 MacroBuilder &Builder) const {
302 // Also include the ARMv8.1 defines
303 getTargetDefinesARMV81A(Opts, Builder);
304}
305
306void AArch64TargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts,
307 MacroBuilder &Builder) const {
308 Builder.defineMacro(Name: "__ARM_FEATURE_COMPLEX", Value: "1");
309 Builder.defineMacro(Name: "__ARM_FEATURE_JCVT", Value: "1");
310 // Also include the Armv8.2 defines
311 getTargetDefinesARMV82A(Opts, Builder);
312}
313
314void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts,
315 MacroBuilder &Builder) const {
316 // Also include the Armv8.3 defines
317 getTargetDefinesARMV83A(Opts, Builder);
318}
319
320void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts,
321 MacroBuilder &Builder) const {
322 Builder.defineMacro(Name: "__ARM_FEATURE_FRINT", Value: "1");
323 // Also include the Armv8.4 defines
324 getTargetDefinesARMV84A(Opts, Builder);
325}
326
327void AArch64TargetInfo::getTargetDefinesARMV86A(const LangOptions &Opts,
328 MacroBuilder &Builder) const {
329 // Also include the Armv8.5 defines
330 // FIXME: Armv8.6 makes the following extensions mandatory:
331 // - __ARM_FEATURE_BF16
332 // - __ARM_FEATURE_MATMUL_INT8
333 // Handle them here.
334 getTargetDefinesARMV85A(Opts, Builder);
335}
336
337void AArch64TargetInfo::getTargetDefinesARMV87A(const LangOptions &Opts,
338 MacroBuilder &Builder) const {
339 // Also include the Armv8.6 defines
340 getTargetDefinesARMV86A(Opts, Builder);
341}
342
343void AArch64TargetInfo::getTargetDefinesARMV88A(const LangOptions &Opts,
344 MacroBuilder &Builder) const {
345 // Also include the Armv8.7 defines
346 getTargetDefinesARMV87A(Opts, Builder);
347}
348
349void AArch64TargetInfo::getTargetDefinesARMV89A(const LangOptions &Opts,
350 MacroBuilder &Builder) const {
351 // Also include the Armv8.8 defines
352 getTargetDefinesARMV88A(Opts, Builder);
353}
354
355void AArch64TargetInfo::getTargetDefinesARMV9A(const LangOptions &Opts,
356 MacroBuilder &Builder) const {
357 // Armv9-A maps to Armv8.5-A
358 getTargetDefinesARMV85A(Opts, Builder);
359}
360
361void AArch64TargetInfo::getTargetDefinesARMV91A(const LangOptions &Opts,
362 MacroBuilder &Builder) const {
363 // Armv9.1-A maps to Armv8.6-A
364 getTargetDefinesARMV86A(Opts, Builder);
365}
366
367void AArch64TargetInfo::getTargetDefinesARMV92A(const LangOptions &Opts,
368 MacroBuilder &Builder) const {
369 // Armv9.2-A maps to Armv8.7-A
370 getTargetDefinesARMV87A(Opts, Builder);
371}
372
373void AArch64TargetInfo::getTargetDefinesARMV93A(const LangOptions &Opts,
374 MacroBuilder &Builder) const {
375 // Armv9.3-A maps to Armv8.8-A
376 getTargetDefinesARMV88A(Opts, Builder);
377}
378
379void AArch64TargetInfo::getTargetDefinesARMV94A(const LangOptions &Opts,
380 MacroBuilder &Builder) const {
381 // Armv9.4-A maps to Armv8.9-A
382 getTargetDefinesARMV89A(Opts, Builder);
383}
384
385void AArch64TargetInfo::getTargetDefinesARMV95A(const LangOptions &Opts,
386 MacroBuilder &Builder) const {
387 // Armv9.5-A does not have a v8.* equivalent, but is a superset of v9.4-A.
388 getTargetDefinesARMV94A(Opts, Builder);
389}
390
391void AArch64TargetInfo::getTargetDefinesARMV96A(const LangOptions &Opts,
392 MacroBuilder &Builder) const {
393 // Armv9.6-A does not have a v8.* equivalent, but is a superset of v9.5-A.
394 getTargetDefinesARMV95A(Opts, Builder);
395}
396
397void AArch64TargetInfo::getTargetDefinesARMV97A(const LangOptions &Opts,
398 MacroBuilder &Builder) const {
399 // Armv9.7-A does not have a v8.* equivalent, but is a superset of v9.6-A.
400 getTargetDefinesARMV96A(Opts, Builder);
401}
402
403void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
404 MacroBuilder &Builder) const {
405 // Target identification.
406 if (getTriple().isWindowsArm64EC()) {
407 // Define the same set of macros as would be defined on x86_64 to ensure that
408 // ARM64EC datatype layouts match those of x86_64 compiled code
409 Builder.defineMacro(Name: "__amd64__");
410 Builder.defineMacro(Name: "__amd64");
411 Builder.defineMacro(Name: "__x86_64");
412 Builder.defineMacro(Name: "__x86_64__");
413 Builder.defineMacro(Name: "__arm64ec__");
414 } else {
415 Builder.defineMacro(Name: "__aarch64__");
416 }
417
418 if (getTriple().isLFI())
419 Builder.defineMacro(Name: "__LFI__");
420
421 // Inline assembly supports AArch64 flag outputs.
422 Builder.defineMacro(Name: "__GCC_ASM_FLAG_OUTPUTS__");
423
424 std::string CodeModel = getTargetOpts().CodeModel;
425 if (CodeModel == "default")
426 CodeModel = "small";
427 for (char &c : CodeModel)
428 c = toupper(c: c);
429 Builder.defineMacro(Name: "__AARCH64_CMODEL_" + CodeModel + "__");
430
431 // ACLE predefines. Many can only have one possible value on v8 AArch64.
432 Builder.defineMacro(Name: "__ARM_ACLE_VERSION(year, quarter, patch)",
433 Value: "(100 * (year) + 10 * (quarter) + (patch))");
434#define ARM_ACLE_VERSION(Y, Q, P) (100 * (Y) + 10 * (Q) + (P))
435 Builder.defineMacro(Name: "__ARM_ACLE", Value: Twine(ARM_ACLE_VERSION(2024, 2, 0)));
436 Builder.defineMacro(Name: "__FUNCTION_MULTI_VERSIONING_SUPPORT_LEVEL",
437 Value: Twine(ARM_ACLE_VERSION(2024, 3, 0)));
438#undef ARM_ACLE_VERSION
439 Builder.defineMacro(Name: "__ARM_ARCH",
440 Value: std::to_string(val: ArchInfo->Version.getMajor()));
441 Builder.defineMacro(Name: "__ARM_ARCH_PROFILE",
442 Value: std::string("'") + (char)ArchInfo->Profile + "'");
443
444 Builder.defineMacro(Name: "__ARM_64BIT_STATE", Value: "1");
445 Builder.defineMacro(Name: "__ARM_PCS_AAPCS64", Value: "1");
446 Builder.defineMacro(Name: "__ARM_ARCH_ISA_A64", Value: "1");
447
448 Builder.defineMacro(Name: "__ARM_FEATURE_CLZ", Value: "1");
449 Builder.defineMacro(Name: "__ARM_FEATURE_FMA", Value: "1");
450 Builder.defineMacro(Name: "__ARM_FEATURE_LDREX", Value: "0xF");
451 Builder.defineMacro(Name: "__ARM_FEATURE_IDIV", Value: "1"); // As specified in ACLE
452 Builder.defineMacro(Name: "__ARM_FEATURE_DIV"); // For backwards compatibility
453 Builder.defineMacro(Name: "__ARM_FEATURE_NUMERIC_MAXMIN", Value: "1");
454 Builder.defineMacro(Name: "__ARM_FEATURE_DIRECTED_ROUNDING", Value: "1");
455
456 Builder.defineMacro(Name: "__ARM_ALIGN_MAX_STACK_PWR", Value: "4");
457
458 // These macros are set when Clang can parse declarations with these
459 // attributes.
460 Builder.defineMacro(Name: "__ARM_STATE_ZA", Value: "1");
461 Builder.defineMacro(Name: "__ARM_STATE_ZT0", Value: "1");
462
463 // 0xe implies support for half, single and double precision operations.
464 if (FPU & FPUMode)
465 Builder.defineMacro(Name: "__ARM_FP", Value: "0xE");
466
467 // PCS specifies this for SysV variants, which is all we support. Other ABIs
468 // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
469 Builder.defineMacro(Name: "__ARM_FP16_FORMAT_IEEE", Value: "1");
470 Builder.defineMacro(Name: "__ARM_FP16_ARGS", Value: "1");
471
472 // Clang supports arm_neon_sve_bridge.h
473 Builder.defineMacro(Name: "__ARM_NEON_SVE_BRIDGE", Value: "1");
474
475 if (Opts.UnsafeFPMath)
476 Builder.defineMacro(Name: "__ARM_FP_FAST", Value: "1");
477
478 Builder.defineMacro(Name: "__ARM_SIZEOF_WCHAR_T",
479 Value: Twine(Opts.WCharSize ? Opts.WCharSize : 4));
480
481 Builder.defineMacro(Name: "__ARM_SIZEOF_MINIMAL_ENUM", Value: Opts.ShortEnums ? "1" : "4");
482
483 // Clang supports range prefetch intrinsics
484 Builder.defineMacro(Name: "__ARM_PREFETCH_RANGE", Value: "1");
485
486 if (FPU & NeonMode) {
487 Builder.defineMacro(Name: "__ARM_NEON", Value: "1");
488 // 64-bit NEON supports half, single and double precision operations.
489 Builder.defineMacro(Name: "__ARM_NEON_FP", Value: "0xE");
490 }
491
492 if (FPU & SveMode)
493 Builder.defineMacro(Name: "__ARM_FEATURE_SVE", Value: "1");
494
495 if (HasSVE2)
496 Builder.defineMacro(Name: "__ARM_FEATURE_SVE2", Value: "1");
497
498 if (HasSVE2p1)
499 Builder.defineMacro(Name: "__ARM_FEATURE_SVE2p1", Value: "1");
500
501 if (HasSVE2 && HasSVEAES)
502 Builder.defineMacro(Name: "__ARM_FEATURE_SVE2_AES", Value: "1");
503
504 if (HasSVE2 && HasSVEBitPerm)
505 Builder.defineMacro(Name: "__ARM_FEATURE_SVE2_BITPERM", Value: "1");
506
507 if (HasSVE2 && HasSVE2SHA3)
508 Builder.defineMacro(Name: "__ARM_FEATURE_SVE2_SHA3", Value: "1");
509
510 if (HasSVE2 && HasSVE2SM4)
511 Builder.defineMacro(Name: "__ARM_FEATURE_SVE2_SM4", Value: "1");
512
513 if (HasSVEB16B16)
514 Builder.defineMacro(Name: "__ARM_FEATURE_SVE_B16B16", Value: "1");
515
516 if (HasSME) {
517 Builder.defineMacro(Name: "__ARM_FEATURE_SME");
518 Builder.defineMacro(Name: "__ARM_FEATURE_LOCALLY_STREAMING", Value: "1");
519 }
520
521 if (HasSME2)
522 Builder.defineMacro(Name: "__ARM_FEATURE_SME2", Value: "1");
523
524 if (HasSME2p1)
525 Builder.defineMacro(Name: "__ARM_FEATURE_SME2p1", Value: "1");
526
527 if (HasSMEF16F16)
528 Builder.defineMacro(Name: "__ARM_FEATURE_SME_F16F16", Value: "1");
529
530 if (HasSMEB16B16)
531 Builder.defineMacro(Name: "__ARM_FEATURE_SME_B16B16", Value: "1");
532
533 if (HasFP8)
534 Builder.defineMacro(Name: "__ARM_FEATURE_FP8", Value: "1");
535
536 if (HasFP8FMA)
537 Builder.defineMacro(Name: "__ARM_FEATURE_FP8FMA", Value: "1");
538
539 if (HasFP8DOT2)
540 Builder.defineMacro(Name: "__ARM_FEATURE_FP8DOT2", Value: "1");
541
542 if (HasFP8DOT4)
543 Builder.defineMacro(Name: "__ARM_FEATURE_FP8DOT4", Value: "1");
544
545 if (HasSSVE_FP8DOT2)
546 Builder.defineMacro(Name: "__ARM_FEATURE_SSVE_FP8DOT2", Value: "1");
547
548 if (HasSSVE_FP8DOT4)
549 Builder.defineMacro(Name: "__ARM_FEATURE_SSVE_FP8DOT4", Value: "1");
550
551 if (HasSSVE_FP8FMA)
552 Builder.defineMacro(Name: "__ARM_FEATURE_SSVE_FP8FMA", Value: "1");
553
554 if (HasSME_F8F32)
555 Builder.defineMacro(Name: "__ARM_FEATURE_SME_F8F32", Value: "1");
556
557 if (HasSME_F8F16)
558 Builder.defineMacro(Name: "__ARM_FEATURE_SME_F8F16", Value: "1");
559
560 if (HasCRC)
561 Builder.defineMacro(Name: "__ARM_FEATURE_CRC32", Value: "1");
562
563 if (HasCSSC)
564 Builder.defineMacro(Name: "__ARM_FEATURE_CSSC", Value: "1");
565
566 if (HasRCPC3)
567 Builder.defineMacro(Name: "__ARM_FEATURE_RCPC", Value: "3");
568 else if (HasRCPC)
569 Builder.defineMacro(Name: "__ARM_FEATURE_RCPC", Value: "1");
570
571 if (HasFPRCVT)
572 Builder.defineMacro(Name: "__ARM_FEATURE_FPRCVT", Value: "1");
573
574 if (HasF8F16MM)
575 Builder.defineMacro(Name: "__ARM_FEATURE_F8F16MM", Value: "1");
576
577 if (HasF8F32MM)
578 Builder.defineMacro(Name: "__ARM_FEATURE_F8F32MM", Value: "1");
579
580 if (HasSVE_F16F32MM)
581 Builder.defineMacro(Name: "__ARM_FEATURE_SVE_F16F32MM", Value: "1");
582
583 if (HasSVE_BFSCALE)
584 Builder.defineMacro(Name: "__ARM_FEATURE_SVE_BFSCALE", Value: "1");
585
586 if (HasSVE_AES2)
587 Builder.defineMacro(Name: "__ARM_FEATURE_SVE_AES2", Value: "1");
588
589 if (HasSSVE_AES)
590 Builder.defineMacro(Name: "__ARM_FEATURE_SSVE_AES", Value: "1");
591
592 if (HasSVE2p2)
593 Builder.defineMacro(Name: "__ARM_FEATURE_SVE2p2", Value: "1");
594
595 if (HasSME2p2)
596 Builder.defineMacro(Name: "__ARM_FEATURE_SME2p2", Value: "1");
597
598 if (HasFMV)
599 Builder.defineMacro(Name: "__HAVE_FUNCTION_MULTI_VERSIONING", Value: "1");
600
601 // The __ARM_FEATURE_CRYPTO is deprecated in favor of finer grained feature
602 // macros for AES, SHA2, SHA3 and SM4
603 if (HasAES && HasSHA2)
604 Builder.defineMacro(Name: "__ARM_FEATURE_CRYPTO", Value: "1");
605
606 if (HasAES)
607 Builder.defineMacro(Name: "__ARM_FEATURE_AES", Value: "1");
608
609 if (HasSHA2)
610 Builder.defineMacro(Name: "__ARM_FEATURE_SHA2", Value: "1");
611
612 if (HasSHA3) {
613 Builder.defineMacro(Name: "__ARM_FEATURE_SHA3", Value: "1");
614 Builder.defineMacro(Name: "__ARM_FEATURE_SHA512", Value: "1");
615 }
616
617 if (HasSM4) {
618 Builder.defineMacro(Name: "__ARM_FEATURE_SM3", Value: "1");
619 Builder.defineMacro(Name: "__ARM_FEATURE_SM4", Value: "1");
620 }
621
622 if (HasPAuth)
623 Builder.defineMacro(Name: "__ARM_FEATURE_PAUTH", Value: "1");
624
625 if (HasPAuthLR)
626 Builder.defineMacro(Name: "__ARM_FEATURE_PAUTH_LR", Value: "1");
627
628 if (HasBTI)
629 Builder.defineMacro(Name: "__ARM_FEATURE_BTI", Value: "1");
630
631 if (HasUnalignedAccess)
632 Builder.defineMacro(Name: "__ARM_FEATURE_UNALIGNED", Value: "1");
633
634 if ((FPU & NeonMode) && HasFullFP16)
635 Builder.defineMacro(Name: "__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", Value: "1");
636 if (HasFullFP16)
637 Builder.defineMacro(Name: "__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", Value: "1");
638
639 if (HasDotProd)
640 Builder.defineMacro(Name: "__ARM_FEATURE_DOTPROD", Value: "1");
641
642 if (HasMTE)
643 Builder.defineMacro(Name: "__ARM_FEATURE_MEMORY_TAGGING", Value: "1");
644
645 if (HasMatMul)
646 Builder.defineMacro(Name: "__ARM_FEATURE_MATMUL_INT8", Value: "1");
647
648 if (HasLSE)
649 Builder.defineMacro(Name: "__ARM_FEATURE_ATOMICS", Value: "1");
650
651 if (HasBFloat16) {
652 Builder.defineMacro(Name: "__ARM_FEATURE_BF16", Value: "1");
653 Builder.defineMacro(Name: "__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", Value: "1");
654 Builder.defineMacro(Name: "__ARM_BF16_FORMAT_ALTERNATIVE", Value: "1");
655 Builder.defineMacro(Name: "__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", Value: "1");
656 }
657
658 if ((FPU & SveMode) && HasBFloat16) {
659 Builder.defineMacro(Name: "__ARM_FEATURE_SVE_BF16", Value: "1");
660 }
661
662 if ((FPU & SveMode) && HasMatmulFP64)
663 Builder.defineMacro(Name: "__ARM_FEATURE_SVE_MATMUL_FP64", Value: "1");
664
665 if ((FPU & SveMode) && HasMatmulFP32)
666 Builder.defineMacro(Name: "__ARM_FEATURE_SVE_MATMUL_FP32", Value: "1");
667
668 if ((FPU & SveMode) && HasMatMul)
669 Builder.defineMacro(Name: "__ARM_FEATURE_SVE_MATMUL_INT8", Value: "1");
670
671 if ((FPU & NeonMode) && HasFP16FML)
672 Builder.defineMacro(Name: "__ARM_FEATURE_FP16_FML", Value: "1");
673
674 if (Opts.hasSignReturnAddress()) {
675 // Bitmask:
676 // 0: Protection using the A key
677 // 1: Protection using the B key
678 // 2: Protection including leaf functions
679 // 3: Protection using PC as a diversifier
680 unsigned Value = 0;
681
682 if (Opts.isSignReturnAddressWithAKey())
683 Value |= (1 << 0);
684 else
685 Value |= (1 << 1);
686
687 if (Opts.isSignReturnAddressScopeAll())
688 Value |= (1 << 2);
689
690 if (Opts.BranchProtectionPAuthLR)
691 Value |= (1 << 3);
692
693 Builder.defineMacro(Name: "__ARM_FEATURE_PAC_DEFAULT", Value: std::to_string(val: Value));
694 }
695
696 if (Opts.BranchTargetEnforcement)
697 Builder.defineMacro(Name: "__ARM_FEATURE_BTI_DEFAULT", Value: "1");
698
699 if (Opts.GuardedControlStack)
700 Builder.defineMacro(Name: "__ARM_FEATURE_GCS_DEFAULT", Value: "1");
701
702 if (HasLS64)
703 Builder.defineMacro(Name: "__ARM_FEATURE_LS64", Value: "1");
704
705 if (HasRandGen)
706 Builder.defineMacro(Name: "__ARM_FEATURE_RNG", Value: "1");
707
708 if (HasMOPS)
709 Builder.defineMacro(Name: "__ARM_FEATURE_MOPS", Value: "1");
710
711 if (HasD128)
712 Builder.defineMacro(Name: "__ARM_FEATURE_SYSREG128", Value: "1");
713
714 if (HasGCS)
715 Builder.defineMacro(Name: "__ARM_FEATURE_GCS", Value: "1");
716
717 if (*ArchInfo == llvm::AArch64::ARMV8_1A)
718 getTargetDefinesARMV81A(Opts, Builder);
719 else if (*ArchInfo == llvm::AArch64::ARMV8_2A)
720 getTargetDefinesARMV82A(Opts, Builder);
721 else if (*ArchInfo == llvm::AArch64::ARMV8_3A)
722 getTargetDefinesARMV83A(Opts, Builder);
723 else if (*ArchInfo == llvm::AArch64::ARMV8_4A)
724 getTargetDefinesARMV84A(Opts, Builder);
725 else if (*ArchInfo == llvm::AArch64::ARMV8_5A)
726 getTargetDefinesARMV85A(Opts, Builder);
727 else if (*ArchInfo == llvm::AArch64::ARMV8_6A)
728 getTargetDefinesARMV86A(Opts, Builder);
729 else if (*ArchInfo == llvm::AArch64::ARMV8_7A)
730 getTargetDefinesARMV87A(Opts, Builder);
731 else if (*ArchInfo == llvm::AArch64::ARMV8_8A)
732 getTargetDefinesARMV88A(Opts, Builder);
733 else if (*ArchInfo == llvm::AArch64::ARMV8_9A)
734 getTargetDefinesARMV89A(Opts, Builder);
735 else if (*ArchInfo == llvm::AArch64::ARMV9A)
736 getTargetDefinesARMV9A(Opts, Builder);
737 else if (*ArchInfo == llvm::AArch64::ARMV9_1A)
738 getTargetDefinesARMV91A(Opts, Builder);
739 else if (*ArchInfo == llvm::AArch64::ARMV9_2A)
740 getTargetDefinesARMV92A(Opts, Builder);
741 else if (*ArchInfo == llvm::AArch64::ARMV9_3A)
742 getTargetDefinesARMV93A(Opts, Builder);
743 else if (*ArchInfo == llvm::AArch64::ARMV9_4A)
744 getTargetDefinesARMV94A(Opts, Builder);
745 else if (*ArchInfo == llvm::AArch64::ARMV9_5A)
746 getTargetDefinesARMV95A(Opts, Builder);
747 else if (*ArchInfo == llvm::AArch64::ARMV9_6A)
748 getTargetDefinesARMV96A(Opts, Builder);
749 else if (*ArchInfo == llvm::AArch64::ARMV9_7A)
750 getTargetDefinesARMV97A(Opts, Builder);
751
752 // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8|16) builtins work.
753 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
754 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
755 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
756 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
757 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
758
759 // Allow detection of fast FMA support.
760 Builder.defineMacro(Name: "__FP_FAST_FMA", Value: "1");
761 Builder.defineMacro(Name: "__FP_FAST_FMAF", Value: "1");
762
763 // C/C++ operators work on both VLS and VLA SVE types
764 if (FPU & SveMode)
765 Builder.defineMacro(Name: "__ARM_FEATURE_SVE_VECTOR_OPERATORS", Value: "2");
766
767 if (Opts.VScaleMin && Opts.VScaleMin == Opts.VScaleMax) {
768 Builder.defineMacro(Name: "__ARM_FEATURE_SVE_BITS", Value: Twine(Opts.VScaleMin * 128));
769 }
770}
771
772llvm::SmallVector<Builtin::InfosShard>
773AArch64TargetInfo::getTargetBuiltins() const {
774 return {
775 {.Strings: &NEON::BuiltinStrings, .Infos: NEON::BuiltinInfos, .NamePrefix: "__builtin_neon_"},
776 {.Strings: &NEON::FP16::BuiltinStrings, .Infos: NEON::FP16::BuiltinInfos,
777 .NamePrefix: "__builtin_neon_"},
778 {.Strings: &SVE::BuiltinStrings, .Infos: SVE::BuiltinInfos, .NamePrefix: "__builtin_sve_"},
779 {.Strings: &BuiltinSVENeonBridgeStrings, .Infos: BuiltinSVENeonBridgeInfos},
780 {.Strings: &SME::BuiltinStrings, .Infos: SME::BuiltinInfos, .NamePrefix: "__builtin_sme_"},
781 {.Strings: &AArch64::BuiltinStrings, .Infos: AArch64::BuiltinInfos},
782 {.Strings: &AArch64::BuiltinStrings, .Infos: AArch64::PrefixedBuiltinInfos,
783 .NamePrefix: "__builtin_arm_"},
784 };
785}
786
787std::optional<std::pair<unsigned, unsigned>>
788AArch64TargetInfo::getVScaleRange(const LangOptions &LangOpts,
789 ArmStreamingKind Mode,
790 llvm::StringMap<bool> *FeatureMap) const {
791 if (Mode == ArmStreamingKind::NotStreaming &&
792 (LangOpts.VScaleMin || LangOpts.VScaleMax))
793 return std::pair<unsigned, unsigned>(
794 LangOpts.VScaleMin ? LangOpts.VScaleMin : 1,
795 LangOpts.VScaleMax ? LangOpts.VScaleMax : 16);
796
797 if (Mode == ArmStreamingKind::Streaming &&
798 (LangOpts.VScaleStreamingMin || LangOpts.VScaleStreamingMax))
799 return std::pair<unsigned, unsigned>(
800 LangOpts.VScaleStreamingMin ? LangOpts.VScaleStreamingMin : 1,
801 LangOpts.VScaleStreamingMax ? LangOpts.VScaleStreamingMax : 16);
802
803 if (Mode == ArmStreamingKind::StreamingCompatible &&
804 ((LangOpts.VScaleMin && LangOpts.VScaleStreamingMin) ||
805 (LangOpts.VScaleMax && LangOpts.VScaleStreamingMax))) {
806 unsigned Min =
807 std::min(a: LangOpts.VScaleMin ? LangOpts.VScaleMin : 1,
808 b: LangOpts.VScaleStreamingMin ? LangOpts.VScaleStreamingMin : 1);
809 unsigned Max = std::max(
810 a: LangOpts.VScaleMax ? LangOpts.VScaleMax : 16,
811 b: LangOpts.VScaleStreamingMax ? LangOpts.VScaleStreamingMax : 16);
812 return std::pair(Min, Max);
813 }
814
815 if (hasFeature(Feature: "sve") || (FeatureMap && (FeatureMap->lookup(Key: "sve"))))
816 return std::pair<unsigned, unsigned>(1, 16);
817
818 if (Mode == ArmStreamingKind::Streaming &&
819 (hasFeature(Feature: "sme") || (FeatureMap && (FeatureMap->lookup(Key: "sme")))))
820 return std::pair<unsigned, unsigned>(1, 16);
821
822 return std::nullopt;
823}
824
825llvm::APInt
826AArch64TargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const {
827 return llvm::AArch64::getFMVPriority(Features);
828}
829
830bool AArch64TargetInfo::doesFeatureAffectCodeGen(StringRef Name) const {
831 // FMV extensions which imply no backend features do not affect codegen.
832 if (auto Ext = llvm::AArch64::parseFMVExtension(Extension: Name))
833 return Ext->ID.has_value();
834 return false;
835}
836
837bool AArch64TargetInfo::validateCpuSupports(StringRef FeatureStr) const {
838 // CPU features might be separated by '+', extract them and check
839 llvm::SmallVector<StringRef, 8> Features;
840 FeatureStr.split(A&: Features, Separator: "+");
841 for (auto &Feature : Features)
842 if (!llvm::AArch64::parseFMVExtension(Extension: Feature.trim()).has_value())
843 return false;
844 return true;
845}
846
847/// A helper class for "hasFeature" lookups (mimicking a StringSwitch).
848struct FeatureLookupBuilder {
849 FeatureLookupBuilder(AArch64FeatureSet &Features) : Features(Features) {
850 Features.clear();
851 }
852
853 FeatureLookupBuilder &Case(StringRef Feat, bool HasFeature) {
854 if (HasFeature)
855 Features.insert(V: Feat);
856 return *this;
857 }
858
859 FeatureLookupBuilder &Cases(ArrayRef<StringRef> Feats, bool HasFeature) {
860 if (HasFeature)
861 Features.insert_range(R&: Feats);
862 return *this;
863 }
864
865private:
866 AArch64FeatureSet &Features;
867};
868
869void AArch64TargetInfo::computeFeatureLookup() {
870 FeatureLookupBuilder(HasFeatureLookup)
871 .Cases(Feats: {"aarch64", "arm64", "arm"}, HasFeature: true)
872 .Case(Feat: "fmv", HasFeature: HasFMV)
873 .Case(Feat: "fp", HasFeature: FPU & FPUMode)
874 .Cases(Feats: {"neon", "simd"}, HasFeature: FPU & NeonMode)
875 .Case(Feat: "jscvt", HasFeature: HasJSCVT)
876 .Case(Feat: "fcma", HasFeature: HasFCMA)
877 .Case(Feat: "rng", HasFeature: HasRandGen)
878 .Case(Feat: "flagm", HasFeature: HasFlagM)
879 .Case(Feat: "flagm2", HasFeature: HasAlternativeNZCV)
880 .Case(Feat: "fp16fml", HasFeature: HasFP16FML)
881 .Case(Feat: "dotprod", HasFeature: HasDotProd)
882 .Case(Feat: "sm4", HasFeature: HasSM4)
883 .Case(Feat: "rdm", HasFeature: HasRDM)
884 .Case(Feat: "lse", HasFeature: HasLSE)
885 .Case(Feat: "crc", HasFeature: HasCRC)
886 .Case(Feat: "cssc", HasFeature: HasCSSC)
887 .Case(Feat: "sha2", HasFeature: HasSHA2)
888 .Case(Feat: "sha3", HasFeature: HasSHA3)
889 .Cases(Feats: {"aes", "pmull"}, HasFeature: HasAES)
890 .Cases(Feats: {"fp16", "fullfp16"}, HasFeature: HasFullFP16)
891 .Case(Feat: "dit", HasFeature: HasDIT)
892 .Case(Feat: "dpb", HasFeature: HasCCPP)
893 .Case(Feat: "dpb2", HasFeature: HasCCDP)
894 .Case(Feat: "rcpc", HasFeature: HasRCPC)
895 .Case(Feat: "frintts", HasFeature: HasFRInt3264)
896 .Case(Feat: "i8mm", HasFeature: HasMatMul)
897 .Case(Feat: "bf16", HasFeature: HasBFloat16)
898 .Case(Feat: "sve", HasFeature: FPU & SveMode)
899 .Case(Feat: "sve-b16b16", HasFeature: HasSVEB16B16)
900 .Case(Feat: "f32mm", HasFeature: FPU & SveMode && HasMatmulFP32)
901 .Case(Feat: "f64mm", HasFeature: FPU & SveMode && HasMatmulFP64)
902 .Case(Feat: "sve2", HasFeature: FPU & SveMode && HasSVE2)
903 .Case(Feat: "sve-aes", HasFeature: HasSVEAES)
904 .Case(Feat: "sve-bitperm", HasFeature: FPU & HasSVEBitPerm)
905 .Case(Feat: "sve2-sha3", HasFeature: FPU & SveMode && HasSVE2SHA3)
906 .Case(Feat: "sve2-sm4", HasFeature: FPU & SveMode && HasSVE2SM4)
907 .Case(Feat: "sve2p1", HasFeature: FPU & SveMode && HasSVE2p1)
908 .Case(Feat: "sme", HasFeature: HasSME)
909 .Case(Feat: "sme2", HasFeature: HasSME2)
910 .Case(Feat: "sme2p1", HasFeature: HasSME2p1)
911 .Case(Feat: "sme-f64f64", HasFeature: HasSMEF64F64)
912 .Case(Feat: "sme-i16i64", HasFeature: HasSMEI16I64)
913 .Case(Feat: "sme-fa64", HasFeature: HasSMEFA64)
914 .Case(Feat: "sme-f16f16", HasFeature: HasSMEF16F16)
915 .Case(Feat: "sme-b16b16", HasFeature: HasSMEB16B16)
916 .Case(Feat: "memtag", HasFeature: HasMTE)
917 .Case(Feat: "sb", HasFeature: HasSB)
918 .Case(Feat: "predres", HasFeature: HasPredRes)
919 .Cases(Feats: {"ssbs", "ssbs2"}, HasFeature: HasSSBS)
920 .Case(Feat: "bti", HasFeature: HasBTI)
921 .Cases(Feats: {"ls64", "ls64_v", "ls64_accdata"}, HasFeature: HasLS64)
922 .Case(Feat: "wfxt", HasFeature: HasWFxT)
923 .Case(Feat: "rcpc3", HasFeature: HasRCPC3)
924 .Case(Feat: "fp8", HasFeature: HasFP8)
925 .Case(Feat: "fp8fma", HasFeature: HasFP8FMA)
926 .Case(Feat: "fp8dot2", HasFeature: HasFP8DOT2)
927 .Case(Feat: "fp8dot4", HasFeature: HasFP8DOT4)
928 .Case(Feat: "ssve-fp8dot2", HasFeature: HasSSVE_FP8DOT2)
929 .Case(Feat: "ssve-fp8dot4", HasFeature: HasSSVE_FP8DOT4)
930 .Case(Feat: "ssve-fp8fma", HasFeature: HasSSVE_FP8FMA)
931 .Case(Feat: "sme-f8f32", HasFeature: HasSME_F8F32)
932 .Case(Feat: "sme-f8f16", HasFeature: HasSME_F8F16)
933 .Case(Feat: "fprcvt", HasFeature: HasFPRCVT)
934 .Case(Feat: "f8f16mm", HasFeature: HasF8F16MM)
935 .Case(Feat: "f8f32mm", HasFeature: HasF8F32MM)
936 .Case(Feat: "sve-f16f32mm", HasFeature: HasSVE_F16F32MM)
937 .Case(Feat: "sve-bfscale", HasFeature: HasSVE_BFSCALE)
938 .Case(Feat: "sve-aes2", HasFeature: HasSVE_AES2)
939 .Case(Feat: "ssve-aes", HasFeature: HasSSVE_AES)
940 .Case(Feat: "sve2p2", HasFeature: FPU & SveMode && HasSVE2p2)
941 .Case(Feat: "sme2p2", HasFeature: HasSME2p2);
942}
943
944bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
945 return HasFeatureLookup.contains(V: Feature);
946}
947
948void AArch64TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
949 StringRef Name, bool Enabled) const {
950 Features[Name] = Enabled;
951 // If the feature is an architecture feature (like v8.2a), add all previous
952 // architecture versions and any dependant target features.
953 const std::optional<llvm::AArch64::ArchInfo> ArchInfo =
954 llvm::AArch64::ArchInfo::findBySubArch(SubArch: Name);
955
956 if (!ArchInfo)
957 return; // Not an architecture, nothing more to do.
958
959 // Disabling an architecture feature does not affect dependent features
960 if (!Enabled)
961 return;
962
963 for (const auto *OtherArch : llvm::AArch64::ArchInfos)
964 if (ArchInfo->implies(Other: *OtherArch))
965 Features[OtherArch->getSubArch()] = true;
966
967 // Set any features implied by the architecture
968 std::vector<StringRef> CPUFeats;
969 if (llvm::AArch64::getExtensionFeatures(Extensions: ArchInfo->DefaultExts, Features&: CPUFeats)) {
970 for (auto F : CPUFeats) {
971 assert(F[0] == '+' && "Expected + in target feature!");
972 Features[F.drop_front(N: 1)] = true;
973 }
974 }
975}
976
977bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
978 DiagnosticsEngine &Diags) {
979 for (const auto &Feature : Features) {
980 if (Feature == "-fp-armv8")
981 HasNoFP = true;
982 if (Feature == "-neon")
983 HasNoNeon = true;
984 if (Feature == "-sve")
985 HasNoSVE = true;
986
987 if (Feature == "+neon" || Feature == "+fp-armv8")
988 FPU |= NeonMode;
989 if (Feature == "+jscvt") {
990 HasJSCVT = true;
991 FPU |= NeonMode;
992 }
993 if (Feature == "+fcma") {
994 HasFCMA = true;
995 FPU |= NeonMode;
996 }
997
998 if (Feature == "+sve") {
999 FPU |= NeonMode;
1000 FPU |= SveMode;
1001 HasFullFP16 = true;
1002 }
1003 if (Feature == "+sve2") {
1004 FPU |= NeonMode;
1005 FPU |= SveMode;
1006 HasFullFP16 = true;
1007 HasSVE2 = true;
1008 }
1009 if (Feature == "+sve2p1") {
1010 FPU |= NeonMode;
1011 FPU |= SveMode;
1012 HasFullFP16 = true;
1013 HasSVE2 = true;
1014 HasSVE2p1 = true;
1015 }
1016 if (Feature == "+sve-aes") {
1017 FPU |= NeonMode;
1018 HasFullFP16 = true;
1019 HasSVEAES = true;
1020 }
1021 if (Feature == "+sve2-sha3") {
1022 FPU |= NeonMode;
1023 FPU |= SveMode;
1024 HasFullFP16 = true;
1025 HasSVE2 = true;
1026 HasSVE2SHA3 = true;
1027 }
1028 if (Feature == "+sve2-sm4") {
1029 FPU |= NeonMode;
1030 FPU |= SveMode;
1031 HasFullFP16 = true;
1032 HasSVE2 = true;
1033 HasSVE2SM4 = true;
1034 }
1035 if (Feature == "+sve-b16b16")
1036 HasSVEB16B16 = true;
1037 if (Feature == "+sve-bitperm") {
1038 FPU |= NeonMode;
1039 HasFullFP16 = true;
1040 HasSVEBitPerm = true;
1041 }
1042 if (Feature == "+f32mm") {
1043 FPU |= NeonMode;
1044 FPU |= SveMode;
1045 HasFullFP16 = true;
1046 HasMatmulFP32 = true;
1047 }
1048 if (Feature == "+f64mm") {
1049 FPU |= NeonMode;
1050 FPU |= SveMode;
1051 HasFullFP16 = true;
1052 HasMatmulFP64 = true;
1053 }
1054 if (Feature == "+sme") {
1055 HasSME = true;
1056 HasBFloat16 = true;
1057 HasFullFP16 = true;
1058 }
1059 if (Feature == "+sme2") {
1060 HasSME = true;
1061 HasSME2 = true;
1062 HasBFloat16 = true;
1063 HasFullFP16 = true;
1064 }
1065 if (Feature == "+sme2p1") {
1066 HasSME = true;
1067 HasSME2 = true;
1068 HasSME2p1 = true;
1069 HasBFloat16 = true;
1070 HasFullFP16 = true;
1071 }
1072 if (Feature == "+sme-f64f64") {
1073 HasSME = true;
1074 HasSMEF64F64 = true;
1075 HasBFloat16 = true;
1076 HasFullFP16 = true;
1077 }
1078 if (Feature == "+sme-i16i64") {
1079 HasSME = true;
1080 HasSMEI16I64 = true;
1081 HasBFloat16 = true;
1082 HasFullFP16 = true;
1083 }
1084 if (Feature == "+sme-fa64") {
1085 FPU |= NeonMode;
1086 FPU |= SveMode;
1087 HasSME = true;
1088 HasSVE2 = true;
1089 HasSMEFA64 = true;
1090 }
1091 if (Feature == "+sme-f16f16") {
1092 HasSME = true;
1093 HasSME2 = true;
1094 HasBFloat16 = true;
1095 HasFullFP16 = true;
1096 HasSMEF16F16 = true;
1097 }
1098 if (Feature == "+sme-b16b16") {
1099 HasSME = true;
1100 HasSME2 = true;
1101 HasBFloat16 = true;
1102 HasFullFP16 = true;
1103 HasSVEB16B16 = true;
1104 HasSMEB16B16 = true;
1105 }
1106
1107 if (Feature == "+fp8")
1108 HasFP8 = true;
1109 if (Feature == "+fp8fma")
1110 HasFP8FMA = true;
1111 if (Feature == "+fp8dot2")
1112 HasFP8DOT2 = true;
1113 if (Feature == "+fp8dot4")
1114 HasFP8DOT4 = true;
1115 if (Feature == "+ssve-fp8dot2")
1116 HasSSVE_FP8DOT2 = true;
1117 if (Feature == "+ssve-fp8dot4")
1118 HasSSVE_FP8DOT4 = true;
1119 if (Feature == "+ssve-fp8fma")
1120 HasSSVE_FP8FMA = true;
1121 if (Feature == "+sme-f8f32")
1122 HasSME_F8F32 = true;
1123 if (Feature == "+sme-f8f16")
1124 HasSME_F8F16 = true;
1125 if (Feature == "+sb")
1126 HasSB = true;
1127 if (Feature == "+predres")
1128 HasPredRes = true;
1129 if (Feature == "+ssbs")
1130 HasSSBS = true;
1131 if (Feature == "+bti")
1132 HasBTI = true;
1133 if (Feature == "+wfxt")
1134 HasWFxT = true;
1135 if (Feature == "-fmv")
1136 HasFMV = false;
1137 if (Feature == "+crc")
1138 HasCRC = true;
1139 if (Feature == "+rcpc")
1140 HasRCPC = true;
1141 if (Feature == "+aes") {
1142 FPU |= NeonMode;
1143 HasAES = true;
1144 }
1145 if (Feature == "+sha2") {
1146 FPU |= NeonMode;
1147 HasSHA2 = true;
1148 }
1149 if (Feature == "+sha3") {
1150 FPU |= NeonMode;
1151 HasSHA2 = true;
1152 HasSHA3 = true;
1153 }
1154 if (Feature == "+rdm") {
1155 FPU |= NeonMode;
1156 HasRDM = true;
1157 }
1158 if (Feature == "+dit")
1159 HasDIT = true;
1160 if (Feature == "+cccp")
1161 HasCCPP = true;
1162 if (Feature == "+ccdp") {
1163 HasCCPP = true;
1164 HasCCDP = true;
1165 }
1166 if (Feature == "+fptoint")
1167 HasFRInt3264 = true;
1168 if (Feature == "+sm4") {
1169 FPU |= NeonMode;
1170 HasSM4 = true;
1171 }
1172 if (Feature == "+strict-align")
1173 HasUnalignedAccess = false;
1174 if (Feature == "+fprcvt")
1175 HasFPRCVT = true;
1176 if (Feature == "+f8f16mm")
1177 HasF8F16MM = true;
1178 if (Feature == "+f8f32mm")
1179 HasF8F32MM = true;
1180 if (Feature == "+sve-f16f32mm")
1181 HasSVE_F16F32MM = true;
1182 if (Feature == "+sve-bfscale")
1183 HasSVE_BFSCALE = true;
1184 if (Feature == "+sve-aes2")
1185 HasSVE_AES2 = true;
1186 if (Feature == "+ssve-aes")
1187 HasSSVE_AES = true;
1188 if (Feature == "+sve2p2")
1189 HasSVE2p2 = true;
1190 if (Feature == "+sme2p2")
1191 HasSME2p2 = true;
1192
1193 // All predecessor archs are added but select the latest one for ArchKind.
1194 if (Feature == "+v8a" && ArchInfo->Version < llvm::AArch64::ARMV8A.Version)
1195 ArchInfo = &llvm::AArch64::ARMV8A;
1196 if (Feature == "+v8.1a" &&
1197 ArchInfo->Version < llvm::AArch64::ARMV8_1A.Version)
1198 ArchInfo = &llvm::AArch64::ARMV8_1A;
1199 if (Feature == "+v8.2a" &&
1200 ArchInfo->Version < llvm::AArch64::ARMV8_2A.Version)
1201 ArchInfo = &llvm::AArch64::ARMV8_2A;
1202 if (Feature == "+v8.3a" &&
1203 ArchInfo->Version < llvm::AArch64::ARMV8_3A.Version)
1204 ArchInfo = &llvm::AArch64::ARMV8_3A;
1205 if (Feature == "+v8.4a" &&
1206 ArchInfo->Version < llvm::AArch64::ARMV8_4A.Version)
1207 ArchInfo = &llvm::AArch64::ARMV8_4A;
1208 if (Feature == "+v8.5a" &&
1209 ArchInfo->Version < llvm::AArch64::ARMV8_5A.Version)
1210 ArchInfo = &llvm::AArch64::ARMV8_5A;
1211 if (Feature == "+v8.6a" &&
1212 ArchInfo->Version < llvm::AArch64::ARMV8_6A.Version)
1213 ArchInfo = &llvm::AArch64::ARMV8_6A;
1214 if (Feature == "+v8.7a" &&
1215 ArchInfo->Version < llvm::AArch64::ARMV8_7A.Version)
1216 ArchInfo = &llvm::AArch64::ARMV8_7A;
1217 if (Feature == "+v8.8a" &&
1218 ArchInfo->Version < llvm::AArch64::ARMV8_8A.Version)
1219 ArchInfo = &llvm::AArch64::ARMV8_8A;
1220 if (Feature == "+v8.9a" &&
1221 ArchInfo->Version < llvm::AArch64::ARMV8_9A.Version)
1222 ArchInfo = &llvm::AArch64::ARMV8_9A;
1223 if (Feature == "+v9a" && ArchInfo->Version < llvm::AArch64::ARMV9A.Version)
1224 ArchInfo = &llvm::AArch64::ARMV9A;
1225 if (Feature == "+v9.1a" &&
1226 ArchInfo->Version < llvm::AArch64::ARMV9_1A.Version)
1227 ArchInfo = &llvm::AArch64::ARMV9_1A;
1228 if (Feature == "+v9.2a" &&
1229 ArchInfo->Version < llvm::AArch64::ARMV9_2A.Version)
1230 ArchInfo = &llvm::AArch64::ARMV9_2A;
1231 if (Feature == "+v9.3a" &&
1232 ArchInfo->Version < llvm::AArch64::ARMV9_3A.Version)
1233 ArchInfo = &llvm::AArch64::ARMV9_3A;
1234 if (Feature == "+v9.4a" &&
1235 ArchInfo->Version < llvm::AArch64::ARMV9_4A.Version)
1236 ArchInfo = &llvm::AArch64::ARMV9_4A;
1237 if (Feature == "+v9.5a" &&
1238 ArchInfo->Version < llvm::AArch64::ARMV9_5A.Version)
1239 ArchInfo = &llvm::AArch64::ARMV9_5A;
1240 if (Feature == "+v9.6a" &&
1241 ArchInfo->Version < llvm::AArch64::ARMV9_6A.Version)
1242 ArchInfo = &llvm::AArch64::ARMV9_6A;
1243 if (Feature == "+v9.7a" &&
1244 ArchInfo->Version < llvm::AArch64::ARMV9_7A.Version)
1245 ArchInfo = &llvm::AArch64::ARMV9_7A;
1246 if (Feature == "+v8r")
1247 ArchInfo = &llvm::AArch64::ARMV8R;
1248 if (Feature == "+fullfp16") {
1249 FPU |= NeonMode;
1250 HasFullFP16 = true;
1251 }
1252 if (Feature == "+dotprod") {
1253 FPU |= NeonMode;
1254 HasDotProd = true;
1255 }
1256 if (Feature == "+fp16fml") {
1257 FPU |= NeonMode;
1258 HasFullFP16 = true;
1259 HasFP16FML = true;
1260 }
1261 if (Feature == "+mte")
1262 HasMTE = true;
1263 if (Feature == "+pauth")
1264 HasPAuth = true;
1265 if (Feature == "+i8mm")
1266 HasMatMul = true;
1267 if (Feature == "+bf16")
1268 HasBFloat16 = true;
1269 if (Feature == "+lse")
1270 HasLSE = true;
1271 if (Feature == "+ls64")
1272 HasLS64 = true;
1273 if (Feature == "+rand")
1274 HasRandGen = true;
1275 if (Feature == "+flagm")
1276 HasFlagM = true;
1277 if (Feature == "+altnzcv") {
1278 HasFlagM = true;
1279 HasAlternativeNZCV = true;
1280 }
1281 if (Feature == "+mops")
1282 HasMOPS = true;
1283 if (Feature == "+d128")
1284 HasD128 = true;
1285 if (Feature == "+gcs")
1286 HasGCS = true;
1287 if (Feature == "+rcpc3")
1288 HasRCPC3 = true;
1289 if (Feature == "+pauth-lr") {
1290 HasPAuthLR = true;
1291 HasPAuth = true;
1292 }
1293 if (Feature == "+cssc")
1294 HasCSSC = true;
1295 }
1296
1297 // Check features that are manually disabled by command line options.
1298 // This needs to be checked after architecture-related features are handled,
1299 // making sure they are properly disabled when required.
1300 for (const auto &Feature : Features) {
1301 if (Feature == "-d128")
1302 HasD128 = false;
1303 }
1304
1305 resetDataLayout();
1306
1307 if (HasNoFP) {
1308 FPU &= ~FPUMode;
1309 FPU &= ~NeonMode;
1310 FPU &= ~SveMode;
1311 }
1312 if (HasNoNeon) {
1313 FPU &= ~NeonMode;
1314 FPU &= ~SveMode;
1315 }
1316 if (HasNoSVE)
1317 FPU &= ~SveMode;
1318
1319 computeFeatureLookup();
1320 return true;
1321}
1322
1323// Parse AArch64 Target attributes, which are a comma separated list of:
1324// "arch=<arch>" - parsed to features as per -march=..
1325// "cpu=<cpu>" - parsed to features as per -mcpu=.., with CPU set to <cpu>
1326// "tune=<cpu>" - TuneCPU set to <cpu>
1327// "feature", "no-feature" - Add (or remove) feature.
1328// "+feature", "+nofeature" - Add (or remove) feature.
1329//
1330// A feature may correspond to an Extension (anything with a corresponding
1331// AEK_), in which case an ExtensionSet is used to parse it and expand its
1332// dependencies. If the feature does not yield a successful parse then it
1333// is passed through.
1334ParsedTargetAttr AArch64TargetInfo::parseTargetAttr(StringRef Features) const {
1335 ParsedTargetAttr Ret;
1336 if (Features == "default")
1337 return Ret;
1338 SmallVector<StringRef, 1> AttrFeatures;
1339 Features.split(A&: AttrFeatures, Separator: ",");
1340 bool FoundArch = false;
1341
1342 auto SplitAndAddFeatures = [](StringRef FeatString,
1343 std::vector<std::string> &Features,
1344 llvm::AArch64::ExtensionSet &FeatureBits) {
1345 SmallVector<StringRef, 8> SplitFeatures;
1346 FeatString.split(A&: SplitFeatures, Separator: StringRef("+"), MaxSplit: -1, KeepEmpty: false);
1347 for (StringRef Feature : SplitFeatures) {
1348 if (FeatureBits.parseModifier(Modifier: Feature))
1349 continue;
1350 // Pass through anything that failed to parse so that we can emit
1351 // diagnostics, as well as valid internal feature names.
1352 //
1353 // FIXME: We should consider rejecting internal feature names like
1354 // neon, v8a, etc.
1355 // FIXME: We should consider emitting diagnostics here.
1356 if (Feature.starts_with(Prefix: "no"))
1357 Features.push_back(x: "-" + Feature.drop_front(N: 2).str());
1358 else
1359 Features.push_back(x: "+" + Feature.str());
1360 }
1361 };
1362
1363 llvm::AArch64::ExtensionSet FeatureBits;
1364 // Reconstruct the bitset from the command line option features.
1365 FeatureBits.reconstructFromParsedFeatures(Features: getTargetOpts().FeaturesAsWritten,
1366 NonExtensions&: Ret.Features);
1367
1368 for (auto &Feature : AttrFeatures) {
1369 Feature = Feature.trim();
1370 if (Feature.starts_with(Prefix: "fpmath="))
1371 continue;
1372
1373 if (Feature.starts_with(Prefix: "branch-protection=")) {
1374 Ret.BranchProtection = Feature.split(Separator: '=').second.trim();
1375 continue;
1376 }
1377
1378 if (Feature.starts_with(Prefix: "arch=")) {
1379 if (FoundArch)
1380 Ret.Duplicate = "arch=";
1381 FoundArch = true;
1382 std::pair<StringRef, StringRef> Split =
1383 Feature.split(Separator: "=").second.trim().split(Separator: "+");
1384 const llvm::AArch64::ArchInfo *AI = llvm::AArch64::parseArch(Arch: Split.first);
1385
1386 // Parse the architecture version, adding the required features to
1387 // Ret.Features.
1388 if (!AI)
1389 continue;
1390 FeatureBits.addArchDefaults(Arch: *AI);
1391 // Add any extra features, after the +
1392 SplitAndAddFeatures(Split.second, Ret.Features, FeatureBits);
1393 } else if (Feature.starts_with(Prefix: "cpu=")) {
1394 if (!Ret.CPU.empty())
1395 Ret.Duplicate = "cpu=";
1396 else {
1397 // Split the cpu string into "cpu=", "cortex-a710" and any remaining
1398 // "+feat" features.
1399 std::pair<StringRef, StringRef> Split =
1400 Feature.split(Separator: "=").second.trim().split(Separator: "+");
1401 Ret.CPU = Split.first;
1402 if (auto CpuInfo = llvm::AArch64::parseCpu(Name: Ret.CPU)) {
1403 FeatureBits.addCPUDefaults(CPU: *CpuInfo);
1404 SplitAndAddFeatures(Split.second, Ret.Features, FeatureBits);
1405 }
1406 }
1407 } else if (Feature.starts_with(Prefix: "tune=")) {
1408 if (!Ret.Tune.empty())
1409 Ret.Duplicate = "tune=";
1410 else
1411 Ret.Tune = Feature.split(Separator: "=").second.trim();
1412 } else if (Feature.starts_with(Prefix: "+")) {
1413 SplitAndAddFeatures(Feature, Ret.Features, FeatureBits);
1414 } else {
1415 if (FeatureBits.parseModifier(Modifier: Feature, /* AllowNoDashForm = */ true))
1416 continue;
1417 // Pass through anything that failed to parse so that we can emit
1418 // diagnostics, as well as valid internal feature names.
1419 //
1420 // FIXME: We should consider rejecting internal feature names like
1421 // neon, v8a, etc.
1422 // FIXME: We should consider emitting diagnostics here.
1423 if (Feature.starts_with(Prefix: "no-"))
1424 Ret.Features.push_back(x: "-" + Feature.drop_front(N: 3).str());
1425 else
1426 Ret.Features.push_back(x: "+" + Feature.str());
1427 }
1428 }
1429 FeatureBits.toLLVMFeatureList(Features&: Ret.Features);
1430 return Ret;
1431}
1432
1433bool AArch64TargetInfo::hasBFloat16Type() const {
1434 return true;
1435}
1436
1437TargetInfo::CallingConvCheckResult
1438AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
1439 switch (CC) {
1440 case CC_C:
1441 case CC_Swift:
1442 case CC_SwiftAsync:
1443 case CC_PreserveMost:
1444 case CC_PreserveAll:
1445 case CC_PreserveNone:
1446 case CC_DeviceKernel:
1447 case CC_AArch64VectorCall:
1448 case CC_AArch64SVEPCS:
1449 case CC_Win64:
1450 return CCCR_OK;
1451 default:
1452 return CCCR_Warning;
1453 }
1454}
1455
1456bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
1457
1458TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
1459 return TargetInfo::AArch64ABIBuiltinVaList;
1460}
1461
1462const char *const AArch64TargetInfo::GCCRegNames[] = {
1463 // clang-format off
1464
1465 // 32-bit Integer registers
1466 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
1467 "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
1468 "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
1469
1470 // 64-bit Integer registers
1471 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
1472 "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
1473 "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
1474
1475 // 32-bit floating point regsisters
1476 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
1477 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
1478 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
1479
1480 // 64-bit floating point regsisters
1481 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
1482 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
1483 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
1484
1485 // Neon vector registers
1486 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
1487 "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
1488 "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
1489
1490 // SVE vector registers
1491 "z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8", "z9", "z10",
1492 "z11", "z12", "z13", "z14", "z15", "z16", "z17", "z18", "z19", "z20", "z21",
1493 "z22", "z23", "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31",
1494
1495 // SVE predicate registers
1496 "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9", "p10",
1497 "p11", "p12", "p13", "p14", "p15",
1498
1499 // SVE predicate-as-counter registers
1500 "pn0", "pn1", "pn2", "pn3", "pn4", "pn5", "pn6", "pn7", "pn8",
1501 "pn9", "pn10", "pn11", "pn12", "pn13", "pn14", "pn15",
1502
1503 // SME registers
1504 "za", "zt0",
1505
1506 // clang-format on
1507};
1508
1509ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
1510 return llvm::ArrayRef(GCCRegNames);
1511}
1512
1513const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
1514 {.Aliases: {"w31"}, .Register: "wsp"},
1515 {.Aliases: {"x31"}, .Register: "sp"},
1516 // GCC rN registers are aliases of xN registers.
1517 {.Aliases: {"r0"}, .Register: "x0"},
1518 {.Aliases: {"r1"}, .Register: "x1"},
1519 {.Aliases: {"r2"}, .Register: "x2"},
1520 {.Aliases: {"r3"}, .Register: "x3"},
1521 {.Aliases: {"r4"}, .Register: "x4"},
1522 {.Aliases: {"r5"}, .Register: "x5"},
1523 {.Aliases: {"r6"}, .Register: "x6"},
1524 {.Aliases: {"r7"}, .Register: "x7"},
1525 {.Aliases: {"r8"}, .Register: "x8"},
1526 {.Aliases: {"r9"}, .Register: "x9"},
1527 {.Aliases: {"r10"}, .Register: "x10"},
1528 {.Aliases: {"r11"}, .Register: "x11"},
1529 {.Aliases: {"r12"}, .Register: "x12"},
1530 {.Aliases: {"r13"}, .Register: "x13"},
1531 {.Aliases: {"r14"}, .Register: "x14"},
1532 {.Aliases: {"r15"}, .Register: "x15"},
1533 {.Aliases: {"r16"}, .Register: "x16"},
1534 {.Aliases: {"r17"}, .Register: "x17"},
1535 {.Aliases: {"r18"}, .Register: "x18"},
1536 {.Aliases: {"r19"}, .Register: "x19"},
1537 {.Aliases: {"r20"}, .Register: "x20"},
1538 {.Aliases: {"r21"}, .Register: "x21"},
1539 {.Aliases: {"r22"}, .Register: "x22"},
1540 {.Aliases: {"r23"}, .Register: "x23"},
1541 {.Aliases: {"r24"}, .Register: "x24"},
1542 {.Aliases: {"r25"}, .Register: "x25"},
1543 {.Aliases: {"r26"}, .Register: "x26"},
1544 {.Aliases: {"r27"}, .Register: "x27"},
1545 {.Aliases: {"r28"}, .Register: "x28"},
1546 {.Aliases: {"r29", "x29"}, .Register: "fp"},
1547 {.Aliases: {"r30", "x30"}, .Register: "lr"},
1548 // The S/D/Q and W/X registers overlap, but aren't really aliases; we
1549 // don't want to substitute one of these for a different-sized one.
1550};
1551
1552ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
1553 return llvm::ArrayRef(GCCRegAliases);
1554}
1555
1556// Returns the length of cc constraint.
1557static unsigned matchAsmCCConstraint(const char *Name) {
1558 constexpr unsigned len = 5;
1559 auto RV = llvm::StringSwitch<unsigned>(Name)
1560 .Case(S: "@cceq", Value: len)
1561 .Case(S: "@ccne", Value: len)
1562 .Case(S: "@cchs", Value: len)
1563 .Case(S: "@cccs", Value: len)
1564 .Case(S: "@cccc", Value: len)
1565 .Case(S: "@cclo", Value: len)
1566 .Case(S: "@ccmi", Value: len)
1567 .Case(S: "@ccpl", Value: len)
1568 .Case(S: "@ccvs", Value: len)
1569 .Case(S: "@ccvc", Value: len)
1570 .Case(S: "@cchi", Value: len)
1571 .Case(S: "@ccls", Value: len)
1572 .Case(S: "@ccge", Value: len)
1573 .Case(S: "@cclt", Value: len)
1574 .Case(S: "@ccgt", Value: len)
1575 .Case(S: "@ccle", Value: len)
1576 .Default(Value: 0);
1577 return RV;
1578}
1579
1580std::string
1581AArch64TargetInfo::convertConstraint(const char *&Constraint) const {
1582 std::string R;
1583 switch (*Constraint) {
1584 case 'U': // Three-character constraint; add "@3" hint for later parsing.
1585 R = std::string("@3") + std::string(Constraint, 3);
1586 Constraint += 2;
1587 break;
1588 case '@':
1589 if (const unsigned Len = matchAsmCCConstraint(Name: Constraint)) {
1590 std::string Converted = "{" + std::string(Constraint, Len) + "}";
1591 Constraint += Len - 1;
1592 return Converted;
1593 }
1594 return std::string(1, *Constraint);
1595 default:
1596 R = TargetInfo::convertConstraint(Constraint);
1597 break;
1598 }
1599 return R;
1600}
1601
1602bool AArch64TargetInfo::validateAsmConstraint(
1603 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
1604 switch (*Name) {
1605 default:
1606 return false;
1607 case 'w': // Floating point and SIMD registers (V0-V31)
1608 Info.setAllowsRegister();
1609 return true;
1610 case 'I': // Constant that can be used with an ADD instruction
1611 case 'J': // Constant that can be used with a SUB instruction
1612 case 'K': // Constant that can be used with a 32-bit logical instruction
1613 case 'L': // Constant that can be used with a 64-bit logical instruction
1614 case 'M': // Constant that can be used as a 32-bit MOV immediate
1615 case 'N': // Constant that can be used as a 64-bit MOV immediate
1616 case 'Y': // Floating point constant zero
1617 case 'Z': // Integer constant zero
1618 return true;
1619 case 'Q': // A memory reference with base register and no offset
1620 Info.setAllowsMemory();
1621 return true;
1622 case 'S': // A symbolic address
1623 Info.setAllowsRegister();
1624 return true;
1625 case 'U':
1626 if (Name[1] == 'p' &&
1627 (Name[2] == 'l' || Name[2] == 'a' || Name[2] == 'h')) {
1628 // SVE predicate registers ("Upa"=P0-15, "Upl"=P0-P7, "Uph"=P8-P15)
1629 Info.setAllowsRegister();
1630 Name += 2;
1631 return true;
1632 }
1633 if (Name[1] == 'c' && (Name[2] == 'i' || Name[2] == 'j')) {
1634 // Gpr registers ("Uci"=w8-11, "Ucj"=w12-15)
1635 Info.setAllowsRegister();
1636 Name += 2;
1637 return true;
1638 }
1639 // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
1640 // Utf: A memory address suitable for ldp/stp in TF mode.
1641 // Usa: An absolute symbolic address.
1642 // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
1643
1644 // Better to return an error saying that it's an unrecognised constraint
1645 // even if this is a valid constraint in gcc.
1646 return false;
1647 case 'z': // Zero register, wzr or xzr
1648 Info.setAllowsRegister();
1649 return true;
1650 case 'x': // Floating point and SIMD registers (V0-V15)
1651 Info.setAllowsRegister();
1652 return true;
1653 case 'y': // SVE registers (V0-V7)
1654 Info.setAllowsRegister();
1655 return true;
1656 case '@':
1657 // CC condition
1658 if (const unsigned Len = matchAsmCCConstraint(Name)) {
1659 Name += Len - 1;
1660 Info.setAllowsRegister();
1661 Info.setOutputOperandBounds(Min: 0, Max: 2);
1662 return true;
1663 }
1664 }
1665 return false;
1666}
1667
1668bool AArch64TargetInfo::validateConstraintModifier(
1669 StringRef Constraint, char Modifier, unsigned Size,
1670 std::string &SuggestedModifier) const {
1671 // Strip off constraint modifiers.
1672 Constraint = Constraint.ltrim(Chars: "=+&");
1673
1674 switch (Constraint[0]) {
1675 default:
1676 return true;
1677 case 'z':
1678 case 'r': {
1679 switch (Modifier) {
1680 case 'x':
1681 case 'w':
1682 // For now assume that the person knows what they're
1683 // doing with the modifier.
1684 return true;
1685 default:
1686 // By default an 'r' constraint will be in the 'x'
1687 // registers.
1688 if (Size == 64)
1689 return true;
1690
1691 if (Size == 512)
1692 return HasLS64;
1693
1694 SuggestedModifier = "w";
1695 return false;
1696 }
1697 }
1698 }
1699}
1700
1701std::string_view AArch64TargetInfo::getClobbers() const { return ""; }
1702
1703int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
1704 if (RegNo == 0)
1705 return 0;
1706 if (RegNo == 1)
1707 return 1;
1708 return -1;
1709}
1710
1711bool AArch64TargetInfo::validatePointerAuthKey(
1712 const llvm::APSInt &value) const {
1713 return 0 <= value && value <= 3;
1714}
1715
1716bool AArch64TargetInfo::hasInt128Type() const { return true; }
1717
1718AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
1719 const TargetOptions &Opts)
1720 : AArch64TargetInfo(Triple, Opts) {}
1721
1722void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
1723 MacroBuilder &Builder) const {
1724 Builder.defineMacro(Name: "__AARCH64EL__");
1725 AArch64TargetInfo::getTargetDefines(Opts, Builder);
1726}
1727
1728AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
1729 const TargetOptions &Opts)
1730 : AArch64TargetInfo(Triple, Opts) {}
1731
1732void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
1733 MacroBuilder &Builder) const {
1734 Builder.defineMacro(Name: "__AARCH64EB__");
1735 Builder.defineMacro(Name: "__AARCH_BIG_ENDIAN");
1736 Builder.defineMacro(Name: "__ARM_BIG_ENDIAN");
1737 AArch64TargetInfo::getTargetDefines(Opts, Builder);
1738}
1739
1740WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
1741 const TargetOptions &Opts)
1742 : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
1743
1744 // This is an LLP64 platform.
1745 // int:4, long:4, long long:8, long double:8.
1746 IntWidth = IntAlign = 32;
1747 LongWidth = LongAlign = 32;
1748 DoubleAlign = LongLongAlign = 64;
1749 LongDoubleWidth = LongDoubleAlign = 64;
1750 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
1751 IntMaxType = SignedLongLong;
1752 Int64Type = SignedLongLong;
1753 SizeType = UnsignedLongLong;
1754 PtrDiffType = SignedLongLong;
1755 IntPtrType = SignedLongLong;
1756}
1757
1758TargetInfo::BuiltinVaListKind
1759WindowsARM64TargetInfo::getBuiltinVaListKind() const {
1760 return TargetInfo::CharPtrBuiltinVaList;
1761}
1762
1763TargetInfo::CallingConvCheckResult
1764WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
1765 switch (CC) {
1766 case CC_X86VectorCall:
1767 if (getTriple().isWindowsArm64EC())
1768 return CCCR_OK;
1769 return CCCR_Ignore;
1770 case CC_X86StdCall:
1771 case CC_X86ThisCall:
1772 case CC_X86FastCall:
1773 return CCCR_Ignore;
1774 case CC_C:
1775 case CC_DeviceKernel:
1776 case CC_PreserveMost:
1777 case CC_PreserveAll:
1778 case CC_PreserveNone:
1779 case CC_Swift:
1780 case CC_SwiftAsync:
1781 case CC_Win64:
1782 return CCCR_OK;
1783 default:
1784 return CCCR_Warning;
1785 }
1786}
1787
1788MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
1789 const TargetOptions &Opts)
1790 : WindowsARM64TargetInfo(Triple, Opts) {
1791 TheCXXABI.set(TargetCXXABI::Microsoft);
1792}
1793
1794void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
1795 MacroBuilder &Builder) const {
1796 WindowsARM64TargetInfo::getTargetDefines(Opts, Builder);
1797 if (getTriple().isWindowsArm64EC()) {
1798 Builder.defineMacro(Name: "_M_X64", Value: "100");
1799 Builder.defineMacro(Name: "_M_AMD64", Value: "100");
1800 Builder.defineMacro(Name: "_M_ARM64EC", Value: "1");
1801 } else {
1802 Builder.defineMacro(Name: "_M_ARM64", Value: "1");
1803 }
1804}
1805
1806TargetInfo::CallingConvKind
1807MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
1808 return CCK_MicrosoftWin64;
1809}
1810
1811unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize,
1812 bool HasNonWeakDef) const {
1813 unsigned Align =
1814 WindowsARM64TargetInfo::getMinGlobalAlign(Size: TypeSize, HasNonWeakDef);
1815
1816 return std::max(a: Align, b: Microsoft64BitMinGlobalAlign(TypeSize));
1817}
1818
1819MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
1820 const TargetOptions &Opts)
1821 : WindowsARM64TargetInfo(Triple, Opts) {
1822 TheCXXABI.set(TargetCXXABI::GenericAArch64);
1823}
1824
1825AppleMachOAArch64TargetInfo::AppleMachOAArch64TargetInfo(
1826 const llvm::Triple &Triple, const TargetOptions &Opts)
1827 : AppleMachOTargetInfo<AArch64leTargetInfo>(Triple, Opts) {}
1828
1829DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
1830 const TargetOptions &Opts)
1831 : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
1832 Int64Type = SignedLongLong;
1833 if (getTriple().isArch32Bit())
1834 IntMaxType = SignedLongLong;
1835
1836 WCharType = SignedInt;
1837 UseSignedCharForObjCBool = false;
1838
1839 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
1840 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
1841
1842 UseZeroLengthBitfieldAlignment = false;
1843
1844 if (getTriple().isArch32Bit()) {
1845 UseBitFieldTypeAlignment = false;
1846 ZeroLengthBitfieldBoundary = 32;
1847 UseZeroLengthBitfieldAlignment = true;
1848 TheCXXABI.set(TargetCXXABI::WatchOS);
1849 } else
1850 TheCXXABI.set(TargetCXXABI::AppleARM64);
1851}
1852
1853void clang::targets::getAppleMachOAArch64Defines(MacroBuilder &Builder,
1854 const LangOptions &Opts,
1855 const llvm::Triple &Triple) {
1856 Builder.defineMacro(Name: "__AARCH64_SIMD__");
1857 if (Triple.isArch32Bit())
1858 Builder.defineMacro(Name: "__ARM64_ARCH_8_32__");
1859 else
1860 Builder.defineMacro(Name: "__ARM64_ARCH_8__");
1861 Builder.defineMacro(Name: "__ARM_NEON__");
1862 Builder.defineMacro(Name: "__REGISTER_PREFIX__", Value: "");
1863 Builder.defineMacro(Name: "__arm64", Value: "1");
1864 Builder.defineMacro(Name: "__arm64__", Value: "1");
1865
1866 if (Triple.isArm64e()) {
1867 Builder.defineMacro(Name: "__arm64e__", Value: "1");
1868 Builder.defineMacro(Name: "__PTRAUTH_INTRINSICS__", Value: "1");
1869 }
1870}
1871
1872void AppleMachOAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
1873 const llvm::Triple &Triple,
1874 MacroBuilder &Builder) const {
1875 getAppleMachOAArch64Defines(Builder, Opts, Triple);
1876 AppleMachOTargetInfo<AArch64leTargetInfo>::getOSDefines(Opts, Triple,
1877 Builder);
1878}
1879
1880void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
1881 const llvm::Triple &Triple,
1882 MacroBuilder &Builder) const {
1883 getAppleMachOAArch64Defines(Builder, Opts, Triple);
1884 DarwinTargetInfo<AArch64leTargetInfo>::getOSDefines(Opts, Triple, Builder);
1885}
1886
1887TargetInfo::BuiltinVaListKind
1888DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
1889 return TargetInfo::CharPtrBuiltinVaList;
1890}
1891