[llvm] [RISCV] Add initial assembler/MC layer support for big-endian (PR #146534)

Djordje Todorovic via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 19 01:28:46 PDT 2025


https://github.com/djtodoro updated https://github.com/llvm/llvm-project/pull/146534

>From 87ab03b76c59a253d5f513a4f527f84f8ac9beb5 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 1/7] [RISCV] Add initial assembler/MC layer support for
 big-endian

This patch adds basic assembler and MC layer infrastructure for
RISC-V big-endian targets (riscv32be/riscv64be):

  - Register big-endian targets in RISCVTargetMachine
  - Add big-endian data layout strings
  - Implement endianness-aware fixup application in assembler
    backend
  - Add byte swapping for data fixups on BE cores
  - Update MC layer components (AsmInfo, MCTargetDesc, Disassembler,
    AsmParser)

This provides the foundation for BE support but does not yet include:
  - Codegen patterns for BE
  - Load/store instruction handling
  - BE-specific subtarget features
---
 llvm/cmake/config.guess                       |  2 +-
 .../CodeGen/TargetLoweringObjectFileImpl.cpp  |  2 +
 .../Target/RISCV/AsmParser/RISCVAsmParser.cpp |  2 +
 .../RISCV/Disassembler/RISCVDisassembler.cpp  |  4 ++
 .../RISCV/MCTargetDesc/RISCVAsmBackend.cpp    | 59 ++++++++++++++++---
 .../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 +
 12 files changed, 98 insertions(+), 25 deletions(-)

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/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index d19ef923ef740..739dcc7f4c868 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -247,6 +247,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/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index d71c42c0a5fc1..c87362a1b4e87 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -4053,4 +4053,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 67cc01e647a04..c535dc0891f9c 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 95ec42f960105..3f662374d4023 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());
 }
 
@@ -361,7 +363,7 @@ bool RISCVAsmBackend::relaxDwarfLineAddr(MCFragment &F,
   } else {
     PCBytes = 2;
     OS << uint8_t(dwarf::DW_LNS_fixed_advance_pc);
-    support::endian::write<uint16_t>(OS, 0, llvm::endianness::little);
+    support::endian::write<uint16_t>(OS, 0, Endian);
   }
   auto Offset = OS.tell() - PCBytes;
 
