Skip to content

Commit b57159c

Browse files
authored
[LoongArch] Support R_LARCH_{ADD,SUB}_ULEB128 for .uleb128 and force relocs when sym is not in section (#76433)
1, Follow RISCV 1df5ea2 to support generates relocs for .uleb128 which can not be folded. Unlike RISCV, the located content of LoongArch should be zero. LoongArch fixup uleb128 value by in-place addition and subtraction reloc types named R_LARCH_{ADD,SUB}_ULEB128. The located content can affect the result and R_LARCH_ADD_ULEB128 has enough info to represent the first symbol value, so it needs to be set to zero. 2, Force relocs if sym is not in section so that it can emit relocs for external symbol. Fixes: #72960 (comment)
1 parent dad614c commit b57159c

File tree

8 files changed

+187
-39
lines changed

8 files changed

+187
-39
lines changed

llvm/include/llvm/MC/MCAsmBackend.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,9 @@ class MCAsmBackend {
198198

199199
// Defined by linker relaxation targets to possibly emit LEB128 relocations
200200
// and set Value at the relocated location.
201-
virtual bool relaxLEB128(MCLEBFragment &LF, MCAsmLayout &Layout,
202-
int64_t &Value) const {
203-
return false;
201+
virtual std::pair<bool, bool>
202+
relaxLEB128(MCLEBFragment &LF, MCAsmLayout &Layout, int64_t &Value) const {
203+
return std::make_pair(false, false);
204204
}
205205

206206
/// @}

llvm/lib/MC/MCAssembler.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1026,14 +1026,18 @@ bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) {
10261026
? LF.getValue().evaluateKnownAbsolute(Value, Layout)
10271027
: LF.getValue().evaluateAsAbsolute(Value, Layout);
10281028
if (!Abs) {
1029-
if (!getBackend().relaxLEB128(LF, Layout, Value)) {
1029+
bool Relaxed, UseZeroPad;
1030+
std::tie(Relaxed, UseZeroPad) = getBackend().relaxLEB128(LF, Layout, Value);
1031+
if (!Relaxed) {
10301032
getContext().reportError(LF.getValue().getLoc(),
10311033
Twine(LF.isSigned() ? ".s" : ".u") +
10321034
"leb128 expression is not absolute");
10331035
LF.setValue(MCConstantExpr::create(0, Context));
10341036
}
10351037
uint8_t Tmp[10]; // maximum size: ceil(64/7)
10361038
PadTo = std::max(PadTo, encodeULEB128(uint64_t(Value), Tmp));
1039+
if (UseZeroPad)
1040+
Value = 0;
10371041
}
10381042
Data.clear();
10391043
raw_svector_ostream OSE(Data);

llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
9191
case FK_Data_2:
9292
case FK_Data_4:
9393
case FK_Data_8:
94+
case FK_Data_leb128:
9495
return Value;
9596
case LoongArch::fixup_loongarch_b16: {
9697
if (!isInt<18>(Value))
@@ -128,6 +129,15 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
128129
}
129130
}
130131

132+
static void fixupLeb128(MCContext &Ctx, const MCFixup &Fixup,
133+
MutableArrayRef<char> Data, uint64_t Value) {
134+
unsigned I;
135+
for (I = 0; I != Data.size() && Value; ++I, Value >>= 7)
136+
Data[I] |= uint8_t(Value & 0x7f);
137+
if (Value)
138+
Ctx.reportError(Fixup.getLoc(), "Invalid uleb128 value!");
139+
}
140+
131141
void LoongArchAsmBackend::applyFixup(const MCAssembler &Asm,
132142
const MCFixup &Fixup,
133143
const MCValue &Target,
@@ -143,6 +153,10 @@ void LoongArchAsmBackend::applyFixup(const MCAssembler &Asm,
143153
MCFixupKindInfo Info = getFixupKindInfo(Kind);
144154
MCContext &Ctx = Asm.getContext();
145155

156+
// Fixup leb128 separately.
157+
if (Fixup.getTargetKind() == FK_Data_leb128)
158+
return fixupLeb128(Ctx, Fixup, Data, Value);
159+
146160
// Apply any target-specific value adjustments.
147161
Value = adjustFixupValue(Fixup, Value, Ctx);
148162

@@ -173,6 +187,7 @@ bool LoongArchAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
173187
case FK_Data_2:
174188
case FK_Data_4:
175189
case FK_Data_8:
190+
case FK_Data_leb128:
176191
return !Target.isAbsolute();
177192
}
178193
}
@@ -202,9 +217,24 @@ getRelocPairForSize(unsigned Size) {
202217
return std::make_pair(
203218
MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_ADD64),
204219
MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_SUB64));
220+
case 128:
221+
return std::make_pair(
222+
MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_ADD_ULEB128),
223+
MCFixupKind(FirstLiteralRelocationKind + ELF::R_LARCH_SUB_ULEB128));
205224
}
206225
}
207226

