aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC/MCAssembler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC/MCAssembler.cpp')
-rw-r--r--llvm/lib/MC/MCAssembler.cpp211
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;
}