aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC/MCAssembler.cpp
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2025-07-17 00:36:10 -0700
committerFangrui Song <i@maskray.me>2025-07-17 00:36:11 -0700
commit3cb0c7f45b97802ddc13a15560fbbca2efb75326 (patch)
tree10adcb53a82017b1fd8c208b1cc1b18b92700137 /llvm/lib/MC/MCAssembler.cpp
parent34c85337424fde5796154d0cb390b39175291373 (diff)
downloadllvm-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.cpp25
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) {