Skip to content

Commit 9d29d9b

Browse files
committed
Relax TLSDESC code sequence.
Original code sequence: * pcalau12i $a0, %desc_pc_hi20(sym_desc) * addi.d $a0, $a0, %desc_pc_lo12(sym_desc) * ld.d $ra, $a0, %desc_ld(sym_desc) * jirl $ra, $ra, %desc_call(sym_desc) Cannot convert to LE/IE, but relax: * pcaddi $a0, %desc_pcrel_20(sym_desc) * ld.d $ra, $a0, %desc_ld(sym_desc) * jirl $ra, $ra, %desc_call(sym_desc) TODO: The conversion of TLSDESC GD/LD to LE/IE will implement in a future patch.
1 parent 1fe702f commit 9d29d9b

File tree

2 files changed

+297
-2
lines changed

2 files changed

+297
-2
lines changed

lld/ELF/Arch/LoongArch.cpp

+17-2
Original file line numberDiff line numberDiff line change
@@ -766,9 +766,12 @@ static bool isPairRelaxable(ArrayRef<Relocation> relocs, size_t i) {
766766
// Relax code sequence.
767767
// From:
768768
// pcalau12i $a0, %pc_hi20(sym) | %ld_pc_hi20(sym) | %gd_pc_hi20(sym)
769+
// | %desc_pc_hi20(sym)
769770
// addi.w/d $a0, $a0, %pc_lo12(sym) | %got_pc_lo12(sym) | %got_pc_lo12(sym)
771+
// | %desc_pc_lo12(sym)
770772
// To:
771-
// pcaddi $a0, %pc_lo12(sym) | %got_pc_lo12(sym) | %got_pc_lo12(sym)
773+
// pcaddi $a0, %pc_lo12(sym) | %got_pc_lo12(sym) | %got_pc_lo12(sym)
774+
// | %desc_pcrel_20(sym)
772775
//
773776
// From:
774777
// pcalau12i $a0, %got_pc_hi20(sym_got)
@@ -786,7 +789,9 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
786789
(rHi20.type == R_LARCH_TLS_GD_PC_HI20 &&
787790
rLo12.type == R_LARCH_GOT_PC_LO12) ||
788791
(rHi20.type == R_LARCH_TLS_LD_PC_HI20 &&
789-
rLo12.type == R_LARCH_GOT_PC_LO12)))
792+
rLo12.type == R_LARCH_GOT_PC_LO12) ||
793+
(rHi20.type == R_LARCH_TLS_DESC_PC_HI20 &&
794+
rLo12.type == R_LARCH_TLS_DESC_PC_LO12)))
790795
return;
791796

