@@ -196,6 +196,7 @@ uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const {
196196  switch  (F.getKind ()) {
197197  case  MCFragment::FT_Data:
198198  case  MCFragment::FT_Relaxable:
199+   case  MCFragment::FT_Align:
199200  case  MCFragment::FT_LEB:
200201  case  MCFragment::FT_Dwarf:
201202  case  MCFragment::FT_DwarfFrame:
@@ -226,27 +227,6 @@ uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const {
226227  case  MCFragment::FT_SymbolId:
227228    return  4 ;
228229
229-   case  MCFragment::FT_Align: {
230-     unsigned  Offset = F.Offset  + F.getFixedSize ();
231-     unsigned  Size = offsetToAlignment (Offset, F.getAlignment ());
232- 
233-     //  Insert extra Nops for code alignment if the target define
234-     //  shouldInsertExtraNopBytesForCodeAlign target hook.
235-     if  (F.getParent ()->useCodeAlign () && F.hasAlignEmitNops () &&
236-         getBackend ().shouldInsertExtraNopBytesForCodeAlign (F, Size))
237-       return  F.getFixedSize () + Size;
238- 
239-     //  If we are padding with nops, force the padding to be larger than the
240-     //  minimum nop size.
241-     if  (Size > 0  && F.hasAlignEmitNops ()) {
242-       while  (Size % getBackend ().getMinimumNopSize ())
243-         Size += F.getAlignment ().value ();
244-     }
245-     if  (Size > F.getAlignMaxBytesToEmit ())
246-       Size = 0 ;
247-     return  F.getFixedSize () + Size;
248-   }
249- 
250230  case  MCFragment::FT_Org: {
251231    const  MCOrgFragment &OF = cast<MCOrgFragment>(F);
252232    MCValue Value;
@@ -418,7 +398,6 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
418398  switch  (F.getKind ()) {
419399  case  MCFragment::FT_Data:
420400  case  MCFragment::FT_Relaxable:
421-   case  MCFragment::FT_Align:
422401  case  MCFragment::FT_LEB:
423402  case  MCFragment::FT_Dwarf:
424403  case  MCFragment::FT_DwarfFrame:
@@ -431,42 +410,41 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
431410    const  auto  &EF = cast<MCFragment>(F);
432411    OS << StringRef (EF.getContents ().data (), EF.getContents ().size ());
433412    OS << StringRef (EF.getVarContents ().data (), EF.getVarContents ().size ());
434-     if  (F.getKind () == MCFragment::FT_Align) {
435-       ++stats::EmittedAlignFragments;
436-       assert (F.getAlignFillLen () &&
437-              " Invalid virtual align in concrete fragment!"  );
438- 
439-       uint64_t  Count = (FragmentSize - F.getFixedSize ()) / F.getAlignFillLen ();
440-       assert ((FragmentSize - F.getFixedSize ()) % F.getAlignFillLen () == 0  &&
441-              " computeFragmentSize computed size is incorrect"  );
442- 
443-       //  See if we are aligning with nops, and if so do that first to try to
444-       //  fill the Count bytes.  Then if that did not fill any bytes or there are
445-       //  any bytes left to fill use the Value and ValueSize to fill the rest. If
446-       //  we are aligning with nops, ask that target to emit the right data.
447-       if  (F.hasAlignEmitNops ()) {
448-         if  (!Asm.getBackend ().writeNopData (OS, Count, F.getSubtargetInfo ()))
449-           report_fatal_error (" unable to write nop sequence of "   + Twine (Count) +
450-                              "  bytes"  );
451-       } else  {
452-         //  Otherwise, write out in multiples of the value size.
453-         for  (uint64_t  i = 0 ; i != Count; ++i) {
454-           switch  (F.getAlignFillLen ()) {
455-           default :
456-             llvm_unreachable (" Invalid size!"  );
457-           case  1 :
458-             OS << char (F.getAlignFill ());
459-             break ;
460-           case  2 :
461-             support::endian::write<uint16_t >(OS, F.getAlignFill (), Endian);
462-             break ;
463-           case  4 :
464-             support::endian::write<uint32_t >(OS, F.getAlignFill (), Endian);
465-             break ;
466-           case  8 :
467-             support::endian::write<uint64_t >(OS, F.getAlignFill (), Endian);
468-             break ;
469-           }
413+   } break ;
414+ 
415+   case  MCFragment::FT_Align: {
416+     ++stats::EmittedAlignFragments;
417+     OS << StringRef (F.getContents ().data (), F.getContents ().size ());
418+     assert (F.getAlignFillLen () &&
419+            " Invalid virtual align in concrete fragment!"  );
420+ 
421+     uint64_t  Count = (FragmentSize - F.getFixedSize ()) / F.getAlignFillLen ();
422+     assert ((FragmentSize - F.getFixedSize ()) % F.getAlignFillLen () == 0  &&
423+            " computeFragmentSize computed size is incorrect"  );
424+ 
425+     //  In the nops mode, call the backend hook to write `Count` nops.
426+     if  (F.hasAlignEmitNops ()) {
427+       if  (!Asm.getBackend ().writeNopData (OS, Count, F.getSubtargetInfo ()))
428+         reportFatalInternalError (" unable to write nop sequence of "   +
429+                                  Twine (Count) + "  bytes"  );
430+     } else  {
431+       //  Otherwise, write out in multiples of the value size.
432+       for  (uint64_t  i = 0 ; i != Count; ++i) {
433+         switch  (F.getAlignFillLen ()) {
434+         default :
435+           llvm_unreachable (" Invalid size!"  );
436+         case  1 :
437+           OS << char (F.getAlignFill ());
438+           break ;
439+         case  2 :
440+           support::endian::write<uint16_t >(OS, F.getAlignFill (), Endian);
441+           break ;
442+         case  4 :
443+           support::endian::write<uint32_t >(OS, F.getAlignFill (), Endian);
444+           break ;
445+         case  8 :
446+           support::endian::write<uint64_t >(OS, F.getAlignFill (), Endian);
447+           break ;
470448        }
471449      }
472450    }
@@ -737,11 +715,6 @@ void MCAssembler::layout() {
737715          evaluateFixup (F, Fixup, Target, FixedValue,
738716                        /* RecordReloc=*/ true , Contents);
739717        }
740-       } else  if  (F.getKind () == MCFragment::FT_Align) {
741-         //  For RISC-V linker relaxation, an alignment relocation might be
742-         //  needed.
743-         if  (F.hasAlignEmitNops ())
744-           getBackend ().shouldInsertFixupForCodeAlign (*this , F);
745718      }
746719    }
747720  }
@@ -992,7 +965,30 @@ void MCAssembler::layoutSection(MCSection &Sec) {
992965  uint64_t  Offset = 0 ;
993966  for  (MCFragment &F : Sec) {
994967    F.Offset  = Offset;
995-     Offset += computeFragmentSize (F);
968+     if  (F.getKind () == MCFragment::FT_Align) {
969+       Offset += F.getFixedSize ();
970+       unsigned  Size = offsetToAlignment (Offset, F.getAlignment ());
971+       //  In the nops mode, RISC-V style linker relaxation might adjust the size
972+       //  and add a fixup, even if `Size` is originally 0.
973+       bool  AlignFixup = false ;
974+       if  (F.hasAlignEmitNops ()) {
975+         AlignFixup = getBackend ().relaxAlign (F, Size);
976+         //  If the backend does not handle the fragment specially, pad with nops,
977+         //  but ensure that the padding is larger than the minimum nop size.
978+         if  (!AlignFixup)
979+           while  (Size % getBackend ().getMinimumNopSize ())
980+             Size += F.getAlignment ().value ();
981+       }
982+       if  (!AlignFixup && Size > F.getAlignMaxBytesToEmit ())
983+         Size = 0 ;
984+       //  Update the variable tail size. The content is ignored.
985+       F.VarContentEnd  = F.VarContentStart  + Size;
986+       if  (F.VarContentEnd  > F.getParent ()->ContentStorage .size ())
987+         F.getParent ()->ContentStorage .resize (F.VarContentEnd );
988+       Offset += Size;
989+     } else  {
990+       Offset += computeFragmentSize (F);
991+     }
996992  }
997993}
998994
0 commit comments