1 //===--- ARM.cpp - Implement ARM target feature support -------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements ARM TargetInfo objects.
11 //===----------------------------------------------------------------------===//
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"
21 using namespace clang;
22 using namespace clang::targets;
24 void ARMTargetInfo::setABIAAPCS() {
27 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
28 const llvm::Triple &T = getTriple();
30 bool IsNetBSD = T.isOSNetBSD();
31 bool IsOpenBSD = T.isOSOpenBSD();
32 if (!T.isOSWindows() && !IsNetBSD && !IsOpenBSD)
33 WCharType = UnsignedInt;
35 UseBitFieldTypeAlignment = true;
37 ZeroLengthBitfieldBoundary = 0;
39 // Thumb1 add sp, #imm requires the immediate value be multiple of 4,
40 // so set preferred for small types to 32.
41 if (T.isOSBinFormatMachO()) {
42 resetDataLayout(BigEndian
43 ? "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
44 : "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64");
45 } else if (T.isOSWindows()) {
46 assert(!BigEndian && "Windows on ARM does not support big endian");
56 } else if (T.isOSNaCl()) {
57 assert(!BigEndian && "NaCl on ARM does not support big endian");
58 resetDataLayout("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S128");
60 resetDataLayout(BigEndian
61 ? "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
62 : "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64");
65 // FIXME: Enumerated types are variable width in straight AAPCS.
68 void ARMTargetInfo::setABIAPCS(bool IsAAPCS16) {
69 const llvm::Triple &T = getTriple();
74 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
76 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32;
78 WCharType = SignedInt;
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;
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
87 ZeroLengthBitfieldBoundary = 32;
89 if (T.isOSBinFormatMachO() && IsAAPCS16) {
90 assert(!BigEndian && "AAPCS16 does not support big-endian");
91 resetDataLayout("e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128");
92 } else if (T.isOSBinFormatMachO())
95 ? "E-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
96 : "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
100 ? "E-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
101 : "e-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
103 // FIXME: Override "preferred align" for double and long long.
106 void ARMTargetInfo::setArchInfo() {
107 StringRef ArchName = getTriple().getArchName();
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)
114 setArchInfo(ArchKind);
117 void ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) {
120 // cache TargetParser info
122 SubArch = llvm::ARM::getSubArch(ArchKind);
123 ArchProfile = llvm::ARM::parseArchProfile(SubArch);
124 ArchVersion = llvm::ARM::parseArchVersion(SubArch);
126 // cache CPU related strings
127 CPUAttr = getCPUAttr();
128 CPUProfile = getCPUProfile();
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;
143 MaxAtomicPromoteWidth = 64;
144 if (ShouldUseInlineAtomic)
145 MaxAtomicInlineWidth = 64;
149 bool ARMTargetInfo::hasMVE() const {
150 return ArchKind == llvm::ARM::ArchKind::ARMV8_1MMainline && MVE != 0;
153 bool ARMTargetInfo::hasMVEFloat() const {
154 return hasMVE() && (MVE & MVE_FP);
157 bool ARMTargetInfo::isThumb() const {
158 return ArchISA == llvm::ARM::ISAKind::THUMB;
161 bool ARMTargetInfo::supportsThumb() const {
162 return CPUAttr.count('T') || ArchVersion >= 6;
165 bool ARMTargetInfo::supportsThumb2() const {
166 return CPUAttr.equals("6T2") ||
167 (ArchVersion >= 7 && !CPUAttr.equals("8M_BASE"));
170 StringRef ARMTargetInfo::getCPUAttr() const {
171 // For most sub-arches, the build attribute CPU name is enough.
172 // For Cortex variants, it's slightly different.
175 return llvm::ARM::getCPUAttr(ArchKind);
176 case llvm::ARM::ArchKind::ARMV6M:
178 case llvm::ARM::ArchKind::ARMV7S:
180 case llvm::ARM::ArchKind::ARMV7A:
182 case llvm::ARM::ArchKind::ARMV7R:
184 case llvm::ARM::ArchKind::ARMV7M:
186 case llvm::ARM::ArchKind::ARMV7EM:
188 case llvm::ARM::ArchKind::ARMV7VE:
190 case llvm::ARM::ArchKind::ARMV8A:
192 case llvm::ARM::ArchKind::ARMV8_1A:
194 case llvm::ARM::ArchKind::ARMV8_2A:
196 case llvm::ARM::ArchKind::ARMV8_3A:
198 case llvm::ARM::ArchKind::ARMV8_4A:
200 case llvm::ARM::ArchKind::ARMV8_5A:
202 case llvm::ARM::ArchKind::ARMV8MBaseline:
204 case llvm::ARM::ArchKind::ARMV8MMainline:
206 case llvm::ARM::ArchKind::ARMV8R:
208 case llvm::ARM::ArchKind::ARMV8_1MMainline:
213 StringRef ARMTargetInfo::getCPUProfile() const {
214 switch (ArchProfile) {
215 case llvm::ARM::ProfileKind::A:
217 case llvm::ARM::ProfileKind::R:
219 case llvm::ARM::ProfileKind::M:
226 ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
227 const TargetOptions &Opts)
228 : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
230 bool IsOpenBSD = Triple.isOSOpenBSD();
231 bool IsNetBSD = Triple.isOSNetBSD();
233 // FIXME: the isOSBinFormatMachO is a workaround for identifying a Darwin-like
234 // environment where size_t is `unsigned long` rather than `unsigned int`
236 PtrDiffType = IntPtrType =
237 (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
242 SizeType = (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
247 // ptrdiff_t is inconsistent on Darwin
248 if ((Triple.isOSDarwin() || Triple.isOSBinFormatMachO()) &&
249 !Triple.isWatchABI())
250 PtrDiffType = SignedInt;
252 // Cache arch related info.
255 // {} in inline assembly are neon specifiers, not assembly variant
257 NoAsmVariants = true;
259 // FIXME: This duplicates code from the driver that sets the -target-abi
260 // option - this code is used if -target-abi isn't passed and should
261 // be unified in some way.
262 if (Triple.isOSBinFormatMachO()) {
263 // The backend is hardwired to assume AAPCS for M-class processors, ensure
264 // the frontend matches that.
265 if (Triple.getEnvironment() == llvm::Triple::EABI ||
266 Triple.getOS() == llvm::Triple::UnknownOS ||
267 ArchProfile == llvm::ARM::ProfileKind::M) {
269 } else if (Triple.isWatchABI()) {
274 } else if (Triple.isOSWindows()) {
275 // FIXME: this is invalid for WindowsCE
278 // Select the default based on the platform.
279 switch (Triple.getEnvironment()) {
280 case llvm::Triple::Android:
281 case llvm::Triple::GNUEABI:
282 case llvm::Triple::GNUEABIHF:
283 case llvm::Triple::MuslEABI:
284 case llvm::Triple::MuslEABIHF:
285 setABI("aapcs-linux");
287 case llvm::Triple::EABIHF:
288 case llvm::Triple::EABI:
291 case llvm::Triple::GNU:
298 setABI("aapcs-linux");
305 // ARM targets default to using the ARM C++ ABI.
306 TheCXXABI.set(TargetCXXABI::GenericARM);
308 // ARM has atomics up to 8 bytes
311 // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS)
312 if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android))
315 // Do force alignment of members that follow zero length bitfields. If
316 // the alignment of the zero-length bitfield is greater than the member
317 // that follows it, `bar', `bar' will be aligned as the type of the
318 // zero length bitfield.
319 UseZeroLengthBitfieldAlignment = true;
321 if (Triple.getOS() == llvm::Triple::Linux ||
322 Triple.getOS() == llvm::Triple::UnknownOS)
323 this->MCountName = Opts.EABIVersion == llvm::EABI::GNU
324 ? "\01__gnu_mcount_nc"
327 SoftFloatABI = llvm::is_contained(Opts.FeaturesAsWritten, "+soft-float-abi");
330 StringRef ARMTargetInfo::getABI() const { return ABI; }
332 bool ARMTargetInfo::setABI(const std::string &Name) {
335 // The defaults (above) are for AAPCS, check if we need to change them.
337 // FIXME: We need support for -meabi... we could just mangle it into the
339 if (Name == "apcs-gnu" || Name == "aapcs16") {
340 setABIAPCS(Name == "aapcs16");
343 if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") {
350 // FIXME: This should be based on Arch attributes, not CPU names.
351 bool ARMTargetInfo::initFeatureMap(
352 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
353 const std::vector<std::string> &FeaturesVec) const {
355 std::string ArchFeature;
356 std::vector<StringRef> TargetFeatures;
357 llvm::ARM::ArchKind Arch = llvm::ARM::parseArch(getTriple().getArchName());
359 // Map the base architecture to an appropriate target feature, so we don't
360 // rely on the target triple.
361 llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(CPU);
362 if (CPUArch == llvm::ARM::ArchKind::INVALID)
364 if (CPUArch != llvm::ARM::ArchKind::INVALID) {
365 ArchFeature = ("+" + llvm::ARM::getArchName(CPUArch)).str();
366 TargetFeatures.push_back(ArchFeature);
369 // get default FPU features
370 unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch);
371 llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures);
373 // get default Extension features
374 unsigned Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch);
375 llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures);
377 for (auto Feature : TargetFeatures)
378 if (Feature[0] == '+')
379 Features[Feature.drop_front(1)] = true;
381 // Enable or disable thumb-mode explicitly per function to enable mixed
382 // ARM and Thumb code generation.
384 Features["thumb-mode"] = true;
386 Features["thumb-mode"] = false;
388 // Convert user-provided arm and thumb GNU target attributes to
389 // [-|+]thumb-mode target features respectively.
390 std::vector<std::string> UpdatedFeaturesVec;
391 for (const auto &Feature : FeaturesVec) {
392 // Skip soft-float-abi; it's something we only use to initialize a bit of
393 // class state, and is otherwise unrecognized.
394 if (Feature == "+soft-float-abi")
397 StringRef FixedFeature;
398 if (Feature == "+arm")
399 FixedFeature = "-thumb-mode";
400 else if (Feature == "+thumb")
401 FixedFeature = "+thumb-mode";
403 FixedFeature = Feature;
404 UpdatedFeaturesVec.push_back(FixedFeature.str());
407 return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);
411 bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
412 DiagnosticsEngine &Diags) {
420 // Note that SoftFloatABI is initialized in our constructor.
425 // This does not diagnose illegal cases like having both
426 // "+vfpv2" and "+vfpv3" or having "+neon" and "-fp64".
427 for (const auto &Feature : Features) {
428 if (Feature == "+soft-float") {
430 } else if (Feature == "+vfp2sp" || Feature == "+vfp2d16sp" ||
431 Feature == "+vfp2" || Feature == "+vfp2d16") {
434 if (Feature == "+vfp2" || Feature == "+vfp2d16")
436 } else if (Feature == "+vfp3sp" || Feature == "+vfp3d16sp" ||
437 Feature == "+vfp3" || Feature == "+vfp3d16") {
440 if (Feature == "+vfp3" || Feature == "+vfp3d16")
442 } else if (Feature == "+vfp4sp" || Feature == "+vfp4d16sp" ||
443 Feature == "+vfp4" || Feature == "+vfp4d16") {
445 HW_FP |= HW_FP_SP | HW_FP_HP;
446 if (Feature == "+vfp4" || Feature == "+vfp4d16")
448 } else if (Feature == "+fp-armv8sp" || Feature == "+fp-armv8d16sp" ||
449 Feature == "+fp-armv8" || Feature == "+fp-armv8d16") {
451 HW_FP |= HW_FP_SP | HW_FP_HP;
452 if (Feature == "+fp-armv8" || Feature == "+fp-armv8d16")
454 } else if (Feature == "+neon") {
457 } else if (Feature == "+hwdiv") {
459 } else if (Feature == "+hwdiv-arm") {
461 } else if (Feature == "+crc") {
463 } else if (Feature == "+crypto") {
465 } else if (Feature == "+dsp") {
467 } else if (Feature == "+fp64") {
469 } else if (Feature == "+8msecext") {
470 if (CPUProfile != "M" || ArchVersion != 8) {
471 Diags.Report(diag::err_target_unsupported_mcmse) << CPU;
474 } else if (Feature == "+strict-align") {
476 } else if (Feature == "+fp16") {
478 } else if (Feature == "+fullfp16") {
479 HasLegalHalfType = true;
480 } else if (Feature == "+dotprod") {
482 } else if (Feature == "+mve") {
485 } else if (Feature == "+mve.fp") {
487 HasLegalHalfType = true;
489 MVE |= MVE_INT | MVE_FP;
490 HW_FP |= HW_FP_SP | HW_FP_HP;
494 switch (ArchVersion) {
496 if (ArchProfile == llvm::ARM::ProfileKind::M)
498 else if (ArchKind == llvm::ARM::ArchKind::ARMV6K)
499 LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
504 if (ArchProfile == llvm::ARM::ProfileKind::M)
505 LDREX = LDREX_W | LDREX_H | LDREX_B;
507 LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
510 LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
513 if (!(FPU & NeonFPU) && FPMath == FP_Neon) {
514 Diags.Report(diag::err_target_unsupported_fpmath) << "neon";
518 if (FPMath == FP_Neon)
519 Features.push_back("+neonfp");
520 else if (FPMath == FP_VFP)
521 Features.push_back("-neonfp");
526 bool ARMTargetInfo::hasFeature(StringRef Feature) const {
527 return llvm::StringSwitch<bool>(Feature)
529 .Case("aarch32", true)
530 .Case("softfloat", SoftFloat)
531 .Case("thumb", isThumb())
532 .Case("neon", (FPU & NeonFPU) && !SoftFloat)
533 .Case("vfp", FPU && !SoftFloat)
534 .Case("hwdiv", HWDiv & HWDivThumb)
535 .Case("hwdiv-arm", HWDiv & HWDivARM)
536 .Case("mve", hasMVE())
540 bool ARMTargetInfo::isValidCPUName(StringRef Name) const {
541 return Name == "generic" ||
542 llvm::ARM::parseCPUArch(Name) != llvm::ARM::ArchKind::INVALID;
545 void ARMTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
546 llvm::ARM::fillValidCPUArchList(Values);
549 bool ARMTargetInfo::setCPU(const std::string &Name) {
550 if (Name != "generic")
551 setArchInfo(llvm::ARM::parseCPUArch(Name));
553 if (ArchKind == llvm::ARM::ArchKind::INVALID)
560 bool ARMTargetInfo::setFPMath(StringRef Name) {
561 if (Name == "neon") {
564 } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" ||
572 void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
573 MacroBuilder &Builder) const {
574 Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
577 void ARMTargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
578 MacroBuilder &Builder) const {
579 // Also include the ARMv8.1-A defines
580 getTargetDefinesARMV81A(Opts, Builder);
583 void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
584 MacroBuilder &Builder) const {
585 // Target identification.
586 Builder.defineMacro("__arm");
587 Builder.defineMacro("__arm__");
588 // For bare-metal none-eabi.
589 if (getTriple().getOS() == llvm::Triple::UnknownOS &&
590 (getTriple().getEnvironment() == llvm::Triple::EABI ||
591 getTriple().getEnvironment() == llvm::Triple::EABIHF))
592 Builder.defineMacro("__ELF__");
594 // Target properties.
595 Builder.defineMacro("__REGISTER_PREFIX__", "");
597 // Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU
598 // happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__.
599 if (getTriple().isWatchABI())
600 Builder.defineMacro("__ARM_ARCH_7K__", "2");
602 if (!CPUAttr.empty())
603 Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__");
605 // ACLE 6.4.1 ARM/Thumb instruction set architecture
606 // __ARM_ARCH is defined as an integer value indicating the current ARM ISA
607 Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion));
609 if (ArchVersion >= 8) {
610 // ACLE 6.5.7 Crypto Extension
612 Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
613 // ACLE 6.5.8 CRC32 Extension
615 Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
616 // ACLE 6.5.10 Numeric Maximum and Minimum
617 Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
618 // ACLE 6.5.9 Directed Rounding
619 Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
622 // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA. It
623 // is not defined for the M-profile.
624 // NOTE that the default profile is assumed to be 'A'
625 if (CPUProfile.empty() || ArchProfile != llvm::ARM::ProfileKind::M)
626 Builder.defineMacro("__ARM_ARCH_ISA_ARM", "1");
628 // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original
629 // Thumb ISA (including v6-M and v8-M Baseline). It is set to 2 if the
630 // core supports the Thumb-2 ISA as found in the v6T2 architecture and all
631 // v7 and v8 architectures excluding v8-M Baseline.
632 if (supportsThumb2())
633 Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2");
634 else if (supportsThumb())
635 Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1");
637 // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit
638 // instruction set such as ARM or Thumb.
639 Builder.defineMacro("__ARM_32BIT_STATE", "1");
641 // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex)
643 // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset.
644 if (!CPUProfile.empty())
645 Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'");
647 // ACLE 6.4.3 Unaligned access supported in hardware
649 Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
651 // ACLE 6.4.4 LDREX/STREX
653 Builder.defineMacro("__ARM_FEATURE_LDREX", "0x" + Twine::utohexstr(LDREX));
656 if (ArchVersion == 5 || (ArchVersion == 6 && CPUProfile != "M") ||
658 Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
660 // ACLE 6.5.1 Hardware Floating Point
662 Builder.defineMacro("__ARM_FP", "0x" + Twine::utohexstr(HW_FP));
665 Builder.defineMacro("__ARM_ACLE", "200");
667 // FP16 support (we currently only support IEEE format).
668 Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
669 Builder.defineMacro("__ARM_FP16_ARGS", "1");
671 // ACLE 6.5.3 Fused multiply-accumulate (FMA)
672 if (ArchVersion >= 7 && (FPU & VFP4FPU))
673 Builder.defineMacro("__ARM_FEATURE_FMA", "1");
675 // Subtarget options.
677 // FIXME: It's more complicated than this and we don't really support
679 // Windows on ARM does not "support" interworking
680 if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows())
681 Builder.defineMacro("__THUMB_INTERWORK__");
683 if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {
684 // Embedded targets on Darwin follow AAPCS, but not EABI.
685 // Windows on ARM follows AAPCS VFP, but does not conform to EABI.
686 if (!getTriple().isOSBinFormatMachO() && !getTriple().isOSWindows())
687 Builder.defineMacro("__ARM_EABI__");
688 Builder.defineMacro("__ARM_PCS", "1");
691 if ((!SoftFloat && !SoftFloatABI) || ABI == "aapcs-vfp" || ABI == "aapcs16")
692 Builder.defineMacro("__ARM_PCS_VFP", "1");
695 Builder.defineMacro("__SOFTFP__");
697 // ACLE position independent code macros.
699 Builder.defineMacro("__ARM_ROPI", "1");
701 Builder.defineMacro("__ARM_RWPI", "1");
703 if (ArchKind == llvm::ARM::ArchKind::XSCALE)
704 Builder.defineMacro("__XSCALE__");
707 Builder.defineMacro("__THUMBEL__");
708 Builder.defineMacro("__thumb__");
709 if (supportsThumb2())
710 Builder.defineMacro("__thumb2__");
713 // ACLE 6.4.9 32-bit SIMD instructions
714 if ((CPUProfile != "M" && ArchVersion >= 6) || (CPUProfile == "M" && DSP))
715 Builder.defineMacro("__ARM_FEATURE_SIMD32", "1");
717 // ACLE 6.4.10 Hardware Integer Divide
718 if (((HWDiv & HWDivThumb) && isThumb()) ||
719 ((HWDiv & HWDivARM) && !isThumb())) {
720 Builder.defineMacro("__ARM_FEATURE_IDIV", "1");
721 Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1");
724 // Note, this is always on in gcc, even though it doesn't make sense.
725 Builder.defineMacro("__APCS_32__");
727 if (FPUModeIsVFP((FPUMode)FPU)) {
728 Builder.defineMacro("__VFP_FP__");
730 Builder.defineMacro("__ARM_VFPV2__");
732 Builder.defineMacro("__ARM_VFPV3__");
734 Builder.defineMacro("__ARM_VFPV4__");
736 Builder.defineMacro("__ARM_FPV5__");
739 // This only gets set when Neon instructions are actually available, unlike
740 // the VFP define, hence the soft float and arch check. This is subtly
741 // different from gcc, we follow the intent which was that it should be set
742 // when Neon instructions are actually available.
743 if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) {
744 Builder.defineMacro("__ARM_NEON", "1");
745 Builder.defineMacro("__ARM_NEON__");
746 // current AArch32 NEON implementations do not support double-precision
747 // floating-point even when it is present in VFP.
748 Builder.defineMacro("__ARM_NEON_FP",
749 "0x" + Twine::utohexstr(HW_FP & ~HW_FP_DP));
753 Builder.defineMacro("__ARM_FEATURE_MVE", hasMVEFloat() ? "3" : "1");
756 Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
757 Twine(Opts.WCharSize ? Opts.WCharSize : 4));
759 Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
762 if (ArchVersion == 8 && ArchProfile == llvm::ARM::ProfileKind::M)
763 Builder.defineMacro("__ARM_FEATURE_CMSE", Opts.Cmse ? "3" : "1");
765 if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE") {
766 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
767 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
768 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
769 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
772 // ACLE 6.4.7 DSP instructions
774 Builder.defineMacro("__ARM_FEATURE_DSP", "1");
777 // ACLE 6.4.8 Saturation instructions
779 if ((ArchVersion == 6 && CPUProfile != "M") || ArchVersion > 6) {
780 Builder.defineMacro("__ARM_FEATURE_SAT", "1");
784 // ACLE 6.4.6 Q (saturation) flag
786 Builder.defineMacro("__ARM_FEATURE_QBIT", "1");
788 if (Opts.UnsafeFPMath)
789 Builder.defineMacro("__ARM_FP_FAST", "1");
791 // Armv8.2-A FP16 vector intrinsic
792 if ((FPU & NeonFPU) && HasLegalHalfType)
793 Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
795 // Armv8.2-A FP16 scalar intrinsics
796 if (HasLegalHalfType)
797 Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
799 // Armv8.2-A dot product intrinsics
801 Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
806 case llvm::ARM::ArchKind::ARMV8_1A:
807 getTargetDefinesARMV81A(Opts, Builder);
809 case llvm::ARM::ArchKind::ARMV8_2A:
810 getTargetDefinesARMV82A(Opts, Builder);
815 const Builtin::Info ARMTargetInfo::BuiltinInfo[] = {
816 #define BUILTIN(ID, TYPE, ATTRS) \
817 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
818 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
819 {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
820 #include "clang/Basic/BuiltinsNEON.def"
822 #define BUILTIN(ID, TYPE, ATTRS) \
823 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
824 #define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \
825 {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
826 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
827 {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
828 #define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
829 {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
830 #include "clang/Basic/BuiltinsARM.def"
833 ArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const {
834 return llvm::makeArrayRef(BuiltinInfo, clang::ARM::LastTSBuiltin -
835 Builtin::FirstTSBuiltin);
838 bool ARMTargetInfo::isCLZForZeroUndef() const { return false; }
839 TargetInfo::BuiltinVaListKind ARMTargetInfo::getBuiltinVaListKind() const {
841 ? AAPCSABIBuiltinVaList
842 : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList
843 : TargetInfo::VoidPtrBuiltinVaList);
846 const char *const ARMTargetInfo::GCCRegNames[] = {
848 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
849 "r12", "sp", "lr", "pc",
852 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
853 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
854 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
857 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
858 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
859 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
862 "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11",
863 "q12", "q13", "q14", "q15"};
865 ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const {
866 return llvm::makeArrayRef(GCCRegNames);
869 const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
870 {{"a1"}, "r0"}, {{"a2"}, "r1"}, {{"a3"}, "r2"}, {{"a4"}, "r3"},
871 {{"v1"}, "r4"}, {{"v2"}, "r5"}, {{"v3"}, "r6"}, {{"v4"}, "r7"},
872 {{"v5"}, "r8"}, {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"},
873 {{"ip"}, "r12"}, {{"r13"}, "sp"}, {{"r14"}, "lr"}, {{"r15"}, "pc"},
874 // The S, D and Q registers overlap, but aren't really aliases; we
875 // don't want to substitute one of these for a different-sized one.
878 ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const {
879 return llvm::makeArrayRef(GCCRegAliases);
882 bool ARMTargetInfo::validateAsmConstraint(
883 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
889 case 't': // VFP Floating point register single precision
890 case 'w': // VFP Floating point register double precision
891 Info.setAllowsRegister();
900 case 'Q': // A memory address that is a single base register.
901 Info.setAllowsMemory();
907 case 'e': // Even general-purpose register
908 case 'o': // Odd general-purpose register
909 Info.setAllowsRegister();
914 case 'U': // a memory reference...
916 case 'q': // ...ARMV4 ldrsb
917 case 'v': // ...VFP load/store (reg+constant offset)
918 case 'y': // ...iWMMXt load/store
919 case 't': // address valid for load/store opaque types wider
921 case 'n': // valid address for Neon doubleword vector load/store
922 case 'm': // valid address for Neon element and structure load/store
923 case 's': // valid address for non-offset loads/stores of quad-word
924 // values in four ARM registers
925 Info.setAllowsMemory();
934 std::string ARMTargetInfo::convertConstraint(const char *&Constraint) const {
936 switch (*Constraint) {
937 case 'U': // Two-character constraint; add "^" hint for later parsing.
939 R = std::string("^") + std::string(Constraint, 2);
942 case 'p': // 'p' should be translated to 'r' by default.
943 R = std::string("r");
946 return std::string(1, *Constraint);
951 bool ARMTargetInfo::validateConstraintModifier(
952 StringRef Constraint, char Modifier, unsigned Size,
953 std::string &SuggestedModifier) const {
954 bool isOutput = (Constraint[0] == '=');
955 bool isInOut = (Constraint[0] == '+');
957 // Strip off constraint modifiers.
958 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
959 Constraint = Constraint.substr(1);
961 switch (Constraint[0]) {
967 return (isInOut || isOutput || Size <= 64);
969 // A register of size 32 cannot fit a vector type.
977 const char *ARMTargetInfo::getClobbers() const {
978 // FIXME: Is this really right?
982 TargetInfo::CallingConvCheckResult
983 ARMTargetInfo::checkCallingConvention(CallingConv CC) const {
988 case CC_OpenCLKernel:
995 int ARMTargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
1003 bool ARMTargetInfo::hasSjLjLowering() const { return true; }
1005 ARMleTargetInfo::ARMleTargetInfo(const llvm::Triple &Triple,
1006 const TargetOptions &Opts)
1007 : ARMTargetInfo(Triple, Opts) {}
1009 void ARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
1010 MacroBuilder &Builder) const {
1011 Builder.defineMacro("__ARMEL__");
1012 ARMTargetInfo::getTargetDefines(Opts, Builder);
1015 ARMbeTargetInfo::ARMbeTargetInfo(const llvm::Triple &Triple,
1016 const TargetOptions &Opts)
1017 : ARMTargetInfo(Triple, Opts) {}
1019 void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts,
1020 MacroBuilder &Builder) const {
1021 Builder.defineMacro("__ARMEB__");
1022 Builder.defineMacro("__ARM_BIG_ENDIAN");
1023 ARMTargetInfo::getTargetDefines(Opts, Builder);
1026 WindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple,
1027 const TargetOptions &Opts)
1028 : WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) {
1031 void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts,
1032 MacroBuilder &Builder) const {
1033 // FIXME: this is invalid for WindowsCE
1034 Builder.defineMacro("_M_ARM_NT", "1");
1035 Builder.defineMacro("_M_ARMT", "_M_ARM");
1036 Builder.defineMacro("_M_THUMB", "_M_ARM");
1038 assert((Triple.getArch() == llvm::Triple::arm ||
1039 Triple.getArch() == llvm::Triple::thumb) &&
1040 "invalid architecture for Windows ARM target info");
1041 unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
1042 Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset));
1044 // TODO map the complete set of values
1045 // 31: VFPv3 40: VFPv4
1046 Builder.defineMacro("_M_ARM_FP", "31");
1049 TargetInfo::BuiltinVaListKind
1050 WindowsARMTargetInfo::getBuiltinVaListKind() const {
1051 return TargetInfo::CharPtrBuiltinVaList;
1054 TargetInfo::CallingConvCheckResult
1055 WindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const {
1058 case CC_X86ThisCall:
1059 case CC_X86FastCall:
1060 case CC_X86VectorCall:
1063 case CC_OpenCLKernel:
1064 case CC_PreserveMost:
1065 case CC_PreserveAll:
1069 return CCCR_Warning;
1073 // Windows ARM + Itanium C++ ABI Target
1074 ItaniumWindowsARMleTargetInfo::ItaniumWindowsARMleTargetInfo(
1075 const llvm::Triple &Triple, const TargetOptions &Opts)
1076 : WindowsARMTargetInfo(Triple, Opts) {
1077 TheCXXABI.set(TargetCXXABI::GenericARM);
1080 void ItaniumWindowsARMleTargetInfo::getTargetDefines(
1081 const LangOptions &Opts, MacroBuilder &Builder) const {
1082 WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
1084 if (Opts.MSVCCompat)
1085 WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
1088 // Windows ARM, MS (C++) ABI
1089 MicrosoftARMleTargetInfo::MicrosoftARMleTargetInfo(const llvm::Triple &Triple,
1090 const TargetOptions &Opts)
1091 : WindowsARMTargetInfo(Triple, Opts) {
1092 TheCXXABI.set(TargetCXXABI::Microsoft);
1095 void MicrosoftARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
1096 MacroBuilder &Builder) const {
1097 WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
1098 WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
1101 MinGWARMTargetInfo::MinGWARMTargetInfo(const llvm::Triple &Triple,
1102 const TargetOptions &Opts)
1103 : WindowsARMTargetInfo(Triple, Opts) {
1104 TheCXXABI.set(TargetCXXABI::GenericARM);
1107 void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts,
1108 MacroBuilder &Builder) const {
1109 WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
1110 Builder.defineMacro("_ARM_");
1113 CygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple,
1114 const TargetOptions &Opts)
1115 : ARMleTargetInfo(Triple, Opts) {
1116 this->WCharType = TargetInfo::UnsignedShort;
1117 TLSSupported = false;
1118 DoubleAlign = LongLongAlign = 64;
1119 resetDataLayout("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64");
1122 void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts,
1123 MacroBuilder &Builder) const {
1124 ARMleTargetInfo::getTargetDefines(Opts, Builder);
1125 Builder.defineMacro("_ARM_");
1126 Builder.defineMacro("__CYGWIN__");
1127 Builder.defineMacro("__CYGWIN32__");
1128 DefineStd(Builder, "unix", Opts);
1130 Builder.defineMacro("_GNU_SOURCE");
1133 DarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple,
1134 const TargetOptions &Opts)
1135 : DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) {
1136 HasAlignMac68kSupport = true;
1137 // iOS always has 64-bit atomic instructions.
1138 // FIXME: This should be based off of the target features in
1140 MaxAtomicInlineWidth = 64;
1142 if (Triple.isWatchABI()) {
1143 // Darwin on iOS uses a variant of the ARM C++ ABI.
1144 TheCXXABI.set(TargetCXXABI::WatchOS);
1146 // BOOL should be a real boolean on the new ABI
1147 UseSignedCharForObjCBool = false;
1149 TheCXXABI.set(TargetCXXABI::iOS);
1152 void DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts,
1153 const llvm::Triple &Triple,
1154 MacroBuilder &Builder) const {
1155 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
1158 RenderScript32TargetInfo::RenderScript32TargetInfo(const llvm::Triple &Triple,
1159 const TargetOptions &Opts)
1160 : ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(),
1162 Triple.getEnvironmentName()),
1164 IsRenderScriptTarget = true;
1165 LongWidth = LongAlign = 64;
1168 void RenderScript32TargetInfo::getTargetDefines(const LangOptions &Opts,
1169 MacroBuilder &Builder) const {
1170 Builder.defineMacro("__RENDERSCRIPT__");
1171 ARMleTargetInfo::getTargetDefines(Opts, Builder);