r296056 - [Driver] Move architecture-specific free helper functions to their own files.

David L. Jones via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 23 16:28:01 PST 2017


Author: dlj
Date: Thu Feb 23 18:28:01 2017
New Revision: 296056

URL: http://llvm.org/viewvc/llvm-project?rev=296056&view=rev
Log:
[Driver] Move architecture-specific free helper functions to their own files.

This patch moves helper functions that are CPU-specific out of Driver.cpp and to
separate implementation files. The new files are named for the architecture,
e.g. ARMArch.cpp.

The next step after this will be to move OS-specific code, which I expect will
include many of the tool implementations, to similarly separate files.

Some CPU-specific functions are not being moved just yet. In cases where the
only caller is the platform-specific tools, I plan to move them together. An
example is Hexagon, where the only caller of the architecture-specific functions
are the tools themselves. (I'm happy to revise this choice, it just seems like
less churn to me.)

This does mean that some functions which were previously static are now exposed
through the library header Driver.h.

Reviewers: rsmith, javed.absar

Subscribers: aemerson, danalbert, srhines, dschuff, jyknight, nemanjai, mgorny, cfe-commits

Differential Revision: https://reviews.llvm.org/D30315

Added:
    cfe/trunk/lib/Driver/Arch/
    cfe/trunk/lib/Driver/Arch/AArch64.cpp
    cfe/trunk/lib/Driver/Arch/ARM.cpp
    cfe/trunk/lib/Driver/Arch/Mips.cpp
    cfe/trunk/lib/Driver/Arch/PPC.cpp
    cfe/trunk/lib/Driver/Arch/Sparc.cpp
    cfe/trunk/lib/Driver/Arch/SystemZ.cpp
    cfe/trunk/lib/Driver/Arch/X86.cpp
Modified:
    cfe/trunk/lib/Driver/CMakeLists.txt
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/lib/Driver/Tools.h

Added: cfe/trunk/lib/Driver/Arch/AArch64.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Arch/AArch64.cpp?rev=296056&view=auto
==============================================================================
--- cfe/trunk/lib/Driver/Arch/AArch64.cpp (added)
+++ cfe/trunk/lib/Driver/Arch/AArch64.cpp Thu Feb 23 18:28:01 2017
@@ -0,0 +1,196 @@
+//===--- AArch64.cpp - AArch64 (not ARM) Helpers for Tools ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Tools.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/TargetParser.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
+/// targeting. Set \p A to the Arg corresponding to the -mcpu or -mtune
+/// arguments if they are provided, or to nullptr otherwise.
+std::string aarch64::getAArch64TargetCPU(const ArgList &Args, Arg *&A) {
+  std::string CPU;
+  // If we have -mtune or -mcpu, use that.
+  if ((A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ))) {
+    CPU = StringRef(A->getValue()).lower();
+  } else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
+    StringRef Mcpu = A->getValue();
+    CPU = Mcpu.split("+").first.lower();
+  }
+
+  // Handle CPU name is 'native'.
+  if (CPU == "native")
+    return llvm::sys::getHostCPUName();
+  else if (CPU.size())
+    return CPU;
+
+  // Make sure we pick "cyclone" if -arch is used.
+  // FIXME: Should this be picked by checking the target triple instead?
+  if (Args.getLastArg(options::OPT_arch))
+    return "cyclone";
+
+  return "generic";
+}
+
+// Decode AArch64 features from string like +[no]featureA+[no]featureB+...
+static bool DecodeAArch64Features(const Driver &D, StringRef text,
+                                  std::vector<StringRef> &Features) {
+  SmallVector<StringRef, 8> Split;
+  text.split(Split, StringRef("+"), -1, false);
+
+  for (StringRef Feature : Split) {
+    StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature);
+    if (!FeatureName.empty())
+      Features.push_back(FeatureName);
+    else if (Feature == "neon" || Feature == "noneon")
+      D.Diag(clang::diag::err_drv_no_neon_modifier);
+    else
+      return false;
+  }
+  return true;
+}
+
+// Check if the CPU name and feature modifiers in -mcpu are legal. If yes,
+// decode CPU and feature.
+static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
+                              std::vector<StringRef> &Features) {
+  std::pair<StringRef, StringRef> Split = Mcpu.split("+");
+  CPU = Split.first;
+
+  if (CPU == "generic") {
+    Features.push_back("+neon");
+  } else {
+    unsigned ArchKind = llvm::AArch64::parseCPUArch(CPU);
+    if (!llvm::AArch64::getArchFeatures(ArchKind, Features))
+      return false;
+
+    unsigned Extension = llvm::AArch64::getDefaultExtensions(CPU, ArchKind);
+    if (!llvm::AArch64::getExtensionFeatures(Extension, Features))
+      return false;
+   }
+
+  if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))
+    return false;
+
+  return true;
+}
+
+static bool
+getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
+                                const ArgList &Args,
+                                std::vector<StringRef> &Features) {
+  std::string MarchLowerCase = March.lower();
+  std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");
+
+  unsigned ArchKind = llvm::AArch64::parseArch(Split.first);
+  if (ArchKind == static_cast<unsigned>(llvm::AArch64::ArchKind::AK_INVALID) ||
+      !llvm::AArch64::getArchFeatures(ArchKind, Features) ||
+      (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features)))
+    return false;
+
+  return true;
+}
+
+static bool
+getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
+                               const ArgList &Args,
+                               std::vector<StringRef> &Features) {
+  StringRef CPU;
+  std::string McpuLowerCase = Mcpu.lower();
+  if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Features))
+    return false;
+
+  return true;
+}
+
+static bool
+getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
+                                     const ArgList &Args,
+                                     std::vector<StringRef> &Features) {
+  std::string MtuneLowerCase = Mtune.lower();
+  // Handle CPU name is 'native'.
+  if (MtuneLowerCase == "native")
+    MtuneLowerCase = llvm::sys::getHostCPUName();
+  if (MtuneLowerCase == "cyclone") {
+    Features.push_back("+zcm");
+    Features.push_back("+zcz");
+  }
+  return true;
+}
+
+static bool
+getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
+                                    const ArgList &Args,
+                                    std::vector<StringRef> &Features) {
+  StringRef CPU;
+  std::vector<StringRef> DecodedFeature;
+  std::string McpuLowerCase = Mcpu.lower();
+  if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, DecodedFeature))
+    return false;
+
+  return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);
+}
+
+void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
+                                       std::vector<StringRef> &Features) {
+  Arg *A;
+  bool success = true;
+  // Enable NEON by default.
+  Features.push_back("+neon");
+  if ((A = Args.getLastArg(options::OPT_march_EQ)))
+    success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features);
+  else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
+    success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
+  else if (Args.hasArg(options::OPT_arch))
+    success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args, A),
+                                             Args, Features);
+
+  if (success && (A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)))
+    success =
+        getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features);
+  else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
+    success =
+        getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
+  else if (success && Args.hasArg(options::OPT_arch))
+    success = getAArch64MicroArchFeaturesFromMcpu(
+        D, getAArch64TargetCPU(Args, A), Args, Features);
+
+  if (!success)
+    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
+
+  if (Args.getLastArg(options::OPT_mgeneral_regs_only)) {
+    Features.push_back("-fp-armv8");
+    Features.push_back("-crypto");
+    Features.push_back("-neon");
+  }
+
+  // En/disable crc
+  if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
+    if (A->getOption().matches(options::OPT_mcrc))
+      Features.push_back("+crc");
+    else
+      Features.push_back("-crc");
+  }
+
+  if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
+                               options::OPT_munaligned_access))
+    if (A->getOption().matches(options::OPT_mno_unaligned_access))
+      Features.push_back("+strict-align");
+
+  if (Args.hasArg(options::OPT_ffixed_x18))
+    Features.push_back("+reserve-x18");
+}

