]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/Basic/Targets/AArch64.cpp
Vendor import of clang trunk r321530:
[FreeBSD/FreeBSD.git] / lib / Basic / Targets / AArch64.cpp
1 //===--- 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 #include "llvm/ADT/StringExtras.h"
19
20 using namespace clang;
21 using namespace clang::targets;
22
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"
27
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"
33 };
34
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;
44   } else {
45     if (!getTriple().isOSDarwin())
46       WCharType = UnsignedInt;
47
48     Int64Type = SignedLong;
49     IntMaxType = SignedLong;
50   }
51
52
53   LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
54   MaxVectorAlign = 128;
55   MaxAtomicInlineWidth = 128;
56   MaxAtomicPromoteWidth = 128;
57
58   LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
59   LongDoubleFormat = &llvm::APFloat::IEEEquad();
60
61   // Make __builtin_ms_va_list available.
62   HasBuiltinMSVaList = true;
63
64   // {} in inline assembly are neon specifiers, not assembly variant
65   // specifiers.
66   NoAsmVariants = true;
67
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;
74
75   // AArch64 targets default to using the ARM C++ ABI.
76   TheCXXABI.set(TargetCXXABI::GenericAArch64);
77
78   if (Triple.getOS() == llvm::Triple::Linux)
79     this->MCountName = "\01_mcount";
80   else if (Triple.getOS() == llvm::Triple::UnknownOS)
81     this->MCountName =
82         Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
83 }
84
85 StringRef AArch64TargetInfo::getABI() const { return ABI; }
86
87 bool AArch64TargetInfo::setABI(const std::string &Name) {
88   if (Name != "aapcs" && Name != "darwinpcs")
89     return false;
90
91   ABI = Name;
92   return true;
93 }
94
95 bool AArch64TargetInfo::isValidCPUName(StringRef Name) const {
96   return Name == "generic" ||
97          llvm::AArch64::parseCPUArch(Name) != llvm::AArch64::ArchKind::INVALID;
98 }
99
100 bool AArch64TargetInfo::setCPU(const std::string &Name) {
101   return isValidCPUName(Name);
102 }
103
104 void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
105                                                 MacroBuilder &Builder) const {
106   Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
107 }
108
109 void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
110                                                 MacroBuilder &Builder) const {
111   // Also include the ARMv8.1 defines
112   getTargetDefinesARMV81A(Opts, Builder);
113 }
114
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__");
124
125   // Target properties.
126   if (!getTriple().isOSWindows()) {
127     Builder.defineMacro("_LP64");
128     Builder.defineMacro("__LP64__");
129   }
130
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'");
135
136   Builder.defineMacro("__ARM_64BIT_STATE", "1");
137   Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
138   Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
139
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");
147
148   Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
149
150   // 0xe implies support for half, single and double precision operations.
151   Builder.defineMacro("__ARM_FP", "0xE");
152
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");
157
158   if (Opts.UnsafeFPMath)
159     Builder.defineMacro("__ARM_FP_FAST", "1");
160
161   Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
162                       Twine(Opts.WCharSize ? Opts.WCharSize : 4));
163
164   Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
165
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");
170   }
171
172   if (FPU & SveMode)
173     Builder.defineMacro("__ARM_FEATURE_SVE", "1");
174
175   if (CRC)
176     Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
177
178   if (Crypto)
179     Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
180
181   if (Unaligned)
182     Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
183
184   if ((FPU & NeonMode) && HasFullFP16)
185     Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
186
187   switch (ArchKind) {
188   default:
189     break;
190   case llvm::AArch64::ArchKind::ARMV8_1A:
191     getTargetDefinesARMV81A(Opts, Builder);
192     break;
193   case llvm::AArch64::ArchKind::ARMV8_2A:
194     getTargetDefinesARMV82A(Opts, Builder);
195     break;
196   }
197
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");
203 }
204
205 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
206   return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
207                                              Builtin::FirstTSBuiltin);
208 }
209
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));
214 }
215
216 bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
217                                              DiagnosticsEngine &Diags) {
218   FPU = FPUMode;
219   CRC = 0;
220   Crypto = 0;
221   Unaligned = 1;
222   HasFullFP16 = 0;
223   ArchKind = llvm::AArch64::ArchKind::ARMV8A;
224
225   for (const auto &Feature : Features) {
226     if (Feature == "+neon")
227       FPU |= NeonMode;
228     if (Feature == "+sve")
229       FPU |= SveMode;
230     if (Feature == "+crc")
231       CRC = 1;
232     if (Feature == "+crypto")
233       Crypto = 1;
234     if (Feature == "+strict-align")
235       Unaligned = 0;
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")
241       HasFullFP16 = 1;
242   }
243
244   setDataLayout();
245
246   return true;
247 }
248
249 TargetInfo::CallingConvCheckResult
250 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
251   switch (CC) {
252   case CC_C:
253   case CC_Swift:
254   case CC_PreserveMost:
255   case CC_PreserveAll:
256   case CC_OpenCLKernel:
257   case CC_Win64:
258     return CCCR_OK;
259   default:
260     return CCCR_Warning;
261   }
262 }
263
264 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
265
266 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
267   return TargetInfo::AArch64ABIBuiltinVaList;
268 }
269
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",
275
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",
280
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",
285
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",
290
291     // Vector registers
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"
295 };
296
297 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
298   return llvm::makeArrayRef(GCCRegNames);
299 }
300
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.
305 };
306
307 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
308   return llvm::makeArrayRef(GCCRegAliases);
309 }
310
311 bool AArch64TargetInfo::validateAsmConstraint(
312     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
313   switch (*Name) {
314   default:
315     return false;
316   case 'w': // Floating point and SIMD registers (V0-V31)
317     Info.setAllowsRegister();
318     return true;
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
327     return true;
328   case 'Q': // A memory reference with base register and no offset
329     Info.setAllowsMemory();
330     return true;
331   case 'S': // A symbolic address
332     Info.setAllowsRegister();
333     return true;
334   case 'U':
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();
342     return true;
343   case 'x': // Floating point and SIMD registers (V0-V15)
344     Info.setAllowsRegister();
345     return true;
346   }
347   return false;
348 }
349
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);
356
357   switch (Constraint[0]) {
358   default:
359     return true;
360   case 'z':
361   case 'r': {
362     switch (Modifier) {
363     case 'x':
364     case 'w':
365       // For now assume that the person knows what they're
366       // doing with the modifier.
367       return true;
368     default:
369       // By default an 'r' constraint will be in the 'x'
370       // registers.
371       if (Size == 64)
372         return true;
373
374       SuggestedModifier = "w";
375       return false;
376     }
377   }
378   }
379 }
380
381 const char *AArch64TargetInfo::getClobbers() const { return ""; }
382
383 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
384   if (RegNo == 0)
385     return 0;
386   if (RegNo == 1)
387     return 1;
388   return -1;
389 }
390
391 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
392                                          const TargetOptions &Opts)
393     : AArch64TargetInfo(Triple, Opts) {}
394
395 void AArch64leTargetInfo::setDataLayout() {
396   if (getTriple().isOSBinFormatMachO())
397     resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
398   else
399     resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
400 }
401
402 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
403                                            MacroBuilder &Builder) const {
404   Builder.defineMacro("__AARCH64EL__");
405   AArch64TargetInfo::getTargetDefines(Opts, Builder);
406 }
407
408 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
409                                          const TargetOptions &Opts)
410     : AArch64TargetInfo(Triple, Opts) {}
411
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);
418 }
419
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");
423 }
424
425 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
426                                                const TargetOptions &Opts)
427     : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
428
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;
441 }
442
443 void WindowsARM64TargetInfo::setDataLayout() {
444   resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
445 }
446
447 TargetInfo::BuiltinVaListKind
448 WindowsARM64TargetInfo::getBuiltinVaListKind() const {
449   return TargetInfo::CharPtrBuiltinVaList;
450 }
451
452 TargetInfo::CallingConvCheckResult
453 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
454   switch (CC) {
455   case CC_X86StdCall:
456   case CC_X86ThisCall:
457   case CC_X86FastCall:
458   case CC_X86VectorCall:
459     return CCCR_Ignore;
460   case CC_C:
461   case CC_OpenCLKernel:
462   case CC_PreserveMost:
463   case CC_PreserveAll:
464   case CC_Win64:
465     return CCCR_OK;
466   default:
467     return CCCR_Warning;
468   }
469 }
470
471 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
472                                                    const TargetOptions &Opts)
473     : WindowsARM64TargetInfo(Triple, Opts) {
474   TheCXXABI.set(TargetCXXABI::Microsoft);
475 }
476
477 void MicrosoftARM64TargetInfo::getVisualStudioDefines(
478     const LangOptions &Opts, MacroBuilder &Builder) const {
479   WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts, Builder);
480   Builder.defineMacro("_M_ARM64", "1");
481 }
482
483 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
484                                                 MacroBuilder &Builder) const {
485   WindowsTargetInfo::getTargetDefines(Opts, Builder);
486   getVisualStudioDefines(Opts, Builder);
487 }
488
489 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
490                                            const TargetOptions &Opts)
491     : WindowsARM64TargetInfo(Triple, Opts) {
492   TheCXXABI.set(TargetCXXABI::GenericAArch64);
493 }
494
495 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
496                                                  const TargetOptions &Opts)
497     : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
498   Int64Type = SignedLongLong;
499   UseSignedCharForObjCBool = false;
500
501   LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
502   LongDoubleFormat = &llvm::APFloat::IEEEdouble();
503
504   TheCXXABI.set(TargetCXXABI::iOS64);
505 }
506
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");
517
518   getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
519 }
520
521 TargetInfo::BuiltinVaListKind
522 DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
523   return TargetInfo::CharPtrBuiltinVaList;
524 }
525
526 // 64-bit RenderScript is aarch64
527 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
528                                                    const TargetOptions &Opts)
529     : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
530                                        Triple.getOSName(),
531                                        Triple.getEnvironmentName()),
532                           Opts) {
533   IsRenderScriptTarget = true;
534 }
535
536 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
537                                                 MacroBuilder &Builder) const {
538   Builder.defineMacro("__RENDERSCRIPT__");
539   AArch64leTargetInfo::getTargetDefines(Opts, Builder);
540 }