blob: af2e35bb866dffcc02fe0a94df15a1a8db476ffd [file] [log] [blame]
Erich Keaneebba5922017-07-21 22:37:03 +00001//===--- AArch64.cpp - Implement AArch64 target feature support -----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements AArch64 TargetInfo objects.
11//
12//===----------------------------------------------------------------------===//
13
14#include "AArch64.h"
15#include "clang/Basic/TargetBuiltins.h"
16#include "clang/Basic/TargetInfo.h"
17#include "llvm/ADT/ArrayRef.h"
18
19using namespace clang;
20using namespace clang::targets;
21
Tim Northoverad4c5db2017-07-24 17:06:23 +000022const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
23#define BUILTIN(ID, TYPE, ATTRS) \
24 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
25#include "clang/Basic/BuiltinsNEON.def"
26
27#define BUILTIN(ID, TYPE, ATTRS) \
28 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
29#include "clang/Basic/BuiltinsAArch64.def"
30};
31
32AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
33 const TargetOptions &Opts)
34 : TargetInfo(Triple), ABI("aapcs") {
35 if (getTriple().getOS() == llvm::Triple::NetBSD ||
36 getTriple().getOS() == llvm::Triple::OpenBSD) {
37 WCharType = SignedInt;
38
39 // NetBSD apparently prefers consistency across ARM targets to
40 // consistency across 64-bit targets.
41 Int64Type = SignedLongLong;
42 IntMaxType = SignedLongLong;
43 } else {
44 WCharType = UnsignedInt;
45 Int64Type = SignedLong;
46 IntMaxType = SignedLong;
47 }
48
49 LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
50 MaxVectorAlign = 128;
51 MaxAtomicInlineWidth = 128;
52 MaxAtomicPromoteWidth = 128;
53
54 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
55 LongDoubleFormat = &llvm::APFloat::IEEEquad();
56
57 // Make __builtin_ms_va_list available.
58 HasBuiltinMSVaList = true;
59
60 // {} in inline assembly are neon specifiers, not assembly variant
61 // specifiers.
62 NoAsmVariants = true;
63
64 // AAPCS gives rules for bitfields. 7.1.7 says: "The container type
65 // contributes to the alignment of the containing aggregate in the same way
66 // a plain (non bit-field) member of that type would, without exception for
67 // zero-sized or anonymous bit-fields."
68 assert(UseBitFieldTypeAlignment && "bitfields affect type alignment");
69 UseZeroLengthBitfieldAlignment = true;
70
71 // AArch64 targets default to using the ARM C++ ABI.
72 TheCXXABI.set(TargetCXXABI::GenericAArch64);
73
74 if (Triple.getOS() == llvm::Triple::Linux)
75 this->MCountName = "\01_mcount";
76 else if (Triple.getOS() == llvm::Triple::UnknownOS)
77 this->MCountName =
78 Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
79}
80
81StringRef AArch64TargetInfo::getABI() const { return ABI; }
82
83bool AArch64TargetInfo::setABI(const std::string &Name) {
84 if (Name != "aapcs" && Name != "darwinpcs")
85 return false;
86
87 ABI = Name;
88 return true;
89}
90
91bool AArch64TargetInfo::isValidCPUName(StringRef Name) const {
92 return Name == "generic" ||
Florian Hahnef5bbd62017-07-27 16:28:39 +000093 llvm::AArch64::parseCPUArch(Name) != llvm::AArch64::ArchKind::INVALID;
Tim Northoverad4c5db2017-07-24 17:06:23 +000094}
95
96bool AArch64TargetInfo::setCPU(const std::string &Name) {
97 return isValidCPUName(Name);
98}
99
100void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
101 MacroBuilder &Builder) const {
102 Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
103}
104
105void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
106 MacroBuilder &Builder) const {
107 // Also include the ARMv8.1 defines
108 getTargetDefinesARMV81A(Opts, Builder);
109}
110
111void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
112 MacroBuilder &Builder) const {
113 // Target identification.
114 Builder.defineMacro("__aarch64__");
115 // For bare-metal none-eabi.
116 if (getTriple().getOS() == llvm::Triple::UnknownOS &&
117 (getTriple().getEnvironment() == llvm::Triple::EABI ||
118 getTriple().getEnvironment() == llvm::Triple::EABIHF))
119 Builder.defineMacro("__ELF__");
120
121 // Target properties.
Martin Storsjo588a3e52017-07-31 20:40:53 +0000122 if (!getTriple().isOSWindows()) {
123 Builder.defineMacro("_LP64");
124 Builder.defineMacro("__LP64__");
125 }
Tim Northoverad4c5db2017-07-24 17:06:23 +0000126
127 // ACLE predefines. Many can only have one possible value on v8 AArch64.
128 Builder.defineMacro("__ARM_ACLE", "200");
129 Builder.defineMacro("__ARM_ARCH", "8");
130 Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
131
132 Builder.defineMacro("__ARM_64BIT_STATE", "1");
133 Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
134 Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
135
136 Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
137 Builder.defineMacro("__ARM_FEATURE_FMA", "1");
138 Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
139 Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
140 Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility
141 Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
142 Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
143
144 Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
145
146 // 0xe implies support for half, single and double precision operations.
147 Builder.defineMacro("__ARM_FP", "0xE");
148
149 // PCS specifies this for SysV variants, which is all we support. Other ABIs
150 // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
151 Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
152 Builder.defineMacro("__ARM_FP16_ARGS", "1");
153
154 if (Opts.UnsafeFPMath)
155 Builder.defineMacro("__ARM_FP_FAST", "1");
156
157 Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", Opts.ShortWChar ? "2" : "4");
158
159 Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
160
161 if (FPU & NeonMode) {
162 Builder.defineMacro("__ARM_NEON", "1");
163 // 64-bit NEON supports half, single and double precision operations.
164 Builder.defineMacro("__ARM_NEON_FP", "0xE");
165 }
166
167 if (FPU & SveMode)
168 Builder.defineMacro("__ARM_FEATURE_SVE", "1");
169
170 if (CRC)
171 Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
172
173 if (Crypto)
174 Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
175
176 if (Unaligned)
177 Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
178
179 switch (ArchKind) {
180 default:
181 break;
Florian Hahnef5bbd62017-07-27 16:28:39 +0000182 case llvm::AArch64::ArchKind::ARMV8_1A:
Tim Northoverad4c5db2017-07-24 17:06:23 +0000183 getTargetDefinesARMV81A(Opts, Builder);
184 break;
Florian Hahnef5bbd62017-07-27 16:28:39 +0000185 case llvm::AArch64::ArchKind::ARMV8_2A:
Tim Northoverad4c5db2017-07-24 17:06:23 +0000186 getTargetDefinesARMV82A(Opts, Builder);
187 break;
188 }
189
190 // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
191 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
192 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
193 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
194 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
195}
196
197ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
198 return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
199 Builtin::FirstTSBuiltin);
200}
201
202bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
203 return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" ||
204 (Feature == "neon" && (FPU & NeonMode)) ||
205 (Feature == "sve" && (FPU & SveMode));
206}
207
208bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
209 DiagnosticsEngine &Diags) {
210 FPU = FPUMode;
211 CRC = 0;
212 Crypto = 0;
213 Unaligned = 1;
214 HasFullFP16 = 0;
Florian Hahnef5bbd62017-07-27 16:28:39 +0000215 ArchKind = llvm::AArch64::ArchKind::ARMV8A;
Tim Northoverad4c5db2017-07-24 17:06:23 +0000216
217 for (const auto &Feature : Features) {
218 if (Feature == "+neon")
219 FPU |= NeonMode;
220 if (Feature == "+sve")
221 FPU |= SveMode;
222 if (Feature == "+crc")
223 CRC = 1;
224 if (Feature == "+crypto")
225 Crypto = 1;
226 if (Feature == "+strict-align")
227 Unaligned = 0;
228 if (Feature == "+v8.1a")
Florian Hahnef5bbd62017-07-27 16:28:39 +0000229 ArchKind = llvm::AArch64::ArchKind::ARMV8_1A;
Tim Northoverad4c5db2017-07-24 17:06:23 +0000230 if (Feature == "+v8.2a")
Florian Hahnef5bbd62017-07-27 16:28:39 +0000231 ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
Tim Northoverad4c5db2017-07-24 17:06:23 +0000232 if (Feature == "+fullfp16")
233 HasFullFP16 = 1;
234 }
235
236 setDataLayout();
237
238 return true;
239}
240
241TargetInfo::CallingConvCheckResult
242AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
243 switch (CC) {
244 case CC_C:
245 case CC_Swift:
246 case CC_PreserveMost:
247 case CC_PreserveAll:
248 case CC_OpenCLKernel:
249 case CC_Win64:
250 return CCCR_OK;
251 default:
252 return CCCR_Warning;
253 }
254}
255
256bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
257
258TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
259 return TargetInfo::AArch64ABIBuiltinVaList;
260}
261
Erich Keaneebba5922017-07-21 22:37:03 +0000262const char *const AArch64TargetInfo::GCCRegNames[] = {
263 // 32-bit Integer registers
264 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
265 "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
266 "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
267
268 // 64-bit Integer registers
269 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
270 "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
271 "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
272
273 // 32-bit floating point regsisters
274 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
275 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
276 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
277
278 // 64-bit floating point regsisters
279 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
280 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
281 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
282
283 // Vector registers
284 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
285 "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
286 "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
287};
288
289ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
290 return llvm::makeArrayRef(GCCRegNames);
291}
292
293const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
294 {{"w31"}, "wsp"}, {{"x29"}, "fp"}, {{"x30"}, "lr"}, {{"x31"}, "sp"},
295 // The S/D/Q and W/X registers overlap, but aren't really aliases; we
296 // don't want to substitute one of these for a different-sized one.
297};
298
299ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
300 return llvm::makeArrayRef(GCCRegAliases);
301}
302
Tim Northoverad4c5db2017-07-24 17:06:23 +0000303bool AArch64TargetInfo::validateAsmConstraint(
304 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
305 switch (*Name) {
306 default:
307 return false;
308 case 'w': // Floating point and SIMD registers (V0-V31)
309 Info.setAllowsRegister();
310 return true;
311 case 'I': // Constant that can be used with an ADD instruction
312 case 'J': // Constant that can be used with a SUB instruction
313 case 'K': // Constant that can be used with a 32-bit logical instruction
314 case 'L': // Constant that can be used with a 64-bit logical instruction
315 case 'M': // Constant that can be used as a 32-bit MOV immediate
316 case 'N': // Constant that can be used as a 64-bit MOV immediate
317 case 'Y': // Floating point constant zero
318 case 'Z': // Integer constant zero
319 return true;
320 case 'Q': // A memory reference with base register and no offset
321 Info.setAllowsMemory();
322 return true;
323 case 'S': // A symbolic address
324 Info.setAllowsRegister();
325 return true;
326 case 'U':
327 // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
328 // Utf: A memory address suitable for ldp/stp in TF mode.
329 // Usa: An absolute symbolic address.
330 // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
331 llvm_unreachable("FIXME: Unimplemented support for U* constraints.");
332 case 'z': // Zero register, wzr or xzr
333 Info.setAllowsRegister();
334 return true;
335 case 'x': // Floating point and SIMD registers (V0-V15)
336 Info.setAllowsRegister();
337 return true;
338 }
339 return false;
340}
Erich Keaneebba5922017-07-21 22:37:03 +0000341
Tim Northoverad4c5db2017-07-24 17:06:23 +0000342bool AArch64TargetInfo::validateConstraintModifier(
343 StringRef Constraint, char Modifier, unsigned Size,
344 std::string &SuggestedModifier) const {
345 // Strip off constraint modifiers.
346 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
347 Constraint = Constraint.substr(1);
348
349 switch (Constraint[0]) {
350 default:
351 return true;
352 case 'z':
353 case 'r': {
354 switch (Modifier) {
355 case 'x':
356 case 'w':
357 // For now assume that the person knows what they're
358 // doing with the modifier.
359 return true;
360 default:
361 // By default an 'r' constraint will be in the 'x'
362 // registers.
363 if (Size == 64)
364 return true;
365
366 SuggestedModifier = "w";
367 return false;
368 }
369 }
370 }
371}
372
373const char *AArch64TargetInfo::getClobbers() const { return ""; }
374
375int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
376 if (RegNo == 0)
377 return 0;
378 if (RegNo == 1)
379 return 1;
380 return -1;
381}
382
383AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
384 const TargetOptions &Opts)
385 : AArch64TargetInfo(Triple, Opts) {}
386
387void AArch64leTargetInfo::setDataLayout() {
388 if (getTriple().isOSBinFormatMachO())
389 resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
390 else
391 resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
392}
393
394void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
395 MacroBuilder &Builder) const {
396 Builder.defineMacro("__AARCH64EL__");
397 AArch64TargetInfo::getTargetDefines(Opts, Builder);
398}
399
400AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
401 const TargetOptions &Opts)
402 : AArch64TargetInfo(Triple, Opts) {}
403
404void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
405 MacroBuilder &Builder) const {
406 Builder.defineMacro("__AARCH64EB__");
407 Builder.defineMacro("__AARCH_BIG_ENDIAN");
408 Builder.defineMacro("__ARM_BIG_ENDIAN");
409 AArch64TargetInfo::getTargetDefines(Opts, Builder);
410}
411
412void AArch64beTargetInfo::setDataLayout() {
413 assert(!getTriple().isOSBinFormatMachO());
414 resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
415}
416
417MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
418 const TargetOptions &Opts)
419 : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
420
421 // This is an LLP64 platform.
422 // int:4, long:4, long long:8, long double:8.
423 WCharType = UnsignedShort;
424 IntWidth = IntAlign = 32;
425 LongWidth = LongAlign = 32;
426 DoubleAlign = LongLongAlign = 64;
427 LongDoubleWidth = LongDoubleAlign = 64;
428 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
429 IntMaxType = SignedLongLong;
430 Int64Type = SignedLongLong;
431 SizeType = UnsignedLongLong;
432 PtrDiffType = SignedLongLong;
433 IntPtrType = SignedLongLong;
434
435 TheCXXABI.set(TargetCXXABI::Microsoft);
436}
437
438void MicrosoftARM64TargetInfo::setDataLayout() {
439 resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
440}
441
442void MicrosoftARM64TargetInfo::getVisualStudioDefines(
443 const LangOptions &Opts, MacroBuilder &Builder) const {
444 WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts, Builder);
445 Builder.defineMacro("_WIN32", "1");
446 Builder.defineMacro("_WIN64", "1");
447 Builder.defineMacro("_M_ARM64", "1");
448}
449
450void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
451 MacroBuilder &Builder) const {
452 WindowsTargetInfo::getTargetDefines(Opts, Builder);
453 getVisualStudioDefines(Opts, Builder);
454}
455
456TargetInfo::BuiltinVaListKind
457MicrosoftARM64TargetInfo::getBuiltinVaListKind() const {
458 return TargetInfo::CharPtrBuiltinVaList;
459}
460
Martin Storsjoc85d26b2017-08-07 20:52:04 +0000461TargetInfo::CallingConvCheckResult
462MicrosoftARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
463 switch (CC) {
464 case CC_X86StdCall:
465 case CC_X86ThisCall:
466 case CC_X86FastCall:
467 case CC_X86VectorCall:
468 return CCCR_Ignore;
469 case CC_C:
470 case CC_OpenCLKernel:
471 case CC_Win64:
472 return CCCR_OK;
473 default:
474 return CCCR_Warning;
475 }
476}
477
Tim Northoverad4c5db2017-07-24 17:06:23 +0000478DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
479 const TargetOptions &Opts)
480 : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
481 Int64Type = SignedLongLong;
482 WCharType = SignedInt;
483 UseSignedCharForObjCBool = false;
484
485 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
486 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
487
488 TheCXXABI.set(TargetCXXABI::iOS64);
489}
490
491void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
492 const llvm::Triple &Triple,
493 MacroBuilder &Builder) const {
494 Builder.defineMacro("__AARCH64_SIMD__");
495 Builder.defineMacro("__ARM64_ARCH_8__");
496 Builder.defineMacro("__ARM_NEON__");
497 Builder.defineMacro("__LITTLE_ENDIAN__");
498 Builder.defineMacro("__REGISTER_PREFIX__", "");
499 Builder.defineMacro("__arm64", "1");
500 Builder.defineMacro("__arm64__", "1");
501
502 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
503}
504
505TargetInfo::BuiltinVaListKind
506DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
507 return TargetInfo::CharPtrBuiltinVaList;
508}
509
510// 64-bit RenderScript is aarch64
511RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
512 const TargetOptions &Opts)
513 : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
514 Triple.getOSName(),
515 Triple.getEnvironmentName()),
516 Opts) {
517 IsRenderScriptTarget = true;
518}
519
520void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
521 MacroBuilder &Builder) const {
522 Builder.defineMacro("__RENDERSCRIPT__");
523 AArch64leTargetInfo::getTargetDefines(Opts, Builder);
524}