Added: cfe/trunk/lib/Driver/Arch/ARM.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Arch/ARM.cpp?rev=296056&view=auto
==============================================================================
--- cfe/trunk/lib/Driver/Arch/ARM.cpp (added)
+++ cfe/trunk/lib/Driver/Arch/ARM.cpp Thu Feb 23 18:28:01 2017
@@ -0,0 +1,445 @@
+//===--- ARM.cpp - ARM (not AArch64) Helpers for Tools ----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Tools.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/TargetParser.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+// Get SubArch (vN).
+int arm::getARMSubArchVersionNumber(const llvm::Triple &Triple) {
+  llvm::StringRef Arch = Triple.getArchName();
+  return llvm::ARM::parseArchVersion(Arch);
+}
+
+// True if M-profile.
+bool arm::isARMMProfile(const llvm::Triple &Triple) {
+  llvm::StringRef Arch = Triple.getArchName();
+  unsigned Profile = llvm::ARM::parseArchProfile(Arch);
+  return Profile == llvm::ARM::PK_M;
+}
+
+// Get Arch/CPU from args.
+void arm::getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch,
+                                llvm::StringRef &CPU, bool FromAs) {
+  if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ))
+    CPU = A->getValue();
+  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+    Arch = A->getValue();
+  if (!FromAs)
+    return;
+
+  for (const Arg *A :
+       Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
+    StringRef Value = A->getValue();
+    if (Value.startswith("-mcpu="))
+      CPU = Value.substr(6);
+    if (Value.startswith("-march="))
+      Arch = Value.substr(7);
+  }
+}
+
+// Handle -mhwdiv=.
+// FIXME: Use ARMTargetParser.
+static void getARMHWDivFeatures(const Driver &D, const Arg *A,
+                                const ArgList &Args, StringRef HWDiv,
+                                std::vector<StringRef> &Features) {
+  unsigned HWDivID = llvm::ARM::parseHWDiv(HWDiv);
+  if (!llvm::ARM::getHWDivFeatures(HWDivID, Features))
+    D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+}
+
+// Handle -mfpu=.
+static void getARMFPUFeatures(const Driver &D, const Arg *A,
+                              const ArgList &Args, StringRef FPU,
+                              std::vector<StringRef> &Features) {
+  unsigned FPUID = llvm::ARM::parseFPU(FPU);
+  if (!llvm::ARM::getFPUFeatures(FPUID, Features))
+    D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+}
+
+// Decode ARM features from string like +[no]featureA+[no]featureB+...
+static bool DecodeARMFeatures(const Driver &D, StringRef text,
+                              std::vector<StringRef> &Features) {
+  SmallVector<StringRef, 8> Split;
+  text.split(Split, StringRef("+"), -1, false);
+
+  for (StringRef Feature : Split) {
+    StringRef FeatureName = llvm::ARM::getArchExtFeature(Feature);
+    if (!FeatureName.empty())
+      Features.push_back(FeatureName);
+    else
+      return false;
+  }
+  return true;
+}
+
+// Check if -march is valid by checking if it can be canonicalised and parsed.
+// getARMArch is used here instead of just checking the -march value in order
+// to handle -march=native correctly.
+static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,
+                             llvm::StringRef ArchName,
+                             std::vector<StringRef> &Features,
+                             const llvm::Triple &Triple) {
+  std::pair<StringRef, StringRef> Split = ArchName.split("+");
+
+  std::string MArch = arm::getARMArch(ArchName, Triple);
+  if (llvm::ARM::parseArch(MArch) == llvm::ARM::AK_INVALID ||
+      (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features)))
+    D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+}
+
+// Check -mcpu=. Needs ArchName to handle -mcpu=generic.
+static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args,
+                            llvm::StringRef CPUName, llvm::StringRef ArchName,
+                            std::vector<StringRef> &Features,
+                            const llvm::Triple &Triple) {
+  std::pair<StringRef, StringRef> Split = CPUName.split("+");
+
+  std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);
+  if (arm::getLLVMArchSuffixForARM(CPU, ArchName, Triple).empty() ||
+      (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features)))
+    D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+}
+
+bool arm::useAAPCSForMachO(const llvm::Triple &T) {
+  // The backend is hardwired to assume AAPCS for M-class processors, ensure
+  // the frontend matches that.
+  return T.getEnvironment() == llvm::Triple::EABI ||
+         T.getOS() == llvm::Triple::UnknownOS || isARMMProfile(T);
+}
+
+// Select the float ABI as determined by -msoft-float, -mhard-float, and
+// -mfloat-abi=.
+arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
+  const Driver &D = TC.getDriver();
+  const llvm::Triple &Triple = TC.getEffectiveTriple();
+  auto SubArch = getARMSubArchVersionNumber(Triple);
+  arm::FloatABI ABI = FloatABI::Invalid;
+  if (Arg *A =
+          Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
+                          options::OPT_mfloat_abi_EQ)) {
+    if (A->getOption().matches(options::OPT_msoft_float)) {
+      ABI = FloatABI::Soft;
+    } else if (A->getOption().matches(options::OPT_mhard_float)) {
+      ABI = FloatABI::Hard;
+    } else {
+      ABI = llvm::StringSwitch<arm::FloatABI>(A->getValue())
+                .Case("soft", FloatABI::Soft)
+                .Case("softfp", FloatABI::SoftFP)
+                .Case("hard", FloatABI::Hard)
+                .Default(FloatABI::Invalid);
+      if (ABI == FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
+        D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
+        ABI = FloatABI::Soft;
+      }
+    }
+
+    // It is incorrect to select hard float ABI on MachO platforms if the ABI is
+    // "apcs-gnu".
+    if (Triple.isOSBinFormatMachO() && !useAAPCSForMachO(Triple) &&
+        ABI == FloatABI::Hard) {
+      D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getAsString(Args)
+                                                       << Triple.getArchName();
+    }
+  }
+
+  // If unspecified, choose the default based on the platform.
+  if (ABI == FloatABI::Invalid) {
+    switch (Triple.getOS()) {
+    case llvm::Triple::Darwin:
+    case llvm::Triple::MacOSX:
+    case llvm::Triple::IOS:
+    case llvm::Triple::TvOS: {
+      // Darwin defaults to "softfp" for v6 and v7.
+      ABI = (SubArch == 6 || SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft;
+      ABI = Triple.isWatchABI() ? FloatABI::Hard : ABI;
+      break;
+    }
+    case llvm::Triple::WatchOS:
+      ABI = FloatABI::Hard;
+      break;
+
+    // FIXME: this is invalid for WindowsCE
+    case llvm::Triple::Win32:
+      ABI = FloatABI::Hard;
+      break;
+
+    case llvm::Triple::FreeBSD:
+      switch (Triple.getEnvironment()) {
+      case llvm::Triple::GNUEABIHF:
+        ABI = FloatABI::Hard;
+        break;
+      default:
+        // FreeBSD defaults to soft float
+        ABI = FloatABI::Soft;
+        break;
+      }
+      break;
+
+    default:
+      switch (Triple.getEnvironment()) {
+      case llvm::Triple::GNUEABIHF:
+      case llvm::Triple::MuslEABIHF:
+      case llvm::Triple::EABIHF:
+        ABI = FloatABI::Hard;
+        break;
+      case llvm::Triple::GNUEABI:
+      case llvm::Triple::MuslEABI:
+      case llvm::Triple::EABI:
+        // EABI is always AAPCS, and if it was not marked 'hard', it's softfp
+        ABI = FloatABI::SoftFP;
+        break;
+      case llvm::Triple::Android:
+        ABI = (SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft;
+        break;
+      default:
+        // Assume "soft", but warn the user we are guessing.
+        if (Triple.isOSBinFormatMachO() &&
+            Triple.getSubArch() == llvm::Triple::ARMSubArch_v7em)
+          ABI = FloatABI::Hard;
+        else
+          ABI = FloatABI::Soft;
+
+        if (Triple.getOS() != llvm::Triple::UnknownOS ||
+            !Triple.isOSBinFormatMachO())
+          D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
+        break;
+      }
+    }
+  }
+
+  assert(ABI != FloatABI::Invalid && "must select an ABI");
+  return ABI;
+}
+
+void arm::getARMTargetFeatures(const ToolChain &TC,
+                               const llvm::Triple &Triple,
+                               const ArgList &Args,
+                               ArgStringList &CmdArgs,
+                               std::vector<StringRef> &Features,
+                               bool ForAS) {
+  const Driver &D = TC.getDriver();
+
+  bool KernelOrKext =
+      Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
+  arm::FloatABI ABI = arm::getARMFloatABI(TC, Args);
+  const Arg *WaCPU = nullptr, *WaFPU = nullptr;
+  const Arg *WaHDiv = nullptr, *WaArch = nullptr;
+
+  if (!ForAS) {
+    // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
+    // yet (it uses the -mfloat-abi and -msoft-float options), and it is
+    // stripped out by the ARM target. We should probably pass this a new
+    // -target-option, which is handled by the -cc1/-cc1as invocation.
+    //
+    // FIXME2:  For consistency, it would be ideal if we set up the target
+    // machine state the same when using the frontend or the assembler. We don't
+    // currently do that for the assembler, we pass the options directly to the
+    // backend and never even instantiate the frontend TargetInfo. If we did,
+    // and used its handleTargetFeatures hook, then we could ensure the
+    // assembler and the frontend behave the same.
+
+    // Use software floating point operations?
+    if (ABI == arm::FloatABI::Soft)
+      Features.push_back("+soft-float");
+
+    // Use software floating point argument passing?
+    if (ABI != arm::FloatABI::Hard)
+      Features.push_back("+soft-float-abi");
+  } else {
+    // Here, we make sure that -Wa,-mfpu/cpu/arch/hwdiv will be passed down
+    // to the assembler correctly.
+    for (const Arg *A :
+         Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
+      StringRef Value = A->getValue();
+      if (Value.startswith("-mfpu=")) {
+        WaFPU = A;
+      } else if (Value.startswith("-mcpu=")) {
+        WaCPU = A;
+      } else if (Value.startswith("-mhwdiv=")) {
+        WaHDiv = A;
+      } else if (Value.startswith("-march=")) {
+        WaArch = A;
+      }
+    }
+  }
+
+  // Check -march. ClangAs gives preference to -Wa,-march=.
+  const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ);
+  StringRef ArchName;
+  if (WaArch) {
+    if (ArchArg)
+      D.Diag(clang::diag::warn_drv_unused_argument)
+          << ArchArg->getAsString(Args);
+    ArchName = StringRef(WaArch->getValue()).substr(7);
+    checkARMArchName(D, WaArch, Args, ArchName, Features, Triple);
+    // FIXME: Set Arch.
+    D.Diag(clang::diag::warn_drv_unused_argument) << WaArch->getAsString(Args);
+  } else if (ArchArg) {
+    ArchName = ArchArg->getValue();
+    checkARMArchName(D, ArchArg, Args, ArchName, Features, Triple);
+  }
+
+  // Check -mcpu. ClangAs gives preference to -Wa,-mcpu=.
+  const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);
+  StringRef CPUName;
+  if (WaCPU) {
+    if (CPUArg)
+      D.Diag(clang::diag::warn_drv_unused_argument)
+          << CPUArg->getAsString(Args);
+    CPUName = StringRef(WaCPU->getValue()).substr(6);
+    checkARMCPUName(D, WaCPU, Args, CPUName, ArchName, Features, Triple);
+  } else if (CPUArg) {
+    CPUName = CPUArg->getValue();
+    checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, Features, Triple);
+  }
+
+  // Add CPU features for generic CPUs
+  if (CPUName == "native") {
+    llvm::StringMap<bool> HostFeatures;
+    if (llvm::sys::getHostCPUFeatures(HostFeatures))
+      for (auto &F : HostFeatures)
+        Features.push_back(
+            Args.MakeArgString((F.second ? "+" : "-") + F.first()));
+  }
+
+  // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=.
+  const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ);
+  if (WaFPU) {
+    if (FPUArg)
+      D.Diag(clang::diag::warn_drv_unused_argument)
+          << FPUArg->getAsString(Args);
+    getARMFPUFeatures(D, WaFPU, Args, StringRef(WaFPU->getValue()).substr(6),
+                      Features);
+  } else if (FPUArg) {
+    getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
+  }
+
+  // Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=.
+  const Arg *HDivArg = Args.getLastArg(options::OPT_mhwdiv_EQ);
+  if (WaHDiv) {
+    if (HDivArg)
+      D.Diag(clang::diag::warn_drv_unused_argument)
+          << HDivArg->getAsString(Args);
+    getARMHWDivFeatures(D, WaHDiv, Args,
+                        StringRef(WaHDiv->getValue()).substr(8), Features);
+  } else if (HDivArg)
+    getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features);
+
+  // Setting -msoft-float effectively disables NEON because of the GCC
+  // implementation, although the same isn't true of VFP or VFP3.
+  if (ABI == arm::FloatABI::Soft) {
+    Features.push_back("-neon");
+    // Also need to explicitly disable features which imply NEON.
+    Features.push_back("-crypto");
+  }
+
+  // En/disable crc code generation.
+  if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
+    if (A->getOption().matches(options::OPT_mcrc))
+      Features.push_back("+crc");
+    else
+      Features.push_back("-crc");
+  }
+
+  // Look for the last occurrence of -mlong-calls or -mno-long-calls. If
+  // neither options are specified, see if we are compiling for kernel/kext and
+  // decide whether to pass "+long-calls" based on the OS and its version.
+  if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
+                               options::OPT_mno_long_calls)) {
+    if (A->getOption().matches(options::OPT_mlong_calls))
+      Features.push_back("+long-calls");
+  } else if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)) &&
+             !Triple.isWatchOS()) {
+      Features.push_back("+long-calls");
+  }
+
+  // Generate execute-only output (no data access to code sections).
+  // Supported only on ARMv6T2 and ARMv7 and above.
+  // Cannot be combined with -mno-movt or -mlong-calls
+  if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) {
+    if (A->getOption().matches(options::OPT_mexecute_only)) {
+      if (getARMSubArchVersionNumber(Triple) < 7 &&
+          llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::AK_ARMV6T2)
+            D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName();
+      else if (Arg *B = Args.getLastArg(options::OPT_mno_movt))
+        D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
+      // Long calls create constant pool entries and have not yet been fixed up
+      // to play nicely with execute-only. Hence, they cannot be used in
+      // execute-only code for now
+      else if (Arg *B = Args.getLastArg(options::OPT_mlong_calls, options::OPT_mno_long_calls)) {
+        if (B->getOption().matches(options::OPT_mlong_calls))
+          D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
+      }
+
+      CmdArgs.push_back("-backend-option");
+      CmdArgs.push_back("-arm-execute-only");
+    }
+  }
+
+  // Kernel code has more strict alignment requirements.
+  if (KernelOrKext)
+    Features.push_back("+strict-align");
+  else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
+                                    options::OPT_munaligned_access)) {
+    if (A->getOption().matches(options::OPT_munaligned_access)) {
+      // No v6M core supports unaligned memory access (v6M ARM ARM A3.2).
+      if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
+        D.Diag(diag::err_target_unsupported_unaligned) << "v6m";
+      // v8M Baseline follows on from v6M, so doesn't support unaligned memory
+      // access either.
+      else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline)
+        D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base";
+    } else
+      Features.push_back("+strict-align");
+  } else {
+    // Assume pre-ARMv6 doesn't support unaligned accesses.
+    //
+    // ARMv6 may or may not support unaligned accesses depending on the
+    // SCTLR.U bit, which is architecture-specific. We assume ARMv6
+    // Darwin and NetBSD targets support unaligned accesses, and others don't.
+    //
+    // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit
+    // which raises an alignment fault on unaligned accesses. Linux
+    // defaults this bit to 0 and handles it as a system-wide (not
+    // per-process) setting. It is therefore safe to assume that ARMv7+
+    // Linux targets support unaligned accesses. The same goes for NaCl.
+    //
+    // The above behavior is consistent with GCC.
+    int VersionNum = getARMSubArchVersionNumber(Triple);
+    if (Triple.isOSDarwin() || Triple.isOSNetBSD()) {
+      if (VersionNum < 6 ||
+          Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
+        Features.push_back("+strict-align");
+    } else if (Triple.isOSLinux() || Triple.isOSNaCl()) {
+      if (VersionNum < 7)
+        Features.push_back("+strict-align");
+    } else
+      Features.push_back("+strict-align");
+  }
+
+  // llvm does not support reserving registers in general. There is support
+  // for reserving r9 on ARM though (defined as a platform-specific register
+  // in ARM EABI).
+  if (Args.hasArg(options::OPT_ffixed_r9))
+    Features.push_back("+reserve-r9");
+
+  // The kext linker doesn't know how to deal with movw/movt.
+  if (KernelOrKext || Args.hasArg(options::OPT_mno_movt))
+    Features.push_back("+no-movt");
+}

