Skip to content

Commit c04f5f7

Browse files
author
git apple-llvm automerger
committed
Merge commit '08289ad13a7d' from llvm.org/release/21.x into stable/21.x
2 parents ca4f219 + 08289ad commit c04f5f7

File tree

8 files changed

+160
-15
lines changed

8 files changed

+160
-15
lines changed

llvm/lib/MC/MCExpr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,9 @@ static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm,
361361
if (BBeforeRelax && AAfterRelax)
362362
return;
363363
}
364+
const auto *RF = dyn_cast<MCRelaxableFragment>(F);
365+
if (RF && RF->isLinkerRelaxable())
366+
return;
364367
if (&*F == FA) {
365368
// If FA and FB belong to the same subsection, the loop will find FA and
366369
// we can resolve the difference.

llvm/lib/MC/MCFragment.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
7070
OS << "\n Fixup @" << F.getOffset() << " Value:";
7171
F.getValue()->print(OS, nullptr);
7272
OS << " Kind:" << F.getKind();
73+
if (F.isLinkerRelaxable())
74+
OS << " LinkerRelaxable";
7375
}
7476
};
7577

@@ -113,6 +115,8 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
113115
}
114116
case MCFragment::FT_Relaxable: {
115117
const auto *F = cast<MCRelaxableFragment>(this);
118+
if (F->isLinkerRelaxable())
119+
OS << " LinkerRelaxable";
116120
OS << " Size:" << F->getContents().size() << ' ';
117121
F->getInst().dump_pretty(OS);
118122
printFixups(F->getFixups());

llvm/lib/MC/MCObjectStreamer.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,13 @@ void MCObjectStreamer::emitInstToFragment(const MCInst &Inst,
408408
Inst, IF->getContentsForAppending(), Fixups, STI);
409409
IF->doneAppending();
410410
IF->appendFixups(Fixups);
411+
412+
for (auto &Fixup : Fixups) {
413+
if (Fixup.isLinkerRelaxable()) {
414+
IF->setLinkerRelaxable();
415+
getCurrentSectionOnly()->setLinkerRelaxable();
416+
}
417+
}
411418
}
412419

413420
#ifndef NDEBUG

