@@ -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