[llvm-branch-commits] [lld] release/22.x: [lld][Hexagon] Fix findMaskR8 missing duplex support (#183936) (PR #184646)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Mar 4 09:19:46 PST 2026
https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/184646
Backport 9105d9c24949d8cf9b740cb874027351e7230e70
Requested by: @androm3da
>From 4b211f334d1606a76ca27a60261cae3595fea7f9 Mon Sep 17 00:00:00 2001
From: Brian Cain <brian.cain at oss.qualcomm.com>
Date: Wed, 4 Mar 2026 11:11:09 -0600
Subject: [PATCH] [lld][Hexagon] Fix findMaskR8 missing duplex support
(#183936)
findMaskR8() lacked an isDuplex() check, unlike findMaskR6(),
findMaskR11(), and findMaskR16() which all handle duplex instructions.
When the assembler generates R_HEX_8_X on a duplex SA1_addi instruction
(e.g. `{ r0 = add(r0, ##target); memw(r1+#0) = r2 }`), the wrong mask
0x00001fe0 placed relocation bits at [12:5] instead of [25:20],
corrupting the low sub-instruction (e.g. memw became memb).
Add the isDuplex() check returning 0x03f00000, and add a comprehensive
test covering all duplex instruction x relocation type combinations
across findMaskR6, findMaskR8, findMaskR11, and findMaskR16.
(cherry picked from commit 9105d9c24949d8cf9b740cb874027351e7230e70)
---
lld/ELF/Arch/Hexagon.cpp | 2 ++
lld/test/ELF/hexagon-duplex-relocs.s | 40 ++++++++++++++++++++++++++++
2 files changed, 42 insertions(+)
create mode 100644 lld/test/ELF/hexagon-duplex-relocs.s
diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp
index d6495e12668d7..09dee664589b2 100644
--- a/lld/ELF/Arch/Hexagon.cpp
+++ b/lld/ELF/Arch/Hexagon.cpp
@@ -217,6 +217,8 @@ static uint32_t findMaskR6(Ctx &ctx, uint32_t insn) {
}
static uint32_t findMaskR8(uint32_t insn) {
+ if (isDuplex(insn))
+ return 0x03f00000;
if ((0xff000000 & insn) == 0xde000000)
return 0x00e020e8;
if ((0xff000000 & insn) == 0x3c000000)
diff --git a/lld/test/ELF/hexagon-duplex-relocs.s b/lld/test/ELF/hexagon-duplex-relocs.s
new file mode 100644
index 0000000000000..8d7705517cb34
--- /dev/null
+++ b/lld/test/ELF/hexagon-duplex-relocs.s
@@ -0,0 +1,40 @@
+# 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 --no-show-raw-insn --print-imm-hex %t | FileCheck %s
+
+## Test R_HEX_8_X relocation on duplex instructions (SA1_addi).
+## findMaskR8() must use the duplex mask 0x03f00000 when parse bits [15:14]
+## are zero. Pair a non-duplex form with a duplex form using the same symbol
+## and verify both resolve to the same address.
+##
+## Duplex paths for the other findMask functions are already covered:
+## findMaskR6: hexagon.s (R_HEX_6_X duplex)
+## findMaskR11: hexagon-tls-ie.s (R_HEX_TPREL_11_X duplex)
+## findMaskR16: hexagon-shared.s (R_HEX_GOT_16_X duplex)
+
+ .globl _start, target
+ .type _start, @function
+_start:
+
+# Non-duplex reference (R_HEX_16_X, via findMaskR16)
+# RELOC: R_HEX_32_6_X target 0x0
+# RELOC-NEXT: R_HEX_16_X target 0x0
+# CHECK: { immext(#
+# CHECK-NEXT: r0 = add(r0,##[[ADDR:0x[0-9a-f]+]]) }
+ r0 = add(r0, ##target)
+
+# Duplex form (R_HEX_8_X, via findMaskR8)
+# RELOC-NEXT: R_HEX_32_6_X target 0x0
+# RELOC-NEXT: R_HEX_8_X target 0x0
+# CHECK-NEXT: { immext(#
+# CHECK-NEXT: r0 = add(r0,##[[ADDR]]); memw(r1+#0x0) = r2 }
+ { r0 = add(r0, ##target)
+ memw(r1+#0) = r2 }
+
+ jumpr r31
+
+target:
+ nop
+ jumpr r31
More information about the llvm-branch-commits
mailing list