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