[llvm] c512d95 - MC: Generalize RISCV/LoongArch handleAddSubRelocations and AVR shouldForceRelocation
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sun May 18 18:08:41 PDT 2025
Author: Fangrui Song
Date: 2025-05-18T18:08:35-07:00
New Revision: c512d951861c9e35649b6c9672c227244bb9b6be
URL: https://github.com/llvm/llvm-project/commit/c512d951861c9e35649b6c9672c227244bb9b6be
DIFF: https://github.com/llvm/llvm-project/commit/c512d951861c9e35649b6c9672c227244bb9b6be.diff
LOG: MC: Generalize RISCV/LoongArch handleAddSubRelocations and AVR shouldForceRelocation
Introduce MCAsmBackend::addReloc to manage relocation appending.
The default implementation uses shouldForceRelocation to check
unresolved fixups and calls recordRelocation to append a relocation when
needed.
RISCV and LoongArch override addReloc to handle ADD/SUB relocations,
with potential support for RELAX relocations in the future.
AVR overrides addReloc to customize shouldForceRelocation behavior
(#121498).
applyFixup is moved into evaluateFixup.
Added:
Modified:
llvm/include/llvm/MC/MCAsmBackend.h
llvm/include/llvm/MC/MCAssembler.h
llvm/lib/MC/ELFObjectWriter.cpp
llvm/lib/MC/MCAsmBackend.cpp
llvm/lib/MC/MCAssembler.cpp
llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
Removed:
################################################################################
diff --git a/llvm/include/llvm/MC/MCAsmBackend.h b/llvm/include/llvm/MC/MCAsmBackend.h
index 455812c0b10aa..105614fb55212 100644
--- a/llvm/include/llvm/MC/MCAsmBackend.h
+++ b/llvm/include/llvm/MC/MCAsmBackend.h
@@ -116,13 +116,10 @@ class MCAsmBackend {
llvm_unreachable("Need to implement hook if target has custom fixups");
}
- virtual bool handleAddSubRelocations(const MCAssembler &Asm,
- const MCFragment &F,
- const MCFixup &Fixup,
- const MCValue &Target,
- uint64_t &FixedValue) const {
- return false;
- }
+ virtual bool addReloc(MCAssembler &Asm, const MCFragment &F,
+ const MCFixup &Fixup, const MCValue &Target,
+ uint64_t &FixedValue, bool IsResolved,
+ const MCSubtargetInfo *);
/// Apply the \p Value for given \p Fixup into the provided data fragment, at
/// the offset specified by the fixup and following the fixup kind as
diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h
index 57143e3d59b4b..d463b40cbd142 100644
--- a/llvm/include/llvm/MC/MCAssembler.h
+++ b/llvm/include/llvm/MC/MCAssembler.h
@@ -99,7 +99,8 @@ class MCAssembler {
/// relocation.
bool evaluateFixup(const MCFixup &Fixup, const MCFragment *DF,
MCValue &Target, const MCSubtargetInfo *STI,
- uint64_t &Value, bool RecordReloc) const;
+ uint64_t &Value, bool RecordReloc,
+ MutableArrayRef<char> Contents) const;
/// Check whether a fixup can be satisfied, or whether it needs to be relaxed
/// (increased in size, in order to hold its value correctly).
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp
index 4c68fb54dcd2d..4fb78b320f114 100644
--- a/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/llvm/lib/MC/ELFObjectWriter.cpp
@@ -1350,13 +1350,9 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
MCFixupKindInfo::FKF_IsPCRel;
uint64_t FixupOffset = Asm.getFragmentOffset(*Fragment) + Fixup.getOffset();
uint64_t Addend = Target.getConstant();
- if (auto *RefB = Target.getSubSym()) {
- // When there is no relocation specifier, a linker relaxation target may
- // emit ADD/SUB relocations for A-B+C.
- if (SymA && Backend.handleAddSubRelocations(Asm, *Fragment, Fixup, Target,
- FixedValue))
- return;
+ // Handle special fixups like ADD/SUB relocation pairs.
+ if (auto *RefB = Target.getSubSym()) {
const auto &SymB = cast<MCSymbolELF>(*RefB);
if (SymB.isUndefined()) {
Ctx.reportError(Fixup.getLoc(),
diff --git a/llvm/lib/MC/MCAsmBackend.cpp b/llvm/lib/MC/MCAsmBackend.cpp
index 3c51755c8820b..9bab0d0e7e78c 100644
--- a/llvm/lib/MC/MCAsmBackend.cpp
+++ b/llvm/lib/MC/MCAsmBackend.cpp
@@ -124,6 +124,17 @@ bool MCAsmBackend::fixupNeedsRelaxationAdvanced(const MCAssembler &,
return fixupNeedsRelaxation(Fixup, Value);
}
+bool MCAsmBackend::addReloc(MCAssembler &Asm, const MCFragment &F,
+ const MCFixup &Fixup, const MCValue &Target,
+ uint64_t &FixedValue, bool IsResolved,
+ const MCSubtargetInfo *STI) {
+ if (IsResolved && shouldForceRelocation(Asm, Fixup, Target, STI))
+ IsResolved = false;
+ if (!IsResolved)
+ Asm.getWriter().recordRelocation(Asm, &F, Fixup, Target, FixedValue);
+ return IsResolved;
+}
+
bool MCAsmBackend::isDarwinCanonicalPersonality(const MCSymbol *Sym) const {
// Consider a NULL personality (ie., no personality encoding) to be canonical
// because it's always at 0.
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index 73c3a3a00b5c6..f8e7204dd797b 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -138,7 +138,8 @@ bool MCAssembler::isThumbFunc(const MCSymbol *Symbol) const {
bool MCAssembler::evaluateFixup(const MCFixup &Fixup, const MCFragment *DF,
MCValue &Target, const MCSubtargetInfo *STI,
- uint64_t &Value, bool RecordReloc) const {
+ uint64_t &Value, bool RecordReloc,
+ MutableArrayRef<char> Contents) const {
++stats::evaluateFixup;
// FIXME: This code has some duplication with recordRelocation. We should
@@ -196,21 +197,13 @@ bool MCAssembler::evaluateFixup(const MCFixup &Fixup, const MCFragment *DF,
if (!RecordReloc)
return IsResolved;
- // .reloc directive and the backend might force the relocation.
- // Backends that customize shouldForceRelocation generally just need the fixup
- // kind. AVR needs the fixup value to bypass the assembly time overflow with a
- // relocation.
- if (IsResolved) {
- auto TargetVal = Target;
- TargetVal.Cst = Value;
- if (mc::isRelocRelocation(Fixup.getKind()) ||
- getBackend().shouldForceRelocation(*this, Fixup, TargetVal, STI))
- IsResolved = false;
- }
- if (!IsResolved)
- getWriter().recordRelocation(const_cast<MCAssembler &>(*this), DF, Fixup,
- Target, Value);
- return IsResolved;
+ if (IsResolved && mc::isRelocRelocation(Fixup.getKind()))
+ IsResolved = false;
+ IsResolved = getBackend().addReloc(const_cast<MCAssembler &>(*this), *DF,
+ Fixup, Target, Value, IsResolved, STI);
+ getBackend().applyFixup(*this, Fixup, Target, Contents, Value, IsResolved,
+ STI);
+ return true;
}
uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const {
@@ -908,7 +901,7 @@ void MCAssembler::layout() {
// Evaluate and apply the fixups, generating relocation entries as necessary.
for (MCSection &Sec : *this) {
for (MCFragment &Frag : Sec) {
- ArrayRef<MCFixup> Fixups;
+ MutableArrayRef<MCFixup> Fixups;
MutableArrayRef<char> Contents;
const MCSubtargetInfo *STI = nullptr;
@@ -974,10 +967,8 @@ void MCAssembler::layout() {
for (const MCFixup &Fixup : Fixups) {
uint64_t FixedValue;
MCValue Target;
- bool IsResolved = evaluateFixup(Fixup, &Frag, Target, STI, FixedValue,
- /*RecordReloc=*/true);
- getBackend().applyFixup(*this, Fixup, Target, Contents, FixedValue,
- IsResolved, STI);
+ evaluateFixup(Fixup, &Frag, Target, STI, FixedValue,
+ /*RecordReloc=*/true, Contents);
}
}
}
@@ -997,8 +988,9 @@ bool MCAssembler::fixupNeedsRelaxation(const MCFixup &Fixup,
assert(getBackendPtr() && "Expected assembler backend");
MCValue Target;
uint64_t Value;
- bool Resolved = evaluateFixup(Fixup, DF, Target, DF->getSubtargetInfo(),
- Value, /*RecordReloc=*/false);
+ bool Resolved =
+ evaluateFixup(const_cast<MCFixup &>(Fixup), DF, Target,
+ DF->getSubtargetInfo(), Value, /*RecordReloc=*/false, {});
return getBackend().fixupNeedsRelaxationAdvanced(*this, Fixup, Target, Value,
Resolved);
}
diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
index fa3f1fe6081ee..47e7539fa472e 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
@@ -368,6 +368,23 @@ AVRAsmBackend::createObjectTargetWriter() const {
return createAVRELFObjectWriter(MCELFObjectTargetWriter::getOSABI(OSType));
}
+bool AVRAsmBackend::addReloc(MCAssembler &Asm, const MCFragment &F,
+ const MCFixup &Fixup, const MCValue &Target,
+ uint64_t &FixedValue, bool IsResolved,
+ const MCSubtargetInfo *STI) {
+ // AVR sets the fixup value to bypass the assembly time overflow with a
+ // relocation.
+ if (IsResolved) {
+ auto TargetVal = MCValue::get(Target.getAddSym(), Target.getSubSym(),
+ FixedValue, Target.getSpecifier());
+ if (shouldForceRelocation(Asm, Fixup, TargetVal, STI))
+ IsResolved = false;
+ }
+ if (!IsResolved)
+ Asm.getWriter().recordRelocation(Asm, &F, Fixup, Target, FixedValue);
+ return IsResolved;
+}
+
void AVRAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h
index c98828bdc50b4..b71ce4957b533 100644
--- a/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h
+++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h
@@ -37,6 +37,10 @@ class AVRAsmBackend : public MCAsmBackend {
std::unique_ptr<MCObjectTargetWriter>
createObjectTargetWriter() const override;
+ bool addReloc(MCAssembler &Asm, const MCFragment &F, const MCFixup &Fixup,
+ const MCValue &Target, uint64_t &FixedValue, bool IsResolved,
+ const MCSubtargetInfo *) override;
+
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
const MCValue &Target, MutableArrayRef<char> Data,
uint64_t Value, bool IsResolved,
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
index 23d936b39a422..7c95cf78215e0 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
@@ -436,11 +436,16 @@ bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
return true;
}
-bool LoongArchAsmBackend::handleAddSubRelocations(const MCAssembler &Asm,
- const MCFragment &F,
- const MCFixup &Fixup,
- const MCValue &Target,
- uint64_t &FixedValue) const {
+bool LoongArchAsmBackend::addReloc(MCAssembler &Asm, const MCFragment &F,
+ const MCFixup &Fixup, const MCValue &Target,
+ uint64_t &FixedValue, bool IsResolved,
+ const MCSubtargetInfo *CurSTI) {
+ auto Fallback = [&]() {
+ return MCAsmBackend::addReloc(Asm, F, Fixup, Target, FixedValue, IsResolved,
+ CurSTI);
+ };
+ if (!Target.getSubSym())
+ return Fallback();
assert(Target.getSpecifier() == 0 &&
"relocatable SymA-SymB cannot have relocation specifier");
std::pair<MCFixupKind, MCFixupKind> FK;
@@ -458,7 +463,7 @@ bool LoongArchAsmBackend::handleAddSubRelocations(const MCAssembler &Asm,
// is not same as the section of Fixup, it will report error. Just return
// false and then this work can be finished by handleFixup.
if (&SecA != &SecB)
- return false;
+ return Fallback();
// In SecA == SecB case. If the linker relaxation is enabled, we need record
// the ADD, SUB relocations. Otherwise the FixedValue has already been calc-
@@ -490,9 +495,8 @@ bool LoongArchAsmBackend::handleAddSubRelocations(const MCAssembler &Asm,
MCValue B = MCValue::get(Target.getSubSym());
auto FA = MCFixup::create(Fixup.getOffset(), nullptr, std::get<0>(FK));
auto FB = MCFixup::create(Fixup.getOffset(), nullptr, std::get<1>(FK));
- auto &Assembler = const_cast<MCAssembler &>(Asm);
- Asm.getWriter().recordRelocation(Assembler, &F, FA, A, FixedValueA);
- Asm.getWriter().recordRelocation(Assembler, &F, FB, B, FixedValueB);
+ Asm.getWriter().recordRelocation(Asm, &F, FA, A, FixedValueA);
+ Asm.getWriter().recordRelocation(Asm, &F, FB, B, FixedValueB);
FixedValue = FixedValueA - FixedValueB;
return true;
}
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
index 94518acb11544..f6eb0c6c42a2b 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
@@ -35,9 +35,9 @@ class LoongArchAsmBackend : public MCAsmBackend {
LoongArchAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit,
const MCTargetOptions &Options);
- bool handleAddSubRelocations(const MCAssembler &Asm, const MCFragment &F,
- const MCFixup &Fixup, const MCValue &Target,
- uint64_t &FixedValue) const override;
+ bool addReloc(MCAssembler &Asm, const MCFragment &F, const MCFixup &Fixup,
+ const MCValue &Target, uint64_t &FixedValue, bool IsResolved,
+ const MCSubtargetInfo *) override;
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
const MCValue &Target, MutableArrayRef<char> Data,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index cdf2dd9aa593c..368a4fe4864f9 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -616,11 +616,13 @@ bool RISCVAsmBackend::evaluateTargetFixup(
return AUIPCFixup->getTargetKind() == RISCV::fixup_riscv_pcrel_hi20;
}
-bool RISCVAsmBackend::handleAddSubRelocations(const MCAssembler &Asm,
- const MCFragment &F,
- const MCFixup &Fixup,
- const MCValue &Target,
- uint64_t &FixedValue) const {
+bool RISCVAsmBackend::addReloc(MCAssembler &Asm, const MCFragment &F,
+ const MCFixup &Fixup, const MCValue &Target,
+ uint64_t &FixedValue, bool IsResolved,
+ const MCSubtargetInfo *STI) {
+ if (!Target.getSubSym())
+ return MCAsmBackend::addReloc(Asm, F, Fixup, Target, FixedValue, IsResolved,
+ STI);
assert(Target.getSpecifier() == 0 &&
"relocatable SymA-SymB cannot have relocation specifier");
uint64_t FixedValueA, FixedValueB;
@@ -653,9 +655,8 @@ bool RISCVAsmBackend::handleAddSubRelocations(const MCAssembler &Asm,
MCValue B = MCValue::get(Target.getSubSym());
auto FA = MCFixup::create(Fixup.getOffset(), nullptr, TA);
auto FB = MCFixup::create(Fixup.getOffset(), nullptr, TB);
- auto &Assembler = const_cast<MCAssembler &>(Asm);
- Asm.getWriter().recordRelocation(Assembler, &F, FA, A, FixedValueA);
- Asm.getWriter().recordRelocation(Assembler, &F, FB, B, FixedValueB);
+ Asm.getWriter().recordRelocation(Asm, &F, FA, A, FixedValueA);
+ Asm.getWriter().recordRelocation(Asm, &F, FB, B, FixedValueB);
FixedValue = FixedValueA - FixedValueB;
return true;
}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
index 5db55ad0b8567..874cf654e7eef 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
@@ -48,9 +48,9 @@ class RISCVAsmBackend : public MCAsmBackend {
const MCSubtargetInfo *STI,
uint64_t &Value) override;
- bool handleAddSubRelocations(const MCAssembler &Asm, const MCFragment &F,
- const MCFixup &Fixup, const MCValue &Target,
- uint64_t &FixedValue) const override;
+ bool addReloc(MCAssembler &Asm, const MCFragment &F, const MCFixup &Fixup,
+ const MCValue &Target, uint64_t &FixedValue, bool IsResolved,
+ const MCSubtargetInfo *) override;
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
const MCValue &Target, MutableArrayRef<char> Data,
More information about the llvm-commits
mailing list