diff options
-rw-r--r-- | include/llvm/MC/MCAsmLayout.h | 8 | ||||
-rw-r--r-- | lib/MC/MCAssembler.cpp | 54 |
2 files changed, 52 insertions, 10 deletions
diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h index 526ecad..991d262 100644 --- a/include/llvm/MC/MCAsmLayout.h +++ b/include/llvm/MC/MCAsmLayout.h @@ -36,6 +36,14 @@ private: /// List of sections in layout order. llvm::SmallVector<MCSectionData*, 16> SectionOrder; + /// The last fragment which was layed out, or 0 if nothing has been layed + /// out. Fragments are always layed out in order, so all fragments with a + /// lower ordinal will be up to date. + mutable MCFragment *LastValidFragment; + + bool isSectionUpToDate(const MCSectionData *SD) const; + bool isFragmentUpToDate(const MCFragment *F) const; + public: MCAsmLayout(MCAssembler &_Assembler); diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 92bdc0c..411c6d9 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -47,7 +47,9 @@ STATISTIC(SectionLayouts, "Number of section layouts"); /* *** */ -MCAsmLayout::MCAsmLayout(MCAssembler &Asm) : Assembler(Asm) { +MCAsmLayout::MCAsmLayout(MCAssembler &Asm) + : Assembler(Asm), LastValidFragment(0) + { // 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())) @@ -57,6 +59,23 @@ MCAsmLayout::MCAsmLayout(MCAssembler &Asm) : Assembler(Asm) { SectionOrder.push_back(&*it); } +bool MCAsmLayout::isSectionUpToDate(const MCSectionData *SD) const { + // The first section is always up-to-date. + unsigned Index = SD->getLayoutOrder(); + if (!Index) + return true; + + // Otherwise, sections are always implicitly computed when the preceeding + // fragment is layed out. + const MCSectionData *Prev = getSectionOrder()[Index - 1]; + return isFragmentUpToDate(&(Prev->getFragmentList().back())); +} + +bool MCAsmLayout::isFragmentUpToDate(const MCFragment *F) const { + return (LastValidFragment && + F->getLayoutOrder() <= LastValidFragment->getLayoutOrder()); +} + void MCAsmLayout::UpdateForSlide(MCFragment *F, int SlideAmount) { // We shouldn't have to do anything special to support negative slides, and it // is a perfectly valid thing to do as long as other parts of the system can @@ -73,6 +92,9 @@ void MCAsmLayout::UpdateForSlide(MCFragment *F, int SlideAmount) { } void MCAsmLayout::FragmentReplaced(MCFragment *Src, MCFragment *Dst) { + if (LastValidFragment == Src) + LastValidFragment = Dst; + Dst->Offset = Src->Offset; Dst->EffectiveSize = Src->EffectiveSize; } @@ -414,7 +436,8 @@ uint64_t MCAssembler::ComputeFragmentSize(MCAsmLayout &Layout, } void MCAsmLayout::LayoutFile() { - // Initialize the first section. + // Initialize the first section and set the valid fragment layout point. + LastValidFragment = 0; if (!getSectionOrder().empty()) getSectionOrder().front()->Address = 0; @@ -428,21 +451,32 @@ void MCAsmLayout::LayoutFile() { } void MCAsmLayout::LayoutFragment(MCFragment *F) { - uint64_t StartAddress = getSectionAddress(F->getParent()); - - // Get the fragment start address. - uint64_t Address = StartAddress; - MCSectionData::iterator it = F; - if (MCFragment *Prev = F->getPrevNode()) - Address = (StartAddress + getFragmentOffset(Prev) + - getFragmentEffectiveSize(Prev)); + MCFragment *Prev = F->getPrevNode(); + + // We should never try to recompute something which is up-to-date. + assert(!isFragmentUpToDate(F) && "Attempt to recompute up-to-date fragment!"); + // We should never try to compute the fragment layout if the section isn't + // up-to-date. + assert(isSectionUpToDate(F->getParent()) && + "Attempt to compute fragment before it's section!"); + // We should never try to compute the fragment layout if it's predecessor + // isn't up-to-date. + assert((!Prev || isFragmentUpToDate(Prev)) && + "Attempt to compute fragment before it's predecessor!"); ++stats::FragmentLayouts; + // Compute the fragment start address. + uint64_t StartAddress = F->getParent()->Address; + uint64_t Address = StartAddress; + if (Prev) + Address += Prev->Offset + Prev->EffectiveSize; + // Compute fragment offset and size. F->Offset = Address - StartAddress; F->EffectiveSize = getAssembler().ComputeFragmentSize(*this, *F, StartAddress, F->Offset); + LastValidFragment = F; // If this is the last fragment in a section, update the next section address. if (!F->getNextNode()) { |