r308898 - AArch64 & ARM: move TargetInfo functions from .h to .cpp file. NFC.

Tim Northover via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 24 10:06:23 PDT 2017


Author: tnorthover
Date: Mon Jul 24 10:06:23 2017
New Revision: 308898

URL: http://llvm.org/viewvc/llvm-project?rev=308898&view=rev
Log:
AArch64 & ARM: move TargetInfo functions from .h to .cpp file. NFC.

Most of them are virtual anyway, and the few remaining ones can move to the
.cpp for consistency.

Modified:
    cfe/trunk/lib/Basic/Targets/AArch64.cpp
    cfe/trunk/lib/Basic/Targets/AArch64.h
    cfe/trunk/lib/Basic/Targets/ARM.cpp
    cfe/trunk/lib/Basic/Targets/ARM.h

Modified: cfe/trunk/lib/Basic/Targets/AArch64.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets/AArch64.cpp?rev=308898&r1=308897&r2=308898&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Targets/AArch64.cpp (original)
+++ cfe/trunk/lib/Basic/Targets/AArch64.cpp Mon Jul 24 10:06:23 2017
@@ -19,6 +19,245 @@
 using namespace clang;
 using namespace clang::targets;
 
+const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS)                                               \
+   {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsNEON.def"
+
+#define BUILTIN(ID, TYPE, ATTRS)                                               \
+   {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsAArch64.def"
+};
+
+AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
+                                     const TargetOptions &Opts)
+    : TargetInfo(Triple), ABI("aapcs") {
+  if (getTriple().getOS() == llvm::Triple::NetBSD ||
+      getTriple().getOS() == llvm::Triple::OpenBSD) {
+    WCharType = SignedInt;
+
+    // NetBSD apparently prefers consistency across ARM targets to
+    // consistency across 64-bit targets.
+    Int64Type = SignedLongLong;
+    IntMaxType = SignedLongLong;
+  } else {
+    WCharType = UnsignedInt;
+    Int64Type = SignedLong;
+    IntMaxType = SignedLong;
+  }
+
+  LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
+  MaxVectorAlign = 128;
+  MaxAtomicInlineWidth = 128;
+  MaxAtomicPromoteWidth = 128;
+
+  LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
+  LongDoubleFormat = &llvm::APFloat::IEEEquad();
+
+  // Make __builtin_ms_va_list available.
+  HasBuiltinMSVaList = true;
+
+  // {} in inline assembly are neon specifiers, not assembly variant
+  // specifiers.
+  NoAsmVariants = true;
+
+  // AAPCS gives rules for bitfields. 7.1.7 says: "The container type
+  // contributes to the alignment of the containing aggregate in the same way
+  // a plain (non bit-field) member of that type would, without exception for
+  // zero-sized or anonymous bit-fields."
+  assert(UseBitFieldTypeAlignment && "bitfields affect type alignment");
+  UseZeroLengthBitfieldAlignment = true;
+
+  // AArch64 targets default to using the ARM C++ ABI.
+  TheCXXABI.set(TargetCXXABI::GenericAArch64);
+
+  if (Triple.getOS() == llvm::Triple::Linux)
+    this->MCountName = "\01_mcount";
+  else if (Triple.getOS() == llvm::Triple::UnknownOS)
+    this->MCountName =
+        Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
+}
+
+StringRef AArch64TargetInfo::getABI() const { return ABI; }
+
+bool AArch64TargetInfo::setABI(const std::string &Name) {
+  if (Name != "aapcs" && Name != "darwinpcs")
+    return false;
+
+  ABI = Name;
+  return true;
+}
+
+bool AArch64TargetInfo::isValidCPUName(StringRef Name) const {
+  return Name == "generic" ||
+         llvm::AArch64::parseCPUArch(Name) !=
+             static_cast<unsigned>(llvm::AArch64::ArchKind::AK_INVALID);
+}
+
+bool AArch64TargetInfo::setCPU(const std::string &Name) {
+  return isValidCPUName(Name);
+}
+
+void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
+                                                MacroBuilder &Builder) const {
+  Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
+}
+
+void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
+                                                MacroBuilder &Builder) const {
+  // Also include the ARMv8.1 defines
+  getTargetDefinesARMV81A(Opts, Builder);
+}
+
+void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
+                                         MacroBuilder &Builder) const {
+  // Target identification.
+  Builder.defineMacro("__aarch64__");
+  // For bare-metal none-eabi.
+  if (getTriple().getOS() == llvm::Triple::UnknownOS &&
+      (getTriple().getEnvironment() == llvm::Triple::EABI ||
+       getTriple().getEnvironment() == llvm::Triple::EABIHF))
+    Builder.defineMacro("__ELF__");
+
+  // Target properties.
+  Builder.defineMacro("_LP64");
+  Builder.defineMacro("__LP64__");
+
+  // ACLE predefines. Many can only have one possible value on v8 AArch64.
+  Builder.defineMacro("__ARM_ACLE", "200");
+  Builder.defineMacro("__ARM_ARCH", "8");
+  Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
+
+  Builder.defineMacro("__ARM_64BIT_STATE", "1");
+  Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
+  Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
+
+  Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
+  Builder.defineMacro("__ARM_FEATURE_FMA", "1");
+  Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
+  Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
+  Builder.defineMacro("__ARM_FEATURE_DIV");       // For backwards compatibility
+  Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
+  Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
+
+  Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
+
+  // 0xe implies support for half, single and double precision operations.
+  Builder.defineMacro("__ARM_FP", "0xE");
+
+  // PCS specifies this for SysV variants, which is all we support. Other ABIs
+  // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
+  Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
+  Builder.defineMacro("__ARM_FP16_ARGS", "1");
+
+  if (Opts.UnsafeFPMath)
+    Builder.defineMacro("__ARM_FP_FAST", "1");
+
+  Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", Opts.ShortWChar ? "2" : "4");
+
+  Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
+
+  if (FPU & NeonMode) {
+    Builder.defineMacro("__ARM_NEON", "1");
+    // 64-bit NEON supports half, single and double precision operations.
+    Builder.defineMacro("__ARM_NEON_FP", "0xE");
+  }
+
+  if (FPU & SveMode)
+    Builder.defineMacro("__ARM_FEATURE_SVE", "1");
+
+  if (CRC)
+    Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
+
+  if (Crypto)
+    Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
+
+  if (Unaligned)
+    Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
+
+  switch (ArchKind) {
+  default:
+    break;
+  case llvm::AArch64::ArchKind::AK_ARMV8_1A:
+    getTargetDefinesARMV81A(Opts, Builder);
+    break;
+  case llvm::AArch64::ArchKind::AK_ARMV8_2A:
+    getTargetDefinesARMV82A(Opts, Builder);
+    break;
+  }
+
+  // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
+  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+  Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+}
+
+ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
+  return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
+                                             Builtin::FirstTSBuiltin);
+}
+
+bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
+  return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" ||
+         (Feature == "neon" && (FPU & NeonMode)) ||
+         (Feature == "sve" && (FPU & SveMode));
+}
+
+bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+                                             DiagnosticsEngine &Diags) {
+  FPU = FPUMode;
+  CRC = 0;
+  Crypto = 0;
+  Unaligned = 1;
+  HasFullFP16 = 0;
+  ArchKind = llvm::AArch64::ArchKind::AK_ARMV8A;
+
+  for (const auto &Feature : Features) {
+    if (Feature == "+neon")
+      FPU |= NeonMode;
+    if (Feature == "+sve")
+      FPU |= SveMode;
+    if (Feature == "+crc")
+      CRC = 1;
+    if (Feature == "+crypto")
+      Crypto = 1;
+    if (Feature == "+strict-align")
+      Unaligned = 0;
+    if (Feature == "+v8.1a")
+      ArchKind = llvm::AArch64::ArchKind::AK_ARMV8_1A;
+    if (Feature == "+v8.2a")
+      ArchKind = llvm::AArch64::ArchKind::AK_ARMV8_2A;
+    if (Feature == "+fullfp16")
+      HasFullFP16 = 1;
+  }
+
+  setDataLayout();
+
+  return true;
+}
+
+TargetInfo::CallingConvCheckResult
+AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
+  switch (CC) {
+  case CC_C:
+  case CC_Swift:
+  case CC_PreserveMost:
+  case CC_PreserveAll:
+  case CC_OpenCLKernel:
+  case CC_Win64:
+    return CCCR_OK;
+  default:
+    return CCCR_Warning;
+  }
+}
+
+bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
+
+TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
+  return TargetInfo::AArch64ABIBuiltinVaList;
+}
+
 const char *const AArch64TargetInfo::GCCRegNames[] = {
     // 32-bit Integer registers
     "w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
@@ -60,12 +299,208 @@ ArrayRef<TargetInfo::GCCRegAlias> AArch6
   return llvm::makeArrayRef(GCCRegAliases);
 }
 
-const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS)                                               \
-  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
-#include "clang/Basic/BuiltinsNEON.def"
+bool AArch64TargetInfo::validateAsmConstraint(
+    const char *&Name, TargetInfo::ConstraintInfo &Info) const {
+  switch (*Name) {
+  default:
+    return false;
+  case 'w': // Floating point and SIMD registers (V0-V31)
+    Info.setAllowsRegister();
+    return true;
+  case 'I': // Constant that can be used with an ADD instruction
+  case 'J': // Constant that can be used with a SUB instruction
+  case 'K': // Constant that can be used with a 32-bit logical instruction
+  case 'L': // Constant that can be used with a 64-bit logical instruction
+  case 'M': // Constant that can be used as a 32-bit MOV immediate
+  case 'N': // Constant that can be used as a 64-bit MOV immediate
+  case 'Y': // Floating point constant zero
+  case 'Z': // Integer constant zero
+    return true;
+  case 'Q': // A memory reference with base register and no offset
+    Info.setAllowsMemory();
+    return true;
+  case 'S': // A symbolic address
+    Info.setAllowsRegister();
+    return true;
+  case 'U':
+    // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
+    // Utf: A memory address suitable for ldp/stp in TF mode.
+    // Usa: An absolute symbolic address.
+    // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
+    llvm_unreachable("FIXME: Unimplemented support for U* constraints.");
+  case 'z': // Zero register, wzr or xzr
+    Info.setAllowsRegister();
+    return true;
+  case 'x': // Floating point and SIMD registers (V0-V15)
+    Info.setAllowsRegister();
+    return true;
+  }
+  return false;
+}
 
