]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/Basic/Targets/AArch64.cpp
Merge clang trunk r321017 to contrib/llvm/tools/clang.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / 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                       llvm::utostr(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   switch (ArchKind) {
185   default:
186     break;
187   case llvm::AArch64::ArchKind::ARMV8_1A:
188     getTargetDefinesARMV81A(Opts, Builder);
189     break;
190   case llvm::AArch64::ArchKind::ARMV8_2A:
191     getTargetDefinesARMV82A(Opts, Builder);
192     break;
193   }
194
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");
200 }
201
202 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
203   return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
204                                              Builtin::FirstTSBuiltin);
205 }
206
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));
211 }
212
213 bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
214                                              DiagnosticsEngine &Diags) {
215   FPU = FPUMode;
216   CRC = 0;
217   Crypto = 0;
218   Unaligned = 1;
219   HasFullFP16 = 0;
220   ArchKind = llvm::AArch64::ArchKind::ARMV8A;
221
222   for (const auto &Feature : Features) {
223     if (Feature == "+neon")
224       FPU |= NeonMode;
225     if (Feature == "+sve")
226       FPU |= SveMode;
227     if (Feature == "+crc")
228       CRC = 1;
229     if (Feature == "+crypto")
230       Crypto = 1;
231     if (Feature == "+strict-align")
232       Unaligned = 0;
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")
238       HasFullFP16 = 1;
239   }
240
241   setDataLayout();
242
243   return true;
244 }
245
246 TargetInfo::CallingConvCheckResult
247 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
248   switch (CC) {
249   case CC_C:
250   case CC_Swift:
251   case CC_PreserveMost:
252   case CC_PreserveAll:
253   case CC_OpenCLKernel:
254   case CC_Win64:
255     return CCCR_OK;
256   default:
257     return CCCR_Warning;
258   }
259 }
260
261 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
262
263 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
264   return TargetInfo::AArch64ABIBuiltinVaList;
265 }
266
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",
272
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",
277
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",
282
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",
287
288     // Vector registers
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"
292 };
293
294 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
295   return llvm::makeArrayRef(GCCRegNames);
296 }
297
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.
302 };
303
304 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
305   return llvm::makeArrayRef(GCCRegAliases);
306 }
307
308 bool AArch64TargetInfo::validateAsmConstraint(
309     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
310   switch (*Name) {
311   default:
312     return false;
313   case 'w': // Floating point and SIMD registers (V0-V31)
314     Info.setAllowsRegister();
315     return true;
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
324     return true;
325   case 'Q': // A memory reference with base register and no offset
326     Info.setAllowsMemory();
327     return true;
328   case 'S': // A symbolic address
329     Info.setAllowsRegister();
330     return true;
331   case 'U':
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();
339     return true;
340   case 'x': // Floating point and SIMD registers (V0-V15)
341     Info.setAllowsRegister();
342     return true;
343   }
344   return false;
345 }
346
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);
353
354   switch (Constraint[0]) {
355   default:
356     return true;
357   case 'z':
358   case 'r': {
359     switch (Modifier) {
360     case 'x':
361     case 'w':
362       // For now assume that the person knows what they're
363       // doing with the modifier.
364       return true;
365     default:
366       // By default an 'r' constraint will be in the 'x'
367       // registers.
368       if (Size == 64)
369         return true;
370
371       SuggestedModifier = "w";
372       return false;
373     }
374   }
375   }
376 }
377
378 const char *AArch64TargetInfo::getClobbers() const { return ""; }
379
380 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
381   if (RegNo == 0)
382     return 0;
383   if (RegNo == 1)
384     return 1;
385   return -1;
386 }
387
388 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
389                                          const TargetOptions &Opts)
390     : AArch64TargetInfo(Triple, Opts) {}
391
392 void AArch64leTargetInfo::setDataLayout() {
393   if (getTriple().isOSBinFormatMachO())
394     resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
395   else
396     resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
397 }
398
399 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
400                                            MacroBuilder &Builder) const {
401   Builder.defineMacro("__AARCH64EL__");
402   AArch64TargetInfo::getTargetDefines(Opts, Builder);
403 }
404
405 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
406                                          const TargetOptions &Opts)
407     : AArch64TargetInfo(Triple, Opts) {}
408
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);
415 }
416
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");
420 }
421
422 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
423                                                const TargetOptions &Opts)
424     : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
425
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;
438 }
439
440 void WindowsARM64TargetInfo::setDataLayout() {
441   resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
442 }
443
444 TargetInfo::BuiltinVaListKind
445 WindowsARM64TargetInfo::getBuiltinVaListKind() const {
446   return TargetInfo::CharPtrBuiltinVaList;
447 }
448
449 TargetInfo::CallingConvCheckResult
450 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
451   switch (CC) {
452   case CC_X86StdCall:
453   case CC_X86ThisCall:
454   case CC_X86FastCall:
455   case CC_X86VectorCall:
456     return CCCR_Ignore;
457   case CC_C:
458   case CC_OpenCLKernel:
459   case CC_PreserveMost:
460   case CC_PreserveAll:
461   case CC_Win64:
462     return CCCR_OK;
463   default:
464     return CCCR_Warning;
465   }
466 }
467
468 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
469                                                    const TargetOptions &Opts)
470     : WindowsARM64TargetInfo(Triple, Opts) {
471   TheCXXABI.set(TargetCXXABI::Microsoft);
472 }
473
474 void MicrosoftARM64TargetInfo::getVisualStudioDefines(
475     const LangOptions &Opts, MacroBuilder &Builder) const {
476   WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts, Builder);
477   Builder.defineMacro("_M_ARM64", "1");
478 }
479
480 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
481                                                 MacroBuilder &Builder) const {
482   WindowsTargetInfo::getTargetDefines(Opts, Builder);
483   getVisualStudioDefines(Opts, Builder);
484 }
485
486 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
487                                            const TargetOptions &Opts)
488     : WindowsARM64TargetInfo(Triple, Opts) {
489   TheCXXABI.set(TargetCXXABI::GenericAArch64);
490 }
491
492 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
493                                                  const TargetOptions &Opts)
494     : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
495   Int64Type = SignedLongLong;
496   UseSignedCharForObjCBool = false;
497
498   LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
499   LongDoubleFormat = &llvm::APFloat::IEEEdouble();
500
501   TheCXXABI.set(TargetCXXABI::iOS64);
502 }
503
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");
514
515   getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
516 }
517
518 TargetInfo::BuiltinVaListKind
519 DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
520   return TargetInfo::CharPtrBuiltinVaList;
521 }
522
523 // 64-bit RenderScript is aarch64
524 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
525                                                    const TargetOptions &Opts)
526     : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
527                                        Triple.getOSName(),
528                                        Triple.getEnvironmentName()),
529                           Opts) {
530   IsRenderScriptTarget = true;
531 }
532
533 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
534                                                 MacroBuilder &Builder) const {
535   Builder.defineMacro("__RENDERSCRIPT__");
536   AArch64leTargetInfo::getTargetDefines(Opts, Builder);
537 }