blob: b45717b0c86ab1dd6f10a7f20e2b168bd444c058 [file] [log] [blame]
Erich Keaneebba5922017-07-21 22:37:03 +00001//===--- ARM.h - Declare ARM target feature support -------------*- C++ -*-===//
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 declares ARM TargetInfo objects.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_ARM_H
15#define LLVM_CLANG_LIB_BASIC_TARGETS_ARM_H
16
17#include "OSTargets.h"
18#include "clang/Basic/TargetInfo.h"
19#include "clang/Basic/TargetOptions.h"
20#include "llvm/ADT/Triple.h"
21#include "llvm/Support/Compiler.h"
22#include "llvm/Support/TargetParser.h"
23
24namespace clang {
25namespace targets {
26
27class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo {
28 // Possible FPU choices.
29 enum FPUMode {
30 VFP2FPU = (1 << 0),
31 VFP3FPU = (1 << 1),
32 VFP4FPU = (1 << 2),
33 NeonFPU = (1 << 3),
34 FPARMV8 = (1 << 4)
35 };
36
37 // Possible HWDiv features.
38 enum HWDivMode { HWDivThumb = (1 << 0), HWDivARM = (1 << 1) };
39
40 static bool FPUModeIsVFP(FPUMode Mode) {
41 return Mode & (VFP2FPU | VFP3FPU | VFP4FPU | NeonFPU | FPARMV8);
42 }
43
44 static const TargetInfo::GCCRegAlias GCCRegAliases[];
45 static const char *const GCCRegNames[];
46
47 std::string ABI, CPU;
48
49 StringRef CPUProfile;
50 StringRef CPUAttr;
51
52 enum { FP_Default, FP_VFP, FP_Neon } FPMath;
53
54 unsigned ArchISA;
55 unsigned ArchKind = llvm::ARM::AK_ARMV4T;
56 unsigned ArchProfile;
57 unsigned ArchVersion;
58
59 unsigned FPU : 5;
60
61 unsigned IsAAPCS : 1;
62 unsigned HWDiv : 2;
63
64 // Initialized via features.
65 unsigned SoftFloat : 1;
66 unsigned SoftFloatABI : 1;
67
68 unsigned CRC : 1;
69 unsigned Crypto : 1;
70 unsigned DSP : 1;
71 unsigned Unaligned : 1;
72
73 enum {
74 LDREX_B = (1 << 0), /// byte (8-bit)
75 LDREX_H = (1 << 1), /// half (16-bit)
76 LDREX_W = (1 << 2), /// word (32-bit)
77 LDREX_D = (1 << 3), /// double (64-bit)
78 };
79
80 uint32_t LDREX;
81
82 // ACLE 6.5.1 Hardware floating point
83 enum {
84 HW_FP_HP = (1 << 1), /// half (16-bit)
85 HW_FP_SP = (1 << 2), /// single (32-bit)
86 HW_FP_DP = (1 << 3), /// double (64-bit)
87 };
88 uint32_t HW_FP;
89
90 static const Builtin::Info BuiltinInfo[];
91
92 void setABIAAPCS() {
93 IsAAPCS = true;
94
95 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
96 const llvm::Triple &T = getTriple();
97
98 // size_t is unsigned long on MachO-derived environments, NetBSD,
99 // OpenBSD and Bitrig.
100 if (T.isOSBinFormatMachO() || T.getOS() == llvm::Triple::NetBSD ||
101 T.getOS() == llvm::Triple::OpenBSD || T.getOS() == llvm::Triple::Bitrig)
102 SizeType = UnsignedLong;
103 else
104 SizeType = UnsignedInt;
105
106 switch (T.getOS()) {
107 case llvm::Triple::NetBSD:
108 case llvm::Triple::OpenBSD:
109 WCharType = SignedInt;
110 break;
111 case llvm::Triple::Win32:
112 WCharType = UnsignedShort;
113 break;
114 case llvm::Triple::Linux:
115 default:
116 // AAPCS 7.1.1, ARM-Linux ABI 2.4: type of wchar_t is unsigned int.
117 WCharType = UnsignedInt;
118 break;
119 }
120
121 UseBitFieldTypeAlignment = true;
122
123 ZeroLengthBitfieldBoundary = 0;
124
125 // Thumb1 add sp, #imm requires the immediate value be multiple of 4,
126 // so set preferred for small types to 32.
127 if (T.isOSBinFormatMachO()) {
128 resetDataLayout(BigEndian
129 ? "E-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
130 : "e-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
131 } else if (T.isOSWindows()) {
132 assert(!BigEndian && "Windows on ARM does not support big endian");
133 resetDataLayout("e"
134 "-m:w"
135 "-p:32:32"
136 "-i64:64"
137 "-v128:64:128"
138 "-a:0:32"
139 "-n32"
140 "-S64");
141 } else if (T.isOSNaCl()) {
142 assert(!BigEndian && "NaCl on ARM does not support big endian");
143 resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128");
144 } else {
145 resetDataLayout(BigEndian
146 ? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
147 : "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
148 }
149
150 // FIXME: Enumerated types are variable width in straight AAPCS.
151 }
152
153 void setABIAPCS(bool IsAAPCS16) {
154 const llvm::Triple &T = getTriple();
155
156 IsAAPCS = false;
157
158 if (IsAAPCS16)
159 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
160 else
161 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32;
162
163 // size_t is unsigned int on FreeBSD.
164 if (T.getOS() == llvm::Triple::FreeBSD)
165 SizeType = UnsignedInt;
166 else
167 SizeType = UnsignedLong;
168
169 // Revert to using SignedInt on apcs-gnu to comply with existing behaviour.
170 WCharType = SignedInt;
171
172 // Do not respect the alignment of bit-field types when laying out
173 // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc.
174 UseBitFieldTypeAlignment = false;
175
176 /// gcc forces the alignment to 4 bytes, regardless of the type of the
177 /// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in
178 /// gcc.
179 ZeroLengthBitfieldBoundary = 32;
180
181 if (T.isOSBinFormatMachO() && IsAAPCS16) {
182 assert(!BigEndian && "AAPCS16 does not support big-endian");
183 resetDataLayout("e-m:o-p:32:32-i64:64-a:0:32-n32-S128");
184 } else if (T.isOSBinFormatMachO())
185 resetDataLayout(
186 BigEndian
187 ? "E-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
188 : "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
189 else
190 resetDataLayout(
191 BigEndian
192 ? "E-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
193 : "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
194
195 // FIXME: Override "preferred align" for double and long long.
196 }
197
198 void setArchInfo() {
199 StringRef ArchName = getTriple().getArchName();
200
201 ArchISA = llvm::ARM::parseArchISA(ArchName);
202 CPU = llvm::ARM::getDefaultCPU(ArchName);
203 unsigned AK = llvm::ARM::parseArch(ArchName);
204 if (AK != llvm::ARM::AK_INVALID)
205 ArchKind = AK;
206 setArchInfo(ArchKind);
207 }
208
209 void setArchInfo(unsigned Kind) {
210 StringRef SubArch;
211
212 // cache TargetParser info
213 ArchKind = Kind;
214 SubArch = llvm::ARM::getSubArch(ArchKind);
215 ArchProfile = llvm::ARM::parseArchProfile(SubArch);
216 ArchVersion = llvm::ARM::parseArchVersion(SubArch);
217
218 // cache CPU related strings
219 CPUAttr = getCPUAttr();
220 CPUProfile = getCPUProfile();
221 }
222
223 void setAtomic() {
224 // when triple does not specify a sub arch,
225 // then we are not using inline atomics
226 bool ShouldUseInlineAtomic =
227 (ArchISA == llvm::ARM::IK_ARM && ArchVersion >= 6) ||
228 (ArchISA == llvm::ARM::IK_THUMB && ArchVersion >= 7);
229 // Cortex M does not support 8 byte atomics, while general Thumb2 does.
230 if (ArchProfile == llvm::ARM::PK_M) {
231 MaxAtomicPromoteWidth = 32;
232 if (ShouldUseInlineAtomic)
233 MaxAtomicInlineWidth = 32;
234 } else {
235 MaxAtomicPromoteWidth = 64;
236 if (ShouldUseInlineAtomic)
237 MaxAtomicInlineWidth = 64;
238 }
239 }
240
241 bool isThumb() const { return (ArchISA == llvm::ARM::IK_THUMB); }
242
243 bool supportsThumb() const { return CPUAttr.count('T') || ArchVersion >= 6; }
244
245 bool supportsThumb2() const {
246 return CPUAttr.equals("6T2") ||
247 (ArchVersion >= 7 && !CPUAttr.equals("8M_BASE"));
248 }
249
250 StringRef getCPUAttr() const {
251 // For most sub-arches, the build attribute CPU name is enough.
252 // For Cortex variants, it's slightly different.
253 switch (ArchKind) {
254 default:
255 return llvm::ARM::getCPUAttr(ArchKind);
256 case llvm::ARM::AK_ARMV6M:
257 return "6M";
258 case llvm::ARM::AK_ARMV7S:
259 return "7S";
260 case llvm::ARM::AK_ARMV7A:
261 return "7A";
262 case llvm::ARM::AK_ARMV7R:
263 return "7R";
264 case llvm::ARM::AK_ARMV7M:
265 return "7M";
266 case llvm::ARM::AK_ARMV7EM:
267 return "7EM";
268 case llvm::ARM::AK_ARMV7VE:
269 return "7VE";
270 case llvm::ARM::AK_ARMV8A:
271 return "8A";
272 case llvm::ARM::AK_ARMV8_1A:
273 return "8_1A";
274 case llvm::ARM::AK_ARMV8_2A:
275 return "8_2A";
276 case llvm::ARM::AK_ARMV8MBaseline:
277 return "8M_BASE";
278 case llvm::ARM::AK_ARMV8MMainline:
279 return "8M_MAIN";
280 case llvm::ARM::AK_ARMV8R:
281 return "8R";
282 }
283 }
284
285 StringRef getCPUProfile() const {
286 switch (ArchProfile) {
287 case llvm::ARM::PK_A:
288 return "A";
289 case llvm::ARM::PK_R:
290 return "R";
291 case llvm::ARM::PK_M:
292 return "M";
293 default:
294 return "";
295 }
296 }
297
298public:
299 ARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
300 : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
301 HW_FP(0) {
302
303 switch (getTriple().getOS()) {
304 case llvm::Triple::NetBSD:
305 case llvm::Triple::OpenBSD:
306 PtrDiffType = SignedLong;
307 break;
308 default:
309 PtrDiffType = SignedInt;
310 break;
311 }
312
313 // Cache arch related info.
314 setArchInfo();
315
316 // {} in inline assembly are neon specifiers, not assembly variant
317 // specifiers.
318 NoAsmVariants = true;
319
320 // FIXME: This duplicates code from the driver that sets the -target-abi
321 // option - this code is used if -target-abi isn't passed and should
322 // be unified in some way.
323 if (Triple.isOSBinFormatMachO()) {
324 // The backend is hardwired to assume AAPCS for M-class processors, ensure
325 // the frontend matches that.
326 if (Triple.getEnvironment() == llvm::Triple::EABI ||
327 Triple.getOS() == llvm::Triple::UnknownOS ||
328 ArchProfile == llvm::ARM::PK_M) {
329 setABI("aapcs");
330 } else if (Triple.isWatchABI()) {
331 setABI("aapcs16");
332 } else {
333 setABI("apcs-gnu");
334 }
335 } else if (Triple.isOSWindows()) {
336 // FIXME: this is invalid for WindowsCE
337 setABI("aapcs");
338 } else {
339 // Select the default based on the platform.
340 switch (Triple.getEnvironment()) {
341 case llvm::Triple::Android:
342 case llvm::Triple::GNUEABI:
343 case llvm::Triple::GNUEABIHF:
344 case llvm::Triple::MuslEABI:
345 case llvm::Triple::MuslEABIHF:
346 setABI("aapcs-linux");
347 break;
348 case llvm::Triple::EABIHF:
349 case llvm::Triple::EABI:
350 setABI("aapcs");
351 break;
352 case llvm::Triple::GNU:
353 setABI("apcs-gnu");
354 break;
355 default:
356 if (Triple.getOS() == llvm::Triple::NetBSD)
357 setABI("apcs-gnu");
358 else if (Triple.getOS() == llvm::Triple::OpenBSD)
359 setABI("aapcs-linux");
360 else
361 setABI("aapcs");
362 break;
363 }
364 }
365
366 // ARM targets default to using the ARM C++ ABI.
367 TheCXXABI.set(TargetCXXABI::GenericARM);
368
369 // ARM has atomics up to 8 bytes
370 setAtomic();
371
372 // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS)
373 if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android))
374 MaxVectorAlign = 64;
375
376 // Do force alignment of members that follow zero length bitfields. If
377 // the alignment of the zero-length bitfield is greater than the member
378 // that follows it, `bar', `bar' will be aligned as the type of the
379 // zero length bitfield.
380 UseZeroLengthBitfieldAlignment = true;
381
382 if (Triple.getOS() == llvm::Triple::Linux ||
383 Triple.getOS() == llvm::Triple::UnknownOS)
384 this->MCountName = Opts.EABIVersion == llvm::EABI::GNU
385 ? "\01__gnu_mcount_nc"
386 : "\01mcount";
387 }
388
389 StringRef getABI() const override { return ABI; }
390
391 bool setABI(const std::string &Name) override {
392 ABI = Name;
393
394 // The defaults (above) are for AAPCS, check if we need to change them.
395 //
396 // FIXME: We need support for -meabi... we could just mangle it into the
397 // name.
398 if (Name == "apcs-gnu" || Name == "aapcs16") {
399 setABIAPCS(Name == "aapcs16");
400 return true;
401 }
402 if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") {
403 setABIAAPCS();
404 return true;
405 }
406 return false;
407 }
408
409 // FIXME: This should be based on Arch attributes, not CPU names.
410 bool
411 initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
412 StringRef CPU,
413 const std::vector<std::string> &FeaturesVec) const override {
414
415 std::vector<StringRef> TargetFeatures;
416 unsigned Arch = llvm::ARM::parseArch(getTriple().getArchName());
417
418 // get default FPU features
419 unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch);
420 llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures);
421
422 // get default Extension features
423 unsigned Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch);
424 llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures);
425
426 for (auto Feature : TargetFeatures)
427 if (Feature[0] == '+')
428 Features[Feature.drop_front(1)] = true;
429
430 // Enable or disable thumb-mode explicitly per function to enable mixed
431 // ARM and Thumb code generation.
432 if (isThumb())
433 Features["thumb-mode"] = true;
434 else
435 Features["thumb-mode"] = false;
436
437 // Convert user-provided arm and thumb GNU target attributes to
438 // [-|+]thumb-mode target features respectively.
439 std::vector<std::string> UpdatedFeaturesVec(FeaturesVec);
440 for (auto &Feature : UpdatedFeaturesVec) {
441 if (Feature.compare("+arm") == 0)
442 Feature = "-thumb-mode";
443 else if (Feature.compare("+thumb") == 0)
444 Feature = "+thumb-mode";
445 }
446
447 return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);
448 }
449
450 bool handleTargetFeatures(std::vector<std::string> &Features,
451 DiagnosticsEngine &Diags) override;
452
453 bool hasFeature(StringRef Feature) const override;
454 bool isValidCPUName(StringRef Name) const override {
455 return Name == "generic" ||
456 llvm::ARM::parseCPUArch(Name) != llvm::ARM::AK_INVALID;
457 }
458
459 bool setCPU(const std::string &Name) override {
460 if (Name != "generic")
461 setArchInfo(llvm::ARM::parseCPUArch(Name));
462
463 if (ArchKind == llvm::ARM::AK_INVALID)
464 return false;
465 setAtomic();
466 CPU = Name;
467 return true;
468 }
469
470 bool setFPMath(StringRef Name) override;
471
472 void getTargetDefinesARMV81A(const LangOptions &Opts,
473 MacroBuilder &Builder) const;
474
475 void getTargetDefinesARMV82A(const LangOptions &Opts,
476 MacroBuilder &Builder) const {
477 // Also include the ARMv8.1-A defines
478 getTargetDefinesARMV81A(Opts, Builder);
479 }
480
481 void getTargetDefines(const LangOptions &Opts,
482 MacroBuilder &Builder) const override;
483 ArrayRef<Builtin::Info> getTargetBuiltins() const override;
484 bool isCLZForZeroUndef() const override { return false; }
485 BuiltinVaListKind getBuiltinVaListKind() const override {
486 return IsAAPCS
487 ? AAPCSABIBuiltinVaList
488 : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList
489 : TargetInfo::VoidPtrBuiltinVaList);
490 }
491 ArrayRef<const char *> getGCCRegNames() const override;
492 ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
493 bool validateAsmConstraint(const char *&Name,
494 TargetInfo::ConstraintInfo &Info) const override {
495 switch (*Name) {
496 default:
497 break;
498 case 'l': // r0-r7
499 case 'h': // r8-r15
500 case 't': // VFP Floating point register single precision
501 case 'w': // VFP Floating point register double precision
502 Info.setAllowsRegister();
503 return true;
504 case 'I':
505 case 'J':
506 case 'K':
507 case 'L':
508 case 'M':
509 // FIXME
510 return true;
511 case 'Q': // A memory address that is a single base register.
512 Info.setAllowsMemory();
513 return true;
514 case 'U': // a memory reference...
515 switch (Name[1]) {
516 case 'q': // ...ARMV4 ldrsb
517 case 'v': // ...VFP load/store (reg+constant offset)
518 case 'y': // ...iWMMXt load/store
519 case 't': // address valid for load/store opaque types wider
520 // than 128-bits
521 case 'n': // valid address for Neon doubleword vector load/store
522 case 'm': // valid address for Neon element and structure load/store
523 case 's': // valid address for non-offset loads/stores of quad-word
524 // values in four ARM registers
525 Info.setAllowsMemory();
526 Name++;
527 return true;
528 }
529 }
530 return false;
531 }
532 std::string convertConstraint(const char *&Constraint) const override {
533 std::string R;
534 switch (*Constraint) {
535 case 'U': // Two-character constraint; add "^" hint for later parsing.
536 R = std::string("^") + std::string(Constraint, 2);
537 Constraint++;
538 break;
539 case 'p': // 'p' should be translated to 'r' by default.
540 R = std::string("r");
541 break;
542 default:
543 return std::string(1, *Constraint);
544 }
545 return R;
546 }
547 bool
548 validateConstraintModifier(StringRef Constraint, char Modifier, unsigned Size,
549 std::string &SuggestedModifier) const override {
550 bool isOutput = (Constraint[0] == '=');
551 bool isInOut = (Constraint[0] == '+');
552
553 // Strip off constraint modifiers.
554 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
555 Constraint = Constraint.substr(1);
556
557 switch (Constraint[0]) {
558 default:
559 break;
560 case 'r': {
561 switch (Modifier) {
562 default:
563 return (isInOut || isOutput || Size <= 64);
564 case 'q':
565 // A register of size 32 cannot fit a vector type.
566 return false;
567 }
568 }
569 }
570
571 return true;
572 }
573 const char *getClobbers() const override {
574 // FIXME: Is this really right?
575 return "";
576 }
577
578 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
579 switch (CC) {
580 case CC_AAPCS:
581 case CC_AAPCS_VFP:
582 case CC_Swift:
583 case CC_OpenCLKernel:
584 return CCCR_OK;
585 default:
586 return CCCR_Warning;
587 }
588 }
589
590 int getEHDataRegisterNumber(unsigned RegNo) const override {
591 if (RegNo == 0)
592 return 0;
593 if (RegNo == 1)
594 return 1;
595 return -1;
596 }
597
598 bool hasSjLjLowering() const override { return true; }
599};
600
601class LLVM_LIBRARY_VISIBILITY ARMleTargetInfo : public ARMTargetInfo {
602public:
603 ARMleTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
604 : ARMTargetInfo(Triple, Opts) {}
605 void getTargetDefines(const LangOptions &Opts,
606 MacroBuilder &Builder) const override;
607};
608
609class LLVM_LIBRARY_VISIBILITY ARMbeTargetInfo : public ARMTargetInfo {
610public:
611 ARMbeTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
612 : ARMTargetInfo(Triple, Opts) {}
613 void getTargetDefines(const LangOptions &Opts,
614 MacroBuilder &Builder) const override;
615};
616
617class LLVM_LIBRARY_VISIBILITY WindowsARMTargetInfo
618 : public WindowsTargetInfo<ARMleTargetInfo> {
619 const llvm::Triple Triple;
620
621public:
622 WindowsARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
623 : WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) {
624 WCharType = UnsignedShort;
625 SizeType = UnsignedInt;
626 }
627 void getVisualStudioDefines(const LangOptions &Opts,
628 MacroBuilder &Builder) const;
629 BuiltinVaListKind getBuiltinVaListKind() const override {
630 return TargetInfo::CharPtrBuiltinVaList;
631 }
632 CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
633 switch (CC) {
634 case CC_X86StdCall:
635 case CC_X86ThisCall:
636 case CC_X86FastCall:
637 case CC_X86VectorCall:
638 return CCCR_Ignore;
639 case CC_C:
640 case CC_OpenCLKernel:
641 return CCCR_OK;
642 default:
643 return CCCR_Warning;
644 }
645 }
646};
647
648// Windows ARM + Itanium C++ ABI Target
649class LLVM_LIBRARY_VISIBILITY ItaniumWindowsARMleTargetInfo
650 : public WindowsARMTargetInfo {
651public:
652 ItaniumWindowsARMleTargetInfo(const llvm::Triple &Triple,
653 const TargetOptions &Opts)
654 : WindowsARMTargetInfo(Triple, Opts) {
655 TheCXXABI.set(TargetCXXABI::GenericARM);
656 }
657
658 void getTargetDefines(const LangOptions &Opts,
659 MacroBuilder &Builder) const override {
660 WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
661
662 if (Opts.MSVCCompat)
663 WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
664 }
665};
666
667// Windows ARM, MS (C++) ABI
668class LLVM_LIBRARY_VISIBILITY MicrosoftARMleTargetInfo
669 : public WindowsARMTargetInfo {
670public:
671 MicrosoftARMleTargetInfo(const llvm::Triple &Triple,
672 const TargetOptions &Opts)
673 : WindowsARMTargetInfo(Triple, Opts) {
674 TheCXXABI.set(TargetCXXABI::Microsoft);
675 }
676
677 void getTargetDefines(const LangOptions &Opts,
678 MacroBuilder &Builder) const override {
679 WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
680 WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
681 }
682};
683
684// ARM MinGW target
685class LLVM_LIBRARY_VISIBILITY MinGWARMTargetInfo : public WindowsARMTargetInfo {
686public:
687 MinGWARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
688 : WindowsARMTargetInfo(Triple, Opts) {
689 TheCXXABI.set(TargetCXXABI::GenericARM);
690 }
691
692 void getTargetDefines(const LangOptions &Opts,
693 MacroBuilder &Builder) const override;
694};
695
696// ARM Cygwin target
697class LLVM_LIBRARY_VISIBILITY CygwinARMTargetInfo : public ARMleTargetInfo {
698public:
699 CygwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
700 : ARMleTargetInfo(Triple, Opts) {
701 TLSSupported = false;
702 WCharType = UnsignedShort;
703 DoubleAlign = LongLongAlign = 64;
704 resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
705 }
706 void getTargetDefines(const LangOptions &Opts,
707 MacroBuilder &Builder) const override;
708};
709
710class LLVM_LIBRARY_VISIBILITY DarwinARMTargetInfo
711 : public DarwinTargetInfo<ARMleTargetInfo> {
712protected:
713 void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
714 MacroBuilder &Builder) const override {
715 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
716 }
717
718public:
719 DarwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
720 : DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) {
721 HasAlignMac68kSupport = true;
722 // iOS always has 64-bit atomic instructions.
723 // FIXME: This should be based off of the target features in
724 // ARMleTargetInfo.
725 MaxAtomicInlineWidth = 64;
726
727 if (Triple.isWatchABI()) {
728 // Darwin on iOS uses a variant of the ARM C++ ABI.
729 TheCXXABI.set(TargetCXXABI::WatchOS);
730
731 // The 32-bit ABI is silent on what ptrdiff_t should be, but given that
732 // size_t is long, it's a bit weird for it to be int.
733 PtrDiffType = SignedLong;
734
735 // BOOL should be a real boolean on the new ABI
736 UseSignedCharForObjCBool = false;
737 } else
738 TheCXXABI.set(TargetCXXABI::iOS);
739 }
740};
741// 32-bit RenderScript is armv7 with width and align of 'long' set to 8-bytes
742class LLVM_LIBRARY_VISIBILITY RenderScript32TargetInfo
743 : public ARMleTargetInfo {
744public:
745 RenderScript32TargetInfo(const llvm::Triple &Triple,
746 const TargetOptions &Opts)
747 : ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(),
748 Triple.getOSName(),
749 Triple.getEnvironmentName()),
750 Opts) {
751 IsRenderScriptTarget = true;
752 LongWidth = LongAlign = 64;
753 }
754 void getTargetDefines(const LangOptions &Opts,
755 MacroBuilder &Builder) const override;
756};
757
758} // namespace targets
759} // namespace clang
760
761#endif // LLVM_CLANG_LIB_BASIC_TARGETS_ARM_H