[clang] [llvm] [RISCV] Add big-endian support to RISC-V backend (PR #146534)
Djordje Todorovic via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 1 07:10:21 PDT 2025
https://github.com/djtodoro created https://github.com/llvm/llvm-project/pull/146534
Initial big-endian RISC-V support:
- Add riscv32be/riscv64be target triples
- Implement BE-aware codegen patterns
- Handle endianness in load/store operations
- Add BE target feature and subtarget info
>From 02c3866116a5134d10f5d9f30504682079538168 Mon Sep 17 00:00:00 2001
From: Djordje Todorovic <djordje.todorovic at htecgroup.com>
Date: Mon, 2 Jun 2025 14:07:16 +0200
Subject: [PATCH] [RISCV] Add big-endian support to RISC-V backend
Initial big-endian RISC-V support:
- Add riscv32be/riscv64be target triples
- Implement BE-aware codegen patterns
- Handle endianness in load/store operations
- Add BE target feature and subtarget info
---
clang/test/Driver/frame-pointer-elim.c | 2 +-
llvm/cmake/config.guess | 2 +-
llvm/include/llvm/Object/ELFObjectFile.h | 8 +--
llvm/include/llvm/TargetParser/Triple.h | 10 +++-
.../CodeGen/TargetLoweringObjectFileImpl.cpp | 2 +
llvm/lib/Object/RelocationResolver.cpp | 6 ++-
.../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 2 +
.../RISCV/Disassembler/RISCVDisassembler.cpp | 4 ++
.../RISCV/MCTargetDesc/RISCVAsmBackend.cpp | 52 +++++++++++++++----
.../RISCV/MCTargetDesc/RISCVAsmBackend.h | 2 +-
.../RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp | 1 +
.../RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp | 3 +-
llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp | 2 +
llvm/lib/Target/RISCV/RISCVTargetMachine.cpp | 30 ++++++-----
.../RISCV/TargetInfo/RISCVTargetInfo.cpp | 14 +++++
.../Target/RISCV/TargetInfo/RISCVTargetInfo.h | 2 +
llvm/lib/TargetParser/Triple.cpp | 24 +++++++--
.../Instrumentation/AddressSanitizer.cpp | 3 +-
.../ELF/binary-output-target.test | 6 +++
llvm/tools/llvm-objcopy/ObjcopyOptions.cpp | 2 +
llvm/unittests/Object/ELFObjectFileTest.cpp | 8 +--
21 files changed, 144 insertions(+), 41 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/cmake/config.guess b/llvm/cmake/config.guess
index 96cc554f181ab..27b55bd166edc 100644
--- a/llvm/cmake/config.guess
+++ b/llvm/cmake/config.guess
@@ -1003,7 +1003,7 @@ EOF
ppcle:Linux:*:*)
echo powerpcle-unknown-linux-gnu
exit ;;
- riscv32:Linux:*:* | riscv64:Linux:*:*)
+ riscv32:Linux:*:* | riscv64:Linux:*:* | riscv32be:Linux:*:* | riscv64be:Linux:*:*)
LIBC=gnu
eval $set_cc_for_build
# Do not check for __GLIBC__ because uclibc defines it too
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..c28838e41ded0 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -76,6 +76,8 @@ class Triple {
amdgcn, // AMDGCN: AMD GCN GPUs
riscv32, // RISC-V (32-bit): riscv32
riscv64, // RISC-V (64-bit): 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/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 5454cd475f5ed..6c99bd030ec96 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -248,6 +248,8 @@ void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx,
break;
case Triple::riscv32:
case Triple::riscv64:
+ case Triple::riscv32be:
+ case Triple::riscv64be:
LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
dwarf::DW_EH_PE_sdata4;
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/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index bb0f9df2032fd..890067e270998 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -4031,4 +4031,6 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeRISCVAsmParser() {
RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
+ RegisterMCAsmParser<RISCVAsmParser> A(getTheRISCV32beTarget());
+ RegisterMCAsmParser<RISCVAsmParser> B(getTheRISCV64beTarget());
}
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 27e04c0cb1f8b..1efc7a896552d 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -72,6 +72,10 @@ LLVMInitializeRISCVDisassembler() {
createRISCVDisassembler);
TargetRegistry::RegisterMCDisassembler(getTheRISCV64Target(),
createRISCVDisassembler);
+ TargetRegistry::RegisterMCDisassembler(getTheRISCV32beTarget(),
+ createRISCVDisassembler);
+ TargetRegistry::RegisterMCDisassembler(getTheRISCV64beTarget(),
+ createRISCVDisassembler);
}
static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint32_t RegNo,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index 75ef861d58a1c..7719ab4d95d16 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -33,9 +33,11 @@ static cl::opt<bool> ULEB128Reloc(
cl::desc("Emit R_RISCV_SET_ULEB128/E_RISCV_SUB_ULEB128 if appropriate"));
RISCVAsmBackend::RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI,
- bool Is64Bit, const MCTargetOptions &Options)
- : MCAsmBackend(llvm::endianness::little), STI(STI), OSABI(OSABI),
- Is64Bit(Is64Bit), TargetOptions(Options) {
+ bool Is64Bit, bool IsLittleEndian,
+ const MCTargetOptions &Options)
+ : MCAsmBackend(IsLittleEndian ? llvm::endianness::little
+ : llvm::endianness::big),
+ STI(STI), OSABI(OSABI), Is64Bit(Is64Bit), TargetOptions(Options) {
RISCVFeatures::validate(STI.getTargetTriple(), STI.getFeatureBits());
}
@@ -313,7 +315,7 @@ bool RISCVAsmBackend::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF,
OS << uint8_t(dwarf::DW_LNS_fixed_advance_pc);
Offset = OS.tell();
Fixup = RISCV::getRelocPairForSize(2);
- support::endian::write<uint16_t>(OS, 0, llvm::endianness::little);
+ support::endian::write<uint16_t>(OS, 0, Endian);
}
const MCBinaryExpr &MBE = cast<MCBinaryExpr>(AddrDelta);
@@ -370,15 +372,15 @@ bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF,
AddFixups(0, {ELF::R_RISCV_SET6, ELF::R_RISCV_SUB6});
} else if (isUInt<8>(Value)) {
OS << uint8_t(dwarf::DW_CFA_advance_loc1);
- support::endian::write<uint8_t>(OS, 0, llvm::endianness::little);
+ support::endian::write<uint8_t>(OS, 0, Endian);
AddFixups(1, {ELF::R_RISCV_SET8, ELF::R_RISCV_SUB8});
} else if (isUInt<16>(Value)) {
OS << uint8_t(dwarf::DW_CFA_advance_loc2);
- support::endian::write<uint16_t>(OS, 0, llvm::endianness::little);
+ support::endian::write<uint16_t>(OS, 0, Endian);
AddFixups(1, {ELF::R_RISCV_SET16, ELF::R_RISCV_SUB16});
} else if (isUInt<32>(Value)) {
OS << uint8_t(dwarf::DW_CFA_advance_loc4);
- support::endian::write<uint32_t>(OS, 0, llvm::endianness::little);
+ support::endian::write<uint32_t>(OS, 0, Endian);
AddFixups(1, {ELF::R_RISCV_SET32, ELF::R_RISCV_SUB32});
} else {
llvm_unreachable("unsupported CFA encoding");
@@ -815,6 +817,34 @@ bool RISCVAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup,
return false;
}
+// Data should be swapped for big endian cores.
+static bool isDataFixup(unsigned Kind) {
+ switch (Kind) {
+ default:
+ llvm_unreachable("Unknown fixup kind!");
+
+ case FK_Data_1:
+ case FK_Data_2:
+ case FK_Data_4:
+ case FK_Data_8:
+ return true;
+
+ case RISCV::fixup_riscv_hi20:
+ case RISCV::fixup_riscv_lo12_i:
+ case RISCV::fixup_riscv_lo12_s:
+ case RISCV::fixup_riscv_pcrel_hi20:
+ case RISCV::fixup_riscv_pcrel_lo12_i:
+ case RISCV::fixup_riscv_pcrel_lo12_s:
+ case RISCV::fixup_riscv_jal:
+ case RISCV::fixup_riscv_branch:
+ case RISCV::fixup_riscv_call:
+ case RISCV::fixup_riscv_call_plt:
+ case RISCV::fixup_riscv_rvc_jump:
+ case RISCV::fixup_riscv_rvc_branch:
+ return false;
+ }
+}
+
void RISCVAsmBackend::applyFixup(const MCFragment &, const MCFixup &Fixup,
const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
@@ -839,8 +869,11 @@ void RISCVAsmBackend::applyFixup(const MCFragment &, const MCFixup &Fixup,
// For each byte of the fragment that the fixup touches, mask in the
// bits from the fixup value.
+ // For big endian cores, data fixup should be swapped.
+ bool SwapValue = (Endian == llvm::endianness::big) && isDataFixup(Kind);
for (unsigned i = 0; i != NumBytes; ++i) {
- Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
+ unsigned Idx = SwapValue ? (NumBytes - 1 - i) : i;
+ Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
}
}
@@ -905,5 +938,6 @@ MCAsmBackend *llvm::createRISCVAsmBackend(const Target &T,
const MCTargetOptions &Options) {
const Triple &TT = STI.getTargetTriple();
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
- return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit(), Options);
+ return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit(), TT.isLittleEndian(),
+ Options);
}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
index 91efd44547509..9c03c7aaa98e2 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
@@ -36,7 +36,7 @@ class RISCVAsmBackend : public MCAsmBackend {
public:
RISCVAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit,
- const MCTargetOptions &Options);
+ bool IsLittleEndian, const MCTargetOptions &Options);
~RISCVAsmBackend() override = default;
// Return Size with extra Nop Bytes for alignment directive in code section.
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
index 090d331d99cab..77f65d814ce7a 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
@@ -21,6 +21,7 @@ using namespace llvm;
void RISCVMCAsmInfo::anchor() {}
RISCVMCAsmInfo::RISCVMCAsmInfo(const Triple &TT) {
+ IsLittleEndian = TT.isLittleEndian();
CodePointerSize = CalleeSaveStackSlotSize = TT.isArch64Bit() ? 8 : 4;
CommentString = "#";
AlignmentIsInBytes = false;
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
index f66c2d5f99cb3..88e564580dc5e 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
@@ -334,7 +334,8 @@ static MCInstrAnalysis *createRISCVInstrAnalysis(const MCInstrInfo *Info) {
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeRISCVTargetMC() {
- for (Target *T : {&getTheRISCV32Target(), &getTheRISCV64Target()}) {
+ for (Target *T : {&getTheRISCV32Target(), &getTheRISCV64Target(),
+ &getTheRISCV32beTarget(), &getTheRISCV64beTarget()}) {
TargetRegistry::RegisterMCAsmInfo(*T, createRISCVMCAsmInfo);
TargetRegistry::RegisterMCObjectFileInfo(*T, createRISCVMCObjectFileInfo);
TargetRegistry::RegisterMCInstrInfo(*T, createRISCVMCInstrInfo);
diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
index b078b9268c984..02a6cbdb9f80d 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -615,6 +615,8 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeRISCVAsmPrinter() {
RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target());
RegisterAsmPrinter<RISCVAsmPrinter> Y(getTheRISCV64Target());
+ RegisterAsmPrinter<RISCVAsmPrinter> A(getTheRISCV32beTarget());
+ RegisterAsmPrinter<RISCVAsmPrinter> B(getTheRISCV64beTarget());
}
void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
index b43b915d0ad4f..32177fe06e889 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -122,6 +122,8 @@ static cl::opt<bool>
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
RegisterTargetMachine<RISCVTargetMachine> X(getTheRISCV32Target());
RegisterTargetMachine<RISCVTargetMachine> Y(getTheRISCV64Target());
+ RegisterTargetMachine<RISCVTargetMachine> A(getTheRISCV32beTarget());
+ RegisterTargetMachine<RISCVTargetMachine> B(getTheRISCV64beTarget());
auto *PR = PassRegistry::getPassRegistry();
initializeGlobalISel(*PR);
initializeRISCVO0PreLegalizerCombinerPass(*PR);
@@ -155,21 +157,23 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
initializeRISCVAsmPrinterPass(*PR);
}
-static StringRef computeDataLayout(const Triple &TT,
- const TargetOptions &Options) {
- StringRef ABIName = Options.MCOptions.getABIName();
- if (TT.isArch64Bit()) {
- if (ABIName == "lp64e")
- return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S64";
+static std::string computeDataLayout(const Triple &TT,
+ const TargetOptions &Opts) {
+ const bool IsLittle = TT.isLittleEndian();
+ StringRef ABI = Opts.MCOptions.getABIName();
+ std::string DL;
- return "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128";
+ if (TT.isArch64Bit()) {
+ DL = (Twine(IsLittle ? "e" : "E") + "-m:e-p:64:64-i64:64-i128:128-n32:64-" +
+ (ABI == "lp64e" ? "S64" : "S128"))
+ .str();
+ } else {
+ assert(TT.isArch32Bit() && "only RV32 and RV64 are currently supported");
+ DL = (Twine(IsLittle ? "e" : "E") + "-m:e-p:32:32-i64:64-n32-" +
+ (ABI == "ilp32e" ? "S32" : "S128"))
+ .str();
}
- assert(TT.isArch32Bit() && "only RV32 and RV64 are currently supported");
-
- if (ABIName == "ilp32e")
- return "e-m:e-p:32:32-i64:64-n32-S32";
-
- return "e-m:e-p:32:32-i64:64-n32-S128";
+ return DL;
}
static Reloc::Model getEffectiveRelocModel(const Triple &TT,
diff --git a/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp b/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp
index fc0965d263a8a..7b0afe46971a3 100644
--- a/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp
+++ b/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.cpp
@@ -21,10 +21,24 @@ Target &llvm::getTheRISCV64Target() {
return TheRISCV64Target;
}
+Target &llvm::getTheRISCV32beTarget() {
+ static Target TheRISCV32beTarget;
+ return TheRISCV32beTarget;
+}
+
+Target &llvm::getTheRISCV64beTarget() {
+ static Target TheRISCV64beTarget;
+ return TheRISCV64beTarget;
+}
+
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeRISCVTargetInfo() {
RegisterTarget<Triple::riscv32, /*HasJIT=*/true> X(
getTheRISCV32Target(), "riscv32", "32-bit RISC-V", "RISCV");
RegisterTarget<Triple::riscv64, /*HasJIT=*/true> Y(
getTheRISCV64Target(), "riscv64", "64-bit RISC-V", "RISCV");
+ RegisterTarget<Triple::riscv32be> A(getTheRISCV32beTarget(), "riscv32be",
+ "32-bit big endian RISC-V", "RISCV");
+ RegisterTarget<Triple::riscv64be> B(getTheRISCV64beTarget(), "riscv64be",
+ "64-bit big endian RISC-V", "RISCV");
}
diff --git a/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.h b/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.h
index ed00a01fa1a2a..9b9fd2cca2fd0 100644
--- a/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.h
+++ b/llvm/lib/Target/RISCV/TargetInfo/RISCVTargetInfo.h
@@ -15,6 +15,8 @@ class Target;
Target &getTheRISCV32Target();
Target &getTheRISCV64Target();
+Target &getTheRISCV32beTarget();
+Target &getTheRISCV64beTarget();
} // namespace llvm
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index a348640d75f26..47d6150a04365 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,9 @@ 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 +456,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 +604,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 +975,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 +1699,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 +1730,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 +1809,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 +1842,7 @@ 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 +1893,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 +1921,7 @@ 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 +1960,6 @@ Triple Triple::getBigEndianArchVariant() const {
case Triple::r600:
case Triple::renderscript32:
case Triple::renderscript64:
- case Triple::riscv32:
- case Triple::riscv64:
case Triple::shave:
case Triple::spir64:
case Triple::spir:
@@ -1976,6 +1990,8 @@ Triple Triple::getBigEndianArchVariant() const {
case Triple::mipsel:
T.setArch(Triple::mips, getSubArch());
break;
+ case Triple::riscv32: T.setArch(Triple::riscv32be); break;
+ case Triple::riscv64: T.setArch(Triple::riscv64be); 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;
@@ -2013,6 +2029,8 @@ Triple Triple::getLittleEndianArchVariant() const {
case Triple::mips:
T.setArch(Triple::mipsel, getSubArch());
break;
+ case Triple::riscv32be: T.setArch(Triple::riscv32); break;
+ case Triple::riscv64be: T.setArch(Triple::riscv64); 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;
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 840a5e3f31dfd..39ffd057b3fb6 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -496,7 +496,8 @@ static ShadowMapping getShadowMapping(const Triple &TargetTriple, int LongSize,
bool IsAArch64 = TargetTriple.getArch() == Triple::aarch64 ||
TargetTriple.getArch() == Triple::aarch64_be;
bool IsLoongArch64 = TargetTriple.isLoongArch64();
- bool IsRISCV64 = TargetTriple.getArch() == Triple::riscv64;
+ bool IsRISCV64 = TargetTriple.getArch() == Triple::riscv64 ||
+ TargetTriple.getArch() == Triple::riscv64be;
bool IsWindows = TargetTriple.isOSWindows();
bool IsFuchsia = TargetTriple.isOSFuchsia();
bool IsAMDGPU = TargetTriple.isAMDGPU();
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]);
}
More information about the cfe-commits
mailing list