[ARM] Restructure cpu handling in the driver to mostly use the triple

Using the target cpu to determine some behaviour is sprinkled in
several places in the driver, but in almost all the information that
is needed can be found in the triple. Restructure things so that the
triple is used, and the cpu is only used if the exact cpu name is
needed.

Also add a check that the -mcpu argument is valid, and correct the
-march argument checking so that it handles -march=native correctly. I
would have liked to move these checks into the computation of the
triple, but the triple is calculated several times in several places
and that would lead to multiple error messages for the same thing.

Differential Revision: http://reviews.llvm.org/D9879

llvm-svn: 237894
diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp
index a54a592..beb6a34 100644
--- a/clang/lib/Driver/Tools.cpp
+++ b/clang/lib/Driver/Tools.cpp
@@ -617,6 +617,44 @@
   }
 }
 
+// FIXME: Move to ARMTargetParser.
+static int getARMSubArchVersionNumber(const llvm::Triple &Triple) {
+  switch (Triple.getSubArch()) {
+  case llvm::Triple::ARMSubArch_v8_1a:
+  case llvm::Triple::ARMSubArch_v8:
+    return 8;
+  case llvm::Triple::ARMSubArch_v7:
+  case llvm::Triple::ARMSubArch_v7em:
+  case llvm::Triple::ARMSubArch_v7m:
+  case llvm::Triple::ARMSubArch_v7s:
+    return 7;
+  case llvm::Triple::ARMSubArch_v6:
+  case llvm::Triple::ARMSubArch_v6m:
+  case llvm::Triple::ARMSubArch_v6k:
+  case llvm::Triple::ARMSubArch_v6t2:
+    return 6;
+  case llvm::Triple::ARMSubArch_v5:
+  case llvm::Triple::ARMSubArch_v5te:
+    return 5;
+  case llvm::Triple::ARMSubArch_v4t:
+    return 4;
+  default:
+    return 0;
+  }
+}
+
+// FIXME: Move to ARMTargetParser.
+static bool isARMMProfile(const llvm::Triple &Triple) {
+  switch (Triple.getSubArch()) {
+  case llvm::Triple::ARMSubArch_v7em:
+  case llvm::Triple::ARMSubArch_v7m:
+  case llvm::Triple::ARMSubArch_v6m:
+    return true;
+  default:
+    return false;
+  }
+}
+
 // Select the float ABI as determined by -msoft-float, -mhard-float, and
 // -mfloat-abi=.
 StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args,
@@ -647,12 +685,8 @@
     case llvm::Triple::IOS: {
       // Darwin defaults to "softfp" for v6 and v7.
       //
-      // FIXME: Factor out an ARM class so we can cache the arch somewhere.
-      std::string ArchName =
-        arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple),
-                                     arm::getARMArch(Args, Triple));
-      if (StringRef(ArchName).startswith("v6") ||
-          StringRef(ArchName).startswith("v7"))
+      if (getARMSubArchVersionNumber(Triple) == 6 ||
+          getARMSubArchVersionNumber(Triple) == 7)
         FloatABI = "softfp";
       else
         FloatABI = "soft";
@@ -692,10 +726,7 @@
         FloatABI = "softfp";
         break;
       case llvm::Triple::Android: {
-        std::string ArchName =
-          arm::getLLVMArchSuffixForARM(arm::getARMTargetCPU(Args, Triple),
-                                       arm::getARMArch(Args, Triple));
-        if (StringRef(ArchName).startswith("v7"))
+        if (getARMSubArchVersionNumber(Triple) == 7)
           FloatABI = "softfp";
         else
           FloatABI = "soft";
@@ -748,12 +779,24 @@
   if (const Arg *A = Args.getLastArg(options::OPT_mhwdiv_EQ))
     getARMHWDivFeatures(D, A, Args, Features);
 
-  // -march is handled in getARMCPUForMarch by translating it into a CPU name,
-  // but it needs to return an empty string on invalid arguments. We therefore
-  // check and give an error here if the -march is invalid.
-  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
-    if (!Triple.getARMCPUForArch(A->getValue()))
+  // Check if -march is valid by checking if it can be canonicalised. getARMArch
+  // is used here instead of just checking the -march value in order to handle
+  // -march=native correctly.
+  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+    StringRef Arch = arm::getARMArch(Args, Triple);
+    if (llvm::ARMTargetParser::getCanonicalArchName(Arch).empty())
       D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
+  }
+
+  // We do a similar thing with -mcpu, but here things are complicated because
+  // the only function we have to check if a cpu is valid is
+  // getLLVMArchSuffixForARM which also needs an architecture.
+  if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
+    StringRef CPU = arm::getARMTargetCPU(Args, Triple);
+    StringRef Arch = arm::getARMArch(Args, Triple);
+    if (strcmp(arm::getLLVMArchSuffixForARM(CPU, Arch), "") == 0)
+      D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
+  }
 
   // Setting -msoft-float effectively disables NEON because of the GCC
   // implementation, although the same isn't true of VFP or VFP3.
@@ -783,7 +826,6 @@
   // Get the effective triple, which takes into account the deployment target.
   std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
   llvm::Triple Triple(TripleStr);
-  std::string CPUName = arm::getARMTargetCPU(Args, Triple);
 
   // Select the ABI to use.
   //
