https://github.com/djtodoro updated https://github.com/llvm/llvm-project/pull/146913
>From a3b50d1a95f4ae76af98e25502a7bdb950592d38 Mon Sep 17 00:00:00 2001 From: Djordje Todorovic <djordje.todoro...@htecgroup.com> Date: Thu, 3 Jul 2025 14:03:14 +0200 Subject: [PATCH 1/2] [llvm-objcopy][libObject] Add RISC-V big-endian support Add support for big-endian RISC-V ELF files: - Add riscv32be/riscv64be target architectures to Triple - Support elf32-bigriscv and elf64-bigriscv output targets in llvm-objcopy - Update ELFObjectFile to handle BE RISC-V format strings and architecture detection - Add BE RISC-V support to RelocationResolver - Add tests for new functionality This is a subset of a bigger RISC-V big-endian support patch, containing only the llvm-objcopy and libObject changes. Other changes will be added later. --- clang/test/Driver/frame-pointer-elim.c | 2 +- llvm/include/llvm/Object/ELFObjectFile.h | 8 ++-- llvm/include/llvm/TargetParser/Triple.h | 14 +++++-- llvm/lib/Object/RelocationResolver.cpp | 6 ++- llvm/lib/TargetParser/Triple.cpp | 41 +++++++++++++++++-- .../ELF/binary-output-target.test | 6 +++ llvm/tools/llvm-objcopy/ObjcopyOptions.cpp | 2 + llvm/unittests/Object/ELFObjectFileTest.cpp | 8 ++-- 8 files changed, 70 insertions(+), 17 deletions(-) diff --git a/clang/test/Driver/frame-pointer-elim.c b/clang/test/Driver/frame-pointer-elim.c index f64ff6efc7261..416afce81050a 100644 --- a/clang/test/Driver/frame-pointer-elim.c +++ b/clang/test/Driver/frame-pointer-elim.c @@ -160,7 +160,7 @@ // RUN: FileCheck --check-prefix=KEEP-ALL %s // RUN: %clang -### --target=riscv64-linux-android -O1 -S %s 2>&1 | \ // RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s -// RUN: not %clang -### --target=riscv64-linux-android -mbig-endian -O1 -S %s 2>&1 | \ +// RUN: %clang -### --target=riscv64-linux-android -mbig-endian -O1 -S %s 2>&1 | \ // RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s // On ARM backend bare metal targets, frame pointer is omitted diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h index 103686884e705..a3aa0d9c137a2 100644 --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -1312,7 +1312,7 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { case ELF::EM_PPC: return (IsLittleEndian ? "elf32-powerpcle" : "elf32-powerpc"); case ELF::EM_RISCV: - return "elf32-littleriscv"; + return (IsLittleEndian ? "elf32-littleriscv" : "elf32-bigriscv"); case ELF::EM_CSKY: return "elf32-csky"; case ELF::EM_SPARC: @@ -1338,7 +1338,7 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { case ELF::EM_PPC64: return (IsLittleEndian ? "elf64-powerpcle" : "elf64-powerpc"); case ELF::EM_RISCV: - return "elf64-littleriscv"; + return (IsLittleEndian ? "elf64-littleriscv" : "elf64-bigriscv"); case ELF::EM_S390: return "elf64-s390"; case ELF::EM_SPARCV9: @@ -1400,9 +1400,9 @@ template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const { case ELF::EM_RISCV: switch (EF.getHeader().e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: - return Triple::riscv32; + return IsLittleEndian ? Triple::riscv32 : Triple::riscv32be; case ELF::ELFCLASS64: - return Triple::riscv64; + return IsLittleEndian ? Triple::riscv64 : Triple::riscv64be; default: report_fatal_error("Invalid ELFCLASS!"); } diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h index cbf85b2ff74f5..0b983e9f7a3bc 100644 --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -74,8 +74,10 @@ class Triple { ppc64le, // PPC64LE: powerpc64le r600, // R600: AMD GPUs HD2XXX - HD6XXX amdgcn, // AMDGCN: AMD GCN GPUs - riscv32, // RISC-V (32-bit): riscv32 - riscv64, // RISC-V (64-bit): riscv64 + riscv32, // RISC-V (32-bit, little endian): riscv32 + riscv64, // RISC-V (64-bit, little endian): riscv64 + riscv32be, // RISC-V (32-bit, big endian): riscv32be + riscv64be, // RISC-V (64-bit, big endian): riscv64be sparc, // Sparc: sparc sparcv9, // Sparcv9: Sparcv9 sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant @@ -1069,10 +1071,14 @@ class Triple { } /// Tests whether the target is 32-bit RISC-V. - bool isRISCV32() const { return getArch() == Triple::riscv32; } + bool isRISCV32() const { + return getArch() == Triple::riscv32 || getArch() == Triple::riscv32be; + } /// Tests whether the target is 64-bit RISC-V. - bool isRISCV64() const { return getArch() == Triple::riscv64; } + bool isRISCV64() const { + return getArch() == Triple::riscv64 || getArch() == Triple::riscv64be; + } /// Tests whether the target is RISC-V (32- and 64-bit). bool isRISCV() const { return isRISCV32() || isRISCV64(); } diff --git a/llvm/lib/Object/RelocationResolver.cpp b/llvm/lib/Object/RelocationResolver.cpp index b6318bbe3ab74..d81899334b2b1 100644 --- a/llvm/lib/Object/RelocationResolver.cpp +++ b/llvm/lib/Object/RelocationResolver.cpp @@ -812,6 +812,7 @@ getRelocationResolver(const ObjectFile &Obj) { case Triple::amdgcn: return {supportsAmdgpu, resolveAmdgpu}; case Triple::riscv64: + case Triple::riscv64be: return {supportsRISCV, resolveRISCV}; default: if (isAMDGPU(Obj)) @@ -851,6 +852,7 @@ getRelocationResolver(const ObjectFile &Obj) { case Triple::r600: return {supportsAmdgpu, resolveAmdgpu}; case Triple::riscv32: + case Triple::riscv32be: return {supportsRISCV, resolveRISCV}; case Triple::csky: return {supportsCSKY, resolveCSKY}; @@ -897,7 +899,9 @@ uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R, if (Obj->getArch() != Triple::loongarch32 && Obj->getArch() != Triple::loongarch64 && Obj->getArch() != Triple::riscv32 && - Obj->getArch() != Triple::riscv64) + Obj->getArch() != Triple::riscv64 && + Obj->getArch() != Triple::riscv32be && + Obj->getArch() != Triple::riscv64be) LocData = 0; } } diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index a348640d75f26..83937861c479a 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -63,6 +63,8 @@ StringRef Triple::getArchTypeName(ArchType Kind) { case renderscript64: return "renderscript64"; case riscv32: return "riscv32"; case riscv64: return "riscv64"; + case riscv32be: return "riscv32be"; + case riscv64be: return "riscv64be"; case shave: return "shave"; case sparc: return "sparc"; case sparcel: return "sparcel"; @@ -237,7 +239,10 @@ StringRef Triple::getArchTypePrefix(ArchType Kind) { case wasm64: return "wasm"; case riscv32: - case riscv64: return "riscv"; + case riscv64: + case riscv32be: + case riscv64be: + return "riscv"; case ve: return "ve"; case csky: return "csky"; @@ -452,6 +457,8 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { .Case("amdgcn", amdgcn) .Case("riscv32", riscv32) .Case("riscv64", riscv64) + .Case("riscv32be", riscv32be) + .Case("riscv64be", riscv64be) .Case("hexagon", hexagon) .Case("sparc", sparc) .Case("sparcel", sparcel) @@ -598,6 +605,8 @@ static Triple::ArchType parseArch(StringRef ArchName) { .Case("amdgcn", Triple::amdgcn) .Case("riscv32", Triple::riscv32) .Case("riscv64", Triple::riscv64) + .Case("riscv32be", Triple::riscv32be) + .Case("riscv64be", Triple::riscv64be) .Case("hexagon", Triple::hexagon) .Cases("s390x", "systemz", Triple::systemz) .Case("sparc", Triple::sparc) @@ -967,6 +976,8 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) { case Triple::renderscript64: case Triple::riscv32: case Triple::riscv64: + case Triple::riscv32be: + case Triple::riscv64be: case Triple::shave: case Triple::sparc: case Triple::sparcel: @@ -1689,6 +1700,7 @@ unsigned Triple::getArchPointerBitWidth(llvm::Triple::ArchType Arch) { case llvm::Triple::r600: case llvm::Triple::renderscript32: case llvm::Triple::riscv32: + case llvm::Triple::riscv32be: case llvm::Triple::shave: case llvm::Triple::sparc: case llvm::Triple::sparcel: @@ -1719,6 +1731,7 @@ unsigned Triple::getArchPointerBitWidth(llvm::Triple::ArchType Arch) { case llvm::Triple::ppc64le: case llvm::Triple::renderscript64: case llvm::Triple::riscv64: + case llvm::Triple::riscv64be: case llvm::Triple::sparcv9: case llvm::Triple::spirv: case llvm::Triple::spir64: @@ -1797,6 +1810,7 @@ Triple Triple::get32BitArchVariant() const { case Triple::r600: case Triple::renderscript32: case Triple::riscv32: + case Triple::riscv32be: case Triple::shave: case Triple::sparc: case Triple::sparcel: @@ -1829,6 +1843,9 @@ Triple Triple::get32BitArchVariant() const { 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::riscv64be: + T.setArch(Triple::riscv32be); + break; case Triple::sparcv9: T.setArch(Triple::sparc); break; case Triple::spir64: T.setArch(Triple::spir); break; case Triple::spirv: @@ -1879,6 +1896,7 @@ Triple Triple::get64BitArchVariant() const { case Triple::ppc64le: case Triple::renderscript64: case Triple::riscv64: + case Triple::riscv64be: case Triple::sparcv9: case Triple::spir64: case Triple::spirv64: @@ -1906,6 +1924,9 @@ Triple Triple::get64BitArchVariant() const { 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::riscv32be: + T.setArch(Triple::riscv64be); + break; case Triple::sparc: T.setArch(Triple::sparcv9); break; case Triple::spir: T.setArch(Triple::spir64); break; case Triple::spirv: @@ -1944,8 +1965,8 @@ Triple Triple::getBigEndianArchVariant() const { case Triple::r600: case Triple::renderscript32: case Triple::renderscript64: - case Triple::riscv32: - case Triple::riscv64: + case Triple::riscv32be: + case Triple::riscv64be: case Triple::shave: case Triple::spir64: case Triple::spir: @@ -1978,6 +1999,12 @@ Triple Triple::getBigEndianArchVariant() const { break; case Triple::ppcle: T.setArch(Triple::ppc); break; case Triple::ppc64le: T.setArch(Triple::ppc64); break; + case Triple::riscv32: + T.setArch(Triple::riscv32be); + break; + case Triple::riscv64: + T.setArch(Triple::riscv64be); + break; case Triple::sparcel: T.setArch(Triple::sparc); break; case Triple::tcele: T.setArch(Triple::tce); break; default: @@ -2015,6 +2042,12 @@ Triple Triple::getLittleEndianArchVariant() const { break; case Triple::ppc: T.setArch(Triple::ppcle); break; case Triple::ppc64: T.setArch(Triple::ppc64le); break; + case Triple::riscv32be: + T.setArch(Triple::riscv32); + break; + case Triple::riscv64be: + T.setArch(Triple::riscv64); + break; case Triple::sparc: T.setArch(Triple::sparcel); break; case Triple::tce: T.setArch(Triple::tcele); break; default: @@ -2053,6 +2086,8 @@ bool Triple::isLittleEndian() const { case Triple::renderscript64: case Triple::riscv32: case Triple::riscv64: + case Triple::riscv32be: + case Triple::riscv64be: case Triple::shave: case Triple::sparcel: case Triple::spir64: diff --git a/llvm/test/tools/llvm-objcopy/ELF/binary-output-target.test b/llvm/test/tools/llvm-objcopy/ELF/binary-output-target.test index f88b7575002a9..3547b728a426d 100644 --- a/llvm/test/tools/llvm-objcopy/ELF/binary-output-target.test +++ b/llvm/test/tools/llvm-objcopy/ELF/binary-output-target.test @@ -33,6 +33,12 @@ # RUN: llvm-objcopy -I binary -O elf64-littleriscv %t.txt %t.rv64.o # RUN: llvm-readobj --file-headers %t.rv64.o | FileCheck %s --check-prefixes=CHECK,LE,RISCV64,64 +# RUN: llvm-objcopy -I binary -O elf32-bigriscv %t.txt %t.rv32.o +# RUN: llvm-readobj --file-headers %t.rv32.o | FileCheck %s --check-prefixes=CHECK,BE,RISCV32,32 + +# RUN: llvm-objcopy -I binary -O elf64-bigriscv %t.txt %t.rv64.o +# RUN: llvm-readobj --file-headers %t.rv64.o | FileCheck %s --check-prefixes=CHECK,BE,RISCV64,64 + # RUN: llvm-objcopy -I binary -O elf32-sparc %t.txt %t.sparc.o # RUN: llvm-readobj --file-headers %t.sparc.o | FileCheck %s --check-prefixes=CHECK,BE,SPARC,32 diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp index 0d209590655ef..175f77c894825 100644 --- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp +++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp @@ -308,6 +308,8 @@ static const StringMap<MachineInfo> TargetMap{ // RISC-V {"elf32-littleriscv", {ELF::EM_RISCV, false, true}}, {"elf64-littleriscv", {ELF::EM_RISCV, true, true}}, + {"elf32-bigriscv", {ELF::EM_RISCV, false, false}}, + {"elf64-bigriscv", {ELF::EM_RISCV, true, false}}, // PowerPC {"elf32-powerpc", {ELF::EM_PPC, false, false}}, {"elf32-powerpcle", {ELF::EM_PPC, false, true}}, diff --git a/llvm/unittests/Object/ELFObjectFileTest.cpp b/llvm/unittests/Object/ELFObjectFileTest.cpp index 423f92ea07b39..650de9dde7145 100644 --- a/llvm/unittests/Object/ELFObjectFileTest.cpp +++ b/llvm/unittests/Object/ELFObjectFileTest.cpp @@ -177,10 +177,10 @@ TEST(ELFObjectFileTest, MachineTestForPPC) { } TEST(ELFObjectFileTest, MachineTestForRISCV) { - std::array<StringRef, 4> Formats = {"elf32-littleriscv", "elf32-littleriscv", - "elf64-littleriscv", "elf64-littleriscv"}; - std::array<Triple::ArchType, 4> Archs = {Triple::riscv32, Triple::riscv32, - Triple::riscv64, Triple::riscv64}; + std::array<StringRef, 4> Formats = {"elf32-littleriscv", "elf32-bigriscv", + "elf64-littleriscv", "elf64-bigriscv"}; + std::array<Triple::ArchType, 4> Archs = {Triple::riscv32, Triple::riscv32be, + Triple::riscv64, Triple::riscv64be}; for (auto [Idx, Data] : enumerate(generateData(ELF::EM_RISCV))) checkFormatAndArch(Data, Formats[Idx], Archs[Idx]); } >From 9f95a0ce364538a7ff0ea4fe752fc87441ad5569 Mon Sep 17 00:00:00 2001 From: Djordje Todorovic <djordje.todoro...@htecgroup.com> Date: Fri, 4 Jul 2025 11:54:29 +0200 Subject: [PATCH 2/2] Fixup: Remove Triple::riscv32/64be from isLittleEndian predicates --- llvm/lib/TargetParser/Triple.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index 83937861c479a..26610dfd97659 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -1965,8 +1965,6 @@ Triple Triple::getBigEndianArchVariant() const { case Triple::r600: case Triple::renderscript32: case Triple::renderscript64: - case Triple::riscv32be: - case Triple::riscv64be: case Triple::shave: case Triple::spir64: case Triple::spir: @@ -2086,8 +2084,6 @@ bool Triple::isLittleEndian() const { case Triple::renderscript64: case Triple::riscv32: case Triple::riscv64: - case Triple::riscv32be: - case Triple::riscv64be: case Triple::shave: case Triple::sparcel: case Triple::spir64: _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits