diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -389,14 +389,15 @@ void MCAsmLayout::layoutFragment(MCFragment *F) { MCFragment *Prev = F->getPrevNode(); - // We should never try to recompute something which is valid. - assert(!isFragmentValid(F) && "Attempt to recompute a valid fragment!"); // We should never try to compute the fragment layout if its predecessor // isn't valid. assert((!Prev || isFragmentValid(Prev)) && "Attempt to compute fragment before its predecessor!"); - ++stats::FragmentLayouts; + // We may need to recompute the offset of valid framents if relaxation changes + // the offset of some fragments. PR#45190 + if (!isFragmentValid(F)) + ++stats::FragmentLayouts; // Compute fragment offset and size. if (Prev) @@ -785,9 +786,18 @@ } // Layout until everything fits. - while (layoutOnce(Layout)) + bool WasRelaxed = false; + while (layoutOnce(Layout)) { if (getContext().hadError()) return; + WasRelaxed = true; + } + // recalculate the offsets of fragments if relaxation happens. PR#45190 + if (WasRelaxed) { + for (MCSection &Sec : *this) + for (MCFragment &F : Sec) + Layout.layoutFragment(&F); + } DEBUG_WITH_TYPE("mc-dump", { errs() << "assembler backend - post-relaxation\n--\n"; diff --git a/llvm/test/MC/X86/relax-offset.s b/llvm/test/MC/X86/relax-offset.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/X86/relax-offset.s @@ -0,0 +1,15 @@ +# RUN: llvm-mc -filetype=obj -triple=i386 %s -o /dev/null + +.macro ALTERNATIVE newinstr + .skip 144f-143f,0x0 + .pushsection .altinstr_replacement,"ax" +143: + \newinstr +144: + .popsection +.endm + + .section .entry.text, "ax" + ALTERNATIVE "jmp .Lint80_keep_stack" +.Lint80_keep_stack: +# CHECK-NOT: error: Assertion `OS.tell() - Start == Layout.getSectionAddressSize(Sec)' failed