summaryrefslogtreecommitdiff
path: root/lib/MC/MCAssembler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MC/MCAssembler.cpp')
-rw-r--r--lib/MC/MCAssembler.cpp280
1 files changed, 193 insertions, 87 deletions
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 01d165944bec..1470e026d985 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -83,9 +83,12 @@ STATISTIC(PaddingFragmentsBytes,
/* *** */
-MCAssembler::MCAssembler(MCContext &Context, MCAsmBackend &Backend,
- MCCodeEmitter &Emitter, MCObjectWriter &Writer)
- : Context(Context), Backend(Backend), Emitter(Emitter), Writer(Writer),
+MCAssembler::MCAssembler(MCContext &Context,
+ std::unique_ptr<MCAsmBackend> Backend,
+ std::unique_ptr<MCCodeEmitter> Emitter,
+ std::unique_ptr<MCObjectWriter> Writer)
+ : Context(Context), Backend(std::move(Backend)),
+ Emitter(std::move(Emitter)), Writer(std::move(Writer)),
BundleAlignSize(0), RelaxAll(false), SubsectionsViaSymbols(false),
IncrementalLinkerCompatible(false), ELFHeaderEFlags(0) {
VersionInfo.Major = 0; // Major version == 0 for "none specified"
@@ -110,9 +113,12 @@ void MCAssembler::reset() {
VersionInfo.Major = 0;
// reset objects owned by us
- getBackend().reset();
- getEmitter().reset();
- getWriter().reset();
+ if (getBackendPtr())
+ getBackendPtr()->reset();
+ if (getEmitterPtr())
+ getEmitterPtr()->reset();
+ if (getWriterPtr())
+ getWriterPtr()->reset();
getLOHContainer().reset();
}
@@ -191,7 +197,8 @@ const MCSymbol *MCAssembler::getAtom(const MCSymbol &S) const {
bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
const MCFixup &Fixup, const MCFragment *DF,
- MCValue &Target, uint64_t &Value) const {
+ MCValue &Target, uint64_t &Value,
+ bool &WasForced) const {
++stats::evaluateFixup;
// FIXME: This code has some duplication with recordRelocation. We should
@@ -203,6 +210,7 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
const MCExpr *Expr = Fixup.getValue();
MCContext &Ctx = getContext();
Value = 0;
+ WasForced = false;
if (!Expr->evaluateAsRelocatable(Target, &Layout, &Fixup)) {
Ctx.reportError(Fixup.getLoc(), "expected relocatable expression");
return true;
@@ -215,10 +223,11 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
}
}
- bool IsPCRel = Backend.getFixupKindInfo(
- Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel;
+ assert(getBackendPtr() && "Expected assembler backend");
+ bool IsPCRel = getBackendPtr()->getFixupKindInfo(Fixup.getKind()).Flags &
+ MCFixupKindInfo::FKF_IsPCRel;
- bool IsResolved;
+ bool IsResolved = false;
if (IsPCRel) {
if (Target.getSymB()) {
IsResolved = false;
@@ -229,8 +238,8 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
const MCSymbol &SA = A->getSymbol();
if (A->getKind() != MCSymbolRefExpr::VK_None || SA.isUndefined()) {
IsResolved = false;
- } else {
- IsResolved = getWriter().isSymbolRefDifferenceFullyResolvedImpl(
+ } else if (auto *Writer = getWriterPtr()) {
+ IsResolved = Writer->isSymbolRefDifferenceFullyResolvedImpl(
*this, SA, *DF, false, true);
}
}
@@ -251,8 +260,8 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
Value -= Layout.getSymbolOffset(Sym);
}
- bool ShouldAlignPC = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
- MCFixupKindInfo::FKF_IsAlignedDownTo32Bits;
+ bool ShouldAlignPC = getBackend().getFixupKindInfo(Fixup.getKind()).Flags &
+ MCFixupKindInfo::FKF_IsAlignedDownTo32Bits;
assert((ShouldAlignPC ? IsPCRel : true) &&
"FKF_IsAlignedDownTo32Bits is only allowed on PC-relative fixups!");
@@ -266,14 +275,17 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
}
// Let the backend force a relocation if needed.
- if (IsResolved && Backend.shouldForceRelocation(*this, Fixup, Target))
+ if (IsResolved && getBackend().shouldForceRelocation(*this, Fixup, Target)) {
IsResolved = false;
+ WasForced = true;
+ }
return IsResolved;
}
uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
const MCFragment &F) const {
+ assert(getBackendPtr() && "Requires assembler backend");
switch (F.getKind()) {
case MCFragment::FT_Data:
return cast<MCDataFragment>(F).getContents().size();
@@ -281,8 +293,21 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
return cast<MCRelaxableFragment>(F).getContents().size();
case MCFragment::FT_CompactEncodedInst:
return cast<MCCompactEncodedInstFragment>(F).getContents().size();
- case MCFragment::FT_Fill:
- return cast<MCFillFragment>(F).getSize();
+ case MCFragment::FT_Fill: {
+ auto &FF = cast<MCFillFragment>(F);
+ int64_t NumValues = 0;
+ if (!FF.getNumValues().evaluateAsAbsolute(NumValues, Layout)) {
+ getContext().reportError(FF.getLoc(),
+ "expected assembly-time absolute expression");
+ return 0;
+ }
+ int64_t Size = NumValues * FF.getValueSize();
+ if (Size < 0) {
+ getContext().reportError(FF.getLoc(), "invalid number of bytes");
+ return 0;
+ }
+ return Size;
+ }
case MCFragment::FT_LEB:
return cast<MCLEBFragment>(F).getContents().size();
@@ -401,17 +426,18 @@ void MCAsmLayout::layoutFragment(MCFragment *F) {
if (Assembler.isBundlingEnabled() && F->hasInstructions()) {
assert(isa<MCEncodedFragment>(F) &&
"Only MCEncodedFragment implementations have instructions");
- uint64_t FSize = Assembler.computeFragmentSize(*this, *F);
+ MCEncodedFragment *EF = cast<MCEncodedFragment>(F);
+ uint64_t FSize = Assembler.computeFragmentSize(*this, *EF);
if (!Assembler.getRelaxAll() && FSize > Assembler.getBundleAlignSize())
report_fatal_error("Fragment can't be larger than a bundle size");
- uint64_t RequiredBundlePadding = computeBundlePadding(Assembler, F,
- F->Offset, FSize);
+ uint64_t RequiredBundlePadding =
+ computeBundlePadding(Assembler, EF, EF->Offset, FSize);
if (RequiredBundlePadding > UINT8_MAX)
report_fatal_error("Padding cannot exceed 255 bytes");
- F->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding));
- F->Offset += RequiredBundlePadding;
+ EF->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding));
+ EF->Offset += RequiredBundlePadding;
}
}
@@ -425,18 +451,20 @@ void MCAssembler::registerSymbol(const MCSymbol &Symbol, bool *Created) {
}
}
-void MCAssembler::writeFragmentPadding(const MCFragment &F, uint64_t FSize,
- MCObjectWriter *OW) const {
+void MCAssembler::writeFragmentPadding(raw_ostream &OS,
+ const MCEncodedFragment &EF,
+ uint64_t FSize) const {
+ assert(getBackendPtr() && "Expected assembler backend");
// Should NOP padding be written out before this fragment?
- unsigned BundlePadding = F.getBundlePadding();
+ unsigned BundlePadding = EF.getBundlePadding();
if (BundlePadding > 0) {
assert(isBundlingEnabled() &&
"Writing bundle padding with disabled bundling");
- assert(F.hasInstructions() &&
+ assert(EF.hasInstructions() &&
"Writing bundle padding for a fragment without instructions");
unsigned TotalLength = BundlePadding + static_cast<unsigned>(FSize);
- if (F.alignToBundleEnd() && TotalLength > getBundleAlignSize()) {
+ if (EF.alignToBundleEnd() && TotalLength > getBundleAlignSize()) {
// If the padding itself crosses a bundle boundary, it must be emitted
// in 2 pieces, since even nop instructions must not cross boundaries.
// v--------------v <- BundleAlignSize
@@ -446,30 +474,31 @@ void MCAssembler::writeFragmentPadding(const MCFragment &F, uint64_t FSize,
// ----------------------------
// ^-------------------^ <- TotalLength
unsigned DistanceToBoundary = TotalLength - getBundleAlignSize();
- if (!getBackend().writeNopData(DistanceToBoundary, OW))
- report_fatal_error("unable to write NOP sequence of " +
- Twine(DistanceToBoundary) + " bytes");
+ if (!getBackend().writeNopData(OS, DistanceToBoundary))
+ report_fatal_error("unable to write NOP sequence of " +
+ Twine(DistanceToBoundary) + " bytes");
BundlePadding -= DistanceToBoundary;
}
- if (!getBackend().writeNopData(BundlePadding, OW))
+ if (!getBackend().writeNopData(OS, BundlePadding))
report_fatal_error("unable to write NOP sequence of " +
Twine(BundlePadding) + " bytes");
}
}
-/// \brief Write the fragment \p F to the output file.
-static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
- const MCFragment &F) {
- MCObjectWriter *OW = &Asm.getWriter();
-
+/// Write the fragment \p F to the output file.
+static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
+ const MCAsmLayout &Layout, const MCFragment &F) {
// FIXME: Embed in fragments instead?
uint64_t FragmentSize = Asm.computeFragmentSize(Layout, F);
- Asm.writeFragmentPadding(F, FragmentSize, OW);
+ support::endianness Endian = Asm.getBackend().Endian;
+
+ if (const MCEncodedFragment *EF = dyn_cast<MCEncodedFragment>(&F))
+ Asm.writeFragmentPadding(OS, *EF, FragmentSize);
// This variable (and its dummy usage) is to participate in the assert at
// the end of the function.
- uint64_t Start = OW->getStream().tell();
+ uint64_t Start = OS.tell();
(void) Start;
++stats::EmittedFragments;
@@ -496,7 +525,7 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
// bytes left to fill use the Value and ValueSize to fill the rest.
// If we are aligning with nops, ask that target to emit the right data.
if (AF.hasEmitNops()) {
- if (!Asm.getBackend().writeNopData(Count, OW))
+ if (!Asm.getBackend().writeNopData(OS, Count))
report_fatal_error("unable to write nop sequence of " +
Twine(Count) + " bytes");
break;
@@ -506,10 +535,16 @@ 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: OS << char(AF.getValue()); break;
+ case 2:
+ support::endian::write<uint16_t>(OS, AF.getValue(), Endian);
+ break;
+ case 4:
+ support::endian::write<uint32_t>(OS, AF.getValue(), Endian);
+ break;
+ case 8:
+ support::endian::write<uint64_t>(OS, AF.getValue(), Endian);
+ break;
}
}
break;
@@ -517,47 +552,60 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
case MCFragment::FT_Data:
++stats::EmittedDataFragments;
- OW->writeBytes(cast<MCDataFragment>(F).getContents());
+ OS << cast<MCDataFragment>(F).getContents();
break;
case MCFragment::FT_Relaxable:
++stats::EmittedRelaxableFragments;
- OW->writeBytes(cast<MCRelaxableFragment>(F).getContents());
+ OS << cast<MCRelaxableFragment>(F).getContents();
break;
case MCFragment::FT_CompactEncodedInst:
++stats::EmittedCompactEncodedInstFragments;
- OW->writeBytes(cast<MCCompactEncodedInstFragment>(F).getContents());
+ OS << cast<MCCompactEncodedInstFragment>(F).getContents();
break;
case MCFragment::FT_Fill: {
++stats::EmittedFillFragments;
const MCFillFragment &FF = cast<MCFillFragment>(F);
- uint8_t V = FF.getValue();
+ uint64_t V = FF.getValue();
+ unsigned VSize = FF.getValueSize();
const unsigned MaxChunkSize = 16;
char Data[MaxChunkSize];
- memcpy(Data, &V, 1);
- for (unsigned I = 1; I < MaxChunkSize; ++I)
- Data[I] = Data[0];
-
- uint64_t Size = FF.getSize();
- for (unsigned ChunkSize = MaxChunkSize; ChunkSize; ChunkSize /= 2) {
- StringRef Ref(Data, ChunkSize);
- for (uint64_t I = 0, E = Size / ChunkSize; I != E; ++I)
- OW->writeBytes(Ref);
- Size = Size % ChunkSize;
+ // Duplicate V into Data as byte vector to reduce number of
+ // writes done. As such, do endian conversion here.
+ for (unsigned I = 0; I != VSize; ++I) {
+ unsigned index = Endian == support::little ? I : (VSize - I - 1);
+ Data[I] = uint8_t(V >> (index * 8));
}
+ for (unsigned I = VSize; I < MaxChunkSize; ++I)
+ Data[I] = Data[I - VSize];
+
+ // Set to largest multiple of VSize in Data.
+ const unsigned NumPerChunk = MaxChunkSize / VSize;
+ // Set ChunkSize to largest multiple of VSize in Data
+ const unsigned ChunkSize = VSize * NumPerChunk;
+
+ // Do copies by chunk.
+ StringRef Ref(Data, ChunkSize);
+ for (uint64_t I = 0, E = FragmentSize / ChunkSize; I != E; ++I)
+ OS << Ref;
+
+ // do remainder if needed.
+ unsigned TrailingCount = FragmentSize % ChunkSize;
+ if (TrailingCount)
+ OS.write(Data, TrailingCount);
break;
}
case MCFragment::FT_LEB: {
const MCLEBFragment &LF = cast<MCLEBFragment>(F);
- OW->writeBytes(LF.getContents());
+ OS << LF.getContents();
break;
}
case MCFragment::FT_Padding: {
- if (!Asm.getBackend().writeNopData(FragmentSize, OW))
+ if (!Asm.getBackend().writeNopData(OS, FragmentSize))
report_fatal_error("unable to write nop sequence of " +
Twine(FragmentSize) + " bytes");
break;
@@ -565,7 +613,7 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
case MCFragment::FT_SymbolId: {
const MCSymbolIdFragment &SF = cast<MCSymbolIdFragment>(F);
- OW->write32(SF.getSymbol()->getIndex());
+ support::endian::write<uint32_t>(OS, SF.getSymbol()->getIndex(), Endian);
break;
}
@@ -574,41 +622,43 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
const MCOrgFragment &OF = cast<MCOrgFragment>(F);
for (uint64_t i = 0, e = FragmentSize; i != e; ++i)
- OW->write8(uint8_t(OF.getValue()));
+ OS << char(OF.getValue());
break;
}
case MCFragment::FT_Dwarf: {
const MCDwarfLineAddrFragment &OF = cast<MCDwarfLineAddrFragment>(F);
- OW->writeBytes(OF.getContents());
+ OS << OF.getContents();
break;
}
case MCFragment::FT_DwarfFrame: {
const MCDwarfCallFrameFragment &CF = cast<MCDwarfCallFrameFragment>(F);
- OW->writeBytes(CF.getContents());
+ OS << CF.getContents();
break;
}
case MCFragment::FT_CVInlineLines: {
const auto &OF = cast<MCCVInlineLineTableFragment>(F);
- OW->writeBytes(OF.getContents());
+ OS << OF.getContents();
break;
}
case MCFragment::FT_CVDefRange: {
const auto &DRF = cast<MCCVDefRangeFragment>(F);
- OW->writeBytes(DRF.getContents());
+ OS << DRF.getContents();
break;
}
case MCFragment::FT_Dummy:
llvm_unreachable("Should not have been added");
}
- assert(OW->getStream().tell() - Start == FragmentSize &&
+ assert(OS.tell() - Start == FragmentSize &&
"The stream should advance by fragment size");
}
-void MCAssembler::writeSectionData(const MCSection *Sec,
+void MCAssembler::writeSectionData(raw_ostream &OS, const MCSection *Sec,
const MCAsmLayout &Layout) const {
+ assert(getBackendPtr() && "Expected assembler backend");
+
// Ignore virtual sections.
if (Sec->isVirtualSection()) {
assert(Layout.getSectionFileSize(Sec) == 0 && "Invalid size for section!");
@@ -651,14 +701,13 @@ void MCAssembler::writeSectionData(const MCSection *Sec,
return;
}
- uint64_t Start = getWriter().getStream().tell();
+ uint64_t Start = OS.tell();
(void)Start;
for (const MCFragment &F : *Sec)
- writeFragment(*this, Layout, F);
+ writeFragment(OS, *this, Layout, F);
- assert(getWriter().getStream().tell() - Start ==
- Layout.getSectionAddressSize(Sec));
+ assert(OS.tell() - Start == Layout.getSectionAddressSize(Sec));
}
std::tuple<MCValue, uint64_t, bool>
@@ -667,17 +716,39 @@ MCAssembler::handleFixup(const MCAsmLayout &Layout, MCFragment &F,
// Evaluate the fixup.
MCValue Target;
uint64_t FixedValue;
- bool IsResolved = evaluateFixup(Layout, Fixup, &F, Target, FixedValue);
+ bool WasForced;
+ bool IsResolved = evaluateFixup(Layout, Fixup, &F, Target, FixedValue,
+ WasForced);
if (!IsResolved) {
// 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);
+ if (Target.getSymA() && Target.getSymB() &&
+ getBackend().requiresDiffExpressionRelocations()) {
+ // The fixup represents the difference between two symbols, which the
+ // backend has indicated must be resolved at link time. Split up the fixup
+ // into two relocations, one for the add, and one for the sub, and emit
+ // both of these. The constant will be associated with the add half of the
+ // expression.
+ MCFixup FixupAdd = MCFixup::createAddFor(Fixup);
+ MCValue TargetAdd =
+ MCValue::get(Target.getSymA(), nullptr, Target.getConstant());
+ getWriter().recordRelocation(*this, Layout, &F, FixupAdd, TargetAdd,
+ FixedValue);
+ MCFixup FixupSub = MCFixup::createSubFor(Fixup);
+ MCValue TargetSub = MCValue::get(Target.getSymB());
+ getWriter().recordRelocation(*this, Layout, &F, FixupSub, TargetSub,
+ FixedValue);
+ } else {
+ getWriter().recordRelocation(*this, Layout, &F, Fixup, Target,
+ FixedValue);
+ }
}
return std::make_tuple(Target, FixedValue, IsResolved);
}
void MCAssembler::layout(MCAsmLayout &Layout) {
+ assert(getBackendPtr() && "Expected assembler backend");
DEBUG_WITH_TYPE("mc-dump", {
errs() << "assembler backend - pre-layout\n--\n";
dump(); });
@@ -737,12 +808,17 @@ void MCAssembler::layout(MCAsmLayout &Layout) {
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();
@@ -755,7 +831,7 @@ void MCAssembler::layout(MCAsmLayout &Layout) {
std::tie(Target, FixedValue, IsResolved) =
handleFixup(Layout, Frag, Fixup);
getBackend().applyFixup(*this, Fixup, Target, Contents, FixedValue,
- IsResolved);
+ IsResolved, STI);
}
}
}
@@ -766,35 +842,33 @@ void MCAssembler::Finish() {
MCAsmLayout Layout(*this);
layout(Layout);
- raw_ostream &OS = getWriter().getStream();
- uint64_t StartOffset = OS.tell();
-
// Write the object file.
- getWriter().writeObject(*this, Layout);
-
- stats::ObjectBytes += OS.tell() - StartOffset;
+ stats::ObjectBytes += getWriter().writeObject(*this, Layout);
}
bool MCAssembler::fixupNeedsRelaxation(const MCFixup &Fixup,
const MCRelaxableFragment *DF,
const MCAsmLayout &Layout) const {
+ assert(getBackendPtr() && "Expected assembler backend");
MCValue Target;
uint64_t Value;
- bool Resolved = evaluateFixup(Layout, Fixup, DF, Target, Value);
+ bool WasForced;
+ bool Resolved = evaluateFixup(Layout, Fixup, DF, Target, Value, WasForced);
if (Target.getSymA() &&
Target.getSymA()->getKind() == MCSymbolRefExpr::VK_X86_ABS8 &&
Fixup.getKind() == FK_Data_1)
return false;
return getBackend().fixupNeedsRelaxationAdvanced(Fixup, Resolved, Value, DF,
- Layout);
+ Layout, WasForced);
}
bool MCAssembler::fragmentNeedsRelaxation(const MCRelaxableFragment *F,
const MCAsmLayout &Layout) const {
+ assert(getBackendPtr() && "Expected assembler backend");
// If this inst doesn't ever need relaxation, ignore it. This occurs when we
// are intentionally pushing out inst fragments, or because we relaxed a
// previous instruction to one that doesn't need relaxation.
- if (!getBackend().mayNeedRelaxation(F->getInst()))
+ if (!getBackend().mayNeedRelaxation(F->getInst(), *F->getSubtargetInfo()))
return false;
for (const MCFixup &Fixup : F->getFixups())
@@ -806,6 +880,8 @@ bool MCAssembler::fragmentNeedsRelaxation(const MCRelaxableFragment *F,
bool MCAssembler::relaxInstruction(MCAsmLayout &Layout,
MCRelaxableFragment &F) {
+ assert(getEmitterPtr() &&
+ "Expected CodeEmitter defined for relaxInstruction");
if (!fragmentNeedsRelaxation(&F, Layout))
return false;
@@ -817,7 +893,7 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout,
// Relax the fragment.
MCInst Relaxed;
- getBackend().relaxInstruction(F.getInst(), F.getSubtargetInfo(), Relaxed);
+ getBackend().relaxInstruction(F.getInst(), *F.getSubtargetInfo(), Relaxed);
// Encode the new instruction.
//
@@ -826,7 +902,7 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout,
SmallVector<MCFixup, 4> Fixups;
SmallString<256> Code;
raw_svector_ostream VecOS(Code);
- getEmitter().encodeInstruction(Relaxed, VecOS, Fixups, F.getSubtargetInfo());
+ getEmitter().encodeInstruction(Relaxed, VecOS, Fixups, *F.getSubtargetInfo());
// Update the fragment.
F.setInst(Relaxed);
@@ -838,6 +914,7 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout,
bool MCAssembler::relaxPaddingFragment(MCAsmLayout &Layout,
MCPaddingFragment &PF) {
+ assert(getBackendPtr() && "Expected assembler backend");
uint64_t OldSize = PF.getSize();
if (!getBackend().relaxFragment(&PF, Layout))
return false;
@@ -858,10 +935,14 @@ bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) {
SmallString<8> &Data = LF.getContents();
Data.clear();
raw_svector_ostream OSE(Data);
+ // The compiler can generate EH table assembly that is impossible to assemble
+ // without either adding padding to an LEB fragment or adding extra padding
+ // to a later alignment fragment. To accommodate such tables, relaxation can
+ // only increase an LEB fragment size here, not decrease it. See PR35809.
if (LF.isSigned())
- encodeSLEB128(Value, OSE);
+ encodeSLEB128(Value, OSE, OldSize);
else
- encodeULEB128(Value, OSE);
+ encodeULEB128(Value, OSE, OldSize);
return OldSize != LF.getContents().size();
}
@@ -978,6 +1059,7 @@ bool MCAssembler::layoutOnce(MCAsmLayout &Layout) {
}
void MCAssembler::finishLayout(MCAsmLayout &Layout) {
+ assert(getBackendPtr() && "Expected assembler backend");
// The layout is done. Mark every fragment as valid.
for (unsigned int i = 0, n = Layout.getSectionOrder().size(); i != n; ++i) {
MCSection &Section = *Layout.getSectionOrder()[i];
@@ -986,3 +1068,27 @@ void MCAssembler::finishLayout(MCAsmLayout &Layout) {
}
getBackend().finishLayout(*this, Layout);
}
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void MCAssembler::dump() const{
+ raw_ostream &OS = errs();
+
+ OS << "<MCAssembler\n";
+ OS << " Sections:[\n ";
+ for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
+ if (it != begin()) OS << ",\n ";
+ it->dump();
+ }
+ OS << "],\n";
+ OS << " Symbols:[";
+
+ for (const_symbol_iterator it = symbol_begin(), ie = symbol_end(); it != ie; ++it) {
+ if (it != symbol_begin()) OS << ",\n ";
+ OS << "(";
+ it->dump();
+ OS << ", Index:" << it->getIndex() << ", ";
+ OS << ")";
+ }
+ OS << "]>\n";
+}
+#endif