[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