| 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++);
|
| }
|
| }
|
| }
|
|
|