792797
// GOT references to absolute symbols can't be relaxed to use pcaddi in
@@ -808,6 +813,8 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
808813
dest = rHi20.sym->getVA(ctx);
809814
else if (rHi20.expr == RE_LOONGARCH_TLSGD_PAGE_PC)
810815
dest = ctx.in.got->getGlobalDynAddr(*rHi20.sym);
816+
else if (rHi20.expr == RE_LOONGARCH_TLSDESC_PAGE_PC)
817+
dest = ctx.in.got->getTlsDescAddr(*rHi20.sym);
811818
else {
812819
Err(ctx) << getErrorLoc(ctx, (const uint8_t *)loc) << "unknown expr ("
813820
<< rHi20.expr << ") against symbol " << rHi20.sym
@@ -841,6 +848,8 @@ static void relaxPCHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
841848
sec.relaxAux->relocTypes[i + 2] = R_LARCH_TLS_GD_PCREL20_S2;
842849
else if (rHi20.type == R_LARCH_TLS_LD_PC_HI20)
843850
sec.relaxAux->relocTypes[i + 2] = R_LARCH_TLS_LD_PCREL20_S2;
851+
else if (rHi20.type == R_LARCH_TLS_DESC_PC_HI20)
852+
sec.relaxAux->relocTypes[i + 2] = R_LARCH_TLS_DESC_PCREL20_S2;
844853
else
845854
sec.relaxAux->relocTypes[i + 2] = R_LARCH_PCREL20_S2;
846855
sec.relaxAux->writes.push_back(insn(PCADDI, getD5(nextInsn), 0, 0));
@@ -947,6 +956,7 @@ static bool relax(Ctx &ctx, InputSection &sec) {
947956
case R_LARCH_GOT_PC_HI20:
948957
case R_LARCH_TLS_GD_PC_HI20:
949958
case R_LARCH_TLS_LD_PC_HI20:
959+
case R_LARCH_TLS_DESC_PC_HI20:
950960
// The overflow check for i+2 will be carried out in isPairRelaxable.
951961
if (isPairRelaxable(relocs, i))
952962
relaxPCHi20Lo12(ctx, sec, i, loc, r, relocs[i + 2], remove);
@@ -1081,6 +1091,11 @@ void LoongArch::finalizeRelax(int passes) const {
10811091
write32le(p, aux.writes[writesIdx++]);
10821092
r.expr = R_TLSGD_PC;
10831093
break;
1094+
case R_LARCH_TLS_DESC_PCREL20_S2:
1095+
skip = 4;
1096+
write32le(p, aux.writes[writesIdx++]);
1097+
r.expr = R_TLSDESC_PC;
1098+
break;
10841099
default:
10851100
llvm_unreachable("unsupported type");
10861101
}
+280
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
# REQUIRES: loongarch
2+
# RUN: rm -rf %t && split-file %s %t && cd %t
3+
# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax a.s -o a.64.o
4+
# RUN: llvm-mc -filetype=obj -triple=loongarch64 -mattr=+relax c.s -o c.64.o
5+
# RUN: ld.lld --relax -shared -soname=c.64.so c.64.o -o c.64.so
6+
7+
## Test the TLSDESC relaxation.
8+
# RUN: ld.lld --relax -shared -z now a.64.o c.64.o -o a.64.so
9+
# RUN: llvm-readobj -r -x .got a.64.so | FileCheck --check-prefix=GD64-RELA %s
10+
# RUN: llvm-objdump --no-show-raw-insn -dr -h a.64.so | FileCheck %s --check-prefix=GD64
11+
12+
## FIXME: The transition frome TLSDESC to IE/LE has not yet been implemented.
13+
## Keep the dynamic relocations and hand them over to dynamic linker.
14+
15+
# RUN: ld.lld --relax -e 0 -z now a.64.o c.64.o -o a.64.le
16+
# RUN: llvm-readobj -r -x .got a.64.le | FileCheck --check-prefix=LE64-RELA %s
17+
# RUN: llvm-objdump --no-show-raw-insn -d -h a.64.le | FileCheck %s --check-prefix=LE64
18+
19+
# RUN: ld.lld --no-relax -e 0 -z now a.64.o c.64.o -o a.64.le.norelax
20+
# RUN: llvm-objdump --no-show-raw-insn -d -h a.64.le.norelax | FileCheck %s --check-prefix=LE64-NORELAX
21+
22+
# RUN: ld.lld --relax -e 0 -z now a.64.o c.64.so -o a.64.ie
23+
# RUN: llvm-readobj -r -x .got a.64.ie | FileCheck --check-prefix=IE64-RELA %s
24+
# RUN: llvm-objdump --no-show-raw-insn -d -h a.64.ie | FileCheck %s --check-prefix=IE64
25+
26+
# RUN: ld.lld --no-relax -e 0 -z now a.64.o c.64.so -o a.64.ie.norelax
27+
# RUN: llvm-objdump --no-show-raw-insn -d -h a.64.ie.norelax | FileCheck %s --check-prefix=IE64-NORELAX
28+
29+
# GD64-RELA: .rela.dyn {
30+
# GD64-RELA-NEXT: 0x20460 R_LARCH_TLS_DESC64 - 0x7FF
31+
# GD64-RELA-NEXT: 0x20430 R_LARCH_TLS_DESC64 a 0x0
32+
# GD64-RELA-NEXT: 0x20440 R_LARCH_TLS_DESC64 c 0x0
33+
# GD64-RELA-NEXT: 0x20450 R_LARCH_TLS_DESC64 d 0x0
34+
# GD64-RELA-NEXT: }
35+
# GD64-RELA: Hex dump of section '.got':
36+
# GD64-RELA-NEXT: 0x00020430 00000000 00000000 00000000 00000000 .
37+
# GD64-RELA-NEXT: 0x00020440 00000000 00000000 00000000 00000000 .
38+
# GD64-RELA-NEXT: 0x00020450 00000000 00000000 00000000 00000000 .
39+
# GD64-RELA-NEXT: 0x00020460 00000000 00000000 00000000 00000000 .
40+
41+
# GD64: .got 00000040 0000000000020430
42+
43+
## &.got[a]-. = 0x20430 - 0x10318 = 16454<<2
44+
# GD64: 10318: pcaddi $a0, 16454
45+
# GD64-NEXT: ld.d $ra, $a0, 0
46+
# GD64-NEXT: jirl $ra, $ra, 0
47+
# GD64-NEXT: add.d $a1, $a0, $tp
48+
49+
## &.got[b]-. = 0x20430+48 - 0x10328: 0x10 pages, page offset 0x460
50+
## R_LARCH_RELAX does not appear in pairs. No relaxation.
51+
# GD64: 10328: pcalau12i $a0, 16
52+
# GD64-NEXT: addi.d $a0, $a0, 1120
53+
# GD64-NEXT: ld.d $ra, $a0, 0
54+
# GD64-NEXT: jirl $ra, $ra, 0
55+
# GD64-NEXT: add.d $a2, $a0, $tp
56+
57+
## &.got[c]-. = 0x20430+16 - 0x1033c: 0x10 pages, page offset 0x440
58+
## Without R_LARCH_RELAX relocation. No relaxation.
59+
# GD64: 1033c: pcalau12i $a0, 16
60+
# GD64-NEXT: addi.d $t0, $zero, 0
61+
# GD64-NEXT: addi.d $a0, $a0, 1088
62+
# GD64-NEXT: addi.d $t0, $t0, 1
63+
# GD64-NEXT: ld.d $ra, $a0, 0
64+
# GD64-NEXT: addi.d $t0, $t0, 1
65+
# GD64-NEXT: jirl $ra, $ra, 0
66+
# GD64-NEXT: add.d $a3, $a0, $tp
67+
68+
## &.got[d]-. = 0x20430+32 - 0x1035c = 16445<<2
69+
# GD64: 1035c: pcaddi $a0, 16445
70+
# GD64-NEXT: ld.d $ra, $a0, 0
71+
# GD64-NEXT: jirl $ra, $ra, 0
72+
# GD64-NEXT: add.d $a4, $a0, $tp
73+
74+
# LE64-RELA: .rela.dyn {
75+
# LE64-RELA-NEXT: 0x30280 R_LARCH_TLS_DESC64 - 0x8
76+
# LE64-RELA-NEXT: 0x30290 R_LARCH_TLS_DESC64 - 0x800
77+
# LE64-RELA-NEXT: 0x302A0 R_LARCH_TLS_DESC64 - 0x1000
78+
# LE64-RELA-NEXT: 0x302B0 R_LARCH_TLS_DESC64 - 0x7FF
79+
# LE64-RELA-NEXT: }
80+
# LE64-RELA: Hex dump of section '.got':
81+
# LE64-RELA-NEXT: 0x00030280 00000000 00000000 00000000 00000000 .
82+
# LE64-RELA-NEXT: 0x00030290 00000000 00000000 00000000 00000000 .
83+
# LE64-RELA-NEXT: 0x000302a0 00000000 00000000 00000000 00000000 .
84+
# LE64-RELA-NEXT: 0x000302b0 00000000 00000000 00000000 00000000 .
85+
86+
# LE64: .got 00000040 0000000000030280
87+
88+
## &.got[a]-. = 0x30280 - 0x20228 = 16406<<2
89+
# LE64: 20228: pcaddi $a0, 16406
90+
# LE64-NEXT: ld.d $ra, $a0, 0
91+
# LE64-NEXT: jirl $ra, $ra, 0
92+
# LE64-NEXT: add.d $a1, $a0, $tp
93+
94+
## &.got[b]-. = 0x30280+48 - 0x20238: 0x10 pages, page offset 0x2b0
95+
## R_LARCH_RELAX does not appear in pairs. No relaxation.
96+
# LE64: 20238: pcalau12i $a0, 16
97+
# LE64-NEXT: addi.d $a0, $a0, 688
98+
# LE64-NEXT: ld.d $ra, $a0, 0
99+
# LE64-NEXT: jirl $ra, $ra, 0
100+
# LE64-NEXT: add.d $a2, $a0, $tp
101+
102+
## &.got[c]-. = 0x30280+16 - 0x2024c: 0x10 pages, page offset 0x290
103+
## Without R_LARCH_RELAX relocation. No relaxation.
104+
# LE64: 2024c: pcalau12i $a0, 16
105+
# LE64-NEXT: addi.d $t0, $zero, 0
106+
# LE64-NEXT: addi.d $a0, $a0, 656
107+
# LE64-NEXT: addi.d $t0, $t0, 1
108+
# LE64-NEXT: ld.d $ra, $a0, 0
109+
# LE64-NEXT: addi.d $t0, $t0, 1
110+
# LE64-NEXT: jirl $ra, $ra, 0
111+
# LE64-NEXT: add.d $a3, $a0, $tp
112+
113+
## &.got[d]-. = 0x30280+32 - 0x2026c = 16397<<2
114+
# LE64: 2026c: pcaddi $a0, 16397
115+
# LE64-NEXT: ld.d $ra, $a0, 0
116+
# LE64-NEXT: jirl $ra, $ra, 0
117+
# LE64-NEXT: add.d $a4, $a0, $tp
118+
119+
# LE64-NORELAX: .got 00000040 0000000000030288
120+
121+
## &.got[a]-. = 0x30288 - 0x20228 = 0x10 pages, page offset 0x288
122+
# LE64-NORELAX: 20228: pcalau12i $a0, 16
123+
# LE64-NORELAX-NEXT: addi.d $a0, $a0, 648
124+
# LE64-NORELAX-NEXT: ld.d $ra, $a0, 0
125+
# LE64-NORELAX-NEXT: jirl $ra, $ra, 0
126+
# LE64-NORELAX-NEXT: add.d $a1, $a0, $tp
127+
128+
## &.got[b]-. = 0x30288+48 - 0x2023c: 0x10 pages, page offset 0x2b8
129+
## R_LARCH_RELAX does not appear in pairs. No relaxation.
130+
# LE64-NORELAX: 2023c: pcalau12i $a0, 16
131+
# LE64-NORELAX-NEXT: addi.d $a0, $a0, 696
132+
# LE64-NORELAX-NEXT: ld.d $ra, $a0, 0
133+
# LE64-NORELAX-NEXT: jirl $ra, $ra, 0
134+
# LE64-NORELAX-NEXT: add.d $a2, $a0, $tp
135+
136+
## &.got[c]-. = 0x30288+16 - 0x20250: 0x10 pages, page offset 0x298
137+
## Without R_LARCH_RELAX relocation. No relaxation.
138+
# LE64-NORELAX: 20250: pcalau12i $a0, 16
139+
# LE64-NORELAX-NEXT: addi.d $t0, $zero, 0
140+
# LE64-NORELAX-NEXT: addi.d $a0, $a0, 664
141+
# LE64-NORELAX-NEXT: addi.d $t0, $t0, 1
142+
# LE64-NORELAX-NEXT: ld.d $ra, $a0, 0
143+
# LE64-NORELAX-NEXT: addi.d $t0, $t0, 1
144+
# LE64-NORELAX-NEXT: jirl $ra, $ra, 0
145+
# LE64-NORELAX-NEXT: add.d $a3, $a0, $tp
146+
147+
## &.got[d]-. = 0x30288+32 - 0x20270: 0x10 pages, page offset 0x2a8
148+
# LE64-NORELAX: 20270: pcalau12i $a0, 16
149+
# LE64-NORELAX-NEXT: addi.d $a0, $a0, 680
150+
# LE64-NORELAX-NEXT: ld.d $ra, $a0, 0
151+
# LE64-NORELAX-NEXT: jirl $ra, $ra, 0
152+
# LE64-NORELAX-NEXT: add.d $a4, $a0, $tp
153+
154+
# IE64-RELA: .rela.dyn {
155+
# IE64-RELA-NEXT: 0x30430 R_LARCH_TLS_DESC64 - 0x8
156+
# IE64-RELA-NEXT: 0x30460 R_LARCH_TLS_DESC64 - 0x7FF
157+
# IE64-RELA-NEXT: 0x30440 R_LARCH_TLS_DESC64 c 0x0
158+
# IE64-RELA-NEXT: 0x30450 R_LARCH_TLS_DESC64 d 0x0
159+
# IE64-RELA-NEXT: }
160+
# IE64-RELA: Hex dump of section '.got':
161+
# IE64-RELA-NEXT: 0x00030430 00000000 00000000 00000000 00000000 .
162+
# IE64-RELA-NEXT: 0x00030440 00000000 00000000 00000000 00000000 .
163+
# IE64-RELA-NEXT: 0x00030450 00000000 00000000 00000000 00000000 .
164+
# IE64-RELA-NEXT: 0x00030460 00000000 00000000 00000000 00000000 .
165+
166+
# IE64: .got 00000040 0000000000030430
167+
168+
## a and b are optimized to use LE. c and d are optimized to IE.
169+
## &.got[a]-. = 0x30430 - 0x202f8 = 16462<<2
170+
# IE64: 202f8: pcaddi $a0, 16462
171+
# IE64-NEXT: ld.d $ra, $a0, 0
172+
# IE64-NEXT: jirl $ra, $ra, 0
173+
# IE64-NEXT: add.d $a1, $a0, $tp
174+
175+
## &.got[b]-. = 0x30430+48 - 0x20308: 0x10 pages, page offset 0x460
176+
## R_LARCH_RELAX does not appear in pairs. No relaxation.
177+
# IE64: 20308: pcalau12i $a0, 16
178+
# IE64-NEXT: addi.d $a0, $a0, 1120
179+
# IE64-NEXT: ld.d $ra, $a0, 0
180+
# IE64-NEXT: jirl $ra, $ra, 0
181+
# IE64-NEXT: add.d $a2, $a0, $tp
182+
183+
## &.got[c]-. = 0x30430+16 - 0x2031c: 0x10 pages, page offset 0x440
184+
## Without R_LARCH_RELAX relocation. No relaxation.
185+
# IE64: 2031c: pcalau12i $a0, 16
186+
# IE64-NEXT: addi.d $t0, $zero, 0
187+
# IE64-NEXT: addi.d $a0, $a0, 1088
188+
# IE64-NEXT: addi.d $t0, $t0, 1
189+
# IE64-NEXT: ld.d $ra, $a0, 0
190+
# IE64-NEXT: addi.d $t0, $t0, 1
191+
# IE64-NEXT: jirl $ra, $ra, 0
192+
# IE64-NEXT: add.d $a3, $a0, $tp
193+
194+
## &.got[d]-. = 0x30430+32 - 0x2033c = 16453<<2
195+
# IE64: 2033c: pcaddi $a0, 16453
196+
# IE64-NEXT: ld.d $ra, $a0, 0
197+
# IE64-NEXT: jirl $ra, $ra, 0
198+
# IE64-NEXT: add.d $a4, $a0, $tp
199+
200+
# IE64-NORELAX: .got 00000040 0000000000030438
201+
202+
## &.got[a]-. = 0x30438 - 0x202f8 = 0x10 pages, page offset 0x438
203+
# IE64-NORELAX: 202f8: pcalau12i $a0, 16
204+
# IE64-NORELAX-NEXT: addi.d $a0, $a0, 1080
205+
# IE64-NORELAX-NEXT: ld.d $ra, $a0, 0
206+
# IE64-NORELAX-NEXT: jirl $ra, $ra, 0
207+
# IE64-NORELAX-NEXT: add.d $a1, $a0, $tp
208+
209+
## &.got[b]-. = 0x30438+48 - 0x2030c: 0x10 pages, page offset 0x468
210+
## R_LARCH_RELAX does not appear in pairs. No relaxation.
211+
# IE64-NORELAX: 2030c: pcalau12i $a0, 16
212+
# IE64-NORELAX-NEXT: addi.d $a0, $a0, 1128
213+
# IE64-NORELAX-NEXT: ld.d $ra, $a0, 0
214+
# IE64-NORELAX-NEXT: jirl $ra, $ra, 0
215+
# IE64-NORELAX-NEXT: add.d $a2, $a0, $tp
216+
217+
## &.got[c]-. = 0x30438+16 - 0x20320: 0x10 pages, page offset 0x448
218+
## Without R_LARCH_RELAX relocation. No relaxation.
219+
# IE64-NORELAX: 20320: pcalau12i $a0, 16
220+
# IE64-NORELAX-NEXT: addi.d $t0, $zero, 0
221+
# IE64-NORELAX-NEXT: addi.d $a0, $a0, 1096
222+
# IE64-NORELAX-NEXT: addi.d $t0, $t0, 1
223+
# IE64-NORELAX-NEXT: ld.d $ra, $a0, 0
224+
# IE64-NORELAX-NEXT: addi.d $t0, $t0, 1
225+
# IE64-NORELAX-NEXT: jirl $ra, $ra, 0
226+
# IE64-NORELAX-NEXT: add.d $a3, $a0, $tp
227+
228+
## &.got[d]-. = 0x30438+32 - 0x20340: 0x10 pages, page offset 0x458
229+
# IE64-NORELAX: 20340: pcalau12i $a0, 16
230+
# IE64-NORELAX-NEXT: addi.d $a0, $a0, 1112
231+
# IE64-NORELAX-NEXT: ld.d $ra, $a0, 0
232+
# IE64-NORELAX-NEXT: jirl $ra, $ra, 0
233+
# IE64-NORELAX-NEXT: add.d $a4, $a0, $tp
234+
235+
#--- a.s
236+
la.tls.desc $a0, a
237+
add.d $a1, $a0, $tp
238+
239+
# ADDI.D does not have R_LARCH_RELAX. No relaxation.
240+
pcalau12i $a0, %desc_pc_hi20(b)
241+
.reloc .-4, R_LARCH_RELAX, 0
242+
addi.d $a0, $a0, %desc_pc_lo12(b)
243+
ld.d $ra, $a0, %desc_ld(b)
244+
jirl $ra, $ra, %desc_call(b)
245+
add.d $a2, $a0, $tp
246+
247+
# TLSDESC to LE. No relaxation.
248+
pcalau12i $a0, %desc_pc_hi20(c)
249+
addi.d $t0, $zero, 0
250+
addi.d $a0, $a0, %desc_pc_lo12(c)
251+
addi.d $t0, $t0, 1
252+
ld.d $ra, $a0, %desc_ld(c)
253+
addi.d $t0, $t0, 1
254+
jirl $ra, $ra, %desc_call(c)
255+
add.d $a3, $a0, $tp
256+
257+
# PCALAU12I and ADDI.D have R_LARCH_RELAX. We preform relaxation.
258+
pcalau12i $a0, %desc_pc_hi20(d)
259+
.reloc .-4, R_LARCH_RELAX, 0
260+
addi.d $a0, $a0, %desc_pc_lo12(d)
261+
.reloc .-4, R_LARCH_RELAX, 0
262+
ld.d $ra, $a0, %desc_ld(d)
263+
jirl $ra, $ra, %desc_call(d)
264+
add.d $a4, $a0, $tp
265+
266+
.section .tbss,"awT",@nobits
267+
.globl a
268+
.zero 8
269+
a:
270+
.zero 2039 ## Place b at 0x7ff
271+
b:
272+
.zero 1
273+
274+
#--- c.s
275+
.section .tbss,"awT",@nobits
276+
.globl c, d
277+
c:
278+
.zero 2048 ## Place d at 0x1000
279+
d:
280+
.zero 4

0 commit comments

Comments
 (0)