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