MC: Generate relocation for a branch crossing linker-relaxable FT_Align fragment
"Encode FT_Align in fragment's variable-size tail" or a neighbor change caused a regression that was similar to the root cause of ab0931b6389838cb5d7d11914063a1ddd84102f0 (See the new test (.text3 with a call at the start")) For a FT_Align fragment, the offset between location A (with offset <= FixedSize) and B (offset == FixedSize+VarSize) cannot be resolved. In addition, delete unneeded condition `F->isLinkerRelaxable()`. LoongArch linker relaxation is largely under-tested, but update it as well.
This commit is contained in:
parent
59fdd97fe6
commit
69d0078f16
@ -346,17 +346,16 @@ static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm,
|
|||||||
Displacement *= -1;
|
Displacement *= -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track whether B is before a relaxable instruction and whether A is after
|
// Track whether B is before a relaxable instruction/alignment and whether A
|
||||||
// a relaxable instruction. If SA and SB are separated by a linker-relaxable
|
// is after a relaxable instruction/alignment. If SA and SB are separated by
|
||||||
// instruction, the difference cannot be resolved as it may be changed by
|
// a linker-relaxable instruction/alignment, the difference cannot be
|
||||||
// the linker.
|
// resolved as it may be changed by the linker.
|
||||||
bool BBeforeRelax = false, AAfterRelax = false;
|
bool BBeforeRelax = false, AAfterRelax = false;
|
||||||
for (auto F = FB; F; F = F->getNext()) {
|
for (auto F = FB; F; F = F->getNext()) {
|
||||||
auto DF = F->getKind() == MCFragment::FT_Data ? F : nullptr;
|
if (F && F->isLinkerRelaxable()) {
|
||||||
if (DF && DF->isLinkerRelaxable()) {
|
if (&*F != FB || SBOffset != F->getSize())
|
||||||
if (&*F != FB || SBOffset != DF->getContents().size())
|
|
||||||
BBeforeRelax = true;
|
BBeforeRelax = true;
|
||||||
if (&*F != FA || SAOffset == DF->getContents().size())
|
if (&*F != FA || SAOffset == F->getSize())
|
||||||
AAfterRelax = true;
|
AAfterRelax = true;
|
||||||
if (BBeforeRelax && AAfterRelax)
|
if (BBeforeRelax && AAfterRelax)
|
||||||
return;
|
return;
|
||||||
@ -370,17 +369,15 @@ static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int64_t Num;
|
int64_t Num;
|
||||||
if (DF) {
|
if (F->getKind() == MCFragment::FT_Data) {
|
||||||
Displacement += DF->getContents().size();
|
Displacement += F->getFixedSize();
|
||||||
} else if (F->getKind() == MCFragment::FT_Relaxable &&
|
} else if ((F->getKind() == MCFragment::FT_Relaxable ||
|
||||||
|
F->getKind() == MCFragment::FT_Align) &&
|
||||||
Asm->hasFinalLayout()) {
|
Asm->hasFinalLayout()) {
|
||||||
// Before finishLayout, a relaxable fragment's size is indeterminate.
|
// Before finishLayout, a relaxable fragment's size is indeterminate.
|
||||||
// After layout, during relocation generation, it can be treated as a
|
// After layout, during relocation generation, it can be treated as a
|
||||||
// data fragment.
|
// data fragment.
|
||||||
Displacement += F->getSize();
|
Displacement += F->getSize();
|
||||||
} else if (F->getKind() == MCFragment::FT_Align && Layout &&
|
|
||||||
F->isLinkerRelaxable()) {
|
|
||||||
Displacement += Asm->computeFragmentSize(*F);
|
|
||||||
} else if (auto *FF = dyn_cast<MCFillFragment>(F);
|
} else if (auto *FF = dyn_cast<MCFillFragment>(F);
|
||||||
FF && FF->getNumValues().evaluateAsAbsolute(Num)) {
|
FF && FF->getNumValues().evaluateAsAbsolute(Num)) {
|
||||||
Displacement += Num * FF->getValueSize();
|
Displacement += Num * FF->getValueSize();
|
||||||
|
@ -254,6 +254,7 @@ bool LoongArchAsmBackend::relaxAlign(MCFragment &F, unsigned &Size) {
|
|||||||
MCFixup Fixup =
|
MCFixup Fixup =
|
||||||
MCFixup::create(0, Expr, FirstLiteralRelocationKind + ELF::R_LARCH_ALIGN);
|
MCFixup::create(0, Expr, FirstLiteralRelocationKind + ELF::R_LARCH_ALIGN);
|
||||||
F.setVarFixups({Fixup});
|
F.setVarFixups({Fixup});
|
||||||
|
F.setLinkerRelaxable();
|
||||||
F.getParent()->setLinkerRelaxable();
|
F.getParent()->setLinkerRelaxable();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -320,6 +320,7 @@ bool RISCVAsmBackend::relaxAlign(MCFragment &F, unsigned &Size) {
|
|||||||
MCFixup Fixup =
|
MCFixup Fixup =
|
||||||
MCFixup::create(0, Expr, FirstLiteralRelocationKind + ELF::R_RISCV_ALIGN);
|
MCFixup::create(0, Expr, FirstLiteralRelocationKind + ELF::R_RISCV_ALIGN);
|
||||||
F.setVarFixups({Fixup});
|
F.setVarFixups({Fixup});
|
||||||
|
F.setLinkerRelaxable();
|
||||||
F.getParent()->setLinkerRelaxable();
|
F.getParent()->setLinkerRelaxable();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
# CHECK-NEXT:0 Data LinkerRelaxable Size:8 [97,00,00,00,e7,80,00,00]
|
# CHECK-NEXT:0 Data LinkerRelaxable Size:8 [97,00,00,00,e7,80,00,00]
|
||||||
# CHECK-NEXT: Fixup @0 Value:specifier(19,ext) Kind:4023
|
# CHECK-NEXT: Fixup @0 Value:specifier(19,ext) Kind:4023
|
||||||
# CHECK-NEXT: Symbol @0 $x
|
# CHECK-NEXT: Symbol @0 $x
|
||||||
# CHECK-NEXT:8 Align Size:0+4 []
|
# CHECK-NEXT:8 Align LinkerRelaxable Size:0+4 []
|
||||||
# CHECK-NEXT: Align:8 Fill:0 FillLen:1 MaxBytesToEmit:8 Nops
|
# CHECK-NEXT: Align:8 Fill:0 FillLen:1 MaxBytesToEmit:8 Nops
|
||||||
# CHECK-NEXT: Fixup @0 Value:4 Kind:[[#]]
|
# CHECK-NEXT: Fixup @0 Value:4 Kind:[[#]]
|
||||||
# CHECK-NEXT:12 Align Size:4+4 [13,05,30,00]
|
# CHECK-NEXT:12 Align LinkerRelaxable Size:4+4 [13,05,30,00]
|
||||||
# CHECK-NEXT: Align:8 Fill:0 FillLen:1 MaxBytesToEmit:8 Nops
|
# CHECK-NEXT: Align:8 Fill:0 FillLen:1 MaxBytesToEmit:8 Nops
|
||||||
# CHECK-NEXT: Fixup @4 Value:4 Kind:[[#]]
|
# CHECK-NEXT: Fixup @4 Value:4 Kind:[[#]]
|
||||||
# CHECK-NEXT:]
|
# CHECK-NEXT:]
|
||||||
|
@ -154,3 +154,41 @@ data2:
|
|||||||
2:
|
2:
|
||||||
bnez t1, 1b
|
bnez t1, 1b
|
||||||
bnez t1, 2b
|
bnez t1, 2b
|
||||||
|
|
||||||
|
## .text3 with a call at the start
|
||||||
|
# NORELAX-RELOC: .rela.text3a
|
||||||
|
# C-OR-ZCA-EXT-NORELAX-RELOC: .rela.text3a
|
||||||
|
# RELAX-RELOC: .rela.text3a {
|
||||||
|
# RELAX-RELOC-NEXT: 0x0 R_RISCV_CALL_PLT foo 0x0
|
||||||
|
# RELAX-RELOC-NEXT: 0x0 R_RISCV_RELAX - 0x0
|
||||||
|
# RELAX-RELOC-NEXT: 0xC R_RISCV_BRANCH .Ltmp[[#]] 0x0
|
||||||
|
# RELAX-RELOC-NEXT: 0x10 R_RISCV_ALIGN - 0x4
|
||||||
|
# RELAX-RELOC-NEXT: 0x14 R_RISCV_BRANCH .Ltmp[[#]] 0x0
|
||||||
|
# RELAX-RELOC-NEXT: }
|
||||||
|
.section .text3a, "ax"
|
||||||
|
call foo
|
||||||
|
bnez t1, 1f
|
||||||
|
bnez t2, 2f
|
||||||
|
1:
|
||||||
|
.p2align 3
|
||||||
|
2:
|
||||||
|
bnez t1, 1b
|
||||||
|
bnez t1, 2b
|
||||||
|
|
||||||
|
## .text3 with a call at the end
|
||||||
|
# RELAX-RELOC: .rela.text3b {
|
||||||
|
# RELAX-RELOC-NEXT: 0x4 R_RISCV_BRANCH .Ltmp[[#]] 0x0
|
||||||
|
# RELAX-RELOC-NEXT: 0x8 R_RISCV_ALIGN - 0x4
|
||||||
|
# RELAX-RELOC-NEXT: 0xC R_RISCV_BRANCH .Ltmp[[#]] 0x0
|
||||||
|
# RELAX-RELOC-NEXT: 0x14 R_RISCV_CALL_PLT foo 0x0
|
||||||
|
# RELAX-RELOC-NEXT: 0x14 R_RISCV_RELAX - 0x0
|
||||||
|
# RELAX-RELOC-NEXT: }
|
||||||
|
.section .text3b, "ax"
|
||||||
|
bnez t1, 1f
|
||||||
|
bnez t2, 2f
|
||||||
|
1:
|
||||||
|
.p2align 3
|
||||||
|
2:
|
||||||
|
bnez t1, 1b
|
||||||
|
bnez t1, 2b
|
||||||
|
call foo
|
||||||
|
Loading…
x
Reference in New Issue
Block a user