Skip to content

Commit 698b45a

Browse files
committed
[PowerPC][lld] Account for additional X-Forms -> D-Form/DS-Forms load/stores when relaxing initial-exec to local-exec
D153645 added additional X-Form load/stores that can be generated for TLS accesses. However, these added instructions have not been accounted for in lld. As a result, lld does not know how to handle them and cannot relax initial-exec to local-exec when the initial-exec sequence contains these additional load/stores. This patch aims to resolve llvm#64424. Differential Revision: https://reviews.llvm.org/D158197
1 parent 07102a1 commit 698b45a

File tree

6 files changed

+287
-43
lines changed

6 files changed

+287
-43
lines changed

lld/ELF/Arch/PPC.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -471,10 +471,14 @@ void PPC::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
471471
if (insn >> 26 != 31)
472472
error("unrecognized instruction for IE to LE R_PPC_TLS");
473473
// addi rT, rT, x@tls --> addi rT, rT, x@tprel@l
474-
uint32_t dFormOp = getPPCDFormOp((read32(loc) & 0x000007fe) >> 1);
475-
if (dFormOp == 0)
476-
error("unrecognized instruction for IE to LE R_PPC_TLS");
477-
write32(loc, (dFormOp << 26) | (insn & 0x03ff0000) | lo(val));
474+
unsigned secondaryOp = (read32(loc) & 0x000007fe) >> 1;
475+
uint32_t dFormOp = getPPCDFormOp(secondaryOp);
476+
if (dFormOp == 0) { // Expecting a DS-Form instruction.
477+
dFormOp = getPPCDSFormOp(secondaryOp);
478+
if (dFormOp == 0)
479+
error("unrecognized instruction for IE to LE R_PPC_TLS");
480+
}
481+
write32(loc, (dFormOp | (insn & 0x03ff0000) | lo(val)));
478482
break;
479483
}
480484
default:

lld/ELF/Arch/PPC64.cpp

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ enum XFormOpcd {
3737
STHX = 407,
3838
STWX = 151,
3939
STDX = 149,
40+
LHAX = 343,
41+
LWAX = 341,
42+
LFSX = 535,
43+
LFDX = 599,
44+
STFSX = 663,
45+
STFDX = 727,
4046
ADD = 266,
4147
};
4248

@@ -49,7 +55,6 @@ enum DFormOpcd {
4955
LWZ = 32,
5056
LWZU = 33,
5157
LFSU = 49,
52-
LD = 58,
5358
LFDU = 51,
5459
STB = 38,
5560
STBU = 39,
@@ -59,10 +64,20 @@ enum DFormOpcd {
5964
STWU = 37,
6065
STFSU = 53,
6166
STFDU = 55,
62-
STD = 62,
67+
LHA = 42,
68+
LFS = 48,
69+
LFD = 50,
70+
STFS = 52,
71+
STFD = 54,
6372
ADDI = 14
6473
};
6574

75+
enum DSFormOpcd {
76+
LD = 58,
77+
LWA = 58,
78+
STD = 62
79+
};
80+
6681
constexpr uint32_t NOP = 0x60000000;
6782

6883
enum class PPCLegacyInsn : uint32_t {
@@ -825,26 +840,48 @@ void PPC64::relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
825840
}
826841
}
827842

