X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FMCAssembler.cpp;h=a6aa5da2421a5be2969b62641098e48046b22b85;hb=6c0e1e0fa658f4e7466c6787aedce992ece2db55;hp=89d7d1901675208f1f0ba7e3c3080a78ccbdf143;hpb=3b8cc2299ba497e7c774622f6770403a0e970494;p=oota-llvm.git diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 89d7d190167..a6aa5da2421 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "assembler" #include "llvm/MC/MCAssembler.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" @@ -28,9 +27,12 @@ #include "llvm/Support/LEB128.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" - +#include "llvm/MC/MCSectionELF.h" +#include using namespace llvm; +#define DEBUG_TYPE "assembler" + namespace { namespace stats { STATISTIC(EmittedFragments, "Number of emitted assembler fragments - total"); @@ -116,36 +118,89 @@ uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const { return F->Offset; } -uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const { +// Simple getSymbolOffset helper for the non-varibale case. +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; +} + +static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, + const MCSymbolData *SD, bool ReportError, + uint64_t &Val) { const MCSymbol &S = SD->getSymbol(); - // If this is a variable, then recursively evaluate now. - if (S.isVariable()) { - MCValue Target; - if (!S.getVariableValue()->EvaluateAsRelocatable(Target, this)) - report_fatal_error("unable to evaluate offset for variable '" + - S.getName() + "'"); + if (!S.isVariable()) + return getLabelOffset(Layout, *SD, ReportError, Val); - // Verify that any used symbols are defined. - if (Target.getSymA() && Target.getSymA()->getSymbol().isUndefined()) - report_fatal_error("unable to evaluate offset to undefined symbol '" + - Target.getSymA()->getSymbol().getName() + "'"); - if (Target.getSymB() && Target.getSymB()->getSymbol().isUndefined()) - report_fatal_error("unable to evaluate offset to undefined symbol '" + - Target.getSymB()->getSymbol().getName() + "'"); - - uint64_t Offset = Target.getConstant(); - if (Target.getSymA()) - Offset += getSymbolOffset(&Assembler.getSymbolData( - Target.getSymA()->getSymbol())); - if (Target.getSymB()) - Offset -= getSymbolOffset(&Assembler.getSymbolData( - Target.getSymB()->getSymbol())); - return Offset; + // If SD is a variable, evaluate it. + MCValue Target; + if (!S.getVariableValue()->EvaluateAsValue(Target, &Layout, nullptr)) + 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) { + uint64_t ValA; + if (!getLabelOffset(Layout, Asm.getSymbolData(A->getSymbol()), ReportError, + ValA)) + return false; + Offset += ValA; } - assert(SD->getFragment() && "Invalid getOffset() on undefined symbol!"); - return getFragmentOffset(SD->getFragment()) + SD->getOffset(); + const MCSymbolRefExpr *B = Target.getSymB(); + if (B) { + uint64_t ValB; + if (!getLabelOffset(Layout, Asm.getSymbolData(B->getSymbol()), ReportError, + ValB)) + return false; + Offset -= ValB; + } + + 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; +} + +const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const { + if (!Symbol.isVariable()) + return &Symbol; + + const MCExpr *Expr = Symbol.getVariableValue(); + MCValue Value; + if (!Expr->EvaluateAsValue(Value, this, nullptr)) + llvm_unreachable("Invalid Expression"); + + const MCSymbolRefExpr *RefB = Value.getSymB(); + if (RefB) + Assembler.getContext().FatalError( + SMLoc(), Twine("symbol '") + RefB->getSymbol().getName() + + "' could not be evaluated in a subtraction expression"); + + const MCSymbolRefExpr *A = Value.getSymA(); + if (!A) + return nullptr; + + return &A->getSymbol(); } uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const { @@ -212,7 +267,7 @@ MCFragment::~MCFragment() { } MCFragment::MCFragment(FragmentType _Kind, MCSectionData *_Parent) - : Kind(_Kind), Parent(_Parent), Atom(0), Offset(~UINT64_C(0)) + : Kind(_Kind), Parent(_Parent), Atom(nullptr), Offset(~UINT64_C(0)) { if (Parent) Parent->getFragmentList().push_back(this); @@ -230,7 +285,7 @@ MCEncodedFragmentWithFixups::~MCEncodedFragmentWithFixups() { /* *** */ -MCSectionData::MCSectionData() : Section(0) {} +MCSectionData::MCSectionData() : Section(nullptr) {} MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A) : Section(&_Section), @@ -250,7 +305,7 @@ MCSectionData::getSubsectionInsertionPoint(unsigned Subsection) { SmallVectorImpl >::iterator MI = std::lower_bound(SubsectionFragmentMap.begin(), SubsectionFragmentMap.end(), - std::make_pair(Subsection, (MCFragment *)0)); + std::make_pair(Subsection, (MCFragment *)nullptr)); bool ExactMatch = false; if (MI != SubsectionFragmentMap.end()) { ExactMatch = MI->first == Subsection; @@ -275,13 +330,13 @@ MCSectionData::getSubsectionInsertionPoint(unsigned Subsection) { /* *** */ -MCSymbolData::MCSymbolData() : Symbol(0) {} +MCSymbolData::MCSymbolData() : Symbol(nullptr) {} MCSymbolData::MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset, MCAssembler *A) : Symbol(&_Symbol), Fragment(_Fragment), Offset(_Offset), IsExternal(false), IsPrivateExtern(false), - CommonSize(0), SymbolSize(0), CommonAlign(0), + CommonSize(0), SymbolSize(nullptr), CommonAlign(0), Flags(0), Index(0) { if (A) @@ -296,6 +351,7 @@ MCAssembler::MCAssembler(MCContext &Context_, MCAsmBackend &Backend_, : Context(Context_), Backend(Backend_), Emitter(Emitter_), Writer(Writer_), OS(OS_), BundleAlignSize(0), RelaxAll(false), NoExecStack(false), SubsectionsViaSymbols(false), ELFHeaderEFlags(0) { + VersionMinInfo.Major = 0; // Major version == 0 for "none specified" } MCAssembler::~MCAssembler() { @@ -318,6 +374,32 @@ void MCAssembler::reset() { getBackend().reset(); getEmitter().reset(); getWriter().reset(); + getLOHContainer().reset(); +} + +bool MCAssembler::isThumbFunc(const MCSymbol *Symbol) const { + if (ThumbFuncs.count(Symbol)) + return true; + + if (!Symbol->isVariable()) + return false; + + // FIXME: It looks like gas supports some cases of the form "foo + 2". It + // is not clear if that is a bug or a feature. + const MCExpr *Expr = Symbol->getVariableValue(); + const MCSymbolRefExpr *Ref = dyn_cast(Expr); + if (!Ref) + return false; + + if (Ref->getKind() != MCSymbolRefExpr::VK_None) + return false; + + const MCSymbol &Sym = Ref->getSymbol(); + if (!isThumbFunc(&Sym)) + return false; + + ThumbFuncs.insert(Symbol); // Cache it. + return true; } bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const { @@ -340,24 +422,40 @@ const MCSymbolData *MCAssembler::getAtom(const MCSymbolData *SD) const { // Absolute and undefined symbols have no defining atom. if (!SD->getFragment()) - return 0; + return nullptr; // Non-linker visible symbols in sections which can't be atomized have no // defining atom. if (!getBackend().isSectionAtomizable( SD->getFragment()->getParent()->getSection())) - return 0; + return nullptr; // Otherwise, return the atom for the containing fragment. return SD->getFragment()->getAtom(); } +// Try to fully compute Expr to an absolute value and if that fails produce +// a relocatable expr. +// FIXME: Should this be the behavior of EvaluateAsRelocatable itself? +static bool evaluate(const MCExpr &Expr, const MCAsmLayout &Layout, + const MCFixup &Fixup, MCValue &Target) { + if (Expr.EvaluateAsValue(Target, &Layout, &Fixup)) { + if (Target.isAbsolute()) + return true; + } + return Expr.EvaluateAsRelocatable(Target, &Layout, &Fixup); +} + bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, MCValue &Target, uint64_t &Value) const { ++stats::evaluateFixup; - if (!Fixup.getValue()->EvaluateAsRelocatable(Target, &Layout)) + // FIXME: This code has some duplication with RecordRelocation. We should + // probably merge the two into a single callback that tries to evaluate a + // fixup and records a relocation if one is needed. + const MCExpr *Expr = Fixup.getValue(); + if (!evaluate(*Expr, Layout, Fixup, Target)) getContext().FatalError(Fixup.getLoc(), "expected relocatable expression"); bool IsPCRel = Backend.getFixupKindInfo( @@ -701,8 +799,13 @@ void MCAssembler::writeSectionData(const MCSectionData *SD, assert(DF.fixup_begin() == DF.fixup_end() && "Cannot have fixups in virtual section!"); for (unsigned i = 0, e = DF.getContents().size(); i != e; ++i) - assert(DF.getContents()[i] == 0 && - "Invalid data value for virtual section!"); + if (DF.getContents()[i]) { + if (auto *ELFSec = dyn_cast(&SD->getSection())) + report_fatal_error("non-zero initializer found in section '" + + ELFSec->getSectionName() + "'"); + else + report_fatal_error("non-zero initializer found in virtual section"); + } break; } case MCFragment::FT_Align: @@ -734,20 +837,22 @@ void MCAssembler::writeSectionData(const MCSectionData *SD, Layout.getSectionAddressSize(SD)); } - -uint64_t MCAssembler::handleFixup(const MCAsmLayout &Layout, - MCFragment &F, - const MCFixup &Fixup) { +std::pair MCAssembler::handleFixup(const MCAsmLayout &Layout, + MCFragment &F, + const MCFixup &Fixup) { // Evaluate the fixup. MCValue Target; uint64_t FixedValue; + bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags & + MCFixupKindInfo::FKF_IsPCRel; if (!evaluateFixup(Layout, Fixup, &F, Target, FixedValue)) { // The fixup was unresolved, we need a relocation. Inform the object // writer of the relocation, and give it an opportunity to adjust the // fixup value if need be. - getWriter().RecordRelocation(*this, Layout, &F, Fixup, Target, FixedValue); + getWriter().RecordRelocation(*this, Layout, &F, Fixup, Target, IsPCRel, + FixedValue); } - return FixedValue; + return std::make_pair(FixedValue, IsPCRel); } void MCAssembler::Finish() { @@ -811,9 +916,11 @@ void MCAssembler::Finish() { for (MCEncodedFragmentWithFixups::fixup_iterator it3 = F->fixup_begin(), ie3 = F->fixup_end(); it3 != ie3; ++it3) { MCFixup &Fixup = *it3; - uint64_t FixedValue = handleFixup(Layout, *F, Fixup); + uint64_t FixedValue; + bool IsPCRel; + std::tie(FixedValue, IsPCRel) = handleFixup(Layout, *F, Fixup); getBackend().applyFixup(Fixup, F->getContents().data(), - F->getContents().size(), FixedValue); + F->getContents().size(), FixedValue, IsPCRel); } } } @@ -887,11 +994,8 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout, } bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { - int64_t Value = 0; uint64_t OldSize = LF.getContents().size(); - bool IsAbs = LF.getValue().EvaluateAsAbsolute(Value, Layout); - (void)IsAbs; - assert(IsAbs); + int64_t Value = LF.getValue().evaluateKnownAbsolute(Layout); SmallString<8> &Data = LF.getContents(); Data.clear(); raw_svector_ostream OSE(Data); @@ -906,11 +1010,8 @@ bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF) { MCContext &Context = Layout.getAssembler().getContext(); - int64_t AddrDelta = 0; uint64_t OldSize = DF.getContents().size(); - bool IsAbs = DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, Layout); - (void)IsAbs; - assert(IsAbs); + int64_t AddrDelta = DF.getAddrDelta().evaluateKnownAbsolute(Layout); int64_t LineDelta; LineDelta = DF.getLineDelta(); SmallString<8> &Data = DF.getContents(); @@ -924,11 +1025,8 @@ bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout, bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout, MCDwarfCallFrameFragment &DF) { MCContext &Context = Layout.getAssembler().getContext(); - int64_t AddrDelta = 0; uint64_t OldSize = DF.getContents().size(); - bool IsAbs = DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, Layout); - (void)IsAbs; - assert(IsAbs); + int64_t AddrDelta = DF.getAddrDelta().evaluateKnownAbsolute(Layout); SmallString<8> &Data = DF.getContents(); Data.clear(); raw_svector_ostream OSE(Data); @@ -942,7 +1040,7 @@ bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD) { // remain NULL if none were relaxed. // When a fragment is relaxed, all the fragments following it should get // invalidated because their offset is going to change. - MCFragment *FirstRelaxedFragment = NULL; + MCFragment *FirstRelaxedFragment = nullptr; // Attempt to relax all the fragments in the section. for (MCSectionData::iterator I = SD.begin(), IE = SD.end(); I != IE; ++I) { @@ -1137,7 +1235,7 @@ void MCSectionData::dump() { OS << "]>"; } -void MCSymbolData::dump() { +void MCSymbolData::dump() const { raw_ostream &OS = llvm::errs(); OS << "