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;
|
||||
}
|
||||
|
||||
// Track whether B is before a relaxable instruction and whether A is after
|
||||
// a relaxable instruction. If SA and SB are separated by a linker-relaxable
|
||||
// instruction, the difference cannot be resolved as it may be changed by
|
||||
// the linker.
|
||||
// Track whether B is before a relaxable instruction/alignment and whether A
|
||||
// is after a relaxable instruction/alignment. If SA and SB are separated by
|
||||
// a linker-relaxable instruction/alignment, the difference cannot be
|
||||
// resolved as it may be changed by the linker.
|
||||
bool BBeforeRelax = false, AAfterRelax = false;
|
||||
for (auto F = FB; F; F = F->getNext()) {
|
||||
auto DF = F->getKind() == MCFragment::FT_Data ? F : nullptr;
|
||||
if (DF && DF->isLinkerRelaxable()) {
|
||||
if (&*F != FB || SBOffset != DF->getContents().size())
|
||||
if (F && F->isLinkerRelaxable()) {
|
||||
if (&*F != FB || SBOffset != F->getSize())
|
||||
BBeforeRelax = true;
|
||||
if (&*F != FA || SAOffset == DF->getContents().size())
|
||||
if (&*F != FA || SAOffset == F->getSize())
|
||||
AAfterRelax = true;
|
||||
if (BBeforeRelax && AAfterRelax)
|
||||
return;
|
||||
@ -370,17 +369,15 @@ static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm,
|
||||
}
|
||||
|
||||
int64_t Num;
|
||||
if (DF) {
|
||||
Displacement += DF->getContents().size();
|
||||
} else if (F->getKind() == MCFragment::FT_Relaxable &&
|
||||
if (F->getKind() == MCFragment::FT_Data) {
|
||||
Displacement += F->getFixedSize();
|
||||
} else if ((F->getKind() == MCFragment::FT_Relaxable ||
|
||||
F->getKind() == MCFragment::FT_Align) &&
|
||||
Asm->hasFinalLayout()) {
|
||||
// Before finishLayout, a relaxable fragment's size is indeterminate.
|
||||
// After layout, during relocation generation, it can be treated as a
|
||||
// data fragment.
|
||||
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);
|
||||
FF && FF->getNumValues().evaluateAsAbsolute(Num)) {
|
||||
Displacement += Num * FF->getValueSize();
|
||||
|
@ -254,6 +254,7 @@ bool LoongArchAsmBackend::relaxAlign(MCFragment &F, unsigned &Size) {
|
||||
MCFixup Fixup =
|
||||
MCFixup::create(0, Expr, FirstLiteralRelocationKind + ELF::R_LARCH_ALIGN);
|
||||
F.setVarFixups({Fixup});
|
||||
F.setLinkerRelaxable();
|
||||
F.getParent()->setLinkerRelaxable();
|
||||
return true;
|
||||
}
|
||||
|
@ -320,6 +320,7 @@ bool RISCVAsmBackend::relaxAlign(MCFragment &F, unsigned &Size) {
|
||||
MCFixup Fixup =
|
||||
MCFixup::create(0, Expr, FirstLiteralRelocationKind + ELF::R_RISCV_ALIGN);
|
||||
F.setVarFixups({Fixup});
|
||||
F.setLinkerRelaxable();
|
||||
F.getParent()->setLinkerRelaxable();
|
||||
return true;
|
||||
}
|
||||
|
@ -9,10 +9,10 @@
|
||||
# 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: 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: 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: Fixup @4 Value:4 Kind:[[#]]
|
||||
# CHECK-NEXT:]
|
||||
|
@ -154,3 +154,41 @@ data2:
|
||||
2:
|
||||
bnez t1, 1b
|
||||
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