843+
// Map X-Form instructions to their DS-Form counterparts, if applicable.
844+
// The full encoding is returned here to distinguish between the different
845+
// DS-Form instructions.
846+
unsigned elf::getPPCDSFormOp(unsigned secondaryOp) {
847+
switch (secondaryOp) {
848+
case LWAX:
849+
return (LWA << 26) | 0x2;
850+
case LDX:
851+
return LD << 26;
852+
case STDX:
853+
return STD << 26;
854+
default:
855+
return 0;
856+
}
857+
}
858+
828859
unsigned elf::getPPCDFormOp(unsigned secondaryOp) {
829860
switch (secondaryOp) {
830861
case LBZX:
831-
return LBZ;
862+
return LBZ << 26;
832863
case LHZX:
833-
return LHZ;
864+
return LHZ << 26;
834865
case LWZX:
835-
return LWZ;
836-
case LDX:
837-
return LD;
866+
return LWZ << 26;
838867
case STBX:
839-
return STB;
868+
return STB << 26;
840869
case STHX:
841-
return STH;
870+
return STH << 26;
842871
case STWX:
843-
return STW;
844-
case STDX:
845-
return STD;
872+
return STW << 26;
873+
case LHAX:
874+
return LHA << 26;
875+
case LFSX:
876+
return LFS << 26;
877+
case LFDX:
878+
return LFD << 26;
879+
case STFSX:
880+
return STFS << 26;
881+
case STFDX:
882+
return STFD << 26;
846883
case ADD:
847-
return ADDI;
884+
return ADDI << 26;
848885
default:
849886
return 0;
850887
}
@@ -898,10 +935,16 @@ void PPC64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
898935
error("unrecognized instruction for IE to LE R_PPC64_TLS");
899936
uint32_t secondaryOp = (read32(loc) & 0x000007FE) >> 1; // bits 21-30
900937
uint32_t dFormOp = getPPCDFormOp(secondaryOp);
901-
if (dFormOp == 0)
902-
error("unrecognized instruction for IE to LE R_PPC64_TLS");
903-
write32(loc, ((dFormOp << 26) | (read32(loc) & 0x03FFFFFF)));
904-
relocateNoSym(loc + offset, R_PPC64_TPREL16_LO, val);
938+
uint32_t finalReloc;
939+
if (dFormOp == 0) { // Expecting a DS-Form instruction.
940+
dFormOp = getPPCDSFormOp(secondaryOp);
941+
if (dFormOp == 0)
942+
error("unrecognized instruction for IE to LE R_PPC64_TLS");
943+
finalReloc = R_PPC64_TPREL16_LO_DS;
944+
} else
945+
finalReloc = R_PPC64_TPREL16_LO;
946+
write32(loc, dFormOp | (read32(loc) & 0x03ff0000));
947+
relocateNoSym(loc + offset, finalReloc, val);
905948
} else if (locAsInt % 4 == 1) {
906949
// If the offset is not 4 byte aligned then we have a PCRel type reloc.
907950
// This version of the relocation is offset by one byte from the
@@ -926,9 +969,12 @@ void PPC64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
926969
}
927970
} else {
928971
uint32_t dFormOp = getPPCDFormOp(secondaryOp);
929-
if (dFormOp == 0)
930-
errorOrWarn("unrecognized instruction for IE to LE R_PPC64_TLS");
931-
write32(loc - 1, ((dFormOp << 26) | (tlsInstr & 0x03FF0000)));
972+
if (dFormOp == 0) { // Expecting a DS-Form instruction.
973+
dFormOp = getPPCDSFormOp(secondaryOp);
974+
if (dFormOp == 0)
975+
errorOrWarn("unrecognized instruction for IE to LE R_PPC64_TLS");
976+
}
977+
write32(loc - 1, (dFormOp | (tlsInstr & 0x03ff0000)));
932978
}
933979
} else {
934980
errorOrWarn("R_PPC64_TLS must be either 4 byte aligned or one byte "

lld/ELF/Target.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ void processArmCmseSymbols();
208208
void writePPC32GlinkSection(uint8_t *buf, size_t numEntries);
209209

210210
unsigned getPPCDFormOp(unsigned secondaryOp);
211+
unsigned getPPCDSFormOp(unsigned secondaryOp);
211212

212213
// In the PowerPC64 Elf V2 abi a function can have 2 entry points. The first
213214
// is a global entry point (GEP) which typically is used to initialize the TOC

lld/test/ELF/ppc32-tls-ie.s

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
# IE-REL: FLAGS STATIC_TLS
1313
## A non-preemptable symbol (b) has 0 st_shndx.
1414
# IE-REL: .rela.dyn {
15-
# IE-REL-NEXT: 0x20238 R_PPC_TPREL32 - 0xC
16-
# IE-REL-NEXT: 0x20234 R_PPC_TPREL32 a 0x0
15+
# IE-REL-NEXT: 0x20258 R_PPC_TPREL32 - 0xC
16+
# IE-REL-NEXT: 0x20254 R_PPC_TPREL32 a 0x0
1717
# IE-REL-NEXT: }
1818

1919
## &.got[3] - _GLOBAL_OFFSET_TABLE_ = 12
@@ -44,19 +44,39 @@ lbzx 10, 8, c@tls
4444
# IE-NEXT: stbx 14, 4, 2
4545
# IE-NEXT: sthx 15, 5, 2
4646
# IE-NEXT: stwx 16, 6, 2
47+
# IE-NEXT: lhax 17, 7, 2
48+
# IE-NEXT: lwax 18, 8, 2
49+
# IE-NEXT: lfsx 19, 9, 2
50+
# IE-NEXT: lfdx 20, 10, 2
51+
# IE-NEXT: stfsx 21, 11, 2
52+
# IE-NEXT: stfdx 22, 12, 2
4753

4854
## In LE, these X-Form instructions are changed to their corresponding D-Form.
4955
# LE-NEXT: lhz 12, -28660(2)
5056
# LE-NEXT: lwz 13, -28660(3)
5157
# LE-NEXT: stb 14, -28660(4)
5258
# LE-NEXT: sth 15, -28660(5)
5359
# LE-NEXT: stw 16, -28660(6)
60+
# LE-NEXT: lha 17, -28660(7)
61+
# LE-NEXT: lwa 18, -28660(8)
62+
# LE-NEXT: lfs 19, -28660(9)
63+
# LE-NEXT: lfd 20, -28660(10)
64+
# LE-NEXT: stfs 21, -28660(11)
65+
# LE-NEXT: stfd 22, -28660(12)
5466

5567
lhzx 12, 2, s@tls
5668
lwzx 13, 3, i@tls
5769
stbx 14, 4, c@tls
5870
sthx 15, 5, s@tls
5971
stwx 16, 6, i@tls
72+
lhax 17, 7, s@tls
73+
lwax 18, 8, i@tls
74+
lfsx 19, 9, f@tls
75+
lfdx 20, 10, d@tls
76+
stfsx 21, 11, f@tls
77+
stfdx 22, 12, d@tls
78+
ldx 23, 13, l@tls
79+
stdx 24, 14, l@tls
6080

6181
.section .tbss
6282
.globl a
@@ -66,3 +86,6 @@ a:
6686
c:
6787
s:
6888
i:
89+
f:
90+
d:
91+
l:

lld/test/ELF/ppc64-tls-ie.s

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@
2424

2525
# IE-REL: FLAGS STATIC_TLS
2626
# IE-REL: .rela.dyn {
27-
# IE-REL-NEXT: 0x204C8 R_PPC64_TPREL64 c 0x0
28-
# IE-REL-NEXT: 0x204D0 R_PPC64_TPREL64 s 0x0
29-
# IE-REL-NEXT: 0x204D8 R_PPC64_TPREL64 i 0x0
30-
# IE-REL-NEXT: 0x204E0 R_PPC64_TPREL64 l 0x0
27+
# IE-REL-NEXT: 0x205A8 R_PPC64_TPREL64 c 0x0
28+
# IE-REL-NEXT: 0x205B0 R_PPC64_TPREL64 s 0x0
29+
# IE-REL-NEXT: 0x205B8 R_PPC64_TPREL64 i 0x0
30+
# IE-REL-NEXT: 0x205C0 R_PPC64_TPREL64 l 0x0
31+
# IE-REL-NEXT: 0x205C8 R_PPC64_TPREL64 f 0x0
32+
# IE-REL-NEXT: 0x205D0 R_PPC64_TPREL64 d 0x0
3133
# IE-REL-NEXT: }
3234

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

157+
# LE-LABEL: <test_lhax>:
158+
# LE-NEXT: nop
159+
# LE-NEXT: addis 3, 13, 0
160+
# LE-NEXT: lha 3, -28670(3)
161+
test_lhax:
162+
addis 3, 2, s@got@tprel@ha
163+
ld 3, s@got@tprel@l(3)
164+
lhax 3, 3, s@tls
165+
166+
# LE-LABEL: <test_lwax>:
167+
# LE-NEXT: nop
168+
# LE-NEXT: addis 3, 13, 0
169+
# LE-NEXT: lwa 3, -28668(3)
170+
test_lwax:
171+
addis 3, 2, i@got@tprel@ha
172+
ld 3, i@got@tprel@l(3)
173+
lwax 3, 3, i@tls
174+
175+
# LE-LABEL: <test_lfsx>:
176+
# LE-NEXT: nop
177+
# LE-NEXT: addis 3, 13, 0
178+
# LE-NEXT: lfs 3, -28656(3)
179+
test_lfsx:
180+
addis 3, 2, f@got@tprel@ha
181+
ld 3, f@got@tprel@l(3)
182+
lfsx 3, 3, f@tls
183+
184+
# LE-LABEL: <test_lfdx>:
185+
# LE-NEXT: nop
186+
# LE-NEXT: addis 3, 13, 0
187+
# LE-NEXT: lfd 3, -28648(3)
188+
test_lfdx:
189+
addis 3, 2, d@got@tprel@ha
190+
ld 3, d@got@tprel@l(3)
191+
lfdx 3, 3, d@tls
192+
193+
# LE-LABEL: <test_stfsx>:
194+
# LE-NEXT: nop
195+
# LE-NEXT: addis 4, 13, 0
196+
# LE-NEXT: stfs 3, -28656(4)
197+
test_stfsx:
198+
addis 4, 2, f@got@tprel@ha
199+
ld 4, f@got@tprel@l(4)
200+
stfsx 3, 4, f@tls
201+
202+
# LE-LABEL: <test_stfdx>:
203+
# LE-NEXT: nop
204+
# LE-NEXT: addis 4, 13, 0
205+
# LE-NEXT: stfd 3, -28648(4)
206+
test_stfdx:
207+
addis 4, 2, d@got@tprel@ha
208+
ld 4, d@got@tprel@l(4)
209+
stfdx 3, 4, d@tls
210+
155211
# NOREL: There are no relocations in this file.
156212

157213
.section .tdata,"awT",@progbits
158-
.globl c, s, i, l
214+
.globl c, s, i, l, f, d
159215
c:
160216
.byte 97
161217

@@ -170,3 +226,9 @@ i:
170226
.p2align 3
171227
l:
172228
.quad 55
229+
f:
230+
.long 55
231+
232+
.p2align 3
233+
d:
234+
.quad 55

0 commit comments

Comments
 (0)