Skip to content

PR for llvm/llvm-project#64424 #675

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions lld/ELF/Arch/PPC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,10 +471,14 @@ void PPC::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
if (insn >> 26 != 31)
error("unrecognized instruction for IE to LE R_PPC_TLS");
// addi rT, rT, x@tls --> addi rT, rT, x@tprel@l
uint32_t dFormOp = getPPCDFormOp((read32(loc) & 0x000007fe) >> 1);
if (dFormOp == 0)
error("unrecognized instruction for IE to LE R_PPC_TLS");
write32(loc, (dFormOp << 26) | (insn & 0x03ff0000) | lo(val));
unsigned secondaryOp = (read32(loc) & 0x000007fe) >> 1;
uint32_t dFormOp = getPPCDFormOp(secondaryOp);
if (dFormOp == 0) { // Expecting a DS-Form instruction.
dFormOp = getPPCDSFormOp(secondaryOp);
if (dFormOp == 0)
error("unrecognized instruction for IE to LE R_PPC_TLS");
}
write32(loc, (dFormOp | (insn & 0x03ff0000) | lo(val)));
break;
}
default:
Expand Down
86 changes: 66 additions & 20 deletions lld/ELF/Arch/PPC64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ enum XFormOpcd {
STHX = 407,
STWX = 151,
STDX = 149,
LHAX = 343,
LWAX = 341,
LFSX = 535,
LFDX = 599,
STFSX = 663,
STFDX = 727,
ADD = 266,
};

Expand All @@ -49,7 +55,6 @@ enum DFormOpcd {
LWZ = 32,
LWZU = 33,
LFSU = 49,
LD = 58,
LFDU = 51,
STB = 38,
STBU = 39,
Expand All @@ -59,10 +64,20 @@ enum DFormOpcd {
STWU = 37,
STFSU = 53,
STFDU = 55,
STD = 62,
LHA = 42,
LFS = 48,
LFD = 50,
STFS = 52,
STFD = 54,
ADDI = 14
};

enum DSFormOpcd {
LD = 58,
LWA = 58,
STD = 62
};

constexpr uint32_t NOP = 0x60000000;

enum class PPCLegacyInsn : uint32_t {
Expand Down Expand Up @@ -825,26 +840,48 @@ void PPC64::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
}
}

// Map X-Form instructions to their DS-Form counterparts, if applicable.
// The full encoding is returned here to distinguish between the different
// DS-Form instructions.
unsigned elf::getPPCDSFormOp(unsigned secondaryOp) {
switch (secondaryOp) {
case LWAX:
return (LWA << 26) | 0x2;
case LDX:
return LD << 26;
case STDX:
return STD << 26;
default:
return 0;
}
}

