Make Triple::parseARMArch use ARMTargetParser
authorRenato Golin <renato.golin@linaro.org>
Thu, 21 May 2015 13:52:20 +0000 (13:52 +0000)
committerRenato Golin <renato.golin@linaro.org>
Thu, 21 May 2015 13:52:20 +0000 (13:52 +0000)
Simplifying Triple::parseARMArch, leaving all the parsing to ARMTargetParser.

This commit also adds AArch64 detection to ARMTargetParser canonicalization,
and a two RedHat arch names (v{6,7}hl, meaning hard-float / little-endian).

Adding enough unit tests to cover the basics. Clang checks fine.

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

include/llvm/Support/TargetParser.h
lib/Support/TargetParser.cpp
lib/Support/Triple.cpp
unittests/ADT/TripleTest.cpp

index 8dedc2c..f588105 100644 (file)
@@ -76,7 +76,9 @@ namespace ARM {
     AK_ARMV5E,
     AK_ARMV5TEJ,
     AK_ARMV6SM,
+    AK_ARMV6HL,
     AK_ARMV7L,
+    AK_ARMV7HL,
     AK_ARMV7S,
     AK_ARMV7EM,
     AK_LAST
@@ -95,6 +97,21 @@ namespace ARM {
     AEK_LAST
   };
 
+  // ISA kinds.
+  enum ISAKind {
+    IK_INVALID = 0,
+    IK_ARM,
+    IK_THUMB,
+    IK_AARCH64
+  };
+
+  // Endianness
+  // FIXME: BE8 vs. BE32?
+  enum EndianKind {
+    EK_INVALID = 0,
+    EK_LITTLE,
+    EK_BIG
+  };
 } // namespace ARM
 
 // Target Parsers, one per architecture.
@@ -118,6 +135,9 @@ public:
   static unsigned parseArch(StringRef Arch);
   static unsigned parseArchExt(StringRef ArchExt);
   static unsigned parseCPUArch(StringRef CPU);
+  static unsigned parseArchISA(StringRef Arch);
+  static unsigned parseArchEndian(StringRef Arch);
+
 };
 
 } // namespace llvm
index e32937e..55f0040 100644 (file)
@@ -80,8 +80,10 @@ struct {
   { "armv5e",    ARM::AK_ARMV5E,   "5E",      ARMBuildAttrs::CPUArch::v5TE },
   { "armv5tej",  ARM::AK_ARMV5TEJ, "5TE",     ARMBuildAttrs::CPUArch::v5TE },
   { "armv6sm",   ARM::AK_ARMV6SM,  "6-M",     ARMBuildAttrs::CPUArch::v6_M },
+  { "armv6hl",   ARM::AK_ARMV6HL,  "6-M",     ARMBuildAttrs::CPUArch::v6_M },
   { "armv7e-m",  ARM::AK_ARMV7EM,  "7E-M",    ARMBuildAttrs::CPUArch::v7E_M },
   { "armv7l",    ARM::AK_ARMV7L,   "7-L",     ARMBuildAttrs::CPUArch::v7 },
+  { "armv7hl",   ARM::AK_ARMV7HL,  "7H-L",    ARMBuildAttrs::CPUArch::v7 },
   { "armv7s",    ARM::AK_ARMV7S,   "7-S",     ARMBuildAttrs::CPUArch::v7 }
 };
 // List of canonical ARCH names (use getARCHSynonym)