llvm/lib/MC/MCSection.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ LLVM_DUMP_METHOD void MCSection::dump(
6363
raw_ostream &OS = errs();
6464

6565
OS << "MCSection Name:" << getName();
66+
if (isLinkerRelaxable())
67+
OS << " LinkerRelaxable";
6668
for (auto &F : *this) {
6769
OS << '\n';
6870
F.dump();

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

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,23 @@ void RISCVAsmBackend::maybeAddVendorReloc(const MCFragment &F,
792792
Asm->getWriter().recordRelocation(F, VendorFixup, VendorTarget, VendorValue);
793793
}
794794

795+
static bool relaxableFixupNeedsRelocation(const MCFixupKind Kind) {
796+
// Some Fixups are marked as LinkerRelaxable by
797+
// `RISCVMCCodeEmitter::getImmOpValue` only because they may be
798+
// (assembly-)relaxed into a linker-relaxable instruction. This function
799+
// should return `false` for those fixups so they do not get a `R_RISCV_RELAX`
800+
// relocation emitted in addition to the relocation.
801+
switch (Kind) {
802+
default:
803+
break;
804+
case RISCV::fixup_riscv_rvc_jump:
805+
case RISCV::fixup_riscv_rvc_branch:
806+
case RISCV::fixup_riscv_jal:
807+
return false;
808+
}
809+
return true;
810+
}
811+
795812
bool RISCVAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup,
796813
const MCValue &Target, uint64_t &FixedValue,
797814
bool IsResolved) {
@@ -834,25 +851,32 @@ bool RISCVAsmBackend::addReloc(const MCFragment &F, const MCFixup &Fixup,
834851
return false;
835852
}
836853

837-
// If linker relaxation is enabled and supported by the current relocation,
838-
// generate a relocation and then append a RELAX.
839-
if (Fixup.isLinkerRelaxable())
854+
// If linker relaxation is enabled and supported by the current fixup, then we
855+
// always want to generate a relocation.
856+
bool NeedsRelax = Fixup.isLinkerRelaxable() &&
857+
relaxableFixupNeedsRelocation(Fixup.getKind());
858+
if (NeedsRelax)
840859
IsResolved = false;
860+
841861
if (IsResolved && Fixup.isPCRel())
842862
IsResolved = isPCRelFixupResolved(Target.getAddSym(), F);
843863

844864
if (!IsResolved) {
845-
// Some Fixups require a vendor relocation, record it (directly) before we
865+
// Some Fixups require a VENDOR relocation, record it (directly) before we
846866
// add the relocation.
847867
maybeAddVendorReloc(F, Fixup);
848868

849869
Asm->getWriter().recordRelocation(F, Fixup, Target, FixedValue);
850-
}
851870

852-
if (Fixup.isLinkerRelaxable()) {
853-
auto FA = MCFixup::create(Fixup.getOffset(), nullptr, ELF::R_RISCV_RELAX);
854-
Asm->getWriter().recordRelocation(F, FA, MCValue::get(nullptr),
855-
FixedValueA);
871+
if (NeedsRelax) {
872+
// Some Fixups get a RELAX relocation, record it (directly) after we add
873+
// the relocation.
874+
MCFixup RelaxFixup =
875+
MCFixup::create(Fixup.getOffset(), nullptr, ELF::R_RISCV_RELAX);
876+
MCValue RelaxTarget = MCValue::get(nullptr);
877+
uint64_t RelaxValue;
878+
Asm->getWriter().recordRelocation(F, RelaxFixup, RelaxTarget, RelaxValue);
879+
}
856880
}
857881

858882
return false;

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

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -576,8 +576,21 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
576576
"getImmOpValue expects only expressions or immediates");
577577
const MCExpr *Expr = MO.getExpr();
578578
MCExpr::ExprKind Kind = Expr->getKind();
579-
unsigned FixupKind = RISCV::fixup_riscv_invalid;
579+
580+
// `RelaxCandidate` must be set to `true` in two cases:
581+
// - The fixup's relocation gets a R_RISCV_RELAX relocation
582+
// - The underlying instruction may be relaxed to an instruction that gets a
583+
// `R_RISCV_RELAX` relocation.
584+
//
585+
// The actual emission of `R_RISCV_RELAX` will be handled in
586+
// `RISCVAsmBackend::applyFixup`.
580587
bool RelaxCandidate = false;
588+
auto AsmRelaxToLinkerRelaxableWithFeature = [&](unsigned Feature) -> void {
589+
if (!STI.hasFeature(RISCV::FeatureExactAssembly) && STI.hasFeature(Feature))
590+
RelaxCandidate = true;
591+
};
592+
593+
unsigned FixupKind = RISCV::fixup_riscv_invalid;
581594
if (Kind == MCExpr::Specifier) {
582595
const auto *RVExpr = cast<MCSpecifierExpr>(Expr);
583596
FixupKind = RVExpr->getSpecifier();
@@ -644,18 +657,26 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
644657
// FIXME: Sub kind binary exprs have chance of underflow.
645658
if (MIFrm == RISCVII::InstFormatJ) {
646659
FixupKind = RISCV::fixup_riscv_jal;
660+
AsmRelaxToLinkerRelaxableWithFeature(RISCV::FeatureVendorXqcilb);
647661
} else if (MIFrm == RISCVII::InstFormatB) {
648662
FixupKind = RISCV::fixup_riscv_branch;
663+
// This might be assembler relaxed to `b<cc>; jal` but we cannot relax
664+
// the `jal` again in the assembler.
649665
} else if (MIFrm == RISCVII::InstFormatCJ) {
650666
FixupKind = RISCV::fixup_riscv_rvc_jump;
667+
AsmRelaxToLinkerRelaxableWithFeature(RISCV::FeatureVendorXqcilb);
651668
} else if (MIFrm == RISCVII::InstFormatCB) {
652669
FixupKind = RISCV::fixup_riscv_rvc_branch;
670+
// This might be assembler relaxed to `b<cc>; jal` but we cannot relax
671+
// the `jal` again in the assembler.
653672
} else if (MIFrm == RISCVII::InstFormatCI) {
654673
FixupKind = RISCV::fixup_riscv_rvc_imm;
655674
} else if (MIFrm == RISCVII::InstFormatI) {
656675
FixupKind = RISCV::fixup_riscv_12_i;
657676
} else if (MIFrm == RISCVII::InstFormatQC_EB) {
658677
FixupKind = RISCV::fixup_riscv_qc_e_branch;
678+
// This might be assembler relaxed to `qc.e.b<cc>; jal` but we cannot
679+
// relax the `jal` again in the assembler.
659680
} else if (MIFrm == RISCVII::InstFormatQC_EAI) {
660681
FixupKind = RISCV::fixup_riscv_qc_e_32;
661682
RelaxCandidate = true;
@@ -670,9 +691,9 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
670691
assert(FixupKind != RISCV::fixup_riscv_invalid && "Unhandled expression!");
671692

672693
addFixup(Fixups, 0, Expr, FixupKind);
673-
// If linker relaxation is enabled and supported by this relocation, set
674-
// a bit so that if fixup is unresolved, a R_RISCV_RELAX relocation will be
675-
// appended.
694+
// If linker relaxation is enabled and supported by this relocation, set a bit
695+
// so that the assembler knows the size of the instruction is not fixed/known,
696+
// and the relocation will need a R_RISCV_RELAX relocation.
676697
if (EnableRelax && RelaxCandidate)
677698
Fixups.back().setLinkerRelaxable();
678699
++MCNumFixups;

llvm/test/MC/RISCV/Relocations/mc-dump.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
# RUN: llvm-mc -filetype=obj --triple=riscv64 --mattr=+relax %s -debug-only=mc-dump -o /dev/null 2>&1 | FileCheck %s
33

44
# CHECK:Sections:[
5-
# CHECK-NEXT:MCSection Name:.text
5+
# CHECK-NEXT:MCSection Name:.text LinkerRelaxable
66
# CHECK-NEXT:0 Data Size:0 []
77
# CHECK-NEXT: Symbol @0 .text
88
# CHECK-NEXT:0 Align Align:4 Fill:0 FillLen:1 MaxBytesToEmit:4 Nops
99
# CHECK-NEXT:0 Data LinkerRelaxable Size:8 [97,00,00,00,e7,80,00,00]
10-
# CHECK-NEXT: Fixup @0 Value:specifier(19,ext) Kind:4023
10+
# CHECK-NEXT: Fixup @0 Value:specifier(19,ext) Kind:4023 LinkerRelaxable
1111
# CHECK-NEXT: Symbol @0 $x
1212
# CHECK-NEXT:8 Align Align:8 Fill:0 FillLen:1 MaxBytesToEmit:8 Nops
1313
# CHECK-NEXT:12 Data Size:4 [13,05,30,00]
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# RUN: llvm-mc --triple=riscv32 -mattr=+relax,+experimental-xqcilb,+experimental-xqcibi \
2+
# RUN: %s -filetype=obj -o - -riscv-add-build-attributes \
3+
# RUN: | llvm-objdump -dr -M no-aliases - \
4+
# RUN: | FileCheck %s
5+
6+
## This tests that we correctly emit relocations for linker relaxation when
7+
## relaxing `JAL` to `QC.E.JAL`.
8+
9+
## PR150071
10+
11+
.global foo
12+
13+
# CHECK-LABEL: <branch_over_relaxable>:
14+
branch_over_relaxable:
15+
jal x1, foo
16+
# CHECK: qc.e.jal 0x0 <branch_over_relaxable>
17+
# CHECK-NEXT: R_RISCV_VENDOR QUALCOMM
18+
# CHECK-NEXT: R_RISCV_CUSTOM195 foo
19+
# CHECK-NEXT: R_RISCV_RELAX *ABS*
20+
bne a0, a1, branch_over_relaxable
21+
# CHECK-NEXT: bne a0, a1, 0x6 <branch_over_relaxable+0x6>
22+
# CHECK-NEXT: R_RISCV_BRANCH branch_over_relaxable
23+
# CHECK-NOT: R_RISCV_RELAX
24+
qc.e.bnei a0, 0x21, branch_over_relaxable
25+
# CHECK-NEXT: qc.e.bnei a0, 0x21, 0xa <branch_over_relaxable+0xa>
26+
# CHECK-NEXT: R_RISCV_VENDOR QUALCOMM
27+
# CHECK-NEXT: R_RISCV_CUSTOM193 branch_over_relaxable
28+
# CHECK-NOT: R_RISCV_RELAX
29+
ret
30+
# CHECK-NEXT: c.jr ra
31+
32+
# CHECK-LABEL: <short_jump_over_fixed>:
33+
short_jump_over_fixed:
34+
nop
35+
# CHECK: c.nop
36+
j short_jump_over_fixed
37+
# CHECK-NEXT: c.j 0x14 <short_jump_over_fixed+0x2>
38+
# CHECK-NEXT: R_RISCV_RVC_JUMP short_jump_over_fixed
39+
# CHECK-NOT: R_RISCV_RELAX
40+
ret
41+
# CHECK-NEXT: c.jr ra
42+
43+
# CHECK-LABEL: <short_jump_over_relaxable>:
44+
short_jump_over_relaxable:
45+
call foo
46+
# CHECK: auipc ra, 0x0
47+
# CHECK-NEXT: R_RISCV_CALL_PLT foo
48+
# CHECK-NEXT: R_RISCV_RELAX *ABS*
49+
# CHECK-NEXT: jalr ra, 0x0(ra) <short_jump_over_relaxable>
50+
j short_jump_over_relaxable
51+
# CHECK-NEXT: c.j 0x20 <short_jump_over_relaxable+0x8>
52+
# CHECK-NEXT: R_RISCV_RVC_JUMP short_jump_over_relaxable
53+
# CHECK-NOT: R_RISCV_RELAX
54+
ret
55+
# CHECK-NEXT: c.jr ra
56+
57+
# CHECK-LABEL: <mid_jump_over_fixed>:
58+
mid_jump_over_fixed:
59+
nop
60+
# CHECK: c.nop
61+
.space 0x1000
62+
# CHECK-NEXT: ...
63+
j mid_jump_over_fixed
64+
# CHECK-NEXT: jal zero, 0x1026 <mid_jump_over_fixed+0x1002>
65+
# CHECK-NEXT: R_RISCV_JAL mid_jump_over_fixed
66+
# CHECK-NOT: R_RISCV_RELAX
67+
ret
68+
# CHECK-NEXT: c.jr ra
69+
70+
# CHECK-LABEL: <mid_jump_over_relaxable>:
71+
mid_jump_over_relaxable:
72+
call foo
73+
# CHECK: auipc ra, 0x0
74+
# CHECK-NEXT: R_RISCV_CALL_PLT foo
75+
# CHECK-NEXT: R_RISCV_RELAX *ABS*
76+
# CHECK-NEXT: jalr ra, 0x0(ra) <mid_jump_over_relaxable>
77+
.space 0x1000
78+
# CHECK-NEXT: ...
79+
j mid_jump_over_relaxable
80+
# CHECK-NEXT: jal zero, 0x2034 <mid_jump_over_relaxable+0x1008>
81+
# CHECK-NEXT: R_RISCV_JAL mid_jump_over_relaxable
82+
# CHECK-NOT: R_RISCV_RELAX
83+
ret
84+
# CHECK-NEXT: c.jr ra

0 commit comments

Comments
 (0)