diff options
Diffstat (limited to 'llvm/lib/MC/MCAssembler.cpp')
-rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 211 |
1 files changed, 114 insertions, 97 deletions
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index b30137aafb8d..3ca8714b7817 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -33,6 +33,7 @@ #include "llvm/Support/Alignment.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/EndianStream.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/MathExtras.h" @@ -217,6 +218,14 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, } assert(getBackendPtr() && "Expected assembler backend"); + bool IsTarget = getBackendPtr()->getFixupKindInfo(Fixup.getKind()).Flags & + MCFixupKindInfo::FKF_IsTarget; + + if (IsTarget) + return getBackend().evaluateTargetFixup(*this, Layout, Fixup, DF, Target, + Value, WasForced); + + unsigned FixupFlags = getBackendPtr()->getFixupKindInfo(Fixup.getKind()).Flags; bool IsPCRel = getBackendPtr()->getFixupKindInfo(Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel; @@ -232,8 +241,9 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, if (A->getKind() != MCSymbolRefExpr::VK_None || SA.isUndefined()) { IsResolved = false; } else if (auto *Writer = getWriterPtr()) { - IsResolved = Writer->isSymbolRefDifferenceFullyResolvedImpl( - *this, SA, *DF, false, true); + IsResolved = (FixupFlags & MCFixupKindInfo::FKF_Constant) || + Writer->isSymbolRefDifferenceFullyResolvedImpl( + *this, SA, *DF, false, true); } } } else { @@ -387,6 +397,9 @@ void MCAsmLayout::layoutFragment(MCFragment *F) { assert((!Prev || isFragmentValid(Prev)) && "Attempt to compute fragment before its predecessor!"); + assert(!F->IsBeingLaidOut && "Already being laid out!"); + F->IsBeingLaidOut = true; + ++stats::FragmentLayouts; // Compute fragment offset and size. @@ -394,6 +407,7 @@ void MCAsmLayout::layoutFragment(MCFragment *F) { F->Offset = Prev->Offset + getAssembler().computeFragmentSize(*this, *Prev); else F->Offset = 0; + F->IsBeingLaidOut = false; LastValidFragment[F->getParent()] = F; // If bundling is enabled and this fragment has instructions in it, it has to @@ -674,14 +688,16 @@ void MCAssembler::writeSectionData(raw_ostream &OS, const MCSection *Sec, // directives to fill the contents of virtual sections. const MCDataFragment &DF = cast<MCDataFragment>(F); if (DF.fixup_begin() != DF.fixup_end()) - report_fatal_error("cannot have fixups in virtual section!"); + getContext().reportError(SMLoc(), Sec->getVirtualSectionKind() + + " section '" + Sec->getName() + + "' cannot have fixups"); for (unsigned i = 0, e = DF.getContents().size(); i != e; ++i) if (DF.getContents()[i]) { - if (auto *ELFSec = dyn_cast<const MCSectionELF>(Sec)) - report_fatal_error("non-zero initializer found in section '" + - ELFSec->getSectionName() + "'"); - else - report_fatal_error("non-zero initializer found in virtual section"); + getContext().reportError(SMLoc(), + Sec->getVirtualSectionKind() + + " section '" + Sec->getName() + + "' cannot have non-zero initializers"); + break; } break; } @@ -776,9 +792,15 @@ void MCAssembler::layout(MCAsmLayout &Layout) { } // Layout until everything fits. - while (layoutOnce(Layout)) + while (layoutOnce(Layout)) { if (getContext().hadError()) return; + // Size of fragments in one section can depend on the size of fragments in + // another. If any fragment has changed size, we have to re-layout (and + // as a result possibly further relax) all. + for (MCSection &Sec : *this) + Layout.invalidateFragmentsFrom(&*Sec.begin()); + } DEBUG_WITH_TYPE("mc-dump", { errs() << "assembler backend - post-relaxation\n--\n"; @@ -798,48 +820,57 @@ void MCAssembler::layout(MCAsmLayout &Layout) { // Evaluate and apply the fixups, generating relocation entries as necessary. for (MCSection &Sec : *this) { for (MCFragment &Frag : Sec) { - // 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 (isa<MCEncodedFragment>(&Frag) && - isa<MCCompactEncodedInstFragment>(&Frag)) - continue; - if (!isa<MCEncodedFragment>(&Frag) && !isa<MCCVDefRangeFragment>(&Frag) && - !isa<MCAlignFragment>(&Frag)) - continue; ArrayRef<MCFixup> Fixups; MutableArrayRef<char> Contents; const MCSubtargetInfo *STI = nullptr; - if (auto *FragWithFixups = dyn_cast<MCDataFragment>(&Frag)) { - Fixups = FragWithFixups->getFixups(); - Contents = FragWithFixups->getContents(); - STI = FragWithFixups->getSubtargetInfo(); - assert(!FragWithFixups->hasInstructions() || STI != nullptr); - } else if (auto *FragWithFixups = dyn_cast<MCRelaxableFragment>(&Frag)) { - Fixups = FragWithFixups->getFixups(); - Contents = FragWithFixups->getContents(); - STI = FragWithFixups->getSubtargetInfo(); - assert(!FragWithFixups->hasInstructions() || STI != nullptr); - } else if (auto *FragWithFixups = dyn_cast<MCCVDefRangeFragment>(&Frag)) { - Fixups = FragWithFixups->getFixups(); - Contents = FragWithFixups->getContents(); - } else if (auto *FragWithFixups = dyn_cast<MCDwarfLineAddrFragment>(&Frag)) { - Fixups = FragWithFixups->getFixups(); - Contents = FragWithFixups->getContents(); - } else if (auto *AF = dyn_cast<MCAlignFragment>(&Frag)) { + + // Process MCAlignFragment and MCEncodedFragmentWithFixups here. + switch (Frag.getKind()) { + default: + continue; + case MCFragment::FT_Align: { + MCAlignFragment &AF = cast<MCAlignFragment>(Frag); // Insert fixup type for code alignment if the target define // shouldInsertFixupForCodeAlign target hook. - if (Sec.UseCodeAlign() && AF->hasEmitNops()) { - getBackend().shouldInsertFixupForCodeAlign(*this, Layout, *AF); - } + if (Sec.UseCodeAlign() && AF.hasEmitNops()) + getBackend().shouldInsertFixupForCodeAlign(*this, Layout, AF); continue; - } else if (auto *FragWithFixups = - dyn_cast<MCDwarfCallFrameFragment>(&Frag)) { - Fixups = FragWithFixups->getFixups(); - Contents = FragWithFixups->getContents(); - } else - llvm_unreachable("Unknown fragment with fixups!"); + } + case MCFragment::FT_Data: { + MCDataFragment &DF = cast<MCDataFragment>(Frag); + Fixups = DF.getFixups(); + Contents = DF.getContents(); + STI = DF.getSubtargetInfo(); + assert(!DF.hasInstructions() || STI != nullptr); + break; + } + case MCFragment::FT_Relaxable: { + MCRelaxableFragment &RF = cast<MCRelaxableFragment>(Frag); + Fixups = RF.getFixups(); + Contents = RF.getContents(); + STI = RF.getSubtargetInfo(); + assert(!RF.hasInstructions() || STI != nullptr); + break; + } + case MCFragment::FT_CVDefRange: { + MCCVDefRangeFragment &CF = cast<MCCVDefRangeFragment>(Frag); + Fixups = CF.getFixups(); + Contents = CF.getContents(); + break; + } + case MCFragment::FT_Dwarf: { + MCDwarfLineAddrFragment &DF = cast<MCDwarfLineAddrFragment>(Frag); + Fixups = DF.getFixups(); + Contents = DF.getContents(); + break; + } + case MCFragment::FT_DwarfFrame: { + MCDwarfCallFrameFragment &DF = cast<MCDwarfCallFrameFragment>(Frag); + Fixups = DF.getFixups(); + Contents = DF.getContents(); + break; + } + } for (const MCFixup &Fixup : Fixups) { uint64_t FixedValue; bool IsResolved; @@ -908,8 +939,8 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout, // Relax the fragment. - MCInst Relaxed; - getBackend().relaxInstruction(F.getInst(), *F.getSubtargetInfo(), Relaxed); + MCInst Relaxed = F.getInst(); + getBackend().relaxInstruction(Relaxed, *F.getSubtargetInfo()); // Encode the new instruction. // @@ -987,27 +1018,22 @@ static bool needPadding(uint64_t StartAddr, uint64_t Size, bool MCAssembler::relaxBoundaryAlign(MCAsmLayout &Layout, MCBoundaryAlignFragment &BF) { - // The MCBoundaryAlignFragment that doesn't emit NOP should not be relaxed. - if (!BF.canEmitNops()) + // BoundaryAlignFragment that doesn't need to align any fragment should not be + // relaxed. + if (!BF.getLastFragment()) return false; - uint64_t AlignedOffset = Layout.getFragmentOffset(BF.getNextNode()); + uint64_t AlignedOffset = Layout.getFragmentOffset(&BF); uint64_t AlignedSize = 0; - const MCFragment *F = BF.getNextNode(); - // If the branch is unfused, it is emitted into one fragment, otherwise it is - // emitted into two fragments at most, the next MCBoundaryAlignFragment(if - // exists) also marks the end of the branch. - for (auto i = 0, N = BF.isFused() ? 2 : 1; - i != N && !isa<MCBoundaryAlignFragment>(F); ++i, F = F->getNextNode()) { + for (const MCFragment *F = BF.getLastFragment(); F != &BF; + F = F->getPrevNode()) AlignedSize += computeFragmentSize(Layout, *F); - } - uint64_t OldSize = BF.getSize(); - AlignedOffset -= OldSize; + Align BoundaryAlignment = BF.getAlignment(); uint64_t NewSize = needPadding(AlignedOffset, AlignedSize, BoundaryAlignment) ? offsetToAlignment(AlignedOffset, BoundaryAlignment) : 0U; - if (NewSize == OldSize) + if (NewSize == BF.getSize()) return false; BF.setSize(NewSize); Layout.invalidateFragmentsFrom(&BF); @@ -1099,6 +1125,30 @@ bool MCAssembler::relaxCVDefRange(MCAsmLayout &Layout, return OldSize != F.getContents().size(); } +bool MCAssembler::relaxFragment(MCAsmLayout &Layout, MCFragment &F) { + switch(F.getKind()) { + default: + return false; + case MCFragment::FT_Relaxable: + assert(!getRelaxAll() && + "Did not expect a MCRelaxableFragment in RelaxAll mode"); + return relaxInstruction(Layout, cast<MCRelaxableFragment>(F)); + case MCFragment::FT_Dwarf: + return relaxDwarfLineAddr(Layout, cast<MCDwarfLineAddrFragment>(F)); + case MCFragment::FT_DwarfFrame: + return relaxDwarfCallFrameFragment(Layout, + cast<MCDwarfCallFrameFragment>(F)); + case MCFragment::FT_LEB: + return relaxLEB(Layout, cast<MCLEBFragment>(F)); + case MCFragment::FT_BoundaryAlign: + return relaxBoundaryAlign(Layout, cast<MCBoundaryAlignFragment>(F)); + case MCFragment::FT_CVInlineLines: + return relaxCVInlineLineTable(Layout, cast<MCCVInlineLineTableFragment>(F)); + case MCFragment::FT_CVDefRange: + return relaxCVDefRange(Layout, cast<MCCVDefRangeFragment>(F)); + } +} + bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec) { // Holds the first fragment which needed relaxing during this layout. It will // remain NULL if none were relaxed. @@ -1107,43 +1157,11 @@ bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec) { MCFragment *FirstRelaxedFragment = nullptr; // Attempt to relax all the fragments in the section. - for (MCSection::iterator I = Sec.begin(), IE = Sec.end(); I != IE; ++I) { + for (MCFragment &Frag : Sec) { // Check if this is a fragment that needs relaxation. - bool RelaxedFrag = false; - switch(I->getKind()) { - default: - break; - case MCFragment::FT_Relaxable: - assert(!getRelaxAll() && - "Did not expect a MCRelaxableFragment in RelaxAll mode"); - RelaxedFrag = relaxInstruction(Layout, *cast<MCRelaxableFragment>(I)); - break; - case MCFragment::FT_Dwarf: - RelaxedFrag = relaxDwarfLineAddr(Layout, - *cast<MCDwarfLineAddrFragment>(I)); - break; - case MCFragment::FT_DwarfFrame: - RelaxedFrag = - relaxDwarfCallFrameFragment(Layout, - *cast<MCDwarfCallFrameFragment>(I)); - break; - case MCFragment::FT_LEB: - RelaxedFrag = relaxLEB(Layout, *cast<MCLEBFragment>(I)); - break; - case MCFragment::FT_BoundaryAlign: - RelaxedFrag = - relaxBoundaryAlign(Layout, *cast<MCBoundaryAlignFragment>(I)); - break; - case MCFragment::FT_CVInlineLines: - RelaxedFrag = - relaxCVInlineLineTable(Layout, *cast<MCCVInlineLineTableFragment>(I)); - break; - case MCFragment::FT_CVDefRange: - RelaxedFrag = relaxCVDefRange(Layout, *cast<MCCVDefRangeFragment>(I)); - break; - } + bool RelaxedFrag = relaxFragment(Layout, Frag); if (RelaxedFrag && !FirstRelaxedFragment) - FirstRelaxedFragment = &*I; + FirstRelaxedFragment = &Frag; } if (FirstRelaxedFragment) { Layout.invalidateFragmentsFrom(FirstRelaxedFragment); @@ -1156,8 +1174,7 @@ bool MCAssembler::layoutOnce(MCAsmLayout &Layout) { ++stats::RelaxationSteps; bool WasRelaxed = false; - for (iterator it = begin(), ie = end(); it != ie; ++it) { - MCSection &Sec = *it; + for (MCSection &Sec : *this) { while (layoutSectionOnce(Layout, Sec)) WasRelaxed = true; } |