[lld] [lld][Hexagon] Fix R_HEX_TPREL_11_X relocation on duplex instructions (PR #179860)
Brian Cain via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 4 20:53:00 PST 2026
https://github.com/androm3da created https://github.com/llvm/llvm-project/pull/179860
findMaskR11() was missing handling for duplex instructions. This caused incorrect encoding when R_HEX_TPREL_11_X relocations were applied to duplex instructions with large TLS offsets.
For duplex instructions, the immediate bits are located at positions 20-25 (mask 0x03f00000), not in the standard positions used for non-duplex instructions.
This fix adds the isDuplex() check to findMaskR11() to return the correct mask for duplex instruction encodings.
>From 17a483e07cba21cc09ff7845453a8c98eeafea1f Mon Sep 17 00:00:00 2001
From: Brian Cain <brian.cain at oss.qualcomm.com>
Date: Wed, 4 Feb 2026 20:51:39 -0800
Subject: [PATCH] [lld][Hexagon] Fix R_HEX_TPREL_11_X relocation on duplex
instructions
findMaskR11() was missing handling for duplex instructions. This caused
incorrect encoding when R_HEX_TPREL_11_X relocations were applied to
duplex instructions with large TLS offsets.
For duplex instructions, the immediate bits are located at positions 20-25
(mask 0x03f00000), not in the standard positions used for non-duplex
instructions.
This fix adds the isDuplex() check to findMaskR11() to return the correct
mask for duplex instruction encodings.
---
lld/ELF/Arch/Hexagon.cpp | 6 +++--
lld/test/ELF/hexagon-tls-tprel-duplex.s | 32 +++++++++++++++++++++++++
2 files changed, 36 insertions(+), 2 deletions(-)
create mode 100644 lld/test/ELF/hexagon-tls-tprel-duplex.s
diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp
index 9b33e78731c97..63621060775e7 100644
--- a/lld/ELF/Arch/Hexagon.cpp
+++ b/lld/ELF/Arch/Hexagon.cpp
@@ -225,6 +225,8 @@ static uint32_t findMaskR8(uint32_t insn) {
}
static uint32_t findMaskR11(uint32_t insn) {
+ if (isDuplex(insn))
+ return 0x03f00000;
if ((0xff000000 & insn) == 0xa1000000)
return 0x060020ff;
return 0x06003fe0;
@@ -390,14 +392,14 @@ void Hexagon::relocate(uint8_t *loc, const Relocation &rel,
break;
case R_HEX_B32_PCREL_X:
case R_HEX_GD_PLT_B32_PCREL_X:
- or32le(loc, applyMask(0x0fff3fff, val >> 6));
+ or32le(loc, applyMask(0x0fff3fff, static_cast<uint32_t>(val) >> 6));
break;
case R_HEX_GOTREL_HI16:
case R_HEX_HI16:
case R_HEX_IE_GOT_HI16:
case R_HEX_IE_HI16:
case R_HEX_TPREL_HI16:
- or32le(loc, applyMask(0x00c03fff, val >> 16));
+ or32le(loc, applyMask(0x00c03fff, static_cast<uint32_t>(val) >> 16));
break;
case R_HEX_GOTREL_LO16:
case R_HEX_LO16:
diff --git a/lld/test/ELF/hexagon-tls-tprel-duplex.s b/lld/test/ELF/hexagon-tls-tprel-duplex.s
new file mode 100644
index 0000000000000..c2f826b6fa3ad
--- /dev/null
+++ b/lld/test/ELF/hexagon-tls-tprel-duplex.s
@@ -0,0 +1,32 @@
+# REQUIRES: hexagon
+# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %s -o %t.o
+# RUN: llvm-readobj -r %t.o | FileCheck --check-prefix=RELOC %s
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-objdump -d --print-imm-hex %t | FileCheck %s
+
+## Test that R_HEX_TPREL_11_X relocations on duplex instructions produce
+## valid encodings. This test uses a large TLS block to ensure the TPREL
+## value is large enough to expose the encoding issue that was previously
+## present.
+
+ .globl _start
+ .type _start, @function
+_start:
+# RELOC: 0x0 R_HEX_TPREL_32_6_X foo 0x0
+# RELOC-NEXT: 0x4 R_HEX_TPREL_11_X foo 0x0
+# CHECK: { immext(#0xfffbffc0)
+# CHECK-NEXT: r2 = add(r2,##-0x40003); memw(r3+#0x0) = #0 }
+ {
+ r2 = add(r2,##foo at TPREL)
+ memw(r3+#0) = #0
+ }
+
+# CHECK: { jumpr r31 }
+ jumpr r31
+
+ .section .tbss,"awT", at nobits
+ .p2align 2
+ .space 0xd
+ .globl foo
+foo:
+ .space 0x40000
More information about the llvm-commits
mailing list