-#define BUILTIN(ID, TYPE, ATTRS)                                               \
-  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
-#include "clang/Basic/BuiltinsAArch64.def"
-};
+bool AArch64TargetInfo::validateConstraintModifier(
+    StringRef Constraint, char Modifier, unsigned Size,
+    std::string &SuggestedModifier) const {
+  // Strip off constraint modifiers.
+  while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
+    Constraint = Constraint.substr(1);
+
+  switch (Constraint[0]) {
+  default:
+    return true;
+  case 'z':
+  case 'r': {
+    switch (Modifier) {
+    case 'x':
+    case 'w':
+      // For now assume that the person knows what they're
+      // doing with the modifier.
+      return true;
+    default:
+      // By default an 'r' constraint will be in the 'x'
+      // registers.
+      if (Size == 64)
+        return true;
+
+      SuggestedModifier = "w";
+      return false;
+    }
+  }
+  }
+}
+
+const char *AArch64TargetInfo::getClobbers() const { return ""; }
+
+int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
+  if (RegNo == 0)
+    return 0;
+  if (RegNo == 1)
+    return 1;
+  return -1;
+}
+
+AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
+                                         const TargetOptions &Opts)
+    : AArch64TargetInfo(Triple, Opts) {}
+
+void AArch64leTargetInfo::setDataLayout() {
+  if (getTriple().isOSBinFormatMachO())
+    resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
+  else
+    resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
+}
+
+void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
+                                           MacroBuilder &Builder) const {
+  Builder.defineMacro("__AARCH64EL__");
+  AArch64TargetInfo::getTargetDefines(Opts, Builder);
+}
+
+AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
+                                         const TargetOptions &Opts)
+    : AArch64TargetInfo(Triple, Opts) {}
+
+void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
+                                           MacroBuilder &Builder) const {
+  Builder.defineMacro("__AARCH64EB__");
+  Builder.defineMacro("__AARCH_BIG_ENDIAN");
+  Builder.defineMacro("__ARM_BIG_ENDIAN");
+  AArch64TargetInfo::getTargetDefines(Opts, Builder);
+}
+
+void AArch64beTargetInfo::setDataLayout() {
+  assert(!getTriple().isOSBinFormatMachO());
+  resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
+}
+
+MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
+                                                   const TargetOptions &Opts)
+    : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
+
+  // This is an LLP64 platform.
+  // int:4, long:4, long long:8, long double:8.
+  WCharType = UnsignedShort;
+  IntWidth = IntAlign = 32;
+  LongWidth = LongAlign = 32;
+  DoubleAlign = LongLongAlign = 64;
+  LongDoubleWidth = LongDoubleAlign = 64;
+  LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+  IntMaxType = SignedLongLong;
+  Int64Type = SignedLongLong;
+  SizeType = UnsignedLongLong;
+  PtrDiffType = SignedLongLong;
+  IntPtrType = SignedLongLong;
+
+  TheCXXABI.set(TargetCXXABI::Microsoft);
+}
+
+void MicrosoftARM64TargetInfo::setDataLayout() {
+  resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
+}
+
+void MicrosoftARM64TargetInfo::getVisualStudioDefines(
+    const LangOptions &Opts, MacroBuilder &Builder) const {
+  WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts, Builder);
+  Builder.defineMacro("_WIN32", "1");
+  Builder.defineMacro("_WIN64", "1");
+  Builder.defineMacro("_M_ARM64", "1");
+}
+
+void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
+                                                MacroBuilder &Builder) const {
+  WindowsTargetInfo::getTargetDefines(Opts, Builder);
+  getVisualStudioDefines(Opts, Builder);
+}
+
+TargetInfo::BuiltinVaListKind
+MicrosoftARM64TargetInfo::getBuiltinVaListKind() const {
+  return TargetInfo::CharPtrBuiltinVaList;
+}
+
+DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
+                                                 const TargetOptions &Opts)
+    : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
+  Int64Type = SignedLongLong;
+  WCharType = SignedInt;
+  UseSignedCharForObjCBool = false;
+
+  LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
+  LongDoubleFormat = &llvm::APFloat::IEEEdouble();
+
+  TheCXXABI.set(TargetCXXABI::iOS64);
+}
+
+void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
+                                           const llvm::Triple &Triple,
+                                           MacroBuilder &Builder) const {
+  Builder.defineMacro("__AARCH64_SIMD__");
+  Builder.defineMacro("__ARM64_ARCH_8__");
+  Builder.defineMacro("__ARM_NEON__");
+  Builder.defineMacro("__LITTLE_ENDIAN__");
+  Builder.defineMacro("__REGISTER_PREFIX__", "");
+  Builder.defineMacro("__arm64", "1");
+  Builder.defineMacro("__arm64__", "1");
+
+  getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
+}
+
+TargetInfo::BuiltinVaListKind
+DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
+  return TargetInfo::CharPtrBuiltinVaList;
+}
+
+// 64-bit RenderScript is aarch64
+RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
+                                                   const TargetOptions &Opts)
+    : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
+                                       Triple.getOSName(),
+                                       Triple.getEnvironmentName()),
+                          Opts) {
+  IsRenderScriptTarget = true;
+}
+
+void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
+                                                MacroBuilder &Builder) const {
+  Builder.defineMacro("__RENDERSCRIPT__");
+  AArch64leTargetInfo::getTargetDefines(Opts, Builder);
+}

Modified: cfe/trunk/lib/Basic/Targets/AArch64.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets/AArch64.h?rev=308898&r1=308897&r2=308898&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Targets/AArch64.h (original)
+++ cfe/trunk/lib/Basic/Targets/AArch64.h Mon Jul 24 10:06:23 2017
@@ -40,331 +40,53 @@ class LLVM_LIBRARY_VISIBILITY AArch64Tar
   std::string ABI;
 
 public:
-  AArch64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
-      : TargetInfo(Triple), ABI("aapcs") {
-    if (getTriple().getOS() == llvm::Triple::NetBSD ||
-        getTriple().getOS() == llvm::Triple::OpenBSD) {
-      WCharType = SignedInt;
-
-      // NetBSD apparently prefers consistency across ARM targets to consistency
-      // across 64-bit targets.
-      Int64Type = SignedLongLong;
-      IntMaxType = SignedLongLong;
-    } else {
-      WCharType = UnsignedInt;
-      Int64Type = SignedLong;
-      IntMaxType = SignedLong;
-    }
-
-    LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
-    MaxVectorAlign = 128;
-    MaxAtomicInlineWidth = 128;
-    MaxAtomicPromoteWidth = 128;
-
-    LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
-    LongDoubleFormat = &llvm::APFloat::IEEEquad();
-
-    // Make __builtin_ms_va_list available.
-    HasBuiltinMSVaList = true;
-
-    // {} in inline assembly are neon specifiers, not assembly variant
-    // specifiers.
-    NoAsmVariants = true;
-
-    // AAPCS gives rules for bitfields. 7.1.7 says: "The container type
-    // contributes to the alignment of the containing aggregate in the same way
-    // a plain (non bit-field) member of that type would, without exception for
-    // zero-sized or anonymous bit-fields."
-    assert(UseBitFieldTypeAlignment && "bitfields affect type alignment");
-    UseZeroLengthBitfieldAlignment = true;
-
-    // AArch64 targets default to using the ARM C++ ABI.
-    TheCXXABI.set(TargetCXXABI::GenericAArch64);
-
-    if (Triple.getOS() == llvm::Triple::Linux)
-      this->MCountName = "\01_mcount";
-    else if (Triple.getOS() == llvm::Triple::UnknownOS)
-      this->MCountName =
-          Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
-  }
-
-  StringRef getABI() const override { return ABI; }
-  bool setABI(const std::string &Name) override {
-    if (Name != "aapcs" && Name != "darwinpcs")
-      return false;
-
-    ABI = Name;
-    return true;
-  }
-
-  bool isValidCPUName(StringRef Name) const override {
-    return Name == "generic" ||
-           llvm::AArch64::parseCPUArch(Name) !=
-               static_cast<unsigned>(llvm::AArch64::ArchKind::AK_INVALID);
-  }
+  AArch64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
 
-  bool setCPU(const std::string &Name) override { return isValidCPUName(Name); }
+  StringRef getABI() const override;
+  bool setABI(const std::string &Name) override;
 
-  void getTargetDefinesARMV81A(const LangOptions &Opts,
-                               MacroBuilder &Builder) const {
-    Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
-  }
+  bool isValidCPUName(StringRef Name) const override;
+  bool setCPU(const std::string &Name) override;
 
+  void getTargetDefinesARMV81A(const LangOptions &Opts,
+                               MacroBuilder &Builder) const;
   void getTargetDefinesARMV82A(const LangOptions &Opts,
-                               MacroBuilder &Builder) const {
-    // Also include the ARMv8.1 defines
-    getTargetDefinesARMV81A(Opts, Builder);
-  }
-
+                               MacroBuilder &Builder) const;
   void getTargetDefines(const LangOptions &Opts,
-                        MacroBuilder &Builder) const override {
-    // Target identification.
-    Builder.defineMacro("__aarch64__");
-    // For bare-metal none-eabi.
-    if (getTriple().getOS() == llvm::Triple::UnknownOS &&
-        (getTriple().getEnvironment() == llvm::Triple::EABI ||
-         getTriple().getEnvironment() == llvm::Triple::EABIHF))
-      Builder.defineMacro("__ELF__");
-
-    // Target properties.
-    Builder.defineMacro("_LP64");
-    Builder.defineMacro("__LP64__");
-
-    // ACLE predefines. Many can only have one possible value on v8 AArch64.
-    Builder.defineMacro("__ARM_ACLE", "200");
-    Builder.defineMacro("__ARM_ARCH", "8");
-    Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
-
-    Builder.defineMacro("__ARM_64BIT_STATE", "1");
-    Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
-    Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
-
-    Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
-    Builder.defineMacro("__ARM_FEATURE_FMA", "1");
-    Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
-    Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
-    Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility
-    Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
-    Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
-
-    Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
-
-    // 0xe implies support for half, single and double precision operations.
-    Builder.defineMacro("__ARM_FP", "0xE");
-
-    // PCS specifies this for SysV variants, which is all we support. Other ABIs
-    // may choose __ARM_FP16_FORMAT_ALTERNATIVE.
-    Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
-    Builder.defineMacro("__ARM_FP16_ARGS", "1");
-
-    if (Opts.UnsafeFPMath)
-      Builder.defineMacro("__ARM_FP_FAST", "1");
-
-    Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", Opts.ShortWChar ? "2" : "4");
-
-    Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM",
-                        Opts.ShortEnums ? "1" : "4");
-
-    if (FPU & NeonMode) {
-      Builder.defineMacro("__ARM_NEON", "1");
-      // 64-bit NEON supports half, single and double precision operations.
-      Builder.defineMacro("__ARM_NEON_FP", "0xE");
-    }
-
-    if (FPU & SveMode)
-      Builder.defineMacro("__ARM_FEATURE_SVE", "1");
-
-    if (CRC)
-      Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
-
-    if (Crypto)
-      Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
-
-    if (Unaligned)
-      Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
-
-    switch (ArchKind) {
-    default:
-      break;
-    case llvm::AArch64::ArchKind::AK_ARMV8_1A:
-      getTargetDefinesARMV81A(Opts, Builder);
-      break;
-    case llvm::AArch64::ArchKind::AK_ARMV8_2A:
-      getTargetDefinesARMV82A(Opts, Builder);
-      break;
-    }
-
-    // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
-    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
-    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
-    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
-    Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
-  }
-
-  ArrayRef<Builtin::Info> getTargetBuiltins() const override {
-    return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
-                                               Builtin::FirstTSBuiltin);
-  }
-
-  bool hasFeature(StringRef Feature) const override {
-    return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" ||
-           (Feature == "neon" && (FPU & NeonMode)) ||
-           (Feature == "sve" && (FPU & SveMode));
-  }
+                        MacroBuilder &Builder) const override;
 
