Skip to content

Commit a54985c

Browse files
MaskRaycachemeifyoucan
authored andcommitted
MC: Rework .reloc directive and fix the offset when it evaluates to a constant
* Fix `.reloc constant` to mean section_symbol+constant instead of .+constant . The initial .reloc support from MIPS incorrectly interpreted the offset. * Delay the evaluation of the offset expression after MCAssembler::layout, deleting a lot of code working with MCFragment. * Delete many FIXME from https://reviews.llvm.org/D79625 * Some lld/ELF/Arch/LoongArch.cpp relaxation tests rely on .reloc ., R_LARCH_ALIGN generating ALIGN relocations at specific location. Sort the relocations.
1 parent ed6dae1 commit a54985c

16 files changed

+113
-206
lines changed

lld/ELF/Relocations.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,8 +1671,9 @@ void RelocationScanner::scan(Relocs<RelTy> rels) {
16711671
}
16721672

16731673
// Sort relocations by offset for more efficient searching for
1674-
// R_RISCV_PCREL_HI20, R_PPC64_ADDR64 and the branch-to-branch optimization.
1675-
if (ctx.arg.emachine == EM_RISCV ||
1674+
// R_RISCV_PCREL_HI20, ALIGN relocations, R_PPC64_ADDR64 and the
1675+
// branch-to-branch optimization.
1676+
if (is_contained({EM_RISCV, EM_LOONGARCH}, ctx.arg.emachine) ||
16761677
(ctx.arg.emachine == EM_PPC64 && sec->name == ".toc") ||
16771678
ctx.arg.branchToBranch)
16781679
llvm::stable_sort(sec->relocs(),

llvm/include/llvm/MC/MCAssembler.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ class MCAssembler {
6969

7070
SmallVector<const MCSymbol *, 0> Symbols;
7171

72+
struct RelocDirective {
73+
const MCExpr &Offset;
74+
const MCExpr *Expr;
75+
uint32_t Kind;
76+
};
77+
SmallVector<RelocDirective, 0> relocDirectives;
78+
7279
mutable SmallVector<std::pair<SMLoc, std::string>, 0> PendingErrors;
7380

7481
MCDwarfLineTableParams LTParams;
@@ -205,6 +212,7 @@ class MCAssembler {
205212

206213
LLVM_ABI bool registerSection(MCSection &Section);
207214
LLVM_ABI bool registerSymbol(const MCSymbol &Symbol);
215+
void addRelocDirective(RelocDirective RD);
208216

209217
LLVM_ABI void reportError(SMLoc L, const Twine &Msg) const;
210218
// Record pending errors during layout iteration, as they may go away once the

llvm/include/llvm/MC/MCELFStreamer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ class MCELFStreamer : public MCObjectStreamer {
141141
}
142142

143143
private:
144-
void finalizeCGProfileEntry(const MCSymbolRefExpr *&S, uint64_t Offset);
144+
void finalizeCGProfileEntry(const MCSymbolRefExpr *Sym, uint64_t Offset,
145+
const MCSymbolRefExpr *&S);
145146
void finalizeCGProfile();
146147

147148
bool SeenIdent = false;

llvm/include/llvm/MC/MCObjectStreamer.h

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,6 @@ class MCObjectStreamer : public MCStreamer {
4040
std::unique_ptr<MCAssembler> Assembler;
4141
bool EmitEHFrame;
4242
bool EmitDebugFrame;
43-
struct PendingMCFixup {
44-
const MCSymbol *Sym;
45-
MCFixup Fixup;
46-
MCFragment *DF;
47-
PendingMCFixup(const MCSymbol *McSym, MCFragment *F, MCFixup McFixup)
48-
: Sym(McSym), Fixup(McFixup), DF(F) {}
49-
};
50-
SmallVector<PendingMCFixup, 2> PendingFixups;
5143

5244
struct PendingAssignment {
5345
MCSymbol *Symbol;
@@ -63,7 +55,6 @@ class MCObjectStreamer : public MCStreamer {
6355
void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
6456
void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
6557
void emitInstructionImpl(const MCInst &Inst, const MCSubtargetInfo &STI);
66-
void resolvePendingFixups();
6758

6859
protected:
6960
MCObjectStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
@@ -162,9 +153,8 @@ class MCObjectStreamer : public MCStreamer {
162153
void emitCVStringTableDirective() override;
163154
void emitCVFileChecksumsDirective() override;
164155
void emitCVFileChecksumOffsetDirective(unsigned FileNo) override;
165-
std::optional<std::pair<bool, std::string>>
166-
emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
167-
SMLoc Loc, const MCSubtargetInfo &STI) override;
156+
void emitRelocDirective(const MCExpr &Offset, StringRef Name,
157+
const MCExpr *Expr, SMLoc Loc = {}) override;
168158
using MCStreamer::emitFill;
169159
void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
170160
SMLoc Loc = SMLoc()) override;

llvm/include/llvm/MC/MCStreamer.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,13 +1061,9 @@ class LLVM_ABI MCStreamer {
10611061

10621062
virtual void emitSyntaxDirective();
10631063

1064-
/// Record a relocation described by the .reloc directive. Return std::nullopt
1065-
/// if succeeded. Otherwise, return a pair (Name is invalid, error message).
1066-
virtual std::optional<std::pair<bool, std::string>>
1067-
emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
1068-
SMLoc Loc, const MCSubtargetInfo &STI) {
1069-
return std::nullopt;
1070-
}
1064+
/// Record a relocation described by the .reloc directive.
1065+
virtual void emitRelocDirective(const MCExpr &Offset, StringRef Name,
1066+
const MCExpr *Expr, SMLoc Loc = {}) {}
10711067

10721068
virtual void emitAddrsig() {}
10731069
virtual void emitAddrsigSym(const MCSymbol *Sym) {}

llvm/lib/MC/MCAsmStreamer.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -409,9 +409,8 @@ class MCAsmStreamer final : public MCStreamer {
409409
const MCPseudoProbeInlineStack &InlineStack,
410410
MCSymbol *FnSym) override;
411411

412-
std::optional<std::pair<bool, std::string>>
413-
emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
414-
SMLoc Loc, const MCSubtargetInfo &STI) override;
412+
void emitRelocDirective(const MCExpr &Offset, StringRef Name,
413+
const MCExpr *Expr, SMLoc Loc) override;
415414

416415
void emitAddrsig() override;
417416
void emitAddrsigSym(const MCSymbol *Sym) override;
@@ -2480,10 +2479,8 @@ void MCAsmStreamer::emitPseudoProbe(uint64_t Guid, uint64_t Index,
24802479
EmitEOL();
24812480
}
24822481

2483-
std::optional<std::pair<bool, std::string>>
2484-
MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
2485-
const MCExpr *Expr, SMLoc,
2486-
const MCSubtargetInfo &STI) {
2482+
void MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
2483+
const MCExpr *Expr, SMLoc) {
24872484
OS << "\t.reloc ";
24882485
MAI->printExpr(OS, Offset);
24892486
OS << ", " << Name;
@@ -2492,7 +2489,6 @@ MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
24922489
MAI->printExpr(OS, *Expr);
24932490
}
24942491
EmitEOL();
2495-
return std::nullopt;
24962492
}
24972493

24982494
void MCAsmStreamer::emitAddrsig() {

llvm/lib/MC/MCAssembler.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,10 @@ bool MCAssembler::registerSymbol(const MCSymbol &Symbol) {
398398
return Changed;
399399
}
400400

401+
void MCAssembler::addRelocDirective(RelocDirective RD) {
402+
relocDirectives.push_back(RD);
403+
}
404+
401405
/// Write the fragment \p F to the output file.
402406
static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
403407
const MCFragment &F) {
@@ -695,6 +699,27 @@ void MCAssembler::layout() {
695699
// helps check whether a PC-relative fixup is fully resolved.
696700
this->HasFinalLayout = true;
697701

702+
// Resolve .reloc offsets and add fixups.
703+
for (auto &PF : relocDirectives) {
704+
MCValue Res;
705+
auto &O = PF.Offset;
706+
if (!O.evaluateAsValue(Res, *this)) {
707+
getContext().reportError(O.getLoc(), ".reloc offset is not relocatable");
708+
continue;
709+
}
710+
auto *Sym = Res.getAddSym();
711+
auto *F = Sym ? Sym->getFragment() : nullptr;
712+
auto *Sec = F ? F->getParent() : nullptr;
713+
if (Res.getSubSym() || !Sec) {
714+
getContext().reportError(O.getLoc(),
715+
".reloc offset is not relative to a section");
716+
continue;
717+
}
718+
719+
uint64_t Offset = Sym ? Sym->getOffset() + Res.getConstant() : 0;
720+
F->addFixup(MCFixup::create(Offset, PF.Expr, PF.Kind));
721+
}
722+
698723
// Evaluate and apply the fixups, generating relocation entries as necessary.
699724
for (MCSection &Sec : *this) {
700725
for (MCFragment &F : Sec) {

llvm/lib/MC/MCELFStreamer.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,9 @@ void MCELFStreamer::emitIdent(StringRef IdentString) {
314314
popSection();
315315
}
316316

317-
void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE,
318-
uint64_t Offset) {
317+
void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *Sym,
318+
uint64_t Offset,
319+
const MCSymbolRefExpr *&SRE) {
319320
const MCSymbol *S = &SRE->getSymbol();
320321
if (S->isTemporary()) {
321322
if (!S->isInSection()) {
@@ -328,13 +329,9 @@ void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE,
328329
S->setUsedInReloc();
329330
SRE = MCSymbolRefExpr::create(S, getContext(), SRE->getLoc());
330331
}
331-
const MCConstantExpr *MCOffset = MCConstantExpr::create(Offset, getContext());
332-
if (std::optional<std::pair<bool, std::string>> Err =
333-
MCObjectStreamer::emitRelocDirective(
334-
*MCOffset, "BFD_RELOC_NONE", SRE, SRE->getLoc(),
335-
*getContext().getSubtargetInfo()))
336-
report_fatal_error("Relocation for CG Profile could not be created: " +
337-
Twine(Err->second));
332+
auto *O = MCBinaryExpr::createAdd(
333+
Sym, MCConstantExpr::create(Offset, getContext()), getContext());
334+
MCObjectStreamer::emitRelocDirective(*O, "BFD_RELOC_NONE", SRE);
338335
}
339336

340337
void MCELFStreamer::finalizeCGProfile() {
@@ -347,9 +344,11 @@ void MCELFStreamer::finalizeCGProfile() {
347344
pushSection();
348345
switchSection(CGProfile);
349346
uint64_t Offset = 0;
347+
auto *Sym =
348+
MCSymbolRefExpr::create(CGProfile->getBeginSymbol(), getContext());
350349
for (auto &E : W.getCGProfile()) {
351-
finalizeCGProfileEntry(E.From, Offset);
352-
finalizeCGProfileEntry(E.To, Offset);
350+
finalizeCGProfileEntry(Sym, Offset, E.From);
351+
finalizeCGProfileEntry(Sym, Offset, E.To);
353352
emitIntValue(E.Count, sizeof(uint64_t));
354353
Offset += sizeof(uint64_t);
355354
}

llvm/lib/MC/MCObjectStreamer.cpp

Lines changed: 13 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -46,35 +46,6 @@ MCAssembler *MCObjectStreamer::getAssemblerPtr() {
4646
return nullptr;
4747
}
4848

49-
// When fixup's offset is a forward declared label, e.g.:
50-
//
51-
// .reloc 1f, R_MIPS_JALR, foo
52-
// 1: nop
53-
//
54-
// postpone adding it to Fixups vector until the label is defined and its offset
55-
// is known.
56-
void MCObjectStreamer::resolvePendingFixups() {
57-
for (PendingMCFixup &PendingFixup : PendingFixups) {
58-
if (!PendingFixup.Sym || PendingFixup.Sym->isUndefined ()) {
59-
getContext().reportError(PendingFixup.Fixup.getLoc(),
60-
"unresolved relocation offset");
61-
continue;
62-
}
63-
PendingFixup.Fixup.setOffset(PendingFixup.Sym->getOffset() +
64-
PendingFixup.Fixup.getOffset());
65-
66-
// If the location symbol to relocate is in MCEncodedFragment,
67-
// put the Fixup into location symbol's fragment. Otherwise
68-
// put into PendingFixup.DF
69-
MCFragment *F = PendingFixup.Sym->getFragment();
70-
if (F->isEncoded())
71-
F->addFixup(PendingFixup.Fixup);
72-
else
73-
PendingFixup.DF->addFixup(PendingFixup.Fixup);
74-
}
75-
PendingFixups.clear();
76-
}
77-
7849
// As a compile-time optimization, avoid allocating and evaluating an MCExpr
7950
// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment's fixed
8051
// part.
@@ -607,76 +578,14 @@ void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
607578
insert(getContext().allocFragment<MCOrgFragment>(*Offset, Value, Loc));
608579
}
609580

610-
static std::optional<std::pair<bool, std::string>>
611-
getOffsetAndDataFragment(const MCSymbol &Symbol, uint32_t &RelocOffset,
612-
MCFragment *&DF) {
613-
if (Symbol.isVariable()) {
614-
const MCExpr *SymbolExpr = Symbol.getVariableValue();
615-
MCValue OffsetVal;
616-
if (!SymbolExpr->evaluateAsRelocatable(OffsetVal, nullptr))
617-
return std::make_pair(false,
618-
std::string("symbol in .reloc offset is not "
619-
"relocatable"));
620-
if (OffsetVal.isAbsolute()) {
621-
RelocOffset = OffsetVal.getConstant();
622-
MCFragment *Fragment = Symbol.getFragment();
623-
// FIXME Support symbols with no DF. For example:
624-
// .reloc .data, ENUM_VALUE, <some expr>
625-
if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
626-
return std::make_pair(false,
627-
std::string("symbol in offset has no data "
628-
"fragment"));
629-
DF = cast<MCFragment>(Fragment);
630-
return std::nullopt;
631-
}
632-
633-
if (OffsetVal.getSubSym())
634-
return std::make_pair(false,
635-
std::string(".reloc symbol offset is not "
636-
"representable"));
637-
638-
const MCSymbol &SA = *OffsetVal.getAddSym();
639-
if (!SA.isDefined())
640-
return std::make_pair(false,
641-
std::string("symbol used in the .reloc offset is "
642-
"not defined"));
643-
644-
if (SA.isVariable())
645-
return std::make_pair(false,
646-
std::string("symbol used in the .reloc offset is "
647-
"variable"));
648-
649-
MCFragment *Fragment = SA.getFragment();
650-
// FIXME Support symbols with no DF. For example:
651-
// .reloc .data, ENUM_VALUE, <some expr>
652-
if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
653-
return std::make_pair(false,
654-
std::string("symbol in offset has no data "
655-
"fragment"));
656-
RelocOffset = SA.getOffset() + OffsetVal.getConstant();
657-
DF = cast<MCFragment>(Fragment);
658-
} else {
659-
RelocOffset = Symbol.getOffset();
660-
MCFragment *Fragment = Symbol.getFragment();
661-
// FIXME Support symbols with no DF. For example:
662-
// .reloc .data, ENUM_VALUE, <some expr>
663-
if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
664-
return std::make_pair(false,
665-
std::string("symbol in offset has no data "
666-
"fragment"));
667-
DF = cast<MCFragment>(Fragment);
668-
}
669-
return std::nullopt;
670-
}
671-
672-
std::optional<std::pair<bool, std::string>>
673-
MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
674-
const MCExpr *Expr, SMLoc Loc,
675-
const MCSubtargetInfo &STI) {
581+
void MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
582+
const MCExpr *Expr, SMLoc Loc) {
676583
std::optional<MCFixupKind> MaybeKind =
677584
Assembler->getBackend().getFixupKind(Name);
678-
if (!MaybeKind)
679-
return std::make_pair(true, std::string("unknown relocation name"));
585+
if (!MaybeKind) {
586+
getContext().reportError(Loc, "unknown relocation name");
587+
return;
588+
}
680589

681590
MCFixupKind Kind = *MaybeKind;
682591
if (Expr)
@@ -685,38 +594,14 @@ MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
685594
Expr =
686595
MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext());
687596

688-
MCFragment *DF = getOrCreateDataFragment(&STI);
689-
MCValue OffsetVal;
690-
if (!Offset.evaluateAsRelocatable(OffsetVal, nullptr))
691-
return std::make_pair(false,
692-
std::string(".reloc offset is not relocatable"));
693-
if (OffsetVal.isAbsolute()) {
694-
if (OffsetVal.getConstant() < 0)
695-
return std::make_pair(false, std::string(".reloc offset is negative"));
696-
DF->addFixup(MCFixup::create(OffsetVal.getConstant(), Expr, Kind));
697-
return std::nullopt;
698-
}
699-
if (OffsetVal.getSubSym())
700-
return std::make_pair(false,
701-
std::string(".reloc offset is not representable"));
702-
703-
const MCSymbol &Symbol = *OffsetVal.getAddSym();
704-
if (Symbol.isDefined()) {
705-
uint32_t SymbolOffset = 0;
706-
std::optional<std::pair<bool, std::string>> Error =
707-
getOffsetAndDataFragment(Symbol, SymbolOffset, DF);
708-
709-
if (Error != std::nullopt)
710-
return Error;
711-
712-
DF->addFixup(
713-
MCFixup::create(SymbolOffset + OffsetVal.getConstant(), Expr, Kind));
714-
return std::nullopt;
597+
auto *O = &Offset;
598+
int64_t Val;
599+
if (Offset.evaluateAsAbsolute(Val, nullptr)) {
600+
auto *SecSym = getCurrentSectionOnly()->getBeginSymbol();
601+
O = MCBinaryExpr::createAdd(MCSymbolRefExpr::create(SecSym, getContext()),
602+
O, getContext(), Loc);
715603
}
716-
717-
PendingFixups.emplace_back(
718-
&Symbol, DF, MCFixup::create(OffsetVal.getConstant(), Expr, Kind));
719-
return std::nullopt;
604+
getAssembler().addRelocDirective({*O, Expr, Kind});
720605
}
721606

722607
void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
@@ -799,6 +684,5 @@ void MCObjectStreamer::finishImpl() {
799684
// Emit pseudo probes for the current module.
800685
MCPseudoProbeTable::emit(this);
801686

802-
resolvePendingFixups();
803687
getAssembler().Finish();
804688
}

0 commit comments

Comments
 (0)