Added: cfe/trunk/lib/Driver/Arch/Mips.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Arch/Mips.cpp?rev=296056&view=auto
==============================================================================
--- cfe/trunk/lib/Driver/Arch/Mips.cpp (added)
+++ cfe/trunk/lib/Driver/Arch/Mips.cpp Thu Feb 23 18:28:01 2017
@@ -0,0 +1,397 @@
+//===--- Mips.cpp - Tools Implementations -----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Tools.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/ArgList.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+// Get CPU and ABI names. They are not independent
+// so we have to calculate them together.
+void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
+                            StringRef &CPUName, StringRef &ABIName) {
+  const char *DefMips32CPU = "mips32r2";
+  const char *DefMips64CPU = "mips64r2";
+
+  // MIPS32r6 is the default for mips(el)?-img-linux-gnu and MIPS64r6 is the
+  // default for mips64(el)?-img-linux-gnu.
+  if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies &&
+      Triple.getEnvironment() == llvm::Triple::GNU) {
+    DefMips32CPU = "mips32r6";
+    DefMips64CPU = "mips64r6";
+  }
+
+  // MIPS64r6 is the default for Android MIPS64 (mips64el-linux-android).
+  if (Triple.isAndroid()) {
+    DefMips32CPU = "mips32";
+    DefMips64CPU = "mips64r6";
+  }
+
+  // MIPS3 is the default for mips64*-unknown-openbsd.
+  if (Triple.getOS() == llvm::Triple::OpenBSD)
+    DefMips64CPU = "mips3";
+
+  if (Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ,
+                               options::OPT_mcpu_EQ))
+    CPUName = A->getValue();
+
+  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
+    ABIName = A->getValue();
+    // Convert a GNU style Mips ABI name to the name
+    // accepted by LLVM Mips backend.
+    ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName)
+                  .Case("32", "o32")
+                  .Case("64", "n64")
+                  .Default(ABIName);
+  }
+
+  // Setup default CPU and ABI names.
+  if (CPUName.empty() && ABIName.empty()) {
+    switch (Triple.getArch()) {
+    default:
+      llvm_unreachable("Unexpected triple arch name");
+    case llvm::Triple::mips:
+    case llvm::Triple::mipsel:
+      CPUName = DefMips32CPU;
+      break;
+    case llvm::Triple::mips64:
+    case llvm::Triple::mips64el:
+      CPUName = DefMips64CPU;
+      break;
+    }
+  }
+
+  if (ABIName.empty() &&
+      (Triple.getVendor() == llvm::Triple::MipsTechnologies ||
+       Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) {
+    ABIName = llvm::StringSwitch<const char *>(CPUName)
+                  .Case("mips1", "o32")
+                  .Case("mips2", "o32")
+                  .Case("mips3", "n64")
+                  .Case("mips4", "n64")
+                  .Case("mips5", "n64")
+                  .Case("mips32", "o32")
+                  .Case("mips32r2", "o32")
+                  .Case("mips32r3", "o32")
+                  .Case("mips32r5", "o32")
+                  .Case("mips32r6", "o32")
+                  .Case("mips64", "n64")
+                  .Case("mips64r2", "n64")
+                  .Case("mips64r3", "n64")
+                  .Case("mips64r5", "n64")
+                  .Case("mips64r6", "n64")
+                  .Case("octeon", "n64")
+                  .Case("p5600", "o32")
+                  .Default("");
+  }
+
+  if (ABIName.empty()) {
+    // Deduce ABI name from the target triple.
+    if (Triple.getArch() == llvm::Triple::mips ||
+        Triple.getArch() == llvm::Triple::mipsel)
+      ABIName = "o32";
+    else
+      ABIName = "n64";
+  }
+
+  if (CPUName.empty()) {
+    // Deduce CPU name from ABI name.
+    CPUName = llvm::StringSwitch<const char *>(ABIName)
+                  .Case("o32", DefMips32CPU)
+                  .Cases("n32", "n64", DefMips64CPU)
+                  .Default("");
+  }
+
+  // FIXME: Warn on inconsistent use of -march and -mabi.
+}
+
+std::string mips::getMipsABILibSuffix(const ArgList &Args,
+                                      const llvm::Triple &Triple) {
+  StringRef CPUName, ABIName;
+  tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
+  return llvm::StringSwitch<std::string>(ABIName)
+      .Case("o32", "")
+      .Case("n32", "32")
+      .Case("n64", "64");
+}
+
+// Convert ABI name to the GNU tools acceptable variant.
+StringRef mips::getGnuCompatibleMipsABIName(StringRef ABI) {
+  return llvm::StringSwitch<llvm::StringRef>(ABI)
+      .Case("o32", "32")
+      .Case("n64", "64")
+      .Default(ABI);
+}
+
+// Select the MIPS float ABI as determined by -msoft-float, -mhard-float,
+// and -mfloat-abi=.
+mips::FloatABI mips::getMipsFloatABI(const Driver &D, const ArgList &Args) {
+  mips::FloatABI ABI = mips::FloatABI::Invalid;
+  if (Arg *A =
+          Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
+                          options::OPT_mfloat_abi_EQ)) {
+    if (A->getOption().matches(options::OPT_msoft_float))
+      ABI = mips::FloatABI::Soft;
+    else if (A->getOption().matches(options::OPT_mhard_float))
+      ABI = mips::FloatABI::Hard;
+    else {
+      ABI = llvm::StringSwitch<mips::FloatABI>(A->getValue())
+                .Case("soft", mips::FloatABI::Soft)
+                .Case("hard", mips::FloatABI::Hard)
+                .Default(mips::FloatABI::Invalid);
+      if (ABI == mips::FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
+        D.Diag(clang::diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
+        ABI = mips::FloatABI::Hard;
+      }
+    }
+  }
+
+  // If unspecified, choose the default based on the platform.
+  if (ABI == mips::FloatABI::Invalid) {
+    // Assume "hard", because it's a default value used by gcc.
+    // When we start to recognize specific target MIPS processors,
+    // we will be able to select the default more correctly.
+    ABI = mips::FloatABI::Hard;
+  }
+
+  assert(ABI != mips::FloatABI::Invalid && "must select an ABI");
+  return ABI;
+}
+
+void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+                                 const ArgList &Args,
+                                 std::vector<StringRef> &Features) {
+  StringRef CPUName;
+  StringRef ABIName;
+  getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
+  ABIName = getGnuCompatibleMipsABIName(ABIName);
+
+  // Historically, PIC code for MIPS was associated with -mabicalls, a.k.a
+  // SVR4 abicalls. Static code does not use SVR4 calling sequences. An ABI
+  // extension was developed by Richard Sandiford & Code Sourcery to support
+  // static code calling PIC code (CPIC). For O32 and N32 this means we have
+  // several combinations of PIC/static and abicalls. Pure static, static
+  // with the CPIC extension, and pure PIC code.
+
+  // At final link time, O32 and N32 with CPIC will have another section
+  // added to the binary which contains the stub functions to perform
+  // any fixups required for PIC code.
+
+  // For N64, the situation is more regular: code can either be static
+  // (non-abicalls) or PIC (abicalls). GCC has traditionally picked PIC code
+  // code for N64. Since Clang has already built the relocation model portion
+  // of the commandline, we pick add +noabicalls feature in the N64 static
+  // case.
+
+  // The is another case to be accounted for: -msym32, which enforces that all
+  // symbols have 32 bits in size. In this case, N64 can in theory use CPIC
+  // but it is unsupported.
+
+  // The combinations for N64 are:
+  // a) Static without abicalls and 64bit symbols.
+  // b) Static with abicalls and 32bit symbols.
+  // c) PIC with abicalls and 64bit symbols.
+
+  // For case (a) we need to add +noabicalls for N64.
+
+  bool IsN64 = ABIName == "64";
+  bool NonPIC = false;
+
+  Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
+                                    options::OPT_fpic, options::OPT_fno_pic,
+                                    options::OPT_fPIE, options::OPT_fno_PIE,
+                                    options::OPT_fpie, options::OPT_fno_pie);
+  if (LastPICArg) {
+    Option O = LastPICArg->getOption();
+    NonPIC =
+        (O.matches(options::OPT_fno_PIC) || O.matches(options::OPT_fno_pic) ||
+         O.matches(options::OPT_fno_PIE) || O.matches(options::OPT_fno_pie));
+  }
+
+  if (IsN64 && NonPIC) {
+    Features.push_back("+noabicalls");
+  } else {
+    AddTargetFeature(Args, Features, options::OPT_mno_abicalls,
+                     options::OPT_mabicalls, "noabicalls");
+  }
+
+  mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args);
+  if (FloatABI == mips::FloatABI::Soft) {
+    // FIXME: Note, this is a hack. We need to pass the selected float
+    // mode to the MipsTargetInfoBase to define appropriate macros there.
+    // Now it is the only method.
+    Features.push_back("+soft-float");
+  }
+
+  if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
+    StringRef Val = StringRef(A->getValue());
+    if (Val == "2008") {
+      if (mips::getSupportedNanEncoding(CPUName) & mips::Nan2008)
+        Features.push_back("+nan2008");
+      else {
+        Features.push_back("-nan2008");
+        D.Diag(diag::warn_target_unsupported_nan2008) << CPUName;
+      }
+    } else if (Val == "legacy") {
+      if (mips::getSupportedNanEncoding(CPUName) & mips::NanLegacy)
+        Features.push_back("-nan2008");
+      else {
+        Features.push_back("+nan2008");
+        D.Diag(diag::warn_target_unsupported_nanlegacy) << CPUName;
+      }
+    } else
+      D.Diag(diag::err_drv_unsupported_option_argument)
+          << A->getOption().getName() << Val;
+  }
+
+  AddTargetFeature(Args, Features, options::OPT_msingle_float,
+                   options::OPT_mdouble_float, "single-float");
+  AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16,
+                   "mips16");
+  AddTargetFeature(Args, Features, options::OPT_mmicromips,
+                   options::OPT_mno_micromips, "micromips");
+  AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp,
+                   "dsp");
+  AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2,
+                   "dspr2");
+  AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa,
+                   "msa");
+
+  // Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32
+  // pass -mfpxx, or if none are given and fp64a is default, pass fp64 and
+  // nooddspreg.
+  if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
+                               options::OPT_mfp64)) {
+    if (A->getOption().matches(options::OPT_mfp32))
+      Features.push_back(Args.MakeArgString("-fp64"));
+    else if (A->getOption().matches(options::OPT_mfpxx)) {
+      Features.push_back(Args.MakeArgString("+fpxx"));
+      Features.push_back(Args.MakeArgString("+nooddspreg"));
+    } else
+      Features.push_back(Args.MakeArgString("+fp64"));
+  } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) {
+    Features.push_back(Args.MakeArgString("+fpxx"));
+    Features.push_back(Args.MakeArgString("+nooddspreg"));
+  } else if (mips::isFP64ADefault(Triple, CPUName)) {
+    Features.push_back(Args.MakeArgString("+fp64"));
+    Features.push_back(Args.MakeArgString("+nooddspreg"));
+  }
+
+  AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg,
+                   options::OPT_modd_spreg, "nooddspreg");
+}
+
+mips::NanEncoding mips::getSupportedNanEncoding(StringRef &CPU) {
+  // Strictly speaking, mips32r2 and mips64r2 are NanLegacy-only since Nan2008
+  // was first introduced in Release 3. However, other compilers have
+  // traditionally allowed it for Release 2 so we should do the same.
+  return (NanEncoding)llvm::StringSwitch<int>(CPU)
+      .Case("mips1", NanLegacy)
+      .Case("mips2", NanLegacy)
+      .Case("mips3", NanLegacy)
+      .Case("mips4", NanLegacy)
+      .Case("mips5", NanLegacy)
+      .Case("mips32", NanLegacy)
+      .Case("mips32r2", NanLegacy | Nan2008)
+      .Case("mips32r3", NanLegacy | Nan2008)
+      .Case("mips32r5", NanLegacy | Nan2008)
+      .Case("mips32r6", Nan2008)
+      .Case("mips64", NanLegacy)
+      .Case("mips64r2", NanLegacy | Nan2008)
+      .Case("mips64r3", NanLegacy | Nan2008)
+      .Case("mips64r5", NanLegacy | Nan2008)
+      .Case("mips64r6", Nan2008)
+      .Default(NanLegacy);
+}
+
+bool mips::hasCompactBranches(StringRef &CPU) {
+  // mips32r6 and mips64r6 have compact branches.
+  return llvm::StringSwitch<bool>(CPU)
+      .Case("mips32r6", true)
+      .Case("mips64r6", true)
+      .Default(false);
+}
+
+bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) {
+  Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
+  return A && (A->getValue() == StringRef(Value));
+}
+
+bool mips::isUCLibc(const ArgList &Args) {
+  Arg *A = Args.getLastArg(options::OPT_m_libc_Group);
+  return A && A->getOption().matches(options::OPT_muclibc);
+}
+
+bool mips::isNaN2008(const ArgList &Args, const llvm::Triple &Triple) {
+  if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ))
+    return llvm::StringSwitch<bool>(NaNArg->getValue())
+        .Case("2008", true)
+        .Case("legacy", false)
+        .Default(false);
+
+  // NaN2008 is the default for MIPS32r6/MIPS64r6.
+  return llvm::StringSwitch<bool>(getCPUName(Args, Triple))
+      .Cases("mips32r6", "mips64r6", true)
+      .Default(false);
+
+  return false;
+}
+
+bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) {
+  if (!Triple.isAndroid())
+    return false;
+
+  // Android MIPS32R6 defaults to FP64A.
+  return llvm::StringSwitch<bool>(CPUName)
+      .Case("mips32r6", true)
+      .Default(false);
+}
+
+bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
+                         StringRef ABIName, mips::FloatABI FloatABI) {
+  if (Triple.getVendor() != llvm::Triple::ImaginationTechnologies &&
+      Triple.getVendor() != llvm::Triple::MipsTechnologies &&
+      !Triple.isAndroid())
+    return false;
+
+  if (ABIName != "32")
+    return false;
+
+  // FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is
+  // present.
+  if (FloatABI == mips::FloatABI::Soft)
+    return false;
+
+  return llvm::StringSwitch<bool>(CPUName)
+      .Cases("mips2", "mips3", "mips4", "mips5", true)
+      .Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true)
+      .Cases("mips64", "mips64r2", "mips64r3", "mips64r5", true)
+      .Default(false);
+}
+
+bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple,
+                         StringRef CPUName, StringRef ABIName,
+                         mips::FloatABI FloatABI) {
+  bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI);
+
+  // FPXX shouldn't be used if -msingle-float is present.
+  if (Arg *A = Args.getLastArg(options::OPT_msingle_float,
+                               options::OPT_mdouble_float))
+    if (A->getOption().matches(options::OPT_msingle_float))
+      UseFPXX = false;
+
+  return UseFPXX;
+}

Added: cfe/trunk/lib/Driver/Arch/PPC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Arch/PPC.cpp?rev=296056&view=auto
==============================================================================
--- cfe/trunk/lib/Driver/Arch/PPC.cpp (added)
+++ cfe/trunk/lib/Driver/Arch/PPC.cpp Thu Feb 23 18:28:01 2017
@@ -0,0 +1,134 @@
+//===--- PPC.cpp - PPC Helpers for Tools ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Tools.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/ArgList.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+/// getPPCTargetCPU - Get the (LLVM) name of the PowerPC cpu we are targeting.
+std::string ppc::getPPCTargetCPU(const ArgList &Args) {
+  if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
+    StringRef CPUName = A->getValue();
+
+    if (CPUName == "native") {
+      std::string CPU = llvm::sys::getHostCPUName();
+      if (!CPU.empty() && CPU != "generic")
+        return CPU;
+      else
+        return "";
+    }
+
+    return llvm::StringSwitch<const char *>(CPUName)
+        .Case("common", "generic")
+        .Case("440", "440")
+        .Case("440fp", "440")
+        .Case("450", "450")
+        .Case("601", "601")
+        .Case("602", "602")
+        .Case("603", "603")
+        .Case("603e", "603e")
+        .Case("603ev", "603ev")
+        .Case("604", "604")
+        .Case("604e", "604e")
+        .Case("620", "620")
+        .Case("630", "pwr3")
+        .Case("G3", "g3")
+        .Case("7400", "7400")
+        .Case("G4", "g4")
+        .Case("7450", "7450")
+        .Case("G4+", "g4+")
+        .Case("750", "750")
+        .Case("970", "970")
+        .Case("G5", "g5")
+        .Case("a2", "a2")
+        .Case("a2q", "a2q")
+        .Case("e500mc", "e500mc")
+        .Case("e5500", "e5500")
+        .Case("power3", "pwr3")
+        .Case("power4", "pwr4")
+        .Case("power5", "pwr5")
+        .Case("power5x", "pwr5x")
+        .Case("power6", "pwr6")
+        .Case("power6x", "pwr6x")
+        .Case("power7", "pwr7")
+        .Case("power8", "pwr8")
+        .Case("power9", "pwr9")
+        .Case("pwr3", "pwr3")
+        .Case("pwr4", "pwr4")
+        .Case("pwr5", "pwr5")
+        .Case("pwr5x", "pwr5x")
+        .Case("pwr6", "pwr6")
+        .Case("pwr6x", "pwr6x")
+        .Case("pwr7", "pwr7")
+        .Case("pwr8", "pwr8")
+        .Case("pwr9", "pwr9")
+        .Case("powerpc", "ppc")
+        .Case("powerpc64", "ppc64")
+        .Case("powerpc64le", "ppc64le")
+        .Default("");
+  }
+
+  return "";
+}
+
+void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+                               const ArgList &Args,
+                               std::vector<StringRef> &Features) {
+  handleTargetFeaturesGroup(Args, Features, options::OPT_m_ppc_Features_Group);
+
+  ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args);
+  if (FloatABI == ppc::FloatABI::Soft)
+    Features.push_back("-hard-float");
+
+  // Altivec is a bit weird, allow overriding of the Altivec feature here.
+  AddTargetFeature(Args, Features, options::OPT_faltivec,
+                   options::OPT_fno_altivec, "altivec");
+}
+
+ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) {
+  ppc::FloatABI ABI = ppc::FloatABI::Invalid;
+  if (Arg *A =
+          Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
+                          options::OPT_mfloat_abi_EQ)) {
+    if (A->getOption().matches(options::OPT_msoft_float))
+      ABI = ppc::FloatABI::Soft;
+    else if (A->getOption().matches(options::OPT_mhard_float))
+      ABI = ppc::FloatABI::Hard;
+    else {
+      ABI = llvm::StringSwitch<ppc::FloatABI>(A->getValue())
+                .Case("soft", ppc::FloatABI::Soft)
+                .Case("hard", ppc::FloatABI::Hard)
+                .Default(ppc::FloatABI::Invalid);
+      if (ABI == ppc::FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
+        D.Diag(clang::diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
+        ABI = ppc::FloatABI::Hard;
+      }
+    }
+  }
+
+  // If unspecified, choose the default based on the platform.
+  if (ABI == ppc::FloatABI::Invalid) {
+    ABI = ppc::FloatABI::Hard;
+  }
+
+  return ABI;
+}
+
+bool ppc::hasPPCAbiArg(const ArgList &Args, const char *Value) {
+  Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
+  return A && (A->getValue() == StringRef(Value));
+}

Added: cfe/trunk/lib/Driver/Arch/Sparc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Arch/Sparc.cpp?rev=296056&view=auto
==============================================================================
--- cfe/trunk/lib/Driver/Arch/Sparc.cpp (added)
+++ cfe/trunk/lib/Driver/Arch/Sparc.cpp Thu Feb 23 18:28:01 2017
@@ -0,0 +1,100 @@
+//===--- Sparc.cpp - Tools Implementations ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Tools.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/ArgList.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+const char *sparc::getSparcAsmModeForCPU(StringRef Name,
+                                         const llvm::Triple &Triple) {
+  if (Triple.getArch() == llvm::Triple::sparcv9) {
+    return llvm::StringSwitch<const char *>(Name)
+        .Case("niagara", "-Av9b")
+        .Case("niagara2", "-Av9b")
+        .Case("niagara3", "-Av9d")
+        .Case("niagara4", "-Av9d")
+        .Default("-Av9");
+  } else {
+    return llvm::StringSwitch<const char *>(Name)
+        .Case("v8", "-Av8")
+        .Case("supersparc", "-Av8")
+        .Case("sparclite", "-Asparclite")
+        .Case("f934", "-Asparclite")
+        .Case("hypersparc", "-Av8")
+        .Case("sparclite86x", "-Asparclite")
+        .Case("sparclet", "-Asparclet")
+        .Case("tsc701", "-Asparclet")
+        .Case("v9", "-Av8plus")
+        .Case("ultrasparc", "-Av8plus")
+        .Case("ultrasparc3", "-Av8plus")
+        .Case("niagara", "-Av8plusb")
+        .Case("niagara2", "-Av8plusb")
+        .Case("niagara3", "-Av8plusd")
+        .Case("niagara4", "-Av8plusd")
+        .Case("leon2", "-Av8")
+        .Case("at697e", "-Av8")
+        .Case("at697f", "-Av8")
+        .Case("leon3", "-Av8")
+        .Case("ut699", "-Av8")
+        .Case("gr712rc", "-Av8")
+        .Case("leon4", "-Av8")
+        .Case("gr740", "-Av8")
+        .Default("-Av8");
+  }
+}
+
+sparc::FloatABI sparc::getSparcFloatABI(const Driver &D,
+                                        const ArgList &Args) {
+  sparc::FloatABI ABI = sparc::FloatABI::Invalid;
+  if (Arg *A = Args.getLastArg(clang::driver::options::OPT_msoft_float,
+                               options::OPT_mhard_float,
+                               options::OPT_mfloat_abi_EQ)) {
+    if (A->getOption().matches(clang::driver::options::OPT_msoft_float))
+      ABI = sparc::FloatABI::Soft;
+    else if (A->getOption().matches(options::OPT_mhard_float))
+      ABI = sparc::FloatABI::Hard;
+    else {
+      ABI = llvm::StringSwitch<sparc::FloatABI>(A->getValue())
+                .Case("soft", sparc::FloatABI::Soft)
+                .Case("hard", sparc::FloatABI::Hard)
+                .Default(sparc::FloatABI::Invalid);
+      if (ABI == sparc::FloatABI::Invalid &&
+          !StringRef(A->getValue()).empty()) {
+        D.Diag(clang::diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
+        ABI = sparc::FloatABI::Hard;
+      }
+    }
+  }
+
+  // If unspecified, choose the default based on the platform.
+  // Only the hard-float ABI on Sparc is standardized, and it is the
+  // default. GCC also supports a nonstandard soft-float ABI mode, also
+  // implemented in LLVM. However as this is not standard we set the default
+  // to be hard-float.
+  if (ABI == sparc::FloatABI::Invalid) {
+    ABI = sparc::FloatABI::Hard;
+  }
+
+  return ABI;
+}
+
+void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
+                                   std::vector<StringRef> &Features) {
+  sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args);
+  if (FloatABI == sparc::FloatABI::Soft)
+    Features.push_back("+soft-float");
+}

