diff options
author | Fangrui Song <i@maskray.me> | 2025-07-17 00:36:10 -0700 |
---|---|---|
committer | Fangrui Song <i@maskray.me> | 2025-07-17 00:36:11 -0700 |
commit | 3cb0c7f45b97802ddc13a15560fbbca2efb75326 (patch) | |
tree | 10adcb53a82017b1fd8c208b1cc1b18b92700137 /llvm/lib/MC/MCAssembler.cpp | |
parent | 34c85337424fde5796154d0cb390b39175291373 (diff) | |
download | llvm-3cb0c7f45b97802ddc13a15560fbbca2efb75326.zip llvm-3cb0c7f45b97802ddc13a15560fbbca2efb75326.tar.gz llvm-3cb0c7f45b97802ddc13a15560fbbca2efb75326.tar.bz2 |
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.
Diffstat (limited to 'llvm/lib/MC/MCAssembler.cpp')
-rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index d4d10e0..f1a82f6 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) { |