Skip to content

Commit

Permalink
[lld][Hexagon] Support predicated-add GOT_16_X mask lookup (#111896)
Browse files Browse the repository at this point in the history
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
(cherry picked from commit 77aa825)
  • Loading branch information
androm3da authored and tru committed Oct 15, 2024
1 parent 35bd5ff commit f8cf339
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 7 deletions.
20 changes: 17 additions & 3 deletions lld/ELF/Arch/Hexagon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,13 @@ static const InstructionMask r6[] = {
{0xd7000000, 0x006020e0}, {0xd8000000, 0x006020e0},
{0xdb000000, 0x006020e0}, {0xdf000000, 0x006020e0}};

constexpr uint32_t instParsePacketEnd = 0x0000c000;

static bool isDuplex(uint32_t insn) {
// Duplex forms have a fixed mask and parse bits 15:14 are always
// zero. Non-duplex insns will always have at least one bit set in the
// parse field.
return (0xC000 & insn) == 0;
return (instParsePacketEnd & insn) == 0;
}

static uint32_t findMaskR6(uint32_t insn) {
Expand Down Expand Up @@ -216,6 +218,12 @@ static uint32_t findMaskR11(uint32_t insn) {
}

static uint32_t findMaskR16(uint32_t insn) {
if (isDuplex(insn))
return 0x03f00000;

// Clear the end-packet-parse bits:
insn = insn & ~instParsePacketEnd;

if ((0xff000000 & insn) == 0x48000000)
return 0x061f20ff;
if ((0xff000000 & insn) == 0x49000000)
Expand All @@ -225,8 +233,14 @@ static uint32_t findMaskR16(uint32_t insn) {
if ((0xff000000 & insn) == 0xb0000000)
return 0x0fe03fe0;

if (isDuplex(insn))
return 0x03f00000;
if ((0xff802000 & insn) == 0x74000000)
return 0x00001fe0;
if ((0xff802000 & insn) == 0x74002000)
return 0x00001fe0;
if ((0xff802000 & insn) == 0x74800000)
return 0x00001fe0;
if ((0xff802000 & insn) == 0x74802000)
return 0x00001fe0;

for (InstructionMask i : r6)
if ((0xff000000 & insn) == i.cmpMask)
Expand Down
19 changes: 15 additions & 4 deletions lld/test/ELF/hexagon-shared.s
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ r0 = add(r1,##bar@GOT)
{ r0 = add(r0,##bar@GOT)
memw(r0) = r2 }

# R_HEX_GOT_16_X, pred add
if (p0) r0 = add(r0,##bar@GOT)
if (!p0) r0 = add(r0,##bar@GOT)
{ p0 = cmp.gtu(r0, r1)
if (p0.new) r0 = add(r0,##bar@GOT) }
{ p0 = cmp.gtu(r0, r1)
if (!p0.new) r0 = add(r0,##bar@GOT) }

# foo is local so no plt will be generated
foo:
Expand Down Expand Up @@ -78,12 +85,16 @@ pvar:
# PLT-NEXT: r28 = memw(r14+#0) }
# PLT-NEXT: jumpr r28 }

# TEXT: 8c 00 01 00 0001008c
# TEXT: { call 0x102d0 }
# TEXT: if (p0) jump:nt 0x102d0
# TEXT: r0 = #0 ; jump 0x102d0
# TEXT: bc 00 01 00 000100bc
# TEXT: { call 0x10300 }
# TEXT: if (p0) jump:nt 0x10300
# TEXT: r0 = #0 ; jump 0x10300
# TEXT: r0 = add(r1,##-65548)
# TEXT: r0 = add(r0,##-65548); memw(r0+#0) = r2 }
# TEXT: if (p0) r0 = add(r0,##-65548)
# TEXT: if (!p0) r0 = add(r0,##-65548)
# TEXT: if (p0.new) r0 = add(r0,##-65548)
# TEXT: if (!p0.new) r0 = add(r0,##-65548)

# GOT: .got:
# GOT: 00 00 00 00 00000000 <unknown>
Expand Down

0 comments on commit f8cf339

Please sign in to comment.