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