+  ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+  bool hasFeature(StringRef Feature) const override;
   bool handleTargetFeatures(std::vector<std::string> &Features,
-                            DiagnosticsEngine &Diags) override {
-    FPU = FPUMode;
-    CRC = 0;
-    Crypto = 0;
-    Unaligned = 1;
-    HasFullFP16 = 0;
-    ArchKind = llvm::AArch64::ArchKind::AK_ARMV8A;
-
-    for (const auto &Feature : Features) {
-      if (Feature == "+neon")
-        FPU |= NeonMode;
-      if (Feature == "+sve")
-        FPU |= SveMode;
-      if (Feature == "+crc")
-        CRC = 1;
-      if (Feature == "+crypto")
-        Crypto = 1;
-      if (Feature == "+strict-align")
-        Unaligned = 0;
-      if (Feature == "+v8.1a")
-        ArchKind = llvm::AArch64::ArchKind::AK_ARMV8_1A;
-      if (Feature == "+v8.2a")
-        ArchKind = llvm::AArch64::ArchKind::AK_ARMV8_2A;
-      if (Feature == "+fullfp16")
-        HasFullFP16 = 1;
-    }
-
-    setDataLayout();
-
-    return true;
-  }
-
-  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
-    switch (CC) {
-    case CC_C:
-    case CC_Swift:
-    case CC_PreserveMost:
-    case CC_PreserveAll:
-    case CC_OpenCLKernel:
-    case CC_Win64:
-      return CCCR_OK;
-    default:
-      return CCCR_Warning;
-    }
-  }
-
-  bool isCLZForZeroUndef() const override { return false; }
-
-  BuiltinVaListKind getBuiltinVaListKind() const override {
-    return TargetInfo::AArch64ABIBuiltinVaList;
-  }
+                            DiagnosticsEngine &Diags) override;
+
+  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
+
+  bool isCLZForZeroUndef() const override;
+
+  BuiltinVaListKind getBuiltinVaListKind() const override;
 
   ArrayRef<const char *> getGCCRegNames() const override;
   ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
-
   bool validateAsmConstraint(const char *&Name,
-                             TargetInfo::ConstraintInfo &Info) const override {
-    switch (*Name) {
-    default:
-      return false;
-    case 'w': // Floating point and SIMD registers (V0-V31)
-      Info.setAllowsRegister();
-      return true;
-    case 'I': // Constant that can be used with an ADD instruction
-    case 'J': // Constant that can be used with a SUB instruction
-    case 'K': // Constant that can be used with a 32-bit logical instruction
-    case 'L': // Constant that can be used with a 64-bit logical instruction
-    case 'M': // Constant that can be used as a 32-bit MOV immediate
-    case 'N': // Constant that can be used as a 64-bit MOV immediate
-    case 'Y': // Floating point constant zero
-    case 'Z': // Integer constant zero
-      return true;
-    case 'Q': // A memory reference with base register and no offset
-      Info.setAllowsMemory();
-      return true;
-    case 'S': // A symbolic address
-      Info.setAllowsRegister();
-      return true;
-    case 'U':
-      // Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
-      // Utf: A memory address suitable for ldp/stp in TF mode.
-      // Usa: An absolute symbolic address.
-      // Ush: The high part (bits 32:12) of a pc-relative symbolic address.
-      llvm_unreachable("FIXME: Unimplemented support for U* constraints.");
-    case 'z': // Zero register, wzr or xzr
-      Info.setAllowsRegister();
-      return true;
-    case 'x': // Floating point and SIMD registers (V0-V15)
-      Info.setAllowsRegister();
-      return true;
-    }
-    return false;
-  }
-
+                             TargetInfo::ConstraintInfo &Info) const override;
   bool
   validateConstraintModifier(StringRef Constraint, char Modifier, unsigned Size,
-                             std::string &SuggestedModifier) const override {
-    // Strip off constraint modifiers.
-    while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
-      Constraint = Constraint.substr(1);
-
-    switch (Constraint[0]) {
-    default:
-      return true;
-    case 'z':
-    case 'r': {
-      switch (Modifier) {
-      case 'x':
-      case 'w':
-        // For now assume that the person knows what they're
-        // doing with the modifier.
-        return true;
-      default:
-        // By default an 'r' constraint will be in the 'x'
-        // registers.
-        if (Size == 64)
-          return true;
-
-        SuggestedModifier = "w";
-        return false;
-      }
-    }
-    }
-  }
-
-  const char *getClobbers() const override { return ""; }
-
-  int getEHDataRegisterNumber(unsigned RegNo) const override {
-    if (RegNo == 0)
-      return 0;
-    if (RegNo == 1)
-      return 1;
-    return -1;
-  }
+                             std::string &SuggestedModifier) const override;
+  const char *getClobbers() const override;
+
+  int getEHDataRegisterNumber(unsigned RegNo) const override;
 };
 
 class LLVM_LIBRARY_VISIBILITY AArch64leTargetInfo : public AArch64TargetInfo {
-  void setDataLayout() override {
-    if (getTriple().isOSBinFormatMachO())
-      resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
-    else
-      resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
-  }
-
 public:
-  AArch64leTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
-      : AArch64TargetInfo(Triple, Opts) {}
+  AArch64leTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
   void getTargetDefines(const LangOptions &Opts,
-                        MacroBuilder &Builder) const override {
-    Builder.defineMacro("__AARCH64EL__");
-    AArch64TargetInfo::getTargetDefines(Opts, Builder);
-  }
+                            MacroBuilder &Builder) const override;
+private:
+  void setDataLayout() override;
 };
 
 class LLVM_LIBRARY_VISIBILITY MicrosoftARM64TargetInfo
@@ -373,100 +95,38 @@ class LLVM_LIBRARY_VISIBILITY MicrosoftA
 
 public:
   MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
-                           const TargetOptions &Opts)
-      : WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
+                           const TargetOptions &Opts);
 
-    // This is an LLP64 platform.
-    // int:4, long:4, long long:8, long double:8.
-    WCharType = UnsignedShort;
-    IntWidth = IntAlign = 32;
-    LongWidth = LongAlign = 32;
-    DoubleAlign = LongLongAlign = 64;
-    LongDoubleWidth = LongDoubleAlign = 64;
-    LongDoubleFormat = &llvm::APFloat::IEEEdouble();
-    IntMaxType = SignedLongLong;
-    Int64Type = SignedLongLong;
-    SizeType = UnsignedLongLong;
-    PtrDiffType = SignedLongLong;
-    IntPtrType = SignedLongLong;
-
-    TheCXXABI.set(TargetCXXABI::Microsoft);
-  }
-
-  void setDataLayout() override {
-    resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
-  }
+  void setDataLayout() override;
 
   void getVisualStudioDefines(const LangOptions &Opts,
-                              MacroBuilder &Builder) const {
-    WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts,
-                                                                   Builder);
-    Builder.defineMacro("_WIN32", "1");
-    Builder.defineMacro("_WIN64", "1");
-    Builder.defineMacro("_M_ARM64", "1");
-  }
-
+                              MacroBuilder &Builder) const;
   void getTargetDefines(const LangOptions &Opts,
-                        MacroBuilder &Builder) const override {
-    WindowsTargetInfo::getTargetDefines(Opts, Builder);
-    getVisualStudioDefines(Opts, Builder);
-  }
-
-  BuiltinVaListKind getBuiltinVaListKind() const override {
-    return TargetInfo::CharPtrBuiltinVaList;
-  }
+                        MacroBuilder &Builder) const override;
+
+  BuiltinVaListKind getBuiltinVaListKind() const override;
 };
 
 class LLVM_LIBRARY_VISIBILITY AArch64beTargetInfo : public AArch64TargetInfo {
-  void setDataLayout() override {
-    assert(!getTriple().isOSBinFormatMachO());
-    resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
-  }
-
 public:
-  AArch64beTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
-      : AArch64TargetInfo(Triple, Opts) {}
+  AArch64beTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
   void getTargetDefines(const LangOptions &Opts,
-                        MacroBuilder &Builder) const override {
-    Builder.defineMacro("__AARCH64EB__");
-    Builder.defineMacro("__AARCH_BIG_ENDIAN");
-    Builder.defineMacro("__ARM_BIG_ENDIAN");
-    AArch64TargetInfo::getTargetDefines(Opts, Builder);
-  }
+                        MacroBuilder &Builder) const override;
+
+private:
+  void setDataLayout() override;
 };
 
 class LLVM_LIBRARY_VISIBILITY DarwinAArch64TargetInfo
     : public DarwinTargetInfo<AArch64leTargetInfo> {
-protected:
-  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
-                    MacroBuilder &Builder) const override {
-    Builder.defineMacro("__AARCH64_SIMD__");
-    Builder.defineMacro("__ARM64_ARCH_8__");
-    Builder.defineMacro("__ARM_NEON__");
-    Builder.defineMacro("__LITTLE_ENDIAN__");
-    Builder.defineMacro("__REGISTER_PREFIX__", "");
-    Builder.defineMacro("__arm64", "1");
-    Builder.defineMacro("__arm64__", "1");
+public:
+  DarwinAArch64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
 
-    getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
-  }
+  BuiltinVaListKind getBuiltinVaListKind() const override;
 
-public:
-  DarwinAArch64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
-      : DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
-    Int64Type = SignedLongLong;
-    WCharType = SignedInt;
-    UseSignedCharForObjCBool = false;
-
-    LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
-    LongDoubleFormat = &llvm::APFloat::IEEEdouble();
-
-    TheCXXABI.set(TargetCXXABI::iOS64);
-  }
-
-  BuiltinVaListKind getBuiltinVaListKind() const override {
-    return TargetInfo::CharPtrBuiltinVaList;
-  }
+ protected:
+  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+                    MacroBuilder &Builder) const override;
 };
 
 // 64-bit RenderScript is aarch64
@@ -474,19 +134,10 @@ class LLVM_LIBRARY_VISIBILITY RenderScri
     : public AArch64leTargetInfo {
 public:
   RenderScript64TargetInfo(const llvm::Triple &Triple,
-                           const TargetOptions &Opts)
-      : AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
-                                         Triple.getOSName(),
-                                         Triple.getEnvironmentName()),
-                            Opts) {
-    IsRenderScriptTarget = true;
-  }
+                           const TargetOptions &Opts);
 
   void getTargetDefines(const LangOptions &Opts,
-                        MacroBuilder &Builder) const override {
-    Builder.defineMacro("__RENDERSCRIPT__");
-    AArch64leTargetInfo::getTargetDefines(Opts, Builder);
-  }
+                        MacroBuilder &Builder) const override;
 };
 
 } // namespace targets

Modified: cfe/trunk/lib/Basic/Targets/ARM.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets/ARM.cpp?rev=308898&r1=308897&r2=308898&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Targets/ARM.cpp (original)
+++ cfe/trunk/lib/Basic/Targets/ARM.cpp Mon Jul 24 10:06:23 2017
@@ -22,72 +22,455 @@
 using namespace clang;
 using namespace clang::targets;
 
