diff --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h index 11da711ab9ca..d5a68be3ec65 100644 --- a/llvm/include/llvm/MC/MCExpr.h +++ b/llvm/include/llvm/MC/MCExpr.h @@ -105,6 +105,13 @@ public: bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const; + /// \brief Try to evaluate the expression to the form (a - b + constant) where + /// neither a nor b are variables. + /// + /// This is a more aggressive variant of EvaluateAsRelocatable. The intended + /// use is for when relocations are not available, like the .size directive. + bool evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const; + /// FindAssociatedSection - Find the "associated section" for this expression, /// which is currently defined as the absolute section for constants, or /// otherwise the section associated with the first defined symbol in the diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 6345bd534171..857eafc0b7e4 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -188,7 +188,7 @@ const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const { const MCExpr *Expr = Symbol.getVariableValue(); MCValue Value; - if (!Expr->EvaluateAsRelocatable(Value, this, nullptr)) + if (!Expr->evaluateAsValue(Value, *this)) llvm_unreachable("Invalid Expression"); const MCSymbolRefExpr *RefB = Value.getSymB(); diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp index 7508ef671233..8a64403362c0 100644 --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -584,7 +584,15 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res, false); } -static bool canExpand(const MCSymbol &Sym, const MCAssembler *Asm) { +bool MCExpr::evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const { + MCAssembler *Assembler = &Layout.getAssembler(); + return EvaluateAsRelocatableImpl(Res, Assembler, &Layout, nullptr, nullptr, + true); +} + +static bool canExpand(const MCSymbol &Sym, const MCAssembler *Asm, bool InSet) { + if (InSet) + return true; if (!Asm) return false; const MCSymbolData &SD = Asm->getSymbolData(Sym); @@ -613,10 +621,11 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, // Evaluate recursively if this is a variable. if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None && - canExpand(Sym, Asm)) { + canExpand(Sym, Asm, InSet)) { + bool IsMachO = SRE->hasSubsectionsViaSymbols(); if (Sym.getVariableValue()->EvaluateAsRelocatableImpl( - Res, Asm, Layout, Fixup, Addrs, true)) { - if (!SRE->hasSubsectionsViaSymbols()) + Res, Asm, Layout, Fixup, Addrs, InSet || IsMachO)) { + if (!IsMachO) return true; const MCSymbolRefExpr *A = Res.getSymA(); diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp index c519a9d6d5e8..c6bc81ddc564 100644 --- a/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -175,6 +175,8 @@ public: const MCFragment &FB, bool InSet, bool IsPCRel) const override; + bool isWeak(const MCSymbolData &SD) const override; + void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, bool &IsPCRel, @@ -661,6 +663,12 @@ bool WinCOFFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( InSet, IsPCRel); } +bool WinCOFFObjectWriter::isWeak(const MCSymbolData &SD) const { + // FIXME: this is for PR23025. Write a good description on + // why this is needed. + return SD.isExternal(); +} + void WinCOFFObjectWriter::RecordRelocation( MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) { diff --git a/llvm/test/MC/X86/expand-var.s b/llvm/test/MC/X86/expand-var.s index b3311b4a8440..ef62d8a260fa 100644 --- a/llvm/test/MC/X86/expand-var.s +++ b/llvm/test/MC/X86/expand-var.s @@ -10,3 +10,9 @@ a: d = a .weak d .long d + (b - c) + + +a2: + .weak b2 + b2 = a2 + c2 = b2 - a2