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/LangOptions.h"
15 #include "clang/Basic/TargetBuiltins.h"
16 #include "clang/Basic/TargetInfo.h"
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/ADT/StringSwitch.h"
20 #include "llvm/Support/AArch64TargetParser.h"
21
22 using namespace clang;
23 using namespace clang::targets;
24
25 const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
26 #define BUILTIN(ID, TYPE, ATTRS) \
27 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
28 #include "clang/Basic/BuiltinsNEON.def"
29
30 #define BUILTIN(ID, TYPE, ATTRS) \
31 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
32 #include "clang/Basic/BuiltinsSVE.def"
33
34 #define BUILTIN(ID, TYPE, ATTRS) \
35 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
36 #define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \
37 {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
38 #define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
39 {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
40 #include "clang/Basic/BuiltinsAArch64.def"
41 };
42
AArch64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)43 AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
44 const TargetOptions &Opts)
45 : TargetInfo(Triple), ABI("aapcs") {
46 if (getTriple().isOSOpenBSD()) {
47 Int64Type = SignedLongLong;
48 IntMaxType = SignedLongLong;
49 } else {
50 if (!getTriple().isOSDarwin() && !getTriple().isOSNetBSD())
51 WCharType = UnsignedInt;
52
53 Int64Type = SignedLong;
54 IntMaxType = SignedLong;
55 }
56
57 // All AArch64 implementations support ARMv8 FP, which makes half a legal type.
58 HasLegalHalfType = true;
59 HasFloat16 = true;
60
61 if (Triple.isArch64Bit())
62 LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
63 else
64 LongWidth = LongAlign = PointerWidth = PointerAlign = 32;
65
66 MaxVectorAlign = 128;
67 MaxAtomicInlineWidth = 128;
68 MaxAtomicPromoteWidth = 128;
69
70 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
71 LongDoubleFormat = &llvm::APFloat::IEEEquad();
72
73 BFloat16Width = BFloat16Align = 16;
74 BFloat16Format = &llvm::APFloat::BFloat();
75
76 // Make __builtin_ms_va_list available.
77 HasBuiltinMSVaList = true;
78
79 // Make the SVE types available. Note that this deliberately doesn't
80 // depend on SveMode, since in principle it should be possible to turn
81 // SVE on and off within a translation unit. It should also be possible
82 // to compile the global declaration:
83 //
84 // __SVInt8_t *ptr;
85 //
86 // even without SVE.
87 HasAArch64SVETypes = true;
88
89 // {} in inline assembly are neon specifiers, not assembly variant
90 // specifiers.
91 NoAsmVariants = true;
92
93 // AAPCS gives rules for bitfields. 7.1.7 says: "The container type
94 // contributes to the alignment of the containing aggregate in the same way
95 // a plain (non bit-field) member of that type would, without exception for
96 // zero-sized or anonymous bit-fields."
97 assert(UseBitFieldTypeAlignment && "bitfields affect type alignment");
98 UseZeroLengthBitfieldAlignment = true;
99
100 // AArch64 targets default to using the ARM C++ ABI.
101 TheCXXABI.set(TargetCXXABI::GenericAArch64);
102
103 if (Triple.getOS() == llvm::Triple::Linux)
104 this->MCountName = "\01_mcount";
105 else if (Triple.getOS() == llvm::Triple::UnknownOS)
106 this->MCountName =
107 Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
108 }
109
getABI() const110 StringRef AArch64TargetInfo::getABI() const { return ABI; }
111
setABI(const std::string & Name)112 bool AArch64TargetInfo::setABI(const std::string &Name) {
113 if (Name != "aapcs" && Name != "darwinpcs")
114 return false;
115
116 ABI = Name;
117 return true;
118 }
119
validateBranchProtection(StringRef Spec,BranchProtectionInfo & BPI,StringRef & Err) const120 bool AArch64TargetInfo::validateBranchProtection(StringRef Spec,
121 BranchProtectionInfo &BPI,
122 StringRef &Err) const {
123 llvm::AArch64::ParsedBranchProtection PBP;
124 if (!llvm::AArch64::parseBranchProtection(Spec, PBP, Err))
125 return false;
126
127 BPI.SignReturnAddr =
128 llvm::StringSwitch<LangOptions::SignReturnAddressScopeKind>(PBP.Scope)
129 .Case("non-leaf", LangOptions::SignReturnAddressScopeKind::NonLeaf)
130 .Case("all", LangOptions::SignReturnAddressScopeKind::All)
131 .Default(LangOptions::SignReturnAddressScopeKind::None);
132
133 if (PBP.Key == "a_key")
134 BPI.SignKey = LangOptions::SignReturnAddressKeyKind::AKey;
135 else
136 BPI.SignKey = LangOptions::SignReturnAddressKeyKind::BKey;
137
138 BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement;
139 return true;
140 }
141
isValidCPUName(StringRef Name) const142 bool AArch64TargetInfo::isValidCPUName(StringRef Name) const {
143 return Name == "generic" ||
144 llvm::AArch64::parseCPUArch(Name) != llvm::AArch64::ArchKind::INVALID;
145 }
146
setCPU(const std::string & Name)147 bool AArch64TargetInfo::setCPU(const std::string &Name) {
148 return isValidCPUName(Name);
149 }
150
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const151 void AArch64TargetInfo::fillValidCPUList(
152 SmallVectorImpl<StringRef> &Values) const {
153 llvm::AArch64::fillValidCPUArchList(Values);
154 }
155
getTargetDefinesARMV81A(const LangOptions & Opts,MacroBuilder & Builder) const156 void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
157 MacroBuilder &Builder) const {
158 Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
159 Builder.defineMacro("__ARM_FEATURE_ATOMICS", "1");
160 Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
161 }
162
getTargetDefinesARMV82A(const LangOptions & Opts,MacroBuilder & Builder) const163 void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
164 MacroBuilder &Builder) const {
165 // Also include the ARMv8.1 defines
166 getTargetDefinesARMV81A(Opts, Builder);
167 }
168
getTargetDefinesARMV83A(const LangOptions & Opts,MacroBuilder & Builder) const169 void AArch64TargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts,
170 MacroBuilder &Builder) const {
171 Builder.defineMacro("__ARM_FEATURE_COMPLEX", "1");
172 Builder.defineMacro("__ARM_FEATURE_JCVT", "1");
173 // Also include the Armv8.2 defines
174 getTargetDefinesARMV82A(Opts, Builder);
175 }
176
getTargetDefinesARMV84A(const LangOptions & Opts,MacroBuilder & Builder) const177 void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts,
178 MacroBuilder &Builder) const {
179 // Also include the Armv8.3 defines
180 getTargetDefinesARMV83A(Opts, Builder);
181 }
182
getTargetDefinesARMV85A(const LangOptions & Opts,MacroBuilder & Builder) const183 void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts,
184 MacroBuilder &Builder) const {
185 // Also include the Armv8.4 defines
186 getTargetDefinesARMV84A(Opts, Builder);
187 }
188
getTargetDefinesARMV86A(const LangOptions & Opts,MacroBuilder & Builder) const189 void AArch64TargetInfo::getTargetDefinesARMV86A(const LangOptions &Opts,
190 MacroBuilder &Builder) const {
191 // Also include the Armv8.5 defines
192 // FIXME: Armv8.6 makes the following extensions mandatory:
193 // - __ARM_FEATURE_BF16
194 // - __ARM_FEATURE_MATMUL_INT8
195 // Handle them here.
196 getTargetDefinesARMV85A(Opts, Builder);
197 }
198
getTargetDefinesARMV87A(const LangOptions & Opts,MacroBuilder & Builder) const199 void AArch64TargetInfo::getTargetDefinesARMV87A(const LangOptions &Opts,
200 MacroBuilder &Builder) const {
201 // Also include the Armv8.6 defines
202 getTargetDefinesARMV86A(Opts, Builder);
203 }
204
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const205 void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
206 MacroBuilder &Builder) const {
207 // Target identification.
208 Builder.defineMacro("__aarch64__");
209 // For bare-metal.
210 if (getTriple().getOS() == llvm::Triple::UnknownOS &&
211 getTriple().isOSBinFormatELF())
212 Builder.defineMacro("__ELF__");
213
214 // Target properties.
215 if (!getTriple().isOSWindows() && getTriple().isArch64Bit()) {
216 Builder.defineMacro("_LP64");
217 Builder.defineMacro("__LP64__");
218 }
219
220 std::string CodeModel = getTargetOpts().CodeModel;
221 if (CodeModel == "default")
222 CodeModel = "small";
223 for (char &c : CodeModel)
224 c = toupper(c);
225 Builder.defineMacro("__AARCH64_CMODEL_" + CodeModel + "__");
226
227 // ACLE predefines. Many can only have one possible value on v8 AArch64.
228 Builder.defineMacro("__ARM_ACLE", "200");
229 Builder.defineMacro("__ARM_ARCH", "8");
230 Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
231
232 Builder.defineMacro("__ARM_64BIT_STATE", "1");
233 Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
234 Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
235
236 Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
237 Builder.defineMacro("__ARM_FEATURE_FMA", "1");
238 Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
239 Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
240 Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility
241 Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
242 Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
243
244 Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
245
246 // 0xe implies support for half, single and double precision operations.
247 Builder.defineMacro("__ARM_FP", "0xE");
248
249 // PCS specifies this for SysV variants, which is all we support. Other ABIs
250 // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
251 Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
252 Builder.defineMacro("__ARM_FP16_ARGS", "1");
253
254 if (Opts.UnsafeFPMath)
255 Builder.defineMacro("__ARM_FP_FAST", "1");
256
257 Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
258 Twine(Opts.WCharSize ? Opts.WCharSize : 4));
259
260 Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
261
262 if (FPU & NeonMode) {
263 Builder.defineMacro("__ARM_NEON", "1");
264 // 64-bit NEON supports half, single and double precision operations.
265 Builder.defineMacro("__ARM_NEON_FP", "0xE");
266 }
267
268 if (FPU & SveMode)
269 Builder.defineMacro("__ARM_FEATURE_SVE", "1");
270
271 if (HasSVE2)
272 Builder.defineMacro("__ARM_FEATURE_SVE2", "1");
273
274 if (HasSVE2 && HasSVE2AES)
275 Builder.defineMacro("__ARM_FEATURE_SVE2_AES", "1");
276
277 if (HasSVE2 && HasSVE2BitPerm)
278 Builder.defineMacro("__ARM_FEATURE_SVE2_BITPERM", "1");
279
280 if (HasSVE2 && HasSVE2SHA3)
281 Builder.defineMacro("__ARM_FEATURE_SVE2_SHA3", "1");
282
283 if (HasSVE2 && HasSVE2SM4)
284 Builder.defineMacro("__ARM_FEATURE_SVE2_SM4", "1");
285
286 if (HasCRC)
287 Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
288
289 if (HasCrypto)
290 Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
291
292 if (HasUnaligned)
293 Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
294
295 if ((FPU & NeonMode) && HasFullFP16)
296 Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
297 if (HasFullFP16)
298 Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
299
300 if (HasDotProd)
301 Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
302
303 if (HasMTE)
304 Builder.defineMacro("__ARM_FEATURE_MEMORY_TAGGING", "1");
305
306 if (HasTME)
307 Builder.defineMacro("__ARM_FEATURE_TME", "1");
308
309 if (HasMatMul)
310 Builder.defineMacro("__ARM_FEATURE_MATMUL_INT8", "1");
311
312 if (HasLSE)
313 Builder.defineMacro("__ARM_FEATURE_ATOMICS", "1");
314
315 if (HasBFloat16) {
316 Builder.defineMacro("__ARM_FEATURE_BF16", "1");
317 Builder.defineMacro("__ARM_FEATURE_BF16_VECTOR_ARITHMETIC", "1");
318 Builder.defineMacro("__ARM_BF16_FORMAT_ALTERNATIVE", "1");
319 Builder.defineMacro("__ARM_FEATURE_BF16_SCALAR_ARITHMETIC", "1");
320 }
321
322 if ((FPU & SveMode) && HasBFloat16) {
323 Builder.defineMacro("__ARM_FEATURE_SVE_BF16", "1");
324 }
325
326 if ((FPU & SveMode) && HasMatmulFP64)
327 Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_FP64", "1");
328
329 if ((FPU & SveMode) && HasMatmulFP32)
330 Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_FP32", "1");
331
332 if ((FPU & SveMode) && HasMatMul)
333 Builder.defineMacro("__ARM_FEATURE_SVE_MATMUL_INT8", "1");
334
335 if ((FPU & NeonMode) && HasFP16FML)
336 Builder.defineMacro("__ARM_FEATURE_FP16FML", "1");
337
338 if (Opts.hasSignReturnAddress()) {
339 // Bitmask:
340 // 0: Protection using the A key
341 // 1: Protection using the B key
342 // 2: Protection including leaf functions
343 unsigned Value = 0;
344
345 if (Opts.isSignReturnAddressWithAKey())
346 Value |= (1 << 0);
347 else
348 Value |= (1 << 1);
349
350 if (Opts.isSignReturnAddressScopeAll())
351 Value |= (1 << 2);
352
353 Builder.defineMacro("__ARM_FEATURE_PAC_DEFAULT", std::to_string(Value));
354 }
355
356 if (Opts.BranchTargetEnforcement)
357 Builder.defineMacro("__ARM_FEATURE_BTI_DEFAULT", "1");
358
359 if (HasLS64)
360 Builder.defineMacro("__ARM_FEATURE_LS64", "1");
361
362 switch (ArchKind) {
363 default:
364 break;
365 case llvm::AArch64::ArchKind::ARMV8_1A:
366 getTargetDefinesARMV81A(Opts, Builder);
367 break;
368 case llvm::AArch64::ArchKind::ARMV8_2A:
369 getTargetDefinesARMV82A(Opts, Builder);
370 break;
371 case llvm::AArch64::ArchKind::ARMV8_3A:
372 getTargetDefinesARMV83A(Opts, Builder);
373 break;
374 case llvm::AArch64::ArchKind::ARMV8_4A:
375 getTargetDefinesARMV84A(Opts, Builder);
376 break;
377 case llvm::AArch64::ArchKind::ARMV8_5A:
378 getTargetDefinesARMV85A(Opts, Builder);
379 break;
380 case llvm::AArch64::ArchKind::ARMV8_6A:
381 getTargetDefinesARMV86A(Opts, Builder);
382 break;
383 case llvm::AArch64::ArchKind::ARMV8_7A:
384 getTargetDefinesARMV87A(Opts, Builder);
385 break;
386 }
387
388 // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
389 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
390 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
391 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
392 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
393
394 if (Opts.ArmSveVectorBits) {
395 Builder.defineMacro("__ARM_FEATURE_SVE_BITS", Twine(Opts.ArmSveVectorBits));
396 Builder.defineMacro("__ARM_FEATURE_SVE_VECTOR_OPERATORS");
397 }
398 }
399
getTargetBuiltins() const400 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
401 return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
402 Builtin::FirstTSBuiltin);
403 }
404
hasFeature(StringRef Feature) const405 bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
406 return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" ||
407 (Feature == "neon" && (FPU & NeonMode)) ||
408 ((Feature == "sve" || Feature == "sve2" || Feature == "sve2-bitperm" ||
409 Feature == "sve2-aes" || Feature == "sve2-sha3" ||
410 Feature == "sve2-sm4" || Feature == "f64mm" || Feature == "f32mm" ||
411 Feature == "i8mm" || Feature == "bf16") &&
412 (FPU & SveMode));
413 }
414
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)415 bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
416 DiagnosticsEngine &Diags) {
417 FPU = FPUMode;
418 HasCRC = false;
419 HasCrypto = false;
420 HasUnaligned = true;
421 HasFullFP16 = false;
422 HasDotProd = false;
423 HasFP16FML = false;
424 HasMTE = false;
425 HasTME = false;
426 HasLS64 = false;
427 HasMatMul = false;
428 HasBFloat16 = false;
429 HasSVE2 = false;
430 HasSVE2AES = false;
431 HasSVE2SHA3 = false;
432 HasSVE2SM4 = false;
433 HasSVE2BitPerm = false;
434 HasMatmulFP64 = false;
435 HasMatmulFP32 = false;
436 HasLSE = false;
437
438 ArchKind = llvm::AArch64::ArchKind::ARMV8A;
439
440 for (const auto &Feature : Features) {
441 if (Feature == "+neon")
442 FPU |= NeonMode;
443 if (Feature == "+sve") {
444 FPU |= SveMode;
445 HasFullFP16 = 1;
446 }
447 if (Feature == "+sve2") {
448 FPU |= SveMode;
449 HasFullFP16 = 1;
450 HasSVE2 = 1;
451 }
452 if (Feature == "+sve2-aes") {
453 FPU |= SveMode;
454 HasFullFP16 = 1;
455 HasSVE2 = 1;
456 HasSVE2AES = 1;
457 }
458 if (Feature == "+sve2-sha3") {
459 FPU |= SveMode;
460 HasFullFP16 = 1;
461 HasSVE2 = 1;
462 HasSVE2SHA3 = 1;
463 }
464 if (Feature == "+sve2-sm4") {
465 FPU |= SveMode;
466 HasFullFP16 = 1;
467 HasSVE2 = 1;
468 HasSVE2SM4 = 1;
469 }
470 if (Feature == "+sve2-bitperm") {
471 FPU |= SveMode;
472 HasFullFP16 = 1;
473 HasSVE2 = 1;
474 HasSVE2BitPerm = 1;
475 }
476 if (Feature == "+f32mm") {
477 FPU |= SveMode;
478 HasMatmulFP32 = true;
479 }
480 if (Feature == "+f64mm") {
481 FPU |= SveMode;
482 HasMatmulFP64 = true;
483 }
484 if (Feature == "+crc")
485 HasCRC = true;
486 if (Feature == "+crypto")
487 HasCrypto = true;
488 if (Feature == "+strict-align")
489 HasUnaligned = false;
490 if (Feature == "+v8.1a")
491 ArchKind = llvm::AArch64::ArchKind::ARMV8_1A;
492 if (Feature == "+v8.2a")
493 ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
494 if (Feature == "+v8.3a")
495 ArchKind = llvm::AArch64::ArchKind::ARMV8_3A;
496 if (Feature == "+v8.4a")
497 ArchKind = llvm::AArch64::ArchKind::ARMV8_4A;
498 if (Feature == "+v8.5a")
499 ArchKind = llvm::AArch64::ArchKind::ARMV8_5A;
500 if (Feature == "+v8.6a")
501 ArchKind = llvm::AArch64::ArchKind::ARMV8_6A;
502 if (Feature == "+v8.7a")
503 ArchKind = llvm::AArch64::ArchKind::ARMV8_7A;
504 if (Feature == "+v8r")
505 ArchKind = llvm::AArch64::ArchKind::ARMV8R;
506 if (Feature == "+fullfp16")
507 HasFullFP16 = true;
508 if (Feature == "+dotprod")
509 HasDotProd = true;
510 if (Feature == "+fp16fml")
511 HasFP16FML = true;
512 if (Feature == "+mte")
513 HasMTE = true;
514 if (Feature == "+tme")
515 HasTME = true;
516 if (Feature == "+pauth")
517 HasPAuth = true;
518 if (Feature == "+i8mm")
519 HasMatMul = true;
520 if (Feature == "+bf16")
521 HasBFloat16 = true;
522 if (Feature == "+lse")
523 HasLSE = true;
524 if (Feature == "+ls64")
525 HasLS64 = true;
526 if (Feature == "+flagm")
527 HasFlagM = true;
528 }
529
530 setDataLayout();
531
532 return true;
533 }
534
535 TargetInfo::CallingConvCheckResult
checkCallingConvention(CallingConv CC) const536 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
537 switch (CC) {
538 case CC_C:
539 case CC_Swift:
540 case CC_PreserveMost:
541 case CC_PreserveAll:
542 case CC_OpenCLKernel:
543 case CC_AArch64VectorCall:
544 case CC_Win64:
545 return CCCR_OK;
546 default:
547 return CCCR_Warning;
548 }
549 }
550
isCLZForZeroUndef() const551 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
552
getBuiltinVaListKind() const553 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
554 return TargetInfo::AArch64ABIBuiltinVaList;
555 }
556
557 const char *const AArch64TargetInfo::GCCRegNames[] = {
558 // 32-bit Integer registers
559 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
560 "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
561 "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
562
563 // 64-bit Integer registers
564 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
565 "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
566 "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
567
568 // 32-bit floating point regsisters
569 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
570 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
571 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
572
573 // 64-bit floating point regsisters
574 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
575 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
576 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
577
578 // Neon vector registers
579 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
580 "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
581 "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
582
583 // SVE vector registers
584 "z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8", "z9", "z10",
585 "z11", "z12", "z13", "z14", "z15", "z16", "z17", "z18", "z19", "z20", "z21",
586 "z22", "z23", "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31",
587
588 // SVE predicate registers
589 "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9", "p10",
590 "p11", "p12", "p13", "p14", "p15"
591 };
592
getGCCRegNames() const593 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
594 return llvm::makeArrayRef(GCCRegNames);
595 }
596
597 const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
598 {{"w31"}, "wsp"},
599 {{"x31"}, "sp"},
600 // GCC rN registers are aliases of xN registers.
601 {{"r0"}, "x0"},
602 {{"r1"}, "x1"},
603 {{"r2"}, "x2"},
604 {{"r3"}, "x3"},
605 {{"r4"}, "x4"},
606 {{"r5"}, "x5"},
607 {{"r6"}, "x6"},
608 {{"r7"}, "x7"},
609 {{"r8"}, "x8"},
610 {{"r9"}, "x9"},
611 {{"r10"}, "x10"},
612 {{"r11"}, "x11"},
613 {{"r12"}, "x12"},
614 {{"r13"}, "x13"},
615 {{"r14"}, "x14"},
616 {{"r15"}, "x15"},
617 {{"r16"}, "x16"},
618 {{"r17"}, "x17"},
619 {{"r18"}, "x18"},
620 {{"r19"}, "x19"},
621 {{"r20"}, "x20"},
622 {{"r21"}, "x21"},
623 {{"r22"}, "x22"},
624 {{"r23"}, "x23"},
625 {{"r24"}, "x24"},
626 {{"r25"}, "x25"},
627 {{"r26"}, "x26"},
628 {{"r27"}, "x27"},
629 {{"r28"}, "x28"},
630 {{"r29", "x29"}, "fp"},
631 {{"r30", "x30"}, "lr"},
632 // The S/D/Q and W/X registers overlap, but aren't really aliases; we
633 // don't want to substitute one of these for a different-sized one.
634 };
635
getGCCRegAliases() const636 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
637 return llvm::makeArrayRef(GCCRegAliases);
638 }
639
validateAsmConstraint(const char * & Name,TargetInfo::ConstraintInfo & Info) const640 bool AArch64TargetInfo::validateAsmConstraint(
641 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
642 switch (*Name) {
643 default:
644 return false;
645 case 'w': // Floating point and SIMD registers (V0-V31)
646 Info.setAllowsRegister();
647 return true;
648 case 'I': // Constant that can be used with an ADD instruction
649 case 'J': // Constant that can be used with a SUB instruction
650 case 'K': // Constant that can be used with a 32-bit logical instruction
651 case 'L': // Constant that can be used with a 64-bit logical instruction
652 case 'M': // Constant that can be used as a 32-bit MOV immediate
653 case 'N': // Constant that can be used as a 64-bit MOV immediate
654 case 'Y': // Floating point constant zero
655 case 'Z': // Integer constant zero
656 return true;
657 case 'Q': // A memory reference with base register and no offset
658 Info.setAllowsMemory();
659 return true;
660 case 'S': // A symbolic address
661 Info.setAllowsRegister();
662 return true;
663 case 'U':
664 if (Name[1] == 'p' && (Name[2] == 'l' || Name[2] == 'a')) {
665 // SVE predicate registers ("Upa"=P0-15, "Upl"=P0-P7)
666 Info.setAllowsRegister();
667 Name += 2;
668 return true;
669 }
670 // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
671 // Utf: A memory address suitable for ldp/stp in TF mode.
672 // Usa: An absolute symbolic address.
673 // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
674
675 // Better to return an error saying that it's an unrecognised constraint
676 // even if this is a valid constraint in gcc.
677 return false;
678 case 'z': // Zero register, wzr or xzr
679 Info.setAllowsRegister();
680 return true;
681 case 'x': // Floating point and SIMD registers (V0-V15)
682 Info.setAllowsRegister();
683 return true;
684 case 'y': // SVE registers (V0-V7)
685 Info.setAllowsRegister();
686 return true;
687 }
688 return false;
689 }
690
validateConstraintModifier(StringRef Constraint,char Modifier,unsigned Size,std::string & SuggestedModifier) const691 bool AArch64TargetInfo::validateConstraintModifier(
692 StringRef Constraint, char Modifier, unsigned Size,
693 std::string &SuggestedModifier) const {
694 // Strip off constraint modifiers.
695 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
696 Constraint = Constraint.substr(1);
697
698 switch (Constraint[0]) {
699 default:
700 return true;
701 case 'z':
702 case 'r': {
703 switch (Modifier) {
704 case 'x':
705 case 'w':
706 // For now assume that the person knows what they're
707 // doing with the modifier.
708 return true;
709 default:
710 // By default an 'r' constraint will be in the 'x'
711 // registers.
712 if (Size == 64)
713 return true;
714
715 SuggestedModifier = "w";
716 return false;
717 }
718 }
719 }
720 }
721
getClobbers() const722 const char *AArch64TargetInfo::getClobbers() const { return ""; }
723
getEHDataRegisterNumber(unsigned RegNo) const724 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
725 if (RegNo == 0)
726 return 0;
727 if (RegNo == 1)
728 return 1;
729 return -1;
730 }
731
hasInt128Type() const732 bool AArch64TargetInfo::hasInt128Type() const { return true; }
733
AArch64leTargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)734 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
735 const TargetOptions &Opts)
736 : AArch64TargetInfo(Triple, Opts) {}
737
setDataLayout()738 void AArch64leTargetInfo::setDataLayout() {
739 if (getTriple().isOSBinFormatMachO()) {
740 if(getTriple().isArch32Bit())
741 resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128");
742 else
743 resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
744 } else
745 resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
746 }
747
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const748 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
749 MacroBuilder &Builder) const {
750 Builder.defineMacro("__AARCH64EL__");
751 AArch64TargetInfo::getTargetDefines(Opts, Builder);
752 }
753
AArch64beTargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)754 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
755 const TargetOptions &Opts)
756 : AArch64TargetInfo(Triple, Opts) {}
757
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const758 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
759 MacroBuilder &Builder) const {
760 Builder.defineMacro("__AARCH64EB__");
761 Builder.defineMacro("__AARCH_BIG_ENDIAN");
762 Builder.defineMacro("__ARM_BIG_ENDIAN");
763 AArch64TargetInfo::getTargetDefines(Opts, Builder);
764 }
765
setDataLayout()766 void AArch64beTargetInfo::setDataLayout() {
767 assert(!getTriple().isOSBinFormatMachO());
768 resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
769 }
770
WindowsARM64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)771 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
772 const TargetOptions &Opts)
773 : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
774
775 // This is an LLP64 platform.
776 // int:4, long:4, long long:8, long double:8.
777 IntWidth = IntAlign = 32;
778 LongWidth = LongAlign = 32;
779 DoubleAlign = LongLongAlign = 64;
780 LongDoubleWidth = LongDoubleAlign = 64;
781 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
782 IntMaxType = SignedLongLong;
783 Int64Type = SignedLongLong;
784 SizeType = UnsignedLongLong;
785 PtrDiffType = SignedLongLong;
786 IntPtrType = SignedLongLong;
787 }
788
setDataLayout()789 void WindowsARM64TargetInfo::setDataLayout() {
790 resetDataLayout(Triple.isOSBinFormatMachO()
791 ? "e-m:o-i64:64-i128:128-n32:64-S128"
792 : "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
793 }
794
795 TargetInfo::BuiltinVaListKind
getBuiltinVaListKind() const796 WindowsARM64TargetInfo::getBuiltinVaListKind() const {
797 return TargetInfo::CharPtrBuiltinVaList;
798 }
799
800 TargetInfo::CallingConvCheckResult
checkCallingConvention(CallingConv CC) const801 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
802 switch (CC) {
803 case CC_X86StdCall:
804 case CC_X86ThisCall:
805 case CC_X86FastCall:
806 case CC_X86VectorCall:
807 return CCCR_Ignore;
808 case CC_C:
809 case CC_OpenCLKernel:
810 case CC_PreserveMost:
811 case CC_PreserveAll:
812 case CC_Swift:
813 case CC_Win64:
814 return CCCR_OK;
815 default:
816 return CCCR_Warning;
817 }
818 }
819
MicrosoftARM64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)820 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
821 const TargetOptions &Opts)
822 : WindowsARM64TargetInfo(Triple, Opts) {
823 TheCXXABI.set(TargetCXXABI::Microsoft);
824 }
825
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const826 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
827 MacroBuilder &Builder) const {
828 WindowsARM64TargetInfo::getTargetDefines(Opts, Builder);
829 Builder.defineMacro("_M_ARM64", "1");
830 }
831
832 TargetInfo::CallingConvKind
getCallingConvKind(bool ClangABICompat4) const833 MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
834 return CCK_MicrosoftWin64;
835 }
836
getMinGlobalAlign(uint64_t TypeSize) const837 unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize) const {
838 unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize);
839
840 // MSVC does size based alignment for arm64 based on alignment section in
841 // below document, replicate that to keep alignment consistent with object
842 // files compiled by MSVC.
843 // https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions
844 if (TypeSize >= 512) { // TypeSize >= 64 bytes
845 Align = std::max(Align, 128u); // align type at least 16 bytes
846 } else if (TypeSize >= 64) { // TypeSize >= 8 bytes
847 Align = std::max(Align, 64u); // align type at least 8 butes
848 } else if (TypeSize >= 16) { // TypeSize >= 2 bytes
849 Align = std::max(Align, 32u); // align type at least 4 bytes
850 }
851 return Align;
852 }
853
MinGWARM64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)854 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
855 const TargetOptions &Opts)
856 : WindowsARM64TargetInfo(Triple, Opts) {
857 TheCXXABI.set(TargetCXXABI::GenericAArch64);
858 }
859
DarwinAArch64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)860 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
861 const TargetOptions &Opts)
862 : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
863 Int64Type = SignedLongLong;
864 if (getTriple().isArch32Bit())
865 IntMaxType = SignedLongLong;
866
867 WCharType = SignedInt;
868 UseSignedCharForObjCBool = false;
869
870 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
871 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
872
873 UseZeroLengthBitfieldAlignment = false;
874
875 if (getTriple().isArch32Bit()) {
876 UseBitFieldTypeAlignment = false;
877 ZeroLengthBitfieldBoundary = 32;
878 UseZeroLengthBitfieldAlignment = true;
879 TheCXXABI.set(TargetCXXABI::WatchOS);
880 } else
881 TheCXXABI.set(TargetCXXABI::AppleARM64);
882 }
883
getOSDefines(const LangOptions & Opts,const llvm::Triple & Triple,MacroBuilder & Builder) const884 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
885 const llvm::Triple &Triple,
886 MacroBuilder &Builder) const {
887 Builder.defineMacro("__AARCH64_SIMD__");
888 if (Triple.isArch32Bit())
889 Builder.defineMacro("__ARM64_ARCH_8_32__");
890 else
891 Builder.defineMacro("__ARM64_ARCH_8__");
892 Builder.defineMacro("__ARM_NEON__");
893 Builder.defineMacro("__LITTLE_ENDIAN__");
894 Builder.defineMacro("__REGISTER_PREFIX__", "");
895 Builder.defineMacro("__arm64", "1");
896 Builder.defineMacro("__arm64__", "1");
897
898 if (Triple.isArm64e())
899 Builder.defineMacro("__arm64e__", "1");
900
901 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
902 }
903
904 TargetInfo::BuiltinVaListKind
getBuiltinVaListKind() const905 DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
906 return TargetInfo::CharPtrBuiltinVaList;
907 }
908
909 // 64-bit RenderScript is aarch64
RenderScript64TargetInfo(const llvm::Triple & Triple,const TargetOptions & Opts)910 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
911 const TargetOptions &Opts)
912 : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
913 Triple.getOSName(),
914 Triple.getEnvironmentName()),
915 Opts) {
916 IsRenderScriptTarget = true;
917 }
918
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const919 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
920 MacroBuilder &Builder) const {
921 Builder.defineMacro("__RENDERSCRIPT__");
922 AArch64leTargetInfo::getTargetDefines(Opts, Builder);
923 }
924