-bool ARMTargetInfo::setFPMath(StringRef Name) {
-  if (Name == "neon") {
-    FPMath = FP_Neon;
+void ARMTargetInfo::setABIAAPCS() {
+  IsAAPCS = true;
+
+  DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
+  const llvm::Triple &T = getTriple();
+
+  // size_t is unsigned long on MachO-derived environments, NetBSD, and
+  // OpenBSD.
+  if (T.isOSBinFormatMachO() || T.getOS() == llvm::Triple::NetBSD ||
+      T.getOS() == llvm::Triple::OpenBSD)
+    SizeType = UnsignedLong;
+  else
+    SizeType = UnsignedInt;
+
+  switch (T.getOS()) {
+  case llvm::Triple::NetBSD:
+  case llvm::Triple::OpenBSD:
+    WCharType = SignedInt;
+    break;
+  case llvm::Triple::Win32:
+    WCharType = UnsignedShort;
+    break;
+  case llvm::Triple::Linux:
+  default:
+    // AAPCS 7.1.1, ARM-Linux ABI 2.4: type of wchar_t is unsigned int.
+    WCharType = UnsignedInt;
+    break;
+  }
+
+  UseBitFieldTypeAlignment = true;
+
+  ZeroLengthBitfieldBoundary = 0;
+
+  // Thumb1 add sp, #imm requires the immediate value be multiple of 4,
+  // so set preferred for small types to 32.
+  if (T.isOSBinFormatMachO()) {
+    resetDataLayout(BigEndian
+                        ? "E-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+                        : "e-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
+  } else if (T.isOSWindows()) {
+    assert(!BigEndian && "Windows on ARM does not support big endian");
+    resetDataLayout("e"
+                    "-m:w"
+                    "-p:32:32"
+                    "-i64:64"
+                    "-v128:64:128"
+                    "-a:0:32"
+                    "-n32"
+                    "-S64");
+  } else if (T.isOSNaCl()) {
+    assert(!BigEndian && "NaCl on ARM does not support big endian");
+    resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128");
+  } else {
+    resetDataLayout(BigEndian
+                        ? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+                        : "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
+  }
+
+  // FIXME: Enumerated types are variable width in straight AAPCS.
+}
+
+void ARMTargetInfo::setABIAPCS(bool IsAAPCS16) {
+  const llvm::Triple &T = getTriple();
+
+  IsAAPCS = false;
+
+  if (IsAAPCS16)
+    DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
+  else
+    DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32;
+
+  // size_t is unsigned int on FreeBSD.
+  if (T.getOS() == llvm::Triple::FreeBSD)
+    SizeType = UnsignedInt;
+  else
+    SizeType = UnsignedLong;
+
+  // Revert to using SignedInt on apcs-gnu to comply with existing behaviour.
+  WCharType = SignedInt;
+
+  // Do not respect the alignment of bit-field types when laying out
+  // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc.
+  UseBitFieldTypeAlignment = false;
+
+  /// gcc forces the alignment to 4 bytes, regardless of the type of the
+  /// zero length bitfield.  This corresponds to EMPTY_FIELD_BOUNDARY in
+  /// gcc.
+  ZeroLengthBitfieldBoundary = 32;
+
+  if (T.isOSBinFormatMachO() && IsAAPCS16) {
+    assert(!BigEndian && "AAPCS16 does not support big-endian");
+    resetDataLayout("e-m:o-p:32:32-i64:64-a:0:32-n32-S128");
+  } else if (T.isOSBinFormatMachO())
+    resetDataLayout(
+        BigEndian
+            ? "E-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
+            : "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
+  else
+    resetDataLayout(
+        BigEndian
+            ? "E-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
+            : "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
+
+  // FIXME: Override "preferred align" for double and long long.
+}
+
+void ARMTargetInfo::setArchInfo() {
+  StringRef ArchName = getTriple().getArchName();
+
+  ArchISA = llvm::ARM::parseArchISA(ArchName);
+  CPU = llvm::ARM::getDefaultCPU(ArchName);
+  unsigned AK = llvm::ARM::parseArch(ArchName);
+  if (AK != llvm::ARM::AK_INVALID)
+    ArchKind = AK;
+  setArchInfo(ArchKind);
+}
+
+void ARMTargetInfo::setArchInfo(unsigned Kind) {
+  StringRef SubArch;
+
+  // cache TargetParser info
+  ArchKind = Kind;
+  SubArch = llvm::ARM::getSubArch(ArchKind);
+  ArchProfile = llvm::ARM::parseArchProfile(SubArch);
+  ArchVersion = llvm::ARM::parseArchVersion(SubArch);
+
+  // cache CPU related strings
+  CPUAttr = getCPUAttr();
+  CPUProfile = getCPUProfile();
+}
+
+void ARMTargetInfo::setAtomic() {
+  // when triple does not specify a sub arch,
+  // then we are not using inline atomics
+  bool ShouldUseInlineAtomic =
+      (ArchISA == llvm::ARM::IK_ARM && ArchVersion >= 6) ||
+      (ArchISA == llvm::ARM::IK_THUMB && ArchVersion >= 7);
+  // Cortex M does not support 8 byte atomics, while general Thumb2 does.
+  if (ArchProfile == llvm::ARM::PK_M) {
+    MaxAtomicPromoteWidth = 32;
+    if (ShouldUseInlineAtomic)
+      MaxAtomicInlineWidth = 32;
+  } else {
+    MaxAtomicPromoteWidth = 64;
+    if (ShouldUseInlineAtomic)
+      MaxAtomicInlineWidth = 64;
+  }
+}
+
+bool ARMTargetInfo::isThumb() const { return (ArchISA == llvm::ARM::IK_THUMB); }
+
+bool ARMTargetInfo::supportsThumb() const {
+  return CPUAttr.count('T') || ArchVersion >= 6;
+}
+
+bool ARMTargetInfo::supportsThumb2() const {
+  return CPUAttr.equals("6T2") ||
+         (ArchVersion >= 7 && !CPUAttr.equals("8M_BASE"));
+}
+
+StringRef ARMTargetInfo::getCPUAttr() const {
+  // For most sub-arches, the build attribute CPU name is enough.
+  // For Cortex variants, it's slightly different.
+  switch (ArchKind) {
+  default:
+    return llvm::ARM::getCPUAttr(ArchKind);
+  case llvm::ARM::AK_ARMV6M:
+    return "6M";
+  case llvm::ARM::AK_ARMV7S:
+    return "7S";
+  case llvm::ARM::AK_ARMV7A:
+    return "7A";
+  case llvm::ARM::AK_ARMV7R:
+    return "7R";
+  case llvm::ARM::AK_ARMV7M:
+    return "7M";
+  case llvm::ARM::AK_ARMV7EM:
+    return "7EM";
+  case llvm::ARM::AK_ARMV7VE:
+    return "7VE";
+  case llvm::ARM::AK_ARMV8A:
+    return "8A";
+  case llvm::ARM::AK_ARMV8_1A:
+    return "8_1A";
+  case llvm::ARM::AK_ARMV8_2A:
+    return "8_2A";
+  case llvm::ARM::AK_ARMV8MBaseline:
+    return "8M_BASE";
+  case llvm::ARM::AK_ARMV8MMainline:
+    return "8M_MAIN";
+  case llvm::ARM::AK_ARMV8R:
+    return "8R";
+  }
+}
+
+StringRef ARMTargetInfo::getCPUProfile() const {
+  switch (ArchProfile) {
+  case llvm::ARM::PK_A:
+    return "A";
+  case llvm::ARM::PK_R:
+    return "R";
+  case llvm::ARM::PK_M:
+    return "M";
+  default:
+    return "";
+  }
+}
+
+ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
+                             const TargetOptions &Opts)
+    : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
+      HW_FP(0) {
+
+  switch (getTriple().getOS()) {
+  case llvm::Triple::NetBSD:
+  case llvm::Triple::OpenBSD:
+    PtrDiffType = SignedLong;
+    break;
+  default:
+    PtrDiffType = SignedInt;
+    break;
+  }
+
+  // Cache arch related info.
+  setArchInfo();
+
+  // {} in inline assembly are neon specifiers, not assembly variant
+  // specifiers.
+  NoAsmVariants = true;
+
+  // FIXME: This duplicates code from the driver that sets the -target-abi
+  // option - this code is used if -target-abi isn't passed and should
+  // be unified in some way.
+  if (Triple.isOSBinFormatMachO()) {
+    // The backend is hardwired to assume AAPCS for M-class processors, ensure
+    // the frontend matches that.
+    if (Triple.getEnvironment() == llvm::Triple::EABI ||
+        Triple.getOS() == llvm::Triple::UnknownOS ||
+        ArchProfile == llvm::ARM::PK_M) {
+      setABI("aapcs");
+    } else if (Triple.isWatchABI()) {
+      setABI("aapcs16");
+    } else {
+      setABI("apcs-gnu");
+    }
+  } else if (Triple.isOSWindows()) {
+    // FIXME: this is invalid for WindowsCE
+    setABI("aapcs");
+  } else {
+    // Select the default based on the platform.
+    switch (Triple.getEnvironment()) {
+    case llvm::Triple::Android:
+    case llvm::Triple::GNUEABI:
+    case llvm::Triple::GNUEABIHF:
+    case llvm::Triple::MuslEABI:
+    case llvm::Triple::MuslEABIHF:
+      setABI("aapcs-linux");
+      break;
+    case llvm::Triple::EABIHF:
+    case llvm::Triple::EABI:
+      setABI("aapcs");
+      break;
+    case llvm::Triple::GNU:
+      setABI("apcs-gnu");
+      break;
+    default:
+      if (Triple.getOS() == llvm::Triple::NetBSD)
+        setABI("apcs-gnu");
+      else if (Triple.getOS() == llvm::Triple::OpenBSD)
+        setABI("aapcs-linux");
+      else
+        setABI("aapcs");
+      break;
+    }
+  }
+
+  // ARM targets default to using the ARM C++ ABI.
+  TheCXXABI.set(TargetCXXABI::GenericARM);
+
+  // ARM has atomics up to 8 bytes
+  setAtomic();
+
+  // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS)
+  if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android))
+    MaxVectorAlign = 64;
+
+  // Do force alignment of members that follow zero length bitfields.  If
+  // the alignment of the zero-length bitfield is greater than the member
+  // that follows it, `bar', `bar' will be aligned as the  type of the
+  // zero length bitfield.
+  UseZeroLengthBitfieldAlignment = true;
+
+  if (Triple.getOS() == llvm::Triple::Linux ||
+      Triple.getOS() == llvm::Triple::UnknownOS)
+    this->MCountName = Opts.EABIVersion == llvm::EABI::GNU
+                           ? "\01__gnu_mcount_nc"
+                           : "\01mcount";
+}
+
+StringRef ARMTargetInfo::getABI() const { return ABI; }
+
+bool ARMTargetInfo::setABI(const std::string &Name) {
+  ABI = Name;
+
+  // The defaults (above) are for AAPCS, check if we need to change them.
+  //
+  // FIXME: We need support for -meabi... we could just mangle it into the
+  // name.
+  if (Name == "apcs-gnu" || Name == "aapcs16") {
+    setABIAPCS(Name == "aapcs16");
     return true;
-  } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" ||
-             Name == "vfp4") {
-    FPMath = FP_VFP;
+  }
+  if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") {
+    setABIAAPCS();
     return true;
   }
   return false;
 }
 
-const char *const ARMTargetInfo::GCCRegNames[] = {
-    // Integer registers
-    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
-    "r12", "sp", "lr", "pc",
+// FIXME: This should be based on Arch attributes, not CPU names.
+bool ARMTargetInfo::initFeatureMap(
+    llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
+    const std::vector<std::string> &FeaturesVec) const {
+
+  std::vector<StringRef> TargetFeatures;
+  unsigned Arch = llvm::ARM::parseArch(getTriple().getArchName());
+
+  // get default FPU features
+  unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch);
+  llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures);
+
+  // get default Extension features
+  unsigned Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch);
+  llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures);
+
+  for (auto Feature : TargetFeatures)
+    if (Feature[0] == '+')
+      Features[Feature.drop_front(1)] = true;
+
+  // Enable or disable thumb-mode explicitly per function to enable mixed
+  // ARM and Thumb code generation.
+  if (isThumb())
+    Features["thumb-mode"] = true;
+  else
+    Features["thumb-mode"] = false;
+
+  // Convert user-provided arm and thumb GNU target attributes to
+  // [-|+]thumb-mode target features respectively.
+  std::vector<std::string> UpdatedFeaturesVec(FeaturesVec);
+  for (auto &Feature : UpdatedFeaturesVec) {
+    if (Feature.compare("+arm") == 0)
+      Feature = "-thumb-mode";
+    else if (Feature.compare("+thumb") == 0)
+      Feature = "+thumb-mode";
+  }
 
