Skip to content

Commit 58e473e

Browse files
committed
[lld][Hexagon] Support predicated-add GOT_16_X mask lookup
When encountering an instruction like `if (p0) r0 = add(r0,##bar@GOT)`, lld would fail with: ``` ld.lld: error: unrecognized instruction for 16_X type: 0x7400C000 ``` This issue was encountered while building libreadline with clang 19.1.0. Fixes: #111876
1 parent 36c34ec commit 58e473e

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

lld/ELF/Arch/Hexagon.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,12 @@ static const InstructionMask r6[] = {
181181
{0xd7000000, 0x006020e0}, {0xd8000000, 0x006020e0},
182182
{0xdb000000, 0x006020e0}, {0xdf000000, 0x006020e0}};
183183

184+
static constexpr uint32_t InstParsePacketEnd = 0x0000c000;
184185
static bool isDuplex(uint32_t insn) {
185186
// Duplex forms have a fixed mask and parse bits 15:14 are always
186187
// zero. Non-duplex insns will always have at least one bit set in the
187188
// parse field.
188-
return (0xC000 & insn) == 0;
189+
return (InstParsePacketEnd & insn) == 0;
189190
}
190191

191192
static uint32_t findMaskR6(uint32_t insn) {
@@ -216,6 +217,12 @@ static uint32_t findMaskR11(uint32_t insn) {
216217
}
217218

218219
static uint32_t findMaskR16(uint32_t insn) {
220+
if (isDuplex(insn))
221+
return 0x03f00000;
222+
223+
// Clear the end-packet-parse bits:
224+
insn = insn & ~InstParsePacketEnd;
225+
219226
if ((0xff000000 & insn) == 0x48000000)
220227
return 0x061f20ff;
221228
if ((0xff000000 & insn) == 0x49000000)
@@ -225,8 +232,14 @@ static uint32_t findMaskR16(uint32_t insn) {
225232
if ((0xff000000 & insn) == 0xb0000000)
226233
return 0x0fe03fe0;
227234

228-
if (isDuplex(insn))
229-
return 0x03f00000;
235+
if ((0xff802000 & insn) == 0x74000000)
236+
return 0x00001fe0;
237+
if ((0xff802000 & insn) == 0x74002000)
238+
return 0x00001fe0;
239+
if ((0xff802000 & insn) == 0x74800000)
240+
return 0x00001fe0;
241+
if ((0xff802000 & insn) == 0x74802000)
242+
return 0x00001fe0;
230243

231244
for (InstructionMask i : r6)
232245
if ((0xff000000 & insn) == i.cmpMask)

lld/test/ELF/hexagon-shared.s

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ r0 = add(r1,##bar@GOT)
4242
{ r0 = add(r0,##bar@GOT)
4343
memw(r0) = r2 }
4444

45+
# R_HEX_GOT_16_X, pred add
46+
if (p0) r0 = add(r0,##bar@GOT)
47+
if (!p0) r0 = add(r0,##bar@GOT)
48+
{ p0 = cmp.gtu(r0, r1)
49+
if (p0.new) r0 = add(r0,##bar@GOT) }
50+
{ p0 = cmp.gtu(r0, r1)
51+
if (!p0.new) r0 = add(r0,##bar@GOT) }
4552

4653
# foo is local so no plt will be generated
4754
foo:
@@ -78,12 +85,16 @@ pvar:
7885
# PLT-NEXT: r28 = memw(r14+#0) }
7986
# PLT-NEXT: jumpr r28 }
8087

81-
# TEXT: 8c 00 01 00 0001008c
82-
# TEXT: { call 0x102d0 }
83-
# TEXT: if (p0) jump:nt 0x102d0
84-
# TEXT: r0 = #0 ; jump 0x102d0
88+
# TEXT: bc 00 01 00 000100bc
89+
# TEXT: { call 0x10300 }
90+
# TEXT: if (p0) jump:nt 0x10300
91+
# TEXT: r0 = #0 ; jump 0x10300
8592
# TEXT: r0 = add(r1,##-65548)
8693
# TEXT: r0 = add(r0,##-65548); memw(r0+#0) = r2 }
94+
# TEXT: if (p0) r0 = add(r0,##-65548)
95+
# TEXT: if (!p0) r0 = add(r0,##-65548)
96+
# TEXT: if (p0.new) r0 = add(r0,##-65548)
97+
# TEXT: if (!p0.new) r0 = add(r0,##-65548)
8798

8899
# GOT: .got:
89100
# GOT: 00 00 00 00 00000000 <unknown>

0 commit comments

Comments
 (0)