Index: lib/MC/MCAssembler.cpp |
=================================================================== |
--- lib/MC/MCAssembler.cpp (revision 119741) |
+++ lib/MC/MCAssembler.cpp (working copy) |
@@ -113,14 +113,42 @@ |
} |
} |
-void MCAsmLayout::FragmentReplaced(MCFragment *Src, MCFragment *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->setLayoutOrder(Src->getLayoutOrder()); |
+ |
if (LastValidFragment == Src) |
LastValidFragment = Dst; |
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); |
+ |
+ if (isFragmentUpToDate(Src)) { |
+ if (LastValidFragment == Src) |
+ LastValidFragment = Dst; |
+ Dst->EffectiveSize += Src->EffectiveSize; |
+ } else { |
+ // We don't know the effective size of Src, so we have to invalidate Dst. |
+ UpdateForSlide(Dst, 0); |
+ } |
+ // Remove Src, but don't delete it yet. |
+ Src->getParent()->getFragmentList().remove(Src); |
+} |
+ |
uint64_t MCAsmLayout::getFragmentAddress(const MCFragment *F) const { |
assert(F->getParent() && "Missing section()!"); |
return getSectionAddress(F->getParent()) + getFragmentOffset(F); |
@@ -888,6 +916,22 @@ |
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. |
@@ -896,35 +940,42 @@ |
// 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; |
+ 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); |
+ // Lower the Instruction Fragment |
+ LowerInstFragment(IF, CurDF); |
- // 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; |
+ // 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++); |
} |
} |
} |