From 3adc8af0ca67f42bbf2d9ef4b939c349ad9c7e34 Mon Sep 17 00:00:00 2001 From: Brandon Bergren Date: Sat, 2 Jan 2021 12:17:22 -0600 Subject: [PATCH] [PowerPC] Add the LLVM triple for powerpcle [1/5] Add a triple for powerpcle-*-*. This is a little-endian encoding of the 32-bit PowerPC ABI, useful in certain niche situations: 1) A loader such as the FreeBSD loader which will be loading a little endian kernel. This is required for PowerPC64LE to load properly in pseries VMs. Such a loader is implemented as a freestanding ELF32 LSB binary. 2) Userspace emulation of a 32-bit LE architecture such as x86 on 64-bit hosts such as PowerPC64LE with tools like box86 requires having a 32-bit LE toolchain and library set, as they operate by translating only the main binary and switching to native code when making library calls. 3) The Void Linux for PowerPC project is experimenting with running an entire powerpcle userland. Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D93918 --- cmake/config.guess | 3 +++ include/llvm/ADT/Triple.h | 12 ++++++++++++ lib/CodeGen/TargetLoweringBase.cpp | 2 +- lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 1 + .../RuntimeDyld/RuntimeDyldELF.cpp | 3 ++- lib/Support/Triple.cpp | 17 ++++++++++++++--- lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 5 +++-- .../PowerPC/Disassembler/PPCDisassembler.cpp | 2 ++ .../PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp | 5 +++-- .../PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp | 4 ++-- lib/Target/PowerPC/PPCAsmPrinter.cpp | 2 ++ lib/Target/PowerPC/PPCSubtarget.cpp | 3 ++- lib/Target/PowerPC/PPCTargetMachine.cpp | 9 +++++---- .../PowerPC/TargetInfo/PowerPCTargetInfo.cpp | 9 ++++++++- .../PowerPC/TargetInfo/PowerPCTargetInfo.h | 1 + unittests/ADT/TripleTest.cpp | 2 +- 16 files changed, 62 insertions(+), 18 deletions(-) diff --git a/cmake/config.guess b/cmake/config.guess index 9fdfcce8d03..60d3f588d6f 100644 --- a/cmake/config.guess +++ b/cmake/config.guess @@ -973,6 +973,9 @@ EOF ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-gnu + exit ;; riscv32:Linux:*:* | riscv64:Linux:*:*) LIBC=gnu eval $set_cc_for_build diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index 6e2957f3c32..f6f01557735 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -64,6 +64,7 @@ public: mips64el, // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el msp430, // MSP430: msp430 ppc, // PPC: powerpc + ppcle, // PPCLE: powerpc (little endian) ppc64, // PPC64: powerpc64, ppu ppc64le, // PPC64LE: powerpc64le r600, // R600: AMD GPUs HD2XXX - HD6XXX @@ -745,6 +746,17 @@ public: return isMIPS32() || isMIPS64(); } + /// Tests whether the target is PowerPC (32- or 64-bit LE or BE). + bool isPPC() const { + return getArch() == Triple::ppc || getArch() == Triple::ppc64 || + getArch() == Triple::ppcle || getArch() == Triple::ppc64le; + } + + /// Tests whether the target is 32-bit PowerPC (little and big endian). + bool isPPC32() const { + return getArch() == Triple::ppc || getArch() == Triple::ppcle; + } + /// Tests whether the target is 64-bit PowerPC (little and big endian). bool isPPC64() const { return getArch() == Triple::ppc64 || getArch() == Triple::ppc64le; diff --git a/lib/CodeGen/TargetLoweringBase.cpp b/lib/CodeGen/TargetLoweringBase.cpp index 5797006c76f..6cacb10ab79 100644 --- a/lib/CodeGen/TargetLoweringBase.cpp +++ b/lib/CodeGen/TargetLoweringBase.cpp @@ -135,7 +135,7 @@ void TargetLoweringBase::InitLibcalls(const Triple &TT) { setLibcallCallingConv((RTLIB::Libcall)LC, CallingConv::C); // For IEEE quad-precision libcall names, PPC uses "kf" instead of "tf". - if (TT.getArch() == Triple::ppc || TT.isPPC64()) { + if (TT.isPPC()) { setLibcallName(RTLIB::ADD_F128, "__addkf3"); setLibcallName(RTLIB::SUB_F128, "__subkf3"); setLibcallName(RTLIB::MUL_F128, "__mulkf3"); diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 6567aaaa3d8..7bc5c98b89b 100644 --- a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -128,6 +128,7 @@ void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx, // Fallthrough if not using EHABI LLVM_FALLTHROUGH; case Triple::ppc: + case Triple::ppcle: case Triple::x86: PersonalityEncoding = isPositionIndependent() ? dwarf::DW_EH_PE_indirect | diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index c1e27410ce3..dc396ae4c21 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -954,7 +954,8 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, resolveARMRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type, (uint32_t)(Addend & 0xffffffffL)); break; - case Triple::ppc: + case Triple::ppc: // Fall through. + case Triple::ppcle: resolvePPC32Relocation(Section, Offset, Value, Type, Addend); break; case Triple::ppc64: // Fall through. diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp index fb1e84f44f6..86208764806 100644 --- a/lib/Support/Triple.cpp +++ b/lib/Support/Triple.cpp @@ -54,6 +54,7 @@ StringRef Triple::getArchTypeName(ArchType Kind) { case ppc64: return "powerpc64"; case ppc64le: return "powerpc64le"; case ppc: return "powerpc"; + case ppcle: return "powerpcle"; case r600: return "r600"; case renderscript32: return "renderscript32"; case renderscript64: return "renderscript64"; @@ -101,7 +102,8 @@ StringRef Triple::getArchTypePrefix(ArchType Kind) { case ppc64: case ppc64le: - case ppc: return "ppc"; + case ppc: + case ppcle: return "ppc"; case mips: case mipsel: @@ -286,6 +288,8 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { .Case("ppc64", ppc64) .Case("ppc32", ppc) .Case("ppc", ppc) + .Case("ppc32le", ppcle) + .Case("ppcle", ppcle) .Case("ppc64le", ppc64le) .Case("r600", r600) .Case("amdgcn", amdgcn) @@ -397,6 +401,7 @@ static Triple::ArchType parseArch(StringRef ArchName) { .Cases("i786", "i886", "i986", Triple::x86) .Cases("amd64", "x86_64", "x86_64h", Triple::x86_64) .Cases("powerpc", "powerpcspe", "ppc", "ppc32", Triple::ppc) + .Cases("powerpcle", "ppcle", "ppc32le", Triple::ppcle) .Cases("powerpc64", "ppu", "ppc64", Triple::ppc64) .Cases("powerpc64le", "ppc64le", Triple::ppc64le) .Case("xscale", Triple::arm) @@ -704,6 +709,7 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) { case Triple::nvptx64: case Triple::nvptx: case Triple::ppc64le: + case Triple::ppcle: case Triple::r600: case Triple::renderscript32: case Triple::renderscript64: @@ -1272,6 +1278,7 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) { case llvm::Triple::mipsel: case llvm::Triple::nvptx: case llvm::Triple::ppc: + case llvm::Triple::ppcle: case llvm::Triple::r600: case llvm::Triple::renderscript32: case llvm::Triple::riscv32: @@ -1335,7 +1342,6 @@ Triple Triple::get32BitArchVariant() const { case Triple::bpfeb: case Triple::bpfel: case Triple::msp430: - case Triple::ppc64le: case Triple::systemz: case Triple::ve: T.setArch(UnknownArch); @@ -1356,6 +1362,7 @@ Triple Triple::get32BitArchVariant() const { case Triple::mipsel: case Triple::nvptx: case Triple::ppc: + case Triple::ppcle: case Triple::r600: case Triple::renderscript32: case Triple::riscv32: @@ -1382,6 +1389,7 @@ Triple Triple::get32BitArchVariant() const { case Triple::mips64el: T.setArch(Triple::mipsel); break; case Triple::nvptx64: T.setArch(Triple::nvptx); break; case Triple::ppc64: T.setArch(Triple::ppc); break; + case Triple::ppc64le: T.setArch(Triple::ppcle); break; case Triple::renderscript64: T.setArch(Triple::renderscript32); break; case Triple::riscv64: T.setArch(Triple::riscv32); break; case Triple::sparcv9: T.setArch(Triple::sparc); break; @@ -1446,6 +1454,7 @@ Triple Triple::get64BitArchVariant() const { case Triple::mipsel: T.setArch(Triple::mips64el); break; case Triple::nvptx: T.setArch(Triple::nvptx64); break; case Triple::ppc: T.setArch(Triple::ppc64); break; + case Triple::ppcle: T.setArch(Triple::ppc64le); break; case Triple::renderscript32: T.setArch(Triple::renderscript64); break; case Triple::riscv32: T.setArch(Triple::riscv64); break; case Triple::sparc: T.setArch(Triple::sparcv9); break; @@ -1505,6 +1514,7 @@ Triple Triple::getBigEndianArchVariant() const { 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::ppcle: T.setArch(Triple::ppc); break; case Triple::ppc64le: T.setArch(Triple::ppc64); break; case Triple::sparcel: T.setArch(Triple::sparc); break; case Triple::tcele: T.setArch(Triple::tce); break; @@ -1522,7 +1532,6 @@ Triple Triple::getLittleEndianArchVariant() const { switch (getArch()) { case Triple::UnknownArch: case Triple::lanai: - case Triple::ppc: case Triple::sparcv9: case Triple::systemz: @@ -1537,6 +1546,7 @@ Triple Triple::getLittleEndianArchVariant() const { 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::ppc: T.setArch(Triple::ppcle); break; case Triple::ppc64: T.setArch(Triple::ppc64le); break; case Triple::sparc: T.setArch(Triple::sparcel); break; case Triple::tce: T.setArch(Triple::tcele); break; @@ -1568,6 +1578,7 @@ bool Triple::isLittleEndian() const { case Triple::msp430: case Triple::nvptx64: case Triple::nvptx: + case Triple::ppcle: case Triple::ppc64le: case Triple::r600: case Triple::renderscript32: diff --git a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index 085acffdb5f..97fad66547f 100644 --- a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -1716,8 +1716,9 @@ bool PPCAsmParser::ParseDirectiveLocalEntry(SMLoc L) { /// Force static initialization. extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCAsmParser() { RegisterMCAsmParser A(getThePPC32Target()); - RegisterMCAsmParser B(getThePPC64Target()); - RegisterMCAsmParser C(getThePPC64LETarget()); + RegisterMCAsmParser B(getThePPC32LETarget()); + RegisterMCAsmParser C(getThePPC64Target()); + RegisterMCAsmParser D(getThePPC64LETarget()); } #define GET_REGISTER_MATCHER diff --git a/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp b/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp index cc9ffc94ead..3e9286fb0b3 100644 --- a/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp +++ b/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp @@ -54,6 +54,8 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCDisassembler() { // Register the disassembler for each target. TargetRegistry::RegisterMCDisassembler(getThePPC32Target(), createPPCDisassembler); + TargetRegistry::RegisterMCDisassembler(getThePPC32LETarget(), + createPPCLEDisassembler); TargetRegistry::RegisterMCDisassembler(getThePPC64Target(), createPPCDisassembler); TargetRegistry::RegisterMCDisassembler(getThePPC64LETarget(), diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp index 593dc2843c3..2b76af279ce 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp @@ -26,7 +26,8 @@ PPCELFMCAsmInfo::PPCELFMCAsmInfo(bool is64Bit, const Triple& T) { if (is64Bit) { CodePointerSize = CalleeSaveStackSlotSize = 8; } - IsLittleEndian = T.getArch() == Triple::ppc64le; + IsLittleEndian = + T.getArch() == Triple::ppc64le || T.getArch() == Triple::ppcle; // ".comm align is in bytes but .align is pow-2." AlignmentIsInBytes = false; @@ -56,7 +57,7 @@ PPCELFMCAsmInfo::PPCELFMCAsmInfo(bool is64Bit, const Triple& T) { void PPCXCOFFMCAsmInfo::anchor() {} PPCXCOFFMCAsmInfo::PPCXCOFFMCAsmInfo(bool Is64Bit, const Triple &T) { - if (T.getArch() == Triple::ppc64le) + if (T.getArch() == Triple::ppc64le || T.getArch() == Triple::ppcle) report_fatal_error("XCOFF is not supported for little-endian targets"); CodePointerSize = CalleeSaveStackSlotSize = Is64Bit ? 8 : 4; diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp index bcc5d877f56..7629fe565bf 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp @@ -336,8 +336,8 @@ static MCInstPrinter *createPPCMCInstPrinter(const Triple &T, } extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTargetMC() { - for (Target *T : - {&getThePPC32Target(), &getThePPC64Target(), &getThePPC64LETarget()}) { + for (Target *T : {&getThePPC32Target(), &getThePPC32LETarget(), + &getThePPC64Target(), &getThePPC64LETarget()}) { // Register the MC asm info. RegisterMCAsmInfoFn C(*T, createPPCMCAsmInfo); diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index 87c4d1bd3eb..34fd0b883d2 100644 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -2373,6 +2373,8 @@ createPPCAsmPrinterPass(TargetMachine &tm, extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCAsmPrinter() { TargetRegistry::RegisterAsmPrinter(getThePPC32Target(), createPPCAsmPrinterPass); + TargetRegistry::RegisterAsmPrinter(getThePPC32LETarget(), + createPPCAsmPrinterPass); TargetRegistry::RegisterAsmPrinter(getThePPC64Target(), createPPCAsmPrinterPass); TargetRegistry::RegisterAsmPrinter(getThePPC64LETarget(), diff --git a/lib/Target/PowerPC/PPCSubtarget.cpp b/lib/Target/PowerPC/PPCSubtarget.cpp index 1afed172e14..4bbcef13b4f 100644 --- a/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/lib/Target/PowerPC/PPCSubtarget.cpp @@ -179,7 +179,8 @@ void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { // Determine endianness. // FIXME: Part of the TargetMachine. - IsLittleEndian = (TargetTriple.getArch() == Triple::ppc64le); + IsLittleEndian = (TargetTriple.getArch() == Triple::ppc64le || + TargetTriple.getArch() == Triple::ppcle); } bool PPCSubtarget::enableMachineScheduler() const { return true; } diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp index c3fb350ab82..b7ebc8dfa25 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -100,8 +100,9 @@ static cl::opt extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTarget() { // Register the targets RegisterTargetMachine A(getThePPC32Target()); - RegisterTargetMachine B(getThePPC64Target()); - RegisterTargetMachine C(getThePPC64LETarget()); + RegisterTargetMachine B(getThePPC32LETarget()); + RegisterTargetMachine C(getThePPC64Target()); + RegisterTargetMachine D(getThePPC64LETarget()); PassRegistry &PR = *PassRegistry::getPassRegistry(); #ifndef NDEBUG @@ -130,8 +131,8 @@ static std::string getDataLayoutString(const Triple &T) { bool is64Bit = T.getArch() == Triple::ppc64 || T.getArch() == Triple::ppc64le; std::string Ret; - // Most PPC* platforms are big endian, PPC64LE is little endian. - if (T.getArch() == Triple::ppc64le) + // Most PPC* platforms are big endian, PPC(64)LE is little endian. + if (T.getArch() == Triple::ppc64le || T.getArch() == Triple::ppcle) Ret = "e"; else Ret = "E"; diff --git a/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp b/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp index 649bd648a6c..6bb952f27fe 100644 --- a/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp +++ b/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp @@ -14,6 +14,10 @@ Target &llvm::getThePPC32Target() { static Target ThePPC32Target; return ThePPC32Target; } +Target &llvm::getThePPC32LETarget() { + static Target ThePPC32LETarget; + return ThePPC32LETarget; +} Target &llvm::getThePPC64Target() { static Target ThePPC64Target; return ThePPC64Target; @@ -24,9 +28,12 @@ Target &llvm::getThePPC64LETarget() { } extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTargetInfo() { - RegisterTarget X(getThePPC32Target(), "ppc32", + RegisterTarget W(getThePPC32Target(), "ppc32", "PowerPC 32", "PPC"); + RegisterTarget X( + getThePPC32LETarget(), "ppc32le", "PowerPC 32 LE", "PPC"); + RegisterTarget Y(getThePPC64Target(), "ppc64", "PowerPC 64", "PPC"); diff --git a/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.h b/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.h index 2d0afbfb1be..f9d20ef00df 100644 --- a/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.h +++ b/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.h @@ -14,6 +14,7 @@ namespace llvm { class Target; Target &getThePPC32Target(); +Target &getThePPC32LETarget(); Target &getThePPC64Target(); Target &getThePPC64LETarget(); diff --git a/unittests/ADT/TripleTest.cpp b/unittests/ADT/TripleTest.cpp index 7a356ae999c..ffce07ba2b1 100644 --- a/unittests/ADT/TripleTest.cpp +++ b/unittests/ADT/TripleTest.cpp @@ -1111,7 +1111,7 @@ TEST(TripleTest, EndianArchVariants) { T.setArch(Triple::ppc); EXPECT_EQ(Triple::ppc, T.getBigEndianArchVariant().getArch()); - EXPECT_EQ(Triple::UnknownArch, T.getLittleEndianArchVariant().getArch()); + EXPECT_EQ(Triple::ppcle, T.getLittleEndianArchVariant().getArch()); T.setArch(Triple::ppc64); EXPECT_EQ(Triple::ppc64, T.getBigEndianArchVariant().getArch());