From b6ea67e0277ba554eb61fc864c5b828d4b0c0f89 Mon Sep 17 00:00:00 2001 From: Renato Golin Date: Thu, 21 May 2015 13:52:20 +0000 Subject: [PATCH] Make Triple::parseARMArch use ARMTargetParser 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 | 20 +++++++ lib/Support/TargetParser.cpp | 47 ++++++++++++++- lib/Support/Triple.cpp | 92 ++++++++++++++--------------- unittests/ADT/TripleTest.cpp | 65 ++++++++++++++++++++ 4 files changed, 174 insertions(+), 50 deletions(-) diff --git a/include/llvm/Support/TargetParser.h b/include/llvm/Support/TargetParser.h index 8dedc2c07e9..f588105b2e9 100644 --- a/include/llvm/Support/TargetParser.h +++ b/include/llvm/Support/TargetParser.h @@ -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 diff --git a/lib/Support/TargetParser.cpp b/lib/Support/TargetParser.cpp index e32937e8499..55f0040a786 100644 --- a/lib/Support/TargetParser.cpp +++ b/lib/Support/TargetParser.cpp @@ -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(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 diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp index 02ccfd31242..b862dbd2a74 100644 --- a/lib/Support/Triple.cpp +++ b/lib/Support/Triple.cpp @@ -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(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) { diff --git a/unittests/ADT/TripleTest.cpp b/unittests/ADT/TripleTest.cpp index a1b2212dea7..4af3bfe9489 100644 --- a/unittests/ADT/TripleTest.cpp +++ b/unittests/ADT/TripleTest.cpp @@ -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 -- 2.34.1