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