150
|
1 //===--- AArch64.cpp - Implement AArch64 target feature support -----------===//
|
|
2 //
|
|
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
4 // See https://llvm.org/LICENSE.txt for license information.
|
|
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
6 //
|
|
7 //===----------------------------------------------------------------------===//
|
|
8 //
|
|
9 // This file implements AArch64 TargetInfo objects.
|
|
10 //
|
|
11 //===----------------------------------------------------------------------===//
|
|
12
|
|
13 #include "AArch64.h"
|
173
|
14 #include "clang/Basic/LangOptions.h"
|
150
|
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 #include "llvm/ADT/StringSwitch.h"
|
|
20 #include "llvm/Support/AArch64TargetParser.h"
|
|
21
|
|
22 using namespace clang;
|
|
23 using namespace clang::targets;
|
|
24
|
|
25 const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
|
|
26 #define BUILTIN(ID, TYPE, ATTRS) \
|
|
27 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
|
|
28 #include "clang/Basic/BuiltinsNEON.def"
|
|
29
|
|
30 #define BUILTIN(ID, TYPE, ATTRS) \
|
|
31 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
|
173
|
32 #include "clang/Basic/BuiltinsSVE.def"
|
|
33
|
|
34 #define BUILTIN(ID, TYPE, ATTRS) \
|
|
35 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
|
150
|
36 #define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \
|
|
37 {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
|
|
38 #define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
|
|
39 {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
|
|
40 #include "clang/Basic/BuiltinsAArch64.def"
|
|
41 };
|
|
42
|
|
43 AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
|
|
44 const TargetOptions &Opts)
|
|
45 : TargetInfo(Triple), ABI("aapcs") {
|
|
46 if (getTriple().isOSOpenBSD()) {
|
|
47 Int64Type = SignedLongLong;
|
|
48 IntMaxType = SignedLongLong;
|
|
49 } else {
|
|
50 if (!getTriple().isOSDarwin() && !getTriple().isOSNetBSD())
|
|
51 WCharType = UnsignedInt;
|
|
52
|
|
53 Int64Type = SignedLong;
|
|
54 IntMaxType = SignedLong;
|
|
55 }
|
|
56
|
|
57 // All AArch64 implementations support ARMv8 FP, which makes half a legal type.
|
|
58 HasLegalHalfType = true;
|
|
59 HasFloat16 = true;
|
|
60
|
|
61 if (Triple.isArch64Bit())
|
|
62 LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
|
|
63 else
|
|
64 LongWidth = LongAlign = PointerWidth = PointerAlign = 32;
|
|
65
|
|
66 MaxVectorAlign = 128;
|
|
67 MaxAtomicInlineWidth = 128;
|
|
68 MaxAtomicPromoteWidth = 128;
|
|
69
|
|
70 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
|
|
71 LongDoubleFormat = &llvm::APFloat::IEEEquad();
|
|
72
|
|
73 // Make __builtin_ms_va_list available.
|
|
74 HasBuiltinMSVaList = true;
|
|
75
|
|
76 // Make the SVE types available. Note that this deliberately doesn't
|
|
77 // depend on SveMode, since in principle it should be possible to turn
|
|
78 // SVE on and off within a translation unit. It should also be possible
|
|
79 // to compile the global declaration:
|
|
80 //
|
|
81 // __SVInt8_t *ptr;
|
|
82 //
|
|
83 // even without SVE.
|
|
84 HasAArch64SVETypes = true;
|
|
85
|
|
86 // {} in inline assembly are neon specifiers, not assembly variant
|
|
87 // specifiers.
|
|
88 NoAsmVariants = true;
|
|
89
|
|
90 // AAPCS gives rules for bitfields. 7.1.7 says: "The container type
|
|
91 // contributes to the alignment of the containing aggregate in the same way
|
|
92 // a plain (non bit-field) member of that type would, without exception for
|
|
93 // zero-sized or anonymous bit-fields."
|
|
94 assert(UseBitFieldTypeAlignment && "bitfields affect type alignment");
|
|
95 UseZeroLengthBitfieldAlignment = true;
|
|
96
|
|
97 // AArch64 targets default to using the ARM C++ ABI.
|
|
98 TheCXXABI.set(TargetCXXABI::GenericAArch64);
|
|
99
|
|
100 if (Triple.getOS() == llvm::Triple::Linux)
|
|
101 this->MCountName = "\01_mcount";
|
|
102 else if (Triple.getOS() == llvm::Triple::UnknownOS)
|
|
103 this->MCountName =
|
|
104 Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
|
|
105 }
|
|
106
|
|
107 StringRef AArch64TargetInfo::getABI() const { return ABI; }
|
|
108
|
|
109 bool AArch64TargetInfo::setABI(const std::string &Name) {
|
|
110 if (Name != "aapcs" && Name != "darwinpcs")
|
|
111 return false;
|
|
112
|
|
113 ABI = Name;
|
|
114 return true;
|
|
115 }
|
|
116
|
|
117 bool AArch64TargetInfo::validateBranchProtection(StringRef Spec,
|
|
118 BranchProtectionInfo &BPI,
|
|
119 StringRef &Err) const {
|
|
120 llvm::AArch64::ParsedBranchProtection PBP;
|
|
121 if (!llvm::AArch64::parseBranchProtection(Spec, PBP, Err))
|
|
122 return false;
|
|
123
|
|
124 BPI.SignReturnAddr =
|
173
|
125 llvm::StringSwitch<LangOptions::SignReturnAddressScopeKind>(PBP.Scope)
|
|
126 .Case("non-leaf", LangOptions::SignReturnAddressScopeKind::NonLeaf)
|
|
127 .Case("all", LangOptions::SignReturnAddressScopeKind::All)
|
|
128 .Default(LangOptions::SignReturnAddressScopeKind::None);
|
150
|
129
|
|
130 if (PBP.Key == "a_key")
|
173
|
131 BPI.SignKey = LangOptions::SignReturnAddressKeyKind::AKey;
|
150
|
132 else
|
173
|
133 BPI.SignKey = LangOptions::SignReturnAddressKeyKind::BKey;
|
150
|
134
|
|
135 BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement;
|
|
136 return true;
|
|
137 }
|
|
138
|
|
139 bool AArch64TargetInfo::isValidCPUName(StringRef Name) const {
|
|
140 return Name == "generic" ||
|
|
141 llvm::AArch64::parseCPUArch(Name) != llvm::AArch64::ArchKind::INVALID;
|
|
142 }
|
|
143
|
|
144 bool AArch64TargetInfo::setCPU(const std::string &Name) {
|
|
145 return isValidCPUName(Name);
|
|
146 }
|
|
147
|
|
148 void AArch64TargetInfo::fillValidCPUList(
|
|
149 SmallVectorImpl<StringRef> &Values) const {
|
|
150 llvm::AArch64::fillValidCPUArchList(Values);
|
|
151 }
|
|
152
|
|
153 void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
|
|
154 MacroBuilder &Builder) const {
|
173
|
155 // FIXME: Armv8.1 makes __ARM_FEATURE_CRC32 mandatory. Handle it here.
|
150
|
156 Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
|
|
157 }
|
|
158
|
|
159 void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
|
|
160 MacroBuilder &Builder) const {
|
|
161 // Also include the ARMv8.1 defines
|
|
162 getTargetDefinesARMV81A(Opts, Builder);
|
|
163 }
|
|
164
|
|
165 void AArch64TargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts,
|
|
166 MacroBuilder &Builder) const {
|
|
167 Builder.defineMacro("__ARM_FEATURE_COMPLEX", "1");
|
|
168 Builder.defineMacro("__ARM_FEATURE_JCVT", "1");
|
|
169 // Also include the Armv8.2 defines
|
|
170 getTargetDefinesARMV82A(Opts, Builder);
|
|
171 }
|
|
172
|
|
173 void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts,
|
|
174 MacroBuilder &Builder) const {
|
|
175 // Also include the Armv8.3 defines
|
173
|
176 // FIXME: Armv8.4 makes __ARM_FEATURE_ATOMICS, defined in GCC, mandatory.
|
|
177 // Add and handle it here.
|
150
|
178 getTargetDefinesARMV83A(Opts, Builder);
|
|
179 }
|
|
180
|
|
181 void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts,
|
|
182 MacroBuilder &Builder) const {
|
|
183 // Also include the Armv8.4 defines
|
|
184 getTargetDefinesARMV84A(Opts, Builder);
|
|
185 }
|
|
186
|
173
|
187 void AArch64TargetInfo::getTargetDefinesARMV86A(const LangOptions &Opts,
|
|
188 MacroBuilder &Builder) const {
|
|
189 // Also include the Armv8.5 defines
|
|
190 // FIXME: Armv8.6 makes the following extensions mandatory:
|
|
191 // - __ARM_FEATURE_BF16
|
|
192 // - __ARM_FEATURE_MATMUL_INT8
|
|
193 // Handle them here.
|
|
194 getTargetDefinesARMV85A(Opts, Builder);
|
|
195 }
|
150
|
196
|
|
197 void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
|
|
198 MacroBuilder &Builder) const {
|
|
199 // Target identification.
|
|
200 Builder.defineMacro("__aarch64__");
|
|
201 // For bare-metal.
|
|
202 if (getTriple().getOS() == llvm::Triple::UnknownOS &&
|
|
203 getTriple().isOSBinFormatELF())
|
|
204 Builder.defineMacro("__ELF__");
|
|
205
|
|
206 // Target properties.
|
|
207 if (!getTriple().isOSWindows() && getTriple().isArch64Bit()) {
|
|
208 Builder.defineMacro("_LP64");
|
|
209 Builder.defineMacro("__LP64__");
|
|
210 }
|
|
211
|
173
|
212 std::string CodeModel = getTargetOpts().CodeModel;
|
|
213 if (CodeModel == "default")
|
|
214 CodeModel = "small";
|
|
215 for (char &c : CodeModel)
|
|
216 c = toupper(c);
|
|
217 Builder.defineMacro("__AARCH64_CMODEL_" + CodeModel + "__");
|
|
218
|
150
|
219 // ACLE predefines. Many can only have one possible value on v8 AArch64.
|
|
220 Builder.defineMacro("__ARM_ACLE", "200");
|
|
221 Builder.defineMacro("__ARM_ARCH", "8");
|
|
222 Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
|
|
223
|
|
224 Builder.defineMacro("__ARM_64BIT_STATE", "1");
|
|
225 Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
|
|
226 Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
|
|
227
|
|
228 Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
|
|
229 Builder.defineMacro("__ARM_FEATURE_FMA", "1");
|
|
230 Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
|
|
231 Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
|
|
232 Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility
|
|
233 Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
|
|
234 Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
|
|
235
|
|
236 Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
|
|
237
|
|
238 // 0xe implies support for half, single and double precision operations.
|
|
239 Builder.defineMacro("__ARM_FP", "0xE");
|
|
240
|
|
241 // PCS specifies this for SysV variants, which is all we support. Other ABIs
|
|
242 // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
|
|
243 Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
|
|
244 Builder.defineMacro("__ARM_FP16_ARGS", "1");
|
|
245
|
|
246 if (Opts.UnsafeFPMath)
|
|
247 Builder.defineMacro("__ARM_FP_FAST", "1");
|
|
248
|
|
249 Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
|
|
250 Twine(Opts.WCharSize ? Opts.WCharSize : 4));
|
|
251
|
|
252 Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
|
|
253
|
|
254 if (FPU & NeonMode) {
|
|
255 Builder.defineMacro("__ARM_NEON", "1");
|
|
256 // 64-bit NEON supports half, single and double precision operations.
|
|
257 Builder.defineMacro("__ARM_NEON_FP", "0xE");
|
|
258 }
|
|
259
|
|
260 if (HasCRC)
|
|
261 Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
|
|
262
|
|
263 if (HasCrypto)
|
|
264 Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
|
|
265
|
|
266 if (HasUnaligned)
|
|
267 Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
|
|
268
|
|
269 if ((FPU & NeonMode) && HasFullFP16)
|
|
270 Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
|
|
271 if (HasFullFP16)
|
|
272 Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
|
|
273
|
|
274 if (HasDotProd)
|
|
275 Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
|
|
276
|
|
277 if (HasMTE)
|
|
278 Builder.defineMacro("__ARM_FEATURE_MEMORY_TAGGING", "1");
|
|
279
|
|
280 if (HasTME)
|
|
281 Builder.defineMacro("__ARM_FEATURE_TME", "1");
|
|
282
|
173
|
283 if (HasMatMul)
|
|
284 Builder.defineMacro("__ARM_FEATURE_MATMUL_INT8", "1");
|
|
285
|
150
|
286 if ((FPU & NeonMode) && HasFP16FML)
|
|
287 Builder.defineMacro("__ARM_FEATURE_FP16FML", "1");
|
|
288
|
173
|
289 if (Opts.hasSignReturnAddress()) {
|
|
290 // Bitmask:
|
|
291 // 0: Protection using the A key
|
|
292 // 1: Protection using the B key
|
|
293 // 2: Protection including leaf functions
|
|
294 unsigned Value = 0;
|
|
295
|
|
296 if (Opts.isSignReturnAddressWithAKey())
|
|
297 Value |= (1 << 0);
|
|
298 else
|
|
299 Value |= (1 << 1);
|
|
300
|
|
301 if (Opts.isSignReturnAddressScopeAll())
|
|
302 Value |= (1 << 2);
|
|
303
|
|
304 Builder.defineMacro("__ARM_FEATURE_PAC_DEFAULT", std::to_string(Value));
|
|
305 }
|
|
306
|
|
307 if (Opts.BranchTargetEnforcement)
|
|
308 Builder.defineMacro("__ARM_FEATURE_BTI_DEFAULT", "1");
|
|
309
|
150
|
310 switch (ArchKind) {
|
|
311 default:
|
|
312 break;
|
|
313 case llvm::AArch64::ArchKind::ARMV8_1A:
|
|
314 getTargetDefinesARMV81A(Opts, Builder);
|
|
315 break;
|
|
316 case llvm::AArch64::ArchKind::ARMV8_2A:
|
|
317 getTargetDefinesARMV82A(Opts, Builder);
|
|
318 break;
|
|
319 case llvm::AArch64::ArchKind::ARMV8_3A:
|
|
320 getTargetDefinesARMV83A(Opts, Builder);
|
|
321 break;
|
|
322 case llvm::AArch64::ArchKind::ARMV8_4A:
|
|
323 getTargetDefinesARMV84A(Opts, Builder);
|
|
324 break;
|
|
325 case llvm::AArch64::ArchKind::ARMV8_5A:
|
|
326 getTargetDefinesARMV85A(Opts, Builder);
|
|
327 break;
|
173
|
328 case llvm::AArch64::ArchKind::ARMV8_6A:
|
|
329 getTargetDefinesARMV86A(Opts, Builder);
|
|
330 break;
|
150
|
331 }
|
|
332
|
|
333 // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
|
|
334 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
|
|
335 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
|
|
336 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
|
|
337 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
|
|
338 }
|
|
339
|
|
340 ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
|
|
341 return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
|
|
342 Builtin::FirstTSBuiltin);
|
|
343 }
|
|
344
|
|
345 bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
|
|
346 return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" ||
|
|
347 (Feature == "neon" && (FPU & NeonMode)) ||
|
|
348 (Feature == "sve" && (FPU & SveMode));
|
|
349 }
|
|
350
|
|
351 bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
|
|
352 DiagnosticsEngine &Diags) {
|
|
353 FPU = FPUMode;
|
|
354 HasCRC = false;
|
|
355 HasCrypto = false;
|
|
356 HasUnaligned = true;
|
|
357 HasFullFP16 = false;
|
|
358 HasDotProd = false;
|
|
359 HasFP16FML = false;
|
|
360 HasMTE = false;
|
|
361 HasTME = false;
|
173
|
362 HasMatMul = false;
|
150
|
363 ArchKind = llvm::AArch64::ArchKind::ARMV8A;
|
|
364
|
|
365 for (const auto &Feature : Features) {
|
|
366 if (Feature == "+neon")
|
|
367 FPU |= NeonMode;
|
|
368 if (Feature == "+sve")
|
|
369 FPU |= SveMode;
|
|
370 if (Feature == "+crc")
|
|
371 HasCRC = true;
|
|
372 if (Feature == "+crypto")
|
|
373 HasCrypto = true;
|
|
374 if (Feature == "+strict-align")
|
|
375 HasUnaligned = false;
|
|
376 if (Feature == "+v8.1a")
|
|
377 ArchKind = llvm::AArch64::ArchKind::ARMV8_1A;
|
|
378 if (Feature == "+v8.2a")
|
|
379 ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
|
|
380 if (Feature == "+v8.3a")
|
|
381 ArchKind = llvm::AArch64::ArchKind::ARMV8_3A;
|
|
382 if (Feature == "+v8.4a")
|
|
383 ArchKind = llvm::AArch64::ArchKind::ARMV8_4A;
|
|
384 if (Feature == "+v8.5a")
|
|
385 ArchKind = llvm::AArch64::ArchKind::ARMV8_5A;
|
173
|
386 if (Feature == "+v8.6a")
|
|
387 ArchKind = llvm::AArch64::ArchKind::ARMV8_6A;
|
150
|
388 if (Feature == "+fullfp16")
|
|
389 HasFullFP16 = true;
|
|
390 if (Feature == "+dotprod")
|
|
391 HasDotProd = true;
|
|
392 if (Feature == "+fp16fml")
|
|
393 HasFP16FML = true;
|
|
394 if (Feature == "+mte")
|
|
395 HasMTE = true;
|
|
396 if (Feature == "+tme")
|
|
397 HasTME = true;
|
173
|
398 if (Feature == "+i8mm")
|
|
399 HasMatMul = true;
|
150
|
400 }
|
|
401
|
|
402 setDataLayout();
|
|
403
|
|
404 return true;
|
|
405 }
|
|
406
|
|
407 TargetInfo::CallingConvCheckResult
|
|
408 AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
|
|
409 switch (CC) {
|
|
410 case CC_C:
|
|
411 case CC_Swift:
|
|
412 case CC_PreserveMost:
|
|
413 case CC_PreserveAll:
|
|
414 case CC_OpenCLKernel:
|
|
415 case CC_AArch64VectorCall:
|
|
416 case CC_Win64:
|
|
417 return CCCR_OK;
|
|
418 default:
|
|
419 return CCCR_Warning;
|
|
420 }
|
|
421 }
|
|
422
|
|
423 bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
|
|
424
|
|
425 TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
|
|
426 return TargetInfo::AArch64ABIBuiltinVaList;
|
|
427 }
|
|
428
|
|
429 const char *const AArch64TargetInfo::GCCRegNames[] = {
|
|
430 // 32-bit Integer registers
|
|
431 "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
|
|
432 "w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
|
|
433 "w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
|
|
434
|
|
435 // 64-bit Integer registers
|
|
436 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
|
|
437 "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
|
|
438 "x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
|
|
439
|
|
440 // 32-bit floating point regsisters
|
|
441 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
|
|
442 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
|
|
443 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
|
|
444
|
|
445 // 64-bit floating point regsisters
|
|
446 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
|
|
447 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
|
|
448 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
|
|
449
|
|
450 // Neon vector registers
|
|
451 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
|
|
452 "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
|
|
453 "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
|
|
454
|
|
455 // SVE vector registers
|
|
456 "z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8", "z9", "z10",
|
|
457 "z11", "z12", "z13", "z14", "z15", "z16", "z17", "z18", "z19", "z20", "z21",
|
|
458 "z22", "z23", "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31",
|
|
459
|
|
460 // SVE predicate registers
|
|
461 "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9", "p10",
|
|
462 "p11", "p12", "p13", "p14", "p15"
|
|
463 };
|
|
464
|
|
465 ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
|
|
466 return llvm::makeArrayRef(GCCRegNames);
|
|
467 }
|
|
468
|
|
469 const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
|
|
470 {{"w31"}, "wsp"},
|
|
471 {{"x31"}, "sp"},
|
|
472 // GCC rN registers are aliases of xN registers.
|
|
473 {{"r0"}, "x0"},
|
|
474 {{"r1"}, "x1"},
|
|
475 {{"r2"}, "x2"},
|
|
476 {{"r3"}, "x3"},
|
|
477 {{"r4"}, "x4"},
|
|
478 {{"r5"}, "x5"},
|
|
479 {{"r6"}, "x6"},
|
|
480 {{"r7"}, "x7"},
|
|
481 {{"r8"}, "x8"},
|
|
482 {{"r9"}, "x9"},
|
|
483 {{"r10"}, "x10"},
|
|
484 {{"r11"}, "x11"},
|
|
485 {{"r12"}, "x12"},
|
|
486 {{"r13"}, "x13"},
|
|
487 {{"r14"}, "x14"},
|
|
488 {{"r15"}, "x15"},
|
|
489 {{"r16"}, "x16"},
|
|
490 {{"r17"}, "x17"},
|
|
491 {{"r18"}, "x18"},
|
|
492 {{"r19"}, "x19"},
|
|
493 {{"r20"}, "x20"},
|
|
494 {{"r21"}, "x21"},
|
|
495 {{"r22"}, "x22"},
|
|
496 {{"r23"}, "x23"},
|
|
497 {{"r24"}, "x24"},
|
|
498 {{"r25"}, "x25"},
|
|
499 {{"r26"}, "x26"},
|
|
500 {{"r27"}, "x27"},
|
|
501 {{"r28"}, "x28"},
|
|
502 {{"r29", "x29"}, "fp"},
|
|
503 {{"r30", "x30"}, "lr"},
|
|
504 // The S/D/Q and W/X registers overlap, but aren't really aliases; we
|
|
505 // don't want to substitute one of these for a different-sized one.
|
|
506 };
|
|
507
|
|
508 ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
|
|
509 return llvm::makeArrayRef(GCCRegAliases);
|
|
510 }
|
|
511
|
|
512 bool AArch64TargetInfo::validateAsmConstraint(
|
|
513 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
|
|
514 switch (*Name) {
|
|
515 default:
|
|
516 return false;
|
|
517 case 'w': // Floating point and SIMD registers (V0-V31)
|
|
518 Info.setAllowsRegister();
|
|
519 return true;
|
|
520 case 'I': // Constant that can be used with an ADD instruction
|
|
521 case 'J': // Constant that can be used with a SUB instruction
|
|
522 case 'K': // Constant that can be used with a 32-bit logical instruction
|
|
523 case 'L': // Constant that can be used with a 64-bit logical instruction
|
|
524 case 'M': // Constant that can be used as a 32-bit MOV immediate
|
|
525 case 'N': // Constant that can be used as a 64-bit MOV immediate
|
|
526 case 'Y': // Floating point constant zero
|
|
527 case 'Z': // Integer constant zero
|
|
528 return true;
|
|
529 case 'Q': // A memory reference with base register and no offset
|
|
530 Info.setAllowsMemory();
|
|
531 return true;
|
|
532 case 'S': // A symbolic address
|
|
533 Info.setAllowsRegister();
|
|
534 return true;
|
|
535 case 'U':
|
173
|
536 if (Name[1] == 'p' && (Name[2] == 'l' || Name[2] == 'a')) {
|
|
537 // SVE predicate registers ("Upa"=P0-15, "Upl"=P0-P7)
|
|
538 Info.setAllowsRegister();
|
|
539 Name += 2;
|
|
540 return true;
|
|
541 }
|
150
|
542 // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
|
|
543 // Utf: A memory address suitable for ldp/stp in TF mode.
|
|
544 // Usa: An absolute symbolic address.
|
|
545 // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
|
173
|
546
|
|
547 // Better to return an error saying that it's an unrecognised constraint
|
|
548 // even if this is a valid constraint in gcc.
|
|
549 return false;
|
150
|
550 case 'z': // Zero register, wzr or xzr
|
|
551 Info.setAllowsRegister();
|
|
552 return true;
|
|
553 case 'x': // Floating point and SIMD registers (V0-V15)
|
|
554 Info.setAllowsRegister();
|
|
555 return true;
|
173
|
556 case 'y': // SVE registers (V0-V7)
|
|
557 Info.setAllowsRegister();
|
|
558 return true;
|
150
|
559 }
|
|
560 return false;
|
|
561 }
|
|
562
|
|
563 bool AArch64TargetInfo::validateConstraintModifier(
|
|
564 StringRef Constraint, char Modifier, unsigned Size,
|
|
565 std::string &SuggestedModifier) const {
|
|
566 // Strip off constraint modifiers.
|
|
567 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
|
|
568 Constraint = Constraint.substr(1);
|
|
569
|
|
570 switch (Constraint[0]) {
|
|
571 default:
|
|
572 return true;
|
|
573 case 'z':
|
|
574 case 'r': {
|
|
575 switch (Modifier) {
|
|
576 case 'x':
|
|
577 case 'w':
|
|
578 // For now assume that the person knows what they're
|
|
579 // doing with the modifier.
|
|
580 return true;
|
|
581 default:
|
|
582 // By default an 'r' constraint will be in the 'x'
|
|
583 // registers.
|
|
584 if (Size == 64)
|
|
585 return true;
|
|
586
|
|
587 SuggestedModifier = "w";
|
|
588 return false;
|
|
589 }
|
|
590 }
|
|
591 }
|
|
592 }
|
|
593
|
|
594 const char *AArch64TargetInfo::getClobbers() const { return ""; }
|
|
595
|
|
596 int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
|
|
597 if (RegNo == 0)
|
|
598 return 0;
|
|
599 if (RegNo == 1)
|
|
600 return 1;
|
|
601 return -1;
|
|
602 }
|
|
603
|
|
604 bool AArch64TargetInfo::hasInt128Type() const { return true; }
|
|
605
|
|
606 AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
|
|
607 const TargetOptions &Opts)
|
|
608 : AArch64TargetInfo(Triple, Opts) {}
|
|
609
|
|
610 void AArch64leTargetInfo::setDataLayout() {
|
|
611 if (getTriple().isOSBinFormatMachO()) {
|
|
612 if(getTriple().isArch32Bit())
|
|
613 resetDataLayout("e-m:o-p:32:32-i64:64-i128:128-n32:64-S128");
|
|
614 else
|
|
615 resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
|
|
616 } else
|
|
617 resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
|
|
618 }
|
|
619
|
|
620 void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
|
|
621 MacroBuilder &Builder) const {
|
|
622 Builder.defineMacro("__AARCH64EL__");
|
|
623 AArch64TargetInfo::getTargetDefines(Opts, Builder);
|
|
624 }
|
|
625
|
|
626 AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
|
|
627 const TargetOptions &Opts)
|
|
628 : AArch64TargetInfo(Triple, Opts) {}
|
|
629
|
|
630 void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
|
|
631 MacroBuilder &Builder) const {
|
|
632 Builder.defineMacro("__AARCH64EB__");
|
|
633 Builder.defineMacro("__AARCH_BIG_ENDIAN");
|
|
634 Builder.defineMacro("__ARM_BIG_ENDIAN");
|
|
635 AArch64TargetInfo::getTargetDefines(Opts, Builder);
|
|
636 }
|
|
637
|
|
638 void AArch64beTargetInfo::setDataLayout() {
|
|
639 assert(!getTriple().isOSBinFormatMachO());
|
|
640 resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
|
|
641 }
|
|
642
|
|
643 WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
|
|
644 const TargetOptions &Opts)
|
|
645 : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
|
|
646
|
|
647 // This is an LLP64 platform.
|
|
648 // int:4, long:4, long long:8, long double:8.
|
|
649 IntWidth = IntAlign = 32;
|
|
650 LongWidth = LongAlign = 32;
|
|
651 DoubleAlign = LongLongAlign = 64;
|
|
652 LongDoubleWidth = LongDoubleAlign = 64;
|
|
653 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
|
|
654 IntMaxType = SignedLongLong;
|
|
655 Int64Type = SignedLongLong;
|
|
656 SizeType = UnsignedLongLong;
|
|
657 PtrDiffType = SignedLongLong;
|
|
658 IntPtrType = SignedLongLong;
|
|
659 }
|
|
660
|
|
661 void WindowsARM64TargetInfo::setDataLayout() {
|
|
662 resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
|
|
663 }
|
|
664
|
|
665 TargetInfo::BuiltinVaListKind
|
|
666 WindowsARM64TargetInfo::getBuiltinVaListKind() const {
|
|
667 return TargetInfo::CharPtrBuiltinVaList;
|
|
668 }
|
|
669
|
|
670 TargetInfo::CallingConvCheckResult
|
|
671 WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
|
|
672 switch (CC) {
|
|
673 case CC_X86StdCall:
|
|
674 case CC_X86ThisCall:
|
|
675 case CC_X86FastCall:
|
|
676 case CC_X86VectorCall:
|
|
677 return CCCR_Ignore;
|
|
678 case CC_C:
|
|
679 case CC_OpenCLKernel:
|
|
680 case CC_PreserveMost:
|
|
681 case CC_PreserveAll:
|
|
682 case CC_Swift:
|
|
683 case CC_Win64:
|
|
684 return CCCR_OK;
|
|
685 default:
|
|
686 return CCCR_Warning;
|
|
687 }
|
|
688 }
|
|
689
|
|
690 MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
|
|
691 const TargetOptions &Opts)
|
|
692 : WindowsARM64TargetInfo(Triple, Opts) {
|
|
693 TheCXXABI.set(TargetCXXABI::Microsoft);
|
|
694 }
|
|
695
|
|
696 void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
|
|
697 MacroBuilder &Builder) const {
|
|
698 WindowsARM64TargetInfo::getTargetDefines(Opts, Builder);
|
|
699 Builder.defineMacro("_M_ARM64", "1");
|
|
700 }
|
|
701
|
|
702 TargetInfo::CallingConvKind
|
|
703 MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
|
|
704 return CCK_MicrosoftWin64;
|
|
705 }
|
|
706
|
|
707 unsigned MicrosoftARM64TargetInfo::getMinGlobalAlign(uint64_t TypeSize) const {
|
|
708 unsigned Align = WindowsARM64TargetInfo::getMinGlobalAlign(TypeSize);
|
|
709
|
|
710 // MSVC does size based alignment for arm64 based on alignment section in
|
|
711 // below document, replicate that to keep alignment consistent with object
|
|
712 // files compiled by MSVC.
|
|
713 // https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions
|
|
714 if (TypeSize >= 512) { // TypeSize >= 64 bytes
|
|
715 Align = std::max(Align, 128u); // align type at least 16 bytes
|
|
716 } else if (TypeSize >= 64) { // TypeSize >= 8 bytes
|
|
717 Align = std::max(Align, 64u); // align type at least 8 butes
|
|
718 } else if (TypeSize >= 16) { // TypeSize >= 2 bytes
|
|
719 Align = std::max(Align, 32u); // align type at least 4 bytes
|
|
720 }
|
|
721 return Align;
|
|
722 }
|
|
723
|
|
724 MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
|
|
725 const TargetOptions &Opts)
|
|
726 : WindowsARM64TargetInfo(Triple, Opts) {
|
|
727 TheCXXABI.set(TargetCXXABI::GenericAArch64);
|
|
728 }
|
|
729
|
|
730 DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
|
|
731 const TargetOptions &Opts)
|
|
732 : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
|
|
733 Int64Type = SignedLongLong;
|
|
734 if (getTriple().isArch32Bit())
|
|
735 IntMaxType = SignedLongLong;
|
|
736
|
|
737 WCharType = SignedInt;
|
|
738 UseSignedCharForObjCBool = false;
|
|
739
|
|
740 LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
|
|
741 LongDoubleFormat = &llvm::APFloat::IEEEdouble();
|
|
742
|
|
743 UseZeroLengthBitfieldAlignment = false;
|
|
744
|
|
745 if (getTriple().isArch32Bit()) {
|
|
746 UseBitFieldTypeAlignment = false;
|
|
747 ZeroLengthBitfieldBoundary = 32;
|
|
748 UseZeroLengthBitfieldAlignment = true;
|
|
749 TheCXXABI.set(TargetCXXABI::WatchOS);
|
|
750 } else
|
|
751 TheCXXABI.set(TargetCXXABI::iOS64);
|
|
752 }
|
|
753
|
|
754 void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
|
|
755 const llvm::Triple &Triple,
|
|
756 MacroBuilder &Builder) const {
|
|
757 Builder.defineMacro("__AARCH64_SIMD__");
|
|
758 if (Triple.isArch32Bit())
|
|
759 Builder.defineMacro("__ARM64_ARCH_8_32__");
|
|
760 else
|
|
761 Builder.defineMacro("__ARM64_ARCH_8__");
|
|
762 Builder.defineMacro("__ARM_NEON__");
|
|
763 Builder.defineMacro("__LITTLE_ENDIAN__");
|
|
764 Builder.defineMacro("__REGISTER_PREFIX__", "");
|
|
765 Builder.defineMacro("__arm64", "1");
|
|
766 Builder.defineMacro("__arm64__", "1");
|
|
767
|
|
768 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
|
|
769 }
|
|
770
|
|
771 TargetInfo::BuiltinVaListKind
|
|
772 DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
|
|
773 return TargetInfo::CharPtrBuiltinVaList;
|
|
774 }
|
|
775
|
|
776 // 64-bit RenderScript is aarch64
|
|
777 RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
|
|
778 const TargetOptions &Opts)
|
|
779 : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
|
|
780 Triple.getOSName(),
|
|
781 Triple.getEnvironmentName()),
|
|
782 Opts) {
|
|
783 IsRenderScriptTarget = true;
|
|
784 }
|
|
785
|
|
786 void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
|
|
787 MacroBuilder &Builder) const {
|
|
788 Builder.defineMacro("__RENDERSCRIPT__");
|
|
789 AArch64leTargetInfo::getTargetDefines(Opts, Builder);
|
|
790 }
|