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[] = {
302 {{"w31"}, "wsp"}, {{"x29"}, "fp"}, {{"x30"}, "lr"}, {{"x31"}, "sp"},
303 // The S/D/Q and W/X registers overlap, but aren't really aliases; we
304 // don't want to substitute one of these for a different-sized one.
307 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
308 return llvm::makeArrayRef(GCCRegAliases);
311 bool AArch64TargetInfo::validateAsmConstraint(
312 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
316 case 'w': // Floating point and SIMD registers (V0-V31)
317 Info.setAllowsRegister();
319 case 'I': // Constant that can be used with an ADD instruction
320 case 'J': // Constant that can be used with a SUB instruction
321 case 'K': // Constant that can be used with a 32-bit logical instruction
322 case 'L': // Constant that can be used with a 64-bit logical instruction
323 case 'M': // Constant that can be used as a 32-bit MOV immediate
324 case 'N': // Constant that can be used as a 64-bit MOV immediate
325 case 'Y': // Floating point constant zero
326 case 'Z': // Integer constant zero
328 case 'Q': // A memory reference with base register and no offset
329 Info.setAllowsMemory();
331 case 'S': // A symbolic address
332 Info.setAllowsRegister();
335 // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
336 // Utf: A memory address suitable for ldp/stp in TF mode.
337 // Usa: An absolute symbolic address.
338 // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
339 llvm_unreachable("FIXME: Unimplemented support for U* constraints.");
340 case 'z': // Zero register, wzr or xzr
341 Info.setAllowsRegister();
343 case 'x': // Floating point and SIMD registers (V0-V15)
344 Info.setAllowsRegister();
350 bool AArch64TargetInfo::validateConstraintModifier(
351 StringRef Constraint, char Modifier, unsigned Size,
352 std::string &SuggestedModifier) const {
353 // Strip off constraint modifiers.
354 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
355 Constraint = Constraint.substr(1);
357 switch (Constraint[0]) {
365 // For now assume that the person knows what they're
366 // doing with the modifier.
369 // By default an 'r' constraint will be in the 'x'
374 SuggestedModifier = "w";
381 const char *AArch64TargetInfo::getClobbers() const { return ""; }
383 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
391 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
392 const TargetOptions &Opts)
393 : AArch64TargetInfo(Triple, Opts) {}
395 void AArch64leTargetInfo::setDataLayout() {
396 if (getTriple().isOSBinFormatMachO())
397 resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
399 resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
402 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
403 MacroBuilder &Builder) const {
404 Builder.defineMacro("__AARCH64EL__");
405 AArch64TargetInfo::getTargetDefines(Opts, Builder);
408 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
409 const TargetOptions &Opts)
410 : AArch64TargetInfo(Triple, Opts) {}
412 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
413 MacroBuilder &Builder) const {
414 Builder.defineMacro("__AARCH64EB__");
415 Builder.defineMacro("__AARCH_BIG_ENDIAN");
416 Builder.defineMacro("__ARM_BIG_ENDIAN");
417 AArch64TargetInfo::getTargetDefines(Opts, Builder);
420 void AArch64beTargetInfo::setDataLayout() {
421 assert(!getTriple().isOSBinFormatMachO());
422 resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
425 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
426 const TargetOptions &Opts)
427 : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
429 // This is an LLP64 platform.
430 // int:4, long:4, long long:8, long double:8.
431 IntWidth = IntAlign = 32;
432 LongWidth = LongAlign = 32;
433 DoubleAlign = LongLongAlign = 64;
434 LongDoubleWidth = LongDoubleAlign = 64;
435 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
436 IntMaxType = SignedLongLong;
437 Int64Type = SignedLongLong;
438 SizeType = UnsignedLongLong;
439 PtrDiffType = SignedLongLong;
440 IntPtrType = SignedLongLong;
443 void WindowsARM64TargetInfo::setDataLayout() {
444 resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
447 TargetInfo::BuiltinVaListKind
448 WindowsARM64TargetInfo::getBuiltinVaListKind() const {
449 return TargetInfo::CharPtrBuiltinVaList;
452 TargetInfo::CallingConvCheckResult
453 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
458 case CC_X86VectorCall:
461 case CC_OpenCLKernel:
462 case CC_PreserveMost:
471 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
472 const TargetOptions &Opts)
473 : WindowsARM64TargetInfo(Triple, Opts) {
474 TheCXXABI.set(TargetCXXABI::Microsoft);
477 void MicrosoftARM64TargetInfo::getVisualStudioDefines(
478 const LangOptions &Opts, MacroBuilder &Builder) const {
479 WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts, Builder);
480 Builder.defineMacro("_M_ARM64", "1");
483 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
484 MacroBuilder &Builder) const {
485 WindowsTargetInfo::getTargetDefines(Opts, Builder);
486 getVisualStudioDefines(Opts, Builder);
489 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
490 const TargetOptions &Opts)
491 : WindowsARM64TargetInfo(Triple, Opts) {
492 TheCXXABI.set(TargetCXXABI::GenericAArch64);
495 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
496 const TargetOptions &Opts)
497 : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
498 Int64Type = SignedLongLong;
499 UseSignedCharForObjCBool = false;
501 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
502 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
504 TheCXXABI.set(TargetCXXABI::iOS64);
507 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
508 const llvm::Triple &Triple,
509 MacroBuilder &Builder) const {
510 Builder.defineMacro("__AARCH64_SIMD__");
511 Builder.defineMacro("__ARM64_ARCH_8__");
512 Builder.defineMacro("__ARM_NEON__");
513 Builder.defineMacro("__LITTLE_ENDIAN__");
514 Builder.defineMacro("__REGISTER_PREFIX__", "");
515 Builder.defineMacro("__arm64", "1");
516 Builder.defineMacro("__arm64__", "1");
518 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
521 TargetInfo::BuiltinVaListKind
522 DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
523 return TargetInfo::CharPtrBuiltinVaList;
526 // 64-bit RenderScript is aarch64
527 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
528 const TargetOptions &Opts)
529 : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
531 Triple.getEnvironmentName()),
533 IsRenderScriptTarget = true;
536 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
537 MacroBuilder &Builder) const {
538 Builder.defineMacro("__RENDERSCRIPT__");
539 AArch64leTargetInfo::getTargetDefines(Opts, Builder);