-    // Float registers
-    "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
-    "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
-    "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
+  return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);
+}
 
-    // Double registers
-    "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
-    "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
-    "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
 
-    // Quad registers
-    "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11",
-    "q12", "q13", "q14", "q15"
-};
+bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+                                         DiagnosticsEngine &Diags) {
+  FPU = 0;
+  CRC = 0;
+  Crypto = 0;
+  DSP = 0;
+  Unaligned = 1;
+  SoftFloat = SoftFloatABI = false;
+  HWDiv = 0;
 
-ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const {
-  return llvm::makeArrayRef(GCCRegNames);
-}
+  // This does not diagnose illegal cases like having both
+  // "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp".
+  uint32_t HW_FP_remove = 0;
+  for (const auto &Feature : Features) {
+    if (Feature == "+soft-float") {
+      SoftFloat = true;
+    } else if (Feature == "+soft-float-abi") {
+      SoftFloatABI = true;
+    } else if (Feature == "+vfp2") {
+      FPU |= VFP2FPU;
+      HW_FP |= HW_FP_SP | HW_FP_DP;
+    } else if (Feature == "+vfp3") {
+      FPU |= VFP3FPU;
+      HW_FP |= HW_FP_SP | HW_FP_DP;
+    } else if (Feature == "+vfp4") {
+      FPU |= VFP4FPU;
+      HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
+    } else if (Feature == "+fp-armv8") {
+      FPU |= FPARMV8;
+      HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
+    } else if (Feature == "+neon") {
+      FPU |= NeonFPU;
+      HW_FP |= HW_FP_SP | HW_FP_DP;
+    } else if (Feature == "+hwdiv") {
+      HWDiv |= HWDivThumb;
+    } else if (Feature == "+hwdiv-arm") {
+      HWDiv |= HWDivARM;
+    } else if (Feature == "+crc") {
+      CRC = 1;
+    } else if (Feature == "+crypto") {
+      Crypto = 1;
+    } else if (Feature == "+dsp") {
+      DSP = 1;
+    } else if (Feature == "+fp-only-sp") {
+      HW_FP_remove |= HW_FP_DP;
+    } else if (Feature == "+strict-align") {
+      Unaligned = 0;
+    } else if (Feature == "+fp16") {
+      HW_FP |= HW_FP_HP;
+    }
+  }
+  HW_FP &= ~HW_FP_remove;
 
-const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
-    {{"a1"}, "r0"},  {{"a2"}, "r1"},        {{"a3"}, "r2"},  {{"a4"}, "r3"},
-    {{"v1"}, "r4"},  {{"v2"}, "r5"},        {{"v3"}, "r6"},  {{"v4"}, "r7"},
-    {{"v5"}, "r8"},  {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"},
-    {{"ip"}, "r12"}, {{"r13"}, "sp"},       {{"r14"}, "lr"}, {{"r15"}, "pc"},
-    // The S, D and Q registers overlap, but aren't really aliases; we
-    // don't want to substitute one of these for a different-sized one.
-};
+  switch (ArchVersion) {
+  case 6:
+    if (ArchProfile == llvm::ARM::PK_M)
+      LDREX = 0;
+    else if (ArchKind == llvm::ARM::AK_ARMV6K)
+      LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
+    else
+      LDREX = LDREX_W;
+    break;
+  case 7:
+    if (ArchProfile == llvm::ARM::PK_M)
+      LDREX = LDREX_W | LDREX_H | LDREX_B;
+    else
+      LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
+    break;
+  case 8:
+    LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
+  }
 
-ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const {
-  return llvm::makeArrayRef(GCCRegAliases);
-}
+  if (!(FPU & NeonFPU) && FPMath == FP_Neon) {
+    Diags.Report(diag::err_target_unsupported_fpmath) << "neon";
+    return false;
+  }
 
-const Builtin::Info ARMTargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS)                                               \
-  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
-  {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
-#include "clang/Basic/BuiltinsNEON.def"
+  if (FPMath == FP_Neon)
+    Features.push_back("+neonfp");
+  else if (FPMath == FP_VFP)
+    Features.push_back("-neonfp");
 
-#define BUILTIN(ID, TYPE, ATTRS)                                               \
-  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
-#define LANGBUILTIN(ID, TYPE, ATTRS, LANG)                                     \
-  {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
-  {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
-#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE)         \
-  {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
-#include "clang/Basic/BuiltinsARM.def"
-};
+  // Remove front-end specific options which the backend handles differently.
+  auto Feature = std::find(Features.begin(), Features.end(), "+soft-float-abi");
+  if (Feature != Features.end())
+    Features.erase(Feature);
+
+  return true;
+}
 
 bool ARMTargetInfo::hasFeature(StringRef Feature) const {
   return llvm::StringSwitch<bool>(Feature)
@@ -102,6 +485,45 @@ bool ARMTargetInfo::hasFeature(StringRef
       .Default(false);
 }
 
+bool ARMTargetInfo::isValidCPUName(StringRef Name) const {
+  return Name == "generic" ||
+         llvm::ARM::parseCPUArch(Name) != llvm::ARM::AK_INVALID;
+}
+
+bool ARMTargetInfo::setCPU(const std::string &Name) {
+  if (Name != "generic")
+    setArchInfo(llvm::ARM::parseCPUArch(Name));
+
+  if (ArchKind == llvm::ARM::AK_INVALID)
+    return false;
+  setAtomic();
+  CPU = Name;
+  return true;
+}
+
+bool ARMTargetInfo::setFPMath(StringRef Name) {
+  if (Name == "neon") {
+    FPMath = FP_Neon;
+    return true;
+  } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" ||
+             Name == "vfp4") {
+    FPMath = FP_VFP;
+    return true;
+  }
+  return false;
+}
+
+void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
+                                            MacroBuilder &Builder) const {
+  Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
+}
+
+void ARMTargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
+                                            MacroBuilder &Builder) const {
+  // Also include the ARMv8.1-A defines
+  getTargetDefinesARMV81A(Opts, Builder);
+}
+
 void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
                                      MacroBuilder &Builder) const {
   // Target identification.
@@ -307,107 +729,197 @@ void ARMTargetInfo::getTargetDefines(con
   }
 }
 
-bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
-                                         DiagnosticsEngine &Diags) {
-  FPU = 0;
-  CRC = 0;
-  Crypto = 0;
-  DSP = 0;
-  Unaligned = 1;
-  SoftFloat = SoftFloatABI = false;
-  HWDiv = 0;
+const Builtin::Info ARMTargetInfo::BuiltinInfo[] = {
+#define BUILTIN(ID, TYPE, ATTRS)                                               \
+  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
+  {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#include "clang/Basic/BuiltinsNEON.def"
 
-  // This does not diagnose illegal cases like having both
-  // "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp".
-  uint32_t HW_FP_remove = 0;
-  for (const auto &Feature : Features) {
-    if (Feature == "+soft-float") {
-      SoftFloat = true;
-    } else if (Feature == "+soft-float-abi") {
-      SoftFloatABI = true;
-    } else if (Feature == "+vfp2") {
-      FPU |= VFP2FPU;
-      HW_FP |= HW_FP_SP | HW_FP_DP;
-    } else if (Feature == "+vfp3") {
-      FPU |= VFP3FPU;
-      HW_FP |= HW_FP_SP | HW_FP_DP;
-    } else if (Feature == "+vfp4") {
-      FPU |= VFP4FPU;
-      HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
-    } else if (Feature == "+fp-armv8") {
-      FPU |= FPARMV8;
-      HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
-    } else if (Feature == "+neon") {
-      FPU |= NeonFPU;
-      HW_FP |= HW_FP_SP | HW_FP_DP;
-    } else if (Feature == "+hwdiv") {
-      HWDiv |= HWDivThumb;
-    } else if (Feature == "+hwdiv-arm") {
-      HWDiv |= HWDivARM;
-    } else if (Feature == "+crc") {
-      CRC = 1;
-    } else if (Feature == "+crypto") {
-      Crypto = 1;
-    } else if (Feature == "+dsp") {
-      DSP = 1;
-    } else if (Feature == "+fp-only-sp") {
-      HW_FP_remove |= HW_FP_DP;
-    } else if (Feature == "+strict-align") {
-      Unaligned = 0;
-    } else if (Feature == "+fp16") {
-      HW_FP |= HW_FP_HP;
+#define BUILTIN(ID, TYPE, ATTRS)                                               \
+  {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
+#define LANGBUILTIN(ID, TYPE, ATTRS, LANG)                                     \
+  {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
+#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
+  {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
+#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE)         \
+  {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
+#include "clang/Basic/BuiltinsARM.def"
+};
+
+ArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const {
+  return llvm::makeArrayRef(BuiltinInfo, clang::ARM::LastTSBuiltin -
+                                             Builtin::FirstTSBuiltin);
+}
+
+bool ARMTargetInfo::isCLZForZeroUndef() const { return false; }
+TargetInfo::BuiltinVaListKind ARMTargetInfo::getBuiltinVaListKind() const {
+  return IsAAPCS
+             ? AAPCSABIBuiltinVaList
+             : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList
+                                         : TargetInfo::VoidPtrBuiltinVaList);
+}
+
+const char *const ARMTargetInfo::GCCRegNames[] = {
+    // Integer registers
+    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
+    "r12", "sp", "lr", "pc",
+
+    // Float registers
+    "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
+    "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
+    "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
+
+    // Double registers
+    "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
+    "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
+    "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
+
+    // Quad registers
+    "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11",
+    "q12", "q13", "q14", "q15"};
+
+ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const {
+  return llvm::makeArrayRef(GCCRegNames);
+}
+
+const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
+    {{"a1"}, "r0"},  {{"a2"}, "r1"},        {{"a3"}, "r2"},  {{"a4"}, "r3"},
+    {{"v1"}, "r4"},  {{"v2"}, "r5"},        {{"v3"}, "r6"},  {{"v4"}, "r7"},
+    {{"v5"}, "r8"},  {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"},
+    {{"ip"}, "r12"}, {{"r13"}, "sp"},       {{"r14"}, "lr"}, {{"r15"}, "pc"},
+    // The S, D and Q registers overlap, but aren't really aliases; we
+    // don't want to substitute one of these for a different-sized one.
+};
+
+ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const {
+  return llvm::makeArrayRef(GCCRegAliases);
+}
+
+bool ARMTargetInfo::validateAsmConstraint(
+    const char *&Name, TargetInfo::ConstraintInfo &Info) const {
+  switch (*Name) {
+  default:
+    break;
+  case 'l': // r0-r7
+  case 'h': // r8-r15
+  case 't': // VFP Floating point register single precision
+  case 'w': // VFP Floating point register double precision
+    Info.setAllowsRegister();
+    return true;
+  case 'I':
+  case 'J':
+  case 'K':
+  case 'L':
+  case 'M':
+    // FIXME
+    return true;
+  case 'Q': // A memory address that is a single base register.
+    Info.setAllowsMemory();
+    return true;
+  case 'U': // a memory reference...
+    switch (Name[1]) {
+    case 'q': // ...ARMV4 ldrsb
+    case 'v': // ...VFP load/store (reg+constant offset)
+    case 'y': // ...iWMMXt load/store
+    case 't': // address valid for load/store opaque types wider
+              // than 128-bits
+    case 'n': // valid address for Neon doubleword vector load/store
+    case 'm': // valid address for Neon element and structure load/store
+    case 's': // valid address for non-offset loads/stores of quad-word
+              // values in four ARM registers
+      Info.setAllowsMemory();
+      Name++;
+      return true;
     }
   }
-  HW_FP &= ~HW_FP_remove;
+  return false;
+}
 
-  switch (ArchVersion) {
-  case 6:
-    if (ArchProfile == llvm::ARM::PK_M)
-      LDREX = 0;
-    else if (ArchKind == llvm::ARM::AK_ARMV6K)
-      LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
-    else
-      LDREX = LDREX_W;
+std::string ARMTargetInfo::convertConstraint(const char *&Constraint) const {
+  std::string R;
+  switch (*Constraint) {
+  case 'U': // Two-character constraint; add "^" hint for later parsing.
+    R = std::string("^") + std::string(Constraint, 2);
+    Constraint++;
     break;
-  case 7:
-    if (ArchProfile == llvm::ARM::PK_M)
-      LDREX = LDREX_W | LDREX_H | LDREX_B;
-    else
-      LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
+  case 'p': // 'p' should be translated to 'r' by default.
+    R = std::string("r");
     break;
-  case 8:
-    LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
-  }
-
-  if (!(FPU & NeonFPU) && FPMath == FP_Neon) {
-    Diags.Report(diag::err_target_unsupported_fpmath) << "neon";
-    return false;
+  default:
+    return std::string(1, *Constraint);
   }
+  return R;
+}
 
-  if (FPMath == FP_Neon)
-    Features.push_back("+neonfp");
-  else if (FPMath == FP_VFP)
-    Features.push_back("-neonfp");
+bool ARMTargetInfo::validateConstraintModifier(
+    StringRef Constraint, char Modifier, unsigned Size,
+    std::string &SuggestedModifier) const {
+  bool isOutput = (Constraint[0] == '=');
+  bool isInOut = (Constraint[0] == '+');
+
+  // Strip off constraint modifiers.
+  while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
+    Constraint = Constraint.substr(1);
 
-  // Remove front-end specific options which the backend handles differently.
-  auto Feature = std::find(Features.begin(), Features.end(), "+soft-float-abi");
-  if (Feature != Features.end())
-    Features.erase(Feature);
+  switch (Constraint[0]) {
+  default:
+    break;
+  case 'r': {
+    switch (Modifier) {
+    default:
+      return (isInOut || isOutput || Size <= 64);
+    case 'q':
+      // A register of size 32 cannot fit a vector type.
+      return false;
+    }
+  }
+  }
 
   return true;
 }
+const char *ARMTargetInfo::getClobbers() const {
+  // FIXME: Is this really right?
+  return "";
+}
 
-void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
-                                            MacroBuilder &Builder) const {
-  Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
+TargetInfo::CallingConvCheckResult
+ARMTargetInfo::checkCallingConvention(CallingConv CC) const {
+  switch (CC) {
+  case CC_AAPCS:
+  case CC_AAPCS_VFP:
+  case CC_Swift:
+  case CC_OpenCLKernel:
+    return CCCR_OK;
+  default:
+    return CCCR_Warning;
+  }
+}
+
+int ARMTargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
+  if (RegNo == 0)
+    return 0;
+  if (RegNo == 1)
+    return 1;
+  return -1;
 }
 
+bool ARMTargetInfo::hasSjLjLowering() const { return true; }
+
+ARMleTargetInfo::ARMleTargetInfo(const llvm::Triple &Triple,
+                                 const TargetOptions &Opts)
+    : ARMTargetInfo(Triple, Opts) {}
+
 void ARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
                                        MacroBuilder &Builder) const {
   Builder.defineMacro("__ARMEL__");
   ARMTargetInfo::getTargetDefines(Opts, Builder);
 }
 
+ARMbeTargetInfo::ARMbeTargetInfo(const llvm::Triple &Triple,
+                                 const TargetOptions &Opts)
+    : ARMTargetInfo(Triple, Opts) {}
+
 void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts,
                                        MacroBuilder &Builder) const {
   Builder.defineMacro("__ARMEB__");
@@ -415,6 +927,13 @@ void ARMbeTargetInfo::getTargetDefines(c
   ARMTargetInfo::getTargetDefines(Opts, Builder);
 }
 
+WindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple,
+                                           const TargetOptions &Opts)
+    : WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) {
+  WCharType = UnsignedShort;
+  SizeType = UnsignedInt;
+}
+
 void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts,
                                                   MacroBuilder &Builder) const {
   WindowsTargetInfo<ARMleTargetInfo>::getVisualStudioDefines(Opts, Builder);
@@ -435,6 +954,61 @@ void WindowsARMTargetInfo::getVisualStud
   Builder.defineMacro("_M_ARM_FP", "31");
 }
 
+TargetInfo::BuiltinVaListKind
+WindowsARMTargetInfo::getBuiltinVaListKind() const {
+  return TargetInfo::CharPtrBuiltinVaList;
+}
+
+TargetInfo::CallingConvCheckResult
+WindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const {
+  switch (CC) {
+  case CC_X86StdCall:
+  case CC_X86ThisCall:
+  case CC_X86FastCall:
+  case CC_X86VectorCall:
+    return CCCR_Ignore;
+  case CC_C:
+  case CC_OpenCLKernel:
+    return CCCR_OK;
+  default:
+    return CCCR_Warning;
+  }
+}
+
+// Windows ARM + Itanium C++ ABI Target
+ItaniumWindowsARMleTargetInfo::ItaniumWindowsARMleTargetInfo(
+    const llvm::Triple &Triple, const TargetOptions &Opts)
+    : WindowsARMTargetInfo(Triple, Opts) {
+  TheCXXABI.set(TargetCXXABI::GenericARM);
+}
+
+void ItaniumWindowsARMleTargetInfo::getTargetDefines(
+    const LangOptions &Opts, MacroBuilder &Builder) const {
+  WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
+
+  if (Opts.MSVCCompat)
+    WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
+}
+
+// Windows ARM, MS (C++) ABI
+MicrosoftARMleTargetInfo::MicrosoftARMleTargetInfo(const llvm::Triple &Triple,
+                                                   const TargetOptions &Opts)
+    : WindowsARMTargetInfo(Triple, Opts) {
+  TheCXXABI.set(TargetCXXABI::Microsoft);
+}
+
+void MicrosoftARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
+                                                MacroBuilder &Builder) const {
+  WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
+  WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
+}
+
+MinGWARMTargetInfo::MinGWARMTargetInfo(const llvm::Triple &Triple,
+                                       const TargetOptions &Opts)
+    : WindowsARMTargetInfo(Triple, Opts) {
+  TheCXXABI.set(TargetCXXABI::GenericARM);
+}
+
 void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts,
                                           MacroBuilder &Builder) const {
   WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
@@ -444,6 +1018,15 @@ void MinGWARMTargetInfo::getTargetDefine
   addMinGWDefines(Opts, Builder);
 }
 
+CygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple,
+                                         const TargetOptions &Opts)
+    : ARMleTargetInfo(Triple, Opts) {
+  TLSSupported = false;
+  WCharType = UnsignedShort;
+  DoubleAlign = LongLongAlign = 64;
+  resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
+}
+
 void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts,
                                            MacroBuilder &Builder) const {
   ARMleTargetInfo::getTargetDefines(Opts, Builder);
@@ -455,13 +1038,47 @@ void CygwinARMTargetInfo::getTargetDefin
     Builder.defineMacro("_GNU_SOURCE");
 }
 
+DarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple,
+                                         const TargetOptions &Opts)
+    : DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) {
+  HasAlignMac68kSupport = true;
+  // iOS always has 64-bit atomic instructions.
+  // FIXME: This should be based off of the target features in
+  // ARMleTargetInfo.
+  MaxAtomicInlineWidth = 64;
+
+  if (Triple.isWatchABI()) {
+    // Darwin on iOS uses a variant of the ARM C++ ABI.
+    TheCXXABI.set(TargetCXXABI::WatchOS);
+
+    // The 32-bit ABI is silent on what ptrdiff_t should be, but given that
+    // size_t is long, it's a bit weird for it to be int.
+    PtrDiffType = SignedLong;
+
+    // BOOL should be a real boolean on the new ABI
+    UseSignedCharForObjCBool = false;
+  } else
+    TheCXXABI.set(TargetCXXABI::iOS);
+}
+
+void DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts,
+                                       const llvm::Triple &Triple,
+                                       MacroBuilder &Builder) const {
+  getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
+}
+
+RenderScript32TargetInfo::RenderScript32TargetInfo(const llvm::Triple &Triple,
+                                                   const TargetOptions &Opts)
+    : ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(),
+                                   Triple.getOSName(),
+                                   Triple.getEnvironmentName()),
+                      Opts) {
+  IsRenderScriptTarget = true;
+  LongWidth = LongAlign = 64;
+}
+
 void RenderScript32TargetInfo::getTargetDefines(const LangOptions &Opts,
                                                 MacroBuilder &Builder) const {
   Builder.defineMacro("__RENDERSCRIPT__");
   ARMleTargetInfo::getTargetDefines(Opts, Builder);
 }
-
-ArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const {
-  return llvm::makeArrayRef(BuiltinInfo, clang::ARM::LastTSBuiltin -
-                                             Builtin::FirstTSBuiltin);
-}

Modified: cfe/trunk/lib/Basic/Targets/ARM.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets/ARM.h?rev=308898&r1=308897&r2=308898&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Targets/ARM.h (original)
+++ cfe/trunk/lib/Basic/Targets/ARM.h Mon Jul 24 10:06:23 2017
@@ -89,383 +89,40 @@ class LLVM_LIBRARY_VISIBILITY ARMTargetI
 
   static const Builtin::Info BuiltinInfo[];
 
