Skip to content

Commit 2e3d212

Browse files
authored
[LoongArch] Allow difference across sections (#141722)
For SecA != SecB but SecB is current section, fallback for pcrel{64,32} relocations. For linker relaxation being disabled and SecA == SecB, return directly for avoid record relocations. In other cases, record relocations which also allows across sections.
1 parent f626620 commit 2e3d212

File tree

5 files changed

+137
-24
lines changed

5 files changed

+137
-24
lines changed

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

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,26 @@ bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
429429
return true;
430430
}
431431

432+
bool LoongArchAsmBackend::isPCRelFixupResolved(const MCSymbol *SymA,
433+
const MCFragment &F) {
434+
// If the section does not contain linker-relaxable fragments, PC-relative
435+
// fixups can be resolved.
436+
if (!F.getParent()->isLinkerRelaxable())
437+
return true;
438+
439+
// Otherwise, check if the offset between the symbol and fragment is fully
440+
// resolved, unaffected by linker-relaxable fragments (e.g. instructions or
441+
// offset-affected MCAlignFragment). Complements the generic
442+
// isSymbolRefDifferenceFullyResolvedImpl.
443+
if (!PCRelTemp)
444+
PCRelTemp = getContext().createTempSymbol();
445+
PCRelTemp->setFragment(const_cast<MCFragment *>(&F));
446+
MCValue Res;
447+
MCExpr::evaluateSymbolicAdd(Asm, false, MCValue::get(SymA),
448+
MCValue::get(nullptr, PCRelTemp), Res);
449+
return !Res.getSubSym();
450+
}
451+
432452
bool LoongArchAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup,
433453
const MCValue &Target, uint64_t &FixedValue,
434454
bool IsResolved) {
@@ -447,19 +467,24 @@ bool LoongArchAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup,
447467
if (!force) {
448468
const MCSection &SecA = SA.getSection();
449469
const MCSection &SecB = SB.getSection();
450-
451-
// We need record relocation if SecA != SecB. Usually SecB is same as the
452-
// section of Fixup, which will be record the relocation as PCRel. If SecB
453-
// is not same as the section of Fixup, it will report error. Just return
454-
// false and then this work can be finished by handleFixup.
455-
if (&SecA != &SecB)
470+
const MCSection &SecCur = *F.getParent();
471+
472+
// To handle the case of A - B which B is same section with the current,
473+
// generate PCRel relocations is better than ADD/SUB relocation pair.
474+
// We can resolve it as A - PC + PC - B. The A - PC will be resolved
475+
// as a PCRel relocation, while PC - B will serve as the addend.
476+
// If the linker relaxation is disabled, it can be done directly since
477+
// PC - B is constant. Otherwise, we should evaluate whether PC - B
478+
// is constant. If it can be resolved as PCRel, use Fallback which
479+
// generates R_LARCH_{32,64}_PCREL relocation later.
480+
if (&SecA != &SecB && &SecB == &SecCur &&
481+
isPCRelFixupResolved(Target.getSubSym(), F))
456482
return Fallback();
457483

458-
// In SecA == SecB case. If the linker relaxation is enabled, we need
459-
// record the ADD, SUB relocations. Otherwise the FixedValue has already
460-
// been calc- ulated out in evaluateFixup, return true and avoid record
461-
// relocations.
462-
if (!STI.hasFeature(LoongArch::FeatureRelax))
484+
// In SecA == SecB case. If the linker relaxation is disabled, the
485+
// FixedValue has already been calculated out in evaluateFixup,
486+
// return true and avoid record relocations.
487+
if (&SecA == &SecB && !STI.hasFeature(LoongArch::FeatureRelax))
463488
return true;
464489
}
465490

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ class LoongArchAsmBackend : public MCAsmBackend {
3030
bool Is64Bit;
3131
const MCTargetOptions &TargetOptions;
3232
DenseMap<MCSection *, const MCSymbolRefExpr *> SecToAlignSym;
33+
// Temporary symbol used to check whether a PC-relative fixup is resolved.
34+
MCSymbol *PCRelTemp = nullptr;
35+
36+
bool isPCRelFixupResolved(const MCSymbol *SymA, const MCFragment &F);
3337

3438
public:
3539
LoongArchAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit,

llvm/test/MC/LoongArch/Misc/cfi-advance.s

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=-relax %s -o %t.o
22
# RUN: llvm-readobj -r %t.o | FileCheck --check-prefix=RELOC %s
33
# RUN: llvm-dwarfdump --debug-frame %t.o | FileCheck --check-prefix=DWARFDUMP %s
4+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 -mattr=+relax %s \
5+
# RUN: | llvm-readobj -r - | FileCheck --check-prefix=RELAX %s
46

57
# RELOC: Relocations [
68
# RELOC-NEXT: .rela.eh_frame {
@@ -12,6 +14,16 @@
1214
# DWARFDUMP-NEXT: DW_CFA_advance_loc: 8
1315
# DWARFDUMP-NEXT: DW_CFA_def_cfa_offset: +8
1416

17+
# RELAX: Relocations [
18+
# RELAX: .rela.eh_frame {
19+
# RELAX-NEXT: 0x1C R_LARCH_32_PCREL .L{{.*}} 0x0
20+
# RELAX-NEXT: 0x20 R_LARCH_ADD32 .L{{.*}} 0x0
21+
# RELAX-NEXT: 0x20 R_LARCH_SUB32 .L{{.*}} 0x0
22+
# RELAX-NEXT: 0x28 R_LARCH_ADD6 .L{{.*}} 0x0
23+
# RELAX-NEXT: 0x28 R_LARCH_SUB6 .L{{.*}} 0x0
24+
# RELAX-NEXT: }
25+
# RELAX-NEXT: ]
26+
1527
.text
1628
.globl test
1729
.p2align 2

llvm/test/MC/LoongArch/Relocations/fde-reloc.s

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
# RUN: llvm-mc --filetype=obj --triple=loongarch64 < %s \
1+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=-relax < %s \
22
# RUN: | llvm-readobj -r - | FileCheck %s
3+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax < %s \
4+
# RUN: | llvm-readobj -r - | FileCheck %s --check-prefix=RELAX
35

46
## Ensure that the eh_frame records the symbolic difference with
57
## the R_LARCH_32_PCREL relocation.
@@ -12,3 +14,6 @@ func:
1214
# CHECK: Section (4) .rela.eh_frame {
1315
# CHECK-NEXT: 0x1C R_LARCH_32_PCREL .text 0x0
1416
# CHECK-NEXT: }
17+
# RELAX: Section ({{.*}}) .rela.eh_frame {
18+
# RELAX-NEXT: 0x1C R_LARCH_32_PCREL .L{{.*}} 0x0
19+
# RELAX-NEXT: }
Lines changed: 79 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,95 @@
1-
# RUN: llvm-mc --filetype=obj --triple=loongarch64 %s -o %t
2-
# RUN: llvm-readobj -r %t | FileCheck %s
1+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=-relax %s \
2+
# RUN: | llvm-readobj -r - | FileCheck %s
3+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s \
4+
# RUN: | llvm-readobj -r - | FileCheck %s --check-prefix=RELAX
35

46
## Check that subtraction expressions emit R_LARCH_32_PCREL and R_LARCH_64_PCREL relocations.
57

68
## TODO: 1- or 2-byte data relocations are not supported for now.
79

810
# CHECK: Relocations [
9-
# CHECK-NEXT: Section ({{.*}}) .rela.data {
10-
# CHECK-NEXT: 0x0 R_LARCH_64_PCREL sx 0x0
11-
# CHECK-NEXT: 0x8 R_LARCH_64_PCREL sy 0x0
12-
# CHECK-NEXT: 0x10 R_LARCH_32_PCREL sx 0x0
13-
# CHECK-NEXT: 0x14 R_LARCH_32_PCREL sy 0x0
14-
# CHECK-NEXT: }
11+
# CHECK-NEXT: Section ({{.*}}) .rela.sx {
12+
# CHECK-NEXT: 0x4 R_LARCH_PCALA_HI20 z 0x0
13+
# CHECK-NEXT: 0x8 R_LARCH_PCALA_LO12 z 0x0
14+
# CHECK-NEXT: 0xC R_LARCH_32_PCREL .sy 0xC
15+
# CHECK-NEXT: }
16+
# CHECK-NEXT: Section ({{.*}}) .rela.data {
17+
# CHECK-NEXT: 0x0 R_LARCH_64_PCREL .sx 0x4
18+
# CHECK-NEXT: 0x8 R_LARCH_64_PCREL .sy 0x4
19+
# CHECK-NEXT: 0x10 R_LARCH_32_PCREL .sx 0x4
20+
# CHECK-NEXT: 0x14 R_LARCH_32_PCREL .sy 0x4
21+
# CHECK-NEXT: 0x18 R_LARCH_ADD64 .sx 0x4
22+
# CHECK-NEXT: 0x18 R_LARCH_SUB64 .sy 0x4
23+
# CHECK-NEXT: 0x20 R_LARCH_ADD64 .sy 0x4
24+
# CHECK-NEXT: 0x20 R_LARCH_SUB64 .sx 0x4
25+
# CHECK-NEXT: 0x28 R_LARCH_ADD32 .sx 0x4
26+
# CHECK-NEXT: 0x28 R_LARCH_SUB32 .sy 0x4
27+
# CHECK-NEXT: 0x2C R_LARCH_ADD32 .sy 0x4
28+
# CHECK-NEXT: 0x2C R_LARCH_SUB32 .sx 0x4
29+
# CHECK-NEXT: 0x30 R_LARCH_ADD64 .data 0x30
30+
# CHECK-NEXT: 0x30 R_LARCH_SUB64 .sx 0x4
31+
# CHECK-NEXT: 0x38 R_LARCH_ADD32 .data 0x38
32+
# CHECK-NEXT: 0x38 R_LARCH_SUB32 .sy 0x4
33+
# CHECK-NEXT: }
34+
# CHECK-NEXT: Section ({{.*}}) .rela.sy {
35+
# CHECK-NEXT: 0x10 R_LARCH_32_PCREL .sx 0x10
36+
# CHECK-NEXT: }
37+
# CHECK-NEXT: ]
1538

16-
.section sx,"a"
17-
x:
39+
# RELAX: Relocations [
40+
# RELAX-NEXT: Section ({{.*}}) .rela.sx {
41+
# RELAX-NEXT: 0x4 R_LARCH_PCALA_HI20 z 0x0
42+
# RELAX-NEXT: 0x4 R_LARCH_RELAX - 0x0
43+
# RELAX-NEXT: 0x8 R_LARCH_PCALA_LO12 z 0x0
44+
# RELAX-NEXT: 0x8 R_LARCH_RELAX - 0x0
45+
# RELAX-NEXT: 0xC R_LARCH_ADD32 y 0x0
46+
# RELAX-NEXT: 0xC R_LARCH_SUB32 x 0x0
47+
# RELAX-NEXT: }
48+
# RELAX-NEXT: Section ({{.*}}) .rela.data {
49+
# RELAX-NEXT: 0x0 R_LARCH_64_PCREL x 0x0
50+
# RELAX-NEXT: 0x8 R_LARCH_64_PCREL y 0x0
51+
# RELAX-NEXT: 0x10 R_LARCH_32_PCREL x 0x0
52+
# RELAX-NEXT: 0x14 R_LARCH_32_PCREL y 0x0
53+
# RELAX-NEXT: 0x18 R_LARCH_ADD64 x 0x0
54+
# RELAX-NEXT: 0x18 R_LARCH_SUB64 y 0x0
55+
# RELAX-NEXT: 0x20 R_LARCH_ADD64 y 0x0
56+
# RELAX-NEXT: 0x20 R_LARCH_SUB64 x 0x0
57+
# RELAX-NEXT: 0x28 R_LARCH_ADD32 x 0x0
58+
# RELAX-NEXT: 0x28 R_LARCH_SUB32 y 0x0
59+
# RELAX-NEXT: 0x2C R_LARCH_ADD32 y 0x0
60+
# RELAX-NEXT: 0x2C R_LARCH_SUB32 x 0x0
61+
# RELAX-NEXT: 0x30 R_LARCH_ADD64 {{.*}} 0x0
62+
# RELAX-NEXT: 0x30 R_LARCH_SUB64 x 0x0
63+
# RELAX-NEXT: 0x38 R_LARCH_ADD32 {{.*}} 0x0
64+
# RELAX-NEXT: 0x38 R_LARCH_SUB32 y 0x0
65+
# RELAX-NEXT: }
66+
# RELAX-NEXT: Section ({{.*}}) .rela.sy {
67+
# RELAX-NEXT: 0x4 R_LARCH_ALIGN - 0xC
68+
# RELAX-NEXT: 0x10 R_LARCH_ADD32 x 0x0
69+
# RELAX-NEXT: 0x10 R_LARCH_SUB32 y 0x0
70+
# RELAX-NEXT: }
71+
# RELAX-NEXT: ]
72+
73+
.section .sx,"ax"
1874
nop
75+
x:
76+
la.pcrel $a0, z
77+
.4byte y-x
1978

2079
.data
2180
.8byte x-.
2281
.8byte y-.
2382
.4byte x-.
2483
.4byte y-.
84+
.8byte x-y
85+
.8byte y-x
86+
.4byte x-y
87+
.4byte y-x
88+
.8byte .-x
89+
.4byte .-y
2590

26-
.section sy,"a"
27-
y:
91+
.section .sy,"ax"
2892
nop
93+
y:
94+
.p2align 4
95+
.4byte x-y

0 commit comments

Comments
 (0)