1 | //===--- ARM.cpp - Implement ARM 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 ARM TargetInfo objects. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "ARM.h" |
14 | #include "clang/Basic/Builtins.h" |
15 | #include "clang/Basic/Diagnostic.h" |
16 | #include "clang/Basic/TargetBuiltins.h" |
17 | #include "llvm/ADT/StringExtras.h" |
18 | #include "llvm/ADT/StringRef.h" |
19 | #include "llvm/ADT/StringSwitch.h" |
20 | #include "llvm/TargetParser/ARMTargetParser.h" |
21 | |
22 | using namespace clang; |
23 | using namespace clang::targets; |
24 | |
25 | void ARMTargetInfo::setABIAAPCS() { |
26 | IsAAPCS = true; |
27 | |
28 | DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64; |
29 | BFloat16Width = BFloat16Align = 16; |
30 | BFloat16Format = &llvm::APFloat::BFloat(); |
31 | |
32 | const llvm::Triple &T = getTriple(); |
33 | |
34 | bool IsNetBSD = T.isOSNetBSD(); |
35 | bool IsOpenBSD = T.isOSOpenBSD(); |
36 | if (!T.isOSWindows() && !IsNetBSD && !IsOpenBSD) |
37 | WCharType = UnsignedInt; |
38 | |
39 | UseBitFieldTypeAlignment = true; |
40 | |
41 | ZeroLengthBitfieldBoundary = 0; |
42 | |
43 | // Thumb1 add sp, #imm requires the immediate value be multiple of 4, |
44 | // so set preferred for small types to 32. |
45 | if (T.isOSBinFormatMachO()) { |
46 | resetDataLayout(DL: BigEndian |
47 | ? "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" |
48 | : "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" , |
49 | UserLabelPrefix: "_" ); |
50 | } else if (T.isOSWindows()) { |
51 | assert(!BigEndian && "Windows on ARM does not support big endian" ); |
52 | resetDataLayout(DL: "e" |
53 | "-m:w" |
54 | "-p:32:32" |
55 | "-Fi8" |
56 | "-i64:64" |
57 | "-v128:64:128" |
58 | "-a:0:32" |
59 | "-n32" |
60 | "-S64" ); |
61 | } else if (T.isOSNaCl()) { |
62 | assert(!BigEndian && "NaCl on ARM does not support big endian" ); |
63 | resetDataLayout(DL: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S128" ); |
64 | } else { |
65 | resetDataLayout(DL: BigEndian |
66 | ? "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" |
67 | : "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" ); |
68 | } |
69 | |
70 | // FIXME: Enumerated types are variable width in straight AAPCS. |
71 | } |
72 | |
73 | void ARMTargetInfo::setABIAPCS(bool IsAAPCS16) { |
74 | const llvm::Triple &T = getTriple(); |
75 | |
76 | IsAAPCS = false; |
77 | |
78 | if (IsAAPCS16) |
79 | DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64; |
80 | else |
81 | DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32; |
82 | BFloat16Width = BFloat16Align = 16; |
83 | BFloat16Format = &llvm::APFloat::BFloat(); |
84 | |
85 | WCharType = SignedInt; |
86 | |
87 | // Do not respect the alignment of bit-field types when laying out |
88 | // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc. |
89 | UseBitFieldTypeAlignment = false; |
90 | |
91 | /// gcc forces the alignment to 4 bytes, regardless of the type of the |
92 | /// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in |
93 | /// gcc. |
94 | ZeroLengthBitfieldBoundary = 32; |
95 | |
96 | if (T.isOSBinFormatMachO() && IsAAPCS16) { |
97 | assert(!BigEndian && "AAPCS16 does not support big-endian" ); |
98 | resetDataLayout(DL: "e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128" , UserLabelPrefix: "_" ); |
99 | } else if (T.isOSBinFormatMachO()) |
100 | resetDataLayout( |
101 | DL: BigEndian |
102 | ? "E-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" |
103 | : "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" , |
104 | UserLabelPrefix: "_" ); |
105 | else |
106 | resetDataLayout( |
107 | DL: BigEndian |
108 | ? "E-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" |
109 | : "e-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" ); |
110 | |
111 | // FIXME: Override "preferred align" for double and long long. |
112 | } |
113 | |
114 | void ARMTargetInfo::setArchInfo() { |
115 | StringRef ArchName = getTriple().getArchName(); |
116 | |
117 | ArchISA = llvm::ARM::parseArchISA(Arch: ArchName); |
118 | CPU = std::string(llvm::ARM::getDefaultCPU(Arch: ArchName)); |
119 | llvm::ARM::ArchKind AK = llvm::ARM::parseArch(Arch: ArchName); |
120 | if (AK != llvm::ARM::ArchKind::INVALID) |
121 | ArchKind = AK; |
122 | setArchInfo(ArchKind); |
123 | } |
124 | |
125 | void ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) { |
126 | StringRef SubArch; |
127 | |
128 | // cache TargetParser info |
129 | ArchKind = Kind; |
130 | SubArch = llvm::ARM::getSubArch(AK: ArchKind); |
131 | ArchProfile = llvm::ARM::parseArchProfile(Arch: SubArch); |
132 | ArchVersion = llvm::ARM::parseArchVersion(Arch: SubArch); |
133 | |
134 | // cache CPU related strings |
135 | CPUAttr = getCPUAttr(); |
136 | CPUProfile = getCPUProfile(); |
137 | } |
138 | |
139 | void ARMTargetInfo::setAtomic() { |
140 | // when triple does not specify a sub arch, |
141 | // then we are not using inline atomics |
142 | bool ShouldUseInlineAtomic = |
143 | (ArchISA == llvm::ARM::ISAKind::ARM && ArchVersion >= 6) || |
144 | (ArchISA == llvm::ARM::ISAKind::THUMB && ArchVersion >= 7); |
145 | // Cortex M does not support 8 byte atomics, while general Thumb2 does. |
146 | if (ArchProfile == llvm::ARM::ProfileKind::M) { |
147 | MaxAtomicPromoteWidth = 32; |
148 | if (ShouldUseInlineAtomic) |
149 | MaxAtomicInlineWidth = 32; |
150 | } else { |
151 | MaxAtomicPromoteWidth = 64; |
152 | if (ShouldUseInlineAtomic) |
153 | MaxAtomicInlineWidth = 64; |
154 | } |
155 | } |
156 | |
157 | bool ARMTargetInfo::hasMVE() const { |
158 | return ArchKind == llvm::ARM::ArchKind::ARMV8_1MMainline && MVE != 0; |
159 | } |
160 | |
161 | bool ARMTargetInfo::hasMVEFloat() const { |
162 | return hasMVE() && (MVE & MVE_FP); |
163 | } |
164 | |
165 | bool ARMTargetInfo::hasCDE() const { return getARMCDECoprocMask() != 0; } |
166 | |
167 | bool ARMTargetInfo::isThumb() const { |
168 | return ArchISA == llvm::ARM::ISAKind::THUMB; |
169 | } |
170 | |
171 | bool ARMTargetInfo::supportsThumb() const { |
172 | return CPUAttr.count(C: 'T') || ArchVersion >= 6; |
173 | } |
174 | |
175 | bool ARMTargetInfo::supportsThumb2() const { |
176 | return CPUAttr.equals(RHS: "6T2" ) || |
177 | (ArchVersion >= 7 && !CPUAttr.equals(RHS: "8M_BASE" )); |
178 | } |
179 | |
180 | StringRef ARMTargetInfo::getCPUAttr() const { |
181 | // For most sub-arches, the build attribute CPU name is enough. |
182 | // For Cortex variants, it's slightly different. |
183 | switch (ArchKind) { |
184 | default: |
185 | return llvm::ARM::getCPUAttr(AK: ArchKind); |
186 | case llvm::ARM::ArchKind::ARMV6M: |
187 | return "6M" ; |
188 | case llvm::ARM::ArchKind::ARMV7S: |
189 | return "7S" ; |
190 | case llvm::ARM::ArchKind::ARMV7A: |
191 | return "7A" ; |
192 | case llvm::ARM::ArchKind::ARMV7R: |
193 | return "7R" ; |
194 | case llvm::ARM::ArchKind::ARMV7M: |
195 | return "7M" ; |
196 | case llvm::ARM::ArchKind::ARMV7EM: |
197 | return "7EM" ; |
198 | case llvm::ARM::ArchKind::ARMV7VE: |
199 | return "7VE" ; |
200 | case llvm::ARM::ArchKind::ARMV8A: |
201 | return "8A" ; |
202 | case llvm::ARM::ArchKind::ARMV8_1A: |
203 | return "8_1A" ; |
204 | case llvm::ARM::ArchKind::ARMV8_2A: |
205 | return "8_2A" ; |
206 | case llvm::ARM::ArchKind::ARMV8_3A: |
207 | return "8_3A" ; |
208 | case llvm::ARM::ArchKind::ARMV8_4A: |
209 | return "8_4A" ; |
210 | case llvm::ARM::ArchKind::ARMV8_5A: |
211 | return "8_5A" ; |
212 | case llvm::ARM::ArchKind::ARMV8_6A: |
213 | return "8_6A" ; |
214 | case llvm::ARM::ArchKind::ARMV8_7A: |
215 | return "8_7A" ; |
216 | case llvm::ARM::ArchKind::ARMV8_8A: |
217 | return "8_8A" ; |
218 | case llvm::ARM::ArchKind::ARMV8_9A: |
219 | return "8_9A" ; |
220 | case llvm::ARM::ArchKind::ARMV9A: |
221 | return "9A" ; |
222 | case llvm::ARM::ArchKind::ARMV9_1A: |
223 | return "9_1A" ; |
224 | case llvm::ARM::ArchKind::ARMV9_2A: |
225 | return "9_2A" ; |
226 | case llvm::ARM::ArchKind::ARMV9_3A: |
227 | return "9_3A" ; |
228 | case llvm::ARM::ArchKind::ARMV9_4A: |
229 | return "9_4A" ; |
230 | case llvm::ARM::ArchKind::ARMV9_5A: |
231 | return "9_5A" ; |
232 | case llvm::ARM::ArchKind::ARMV8MBaseline: |
233 | return "8M_BASE" ; |
234 | case llvm::ARM::ArchKind::ARMV8MMainline: |
235 | return "8M_MAIN" ; |
236 | case llvm::ARM::ArchKind::ARMV8R: |
237 | return "8R" ; |
238 | case llvm::ARM::ArchKind::ARMV8_1MMainline: |
239 | return "8_1M_MAIN" ; |
240 | } |
241 | } |
242 | |
243 | StringRef ARMTargetInfo::getCPUProfile() const { |
244 | switch (ArchProfile) { |
245 | case llvm::ARM::ProfileKind::A: |
246 | return "A" ; |
247 | case llvm::ARM::ProfileKind::R: |
248 | return "R" ; |
249 | case llvm::ARM::ProfileKind::M: |
250 | return "M" ; |
251 | default: |
252 | return "" ; |
253 | } |
254 | } |
255 | |
256 | ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple, |
257 | const TargetOptions &Opts) |
258 | : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0), |
259 | HW_FP(0) { |
260 | bool IsFreeBSD = Triple.isOSFreeBSD(); |
261 | bool IsOpenBSD = Triple.isOSOpenBSD(); |
262 | bool IsNetBSD = Triple.isOSNetBSD(); |
263 | bool IsHaiku = Triple.isOSHaiku(); |
264 | bool IsOHOS = Triple.isOHOSFamily(); |
265 | |
266 | // FIXME: the isOSBinFormatMachO is a workaround for identifying a Darwin-like |
267 | // environment where size_t is `unsigned long` rather than `unsigned int` |
268 | |
269 | PtrDiffType = IntPtrType = |
270 | (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD || |
271 | IsNetBSD) |
272 | ? SignedLong |
273 | : SignedInt; |
274 | |
275 | SizeType = (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD || |
276 | IsNetBSD) |
277 | ? UnsignedLong |
278 | : UnsignedInt; |
279 | |
280 | // ptrdiff_t is inconsistent on Darwin |
281 | if ((Triple.isOSDarwin() || Triple.isOSBinFormatMachO()) && |
282 | !Triple.isWatchABI()) |
283 | PtrDiffType = SignedInt; |
284 | |
285 | // Cache arch related info. |
286 | setArchInfo(); |
287 | |
288 | // {} in inline assembly are neon specifiers, not assembly variant |
289 | // specifiers. |
290 | NoAsmVariants = true; |
291 | |
292 | // FIXME: This duplicates code from the driver that sets the -target-abi |
293 | // option - this code is used if -target-abi isn't passed and should |
294 | // be unified in some way. |
295 | if (Triple.isOSBinFormatMachO()) { |
296 | // The backend is hardwired to assume AAPCS for M-class processors, ensure |
297 | // the frontend matches that. |
298 | if (Triple.getEnvironment() == llvm::Triple::EABI || |
299 | Triple.getOS() == llvm::Triple::UnknownOS || |
300 | ArchProfile == llvm::ARM::ProfileKind::M) { |
301 | setABI("aapcs" ); |
302 | } else if (Triple.isWatchABI()) { |
303 | setABI("aapcs16" ); |
304 | } else { |
305 | setABI("apcs-gnu" ); |
306 | } |
307 | } else if (Triple.isOSWindows()) { |
308 | // FIXME: this is invalid for WindowsCE |
309 | setABI("aapcs" ); |
310 | } else { |
311 | // Select the default based on the platform. |
312 | switch (Triple.getEnvironment()) { |
313 | case llvm::Triple::Android: |
314 | case llvm::Triple::GNUEABI: |
315 | case llvm::Triple::GNUEABIHF: |
316 | case llvm::Triple::MuslEABI: |
317 | case llvm::Triple::MuslEABIHF: |
318 | case llvm::Triple::OpenHOS: |
319 | setABI("aapcs-linux" ); |
320 | break; |
321 | case llvm::Triple::EABIHF: |
322 | case llvm::Triple::EABI: |
323 | setABI("aapcs" ); |
324 | break; |
325 | case llvm::Triple::GNU: |
326 | setABI("apcs-gnu" ); |
327 | break; |
328 | default: |
329 | if (IsNetBSD) |
330 | setABI("apcs-gnu" ); |
331 | else if (IsFreeBSD || IsOpenBSD || IsHaiku || IsOHOS) |
332 | setABI("aapcs-linux" ); |
333 | else |
334 | setABI("aapcs" ); |
335 | break; |
336 | } |
337 | } |
338 | |
339 | // ARM targets default to using the ARM C++ ABI. |
340 | TheCXXABI.set(TargetCXXABI::GenericARM); |
341 | |
342 | // ARM has atomics up to 8 bytes |
343 | setAtomic(); |
344 | |
345 | // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS) |
346 | // as well the default alignment |
347 | if (IsAAPCS && !Triple.isAndroid()) |
348 | DefaultAlignForAttributeAligned = MaxVectorAlign = 64; |
349 | |
350 | // Do force alignment of members that follow zero length bitfields. If |
351 | // the alignment of the zero-length bitfield is greater than the member |
352 | // that follows it, `bar', `bar' will be aligned as the type of the |
353 | // zero length bitfield. |
354 | UseZeroLengthBitfieldAlignment = true; |
355 | |
356 | if (Triple.getOS() == llvm::Triple::Linux || |
357 | Triple.getOS() == llvm::Triple::UnknownOS) |
358 | this->MCountName = Opts.EABIVersion == llvm::EABI::GNU |
359 | ? "llvm.arm.gnu.eabi.mcount" |
360 | : "\01mcount" ; |
361 | |
362 | SoftFloatABI = llvm::is_contained(Range: Opts.FeaturesAsWritten, Element: "+soft-float-abi" ); |
363 | } |
364 | |
365 | StringRef ARMTargetInfo::getABI() const { return ABI; } |
366 | |
367 | bool ARMTargetInfo::setABI(const std::string &Name) { |
368 | ABI = Name; |
369 | |
370 | // The defaults (above) are for AAPCS, check if we need to change them. |
371 | // |
372 | // FIXME: We need support for -meabi... we could just mangle it into the |
373 | // name. |
374 | if (Name == "apcs-gnu" || Name == "aapcs16" ) { |
375 | setABIAPCS(Name == "aapcs16" ); |
376 | return true; |
377 | } |
378 | if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux" ) { |
379 | setABIAAPCS(); |
380 | return true; |
381 | } |
382 | return false; |
383 | } |
384 | |
385 | bool ARMTargetInfo::isBranchProtectionSupportedArch(StringRef Arch) const { |
386 | llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(CPU: Arch); |
387 | if (CPUArch == llvm::ARM::ArchKind::INVALID) |
388 | CPUArch = llvm::ARM::parseArch(Arch: getTriple().getArchName()); |
389 | |
390 | if (CPUArch == llvm::ARM::ArchKind::INVALID) |
391 | return false; |
392 | |
393 | StringRef ArchFeature = llvm::ARM::getArchName(AK: CPUArch); |
394 | auto a = |
395 | llvm::Triple(ArchFeature, getTriple().getVendorName(), |
396 | getTriple().getOSName(), getTriple().getEnvironmentName()); |
397 | |
398 | StringRef SubArch = llvm::ARM::getSubArch(AK: CPUArch); |
399 | llvm::ARM::ProfileKind Profile = llvm::ARM::parseArchProfile(Arch: SubArch); |
400 | return a.isArmT32() && (Profile == llvm::ARM::ProfileKind::M); |
401 | } |
402 | |
403 | bool ARMTargetInfo::validateBranchProtection(StringRef Spec, StringRef Arch, |
404 | BranchProtectionInfo &BPI, |
405 | StringRef &Err) const { |
406 | llvm::ARM::ParsedBranchProtection PBP; |
407 | if (!llvm::ARM::parseBranchProtection(Spec, PBP, Err)) |
408 | return false; |
409 | |
410 | if (!isBranchProtectionSupportedArch(Arch)) |
411 | return false; |
412 | |
413 | BPI.SignReturnAddr = |
414 | llvm::StringSwitch<LangOptions::SignReturnAddressScopeKind>(PBP.Scope) |
415 | .Case(S: "non-leaf" , Value: LangOptions::SignReturnAddressScopeKind::NonLeaf) |
416 | .Case(S: "all" , Value: LangOptions::SignReturnAddressScopeKind::All) |
417 | .Default(Value: LangOptions::SignReturnAddressScopeKind::None); |
418 | |
419 | // Don't care for the sign key, beyond issuing a warning. |
420 | if (PBP.Key == "b_key" ) |
421 | Err = "b-key" ; |
422 | BPI.SignKey = LangOptions::SignReturnAddressKeyKind::AKey; |
423 | |
424 | BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement; |
425 | BPI.BranchProtectionPAuthLR = PBP.BranchProtectionPAuthLR; |
426 | return true; |
427 | } |
428 | |
429 | // FIXME: This should be based on Arch attributes, not CPU names. |
430 | bool ARMTargetInfo::initFeatureMap( |
431 | llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, |
432 | const std::vector<std::string> &FeaturesVec) const { |
433 | |
434 | std::string ArchFeature; |
435 | std::vector<StringRef> TargetFeatures; |
436 | llvm::ARM::ArchKind Arch = llvm::ARM::parseArch(Arch: getTriple().getArchName()); |
437 | |
438 | // Map the base architecture to an appropriate target feature, so we don't |
439 | // rely on the target triple. |
440 | llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(CPU); |
441 | if (CPUArch == llvm::ARM::ArchKind::INVALID) |
442 | CPUArch = Arch; |
443 | if (CPUArch != llvm::ARM::ArchKind::INVALID) { |
444 | ArchFeature = ("+" + llvm::ARM::getArchName(AK: CPUArch)).str(); |
445 | TargetFeatures.push_back(x: ArchFeature); |
446 | |
447 | // These features are added to allow arm_neon.h target(..) attributes to |
448 | // match with both arm and aarch64. We need to add all previous architecture |
449 | // versions, so that "8.6" also allows "8.1" functions. In case of v9.x the |
450 | // v8.x counterparts are added too. We only need these for anything > 8.0-A. |
451 | for (llvm::ARM::ArchKind I = llvm::ARM::convertV9toV8(AK: CPUArch); |
452 | I != llvm::ARM::ArchKind::INVALID; --I) |
453 | Features[llvm::ARM::getSubArch(AK: I)] = true; |
454 | if (CPUArch > llvm::ARM::ArchKind::ARMV8A && |
455 | CPUArch <= llvm::ARM::ArchKind::ARMV9_3A) |
456 | for (llvm::ARM::ArchKind I = CPUArch; I != llvm::ARM::ArchKind::INVALID; |
457 | --I) |
458 | Features[llvm::ARM::getSubArch(AK: I)] = true; |
459 | } |
460 | |
461 | // get default FPU features |
462 | llvm::ARM::FPUKind FPUKind = llvm::ARM::getDefaultFPU(CPU, AK: Arch); |
463 | llvm::ARM::getFPUFeatures(FPUKind, Features&: TargetFeatures); |
464 | |
465 | // get default Extension features |
466 | uint64_t Extensions = llvm::ARM::getDefaultExtensions(CPU, AK: Arch); |
467 | llvm::ARM::getExtensionFeatures(Extensions, Features&: TargetFeatures); |
468 | |
469 | for (auto Feature : TargetFeatures) |
470 | if (Feature[0] == '+') |
471 | Features[Feature.drop_front(N: 1)] = true; |
472 | |
473 | // Enable or disable thumb-mode explicitly per function to enable mixed |
474 | // ARM and Thumb code generation. |
475 | if (isThumb()) |
476 | Features["thumb-mode" ] = true; |
477 | else |
478 | Features["thumb-mode" ] = false; |
479 | |
480 | // Convert user-provided arm and thumb GNU target attributes to |
481 | // [-|+]thumb-mode target features respectively. |
482 | std::vector<std::string> UpdatedFeaturesVec; |
483 | for (const auto &Feature : FeaturesVec) { |
484 | // Skip soft-float-abi; it's something we only use to initialize a bit of |
485 | // class state, and is otherwise unrecognized. |
486 | if (Feature == "+soft-float-abi" ) |
487 | continue; |
488 | |
489 | StringRef FixedFeature; |
490 | if (Feature == "+arm" ) |
491 | FixedFeature = "-thumb-mode" ; |
492 | else if (Feature == "+thumb" ) |
493 | FixedFeature = "+thumb-mode" ; |
494 | else |
495 | FixedFeature = Feature; |
496 | UpdatedFeaturesVec.push_back(x: FixedFeature.str()); |
497 | } |
498 | |
499 | return TargetInfo::initFeatureMap(Features, Diags, CPU, FeatureVec: UpdatedFeaturesVec); |
500 | } |
501 | |
502 | |
503 | bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, |
504 | DiagnosticsEngine &Diags) { |
505 | FPU = 0; |
506 | MVE = 0; |
507 | CRC = 0; |
508 | Crypto = 0; |
509 | SHA2 = 0; |
510 | AES = 0; |
511 | DSP = 0; |
512 | HasUnalignedAccess = true; |
513 | SoftFloat = false; |
514 | // Note that SoftFloatABI is initialized in our constructor. |
515 | HWDiv = 0; |
516 | DotProd = 0; |
517 | HasMatMul = 0; |
518 | HasPAC = 0; |
519 | HasBTI = 0; |
520 | HasFloat16 = true; |
521 | ARMCDECoprocMask = 0; |
522 | HasBFloat16 = false; |
523 | HasFullBFloat16 = false; |
524 | FPRegsDisabled = false; |
525 | |
526 | // This does not diagnose illegal cases like having both |
527 | // "+vfpv2" and "+vfpv3" or having "+neon" and "-fp64". |
528 | for (const auto &Feature : Features) { |
529 | if (Feature == "+soft-float" ) { |
530 | SoftFloat = true; |
531 | } else if (Feature == "+vfp2sp" || Feature == "+vfp2" ) { |
532 | FPU |= VFP2FPU; |
533 | HW_FP |= HW_FP_SP; |
534 | if (Feature == "+vfp2" ) |
535 | HW_FP |= HW_FP_DP; |
536 | } else if (Feature == "+vfp3sp" || Feature == "+vfp3d16sp" || |
537 | Feature == "+vfp3" || Feature == "+vfp3d16" ) { |
538 | FPU |= VFP3FPU; |
539 | HW_FP |= HW_FP_SP; |
540 | if (Feature == "+vfp3" || Feature == "+vfp3d16" ) |
541 | HW_FP |= HW_FP_DP; |
542 | } else if (Feature == "+vfp4sp" || Feature == "+vfp4d16sp" || |
543 | Feature == "+vfp4" || Feature == "+vfp4d16" ) { |
544 | FPU |= VFP4FPU; |
545 | HW_FP |= HW_FP_SP | HW_FP_HP; |
546 | if (Feature == "+vfp4" || Feature == "+vfp4d16" ) |
547 | HW_FP |= HW_FP_DP; |
548 | } else if (Feature == "+fp-armv8sp" || Feature == "+fp-armv8d16sp" || |
549 | Feature == "+fp-armv8" || Feature == "+fp-armv8d16" ) { |
550 | FPU |= FPARMV8; |
551 | HW_FP |= HW_FP_SP | HW_FP_HP; |
552 | if (Feature == "+fp-armv8" || Feature == "+fp-armv8d16" ) |
553 | HW_FP |= HW_FP_DP; |
554 | } else if (Feature == "+neon" ) { |
555 | FPU |= NeonFPU; |
556 | HW_FP |= HW_FP_SP; |
557 | } else if (Feature == "+hwdiv" ) { |
558 | HWDiv |= HWDivThumb; |
559 | } else if (Feature == "+hwdiv-arm" ) { |
560 | HWDiv |= HWDivARM; |
561 | } else if (Feature == "+crc" ) { |
562 | CRC = 1; |
563 | } else if (Feature == "+crypto" ) { |
564 | Crypto = 1; |
565 | } else if (Feature == "+sha2" ) { |
566 | SHA2 = 1; |
567 | } else if (Feature == "+aes" ) { |
568 | AES = 1; |
569 | } else if (Feature == "+dsp" ) { |
570 | DSP = 1; |
571 | } else if (Feature == "+fp64" ) { |
572 | HW_FP |= HW_FP_DP; |
573 | } else if (Feature == "+8msecext" ) { |
574 | if (CPUProfile != "M" || ArchVersion != 8) { |
575 | Diags.Report(diag::err_target_unsupported_mcmse) << CPU; |
576 | return false; |
577 | } |
578 | } else if (Feature == "+strict-align" ) { |
579 | HasUnalignedAccess = false; |
580 | } else if (Feature == "+fp16" ) { |
581 | HW_FP |= HW_FP_HP; |
582 | } else if (Feature == "+fullfp16" ) { |
583 | HasLegalHalfType = true; |
584 | } else if (Feature == "+dotprod" ) { |
585 | DotProd = true; |
586 | } else if (Feature == "+mve" ) { |
587 | MVE |= MVE_INT; |
588 | } else if (Feature == "+mve.fp" ) { |
589 | HasLegalHalfType = true; |
590 | FPU |= FPARMV8; |
591 | MVE |= MVE_INT | MVE_FP; |
592 | HW_FP |= HW_FP_SP | HW_FP_HP; |
593 | } else if (Feature == "+i8mm" ) { |
594 | HasMatMul = 1; |
595 | } else if (Feature.size() == strlen(s: "+cdecp0" ) && Feature >= "+cdecp0" && |
596 | Feature <= "+cdecp7" ) { |
597 | unsigned Coproc = Feature.back() - '0'; |
598 | ARMCDECoprocMask |= (1U << Coproc); |
599 | } else if (Feature == "+bf16" ) { |
600 | HasBFloat16 = true; |
601 | } else if (Feature == "-fpregs" ) { |
602 | FPRegsDisabled = true; |
603 | } else if (Feature == "+pacbti" ) { |
604 | HasPAC = 1; |
605 | HasBTI = 1; |
606 | } else if (Feature == "+fullbf16" ) { |
607 | HasFullBFloat16 = true; |
608 | } |
609 | } |
610 | |
611 | HalfArgsAndReturns = true; |
612 | |
613 | switch (ArchVersion) { |
614 | case 6: |
615 | if (ArchProfile == llvm::ARM::ProfileKind::M) |
616 | LDREX = 0; |
617 | else if (ArchKind == llvm::ARM::ArchKind::ARMV6K) |
618 | LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; |
619 | else |
620 | LDREX = LDREX_W; |
621 | break; |
622 | case 7: |
623 | if (ArchProfile == llvm::ARM::ProfileKind::M) |
624 | LDREX = LDREX_W | LDREX_H | LDREX_B; |
625 | else |
626 | LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; |
627 | break; |
628 | case 8: |
629 | case 9: |
630 | LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; |
631 | } |
632 | |
633 | if (!(FPU & NeonFPU) && FPMath == FP_Neon) { |
634 | Diags.Report(diag::err_target_unsupported_fpmath) << "neon" ; |
635 | return false; |
636 | } |
637 | |
638 | if (FPMath == FP_Neon) |
639 | Features.push_back(x: "+neonfp" ); |
640 | else if (FPMath == FP_VFP) |
641 | Features.push_back(x: "-neonfp" ); |
642 | |
643 | return true; |
644 | } |
645 | |
646 | bool ARMTargetInfo::hasFeature(StringRef Feature) const { |
647 | return llvm::StringSwitch<bool>(Feature) |
648 | .Case(S: "arm" , Value: true) |
649 | .Case(S: "aarch32" , Value: true) |
650 | .Case(S: "softfloat" , Value: SoftFloat) |
651 | .Case(S: "thumb" , Value: isThumb()) |
652 | .Case(S: "neon" , Value: (FPU & NeonFPU) && !SoftFloat) |
653 | .Case(S: "vfp" , Value: FPU && !SoftFloat) |
654 | .Case(S: "hwdiv" , Value: HWDiv & HWDivThumb) |
655 | .Case(S: "hwdiv-arm" , Value: HWDiv & HWDivARM) |
656 | .Case(S: "mve" , Value: hasMVE()) |
657 | .Default(Value: false); |
658 | } |
659 | |
660 | bool ARMTargetInfo::hasBFloat16Type() const { |
661 | // The __bf16 type is generally available so long as we have any fp registers. |
662 | return HasBFloat16 || (FPU && !SoftFloat); |
663 | } |
664 | |
665 | bool ARMTargetInfo::isValidCPUName(StringRef Name) const { |
666 | return Name == "generic" || |
667 | llvm::ARM::parseCPUArch(CPU: Name) != llvm::ARM::ArchKind::INVALID; |
668 | } |
669 | |
670 | void ARMTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const { |
671 | llvm::ARM::fillValidCPUArchList(Values); |
672 | } |
673 | |
674 | bool ARMTargetInfo::setCPU(const std::string &Name) { |
675 | if (Name != "generic" ) |
676 | setArchInfo(llvm::ARM::parseCPUArch(CPU: Name)); |
677 | |
678 | if (ArchKind == llvm::ARM::ArchKind::INVALID) |
679 | return false; |
680 | setAtomic(); |
681 | CPU = Name; |
682 | return true; |
683 | } |
684 | |
685 | bool ARMTargetInfo::setFPMath(StringRef Name) { |
686 | if (Name == "neon" ) { |
687 | FPMath = FP_Neon; |
688 | return true; |
689 | } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" || |
690 | Name == "vfp4" ) { |
691 | FPMath = FP_VFP; |
692 | return true; |
693 | } |
694 | return false; |
695 | } |
696 | |
697 | void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts, |
698 | MacroBuilder &Builder) const { |
699 | Builder.defineMacro(Name: "__ARM_FEATURE_QRDMX" , Value: "1" ); |
700 | } |
701 | |
702 | void ARMTargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts, |
703 | MacroBuilder &Builder) const { |
704 | // Also include the ARMv8.1-A defines |
705 | getTargetDefinesARMV81A(Opts, Builder); |
706 | } |
707 | |
708 | void ARMTargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts, |
709 | MacroBuilder &Builder) const { |
710 | // Also include the ARMv8.2-A defines |
711 | Builder.defineMacro(Name: "__ARM_FEATURE_COMPLEX" , Value: "1" ); |
712 | getTargetDefinesARMV82A(Opts, Builder); |
713 | } |
714 | |
715 | void ARMTargetInfo::getTargetDefines(const LangOptions &Opts, |
716 | MacroBuilder &Builder) const { |
717 | // Target identification. |
718 | Builder.defineMacro(Name: "__arm" ); |
719 | Builder.defineMacro(Name: "__arm__" ); |
720 | // For bare-metal none-eabi. |
721 | if (getTriple().getOS() == llvm::Triple::UnknownOS && |
722 | (getTriple().getEnvironment() == llvm::Triple::EABI || |
723 | getTriple().getEnvironment() == llvm::Triple::EABIHF) && |
724 | Opts.CPlusPlus) { |
725 | Builder.defineMacro(Name: "_GNU_SOURCE" ); |
726 | } |
727 | |
728 | // Target properties. |
729 | Builder.defineMacro(Name: "__REGISTER_PREFIX__" , Value: "" ); |
730 | |
731 | // Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU |
732 | // happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__. |
733 | if (getTriple().isWatchABI()) |
734 | Builder.defineMacro(Name: "__ARM_ARCH_7K__" , Value: "2" ); |
735 | |
736 | if (!CPUAttr.empty()) |
737 | Builder.defineMacro(Name: "__ARM_ARCH_" + CPUAttr + "__" ); |
738 | |
739 | // ACLE 6.4.1 ARM/Thumb instruction set architecture |
740 | // __ARM_ARCH is defined as an integer value indicating the current ARM ISA |
741 | Builder.defineMacro(Name: "__ARM_ARCH" , Value: Twine(ArchVersion)); |
742 | |
743 | if (ArchVersion >= 8) { |
744 | // ACLE 6.5.7 Crypto Extension |
745 | // The __ARM_FEATURE_CRYPTO is deprecated in favor of finer grained |
746 | // feature macros for AES and SHA2 |
747 | if (SHA2 && AES) |
748 | Builder.defineMacro(Name: "__ARM_FEATURE_CRYPTO" , Value: "1" ); |
749 | if (SHA2) |
750 | Builder.defineMacro(Name: "__ARM_FEATURE_SHA2" , Value: "1" ); |
751 | if (AES) |
752 | Builder.defineMacro(Name: "__ARM_FEATURE_AES" , Value: "1" ); |
753 | // ACLE 6.5.8 CRC32 Extension |
754 | if (CRC) |
755 | Builder.defineMacro(Name: "__ARM_FEATURE_CRC32" , Value: "1" ); |
756 | // ACLE 6.5.10 Numeric Maximum and Minimum |
757 | Builder.defineMacro(Name: "__ARM_FEATURE_NUMERIC_MAXMIN" , Value: "1" ); |
758 | // ACLE 6.5.9 Directed Rounding |
759 | Builder.defineMacro(Name: "__ARM_FEATURE_DIRECTED_ROUNDING" , Value: "1" ); |
760 | } |
761 | |
762 | // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA. It |
763 | // is not defined for the M-profile. |
764 | // NOTE that the default profile is assumed to be 'A' |
765 | if (CPUProfile.empty() || ArchProfile != llvm::ARM::ProfileKind::M) |
766 | Builder.defineMacro(Name: "__ARM_ARCH_ISA_ARM" , Value: "1" ); |
767 | |
768 | // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original |
769 | // Thumb ISA (including v6-M and v8-M Baseline). It is set to 2 if the |
770 | // core supports the Thumb-2 ISA as found in the v6T2 architecture and all |
771 | // v7 and v8 architectures excluding v8-M Baseline. |
772 | if (supportsThumb2()) |
773 | Builder.defineMacro(Name: "__ARM_ARCH_ISA_THUMB" , Value: "2" ); |
774 | else if (supportsThumb()) |
775 | Builder.defineMacro(Name: "__ARM_ARCH_ISA_THUMB" , Value: "1" ); |
776 | |
777 | // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit |
778 | // instruction set such as ARM or Thumb. |
779 | Builder.defineMacro(Name: "__ARM_32BIT_STATE" , Value: "1" ); |
780 | |
781 | // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex) |
782 | |
783 | // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset. |
784 | if (!CPUProfile.empty()) |
785 | Builder.defineMacro(Name: "__ARM_ARCH_PROFILE" , Value: "'" + CPUProfile + "'" ); |
786 | |
787 | // ACLE 6.4.3 Unaligned access supported in hardware |
788 | if (HasUnalignedAccess) |
789 | Builder.defineMacro(Name: "__ARM_FEATURE_UNALIGNED" , Value: "1" ); |
790 | |
791 | // ACLE 6.4.4 LDREX/STREX |
792 | if (LDREX) |
793 | Builder.defineMacro(Name: "__ARM_FEATURE_LDREX" , Value: "0x" + Twine::utohexstr(Val: LDREX)); |
794 | |
795 | // ACLE 6.4.5 CLZ |
796 | if (ArchVersion == 5 || (ArchVersion == 6 && CPUProfile != "M" ) || |
797 | ArchVersion > 6) |
798 | Builder.defineMacro(Name: "__ARM_FEATURE_CLZ" , Value: "1" ); |
799 | |
800 | // ACLE 6.5.1 Hardware Floating Point |
801 | if (HW_FP) |
802 | Builder.defineMacro(Name: "__ARM_FP" , Value: "0x" + Twine::utohexstr(Val: HW_FP)); |
803 | |
804 | // ACLE predefines. |
805 | Builder.defineMacro(Name: "__ARM_ACLE" , Value: "200" ); |
806 | |
807 | // FP16 support (we currently only support IEEE format). |
808 | Builder.defineMacro(Name: "__ARM_FP16_FORMAT_IEEE" , Value: "1" ); |
809 | Builder.defineMacro(Name: "__ARM_FP16_ARGS" , Value: "1" ); |
810 | |
811 | // ACLE 6.5.3 Fused multiply-accumulate (FMA) |
812 | if (ArchVersion >= 7 && (FPU & VFP4FPU)) |
813 | Builder.defineMacro(Name: "__ARM_FEATURE_FMA" , Value: "1" ); |
814 | |
815 | // Subtarget options. |
816 | |
817 | // FIXME: It's more complicated than this and we don't really support |
818 | // interworking. |
819 | // Windows on ARM does not "support" interworking |
820 | if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows()) |
821 | Builder.defineMacro(Name: "__THUMB_INTERWORK__" ); |
822 | |
823 | if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp" ) { |
824 | // Embedded targets on Darwin follow AAPCS, but not EABI. |
825 | // Windows on ARM follows AAPCS VFP, but does not conform to EABI. |
826 | if (!getTriple().isOSBinFormatMachO() && !getTriple().isOSWindows()) |
827 | Builder.defineMacro(Name: "__ARM_EABI__" ); |
828 | Builder.defineMacro(Name: "__ARM_PCS" , Value: "1" ); |
829 | } |
830 | |
831 | if ((!SoftFloat && !SoftFloatABI) || ABI == "aapcs-vfp" || ABI == "aapcs16" ) |
832 | Builder.defineMacro(Name: "__ARM_PCS_VFP" , Value: "1" ); |
833 | |
834 | if (SoftFloat || (SoftFloatABI && !FPU)) |
835 | Builder.defineMacro(Name: "__SOFTFP__" ); |
836 | |
837 | // ACLE position independent code macros. |
838 | if (Opts.ROPI) |
839 | Builder.defineMacro(Name: "__ARM_ROPI" , Value: "1" ); |
840 | if (Opts.RWPI) |
841 | Builder.defineMacro(Name: "__ARM_RWPI" , Value: "1" ); |
842 | |
843 | // Macros for enabling co-proc intrinsics |
844 | uint64_t FeatureCoprocBF = 0; |
845 | switch (ArchKind) { |
846 | default: |
847 | break; |
848 | case llvm::ARM::ArchKind::ARMV4: |
849 | case llvm::ARM::ArchKind::ARMV4T: |
850 | // Filter __arm_ldcl and __arm_stcl in acle.h |
851 | FeatureCoprocBF = isThumb() ? 0 : FEATURE_COPROC_B1; |
852 | break; |
853 | case llvm::ARM::ArchKind::ARMV5T: |
854 | FeatureCoprocBF = isThumb() ? 0 : FEATURE_COPROC_B1 | FEATURE_COPROC_B2; |
855 | break; |
856 | case llvm::ARM::ArchKind::ARMV5TE: |
857 | case llvm::ARM::ArchKind::ARMV5TEJ: |
858 | if (!isThumb()) |
859 | FeatureCoprocBF = |
860 | FEATURE_COPROC_B1 | FEATURE_COPROC_B2 | FEATURE_COPROC_B3; |
861 | break; |
862 | case llvm::ARM::ArchKind::ARMV6: |
863 | case llvm::ARM::ArchKind::ARMV6K: |
864 | case llvm::ARM::ArchKind::ARMV6KZ: |
865 | case llvm::ARM::ArchKind::ARMV6T2: |
866 | if (!isThumb() || ArchKind == llvm::ARM::ArchKind::ARMV6T2) |
867 | FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 | |
868 | FEATURE_COPROC_B3 | FEATURE_COPROC_B4; |
869 | break; |
870 | case llvm::ARM::ArchKind::ARMV7A: |
871 | case llvm::ARM::ArchKind::ARMV7R: |
872 | case llvm::ARM::ArchKind::ARMV7M: |
873 | case llvm::ARM::ArchKind::ARMV7S: |
874 | case llvm::ARM::ArchKind::ARMV7EM: |
875 | FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 | |
876 | FEATURE_COPROC_B3 | FEATURE_COPROC_B4; |
877 | break; |
878 | case llvm::ARM::ArchKind::ARMV8A: |
879 | case llvm::ARM::ArchKind::ARMV8R: |
880 | case llvm::ARM::ArchKind::ARMV8_1A: |
881 | case llvm::ARM::ArchKind::ARMV8_2A: |
882 | case llvm::ARM::ArchKind::ARMV8_3A: |
883 | case llvm::ARM::ArchKind::ARMV8_4A: |
884 | case llvm::ARM::ArchKind::ARMV8_5A: |
885 | case llvm::ARM::ArchKind::ARMV8_6A: |
886 | case llvm::ARM::ArchKind::ARMV8_7A: |
887 | case llvm::ARM::ArchKind::ARMV8_8A: |
888 | case llvm::ARM::ArchKind::ARMV8_9A: |
889 | case llvm::ARM::ArchKind::ARMV9A: |
890 | case llvm::ARM::ArchKind::ARMV9_1A: |
891 | case llvm::ARM::ArchKind::ARMV9_2A: |
892 | case llvm::ARM::ArchKind::ARMV9_3A: |
893 | case llvm::ARM::ArchKind::ARMV9_4A: |
894 | case llvm::ARM::ArchKind::ARMV9_5A: |
895 | // Filter __arm_cdp, __arm_ldcl, __arm_stcl in arm_acle.h |
896 | FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B3; |
897 | break; |
898 | case llvm::ARM::ArchKind::ARMV8MMainline: |
899 | case llvm::ARM::ArchKind::ARMV8_1MMainline: |
900 | FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B2 | |
901 | FEATURE_COPROC_B3 | FEATURE_COPROC_B4; |
902 | break; |
903 | } |
904 | Builder.defineMacro(Name: "__ARM_FEATURE_COPROC" , |
905 | Value: "0x" + Twine::utohexstr(Val: FeatureCoprocBF)); |
906 | |
907 | if (ArchKind == llvm::ARM::ArchKind::XSCALE) |
908 | Builder.defineMacro(Name: "__XSCALE__" ); |
909 | |
910 | if (isThumb()) { |
911 | Builder.defineMacro(Name: "__THUMBEL__" ); |
912 | Builder.defineMacro(Name: "__thumb__" ); |
913 | if (supportsThumb2()) |
914 | Builder.defineMacro(Name: "__thumb2__" ); |
915 | } |
916 | |
917 | // ACLE 6.4.9 32-bit SIMD instructions |
918 | if ((CPUProfile != "M" && ArchVersion >= 6) || (CPUProfile == "M" && DSP)) |
919 | Builder.defineMacro(Name: "__ARM_FEATURE_SIMD32" , Value: "1" ); |
920 | |
921 | // ACLE 6.4.10 Hardware Integer Divide |
922 | if (((HWDiv & HWDivThumb) && isThumb()) || |
923 | ((HWDiv & HWDivARM) && !isThumb())) { |
924 | Builder.defineMacro(Name: "__ARM_FEATURE_IDIV" , Value: "1" ); |
925 | Builder.defineMacro(Name: "__ARM_ARCH_EXT_IDIV__" , Value: "1" ); |
926 | } |
927 | |
928 | // Note, this is always on in gcc, even though it doesn't make sense. |
929 | Builder.defineMacro(Name: "__APCS_32__" ); |
930 | |
931 | // __VFP_FP__ means that the floating-point format is VFP, not that a hardware |
932 | // FPU is present. Moreover, the VFP format is the only one supported by |
933 | // clang. For these reasons, this macro is always defined. |
934 | Builder.defineMacro(Name: "__VFP_FP__" ); |
935 | |
936 | if (FPUModeIsVFP(Mode: (FPUMode)FPU)) { |
937 | if (FPU & VFP2FPU) |
938 | Builder.defineMacro(Name: "__ARM_VFPV2__" ); |
939 | if (FPU & VFP3FPU) |
940 | Builder.defineMacro(Name: "__ARM_VFPV3__" ); |
941 | if (FPU & VFP4FPU) |
942 | Builder.defineMacro(Name: "__ARM_VFPV4__" ); |
943 | if (FPU & FPARMV8) |
944 | Builder.defineMacro(Name: "__ARM_FPV5__" ); |
945 | } |
946 | |
947 | // This only gets set when Neon instructions are actually available, unlike |
948 | // the VFP define, hence the soft float and arch check. This is subtly |
949 | // different from gcc, we follow the intent which was that it should be set |
950 | // when Neon instructions are actually available. |
951 | if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) { |
952 | Builder.defineMacro(Name: "__ARM_NEON" , Value: "1" ); |
953 | Builder.defineMacro(Name: "__ARM_NEON__" ); |
954 | // current AArch32 NEON implementations do not support double-precision |
955 | // floating-point even when it is present in VFP. |
956 | Builder.defineMacro(Name: "__ARM_NEON_FP" , |
957 | Value: "0x" + Twine::utohexstr(Val: HW_FP & ~HW_FP_DP)); |
958 | } |
959 | |
960 | if (hasMVE()) { |
961 | Builder.defineMacro(Name: "__ARM_FEATURE_MVE" , Value: hasMVEFloat() ? "3" : "1" ); |
962 | } |
963 | |
964 | if (hasCDE()) { |
965 | Builder.defineMacro(Name: "__ARM_FEATURE_CDE" , Value: "1" ); |
966 | Builder.defineMacro(Name: "__ARM_FEATURE_CDE_COPROC" , |
967 | Value: "0x" + Twine::utohexstr(Val: getARMCDECoprocMask())); |
968 | } |
969 | |
970 | Builder.defineMacro(Name: "__ARM_SIZEOF_WCHAR_T" , |
971 | Value: Twine(Opts.WCharSize ? Opts.WCharSize : 4)); |
972 | |
973 | Builder.defineMacro(Name: "__ARM_SIZEOF_MINIMAL_ENUM" , Value: Opts.ShortEnums ? "1" : "4" ); |
974 | |
975 | // CMSE |
976 | if (ArchVersion == 8 && ArchProfile == llvm::ARM::ProfileKind::M) |
977 | Builder.defineMacro(Name: "__ARM_FEATURE_CMSE" , Value: Opts.Cmse ? "3" : "1" ); |
978 | |
979 | if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE" ) { |
980 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1" ); |
981 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2" ); |
982 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" ); |
983 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8" ); |
984 | } |
985 | |
986 | // ACLE 6.4.7 DSP instructions |
987 | if (DSP) { |
988 | Builder.defineMacro(Name: "__ARM_FEATURE_DSP" , Value: "1" ); |
989 | } |
990 | |
991 | // ACLE 6.4.8 Saturation instructions |
992 | bool SAT = false; |
993 | if ((ArchVersion == 6 && CPUProfile != "M" ) || ArchVersion > 6) { |
994 | Builder.defineMacro(Name: "__ARM_FEATURE_SAT" , Value: "1" ); |
995 | SAT = true; |
996 | } |
997 | |
998 | // ACLE 6.4.6 Q (saturation) flag |
999 | if (DSP || SAT) |
1000 | Builder.defineMacro(Name: "__ARM_FEATURE_QBIT" , Value: "1" ); |
1001 | |
1002 | if (Opts.UnsafeFPMath) |
1003 | Builder.defineMacro(Name: "__ARM_FP_FAST" , Value: "1" ); |
1004 | |
1005 | // Armv8.2-A FP16 vector intrinsic |
1006 | if ((FPU & NeonFPU) && HasLegalHalfType) |
1007 | Builder.defineMacro(Name: "__ARM_FEATURE_FP16_VECTOR_ARITHMETIC" , Value: "1" ); |
1008 | |
1009 | // Armv8.2-A FP16 scalar intrinsics |
1010 | if (HasLegalHalfType) |
1011 | Builder.defineMacro(Name: "__ARM_FEATURE_FP16_SCALAR_ARITHMETIC" , Value: "1" ); |
1012 | |
1013 | // Armv8.2-A dot product intrinsics |
1014 | if (DotProd) |
1015 | Builder.defineMacro(Name: "__ARM_FEATURE_DOTPROD" , Value: "1" ); |
1016 | |
1017 | if (HasMatMul) |
1018 | Builder.defineMacro(Name: "__ARM_FEATURE_MATMUL_INT8" , Value: "1" ); |
1019 | |
1020 | if (HasPAC) |
1021 | Builder.defineMacro(Name: "__ARM_FEATURE_PAUTH" , Value: "1" ); |
1022 | |
1023 | if (HasBTI) |
1024 | Builder.defineMacro(Name: "__ARM_FEATURE_BTI" , Value: "1" ); |
1025 | |
1026 | if (HasBFloat16) { |
1027 | Builder.defineMacro(Name: "__ARM_FEATURE_BF16" , Value: "1" ); |
1028 | Builder.defineMacro(Name: "__ARM_FEATURE_BF16_VECTOR_ARITHMETIC" , Value: "1" ); |
1029 | Builder.defineMacro(Name: "__ARM_BF16_FORMAT_ALTERNATIVE" , Value: "1" ); |
1030 | } |
1031 | |
1032 | if (Opts.BranchTargetEnforcement) |
1033 | Builder.defineMacro(Name: "__ARM_FEATURE_BTI_DEFAULT" , Value: "1" ); |
1034 | |
1035 | if (Opts.hasSignReturnAddress()) { |
1036 | unsigned Value = 1; |
1037 | if (Opts.isSignReturnAddressScopeAll()) |
1038 | Value |= 1 << 2; |
1039 | Builder.defineMacro(Name: "__ARM_FEATURE_PAC_DEFAULT" , Value: Twine(Value)); |
1040 | } |
1041 | |
1042 | switch (ArchKind) { |
1043 | default: |
1044 | break; |
1045 | case llvm::ARM::ArchKind::ARMV8_1A: |
1046 | getTargetDefinesARMV81A(Opts, Builder); |
1047 | break; |
1048 | case llvm::ARM::ArchKind::ARMV8_2A: |
1049 | getTargetDefinesARMV82A(Opts, Builder); |
1050 | break; |
1051 | case llvm::ARM::ArchKind::ARMV8_3A: |
1052 | case llvm::ARM::ArchKind::ARMV8_4A: |
1053 | case llvm::ARM::ArchKind::ARMV8_5A: |
1054 | case llvm::ARM::ArchKind::ARMV8_6A: |
1055 | case llvm::ARM::ArchKind::ARMV8_7A: |
1056 | case llvm::ARM::ArchKind::ARMV8_8A: |
1057 | case llvm::ARM::ArchKind::ARMV8_9A: |
1058 | case llvm::ARM::ArchKind::ARMV9A: |
1059 | case llvm::ARM::ArchKind::ARMV9_1A: |
1060 | case llvm::ARM::ArchKind::ARMV9_2A: |
1061 | case llvm::ARM::ArchKind::ARMV9_3A: |
1062 | case llvm::ARM::ArchKind::ARMV9_4A: |
1063 | case llvm::ARM::ArchKind::ARMV9_5A: |
1064 | getTargetDefinesARMV83A(Opts, Builder); |
1065 | break; |
1066 | } |
1067 | } |
1068 | |
1069 | static constexpr Builtin::Info BuiltinInfo[] = { |
1070 | #define BUILTIN(ID, TYPE, ATTRS) \ |
1071 | {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, |
1072 | #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ |
1073 | {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES}, |
1074 | #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ |
1075 | {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, |
1076 | #include "clang/Basic/BuiltinsNEON.def" |
1077 | |
1078 | #define BUILTIN(ID, TYPE, ATTRS) \ |
1079 | {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, |
1080 | #define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \ |
1081 | {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, LANG}, |
1082 | #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ |
1083 | {#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES}, |
1084 | #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ |
1085 | {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES}, |
1086 | #define (ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \ |
1087 | {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::HEADER, LANGS}, |
1088 | #include "clang/Basic/BuiltinsARM.def" |
1089 | }; |
1090 | |
1091 | ArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const { |
1092 | return llvm::ArrayRef(BuiltinInfo, |
1093 | clang::ARM::LastTSBuiltin - Builtin::FirstTSBuiltin); |
1094 | } |
1095 | |
1096 | bool ARMTargetInfo::isCLZForZeroUndef() const { return false; } |
1097 | TargetInfo::BuiltinVaListKind ARMTargetInfo::getBuiltinVaListKind() const { |
1098 | return IsAAPCS |
1099 | ? AAPCSABIBuiltinVaList |
1100 | : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList |
1101 | : TargetInfo::VoidPtrBuiltinVaList); |
1102 | } |
1103 | |
1104 | const char *const ARMTargetInfo::GCCRegNames[] = { |
1105 | // Integer registers |
1106 | "r0" , "r1" , "r2" , "r3" , "r4" , "r5" , "r6" , "r7" , "r8" , "r9" , "r10" , "r11" , |
1107 | "r12" , "sp" , "lr" , "pc" , |
1108 | |
1109 | // Float registers |
1110 | "s0" , "s1" , "s2" , "s3" , "s4" , "s5" , "s6" , "s7" , "s8" , "s9" , "s10" , "s11" , |
1111 | "s12" , "s13" , "s14" , "s15" , "s16" , "s17" , "s18" , "s19" , "s20" , "s21" , "s22" , |
1112 | "s23" , "s24" , "s25" , "s26" , "s27" , "s28" , "s29" , "s30" , "s31" , |
1113 | |
1114 | // Double registers |
1115 | "d0" , "d1" , "d2" , "d3" , "d4" , "d5" , "d6" , "d7" , "d8" , "d9" , "d10" , "d11" , |
1116 | "d12" , "d13" , "d14" , "d15" , "d16" , "d17" , "d18" , "d19" , "d20" , "d21" , "d22" , |
1117 | "d23" , "d24" , "d25" , "d26" , "d27" , "d28" , "d29" , "d30" , "d31" , |
1118 | |
1119 | // Quad registers |
1120 | "q0" , "q1" , "q2" , "q3" , "q4" , "q5" , "q6" , "q7" , "q8" , "q9" , "q10" , "q11" , |
1121 | "q12" , "q13" , "q14" , "q15" }; |
1122 | |
1123 | ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const { |
1124 | return llvm::ArrayRef(GCCRegNames); |
1125 | } |
1126 | |
1127 | const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = { |
1128 | {.Aliases: {"a1" }, .Register: "r0" }, {.Aliases: {"a2" }, .Register: "r1" }, {.Aliases: {"a3" }, .Register: "r2" }, {.Aliases: {"a4" }, .Register: "r3" }, |
1129 | {.Aliases: {"v1" }, .Register: "r4" }, {.Aliases: {"v2" }, .Register: "r5" }, {.Aliases: {"v3" }, .Register: "r6" }, {.Aliases: {"v4" }, .Register: "r7" }, |
1130 | {.Aliases: {"v5" }, .Register: "r8" }, {.Aliases: {"v6" , "rfp" }, .Register: "r9" }, {.Aliases: {"sl" }, .Register: "r10" }, {.Aliases: {"fp" }, .Register: "r11" }, |
1131 | {.Aliases: {"ip" }, .Register: "r12" }, {.Aliases: {"r13" }, .Register: "sp" }, {.Aliases: {"r14" }, .Register: "lr" }, {.Aliases: {"r15" }, .Register: "pc" }, |
1132 | // The S, D and Q registers overlap, but aren't really aliases; we |
1133 | // don't want to substitute one of these for a different-sized one. |
1134 | }; |
1135 | |
1136 | ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const { |
1137 | return llvm::ArrayRef(GCCRegAliases); |
1138 | } |
1139 | |
1140 | bool ARMTargetInfo::validateAsmConstraint( |
1141 | const char *&Name, TargetInfo::ConstraintInfo &Info) const { |
1142 | switch (*Name) { |
1143 | default: |
1144 | break; |
1145 | case 'l': // r0-r7 if thumb, r0-r15 if ARM |
1146 | Info.setAllowsRegister(); |
1147 | return true; |
1148 | case 'h': // r8-r15, thumb only |
1149 | if (isThumb()) { |
1150 | Info.setAllowsRegister(); |
1151 | return true; |
1152 | } |
1153 | break; |
1154 | case 's': // An integer constant, but allowing only relocatable values. |
1155 | return true; |
1156 | case 't': // s0-s31, d0-d31, or q0-q15 |
1157 | case 'w': // s0-s15, d0-d7, or q0-q3 |
1158 | case 'x': // s0-s31, d0-d15, or q0-q7 |
1159 | if (FPRegsDisabled) |
1160 | return false; |
1161 | Info.setAllowsRegister(); |
1162 | return true; |
1163 | case 'j': // An immediate integer between 0 and 65535 (valid for MOVW) |
1164 | // only available in ARMv6T2 and above |
1165 | if (CPUAttr.equals(RHS: "6T2" ) || ArchVersion >= 7) { |
1166 | Info.setRequiresImmediate(Min: 0, Max: 65535); |
1167 | return true; |
1168 | } |
1169 | break; |
1170 | case 'I': |
1171 | if (isThumb()) { |
1172 | if (!supportsThumb2()) |
1173 | Info.setRequiresImmediate(Min: 0, Max: 255); |
1174 | else |
1175 | // FIXME: should check if immediate value would be valid for a Thumb2 |
1176 | // data-processing instruction |
1177 | Info.setRequiresImmediate(); |
1178 | } else |
1179 | // FIXME: should check if immediate value would be valid for an ARM |
1180 | // data-processing instruction |
1181 | Info.setRequiresImmediate(); |
1182 | return true; |
1183 | case 'J': |
1184 | if (isThumb() && !supportsThumb2()) |
1185 | Info.setRequiresImmediate(Min: -255, Max: -1); |
1186 | else |
1187 | Info.setRequiresImmediate(Min: -4095, Max: 4095); |
1188 | return true; |
1189 | case 'K': |
1190 | if (isThumb()) { |
1191 | if (!supportsThumb2()) |
1192 | // FIXME: should check if immediate value can be obtained from shifting |
1193 | // a value between 0 and 255 left by any amount |
1194 | Info.setRequiresImmediate(); |
1195 | else |
1196 | // FIXME: should check if immediate value would be valid for a Thumb2 |
1197 | // data-processing instruction when inverted |
1198 | Info.setRequiresImmediate(); |
1199 | } else |
1200 | // FIXME: should check if immediate value would be valid for an ARM |
1201 | // data-processing instruction when inverted |
1202 | Info.setRequiresImmediate(); |
1203 | return true; |
1204 | case 'L': |
1205 | if (isThumb()) { |
1206 | if (!supportsThumb2()) |
1207 | Info.setRequiresImmediate(Min: -7, Max: 7); |
1208 | else |
1209 | // FIXME: should check if immediate value would be valid for a Thumb2 |
1210 | // data-processing instruction when negated |
1211 | Info.setRequiresImmediate(); |
1212 | } else |
1213 | // FIXME: should check if immediate value would be valid for an ARM |
1214 | // data-processing instruction when negated |
1215 | Info.setRequiresImmediate(); |
1216 | return true; |
1217 | case 'M': |
1218 | if (isThumb() && !supportsThumb2()) |
1219 | // FIXME: should check if immediate value is a multiple of 4 between 0 and |
1220 | // 1020 |
1221 | Info.setRequiresImmediate(); |
1222 | else |
1223 | // FIXME: should check if immediate value is a power of two or a integer |
1224 | // between 0 and 32 |
1225 | Info.setRequiresImmediate(); |
1226 | return true; |
1227 | case 'N': |
1228 | // Thumb1 only |
1229 | if (isThumb() && !supportsThumb2()) { |
1230 | Info.setRequiresImmediate(Min: 0, Max: 31); |
1231 | return true; |
1232 | } |
1233 | break; |
1234 | case 'O': |
1235 | // Thumb1 only |
1236 | if (isThumb() && !supportsThumb2()) { |
1237 | // FIXME: should check if immediate value is a multiple of 4 between -508 |
1238 | // and 508 |
1239 | Info.setRequiresImmediate(); |
1240 | return true; |
1241 | } |
1242 | break; |
1243 | case 'Q': // A memory address that is a single base register. |
1244 | Info.setAllowsMemory(); |
1245 | return true; |
1246 | case 'T': |
1247 | switch (Name[1]) { |
1248 | default: |
1249 | break; |
1250 | case 'e': // Even general-purpose register |
1251 | case 'o': // Odd general-purpose register |
1252 | Info.setAllowsRegister(); |
1253 | Name++; |
1254 | return true; |
1255 | } |
1256 | break; |
1257 | case 'U': // a memory reference... |
1258 | switch (Name[1]) { |
1259 | case 'q': // ...ARMV4 ldrsb |
1260 | case 'v': // ...VFP load/store (reg+constant offset) |
1261 | case 'y': // ...iWMMXt load/store |
1262 | case 't': // address valid for load/store opaque types wider |
1263 | // than 128-bits |
1264 | case 'n': // valid address for Neon doubleword vector load/store |
1265 | case 'm': // valid address for Neon element and structure load/store |
1266 | case 's': // valid address for non-offset loads/stores of quad-word |
1267 | // values in four ARM registers |
1268 | Info.setAllowsMemory(); |
1269 | Name++; |
1270 | return true; |
1271 | } |
1272 | break; |
1273 | } |
1274 | return false; |
1275 | } |
1276 | |
1277 | std::string ARMTargetInfo::convertConstraint(const char *&Constraint) const { |
1278 | std::string R; |
1279 | switch (*Constraint) { |
1280 | case 'U': // Two-character constraint; add "^" hint for later parsing. |
1281 | case 'T': |
1282 | R = std::string("^" ) + std::string(Constraint, 2); |
1283 | Constraint++; |
1284 | break; |
1285 | case 'p': // 'p' should be translated to 'r' by default. |
1286 | R = std::string("r" ); |
1287 | break; |
1288 | default: |
1289 | return std::string(1, *Constraint); |
1290 | } |
1291 | return R; |
1292 | } |
1293 | |
1294 | bool ARMTargetInfo::validateConstraintModifier( |
1295 | StringRef Constraint, char Modifier, unsigned Size, |
1296 | std::string &SuggestedModifier) const { |
1297 | bool isOutput = (Constraint[0] == '='); |
1298 | bool isInOut = (Constraint[0] == '+'); |
1299 | |
1300 | // Strip off constraint modifiers. |
1301 | Constraint = Constraint.ltrim(Chars: "=+&" ); |
1302 | |
1303 | switch (Constraint[0]) { |
1304 | default: |
1305 | break; |
1306 | case 'r': { |
1307 | switch (Modifier) { |
1308 | default: |
1309 | return (isInOut || isOutput || Size <= 64); |
1310 | case 'q': |
1311 | // A register of size 32 cannot fit a vector type. |
1312 | return false; |
1313 | } |
1314 | } |
1315 | } |
1316 | |
1317 | return true; |
1318 | } |
1319 | std::string_view ARMTargetInfo::getClobbers() const { |
1320 | // FIXME: Is this really right? |
1321 | return "" ; |
1322 | } |
1323 | |
1324 | TargetInfo::CallingConvCheckResult |
1325 | ARMTargetInfo::checkCallingConvention(CallingConv CC) const { |
1326 | switch (CC) { |
1327 | case CC_AAPCS: |
1328 | case CC_AAPCS_VFP: |
1329 | case CC_Swift: |
1330 | case CC_SwiftAsync: |
1331 | case CC_OpenCLKernel: |
1332 | return CCCR_OK; |
1333 | default: |
1334 | return CCCR_Warning; |
1335 | } |
1336 | } |
1337 | |
1338 | int ARMTargetInfo::getEHDataRegisterNumber(unsigned RegNo) const { |
1339 | if (RegNo == 0) |
1340 | return 0; |
1341 | if (RegNo == 1) |
1342 | return 1; |
1343 | return -1; |
1344 | } |
1345 | |
1346 | bool ARMTargetInfo::hasSjLjLowering() const { return true; } |
1347 | |
1348 | ARMleTargetInfo::ARMleTargetInfo(const llvm::Triple &Triple, |
1349 | const TargetOptions &Opts) |
1350 | : ARMTargetInfo(Triple, Opts) {} |
1351 | |
1352 | void ARMleTargetInfo::getTargetDefines(const LangOptions &Opts, |
1353 | MacroBuilder &Builder) const { |
1354 | Builder.defineMacro(Name: "__ARMEL__" ); |
1355 | ARMTargetInfo::getTargetDefines(Opts, Builder); |
1356 | } |
1357 | |
1358 | ARMbeTargetInfo::ARMbeTargetInfo(const llvm::Triple &Triple, |
1359 | const TargetOptions &Opts) |
1360 | : ARMTargetInfo(Triple, Opts) {} |
1361 | |
1362 | void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts, |
1363 | MacroBuilder &Builder) const { |
1364 | Builder.defineMacro(Name: "__ARMEB__" ); |
1365 | Builder.defineMacro(Name: "__ARM_BIG_ENDIAN" ); |
1366 | ARMTargetInfo::getTargetDefines(Opts, Builder); |
1367 | } |
1368 | |
1369 | WindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple, |
1370 | const TargetOptions &Opts) |
1371 | : WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) { |
1372 | } |
1373 | |
1374 | void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts, |
1375 | MacroBuilder &Builder) const { |
1376 | // FIXME: this is invalid for WindowsCE |
1377 | Builder.defineMacro(Name: "_M_ARM_NT" , Value: "1" ); |
1378 | Builder.defineMacro(Name: "_M_ARMT" , Value: "_M_ARM" ); |
1379 | Builder.defineMacro(Name: "_M_THUMB" , Value: "_M_ARM" ); |
1380 | |
1381 | assert((Triple.getArch() == llvm::Triple::arm || |
1382 | Triple.getArch() == llvm::Triple::thumb) && |
1383 | "invalid architecture for Windows ARM target info" ); |
1384 | unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6; |
1385 | Builder.defineMacro(Name: "_M_ARM" , Value: Triple.getArchName().substr(Start: Offset)); |
1386 | |
1387 | // TODO map the complete set of values |
1388 | // 31: VFPv3 40: VFPv4 |
1389 | Builder.defineMacro(Name: "_M_ARM_FP" , Value: "31" ); |
1390 | } |
1391 | |
1392 | TargetInfo::BuiltinVaListKind |
1393 | WindowsARMTargetInfo::getBuiltinVaListKind() const { |
1394 | return TargetInfo::CharPtrBuiltinVaList; |
1395 | } |
1396 | |
1397 | TargetInfo::CallingConvCheckResult |
1398 | WindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const { |
1399 | switch (CC) { |
1400 | case CC_X86StdCall: |
1401 | case CC_X86ThisCall: |
1402 | case CC_X86FastCall: |
1403 | case CC_X86VectorCall: |
1404 | return CCCR_Ignore; |
1405 | case CC_C: |
1406 | case CC_OpenCLKernel: |
1407 | case CC_PreserveMost: |
1408 | case CC_PreserveAll: |
1409 | case CC_Swift: |
1410 | case CC_SwiftAsync: |
1411 | return CCCR_OK; |
1412 | default: |
1413 | return CCCR_Warning; |
1414 | } |
1415 | } |
1416 | |
1417 | // Windows ARM + Itanium C++ ABI Target |
1418 | ItaniumWindowsARMleTargetInfo::ItaniumWindowsARMleTargetInfo( |
1419 | const llvm::Triple &Triple, const TargetOptions &Opts) |
1420 | : WindowsARMTargetInfo(Triple, Opts) { |
1421 | TheCXXABI.set(TargetCXXABI::GenericARM); |
1422 | } |
1423 | |
1424 | void ItaniumWindowsARMleTargetInfo::getTargetDefines( |
1425 | const LangOptions &Opts, MacroBuilder &Builder) const { |
1426 | WindowsARMTargetInfo::getTargetDefines(Opts, Builder); |
1427 | |
1428 | if (Opts.MSVCCompat) |
1429 | WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder); |
1430 | } |
1431 | |
1432 | // Windows ARM, MS (C++) ABI |
1433 | MicrosoftARMleTargetInfo::MicrosoftARMleTargetInfo(const llvm::Triple &Triple, |
1434 | const TargetOptions &Opts) |
1435 | : WindowsARMTargetInfo(Triple, Opts) { |
1436 | TheCXXABI.set(TargetCXXABI::Microsoft); |
1437 | } |
1438 | |
1439 | void MicrosoftARMleTargetInfo::getTargetDefines(const LangOptions &Opts, |
1440 | MacroBuilder &Builder) const { |
1441 | WindowsARMTargetInfo::getTargetDefines(Opts, Builder); |
1442 | WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder); |
1443 | } |
1444 | |
1445 | MinGWARMTargetInfo::MinGWARMTargetInfo(const llvm::Triple &Triple, |
1446 | const TargetOptions &Opts) |
1447 | : WindowsARMTargetInfo(Triple, Opts) { |
1448 | TheCXXABI.set(TargetCXXABI::GenericARM); |
1449 | } |
1450 | |
1451 | void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts, |
1452 | MacroBuilder &Builder) const { |
1453 | WindowsARMTargetInfo::getTargetDefines(Opts, Builder); |
1454 | Builder.defineMacro(Name: "_ARM_" ); |
1455 | } |
1456 | |
1457 | CygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple, |
1458 | const TargetOptions &Opts) |
1459 | : ARMleTargetInfo(Triple, Opts) { |
1460 | this->WCharType = TargetInfo::UnsignedShort; |
1461 | TLSSupported = false; |
1462 | DoubleAlign = LongLongAlign = 64; |
1463 | resetDataLayout(DL: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" ); |
1464 | } |
1465 | |
1466 | void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts, |
1467 | MacroBuilder &Builder) const { |
1468 | ARMleTargetInfo::getTargetDefines(Opts, Builder); |
1469 | Builder.defineMacro(Name: "_ARM_" ); |
1470 | Builder.defineMacro(Name: "__CYGWIN__" ); |
1471 | Builder.defineMacro(Name: "__CYGWIN32__" ); |
1472 | DefineStd(Builder, MacroName: "unix" , Opts); |
1473 | if (Opts.CPlusPlus) |
1474 | Builder.defineMacro(Name: "_GNU_SOURCE" ); |
1475 | } |
1476 | |
1477 | DarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple, |
1478 | const TargetOptions &Opts) |
1479 | : DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) { |
1480 | HasAlignMac68kSupport = true; |
1481 | if (Triple.isWatchABI()) { |
1482 | // Darwin on iOS uses a variant of the ARM C++ ABI. |
1483 | TheCXXABI.set(TargetCXXABI::WatchOS); |
1484 | |
1485 | // BOOL should be a real boolean on the new ABI |
1486 | UseSignedCharForObjCBool = false; |
1487 | } else |
1488 | TheCXXABI.set(TargetCXXABI::iOS); |
1489 | } |
1490 | |
1491 | void DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts, |
1492 | const llvm::Triple &Triple, |
1493 | MacroBuilder &Builder) const { |
1494 | getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); |
1495 | } |
1496 | |
1497 | RenderScript32TargetInfo::RenderScript32TargetInfo(const llvm::Triple &Triple, |
1498 | const TargetOptions &Opts) |
1499 | : ARMleTargetInfo(llvm::Triple("armv7" , Triple.getVendorName(), |
1500 | Triple.getOSName(), |
1501 | Triple.getEnvironmentName()), |
1502 | Opts) { |
1503 | IsRenderScriptTarget = true; |
1504 | LongWidth = LongAlign = 64; |
1505 | } |
1506 | |
1507 | void RenderScript32TargetInfo::getTargetDefines(const LangOptions &Opts, |
1508 | MacroBuilder &Builder) const { |
1509 | Builder.defineMacro(Name: "__RENDERSCRIPT__" ); |
1510 | ARMleTargetInfo::getTargetDefines(Opts, Builder); |
1511 | } |
1512 | |