[ARM] Reject invalid -march values
authorJohn Brawn <john.brawn@arm.com>
Fri, 8 May 2015 12:52:02 +0000 (12:52 +0000)
committerJohn Brawn <john.brawn@arm.com>
Fri, 8 May 2015 12:52:02 +0000 (12:52 +0000)
Restructure Triple::getARMCPUForArch so that invalid values will
return nullptr, while retaining the behaviour that an argument
specifying no particular architecture version will give a default
CPU. This will be used by clang to give an error on invalid -march
values.

Also restructure the extraction of the architecture version from
the MArch string a little to hopefully make what it's doing clearer.

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236845 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Support/Triple.cpp
unittests/ADT/TripleTest.cpp

index 0a10a48557e4f97f2f90ac9ba1262f2a3985fdf3..dd7423e46a8869768450fcd896dc4038ba8754d5 100644 (file)
@@ -1088,18 +1088,52 @@ const char *Triple::getARMCPUForArch(StringRef MArch) const {
     break;
   }
 
+  // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?
+  // Only the (v.+) part is relevant for determining the CPU, as it determines
+  // the architecture version, so we first remove the surrounding parts.
+  // (ep9312|iwmmxt|xscale)(eb)? is also permitted, so we have to be a bit
+  // careful when removing the leading (arm|thumb)?(eb)? as we don't want to
+  // permit things like armep9312.
   const char *result = nullptr;
   size_t offset = StringRef::npos;
   if (MArch.startswith("arm"))
     offset = 3;
-  if (MArch.startswith("thumb"))
+  else if (MArch.startswith("thumb"))
     offset = 5;
   if (offset != StringRef::npos && MArch.substr(offset, 2) == "eb")
     offset += 2;
-  if (MArch.endswith("eb"))
+  else if (MArch.endswith("eb"))
     MArch = MArch.substr(0, MArch.size() - 2);
-  if (offset != StringRef::npos)
-    result = llvm::StringSwitch<const char *>(MArch.substr(offset))
+  if (offset != StringRef::npos && (offset == MArch.size() || MArch[offset] == 'v'))
+    MArch = MArch.substr(offset);
+
+  if (MArch == "") {
+    // If no specific architecture version is requested, return the minimum CPU
+    // required by the OS and environment.
+    switch (getOS()) {
+    case llvm::Triple::NetBSD:
+      switch (getEnvironment()) {
+      case llvm::Triple::GNUEABIHF:
+      case llvm::Triple::GNUEABI:
+      case llvm::Triple::EABIHF:
+      case llvm::Triple::EABI:
+        return "arm926ej-s";
+      default:
+        return "strongarm";
+      }
+    case llvm::Triple::NaCl:
+      return "cortex-a8";
+    default:
+      switch (getEnvironment()) {
+      case llvm::Triple::EABIHF:
+      case llvm::Triple::GNUEABIHF:
+        return "arm1176jzf-s";
+      default:
+        return "arm7tdmi";
+      }
+    }
+  } else {
+    result = llvm::StringSwitch<const char *>(MArch)
       .Cases("v2", "v2a", "arm2")
       .Case("v3", "arm6")
       .Case("v3m", "arm7m")
@@ -1120,40 +1154,11 @@ const char *Triple::getARMCPUForArch(StringRef MArch) const {
       .Cases("v7em", "v7e-m", "cortex-m4")
       .Cases("v8", "v8a", "v8-a", "cortex-a53")
       .Cases("v8.1a", "v8.1-a", "generic")
-      .Default(nullptr);
-  else
-    result = llvm::StringSwitch<const char *>(MArch)
       .Case("ep9312", "ep9312")
       .Case("iwmmxt", "iwmmxt")
       .Case("xscale", "xscale")
       .Default(nullptr);
-
-  if (result)
-    return result;
-
-  // If all else failed, return the most base CPU with thumb interworking
-  // supported by LLVM.
-  // FIXME: Should warn once that we're falling back.
-  switch (getOS()) {
-  case llvm::Triple::NetBSD:
-    switch (getEnvironment()) {
-    case llvm::Triple::GNUEABIHF:
-    case llvm::Triple::GNUEABI:
-    case llvm::Triple::EABIHF:
-    case llvm::Triple::EABI:
-      return "arm926ej-s";
-    default:
-      return "strongarm";
-    }
-  case llvm::Triple::NaCl:
-    return "cortex-a8";
-  default:
-    switch (getEnvironment()) {
-    case llvm::Triple::EABIHF:
-    case llvm::Triple::GNUEABIHF:
-      return "arm1176jzf-s";
-    default:
-      return "arm7tdmi";
-    }
   }
+
+  return result;
 }
index 96050374221855400025de7307b4661bd1707a63..d168097d54062bbf72655125357ccc54141ca86b 100644 (file)
@@ -705,6 +705,37 @@ TEST(TripleTest, getARMCPUForArch) {
     llvm::Triple Triple("arm--nacl");
     EXPECT_STREQ("cortex-a8", Triple.getARMCPUForArch("arm"));
   }
+  // armebv6 and armv6eb are permitted, but armebv6eb is not
+  {
+    llvm::Triple Triple("armebv6-non-eabi");
+    EXPECT_STREQ("arm1136jf-s", Triple.getARMCPUForArch());
+  }
+  {
+    llvm::Triple Triple("armv6eb-none-eabi");
+    EXPECT_STREQ("arm1136jf-s", Triple.getARMCPUForArch());
+  }
+  {
+    llvm::Triple Triple("armebv6eb-none-eabi");
+    EXPECT_EQ(nullptr, Triple.getARMCPUForArch());
+  }
+  // armeb is permitted, but armebeb is not
+  {
+    llvm::Triple Triple("armeb-none-eabi");
+    EXPECT_STREQ("arm7tdmi", Triple.getARMCPUForArch());
+  }
+  {
+    llvm::Triple Triple("armebeb-none-eabi");
+    EXPECT_EQ(nullptr, Triple.getARMCPUForArch());
+  }
+  // xscaleeb is permitted, but armebxscale is not
+  {
+    llvm::Triple Triple("xscaleeb-none-eabi");
+    EXPECT_STREQ("xscale", Triple.getARMCPUForArch());
+  }
+  {
+    llvm::Triple Triple("armebxscale-none-eabi");
+    EXPECT_EQ(nullptr, Triple.getARMCPUForArch());
+  }
 }
 
 TEST(TripleTest, NormalizeARM) {