diff options
-rw-r--r-- | include/llvm/MC/MCAsmLayout.h | 4 | ||||
-rw-r--r-- | include/llvm/MC/MCAssembler.h | 25 | ||||
-rw-r--r-- | lib/MC/MCAssembler.cpp | 55 | ||||
-rw-r--r-- | test/MC/MachO/relax-recompute-align.s | 10 |
4 files changed, 46 insertions, 48 deletions
diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h index 64b0b4e026..7ea0bac0f7 100644 --- a/include/llvm/MC/MCAsmLayout.h +++ b/include/llvm/MC/MCAsmLayout.h @@ -76,10 +76,6 @@ public: /// @name Fragment Layout Data /// @{ - /// \brief Get the effective size of the given fragment, as computed in the - /// current layout. - uint64_t getFragmentEffectiveSize(const MCFragment *F) const; - /// \brief Get the offset of the given fragment inside its containing section. uint64_t getFragmentOffset(const MCFragment *F) const; diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index ea250045ad..19d8ea5d09 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -75,10 +75,6 @@ private: /// initialized. uint64_t Offset; - /// EffectiveSize - The compute size of this section. This is ~0 until - /// initialized. - uint64_t EffectiveSize; - /// LayoutOrder - The layout order of this fragment. unsigned LayoutOrder; @@ -231,6 +227,9 @@ class MCAlignFragment : public MCFragment { /// cannot be satisfied in this width then this fragment is ignored. unsigned MaxBytesToEmit; + /// Size - The current estimate of the size. + unsigned Size; + /// EmitNops - Flag to indicate that (optimal) NOPs should be emitted instead /// of using the provided value. The exact interpretation of this flag is /// target dependent. @@ -241,7 +240,7 @@ public: unsigned _MaxBytesToEmit, MCSectionData *SD = 0) : MCFragment(FT_Align, SD), Alignment(_Alignment), Value(_Value),ValueSize(_ValueSize), - MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false) {} + MaxBytesToEmit(_MaxBytesToEmit), Size(0), EmitNops(false) {} /// @name Accessors /// @{ @@ -252,6 +251,10 @@ public: unsigned getValueSize() const { return ValueSize; } + unsigned getSize() const { return Size; } + + void setSize(unsigned Size_) { Size = Size_; } + unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; } bool hasEmitNops() const { return EmitNops; } @@ -704,11 +707,6 @@ private: const MCInstFragment *IF, const MCAsmLayout &Layout) const; - /// Compute the effective fragment size assuming it is layed out at the given - /// \arg SectionAddress and \arg FragmentOffset. - uint64_t ComputeFragmentSize(const MCFragment &F, - uint64_t FragmentOffset) const; - /// LayoutOnce - Perform one layout iteration and return true if any offsets /// were adjusted. bool LayoutOnce(const MCObjectWriter &Writer, MCAsmLayout &Layout); @@ -725,6 +723,9 @@ private: bool RelaxDwarfLineAddr(const MCObjectWriter &Writer, MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF); + bool RelaxAlignment(const MCObjectWriter &Writer, MCAsmLayout &Layout, + MCAlignFragment &DF); + /// FinishLayout - Finalize a layout, including fragment lowering. void FinishLayout(MCAsmLayout &Layout); @@ -732,6 +733,10 @@ private: MCFragment &F, const MCFixup &Fixup); public: + /// Compute the effective fragment size assuming it is layed out at the given + /// \arg SectionAddress and \arg FragmentOffset. + uint64_t ComputeFragmentSize(const MCFragment &F) const; + /// Find the symbol which defines the atom containing the given symbol, or /// null if there is no such symbol. const MCSymbolData *getAtom(const MCSymbolData *Symbol) const; diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index f05f6acd63..0fbd77c7f1 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -74,10 +74,9 @@ void MCAsmLayout::Invalidate(MCFragment *F) { if (!isFragmentUpToDate(F)) return; - // Otherwise, reset the last valid fragment to the predecessor of the - // invalidated fragment. + // Otherwise, reset the last valid fragment to this fragment. const MCSectionData &SD = *F->getParent(); - LastValidFragment[&SD] = F->getPrevNode(); + LastValidFragment[&SD] = F; } void MCAsmLayout::EnsureValid(const MCFragment *F) const { @@ -96,12 +95,6 @@ void MCAsmLayout::EnsureValid(const MCFragment *F) const { } } -uint64_t MCAsmLayout::getFragmentEffectiveSize(const MCFragment *F) const { - EnsureValid(F); - assert(F->EffectiveSize != ~UINT64_C(0) && "Address not set!"); - return F->EffectiveSize; -} - uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const { EnsureValid(F); assert(F->Offset != ~UINT64_C(0) && "Address not set!"); @@ -116,7 +109,7 @@ uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const { uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const { // The size is the last fragment's end offset. const MCFragment &F = SD->getFragmentList().back(); - return getFragmentOffset(&F) + getFragmentEffectiveSize(&F); + return getFragmentOffset(&F) + getAssembler().ComputeFragmentSize(F); } uint64_t MCAsmLayout::getSectionFileSize(const MCSectionData *SD) const { @@ -137,8 +130,7 @@ MCFragment::~MCFragment() { } MCFragment::MCFragment(FragmentType _Kind, MCSectionData *_Parent) - : Kind(_Kind), Parent(_Parent), Atom(0), Offset(~UINT64_C(0)), - EffectiveSize(~UINT64_C(0)) + : Kind(_Kind), Parent(_Parent), Atom(0), Offset(~UINT64_C(0)) { if (Parent) Parent->getFragmentList().push_back(this); @@ -276,8 +268,7 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer, return IsResolved; } -uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F, - uint64_t FragmentOffset) const { +uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F) const { switch (F.getKind()) { case MCFragment::FT_Data: return cast<MCDataFragment>(F).getContents().size(); @@ -289,17 +280,8 @@ uint64_t MCAssembler::ComputeFragmentSize(const MCFragment &F, case MCFragment::FT_LEB: return cast<MCLEBFragment>(F).getContents().size(); - case MCFragment::FT_Align: { - const MCAlignFragment &AF = cast<MCAlignFragment>(F); - - uint64_t Size = OffsetToAlignment(FragmentOffset, AF.getAlignment()); - - // Honor MaxBytesToEmit. - if (Size > AF.getMaxBytesToEmit()) - return 0; - - return Size; - } + case MCFragment::FT_Align: + return cast<MCAlignFragment>(F).getSize(); case MCFragment::FT_Org: return cast<MCOrgFragment>(F).getSize(); @@ -327,10 +309,9 @@ void MCAsmLayout::LayoutFragment(MCFragment *F) { // Compute fragment offset and size. uint64_t Offset = 0; if (Prev) - Offset += Prev->Offset + Prev->EffectiveSize; + Offset += Prev->Offset + getAssembler().ComputeFragmentSize(*Prev); F->Offset = Offset; - F->EffectiveSize = getAssembler().ComputeFragmentSize(*F, F->Offset); LastValidFragment[F->getParent()] = F; } @@ -343,7 +324,7 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout, ++stats::EmittedFragments; // FIXME: Embed in fragments instead? - uint64_t FragmentSize = Layout.getFragmentEffectiveSize(&F); + uint64_t FragmentSize = Asm.ComputeFragmentSize(F); switch (F.getKind()) { case MCFragment::FT_Align: { MCAlignFragment &AF = cast<MCAlignFragment>(F); @@ -730,6 +711,18 @@ bool MCAssembler::RelaxDwarfLineAddr(const MCObjectWriter &Writer, return OldSize != Data.size(); } +bool MCAssembler::RelaxAlignment(const MCObjectWriter &Writer, + MCAsmLayout &Layout, + MCAlignFragment &AF) { + unsigned Offset = Layout.getFragmentOffset(&AF); + unsigned Size = OffsetToAlignment(Offset, AF.getAlignment()); + if (Size > AF.getMaxBytesToEmit()) + Size = 0; + unsigned OldSize = AF.getSize(); + AF.setSize(Size); + return OldSize != Size; +} + bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer, MCAsmLayout &Layout) { ++stats::RelaxationSteps; @@ -747,6 +740,10 @@ bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer, switch(it2->getKind()) { default: break; + case MCFragment::FT_Align: + relaxedFrag = RelaxAlignment(Writer, Layout, + *cast<MCAlignFragment>(it2)); + break; case MCFragment::FT_Inst: relaxedFrag = RelaxInstruction(Writer, Layout, *cast<MCInstFragment>(it2)); @@ -809,7 +806,7 @@ void MCFragment::dump() { } OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder - << " Offset:" << Offset << " EffectiveSize:" << EffectiveSize << ">"; + << " Offset:" << Offset << ">"; switch (getKind()) { case MCFragment::FT_Align: { diff --git a/test/MC/MachO/relax-recompute-align.s b/test/MC/MachO/relax-recompute-align.s index b9734cebf3..249402502f 100644 --- a/test/MC/MachO/relax-recompute-align.s +++ b/test/MC/MachO/relax-recompute-align.s @@ -3,16 +3,16 @@ // FIXME: This is a horrible way of checking the output, we need an llvm-mc // based 'otool'. -// FIXME: PR8467. -// There is an unnecessary relaxation here. After the first jmp slides, -// the .align size could be recomputed so that the second jump will be in range -// for a 1-byte jump. For performance reasons, this is not currently done. +// This is a case where llvm-mc computes a better layout than Darwin 'as'. This +// issue is that after the first jmp slides, the .align size must be +// recomputed -- otherwise the second jump will appear to be out-of-range for a +// 1-byte jump. // CHECK: # Section 0 // CHECK: (('section_name', '__text\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') // CHECK: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') // CHECK: ('address', 0) -// CHECK: ('size', 322) +// CHECK: ('size', 306) // CHECK: ('offset', 324) // CHECK: ('alignment', 4) // CHECK: ('reloc_offset', 0) |