Added: cfe/trunk/lib/Driver/Arch/SystemZ.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Arch/SystemZ.cpp?rev=296056&view=auto
==============================================================================
--- cfe/trunk/lib/Driver/Arch/SystemZ.cpp (added)
+++ cfe/trunk/lib/Driver/Arch/SystemZ.cpp Thu Feb 23 18:28:01 2017
@@ -0,0 +1,41 @@
+//===--- SystemZ.cpp - SystemZ Helpers for Tools ----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Tools.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Option/ArgList.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+const char *systemz::getSystemZTargetCPU(const ArgList &Args) {
+  if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ))
+    return A->getValue();
+  return "z10";
+}
+
+void systemz::getSystemZTargetFeatures(const ArgList &Args,
+                                       std::vector<StringRef> &Features) {
+  // -m(no-)htm overrides use of the transactional-execution facility.
+  if (Arg *A = Args.getLastArg(options::OPT_mhtm, options::OPT_mno_htm)) {
+    if (A->getOption().matches(options::OPT_mhtm))
+      Features.push_back("+transactional-execution");
+    else
+      Features.push_back("-transactional-execution");
+  }
+  // -m(no-)vx overrides use of the vector facility.
+  if (Arg *A = Args.getLastArg(options::OPT_mvx, options::OPT_mno_vx)) {
+    if (A->getOption().matches(options::OPT_mvx))
+      Features.push_back("+vector");
+    else
+      Features.push_back("-vector");
+  }
+}

Added: cfe/trunk/lib/Driver/Arch/X86.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Arch/X86.cpp?rev=296056&view=auto
==============================================================================
--- cfe/trunk/lib/Driver/Arch/X86.cpp (added)
+++ cfe/trunk/lib/Driver/Arch/X86.cpp Thu Feb 23 18:28:01 2017
@@ -0,0 +1,173 @@
+//===--- X86.cpp - X86 Helpers for Tools ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Tools.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/ArgList.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+const char *x86::getX86TargetCPU(const ArgList &Args,
+                                 const llvm::Triple &Triple) {
+  if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) {
+    if (StringRef(A->getValue()) != "native") {
+      if (Triple.isOSDarwin() && Triple.getArchName() == "x86_64h")
+        return "core-avx2";
+
+      return A->getValue();
+    }
+
+    // FIXME: Reject attempts to use -march=native unless the target matches
+    // the host.
+    //
+    // FIXME: We should also incorporate the detected target features for use
+    // with -native.
+    std::string CPU = llvm::sys::getHostCPUName();
+    if (!CPU.empty() && CPU != "generic")
+      return Args.MakeArgString(CPU);
+  }
+
+  if (const Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
+    // Mapping built by referring to X86TargetInfo::getDefaultFeatures().
+    StringRef Arch = A->getValue();
+    const char *CPU;
+    if (Triple.getArch() == llvm::Triple::x86) {
+      CPU = llvm::StringSwitch<const char *>(Arch)
+                .Case("IA32", "i386")
+                .Case("SSE", "pentium3")
+                .Case("SSE2", "pentium4")
+                .Case("AVX", "sandybridge")
+                .Case("AVX2", "haswell")
+                .Default(nullptr);
+    } else {
+      CPU = llvm::StringSwitch<const char *>(Arch)
+                .Case("AVX", "sandybridge")
+                .Case("AVX2", "haswell")
+                .Default(nullptr);
+    }
+    if (CPU)
+      return CPU;
+  }
+
+  // Select the default CPU if none was given (or detection failed).
+
+  if (Triple.getArch() != llvm::Triple::x86_64 &&
+      Triple.getArch() != llvm::Triple::x86)
+    return nullptr; // This routine is only handling x86 targets.
+
+  bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64;
+
+  // FIXME: Need target hooks.
+  if (Triple.isOSDarwin()) {
+    if (Triple.getArchName() == "x86_64h")
+      return "core-avx2";
+    // macosx10.12 drops support for all pre-Penryn Macs.
+    // Simulators can still run on 10.11 though, like Xcode.
+    if (Triple.isMacOSX() && !Triple.isOSVersionLT(10, 12))
+      return "penryn";
+    // The oldest x86_64 Macs have core2/Merom; the oldest x86 Macs have Yonah.
+    return Is64Bit ? "core2" : "yonah";
+  }
+
+  // Set up default CPU name for PS4 compilers.
+  if (Triple.isPS4CPU())
+    return "btver2";
+
+  // On Android use targets compatible with gcc
+  if (Triple.isAndroid())
+    return Is64Bit ? "x86-64" : "i686";
+
+  // Everything else goes to x86-64 in 64-bit mode.
+  if (Is64Bit)
+    return "x86-64";
+
+  switch (Triple.getOS()) {
+  case llvm::Triple::FreeBSD:
+  case llvm::Triple::NetBSD:
+  case llvm::Triple::OpenBSD:
+    return "i486";
+  case llvm::Triple::Haiku:
+    return "i586";
+  case llvm::Triple::Bitrig:
+    return "i686";
+  default:
+    // Fallback to p4.
+    return "pentium4";
+  }
+}
+
+void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
+                               const ArgList &Args,
+                               std::vector<StringRef> &Features) {
+  // If -march=native, autodetect the feature list.
+  if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) {
+    if (StringRef(A->getValue()) == "native") {
+      llvm::StringMap<bool> HostFeatures;
+      if (llvm::sys::getHostCPUFeatures(HostFeatures))
+        for (auto &F : HostFeatures)
+          Features.push_back(
+              Args.MakeArgString((F.second ? "+" : "-") + F.first()));
+    }
+  }
+
+  if (Triple.getArchName() == "x86_64h") {
+    // x86_64h implies quite a few of the more modern subtarget features
+    // for Haswell class CPUs, but not all of them. Opt-out of a few.
+    Features.push_back("-rdrnd");
+    Features.push_back("-aes");
+    Features.push_back("-pclmul");
+    Features.push_back("-rtm");
+    Features.push_back("-hle");
+    Features.push_back("-fsgsbase");
+  }
+
+  const llvm::Triple::ArchType ArchType = Triple.getArch();
+  // Add features to be compatible with gcc for Android.
+  if (Triple.isAndroid()) {
+    if (ArchType == llvm::Triple::x86_64) {
+      Features.push_back("+sse4.2");
+      Features.push_back("+popcnt");
+    } else
+      Features.push_back("+ssse3");
+  }
+
+  // Set features according to the -arch flag on MSVC.
+  if (Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
+    StringRef Arch = A->getValue();
+    bool ArchUsed = false;
+    // First, look for flags that are shared in x86 and x86-64.
+    if (ArchType == llvm::Triple::x86_64 || ArchType == llvm::Triple::x86) {
+      if (Arch == "AVX" || Arch == "AVX2") {
+        ArchUsed = true;
+        Features.push_back(Args.MakeArgString("+" + Arch.lower()));
+      }
+    }
+    // Then, look for x86-specific flags.
+    if (ArchType == llvm::Triple::x86) {
+      if (Arch == "IA32") {
+        ArchUsed = true;
+      } else if (Arch == "SSE" || Arch == "SSE2") {
+        ArchUsed = true;
+        Features.push_back(Args.MakeArgString("+" + Arch.lower()));
+      }
+    }
+    if (!ArchUsed)
+      D.Diag(clang::diag::warn_drv_unused_argument) << A->getAsString(Args);
+  }
+
+  // Now add any that the user explicitly requested on the command line,
+  // which may override the defaults.
+  handleTargetFeaturesGroup(Args, Features, options::OPT_m_x86_Features_Group);
+}

