[llvm] [SPARC] Fix %hi/%lo of absolute expressions in PIC mode (PR #215066)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 9 00:06:15 PDT 2026


https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/215066

adjustPICRelocation maps %hi/%lo to GOT22/PC22 or GOT10/PC10 at parse
time, before the operand is known to be absolute. adjustFixupValue has
no case for the GOT types, so an absolute operand encodes the unshifted
value:

Encode %got22/%got10 like %hi/%lo. Also drop them as input syntax; GNU
as has no such operators.

>From b85cc273d7868da3d6058d7fd7d10a56ecbea603 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sat, 8 Aug 2026 23:33:06 -0700
Subject: [PATCH] [SPARC] Fix %hi/%lo of absolute expressions in PIC mode

adjustPICRelocation maps %hi/%lo to GOT22/PC22 or GOT10/PC10 at parse
time, before the operand is known to be absolute. adjustFixupValue has
no case for the GOT types, so an absolute operand encodes the unshifted
value:

Encode %got22/%got10 like %hi/%lo. Also drop them as input syntax; GNU
as has no such operators.
---
 .../Sparc/MCTargetDesc/SparcAsmBackend.cpp    |  4 +++
 .../Target/Sparc/MCTargetDesc/SparcMCExpr.cpp |  2 --
 .../MC/Sparc/Relocations/absolute-hi-lo.s     | 35 +++++++++++++++++++
 .../Sparc/Relocations/relocation-specifier.s  | 12 +++++++
 4 files changed, 51 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/MC/Sparc/Relocations/absolute-hi-lo.s

diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
index bc60842c3fd76..3be4ecbae843d 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
@@ -64,8 +64,11 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
   case ELF::R_SPARC_HIX22:
     return (~Value >> 10) & 0x3fffff;
 
+  // In PIC mode the parser may map %hi to PC22/GOT22. An operand that folds to
+  // an absolute value emits no relocation and needs the %hi encoding.
   case ELF::R_SPARC_PC22:
   case ELF::R_SPARC_HI22:
+  case ELF::R_SPARC_GOT22:
   case ELF::R_SPARC_LM22:
     return (Value >> 10) & 0x3fffff;
 
@@ -80,6 +83,7 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
 
   case ELF::R_SPARC_PC10:
   case ELF::R_SPARC_LO10:
+  case ELF::R_SPARC_GOT10:
     return Value & 0x3ff;
 
   case ELF::R_SPARC_H44:
diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
index 0f84fbd702b95..f21957882c3bb 100644
--- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
+++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
@@ -82,8 +82,6 @@ uint16_t Sparc::parseSpecifier(StringRef name) {
       .Case("lm", ELF::R_SPARC_LM22)
       .Case("pc22", ELF::R_SPARC_PC22)
       .Case("pc10", ELF::R_SPARC_PC10)
-      .Case("got22", ELF::R_SPARC_GOT22)
-      .Case("got10", ELF::R_SPARC_GOT10)
       .Case("got13", ELF::R_SPARC_GOT13)
       .Case("tgd_hi22", ELF::R_SPARC_TLS_GD_HI22)
       .Case("tgd_lo10", ELF::R_SPARC_TLS_GD_LO10)
diff --git a/llvm/test/MC/Sparc/Relocations/absolute-hi-lo.s b/llvm/test/MC/Sparc/Relocations/absolute-hi-lo.s
new file mode 100644
index 0000000000000..ed50b63e22ef5
--- /dev/null
+++ b/llvm/test/MC/Sparc/Relocations/absolute-hi-lo.s
@@ -0,0 +1,35 @@
+# RUN: llvm-mc -triple=sparcv9 -filetype=obj %s | llvm-objdump -dr - | FileCheck %s --implicit-check-not=R_SPARC
+# RUN: llvm-mc -triple=sparcv9 --position-independent -filetype=obj %s | llvm-objdump -dr - | FileCheck %s --implicit-check-not=R_SPARC
+
+# CHECK-LABEL: <abs>:
+# CHECK-NEXT:  sethi 0x48d15, %l5
+# CHECK-NEXT:  or %l5, 0x278, %l5
+# CHECK-NEXT:  sethi 0x3fb72e, %o0
+# CHECK-NEXT:  xor %o0, 0x298, %o0
+# CHECK-NEXT:  sethi 0x21d950, %o1
+# CHECK-NEXT:  or %o1, 0x321, %o1
+# CHECK-NEXT:  sethi 0x4, %o2
+# CHECK-NEXT:  or %o2, 0x234, %o2
+# CHECK-NEXT:  sethi 0x48d15, %o3
+# CHECK-NEXT:  or %o3, 0x278, %o3
+
+defined = 0xfedcba98
+
+.globl abs
+abs:
+  sethi %hi(0x12345678), %l5
+  or %l5, %lo(0x12345678), %l5
+  sethi %hi(defined), %o0
+  xor %o0, %lo(defined), %o0
+  sethi %hi(forward), %o1
+  or %o1, %lo(forward), %o1
+  sethi %hi(.Lend-.Lbegin), %o2
+  or %o2, %lo(.Lend-.Lbegin), %o2
+  set 0x12345678, %o3
+
+forward = 0x87654321
+
+.data
+.Lbegin:
+  .space 0x1234
+.Lend:
diff --git a/llvm/test/MC/Sparc/Relocations/relocation-specifier.s b/llvm/test/MC/Sparc/Relocations/relocation-specifier.s
index 8a996c99e55ac..c5900403617cc 100644
--- a/llvm/test/MC/Sparc/Relocations/relocation-specifier.s
+++ b/llvm/test/MC/Sparc/Relocations/relocation-specifier.s
@@ -8,6 +8,8 @@
 # RUN: llvm-objdump -dr %t | FileCheck %s --check-prefixes=OBJDUMP,OBJDUMP-V9
 # RUN: llvm-readelf -s - < %t | FileCheck %s --check-prefixes=READELF,READELF-V9 --implicit-check-not=TLS
 
+# RUN: not llvm-mc %s --defsym ERR=1 -triple=sparc 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
+
 # READELF: TLS     LOCAL  DEFAULT [[#]] s_tle_hix22
 # READELF: TLS     LOCAL  DEFAULT [[#]] s_tldo_hix22
 # READELF: TLS     GLOBAL DEFAULT   UND s_tle_lox10
@@ -217,3 +219,13 @@ s_tle_hix22:
 s_tldo_hix22:
         .word  0
         .size  Local, 4
+
+.ifdef ERR
+## GNU as has no %got22/%got10; PIC mode maps %hi/%lo to them instead.
+# ERR: [[#@LINE+2]]:8: error: invalid relocation specifier
+# ERR: [[#@LINE+1]]:8: error: unexpected token
+sethi %got22(sym), %l0
+# ERR: [[#@LINE+2]]:10: error: invalid relocation specifier
+# ERR: [[#@LINE+1]]:10: error: unexpected token
+or %g1, %got10(sym), %g3
+.endif



More information about the llvm-commits mailing list