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