[llvm] b686226 - [RISC-V][Mach-O] Use RISCV_RELOC_ADDEND for large pc-relative offset. (#178699)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 30 10:14:40 PST 2026
Author: Francesco Petrogalli
Date: 2026-01-30T10:14:36-08:00
New Revision: b6862267320e51915cff8c2156bfef6a1e38880f
URL: https://github.com/llvm/llvm-project/commit/b6862267320e51915cff8c2156bfef6a1e38880f
DIFF: https://github.com/llvm/llvm-project/commit/b6862267320e51915cff8c2156bfef6a1e38880f.diff
LOG: [RISC-V][Mach-O] Use RISCV_RELOC_ADDEND for large pc-relative offset. (#178699)
Do not inline the pc-relative offset from the auipc into the addi/lw
immediates if the offset requires than the 12-bit (signed). Instead,
emit a 24-bit (signed) relocation record with RISCV_RELOC_ADDEND.
Added:
llvm/test/MC/RISCV/macho-offset-relocations.s
Modified:
llvm/include/llvm/BinaryFormat/MachO.h
llvm/lib/Target/RISCV/MCTargetDesc/RISCVMachObjectWriter.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/BinaryFormat/MachO.h b/llvm/include/llvm/BinaryFormat/MachO.h
index 4db854aa76ec6..4dfc1ff204555 100644
--- a/llvm/include/llvm/BinaryFormat/MachO.h
+++ b/llvm/include/llvm/BinaryFormat/MachO.h
@@ -509,9 +509,10 @@ enum RelocationInfoType {
// not support no-PIC). Note: the compiler places the distance to
// the paired AUIPC in the imm12 (e.g. if previous instruction is
// the AUIPC, the imm12 is -4 or 0xFFC). NOTE: this mean that the
- // separation between hi/lo has to fit in (signed) 12 bits. FIXME:
- // this needs addressing for code models that go beyond 4k
- // functions.
+ // separation between hi/lo has to fit in (signed) 12 bits. Beyond
+ // 12-bits, the pc-relative offset is not inlined in the imm12, but
+ // it is instead stored in the 24-bits of a RISCV_RELOC_ADDEND
+ // record.
RISCV_RELOC_LO12 = 4,
// High 20 bits of GOT slot. r_pcrel=1 means this is paired with an
// AUIPC. r_pcrel=0 means this is paired with a LUI (the compiler
@@ -527,8 +528,8 @@ enum RelocationInfoType {
// section). Not currently used, but added for completeness.
RISCV_RELOC_POINTER_TO_GOT = 7,
// Adds a static offset to a relocation. Must be followed by
- // RISCV_RELOC_PCREL_HI or RISCV_RELOC_BRANCH21. For example, the 16
- // bytes offset in:
+ // RISCV_RELOC_PCREL_HI, RISCV_RELOC_BRANCH21 or
+ // RISCV_RELOC_LO12. For example, the 16 bytes offset in:
//
// auipc a0, %pcrel_hi(var+16)
RISCV_RELOC_ADDEND = 8,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMachObjectWriter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMachObjectWriter.cpp
index c3545d8bc524b..8a6a4561d8b5a 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMachObjectWriter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMachObjectWriter.cpp
@@ -186,6 +186,8 @@ void RISCVMachObjectWriter::recordRelocation(
unsigned Type = 0;
const unsigned Kind = Fixup.getKind();
const MCSymbol *RelSymbol = nullptr;
+ bool RequireExtraAddend = false;
+ uint64_t ExtraAddendValue = 0;
FixupOffset += Fixup.getOffset();
@@ -213,11 +215,15 @@ void RISCVMachObjectWriter::recordRelocation(
// will be put into the instruction itself.
FixedValue =
Asm.getFragmentOffset(*AUIPCDF) + AUIPCFixup->getOffset() - FixupOffset;
- if (!isValidInt<12>(
- FixedValue,
- "AUIPC out of range of corresponding %pcrel_lo instruction", Asm,
- Fixup.getLoc()))
- return;
+ if (!isInt<12>(FixedValue)) {
+ RequireExtraAddend = true;
+ ExtraAddendValue = FixedValue;
+ if (!isValidInt<24>(
+ ExtraAddendValue,
+ "AUIPC out of range of corresponding %pcrel_lo instruction", Asm,
+ Fixup.getLoc()))
+ return;
+ }
// Retarget the rest of this function to reference the AUIPC's symbol.
MCValue RealTarget;
@@ -260,9 +266,11 @@ void RISCVMachObjectWriter::recordRelocation(
Value = Target.getConstant();
// Only .word and %pcrel_lo instructions inline the pc-relative
- // offset in the instruction.
- if (Type != MachO::RISCV_RELOC_UNSIGNED && Type != MachO::RISCV_RELOC_LO12 &&
- Type != MachO::RISCV_RELOC_GOT_LO12)
+ // offset in the instruction, but only if such offset fits the
+ // 12-bit immediate of an addi or an lw instrucion.
+ if ((Type != MachO::RISCV_RELOC_UNSIGNED && Type != MachO::RISCV_RELOC_LO12 &&
+ Type != MachO::RISCV_RELOC_GOT_LO12) ||
+ RequireExtraAddend)
FixedValue = 0;
// Emit relocations.
@@ -419,6 +427,12 @@ void RISCVMachObjectWriter::recordRelocation(
emitRelocation(Writer, Fragment, FixupOffset, RelSymbol, Index, IsPCRel,
Log2Size, Type);
}
+
+ if (RequireExtraAddend) {
+ emitRelocation(Writer, Fragment, FixupOffset, /*RelSymbol*/ nullptr,
+ ExtraAddendValue & 0xffffff, /*IsPCRel*/ false,
+ /*Log2Size*/ 2, /*Type*/ MachO::RISCV_RELOC_ADDEND);
+ }
}
std::unique_ptr<MCObjectTargetWriter>
diff --git a/llvm/test/MC/RISCV/macho-offset-relocations.s b/llvm/test/MC/RISCV/macho-offset-relocations.s
new file mode 100644
index 0000000000000..c2cc5aadcc622
--- /dev/null
+++ b/llvm/test/MC/RISCV/macho-offset-relocations.s
@@ -0,0 +1,46 @@
+; RUN: llvm-mc -triple riscv32-apple-macho %s -o %t.o -filetype=obj
+; RUN: llvm-objdump -dr %t.o | FileCheck %s
+; RUN: llvm-otool -Vtr %t.o | FileCheck %s --check-prefix=OTOOL
+
+Lpcrel_hi0:
+ auipc a0, %pcrel_hi(_glob)
+ .rep 511
+ nop
+ .endr
+ lw a1, %pcrel_lo(Lpcrel_hi0)(a0)
+ addi a1, a1, 1
+ ;; 4(auipc) + 511 * 4(nop) + 4(lw) + 4(addi) = 4 + 2044 + 8 = 2056
+ ;; -2056 is 0xfff7f8 in 24-bit two's complement representation
+ sw a1, %pcrel_lo(Lpcrel_hi0)(a0)
+ ret
+
+; CHECK-LABEL: 00000000 <ltmp0>:
+; CHECK-LABEL: 0: 00000517 auipc a0, 0x0
+; CHECK-NEXT: 00000000: RISCV_RELOC_HI20(pcrel) _glob
+; CHECK-NEXT: 4: 00000013 nop
+; CHECK-NEXT: 8: 00000013 nop
+; CHECK-NEXT: c: 00000013 nop
+; ...
+; CHECK-LABEL: 7fc: 00000013 nop
+; CHECK-NEXT: 800: 80052583 lw a1, -0x800(a0)
+; CHECK-NEXT: 00000800: RISCV_RELOC_LO12(pcrel) _glob
+; CHECK-NEXT: 804: 00158593 addi a1, a1, 0x1
+; CHECK-NEXT: 808: 00b52023 sw a1, 0x0(a0)
+; CHECK-NEXT: 00000808: RISCV_RELOC_ADDEND 0xfff7f8
+; CHECK-NEXT: 00000808: RISCV_RELOC_LO12(pcrel) _glob
+; CHECK-NEXT: 80c: 00008067 ret
+
+; OTOOL-LABEL: Relocation information (__TEXT,__text) 4 entries
+; OTOOL-NEXT: address pcrel length extern type scattered symbolnum/value
+; OTOOL-NEXT: 00000808 False long False 8 False addend = 0xfff7f8
+; OTOOL-NEXT: 00000808 True long True 4 False _glob
+; OTOOL-NEXT: 00000800 True long True 4 False _glob
+; OTOOL-NEXT: 00000000 True long True 3 False _glob
+; OTOOL-NEXT: Contents of (__TEXT,__text) section
+; OTOOL-NEXT: 00000000 auipc a0, 0x0
+; ...
+; OTOOL-LABEL: 000007fc nop
+; OTOOL-NEXT: 00000800 lw a1, -0x800(a0)
+; OTOOL-NEXT: 00000804 addi a1, a1, 0x1
+; OTOOL-NEXT: 00000808 sw a1, 0x0(a0)
+; OTOOL-NEXT: 0000080c ret
More information about the llvm-commits
mailing list