diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index 06f5870119c..947812d94ec 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -569,6 +569,22 @@ public: /// architecture if no such variant can be found. llvm::Triple get64BitArchVariant() const; + /// Form a triple with a big endian variant of the current architecture. + /// + /// This can be used to move across "families" of architectures where useful. + /// + /// \returns A new triple with a big endian architecture or an unknown + /// architecture if no such variant can be found. + llvm::Triple getBigEndianArchVariant() const; + + /// Form a triple with a little endian variant of the current architecture. + /// + /// This can be used to move across "families" of architectures where useful. + /// + /// \returns A new triple with a little endian architecture or an unknown + /// architecture if no such variant can be found. + llvm::Triple getLittleEndianArchVariant() const; + /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting. /// /// \param Arch the architecture name (e.g., "armv7s"). If it is an empty diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp index 92be0e047f6..c6646fb101b 100644 --- a/lib/Support/Triple.cpp +++ b/lib/Support/Triple.cpp @@ -1165,6 +1165,122 @@ Triple Triple::get64BitArchVariant() const { return T; } +Triple Triple::getBigEndianArchVariant() const { + Triple T(*this); + switch (getArch()) { + case Triple::UnknownArch: + case Triple::amdgcn: + case Triple::amdil64: + case Triple::amdil: + case Triple::hexagon: + case Triple::hsail64: + case Triple::hsail: + case Triple::kalimba: + case Triple::le32: + case Triple::le64: + case Triple::msp430: + case Triple::nvptx64: + case Triple::nvptx: + case Triple::r600: + case Triple::shave: + case Triple::spir64: + case Triple::spir: + case Triple::wasm32: + case Triple::wasm64: + case Triple::x86: + case Triple::x86_64: + case Triple::xcore: + + // ARM is intentionally unsupported here, changing the architecture would + // drop any arch suffixes. + case Triple::arm: + case Triple::thumb: + T.setArch(UnknownArch); + break; + + case Triple::aarch64_be: + case Triple::armeb: + case Triple::bpfeb: + case Triple::mips64: + case Triple::mips: + case Triple::ppc64: + case Triple::ppc: + case Triple::sparc: + case Triple::sparcv9: + case Triple::systemz: + case Triple::tce: + case Triple::thumbeb: + // Already big endian. + break; + + case Triple::aarch64: T.setArch(Triple::aarch64_be); break; + case Triple::bpfel: T.setArch(Triple::bpfeb); break; + case Triple::mips64el:T.setArch(Triple::mips64); break; + case Triple::mipsel: T.setArch(Triple::mips); break; + case Triple::ppc64le: T.setArch(Triple::ppc64); break; + case Triple::sparcel: T.setArch(Triple::sparc); break; + } + return T; +} + +Triple Triple::getLittleEndianArchVariant() const { + Triple T(*this); + switch (getArch()) { + case Triple::UnknownArch: + case Triple::ppc: + case Triple::sparcv9: + case Triple::systemz: + case Triple::tce: + + // ARM is intentionally unsupported here, changing the architecture would + // drop any arch suffixes. + case Triple::armeb: + case Triple::thumbeb: + T.setArch(UnknownArch); + break; + + case Triple::aarch64: + case Triple::amdgcn: + case Triple::amdil64: + case Triple::amdil: + case Triple::arm: + case Triple::bpfel: + case Triple::hexagon: + case Triple::hsail64: + case Triple::hsail: + case Triple::kalimba: + case Triple::le32: + case Triple::le64: + case Triple::mips64el: + case Triple::mipsel: + case Triple::msp430: + case Triple::nvptx64: + case Triple::nvptx: + case Triple::ppc64le: + case Triple::r600: + case Triple::shave: + case Triple::sparcel: + case Triple::spir64: + case Triple::spir: + case Triple::thumb: + case Triple::wasm32: + case Triple::wasm64: + case Triple::x86: + case Triple::x86_64: + case Triple::xcore: + // Already little endian. + break; + + case Triple::aarch64_be: T.setArch(Triple::aarch64); break; + case Triple::bpfeb: T.setArch(Triple::bpfel); break; + case Triple::mips64: T.setArch(Triple::mips64el); break; + case Triple::mips: T.setArch(Triple::mipsel); break; + case Triple::ppc64: T.setArch(Triple::ppc64le); break; + case Triple::sparc: T.setArch(Triple::sparcel); break; + } + return T; +} + const char *Triple::getARMCPUForArch(StringRef MArch) const { if (MArch.empty()) MArch = getArchName(); diff --git a/unittests/ADT/TripleTest.cpp b/unittests/ADT/TripleTest.cpp index d50768412d7..2b1e871b94c 100644 --- a/unittests/ADT/TripleTest.cpp +++ b/unittests/ADT/TripleTest.cpp @@ -553,6 +553,84 @@ TEST(TripleTest, BitWidthArchVariants) { EXPECT_EQ(Triple::wasm64, T.get64BitArchVariant().getArch()); } +TEST(TripleTest, EndianArchVariants) { + Triple T; + EXPECT_EQ(Triple::UnknownArch, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::UnknownArch, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::UnknownArch); + EXPECT_EQ(Triple::UnknownArch, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::UnknownArch, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::aarch64_be); + EXPECT_EQ(Triple::aarch64_be, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::aarch64, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::aarch64); + EXPECT_EQ(Triple::aarch64_be, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::aarch64, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::armeb); + EXPECT_EQ(Triple::armeb, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::UnknownArch, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::arm); + EXPECT_EQ(Triple::UnknownArch, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::arm, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::bpfeb); + EXPECT_EQ(Triple::bpfeb, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::bpfel, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::bpfel); + EXPECT_EQ(Triple::bpfeb, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::bpfel, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::mips64); + EXPECT_EQ(Triple::mips64, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::mips64el, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::mips64el); + EXPECT_EQ(Triple::mips64, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::mips64el, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::mips); + EXPECT_EQ(Triple::mips, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::mipsel, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::mipsel); + EXPECT_EQ(Triple::mips, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::mipsel, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::ppc); + EXPECT_EQ(Triple::ppc, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::UnknownArch, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::ppc64); + EXPECT_EQ(Triple::ppc64, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::ppc64le, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::ppc64le); + EXPECT_EQ(Triple::ppc64, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::ppc64le, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::sparc); + EXPECT_EQ(Triple::sparc, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::sparcel, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::sparcel); + EXPECT_EQ(Triple::sparc, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::sparcel, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::thumb); + EXPECT_EQ(Triple::UnknownArch, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::thumb, T.getLittleEndianArchVariant().getArch()); + + T.setArch(Triple::thumbeb); + EXPECT_EQ(Triple::thumbeb, T.getBigEndianArchVariant().getArch()); + EXPECT_EQ(Triple::UnknownArch, T.getLittleEndianArchVariant().getArch()); +} + TEST(TripleTest, getOSVersion) { Triple T; unsigned Major, Minor, Micro;