diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h index 3058b7b4874..d942e273a4c 100644 --- a/include/llvm/MC/MCAsmLayout.h +++ b/include/llvm/MC/MCAsmLayout.h @@ -102,6 +102,10 @@ public: /// \brief Get the offset of the given symbol, as computed in the current /// layout. + /// \result True on success. + bool getSymbolOffset(const MCSymbolData *SD, uint64_t &Val) const; + + /// \brief Variant that reports a fatal error if the offset is not computable. uint64_t getSymbolOffset(const MCSymbolData *SD) const; /// @} diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 27e34da6322..9c224b3da6a 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -486,34 +486,16 @@ void ELFObjectWriter::WriteHeader(const MCAssembler &Asm, Write16(ShstrtabIndex); } -uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &OrigData, +uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout) { - MCSymbolData *Data = &OrigData; - if (Data->isCommon() && Data->isExternal()) - return Data->getCommonAlignment(); + if (Data.isCommon() && Data.isExternal()) + return Data.getCommonAlignment(); - const MCSymbol *Symbol = &Data->getSymbol(); - MCAssembler &Asm = Layout.getAssembler(); - bool IsThumb = Asm.isThumbFunc(Symbol); - - // Given how we implement symver, we can end up with an symbol reference - // to an undefined symbol. Walk past it first. - if (Symbol->isVariable()) { - const MCExpr *Expr = Symbol->getVariableValue(); - if (auto *Ref = dyn_cast(Expr)) { - if (Ref->getKind() == MCSymbolRefExpr::VK_None) { - Symbol = &Ref->getSymbol(); - Data = &Asm.getOrCreateSymbolData(*Symbol); - } - } - } - - if (!Symbol->isVariable() && !Data->getFragment()) + uint64_t Res; + if (!Layout.getSymbolOffset(&Data, Res)) return 0; - uint64_t Res = Layout.getSymbolOffset(Data); - - if (IsThumb) + if (Layout.getAssembler().isThumbFunc(&Data.getSymbol())) Res |= 1; return Res; diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index a96e4ba1514..c65e44e5313 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -118,37 +118,66 @@ uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const { } // Simple getSymbolOffset helper for the non-varibale case. -static uint64_t getLabelOffset(const MCAsmLayout &Layout, - const MCSymbolData &SD) { - if (!SD.getFragment()) - report_fatal_error("unable to evaluate offset to undefined symbol '" + - SD.getSymbol().getName() + "'"); - return Layout.getFragmentOffset(SD.getFragment()) + SD.getOffset(); +static bool getLabelOffset(const MCAsmLayout &Layout, const MCSymbolData &SD, + bool ReportError, uint64_t &Val) { + if (!SD.getFragment()) { + if (ReportError) + report_fatal_error("unable to evaluate offset to undefined symbol '" + + SD.getSymbol().getName() + "'"); + return false; + } + Val = Layout.getFragmentOffset(SD.getFragment()) + SD.getOffset(); + return true; } -uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const { +static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, + const MCSymbolData *SD, bool ReportError, + uint64_t &Val) { const MCSymbol &S = SD->getSymbol(); if (!S.isVariable()) - return getLabelOffset(*this, *SD); + return getLabelOffset(Layout, *SD, ReportError, Val); // If SD is a variable, evaluate it. MCValue Target; - if (!S.getVariableValue()->EvaluateAsValue(Target, this)) + if (!S.getVariableValue()->EvaluateAsValue(Target, &Layout)) report_fatal_error("unable to evaluate offset for variable '" + S.getName() + "'"); uint64_t Offset = Target.getConstant(); + const MCAssembler &Asm = Layout.getAssembler(); + const MCSymbolRefExpr *A = Target.getSymA(); - if (A) - Offset += getLabelOffset(*this, Assembler.getSymbolData(A->getSymbol())); + if (A) { + uint64_t ValA; + if (!getLabelOffset(Layout, Asm.getSymbolData(A->getSymbol()), ReportError, + ValA)) + return false; + Offset += ValA; + } const MCSymbolRefExpr *B = Target.getSymB(); - if (B) - Offset -= getLabelOffset(*this, Assembler.getSymbolData(B->getSymbol())); + if (B) { + uint64_t ValB; + if (!getLabelOffset(Layout, Asm.getSymbolData(B->getSymbol()), ReportError, + ValB)) + return false; + Offset -= ValB; + } - return Offset; + Val = Offset; + return true; +} + +bool MCAsmLayout::getSymbolOffset(const MCSymbolData *SD, uint64_t &Val) const { + return getSymbolOffsetImpl(*this, SD, false, Val); +} + +uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const { + uint64_t Val; + getSymbolOffsetImpl(*this, SD, true, Val); + return Val; } uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const {