227+
std::pair<bool, bool> LoongArchAsmBackend::relaxLEB128(MCLEBFragment &LF,
228+
MCAsmLayout &Layout,
229+
int64_t &Value) const {
230+
const MCExpr &Expr = LF.getValue();
231+
if (LF.isSigned() || !Expr.evaluateKnownAbsolute(Value, Layout))
232+
return std::make_pair(false, false);
233+
LF.getFixups().push_back(
234+
MCFixup::create(0, &Expr, FK_Data_leb128, Expr.getLoc()));
235+
return std::make_pair(true, true);
236+
}
237+
208238
bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
209239
const MCSubtargetInfo *STI) const {
210240
// We mostly follow binutils' convention here: align to 4-byte boundary with a
@@ -226,21 +256,27 @@ bool LoongArchAsmBackend::handleAddSubRelocations(const MCAsmLayout &Layout,
226256
uint64_t &FixedValue) const {
227257
std::pair<MCFixupKind, MCFixupKind> FK;
228258
uint64_t FixedValueA, FixedValueB;
229-
const MCSection &SecA = Target.getSymA()->getSymbol().getSection();
230-
const MCSection &SecB = Target.getSymB()->getSymbol().getSection();
231-
232-
// We need record relocation if SecA != SecB. Usually SecB is same as the
233-
// section of Fixup, which will be record the relocation as PCRel. If SecB
234-
// is not same as the section of Fixup, it will report error. Just return
235-
// false and then this work can be finished by handleFixup.
236-
if (&SecA != &SecB)
237-
return false;
238-
239-
// In SecA == SecB case. If the linker relaxation is enabled, we need record
240-
// the ADD, SUB relocations. Otherwise the FixedValue has already been
241-
// calculated out in evaluateFixup, return true and avoid record relocations.
242-
if (!STI.hasFeature(LoongArch::FeatureRelax))
243-
return true;
259+
const MCSymbol &SA = Target.getSymA()->getSymbol();
260+
const MCSymbol &SB = Target.getSymB()->getSymbol();
261+
262+
bool force = !SA.isInSection() || !SB.isInSection();
263+
if (!force) {
264+
const MCSection &SecA = SA.getSection();
265+
const MCSection &SecB = SB.getSection();
266+
267+
// We need record relocation if SecA != SecB. Usually SecB is same as the
268+
// section of Fixup, which will be record the relocation as PCRel. If SecB
269+
// is not same as the section of Fixup, it will report error. Just return
270+
// false and then this work can be finished by handleFixup.
271+
if (&SecA != &SecB)
272+
return false;
273+
274+
// In SecA == SecB case. If the linker relaxation is enabled, we need record
275+
// the ADD, SUB relocations. Otherwise the FixedValue has already been calc-
276+
// ulated out in evaluateFixup, return true and avoid record relocations.
277+
if (!STI.hasFeature(LoongArch::FeatureRelax))
278+
return true;
279+
}
244280

245281
switch (Fixup.getKind()) {
246282
case llvm::FK_Data_1:
@@ -255,6 +291,9 @@ bool LoongArchAsmBackend::handleAddSubRelocations(const MCAsmLayout &Layout,
255291
case llvm::FK_Data_8:
256292
FK = getRelocPairForSize(64);
257293
break;
294+
case llvm::FK_Data_leb128:
295+
FK = getRelocPairForSize(128);
296+
break;
258297
default:
259298
llvm_unreachable("unsupported fixup size");
260299
}

llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ class LoongArchAsmBackend : public MCAsmBackend {
6666
void relaxInstruction(MCInst &Inst,
6767
const MCSubtargetInfo &STI) const override {}
6868

69+
std::pair<bool, bool> relaxLEB128(MCLEBFragment &LF, MCAsmLayout &Layout,
70+
int64_t &Value) const override;
71+
6972
bool writeNopData(raw_ostream &OS, uint64_t Count,
7073
const MCSubtargetInfo *STI) const override;
7174

llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -329,16 +329,17 @@ bool RISCVAsmBackend::relaxDwarfCFA(MCDwarfCallFrameFragment &DF,
329329
return true;
330330
}
331331

332-
bool RISCVAsmBackend::relaxLEB128(MCLEBFragment &LF, MCAsmLayout &Layout,
333-
int64_t &Value) const {
332+
std::pair<bool, bool> RISCVAsmBackend::relaxLEB128(MCLEBFragment &LF,
333+
MCAsmLayout &Layout,
334+
int64_t &Value) const {
334335
if (LF.isSigned())
335-
return false;
336+
return std::make_pair(false, false);
336337
const MCExpr &Expr = LF.getValue();
337338
if (ULEB128Reloc) {
338339
LF.getFixups().push_back(
339340
MCFixup::create(0, &Expr, FK_Data_leb128, Expr.getLoc()));
340341
}
341-
return Expr.evaluateKnownAbsolute(Value, Layout);
342+
return std::make_pair(Expr.evaluateKnownAbsolute(Value, Layout), false);
342343
}
343344

344345
// Given a compressed control flow instruction this function returns

llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ class RISCVAsmBackend : public MCAsmBackend {
100100
bool &WasRelaxed) const override;
101101
bool relaxDwarfCFA(MCDwarfCallFrameFragment &DF, MCAsmLayout &Layout,
102102
bool &WasRelaxed) const override;
103-
bool relaxLEB128(MCLEBFragment &LF, MCAsmLayout &Layout,
104-
int64_t &Value) const override;
103+
std::pair<bool, bool> relaxLEB128(MCLEBFragment &LF, MCAsmLayout &Layout,
104+
int64_t &Value) const override;
105105

106106
bool writeNopData(raw_ostream &OS, uint64_t Count,
107107
const MCSubtargetInfo *STI) const override;
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=-relax %s -o %t
2+
# RUN: llvm-readobj -r -x .alloc_w %t | FileCheck --check-prefixes=CHECK,NORELAX %s
3+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.relax
4+
# RUN: llvm-readobj -r -x .alloc_w %t.relax | FileCheck --check-prefixes=CHECK,RELAX %s
5+
6+
# RUN: not llvm-mc --filetype=obj --triple=loongarch64 --mattr=-relax --defsym ERR=1 %s -o /dev/null 2>&1 | \
7+
# RUN: FileCheck %s --check-prefix=ERR
8+
# RUN: not llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax --defsym ERR=1 %s -o /dev/null 2>&1 | \
9+
# RUN: FileCheck %s --check-prefix=ERR
10+
11+
# CHECK: Relocations [
12+
# CHECK-NEXT: .rela.alloc_w {
13+
# RELAX-NEXT: 0x0 R_LARCH_ADD_ULEB128 w1 0x0
14+
# RELAX-NEXT: 0x0 R_LARCH_SUB_ULEB128 w 0x0
15+
# RELAX-NEXT: 0x1 R_LARCH_ADD_ULEB128 w2 0x0
16+
# RELAX-NEXT: 0x1 R_LARCH_SUB_ULEB128 w1 0x0
17+
# CHECK-NEXT: 0x2 R_LARCH_PCALA_HI20 foo 0x0
18+
# RELAX-NEXT: 0x2 R_LARCH_RELAX - 0x0
19+
# CHECK-NEXT: 0x6 R_LARCH_PCALA_LO12 foo 0x0
20+
# RELAX-NEXT: 0x6 R_LARCH_RELAX - 0x0
21+
# RELAX-NEXT: 0xA R_LARCH_ADD_ULEB128 w2 0x0
22+
# RELAX-NEXT: 0xA R_LARCH_SUB_ULEB128 w1 0x0
23+
# RELAX-NEXT: 0xB R_LARCH_ADD_ULEB128 w2 0x78
24+
# RELAX-NEXT: 0xB R_LARCH_SUB_ULEB128 w1 0x0
25+
# RELAX-NEXT: 0xD R_LARCH_ADD_ULEB128 w1 0x0
26+
# RELAX-NEXT: 0xD R_LARCH_SUB_ULEB128 w2 0x0
27+
# RELAX-NEXT: 0x17 R_LARCH_ADD_ULEB128 w3 0x6F
28+
# RELAX-NEXT: 0x17 R_LARCH_SUB_ULEB128 w2 0x0
29+
# RELAX-NEXT: 0x18 R_LARCH_ADD_ULEB128 w3 0x71
30+
# RELAX-NEXT: 0x18 R_LARCH_SUB_ULEB128 w2 0x0
31+
# CHECK-NEXT: }
32+
# CHECK-NEXT: ]
33+
34+
# CHECK: Hex dump of section '.alloc_w':
35+
# NORELAX-NEXT: 0x00000000 02080c00 001a8c01 c0020880 01f8ffff
36+
# NORELAX-NEXT: 0x00000010 ffffffff ffff017f 8101
37+
# RELAX-NEXT: 0x00000000 00000c00 001a8c01 c0020080 00808080
38+
# RELAX-NEXT: 0x00000010 80808080 80800000 8000
39+
40+
.section .alloc_w,"ax",@progbits; w:
41+
.uleb128 w1-w # w1 is later defined in the same section
42+
.uleb128 w2-w1 # w1 and w2 are separated by a linker relaxable instruction
43+
w1:
44+
la.pcrel $t0, foo
45+
w2:
46+
.uleb128 w2-w1 # 0x08
47+
.uleb128 w2-w1+120 # 0x0180
48+
.uleb128 -(w2-w1) # 0x01fffffffffffffffff8
49+
.uleb128 w3-w2+111 # 0x7f
50+
.uleb128 w3-w2+113 # 0x0181
51+
w3:
52+
53+
.ifdef ERR
54+
# ERR: :[[#@LINE+1]]:16: error: .uleb128 expression is not absolute
55+
.uleb128 extern-w # extern is undefined
56+
# ERR: :[[#@LINE+1]]:11: error: .uleb128 expression is not absolute
57+
.uleb128 w-extern
58+
# ERR: :[[#@LINE+1]]:11: error: .uleb128 expression is not absolute
59+
.uleb128 x-w # x is later defined in another section
60+
61+
.section .alloc_x,"aw",@progbits; x:
62+
# ERR: :[[#@LINE+1]]:11: error: .uleb128 expression is not absolute
63+
.uleb128 y-x
64+
.section .alloc_y,"aw",@progbits; y:
65+
# ERR: :[[#@LINE+1]]:11: error: .uleb128 expression is not absolute
66+
.uleb128 x-y
67+
68+
# ERR: :[[#@LINE+1]]:10: error: .uleb128 expression is not absolute
69+
.uleb128 extern
70+
# ERR: :[[#@LINE+1]]:10: error: .uleb128 expression is not absolute
71+
.uleb128 y
72+
.endif

llvm/test/MC/LoongArch/Relocations/relax-addsub.s

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,23 @@
88
# NORELAX-NEXT: 0x10 R_LARCH_PCALA_HI20 .text 0x0
99
# NORELAX-NEXT: 0x14 R_LARCH_PCALA_LO12 .text 0x0
1010
# NORELAX-NEXT: }
11+
# NORELAX-NEXT: Section ({{.*}}) .rela.data {
12+
# NORELAX-NEXT: 0x30 R_LARCH_ADD8 foo 0x0
13+
# NORELAX-NEXT: 0x30 R_LARCH_SUB8 .text 0x10
14+
# NORELAX-NEXT: 0x31 R_LARCH_ADD16 foo 0x0
15+
# NORELAX-NEXT: 0x31 R_LARCH_SUB16 .text 0x10
16+
# NORELAX-NEXT: 0x33 R_LARCH_ADD32 foo 0x0
17+
# NORELAX-NEXT: 0x33 R_LARCH_SUB32 .text 0x10
18+
# NORELAX-NEXT: 0x37 R_LARCH_ADD64 foo 0x0
19+
# NORELAX-NEXT: 0x37 R_LARCH_SUB64 .text 0x10
20+
# NORELAX-NEXT: }
1121
# NORELAX-NEXT: ]
1222

1323
# NORELAX: Hex dump of section '.data':
14-
# NORELAX-NEXT: 0x00000000 04040004 00000004 00000000 0000000c
15-
# NORELAX-NEXT: 0x00000010 0c000c00 00000c00 00000000 00000808
16-
# NORELAX-NEXT: 0x00000020 00080000 00080000 00000000 00
24+
# NORELAX-NEXT: 0x00000000 04040004 00000004 00000000 00000004
25+
# NORELAX-NEXT: 0x00000010 0c0c000c 0000000c 00000000 0000000c
26+
# NORELAX-NEXT: 0x00000020 08080008 00000008 00000000 00000008
27+
# NORELAX-NEXT: 0x00000030 00000000 00000000 00000000 000000
1728

1829
# RELAX: Relocations [
1930
# RELAX-NEXT: Section ({{.*}}) .rela.text {
@@ -23,21 +34,32 @@
2334
# RELAX-NEXT: 0x14 R_LARCH_RELAX - 0x0
2435
# RELAX-NEXT: }
2536
# RELAX-NEXT: Section ({{.*}}) .rela.data {
26-
# RELAX-NEXT: 0x1E R_LARCH_ADD8 .L4 0x0
27-
# RELAX-NEXT: 0x1E R_LARCH_SUB8 .L3 0x0
28-
# RELAX-NEXT: 0x1F R_LARCH_ADD16 .L4 0x0
29-
# RELAX-NEXT: 0x1F R_LARCH_SUB16 .L3 0x0
30-
# RELAX-NEXT: 0x21 R_LARCH_ADD32 .L4 0x0
31-
# RELAX-NEXT: 0x21 R_LARCH_SUB32 .L3 0x0
32-
# RELAX-NEXT: 0x25 R_LARCH_ADD64 .L4 0x0
33-
# RELAX-NEXT: 0x25 R_LARCH_SUB64 .L3 0x0
37+
# RELAX-NEXT: 0x20 R_LARCH_ADD8 .L4 0x0
38+
# RELAX-NEXT: 0x20 R_LARCH_SUB8 .L3 0x0
39+
# RELAX-NEXT: 0x21 R_LARCH_ADD16 .L4 0x0
40+
# RELAX-NEXT: 0x21 R_LARCH_SUB16 .L3 0x0
41+
# RELAX-NEXT: 0x23 R_LARCH_ADD32 .L4 0x0
42+
# RELAX-NEXT: 0x23 R_LARCH_SUB32 .L3 0x0
43+
# RELAX-NEXT: 0x27 R_LARCH_ADD64 .L4 0x0
44+
# RELAX-NEXT: 0x27 R_LARCH_SUB64 .L3 0x0
45+
# RELAX-NEXT: 0x2F R_LARCH_ADD_ULEB128 .L4 0x0
46+
# RELAX-NEXT: 0x2F R_LARCH_SUB_ULEB128 .L3 0x0
47+
# RELAX-NEXT: 0x30 R_LARCH_ADD8 foo 0x0
48+
# RELAX-NEXT: 0x30 R_LARCH_SUB8 .L3 0x0
49+
# RELAX-NEXT: 0x31 R_LARCH_ADD16 foo 0x0
50+
# RELAX-NEXT: 0x31 R_LARCH_SUB16 .L3 0x0
51+
# RELAX-NEXT: 0x33 R_LARCH_ADD32 foo 0x0
52+
# RELAX-NEXT: 0x33 R_LARCH_SUB32 .L3 0x0
53+
# RELAX-NEXT: 0x37 R_LARCH_ADD64 foo 0x0
54+
# RELAX-NEXT: 0x37 R_LARCH_SUB64 .L3 0x0
3455
# RELAX-NEXT: }
3556
# RELAX-NEXT: ]
3657

3758
# RELAX: Hex dump of section '.data':
38-
# RELAX-NEXT: 0x00000000 04040004 00000004 00000000 0000000c
39-
# RELAX-NEXT: 0x00000010 0c000c00 00000c00 00000000 00000000
40-
# RELAX-NEXT: 0x00000020 00000000 00000000 00000000 00
59+
# RELAX-NEXT: 0x00000000 04040004 00000004 00000000 00000004
60+
# RELAX-NEXT: 0x00000010 0c0c000c 0000000c 00000000 0000000c
61+
# RELAX-NEXT: 0x00000020 00000000 00000000 00000000 00000000
62+
# RELAX-NEXT: 0x00000030 00000000 00000000 00000000 000000
4163

4264
.text
4365
.L1:
@@ -55,13 +77,20 @@
5577
.short .L2 - .L1
5678
.word .L2 - .L1
5779
.dword .L2 - .L1
80+
.uleb128 .L2 - .L1
5881
## TODO Handle alignment directive.
5982
.byte .L3 - .L2
6083
.short .L3 - .L2
6184
.word .L3 - .L2
6285
.dword .L3 - .L2
86+
.uleb128 .L3 - .L2
6387
## With relaxation, emit relocs because the la.pcrel makes the diff variable.
6488
.byte .L4 - .L3
6589
.short .L4 - .L3
6690
.word .L4 - .L3
6791
.dword .L4 - .L3
92+
.uleb128 .L4 - .L3
93+
.byte foo - .L3
94+
.short foo - .L3
95+
.word foo - .L3
96+
.dword foo - .L3

0 commit comments

Comments
 (0)