unsigned elf::getPPCDFormOp(unsigned secondaryOp) {
switch (secondaryOp) {
case LBZX:
return LBZ;
return LBZ << 26;
case LHZX:
return LHZ;
return LHZ << 26;
case LWZX:
return LWZ;
case LDX:
return LD;
return LWZ << 26;
case STBX:
return STB;
return STB << 26;
case STHX:
return STH;
return STH << 26;
case STWX:
return STW;
case STDX:
return STD;
return STW << 26;
case LHAX:
return LHA << 26;
case LFSX:
return LFS << 26;
case LFDX:
return LFD << 26;
case STFSX:
return STFS << 26;
case STFDX:
return STFD << 26;
case ADD:
return ADDI;
return ADDI << 26;
default:
return 0;
}
Expand Down Expand Up @@ -898,10 +935,16 @@ void PPC64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
error("unrecognized instruction for IE to LE R_PPC64_TLS");
uint32_t secondaryOp = (read32(loc) & 0x000007FE) >> 1; // bits 21-30
uint32_t dFormOp = getPPCDFormOp(secondaryOp);
if (dFormOp == 0)
error("unrecognized instruction for IE to LE R_PPC64_TLS");
write32(loc, ((dFormOp << 26) | (read32(loc) & 0x03FFFFFF)));
relocateNoSym(loc + offset, R_PPC64_TPREL16_LO, val);
uint32_t finalReloc;
if (dFormOp == 0) { // Expecting a DS-Form instruction.
dFormOp = getPPCDSFormOp(secondaryOp);
if (dFormOp == 0)
error("unrecognized instruction for IE to LE R_PPC64_TLS");
finalReloc = R_PPC64_TPREL16_LO_DS;
} else
finalReloc = R_PPC64_TPREL16_LO;
write32(loc, dFormOp | (read32(loc) & 0x03ff0000));
relocateNoSym(loc + offset, finalReloc, val);
} else if (locAsInt % 4 == 1) {
// If the offset is not 4 byte aligned then we have a PCRel type reloc.
// This version of the relocation is offset by one byte from the
Expand All @@ -926,9 +969,12 @@ void PPC64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
}
} else {
uint32_t dFormOp = getPPCDFormOp(secondaryOp);
if (dFormOp == 0)
errorOrWarn("unrecognized instruction for IE to LE R_PPC64_TLS");
write32(loc - 1, ((dFormOp << 26) | (tlsInstr & 0x03FF0000)));
if (dFormOp == 0) { // Expecting a DS-Form instruction.
dFormOp = getPPCDSFormOp(secondaryOp);
if (dFormOp == 0)
errorOrWarn("unrecognized instruction for IE to LE R_PPC64_TLS");
}
write32(loc - 1, (dFormOp | (tlsInstr & 0x03ff0000)));
}
} else {
errorOrWarn("R_PPC64_TLS must be either 4 byte aligned or one byte "
Expand Down
1 change: 1 addition & 0 deletions lld/ELF/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ void processArmCmseSymbols();
void writePPC32GlinkSection(uint8_t *buf, size_t numEntries);

unsigned getPPCDFormOp(unsigned secondaryOp);
unsigned getPPCDSFormOp(unsigned secondaryOp);

// In the PowerPC64 Elf V2 abi a function can have 2 entry points. The first
// is a global entry point (GEP) which typically is used to initialize the TOC
Expand Down
27 changes: 25 additions & 2 deletions lld/test/ELF/ppc32-tls-ie.s
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
# IE-REL: FLAGS STATIC_TLS
## A non-preemptable symbol (b) has 0 st_shndx.
# IE-REL: .rela.dyn {
# IE-REL-NEXT: 0x20238 R_PPC_TPREL32 - 0xC
# IE-REL-NEXT: 0x20234 R_PPC_TPREL32 a 0x0
# IE-REL-NEXT: 0x20258 R_PPC_TPREL32 - 0xC
# IE-REL-NEXT: 0x20254 R_PPC_TPREL32 a 0x0
# IE-REL-NEXT: }

## &.got[3] - _GLOBAL_OFFSET_TABLE_ = 12
Expand Down Expand Up @@ -44,19 +44,39 @@ lbzx 10, 8, c@tls
# IE-NEXT: stbx 14, 4, 2
# IE-NEXT: sthx 15, 5, 2
# IE-NEXT: stwx 16, 6, 2
# IE-NEXT: lhax 17, 7, 2
# IE-NEXT: lwax 18, 8, 2
# IE-NEXT: lfsx 19, 9, 2
# IE-NEXT: lfdx 20, 10, 2
# IE-NEXT: stfsx 21, 11, 2
# IE-NEXT: stfdx 22, 12, 2

## In LE, these X-Form instructions are changed to their corresponding D-Form.
# LE-NEXT: lhz 12, -28660(2)
# LE-NEXT: lwz 13, -28660(3)
# LE-NEXT: stb 14, -28660(4)
# LE-NEXT: sth 15, -28660(5)
# LE-NEXT: stw 16, -28660(6)
# LE-NEXT: lha 17, -28660(7)
# LE-NEXT: lwa 18, -28660(8)
# LE-NEXT: lfs 19, -28660(9)
# LE-NEXT: lfd 20, -28660(10)
# LE-NEXT: stfs 21, -28660(11)
# LE-NEXT: stfd 22, -28660(12)

lhzx 12, 2, s@tls
lwzx 13, 3, i@tls
stbx 14, 4, c@tls
sthx 15, 5, s@tls
stwx 16, 6, i@tls
lhax 17, 7, s@tls
lwax 18, 8, i@tls
lfsx 19, 9, f@tls
lfdx 20, 10, d@tls
stfsx 21, 11, f@tls
stfdx 22, 12, d@tls
ldx 23, 13, l@tls
stdx 24, 14, l@tls

.section .tbss
.globl a
Expand All @@ -66,3 +86,6 @@ a:
c:
s:
i:
f:
d:
l:
72 changes: 67 additions & 5 deletions lld/test/ELF/ppc64-tls-ie.s
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@

# IE-REL: FLAGS STATIC_TLS
# IE-REL: .rela.dyn {
# IE-REL-NEXT: 0x204C8 R_PPC64_TPREL64 c 0x0
# IE-REL-NEXT: 0x204D0 R_PPC64_TPREL64 s 0x0
# IE-REL-NEXT: 0x204D8 R_PPC64_TPREL64 i 0x0
# IE-REL-NEXT: 0x204E0 R_PPC64_TPREL64 l 0x0
# IE-REL-NEXT: 0x205A8 R_PPC64_TPREL64 c 0x0
# IE-REL-NEXT: 0x205B0 R_PPC64_TPREL64 s 0x0
# IE-REL-NEXT: 0x205B8 R_PPC64_TPREL64 i 0x0
# IE-REL-NEXT: 0x205C0 R_PPC64_TPREL64 l 0x0
# IE-REL-NEXT: 0x205C8 R_PPC64_TPREL64 f 0x0
# IE-REL-NEXT: 0x205D0 R_PPC64_TPREL64 d 0x0
# IE-REL-NEXT: }

# INPUT-REL: R_PPC64_GOT_TPREL16_HA c 0x0
Expand Down Expand Up @@ -152,10 +154,64 @@ test_ds:
ld 4, l@got@tprel(2)
stdx 3, 4, l@tls

# LE-LABEL: <test_lhax>:
# LE-NEXT: nop
# LE-NEXT: addis 3, 13, 0
# LE-NEXT: lha 3, -28670(3)
test_lhax:
addis 3, 2, s@got@tprel@ha
ld 3, s@got@tprel@l(3)
lhax 3, 3, s@tls

# LE-LABEL: <test_lwax>:
# LE-NEXT: nop
# LE-NEXT: addis 3, 13, 0
# LE-NEXT: lwa 3, -28668(3)
test_lwax:
addis 3, 2, i@got@tprel@ha
ld 3, i@got@tprel@l(3)
lwax 3, 3, i@tls

# LE-LABEL: <test_lfsx>:
# LE-NEXT: nop
# LE-NEXT: addis 3, 13, 0
# LE-NEXT: lfs 3, -28656(3)
test_lfsx:
addis 3, 2, f@got@tprel@ha
ld 3, f@got@tprel@l(3)
lfsx 3, 3, f@tls

# LE-LABEL: <test_lfdx>:
# LE-NEXT: nop
# LE-NEXT: addis 3, 13, 0
# LE-NEXT: lfd 3, -28648(3)
test_lfdx:
addis 3, 2, d@got@tprel@ha
ld 3, d@got@tprel@l(3)
lfdx 3, 3, d@tls

# LE-LABEL: <test_stfsx>:
# LE-NEXT: nop
# LE-NEXT: addis 4, 13, 0
# LE-NEXT: stfs 3, -28656(4)
test_stfsx:
addis 4, 2, f@got@tprel@ha
ld 4, f@got@tprel@l(4)
stfsx 3, 4, f@tls

# LE-LABEL: <test_stfdx>:
# LE-NEXT: nop
# LE-NEXT: addis 4, 13, 0
# LE-NEXT: stfd 3, -28648(4)
test_stfdx:
addis 4, 2, d@got@tprel@ha
ld 4, d@got@tprel@l(4)
stfdx 3, 4, d@tls

# NOREL: There are no relocations in this file.

.section .tdata,"awT",@progbits
.globl c, s, i, l
.globl c, s, i, l, f, d
c:
.byte 97

Expand All @@ -170,3 +226,9 @@ i:
.p2align 3
l:
.quad 55
f:
.long 55

.p2align 3
d:
.quad 55
Loading