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