/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/clang/lib/Basic/Targets/ARM.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- ARM.cpp - Implement ARM target feature support -------------------===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | // |
10 | | // This file implements ARM TargetInfo objects. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "ARM.h" |
15 | | #include "clang/Basic/Builtins.h" |
16 | | #include "clang/Basic/Diagnostic.h" |
17 | | #include "clang/Basic/TargetBuiltins.h" |
18 | | #include "llvm/ADT/StringExtras.h" |
19 | | #include "llvm/ADT/StringRef.h" |
20 | | #include "llvm/ADT/StringSwitch.h" |
21 | | |
22 | | using namespace clang; |
23 | | using namespace clang::targets; |
24 | | |
25 | 3.24k | void ARMTargetInfo::setABIAAPCS() { |
26 | 3.24k | IsAAPCS = true; |
27 | 3.24k | |
28 | 3.24k | DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64; |
29 | 3.24k | const llvm::Triple &T = getTriple(); |
30 | 3.24k | |
31 | 3.24k | // size_t is unsigned long on MachO-derived environments, NetBSD, and |
32 | 3.24k | // OpenBSD. |
33 | 3.24k | if (T.isOSBinFormatMachO() || 3.24k T.getOS() == llvm::Triple::NetBSD776 || |
34 | 765 | T.getOS() == llvm::Triple::OpenBSD) |
35 | 2.48k | SizeType = UnsignedLong; |
36 | 3.24k | else |
37 | 759 | SizeType = UnsignedInt; |
38 | 3.24k | |
39 | 3.24k | switch (T.getOS()) { |
40 | 17 | case llvm::Triple::NetBSD: |
41 | 17 | case llvm::Triple::OpenBSD: |
42 | 17 | WCharType = SignedInt; |
43 | 17 | break; |
44 | 72 | case llvm::Triple::Win32: |
45 | 72 | WCharType = UnsignedShort; |
46 | 72 | break; |
47 | 230 | case llvm::Triple::Linux: |
48 | 3.15k | default: |
49 | 3.15k | // AAPCS 7.1.1, ARM-Linux ABI 2.4: type of wchar_t is unsigned int. |
50 | 3.15k | WCharType = UnsignedInt; |
51 | 3.15k | break; |
52 | 3.24k | } |
53 | 3.24k | |
54 | 3.24k | UseBitFieldTypeAlignment = true; |
55 | 3.24k | |
56 | 3.24k | ZeroLengthBitfieldBoundary = 0; |
57 | 3.24k | |
58 | 3.24k | // Thumb1 add sp, #imm requires the immediate value be multiple of 4, |
59 | 3.24k | // so set preferred for small types to 32. |
60 | 3.24k | if (T.isOSBinFormatMachO()3.24k ) { |
61 | 2.47k | resetDataLayout(BigEndian |
62 | 0 | ? "E-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" |
63 | 2.47k | : "e-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"); |
64 | 3.24k | } else if (776 T.isOSWindows()776 ) { |
65 | 72 | assert(!BigEndian && "Windows on ARM does not support big endian"); |
66 | 72 | resetDataLayout("e" |
67 | 72 | "-m:w" |
68 | 72 | "-p:32:32" |
69 | 72 | "-i64:64" |
70 | 72 | "-v128:64:128" |
71 | 72 | "-a:0:32" |
72 | 72 | "-n32" |
73 | 72 | "-S64"); |
74 | 776 | } else if (704 T.isOSNaCl()704 ) { |
75 | 2 | assert(!BigEndian && "NaCl on ARM does not support big endian"); |
76 | 2 | resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128"); |
77 | 704 | } else { |
78 | 702 | resetDataLayout(BigEndian |
79 | 16 | ? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" |
80 | 686 | : "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"); |
81 | 776 | } |
82 | 3.24k | |
83 | 3.24k | // FIXME: Enumerated types are variable width in straight AAPCS. |
84 | 3.24k | } |
85 | | |
86 | 2.71k | void ARMTargetInfo::setABIAPCS(bool IsAAPCS16) { |
87 | 2.71k | const llvm::Triple &T = getTriple(); |
88 | 2.71k | |
89 | 2.71k | IsAAPCS = false; |
90 | 2.71k | |
91 | 2.71k | if (IsAAPCS16) |
92 | 1.14k | DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64; |
93 | 2.71k | else |
94 | 1.56k | DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32; |
95 | 2.71k | |
96 | 2.71k | // size_t is unsigned int on FreeBSD. |
97 | 2.71k | if (T.getOS() == llvm::Triple::FreeBSD) |
98 | 0 | SizeType = UnsignedInt; |
99 | 2.71k | else |
100 | 2.71k | SizeType = UnsignedLong; |
101 | 2.71k | |
102 | 2.71k | // Revert to using SignedInt on apcs-gnu to comply with existing behaviour. |
103 | 2.71k | WCharType = SignedInt; |
104 | 2.71k | |
105 | 2.71k | // Do not respect the alignment of bit-field types when laying out |
106 | 2.71k | // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc. |
107 | 2.71k | UseBitFieldTypeAlignment = false; |
108 | 2.71k | |
109 | 2.71k | /// gcc forces the alignment to 4 bytes, regardless of the type of the |
110 | 2.71k | /// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in |
111 | 2.71k | /// gcc. |
112 | 2.71k | ZeroLengthBitfieldBoundary = 32; |
113 | 2.71k | |
114 | 2.71k | if (T.isOSBinFormatMachO() && 2.71k IsAAPCS162.68k ) { |
115 | 1.14k | assert(!BigEndian && "AAPCS16 does not support big-endian"); |
116 | 1.14k | resetDataLayout("e-m:o-p:32:32-i64:64-a:0:32-n32-S128"); |
117 | 2.71k | } else if (1.56k T.isOSBinFormatMachO()1.56k ) |
118 | 1.53k | resetDataLayout( |
119 | 1.53k | BigEndian |
120 | 0 | ? "E-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" |
121 | 1.53k | : "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"); |
122 | 1.56k | else |
123 | 30 | resetDataLayout( |
124 | 30 | BigEndian |
125 | 0 | ? "E-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" |
126 | 1.56k | : "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"); |
127 | 2.71k | |
128 | 2.71k | // FIXME: Override "preferred align" for double and long long. |
129 | 2.71k | } |
130 | | |
131 | 3.17k | void ARMTargetInfo::setArchInfo() { |
132 | 3.17k | StringRef ArchName = getTriple().getArchName(); |
133 | 3.17k | |
134 | 3.17k | ArchISA = llvm::ARM::parseArchISA(ArchName); |
135 | 3.17k | CPU = llvm::ARM::getDefaultCPU(ArchName); |
136 | 3.17k | llvm::ARM::ArchKind AK = llvm::ARM::parseArch(ArchName); |
137 | 3.17k | if (AK != llvm::ARM::ArchKind::INVALID) |
138 | 3.07k | ArchKind = AK; |
139 | 3.17k | setArchInfo(ArchKind); |
140 | 3.17k | } |
141 | | |
142 | 5.12k | void ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) { |
143 | 5.12k | StringRef SubArch; |
144 | 5.12k | |
145 | 5.12k | // cache TargetParser info |
146 | 5.12k | ArchKind = Kind; |
147 | 5.12k | SubArch = llvm::ARM::getSubArch(ArchKind); |
148 | 5.12k | ArchProfile = llvm::ARM::parseArchProfile(SubArch); |
149 | 5.12k | ArchVersion = llvm::ARM::parseArchVersion(SubArch); |
150 | 5.12k | |
151 | 5.12k | // cache CPU related strings |
152 | 5.12k | CPUAttr = getCPUAttr(); |
153 | 5.12k | CPUProfile = getCPUProfile(); |
154 | 5.12k | } |
155 | | |
156 | 5.96k | void ARMTargetInfo::setAtomic() { |
157 | 5.96k | // when triple does not specify a sub arch, |
158 | 5.96k | // then we are not using inline atomics |
159 | 5.96k | bool ShouldUseInlineAtomic = |
160 | 636 | (ArchISA == llvm::ARM::ISAKind::ARM && ArchVersion >= 6) || |
161 | 5.53k | (ArchISA == llvm::ARM::ISAKind::THUMB && 5.53k ArchVersion >= 75.33k ); |
162 | 5.96k | // Cortex M does not support 8 byte atomics, while general Thumb2 does. |
163 | 5.96k | if (ArchProfile == llvm::ARM::ProfileKind::M5.96k ) { |
164 | 1.64k | MaxAtomicPromoteWidth = 32; |
165 | 1.64k | if (ShouldUseInlineAtomic) |
166 | 1.26k | MaxAtomicInlineWidth = 32; |
167 | 5.96k | } else { |
168 | 4.32k | MaxAtomicPromoteWidth = 64; |
169 | 4.32k | if (ShouldUseInlineAtomic) |
170 | 4.10k | MaxAtomicInlineWidth = 64; |
171 | 4.32k | } |
172 | 5.96k | } |
173 | | |
174 | 9.00k | bool ARMTargetInfo::isThumb() const { |
175 | 9.00k | return ArchISA == llvm::ARM::ISAKind::THUMB; |
176 | 9.00k | } |
177 | | |
178 | 378 | bool ARMTargetInfo::supportsThumb() const { |
179 | 232 | return CPUAttr.count('T') || ArchVersion >= 6; |
180 | 378 | } |
181 | | |
182 | 5.88k | bool ARMTargetInfo::supportsThumb2() const { |
183 | 5.88k | return CPUAttr.equals("6T2") || |
184 | 5.88k | (ArchVersion >= 7 && 5.88k !CPUAttr.equals("8M_BASE")5.29k ); |
185 | 5.88k | } |
186 | | |
187 | 5.12k | StringRef ARMTargetInfo::getCPUAttr() const { |
188 | 5.12k | // For most sub-arches, the build attribute CPU name is enough. |
189 | 5.12k | // For Cortex variants, it's slightly different. |
190 | 5.12k | switch (ArchKind) { |
191 | 853 | default: |
192 | 853 | return llvm::ARM::getCPUAttr(ArchKind); |
193 | 375 | case llvm::ARM::ArchKind::ARMV6M: |
194 | 375 | return "6M"; |
195 | 706 | case llvm::ARM::ArchKind::ARMV7S: |
196 | 706 | return "7S"; |
197 | 1.78k | case llvm::ARM::ArchKind::ARMV7A: |
198 | 1.78k | return "7A"; |
199 | 41 | case llvm::ARM::ArchKind::ARMV7R: |
200 | 41 | return "7R"; |
201 | 431 | case llvm::ARM::ArchKind::ARMV7M: |
202 | 431 | return "7M"; |
203 | 824 | case llvm::ARM::ArchKind::ARMV7EM: |
204 | 824 | return "7EM"; |
205 | 5 | case llvm::ARM::ArchKind::ARMV7VE: |
206 | 5 | return "7VE"; |
207 | 89 | case llvm::ARM::ArchKind::ARMV8A: |
208 | 89 | return "8A"; |
209 | 2 | case llvm::ARM::ArchKind::ARMV8_1A: |
210 | 2 | return "8_1A"; |
211 | 1 | case llvm::ARM::ArchKind::ARMV8_2A: |
212 | 1 | return "8_2A"; |
213 | 3 | case llvm::ARM::ArchKind::ARMV8MBaseline: |
214 | 3 | return "8M_BASE"; |
215 | 4 | case llvm::ARM::ArchKind::ARMV8MMainline: |
216 | 4 | return "8M_MAIN"; |
217 | 2 | case llvm::ARM::ArchKind::ARMV8R: |
218 | 2 | return "8R"; |
219 | 0 | } |
220 | 0 | } |
221 | | |
222 | 5.12k | StringRef ARMTargetInfo::getCPUProfile() const { |
223 | 5.12k | switch (ArchProfile) { |
224 | 2.46k | case llvm::ARM::ProfileKind::A: |
225 | 2.46k | return "A"; |
226 | 43 | case llvm::ARM::ProfileKind::R: |
227 | 43 | return "R"; |
228 | 1.63k | case llvm::ARM::ProfileKind::M: |
229 | 1.63k | return "M"; |
230 | 980 | default: |
231 | 980 | return ""; |
232 | 0 | } |
233 | 0 | } |
234 | | |
235 | | ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple, |
236 | | const TargetOptions &Opts) |
237 | | : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0), |
238 | 3.17k | HW_FP(0) { |
239 | 3.17k | |
240 | 3.17k | switch (getTriple().getOS()) { |
241 | 10 | case llvm::Triple::NetBSD: |
242 | 10 | case llvm::Triple::OpenBSD: |
243 | 10 | PtrDiffType = SignedLong; |
244 | 10 | break; |
245 | 3.16k | default: |
246 | 3.16k | PtrDiffType = SignedInt; |
247 | 3.16k | break; |
248 | 3.17k | } |
249 | 3.17k | |
250 | 3.17k | // Cache arch related info. |
251 | 3.17k | setArchInfo(); |
252 | 3.17k | |
253 | 3.17k | // {} in inline assembly are neon specifiers, not assembly variant |
254 | 3.17k | // specifiers. |
255 | 3.17k | NoAsmVariants = true; |
256 | 3.17k | |
257 | 3.17k | // FIXME: This duplicates code from the driver that sets the -target-abi |
258 | 3.17k | // option - this code is used if -target-abi isn't passed and should |
259 | 3.17k | // be unified in some way. |
260 | 3.17k | if (Triple.isOSBinFormatMachO()3.17k ) { |
261 | 2.63k | // The backend is hardwired to assume AAPCS for M-class processors, ensure |
262 | 2.63k | // the frontend matches that. |
263 | 2.63k | if (Triple.getEnvironment() == llvm::Triple::EABI || |
264 | 2.19k | Triple.getOS() == llvm::Triple::UnknownOS || |
265 | 2.63k | ArchProfile == llvm::ARM::ProfileKind::M1.40k ) { |
266 | 1.23k | setABI("aapcs"); |
267 | 2.63k | } else if (1.40k Triple.isWatchABI()1.40k ) { |
268 | 579 | setABI("aapcs16"); |
269 | 1.40k | } else { |
270 | 821 | setABI("apcs-gnu"); |
271 | 821 | } |
272 | 3.17k | } else if (536 Triple.isOSWindows()536 ) { |
273 | 69 | // FIXME: this is invalid for WindowsCE |
274 | 69 | setABI("aapcs"); |
275 | 536 | } else { |
276 | 467 | // Select the default based on the platform. |
277 | 467 | switch (Triple.getEnvironment()) { |
278 | 143 | case llvm::Triple::Android: |
279 | 143 | case llvm::Triple::GNUEABI: |
280 | 143 | case llvm::Triple::GNUEABIHF: |
281 | 143 | case llvm::Triple::MuslEABI: |
282 | 143 | case llvm::Triple::MuslEABIHF: |
283 | 143 | setABI("aapcs-linux"); |
284 | 143 | break; |
285 | 149 | case llvm::Triple::EABIHF: |
286 | 149 | case llvm::Triple::EABI: |
287 | 149 | setABI("aapcs"); |
288 | 149 | break; |
289 | 17 | case llvm::Triple::GNU: |
290 | 17 | setABI("apcs-gnu"); |
291 | 17 | break; |
292 | 158 | default: |
293 | 158 | if (Triple.getOS() == llvm::Triple::NetBSD) |
294 | 0 | setABI("apcs-gnu"); |
295 | 158 | else if (158 Triple.getOS() == llvm::Triple::OpenBSD158 ) |
296 | 1 | setABI("aapcs-linux"); |
297 | 158 | else |
298 | 157 | setABI("aapcs"); |
299 | 143 | break; |
300 | 3.17k | } |
301 | 3.17k | } |
302 | 3.17k | |
303 | 3.17k | // ARM targets default to using the ARM C++ ABI. |
304 | 3.17k | TheCXXABI.set(TargetCXXABI::GenericARM); |
305 | 3.17k | |
306 | 3.17k | // ARM has atomics up to 8 bytes |
307 | 3.17k | setAtomic(); |
308 | 3.17k | |
309 | 3.17k | // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS) |
310 | 3.17k | if (IsAAPCS && 3.17k (Triple.getEnvironment() != llvm::Triple::Android)1.75k ) |
311 | 1.74k | MaxVectorAlign = 64; |
312 | 3.17k | |
313 | 3.17k | // Do force alignment of members that follow zero length bitfields. If |
314 | 3.17k | // the alignment of the zero-length bitfield is greater than the member |
315 | 3.17k | // that follows it, `bar', `bar' will be aligned as the type of the |
316 | 3.17k | // zero length bitfield. |
317 | 3.17k | UseZeroLengthBitfieldAlignment = true; |
318 | 3.17k | |
319 | 3.17k | if (Triple.getOS() == llvm::Triple::Linux || |
320 | 2.99k | Triple.getOS() == llvm::Triple::UnknownOS) |
321 | 1.23k | this->MCountName = Opts.EABIVersion == llvm::EABI::GNU |
322 | 9 | ? "\01__gnu_mcount_nc" |
323 | 1.22k | : "\01mcount"; |
324 | 3.17k | } |
325 | | |
326 | 2.10k | StringRef ARMTargetInfo::getABI() const { return ABI; } |
327 | | |
328 | 5.96k | bool ARMTargetInfo::setABI(const std::string &Name) { |
329 | 5.96k | ABI = Name; |
330 | 5.96k | |
331 | 5.96k | // The defaults (above) are for AAPCS, check if we need to change them. |
332 | 5.96k | // |
333 | 5.96k | // FIXME: We need support for -meabi... we could just mangle it into the |
334 | 5.96k | // name. |
335 | 5.96k | if (Name == "apcs-gnu" || 5.96k Name == "aapcs16"4.39k ) { |
336 | 2.71k | setABIAPCS(Name == "aapcs16"); |
337 | 2.71k | return true; |
338 | 2.71k | } |
339 | 3.24k | if (3.24k Name == "aapcs" || 3.24k Name == "aapcs-vfp"194 || Name == "aapcs-linux"193 ) { |
340 | 3.24k | setABIAAPCS(); |
341 | 3.24k | return true; |
342 | 3.24k | } |
343 | 0 | return false; |
344 | 0 | } |
345 | | |
346 | | // FIXME: This should be based on Arch attributes, not CPU names. |
347 | | bool ARMTargetInfo::initFeatureMap( |
348 | | llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU, |
349 | 3.18k | const std::vector<std::string> &FeaturesVec) const { |
350 | 3.18k | |
351 | 3.18k | std::vector<StringRef> TargetFeatures; |
352 | 3.18k | llvm::ARM::ArchKind Arch = llvm::ARM::parseArch(getTriple().getArchName()); |
353 | 3.18k | |
354 | 3.18k | // get default FPU features |
355 | 3.18k | unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch); |
356 | 3.18k | llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures); |
357 | 3.18k | |
358 | 3.18k | // get default Extension features |
359 | 3.18k | unsigned Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch); |
360 | 3.18k | llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures); |
361 | 3.18k | |
362 | 3.18k | for (auto Feature : TargetFeatures) |
363 | 36.7k | if (36.7k Feature[0] == '+'36.7k ) |
364 | 10.2k | Features[Feature.drop_front(1)] = true; |
365 | 3.18k | |
366 | 3.18k | // Enable or disable thumb-mode explicitly per function to enable mixed |
367 | 3.18k | // ARM and Thumb code generation. |
368 | 3.18k | if (isThumb()) |
369 | 2.74k | Features["thumb-mode"] = true; |
370 | 3.18k | else |
371 | 445 | Features["thumb-mode"] = false; |
372 | 3.18k | |
373 | 3.18k | // Convert user-provided arm and thumb GNU target attributes to |
374 | 3.18k | // [-|+]thumb-mode target features respectively. |
375 | 3.18k | std::vector<std::string> UpdatedFeaturesVec(FeaturesVec); |
376 | 7.50k | for (auto &Feature : UpdatedFeaturesVec) { |
377 | 7.50k | if (Feature.compare("+arm") == 0) |
378 | 4 | Feature = "-thumb-mode"; |
379 | 7.50k | else if (7.50k Feature.compare("+thumb") == 07.50k ) |
380 | 4 | Feature = "+thumb-mode"; |
381 | 7.50k | } |
382 | 3.18k | |
383 | 3.18k | return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec); |
384 | 3.18k | } |
385 | | |
386 | | |
387 | | bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, |
388 | 3.17k | DiagnosticsEngine &Diags) { |
389 | 3.17k | FPU = 0; |
390 | 3.17k | CRC = 0; |
391 | 3.17k | Crypto = 0; |
392 | 3.17k | DSP = 0; |
393 | 3.17k | Unaligned = 1; |
394 | 3.17k | SoftFloat = SoftFloatABI = false; |
395 | 3.17k | HWDiv = 0; |
396 | 3.17k | |
397 | 3.17k | // This does not diagnose illegal cases like having both |
398 | 3.17k | // "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp". |
399 | 3.17k | uint32_t HW_FP_remove = 0; |
400 | 20.2k | for (const auto &Feature : Features) { |
401 | 20.2k | if (Feature == "+soft-float"20.2k ) { |
402 | 901 | SoftFloat = true; |
403 | 20.2k | } else if (19.3k Feature == "+soft-float-abi"19.3k ) { |
404 | 1.72k | SoftFloatABI = true; |
405 | 19.3k | } else if (17.6k Feature == "+vfp2"17.6k ) { |
406 | 14 | FPU |= VFP2FPU; |
407 | 14 | HW_FP |= HW_FP_SP | HW_FP_DP; |
408 | 17.6k | } else if (17.6k Feature == "+vfp3"17.6k ) { |
409 | 879 | FPU |= VFP3FPU; |
410 | 879 | HW_FP |= HW_FP_SP | HW_FP_DP; |
411 | 17.6k | } else if (16.7k Feature == "+vfp4"16.7k ) { |
412 | 1.38k | FPU |= VFP4FPU; |
413 | 1.38k | HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP; |
414 | 16.7k | } else if (15.3k Feature == "+fp-armv8"15.3k ) { |
415 | 67 | FPU |= FPARMV8; |
416 | 67 | HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP; |
417 | 15.3k | } else if (15.3k Feature == "+neon"15.3k ) { |
418 | 1.62k | FPU |= NeonFPU; |
419 | 1.62k | HW_FP |= HW_FP_SP | HW_FP_DP; |
420 | 15.3k | } else if (13.7k Feature == "+hwdiv"13.7k ) { |
421 | 1.67k | HWDiv |= HWDivThumb; |
422 | 13.7k | } else if (12.0k Feature == "+hwdiv-arm"12.0k ) { |
423 | 1.02k | HWDiv |= HWDivARM; |
424 | 12.0k | } else if (11.0k Feature == "+crc"11.0k ) { |
425 | 55 | CRC = 1; |
426 | 11.0k | } else if (10.9k Feature == "+crypto"10.9k ) { |
427 | 32 | Crypto = 1; |
428 | 10.9k | } else if (10.9k Feature == "+dsp"10.9k ) { |
429 | 2.33k | DSP = 1; |
430 | 10.9k | } else if (8.58k Feature == "+fp-only-sp"8.58k ) { |
431 | 416 | HW_FP_remove |= HW_FP_DP; |
432 | 8.58k | } else if (8.16k Feature == "+strict-align"8.16k ) { |
433 | 1.54k | Unaligned = 0; |
434 | 8.16k | } else if (6.61k Feature == "+fp16"6.61k ) { |
435 | 21 | HW_FP |= HW_FP_HP; |
436 | 21 | } |
437 | 20.2k | } |
438 | 3.17k | HW_FP &= ~HW_FP_remove; |
439 | 3.17k | |
440 | 3.17k | switch (ArchVersion) { |
441 | 228 | case 6: |
442 | 228 | if (ArchProfile == llvm::ARM::ProfileKind::M) |
443 | 188 | LDREX = 0; |
444 | 40 | else if (40 ArchKind == llvm::ARM::ArchKind::ARMV6K40 ) |
445 | 4 | LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; |
446 | 40 | else |
447 | 36 | LDREX = LDREX_W; |
448 | 228 | break; |
449 | 2.71k | case 7: |
450 | 2.71k | if (ArchProfile == llvm::ARM::ProfileKind::M) |
451 | 631 | LDREX = LDREX_W | LDREX_H | LDREX_B; |
452 | 2.71k | else |
453 | 2.08k | LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; |
454 | 2.71k | break; |
455 | 72 | case 8: |
456 | 72 | LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B; |
457 | 3.17k | } |
458 | 3.17k | |
459 | 3.17k | if (3.17k !(FPU & NeonFPU) && 3.17k FPMath == FP_Neon1.55k ) { |
460 | 2 | Diags.Report(diag::err_target_unsupported_fpmath) << "neon"; |
461 | 2 | return false; |
462 | 2 | } |
463 | 3.16k | |
464 | 3.16k | if (3.16k FPMath == FP_Neon3.16k ) |
465 | 1 | Features.push_back("+neonfp"); |
466 | 3.16k | else if (3.16k FPMath == FP_VFP3.16k ) |
467 | 5 | Features.push_back("-neonfp"); |
468 | 3.16k | |
469 | 3.16k | // Remove front-end specific options which the backend handles differently. |
470 | 3.16k | auto Feature = std::find(Features.begin(), Features.end(), "+soft-float-abi"); |
471 | 3.16k | if (Feature != Features.end()) |
472 | 1.72k | Features.erase(Feature); |
473 | 3.17k | |
474 | 3.17k | return true; |
475 | 3.17k | } |
476 | | |
477 | 918 | bool ARMTargetInfo::hasFeature(StringRef Feature) const { |
478 | 918 | return llvm::StringSwitch<bool>(Feature) |
479 | 918 | .Case("arm", true) |
480 | 918 | .Case("aarch32", true) |
481 | 918 | .Case("softfloat", SoftFloat) |
482 | 918 | .Case("thumb", isThumb()) |
483 | 879 | .Case("neon", (FPU & NeonFPU) && !SoftFloat) |
484 | 888 | .Case("vfp", FPU && !SoftFloat) |
485 | 918 | .Case("hwdiv", HWDiv & HWDivThumb) |
486 | 918 | .Case("hwdiv-arm", HWDiv & HWDivARM) |
487 | 918 | .Default(false); |
488 | 918 | } |
489 | | |
490 | 0 | bool ARMTargetInfo::isValidCPUName(StringRef Name) const { |
491 | 0 | return Name == "generic" || |
492 | 0 | llvm::ARM::parseCPUArch(Name) != llvm::ARM::ArchKind::INVALID; |
493 | 0 | } |
494 | | |
495 | 2.79k | bool ARMTargetInfo::setCPU(const std::string &Name) { |
496 | 2.79k | if (Name != "generic") |
497 | 1.95k | setArchInfo(llvm::ARM::parseCPUArch(Name)); |
498 | 2.79k | |
499 | 2.79k | if (ArchKind == llvm::ARM::ArchKind::INVALID) |
500 | 1 | return false; |
501 | 2.79k | setAtomic(); |
502 | 2.79k | CPU = Name; |
503 | 2.79k | return true; |
504 | 2.79k | } |
505 | | |
506 | 8 | bool ARMTargetInfo::setFPMath(StringRef Name) { |
507 | 8 | if (Name == "neon"8 ) { |
508 | 3 | FPMath = FP_Neon; |
509 | 3 | return true; |
510 | 5 | } else if (5 Name == "vfp" || 5 Name == "vfp2"3 || Name == "vfp3"2 || |
511 | 5 | Name == "vfp4"1 ) { |
512 | 5 | FPMath = FP_VFP; |
513 | 5 | return true; |
514 | 5 | } |
515 | 0 | return false; |
516 | 0 | } |
517 | | |
518 | | void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts, |
519 | 3 | MacroBuilder &Builder) const { |
520 | 3 | Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); |
521 | 3 | } |
522 | | |
523 | | void ARMTargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts, |
524 | 1 | MacroBuilder &Builder) const { |
525 | 1 | // Also include the ARMv8.1-A defines |
526 | 1 | getTargetDefinesARMV81A(Opts, Builder); |
527 | 1 | } |
528 | | |
529 | | void ARMTargetInfo::getTargetDefines(const LangOptions &Opts, |
530 | 3.16k | MacroBuilder &Builder) const { |
531 | 3.16k | // Target identification. |
532 | 3.16k | Builder.defineMacro("__arm"); |
533 | 3.16k | Builder.defineMacro("__arm__"); |
534 | 3.16k | // For bare-metal none-eabi. |
535 | 3.16k | if (getTriple().getOS() == llvm::Triple::UnknownOS && |
536 | 1.06k | (getTriple().getEnvironment() == llvm::Triple::EABI || |
537 | 952 | getTriple().getEnvironment() == llvm::Triple::EABIHF)) |
538 | 119 | Builder.defineMacro("__ELF__"); |
539 | 3.16k | |
540 | 3.16k | // Target properties. |
541 | 3.16k | Builder.defineMacro("__REGISTER_PREFIX__", ""); |
542 | 3.16k | |
543 | 3.16k | // Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU |
544 | 3.16k | // happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__. |
545 | 3.16k | if (getTriple().isWatchABI()) |
546 | 579 | Builder.defineMacro("__ARM_ARCH_7K__", "2"); |
547 | 3.16k | |
548 | 3.16k | if (!CPUAttr.empty()) |
549 | 3.16k | Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__"); |
550 | 3.16k | |
551 | 3.16k | // ACLE 6.4.1 ARM/Thumb instruction set architecture |
552 | 3.16k | // __ARM_ARCH is defined as an integer value indicating the current ARM ISA |
553 | 3.16k | Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion)); |
554 | 3.16k | |
555 | 3.16k | if (ArchVersion >= 83.16k ) { |
556 | 72 | // ACLE 6.5.7 Crypto Extension |
557 | 72 | if (Crypto) |
558 | 30 | Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1"); |
559 | 72 | // ACLE 6.5.8 CRC32 Extension |
560 | 72 | if (CRC) |
561 | 55 | Builder.defineMacro("__ARM_FEATURE_CRC32", "1"); |
562 | 72 | // ACLE 6.5.10 Numeric Maximum and Minimum |
563 | 72 | Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1"); |
564 | 72 | // ACLE 6.5.9 Directed Rounding |
565 | 72 | Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1"); |
566 | 72 | } |
567 | 3.16k | |
568 | 3.16k | // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA. It |
569 | 3.16k | // is not defined for the M-profile. |
570 | 3.16k | // NOTE that the default profile is assumed to be 'A' |
571 | 3.16k | if (CPUProfile.empty() || 3.16k ArchProfile != llvm::ARM::ProfileKind::M2.61k ) |
572 | 2.33k | Builder.defineMacro("__ARM_ARCH_ISA_ARM", "1"); |
573 | 3.16k | |
574 | 3.16k | // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original |
575 | 3.16k | // Thumb ISA (including v6-M and v8-M Baseline). It is set to 2 if the |
576 | 3.16k | // core supports the Thumb-2 ISA as found in the v6T2 architecture and all |
577 | 3.16k | // v7 and v8 architectures excluding v8-M Baseline. |
578 | 3.16k | if (supportsThumb2()) |
579 | 2.78k | Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2"); |
580 | 378 | else if (378 supportsThumb()378 ) |
581 | 373 | Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1"); |
582 | 3.16k | |
583 | 3.16k | // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit |
584 | 3.16k | // instruction set such as ARM or Thumb. |
585 | 3.16k | Builder.defineMacro("__ARM_32BIT_STATE", "1"); |
586 | 3.16k | |
587 | 3.16k | // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex) |
588 | 3.16k | |
589 | 3.16k | // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset. |
590 | 3.16k | if (!CPUProfile.empty()) |
591 | 2.61k | Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'"); |
592 | 3.16k | |
593 | 3.16k | // ACLE 6.4.3 Unaligned access supported in hardware |
594 | 3.16k | if (Unaligned) |
595 | 1.61k | Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); |
596 | 3.16k | |
597 | 3.16k | // ACLE 6.4.4 LDREX/STREX |
598 | 3.16k | if (LDREX) |
599 | 2.82k | Builder.defineMacro("__ARM_FEATURE_LDREX", "0x" + llvm::utohexstr(LDREX)); |
600 | 3.16k | |
601 | 3.16k | // ACLE 6.4.5 CLZ |
602 | 3.16k | if (ArchVersion == 5 || 3.16k (ArchVersion == 6 && 3.14k CPUProfile != "M"227 ) || |
603 | 3.10k | ArchVersion > 6) |
604 | 2.83k | Builder.defineMacro("__ARM_FEATURE_CLZ", "1"); |
605 | 3.16k | |
606 | 3.16k | // ACLE 6.5.1 Hardware Floating Point |
607 | 3.16k | if (HW_FP) |
608 | 2.36k | Builder.defineMacro("__ARM_FP", "0x" + llvm::utohexstr(HW_FP)); |
609 | 3.16k | |
610 | 3.16k | // ACLE predefines. |
611 | 3.16k | Builder.defineMacro("__ARM_ACLE", "200"); |
612 | 3.16k | |
613 | 3.16k | // FP16 support (we currently only support IEEE format). |
614 | 3.16k | Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1"); |
615 | 3.16k | Builder.defineMacro("__ARM_FP16_ARGS", "1"); |
616 | 3.16k | |
617 | 3.16k | // ACLE 6.5.3 Fused multiply-accumulate (FMA) |
618 | 3.16k | if (ArchVersion >= 7 && 3.16k (FPU & VFP4FPU)2.78k ) |
619 | 1.37k | Builder.defineMacro("__ARM_FEATURE_FMA", "1"); |
620 | 3.16k | |
621 | 3.16k | // Subtarget options. |
622 | 3.16k | |
623 | 3.16k | // FIXME: It's more complicated than this and we don't really support |
624 | 3.16k | // interworking. |
625 | 3.16k | // Windows on ARM does not "support" interworking |
626 | 3.16k | if (5 <= ArchVersion && 3.16k ArchVersion <= 83.02k && !getTriple().isOSWindows()3.02k ) |
627 | 2.95k | Builder.defineMacro("__THUMB_INTERWORK__"); |
628 | 3.16k | |
629 | 3.16k | if (ABI == "aapcs" || 3.16k ABI == "aapcs-linux"1.53k || ABI == "aapcs-vfp"1.39k ) { |
630 | 1.76k | // Embedded targets on Darwin follow AAPCS, but not EABI. |
631 | 1.76k | // Windows on ARM follows AAPCS VFP, but does not conform to EABI. |
632 | 1.76k | if (!getTriple().isOSBinFormatMachO() && 1.76k !getTriple().isOSWindows()521 ) |
633 | 452 | Builder.defineMacro("__ARM_EABI__"); |
634 | 1.76k | Builder.defineMacro("__ARM_PCS", "1"); |
635 | 1.76k | } |
636 | 3.16k | |
637 | 3.16k | if ((!SoftFloat && 3.16k !SoftFloatABI2.25k ) || ABI == "aapcs-vfp"1.72k || ABI == "aapcs16"1.72k ) |
638 | 1.43k | Builder.defineMacro("__ARM_PCS_VFP", "1"); |
639 | 3.16k | |
640 | 3.16k | if (SoftFloat) |
641 | 901 | Builder.defineMacro("__SOFTFP__"); |
642 | 3.16k | |
643 | 3.16k | if (ArchKind == llvm::ARM::ArchKind::XSCALE) |
644 | 0 | Builder.defineMacro("__XSCALE__"); |
645 | 3.16k | |
646 | 3.16k | if (isThumb()3.16k ) { |
647 | 2.72k | Builder.defineMacro("__THUMBEL__"); |
648 | 2.72k | Builder.defineMacro("__thumb__"); |
649 | 2.72k | if (supportsThumb2()) |
650 | 2.51k | Builder.defineMacro("__thumb2__"); |
651 | 2.72k | } |
652 | 3.16k | |
653 | 3.16k | // ACLE 6.4.9 32-bit SIMD instructions |
654 | 3.16k | if (ArchVersion >= 6 && 3.16k (CPUProfile != "M" || 3.00k CPUAttr == "7EM"824 )) |
655 | 2.59k | Builder.defineMacro("__ARM_FEATURE_SIMD32", "1"); |
656 | 3.16k | |
657 | 3.16k | // ACLE 6.4.10 Hardware Integer Divide |
658 | 3.16k | if (((HWDiv & HWDivThumb) && 3.16k isThumb()1.67k ) || |
659 | 3.16k | ((HWDiv & HWDivARM) && 1.56k !isThumb()68 )) { |
660 | 1.66k | Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); |
661 | 1.66k | Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1"); |
662 | 1.66k | } |
663 | 3.16k | |
664 | 3.16k | // Note, this is always on in gcc, even though it doesn't make sense. |
665 | 3.16k | Builder.defineMacro("__APCS_32__"); |
666 | 3.16k | |
667 | 3.16k | if (FPUModeIsVFP((FPUMode)FPU)3.16k ) { |
668 | 2.36k | Builder.defineMacro("__VFP_FP__"); |
669 | 2.36k | if (FPU & VFP2FPU) |
670 | 14 | Builder.defineMacro("__ARM_VFPV2__"); |
671 | 2.36k | if (FPU & VFP3FPU) |
672 | 878 | Builder.defineMacro("__ARM_VFPV3__"); |
673 | 2.36k | if (FPU & VFP4FPU) |
674 | 1.38k | Builder.defineMacro("__ARM_VFPV4__"); |
675 | 2.36k | if (FPU & FPARMV8) |
676 | 67 | Builder.defineMacro("__ARM_FPV5__"); |
677 | 2.36k | } |
678 | 3.16k | |
679 | 3.16k | // This only gets set when Neon instructions are actually available, unlike |
680 | 3.16k | // the VFP define, hence the soft float and arch check. This is subtly |
681 | 3.16k | // different from gcc, we follow the intent which was that it should be set |
682 | 3.16k | // when Neon instructions are actually available. |
683 | 3.16k | if ((FPU & NeonFPU) && 3.16k !SoftFloat1.62k && ArchVersion >= 71.61k ) { |
684 | 1.61k | Builder.defineMacro("__ARM_NEON", "1"); |
685 | 1.61k | Builder.defineMacro("__ARM_NEON__"); |
686 | 1.61k | // current AArch32 NEON implementations do not support double-precision |
687 | 1.61k | // floating-point even when it is present in VFP. |
688 | 1.61k | Builder.defineMacro("__ARM_NEON_FP", |
689 | 1.61k | "0x" + llvm::utohexstr(HW_FP & ~HW_FP_DP)); |
690 | 1.61k | } |
691 | 3.16k | |
692 | 3.16k | Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", Opts.ShortWChar ? "2"2 : "4"3.15k ); |
693 | 3.16k | |
694 | 3.16k | Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1"2 : "4"3.15k ); |
695 | 3.16k | |
696 | 3.16k | if (ArchVersion >= 6 && 3.16k CPUAttr != "6M"3.00k && CPUAttr != "8M_BASE"2.82k ) { |
697 | 2.81k | Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); |
698 | 2.81k | Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); |
699 | 2.81k | Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4"); |
700 | 2.81k | Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8"); |
701 | 2.81k | } |
702 | 3.16k | |
703 | 3.16k | // ACLE 6.4.7 DSP instructions |
704 | 3.16k | if (DSP3.16k ) { |
705 | 2.33k | Builder.defineMacro("__ARM_FEATURE_DSP", "1"); |
706 | 2.33k | } |
707 | 3.16k | |
708 | 3.16k | // ACLE 6.4.8 Saturation instructions |
709 | 3.16k | bool SAT = false; |
710 | 3.16k | if ((ArchVersion == 6 && 3.16k CPUProfile != "M"227 ) || ArchVersion > 63.12k ) { |
711 | 2.82k | Builder.defineMacro("__ARM_FEATURE_SAT", "1"); |
712 | 2.82k | SAT = true; |
713 | 2.82k | } |
714 | 3.16k | |
715 | 3.16k | // ACLE 6.4.6 Q (saturation) flag |
716 | 3.16k | if (DSP || 3.16k SAT825 ) |
717 | 2.82k | Builder.defineMacro("__ARM_FEATURE_QBIT", "1"); |
718 | 3.16k | |
719 | 3.16k | if (Opts.UnsafeFPMath) |
720 | 2 | Builder.defineMacro("__ARM_FP_FAST", "1"); |
721 | 3.16k | |
722 | 3.16k | switch (ArchKind) { |
723 | 3.15k | default: |
724 | 3.15k | break; |
725 | 2 | case llvm::ARM::ArchKind::ARMV8_1A: |
726 | 2 | getTargetDefinesARMV81A(Opts, Builder); |
727 | 2 | break; |
728 | 1 | case llvm::ARM::ArchKind::ARMV8_2A: |
729 | 1 | getTargetDefinesARMV82A(Opts, Builder); |
730 | 1 | break; |
731 | 3.16k | } |
732 | 3.16k | } |
733 | | |
734 | | const Builtin::Info ARMTargetInfo::BuiltinInfo[] = { |
735 | | #define BUILTIN(ID, TYPE, ATTRS) \ |
736 | | {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, |
737 | | #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ |
738 | | {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr}, |
739 | | #include "clang/Basic/BuiltinsNEON.def" |
740 | | |
741 | | #define BUILTIN(ID, TYPE, ATTRS) \ |
742 | | {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, |
743 | | #define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \ |
744 | | {#ID, TYPE, ATTRS, nullptr, LANG, nullptr}, |
745 | | #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \ |
746 | | {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr}, |
747 | | #define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \ |
748 | | {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE}, |
749 | | #include "clang/Basic/BuiltinsARM.def" |
750 | | }; |
751 | | |
752 | 3.16k | ArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const { |
753 | 3.16k | return llvm::makeArrayRef(BuiltinInfo, clang::ARM::LastTSBuiltin - |
754 | 3.16k | Builtin::FirstTSBuiltin); |
755 | 3.16k | } |
756 | | |
757 | 536 | bool ARMTargetInfo::isCLZForZeroUndef() const { return false; } |
758 | 2.18k | TargetInfo::BuiltinVaListKind ARMTargetInfo::getBuiltinVaListKind() const { |
759 | 2.18k | return IsAAPCS |
760 | 1.17k | ? AAPCSABIBuiltinVaList |
761 | 1.00k | : (getTriple().isWatchABI() ? 1.00k TargetInfo::CharPtrBuiltinVaList407 |
762 | 1.00k | : TargetInfo::VoidPtrBuiltinVaList); |
763 | 2.18k | } |
764 | | |
765 | | const char *const ARMTargetInfo::GCCRegNames[] = { |
766 | | // Integer registers |
767 | | "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", |
768 | | "r12", "sp", "lr", "pc", |
769 | | |
770 | | // Float registers |
771 | | "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", |
772 | | "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22", |
773 | | "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", |
774 | | |
775 | | // Double registers |
776 | | "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", |
777 | | "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22", |
778 | | "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", |
779 | | |
780 | | // Quad registers |
781 | | "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", |
782 | | "q12", "q13", "q14", "q15"}; |
783 | | |
784 | 1.38k | ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const { |
785 | 1.38k | return llvm::makeArrayRef(GCCRegNames); |
786 | 1.38k | } |
787 | | |
788 | | const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = { |
789 | | {{"a1"}, "r0"}, {{"a2"}, "r1"}, {{"a3"}, "r2"}, {{"a4"}, "r3"}, |
790 | | {{"v1"}, "r4"}, {{"v2"}, "r5"}, {{"v3"}, "r6"}, {{"v4"}, "r7"}, |
791 | | {{"v5"}, "r8"}, {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"}, |
792 | | {{"ip"}, "r12"}, {{"r13"}, "sp"}, {{"r14"}, "lr"}, {{"r15"}, "pc"}, |
793 | | // The S, D and Q registers overlap, but aren't really aliases; we |
794 | | // don't want to substitute one of these for a different-sized one. |
795 | | }; |
796 | | |
797 | 1.32k | ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const { |
798 | 1.32k | return llvm::makeArrayRef(GCCRegAliases); |
799 | 1.32k | } |
800 | | |
801 | | bool ARMTargetInfo::validateAsmConstraint( |
802 | 27 | const char *&Name, TargetInfo::ConstraintInfo &Info) const { |
803 | 27 | switch (*Name) { |
804 | 1 | default: |
805 | 1 | break; |
806 | 20 | case 'l': // r0-r7 |
807 | 20 | case 'h': // r8-r15 |
808 | 20 | case 't': // VFP Floating point register single precision |
809 | 20 | case 'w': // VFP Floating point register double precision |
810 | 20 | Info.setAllowsRegister(); |
811 | 20 | return true; |
812 | 0 | case 'I': |
813 | 0 | case 'J': |
814 | 0 | case 'K': |
815 | 0 | case 'L': |
816 | 0 | case 'M': |
817 | 0 | // FIXME |
818 | 0 | return true; |
819 | 4 | case 'Q': // A memory address that is a single base register. |
820 | 4 | Info.setAllowsMemory(); |
821 | 4 | return true; |
822 | 2 | case 'U': // a memory reference... |
823 | 2 | switch (Name[1]) { |
824 | 2 | case 'q': // ...ARMV4 ldrsb |
825 | 2 | case 'v': // ...VFP load/store (reg+constant offset) |
826 | 2 | case 'y': // ...iWMMXt load/store |
827 | 2 | case 't': // address valid for load/store opaque types wider |
828 | 2 | // than 128-bits |
829 | 2 | case 'n': // valid address for Neon doubleword vector load/store |
830 | 2 | case 'm': // valid address for Neon element and structure load/store |
831 | 2 | case 's': // valid address for non-offset loads/stores of quad-word |
832 | 2 | // values in four ARM registers |
833 | 2 | Info.setAllowsMemory(); |
834 | 2 | Name++; |
835 | 2 | return true; |
836 | 1 | } |
837 | 1 | } |
838 | 1 | return false; |
839 | 1 | } |
840 | | |
841 | 309 | std::string ARMTargetInfo::convertConstraint(const char *&Constraint) const { |
842 | 309 | std::string R; |
843 | 309 | switch (*Constraint) { |
844 | 1 | case 'U': // Two-character constraint; add "^" hint for later parsing. |
845 | 1 | R = std::string("^") + std::string(Constraint, 2); |
846 | 1 | Constraint++; |
847 | 1 | break; |
848 | 5 | case 'p': // 'p' should be translated to 'r' by default. |
849 | 5 | R = std::string("r"); |
850 | 5 | break; |
851 | 303 | default: |
852 | 303 | return std::string(1, *Constraint); |
853 | 6 | } |
854 | 6 | return R; |
855 | 6 | } |
856 | | |
857 | | bool ARMTargetInfo::validateConstraintModifier( |
858 | | StringRef Constraint, char Modifier, unsigned Size, |
859 | 203 | std::string &SuggestedModifier) const { |
860 | 203 | bool isOutput = (Constraint[0] == '='); |
861 | 203 | bool isInOut = (Constraint[0] == '+'); |
862 | 203 | |
863 | 203 | // Strip off constraint modifiers. |
864 | 310 | while (Constraint[0] == '=' || 310 Constraint[0] == '+'207 || Constraint[0] == '&'205 ) |
865 | 107 | Constraint = Constraint.substr(1); |
866 | 203 | |
867 | 203 | switch (Constraint[0]) { |
868 | 55 | default: |
869 | 55 | break; |
870 | 148 | case 'r': { |
871 | 148 | switch (Modifier) { |
872 | 140 | default: |
873 | 140 | return (isInOut || isOutput138 || Size <= 6456 ); |
874 | 8 | case 'q': |
875 | 8 | // A register of size 32 cannot fit a vector type. |
876 | 8 | return false; |
877 | 55 | } |
878 | 55 | } |
879 | 55 | } |
880 | 55 | |
881 | 55 | return true; |
882 | 55 | } |
883 | 502 | const char *ARMTargetInfo::getClobbers() const { |
884 | 502 | // FIXME: Is this really right? |
885 | 502 | return ""; |
886 | 502 | } |
887 | | |
888 | | TargetInfo::CallingConvCheckResult |
889 | 524 | ARMTargetInfo::checkCallingConvention(CallingConv CC) const { |
890 | 524 | switch (CC) { |
891 | 524 | case CC_AAPCS: |
892 | 524 | case CC_AAPCS_VFP: |
893 | 524 | case CC_Swift: |
894 | 524 | case CC_OpenCLKernel: |
895 | 524 | return CCCR_OK; |
896 | 0 | default: |
897 | 0 | return CCCR_Warning; |
898 | 0 | } |
899 | 0 | } |
900 | | |
901 | 16 | int ARMTargetInfo::getEHDataRegisterNumber(unsigned RegNo) const { |
902 | 16 | if (RegNo == 0) |
903 | 8 | return 0; |
904 | 8 | if (8 RegNo == 18 ) |
905 | 8 | return 1; |
906 | 0 | return -1; |
907 | 0 | } |
908 | | |
909 | 0 | bool ARMTargetInfo::hasSjLjLowering() const { return true; } |
910 | | |
911 | | ARMleTargetInfo::ARMleTargetInfo(const llvm::Triple &Triple, |
912 | | const TargetOptions &Opts) |
913 | 3.15k | : ARMTargetInfo(Triple, Opts) {} |
914 | | |
915 | | void ARMleTargetInfo::getTargetDefines(const LangOptions &Opts, |
916 | 3.14k | MacroBuilder &Builder) const { |
917 | 3.14k | Builder.defineMacro("__ARMEL__"); |
918 | 3.14k | ARMTargetInfo::getTargetDefines(Opts, Builder); |
919 | 3.14k | } |
920 | | |
921 | | ARMbeTargetInfo::ARMbeTargetInfo(const llvm::Triple &Triple, |
922 | | const TargetOptions &Opts) |
923 | 14 | : ARMTargetInfo(Triple, Opts) {} |
924 | | |
925 | | void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts, |
926 | 14 | MacroBuilder &Builder) const { |
927 | 14 | Builder.defineMacro("__ARMEB__"); |
928 | 14 | Builder.defineMacro("__ARM_BIG_ENDIAN"); |
929 | 14 | ARMTargetInfo::getTargetDefines(Opts, Builder); |
930 | 14 | } |
931 | | |
932 | | WindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple, |
933 | | const TargetOptions &Opts) |
934 | 69 | : WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) { |
935 | 69 | WCharType = UnsignedShort; |
936 | 69 | SizeType = UnsignedInt; |
937 | 69 | } |
938 | | |
939 | | void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts, |
940 | 60 | MacroBuilder &Builder) const { |
941 | 60 | WindowsTargetInfo<ARMleTargetInfo>::getVisualStudioDefines(Opts, Builder); |
942 | 60 | |
943 | 60 | // FIXME: this is invalid for WindowsCE |
944 | 60 | Builder.defineMacro("_M_ARM_NT", "1"); |
945 | 60 | Builder.defineMacro("_M_ARMT", "_M_ARM"); |
946 | 60 | Builder.defineMacro("_M_THUMB", "_M_ARM"); |
947 | 60 | |
948 | 60 | assert((Triple.getArch() == llvm::Triple::arm || |
949 | 60 | Triple.getArch() == llvm::Triple::thumb) && |
950 | 60 | "invalid architecture for Windows ARM target info"); |
951 | 60 | unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 44 : 656 ; |
952 | 60 | Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset)); |
953 | 60 | |
954 | 60 | // TODO map the complete set of values |
955 | 60 | // 31: VFPv3 40: VFPv4 |
956 | 60 | Builder.defineMacro("_M_ARM_FP", "31"); |
957 | 60 | } |
958 | | |
959 | | TargetInfo::BuiltinVaListKind |
960 | 65 | WindowsARMTargetInfo::getBuiltinVaListKind() const { |
961 | 65 | return TargetInfo::CharPtrBuiltinVaList; |
962 | 65 | } |
963 | | |
964 | | TargetInfo::CallingConvCheckResult |
965 | 16 | WindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const { |
966 | 16 | switch (CC) { |
967 | 1 | case CC_X86StdCall: |
968 | 1 | case CC_X86ThisCall: |
969 | 1 | case CC_X86FastCall: |
970 | 1 | case CC_X86VectorCall: |
971 | 1 | return CCCR_Ignore; |
972 | 15 | case CC_C: |
973 | 15 | case CC_OpenCLKernel: |
974 | 15 | return CCCR_OK; |
975 | 0 | default: |
976 | 0 | return CCCR_Warning; |
977 | 0 | } |
978 | 0 | } |
979 | | |
980 | | // Windows ARM + Itanium C++ ABI Target |
981 | | ItaniumWindowsARMleTargetInfo::ItaniumWindowsARMleTargetInfo( |
982 | | const llvm::Triple &Triple, const TargetOptions &Opts) |
983 | 8 | : WindowsARMTargetInfo(Triple, Opts) { |
984 | 8 | TheCXXABI.set(TargetCXXABI::GenericARM); |
985 | 8 | } |
986 | | |
987 | | void ItaniumWindowsARMleTargetInfo::getTargetDefines( |
988 | 8 | const LangOptions &Opts, MacroBuilder &Builder) const { |
989 | 8 | WindowsARMTargetInfo::getTargetDefines(Opts, Builder); |
990 | 8 | |
991 | 8 | if (Opts.MSVCCompat) |
992 | 1 | WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder); |
993 | 8 | } |
994 | | |
995 | | // Windows ARM, MS (C++) ABI |
996 | | MicrosoftARMleTargetInfo::MicrosoftARMleTargetInfo(const llvm::Triple &Triple, |
997 | | const TargetOptions &Opts) |
998 | 59 | : WindowsARMTargetInfo(Triple, Opts) { |
999 | 59 | TheCXXABI.set(TargetCXXABI::Microsoft); |
1000 | 59 | } |
1001 | | |
1002 | | void MicrosoftARMleTargetInfo::getTargetDefines(const LangOptions &Opts, |
1003 | 59 | MacroBuilder &Builder) const { |
1004 | 59 | WindowsARMTargetInfo::getTargetDefines(Opts, Builder); |
1005 | 59 | WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder); |
1006 | 59 | } |
1007 | | |
1008 | | MinGWARMTargetInfo::MinGWARMTargetInfo(const llvm::Triple &Triple, |
1009 | | const TargetOptions &Opts) |
1010 | 2 | : WindowsARMTargetInfo(Triple, Opts) { |
1011 | 2 | TheCXXABI.set(TargetCXXABI::GenericARM); |
1012 | 2 | } |
1013 | | |
1014 | | void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts, |
1015 | 2 | MacroBuilder &Builder) const { |
1016 | 2 | WindowsARMTargetInfo::getTargetDefines(Opts, Builder); |
1017 | 2 | DefineStd(Builder, "WIN32", Opts); |
1018 | 2 | DefineStd(Builder, "WINNT", Opts); |
1019 | 2 | Builder.defineMacro("_ARM_"); |
1020 | 2 | addMinGWDefines(Opts, Builder); |
1021 | 2 | } |
1022 | | |
1023 | | CygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple, |
1024 | | const TargetOptions &Opts) |
1025 | 0 | : ARMleTargetInfo(Triple, Opts) { |
1026 | 0 | TLSSupported = false; |
1027 | 0 | WCharType = UnsignedShort; |
1028 | 0 | DoubleAlign = LongLongAlign = 64; |
1029 | 0 | resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"); |
1030 | 0 | } |
1031 | | |
1032 | | void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts, |
1033 | 0 | MacroBuilder &Builder) const { |
1034 | 0 | ARMleTargetInfo::getTargetDefines(Opts, Builder); |
1035 | 0 | Builder.defineMacro("_ARM_"); |
1036 | 0 | Builder.defineMacro("__CYGWIN__"); |
1037 | 0 | Builder.defineMacro("__CYGWIN32__"); |
1038 | 0 | DefineStd(Builder, "unix", Opts); |
1039 | 0 | if (Opts.CPlusPlus) |
1040 | 0 | Builder.defineMacro("_GNU_SOURCE"); |
1041 | 0 | } |
1042 | | |
1043 | | DarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple, |
1044 | | const TargetOptions &Opts) |
1045 | 2.63k | : DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) { |
1046 | 2.63k | HasAlignMac68kSupport = true; |
1047 | 2.63k | // iOS always has 64-bit atomic instructions. |
1048 | 2.63k | // FIXME: This should be based off of the target features in |
1049 | 2.63k | // ARMleTargetInfo. |
1050 | 2.63k | MaxAtomicInlineWidth = 64; |
1051 | 2.63k | |
1052 | 2.63k | if (Triple.isWatchABI()2.63k ) { |
1053 | 579 | // Darwin on iOS uses a variant of the ARM C++ ABI. |
1054 | 579 | TheCXXABI.set(TargetCXXABI::WatchOS); |
1055 | 579 | |
1056 | 579 | // The 32-bit ABI is silent on what ptrdiff_t should be, but given that |
1057 | 579 | // size_t is long, it's a bit weird for it to be int. |
1058 | 579 | PtrDiffType = SignedLong; |
1059 | 579 | |
1060 | 579 | // BOOL should be a real boolean on the new ABI |
1061 | 579 | UseSignedCharForObjCBool = false; |
1062 | 579 | } else |
1063 | 2.05k | TheCXXABI.set(TargetCXXABI::iOS); |
1064 | 2.63k | } |
1065 | | |
1066 | | void DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts, |
1067 | | const llvm::Triple &Triple, |
1068 | 2.62k | MacroBuilder &Builder) const { |
1069 | 2.62k | getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); |
1070 | 2.62k | } |
1071 | | |
1072 | | RenderScript32TargetInfo::RenderScript32TargetInfo(const llvm::Triple &Triple, |
1073 | | const TargetOptions &Opts) |
1074 | | : ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(), |
1075 | | Triple.getOSName(), |
1076 | | Triple.getEnvironmentName()), |
1077 | 1 | Opts) { |
1078 | 1 | IsRenderScriptTarget = true; |
1079 | 1 | LongWidth = LongAlign = 64; |
1080 | 1 | } |
1081 | | |
1082 | | void RenderScript32TargetInfo::getTargetDefines(const LangOptions &Opts, |
1083 | 1 | MacroBuilder &Builder) const { |
1084 | 1 | Builder.defineMacro("__RENDERSCRIPT__"); |
1085 | 1 | ARMleTargetInfo::getTargetDefines(Opts, Builder); |
1086 | 1 | } |