@@ -797,7 +839,7 @@
     // the frontend matches that.
     if (Triple.getEnvironment() == llvm::Triple::EABI ||
         Triple.getOS() == llvm::Triple::UnknownOS ||
-        StringRef(CPUName).startswith("cortex-m")) {
+        isARMMProfile(Triple)) {
       ABIName = "aapcs";
     } else {
       ABIName = "apcs-gnu";
@@ -3209,9 +3251,7 @@
   }
 
   // Add the target cpu
-  std::string ETripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
-  llvm::Triple ETriple(ETripleStr);
-  std::string CPU = getCPUName(Args, ETriple);
+  std::string CPU = getCPUName(Args, Triple);
   if (!CPU.empty()) {
     CmdArgs.push_back("-target-cpu");
     CmdArgs.push_back(Args.MakeArgString(CPU));
@@ -3223,7 +3263,7 @@
   }
 
   // Add the target features
-  getTargetFeatures(D, ETriple, Args, CmdArgs, false);
+  getTargetFeatures(D, Triple, Args, CmdArgs, false);
 
   // Add target specific flags.
   switch(getToolChain().getArch()) {
@@ -5105,7 +5145,7 @@
   CmdArgs.push_back(Clang::getBaseInputName(Args, Input));
 
   // Add the target cpu
-  const llvm::Triple &Triple = getToolChain().getTriple();
+  const llvm::Triple Triple(TripleStr);
   std::string CPU = getCPUName(Args, Triple);
   if (!CPU.empty()) {
     CmdArgs.push_back("-target-cpu");
@@ -5630,23 +5670,32 @@
     // Otherwise, use the Arch from the triple.
     MArch = Triple.getArchName();
   }
+
+  // Handle -march=native.
+  if (MArch == "native") {
+    std::string CPU = llvm::sys::getHostCPUName();
+    if (CPU != "generic") {
+      // Translate the native cpu into the architecture suffix for that CPU.
+      const char *Suffix = arm::getLLVMArchSuffixForARM(CPU, MArch);
+      // If there is no valid architecture suffix for this CPU we don't know how
+      // to handle it, so return no architecture.
+      if (strcmp(Suffix,"") == 0)
+        MArch = "";
+      else
+        MArch = std::string("arm") + Suffix;
+    }
+  }
+
   return MArch;
 }
 /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
 const char *arm::getARMCPUForMArch(const ArgList &Args,
                                    const llvm::Triple &Triple) {
   StringRef MArch = getARMArch(Args, Triple);
-
-  // Handle -march=native.
-  if (MArch == "native") {
-    std::string CPU = llvm::sys::getHostCPUName();
-    if (CPU != "generic") {
-      // Translate the native cpu into the architecture. The switch below will
-      // then chose the minimum cpu for that arch.
-      MArch = std::string("arm") + 
-        arm::getLLVMArchSuffixForARM(CPU, arm::getARMArch(Args, Triple));
-    }
-  }
+  // getARMCPUForArch defaults to the triple if MArch is empty, but empty MArch
+  // here means an -march=native that we can't handle, so instead return no CPU.
+  if (MArch.empty())
+    return "";
 
   // We need to return an empty string here on invalid MArch values as the
   // various places that call this function can't cope with a null result.
@@ -5689,8 +5738,10 @@
     }
   }
 
+  // FIXME: Use ARMTargetParser
   return llvm::StringSwitch<const char *>(CPU)
-    .Case("strongarm", "v4")
+    .Cases("arm8", "arm810", "v4")
+    .Cases("strongarm", "strongarm110", "strongarm1100", "strongarm1110", "v4")
     .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t")
     .Cases("arm720t", "arm9", "arm9tdmi", "v4t")
     .Cases("arm920", "arm920t", "arm922t", "v4t")
@@ -5720,15 +5771,10 @@
   if (Args.hasArg(options::OPT_r))
     return;
 
-  StringRef Suffix = getLLVMArchSuffixForARM(getARMCPUForMArch(Args, Triple), 
-                                             getARMArch(Args, Triple));
-  const char *LinkFlag = llvm::StringSwitch<const char *>(Suffix)
-    .Cases("v4", "v4t", "v5", "v5e", nullptr)
-    .Cases("v6", "v6k", "v6t2", nullptr)
-    .Default("--be8");
-
-  if (LinkFlag)
-    CmdArgs.push_back(LinkFlag);
+  // 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))
+    CmdArgs.push_back("--be8");
 }
 
 mips::NanEncoding mips::getSupportedNanEncoding(StringRef &CPU) {
@@ -7329,7 +7375,8 @@
     break;
   case llvm::Triple::armeb:
   case llvm::Triple::thumbeb:
-    arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getTriple());
+    arm::appendEBLinkFlags(Args, CmdArgs,
+        llvm::Triple(getToolChain().ComputeEffectiveClangTriple(Args)));
     CmdArgs.push_back("-m");
     switch (getToolChain().getTriple().getEnvironment()) {
     case llvm::Triple::EABI:
@@ -7905,7 +7952,8 @@
 
   if (ToolChain.getArch() == llvm::Triple::armeb ||
       ToolChain.getArch() == llvm::Triple::thumbeb)
-    arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getTriple());
+    arm::appendEBLinkFlags(Args, CmdArgs,
+        llvm::Triple(getToolChain().ComputeEffectiveClangTriple(Args)));
 
   for (const auto &Opt : ToolChain.ExtraOpts)
     CmdArgs.push_back(Opt.c_str());