1 //===--- AArch64.cpp - Implement AArch64 target feature support -----------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements AArch64 TargetInfo objects.
12 //===----------------------------------------------------------------------===//
15 #include "clang/Basic/TargetBuiltins.h"
16 #include "clang/Basic/TargetInfo.h"
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/StringExtras.h"
20 using namespace clang;
21 using namespace clang::targets;
23 const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
24 #define BUILTIN(ID, TYPE, ATTRS) \
25 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
26 #include "clang/Basic/BuiltinsNEON.def"
28 #define BUILTIN(ID, TYPE, ATTRS) \
29 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
30 #define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \
31 {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
32 #include "clang/Basic/BuiltinsAArch64.def"
35 AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
36 const TargetOptions &Opts)
37 : TargetInfo(Triple), ABI("aapcs") {
38 if (getTriple().getOS() == llvm::Triple::NetBSD ||
39 getTriple().getOS() == llvm::Triple::OpenBSD) {
40 // NetBSD apparently prefers consistency across ARM targets to
41 // consistency across 64-bit targets.
42 Int64Type = SignedLongLong;
43 IntMaxType = SignedLongLong;
45 if (!getTriple().isOSDarwin())
46 WCharType = UnsignedInt;
48 Int64Type = SignedLong;
49 IntMaxType = SignedLong;
53 LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
55 MaxAtomicInlineWidth = 128;
56 MaxAtomicPromoteWidth = 128;
58 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
59 LongDoubleFormat = &llvm::APFloat::IEEEquad();
61 // Make __builtin_ms_va_list available.
62 HasBuiltinMSVaList = true;
64 // {} in inline assembly are neon specifiers, not assembly variant
68 // AAPCS gives rules for bitfields. 7.1.7 says: "The container type
69 // contributes to the alignment of the containing aggregate in the same way
70 // a plain (non bit-field) member of that type would, without exception for
71 // zero-sized or anonymous bit-fields."
72 assert(UseBitFieldTypeAlignment && "bitfields affect type alignment");
73 UseZeroLengthBitfieldAlignment = true;
75 // AArch64 targets default to using the ARM C++ ABI.
76 TheCXXABI.set(TargetCXXABI::GenericAArch64);
78 if (Triple.getOS() == llvm::Triple::Linux)
79 this->MCountName = "\01_mcount";
80 else if (Triple.getOS() == llvm::Triple::UnknownOS)
82 Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
85 StringRef AArch64TargetInfo::getABI() const { return ABI; }
87 bool AArch64TargetInfo::setABI(const std::string &Name) {
88 if (Name != "aapcs" && Name != "darwinpcs")
95 bool AArch64TargetInfo::isValidCPUName(StringRef Name) const {
96 return Name == "generic" ||
97 llvm::AArch64::parseCPUArch(Name) != llvm::AArch64::ArchKind::INVALID;
100 bool AArch64TargetInfo::setCPU(const std::string &Name) {
101 return isValidCPUName(Name);
104 void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
105 MacroBuilder &Builder) const {
106 Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
109 void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
110 MacroBuilder &Builder) const {
111 // Also include the ARMv8.1 defines
112 getTargetDefinesARMV81A(Opts, Builder);
115 void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
116 MacroBuilder &Builder) const {
117 // Target identification.
118 Builder.defineMacro("__aarch64__");
119 // For bare-metal none-eabi.
120 if (getTriple().getOS() == llvm::Triple::UnknownOS &&
121 (getTriple().getEnvironment() == llvm::Triple::EABI ||
122 getTriple().getEnvironment() == llvm::Triple::EABIHF))
123 Builder.defineMacro("__ELF__");
125 // Target properties.
126 if (!getTriple().isOSWindows()) {
127 Builder.defineMacro("_LP64");
128 Builder.defineMacro("__LP64__");
131 // ACLE predefines. Many can only have one possible value on v8 AArch64.
132 Builder.defineMacro("__ARM_ACLE", "200");
133 Builder.defineMacro("__ARM_ARCH", "8");
134 Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
136 Builder.defineMacro("__ARM_64BIT_STATE", "1");
137 Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
138 Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
140 Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
141 Builder.defineMacro("__ARM_FEATURE_FMA", "1");
142 Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
143 Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
144 Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility
145 Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
146 Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
148 Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
150 // 0xe implies support for half, single and double precision operations.
151 Builder.defineMacro("__ARM_FP", "0xE");
153 // PCS specifies this for SysV variants, which is all we support. Other ABIs
154 // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
155 Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
156 Builder.defineMacro("__ARM_FP16_ARGS", "1");
158 if (Opts.UnsafeFPMath)
159 Builder.defineMacro("__ARM_FP_FAST", "1");
161 Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
162 Twine(Opts.WCharSize ? Opts.WCharSize : 4));
164 Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
166 if (FPU & NeonMode) {
167 Builder.defineMacro("__ARM_NEON", "1");
168 // 64-bit NEON supports half, single and double precision operations.
169 Builder.defineMacro("__ARM_NEON_FP", "0xE");
173 Builder.defineMacro("__ARM_FEATURE_SVE", "1");
176 Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
179 Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
182 Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
184 if ((FPU & NeonMode) && HasFullFP16)
185 Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
190 case llvm::AArch64::ArchKind::ARMV8_1A:
191 getTargetDefinesARMV81A(Opts, Builder);
193 case llvm::AArch64::ArchKind::ARMV8_2A:
194 getTargetDefinesARMV82A(Opts, Builder);
198 // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
199 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
200 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
201 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
202 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
205 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
206 return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
207 Builtin::FirstTSBuiltin);
210 bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
211 return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" ||
212 (Feature == "neon" && (FPU & NeonMode)) ||
213 (Feature == "sve" && (FPU & SveMode));
216 bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
217 DiagnosticsEngine &Diags) {
223 ArchKind = llvm::AArch64::ArchKind::ARMV8A;
225 for (const auto &Feature : Features) {
226 if (Feature == "+neon")
228 if (Feature == "+sve")
230 if (Feature == "+crc")
232 if (Feature == "+crypto")
234 if (Feature == "+strict-align")
236 if (Feature == "+v8.1a")
237 ArchKind = llvm::AArch64::ArchKind::ARMV8_1A;
238 if (Feature == "+v8.2a")
239 ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
240 if (Feature == "+fullfp16")
249 TargetInfo::CallingConvCheckResult
250 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
254 case CC_PreserveMost:
256 case CC_OpenCLKernel:
264 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
266 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
267 return TargetInfo::AArch64ABIBuiltinVaList;
270 const char *const AArch64TargetInfo::GCCRegNames[] = {
271 // 32-bit Integer registers
272 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
273 "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
274 "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
276 // 64-bit Integer registers
277 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
278 "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
279 "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
281 // 32-bit floating point regsisters
282 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
283 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
284 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
286 // 64-bit floating point regsisters
287 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
288 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
289 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
292 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
293 "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
294 "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
297 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
298 return llvm::makeArrayRef(GCCRegNames);
301 const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
304 // GCC rN registers are aliases of xN registers.
334 {{"r29", "x29"}, "fp"},
335 {{"r30", "x30"}, "lr"},
336 // The S/D/Q and W/X registers overlap, but aren't really aliases; we
337 // don't want to substitute one of these for a different-sized one.
340 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
341 return llvm::makeArrayRef(GCCRegAliases);
344 bool AArch64TargetInfo::validateAsmConstraint(
345 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
349 case 'w': // Floating point and SIMD registers (V0-V31)
350 Info.setAllowsRegister();
352 case 'I': // Constant that can be used with an ADD instruction
353 case 'J': // Constant that can be used with a SUB instruction
354 case 'K': // Constant that can be used with a 32-bit logical instruction
355 case 'L': // Constant that can be used with a 64-bit logical instruction
356 case 'M': // Constant that can be used as a 32-bit MOV immediate
357 case 'N': // Constant that can be used as a 64-bit MOV immediate
358 case 'Y': // Floating point constant zero
359 case 'Z': // Integer constant zero
361 case 'Q': // A memory reference with base register and no offset
362 Info.setAllowsMemory();
364 case 'S': // A symbolic address
365 Info.setAllowsRegister();
368 // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
369 // Utf: A memory address suitable for ldp/stp in TF mode.
370 // Usa: An absolute symbolic address.
371 // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
372 llvm_unreachable("FIXME: Unimplemented support for U* constraints.");
373 case 'z': // Zero register, wzr or xzr
374 Info.setAllowsRegister();
376 case 'x': // Floating point and SIMD registers (V0-V15)
377 Info.setAllowsRegister();
383 bool AArch64TargetInfo::validateConstraintModifier(
384 StringRef Constraint, char Modifier, unsigned Size,
385 std::string &SuggestedModifier) const {
386 // Strip off constraint modifiers.
387 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
388 Constraint = Constraint.substr(1);
390 switch (Constraint[0]) {
398 // For now assume that the person knows what they're
399 // doing with the modifier.
402 // By default an 'r' constraint will be in the 'x'
407 SuggestedModifier = "w";
414 const char *AArch64TargetInfo::getClobbers() const { return ""; }
416 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
424 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
425 const TargetOptions &Opts)
426 : AArch64TargetInfo(Triple, Opts) {}
428 void AArch64leTargetInfo::setDataLayout() {
429 if (getTriple().isOSBinFormatMachO())
430 resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
432 resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
435 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
436 MacroBuilder &Builder) const {
437 Builder.defineMacro("__AARCH64EL__");
438 AArch64TargetInfo::getTargetDefines(Opts, Builder);
441 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
442 const TargetOptions &Opts)
443 : AArch64TargetInfo(Triple, Opts) {}
445 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
446 MacroBuilder &Builder) const {
447 Builder.defineMacro("__AARCH64EB__");
448 Builder.defineMacro("__AARCH_BIG_ENDIAN");
449 Builder.defineMacro("__ARM_BIG_ENDIAN");
450 AArch64TargetInfo::getTargetDefines(Opts, Builder);
453 void AArch64beTargetInfo::setDataLayout() {
454 assert(!getTriple().isOSBinFormatMachO());
455 resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
458 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
459 const TargetOptions &Opts)
460 : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
462 // This is an LLP64 platform.
463 // int:4, long:4, long long:8, long double:8.
464 IntWidth = IntAlign = 32;
465 LongWidth = LongAlign = 32;
466 DoubleAlign = LongLongAlign = 64;
467 LongDoubleWidth = LongDoubleAlign = 64;
468 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
469 IntMaxType = SignedLongLong;
470 Int64Type = SignedLongLong;
471 SizeType = UnsignedLongLong;
472 PtrDiffType = SignedLongLong;
473 IntPtrType = SignedLongLong;
476 void WindowsARM64TargetInfo::setDataLayout() {
477 resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
480 TargetInfo::BuiltinVaListKind
481 WindowsARM64TargetInfo::getBuiltinVaListKind() const {
482 return TargetInfo::CharPtrBuiltinVaList;
485 TargetInfo::CallingConvCheckResult
486 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
491 case CC_X86VectorCall:
494 case CC_OpenCLKernel:
495 case CC_PreserveMost:
504 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
505 const TargetOptions &Opts)
506 : WindowsARM64TargetInfo(Triple, Opts) {
507 TheCXXABI.set(TargetCXXABI::Microsoft);
510 void MicrosoftARM64TargetInfo::getVisualStudioDefines(
511 const LangOptions &Opts, MacroBuilder &Builder) const {
512 WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts, Builder);
513 Builder.defineMacro("_M_ARM64", "1");
516 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
517 MacroBuilder &Builder) const {
518 WindowsTargetInfo::getTargetDefines(Opts, Builder);
519 getVisualStudioDefines(Opts, Builder);
522 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
523 const TargetOptions &Opts)
524 : WindowsARM64TargetInfo(Triple, Opts) {
525 TheCXXABI.set(TargetCXXABI::GenericAArch64);
528 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
529 const TargetOptions &Opts)
530 : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
531 Int64Type = SignedLongLong;
532 UseSignedCharForObjCBool = false;
534 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
535 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
537 TheCXXABI.set(TargetCXXABI::iOS64);
540 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
541 const llvm::Triple &Triple,
542 MacroBuilder &Builder) const {
543 Builder.defineMacro("__AARCH64_SIMD__");
544 Builder.defineMacro("__ARM64_ARCH_8__");
545 Builder.defineMacro("__ARM_NEON__");
546 Builder.defineMacro("__LITTLE_ENDIAN__");
547 Builder.defineMacro("__REGISTER_PREFIX__", "");
548 Builder.defineMacro("__arm64", "1");
549 Builder.defineMacro("__arm64__", "1");
551 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
554 TargetInfo::BuiltinVaListKind
555 DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
556 return TargetInfo::CharPtrBuiltinVaList;
559 // 64-bit RenderScript is aarch64
560 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
561 const TargetOptions &Opts)
562 : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
564 Triple.getEnvironmentName()),
566 IsRenderScriptTarget = true;
569 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
570 MacroBuilder &Builder) const {
571 Builder.defineMacro("__RENDERSCRIPT__");
572 AArch64leTargetInfo::getTargetDefines(Opts, Builder);