diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/MC/MCObjectStreamer.cpp | 23 |
2 files changed, 27 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 5af083536d7..17bbf01c43f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1591,6 +1591,10 @@ void AsmPrinter::EmitInt32(int Value) const { /// .set if it avoids relocations. void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size) const { + if (!MAI->doesDwarfUseRelocationsAcrossSections()) + if (OutStreamer->emitAbsoluteSymbolDiff(Hi, Lo, Size)) + return; + // Get the Hi-Lo expression. const MCExpr *Diff = MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(Hi, OutContext), diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index d82dd15df2b..836b1ced5c5 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -53,6 +53,29 @@ void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) { } } +bool MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi, + const MCSymbol *Lo, + unsigned Size) { + // Must have symbol data. + if (!Assembler->hasSymbolData(*Hi) || !Assembler->hasSymbolData(*Lo)) + return false; + auto &HiD = Assembler->getSymbolData(*Hi); + auto &LoD = Assembler->getSymbolData(*Lo); + + // Must both be assigned to the same (valid) fragment. + if (!HiD.getFragment() || HiD.getFragment() != LoD.getFragment()) + return false; + + // Must be a data fragment. + if (!isa<MCDataFragment>(HiD.getFragment())) + return false; + + assert(HiD.getOffset() >= LoD.getOffset() && + "Expected Hi to be greater than Lo"); + EmitIntValue(HiD.getOffset() - LoD.getOffset(), Size); + return true; +} + void MCObjectStreamer::reset() { if (Assembler) Assembler->reset(); |