@@ -179,7 +181,9 @@ struct {
   { "arm1022e",      ARM::AK_ARMV5E,   true },
   { "arm926ej-s",    ARM::AK_ARMV5TEJ, true },
   { "cortex-m0",     ARM::AK_ARMV6SM,  true },
+  { "arm1176jzf-s",  ARM::AK_ARMV6HL,  true },
   { "cortex-a8",     ARM::AK_ARMV7L,   true },
+  { "cortex-a8",     ARM::AK_ARMV7HL,  true },
   { "cortex-m4",     ARM::AK_ARMV7EM,  true },
   { "swift",         ARM::AK_ARMV7S,   true },
   // Invalid CPU
@@ -269,6 +273,7 @@ StringRef ARMTargetParser::getArchSynonym(StringRef Arch) {
     .Cases("armv8",    "v8",    "armv8-a")
     .Cases("armv8a",   "v8a",   "armv8-a")
     .Cases("armv8.1a", "v8.1a", "armv8.1-a")
+    .Cases("aarch64",  "arm64", "armv8-a")
     .Default(Arch);
 }
 
@@ -278,12 +283,22 @@ StringRef ARMTargetParser::getArchSynonym(StringRef Arch) {
 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"))
     offset = 3;
   else if (A.startswith("thumb"))
     offset = 5;
+  else if (A.startswith("aarch64")) {
+    offset = 7;
+    // AArch64 uses "_be", not "eb" suffix.
+    if (A.find("eb") != StringRef::npos)
+      return Error;
+    if (A.substr(offset,3) == "_be")
+      offset += 3;
+  }
+
   // Ex. "armebv7", move past the "eb".
   if (offset != StringRef::npos && A.substr(offset, 2) == "eb")
     offset += 2;
@@ -301,7 +316,7 @@ StringRef ARMTargetParser::getCanonicalArchName(StringRef Arch) {
 
   // If can't find the arch, return an empty StringRef.
   if (parseArch(A) == ARM::AK_INVALID)
-    A = A.substr(A.size());
+    return Error;
 
   // Arch will either be a 'v' name (v7a) or a marketing name (xscale)
   // or empty, if invalid.
@@ -343,4 +358,34 @@ unsigned ARMTargetParser::parseCPUArch(StringRef CPU) {
   return ARM::AK_INVALID;
 }
 
+// ARM, Thumb, AArch64
+unsigned ARMTargetParser::parseArchISA(StringRef Arch) {
+  return StringSwitch<unsigned>(Arch)
+      .StartsWith("aarch64", ARM::IK_AARCH64)
+      .StartsWith("arm64",   ARM::IK_AARCH64)
+      .StartsWith("thumb",   ARM::IK_THUMB)
+      .StartsWith("arm",     ARM::IK_ARM)
+      .Default(ARM::EK_INVALID);
+}
+
+// Little/Big endian
+unsigned ARMTargetParser::parseArchEndian(StringRef Arch) {
+  if (Arch.startswith("armeb") ||
+      Arch.startswith("thumbeb") ||
+      Arch.startswith("aarch64_be"))
+    return ARM::EK_BIG;
+
+  if (Arch.startswith("arm") || Arch.startswith("thumb")) {
+    if (Arch.endswith("eb"))
+      return ARM::EK_BIG;
+    else
+      return ARM::EK_LITTLE;
+  }
+
+  if (Arch.startswith("aarch64"))
+    return ARM::EK_LITTLE;
+
+  return ARM::EK_INVALID;
+}
+
 } // namespace llvm
index 02ccfd3..b862dbd 100644 (file)
@@ -236,60 +236,54 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
     .Default(UnknownArch);
 }
 
-// FIXME: Use ARMTargetParser. This would require Triple::arm/thumb
-// to be recogniseable universally.
 static Triple::ArchType parseARMArch(StringRef ArchName) {
-  size_t offset = StringRef::npos;
+  unsigned ISA = ARMTargetParser::parseArchISA(ArchName);
+  unsigned ENDIAN = ARMTargetParser::parseArchEndian(ArchName);
+
   Triple::ArchType arch = Triple::UnknownArch;
-  bool isThumb = ArchName.startswith("thumb");
-
-  if (ArchName.equals("arm"))
-    return Triple::arm;
-  if (ArchName.equals("armeb"))
-    return Triple::armeb;
-  if (ArchName.equals("thumb"))
-    return Triple::thumb;
-  if (ArchName.equals("thumbeb"))
-    return Triple::thumbeb;
-  if (ArchName.equals("arm64") || ArchName.equals("aarch64"))
-    return Triple::aarch64;
-  if (ArchName.equals("aarch64_be"))
-    return Triple::aarch64_be;
-
-  if (ArchName.startswith("armv")) {
-    offset = 3;
-    if (ArchName.endswith("eb")) {
-      arch = Triple::armeb;
-      ArchName = ArchName.substr(0, ArchName.size() - 2);
-    } else
+  switch (ENDIAN) {
+  case ARM::EK_LITTLE: {
+    switch (ISA) {
+    case ARM::IK_ARM:
       arch = Triple::arm;
-  } else if (ArchName.startswith("armebv")) {
-    offset = 5;
-    arch = Triple::armeb;
-  } else if (ArchName.startswith("thumbv")) {
-    offset = 5;
-    if (ArchName.endswith("eb")) {
-      arch = Triple::thumbeb;
-      ArchName = ArchName.substr(0, ArchName.size() - 2);
-    } else
+      break;
+    case ARM::IK_THUMB:
       arch = Triple::thumb;
-  } else if (ArchName.startswith("thumbebv")) {
-    offset = 7;
-    arch = Triple::thumbeb;
+      break;
+    case ARM::IK_AARCH64:
+      arch = Triple::aarch64;
+      break;
+    }
+    break;
   }
-  return StringSwitch<Triple::ArchType>(ArchName.substr(offset))
-    .Cases("v2", "v2a", isThumb ? Triple::UnknownArch : arch)
-    .Cases("v3", "v3m", isThumb ? Triple::UnknownArch : arch)
-    .Cases("v4", "v4t", arch)
-    .Cases("v5", "v5e", "v5t", "v5te", "v5tej", arch)
-    .Cases("v6", "v6hl", "v6j", "v6k", arch)
-    .Cases("v6m", "v6sm", arch)
-    .Cases("v6t2", "v6z", "v6zk", arch)
-    .Cases("v7", "v7a", "v7em", "v7hl", "v7l", arch)
-    .Cases("v7m", "v7r", "v7s", arch)
-    .Cases("v8", "v8a", arch)
-    .Cases("v8.1", "v8.1a", arch)
-    .Default(Triple::UnknownArch);
+  case ARM::EK_BIG: {
+    switch (ISA) {
+    case ARM::IK_ARM:
+      arch = Triple::armeb;
+      break;
+    case ARM::IK_THUMB:
+      arch = Triple::thumbeb;
+      break;
+    case ARM::IK_AARCH64:
+      arch = Triple::aarch64_be;
+      break;
+    }
+    break;
+  }
+  }
+
+  ArchName = ARMTargetParser::getCanonicalArchName(ArchName);
+  if (ArchName.empty())
+    return Triple::UnknownArch;
+
+  // Thumb only exists in v4+
+  if (ISA == ARM::IK_THUMB &&
+      (ArchName.startswith("v2") || ArchName.startswith("v3")))
+    return Triple::UnknownArch;
+
+  // FIXME: Add isMProfile to ARMTargetParser and
+  // either change armv6m to thumb or UnknownArch.
+  return arch;
 }
 
 static Triple::ArchType parseArch(StringRef ArchName) {
index a1b2212..4af3bfe 100644 (file)
@@ -878,4 +878,69 @@ TEST(TripleTest, NormalizeARM) {
   EXPECT_EQ(Triple::armeb, T.getArch());
 }
 
+TEST(TripleTest, ParseARMArch) {
+  // ARM
+  {
+    Triple T = Triple("arm");
+    EXPECT_EQ(Triple::arm, T.getArch());
+  }
+  {
+    Triple T = Triple("armv6t2");
+    EXPECT_EQ(Triple::arm, T.getArch());
+  }
+  {
+    Triple T = Triple("armv8");
+    EXPECT_EQ(Triple::arm, T.getArch());
+  }
+  {
+    Triple T = Triple("armeb");
+    EXPECT_EQ(Triple::armeb, T.getArch());
+  }
+  {
+    Triple T = Triple("armv5eb");
+    EXPECT_EQ(Triple::armeb, T.getArch());
+  }
+  // THUMB
+  {
+    Triple T = Triple("thumb");
+    EXPECT_EQ(Triple::thumb, T.getArch());
+  }
+  {
+    Triple T = Triple("thumbv7a");
+    EXPECT_EQ(Triple::thumb, T.getArch());
+  }
+  {
+    Triple T = Triple("thumbeb");
+    EXPECT_EQ(Triple::thumbeb, T.getArch());
+  }
+  {
+    Triple T = Triple("thumbv4teb");
+    EXPECT_EQ(Triple::thumbeb, T.getArch());
+  }
+  {
+    Triple T = Triple("thumbv2");
+    EXPECT_EQ(Triple::UnknownArch, T.getArch());
+  }
+  // AARCH64
+  {
+    Triple T = Triple("arm64");
+    EXPECT_EQ(Triple::aarch64, T.getArch());
+  }
+  {
+    Triple T = Triple("aarch64");
+    EXPECT_EQ(Triple::aarch64, T.getArch());
+  }
+  {
+    Triple T = Triple("aarch64_be");
+    EXPECT_EQ(Triple::aarch64_be, T.getArch());
+  }
+  {
+    Triple T = Triple("aarch64be");
+    EXPECT_EQ(Triple::UnknownArch, T.getArch());
+  }
+  {
+    Triple T = Triple("arm64be");
+    EXPECT_EQ(Triple::UnknownArch, T.getArch());
+  }
+}
 } // end anonymous namespace