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 llvm::utostr(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");
187 case llvm::AArch64::ArchKind::ARMV8_1A:
188 getTargetDefinesARMV81A(Opts, Builder);
190 case llvm::AArch64::ArchKind::ARMV8_2A:
191 getTargetDefinesARMV82A(Opts, Builder);
195 // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
196 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
197 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
198 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
199 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
202 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
203 return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
204 Builtin::FirstTSBuiltin);
207 bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
208 return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" ||
209 (Feature == "neon" && (FPU & NeonMode)) ||
210 (Feature == "sve" && (FPU & SveMode));
213 bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
214 DiagnosticsEngine &Diags) {
220 ArchKind = llvm::AArch64::ArchKind::ARMV8A;
222 for (const auto &Feature : Features) {
223 if (Feature == "+neon")
225 if (Feature == "+sve")
227 if (Feature == "+crc")
229 if (Feature == "+crypto")
231 if (Feature == "+strict-align")
233 if (Feature == "+v8.1a")
234 ArchKind = llvm::AArch64::ArchKind::ARMV8_1A;
235 if (Feature == "+v8.2a")
236 ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
237 if (Feature == "+fullfp16")
246 TargetInfo::CallingConvCheckResult
247 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
251 case CC_PreserveMost:
253 case CC_OpenCLKernel:
261 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
263 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
264 return TargetInfo::AArch64ABIBuiltinVaList;
267 const char *const AArch64TargetInfo::GCCRegNames[] = {
268 // 32-bit Integer registers
269 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
270 "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
271 "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
273 // 64-bit Integer registers
274 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
275 "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
276 "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
278 // 32-bit floating point regsisters
279 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
280 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
281 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
283 // 64-bit floating point regsisters
284 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
285 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
286 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
289 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
290 "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
291 "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
294 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
295 return llvm::makeArrayRef(GCCRegNames);
298 const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
299 {{"w31"}, "wsp"}, {{"x29"}, "fp"}, {{"x30"}, "lr"}, {{"x31"}, "sp"},
300 // The S/D/Q and W/X registers overlap, but aren't really aliases; we
301 // don't want to substitute one of these for a different-sized one.
304 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
305 return llvm::makeArrayRef(GCCRegAliases);
308 bool AArch64TargetInfo::validateAsmConstraint(
309 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
313 case 'w': // Floating point and SIMD registers (V0-V31)
314 Info.setAllowsRegister();
316 case 'I': // Constant that can be used with an ADD instruction
317 case 'J': // Constant that can be used with a SUB instruction
318 case 'K': // Constant that can be used with a 32-bit logical instruction
319 case 'L': // Constant that can be used with a 64-bit logical instruction
320 case 'M': // Constant that can be used as a 32-bit MOV immediate
321 case 'N': // Constant that can be used as a 64-bit MOV immediate
322 case 'Y': // Floating point constant zero
323 case 'Z': // Integer constant zero
325 case 'Q': // A memory reference with base register and no offset
326 Info.setAllowsMemory();
328 case 'S': // A symbolic address
329 Info.setAllowsRegister();
332 // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
333 // Utf: A memory address suitable for ldp/stp in TF mode.
334 // Usa: An absolute symbolic address.
335 // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
336 llvm_unreachable("FIXME: Unimplemented support for U* constraints.");
337 case 'z': // Zero register, wzr or xzr
338 Info.setAllowsRegister();
340 case 'x': // Floating point and SIMD registers (V0-V15)
341 Info.setAllowsRegister();
347 bool AArch64TargetInfo::validateConstraintModifier(
348 StringRef Constraint, char Modifier, unsigned Size,
349 std::string &SuggestedModifier) const {
350 // Strip off constraint modifiers.
351 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
352 Constraint = Constraint.substr(1);
354 switch (Constraint[0]) {
362 // For now assume that the person knows what they're
363 // doing with the modifier.
366 // By default an 'r' constraint will be in the 'x'
371 SuggestedModifier = "w";
378 const char *AArch64TargetInfo::getClobbers() const { return ""; }
380 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
388 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
389 const TargetOptions &Opts)
390 : AArch64TargetInfo(Triple, Opts) {}
392 void AArch64leTargetInfo::setDataLayout() {
393 if (getTriple().isOSBinFormatMachO())
394 resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
396 resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
399 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
400 MacroBuilder &Builder) const {
401 Builder.defineMacro("__AARCH64EL__");
402 AArch64TargetInfo::getTargetDefines(Opts, Builder);
405 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
406 const TargetOptions &Opts)
407 : AArch64TargetInfo(Triple, Opts) {}
409 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
410 MacroBuilder &Builder) const {
411 Builder.defineMacro("__AARCH64EB__");
412 Builder.defineMacro("__AARCH_BIG_ENDIAN");
413 Builder.defineMacro("__ARM_BIG_ENDIAN");
414 AArch64TargetInfo::getTargetDefines(Opts, Builder);
417 void AArch64beTargetInfo::setDataLayout() {
418 assert(!getTriple().isOSBinFormatMachO());
419 resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
422 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
423 const TargetOptions &Opts)
424 : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
426 // This is an LLP64 platform.
427 // int:4, long:4, long long:8, long double:8.
428 IntWidth = IntAlign = 32;
429 LongWidth = LongAlign = 32;
430 DoubleAlign = LongLongAlign = 64;
431 LongDoubleWidth = LongDoubleAlign = 64;
432 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
433 IntMaxType = SignedLongLong;
434 Int64Type = SignedLongLong;
435 SizeType = UnsignedLongLong;
436 PtrDiffType = SignedLongLong;
437 IntPtrType = SignedLongLong;
440 void WindowsARM64TargetInfo::setDataLayout() {
441 resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
444 TargetInfo::BuiltinVaListKind
445 WindowsARM64TargetInfo::getBuiltinVaListKind() const {
446 return TargetInfo::CharPtrBuiltinVaList;
449 TargetInfo::CallingConvCheckResult
450 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
455 case CC_X86VectorCall:
458 case CC_OpenCLKernel:
459 case CC_PreserveMost:
468 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
469 const TargetOptions &Opts)
470 : WindowsARM64TargetInfo(Triple, Opts) {
471 TheCXXABI.set(TargetCXXABI::Microsoft);
474 void MicrosoftARM64TargetInfo::getVisualStudioDefines(
475 const LangOptions &Opts, MacroBuilder &Builder) const {
476 WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts, Builder);
477 Builder.defineMacro("_M_ARM64", "1");
480 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
481 MacroBuilder &Builder) const {
482 WindowsTargetInfo::getTargetDefines(Opts, Builder);
483 getVisualStudioDefines(Opts, Builder);
486 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
487 const TargetOptions &Opts)
488 : WindowsARM64TargetInfo(Triple, Opts) {
489 TheCXXABI.set(TargetCXXABI::GenericAArch64);
492 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
493 const TargetOptions &Opts)
494 : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
495 Int64Type = SignedLongLong;
496 UseSignedCharForObjCBool = false;
498 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
499 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
501 TheCXXABI.set(TargetCXXABI::iOS64);
504 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
505 const llvm::Triple &Triple,
506 MacroBuilder &Builder) const {
507 Builder.defineMacro("__AARCH64_SIMD__");
508 Builder.defineMacro("__ARM64_ARCH_8__");
509 Builder.defineMacro("__ARM_NEON__");
510 Builder.defineMacro("__LITTLE_ENDIAN__");
511 Builder.defineMacro("__REGISTER_PREFIX__", "");
512 Builder.defineMacro("__arm64", "1");
513 Builder.defineMacro("__arm64__", "1");
515 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
518 TargetInfo::BuiltinVaListKind
519 DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
520 return TargetInfo::CharPtrBuiltinVaList;
523 // 64-bit RenderScript is aarch64
524 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
525 const TargetOptions &Opts)
526 : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
528 Triple.getEnvironmentName()),
530 IsRenderScriptTarget = true;
533 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
534 MacroBuilder &Builder) const {
535 Builder.defineMacro("__RENDERSCRIPT__");
536 AArch64leTargetInfo::getTargetDefines(Opts, Builder);