Modified: cfe/trunk/lib/Driver/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/CMakeLists.txt?rev=296056&r1=296055&r2=296056&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/CMakeLists.txt (original)
+++ cfe/trunk/lib/Driver/CMakeLists.txt Thu Feb 23 18:28:01 2017
@@ -10,15 +10,22 @@ endif()
 
 add_clang_library(clangDriver
   Action.cpp
+  Arch/AArch64.cpp
+  Arch/ARM.cpp
+  Arch/Mips.cpp
+  Arch/PPC.cpp
+  Arch/Sparc.cpp
+  Arch/SystemZ.cpp
+  Arch/X86.cpp
   Compilation.cpp
   CrossWindowsToolChain.cpp
   Distro.cpp
   Driver.cpp
   DriverOptions.cpp
   Job.cpp
+  MSVCToolChain.cpp
   MinGWToolChain.cpp
   Multilib.cpp
-  MSVCToolChain.cpp
   Phases.cpp
   SanitizerArgs.cpp
   Tool.cpp

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=296056&r1=296055&r2=296056&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Thu Feb 23 18:28:01 2017
@@ -53,7 +53,7 @@ using namespace clang::driver::tools;
 using namespace clang;
 using namespace llvm::opt;
 
-static void handleTargetFeaturesGroup(const ArgList &Args,
+void tools::handleTargetFeaturesGroup(const ArgList &Args,
                                       std::vector<StringRef> &Features,
                                       OptSpecifier Group) {
   for (const Arg *A : Args.filtered(Group)) {
@@ -71,44 +71,6 @@ static void handleTargetFeaturesGroup(co
   }
 }
 
-static const char *getSparcAsmModeForCPU(StringRef Name,
-                                         const llvm::Triple &Triple) {
-  if (Triple.getArch() == llvm::Triple::sparcv9) {
-    return llvm::StringSwitch<const char *>(Name)
-          .Case("niagara", "-Av9b")
-          .Case("niagara2", "-Av9b")
-          .Case("niagara3", "-Av9d")
-          .Case("niagara4", "-Av9d")
-          .Default("-Av9");
-  } else {
-    return llvm::StringSwitch<const char *>(Name)
-          .Case("v8", "-Av8")
-          .Case("supersparc", "-Av8")
-          .Case("sparclite", "-Asparclite")
-          .Case("f934", "-Asparclite")
-          .Case("hypersparc", "-Av8")
-          .Case("sparclite86x", "-Asparclite")
-          .Case("sparclet", "-Asparclet")
-          .Case("tsc701", "-Asparclet")
-          .Case("v9", "-Av8plus")
-          .Case("ultrasparc", "-Av8plus")
-          .Case("ultrasparc3", "-Av8plus")
-          .Case("niagara", "-Av8plusb")
-          .Case("niagara2", "-Av8plusb")
-          .Case("niagara3", "-Av8plusd")
-          .Case("niagara4", "-Av8plusd")
-          .Case("leon2", "-Av8")
-          .Case("at697e", "-Av8")
-          .Case("at697f", "-Av8")
-          .Case("leon3", "-Av8")
-          .Case("ut699", "-Av8")
-          .Case("gr712rc", "-Av8")
-          .Case("leon4", "-Av8")
-          .Case("gr740", "-Av8")
-          .Default("-Av8");
-  }
-}
-
 static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
   if (Arg *A = Args.getLastArg(options::OPT_C, options::OPT_CC)) {
     if (!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_P) &&
@@ -789,432 +751,6 @@ static bool isNoCommonDefault(const llvm
   }
 }
 
-// ARM tools start.
-
-// Get SubArch (vN).
-static int getARMSubArchVersionNumber(const llvm::Triple &Triple) {
-  llvm::StringRef Arch = Triple.getArchName();
-  return llvm::ARM::parseArchVersion(Arch);
-}
-
-// True if M-profile.
-static bool isARMMProfile(const llvm::Triple &Triple) {
-  llvm::StringRef Arch = Triple.getArchName();
-  unsigned Profile = llvm::ARM::parseArchProfile(Arch);
-  return Profile == llvm::ARM::PK_M;
-}
-
-// Get Arch/CPU from args.
-static void getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch,
-                                  llvm::StringRef &CPU, bool FromAs = false) {
-  if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
-    CPU = A->getValue();
-  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
-    Arch = A->getValue();
-  if (!FromAs)
-    return;
-
-  for (const Arg *A :
-       Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
-    StringRef Value = A->getValue();
-    if (Value.startswith("-mcpu="))
-      CPU = Value.substr(6);
-    if (Value.startswith("-march="))
-      Arch = Value.substr(7);
-  }
-}
-
-// Handle -mhwdiv=.
-// FIXME: Use ARMTargetParser.
-static void getARMHWDivFeatures(const Driver &D, const Arg *A,
-                                const ArgList &Args, StringRef HWDiv,
-                                std::vector<StringRef> &Features) {
-  unsigned HWDivID = llvm::ARM::parseHWDiv(HWDiv);
-  if (!llvm::ARM::getHWDivFeatures(HWDivID, Features))
-    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
-}
-
-// Handle -mfpu=.
-static void getARMFPUFeatures(const Driver &D, const Arg *A,
-                              const ArgList &Args, StringRef FPU,
-                              std::vector<StringRef> &Features) {
-  unsigned FPUID = llvm::ARM::parseFPU(FPU);
-  if (!llvm::ARM::getFPUFeatures(FPUID, Features))
-    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
-}
-
-// Decode ARM features from string like +[no]featureA+[no]featureB+...
-static bool DecodeARMFeatures(const Driver &D, StringRef text,
-                              std::vector<StringRef> &Features) {
-  SmallVector<StringRef, 8> Split;
-  text.split(Split, StringRef("+"), -1, false);
-
-  for (StringRef Feature : Split) {
-    StringRef FeatureName = llvm::ARM::getArchExtFeature(Feature);
-    if (!FeatureName.empty())
-      Features.push_back(FeatureName);
-    else
-      return false;
-  }
-  return true;
-}
-
-// Check if -march is valid by checking if it can be canonicalised and parsed.
-// getARMArch is used here instead of just checking the -march value in order
-// to handle -march=native correctly.
-static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,
-                             llvm::StringRef ArchName,
-                             std::vector<StringRef> &Features,
-                             const llvm::Triple &Triple) {
-  std::pair<StringRef, StringRef> Split = ArchName.split("+");
-
-  std::string MArch = arm::getARMArch(ArchName, Triple);
-  if (llvm::ARM::parseArch(MArch) == llvm::ARM::AK_INVALID ||
-      (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features)))
-    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
-}
-
-// Check -mcpu=. Needs ArchName to handle -mcpu=generic.
-static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args,
-                            llvm::StringRef CPUName, llvm::StringRef ArchName,
-                            std::vector<StringRef> &Features,
-                            const llvm::Triple &Triple) {
-  std::pair<StringRef, StringRef> Split = CPUName.split("+");
-
-  std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple);
-  if (arm::getLLVMArchSuffixForARM(CPU, ArchName, Triple).empty() ||
-      (Split.second.size() && !DecodeARMFeatures(D, Split.second, Features)))
-    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
-}
-
-static bool useAAPCSForMachO(const llvm::Triple &T) {
-  // The backend is hardwired to assume AAPCS for M-class processors, ensure
-  // the frontend matches that.
-  return T.getEnvironment() == llvm::Triple::EABI ||
-         T.getOS() == llvm::Triple::UnknownOS || isARMMProfile(T);
-}
-
-// Select the float ABI as determined by -msoft-float, -mhard-float, and
-// -mfloat-abi=.
-arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
-  const Driver &D = TC.getDriver();
-  const llvm::Triple &Triple = TC.getEffectiveTriple();
-  auto SubArch = getARMSubArchVersionNumber(Triple);
-  arm::FloatABI ABI = FloatABI::Invalid;
-  if (Arg *A =
-          Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
-                          options::OPT_mfloat_abi_EQ)) {
-    if (A->getOption().matches(options::OPT_msoft_float)) {
-      ABI = FloatABI::Soft;
-    } else if (A->getOption().matches(options::OPT_mhard_float)) {
-      ABI = FloatABI::Hard;
-    } else {
-      ABI = llvm::StringSwitch<arm::FloatABI>(A->getValue())
-                .Case("soft", FloatABI::Soft)
-                .Case("softfp", FloatABI::SoftFP)
-                .Case("hard", FloatABI::Hard)
-                .Default(FloatABI::Invalid);
-      if (ABI == FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
-        D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
-        ABI = FloatABI::Soft;
-      }
-    }
-
-    // It is incorrect to select hard float ABI on MachO platforms if the ABI is
-    // "apcs-gnu".
-    if (Triple.isOSBinFormatMachO() && !useAAPCSForMachO(Triple) &&
-        ABI == FloatABI::Hard) {
-      D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getAsString(Args)
-                                                       << Triple.getArchName();
-    }
-  }
-
-  // If unspecified, choose the default based on the platform.
-  if (ABI == FloatABI::Invalid) {
-    switch (Triple.getOS()) {
-    case llvm::Triple::Darwin:
-    case llvm::Triple::MacOSX:
-    case llvm::Triple::IOS:
-    case llvm::Triple::TvOS: {
-      // Darwin defaults to "softfp" for v6 and v7.
-      ABI = (SubArch == 6 || SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft;
-      ABI = Triple.isWatchABI() ? FloatABI::Hard : ABI;
-      break;
-    }
-    case llvm::Triple::WatchOS:
-      ABI = FloatABI::Hard;
-      break;
-
-    // FIXME: this is invalid for WindowsCE
-    case llvm::Triple::Win32:
-      ABI = FloatABI::Hard;
-      break;
-
-    case llvm::Triple::FreeBSD:
-      switch (Triple.getEnvironment()) {
-      case llvm::Triple::GNUEABIHF:
-        ABI = FloatABI::Hard;
-        break;
-      default:
-        // FreeBSD defaults to soft float
-        ABI = FloatABI::Soft;
-        break;
-      }
-      break;
-
-    default:
-      switch (Triple.getEnvironment()) {
-      case llvm::Triple::GNUEABIHF:
-      case llvm::Triple::MuslEABIHF:
-      case llvm::Triple::EABIHF:
-        ABI = FloatABI::Hard;
-        break;
-      case llvm::Triple::GNUEABI:
-      case llvm::Triple::MuslEABI:
-      case llvm::Triple::EABI:
-        // EABI is always AAPCS, and if it was not marked 'hard', it's softfp
-        ABI = FloatABI::SoftFP;
-        break;
-      case llvm::Triple::Android:
-        ABI = (SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft;
-        break;
-      default:
-        // Assume "soft", but warn the user we are guessing.
-        if (Triple.isOSBinFormatMachO() &&
-            Triple.getSubArch() == llvm::Triple::ARMSubArch_v7em)
-          ABI = FloatABI::Hard;
-        else
-          ABI = FloatABI::Soft;
-
-        if (Triple.getOS() != llvm::Triple::UnknownOS ||
-            !Triple.isOSBinFormatMachO())
-          D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
-        break;
-      }
-    }
-  }
-
-  assert(ABI != FloatABI::Invalid && "must select an ABI");
-  return ABI;
-}
-
-static void getARMTargetFeatures(const ToolChain &TC,
-                                 const llvm::Triple &Triple,
-                                 const ArgList &Args,
-                                 ArgStringList &CmdArgs,
-                                 std::vector<StringRef> &Features,
-                                 bool ForAS) {
-  const Driver &D = TC.getDriver();
-
-  bool KernelOrKext =
-      Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
-  arm::FloatABI ABI = arm::getARMFloatABI(TC, Args);
-  const Arg *WaCPU = nullptr, *WaFPU = nullptr;
-  const Arg *WaHDiv = nullptr, *WaArch = nullptr;
-
-  if (!ForAS) {
-    // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these
-    // yet (it uses the -mfloat-abi and -msoft-float options), and it is
-    // stripped out by the ARM target. We should probably pass this a new
-    // -target-option, which is handled by the -cc1/-cc1as invocation.
-    //
-    // FIXME2:  For consistency, it would be ideal if we set up the target
-    // machine state the same when using the frontend or the assembler. We don't
-    // currently do that for the assembler, we pass the options directly to the
-    // backend and never even instantiate the frontend TargetInfo. If we did,
-    // and used its handleTargetFeatures hook, then we could ensure the
-    // assembler and the frontend behave the same.
-
-    // Use software floating point operations?
-    if (ABI == arm::FloatABI::Soft)
-      Features.push_back("+soft-float");
-
-    // Use software floating point argument passing?
-    if (ABI != arm::FloatABI::Hard)
-      Features.push_back("+soft-float-abi");
-  } else {
-    // Here, we make sure that -Wa,-mfpu/cpu/arch/hwdiv will be passed down
-    // to the assembler correctly.
-    for (const Arg *A :
-         Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
-      StringRef Value = A->getValue();
-      if (Value.startswith("-mfpu=")) {
-        WaFPU = A;
-      } else if (Value.startswith("-mcpu=")) {
-        WaCPU = A;
-      } else if (Value.startswith("-mhwdiv=")) {
-        WaHDiv = A;
-      } else if (Value.startswith("-march=")) {
-        WaArch = A;
-      }
-    }
-  }
-
-  // Check -march. ClangAs gives preference to -Wa,-march=.
-  const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ);
-  StringRef ArchName;
-  if (WaArch) {
-    if (ArchArg)
-      D.Diag(clang::diag::warn_drv_unused_argument)
-          << ArchArg->getAsString(Args);
-    ArchName = StringRef(WaArch->getValue()).substr(7);
-    checkARMArchName(D, WaArch, Args, ArchName, Features, Triple);
-    // FIXME: Set Arch.
-    D.Diag(clang::diag::warn_drv_unused_argument) << WaArch->getAsString(Args);
-  } else if (ArchArg) {
-    ArchName = ArchArg->getValue();
-    checkARMArchName(D, ArchArg, Args, ArchName, Features, Triple);
-  }
-
-  // Check -mcpu. ClangAs gives preference to -Wa,-mcpu=.
-  const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ);
-  StringRef CPUName;
-  if (WaCPU) {
-    if (CPUArg)
-      D.Diag(clang::diag::warn_drv_unused_argument)
-          << CPUArg->getAsString(Args);
-    CPUName = StringRef(WaCPU->getValue()).substr(6);
-    checkARMCPUName(D, WaCPU, Args, CPUName, ArchName, Features, Triple);
-  } else if (CPUArg) {
-    CPUName = CPUArg->getValue();
-    checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, Features, Triple);
-  }
-
-  // Add CPU features for generic CPUs
-  if (CPUName == "native") {
-    llvm::StringMap<bool> HostFeatures;
-    if (llvm::sys::getHostCPUFeatures(HostFeatures))
-      for (auto &F : HostFeatures)
-        Features.push_back(
-            Args.MakeArgString((F.second ? "+" : "-") + F.first()));
-  }
-
-  // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=.
-  const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ);
-  if (WaFPU) {
-    if (FPUArg)
-      D.Diag(clang::diag::warn_drv_unused_argument)
-          << FPUArg->getAsString(Args);
-    getARMFPUFeatures(D, WaFPU, Args, StringRef(WaFPU->getValue()).substr(6),
-                      Features);
-  } else if (FPUArg) {
-    getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
-  }
-
-  // Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=.
-  const Arg *HDivArg = Args.getLastArg(options::OPT_mhwdiv_EQ);
-  if (WaHDiv) {
-    if (HDivArg)
-      D.Diag(clang::diag::warn_drv_unused_argument)
-          << HDivArg->getAsString(Args);
-    getARMHWDivFeatures(D, WaHDiv, Args,
-                        StringRef(WaHDiv->getValue()).substr(8), Features);
-  } else if (HDivArg)
-    getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features);
-
-  // Setting -msoft-float effectively disables NEON because of the GCC
-  // implementation, although the same isn't true of VFP or VFP3.
-  if (ABI == arm::FloatABI::Soft) {
-    Features.push_back("-neon");
-    // Also need to explicitly disable features which imply NEON.
-    Features.push_back("-crypto");
-  }
-
-  // En/disable crc code generation.
-  if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
-    if (A->getOption().matches(options::OPT_mcrc))
-      Features.push_back("+crc");
-    else
-      Features.push_back("-crc");
-  }
-
-  // Look for the last occurrence of -mlong-calls or -mno-long-calls. If
-  // neither options are specified, see if we are compiling for kernel/kext and
-  // decide whether to pass "+long-calls" based on the OS and its version.
-  if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
-                               options::OPT_mno_long_calls)) {
-    if (A->getOption().matches(options::OPT_mlong_calls))
-      Features.push_back("+long-calls");
-  } else if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)) &&
-             !Triple.isWatchOS()) {
-      Features.push_back("+long-calls");
-  }
-
-  // Generate execute-only output (no data access to code sections).
-  // Supported only on ARMv6T2 and ARMv7 and above.
-  // Cannot be combined with -mno-movt or -mlong-calls
-  if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) {
-    if (A->getOption().matches(options::OPT_mexecute_only)) {
-      if (getARMSubArchVersionNumber(Triple) < 7 &&
-          llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::AK_ARMV6T2)
-            D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName();
-      else if (Arg *B = Args.getLastArg(options::OPT_mno_movt))
-        D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
-      // Long calls create constant pool entries and have not yet been fixed up
-      // to play nicely with execute-only. Hence, they cannot be used in
-      // execute-only code for now
-      else if (Arg *B = Args.getLastArg(options::OPT_mlong_calls, options::OPT_mno_long_calls)) {
-        if (B->getOption().matches(options::OPT_mlong_calls))
-          D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
-      }
-
-      CmdArgs.push_back("-backend-option");
-      CmdArgs.push_back("-arm-execute-only");
-    }
-  }
-
-  // Kernel code has more strict alignment requirements.
-  if (KernelOrKext)
-    Features.push_back("+strict-align");
-  else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
-                                    options::OPT_munaligned_access)) {
-    if (A->getOption().matches(options::OPT_munaligned_access)) {
-      // No v6M core supports unaligned memory access (v6M ARM ARM A3.2).
-      if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
-        D.Diag(diag::err_target_unsupported_unaligned) << "v6m";
-      // v8M Baseline follows on from v6M, so doesn't support unaligned memory
-      // access either.
-      else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline)
-        D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base";
-    } else
-      Features.push_back("+strict-align");
-  } else {
-    // Assume pre-ARMv6 doesn't support unaligned accesses.
-    //
-    // ARMv6 may or may not support unaligned accesses depending on the
-    // SCTLR.U bit, which is architecture-specific. We assume ARMv6
-    // Darwin and NetBSD targets support unaligned accesses, and others don't.
-    //
-    // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit
-    // which raises an alignment fault on unaligned accesses. Linux
-    // defaults this bit to 0 and handles it as a system-wide (not
-    // per-process) setting. It is therefore safe to assume that ARMv7+
-    // Linux targets support unaligned accesses. The same goes for NaCl.
-    //
-    // The above behavior is consistent with GCC.
-    int VersionNum = getARMSubArchVersionNumber(Triple);
-    if (Triple.isOSDarwin() || Triple.isOSNetBSD()) {
-      if (VersionNum < 6 ||
-          Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
-        Features.push_back("+strict-align");
-    } else if (Triple.isOSLinux() || Triple.isOSNaCl()) {
-      if (VersionNum < 7)
-        Features.push_back("+strict-align");
-    } else
-      Features.push_back("+strict-align");
-  }
-
-  // llvm does not support reserving registers in general. There is support
-  // for reserving r9 on ARM though (defined as a platform-specific register
-  // in ARM EABI).
-  if (Args.hasArg(options::OPT_ffixed_r9))
-    Features.push_back("+reserve-r9");
-
-  // The kext linker doesn't know how to deal with movw/movt.
-  if (KernelOrKext || Args.hasArg(options::OPT_mno_movt))
-    Features.push_back("+no-movt");
-}
-
 void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
                              ArgStringList &CmdArgs, bool KernelOrKext) const {
   // Select the ABI to use.
@@ -1224,7 +760,7 @@ void Clang::AddARMTargetArgs(const llvm:
   if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
     ABIName = A->getValue();
   } else if (Triple.isOSBinFormatMachO()) {
-    if (useAAPCSForMachO(Triple)) {
+    if (arm::useAAPCSForMachO(Triple)) {
       ABIName = "aapcs";
     } else if (Triple.isWatchABI()) {
       ABIName = "aapcs16";
@@ -1292,34 +828,6 @@ void Clang::AddARMTargetArgs(const llvm:
                     options::OPT_mno_implicit_float, true))
     CmdArgs.push_back("-no-implicit-float");
 }
-// ARM tools end.
-
-/// getAArch64TargetCPU - Get the (LLVM) name of the AArch64 cpu we are
-/// targeting. Set \p A to the Arg corresponding to the -mcpu or -mtune
-/// arguments if they are provided, or to nullptr otherwise.
-static std::string getAArch64TargetCPU(const ArgList &Args, Arg *&A) {
-  std::string CPU;
-  // If we have -mtune or -mcpu, use that.
-  if ((A = Args.getLastArg(options::OPT_mtune_EQ))) {
-    CPU = StringRef(A->getValue()).lower();
-  } else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
-    StringRef Mcpu = A->getValue();
-    CPU = Mcpu.split("+").first.lower();
-  }
-
-  // Handle CPU name is 'native'.
-  if (CPU == "native")
-    return llvm::sys::getHostCPUName();
-  else if (CPU.size())
-    return CPU;
-
-  // Make sure we pick "cyclone" if -arch is used.
-  // FIXME: Should this be picked by checking the target triple instead?
-  if (Args.getLastArg(options::OPT_arch))
-    return "cyclone";
-
-  return "generic";
-}
 
 void Clang::AddAArch64TargetArgs(const ArgList &Args,
                                  ArgStringList &CmdArgs) const {
@@ -1369,158 +877,7 @@ void Clang::AddAArch64TargetArgs(const A
   }
 }
 
-// Get CPU and ABI names. They are not independent
-// so we have to calculate them together.
-void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
-                            StringRef &CPUName, StringRef &ABIName) {
-  const char *DefMips32CPU = "mips32r2";
-  const char *DefMips64CPU = "mips64r2";
-
-  // MIPS32r6 is the default for mips(el)?-img-linux-gnu and MIPS64r6 is the
-  // default for mips64(el)?-img-linux-gnu.
-  if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies &&
-      Triple.getEnvironment() == llvm::Triple::GNU) {
-    DefMips32CPU = "mips32r6";
-    DefMips64CPU = "mips64r6";
-  }
-
-  // MIPS64r6 is the default for Android MIPS64 (mips64el-linux-android).
-  if (Triple.isAndroid()) {
-    DefMips32CPU = "mips32";
-    DefMips64CPU = "mips64r6";
-  }
-
-  // MIPS3 is the default for mips64*-unknown-openbsd.
-  if (Triple.getOS() == llvm::Triple::OpenBSD)
-    DefMips64CPU = "mips3";
-
-  if (Arg *A = Args.getLastArg(options::OPT_march_EQ, options::OPT_mcpu_EQ))
-    CPUName = A->getValue();
-
-  if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
-    ABIName = A->getValue();
-    // Convert a GNU style Mips ABI name to the name
-    // accepted by LLVM Mips backend.
-    ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName)
-                  .Case("32", "o32")
-                  .Case("64", "n64")
-                  .Default(ABIName);
-  }
-
-  // Setup default CPU and ABI names.
-  if (CPUName.empty() && ABIName.empty()) {
-    switch (Triple.getArch()) {
-    default:
-      llvm_unreachable("Unexpected triple arch name");
-    case llvm::Triple::mips:
-    case llvm::Triple::mipsel:
-      CPUName = DefMips32CPU;
-      break;
-    case llvm::Triple::mips64:
-    case llvm::Triple::mips64el:
-      CPUName = DefMips64CPU;
-      break;
-    }
-  }
-
-  if (ABIName.empty() &&
-      (Triple.getVendor() == llvm::Triple::MipsTechnologies ||
-       Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) {
-    ABIName = llvm::StringSwitch<const char *>(CPUName)
-                  .Case("mips1", "o32")
-                  .Case("mips2", "o32")
-                  .Case("mips3", "n64")
-                  .Case("mips4", "n64")
-                  .Case("mips5", "n64")
-                  .Case("mips32", "o32")
-                  .Case("mips32r2", "o32")
-                  .Case("mips32r3", "o32")
-                  .Case("mips32r5", "o32")
-                  .Case("mips32r6", "o32")
-                  .Case("mips64", "n64")
-                  .Case("mips64r2", "n64")
-                  .Case("mips64r3", "n64")
-                  .Case("mips64r5", "n64")
-                  .Case("mips64r6", "n64")
-                  .Case("octeon", "n64")
-                  .Case("p5600", "o32")
-                  .Default("");
-  }
-
-  if (ABIName.empty()) {
-    // Deduce ABI name from the target triple.
-    if (Triple.getArch() == llvm::Triple::mips ||
-        Triple.getArch() == llvm::Triple::mipsel)
-      ABIName = "o32";
-    else
-      ABIName = "n64";
-  }
-
-  if (CPUName.empty()) {
-    // Deduce CPU name from ABI name.
-    CPUName = llvm::StringSwitch<const char *>(ABIName)
-                  .Case("o32", DefMips32CPU)
-                  .Cases("n32", "n64", DefMips64CPU)
-                  .Default("");
-  }
-
-  // FIXME: Warn on inconsistent use of -march and -mabi.
-}
-
-std::string mips::getMipsABILibSuffix(const ArgList &Args,
-                                      const llvm::Triple &Triple) {
-  StringRef CPUName, ABIName;
-  tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
-  return llvm::StringSwitch<std::string>(ABIName)
-      .Case("o32", "")
-      .Case("n32", "32")
-      .Case("n64", "64");
-}
-
-// Convert ABI name to the GNU tools acceptable variant.
-static StringRef getGnuCompatibleMipsABIName(StringRef ABI) {
-  return llvm::StringSwitch<llvm::StringRef>(ABI)
-      .Case("o32", "32")
-      .Case("n64", "64")
-      .Default(ABI);
-}
-
-// Select the MIPS float ABI as determined by -msoft-float, -mhard-float,
-// and -mfloat-abi=.
-static mips::FloatABI getMipsFloatABI(const Driver &D, const ArgList &Args) {
-  mips::FloatABI ABI = mips::FloatABI::Invalid;
-  if (Arg *A =
-          Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
-                          options::OPT_mfloat_abi_EQ)) {
-    if (A->getOption().matches(options::OPT_msoft_float))
-      ABI = mips::FloatABI::Soft;
-    else if (A->getOption().matches(options::OPT_mhard_float))
-      ABI = mips::FloatABI::Hard;
-    else {
-      ABI = llvm::StringSwitch<mips::FloatABI>(A->getValue())
-                .Case("soft", mips::FloatABI::Soft)
-                .Case("hard", mips::FloatABI::Hard)
-                .Default(mips::FloatABI::Invalid);
-      if (ABI == mips::FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
-        D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
-        ABI = mips::FloatABI::Hard;
-      }
-    }
-  }
-
-  // If unspecified, choose the default based on the platform.
-  if (ABI == mips::FloatABI::Invalid) {
-    // Assume "hard", because it's a default value used by gcc.
-    // When we start to recognize specific target MIPS processors,
-    // we will be able to select the default more correctly.
-    ABI = mips::FloatABI::Hard;
-  }
-
-  assert(ABI != mips::FloatABI::Invalid && "must select an ABI");
-  return ABI;
-}
-
-static void AddTargetFeature(const ArgList &Args,
+void tools::AddTargetFeature(const ArgList &Args,
                              std::vector<StringRef> &Features,
                              OptSpecifier OnOpt, OptSpecifier OffOpt,
                              StringRef FeatureName) {
@@ -1532,129 +889,6 @@ static void AddTargetFeature(const ArgLi
   }
 }
 
-static void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
-                                  const ArgList &Args,
-                                  std::vector<StringRef> &Features) {
-  StringRef CPUName;
-  StringRef ABIName;
-  mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
-  ABIName = getGnuCompatibleMipsABIName(ABIName);
-
-  // Historically, PIC code for MIPS was associated with -mabicalls, a.k.a
-  // SVR4 abicalls. Static code does not use SVR4 calling sequences. An ABI
-  // extension was developed by Richard Sandiford & Code Sourcery to support
-  // static code calling PIC code (CPIC). For O32 and N32 this means we have
-  // several combinations of PIC/static and abicalls. Pure static, static
-  // with the CPIC extension, and pure PIC code.
-
-  // At final link time, O32 and N32 with CPIC will have another section
-  // added to the binary which contains the stub functions to perform
-  // any fixups required for PIC code.
-
-  // For N64, the situation is more regular: code can either be static
-  // (non-abicalls) or PIC (abicalls). GCC has traditionally picked PIC code
-  // code for N64. Since Clang has already built the relocation model portion
-  // of the commandline, we pick add +noabicalls feature in the N64 static
-  // case.
-
-  // The is another case to be accounted for: -msym32, which enforces that all
-  // symbols have 32 bits in size. In this case, N64 can in theory use CPIC
-  // but it is unsupported.
-
-  // The combinations for N64 are:
-  // a) Static without abicalls and 64bit symbols.
-  // b) Static with abicalls and 32bit symbols.
-  // c) PIC with abicalls and 64bit symbols.
-
-  // For case (a) we need to add +noabicalls for N64.
-
-  bool IsN64 = ABIName == "64";
-  bool NonPIC = false;
-
-  Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
-                                    options::OPT_fpic, options::OPT_fno_pic,
-                                    options::OPT_fPIE, options::OPT_fno_PIE,
-                                    options::OPT_fpie, options::OPT_fno_pie);
-  if (LastPICArg) {
-    Option O = LastPICArg->getOption();
-    NonPIC =
-        (O.matches(options::OPT_fno_PIC) || O.matches(options::OPT_fno_pic) ||
-         O.matches(options::OPT_fno_PIE) || O.matches(options::OPT_fno_pie));
-  }
-
-  if (IsN64 && NonPIC) {
-    Features.push_back("+noabicalls");
-  } else {
-    AddTargetFeature(Args, Features, options::OPT_mno_abicalls,
-                     options::OPT_mabicalls, "noabicalls");
-  }
-
-  mips::FloatABI FloatABI = getMipsFloatABI(D, Args);
-  if (FloatABI == mips::FloatABI::Soft) {
-    // FIXME: Note, this is a hack. We need to pass the selected float
-    // mode to the MipsTargetInfoBase to define appropriate macros there.
-    // Now it is the only method.
-    Features.push_back("+soft-float");
-  }
-
-  if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
-    StringRef Val = StringRef(A->getValue());
-    if (Val == "2008") {
-      if (mips::getSupportedNanEncoding(CPUName) & mips::Nan2008)
-        Features.push_back("+nan2008");
-      else {
-        Features.push_back("-nan2008");
-        D.Diag(diag::warn_target_unsupported_nan2008) << CPUName;
-      }
-    } else if (Val == "legacy") {
-      if (mips::getSupportedNanEncoding(CPUName) & mips::NanLegacy)
-        Features.push_back("-nan2008");
-      else {
-        Features.push_back("+nan2008");
-        D.Diag(diag::warn_target_unsupported_nanlegacy) << CPUName;
-      }
-    } else
-      D.Diag(diag::err_drv_unsupported_option_argument)
-          << A->getOption().getName() << Val;
-  }
-
-  AddTargetFeature(Args, Features, options::OPT_msingle_float,
-                   options::OPT_mdouble_float, "single-float");
-  AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16,
-                   "mips16");
-  AddTargetFeature(Args, Features, options::OPT_mmicromips,
-                   options::OPT_mno_micromips, "micromips");
-  AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp,
-                   "dsp");
-  AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2,
-                   "dspr2");
-  AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa,
-                   "msa");
-
-  // Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32
-  // pass -mfpxx, or if none are given and fp64a is default, pass fp64 and
-  // nooddspreg.
-  if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
-                               options::OPT_mfp64)) {
-    if (A->getOption().matches(options::OPT_mfp32))
-      Features.push_back(Args.MakeArgString("-fp64"));
-    else if (A->getOption().matches(options::OPT_mfpxx)) {
-      Features.push_back(Args.MakeArgString("+fpxx"));
-      Features.push_back(Args.MakeArgString("+nooddspreg"));
-    } else
-      Features.push_back(Args.MakeArgString("+fp64"));
-  } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) {
-    Features.push_back(Args.MakeArgString("+fpxx"));
-    Features.push_back(Args.MakeArgString("+nooddspreg"));
-  } else if (mips::isFP64ADefault(Triple, CPUName)) {
-    Features.push_back(Args.MakeArgString("+fp64"));
-    Features.push_back(Args.MakeArgString("+nooddspreg"));
-  }
-
-  AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg,
-                   options::OPT_modd_spreg, "nooddspreg");
-}
-
 void Clang::AddMIPSTargetArgs(const ArgList &Args,
                               ArgStringList &CmdArgs) const {
   const Driver &D = getToolChain().getDriver();
@@ -1666,7 +900,7 @@ void Clang::AddMIPSTargetArgs(const ArgL
   CmdArgs.push_back("-target-abi");
   CmdArgs.push_back(ABIName.data());
 
-  mips::FloatABI ABI = getMipsFloatABI(D, Args);
+  mips::FloatABI ABI = mips::getMipsFloatABI(D, Args);
   if (ABI == mips::FloatABI::Soft) {
     // Floating point operations and argument passing are soft.
     CmdArgs.push_back("-msoft-float");
@@ -1723,115 +957,6 @@ void Clang::AddMIPSTargetArgs(const ArgL
   }
 }
 
-/// getPPCTargetCPU - Get the (LLVM) name of the PowerPC cpu we are targeting.
-static std::string getPPCTargetCPU(const ArgList &Args) {
-  if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
-    StringRef CPUName = A->getValue();
-
-    if (CPUName == "native") {
-      std::string CPU = llvm::sys::getHostCPUName();
-      if (!CPU.empty() && CPU != "generic")
-        return CPU;
-      else
-        return "";
-    }
-
-    return llvm::StringSwitch<const char *>(CPUName)
-        .Case("common", "generic")
-        .Case("440", "440")
-        .Case("440fp", "440")
-        .Case("450", "450")
-        .Case("601", "601")
-        .Case("602", "602")
-        .Case("603", "603")
-        .Case("603e", "603e")
-        .Case("603ev", "603ev")
-        .Case("604", "604")
-        .Case("604e", "604e")
-        .Case("620", "620")
-        .Case("630", "pwr3")
-        .Case("G3", "g3")
-        .Case("7400", "7400")
-        .Case("G4", "g4")
-        .Case("7450", "7450")
-        .Case("G4+", "g4+")
-        .Case("750", "750")
-        .Case("970", "970")
-        .Case("G5", "g5")
-        .Case("a2", "a2")
-        .Case("a2q", "a2q")
-        .Case("e500mc", "e500mc")
-        .Case("e5500", "e5500")
-        .Case("power3", "pwr3")
-        .Case("power4", "pwr4")
-        .Case("power5", "pwr5")
-        .Case("power5x", "pwr5x")
-        .Case("power6", "pwr6")
-        .Case("power6x", "pwr6x")
-        .Case("power7", "pwr7")
-        .Case("power8", "pwr8")
-        .Case("power9", "pwr9")
-        .Case("pwr3", "pwr3")
-        .Case("pwr4", "pwr4")
-        .Case("pwr5", "pwr5")
-        .Case("pwr5x", "pwr5x")
-        .Case("pwr6", "pwr6")
-        .Case("pwr6x", "pwr6x")
-        .Case("pwr7", "pwr7")
-        .Case("pwr8", "pwr8")
-        .Case("pwr9", "pwr9")
-        .Case("powerpc", "ppc")
-        .Case("powerpc64", "ppc64")
-        .Case("powerpc64le", "ppc64le")
-        .Default("");
-  }
-
-  return "";
-}
-
-static void getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
-                                 const ArgList &Args,
-                                 std::vector<StringRef> &Features) {
-  handleTargetFeaturesGroup(Args, Features, options::OPT_m_ppc_Features_Group);
-
-  ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args);
-  if (FloatABI == ppc::FloatABI::Soft)
-    Features.push_back("-hard-float");
-
-  // Altivec is a bit weird, allow overriding of the Altivec feature here.
-  AddTargetFeature(Args, Features, options::OPT_faltivec,
-                   options::OPT_fno_altivec, "altivec");
-}
-
-ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) {
-  ppc::FloatABI ABI = ppc::FloatABI::Invalid;
-  if (Arg *A =
-          Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
-                          options::OPT_mfloat_abi_EQ)) {
-    if (A->getOption().matches(options::OPT_msoft_float))
-      ABI = ppc::FloatABI::Soft;
-    else if (A->getOption().matches(options::OPT_mhard_float))
-      ABI = ppc::FloatABI::Hard;
-    else {
-      ABI = llvm::StringSwitch<ppc::FloatABI>(A->getValue())
-                .Case("soft", ppc::FloatABI::Soft)
-                .Case("hard", ppc::FloatABI::Hard)
-                .Default(ppc::FloatABI::Invalid);
-      if (ABI == ppc::FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
-        D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
-        ABI = ppc::FloatABI::Hard;
-      }
-    }
-  }
-
-  // If unspecified, choose the default based on the platform.
-  if (ABI == ppc::FloatABI::Invalid) {
-    ABI = ppc::FloatABI::Hard;
-  }
-
-  return ABI;
-}
-
 void Clang::AddPPCTargetArgs(const ArgList &Args,
                              ArgStringList &CmdArgs) const {
   // Select the ABI to use.
@@ -1889,11 +1014,6 @@ void Clang::AddPPCTargetArgs(const ArgLi
   }
 }
 
