{
// Compute the section layout order. Virtual sections must go last.
for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
- if (!Asm.getBackend().isVirtualSection(it->getSection()))
+ if (!it->getSection().isVirtualSection())
SectionOrder.push_back(&*it);
for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
- if (Asm.getBackend().isVirtualSection(it->getSection()))
+ if (it->getSection().isVirtualSection())
SectionOrder.push_back(&*it);
}
F->getLayoutOrder() <= LastValidFragment->getLayoutOrder());
}
-void MCAsmLayout::UpdateForSlide(MCFragment *F, int SlideAmount) {
+void MCAsmLayout::Invalidate(MCFragment *F) {
// If this fragment wasn't already up-to-date, we don't need to do anything.
if (!isFragmentUpToDate(F))
return;
}
}
-void MCAsmLayout::FragmentReplaced(MCFragment *Src, MCFragment *Dst) {
- if (LastValidFragment == Src)
- LastValidFragment = Dst;
+void MCAsmLayout::ReplaceFragment(MCFragment *Src, MCFragment *Dst) {
+ MCSectionData *SD = Src->getParent();
+
+ // Insert Dst immediately before Src
+ SD->getFragmentList().insert(Src, Dst);
+
+ // Set the data fragment's layout data.
+ Dst->setParent(Src->getParent());
+ Dst->setAtom(Src->getAtom());
Dst->Offset = Src->Offset;
Dst->EffectiveSize = Src->EffectiveSize;
+
+ // Remove Src, but don't delete it yet.
+ SD->getFragmentList().remove(Src);
+}
+
+void MCAsmLayout::CoalesceFragments(MCFragment *Src, MCFragment *Dst) {
+ assert(Src->getPrevNode() == Dst);
+ Dst->EffectiveSize += Src->EffectiveSize;
+ // Remove Src, but don't delete it yet.
+ Src->getParent()->getFragmentList().remove(Src);
}
uint64_t MCAsmLayout::getFragmentAddress(const MCFragment *F) const {
uint64_t MCAsmLayout::getSectionFileSize(const MCSectionData *SD) const {
// Virtual sections have no file size.
- if (getAssembler().getBackend().isVirtualSection(SD->getSection()))
+ if (SD->getSection().isVirtualSection())
return 0;
// Otherwise, the file size is the same as the address space size.
return IsResolved;
}
-uint64_t MCAssembler::ComputeFragmentSize(MCAsmLayout &Layout,
- const MCFragment &F,
+uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F,
uint64_t SectionAddress,
uint64_t FragmentOffset) const {
switch (F.getKind()) {
return cast<MCInstFragment>(F).getInstSize();
case MCFragment::FT_LEB:
- return cast<MCLEBFragment>(F).getSize();
+ return cast<MCLEBFragment>(F).getContents().size();
case MCFragment::FT_Align: {
const MCAlignFragment &AF = cast<MCAlignFragment>(F);
return cast<MCOrgFragment>(F).getSize();
case MCFragment::FT_Dwarf:
- return cast<MCDwarfLineAddrFragment>(F).getSize();
+ return cast<MCDwarfLineAddrFragment>(F).getContents().size();
}
assert(0 && "invalid fragment kind");
// Compute fragment offset and size.
F->Offset = Address - StartAddress;
- F->EffectiveSize = getAssembler().ComputeFragmentSize(*this, *F, StartAddress,
+ F->EffectiveSize = getAssembler().ComputeFragmentSize(*F, StartAddress,
F->Offset);
LastValidFragment = F;
case MCFragment::FT_LEB: {
MCLEBFragment &LF = cast<MCLEBFragment>(F);
-
- // FIXME: It is probably better if we don't call EvaluateAsAbsolute in
- // here.
- int64_t Value;
- LF.getValue().EvaluateAsAbsolute(Value, &Layout);
- SmallString<32> Tmp;
- raw_svector_ostream OSE(Tmp);
- if (LF.isSigned())
- MCObjectWriter::EncodeSLEB128(Value, OSE);
- else
- MCObjectWriter::EncodeULEB128(Value, OSE);
- OW->WriteBytes(OSE.str());
+ OW->WriteBytes(LF.getContents().str());
break;
}
case MCFragment::FT_Dwarf: {
const MCDwarfLineAddrFragment &OF = cast<MCDwarfLineAddrFragment>(F);
-
- // The AddrDelta is really unsigned and it can only increase.
- int64_t AddrDelta;
- OF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, &Layout);
-
- int64_t LineDelta;
- LineDelta = OF.getLineDelta();
-
- MCDwarfLineAddr::Write(OW, LineDelta, (uint64_t)AddrDelta);
+ OW->WriteBytes(OF.getContents().str());
break;
}
}
const MCAsmLayout &Layout,
MCObjectWriter *OW) const {
// Ignore virtual sections.
- if (getBackend().isVirtualSection(SD->getSection())) {
+ if (SD->getSection().isVirtualSection()) {
assert(Layout.getSectionFileSize(SD) == 0 && "Invalid size for section!");
// Check that contents are only things legal inside a virtual section.
assert(OW->getStream().tell() - Start == Layout.getSectionFileSize(SD));
}
-void MCAssembler::AddSectionToTheEnd(const MCObjectWriter &Writer,
- MCSectionData &SD, MCAsmLayout &Layout) {
- // Create dummy fragments and assign section ordinals.
- unsigned SectionIndex = size();
- SD.setOrdinal(SectionIndex);
-
- // Assign layout order indices to sections and fragments.
- const MCFragment &Last = *Layout.getSectionOrder().back()->rbegin();
- unsigned FragmentIndex = Last.getLayoutOrder() + 1;
-
- SD.setLayoutOrder(Layout.getSectionOrder().size());
- for (MCSectionData::iterator it2 = SD.begin(),
- ie2 = SD.end(); it2 != ie2; ++it2) {
- it2->setLayoutOrder(FragmentIndex++);
- }
- Layout.getSectionOrder().push_back(&SD);
-
- Layout.LayoutSection(&SD);
-}
-
void MCAssembler::Finish(MCObjectWriter *Writer) {
DEBUG_WITH_TYPE("mc-dump", {
llvm::errs() << "assembler backend - pre-layout\n--\n";
continue;
// Ignore virtual sections, they don't cause file size modifications.
- if (getBackend().isVirtualSection(SD->getSection()))
+ if (SD->getSection().isVirtualSection())
continue;
// Otherwise, create a new align fragment at the end of the previous
VecOS.flush();
// Update the instruction fragment.
- int SlideAmount = Code.size() - IF.getInstSize();
IF.setInst(Relaxed);
IF.getCode() = Code;
IF.getFixups().clear();
for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
IF.getFixups().push_back(Fixups[i]);
- // Update the layout, and remember that we relaxed.
- Layout.UpdateForSlide(&IF, SlideAmount);
return true;
}
bool MCAssembler::RelaxLEB(const MCObjectWriter &Writer,
MCAsmLayout &Layout,
MCLEBFragment &LF) {
- int64_t Value;
+ int64_t Value = 0;
+ uint64_t OldSize = LF.getContents().size();
LF.getValue().EvaluateAsAbsolute(Value, &Layout);
- SmallString<32> Tmp;
- raw_svector_ostream OSE(Tmp);
+ SmallString<8> &Data = LF.getContents();
+ Data.clear();
+ raw_svector_ostream OSE(Data);
if (LF.isSigned())
MCObjectWriter::EncodeSLEB128(Value, OSE);
else
MCObjectWriter::EncodeULEB128(Value, OSE);
- uint64_t OldSize = LF.getSize();
- LF.setSize(OSE.GetNumBytesInBuffer());
- return OldSize != LF.getSize();
+ OSE.flush();
+ return OldSize != LF.getContents().size();
}
bool MCAssembler::RelaxDwarfLineAddr(const MCObjectWriter &Writer,
MCAsmLayout &Layout,
MCDwarfLineAddrFragment &DF) {
- int64_t AddrDelta;
+ int64_t AddrDelta = 0;
+ uint64_t OldSize = DF.getContents().size();
DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, &Layout);
int64_t LineDelta;
LineDelta = DF.getLineDelta();
- uint64_t OldSize = DF.getSize();
- DF.setSize(MCDwarfLineAddr::ComputeSize(LineDelta, AddrDelta));
- return OldSize != DF.getSize();
+ SmallString<8> &Data = DF.getContents();
+ Data.clear();
+ raw_svector_ostream OSE(Data);
+ MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OSE);
+ OSE.flush();
+ return OldSize != Data.size();
}
bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
for (MCSectionData::iterator it2 = SD.begin(),
ie2 = SD.end(); it2 != ie2; ++it2) {
// Check if this is an fragment that needs relaxation.
+ bool relaxedFrag = false;
switch(it2->getKind()) {
default:
break;
case MCFragment::FT_Inst:
- WasRelaxed |= RelaxInstruction(Writer, Layout,
+ relaxedFrag = RelaxInstruction(Writer, Layout,
*cast<MCInstFragment>(it2));
break;
case MCFragment::FT_Org:
- WasRelaxed |= RelaxOrg(Writer, Layout, *cast<MCOrgFragment>(it2));
+ relaxedFrag = RelaxOrg(Writer, Layout, *cast<MCOrgFragment>(it2));
break;
case MCFragment::FT_Dwarf:
- WasRelaxed |= RelaxDwarfLineAddr(Writer, Layout,
+ relaxedFrag = RelaxDwarfLineAddr(Writer, Layout,
*cast<MCDwarfLineAddrFragment>(it2));
break;
case MCFragment::FT_LEB:
- WasRelaxed |= RelaxLEB(Writer, Layout, *cast<MCLEBFragment>(it2));
+ relaxedFrag = RelaxLEB(Writer, Layout, *cast<MCLEBFragment>(it2));
break;
}
+ // Update the layout, and remember that we relaxed.
+ if (relaxedFrag)
+ Layout.Invalidate(it2);
+ WasRelaxed |= relaxedFrag;
}
}
return WasRelaxed;
}
+static void LowerInstFragment(MCInstFragment *IF,
+ MCDataFragment *DF) {
+
+ uint64_t DataOffset = DF->getContents().size();
+
+ // Copy in the data
+ DF->getContents().append(IF->getCode().begin(), IF->getCode().end());
+
+ // Adjust the fixup offsets and add them to the data fragment.
+ for (unsigned i = 0, e = IF->getFixups().size(); i != e; ++i) {
+ MCFixup &F = IF->getFixups()[i];
+ F.setOffset(DataOffset + F.getOffset());
+ DF->getFixups().push_back(F);
+ }
+}
+
void MCAssembler::FinishLayout(MCAsmLayout &Layout) {
// Lower out any instruction fragments, to simplify the fixup application and
// output.
// cheap (we will mostly end up eliminating fragments and appending on to data
// fragments), so the extra complexity downstream isn't worth it. Evaluate
// this assumption.
- for (iterator it = begin(), ie = end(); it != ie; ++it) {
- MCSectionData &SD = *it;
+
+ // The layout is done. Mark every fragment as valid.
+ Layout.getFragmentOffset(&*Layout.getSectionOrder().back()->rbegin());
+
+ unsigned FragmentIndex = 0;
+ for (unsigned i = 0, e = Layout.getSectionOrder().size(); i != e; ++i) {
+ MCSectionData &SD = *Layout.getSectionOrder()[i];
+ MCDataFragment *CurDF = NULL;
for (MCSectionData::iterator it2 = SD.begin(),
ie2 = SD.end(); it2 != ie2; ++it2) {
- MCInstFragment *IF = dyn_cast<MCInstFragment>(it2);
- if (!IF)
- continue;
+ switch (it2->getKind()) {
+ default:
+ CurDF = NULL;
+ break;
+ case MCFragment::FT_Data:
+ CurDF = cast<MCDataFragment>(it2);
+ break;
+ case MCFragment::FT_Inst: {
+ MCInstFragment *IF = cast<MCInstFragment>(it2);
+ // Use the existing data fragment if possible.
+ if (CurDF && CurDF->getAtom() == IF->getAtom()) {
+ Layout.CoalesceFragments(IF, CurDF);
+ } else {
+ // Otherwise, create a new data fragment.
+ CurDF = new MCDataFragment();
+ Layout.ReplaceFragment(IF, CurDF);
+ }
- // Create a new data fragment for the instruction.
- //
- // FIXME-PERF: Reuse previous data fragment if possible.
- MCDataFragment *DF = new MCDataFragment();
- SD.getFragmentList().insert(it2, DF);
-
- // Update the data fragments layout data.
- DF->setParent(IF->getParent());
- DF->setAtom(IF->getAtom());
- DF->setLayoutOrder(IF->getLayoutOrder());
- Layout.FragmentReplaced(IF, DF);
-
- // Copy in the data and the fixups.
- DF->getContents().append(IF->getCode().begin(), IF->getCode().end());
- for (unsigned i = 0, e = IF->getFixups().size(); i != e; ++i)
- DF->getFixups().push_back(IF->getFixups()[i]);
-
- // Delete the instruction fragment and update the iterator.
- SD.getFragmentList().erase(IF);
- it2 = DF;
+ // Lower the Instruction Fragment
+ LowerInstFragment(IF, CurDF);
+
+ // Delete the instruction fragment and update the iterator.
+ delete IF;
+ it2 = CurDF;
+ break;
+ }
+ }
+ // Since we may have merged fragments, fix the layout order.
+ it2->setLayoutOrder(FragmentIndex++);
}
}
}