1326941Sdim//===--- ARM.cpp - Implement ARM target feature support -------------------===//
2326941Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6326941Sdim//
7326941Sdim//===----------------------------------------------------------------------===//
8326941Sdim//
9326941Sdim// This file implements ARM TargetInfo objects.
10326941Sdim//
11326941Sdim//===----------------------------------------------------------------------===//
12326941Sdim
13326941Sdim#include "ARM.h"
14326941Sdim#include "clang/Basic/Builtins.h"
15326941Sdim#include "clang/Basic/Diagnostic.h"
16326941Sdim#include "clang/Basic/TargetBuiltins.h"
17326941Sdim#include "llvm/ADT/StringExtras.h"
18326941Sdim#include "llvm/ADT/StringRef.h"
19326941Sdim#include "llvm/ADT/StringSwitch.h"
20326941Sdim
21326941Sdimusing namespace clang;
22326941Sdimusing namespace clang::targets;
23326941Sdim
24326941Sdimvoid ARMTargetInfo::setABIAAPCS() {
25326941Sdim  IsAAPCS = true;
26326941Sdim
27326941Sdim  DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
28326941Sdim  const llvm::Triple &T = getTriple();
29326941Sdim
30344779Sdim  bool IsNetBSD = T.isOSNetBSD();
31344779Sdim  bool IsOpenBSD = T.isOSOpenBSD();
32326941Sdim  if (!T.isOSWindows() && !IsNetBSD && !IsOpenBSD)
33326941Sdim    WCharType = UnsignedInt;
34326941Sdim
35326941Sdim  UseBitFieldTypeAlignment = true;
36326941Sdim
37326941Sdim  ZeroLengthBitfieldBoundary = 0;
38326941Sdim
39326941Sdim  // Thumb1 add sp, #imm requires the immediate value be multiple of 4,
40326941Sdim  // so set preferred for small types to 32.
41326941Sdim  if (T.isOSBinFormatMachO()) {
42326941Sdim    resetDataLayout(BigEndian
43353358Sdim                        ? "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
44353358Sdim                        : "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64");
45326941Sdim  } else if (T.isOSWindows()) {
46326941Sdim    assert(!BigEndian && "Windows on ARM does not support big endian");
47326941Sdim    resetDataLayout("e"
48326941Sdim                    "-m:w"
49326941Sdim                    "-p:32:32"
50353358Sdim                    "-Fi8"
51326941Sdim                    "-i64:64"
52326941Sdim                    "-v128:64:128"
53326941Sdim                    "-a:0:32"
54326941Sdim                    "-n32"
55326941Sdim                    "-S64");
56326941Sdim  } else if (T.isOSNaCl()) {
57326941Sdim    assert(!BigEndian && "NaCl on ARM does not support big endian");
58353358Sdim    resetDataLayout("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S128");
59326941Sdim  } else {
60326941Sdim    resetDataLayout(BigEndian
61353358Sdim                        ? "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
62353358Sdim                        : "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64");
63326941Sdim  }
64326941Sdim
65326941Sdim  // FIXME: Enumerated types are variable width in straight AAPCS.
66326941Sdim}
67326941Sdim
68326941Sdimvoid ARMTargetInfo::setABIAPCS(bool IsAAPCS16) {
69326941Sdim  const llvm::Triple &T = getTriple();
70326941Sdim
71326941Sdim  IsAAPCS = false;
72326941Sdim
73326941Sdim  if (IsAAPCS16)
74326941Sdim    DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
75326941Sdim  else
76326941Sdim    DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32;
77326941Sdim
78326941Sdim  WCharType = SignedInt;
79326941Sdim
80326941Sdim  // Do not respect the alignment of bit-field types when laying out
81326941Sdim  // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc.
82326941Sdim  UseBitFieldTypeAlignment = false;
83326941Sdim
84326941Sdim  /// gcc forces the alignment to 4 bytes, regardless of the type of the
85326941Sdim  /// zero length bitfield.  This corresponds to EMPTY_FIELD_BOUNDARY in
86326941Sdim  /// gcc.
87326941Sdim  ZeroLengthBitfieldBoundary = 32;
88326941Sdim
89326941Sdim  if (T.isOSBinFormatMachO() && IsAAPCS16) {
90326941Sdim    assert(!BigEndian && "AAPCS16 does not support big-endian");
91353358Sdim    resetDataLayout("e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128");
92326941Sdim  } else if (T.isOSBinFormatMachO())
93326941Sdim    resetDataLayout(
94326941Sdim        BigEndian
95353358Sdim            ? "E-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
96353358Sdim            : "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
97326941Sdim  else
98326941Sdim    resetDataLayout(
99326941Sdim        BigEndian
100353358Sdim            ? "E-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
101353358Sdim            : "e-m:e-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
102326941Sdim
103326941Sdim  // FIXME: Override "preferred align" for double and long long.
104326941Sdim}
105326941Sdim
106326941Sdimvoid ARMTargetInfo::setArchInfo() {
107326941Sdim  StringRef ArchName = getTriple().getArchName();
108326941Sdim
109326941Sdim  ArchISA = llvm::ARM::parseArchISA(ArchName);
110326941Sdim  CPU = llvm::ARM::getDefaultCPU(ArchName);
111326941Sdim  llvm::ARM::ArchKind AK = llvm::ARM::parseArch(ArchName);
112326941Sdim  if (AK != llvm::ARM::ArchKind::INVALID)
113326941Sdim    ArchKind = AK;
114326941Sdim  setArchInfo(ArchKind);
115326941Sdim}
116326941Sdim
117326941Sdimvoid ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) {
118326941Sdim  StringRef SubArch;
119326941Sdim
120326941Sdim  // cache TargetParser info
121326941Sdim  ArchKind = Kind;
122326941Sdim  SubArch = llvm::ARM::getSubArch(ArchKind);
123326941Sdim  ArchProfile = llvm::ARM::parseArchProfile(SubArch);
124326941Sdim  ArchVersion = llvm::ARM::parseArchVersion(SubArch);
125326941Sdim
126326941Sdim  // cache CPU related strings
127326941Sdim  CPUAttr = getCPUAttr();
128326941Sdim  CPUProfile = getCPUProfile();
129326941Sdim}
130326941Sdim
131326941Sdimvoid ARMTargetInfo::setAtomic() {
132326941Sdim  // when triple does not specify a sub arch,
133326941Sdim  // then we are not using inline atomics
134326941Sdim  bool ShouldUseInlineAtomic =
135326941Sdim      (ArchISA == llvm::ARM::ISAKind::ARM && ArchVersion >= 6) ||
136326941Sdim      (ArchISA == llvm::ARM::ISAKind::THUMB && ArchVersion >= 7);
137326941Sdim  // Cortex M does not support 8 byte atomics, while general Thumb2 does.
138326941Sdim  if (ArchProfile == llvm::ARM::ProfileKind::M) {
139326941Sdim    MaxAtomicPromoteWidth = 32;
140326941Sdim    if (ShouldUseInlineAtomic)
141326941Sdim      MaxAtomicInlineWidth = 32;
142326941Sdim  } else {
143326941Sdim    MaxAtomicPromoteWidth = 64;
144326941Sdim    if (ShouldUseInlineAtomic)
145326941Sdim      MaxAtomicInlineWidth = 64;
146326941Sdim  }
147326941Sdim}
148326941Sdim
149353358Sdimbool ARMTargetInfo::hasMVE() const {
150353358Sdim  return ArchKind == llvm::ARM::ArchKind::ARMV8_1MMainline && MVE != 0;
151353358Sdim}
152353358Sdim
153353358Sdimbool ARMTargetInfo::hasMVEFloat() const {
154353358Sdim  return hasMVE() && (MVE & MVE_FP);
155353358Sdim}
156353358Sdim
157326941Sdimbool ARMTargetInfo::isThumb() const {
158326941Sdim  return ArchISA == llvm::ARM::ISAKind::THUMB;
159326941Sdim}
160326941Sdim
161326941Sdimbool ARMTargetInfo::supportsThumb() const {
162326941Sdim  return CPUAttr.count('T') || ArchVersion >= 6;
163326941Sdim}
164326941Sdim
165326941Sdimbool ARMTargetInfo::supportsThumb2() const {
166326941Sdim  return CPUAttr.equals("6T2") ||
167326941Sdim         (ArchVersion >= 7 && !CPUAttr.equals("8M_BASE"));
168326941Sdim}
169326941Sdim
170326941SdimStringRef ARMTargetInfo::getCPUAttr() const {
171326941Sdim  // For most sub-arches, the build attribute CPU name is enough.
172326941Sdim  // For Cortex variants, it's slightly different.
173326941Sdim  switch (ArchKind) {
174326941Sdim  default:
175326941Sdim    return llvm::ARM::getCPUAttr(ArchKind);
176326941Sdim  case llvm::ARM::ArchKind::ARMV6M:
177326941Sdim    return "6M";
178326941Sdim  case llvm::ARM::ArchKind::ARMV7S:
179326941Sdim    return "7S";
180326941Sdim  case llvm::ARM::ArchKind::ARMV7A:
181326941Sdim    return "7A";
182326941Sdim  case llvm::ARM::ArchKind::ARMV7R:
183326941Sdim    return "7R";
184326941Sdim  case llvm::ARM::ArchKind::ARMV7M:
185326941Sdim    return "7M";
186326941Sdim  case llvm::ARM::ArchKind::ARMV7EM:
187326941Sdim    return "7EM";
188326941Sdim  case llvm::ARM::ArchKind::ARMV7VE:
189326941Sdim    return "7VE";
190326941Sdim  case llvm::ARM::ArchKind::ARMV8A:
191326941Sdim    return "8A";
192326941Sdim  case llvm::ARM::ArchKind::ARMV8_1A:
193326941Sdim    return "8_1A";
194326941Sdim  case llvm::ARM::ArchKind::ARMV8_2A:
195326941Sdim    return "8_2A";
196341825Sdim  case llvm::ARM::ArchKind::ARMV8_3A:
197341825Sdim    return "8_3A";
198341825Sdim  case llvm::ARM::ArchKind::ARMV8_4A:
199341825Sdim    return "8_4A";
200344779Sdim  case llvm::ARM::ArchKind::ARMV8_5A:
201344779Sdim    return "8_5A";
202326941Sdim  case llvm::ARM::ArchKind::ARMV8MBaseline:
203326941Sdim    return "8M_BASE";
204326941Sdim  case llvm::ARM::ArchKind::ARMV8MMainline:
205326941Sdim    return "8M_MAIN";
206326941Sdim  case llvm::ARM::ArchKind::ARMV8R:
207326941Sdim    return "8R";
208353358Sdim  case llvm::ARM::ArchKind::ARMV8_1MMainline:
209353358Sdim    return "8_1M_MAIN";
210326941Sdim  }
211326941Sdim}
212326941Sdim
213326941SdimStringRef ARMTargetInfo::getCPUProfile() const {
214326941Sdim  switch (ArchProfile) {
215326941Sdim  case llvm::ARM::ProfileKind::A:
216326941Sdim    return "A";
217326941Sdim  case llvm::ARM::ProfileKind::R:
218326941Sdim    return "R";
219326941Sdim  case llvm::ARM::ProfileKind::M:
220326941Sdim    return "M";
221326941Sdim  default:
222326941Sdim    return "";
223326941Sdim  }
224326941Sdim}
225326941Sdim
226326941SdimARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
227326941Sdim                             const TargetOptions &Opts)
228326941Sdim    : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
229326941Sdim      HW_FP(0) {
230344779Sdim  bool IsOpenBSD = Triple.isOSOpenBSD();
231344779Sdim  bool IsNetBSD = Triple.isOSNetBSD();
232326941Sdim
233326941Sdim  // FIXME: the isOSBinFormatMachO is a workaround for identifying a Darwin-like
234326941Sdim  // environment where size_t is `unsigned long` rather than `unsigned int`
235326941Sdim
236326941Sdim  PtrDiffType = IntPtrType =
237326941Sdim      (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
238326941Sdim       IsNetBSD)
239326941Sdim          ? SignedLong
240326941Sdim          : SignedInt;
241326941Sdim
242326941Sdim  SizeType = (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
243326941Sdim              IsNetBSD)
244326941Sdim                 ? UnsignedLong
245326941Sdim                 : UnsignedInt;
246326941Sdim
247326941Sdim  // ptrdiff_t is inconsistent on Darwin
248326941Sdim  if ((Triple.isOSDarwin() || Triple.isOSBinFormatMachO()) &&
249326941Sdim      !Triple.isWatchABI())
250326941Sdim    PtrDiffType = SignedInt;
251326941Sdim
252326941Sdim  // Cache arch related info.
253326941Sdim  setArchInfo();
254326941Sdim
255326941Sdim  // {} in inline assembly are neon specifiers, not assembly variant
256326941Sdim  // specifiers.
257326941Sdim  NoAsmVariants = true;
258326941Sdim
259326941Sdim  // FIXME: This duplicates code from the driver that sets the -target-abi
260326941Sdim  // option - this code is used if -target-abi isn't passed and should
261326941Sdim  // be unified in some way.
262326941Sdim  if (Triple.isOSBinFormatMachO()) {
263326941Sdim    // The backend is hardwired to assume AAPCS for M-class processors, ensure
264326941Sdim    // the frontend matches that.
265326941Sdim    if (Triple.getEnvironment() == llvm::Triple::EABI ||
266326941Sdim        Triple.getOS() == llvm::Triple::UnknownOS ||
267326941Sdim        ArchProfile == llvm::ARM::ProfileKind::M) {
268326941Sdim      setABI("aapcs");
269326941Sdim    } else if (Triple.isWatchABI()) {
270326941Sdim      setABI("aapcs16");
271326941Sdim    } else {
272326941Sdim      setABI("apcs-gnu");
273326941Sdim    }
274326941Sdim  } else if (Triple.isOSWindows()) {
275326941Sdim    // FIXME: this is invalid for WindowsCE
276326941Sdim    setABI("aapcs");
277326941Sdim  } else {
278326941Sdim    // Select the default based on the platform.
279326941Sdim    switch (Triple.getEnvironment()) {
280326941Sdim    case llvm::Triple::Android:
281326941Sdim    case llvm::Triple::GNUEABI:
282326941Sdim    case llvm::Triple::GNUEABIHF:
283326941Sdim    case llvm::Triple::MuslEABI:
284326941Sdim    case llvm::Triple::MuslEABIHF:
285326941Sdim      setABI("aapcs-linux");
286326941Sdim      break;
287326941Sdim    case llvm::Triple::EABIHF:
288326941Sdim    case llvm::Triple::EABI:
289326941Sdim      setABI("aapcs");
290326941Sdim      break;
291326941Sdim    case llvm::Triple::GNU:
292326941Sdim      setABI("apcs-gnu");
293326941Sdim      break;
294326941Sdim    default:
295344779Sdim      if (IsNetBSD)
296326941Sdim        setABI("apcs-gnu");
297344779Sdim      else if (IsOpenBSD)
298326941Sdim        setABI("aapcs-linux");
299326941Sdim      else
300326941Sdim        setABI("aapcs");
301326941Sdim      break;
302326941Sdim    }
303326941Sdim  }
304326941Sdim
305326941Sdim  // ARM targets default to using the ARM C++ ABI.
306326941Sdim  TheCXXABI.set(TargetCXXABI::GenericARM);
307326941Sdim
308326941Sdim  // ARM has atomics up to 8 bytes
309326941Sdim  setAtomic();
310326941Sdim
311326941Sdim  // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS)
312360784Sdim  // as well the default alignment
313326941Sdim  if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android))
314360784Sdim    DefaultAlignForAttributeAligned = MaxVectorAlign = 64;
315326941Sdim
316326941Sdim  // Do force alignment of members that follow zero length bitfields.  If
317326941Sdim  // the alignment of the zero-length bitfield is greater than the member
318326941Sdim  // that follows it, `bar', `bar' will be aligned as the  type of the
319326941Sdim  // zero length bitfield.
320326941Sdim  UseZeroLengthBitfieldAlignment = true;
321326941Sdim
322326941Sdim  if (Triple.getOS() == llvm::Triple::Linux ||
323326941Sdim      Triple.getOS() == llvm::Triple::UnknownOS)
324326941Sdim    this->MCountName = Opts.EABIVersion == llvm::EABI::GNU
325360784Sdim                           ? "llvm.arm.gnu.eabi.mcount"
326326941Sdim                           : "\01mcount";
327353358Sdim
328353358Sdim  SoftFloatABI = llvm::is_contained(Opts.FeaturesAsWritten, "+soft-float-abi");
329326941Sdim}
330326941Sdim
331326941SdimStringRef ARMTargetInfo::getABI() const { return ABI; }
332326941Sdim
333326941Sdimbool ARMTargetInfo::setABI(const std::string &Name) {
334326941Sdim  ABI = Name;
335326941Sdim
336326941Sdim  // The defaults (above) are for AAPCS, check if we need to change them.
337326941Sdim  //
338326941Sdim  // FIXME: We need support for -meabi... we could just mangle it into the
339326941Sdim  // name.
340326941Sdim  if (Name == "apcs-gnu" || Name == "aapcs16") {
341326941Sdim    setABIAPCS(Name == "aapcs16");
342326941Sdim    return true;
343326941Sdim  }
344326941Sdim  if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") {
345326941Sdim    setABIAAPCS();
346326941Sdim    return true;
347326941Sdim  }
348326941Sdim  return false;
349326941Sdim}
350326941Sdim
351326941Sdim// FIXME: This should be based on Arch attributes, not CPU names.
352326941Sdimbool ARMTargetInfo::initFeatureMap(
353326941Sdim    llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
354326941Sdim    const std::vector<std::string> &FeaturesVec) const {
355326941Sdim
356341825Sdim  std::string ArchFeature;
357326941Sdim  std::vector<StringRef> TargetFeatures;
358326941Sdim  llvm::ARM::ArchKind Arch = llvm::ARM::parseArch(getTriple().getArchName());
359326941Sdim
360341825Sdim  // Map the base architecture to an appropriate target feature, so we don't
361341825Sdim  // rely on the target triple.
362341825Sdim  llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(CPU);
363341825Sdim  if (CPUArch == llvm::ARM::ArchKind::INVALID)
364341825Sdim    CPUArch = Arch;
365341825Sdim  if (CPUArch != llvm::ARM::ArchKind::INVALID) {
366341825Sdim    ArchFeature = ("+" + llvm::ARM::getArchName(CPUArch)).str();
367341825Sdim    TargetFeatures.push_back(ArchFeature);
368341825Sdim  }
369341825Sdim
370326941Sdim  // get default FPU features
371326941Sdim  unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch);
372326941Sdim  llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures);
373326941Sdim
374326941Sdim  // get default Extension features
375326941Sdim  unsigned Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch);
376326941Sdim  llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures);
377326941Sdim
378326941Sdim  for (auto Feature : TargetFeatures)
379326941Sdim    if (Feature[0] == '+')
380326941Sdim      Features[Feature.drop_front(1)] = true;
381326941Sdim
382326941Sdim  // Enable or disable thumb-mode explicitly per function to enable mixed
383326941Sdim  // ARM and Thumb code generation.
384326941Sdim  if (isThumb())
385326941Sdim    Features["thumb-mode"] = true;
386326941Sdim  else
387326941Sdim    Features["thumb-mode"] = false;
388326941Sdim
389326941Sdim  // Convert user-provided arm and thumb GNU target attributes to
390326941Sdim  // [-|+]thumb-mode target features respectively.
391353358Sdim  std::vector<std::string> UpdatedFeaturesVec;
392353358Sdim  for (const auto &Feature : FeaturesVec) {
393353358Sdim    // Skip soft-float-abi; it's something we only use to initialize a bit of
394353358Sdim    // class state, and is otherwise unrecognized.
395353358Sdim    if (Feature == "+soft-float-abi")
396353358Sdim      continue;
397353358Sdim
398353358Sdim    StringRef FixedFeature;
399353358Sdim    if (Feature == "+arm")
400353358Sdim      FixedFeature = "-thumb-mode";
401353358Sdim    else if (Feature == "+thumb")
402353358Sdim      FixedFeature = "+thumb-mode";
403353358Sdim    else
404353358Sdim      FixedFeature = Feature;
405353358Sdim    UpdatedFeaturesVec.push_back(FixedFeature.str());
406326941Sdim  }
407326941Sdim
408326941Sdim  return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);
409326941Sdim}
410326941Sdim
411326941Sdim
412326941Sdimbool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
413326941Sdim                                         DiagnosticsEngine &Diags) {
414326941Sdim  FPU = 0;
415353358Sdim  MVE = 0;
416326941Sdim  CRC = 0;
417326941Sdim  Crypto = 0;
418326941Sdim  DSP = 0;
419326941Sdim  Unaligned = 1;
420353358Sdim  SoftFloat = false;
421353358Sdim  // Note that SoftFloatABI is initialized in our constructor.
422326941Sdim  HWDiv = 0;
423341825Sdim  DotProd = 0;
424344779Sdim  HasFloat16 = true;
425326941Sdim
426326941Sdim  // This does not diagnose illegal cases like having both
427353358Sdim  // "+vfpv2" and "+vfpv3" or having "+neon" and "-fp64".
428326941Sdim  for (const auto &Feature : Features) {
429326941Sdim    if (Feature == "+soft-float") {
430326941Sdim      SoftFloat = true;
431360784Sdim    } else if (Feature == "+vfp2sp" || Feature == "+vfp2") {
432326941Sdim      FPU |= VFP2FPU;
433353358Sdim      HW_FP |= HW_FP_SP;
434360784Sdim      if (Feature == "+vfp2")
435353358Sdim          HW_FP |= HW_FP_DP;
436353358Sdim    } else if (Feature == "+vfp3sp" || Feature == "+vfp3d16sp" ||
437353358Sdim               Feature == "+vfp3" || Feature == "+vfp3d16") {
438326941Sdim      FPU |= VFP3FPU;
439353358Sdim      HW_FP |= HW_FP_SP;
440353358Sdim      if (Feature == "+vfp3" || Feature == "+vfp3d16")
441353358Sdim          HW_FP |= HW_FP_DP;
442353358Sdim    } else if (Feature == "+vfp4sp" || Feature == "+vfp4d16sp" ||
443353358Sdim               Feature == "+vfp4" || Feature == "+vfp4d16") {
444326941Sdim      FPU |= VFP4FPU;
445353358Sdim      HW_FP |= HW_FP_SP | HW_FP_HP;
446353358Sdim      if (Feature == "+vfp4" || Feature == "+vfp4d16")
447353358Sdim          HW_FP |= HW_FP_DP;
448353358Sdim    } else if (Feature == "+fp-armv8sp" || Feature == "+fp-armv8d16sp" ||
449353358Sdim               Feature == "+fp-armv8" || Feature == "+fp-armv8d16") {
450326941Sdim      FPU |= FPARMV8;
451353358Sdim      HW_FP |= HW_FP_SP | HW_FP_HP;
452353358Sdim      if (Feature == "+fp-armv8" || Feature == "+fp-armv8d16")
453353358Sdim          HW_FP |= HW_FP_DP;
454326941Sdim    } else if (Feature == "+neon") {
455326941Sdim      FPU |= NeonFPU;
456353358Sdim      HW_FP |= HW_FP_SP;
457326941Sdim    } else if (Feature == "+hwdiv") {
458326941Sdim      HWDiv |= HWDivThumb;
459326941Sdim    } else if (Feature == "+hwdiv-arm") {
460326941Sdim      HWDiv |= HWDivARM;
461326941Sdim    } else if (Feature == "+crc") {
462326941Sdim      CRC = 1;
463326941Sdim    } else if (Feature == "+crypto") {
464326941Sdim      Crypto = 1;
465326941Sdim    } else if (Feature == "+dsp") {
466326941Sdim      DSP = 1;
467353358Sdim    } else if (Feature == "+fp64") {
468353358Sdim      HW_FP |= HW_FP_DP;
469353358Sdim    } else if (Feature == "+8msecext") {
470353358Sdim      if (CPUProfile != "M" || ArchVersion != 8) {
471353358Sdim        Diags.Report(diag::err_target_unsupported_mcmse) << CPU;
472353358Sdim        return false;
473353358Sdim      }
474326941Sdim    } else if (Feature == "+strict-align") {
475326941Sdim      Unaligned = 0;
476326941Sdim    } else if (Feature == "+fp16") {
477326941Sdim      HW_FP |= HW_FP_HP;
478341825Sdim    } else if (Feature == "+fullfp16") {
479341825Sdim      HasLegalHalfType = true;
480341825Sdim    } else if (Feature == "+dotprod") {
481341825Sdim      DotProd = true;
482353358Sdim    } else if (Feature == "+mve") {
483353358Sdim      DSP = 1;
484353358Sdim      MVE |= MVE_INT;
485353358Sdim    } else if (Feature == "+mve.fp") {
486353358Sdim      DSP = 1;
487353358Sdim      HasLegalHalfType = true;
488353358Sdim      FPU |= FPARMV8;
489353358Sdim      MVE |= MVE_INT | MVE_FP;
490353358Sdim      HW_FP |= HW_FP_SP | HW_FP_HP;
491326941Sdim    }
492326941Sdim  }
493326941Sdim
494326941Sdim  switch (ArchVersion) {
495326941Sdim  case 6:
496326941Sdim    if (ArchProfile == llvm::ARM::ProfileKind::M)
497326941Sdim      LDREX = 0;
498326941Sdim    else if (ArchKind == llvm::ARM::ArchKind::ARMV6K)
499326941Sdim      LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
500326941Sdim    else
501326941Sdim      LDREX = LDREX_W;
502326941Sdim    break;
503326941Sdim  case 7:
504326941Sdim    if (ArchProfile == llvm::ARM::ProfileKind::M)
505326941Sdim      LDREX = LDREX_W | LDREX_H | LDREX_B;
506326941Sdim    else
507326941Sdim      LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
508326941Sdim    break;
509326941Sdim  case 8:
510326941Sdim    LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
511326941Sdim  }
512326941Sdim
513326941Sdim  if (!(FPU & NeonFPU) && FPMath == FP_Neon) {
514326941Sdim    Diags.Report(diag::err_target_unsupported_fpmath) << "neon";
515326941Sdim    return false;
516326941Sdim  }
517326941Sdim
518326941Sdim  if (FPMath == FP_Neon)
519326941Sdim    Features.push_back("+neonfp");
520326941Sdim  else if (FPMath == FP_VFP)
521326941Sdim    Features.push_back("-neonfp");
522326941Sdim
523326941Sdim  return true;
524326941Sdim}
525326941Sdim
526326941Sdimbool ARMTargetInfo::hasFeature(StringRef Feature) const {
527326941Sdim  return llvm::StringSwitch<bool>(Feature)
528326941Sdim      .Case("arm", true)
529326941Sdim      .Case("aarch32", true)
530326941Sdim      .Case("softfloat", SoftFloat)
531326941Sdim      .Case("thumb", isThumb())
532326941Sdim      .Case("neon", (FPU & NeonFPU) && !SoftFloat)
533326941Sdim      .Case("vfp", FPU && !SoftFloat)
534326941Sdim      .Case("hwdiv", HWDiv & HWDivThumb)
535326941Sdim      .Case("hwdiv-arm", HWDiv & HWDivARM)
536353358Sdim      .Case("mve", hasMVE())
537326941Sdim      .Default(false);
538326941Sdim}
539326941Sdim
540326941Sdimbool ARMTargetInfo::isValidCPUName(StringRef Name) const {
541326941Sdim  return Name == "generic" ||
542326941Sdim         llvm::ARM::parseCPUArch(Name) != llvm::ARM::ArchKind::INVALID;
543326941Sdim}
544326941Sdim
545341825Sdimvoid ARMTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
546341825Sdim  llvm::ARM::fillValidCPUArchList(Values);
547341825Sdim}
548341825Sdim
549326941Sdimbool ARMTargetInfo::setCPU(const std::string &Name) {
550326941Sdim  if (Name != "generic")
551326941Sdim    setArchInfo(llvm::ARM::parseCPUArch(Name));
552326941Sdim
553326941Sdim  if (ArchKind == llvm::ARM::ArchKind::INVALID)
554326941Sdim    return false;
555326941Sdim  setAtomic();
556326941Sdim  CPU = Name;
557326941Sdim  return true;
558326941Sdim}
559326941Sdim
560326941Sdimbool ARMTargetInfo::setFPMath(StringRef Name) {
561326941Sdim  if (Name == "neon") {
562326941Sdim    FPMath = FP_Neon;
563326941Sdim    return true;
564326941Sdim  } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" ||
565326941Sdim             Name == "vfp4") {
566326941Sdim    FPMath = FP_VFP;
567326941Sdim    return true;
568326941Sdim  }
569326941Sdim  return false;
570326941Sdim}
571326941Sdim
572326941Sdimvoid ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
573326941Sdim                                            MacroBuilder &Builder) const {
574326941Sdim  Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
575326941Sdim}
576326941Sdim
577326941Sdimvoid ARMTargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
578326941Sdim                                            MacroBuilder &Builder) const {
579326941Sdim  // Also include the ARMv8.1-A defines
580326941Sdim  getTargetDefinesARMV81A(Opts, Builder);
581326941Sdim}
582326941Sdim
583360784Sdimvoid ARMTargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts,
584360784Sdim                                            MacroBuilder &Builder) const {
585360784Sdim  // Also include the ARMv8.2-A defines
586360784Sdim  Builder.defineMacro("__ARM_FEATURE_COMPLEX", "1");
587360784Sdim  getTargetDefinesARMV82A(Opts, Builder);
588360784Sdim}
589360784Sdim
590326941Sdimvoid ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
591326941Sdim                                     MacroBuilder &Builder) const {
592326941Sdim  // Target identification.
593326941Sdim  Builder.defineMacro("__arm");
594326941Sdim  Builder.defineMacro("__arm__");
595326941Sdim  // For bare-metal none-eabi.
596326941Sdim  if (getTriple().getOS() == llvm::Triple::UnknownOS &&
597326941Sdim      (getTriple().getEnvironment() == llvm::Triple::EABI ||
598326941Sdim       getTriple().getEnvironment() == llvm::Triple::EABIHF))
599326941Sdim    Builder.defineMacro("__ELF__");
600326941Sdim
601326941Sdim  // Target properties.
602326941Sdim  Builder.defineMacro("__REGISTER_PREFIX__", "");
603326941Sdim
604326941Sdim  // Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU
605326941Sdim  // happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__.
606326941Sdim  if (getTriple().isWatchABI())
607326941Sdim    Builder.defineMacro("__ARM_ARCH_7K__", "2");
608326941Sdim
609326941Sdim  if (!CPUAttr.empty())
610326941Sdim    Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__");
611326941Sdim
612326941Sdim  // ACLE 6.4.1 ARM/Thumb instruction set architecture
613326941Sdim  // __ARM_ARCH is defined as an integer value indicating the current ARM ISA
614326941Sdim  Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion));
615326941Sdim
616326941Sdim  if (ArchVersion >= 8) {
617326941Sdim    // ACLE 6.5.7 Crypto Extension
618326941Sdim    if (Crypto)
619326941Sdim      Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
620326941Sdim    // ACLE 6.5.8 CRC32 Extension
621326941Sdim    if (CRC)
622326941Sdim      Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
623326941Sdim    // ACLE 6.5.10 Numeric Maximum and Minimum
624326941Sdim    Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
625326941Sdim    // ACLE 6.5.9 Directed Rounding
626326941Sdim    Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
627326941Sdim  }
628326941Sdim
629326941Sdim  // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA.  It
630326941Sdim  // is not defined for the M-profile.
631326941Sdim  // NOTE that the default profile is assumed to be 'A'
632326941Sdim  if (CPUProfile.empty() || ArchProfile != llvm::ARM::ProfileKind::M)
633326941Sdim    Builder.defineMacro("__ARM_ARCH_ISA_ARM", "1");
634326941Sdim
635326941Sdim  // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original
636326941Sdim  // Thumb ISA (including v6-M and v8-M Baseline).  It is set to 2 if the
637326941Sdim  // core supports the Thumb-2 ISA as found in the v6T2 architecture and all
638326941Sdim  // v7 and v8 architectures excluding v8-M Baseline.
639326941Sdim  if (supportsThumb2())
640326941Sdim    Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2");
641326941Sdim  else if (supportsThumb())
642326941Sdim    Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1");
643326941Sdim
644326941Sdim  // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit
645326941Sdim  // instruction set such as ARM or Thumb.
646326941Sdim  Builder.defineMacro("__ARM_32BIT_STATE", "1");
647326941Sdim
648326941Sdim  // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex)
649326941Sdim
650326941Sdim  // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset.
651326941Sdim  if (!CPUProfile.empty())
652326941Sdim    Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'");
653326941Sdim
654326941Sdim  // ACLE 6.4.3 Unaligned access supported in hardware
655326941Sdim  if (Unaligned)
656326941Sdim    Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
657326941Sdim
658326941Sdim  // ACLE 6.4.4 LDREX/STREX
659326941Sdim  if (LDREX)
660327330Sdim    Builder.defineMacro("__ARM_FEATURE_LDREX", "0x" + Twine::utohexstr(LDREX));
661326941Sdim
662326941Sdim  // ACLE 6.4.5 CLZ
663326941Sdim  if (ArchVersion == 5 || (ArchVersion == 6 && CPUProfile != "M") ||
664326941Sdim      ArchVersion > 6)
665326941Sdim    Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
666326941Sdim
667326941Sdim  // ACLE 6.5.1 Hardware Floating Point
668326941Sdim  if (HW_FP)
669327330Sdim    Builder.defineMacro("__ARM_FP", "0x" + Twine::utohexstr(HW_FP));
670326941Sdim
671326941Sdim  // ACLE predefines.
672326941Sdim  Builder.defineMacro("__ARM_ACLE", "200");
673326941Sdim
674326941Sdim  // FP16 support (we currently only support IEEE format).
675326941Sdim  Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
676326941Sdim  Builder.defineMacro("__ARM_FP16_ARGS", "1");
677326941Sdim
678326941Sdim  // ACLE 6.5.3 Fused multiply-accumulate (FMA)
679326941Sdim  if (ArchVersion >= 7 && (FPU & VFP4FPU))
680326941Sdim    Builder.defineMacro("__ARM_FEATURE_FMA", "1");
681326941Sdim
682326941Sdim  // Subtarget options.
683326941Sdim
684326941Sdim  // FIXME: It's more complicated than this and we don't really support
685326941Sdim  // interworking.
686326941Sdim  // Windows on ARM does not "support" interworking
687326941Sdim  if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows())
688326941Sdim    Builder.defineMacro("__THUMB_INTERWORK__");
689326941Sdim
690326941Sdim  if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {
691326941Sdim    // Embedded targets on Darwin follow AAPCS, but not EABI.
692326941Sdim    // Windows on ARM follows AAPCS VFP, but does not conform to EABI.
693326941Sdim    if (!getTriple().isOSBinFormatMachO() && !getTriple().isOSWindows())
694326941Sdim      Builder.defineMacro("__ARM_EABI__");
695326941Sdim    Builder.defineMacro("__ARM_PCS", "1");
696326941Sdim  }
697326941Sdim
698326941Sdim  if ((!SoftFloat && !SoftFloatABI) || ABI == "aapcs-vfp" || ABI == "aapcs16")
699326941Sdim    Builder.defineMacro("__ARM_PCS_VFP", "1");
700326941Sdim
701326941Sdim  if (SoftFloat)
702326941Sdim    Builder.defineMacro("__SOFTFP__");
703326941Sdim
704353358Sdim  // ACLE position independent code macros.
705353358Sdim  if (Opts.ROPI)
706353358Sdim    Builder.defineMacro("__ARM_ROPI", "1");
707353358Sdim  if (Opts.RWPI)
708353358Sdim    Builder.defineMacro("__ARM_RWPI", "1");
709353358Sdim
710326941Sdim  if (ArchKind == llvm::ARM::ArchKind::XSCALE)
711326941Sdim    Builder.defineMacro("__XSCALE__");
712326941Sdim
713326941Sdim  if (isThumb()) {
714326941Sdim    Builder.defineMacro("__THUMBEL__");
715326941Sdim    Builder.defineMacro("__thumb__");
716326941Sdim    if (supportsThumb2())
717326941Sdim      Builder.defineMacro("__thumb2__");
718326941Sdim  }
719326941Sdim
720326941Sdim  // ACLE 6.4.9 32-bit SIMD instructions
721344779Sdim  if ((CPUProfile != "M" && ArchVersion >= 6) || (CPUProfile == "M" && DSP))
722326941Sdim    Builder.defineMacro("__ARM_FEATURE_SIMD32", "1");
723326941Sdim
724326941Sdim  // ACLE 6.4.10 Hardware Integer Divide
725326941Sdim  if (((HWDiv & HWDivThumb) && isThumb()) ||
726326941Sdim      ((HWDiv & HWDivARM) && !isThumb())) {
727326941Sdim    Builder.defineMacro("__ARM_FEATURE_IDIV", "1");
728326941Sdim    Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1");
729326941Sdim  }
730326941Sdim
731326941Sdim  // Note, this is always on in gcc, even though it doesn't make sense.
732326941Sdim  Builder.defineMacro("__APCS_32__");
733326941Sdim
734326941Sdim  if (FPUModeIsVFP((FPUMode)FPU)) {
735326941Sdim    Builder.defineMacro("__VFP_FP__");
736326941Sdim    if (FPU & VFP2FPU)
737326941Sdim      Builder.defineMacro("__ARM_VFPV2__");
738326941Sdim    if (FPU & VFP3FPU)
739326941Sdim      Builder.defineMacro("__ARM_VFPV3__");
740326941Sdim    if (FPU & VFP4FPU)
741326941Sdim      Builder.defineMacro("__ARM_VFPV4__");
742326941Sdim    if (FPU & FPARMV8)
743326941Sdim      Builder.defineMacro("__ARM_FPV5__");
744326941Sdim  }
745326941Sdim
746326941Sdim  // This only gets set when Neon instructions are actually available, unlike
747326941Sdim  // the VFP define, hence the soft float and arch check. This is subtly
748326941Sdim  // different from gcc, we follow the intent which was that it should be set
749326941Sdim  // when Neon instructions are actually available.
750326941Sdim  if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) {
751326941Sdim    Builder.defineMacro("__ARM_NEON", "1");
752326941Sdim    Builder.defineMacro("__ARM_NEON__");
753326941Sdim    // current AArch32 NEON implementations do not support double-precision
754326941Sdim    // floating-point even when it is present in VFP.
755326941Sdim    Builder.defineMacro("__ARM_NEON_FP",
756327330Sdim                        "0x" + Twine::utohexstr(HW_FP & ~HW_FP_DP));
757326941Sdim  }
758326941Sdim
759353358Sdim  if (hasMVE()) {
760353358Sdim    Builder.defineMacro("__ARM_FEATURE_MVE", hasMVEFloat() ? "3" : "1");
761353358Sdim  }
762353358Sdim
763326941Sdim  Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
764327330Sdim                      Twine(Opts.WCharSize ? Opts.WCharSize : 4));
765326941Sdim
766326941Sdim  Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
767326941Sdim
768353358Sdim  // CMSE
769353358Sdim  if (ArchVersion == 8 && ArchProfile == llvm::ARM::ProfileKind::M)
770353358Sdim    Builder.defineMacro("__ARM_FEATURE_CMSE", Opts.Cmse ? "3" : "1");
771353358Sdim
772326941Sdim  if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE") {
773326941Sdim    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
774326941Sdim    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
775326941Sdim    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
776326941Sdim    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
777326941Sdim  }
778326941Sdim
779326941Sdim  // ACLE 6.4.7 DSP instructions
780326941Sdim  if (DSP) {
781326941Sdim    Builder.defineMacro("__ARM_FEATURE_DSP", "1");
782326941Sdim  }
783326941Sdim
784326941Sdim  // ACLE 6.4.8 Saturation instructions
785326941Sdim  bool SAT = false;
786326941Sdim  if ((ArchVersion == 6 && CPUProfile != "M") || ArchVersion > 6) {
787326941Sdim    Builder.defineMacro("__ARM_FEATURE_SAT", "1");
788326941Sdim    SAT = true;
789326941Sdim  }
790326941Sdim
791326941Sdim  // ACLE 6.4.6 Q (saturation) flag
792326941Sdim  if (DSP || SAT)
793326941Sdim    Builder.defineMacro("__ARM_FEATURE_QBIT", "1");
794326941Sdim
795326941Sdim  if (Opts.UnsafeFPMath)
796326941Sdim    Builder.defineMacro("__ARM_FP_FAST", "1");
797326941Sdim
798341825Sdim  // Armv8.2-A FP16 vector intrinsic
799341825Sdim  if ((FPU & NeonFPU) && HasLegalHalfType)
800341825Sdim    Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
801341825Sdim
802341825Sdim  // Armv8.2-A FP16 scalar intrinsics
803341825Sdim  if (HasLegalHalfType)
804341825Sdim    Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
805341825Sdim
806341825Sdim  // Armv8.2-A dot product intrinsics
807341825Sdim  if (DotProd)
808341825Sdim    Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
809341825Sdim
810326941Sdim  switch (ArchKind) {
811326941Sdim  default:
812326941Sdim    break;
813326941Sdim  case llvm::ARM::ArchKind::ARMV8_1A:
814326941Sdim    getTargetDefinesARMV81A(Opts, Builder);
815326941Sdim    break;
816326941Sdim  case llvm::ARM::ArchKind::ARMV8_2A:
817326941Sdim    getTargetDefinesARMV82A(Opts, Builder);
818326941Sdim    break;
819360784Sdim  case llvm::ARM::ArchKind::ARMV8_3A:
820360784Sdim  case llvm::ARM::ArchKind::ARMV8_4A:
821360784Sdim  case llvm::ARM::ArchKind::ARMV8_5A:
822360784Sdim    getTargetDefinesARMV83A(Opts, Builder);
823360784Sdim    break;
824326941Sdim  }
825326941Sdim}
826326941Sdim
827326941Sdimconst Builtin::Info ARMTargetInfo::BuiltinInfo[] = {
828326941Sdim#define BUILTIN(ID, TYPE, ATTRS)                                               \
829326941Sdim  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
830326941Sdim#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
831326941Sdim  {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
832326941Sdim#include "clang/Basic/BuiltinsNEON.def"
833326941Sdim
834326941Sdim#define BUILTIN(ID, TYPE, ATTRS)                                               \
835326941Sdim  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
836326941Sdim#define LANGBUILTIN(ID, TYPE, ATTRS, LANG)                                     \
837326941Sdim  {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
838326941Sdim#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
839326941Sdim  {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
840326941Sdim#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE)         \
841326941Sdim  {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
842326941Sdim#include "clang/Basic/BuiltinsARM.def"
843326941Sdim};
844326941Sdim
845326941SdimArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const {
846326941Sdim  return llvm::makeArrayRef(BuiltinInfo, clang::ARM::LastTSBuiltin -
847326941Sdim                                             Builtin::FirstTSBuiltin);
848326941Sdim}
849326941Sdim
850326941Sdimbool ARMTargetInfo::isCLZForZeroUndef() const { return false; }
851326941SdimTargetInfo::BuiltinVaListKind ARMTargetInfo::getBuiltinVaListKind() const {
852326941Sdim  return IsAAPCS
853326941Sdim             ? AAPCSABIBuiltinVaList
854326941Sdim             : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList
855326941Sdim                                         : TargetInfo::VoidPtrBuiltinVaList);
856326941Sdim}
857326941Sdim
858326941Sdimconst char *const ARMTargetInfo::GCCRegNames[] = {
859326941Sdim    // Integer registers
860326941Sdim    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
861326941Sdim    "r12", "sp", "lr", "pc",
862326941Sdim
863326941Sdim    // Float registers
864326941Sdim    "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
865326941Sdim    "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
866326941Sdim    "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
867326941Sdim
868326941Sdim    // Double registers
869326941Sdim    "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
870326941Sdim    "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
871326941Sdim    "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
872326941Sdim
873326941Sdim    // Quad registers
874326941Sdim    "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11",
875326941Sdim    "q12", "q13", "q14", "q15"};
876326941Sdim
877326941SdimArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const {
878326941Sdim  return llvm::makeArrayRef(GCCRegNames);
879326941Sdim}
880326941Sdim
881326941Sdimconst TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
882326941Sdim    {{"a1"}, "r0"},  {{"a2"}, "r1"},        {{"a3"}, "r2"},  {{"a4"}, "r3"},
883326941Sdim    {{"v1"}, "r4"},  {{"v2"}, "r5"},        {{"v3"}, "r6"},  {{"v4"}, "r7"},
884326941Sdim    {{"v5"}, "r8"},  {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"},
885326941Sdim    {{"ip"}, "r12"}, {{"r13"}, "sp"},       {{"r14"}, "lr"}, {{"r15"}, "pc"},
886326941Sdim    // The S, D and Q registers overlap, but aren't really aliases; we
887326941Sdim    // don't want to substitute one of these for a different-sized one.
888326941Sdim};
889326941Sdim
890326941SdimArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const {
891326941Sdim  return llvm::makeArrayRef(GCCRegAliases);
892326941Sdim}
893326941Sdim
894326941Sdimbool ARMTargetInfo::validateAsmConstraint(
895326941Sdim    const char *&Name, TargetInfo::ConstraintInfo &Info) const {
896326941Sdim  switch (*Name) {
897326941Sdim  default:
898326941Sdim    break;
899360784Sdim  case 'l': // r0-r7 if thumb, r0-r15 if ARM
900326941Sdim    Info.setAllowsRegister();
901326941Sdim    return true;
902360784Sdim  case 'h': // r8-r15, thumb only
903360784Sdim    if (isThumb()) {
904360784Sdim      Info.setAllowsRegister();
905360784Sdim      return true;
906360784Sdim    }
907360784Sdim    break;
908360784Sdim  case 's': // An integer constant, but allowing only relocatable values.
909360784Sdim    return true;
910360784Sdim  case 't': // s0-s31, d0-d31, or q0-q15
911360784Sdim  case 'w': // s0-s15, d0-d7, or q0-q3
912360784Sdim  case 'x': // s0-s31, d0-d15, or q0-q7
913360784Sdim    Info.setAllowsRegister();
914360784Sdim    return true;
915360784Sdim  case 'j': // An immediate integer between 0 and 65535 (valid for MOVW)
916360784Sdim    // only available in ARMv6T2 and above
917360784Sdim    if (CPUAttr.equals("6T2") || ArchVersion >= 7) {
918360784Sdim      Info.setRequiresImmediate(0, 65535);
919360784Sdim      return true;
920360784Sdim    }
921360784Sdim    break;
922326941Sdim  case 'I':
923360784Sdim    if (isThumb()) {
924360784Sdim      if (!supportsThumb2())
925360784Sdim        Info.setRequiresImmediate(0, 255);
926360784Sdim      else
927360784Sdim        // FIXME: should check if immediate value would be valid for a Thumb2
928360784Sdim        // data-processing instruction
929360784Sdim        Info.setRequiresImmediate();
930360784Sdim    } else
931360784Sdim      // FIXME: should check if immediate value would be valid for an ARM
932360784Sdim      // data-processing instruction
933360784Sdim      Info.setRequiresImmediate();
934360784Sdim    return true;
935326941Sdim  case 'J':
936360784Sdim    if (isThumb() && !supportsThumb2())
937360784Sdim      Info.setRequiresImmediate(-255, -1);
938360784Sdim    else
939360784Sdim      Info.setRequiresImmediate(-4095, 4095);
940360784Sdim    return true;
941326941Sdim  case 'K':
942360784Sdim    if (isThumb()) {
943360784Sdim      if (!supportsThumb2())
944360784Sdim        // FIXME: should check if immediate value can be obtained from shifting
945360784Sdim        // a value between 0 and 255 left by any amount
946360784Sdim        Info.setRequiresImmediate();
947360784Sdim      else
948360784Sdim        // FIXME: should check if immediate value would be valid for a Thumb2
949360784Sdim        // data-processing instruction when inverted
950360784Sdim        Info.setRequiresImmediate();
951360784Sdim    } else
952360784Sdim      // FIXME: should check if immediate value would be valid for an ARM
953360784Sdim      // data-processing instruction when inverted
954360784Sdim      Info.setRequiresImmediate();
955360784Sdim    return true;
956326941Sdim  case 'L':
957360784Sdim    if (isThumb()) {
958360784Sdim      if (!supportsThumb2())
959360784Sdim        Info.setRequiresImmediate(-7, 7);
960360784Sdim      else
961360784Sdim        // FIXME: should check if immediate value would be valid for a Thumb2
962360784Sdim        // data-processing instruction when negated
963360784Sdim        Info.setRequiresImmediate();
964360784Sdim    } else
965360784Sdim      // FIXME: should check if immediate value  would be valid for an ARM
966360784Sdim      // data-processing instruction when negated
967360784Sdim      Info.setRequiresImmediate();
968360784Sdim    return true;
969326941Sdim  case 'M':
970360784Sdim    if (isThumb() && !supportsThumb2())
971360784Sdim      // FIXME: should check if immediate value is a multiple of 4 between 0 and
972360784Sdim      // 1020
973360784Sdim      Info.setRequiresImmediate();
974360784Sdim    else
975360784Sdim      // FIXME: should check if immediate value is a power of two or a integer
976360784Sdim      // between 0 and 32
977360784Sdim      Info.setRequiresImmediate();
978326941Sdim    return true;
979360784Sdim  case 'N':
980360784Sdim    // Thumb1 only
981360784Sdim    if (isThumb() && !supportsThumb2()) {
982360784Sdim      Info.setRequiresImmediate(0, 31);
983360784Sdim      return true;
984360784Sdim    }
985360784Sdim    break;
986360784Sdim  case 'O':
987360784Sdim    // Thumb1 only
988360784Sdim    if (isThumb() && !supportsThumb2()) {
989360784Sdim      // FIXME: should check if immediate value is a multiple of 4 between -508
990360784Sdim      // and 508
991360784Sdim      Info.setRequiresImmediate();
992360784Sdim      return true;
993360784Sdim    }
994360784Sdim    break;
995326941Sdim  case 'Q': // A memory address that is a single base register.
996326941Sdim    Info.setAllowsMemory();
997326941Sdim    return true;
998353358Sdim  case 'T':
999353358Sdim    switch (Name[1]) {
1000353358Sdim    default:
1001353358Sdim      break;
1002353358Sdim    case 'e': // Even general-purpose register
1003353358Sdim    case 'o': // Odd general-purpose register
1004353358Sdim      Info.setAllowsRegister();
1005353358Sdim      Name++;
1006353358Sdim      return true;
1007353358Sdim    }
1008353358Sdim    break;
1009326941Sdim  case 'U': // a memory reference...
1010326941Sdim    switch (Name[1]) {
1011326941Sdim    case 'q': // ...ARMV4 ldrsb
1012326941Sdim    case 'v': // ...VFP load/store (reg+constant offset)
1013326941Sdim    case 'y': // ...iWMMXt load/store
1014326941Sdim    case 't': // address valid for load/store opaque types wider
1015326941Sdim              // than 128-bits
1016326941Sdim    case 'n': // valid address for Neon doubleword vector load/store
1017326941Sdim    case 'm': // valid address for Neon element and structure load/store
1018326941Sdim    case 's': // valid address for non-offset loads/stores of quad-word
1019326941Sdim              // values in four ARM registers
1020326941Sdim      Info.setAllowsMemory();
1021326941Sdim      Name++;
1022326941Sdim      return true;
1023326941Sdim    }
1024353358Sdim    break;
1025326941Sdim  }
1026326941Sdim  return false;
1027326941Sdim}
1028326941Sdim
1029326941Sdimstd::string ARMTargetInfo::convertConstraint(const char *&Constraint) const {
1030326941Sdim  std::string R;
1031326941Sdim  switch (*Constraint) {
1032326941Sdim  case 'U': // Two-character constraint; add "^" hint for later parsing.
1033353358Sdim  case 'T':
1034326941Sdim    R = std::string("^") + std::string(Constraint, 2);
1035326941Sdim    Constraint++;
1036326941Sdim    break;
1037326941Sdim  case 'p': // 'p' should be translated to 'r' by default.
1038326941Sdim    R = std::string("r");
1039326941Sdim    break;
1040326941Sdim  default:
1041326941Sdim    return std::string(1, *Constraint);
1042326941Sdim  }
1043326941Sdim  return R;
1044326941Sdim}
1045326941Sdim
1046326941Sdimbool ARMTargetInfo::validateConstraintModifier(
1047326941Sdim    StringRef Constraint, char Modifier, unsigned Size,
1048326941Sdim    std::string &SuggestedModifier) const {
1049326941Sdim  bool isOutput = (Constraint[0] == '=');
1050326941Sdim  bool isInOut = (Constraint[0] == '+');
1051326941Sdim
1052326941Sdim  // Strip off constraint modifiers.
1053326941Sdim  while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
1054326941Sdim    Constraint = Constraint.substr(1);
1055326941Sdim
1056326941Sdim  switch (Constraint[0]) {
1057326941Sdim  default:
1058326941Sdim    break;
1059326941Sdim  case 'r': {
1060326941Sdim    switch (Modifier) {
1061326941Sdim    default:
1062326941Sdim      return (isInOut || isOutput || Size <= 64);
1063326941Sdim    case 'q':
1064326941Sdim      // A register of size 32 cannot fit a vector type.
1065326941Sdim      return false;
1066326941Sdim    }
1067326941Sdim  }
1068326941Sdim  }
1069326941Sdim
1070326941Sdim  return true;
1071326941Sdim}
1072326941Sdimconst char *ARMTargetInfo::getClobbers() const {
1073326941Sdim  // FIXME: Is this really right?
1074326941Sdim  return "";
1075326941Sdim}
1076326941Sdim
1077326941SdimTargetInfo::CallingConvCheckResult
1078326941SdimARMTargetInfo::checkCallingConvention(CallingConv CC) const {
1079326941Sdim  switch (CC) {
1080326941Sdim  case CC_AAPCS:
1081326941Sdim  case CC_AAPCS_VFP:
1082326941Sdim  case CC_Swift:
1083326941Sdim  case CC_OpenCLKernel:
1084326941Sdim    return CCCR_OK;
1085326941Sdim  default:
1086326941Sdim    return CCCR_Warning;
1087326941Sdim  }
1088326941Sdim}
1089326941Sdim
1090326941Sdimint ARMTargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
1091326941Sdim  if (RegNo == 0)
1092326941Sdim    return 0;
1093326941Sdim  if (RegNo == 1)
1094326941Sdim    return 1;
1095326941Sdim  return -1;
1096326941Sdim}
1097326941Sdim
1098326941Sdimbool ARMTargetInfo::hasSjLjLowering() const { return true; }
1099326941Sdim
1100326941SdimARMleTargetInfo::ARMleTargetInfo(const llvm::Triple &Triple,
1101326941Sdim                                 const TargetOptions &Opts)
1102326941Sdim    : ARMTargetInfo(Triple, Opts) {}
1103326941Sdim
1104326941Sdimvoid ARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
1105326941Sdim                                       MacroBuilder &Builder) const {
1106326941Sdim  Builder.defineMacro("__ARMEL__");
1107326941Sdim  ARMTargetInfo::getTargetDefines(Opts, Builder);
1108326941Sdim}
1109326941Sdim
1110326941SdimARMbeTargetInfo::ARMbeTargetInfo(const llvm::Triple &Triple,
1111326941Sdim                                 const TargetOptions &Opts)
1112326941Sdim    : ARMTargetInfo(Triple, Opts) {}
1113326941Sdim
1114326941Sdimvoid ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts,
1115326941Sdim                                       MacroBuilder &Builder) const {
1116326941Sdim  Builder.defineMacro("__ARMEB__");
1117326941Sdim  Builder.defineMacro("__ARM_BIG_ENDIAN");
1118326941Sdim  ARMTargetInfo::getTargetDefines(Opts, Builder);
1119326941Sdim}
1120326941Sdim
1121326941SdimWindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple,
1122326941Sdim                                           const TargetOptions &Opts)
1123326941Sdim    : WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) {
1124326941Sdim}
1125326941Sdim
1126326941Sdimvoid WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts,
1127326941Sdim                                                  MacroBuilder &Builder) const {
1128326941Sdim  // FIXME: this is invalid for WindowsCE
1129326941Sdim  Builder.defineMacro("_M_ARM_NT", "1");
1130326941Sdim  Builder.defineMacro("_M_ARMT", "_M_ARM");
1131326941Sdim  Builder.defineMacro("_M_THUMB", "_M_ARM");
1132326941Sdim
1133326941Sdim  assert((Triple.getArch() == llvm::Triple::arm ||
1134326941Sdim          Triple.getArch() == llvm::Triple::thumb) &&
1135326941Sdim         "invalid architecture for Windows ARM target info");
1136326941Sdim  unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
1137326941Sdim  Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset));
1138326941Sdim
1139326941Sdim  // TODO map the complete set of values
1140326941Sdim  // 31: VFPv3 40: VFPv4
1141326941Sdim  Builder.defineMacro("_M_ARM_FP", "31");
1142326941Sdim}
1143326941Sdim
1144326941SdimTargetInfo::BuiltinVaListKind
1145326941SdimWindowsARMTargetInfo::getBuiltinVaListKind() const {
1146326941Sdim  return TargetInfo::CharPtrBuiltinVaList;
1147326941Sdim}
1148326941Sdim
1149326941SdimTargetInfo::CallingConvCheckResult
1150326941SdimWindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const {
1151326941Sdim  switch (CC) {
1152326941Sdim  case CC_X86StdCall:
1153326941Sdim  case CC_X86ThisCall:
1154326941Sdim  case CC_X86FastCall:
1155326941Sdim  case CC_X86VectorCall:
1156326941Sdim    return CCCR_Ignore;
1157326941Sdim  case CC_C:
1158326941Sdim  case CC_OpenCLKernel:
1159341825Sdim  case CC_PreserveMost:
1160341825Sdim  case CC_PreserveAll:
1161344779Sdim  case CC_Swift:
1162326941Sdim    return CCCR_OK;
1163326941Sdim  default:
1164326941Sdim    return CCCR_Warning;
1165326941Sdim  }
1166326941Sdim}
1167326941Sdim
1168326941Sdim// Windows ARM + Itanium C++ ABI Target
1169326941SdimItaniumWindowsARMleTargetInfo::ItaniumWindowsARMleTargetInfo(
1170326941Sdim    const llvm::Triple &Triple, const TargetOptions &Opts)
1171326941Sdim    : WindowsARMTargetInfo(Triple, Opts) {
1172326941Sdim  TheCXXABI.set(TargetCXXABI::GenericARM);
1173326941Sdim}
1174326941Sdim
1175326941Sdimvoid ItaniumWindowsARMleTargetInfo::getTargetDefines(
1176326941Sdim    const LangOptions &Opts, MacroBuilder &Builder) const {
1177326941Sdim  WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
1178326941Sdim
1179326941Sdim  if (Opts.MSVCCompat)
1180326941Sdim    WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
1181326941Sdim}
1182326941Sdim
1183326941Sdim// Windows ARM, MS (C++) ABI
1184326941SdimMicrosoftARMleTargetInfo::MicrosoftARMleTargetInfo(const llvm::Triple &Triple,
1185326941Sdim                                                   const TargetOptions &Opts)
1186326941Sdim    : WindowsARMTargetInfo(Triple, Opts) {
1187326941Sdim  TheCXXABI.set(TargetCXXABI::Microsoft);
1188326941Sdim}
1189326941Sdim
1190326941Sdimvoid MicrosoftARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
1191326941Sdim                                                MacroBuilder &Builder) const {
1192326941Sdim  WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
1193326941Sdim  WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
1194326941Sdim}
1195326941Sdim
1196326941SdimMinGWARMTargetInfo::MinGWARMTargetInfo(const llvm::Triple &Triple,
1197326941Sdim                                       const TargetOptions &Opts)
1198326941Sdim    : WindowsARMTargetInfo(Triple, Opts) {
1199326941Sdim  TheCXXABI.set(TargetCXXABI::GenericARM);
1200326941Sdim}
1201326941Sdim
1202326941Sdimvoid MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts,
1203326941Sdim                                          MacroBuilder &Builder) const {
1204326941Sdim  WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
1205326941Sdim  Builder.defineMacro("_ARM_");
1206326941Sdim}
1207326941Sdim
1208326941SdimCygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple,
1209326941Sdim                                         const TargetOptions &Opts)
1210326941Sdim    : ARMleTargetInfo(Triple, Opts) {
1211326941Sdim  this->WCharType = TargetInfo::UnsignedShort;
1212326941Sdim  TLSSupported = false;
1213326941Sdim  DoubleAlign = LongLongAlign = 64;
1214353358Sdim  resetDataLayout("e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64");
1215326941Sdim}
1216326941Sdim
1217326941Sdimvoid CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts,
1218326941Sdim                                           MacroBuilder &Builder) const {
1219326941Sdim  ARMleTargetInfo::getTargetDefines(Opts, Builder);
1220326941Sdim  Builder.defineMacro("_ARM_");
1221326941Sdim  Builder.defineMacro("__CYGWIN__");
1222326941Sdim  Builder.defineMacro("__CYGWIN32__");
1223326941Sdim  DefineStd(Builder, "unix", Opts);
1224326941Sdim  if (Opts.CPlusPlus)
1225326941Sdim    Builder.defineMacro("_GNU_SOURCE");
1226326941Sdim}
1227326941Sdim
1228326941SdimDarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple,
1229326941Sdim                                         const TargetOptions &Opts)
1230326941Sdim    : DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) {
1231326941Sdim  HasAlignMac68kSupport = true;
1232326941Sdim  // iOS always has 64-bit atomic instructions.
1233326941Sdim  // FIXME: This should be based off of the target features in
1234326941Sdim  // ARMleTargetInfo.
1235326941Sdim  MaxAtomicInlineWidth = 64;
1236326941Sdim
1237326941Sdim  if (Triple.isWatchABI()) {
1238326941Sdim    // Darwin on iOS uses a variant of the ARM C++ ABI.
1239326941Sdim    TheCXXABI.set(TargetCXXABI::WatchOS);
1240326941Sdim
1241326941Sdim    // BOOL should be a real boolean on the new ABI
1242326941Sdim    UseSignedCharForObjCBool = false;
1243326941Sdim  } else
1244326941Sdim    TheCXXABI.set(TargetCXXABI::iOS);
1245326941Sdim}
1246326941Sdim
1247326941Sdimvoid DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts,
1248326941Sdim                                       const llvm::Triple &Triple,
1249326941Sdim                                       MacroBuilder &Builder) const {
1250326941Sdim  getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
1251326941Sdim}
1252326941Sdim
1253326941SdimRenderScript32TargetInfo::RenderScript32TargetInfo(const llvm::Triple &Triple,
1254326941Sdim                                                   const TargetOptions &Opts)
1255326941Sdim    : ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(),
1256326941Sdim                                   Triple.getOSName(),
1257326941Sdim                                   Triple.getEnvironmentName()),
1258326941Sdim                      Opts) {
1259326941Sdim  IsRenderScriptTarget = true;
1260326941Sdim  LongWidth = LongAlign = 64;
1261326941Sdim}
1262326941Sdim
1263326941Sdimvoid RenderScript32TargetInfo::getTargetDefines(const LangOptions &Opts,
1264326941Sdim                                                MacroBuilder &Builder) const {
1265326941Sdim  Builder.defineMacro("__RENDERSCRIPT__");
1266326941Sdim  ARMleTargetInfo::getTargetDefines(Opts, Builder);
1267326941Sdim}
1268