@@ -415,15 +417,15 @@ bool RISCVAsmBackend::relaxDwarfCFA(MCFragment &F, bool &WasRelaxed) const {
     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");
@@ -869,6 +871,41 @@ 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:
+  case RISCV::fixup_riscv_12_i:
+  case RISCV::fixup_riscv_rvc_imm:
+  case RISCV::fixup_riscv_qc_e_branch:
+  case RISCV::fixup_riscv_qc_e_32:
+  case RISCV::fixup_riscv_qc_abs20_u:
+  case RISCV::fixup_riscv_qc_e_call_plt:
+  case RISCV::fixup_riscv_nds_branch_10:
+    return false;
+  }
+}
+
 void RISCVAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
                                  const MCValue &Target, uint8_t *Data,
                                  uint64_t Value, bool IsResolved) {
@@ -892,8 +929,11 @@ void RISCVAsmBackend::applyFixup(const MCFragment &F, 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[i] |= uint8_t((Value >> (i * 8)) & 0xff);
+    unsigned Idx = SwapValue ? (NumBytes - 1 - i) : i;
+    Data[Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
   }
 }
 
@@ -908,5 +948,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 adec1ec699da0..3a5214a5f350f 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
@@ -35,7 +35,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;
 
   std::optional<bool> evaluateFixup(const MCFragment &, MCFixup &, MCValue &,
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 61ecfb278a7d3..d917ef4129791 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp
@@ -376,7 +376,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 2f32e2ac3eba3..83566b1c57782 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -611,6 +611,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 da6ac2f6f31e9..3a16256aed462 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -117,6 +117,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);
@@ -150,21 +152,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
 

>From 4131779058b314cc22133bb399673a956cbd75da Mon Sep 17 00:00:00 2001
From: Djordje Todorovic <djordje.todorovic at htecgroup.com>
Date: Mon, 4 Aug 2025 13:19:06 +0200
Subject: [PATCH 2/7] [RISCV] Add tests for BE

---
 llvm/test/MC/Disassembler/RISCV/bigendian.txt | 29 +++++++++
 .../test/MC/RISCV/bigendian-data-directives.s | 36 +++++++++++
 llvm/test/MC/RISCV/bigendian-fixups.s         | 60 +++++++++++++++++++
 llvm/test/MC/RISCV/elf-bigendian.s            | 46 ++++++++++++++
 4 files changed, 171 insertions(+)
 create mode 100644 llvm/test/MC/Disassembler/RISCV/bigendian.txt
 create mode 100644 llvm/test/MC/RISCV/bigendian-data-directives.s
 create mode 100644 llvm/test/MC/RISCV/bigendian-fixups.s
 create mode 100644 llvm/test/MC/RISCV/elf-bigendian.s

diff --git a/llvm/test/MC/Disassembler/RISCV/bigendian.txt b/llvm/test/MC/Disassembler/RISCV/bigendian.txt
new file mode 100644
index 0000000000000..54930f94b75ed
--- /dev/null
+++ b/llvm/test/MC/Disassembler/RISCV/bigendian.txt
@@ -0,0 +1,29 @@
+# RUN: llvm-mc --disassemble %s -triple=riscv32be -mattr=+c 2>&1 | FileCheck %s
+# RUN: llvm-mc --disassemble %s -triple=riscv64be -mattr=+c 2>&1 | FileCheck %s
+
+# Test basic disassembly for big-endian RISC-V
+# Instructions are always little-endian encoded in RISC-V
+
+[0x13,0x05,0x45,0x06]
+# CHECK: addi a0, a0, 100
+
+[0xb7,0x52,0x34,0x12]
+# CHECK: lui t0, 74565
+
+[0x03,0x26,0x05,0x00]
+# CHECK: lw a2, 0(a0)
+
+[0x23,0x22,0xc5,0x00]
+# CHECK: sw a2, 4(a0)
+
+[0xef,0x00,0x00,0x00]
+# CHECK: jal 0
+
+[0x63,0x00,0xb5,0x00]
+# CHECK: beq a0, a1, 0
+
+[0x01,0x00]
+# CHECK: nop
+
+[0x05,0x05]
+# CHECK: addi a0, a0, 1
diff --git a/llvm/test/MC/RISCV/bigendian-data-directives.s b/llvm/test/MC/RISCV/bigendian-data-directives.s
new file mode 100644
index 0000000000000..54dd9211e2b64
--- /dev/null
+++ b/llvm/test/MC/RISCV/bigendian-data-directives.s
@@ -0,0 +1,36 @@
+# RUN: llvm-mc -filetype=obj -triple=riscv32be %s -o %t.32be.o
+# RUN: llvm-objdump -s %t.32be.o | FileCheck -check-prefix=RV32BE %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64be %s -o %t.64be.o
+# RUN: llvm-objdump -s %t.64be.o | FileCheck -check-prefix=RV64BE %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 %s -o %t.32le.o
+# RUN: llvm-objdump -s %t.32le.o | FileCheck -check-prefix=RV32LE %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.64le.o
+# RUN: llvm-objdump -s %t.64le.o | FileCheck -check-prefix=RV64LE %s
+
+# Test that data directives are properly byte-swapped on big-endian RISC-V
+
+.data
+
+byte_data:
+  .byte 0x11
+  .byte 0x22
+  .half 0x3344
+  .word 0x55667788
+  .long 0x99aabbcc
+  .quad 0x1122334455667788
+
+# RV32BE: Contents of section .data:
+# RV32BE-NEXT:  0000 11223344 55667788 99aabbcc 11223344
+# RV32BE-NEXT:  0010 55667788
+
+# RV64BE: Contents of section .data:
+# RV64BE-NEXT:  0000 11223344 55667788 99aabbcc 11223344
+# RV64BE-NEXT:  0010 55667788
+
+# RV32LE: Contents of section .data:
+# RV32LE-NEXT:  0000 11224433 88776655 ccbbaa99 88776655
+# RV32LE-NEXT:  0010 44332211
+
+# RV64LE: Contents of section .data:
+# RV64LE-NEXT:  0000 11224433 88776655 ccbbaa99 88776655
+# RV64LE-NEXT:  0010 44332211
diff --git a/llvm/test/MC/RISCV/bigendian-fixups.s b/llvm/test/MC/RISCV/bigendian-fixups.s
new file mode 100644
index 0000000000000..8c9f448e83b5e
--- /dev/null
+++ b/llvm/test/MC/RISCV/bigendian-fixups.s
@@ -0,0 +1,60 @@
+# RUN: llvm-mc -filetype=obj -triple=riscv32be < %s \
+# RUN:     | llvm-objdump --no-print-imm-hex -M no-aliases -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INSTR %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32be %s \
+# RUN:     | llvm-readobj -r - | FileCheck %s -check-prefix=CHECK-REL
+# RUN: llvm-mc -filetype=obj -triple=riscv64be < %s \
+# RUN:     | llvm-objdump --no-print-imm-hex -M no-aliases -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INSTR %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64be %s \
+# RUN:     | llvm-readobj -r - | FileCheck %s -check-prefix=CHECK-REL
+
+# Test that fixups work correctly on big-endian RISC-V targets
+
+.LBB0:
+lui t1, %hi(val)
+# CHECK-INSTR: lui t1, 74565
+
+lw a0, %lo(val)(t1)
+# CHECK-INSTR: lw a0, 1656(t1)
+addi a1, t1, %lo(val)
+# CHECK-INSTR: addi a1, t1, 1656
+sw a0, %lo(val)(t1)
+# CHECK-INSTR: sw a0, 1656(t1)
+
+1:
+auipc t1, %pcrel_hi(.LBB0)
+# CHECK-INSTR: auipc t1, 0
+addi t1, t1, %pcrel_lo(1b)
+# CHECK-INSTR: addi t1, t1, -16
+sw t1, %pcrel_lo(1b)(t1)
+# CHECK-INSTR: sw t1, -16(t1)
+
+jal zero, .LBB0
+# CHECK-INSTR: jal zero, 0x0
+jal zero, .LBB2
+# CHECK-INSTR: jal zero, 0x50d14
+beq a0, a1, .LBB0
+# CHECK-INSTR: beq a0, a1, 0x0
+blt a0, a1, .LBB1
+# CHECK-INSTR: blt a0, a1, 0x47c
+
+.fill 1104
+
+.LBB1:
+
+.fill 329876
+addi zero, zero, 0
+.LBB2:
+
+.set val, 0x12345678
+
+# CHECK-REL-NOT: R_RISCV
+
+# Test data fixups
+.data
+.align 3
+data_label:
+  .word val
+  .long val
+  .quad val
diff --git a/llvm/test/MC/RISCV/elf-bigendian.s b/llvm/test/MC/RISCV/elf-bigendian.s
new file mode 100644
index 0000000000000..da12a14aea142
--- /dev/null
+++ b/llvm/test/MC/RISCV/elf-bigendian.s
@@ -0,0 +1,46 @@
+# RUN: llvm-mc %s -filetype=obj -triple=riscv32be | llvm-readobj -h - \
+# RUN:     | FileCheck -check-prefix=RV32BE %s
+# RUN: llvm-mc %s -filetype=obj -triple=riscv64be | llvm-readobj -h - \
+# RUN:     | FileCheck -check-prefix=RV64BE %s
+
+# Test that RISC-V big-endian targets produce correct ELF headers
+
+# RV32BE: Format: elf32-bigriscv
+# RV32BE: Arch: riscv32
+# RV32BE: AddressSize: 32bit
+# RV32BE: ElfHeader {
+# RV32BE:   Ident {
+# RV32BE:     Magic: (7F 45 4C 46)
+# RV32BE:     Class: 32-bit (0x1)
+# RV32BE:     DataEncoding: BigEndian (0x2)
+# RV32BE:     FileVersion: 1
+# RV32BE:     OS/ABI: SystemV (0x0)
+# RV32BE:     ABIVersion: 0
+# RV32BE:   }
+# RV32BE:   Type: Relocatable (0x1)
+# RV32BE:   Machine: EM_RISCV (0xF3)
+# RV32BE:   Version: 1
+# RV32BE:   Flags [ (0x0)
+# RV32BE:   ]
+# RV32BE: }
+
+# RV64BE: Format: elf64-bigriscv
+# RV64BE: Arch: riscv64
+# RV64BE: AddressSize: 64bit
+# RV64BE: ElfHeader {
+# RV64BE:   Ident {
+# RV64BE:     Magic: (7F 45 4C 46)
+# RV64BE:     Class: 64-bit (0x2)
+# RV64BE:     DataEncoding: BigEndian (0x2)
+# RV64BE:     FileVersion: 1
+# RV64BE:     OS/ABI: SystemV (0x0)
+# RV64BE:     ABIVersion: 0
+# RV64BE:   }
+# RV64BE:   Type: Relocatable (0x1)
+# RV64BE:   Machine: EM_RISCV (0xF3)
+# RV64BE:   Version: 1
+# RV64BE:   Flags [ (0x0)
+# RV64BE:   ]
+# RV64BE: }
+
+nop

>From 1d05e18f241b6c53bb6a6623ad5ec27432dd4fbb Mon Sep 17 00:00:00 2001
From: Djordje Todorovic <djordje.todorovic at htecgroup.com>
Date: Thu, 7 Aug 2025 18:07:26 +0200
Subject: [PATCH 3/7] Address comments

---
 .../RISCV/MCTargetDesc/RISCVAsmBackend.cpp    |  2 +-
 llvm/lib/Target/RISCV/RISCVTargetMachine.cpp  | 30 ++++++++++++-------
 2 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index 3f662374d4023..d38e3601fbd7e 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -930,7 +930,7 @@ void RISCVAsmBackend::applyFixup(const MCFragment &F, 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);
+  bool SwapValue = Endian == llvm::endianness::big && isDataFixup(Kind);
   for (unsigned i = 0; i != NumBytes; ++i) {
     unsigned Idx = SwapValue ? (NumBytes - 1 - i) : i;
     Data[Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
index 3a16256aed462..d2446c43e3a08 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -154,21 +154,31 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
 
 static std::string computeDataLayout(const Triple &TT,
                                      const TargetOptions &Opts) {
-  const bool IsLittle = TT.isLittleEndian();
-  StringRef ABI = Opts.MCOptions.getABIName();
-  std::string DL;
+  std::string Endianness = TT.isLittleEndian() ? "e" : "E";
+
+  std::string PointerAndIntegerLayout;
+  std::string NativeIntegerWidths;
 
   if (TT.isArch64Bit()) {
-    DL = (Twine(IsLittle ? "e" : "E") + "-m:e-p:64:64-i64:64-i128:128-n32:64-" +
-          (ABI == "lp64e" ? "S64" : "S128"))
-             .str();
+    PointerAndIntegerLayout = "p:64:64-i64:64-i128:128";
+    NativeIntegerWidths = "n32:64";
   } 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();
+    PointerAndIntegerLayout = "p:32:32-i64:64";
+    NativeIntegerWidths = "n32";
   }
-  return DL;
+
+  StringRef ABI = Opts.MCOptions.getABIName();
+  std::string StackAlignment;
+
+  if (TT.isArch64Bit()) {
+    StackAlignment = (ABI == "lp64e") ? "S64" : "S128";
+  } else {
+    StackAlignment = (ABI == "ilp32e") ? "S32" : "S128";
+  }
+
+  return Endianness + "-m:e-" + PointerAndIntegerLayout + "-" +
+         NativeIntegerWidths + "-" + StackAlignment;
 }
 
 static Reloc::Model getEffectiveRelocModel(const Triple &TT,

>From 3ef49fb75fbe23b4dfb2147a1698cd7ff7b743ef Mon Sep 17 00:00:00 2001
From: Djordje Todorovic <djordje.todorovic at htecgroup.com>
Date: Wed, 13 Aug 2025 11:54:24 +0200
Subject: [PATCH 4/7] Address comments

- Drop change in llvm/cmake/config.guess
- Align computeDataLayout with X86 and ARM
---
 llvm/cmake/config.guess                      |  2 +-
 llvm/lib/Target/RISCV/RISCVTargetMachine.cpp | 29 +++++++++++---------
 2 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/llvm/cmake/config.guess b/llvm/cmake/config.guess
index 27b55bd166edc..96cc554f181ab 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:*:* | riscv32be:Linux:*:* | riscv64be:Linux:*:*)
+    riscv32:Linux:*:* | riscv64:Linux:*:*)
 	LIBC=gnu
 	eval $set_cc_for_build
 	# Do not check for __GLIBC__ because uclibc defines it too
diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
index d2446c43e3a08..7ea0d199cd896 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -154,31 +154,34 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
 
 static std::string computeDataLayout(const Triple &TT,
                                      const TargetOptions &Opts) {
-  std::string Endianness = TT.isLittleEndian() ? "e" : "E";
+  std::string Ret;
 
-  std::string PointerAndIntegerLayout;
-  std::string NativeIntegerWidths;
+  if (TT.isLittleEndian())
+    Ret += "e";
+  else
+    Ret += "E";
 
+  Ret += "-m:e";
+
+  // Pointer and integer sizes.
   if (TT.isArch64Bit()) {
-    PointerAndIntegerLayout = "p:64:64-i64:64-i128:128";
-    NativeIntegerWidths = "n32:64";
+    Ret += "-p:64:64-i64:64-i128:128";
+    Ret += "-n32:64";
   } else {
     assert(TT.isArch32Bit() && "only RV32 and RV64 are currently supported");
-    PointerAndIntegerLayout = "p:32:32-i64:64";
-    NativeIntegerWidths = "n32";
+    Ret += "-p:32:32-i64:64";
+    Ret += "-n32";
   }
 
+  // Stack alignment based on ABI.
   StringRef ABI = Opts.MCOptions.getABIName();
-  std::string StackAlignment;
-
   if (TT.isArch64Bit()) {
-    StackAlignment = (ABI == "lp64e") ? "S64" : "S128";
+    Ret += (ABI == "lp64e") ? "-S64" : "-S128";
   } else {
-    StackAlignment = (ABI == "ilp32e") ? "S32" : "S128";
+    Ret += (ABI == "ilp32e") ? "-S32" : "-S128";
   }
 
-  return Endianness + "-m:e-" + PointerAndIntegerLayout + "-" +
-         NativeIntegerWidths + "-" + StackAlignment;
+  return Ret;
 }
 
 static Reloc::Model getEffectiveRelocModel(const Triple &TT,

>From 565097c32c083e9cca69588bd52d26b6b09855d7 Mon Sep 17 00:00:00 2001
From: Djordje Todorovic <djordje.todorovic at htecgroup.com>
Date: Thu, 14 Aug 2025 10:47:43 +0200
Subject: [PATCH 5/7] Apply refactor

---
 llvm/lib/Target/RISCV/RISCVTargetMachine.cpp | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
index 7ea0d199cd896..12e4e813f5d96 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -175,10 +175,14 @@ static std::string computeDataLayout(const Triple &TT,
 
   // Stack alignment based on ABI.
   StringRef ABI = Opts.MCOptions.getABIName();
-  if (TT.isArch64Bit()) {
-    Ret += (ABI == "lp64e") ? "-S64" : "-S128";
+  if (ABI == "ilp32e") {
+    assert(TT.isArch32Bit() && "ilp32e is only for RV32");
+    Ret += "-S32";
+  } else if (ABI == "lp64e") {
+    assert(TT.isArch64Bit() && "lp64e is only for RV64");
+    Ret += "-S64";
   } else {
-    Ret += (ABI == "ilp32e") ? "-S32" : "-S128";
+    Ret += "-S128";
   }
 
   return Ret;

>From df1944942a743f957df16a610ef2874b7c629af8 Mon Sep 17 00:00:00 2001
From: Djordje Todorovic <djordje.todorovic at htecgroup.com>
Date: Mon, 18 Aug 2025 12:42:14 +0200
Subject: [PATCH 6/7] Improve tests

---
 llvm/lib/MC/MCAsmStreamer.cpp                 |   7 +-
 llvm/lib/Target/RISCV/RISCVTargetMachine.cpp  |   9 +-
 .../MC/RISCV/Relocations/bigendian-fixups.s   | 101 ++++++++++++++++++
 llvm/test/MC/RISCV/bigendian-fixups.s         |  60 -----------
 4 files changed, 110 insertions(+), 67 deletions(-)
 create mode 100644 llvm/test/MC/RISCV/Relocations/bigendian-fixups.s
 delete mode 100644 llvm/test/MC/RISCV/bigendian-fixups.s

diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 93614cd61bf6e..12774cbb8cc66 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -2341,6 +2341,9 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
 
   getAssembler().getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
 
+  // RISC-V instructions are always little-endian, even on BE systems.
+  bool ForceLE = getContext().getTargetTriple().isRISCV();
+
   // If we are showing fixups, create symbolic markers in the encoded
   // representation. We do this by making a per-bit map to the fixup item index,
   // then trying to display it as nicely as possible.
@@ -2395,7 +2398,9 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
         unsigned Bit = (Code[i] >> j) & 1;
 
         unsigned FixupBit;
-        if (MAI->isLittleEndian())
+        // RISC-V instructions are always little-endian.
+        // The FixupMap is indexed by actual bit positions in the LE instruction.
+        if (MAI->isLittleEndian() || ForceLE)
           FixupBit = i * 8 + j;
         else
           FixupBit = i * 8 + (7-j);
diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
index 12e4e813f5d96..610cd796c996d 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -175,15 +175,12 @@ static std::string computeDataLayout(const Triple &TT,
 
   // Stack alignment based on ABI.
   StringRef ABI = Opts.MCOptions.getABIName();
-  if (ABI == "ilp32e") {
-    assert(TT.isArch32Bit() && "ilp32e is only for RV32");
+  if (ABI == "ilp32e")
     Ret += "-S32";
-  } else if (ABI == "lp64e") {
-    assert(TT.isArch64Bit() && "lp64e is only for RV64");
+  else if (ABI == "lp64e")
     Ret += "-S64";
-  } else {
+  else
     Ret += "-S128";
-  }
 
   return Ret;
 }
diff --git a/llvm/test/MC/RISCV/Relocations/bigendian-fixups.s b/llvm/test/MC/RISCV/Relocations/bigendian-fixups.s
new file mode 100644
index 0000000000000..b79a282de932b
--- /dev/null
+++ b/llvm/test/MC/RISCV/Relocations/bigendian-fixups.s
@@ -0,0 +1,101 @@
+# RUN: llvm-mc --triple=riscv32be %s --show-encoding \
+# RUN:     | FileCheck --check-prefixes=CHECK-FIXUP,CHECK-ENCODING %s
+# RUN: llvm-mc --filetype=obj --triple=riscv32be %s \
+# RUN:     | llvm-objdump -d - | FileCheck --check-prefix=CHECK-INSTR %s
+# RUN: llvm-mc --filetype=obj --triple=riscv32be %s \
+# RUN:     | llvm-readobj -r - | FileCheck --check-prefix=CHECK-REL %s
+
+# RUN: llvm-mc --triple=riscv64be %s --show-encoding \
+# RUN:     | FileCheck --check-prefixes=CHECK-FIXUP,CHECK-ENCODING %s
+# RUN: llvm-mc --filetype=obj --triple=riscv64be %s \
+# RUN:     | llvm-objdump -d - | FileCheck --check-prefix=CHECK-INSTR %s
+# RUN: llvm-mc --filetype=obj --triple=riscv64be %s \
+# RUN:     | llvm-readobj -r - | FileCheck --check-prefix=CHECK-REL %s
+
+## Checks that fixups that can be resolved within the same object file are
+## applied correctly on big-endian RISC-V targets.
+##
+## This test verifies that RISC-V instructions remain little-endian even on
+## big-endian systems. This is a fundamental property of RISC-V:
+## - Instructions are always little-endian
+## - Data can be big-endian or little-endian depending on the system
+
+.LBB0:
+addi t0, t0, 1
+# CHECK-ENCODING: encoding: [0x93,0x82,0x12,0x00]
+# CHECK-INSTR: addi t0, t0, 0x1
+
+lui t1, %hi(val)
+# CHECK-ENCODING: encoding: [0x37,0bAAAA0011,A,A]
+# CHECK-FIXUP: fixup A - offset: 0, value: %hi(val), kind: fixup_riscv_hi20
+# CHECK-INSTR: lui t1, 0x12345
+
+lw a0, %lo(val)(t1)
+# CHECK-ENCODING: encoding: [0x03,0x25,0bAAAA0011,A]
+# CHECK-FIXUP: fixup A - offset: 0, value: %lo(val), kind: fixup_riscv_lo12_i
+# CHECK-INSTR: lw a0, 0x678(t1)
+
+addi a1, t1, %lo(val)
+# CHECK-ENCODING: encoding: [0x93,0x05,0bAAAA0011,A]
+# CHECK-FIXUP: fixup A - offset: 0, value: %lo(val), kind: fixup_riscv_lo12_i
+# CHECK-INSTR: addi a1, t1, 0x678
+
+sw a0, %lo(val)(t1)
+# CHECK-ENCODING: encoding: [0x23'A',0x20'A',0xa3'A',A]
+# CHECK-FIXUP: fixup A - offset: 0, value: %lo(val), kind: fixup_riscv_lo12_s
+# CHECK-INSTR: sw a0, 0x678(t1)
+
+1:
+auipc t1, %pcrel_hi(.LBB0)
+# CHECK-ENCODING: encoding: [0x17,0bAAAA0011,A,A]
+# CHECK-FIXUP: fixup A - offset: 0, value: %pcrel_hi(.LBB0), kind: fixup_riscv_pcrel_hi20
+# CHECK-INSTR: auipc t1, 0
+
+addi t1, t1, %pcrel_lo(1b)
+# CHECK-ENCODING: encoding: [0x13,0x03,0bAAAA0011,A]
+# CHECK-FIXUP: fixup A - offset: 0, value: %pcrel_lo({{.*}}), kind: fixup_riscv_pcrel_lo12_i
+# CHECK-INSTR: addi t1, t1, -0x14
+
+sw t1, %pcrel_lo(1b)(t1)
+# CHECK-ENCODING: encoding: [0x23'A',0x20'A',0x63'A',A]
+# CHECK-FIXUP: fixup A - offset: 0, value: %pcrel_lo({{.*}}), kind: fixup_riscv_pcrel_lo12_s
+# CHECK-INSTR: sw t1, -0x14(t1)
+
+jal zero, .LBB0
+# CHECK-ENCODING: encoding: [0x6f,0bAAAA0000,A,A]
+# CHECK-FIXUP: fixup A - offset: 0, value: .LBB0, kind: fixup_riscv_jal
+# CHECK-INSTR: j 0x0 <.text>
+
+jal zero, .LBB2
+# CHECK-ENCODING: encoding: [0x6f,0bAAAA0000,A,A]
+# CHECK-FIXUP: fixup A - offset: 0, value: .LBB2, kind: fixup_riscv_jal
+# CHECK-INSTR: j 0x50d18 <.text+0x50d18>
+
+beq a0, a1, .LBB0
+# CHECK-ENCODING: encoding: [0x63'A',A,0xb5'A',A]
+# CHECK-FIXUP: fixup A - offset: 0, value: .LBB0, kind: fixup_riscv_branch
+# CHECK-INSTR: beq a0, a1, 0x0 <.text>
+
+blt a0, a1, .LBB1
+# CHECK-ENCODING: encoding: [0x63'A',0x40'A',0xb5'A',A]
+# CHECK-FIXUP: fixup A - offset: 0, value: .LBB1, kind: fixup_riscv_branch
+# CHECK-INSTR: blt a0, a1, 0x480 <.text+0x480>
+
+.fill 1104
+
+.LBB1:
+
+.fill 329876
+addi zero, zero, 0
+.LBB2:
+
+.set val, 0x12345678
+
+# CHECK-REL-NOT: R_RISCV
+
+.data
+.align 3
+data_label:
+  .word val  # On BE: 0x12345678 stored as [0x12, 0x34, 0x56, 0x78]
+  .long val  # On BE: 0x12345678 stored as [0x12, 0x34, 0x56, 0x78]
+  .quad val  # On BE: 0x0000000012345678 stored as [0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78]
diff --git a/llvm/test/MC/RISCV/bigendian-fixups.s b/llvm/test/MC/RISCV/bigendian-fixups.s
deleted file mode 100644
index 8c9f448e83b5e..0000000000000
--- a/llvm/test/MC/RISCV/bigendian-fixups.s
+++ /dev/null
@@ -1,60 +0,0 @@
-# RUN: llvm-mc -filetype=obj -triple=riscv32be < %s \
-# RUN:     | llvm-objdump --no-print-imm-hex -M no-aliases -d - \
-# RUN:     | FileCheck -check-prefix=CHECK-INSTR %s
-# RUN: llvm-mc -filetype=obj -triple=riscv32be %s \
-# RUN:     | llvm-readobj -r - | FileCheck %s -check-prefix=CHECK-REL
-# RUN: llvm-mc -filetype=obj -triple=riscv64be < %s \
-# RUN:     | llvm-objdump --no-print-imm-hex -M no-aliases -d - \
-# RUN:     | FileCheck -check-prefix=CHECK-INSTR %s
-# RUN: llvm-mc -filetype=obj -triple=riscv64be %s \
-# RUN:     | llvm-readobj -r - | FileCheck %s -check-prefix=CHECK-REL
-
-# Test that fixups work correctly on big-endian RISC-V targets
-
-.LBB0:
-lui t1, %hi(val)
-# CHECK-INSTR: lui t1, 74565
-
-lw a0, %lo(val)(t1)
-# CHECK-INSTR: lw a0, 1656(t1)
-addi a1, t1, %lo(val)
-# CHECK-INSTR: addi a1, t1, 1656
-sw a0, %lo(val)(t1)
-# CHECK-INSTR: sw a0, 1656(t1)
-
-1:
-auipc t1, %pcrel_hi(.LBB0)
-# CHECK-INSTR: auipc t1, 0
-addi t1, t1, %pcrel_lo(1b)
-# CHECK-INSTR: addi t1, t1, -16
-sw t1, %pcrel_lo(1b)(t1)
-# CHECK-INSTR: sw t1, -16(t1)
-
-jal zero, .LBB0
-# CHECK-INSTR: jal zero, 0x0
-jal zero, .LBB2
-# CHECK-INSTR: jal zero, 0x50d14
-beq a0, a1, .LBB0
-# CHECK-INSTR: beq a0, a1, 0x0
-blt a0, a1, .LBB1
-# CHECK-INSTR: blt a0, a1, 0x47c
-
-.fill 1104
-
-.LBB1:
-
-.fill 329876
-addi zero, zero, 0
-.LBB2:
-
-.set val, 0x12345678
-
-# CHECK-REL-NOT: R_RISCV
-
-# Test data fixups
-.data
-.align 3
-data_label:
-  .word val
-  .long val
-  .quad val

>From 660d163a8978a2b4e2f3912c898ceac98460792f Mon Sep 17 00:00:00 2001
From: Djordje Todorovic <djordje.todorovic at htecgroup.com>
Date: Tue, 19 Aug 2025 10:27:55 +0200
Subject: [PATCH 7/7] Remove fixup_riscv_*

---
 .../RISCV/MCTargetDesc/RISCVAsmBackend.cpp    | 27 +++----------------
 1 file changed, 4 insertions(+), 23 deletions(-)

diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index d38e3601fbd7e..e55538c018cb6 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -871,38 +871,19 @@ bool RISCVAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup,
   return false;
 }
 
-// Data should be swapped for big endian cores.
+// Data fixups should be swapped for big endian cores.
+// Instruction fixups should not be swapped as RISC-V instructions
+// are always little-endian.
 static bool isDataFixup(unsigned Kind) {
   switch (Kind) {
   default:
-    llvm_unreachable("Unknown fixup kind!");
+    return false;
 
   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:
-  case RISCV::fixup_riscv_12_i:
-  case RISCV::fixup_riscv_rvc_imm:
-  case RISCV::fixup_riscv_qc_e_branch:
-  case RISCV::fixup_riscv_qc_e_32:
-  case RISCV::fixup_riscv_qc_abs20_u:
-  case RISCV::fixup_riscv_qc_e_call_plt:
-  case RISCV::fixup_riscv_nds_branch_10:
-    return false;
   }
 }
 



More information about the llvm-commits mailing list