-bool ppc::hasPPCAbiArg(const ArgList &Args, const char *Value) {
-  Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
-  return A && (A->getValue() == StringRef(Value));
-}
-
 /// Get the (LLVM) name of the R600 gpu we are targeting.
 static std::string getR600TargetGPU(const ArgList &Args) {
   if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
@@ -1918,48 +1038,6 @@ static std::string getLanaiTargetCPU(con
   return "";
 }
 
-sparc::FloatABI sparc::getSparcFloatABI(const Driver &D,
-                                        const ArgList &Args) {
-  sparc::FloatABI ABI = sparc::FloatABI::Invalid;
-  if (Arg *A =
-          Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
-                          options::OPT_mfloat_abi_EQ)) {
-    if (A->getOption().matches(options::OPT_msoft_float))
-      ABI = sparc::FloatABI::Soft;
-    else if (A->getOption().matches(options::OPT_mhard_float))
-      ABI = sparc::FloatABI::Hard;
-    else {
-      ABI = llvm::StringSwitch<sparc::FloatABI>(A->getValue())
-                .Case("soft", sparc::FloatABI::Soft)
-                .Case("hard", sparc::FloatABI::Hard)
-                .Default(sparc::FloatABI::Invalid);
-      if (ABI == sparc::FloatABI::Invalid &&
-          !StringRef(A->getValue()).empty()) {
-        D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
-        ABI = sparc::FloatABI::Hard;
-      }
-    }
-  }
-
-  // If unspecified, choose the default based on the platform.
-  // Only the hard-float ABI on Sparc is standardized, and it is the
-  // default. GCC also supports a nonstandard soft-float ABI mode, also
-  // implemented in LLVM. However as this is not standard we set the default
-  // to be hard-float.
-  if (ABI == sparc::FloatABI::Invalid) {
-    ABI = sparc::FloatABI::Hard;
-  }
-
-  return ABI;
-}
-
-static void getSparcTargetFeatures(const Driver &D, const ArgList &Args,
-                                 std::vector<StringRef> &Features) {
-  sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args);
-  if (FloatABI == sparc::FloatABI::Soft)
-    Features.push_back("+soft-float");
-}
-
 void Clang::AddSparcTargetArgs(const ArgList &Args,
                                ArgStringList &CmdArgs) const {
   sparc::FloatABI FloatABI =
@@ -1984,119 +1062,6 @@ void Clang::AddSystemZTargetArgs(const A
     CmdArgs.push_back("-mbackchain");
 }
 
-static const char *getSystemZTargetCPU(const ArgList &Args) {
-  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
-    return A->getValue();
-  return "z10";
-}
-
-static void getSystemZTargetFeatures(const ArgList &Args,
-                                     std::vector<StringRef> &Features) {
-  // -m(no-)htm overrides use of the transactional-execution facility.
-  if (Arg *A = Args.getLastArg(options::OPT_mhtm, options::OPT_mno_htm)) {
-    if (A->getOption().matches(options::OPT_mhtm))
-      Features.push_back("+transactional-execution");
-    else
-      Features.push_back("-transactional-execution");
-  }
-  // -m(no-)vx overrides use of the vector facility.
-  if (Arg *A = Args.getLastArg(options::OPT_mvx, options::OPT_mno_vx)) {
-    if (A->getOption().matches(options::OPT_mvx))
-      Features.push_back("+vector");
-    else
-      Features.push_back("-vector");
-  }
-}
-
-static const char *getX86TargetCPU(const ArgList &Args,
-                                   const llvm::Triple &Triple) {
-  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
-    if (StringRef(A->getValue()) != "native") {
-      if (Triple.isOSDarwin() && Triple.getArchName() == "x86_64h")
-        return "core-avx2";
-
-      return A->getValue();
-    }
-
-    // FIXME: Reject attempts to use -march=native unless the target matches
-    // the host.
-    //
-    // FIXME: We should also incorporate the detected target features for use
-    // with -native.
-    std::string CPU = llvm::sys::getHostCPUName();
-    if (!CPU.empty() && CPU != "generic")
-      return Args.MakeArgString(CPU);
-  }
-
-  if (const Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
-    // Mapping built by referring to X86TargetInfo::getDefaultFeatures().
-    StringRef Arch = A->getValue();
-    const char *CPU;
-    if (Triple.getArch() == llvm::Triple::x86) {
-      CPU = llvm::StringSwitch<const char *>(Arch)
-                .Case("IA32", "i386")
-                .Case("SSE", "pentium3")
-                .Case("SSE2", "pentium4")
-                .Case("AVX", "sandybridge")
-                .Case("AVX2", "haswell")
-                .Default(nullptr);
-    } else {
-      CPU = llvm::StringSwitch<const char *>(Arch)
-                .Case("AVX", "sandybridge")
-                .Case("AVX2", "haswell")
-                .Default(nullptr);
-    }
-    if (CPU)
-      return CPU;
-  }
-
-  // Select the default CPU if none was given (or detection failed).
-
-  if (Triple.getArch() != llvm::Triple::x86_64 &&
-      Triple.getArch() != llvm::Triple::x86)
-    return nullptr; // This routine is only handling x86 targets.
-
-  bool Is64Bit = Triple.getArch() == llvm::Triple::x86_64;
-
-  // FIXME: Need target hooks.
-  if (Triple.isOSDarwin()) {
-    if (Triple.getArchName() == "x86_64h")
-      return "core-avx2";
-    // macosx10.12 drops support for all pre-Penryn Macs.
-    // Simulators can still run on 10.11 though, like Xcode.
-    if (Triple.isMacOSX() && !Triple.isOSVersionLT(10, 12))
-      return "penryn";
-    // The oldest x86_64 Macs have core2/Merom; the oldest x86 Macs have Yonah.
-    return Is64Bit ? "core2" : "yonah";
-  }
-
-  // Set up default CPU name for PS4 compilers.
-  if (Triple.isPS4CPU())
-    return "btver2";
-
-  // On Android use targets compatible with gcc
-  if (Triple.isAndroid())
-    return Is64Bit ? "x86-64" : "i686";
-
-  // Everything else goes to x86-64 in 64-bit mode.
-  if (Is64Bit)
-    return "x86-64";
-
-  switch (Triple.getOS()) {
-  case llvm::Triple::FreeBSD:
-  case llvm::Triple::NetBSD:
-  case llvm::Triple::OpenBSD:
-    return "i486";
-  case llvm::Triple::Haiku:
-    return "i586";
-  case llvm::Triple::Bitrig:
-    return "i686";
-  default:
-    // Fallback to p4.
-    return "pentium4";
-  }
-}
-
 /// Get the (LLVM) name of the WebAssembly cpu we are targeting.
 static StringRef getWebAssemblyTargetCPU(const ArgList &Args) {
   // If we have -mcpu=, use that.
@@ -2116,8 +1081,8 @@ static StringRef getWebAssemblyTargetCPU
   return "generic";
 }
 
