blob: b65a44928f2269beed1683aaf011be8f61db6d88 [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" ||
93 llvm::AArch64::parseCPUArch(Name) !=
94 static_cast<unsigned>(llvm::AArch64::ArchKind::AK_INVALID);
95}
96
97bool AArch64TargetInfo::setCPU(const std::string &Name) {
98 return isValidCPUName(Name);
99}
100
101void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
102 MacroBuilder &Builder) const {
103 Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
104}
105
106void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
107 MacroBuilder &Builder) const {
108 // Also include the ARMv8.1 defines
109 getTargetDefinesARMV81A(Opts, Builder);
110}
111
112void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
113 MacroBuilder &Builder) const {
114 // Target identification.
115 Builder.defineMacro("__aarch64__");
116 // For bare-metal none-eabi.
117 if (getTriple().getOS() == llvm::Triple::UnknownOS &&
118 (getTriple().getEnvironment() == llvm::Triple::EABI ||
119 getTriple().getEnvironment() == llvm::Triple::EABIHF))
120 Builder.defineMacro("__ELF__");
121
122 // Target properties.
123 Builder.defineMacro("_LP64");
124 Builder.defineMacro("__LP64__");
125
126 // ACLE predefines. Many can only have one possible value on v8 AArch64.
127 Builder.defineMacro("__ARM_ACLE", "200");
128 Builder.defineMacro("__ARM_ARCH", "8");
129 Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
130
131 Builder.defineMacro("__ARM_64BIT_STATE", "1");
132 Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
133 Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
134
135 Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
136 Builder.defineMacro("__ARM_FEATURE_FMA", "1");
137 Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
138 Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
139 Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility
140 Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
141 Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
142
143 Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
144
145 // 0xe implies support for half, single and double precision operations.
146 Builder.defineMacro("__ARM_FP", "0xE");
147
148 // PCS specifies this for SysV variants, which is all we support. Other ABIs
149 // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
150 Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
151 Builder.defineMacro("__ARM_FP16_ARGS", "1");
152
153 if (Opts.UnsafeFPMath)
154 Builder.defineMacro("__ARM_FP_FAST", "1");
155
156 Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", Opts.ShortWChar ? "2" : "4");
157
158 Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
159
160 if (FPU & NeonMode) {
161 Builder.defineMacro("__ARM_NEON", "1");
162 // 64-bit NEON supports half, single and double precision operations.
163 Builder.defineMacro("__ARM_NEON_FP", "0xE");
164 }
165
166 if (FPU & SveMode)
167 Builder.defineMacro("__ARM_FEATURE_SVE", "1");
168
169 if (CRC)
170 Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
171
172 if (Crypto)
173 Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
174
175 if (Unaligned)
176 Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
177
178 switch (ArchKind) {
179 default:
180 break;
181 case llvm::AArch64::ArchKind::AK_ARMV8_1A:
182 getTargetDefinesARMV81A(Opts, Builder);
183 break;
184 case llvm::AArch64::ArchKind::AK_ARMV8_2A:
185 getTargetDefinesARMV82A(Opts, Builder);
186 break;
187 }
188
189 // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
190 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
191 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
192 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
193 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
194}
195
196ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
197 return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
198 Builtin::FirstTSBuiltin);
199}
200
201bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
202 return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" ||
203 (Feature == "neon" && (FPU & NeonMode)) ||
204 (Feature == "sve" && (FPU & SveMode));
205}
206
207bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
208 DiagnosticsEngine &Diags) {
209 FPU = FPUMode;
210 CRC = 0;
211 Crypto = 0;
212 Unaligned = 1;
213 HasFullFP16 = 0;
214 ArchKind = llvm::AArch64::ArchKind::AK_ARMV8A;
215
216 for (const auto &Feature : Features) {
217 if (Feature == "+neon")
218 FPU |= NeonMode;
219 if (Feature == "+sve")
220 FPU |= SveMode;
221 if (Feature == "+crc")
222 CRC = 1;
223 if (Feature == "+crypto")
224 Crypto = 1;
225 if (Feature == "+strict-align")
226 Unaligned = 0;
227 if (Feature == "+v8.1a")
228 ArchKind = llvm::AArch64::ArchKind::AK_ARMV8_1A;
229 if (Feature == "+v8.2a")
230 ArchKind = llvm::AArch64::ArchKind::AK_ARMV8_2A;
231 if (Feature == "+fullfp16")
232 HasFullFP16 = 1;
233 }
234
235 setDataLayout();
236
237 return true;
238}
239
240TargetInfo::CallingConvCheckResult
241AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
242 switch (CC) {
243 case CC_C:
244 case CC_Swift:
245 case CC_PreserveMost:
246 case CC_PreserveAll:
247 case CC_OpenCLKernel:
248 case CC_Win64:
249 return CCCR_OK;
250 default:
251 return CCCR_Warning;
252 }
253}
254
255bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
256
257TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
258 return TargetInfo::AArch64ABIBuiltinVaList;
259}
260
Erich Keaneebba5922017-07-21 22:37:03 +0000261const char *const AArch64TargetInfo::GCCRegNames[] = {
262 // 32-bit Integer registers
263 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
264 "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
265 "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
266
267 // 64-bit Integer registers
268 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
269 "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
270 "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
271
272 // 32-bit floating point regsisters
273 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
274 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
275 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
276
277 // 64-bit floating point regsisters
278 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
279 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
280 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
281
282 // Vector registers
283 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
284 "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
285 "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
286};
287
288ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
289 return llvm::makeArrayRef(GCCRegNames);
290}
291
292const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
293 {{"w31"}, "wsp"}, {{"x29"}, "fp"}, {{"x30"}, "lr"}, {{"x31"}, "sp"},
294 // The S/D/Q and W/X registers overlap, but aren't really aliases; we
295 // don't want to substitute one of these for a different-sized one.
296};
297
298ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
299 return llvm::makeArrayRef(GCCRegAliases);
300}
301
Tim Northoverad4c5db2017-07-24 17:06:23 +0000302bool AArch64TargetInfo::validateAsmConstraint(
303 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
304 switch (*Name) {
305 default:
306 return false;
307 case 'w': // Floating point and SIMD registers (V0-V31)
308 Info.setAllowsRegister();
309 return true;
310 case 'I': // Constant that can be used with an ADD instruction
311 case 'J': // Constant that can be used with a SUB instruction
312 case 'K': // Constant that can be used with a 32-bit logical instruction
313 case 'L': // Constant that can be used with a 64-bit logical instruction
314 case 'M': // Constant that can be used as a 32-bit MOV immediate
315 case 'N': // Constant that can be used as a 64-bit MOV immediate
316 case 'Y': // Floating point constant zero
317 case 'Z': // Integer constant zero
318 return true;
319 case 'Q': // A memory reference with base register and no offset
320 Info.setAllowsMemory();
321 return true;
322 case 'S': // A symbolic address
323 Info.setAllowsRegister();
324 return true;
325 case 'U':
326 // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
327 // Utf: A memory address suitable for ldp/stp in TF mode.
328 // Usa: An absolute symbolic address.
329 // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
330 llvm_unreachable("FIXME: Unimplemented support for U* constraints.");
331 case 'z': // Zero register, wzr or xzr
332 Info.setAllowsRegister();
333 return true;
334 case 'x': // Floating point and SIMD registers (V0-V15)
335 Info.setAllowsRegister();
336 return true;
337 }
338 return false;
339}
Erich Keaneebba5922017-07-21 22:37:03 +0000340
Tim Northoverad4c5db2017-07-24 17:06:23 +0000341bool AArch64TargetInfo::validateConstraintModifier(
342 StringRef Constraint, char Modifier, unsigned Size,
343 std::string &SuggestedModifier) const {
344 // Strip off constraint modifiers.
345 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
346 Constraint = Constraint.substr(1);
347
348 switch (Constraint[0]) {
349 default:
350 return true;
351 case 'z':
352 case 'r': {
353 switch (Modifier) {
354 case 'x':
355 case 'w':
356 // For now assume that the person knows what they're
357 // doing with the modifier.
358 return true;
359 default:
360 // By default an 'r' constraint will be in the 'x'
361 // registers.
362 if (Size == 64)
363 return true;
364
365 SuggestedModifier = "w";
366 return false;
367 }
368 }
369 }
370}
371
372const char *AArch64TargetInfo::getClobbers() const { return ""; }
373
374int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
375 if (RegNo == 0)
376 return 0;
377 if (RegNo == 1)
378 return 1;
379 return -1;
380}
381
382AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
383 const TargetOptions &Opts)
384 : AArch64TargetInfo(Triple, Opts) {}
385
386void AArch64leTargetInfo::setDataLayout() {
387 if (getTriple().isOSBinFormatMachO())
388 resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
389 else
390 resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
391}
392
393void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
394 MacroBuilder &Builder) const {
395 Builder.defineMacro("__AARCH64EL__");
396 AArch64TargetInfo::getTargetDefines(Opts, Builder);
397}
398
399AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
400 const TargetOptions &Opts)
401 : AArch64TargetInfo(Triple, Opts) {}
402
403void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
404 MacroBuilder &Builder) const {
405 Builder.defineMacro("__AARCH64EB__");
406 Builder.defineMacro("__AARCH_BIG_ENDIAN");
407 Builder.defineMacro("__ARM_BIG_ENDIAN");
408 AArch64TargetInfo::getTargetDefines(Opts, Builder);
409}
410
411void AArch64beTargetInfo::setDataLayout() {
412 assert(!getTriple().isOSBinFormatMachO());
413 resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
414}
415
416MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
417 const TargetOptions &Opts)
418 : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
419
420 // This is an LLP64 platform.
421 // int:4, long:4, long long:8, long double:8.
422 WCharType = UnsignedShort;
423 IntWidth = IntAlign = 32;
424 LongWidth = LongAlign = 32;
425 DoubleAlign = LongLongAlign = 64;
426 LongDoubleWidth = LongDoubleAlign = 64;
427 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
428 IntMaxType = SignedLongLong;
429 Int64Type = SignedLongLong;
430 SizeType = UnsignedLongLong;
431 PtrDiffType = SignedLongLong;
432 IntPtrType = SignedLongLong;
433
434 TheCXXABI.set(TargetCXXABI::Microsoft);
435}
436
437void MicrosoftARM64TargetInfo::setDataLayout() {
438 resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
439}
440
441void MicrosoftARM64TargetInfo::getVisualStudioDefines(
442 const LangOptions &Opts, MacroBuilder &Builder) const {
443 WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts, Builder);
444 Builder.defineMacro("_WIN32", "1");
445 Builder.defineMacro("_WIN64", "1");
446 Builder.defineMacro("_M_ARM64", "1");
447}
448
449void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
450 MacroBuilder &Builder) const {
451 WindowsTargetInfo::getTargetDefines(Opts, Builder);
452 getVisualStudioDefines(Opts, Builder);
453}
454
455TargetInfo::BuiltinVaListKind
456MicrosoftARM64TargetInfo::getBuiltinVaListKind() const {
457 return TargetInfo::CharPtrBuiltinVaList;
458}
459
460DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
461 const TargetOptions &Opts)
462 : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
463 Int64Type = SignedLongLong;
464 WCharType = SignedInt;
465 UseSignedCharForObjCBool = false;
466
467 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
468 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
469
470 TheCXXABI.set(TargetCXXABI::iOS64);
471}
472
473void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
474 const llvm::Triple &Triple,
475 MacroBuilder &Builder) const {
476 Builder.defineMacro("__AARCH64_SIMD__");
477 Builder.defineMacro("__ARM64_ARCH_8__");
478 Builder.defineMacro("__ARM_NEON__");
479 Builder.defineMacro("__LITTLE_ENDIAN__");
480 Builder.defineMacro("__REGISTER_PREFIX__", "");
481 Builder.defineMacro("__arm64", "1");
482 Builder.defineMacro("__arm64__", "1");
483
484 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
485}
486
487TargetInfo::BuiltinVaListKind
488DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
489 return TargetInfo::CharPtrBuiltinVaList;
490}
491
492// 64-bit RenderScript is aarch64
493RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
494 const TargetOptions &Opts)
495 : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
496 Triple.getOSName(),
497 Triple.getEnvironmentName()),
498 Opts) {
499 IsRenderScriptTarget = true;
500}
501
502void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
503 MacroBuilder &Builder) const {
504 Builder.defineMacro("__RENDERSCRIPT__");
505 AArch64leTargetInfo::getTargetDefines(Opts, Builder);
506}