diff options
author | Fangrui Song <i@maskray.me> | 2025-04-12 19:02:07 -0700 |
---|---|---|
committer | Fangrui Song <i@maskray.me> | 2025-04-12 19:02:07 -0700 |
commit | 39662922e15c53f54da93b5a1d029589d49caec9 (patch) | |
tree | fb0b4b9eedc7865f505fd05959e9dd386b19e6b6 /llvm/lib/MC/MCObjectStreamer.cpp | |
parent | b0acbbee88f8ae706658f2a7635df4ce39e15e74 (diff) | |
download | llvm-39662922e15c53f54da93b5a1d029589d49caec9.zip llvm-39662922e15c53f54da93b5a1d029589d49caec9.tar.gz llvm-39662922e15c53f54da93b5a1d029589d49caec9.tar.bz2 |
MCObjectStreamer: Refine absoluteSymbolDiff condition
The function is called to test the fast path - when Lo/Hi are within the
same fragment. This is unsafe - Lo/Hi at the begin and end of a
relaxable fragment should not evaluate to a constant. However, we don't
have tests that exercise the code path.
Nevertheless, make the check safer and remove the now unnecessary
isRISCV check (from https://reviews.llvm.org/D103539).
Diffstat (limited to 'llvm/lib/MC/MCObjectStreamer.cpp')
-rw-r--r-- | llvm/lib/MC/MCObjectStreamer.cpp | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index e228418..e9295f0 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -94,8 +94,12 @@ void MCObjectStreamer::resolvePendingFixups() { static std::optional<uint64_t> absoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo) { assert(Hi && Lo); - if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() || - Hi->isVariable() || Lo->isVariable()) + if (Lo == Hi) + return 0; + if (Hi->isVariable() || Lo->isVariable()) + return std::nullopt; + auto *LoF = dyn_cast_or_null<MCDataFragment>(Lo->getFragment()); + if (!LoF || Hi->getFragment() != LoF || LoF->isLinkerRelaxable()) return std::nullopt; return Hi->getOffset() - Lo->getOffset(); @@ -104,20 +108,18 @@ static std::optional<uint64_t> absoluteSymbolDiff(const MCSymbol *Hi, void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size) { - if (!getAssembler().getContext().getTargetTriple().isRISCV()) - if (std::optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo)) - return emitIntValue(*Diff, Size); - MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size); + if (std::optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo)) + emitIntValue(*Diff, Size); + else + MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size); } void MCObjectStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi, const MCSymbol *Lo) { - if (!getAssembler().getContext().getTargetTriple().isRISCV()) - if (std::optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo)) { - emitULEB128IntValue(*Diff); - return; - } - MCStreamer::emitAbsoluteSymbolDiffAsULEB128(Hi, Lo); + if (std::optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo)) + emitULEB128IntValue(*Diff); + else + MCStreamer::emitAbsoluteSymbolDiffAsULEB128(Hi, Lo); } void MCObjectStreamer::reset() { |