-  void setABIAAPCS() {
-    IsAAPCS = true;
+  void setABIAAPCS();
+  void setABIAPCS(bool IsAAPCS16);
 
-    DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
-    const llvm::Triple &T = getTriple();
+  void setArchInfo();
+  void setArchInfo(unsigned Kind);
 
-    // size_t is unsigned long on MachO-derived environments, NetBSD, and
-    // OpenBSD.
-    if (T.isOSBinFormatMachO() || T.getOS() == llvm::Triple::NetBSD ||
-        T.getOS() == llvm::Triple::OpenBSD)
-      SizeType = UnsignedLong;
-    else
-      SizeType = UnsignedInt;
-
-    switch (T.getOS()) {
-    case llvm::Triple::NetBSD:
-    case llvm::Triple::OpenBSD:
-      WCharType = SignedInt;
-      break;
-    case llvm::Triple::Win32:
-      WCharType = UnsignedShort;
-      break;
-    case llvm::Triple::Linux:
-    default:
-      // AAPCS 7.1.1, ARM-Linux ABI 2.4: type of wchar_t is unsigned int.
-      WCharType = UnsignedInt;
-      break;
-    }
-
-    UseBitFieldTypeAlignment = true;
-
-    ZeroLengthBitfieldBoundary = 0;
-
-    // Thumb1 add sp, #imm requires the immediate value be multiple of 4,
-    // so set preferred for small types to 32.
-    if (T.isOSBinFormatMachO()) {
-      resetDataLayout(BigEndian
-                          ? "E-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
-                          : "e-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
-    } else if (T.isOSWindows()) {
-      assert(!BigEndian && "Windows on ARM does not support big endian");
-      resetDataLayout("e"
-                      "-m:w"
-                      "-p:32:32"
-                      "-i64:64"
-                      "-v128:64:128"
-                      "-a:0:32"
-                      "-n32"
-                      "-S64");
-    } else if (T.isOSNaCl()) {
-      assert(!BigEndian && "NaCl on ARM does not support big endian");
-      resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128");
-    } else {
-      resetDataLayout(BigEndian
-                          ? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
-                          : "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
-    }
-
-    // FIXME: Enumerated types are variable width in straight AAPCS.
-  }
-
-  void setABIAPCS(bool IsAAPCS16) {
-    const llvm::Triple &T = getTriple();
-
-    IsAAPCS = false;
-
-    if (IsAAPCS16)
-      DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
-    else
-      DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32;
-
-    // size_t is unsigned int on FreeBSD.
-    if (T.getOS() == llvm::Triple::FreeBSD)
-      SizeType = UnsignedInt;
-    else
-      SizeType = UnsignedLong;
-
-    // Revert to using SignedInt on apcs-gnu to comply with existing behaviour.
-    WCharType = SignedInt;
-
-    // Do not respect the alignment of bit-field types when laying out
-    // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc.
-    UseBitFieldTypeAlignment = false;
-
-    /// gcc forces the alignment to 4 bytes, regardless of the type of the
-    /// zero length bitfield.  This corresponds to EMPTY_FIELD_BOUNDARY in
-    /// gcc.
-    ZeroLengthBitfieldBoundary = 32;
-
-    if (T.isOSBinFormatMachO() && IsAAPCS16) {
-      assert(!BigEndian && "AAPCS16 does not support big-endian");
-      resetDataLayout("e-m:o-p:32:32-i64:64-a:0:32-n32-S128");
-    } else if (T.isOSBinFormatMachO())
-      resetDataLayout(
-          BigEndian
-              ? "E-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
-              : "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
-    else
-      resetDataLayout(
-          BigEndian
-              ? "E-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
-              : "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
-
-    // FIXME: Override "preferred align" for double and long long.
-  }
-
-  void setArchInfo() {
-    StringRef ArchName = getTriple().getArchName();
-
-    ArchISA = llvm::ARM::parseArchISA(ArchName);
-    CPU = llvm::ARM::getDefaultCPU(ArchName);
-    unsigned AK = llvm::ARM::parseArch(ArchName);
-    if (AK != llvm::ARM::AK_INVALID)
-      ArchKind = AK;
-    setArchInfo(ArchKind);
-  }
-
-  void setArchInfo(unsigned Kind) {
-    StringRef SubArch;
-
-    // cache TargetParser info
-    ArchKind = Kind;
-    SubArch = llvm::ARM::getSubArch(ArchKind);
-    ArchProfile = llvm::ARM::parseArchProfile(SubArch);
-    ArchVersion = llvm::ARM::parseArchVersion(SubArch);
-
-    // cache CPU related strings
-    CPUAttr = getCPUAttr();
-    CPUProfile = getCPUProfile();
-  }
-
-  void setAtomic() {
-    // when triple does not specify a sub arch,
-    // then we are not using inline atomics
-    bool ShouldUseInlineAtomic =
-        (ArchISA == llvm::ARM::IK_ARM && ArchVersion >= 6) ||
-        (ArchISA == llvm::ARM::IK_THUMB && ArchVersion >= 7);
-    // Cortex M does not support 8 byte atomics, while general Thumb2 does.
-    if (ArchProfile == llvm::ARM::PK_M) {
-      MaxAtomicPromoteWidth = 32;
-      if (ShouldUseInlineAtomic)
-        MaxAtomicInlineWidth = 32;
-    } else {
-      MaxAtomicPromoteWidth = 64;
-      if (ShouldUseInlineAtomic)
-        MaxAtomicInlineWidth = 64;
-    }
-  }
-
-  bool isThumb() const { return (ArchISA == llvm::ARM::IK_THUMB); }
-
-  bool supportsThumb() const { return CPUAttr.count('T') || ArchVersion >= 6; }
-
-  bool supportsThumb2() const {
-    return CPUAttr.equals("6T2") ||
-           (ArchVersion >= 7 && !CPUAttr.equals("8M_BASE"));
-  }
-
-  StringRef getCPUAttr() const {
-    // For most sub-arches, the build attribute CPU name is enough.
-    // For Cortex variants, it's slightly different.
-    switch (ArchKind) {
-    default:
-      return llvm::ARM::getCPUAttr(ArchKind);
-    case llvm::ARM::AK_ARMV6M:
-      return "6M";
-    case llvm::ARM::AK_ARMV7S:
-      return "7S";
-    case llvm::ARM::AK_ARMV7A:
-      return "7A";
-    case llvm::ARM::AK_ARMV7R:
-      return "7R";
-    case llvm::ARM::AK_ARMV7M:
-      return "7M";
-    case llvm::ARM::AK_ARMV7EM:
-      return "7EM";
-    case llvm::ARM::AK_ARMV7VE:
-      return "7VE";
-    case llvm::ARM::AK_ARMV8A:
-      return "8A";
-    case llvm::ARM::AK_ARMV8_1A:
-      return "8_1A";
-    case llvm::ARM::AK_ARMV8_2A:
-      return "8_2A";
-    case llvm::ARM::AK_ARMV8MBaseline:
-      return "8M_BASE";
-    case llvm::ARM::AK_ARMV8MMainline:
-      return "8M_MAIN";
-    case llvm::ARM::AK_ARMV8R:
-      return "8R";
-    }
-  }
-
-  StringRef getCPUProfile() const {
-    switch (ArchProfile) {
-    case llvm::ARM::PK_A:
-      return "A";
-    case llvm::ARM::PK_R:
-      return "R";
-    case llvm::ARM::PK_M:
-      return "M";
-    default:
-      return "";
-    }
-  }
+  void setAtomic();
+
+  bool isThumb() const;
+  bool supportsThumb() const;
+  bool supportsThumb2() const;
+
+  StringRef getCPUAttr() const;
+  StringRef getCPUProfile() const;
 
 public:
-  ARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
-      : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
-        HW_FP(0) {
-
-    switch (getTriple().getOS()) {
-    case llvm::Triple::NetBSD:
-    case llvm::Triple::OpenBSD:
-      PtrDiffType = SignedLong;
-      break;
-    default:
-      PtrDiffType = SignedInt;
-      break;
-    }
-
-    // Cache arch related info.
-    setArchInfo();
-
-    // {} in inline assembly are neon specifiers, not assembly variant
-    // specifiers.
-    NoAsmVariants = true;
-
-    // FIXME: This duplicates code from the driver that sets the -target-abi
-    // option - this code is used if -target-abi isn't passed and should
-    // be unified in some way.
-    if (Triple.isOSBinFormatMachO()) {
-      // The backend is hardwired to assume AAPCS for M-class processors, ensure
-      // the frontend matches that.
-      if (Triple.getEnvironment() == llvm::Triple::EABI ||
-          Triple.getOS() == llvm::Triple::UnknownOS ||
-          ArchProfile == llvm::ARM::PK_M) {
-        setABI("aapcs");
-      } else if (Triple.isWatchABI()) {
-        setABI("aapcs16");
-      } else {
-        setABI("apcs-gnu");
-      }
-    } else if (Triple.isOSWindows()) {
-      // FIXME: this is invalid for WindowsCE
-      setABI("aapcs");
-    } else {
-      // Select the default based on the platform.
-      switch (Triple.getEnvironment()) {
-      case llvm::Triple::Android:
-      case llvm::Triple::GNUEABI:
-      case llvm::Triple::GNUEABIHF:
-      case llvm::Triple::MuslEABI:
-      case llvm::Triple::MuslEABIHF:
-        setABI("aapcs-linux");
-        break;
-      case llvm::Triple::EABIHF:
-      case llvm::Triple::EABI:
-        setABI("aapcs");
-        break;
-      case llvm::Triple::GNU:
-        setABI("apcs-gnu");
-        break;
-      default:
-        if (Triple.getOS() == llvm::Triple::NetBSD)
-          setABI("apcs-gnu");
-        else if (Triple.getOS() == llvm::Triple::OpenBSD)
-          setABI("aapcs-linux");
-        else
-          setABI("aapcs");
-        break;
-      }
-    }
-
-    // ARM targets default to using the ARM C++ ABI.
-    TheCXXABI.set(TargetCXXABI::GenericARM);
-
-    // ARM has atomics up to 8 bytes
-    setAtomic();
-
-    // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS)
-    if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android))
-      MaxVectorAlign = 64;
-
-    // Do force alignment of members that follow zero length bitfields.  If
-    // the alignment of the zero-length bitfield is greater than the member
-    // that follows it, `bar', `bar' will be aligned as the  type of the
-    // zero length bitfield.
-    UseZeroLengthBitfieldAlignment = true;
-
-    if (Triple.getOS() == llvm::Triple::Linux ||
-        Triple.getOS() == llvm::Triple::UnknownOS)
-      this->MCountName = Opts.EABIVersion == llvm::EABI::GNU
-                             ? "\01__gnu_mcount_nc"
-                             : "\01mcount";
-  }
-
-  StringRef getABI() const override { return ABI; }
-
-  bool setABI(const std::string &Name) override {
-    ABI = Name;
-
-    // The defaults (above) are for AAPCS, check if we need to change them.
-    //
-    // FIXME: We need support for -meabi... we could just mangle it into the
-    // name.
-    if (Name == "apcs-gnu" || Name == "aapcs16") {
-      setABIAPCS(Name == "aapcs16");
-      return true;
-    }
-    if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") {
-      setABIAAPCS();
-      return true;
-    }
-    return false;
-  }
+  ARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
+  StringRef getABI() const override;
+  bool setABI(const std::string &Name) override;
 
   // FIXME: This should be based on Arch attributes, not CPU names.
   bool
   initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
                  StringRef CPU,
-                 const std::vector<std::string> &FeaturesVec) const override {
-
-    std::vector<StringRef> TargetFeatures;
-    unsigned Arch = llvm::ARM::parseArch(getTriple().getArchName());
-
-    // get default FPU features
-    unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch);
-    llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures);
-
-    // get default Extension features
-    unsigned Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch);
-    llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures);
-
-    for (auto Feature : TargetFeatures)
-      if (Feature[0] == '+')
-        Features[Feature.drop_front(1)] = true;
-
-    // Enable or disable thumb-mode explicitly per function to enable mixed
-    // ARM and Thumb code generation.
-    if (isThumb())
-      Features["thumb-mode"] = true;
-    else
-      Features["thumb-mode"] = false;
-
-    // Convert user-provided arm and thumb GNU target attributes to
-    // [-|+]thumb-mode target features respectively.
-    std::vector<std::string> UpdatedFeaturesVec(FeaturesVec);
-    for (auto &Feature : UpdatedFeaturesVec) {
-      if (Feature.compare("+arm") == 0)
-        Feature = "-thumb-mode";
-      else if (Feature.compare("+thumb") == 0)
-        Feature = "+thumb-mode";
-    }
-
-    return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);
-  }
+                 const std::vector<std::string> &FeaturesVec) const override;
 
   bool handleTargetFeatures(std::vector<std::string> &Features,
                             DiagnosticsEngine &Diags) override;
 
   bool hasFeature(StringRef Feature) const override;
