Reinforce ARMTargetParser::getCanonicalArchName validation
authorRenato Golin <renato.golin@linaro.org>
Fri, 22 May 2015 20:43:30 +0000 (20:43 +0000)
committerRenato Golin <renato.golin@linaro.org>
Fri, 22 May 2015 20:43:30 +0000 (20:43 +0000)
Before, getCanonicalArchName was relying on parseArch() to validate the arch
name, which was a problem when other methods, that also needed to call it,
were duplicating the steps.

But to dissociate getCanonicalArchName from parseArch, we needed to make
getCanonicalArchName more robust in detecting valid arch names. It's still
not perfect, but will do for the time being, until we merge Triple with
TargetParser into a TargetDescription mega class.

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

lib/Support/TargetParser.cpp

index 590a1458558d1a487a9c9edd0da788165ff5deeb..a3998d2d13ea9a4430aed53daaf5c1fd69c66b2f 100644 (file)
@@ -16,6 +16,7 @@
 #include "llvm/Support/TargetParser.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSwitch.h"
+#include <cctype>
 
 using namespace llvm;
 
@@ -279,14 +280,17 @@ StringRef ARMTargetParser::getArchSynonym(StringRef Arch) {
 
 // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
 // (iwmmxt|xscale)(eb)? is also permitted. If the former, return
-// "v.+", if the latter, return unmodified string. If invalid, return "".
+// "v.+", if the latter, return unmodified string, minus 'eb'.
+// If invalid, return empty string.
 StringRef ARMTargetParser::getCanonicalArchName(StringRef Arch) {
   size_t offset = StringRef::npos;
   StringRef A = Arch;
   StringRef Error = "";
 
   // Begins with "arm" / "thumb", move past it.
-  if (A.startswith("arm"))
+  if (A.startswith("arm64"))
+    offset = 5;
+  else if (A.startswith("arm"))
     offset = 3;
   else if (A.startswith("thumb"))
     offset = 5;
@@ -305,21 +309,25 @@ StringRef ARMTargetParser::getCanonicalArchName(StringRef Arch) {
   // Or, if it ends with eb ("armv7eb"), chop it off.
   else if (A.endswith("eb"))
     A = A.substr(0, A.size() - 2);
-  // Reached the end or a 'v', canonicalise.
-  if (offset != StringRef::npos && (offset == A.size() || A[offset] == 'v'))
+  // Trim the head
+  if (offset != StringRef::npos)
     A = A.substr(offset);
 
-  // Empty string mans offset reached the end. Although valid, this arch
-  // will not have a match in the table. Return the original string.
+  // Empty string means offset reached the end, which means it's valid.
   if (A.empty())
     return Arch;
 
-  // If can't find the arch, return an empty StringRef.
-  if (parseArch(A) == ARM::AK_INVALID)
-    return Error;
+  // Only match non-marketing names
+  if (offset != StringRef::npos) {
+  // Must start with 'vN'.
+    if (A[0] != 'v' || !std::isdigit(A[1]))
+      return Error;
+    // Can't have an extra 'eb'.
+    if (A.find("eb") != StringRef::npos)
+      return Error;
+  }
 
-  // Arch will either be a 'v' name (v7a) or a marketing name (xscale)
-  // or empty, if invalid.
+  // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
   return A;
 }
 
@@ -390,7 +398,6 @@ unsigned ARMTargetParser::parseArchEndian(StringRef Arch) {
 
 // Profile A/R/M
 unsigned ARMTargetParser::parseArchProfile(StringRef Arch) {
-  // FIXME: We're running parseArch twice.
   Arch = getCanonicalArchName(Arch);
   switch(parseArch(Arch)) {
   case ARM::AK_ARMV6M:
@@ -409,9 +416,8 @@ unsigned ARMTargetParser::parseArchProfile(StringRef Arch) {
   return ARM::PK_INVALID;
 }
 
-// Version number 4 ~ 8 (ex. v7 = 7).
+// Version number (ex. v7 = 7).
 unsigned ARMTargetParser::parseArchVersion(StringRef Arch) {
-  // FIXME: We're running parseArch twice.
   Arch = getCanonicalArchName(Arch);
   switch(parseArch(Arch)) {
   case ARM::AK_ARMV2: