X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FMCAssembler.cpp;h=9f3ab18a40b485294b51c978834f6c9b3abb4beb;hb=0d2b021de66106051a388d6e9945ab8d147085d8;hp=ec2518c77ddbbfa4d6ae7412d16599a83eac00a6;hpb=919ce81d38ae7707ffdfba2ab775bda3b7c79db3;p=oota-llvm.git diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index ec2518c77dd..9f3ab18a40b 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -68,12 +68,12 @@ MCAsmLayout::MCAsmLayout(MCAssembler &Asm) : Assembler(Asm), LastValidFragment() { // Compute the section layout order. Virtual sections must go last. - for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) - if (!it->isVirtualSection()) - SectionOrder.push_back(&*it); - for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) - if (it->isVirtualSection()) - SectionOrder.push_back(&*it); + for (MCSection &Sec : Asm) + if (!Sec.isVirtualSection()) + SectionOrder.push_back(&Sec); + for (MCSection &Sec : Asm) + if (Sec.isVirtualSection()) + SectionOrder.push_back(&Sec); } bool MCAsmLayout::isFragmentValid(const MCFragment *F) const { @@ -97,17 +97,17 @@ void MCAsmLayout::invalidateFragmentsFrom(MCFragment *F) { void MCAsmLayout::ensureValid(const MCFragment *F) const { MCSection *Sec = F->getParent(); - MCFragment *Cur = LastValidFragment[Sec]; - if (!Cur) - Cur = Sec->begin(); + MCSection::iterator I; + if (MCFragment *Cur = LastValidFragment[Sec]) + I = ++MCSection::iterator(Cur); else - Cur = Cur->getNextNode(); + I = Sec->begin(); // Advance the layout position until the fragment is valid. while (!isFragmentValid(F)) { - assert(Cur && "Layout bookkeeping error"); - const_cast(this)->layoutFragment(Cur); - Cur = Cur->getNextNode(); + assert(I != Sec->end() && "Layout bookkeeping error"); + const_cast(this)->layoutFragment(&*I); + ++I; } } @@ -120,14 +120,13 @@ uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const { // Simple getSymbolOffset helper for the non-varibale case. static bool getLabelOffset(const MCAsmLayout &Layout, const MCSymbol &S, bool ReportError, uint64_t &Val) { - const MCSymbolData &SD = S.getData(); - if (!SD.getFragment()) { + if (!S.getFragment()) { if (ReportError) report_fatal_error("unable to evaluate offset to undefined symbol '" + S.getName() + "'"); return false; } - Val = Layout.getFragmentOffset(SD.getFragment()) + SD.getOffset(); + Val = Layout.getFragmentOffset(S.getFragment()) + S.getOffset(); return true; } @@ -138,7 +137,7 @@ static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, const MCSymbol &S, // If SD is a variable, evaluate it. MCValue Target; - if (!S.getVariableValue()->EvaluateAsRelocatable(Target, &Layout, nullptr)) + if (!S.getVariableValue()->evaluateAsValue(Target, Layout)) report_fatal_error("unable to evaluate offset for variable '" + S.getName() + "'"); @@ -180,14 +179,19 @@ const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const { const MCExpr *Expr = Symbol.getVariableValue(); MCValue Value; - if (!Expr->evaluateAsValue(Value, *this)) - llvm_unreachable("Invalid Expression"); + if (!Expr->evaluateAsValue(Value, *this)) { + Assembler.getContext().reportError( + SMLoc(), "expression could not be evaluated"); + return nullptr; + } const MCSymbolRefExpr *RefB = Value.getSymB(); - if (RefB) - Assembler.getContext().reportFatalError( + if (RefB) { + Assembler.getContext().reportError( SMLoc(), Twine("symbol '") + RefB->getSymbol().getName() + "' could not be evaluated in a subtraction expression"); + return nullptr; + } const MCSymbolRefExpr *A = Value.getSymA(); if (!A) @@ -195,12 +199,12 @@ const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const { const MCSymbol &ASym = A->getSymbol(); const MCAssembler &Asm = getAssembler(); - const MCSymbolData &ASD = Asm.getSymbolData(ASym); - if (ASD.isCommon()) { + if (ASym.isCommon()) { // FIXME: we should probably add a SMLoc to MCExpr. - Asm.getContext().reportFatalError(SMLoc(), - "Common symbol " + ASym.getName() + - " cannot be used in assignment expr"); + Asm.getContext().reportError(SMLoc(), + "Common symbol '" + ASym.getName() + + "' cannot be used in assignment expr"); + return nullptr; } return &ASym; @@ -256,7 +260,7 @@ uint64_t llvm::computeBundlePadding(const MCAssembler &Assembler, else { // EndOfFragment > BundleSize return 2 * BundleSize - EndOfFragment; } - } else if (EndOfFragment > BundleSize) + } else if (OffsetInBundle > 0 && EndOfFragment > BundleSize) return BundleSize - OffsetInBundle; else return 0; @@ -264,40 +268,76 @@ uint64_t llvm::computeBundlePadding(const MCAssembler &Assembler, /* *** */ -MCFragment::MCFragment() : Kind(FragmentType(~0)) { +void ilist_node_traits::deleteNode(MCFragment *V) { + V->destroy(); } -MCFragment::~MCFragment() { +MCFragment::MCFragment() : Kind(FragmentType(~0)), HasInstructions(false), + AlignToBundleEnd(false), BundlePadding(0) { } -MCFragment::MCFragment(FragmentType Kind, MCSection *Parent) - : Kind(Kind), Parent(Parent), Atom(nullptr), Offset(~UINT64_C(0)) { - if (Parent) - Parent->getFragmentList().push_back(this); -} - -/* *** */ +MCFragment::~MCFragment() { } -MCEncodedFragment::~MCEncodedFragment() { +MCFragment::MCFragment(FragmentType Kind, bool HasInstructions, + uint8_t BundlePadding, MCSection *Parent) + : Kind(Kind), HasInstructions(HasInstructions), AlignToBundleEnd(false), + BundlePadding(BundlePadding), Parent(Parent), Atom(nullptr), + Offset(~UINT64_C(0)) { + if (Parent && !isDummy()) + Parent->getFragmentList().push_back(this); } -/* *** */ +void MCFragment::destroy() { + // First check if we are the sentinal. + if (Kind == FragmentType(~0)) { + delete this; + return; + } -MCEncodedFragmentWithFixups::~MCEncodedFragmentWithFixups() { + switch (Kind) { + case FT_Align: + delete cast(this); + return; + case FT_Data: + delete cast(this); + return; + case FT_CompactEncodedInst: + delete cast(this); + return; + case FT_Fill: + delete cast(this); + return; + case FT_Relaxable: + delete cast(this); + return; + case FT_Org: + delete cast(this); + return; + case FT_Dwarf: + delete cast(this); + return; + case FT_DwarfFrame: + delete cast(this); + return; + case FT_LEB: + delete cast(this); + return; + case FT_SafeSEH: + delete cast(this); + return; + case FT_Dummy: + delete cast(this); + return; + } } /* *** */ -MCSectionData::MCSectionData(MCSection &Section) : Section(&Section) {} - -/* *** */ - MCAssembler::MCAssembler(MCContext &Context_, MCAsmBackend &Backend_, - MCCodeEmitter &Emitter_, MCObjectWriter &Writer_, - raw_ostream &OS_) + MCCodeEmitter &Emitter_, MCObjectWriter &Writer_) : Context(Context_), Backend(Backend_), Emitter(Emitter_), Writer(Writer_), - OS(OS_), BundleAlignSize(0), RelaxAll(false), - SubsectionsViaSymbols(false), ELFHeaderEFlags(0) { + BundleAlignSize(0), RelaxAll(false), SubsectionsViaSymbols(false), + ELFHeaderEFlags(0) { VersionMinInfo.Major = 0; // Major version == 0 for "none specified" } @@ -326,6 +366,14 @@ void MCAssembler::reset() { getLOHContainer().reset(); } +bool MCAssembler::registerSection(MCSection &Section) { + if (Section.isRegistered()) + return false; + Sections.push_back(&Section); + Section.setIsRegistered(true); + return true; +} + bool MCAssembler::isThumbFunc(const MCSymbol *Symbol) const { if (ThumbFuncs.count(Symbol)) return true; @@ -351,16 +399,6 @@ bool MCAssembler::isThumbFunc(const MCSymbol *Symbol) const { return true; } -void MCAssembler::addLocalUsedInReloc(const MCSymbol &Sym) { - assert(Sym.isTemporary()); - LocalsUsedInReloc.insert(&Sym); -} - -bool MCAssembler::isLocalUsedInReloc(const MCSymbol &Sym) const { - assert(Sym.isTemporary()); - return LocalsUsedInReloc.count(&Sym); -} - bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const { // Non-temporary labels should always be visible to the linker. if (!Symbol.isTemporary()) @@ -370,7 +408,7 @@ bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const { if (!Symbol.isInSection()) return false; - if (isLocalUsedInReloc(Symbol)) + if (Symbol.isUsedInReloc()) return true; return false; @@ -382,17 +420,17 @@ const MCSymbol *MCAssembler::getAtom(const MCSymbol &S) const { return &S; // Absolute and undefined symbols have no defining atom. - if (!S.getData().getFragment()) + if (!S.isInSection()) return nullptr; // Non-linker visible symbols in sections which can't be atomized have no // defining atom. if (!getContext().getAsmInfo()->isSectionAtomizableBySymbols( - *S.getData().getFragment()->getParent())) + *S.getFragment()->getParent())) return nullptr; // Otherwise, return the atom for the containing fragment. - return S.getData().getFragment()->getAtom(); + return S.getFragment()->getAtom(); } bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, @@ -400,12 +438,17 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, MCValue &Target, uint64_t &Value) const { ++stats::evaluateFixup; - // FIXME: This code has some duplication with RecordRelocation. We should + // 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 (!Expr->EvaluateAsRelocatable(Target, &Layout, &Fixup)) - getContext().reportFatalError(Fixup.getLoc(), "expected relocatable expression"); + if (!Expr->evaluateAsRelocatable(Target, &Layout, &Fixup)) { + getContext().reportError(Fixup.getLoc(), "expected relocatable expression"); + // Claim to have completely evaluated the fixup, to prevent any further + // processing from being done. + Value = 0; + return true; + } bool IsPCRel = Backend.getFixupKindInfo( Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel; @@ -422,7 +465,7 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, if (A->getKind() != MCSymbolRefExpr::VK_None || SA.isUndefined()) { IsResolved = false; } else { - IsResolved = getWriter().IsSymbolRefDifferenceFullyResolvedImpl( + IsResolved = getWriter().isSymbolRefDifferenceFullyResolvedImpl( *this, SA, *DF, false, true); } } @@ -470,15 +513,20 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, const MCFragment &F) const { switch (F.getKind()) { case MCFragment::FT_Data: + return cast(F).getContents().size(); case MCFragment::FT_Relaxable: + return cast(F).getContents().size(); case MCFragment::FT_CompactEncodedInst: - return cast(F).getContents().size(); + return cast(F).getContents().size(); case MCFragment::FT_Fill: return cast(F).getSize(); case MCFragment::FT_LEB: return cast(F).getContents().size(); + case MCFragment::FT_SafeSEH: + return 4; + case MCFragment::FT_Align: { const MCAlignFragment &AF = cast(F); unsigned Offset = Layout.getFragmentOffset(&AF); @@ -496,12 +544,19 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, case MCFragment::FT_Org: { const MCOrgFragment &OF = cast(F); - int64_t TargetLocation; - if (!OF.getOffset().EvaluateAsAbsolute(TargetLocation, Layout)) + MCValue Value; + if (!OF.getOffset().evaluateAsValue(Value, Layout)) report_fatal_error("expected assembly-time absolute expression"); // FIXME: We need a way to communicate this error. uint64_t FragmentOffset = Layout.getFragmentOffset(&OF); + int64_t TargetLocation = Value.getConstant(); + if (const MCSymbolRefExpr *A = Value.getSymA()) { + uint64_t Val; + if (!Layout.getSymbolOffset(A->getSymbol(), Val)) + report_fatal_error("expected absolute expression"); + TargetLocation += Val; + } int64_t Size = TargetLocation - FragmentOffset; if (Size < 0 || Size >= 0x40000000) report_fatal_error("invalid .org offset '" + Twine(TargetLocation) + @@ -513,6 +568,8 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, return cast(F).getContents().size(); case MCFragment::FT_DwarfFrame: return cast(F).getContents().size(); + case MCFragment::FT_Dummy: + llvm_unreachable("Should not have been added"); } llvm_unreachable("invalid fragment kind"); @@ -554,16 +611,22 @@ void MCAsmLayout::layoutFragment(MCFragment *F) { // size won't include the padding. // // When the -mc-relax-all flag is used, we optimize bundling by writting the - // bundle padding directly into fragments when the instructions are emitted - // inside the streamer. + // padding directly into fragments when the instructions are emitted inside + // the streamer. When the fragment is larger than the bundle size, we need to + // ensure that it's bundle aligned. This means that if we end up with + // multiple fragments, we must emit bundle padding between fragments. // - if (Assembler.isBundlingEnabled() && !Assembler.getRelaxAll() && - F->hasInstructions()) { + // ".align N" is an example of a directive that introduces multiple + // fragments. We could add a special case to handle ".align N" by emitting + // within-fragment padding (which would produce less padding when N is less + // than the bundle size), but for now we don't. + // + if (Assembler.isBundlingEnabled() && F->hasInstructions()) { assert(isa(F) && "Only MCEncodedFragment implementations have instructions"); uint64_t FSize = Assembler.computeFragmentSize(*this, *F); - if (FSize > Assembler.getBundleAlignSize()) + if (!Assembler.getRelaxAll() && FSize > Assembler.getBundleAlignSize()) report_fatal_error("Fragment can't be larger than a bundle size"); uint64_t RequiredBundlePadding = computeBundlePadding(Assembler, F, @@ -575,11 +638,14 @@ void MCAsmLayout::layoutFragment(MCFragment *F) { } } -/// \brief Write the contents of a fragment to the given object writer. Expects -/// a MCEncodedFragment. -static void writeFragmentContents(const MCFragment &F, MCObjectWriter *OW) { - const MCEncodedFragment &EF = cast(F); - OW->WriteBytes(EF.getContents()); +void MCAssembler::registerSymbol(const MCSymbol &Symbol, bool *Created) { + bool New = !Symbol.isRegistered(); + if (Created) + *Created = New; + if (New) { + Symbol.setIsRegistered(true); + Symbols.push_back(&Symbol); + } } void MCAssembler::writeFragmentPadding(const MCFragment &F, uint64_t FSize, @@ -663,10 +729,10 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, for (uint64_t i = 0; i != Count; ++i) { switch (AF.getValueSize()) { default: llvm_unreachable("Invalid size!"); - case 1: OW->Write8 (uint8_t (AF.getValue())); break; - case 2: OW->Write16(uint16_t(AF.getValue())); break; - case 4: OW->Write32(uint32_t(AF.getValue())); break; - case 8: OW->Write64(uint64_t(AF.getValue())); break; + case 1: OW->write8 (uint8_t (AF.getValue())); break; + case 2: OW->write16(uint16_t(AF.getValue())); break; + case 4: OW->write32(uint32_t(AF.getValue())); break; + case 8: OW->write64(uint64_t(AF.getValue())); break; } } break; @@ -674,17 +740,17 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, case MCFragment::FT_Data: ++stats::EmittedDataFragments; - writeFragmentContents(F, OW); + OW->writeBytes(cast(F).getContents()); break; case MCFragment::FT_Relaxable: ++stats::EmittedRelaxableFragments; - writeFragmentContents(F, OW); + OW->writeBytes(cast(F).getContents()); break; case MCFragment::FT_CompactEncodedInst: ++stats::EmittedCompactEncodedInstFragments; - writeFragmentContents(F, OW); + OW->writeBytes(cast(F).getContents()); break; case MCFragment::FT_Fill: { @@ -696,10 +762,10 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, for (uint64_t i = 0, e = FF.getSize() / FF.getValueSize(); i != e; ++i) { switch (FF.getValueSize()) { default: llvm_unreachable("Invalid size!"); - case 1: OW->Write8 (uint8_t (FF.getValue())); break; - case 2: OW->Write16(uint16_t(FF.getValue())); break; - case 4: OW->Write32(uint32_t(FF.getValue())); break; - case 8: OW->Write64(uint64_t(FF.getValue())); break; + case 1: OW->write8 (uint8_t (FF.getValue())); break; + case 2: OW->write16(uint16_t(FF.getValue())); break; + case 4: OW->write32(uint32_t(FF.getValue())); break; + case 8: OW->write64(uint64_t(FF.getValue())); break; } } break; @@ -707,7 +773,13 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, case MCFragment::FT_LEB: { const MCLEBFragment &LF = cast(F); - OW->WriteBytes(LF.getContents()); + OW->writeBytes(LF.getContents()); + break; + } + + case MCFragment::FT_SafeSEH: { + const MCSafeSEHFragment &SF = cast(F); + OW->write32(SF.getSymbol()->getIndex()); break; } @@ -716,21 +788,23 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCOrgFragment &OF = cast(F); for (uint64_t i = 0, e = FragmentSize; i != e; ++i) - OW->Write8(uint8_t(OF.getValue())); + OW->write8(uint8_t(OF.getValue())); break; } case MCFragment::FT_Dwarf: { const MCDwarfLineAddrFragment &OF = cast(F); - OW->WriteBytes(OF.getContents()); + OW->writeBytes(OF.getContents()); break; } case MCFragment::FT_DwarfFrame: { const MCDwarfCallFrameFragment &CF = cast(F); - OW->WriteBytes(CF.getContents()); + OW->writeBytes(CF.getContents()); break; } + case MCFragment::FT_Dummy: + llvm_unreachable("Should not have been added"); } assert(OW->getStream().tell() - Start == FragmentSize && @@ -744,15 +818,14 @@ void MCAssembler::writeSectionData(const MCSection *Sec, assert(Layout.getSectionFileSize(Sec) == 0 && "Invalid size for section!"); // Check that contents are only things legal inside a virtual section. - for (MCSectionData::const_iterator it = Sec->begin(), ie = Sec->end(); - it != ie; ++it) { - switch (it->getKind()) { + for (const MCFragment &F : *Sec) { + switch (F.getKind()) { default: llvm_unreachable("Invalid fragment in virtual section!"); case MCFragment::FT_Data: { // Check that we aren't trying to write a non-zero contents (or fixups) // into a virtual section. This is to support clients which use standard // directives to fill the contents of virtual sections. - const MCDataFragment &DF = cast(*it); + const MCDataFragment &DF = cast(F); assert(DF.fixup_begin() == DF.fixup_end() && "Cannot have fixups in virtual section!"); for (unsigned i = 0, e = DF.getContents().size(); i != e; ++i) @@ -768,13 +841,13 @@ void MCAssembler::writeSectionData(const MCSection *Sec, case MCFragment::FT_Align: // Check that we aren't trying to write a non-zero value into a virtual // section. - assert((cast(it)->getValueSize() == 0 || - cast(it)->getValue() == 0) && + assert((cast(F).getValueSize() == 0 || + cast(F).getValue() == 0) && "Invalid align in virtual section!"); break; case MCFragment::FT_Fill: - assert((cast(it)->getValueSize() == 0 || - cast(it)->getValue() == 0) && + assert((cast(F).getValueSize() == 0 || + cast(F).getValue() == 0) && "Invalid fill in virtual section!"); break; } @@ -786,9 +859,8 @@ void MCAssembler::writeSectionData(const MCSection *Sec, uint64_t Start = getWriter().getStream().tell(); (void)Start; - for (MCSectionData::const_iterator it = Sec->begin(), ie = Sec->end(); - it != ie; ++it) - writeFragment(*this, Layout, *it); + for (const MCFragment &F : *Sec) + writeFragment(*this, Layout, F); assert(getWriter().getStream().tell() - Start == Layout.getSectionAddressSize(Sec)); @@ -806,29 +878,26 @@ std::pair MCAssembler::handleFixup(const MCAsmLayout &Layout, // 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, IsPCRel, + getWriter().recordRelocation(*this, Layout, &F, Fixup, Target, IsPCRel, FixedValue); } return std::make_pair(FixedValue, IsPCRel); } -void MCAssembler::Finish() { +void MCAssembler::layout(MCAsmLayout &Layout) { DEBUG_WITH_TYPE("mc-dump", { llvm::errs() << "assembler backend - pre-layout\n--\n"; dump(); }); - // Create the layout object. - MCAsmLayout Layout(*this); - // Create dummy fragments and assign section ordinals. unsigned SectionIndex = 0; - for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it) { + for (MCSection &Sec : *this) { // Create dummy fragments to eliminate any empty sections, this simplifies // layout. - if (it->getFragmentList().empty()) - new MCDataFragment(&*it); + if (Sec.getFragmentList().empty()) + new MCDataFragment(&Sec); - it->setOrdinal(SectionIndex++); + Sec.setOrdinal(SectionIndex++); } // Assign layout order indices to sections and fragments. @@ -837,9 +906,8 @@ void MCAssembler::Finish() { Sec->setLayoutOrder(i); unsigned FragmentIndex = 0; - for (MCSectionData::iterator iFrag = Sec->begin(), iFragEnd = Sec->end(); - iFrag != iFragEnd; ++iFrag) - iFrag->setLayoutOrder(FragmentIndex++); + for (MCFragment &Frag : *Sec) + Frag.setLayoutOrder(FragmentIndex++); } // Layout until everything fits. @@ -857,34 +925,51 @@ void MCAssembler::Finish() { llvm::errs() << "assembler backend - final-layout\n--\n"; dump(); }); - uint64_t StartOffset = OS.tell(); - // Allow the object writer a chance to perform post-layout binding (for // example, to set the index fields in the symbol data). - getWriter().ExecutePostLayoutBinding(*this, Layout); + getWriter().executePostLayoutBinding(*this, Layout); // Evaluate and apply the fixups, generating relocation entries as necessary. - for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it) { - for (MCSectionData::iterator it2 = it->begin(), - ie2 = it->end(); it2 != ie2; ++it2) { - MCEncodedFragmentWithFixups *F = - dyn_cast(it2); - if (F) { - for (MCEncodedFragmentWithFixups::fixup_iterator it3 = F->fixup_begin(), - ie3 = F->fixup_end(); it3 != ie3; ++it3) { - MCFixup &Fixup = *it3; - uint64_t FixedValue; - bool IsPCRel; - std::tie(FixedValue, IsPCRel) = handleFixup(Layout, *F, Fixup); - getBackend().applyFixup(Fixup, F->getContents().data(), - F->getContents().size(), FixedValue, IsPCRel); - } + for (MCSection &Sec : *this) { + for (MCFragment &Frag : Sec) { + MCEncodedFragment *F = dyn_cast(&Frag); + // Data and relaxable fragments both have fixups. So only process + // those here. + // FIXME: Is there a better way to do this? MCEncodedFragmentWithFixups + // being templated makes this tricky. + if (!F || isa(F)) + continue; + ArrayRef Fixups; + MutableArrayRef Contents; + if (auto *FragWithFixups = dyn_cast(F)) { + Fixups = FragWithFixups->getFixups(); + Contents = FragWithFixups->getContents(); + } else if (auto *FragWithFixups = dyn_cast(F)) { + Fixups = FragWithFixups->getFixups(); + Contents = FragWithFixups->getContents(); + } else + llvm_unreachable("Unknown fragment with fixups!"); + for (const MCFixup &Fixup : Fixups) { + uint64_t FixedValue; + bool IsPCRel; + std::tie(FixedValue, IsPCRel) = handleFixup(Layout, *F, Fixup); + getBackend().applyFixup(Fixup, Contents.data(), + Contents.size(), FixedValue, IsPCRel); } } } +} + +void MCAssembler::Finish() { + // Create the layout object. + MCAsmLayout Layout(*this); + layout(Layout); + + raw_ostream &OS = getWriter().getStream(); + uint64_t StartOffset = OS.tell(); // Write the object file. - getWriter().WriteObject(*this, Layout); + getWriter().writeObject(*this, Layout); stats::ObjectBytes += OS.tell() - StartOffset; } @@ -892,13 +977,11 @@ void MCAssembler::Finish() { bool MCAssembler::fixupNeedsRelaxation(const MCFixup &Fixup, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const { - // If we cannot resolve the fixup value, it requires relaxation. MCValue Target; uint64_t Value; - if (!evaluateFixup(Layout, Fixup, DF, Target, Value)) - return true; - - return getBackend().fixupNeedsRelaxation(Fixup, Value, DF, Layout); + bool Resolved = evaluateFixup(Layout, Fixup, DF, Target, Value); + return getBackend().fixupNeedsRelaxationAdvanced(Fixup, Resolved, Value, DF, + Layout); } bool MCAssembler::fragmentNeedsRelaxation(const MCRelaxableFragment *F, @@ -909,9 +992,8 @@ bool MCAssembler::fragmentNeedsRelaxation(const MCRelaxableFragment *F, if (!getBackend().mayNeedRelaxation(F->getInst())) return false; - for (MCRelaxableFragment::const_fixup_iterator it = F->fixup_begin(), - ie = F->fixup_end(); it != ie; ++it) - if (fixupNeedsRelaxation(*it, F, Layout)) + for (const MCFixup &Fixup : F->getFixups()) + if (fixupNeedsRelaxation(Fixup, F, Layout)) return true; return false; @@ -940,7 +1022,6 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout, SmallString<256> Code; raw_svector_ostream VecOS(Code); getEmitter().encodeInstruction(Relaxed, VecOS, Fixups, F.getSubtargetInfo()); - VecOS.flush(); // Update the fragment. F.setInst(Relaxed); @@ -963,7 +1044,6 @@ bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { encodeSLEB128(Value, OSE); else encodeULEB128(Value, OSE); - OSE.flush(); return OldSize != LF.getContents().size(); } @@ -980,8 +1060,8 @@ bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout, SmallString<8> &Data = DF.getContents(); Data.clear(); raw_svector_ostream OSE(Data); - MCDwarfLineAddr::Encode(Context, LineDelta, AddrDelta, OSE); - OSE.flush(); + MCDwarfLineAddr::Encode(Context, getDWARFLinetableParams(), LineDelta, + AddrDelta, OSE); return OldSize != Data.size(); } @@ -997,7 +1077,6 @@ bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout, Data.clear(); raw_svector_ostream OSE(Data); MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OSE); - OSE.flush(); return OldSize != Data.size(); } @@ -1009,7 +1088,7 @@ bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec) { MCFragment *FirstRelaxedFragment = nullptr; // Attempt to relax all the fragments in the section. - for (MCSectionData::iterator I = Sec.begin(), IE = Sec.end(); I != IE; ++I) { + for (MCSection::iterator I = Sec.begin(), IE = Sec.end(); I != IE; ++I) { // Check if this is a fragment that needs relaxation. bool RelaxedFrag = false; switch(I->getKind()) { @@ -1034,7 +1113,7 @@ bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec) { break; } if (RelaxedFrag && !FirstRelaxedFragment) - FirstRelaxedFragment = I; + FirstRelaxedFragment = &*I; } if (FirstRelaxedFragment) { Layout.invalidateFragmentsFrom(FirstRelaxedFragment); @@ -1092,6 +1171,10 @@ void MCFragment::dump() { case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break; case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break; case MCFragment::FT_LEB: OS << "MCLEBFragment"; break; + case MCFragment::FT_SafeSEH: OS << "MCSafeSEHFragment"; break; + case MCFragment::FT_Dummy: + OS << "MCDummyFragment"; + break; } OS << "getValue() << " Signed:" << LF->isSigned(); break; } + case MCFragment::FT_SafeSEH: { + const MCSafeSEHFragment *F = cast(this); + OS << "\n "; + OS << " Sym:" << F->getSymbol(); + break; } - OS << ">"; -} - -void MCSectionData::dump() { - raw_ostream &OS = llvm::errs(); - - OS << "dump(); + case MCFragment::FT_Dummy: + break; } - OS << "]>"; -} - -void MCSymbolData::dump() const { - raw_ostream &OS = llvm::errs(); - - OS << ""; } @@ -1225,7 +1286,7 @@ void MCAssembler::dump() { OS << " Sections:[\n "; for (iterator it = begin(), ie = end(); it != ie; ++it) { if (it != begin()) OS << ",\n "; - it->getSectionData().dump(); + it->dump(); } OS << "],\n"; OS << " Symbols:["; @@ -1235,22 +1296,8 @@ void MCAssembler::dump() { OS << "("; it->dump(); OS << ", Index:" << it->getIndex() << ", "; - it->getData().dump(); OS << ")"; } OS << "]>\n"; } #endif - -// anchors for MC*Fragment vtables -void MCEncodedFragment::anchor() { } -void MCEncodedFragmentWithFixups::anchor() { } -void MCDataFragment::anchor() { } -void MCCompactEncodedInstFragment::anchor() { } -void MCRelaxableFragment::anchor() { } -void MCAlignFragment::anchor() { } -void MCFillFragment::anchor() { } -void MCOrgFragment::anchor() { } -void MCLEBFragment::anchor() { } -void MCDwarfLineAddrFragment::anchor() { } -void MCDwarfCallFrameFragment::anchor() { }