diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 3d270ce7e0d..eb2789b90f9 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -262,6 +262,7 @@ public: bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, const MCSymbolData &DataA, + const MCSymbolData *DataB, const MCFragment &FB, bool InSet, bool IsPCRel) const override; diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index fcfa968362b..2965ce21b82 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -91,12 +91,12 @@ public: const MCSymbolRefExpr *B, bool InSet) const; - virtual bool - IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, - const MCSymbolData &DataA, - const MCFragment &FB, - bool InSet, - bool IsPCRel) const; + virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCSymbolData *DataB, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const; /// \brief True if this symbol (which is a variable) is weak. This is not /// just STB_WEAK, but more generally whether or not we can evaluate diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 2004b1b8a2d..6105b25b8bf 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -300,6 +300,7 @@ class ELFObjectWriter : public MCObjectWriter { bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, const MCSymbolData &DataA, + const MCSymbolData *DataB, const MCFragment &FB, bool InSet, bool IsPCRel) const override; @@ -619,7 +620,7 @@ void ELFObjectWriter::WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD, if (ESize) { int64_t Res; - if (!ESize->EvaluateAsAbsolute(Res, Layout)) + if (!ESize->evaluateKnownAbsolute(Res, Layout)) report_fatal_error("Size expression must be absolute."); Size = Res; } @@ -1765,16 +1766,14 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, WriteDataSectionData(Asm, Layout, *Sections[i]); } -bool -ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, - const MCSymbolData &DataA, - const MCFragment &FB, - bool InSet, - bool IsPCRel) const { - if (::isWeak(DataA)) +bool ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( + const MCAssembler &Asm, const MCSymbolData &DataA, + const MCSymbolData *DataB, const MCFragment &FB, bool InSet, + bool IsPCRel) const { + if (!InSet && (::isWeak(DataA) || (DataB && ::isWeak(*DataB)))) return false; return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( - Asm, DataA, FB,InSet, IsPCRel); + Asm, DataA, DataB, FB, InSet, IsPCRel); } bool ELFObjectWriter::isWeak(const MCSymbolData &SD) const { diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 857eafc0b7e..d7ca875f297 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -502,9 +502,8 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, IsResolved = false; } else { const MCSymbolData &DataA = getSymbolData(SA); - IsResolved = - getWriter().IsSymbolRefDifferenceFullyResolvedImpl(*this, DataA, - *DF, false, true); + IsResolved = getWriter().IsSymbolRefDifferenceFullyResolvedImpl( + *this, DataA, nullptr, *DF, false, true); } } } else { diff --git a/lib/MC/MCObjectWriter.cpp b/lib/MC/MCObjectWriter.cpp index 3c536ecc9fd..33e4556e102 100644 --- a/lib/MC/MCObjectWriter.cpp +++ b/lib/MC/MCObjectWriter.cpp @@ -35,18 +35,14 @@ bool MCObjectWriter::IsSymbolRefDifferenceFullyResolved( if(!DataA.getFragment() || !DataB.getFragment()) return false; - return IsSymbolRefDifferenceFullyResolvedImpl(Asm, DataA, - *DataB.getFragment(), - InSet, - false); + return IsSymbolRefDifferenceFullyResolvedImpl( + Asm, DataA, &DataB, *DataB.getFragment(), InSet, false); } -bool -MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, - const MCSymbolData &DataA, - const MCFragment &FB, - bool InSet, - bool IsPCRel) const { +bool MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( + const MCAssembler &Asm, const MCSymbolData &DataA, + const MCSymbolData *DataB, const MCFragment &FB, bool InSet, + bool IsPCRel) const { const MCSection &SecA = DataA.getSymbol().AliasedSymbol().getSection(); const MCSection &SecB = FB.getParent()->getSection(); // On ELF and COFF A - B is absolute if A and B are in the same section. diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index 56cccab1d39..93ff75211c4 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -660,6 +660,7 @@ void MachObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, bool MachObjectWriter:: IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, const MCSymbolData &DataA, + const MCSymbolData *DataB, const MCFragment &FB, bool InSet, bool IsPCRel) const { diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp index ff90b7c2cef..b62b342edd1 100644 --- a/lib/MC/WinCOFFObjectWriter.cpp +++ b/lib/MC/WinCOFFObjectWriter.cpp @@ -172,6 +172,7 @@ public: bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, const MCSymbolData &DataA, + const MCSymbolData *DataB, const MCFragment &FB, bool InSet, bool IsPCRel) const override; @@ -649,16 +650,17 @@ void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, } bool WinCOFFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( - const MCAssembler &Asm, const MCSymbolData &DataA, const MCFragment &FB, - bool InSet, bool IsPCRel) const { + const MCAssembler &Asm, const MCSymbolData &DataA, + const MCSymbolData *DataB, const MCFragment &FB, bool InSet, + bool IsPCRel) const { // MS LINK expects to be able to replace all references to a function with a // thunk to implement their /INCREMENTAL feature. Make sure we don't optimize // away any relocations to functions. if ((((DataA.getFlags() & COFF::SF_TypeMask) >> COFF::SF_TypeShift) >> COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION) return false; - return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(Asm, DataA, FB, - InSet, IsPCRel); + return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( + Asm, DataA, DataB, FB, InSet, IsPCRel); } bool WinCOFFObjectWriter::isWeak(const MCSymbolData &SD) const { diff --git a/test/MC/ELF/weak-diff2.s b/test/MC/ELF/weak-diff2.s new file mode 100644 index 00000000000..daf64a44232 --- /dev/null +++ b/test/MC/ELF/weak-diff2.s @@ -0,0 +1,10 @@ +// RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t 2>&1 | FileCheck %s + +// CHECK: error: Cannot represent a subtraction with a weak symbol + +.weak f +f: + nop +g: + nop +.quad g - f