-static std::string getCPUName(const ArgList &Args, const llvm::Triple &T,
-                              bool FromAs = false) {
+std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
+                              bool FromAs) {
   Arg *A;
 
   switch (T.getArch()) {
@@ -2126,14 +1091,14 @@ static std::string getCPUName(const ArgL
 
   case llvm::Triple::aarch64:
   case llvm::Triple::aarch64_be:
-    return getAArch64TargetCPU(Args, A);
+    return aarch64::getAArch64TargetCPU(Args, A);
 
   case llvm::Triple::arm:
   case llvm::Triple::armeb:
   case llvm::Triple::thumb:
   case llvm::Triple::thumbeb: {
     StringRef MArch, MCPU;
-    getARMArchCPUFromArgs(Args, MArch, MCPU, FromAs);
+    arm::getARMArchCPUFromArgs(Args, MArch, MCPU, FromAs);
     return arm::getARMTargetCPU(MCPU, MArch, T);
   }
   case llvm::Triple::mips:
@@ -2155,7 +1120,7 @@ static std::string getCPUName(const ArgL
   case llvm::Triple::ppc:
   case llvm::Triple::ppc64:
   case llvm::Triple::ppc64le: {
-    std::string TargetCPUName = getPPCTargetCPU(Args);
+    std::string TargetCPUName = ppc::getPPCTargetCPU(Args);
     // LLVM may default to generating code for the native CPU,
     // but, like gcc, we default to a more generic option for
     // each architecture. (except on Darwin)
@@ -2179,7 +1144,7 @@ static std::string getCPUName(const ArgL
 
   case llvm::Triple::x86:
   case llvm::Triple::x86_64:
-    return getX86TargetCPU(Args, T);
+    return x86::getX86TargetCPU(Args, T);
 
   case llvm::Triple::hexagon:
     return "hexagon" +
@@ -2189,7 +1154,7 @@ static std::string getCPUName(const ArgL
     return getLanaiTargetCPU(Args);
 
   case llvm::Triple::systemz:
-    return getSystemZTargetCPU(Args);
+    return systemz::getSystemZTargetCPU(Args);
 
   case llvm::Triple::r600:
   case llvm::Triple::amdgcn:
@@ -2423,70 +1388,6 @@ static void ParseMRecip(const Driver &D,
   OutStrings.push_back(Args.MakeArgString(Out));
 }
 
-static void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
-                                 const ArgList &Args,
-                                 std::vector<StringRef> &Features) {
-  // If -march=native, autodetect the feature list.
-  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
-    if (StringRef(A->getValue()) == "native") {
-      llvm::StringMap<bool> HostFeatures;
-      if (llvm::sys::getHostCPUFeatures(HostFeatures))
-        for (auto &F : HostFeatures)
-          Features.push_back(
-              Args.MakeArgString((F.second ? "+" : "-") + F.first()));
-    }
-  }
-
-  if (Triple.getArchName() == "x86_64h") {
-    // x86_64h implies quite a few of the more modern subtarget features
-    // for Haswell class CPUs, but not all of them. Opt-out of a few.
-    Features.push_back("-rdrnd");
-    Features.push_back("-aes");
-    Features.push_back("-pclmul");
-    Features.push_back("-rtm");
-    Features.push_back("-hle");
-    Features.push_back("-fsgsbase");
-  }
-
-  const llvm::Triple::ArchType ArchType = Triple.getArch();
-  // Add features to be compatible with gcc for Android.
-  if (Triple.isAndroid()) {
-    if (ArchType == llvm::Triple::x86_64) {
-      Features.push_back("+sse4.2");
-      Features.push_back("+popcnt");
-    } else
-      Features.push_back("+ssse3");
-  }
-
-  // Set features according to the -arch flag on MSVC.
-  if (Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
-    StringRef Arch = A->getValue();
-    bool ArchUsed = false;
-    // First, look for flags that are shared in x86 and x86-64.
-    if (ArchType == llvm::Triple::x86_64 || ArchType == llvm::Triple::x86) {
-      if (Arch == "AVX" || Arch == "AVX2") {
-        ArchUsed = true;
-        Features.push_back(Args.MakeArgString("+" + Arch.lower()));
-      }
-    }
-    // Then, look for x86-specific flags.
-    if (ArchType == llvm::Triple::x86) {
-      if (Arch == "IA32") {
-        ArchUsed = true;
-      } else if (Arch == "SSE" || Arch == "SSE2") {
-        ArchUsed = true;
-        Features.push_back(Args.MakeArgString("+" + Arch.lower()));
-      }
-    }
-    if (!ArchUsed)
-      D.Diag(clang::diag::warn_drv_unused_argument) << A->getAsString(Args);
-  }
-
-  // Now add any that the user explicitly requested on the command line,
-  // which may override the defaults.
-  handleTargetFeaturesGroup(Args, Features, options::OPT_m_x86_Features_Group);
-}
-
 void Clang::AddX86TargetArgs(const ArgList &Args,
                              ArgStringList &CmdArgs) const {
   if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
@@ -2582,155 +1483,6 @@ void Clang::AddWebAssemblyTargetArgs(con
   }
 }
 
-// Decode AArch64 features from string like +[no]featureA+[no]featureB+...
-static bool DecodeAArch64Features(const Driver &D, StringRef text,
-                                  std::vector<StringRef> &Features) {
-  SmallVector<StringRef, 8> Split;
-  text.split(Split, StringRef("+"), -1, false);
-
-  for (StringRef Feature : Split) {
-    StringRef FeatureName = llvm::AArch64::getArchExtFeature(Feature);
-    if (!FeatureName.empty())
-      Features.push_back(FeatureName);
-    else if (Feature == "neon" || Feature == "noneon")
-      D.Diag(diag::err_drv_no_neon_modifier);
-    else
-      return false;
-  }
-  return true;
-}
-
-// Check if the CPU name and feature modifiers in -mcpu are legal. If yes,
-// decode CPU and feature.
-static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
-                              std::vector<StringRef> &Features) {
-  std::pair<StringRef, StringRef> Split = Mcpu.split("+");
-  CPU = Split.first;
-
-  if (CPU == "generic") {
-    Features.push_back("+neon");
-  } else {
-    unsigned ArchKind = llvm::AArch64::parseCPUArch(CPU);
-    if (!llvm::AArch64::getArchFeatures(ArchKind, Features))
-      return false;
-
-    unsigned Extension = llvm::AArch64::getDefaultExtensions(CPU, ArchKind);
-    if (!llvm::AArch64::getExtensionFeatures(Extension, Features))
-      return false;
-   }
-
-  if (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features))
-    return false;
-
-  return true;
-}
-
-static bool
-getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
-                                const ArgList &Args,
-                                std::vector<StringRef> &Features) {
-  std::string MarchLowerCase = March.lower();
-  std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");
-
-  unsigned ArchKind = llvm::AArch64::parseArch(Split.first);
-  if (ArchKind == static_cast<unsigned>(llvm::AArch64::ArchKind::AK_INVALID) ||
-      !llvm::AArch64::getArchFeatures(ArchKind, Features) ||
-      (Split.second.size() && !DecodeAArch64Features(D, Split.second, Features)))
-    return false;
-
-  return true;
-}
-
-static bool
-getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
-                               const ArgList &Args,
-                               std::vector<StringRef> &Features) {
-  StringRef CPU;
-  std::string McpuLowerCase = Mcpu.lower();
-  if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Features))
-    return false;
-
-  return true;
-}
-
-static bool
-getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
-                                     const ArgList &Args,
-                                     std::vector<StringRef> &Features) {
-  std::string MtuneLowerCase = Mtune.lower();
-  // Handle CPU name is 'native'.
-  if (MtuneLowerCase == "native")
-    MtuneLowerCase = llvm::sys::getHostCPUName();
-  if (MtuneLowerCase == "cyclone") {
-    Features.push_back("+zcm");
-    Features.push_back("+zcz");
-  }
-  return true;
-}
-
-static bool
-getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
-                                    const ArgList &Args,
-                                    std::vector<StringRef> &Features) {
-  StringRef CPU;
-  std::vector<StringRef> DecodedFeature;
-  std::string McpuLowerCase = Mcpu.lower();
-  if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, DecodedFeature))
-    return false;
-
-  return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);
-}
-
-static void getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
-                                     std::vector<StringRef> &Features) {
-  Arg *A;
-  bool success = true;
-  // Enable NEON by default.
-  Features.push_back("+neon");
-  if ((A = Args.getLastArg(options::OPT_march_EQ)))
-    success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Features);
-  else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
-    success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
-  else if (Args.hasArg(options::OPT_arch))
-    success = getAArch64ArchFeaturesFromMcpu(D, getAArch64TargetCPU(Args, A),
-                                             Args, Features);
-
-  if (success && (A = Args.getLastArg(options::OPT_mtune_EQ)))
-    success =
-        getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args, Features);
-  else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
-    success =
-        getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, Features);
-  else if (success && Args.hasArg(options::OPT_arch))
-    success = getAArch64MicroArchFeaturesFromMcpu(
-        D, getAArch64TargetCPU(Args, A), Args, Features);
-
-  if (!success)
-    D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
-
-  if (Args.getLastArg(options::OPT_mgeneral_regs_only)) {
-    Features.push_back("-fp-armv8");
-    Features.push_back("-crypto");
-    Features.push_back("-neon");
-  }
-
-  // En/disable crc
-  if (Arg *A = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) {
-    if (A->getOption().matches(options::OPT_mcrc))
-      Features.push_back("+crc");
-    else
-      Features.push_back("-crc");
-  }
-
-  if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
-                               options::OPT_munaligned_access))
-    if (A->getOption().matches(options::OPT_mno_unaligned_access))
-      Features.push_back("+strict-align");
-
-  if (Args.hasArg(options::OPT_ffixed_x18))
-    Features.push_back("+reserve-x18");
-}
-
 static void getHexagonTargetFeatures(const ArgList &Args,
                                      std::vector<StringRef> &Features) {
   handleTargetFeaturesGroup(Args, Features,
@@ -2780,31 +1532,31 @@ static void getTargetFeatures(const Tool
   case llvm::Triple::mipsel:
   case llvm::Triple::mips64:
   case llvm::Triple::mips64el:
-    getMIPSTargetFeatures(D, Triple, Args, Features);
+    mips::getMIPSTargetFeatures(D, Triple, Args, Features);
     break;
 
   case llvm::Triple::arm:
   case llvm::Triple::armeb:
   case llvm::Triple::thumb:
   case llvm::Triple::thumbeb:
-    getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS);
+    arm::getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS);
     break;
 
   case llvm::Triple::ppc:
   case llvm::Triple::ppc64:
   case llvm::Triple::ppc64le:
-    getPPCTargetFeatures(D, Triple, Args, Features);
+    ppc::getPPCTargetFeatures(D, Triple, Args, Features);
     break;
   case llvm::Triple::systemz:
-    getSystemZTargetFeatures(Args, Features);
+    systemz::getSystemZTargetFeatures(Args, Features);
     break;
   case llvm::Triple::aarch64:
   case llvm::Triple::aarch64_be:
-    getAArch64TargetFeatures(D, Args, Features);
+    aarch64::getAArch64TargetFeatures(D, Args, Features);
     break;
   case llvm::Triple::x86:
   case llvm::Triple::x86_64:
-    getX86TargetFeatures(D, Triple, Args, Features);
+    x86::getX86TargetFeatures(D, Triple, Args, Features);
     break;
   case llvm::Triple::hexagon:
     getHexagonTargetFeatures(Args, Features);
@@ -2816,7 +1568,7 @@ static void getTargetFeatures(const Tool
   case llvm::Triple::sparc:
   case llvm::Triple::sparcel:
   case llvm::Triple::sparcv9:
-    getSparcTargetFeatures(D, Args, Features);
+    sparc::getSparcTargetFeatures(D, Args, Features);
     break;
   case llvm::Triple::r600:
   case llvm::Triple::amdgcn:
@@ -7982,112 +6734,10 @@ void arm::appendEBLinkFlags(const ArgLis
 
   // ARMv7 (and later) and ARMv6-M do not support BE-32, so instruct the linker
   // to generate BE-8 executables.
-  if (getARMSubArchVersionNumber(Triple) >= 7 || isARMMProfile(Triple))
+  if (arm::getARMSubArchVersionNumber(Triple) >= 7 || arm::isARMMProfile(Triple))
     CmdArgs.push_back("--be8");
 }
 
-mips::NanEncoding mips::getSupportedNanEncoding(StringRef &CPU) {
-  // Strictly speaking, mips32r2 and mips64r2 are NanLegacy-only since Nan2008
-  // was first introduced in Release 3. However, other compilers have
-  // traditionally allowed it for Release 2 so we should do the same.
-  return (NanEncoding)llvm::StringSwitch<int>(CPU)
-      .Case("mips1", NanLegacy)
-      .Case("mips2", NanLegacy)
-      .Case("mips3", NanLegacy)
-      .Case("mips4", NanLegacy)
-      .Case("mips5", NanLegacy)
-      .Case("mips32", NanLegacy)
-      .Case("mips32r2", NanLegacy | Nan2008)
-      .Case("mips32r3", NanLegacy | Nan2008)
-      .Case("mips32r5", NanLegacy | Nan2008)
-      .Case("mips32r6", Nan2008)
-      .Case("mips64", NanLegacy)
-      .Case("mips64r2", NanLegacy | Nan2008)
-      .Case("mips64r3", NanLegacy | Nan2008)
-      .Case("mips64r5", NanLegacy | Nan2008)
-      .Case("mips64r6", Nan2008)
-      .Default(NanLegacy);
-}
-
-bool mips::hasCompactBranches(StringRef &CPU) {
-  // mips32r6 and mips64r6 have compact branches.
-  return llvm::StringSwitch<bool>(CPU)
-      .Case("mips32r6", true)
-      .Case("mips64r6", true)
-      .Default(false);
-}
-
-bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) {
-  Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
-  return A && (A->getValue() == StringRef(Value));
-}
-
-bool mips::isUCLibc(const ArgList &Args) {
-  Arg *A = Args.getLastArg(options::OPT_m_libc_Group);
-  return A && A->getOption().matches(options::OPT_muclibc);
-}
-
-bool mips::isNaN2008(const ArgList &Args, const llvm::Triple &Triple) {
-  if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ))
-    return llvm::StringSwitch<bool>(NaNArg->getValue())
-        .Case("2008", true)
-        .Case("legacy", false)
-        .Default(false);
-
-  // NaN2008 is the default for MIPS32r6/MIPS64r6.
-  return llvm::StringSwitch<bool>(getCPUName(Args, Triple))
-      .Cases("mips32r6", "mips64r6", true)
-      .Default(false);
-
-  return false;
-}
-
-bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) {
-  if (!Triple.isAndroid())
-    return false;
-
-  // Android MIPS32R6 defaults to FP64A.
-  return llvm::StringSwitch<bool>(CPUName)
-      .Case("mips32r6", true)
-      .Default(false);
-}
-
-bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
-                         StringRef ABIName, mips::FloatABI FloatABI) {
-  if (Triple.getVendor() != llvm::Triple::ImaginationTechnologies &&
-      Triple.getVendor() != llvm::Triple::MipsTechnologies &&
-      !Triple.isAndroid())
-    return false;
-
-  if (ABIName != "32")
-    return false;
-
-  // FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is
-  // present.
-  if (FloatABI == mips::FloatABI::Soft)
-    return false;
-
-  return llvm::StringSwitch<bool>(CPUName)
-      .Cases("mips2", "mips3", "mips4", "mips5", true)
-      .Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true)
-      .Cases("mips64", "mips64r2", "mips64r3", "mips64r5", true)
-      .Default(false);
-}
-
-bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple,
-                         StringRef CPUName, StringRef ABIName,
-                         mips::FloatABI FloatABI) {
-  bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI);
-
-  // FPXX shouldn't be used if -msingle-float is present.
-  if (Arg *A = Args.getLastArg(options::OPT_msingle_float,
-                               options::OPT_mdouble_float))
-    if (A->getOption().matches(options::OPT_msingle_float))
-      UseFPXX = false;
-
-  return UseFPXX;
-}
-
 llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
   // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
   // archs which Darwin doesn't use.
@@ -8924,7 +7574,7 @@ void openbsd::Assembler::ConstructJob(Co
   case llvm::Triple::sparcel: {
     CmdArgs.push_back("-32");
     std::string CPU = getCPUName(Args, getToolChain().getTriple());
-    CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
+    CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
     AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
     break;
   }
@@ -8932,7 +7582,7 @@ void openbsd::Assembler::ConstructJob(Co
   case llvm::Triple::sparcv9: {
     CmdArgs.push_back("-64");
     std::string CPU = getCPUName(Args, getToolChain().getTriple());
-    CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
+    CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
     AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
     break;
   }
@@ -8944,7 +7594,7 @@ void openbsd::Assembler::ConstructJob(Co
     mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
 
     CmdArgs.push_back("-mabi");
-    CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());
+    CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data());
 
     if (getToolChain().getArch() == llvm::Triple::mips64)
       CmdArgs.push_back("-EB");
@@ -9257,7 +7907,7 @@ void freebsd::Assembler::ConstructJob(Co
     CmdArgs.push_back(CPUName.data());
 
     CmdArgs.push_back("-mabi");
-    CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());
+    CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data());
 
     if (getToolChain().getArch() == llvm::Triple::mips ||
         getToolChain().getArch() == llvm::Triple::mips64)
@@ -9301,7 +7951,7 @@ void freebsd::Assembler::ConstructJob(Co
   case llvm::Triple::sparcel:
   case llvm::Triple::sparcv9: {
     std::string CPU = getCPUName(Args, getToolChain().getTriple());
-    CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
+    CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
     AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
     break;
   }
@@ -9528,7 +8178,7 @@ void netbsd::Assembler::ConstructJob(Com
   case llvm::Triple::thumb:
   case llvm::Triple::thumbeb: {
     StringRef MArch, MCPU;
-    getARMArchCPUFromArgs(Args, MArch, MCPU, /*FromAs*/ true);
+    arm::getARMArchCPUFromArgs(Args, MArch, MCPU, /*FromAs*/ true);
     std::string Arch =
         arm::getARMTargetCPU(MCPU, MArch, getToolChain().getTriple());
     CmdArgs.push_back(Args.MakeArgString("-mcpu=" + Arch));
@@ -9547,7 +8197,7 @@ void netbsd::Assembler::ConstructJob(Com
     CmdArgs.push_back(CPUName.data());
 
     CmdArgs.push_back("-mabi");
-    CmdArgs.push_back(getGnuCompatibleMipsABIName(ABIName).data());
+    CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data());
 
     if (getToolChain().getArch() == llvm::Triple::mips ||
         getToolChain().getArch() == llvm::Triple::mips64)
@@ -9563,7 +8213,7 @@ void netbsd::Assembler::ConstructJob(Com
   case llvm::Triple::sparcel: {
     CmdArgs.push_back("-32");
     std::string CPU = getCPUName(Args, getToolChain().getTriple());
-    CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
+    CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
     AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
     break;
   }
@@ -9571,7 +8221,7 @@ void netbsd::Assembler::ConstructJob(Com
   case llvm::Triple::sparcv9: {
     CmdArgs.push_back("-64");
     std::string CPU = getCPUName(Args, getToolChain().getTriple());
-    CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
+    CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
     AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
     break;
   }
@@ -9851,14 +8501,14 @@ void gnutools::Assembler::ConstructJob(C
   case llvm::Triple::sparcel: {
     CmdArgs.push_back("-32");
     std::string CPU = getCPUName(Args, getToolChain().getTriple());
-    CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
+    CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
     AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
     break;
   }
   case llvm::Triple::sparcv9: {
     CmdArgs.push_back("-64");
     std::string CPU = getCPUName(Args, getToolChain().getTriple());
-    CmdArgs.push_back(getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
+    CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
     AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
     break;
   }
@@ -9912,7 +8562,7 @@ void gnutools::Assembler::ConstructJob(C
     StringRef CPUName;
     StringRef ABIName;
     mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
-    ABIName = getGnuCompatibleMipsABIName(ABIName);
+    ABIName = mips::getGnuCompatibleMipsABIName(ABIName);
 
     CmdArgs.push_back("-march");
     CmdArgs.push_back(CPUName.data());
@@ -9948,7 +8598,7 @@ void gnutools::Assembler::ConstructJob(C
       A->render(Args, CmdArgs);
     } else if (mips::shouldUseFPXX(
                    Args, getToolChain().getTriple(), CPUName, ABIName,
-                   getMipsFloatABI(getToolChain().getDriver(), Args)))
+                   mips::getMipsFloatABI(getToolChain().getDriver(), Args)))
       CmdArgs.push_back("-mfpxx");
 
     // Pass on -mmips16 or -mno-mips16. However, the assembler equivalent of
@@ -9991,7 +8641,7 @@ void gnutools::Assembler::ConstructJob(C
   case llvm::Triple::systemz: {
     // Always pass an -march option, since our default of z10 is later
     // than the GNU assembler's default.
-    StringRef CPUName = getSystemZTargetCPU(Args);
+    StringRef CPUName = systemz::getSystemZTargetCPU(Args);
     CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));
     break;
   }

Modified: cfe/trunk/lib/Driver/Tools.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.h?rev=296056&r1=296055&r2=296056&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.h (original)
+++ cfe/trunk/lib/Driver/Tools.h Thu Feb 23 18:28:01 2017
@@ -38,11 +38,23 @@ class Compiler;
 }
 
 using llvm::opt::ArgStringList;
+using llvm::opt::ArgList;
 
 SmallString<128> getCompilerRT(const ToolChain &TC,
                                const llvm::opt::ArgList &Args,
                                StringRef Component, bool Shared = false);
 
+std::string getCPUName(const ArgList &Args, const llvm::Triple &T,
+                       bool FromAs = false);
+
+void AddTargetFeature(const ArgList &Args, std::vector<StringRef> &Features,
+                      llvm::opt::OptSpecifier OnOpt,
+                      llvm::opt::OptSpecifier OffOpt, StringRef FeatureName);
+
+void handleTargetFeaturesGroup(const ArgList &Args,
+                               std::vector<StringRef> &Features,
+                               llvm::opt::OptSpecifier Group);
+
 /// \brief Clang compiler tool.
 class LLVM_LIBRARY_VISIBILITY Clang : public Tool {
 public:
@@ -321,6 +333,11 @@ bool hasCompactBranches(StringRef &CPU);
 void getMipsCPUAndABI(const llvm::opt::ArgList &Args,
                       const llvm::Triple &Triple, StringRef &CPUName,
                       StringRef &ABIName);
+void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+                           const ArgList &Args,
+                           std::vector<StringRef> &Features);
+StringRef getGnuCompatibleMipsABIName(StringRef ABI);
+mips::FloatABI getMipsFloatABI(const Driver &D, const ArgList &Args);
 std::string getMipsABILibSuffix(const llvm::opt::ArgList &Args,
                                 const llvm::Triple &Triple);
 bool hasMipsAbiArg(const llvm::opt::ArgList &Args, const char *Value);
@@ -332,6 +349,7 @@ bool isFPXXDefault(const llvm::Triple &T
 bool shouldUseFPXX(const llvm::opt::ArgList &Args, const llvm::Triple &Triple,
                    StringRef CPUName, StringRef ABIName,
                    mips::FloatABI FloatABI);
+
 } // end namespace mips
 
 namespace ppc {
@@ -803,8 +821,23 @@ enum class FloatABI {
 };
 
 FloatABI getARMFloatABI(const ToolChain &TC, const llvm::opt::ArgList &Args);
+
+bool useAAPCSForMachO(const llvm::Triple &T);
+void getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch,
+                           llvm::StringRef &CPU, bool FromAs = false);
+void getARMTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
+                          const ArgList &Args, ArgStringList &CmdArgs,
+                          std::vector<StringRef> &Features, bool ForAS);
+int getARMSubArchVersionNumber(const llvm::Triple &Triple);
+bool isARMMProfile(const llvm::Triple &Triple);
 } // end namespace arm
 
+namespace aarch64 {
+void getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
+                              std::vector<StringRef> &Features);
+std::string getAArch64TargetCPU(const ArgList &Args, llvm::opt::Arg *&A);
+} // end namespace aarch64
+
 namespace ppc {
 enum class FloatABI {
   Invalid,
@@ -813,6 +846,11 @@ enum class FloatABI {
 };
 
 FloatABI getPPCFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
+
+std::string getPPCTargetCPU(const ArgList &Args);
+void getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+                          const ArgList &Args,
+                          std::vector<StringRef> &Features);
 } // end namespace ppc
 
 namespace sparc {
@@ -823,6 +861,11 @@ enum class FloatABI {
 };
 
 FloatABI getSparcFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
+
+void getSparcTargetFeatures(const Driver &D, const ArgList &Args,
+                            std::vector<StringRef> &Features);
+const char *getSparcAsmModeForCPU(StringRef Name,
+                                  const llvm::Triple &Triple);
 } // end namespace sparc
 
 namespace XCore {
@@ -1003,6 +1046,20 @@ public:
 };
 } // end namespace AVR
 
+namespace systemz {
+const char *getSystemZTargetCPU(const ArgList &Args);
+void getSystemZTargetFeatures(const ArgList &Args,
+                              std::vector<StringRef> &Features);
+} // end namespace systemz
+
+namespace x86 {
+const char *getX86TargetCPU(const ArgList &Args,
+                            const llvm::Triple &Triple);
+void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
+                          const ArgList &Args,
+                          std::vector<StringRef> &Features);
+} // end namespace x86
+
 } // end namespace tools
 } // end namespace driver
 } // end namespace clang




More information about the cfe-commits mailing list