Index: include/llvm/MC/MCObjectStreamer.h =================================================================== --- include/llvm/MC/MCObjectStreamer.h +++ include/llvm/MC/MCObjectStreamer.h @@ -169,11 +169,18 @@ void FinishImpl() override; +private: + Optional absoluteSymbolDiff(const MCSymbol *hi, + const MCSymbol *Lo); + +public: /// Emit the absolute difference between two symbols if possible. /// /// Emit the absolute difference between \c Hi and \c Lo, as long as we can /// compute it. Currently, that requires that both symbols are in the same - /// data fragment. Otherwise, do nothing and return \c false. + /// data fragment and that the target has not specified that diff expressions + /// require relocations to be emitted. Otherwise, do nothing and return + /// \c false. /// /// \pre Offset of \c Hi is greater than the offset \c Lo. void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, Index: lib/MC/MCObjectStreamer.cpp =================================================================== --- lib/MC/MCObjectStreamer.cpp +++ lib/MC/MCObjectStreamer.cpp @@ -53,9 +53,12 @@ // As a compile-time optimization, avoid allocating and evaluating an MCExpr // tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment. -static Optional absoluteSymbolDiff(const MCSymbol *Hi, - const MCSymbol *Lo) { +Optional +MCObjectStreamer::absoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo) { assert(Hi && Lo); + if (TAB->requiresDiffExpressionRelocations()) + return None; + if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() || Hi->isVariable() || Lo->isVariable()) return None;