[lld] 3cb0c7f - MC: Rework .reloc directive and fix the offset when it evaluates to a constant
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 17 00:36:16 PDT 2025
Author: Fangrui Song
Date: 2025-07-17T00:36:11-07:00
New Revision: 3cb0c7f45b97802ddc13a15560fbbca2efb75326
URL: https://github.com/llvm/llvm-project/commit/3cb0c7f45b97802ddc13a15560fbbca2efb75326
DIFF: https://github.com/llvm/llvm-project/commit/3cb0c7f45b97802ddc13a15560fbbca2efb75326.diff
LOG: 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.
Added:
Modified:
lld/ELF/Relocations.cpp
llvm/include/llvm/MC/MCAssembler.h
llvm/include/llvm/MC/MCELFStreamer.h
llvm/include/llvm/MC/MCObjectStreamer.h
llvm/include/llvm/MC/MCStreamer.h
llvm/lib/MC/MCAsmStreamer.cpp
llvm/lib/MC/MCAssembler.cpp
llvm/lib/MC/MCELFStreamer.cpp
llvm/lib/MC/MCObjectStreamer.cpp
llvm/lib/MC/MCParser/AsmParser.cpp
llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
llvm/lib/Target/Mips/MipsAsmPrinter.cpp
llvm/test/MC/ELF/reloc-directive.s
llvm/test/MC/Mips/reloc-directive-bad-obj.s
llvm/test/MC/Mips/reloc-directive-label-offset.s
Removed:
################################################################################
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index cebd564036b2c..4333b032c9d4e 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1671,8 +1671,9 @@ void RelocationScanner::scan(Relocs<RelTy> rels) {
}
// Sort relocations by offset for more efficient searching for
- // R_RISCV_PCREL_HI20, R_PPC64_ADDR64 and the branch-to-branch optimization.
- if (ctx.arg.emachine == EM_RISCV ||
+ // R_RISCV_PCREL_HI20, ALIGN relocations, R_PPC64_ADDR64 and the
+ // branch-to-branch optimization.
+ if (is_contained({EM_RISCV, EM_LOONGARCH}, ctx.arg.emachine) ||
(ctx.arg.emachine == EM_PPC64 && sec->name == ".toc") ||
ctx.arg.branchToBranch)
llvm::stable_sort(sec->relocs(),
diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h
index aa396efa9f018..ade9ee6fa56e0 100644
--- a/llvm/include/llvm/MC/MCAssembler.h
+++ b/llvm/include/llvm/MC/MCAssembler.h
@@ -69,6 +69,13 @@ class MCAssembler {
SmallVector<const MCSymbol *, 0> Symbols;
+ struct RelocDirective {
+ const MCExpr &Offset;
+ const MCExpr *Expr;
+ uint32_t Kind;
+ };
+ SmallVector<RelocDirective, 0> relocDirectives;
+
mutable SmallVector<std::pair<SMLoc, std::string>, 0> PendingErrors;
MCDwarfLineTableParams LTParams;
@@ -205,6 +212,7 @@ class MCAssembler {
LLVM_ABI bool registerSection(MCSection &Section);
LLVM_ABI bool registerSymbol(const MCSymbol &Symbol);
+ void addRelocDirective(RelocDirective RD);
LLVM_ABI void reportError(SMLoc L, const Twine &Msg) const;
// Record pending errors during layout iteration, as they may go away once the
diff --git a/llvm/include/llvm/MC/MCELFStreamer.h b/llvm/include/llvm/MC/MCELFStreamer.h
index ad0961c8bcf97..144f6bc3bd91c 100644
--- a/llvm/include/llvm/MC/MCELFStreamer.h
+++ b/llvm/include/llvm/MC/MCELFStreamer.h
@@ -141,7 +141,8 @@ class MCELFStreamer : public MCObjectStreamer {
}
private:
- void finalizeCGProfileEntry(const MCSymbolRefExpr *&S, uint64_t Offset);
+ void finalizeCGProfileEntry(const MCSymbolRefExpr *Sym, uint64_t Offset,
+ const MCSymbolRefExpr *&S);
void finalizeCGProfile();
bool SeenIdent = false;
diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h
index e2a77b809b6ca..a55fd4a14675f 100644
--- a/llvm/include/llvm/MC/MCObjectStreamer.h
+++ b/llvm/include/llvm/MC/MCObjectStreamer.h
@@ -40,14 +40,6 @@ class MCObjectStreamer : public MCStreamer {
std::unique_ptr<MCAssembler> Assembler;
bool EmitEHFrame;
bool EmitDebugFrame;
- struct PendingMCFixup {
- const MCSymbol *Sym;
- MCFixup Fixup;
- MCFragment *DF;
- PendingMCFixup(const MCSymbol *McSym, MCFragment *F, MCFixup McFixup)
- : Sym(McSym), Fixup(McFixup), DF(F) {}
- };
- SmallVector<PendingMCFixup, 2> PendingFixups;
struct PendingAssignment {
MCSymbol *Symbol;
@@ -63,7 +55,6 @@ class MCObjectStreamer : public MCStreamer {
void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
void emitInstructionImpl(const MCInst &Inst, const MCSubtargetInfo &STI);
- void resolvePendingFixups();
protected:
MCObjectStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
@@ -162,9 +153,8 @@ class MCObjectStreamer : public MCStreamer {
void emitCVStringTableDirective() override;
void emitCVFileChecksumsDirective() override;
void emitCVFileChecksumOffsetDirective(unsigned FileNo) override;
- std::optional<std::pair<bool, std::string>>
- emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
- SMLoc Loc, const MCSubtargetInfo &STI) override;
+ void emitRelocDirective(const MCExpr &Offset, StringRef Name,
+ const MCExpr *Expr, SMLoc Loc = {}) override;
using MCStreamer::emitFill;
void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
SMLoc Loc = SMLoc()) override;
diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index 1f7c8b57540a7..b3a9aabd6ece5 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -1048,13 +1048,9 @@ class LLVM_ABI MCStreamer {
virtual void emitSyntaxDirective();
- /// Record a relocation described by the .reloc directive. Return std::nullopt
- /// if succeeded. Otherwise, return a pair (Name is invalid, error message).
- virtual std::optional<std::pair<bool, std::string>>
- emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
- SMLoc Loc, const MCSubtargetInfo &STI) {
- return std::nullopt;
- }
+ /// Record a relocation described by the .reloc directive.
+ virtual void emitRelocDirective(const MCExpr &Offset, StringRef Name,
+ const MCExpr *Expr, SMLoc Loc = {}) {}
virtual void emitAddrsig() {}
virtual void emitAddrsigSym(const MCSymbol *Sym) {}
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 3a330dbfec342..67c53e01a6111 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -407,9 +407,8 @@ class MCAsmStreamer final : public MCStreamer {
const MCPseudoProbeInlineStack &InlineStack,
MCSymbol *FnSym) override;
- std::optional<std::pair<bool, std::string>>
- emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
- SMLoc Loc, const MCSubtargetInfo &STI) override;
+ void emitRelocDirective(const MCExpr &Offset, StringRef Name,
+ const MCExpr *Expr, SMLoc Loc) override;
void emitAddrsig() override;
void emitAddrsigSym(const MCSymbol *Sym) override;
@@ -2468,10 +2467,8 @@ void MCAsmStreamer::emitPseudoProbe(uint64_t Guid, uint64_t Index,
EmitEOL();
}
-std::optional<std::pair<bool, std::string>>
-MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
- const MCExpr *Expr, SMLoc,
- const MCSubtargetInfo &STI) {
+void MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
+ const MCExpr *Expr, SMLoc) {
OS << "\t.reloc ";
MAI->printExpr(OS, Offset);
OS << ", " << Name;
@@ -2480,7 +2477,6 @@ MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
MAI->printExpr(OS, *Expr);
}
EmitEOL();
- return std::nullopt;
}
void MCAsmStreamer::emitAddrsig() {
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index d4d10e0cd74a5..f1a82f6b08d31 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -398,6 +398,10 @@ bool MCAssembler::registerSymbol(const MCSymbol &Symbol) {
return Changed;
}
+void MCAssembler::addRelocDirective(RelocDirective RD) {
+ relocDirectives.push_back(RD);
+}
+
/// Write the fragment \p F to the output file.
static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
const MCFragment &F) {
@@ -695,6 +699,27 @@ void MCAssembler::layout() {
// helps check whether a PC-relative fixup is fully resolved.
this->HasFinalLayout = true;
+ // Resolve .reloc offsets and add fixups.
+ for (auto &PF : relocDirectives) {
+ MCValue Res;
+ auto &O = PF.Offset;
+ if (!O.evaluateAsValue(Res, *this)) {
+ getContext().reportError(O.getLoc(), ".reloc offset is not relocatable");
+ continue;
+ }
+ auto *Sym = Res.getAddSym();
+ auto *F = Sym ? Sym->getFragment() : nullptr;
+ auto *Sec = F ? F->getParent() : nullptr;
+ if (Res.getSubSym() || !Sec) {
+ getContext().reportError(O.getLoc(),
+ ".reloc offset is not relative to a section");
+ continue;
+ }
+
+ uint64_t Offset = Sym ? Sym->getOffset() + Res.getConstant() : 0;
+ F->addFixup(MCFixup::create(Offset, PF.Expr, PF.Kind));
+ }
+
// Evaluate and apply the fixups, generating relocation entries as necessary.
for (MCSection &Sec : *this) {
for (MCFragment &F : Sec) {
diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index ffc57227cff16..49071bdec3dbd 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -314,8 +314,9 @@ void MCELFStreamer::emitIdent(StringRef IdentString) {
popSection();
}
-void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE,
- uint64_t Offset) {
+void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *Sym,
+ uint64_t Offset,
+ const MCSymbolRefExpr *&SRE) {
const MCSymbol *S = &SRE->getSymbol();
if (S->isTemporary()) {
if (!S->isInSection()) {
@@ -328,13 +329,9 @@ void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE,
S->setUsedInReloc();
SRE = MCSymbolRefExpr::create(S, getContext(), SRE->getLoc());
}
- const MCConstantExpr *MCOffset = MCConstantExpr::create(Offset, getContext());
- if (std::optional<std::pair<bool, std::string>> Err =
- MCObjectStreamer::emitRelocDirective(
- *MCOffset, "BFD_RELOC_NONE", SRE, SRE->getLoc(),
- *getContext().getSubtargetInfo()))
- report_fatal_error("Relocation for CG Profile could not be created: " +
- Twine(Err->second));
+ auto *O = MCBinaryExpr::createAdd(
+ Sym, MCConstantExpr::create(Offset, getContext()), getContext());
+ MCObjectStreamer::emitRelocDirective(*O, "BFD_RELOC_NONE", SRE);
}
void MCELFStreamer::finalizeCGProfile() {
@@ -347,9 +344,11 @@ void MCELFStreamer::finalizeCGProfile() {
pushSection();
switchSection(CGProfile);
uint64_t Offset = 0;
+ auto *Sym =
+ MCSymbolRefExpr::create(CGProfile->getBeginSymbol(), getContext());
for (auto &E : W.getCGProfile()) {
- finalizeCGProfileEntry(E.From, Offset);
- finalizeCGProfileEntry(E.To, Offset);
+ finalizeCGProfileEntry(Sym, Offset, E.From);
+ finalizeCGProfileEntry(Sym, Offset, E.To);
emitIntValue(E.Count, sizeof(uint64_t));
Offset += sizeof(uint64_t);
}
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index c0cef0f06c57a..67433f2b265e5 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -46,35 +46,6 @@ MCAssembler *MCObjectStreamer::getAssemblerPtr() {
return nullptr;
}
-// When fixup's offset is a forward declared label, e.g.:
-//
-// .reloc 1f, R_MIPS_JALR, foo
-// 1: nop
-//
-// postpone adding it to Fixups vector until the label is defined and its offset
-// is known.
-void MCObjectStreamer::resolvePendingFixups() {
- for (PendingMCFixup &PendingFixup : PendingFixups) {
- if (!PendingFixup.Sym || PendingFixup.Sym->isUndefined ()) {
- getContext().reportError(PendingFixup.Fixup.getLoc(),
- "unresolved relocation offset");
- continue;
- }
- PendingFixup.Fixup.setOffset(PendingFixup.Sym->getOffset() +
- PendingFixup.Fixup.getOffset());
-
- // If the location symbol to relocate is in MCEncodedFragment,
- // put the Fixup into location symbol's fragment. Otherwise
- // put into PendingFixup.DF
- MCFragment *F = PendingFixup.Sym->getFragment();
- if (F->isEncoded())
- F->addFixup(PendingFixup.Fixup);
- else
- PendingFixup.DF->addFixup(PendingFixup.Fixup);
- }
- PendingFixups.clear();
-}
-
// As a compile-time optimization, avoid allocating and evaluating an MCExpr
// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment's fixed
// part.
@@ -607,76 +578,14 @@ void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
insert(getContext().allocFragment<MCOrgFragment>(*Offset, Value, Loc));
}
-static std::optional<std::pair<bool, std::string>>
-getOffsetAndDataFragment(const MCSymbol &Symbol, uint32_t &RelocOffset,
- MCFragment *&DF) {
- if (Symbol.isVariable()) {
- const MCExpr *SymbolExpr = Symbol.getVariableValue();
- MCValue OffsetVal;
- if (!SymbolExpr->evaluateAsRelocatable(OffsetVal, nullptr))
- return std::make_pair(false,
- std::string("symbol in .reloc offset is not "
- "relocatable"));
- if (OffsetVal.isAbsolute()) {
- RelocOffset = OffsetVal.getConstant();
- MCFragment *Fragment = Symbol.getFragment();
- // FIXME Support symbols with no DF. For example:
- // .reloc .data, ENUM_VALUE, <some expr>
- if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
- return std::make_pair(false,
- std::string("symbol in offset has no data "
- "fragment"));
- DF = cast<MCFragment>(Fragment);
- return std::nullopt;
- }
-
- if (OffsetVal.getSubSym())
- return std::make_pair(false,
- std::string(".reloc symbol offset is not "
- "representable"));
-
- const MCSymbol &SA = *OffsetVal.getAddSym();
- if (!SA.isDefined())
- return std::make_pair(false,
- std::string("symbol used in the .reloc offset is "
- "not defined"));
-
- if (SA.isVariable())
- return std::make_pair(false,
- std::string("symbol used in the .reloc offset is "
- "variable"));
-
- MCFragment *Fragment = SA.getFragment();
- // FIXME Support symbols with no DF. For example:
- // .reloc .data, ENUM_VALUE, <some expr>
- if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
- return std::make_pair(false,
- std::string("symbol in offset has no data "
- "fragment"));
- RelocOffset = SA.getOffset() + OffsetVal.getConstant();
- DF = cast<MCFragment>(Fragment);
- } else {
- RelocOffset = Symbol.getOffset();
- MCFragment *Fragment = Symbol.getFragment();
- // FIXME Support symbols with no DF. For example:
- // .reloc .data, ENUM_VALUE, <some expr>
- if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
- return std::make_pair(false,
- std::string("symbol in offset has no data "
- "fragment"));
- DF = cast<MCFragment>(Fragment);
- }
- return std::nullopt;
-}
-
-std::optional<std::pair<bool, std::string>>
-MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
- const MCExpr *Expr, SMLoc Loc,
- const MCSubtargetInfo &STI) {
+void MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
+ const MCExpr *Expr, SMLoc Loc) {
std::optional<MCFixupKind> MaybeKind =
Assembler->getBackend().getFixupKind(Name);
- if (!MaybeKind)
- return std::make_pair(true, std::string("unknown relocation name"));
+ if (!MaybeKind) {
+ getContext().reportError(Loc, "unknown relocation name");
+ return;
+ }
MCFixupKind Kind = *MaybeKind;
if (Expr)
@@ -685,38 +594,14 @@ MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
Expr =
MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext());
- MCFragment *DF = getOrCreateDataFragment(&STI);
- MCValue OffsetVal;
- if (!Offset.evaluateAsRelocatable(OffsetVal, nullptr))
- return std::make_pair(false,
- std::string(".reloc offset is not relocatable"));
- if (OffsetVal.isAbsolute()) {
- if (OffsetVal.getConstant() < 0)
- return std::make_pair(false, std::string(".reloc offset is negative"));
- DF->addFixup(MCFixup::create(OffsetVal.getConstant(), Expr, Kind));
- return std::nullopt;
- }
- if (OffsetVal.getSubSym())
- return std::make_pair(false,
- std::string(".reloc offset is not representable"));
-
- const MCSymbol &Symbol = *OffsetVal.getAddSym();
- if (Symbol.isDefined()) {
- uint32_t SymbolOffset = 0;
- std::optional<std::pair<bool, std::string>> Error =
- getOffsetAndDataFragment(Symbol, SymbolOffset, DF);
-
- if (Error != std::nullopt)
- return Error;
-
- DF->addFixup(
- MCFixup::create(SymbolOffset + OffsetVal.getConstant(), Expr, Kind));
- return std::nullopt;
+ auto *O = &Offset;
+ int64_t Val;
+ if (Offset.evaluateAsAbsolute(Val, nullptr)) {
+ auto *SecSym = getCurrentSectionOnly()->getBeginSymbol();
+ O = MCBinaryExpr::createAdd(MCSymbolRefExpr::create(SecSym, getContext()),
+ O, getContext(), Loc);
}
-
- PendingFixups.emplace_back(
- &Symbol, DF, MCFixup::create(OffsetVal.getConstant(), Expr, Kind));
- return std::nullopt;
+ getAssembler().addRelocDirective({*O, Expr, Kind});
}
void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
@@ -799,6 +684,5 @@ void MCObjectStreamer::finishImpl() {
// Emit pseudo probes for the current module.
MCPseudoProbeTable::emit(this);
- resolvePendingFixups();
getAssembler().Finish();
}
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index a36b2dea70ccf..77bf84364c5a3 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -3079,7 +3079,6 @@ bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
const MCExpr *Offset;
const MCExpr *Expr = nullptr;
- SMLoc OffsetLoc = Lexer.getTok().getLoc();
if (parseExpression(Offset))
return true;
@@ -3105,13 +3104,7 @@ bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
if (parseEOL())
return true;
- const MCTargetAsmParser &MCT = getTargetParser();
- const MCSubtargetInfo &STI = MCT.getSTI();
- if (std::optional<std::pair<bool, std::string>> Err =
- getStreamer().emitRelocDirective(*Offset, Name, Expr, DirectiveLoc,
- STI))
- return Error(Err->first ? NameLoc : OffsetLoc, Err->second);
-
+ getStreamer().emitRelocDirective(*Offset, Name, Expr, NameLoc);
return false;
}
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
index 233f42b7a4790..08f547a85073e 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp
@@ -559,8 +559,7 @@ void AArch64TargetELFStreamer::finish() {
if (!Sym.isMemtag())
continue;
auto *SRE = MCSymbolRefExpr::create(&Sym, Ctx);
- (void)S.emitRelocDirective(*Zero, "BFD_RELOC_NONE", SRE, SMLoc(),
- *Ctx.getSubtargetInfo());
+ S.emitRelocDirective(*Zero, "BFD_RELOC_NONE", SRE);
}
}
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 01e4d17f6236d..259b71b37d9a3 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -2101,7 +2101,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
TOut.getStreamer().emitRelocDirective(
*TmpExpr, inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR",
- RelocJalrExpr, IDLoc, *STI);
+ RelocJalrExpr);
TOut.getStreamer().emitLabel(TmpLabel);
}
diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
index c18ba44bea08e..ca0331006be74 100644
--- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -166,7 +166,7 @@ static void emitDirectiveRelocJalr(const MachineInstr &MI,
OutStreamer.emitRelocDirective(
*OffsetExpr,
Subtarget.inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR",
- CaleeExpr, SMLoc(), *TM.getMCSubtargetInfo());
+ CaleeExpr);
OutStreamer.emitLabel(OffsetLabel);
return;
}
diff --git a/llvm/test/MC/ELF/reloc-directive.s b/llvm/test/MC/ELF/reloc-directive.s
index 42995aa9e7d81..9871fba2e0021 100644
--- a/llvm/test/MC/ELF/reloc-directive.s
+++ b/llvm/test/MC/ELF/reloc-directive.s
@@ -9,15 +9,18 @@
# ASM-NEXT: .reloc .Ltmp1-1, R_X86_64_NONE, foo
# ASM-NEXT: .Ltmp2:
# ASM-NEXT: .reloc 2+.Ltmp2, R_X86_64_NONE, local
-# ASM-NEXT: .reloc 1+foo+3, R_X86_64_NONE, data+1
-# ASM-NEXT: .Ltmp3:
-# ASM-NEXT: .reloc .Ltmp3, BFD_RELOC_NONE, unused
# CHECK: 0x2 R_X86_64_NONE foo 0x0
# CHECK-NEXT: 0x0 R_X86_64_NONE foo 0x0
# CHECK-NEXT: 0x3 R_X86_64_NONE local 0x0
-# CHECK-NEXT: 0x4 R_X86_64_NONE data 0x1
# CHECK-NEXT: 0x1 R_X86_64_NONE unused 0x0
+# CHECK-NEXT: 0x4 R_X86_64_NONE data 0x1
+
+# CHECK: .rela.my {
+# CHECK: 0x0 R_X86_64_NONE foo 0x0
+# CHECK-NEXT: 0x4 R_X86_64_NONE foo 0x0
+# CHECK-NEXT: 0x8 R_X86_64_NONE foo 0x0
+# CHECK-NEXT: }
.text
.globl foo
@@ -27,17 +30,25 @@ local:
.reloc .+3-2, R_X86_64_NONE, foo
.reloc .-1, R_X86_64_NONE, foo
.reloc 2+., R_X86_64_NONE, local
- .reloc 1+foo+3, R_X86_64_NONE, data+1
.reloc ., BFD_RELOC_NONE, unused
+ .space 3
.data
.globl data
data:
+ .reloc 1+foo+3, R_X86_64_NONE, data+1
.long 0
-# RUN: not llvm-mc -filetype=obj -triple=x86_64 --defsym=ERR=1 %s 2>&1 | FileCheck %s --check-prefix=ERR
+## Constant offsets are relative to the section start.
+.section .my
+.word 0
+.reloc 0, BFD_RELOC_NONE, foo
+.word 0
+.p2align 3
+.reloc 2+2, BFD_RELOC_NONE, foo
+.p2align 4
+.reloc 8, BFD_RELOC_NONE, foo
-.ifdef ERR
.text
.globl a, b
a: ret
@@ -45,22 +56,26 @@ b: ret
x: ret
y: ret
-# ERR: {{.*}}.s:[[#@LINE+1]]:10: error: expected comma
+# RUN: not llvm-mc -filetype=obj -triple=x86_64 --defsym=PARSE=1 %s 2>&1 | FileCheck %s --check-prefix=PARSE
+# RUN: not llvm-mc -filetype=obj -triple=x86_64 --defsym=ERR=1 %s 2>&1 | FileCheck %s --check-prefix=ERR
+
+.ifdef PARSE
+# PARSE: {{.*}}.s:[[#@LINE+1]]:10: error: expected comma
.reloc 0 R_X86_64_NONE, a
-# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: .reloc offset is negative
+# PARSE: {{.*}}.s:[[#@LINE+1]]:8: error: directional label undefined
+.reloc 1f, R_X86_64_NONE, a
+.endif
+
+.ifdef ERR
.reloc -1, R_X86_64_NONE, a
-# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: .reloc offset is not relocatable
+# ERR: {{.*}}.s:[[#@LINE+1]]:9: error: .reloc offset is not relocatable
.reloc 2*., R_X86_64_NONE, a
-# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: .reloc offset is not relocatable
+# ERR: {{.*}}.s:[[#@LINE+1]]:9: error: .reloc offset is not relocatable
.reloc a+a, R_X86_64_NONE, a
-## GNU as accepts a-a but rejects b-a.
-# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: .reloc offset is not representable
-.reloc a-a, R_X86_64_NONE, a
-## TODO GNU as accepts x-x and y-x.
-# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: .reloc offset is not representable
+# ERR: {{.*}}.s:[[#@LINE+1]]:9: error: .reloc offset is not relative to a section
+.reloc b-a, R_X86_64_NONE, a
+# ERR: {{.*}}.s:[[#@LINE+1]]:9: error: .reloc offset is not relative to a section
.reloc x-x, R_X86_64_NONE, a
-# ERR: {{.*}}.s:[[#@LINE+1]]:8: error: directional label undefined
-.reloc 1f, R_X86_64_NONE, a
.endif
diff --git a/llvm/test/MC/Mips/reloc-directive-bad-obj.s b/llvm/test/MC/Mips/reloc-directive-bad-obj.s
index 86d6d0cc66c57..74e5dae5264f6 100644
--- a/llvm/test/MC/Mips/reloc-directive-bad-obj.s
+++ b/llvm/test/MC/Mips/reloc-directive-bad-obj.s
@@ -2,8 +2,8 @@
# RUN: -target-abi=o32 -filetype=obj -o /dev/null 2>&1 | FileCheck %s
.text
nop
-.reloc foo, R_MIPS_32, .text # CHECK: :[[@LINE]]:24: error: unresolved relocation offset
+.reloc foo, R_MIPS_32, .text # CHECK: :[[@LINE]]:8: error: .reloc offset is not relative to a section
nop
nop
-.reloc bar, R_MIPS_32, .text # CHECK: :[[@LINE]]:24: error: unresolved relocation offset
+.reloc bar, R_MIPS_32, .text # CHECK: :[[@LINE]]:8: error: .reloc offset is not relative to a section
nop
diff --git a/llvm/test/MC/Mips/reloc-directive-label-offset.s b/llvm/test/MC/Mips/reloc-directive-label-offset.s
index 257bfeb10d151..279fc7860dcea 100644
--- a/llvm/test/MC/Mips/reloc-directive-label-offset.s
+++ b/llvm/test/MC/Mips/reloc-directive-label-offset.s
@@ -58,18 +58,18 @@ bar:
# OBJ-N32-LABEL: Relocations [
# OBJ-N32: 0x4 R_MIPS_NONE .text
-# OBJ-N32-NEXT: 0x1C R_MIPS_GOT_OFST .text
-# OBJ-N32-NEXT: 0x0 R_MIPS_32 .text
# OBJ-N32-NEXT: 0xC R_MIPS_32 .text
# OBJ-N32-NEXT: 0x10 R_MIPS_CALL16 foo
# OBJ-N32-NEXT: 0x20 R_MIPS_GOT_DISP foo
# OBJ-N32-NEXT: 0x24 R_MIPS_GOT_PAGE .text
+# OBJ-N32-NEXT: 0x1C R_MIPS_GOT_OFST .text
+# OBJ-N32-NEXT: 0x0 R_MIPS_32 .text
# OBJ-N64-LABEL: Relocations [
# OBJ-N64: 0x4 R_MIPS_NONE/R_MIPS_NONE/R_MIPS_NONE .text 0x0
-# OBJ-N64-NEXT: 0x1C R_MIPS_GOT_OFST/R_MIPS_NONE/R_MIPS_NONE .text 0x0
-# OBJ-N64-NEXT: 0x0 R_MIPS_32/R_MIPS_NONE/R_MIPS_NONE .text 0x0
# OBJ-N64-NEXT: 0xC R_MIPS_32/R_MIPS_NONE/R_MIPS_NONE .text 0x0
# OBJ-N64-NEXT: 0x10 R_MIPS_CALL16/R_MIPS_NONE/R_MIPS_NONE foo 0x0
# OBJ-N64-NEXT: 0x20 R_MIPS_GOT_DISP/R_MIPS_NONE/R_MIPS_NONE foo 0x0
# OBJ-N64-NEXT: 0x24 R_MIPS_GOT_PAGE/R_MIPS_NONE/R_MIPS_NONE .text 0x0
+# OBJ-N64-NEXT: 0x1C R_MIPS_GOT_OFST/R_MIPS_NONE/R_MIPS_NONE .text 0x0
+# OBJ-N64-NEXT: 0x0 R_MIPS_32/R_MIPS_NONE/R_MIPS_NONE .text 0x0
More information about the llvm-commits
mailing list