diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h index 8cb46012831..3058b7b4874 100644 --- a/include/llvm/MC/MCAsmLayout.h +++ b/include/llvm/MC/MCAsmLayout.h @@ -60,9 +60,10 @@ public: /// Get the assembler object this is a layout for. MCAssembler &getAssembler() const { return Assembler; } - /// \brief Invalidate the fragments after F because it has been resized. - /// The fragment's size should have already been updated. - void invalidateFragmentsAfter(MCFragment *F); + /// \brief Invalidate the fragments starting with F because it has been + /// resized. The fragment's size should have already been updated, but + /// its bundle padding will be recomputed. + void invalidateFragmentsFrom(MCFragment *F); /// \brief Perform layout for a single fragment, assuming that the previous /// fragment has already been laid out correctly, and the parent section has diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 498fbf77ad5..fd281e67c78 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -82,14 +82,15 @@ bool MCAsmLayout::isFragmentValid(const MCFragment *F) const { return F->getLayoutOrder() <= LastValid->getLayoutOrder(); } -void MCAsmLayout::invalidateFragmentsAfter(MCFragment *F) { +void MCAsmLayout::invalidateFragmentsFrom(MCFragment *F) { // If this fragment wasn't already valid, we don't need to do anything. if (!isFragmentValid(F)) return; - // Otherwise, reset the last valid fragment to this fragment. + // Otherwise, reset the last valid fragment to the previous fragment + // (if this is the first fragment, it will be NULL). const MCSectionData &SD = *F->getParent(); - LastValidFragment[&SD] = F; + LastValidFragment[&SD] = F->getPrevNode(); } void MCAsmLayout::ensureValid(const MCFragment *F) const { @@ -165,14 +166,14 @@ uint64_t MCAsmLayout::getSectionFileSize(const MCSectionData *SD) const { uint64_t MCAsmLayout::computeBundlePadding(const MCFragment *F, uint64_t FOffset, uint64_t FSize) { uint64_t BundleSize = Assembler.getBundleAlignSize(); - assert(BundleSize > 0 && + assert(BundleSize > 0 && "computeBundlePadding should only be called if bundling is enabled"); uint64_t BundleMask = BundleSize - 1; uint64_t OffsetInBundle = FOffset & BundleMask; uint64_t EndOfFragment = OffsetInBundle + FSize; // There are two kinds of bundling restrictions: - // + // // 1) For alignToBundleEnd(), add padding to ensure that the fragment will // *end* on a bundle boundary. // 2) Otherwise, check if the fragment would cross a bundle boundary. If it @@ -939,7 +940,7 @@ bool MCAssembler::layoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD) { FirstRelaxedFragment = I; } if (FirstRelaxedFragment) { - Layout.invalidateFragmentsAfter(FirstRelaxedFragment); + Layout.invalidateFragmentsFrom(FirstRelaxedFragment); return true; } return false; @@ -999,7 +1000,7 @@ void MCFragment::dump() { OS << ""; + << " BundlePadding:" << static_cast(getBundlePadding()) << ">"; switch (getKind()) { case MCFragment::FT_Align: { diff --git a/test/MC/X86/AlignedBundling/relax-at-bundle-end.s b/test/MC/X86/AlignedBundling/relax-at-bundle-end.s new file mode 100644 index 00000000000..ab4affbbeac --- /dev/null +++ b/test/MC/X86/AlignedBundling/relax-at-bundle-end.s @@ -0,0 +1,16 @@ +# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - \ +# RUN: | llvm-objdump -disassemble -no-show-raw-insn - | FileCheck %s + +# Test that an instruction near a bundle end gets properly padded +# after it is relaxed. +.text +foo: + .bundle_align_mode 5 + .rept 29 + push %rax + .endr +# CHECK: 1c: push +# CHECK: 1d: nop +# CHECK: 20: jne + jne 0x100 +