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