[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