summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp4
-rw-r--r--llvm/lib/MC/MCObjectStreamer.cpp23
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();
OpenPOWER on IntegriCloud