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

John Brawn john.brawn at arm.com
Thu May 21 05:19:49 PDT 2015


Author: john.brawn
Date: Thu May 21 07:19:49 2015
New Revision: 237894

URL: http://llvm.org/viewvc/llvm-project?rev=237894&view=rev
Log:
[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

Modified:
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/test/Driver/arm-cortex-cpus.c

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=237894&r1=237893&r2=237894&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Thu May 21 07:19:49 2015
@@ -617,6 +617,44 @@ static void getARMFPUFeatures(const Driv
   }
 }
 
+// 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 @@ StringRef tools::arm::getARMFloatABI(con
     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 @@ StringRef tools::arm::getARMFloatABI(con
         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 @@ static void getARMTargetFeatures(const D
   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 @@ void Clang::AddARMTargetArgs(const ArgLi
   // 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 @@ void Clang::AddARMTargetArgs(const ArgLi
     // 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 @@ void Clang::ConstructJob(Compilation &C,
   }
 
   // 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 @@ void Clang::ConstructJob(Compilation &C,
   }
 
   // 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 @@ void ClangAs::ConstructJob(Compilation &
   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,24 +5670,33 @@ const StringRef arm::getARMArch(const Ar
     // Otherwise, use the Arch from the triple.
     MArch = Triple.getArchName();
   }
-  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));
+      // 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);
+  // 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.
   const char *result = Triple.getARMCPUForArch(MArch);
@@ -5689,8 +5738,10 @@ const char *arm::getLLVMArchSuffixForARM
     }
   }
 
+  // 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 @@ void arm::appendEBLinkFlags(const ArgLis
   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 @@ void netbsd::Link::ConstructJob(Compilat
     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 @@ void gnutools::Link::ConstructJob(Compil
 
   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());

Modified: cfe/trunk/test/Driver/arm-cortex-cpus.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/arm-cortex-cpus.c?rev=237894&r1=237893&r2=237894&view=diff
==============================================================================
--- cfe/trunk/test/Driver/arm-cortex-cpus.c (original)
+++ cfe/trunk/test/Driver/arm-cortex-cpus.c Thu May 21 07:19:49 2015
@@ -205,6 +205,10 @@
 // RUN: %clang -target arm---eabihf -march=armbogusv7 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BOGUS-HF %s
 // CHECK-BOGUS-HF: error: the clang compiler does not support '-march=armbogusv7' 
 
+// ================== Check that a bogus CPU gives an error
+// RUN: %clang -target arm -mcpu=bogus -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-BOGUS-CPU %s
+// CHECK-BOGUS-CPU: error: the clang compiler does not support '-mcpu=bogus' 
+
 // ================== Check default Architecture on each ARM11 CPU
 // RUN: %clang -target arm-linux-gnueabi -mcpu=arm1136j-s -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV6 %s
 // RUN: %clang -target arm-linux-gnueabi -mcpu=arm1136jf-s -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CPUV6 %s





More information about the cfe-commits mailing list