-  bool isValidCPUName(StringRef Name) const override {
-    return Name == "generic" ||
-           llvm::ARM::parseCPUArch(Name) != llvm::ARM::AK_INVALID;
-  }
-
-  bool setCPU(const std::string &Name) override {
-    if (Name != "generic")
-      setArchInfo(llvm::ARM::parseCPUArch(Name));
-
-    if (ArchKind == llvm::ARM::AK_INVALID)
-      return false;
-    setAtomic();
-    CPU = Name;
-    return true;
-  }
+
+  bool isValidCPUName(StringRef Name) const override;
+  bool setCPU(const std::string &Name) override;
 
   bool setFPMath(StringRef Name) override;
 
@@ -473,143 +130,42 @@ public:
                                MacroBuilder &Builder) const;
 
   void getTargetDefinesARMV82A(const LangOptions &Opts,
-                               MacroBuilder &Builder) const {
-    // Also include the ARMv8.1-A defines
-    getTargetDefinesARMV81A(Opts, Builder);
-  }
-
+                               MacroBuilder &Builder) const;
   void getTargetDefines(const LangOptions &Opts,
                         MacroBuilder &Builder) const override;
+
   ArrayRef<Builtin::Info> getTargetBuiltins() const override;
-  bool isCLZForZeroUndef() const override { return false; }
-  BuiltinVaListKind getBuiltinVaListKind() const override {
-    return IsAAPCS
-               ? AAPCSABIBuiltinVaList
-               : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList
-                                           : TargetInfo::VoidPtrBuiltinVaList);
-  }
+
+  bool isCLZForZeroUndef() const override;
+  BuiltinVaListKind getBuiltinVaListKind() const override;
+
   ArrayRef<const char *> getGCCRegNames() const override;
   ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override;
   bool validateAsmConstraint(const char *&Name,
-                             TargetInfo::ConstraintInfo &Info) const override {
-    switch (*Name) {
-    default:
-      break;
-    case 'l': // r0-r7
-    case 'h': // r8-r15
-    case 't': // VFP Floating point register single precision
-    case 'w': // VFP Floating point register double precision
-      Info.setAllowsRegister();
-      return true;
-    case 'I':
-    case 'J':
-    case 'K':
-    case 'L':
-    case 'M':
-      // FIXME
-      return true;
-    case 'Q': // A memory address that is a single base register.
-      Info.setAllowsMemory();
-      return true;
-    case 'U': // a memory reference...
-      switch (Name[1]) {
-      case 'q': // ...ARMV4 ldrsb
-      case 'v': // ...VFP load/store (reg+constant offset)
-      case 'y': // ...iWMMXt load/store
-      case 't': // address valid for load/store opaque types wider
-                // than 128-bits
-      case 'n': // valid address for Neon doubleword vector load/store
-      case 'm': // valid address for Neon element and structure load/store
-      case 's': // valid address for non-offset loads/stores of quad-word
-                // values in four ARM registers
-        Info.setAllowsMemory();
-        Name++;
-        return true;
-      }
-    }
-    return false;
-  }
-  std::string convertConstraint(const char *&Constraint) const override {
-    std::string R;
-    switch (*Constraint) {
-    case 'U': // Two-character constraint; add "^" hint for later parsing.
-      R = std::string("^") + std::string(Constraint, 2);
-      Constraint++;
-      break;
-    case 'p': // 'p' should be translated to 'r' by default.
-      R = std::string("r");
-      break;
-    default:
-      return std::string(1, *Constraint);
-    }
-    return R;
-  }
+                             TargetInfo::ConstraintInfo &Info) const override;
+  std::string convertConstraint(const char *&Constraint) const override;
   bool
   validateConstraintModifier(StringRef Constraint, char Modifier, unsigned Size,
-                             std::string &SuggestedModifier) const override {
-    bool isOutput = (Constraint[0] == '=');
-    bool isInOut = (Constraint[0] == '+');
-
-    // Strip off constraint modifiers.
-    while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
-      Constraint = Constraint.substr(1);
-
-    switch (Constraint[0]) {
-    default:
-      break;
-    case 'r': {
-      switch (Modifier) {
-      default:
-        return (isInOut || isOutput || Size <= 64);
-      case 'q':
-        // A register of size 32 cannot fit a vector type.
-        return false;
-      }
-    }
-    }
-
-    return true;
-  }
-  const char *getClobbers() const override {
-    // FIXME: Is this really right?
-    return "";
-  }
-
-  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
-    switch (CC) {
-    case CC_AAPCS:
-    case CC_AAPCS_VFP:
-    case CC_Swift:
-    case CC_OpenCLKernel:
-      return CCCR_OK;
-    default:
-      return CCCR_Warning;
-    }
-  }
-
-  int getEHDataRegisterNumber(unsigned RegNo) const override {
-    if (RegNo == 0)
-      return 0;
-    if (RegNo == 1)
-      return 1;
-    return -1;
-  }
+                             std::string &SuggestedModifier) const override;
+  const char *getClobbers() const override;
 
-  bool hasSjLjLowering() const override { return true; }
+  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
+
+  int getEHDataRegisterNumber(unsigned RegNo) const override;
+
+  bool hasSjLjLowering() const override;
 };
 
 class LLVM_LIBRARY_VISIBILITY ARMleTargetInfo : public ARMTargetInfo {
 public:
-  ARMleTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
-      : ARMTargetInfo(Triple, Opts) {}
+  ARMleTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
   void getTargetDefines(const LangOptions &Opts,
                         MacroBuilder &Builder) const override;
 };
 
 class LLVM_LIBRARY_VISIBILITY ARMbeTargetInfo : public ARMTargetInfo {
 public:
-  ARMbeTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
-      : ARMTargetInfo(Triple, Opts) {}
+  ARMbeTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
   void getTargetDefines(const LangOptions &Opts,
                         MacroBuilder &Builder) const override;
 };
@@ -619,30 +175,14 @@ class LLVM_LIBRARY_VISIBILITY WindowsARM
   const llvm::Triple Triple;
 
 public:
-  WindowsARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
-      : WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) {
-    WCharType = UnsignedShort;
-    SizeType = UnsignedInt;
-  }
+  WindowsARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
   void getVisualStudioDefines(const LangOptions &Opts,
                               MacroBuilder &Builder) const;
-  BuiltinVaListKind getBuiltinVaListKind() const override {
-    return TargetInfo::CharPtrBuiltinVaList;
-  }
-  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
-    switch (CC) {
-    case CC_X86StdCall:
-    case CC_X86ThisCall:
-    case CC_X86FastCall:
-    case CC_X86VectorCall:
-      return CCCR_Ignore;
-    case CC_C:
-    case CC_OpenCLKernel:
-      return CCCR_OK;
-    default:
-      return CCCR_Warning;
-    }
-  }
+
+  BuiltinVaListKind getBuiltinVaListKind() const override;
+
+  CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
 };
 
 // Windows ARM + Itanium C++ ABI Target
@@ -650,18 +190,10 @@ class LLVM_LIBRARY_VISIBILITY ItaniumWin
     : public WindowsARMTargetInfo {
 public:
   ItaniumWindowsARMleTargetInfo(const llvm::Triple &Triple,
-                                const TargetOptions &Opts)
-      : WindowsARMTargetInfo(Triple, Opts) {
-    TheCXXABI.set(TargetCXXABI::GenericARM);
-  }
+                                const TargetOptions &Opts);
 
   void getTargetDefines(const LangOptions &Opts,
-                        MacroBuilder &Builder) const override {
-    WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
-
-    if (Opts.MSVCCompat)
-      WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
-  }
+                        MacroBuilder &Builder) const override;
 };
 
 // Windows ARM, MS (C++) ABI
@@ -669,25 +201,16 @@ class LLVM_LIBRARY_VISIBILITY MicrosoftA
     : public WindowsARMTargetInfo {
 public:
   MicrosoftARMleTargetInfo(const llvm::Triple &Triple,
-                           const TargetOptions &Opts)
-      : WindowsARMTargetInfo(Triple, Opts) {
-    TheCXXABI.set(TargetCXXABI::Microsoft);
-  }
+                           const TargetOptions &Opts);
 
   void getTargetDefines(const LangOptions &Opts,
-                        MacroBuilder &Builder) const override {
-    WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
-    WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
-  }
+                        MacroBuilder &Builder) const override;
 };
 
 // ARM MinGW target
 class LLVM_LIBRARY_VISIBILITY MinGWARMTargetInfo : public WindowsARMTargetInfo {
 public:
-  MinGWARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
-      : WindowsARMTargetInfo(Triple, Opts) {
-    TheCXXABI.set(TargetCXXABI::GenericARM);
-  }
+  MinGWARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
 
   void getTargetDefines(const LangOptions &Opts,
                         MacroBuilder &Builder) const override;
@@ -696,13 +219,8 @@ public:
 // ARM Cygwin target
 class LLVM_LIBRARY_VISIBILITY CygwinARMTargetInfo : public ARMleTargetInfo {
 public:
-  CygwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
-      : ARMleTargetInfo(Triple, Opts) {
-    TLSSupported = false;
-    WCharType = UnsignedShort;
-    DoubleAlign = LongLongAlign = 64;
-    resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
-  }
+  CygwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
+
   void getTargetDefines(const LangOptions &Opts,
                         MacroBuilder &Builder) const override;
 };
@@ -711,46 +229,19 @@ class LLVM_LIBRARY_VISIBILITY DarwinARMT
     : public DarwinTargetInfo<ARMleTargetInfo> {
 protected:
   void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
-                    MacroBuilder &Builder) const override {
-    getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
-  }
+                    MacroBuilder &Builder) const override;
 
 public:
-  DarwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
-      : DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) {
-    HasAlignMac68kSupport = true;
-    // iOS always has 64-bit atomic instructions.
-    // FIXME: This should be based off of the target features in
-    // ARMleTargetInfo.
-    MaxAtomicInlineWidth = 64;
-
-    if (Triple.isWatchABI()) {
-      // Darwin on iOS uses a variant of the ARM C++ ABI.
-      TheCXXABI.set(TargetCXXABI::WatchOS);
-
-      // The 32-bit ABI is silent on what ptrdiff_t should be, but given that
-      // size_t is long, it's a bit weird for it to be int.
-      PtrDiffType = SignedLong;
-
-      // BOOL should be a real boolean on the new ABI
-      UseSignedCharForObjCBool = false;
-    } else
-      TheCXXABI.set(TargetCXXABI::iOS);
-  }
+  DarwinARMTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);
 };
+
 // 32-bit RenderScript is armv7 with width and align of 'long' set to 8-bytes
 class LLVM_LIBRARY_VISIBILITY RenderScript32TargetInfo
     : public ARMleTargetInfo {
 public:
   RenderScript32TargetInfo(const llvm::Triple &Triple,
-                           const TargetOptions &Opts)
-      : ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(),
-                                     Triple.getOSName(),
-                                     Triple.getEnvironmentName()),
-                        Opts) {
-    IsRenderScriptTarget = true;
-    LongWidth = LongAlign = 64;
-  }
+                           const TargetOptions &Opts);
+
   void getTargetDefines(const LangOptions &Opts,
                         MacroBuilder &Builder) const override;
 };




More information about the cfe-commits mailing list