[lld] [lld][Mips] Remove signed range check for R_MICROMIPS_26_S1 (PR #228880)
Jiaxun Yang via llvm-commits
llvm-commits at lists.llvm.org
Sun Oct 4 05:36:34 PDT 2026
https://github.com/FlyGoat created https://github.com/llvm/llvm-project/pull/228880
R_MICROMIPS_26_S1 encodes a shifted index within the current PC region,
not a signed absolute address. Applying the PC-relative relocation's
signed 27-bit check rejects valid destinations in higher address regions.
Write the jump index without that check, as for R_MIPS_26, while retaining
the signed range check for R_MICROMIPS_PC26_S1. Cover both jumps and calls
at a high address in little- and big-endian objects.
Assisted-by: OpenAI Codex # Testcases
Validation: `git diff --check` passes. Tests were not rerun for this cherry-pick.
>From edbb8e566acb96caebbb40ab6ed781bbdfbdc32c Mon Sep 17 00:00:00 2001
From: Jiaxun Yang <jiaxun.yang at flygoat.com>
Date: Sun, 4 Oct 2026 12:23:41 +0100
Subject: [PATCH] [lld][Mips] Remove signed range check for R_MICROMIPS_26_S1
R_MICROMIPS_26_S1 encodes a shifted index within the current PC region,
not a signed absolute address. Applying the PC-relative relocation's
signed 27-bit check rejects valid destinations in higher address regions.
Write the jump index without that check, as for R_MIPS_26, while retaining
the signed range check for R_MICROMIPS_PC26_S1. Cover both jumps and calls
at a high address in little- and big-endian objects.
Assisted-by: OpenAI Codex # Testcases
---
lld/ELF/Arch/Mips.cpp | 4 ++++
lld/test/ELF/mips-micro-jump-region.s | 27 +++++++++++++++++++++++++++
2 files changed, 31 insertions(+)
create mode 100644 lld/test/ELF/mips-micro-jump-region.s
diff --git a/lld/ELF/Arch/Mips.cpp b/lld/ELF/Arch/Mips.cpp
index ba751660df1fa..308a0f75e588d 100644
--- a/lld/ELF/Arch/Mips.cpp
+++ b/lld/ELF/Arch/Mips.cpp
@@ -907,6 +907,10 @@ void MIPS<ELFT>::relocate(uint8_t *loc, const Relocation &rel,
writeValue(ctx, loc, val, 32, 0);
break;
case R_MICROMIPS_26_S1:
+ // Like R_MIPS_26, this encodes an index within the current PC region,
+ // not a signed absolute address. The destination need not fit in 27 bits.
+ writeShuffle<e>(ctx, loc, val, 26, 1);
+ break;
case R_MICROMIPS_PC26_S1:
checkInt(ctx, loc, val, 27, rel);
writeShuffle<e>(ctx, loc, val, 26, 1);
diff --git a/lld/test/ELF/mips-micro-jump-region.s b/lld/test/ELF/mips-micro-jump-region.s
new file mode 100644
index 0000000000000..ceb604f561911
--- /dev/null
+++ b/lld/test/ELF/mips-micro-jump-region.s
@@ -0,0 +1,27 @@
+# REQUIRES: mips
+# RUN: llvm-mc -triple=mipsel -mcpu=mips32r2 -mattr=+micromips -filetype=obj %s -o %t.le.o
+# RUN: ld.lld -Ttext=0x80100000 %t.le.o -o %t.le
+# RUN: llvm-objdump -s -j .text %t.le | FileCheck %s --check-prefix=LE
+# RUN: llvm-mc -triple=mips -mcpu=mips32r2 -mattr=+micromips -filetype=obj %s -o %t.be.o
+# RUN: ld.lld -Ttext=0x80100000 %t.be.o -o %t.be
+# RUN: llvm-objdump -s -j .text %t.be | FileCheck %s --check-prefix=BE
+
+## The jump index occupies 26 bits within the current PC region; the full
+## destination address need not fit in a signed 27-bit value.
+## Both a tail jump and a call must retain the low 27 address bits.
+# LE: 80100000 08d40800 00000000 08f40800 00000000
+# BE: 80100000 d4080008 00000000 f4080008 00000000
+
+.set micromips
+.set noreorder
+.globl __start, target
+.type __start, at function
+__start:
+ j target
+ sll $0, $0, 0
+ jal target
+ sll $0, $0, 0
+.type target, at function
+target:
+ jr $ra
+ sll $0, $0, 0
More information about the llvm-commits
mailing list