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