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