[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