@@ -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 }
@@ -720,11 +698,6 @@ void MCAssembler::layout() {
720698 evaluateFixup (F, Fixup, Target, FixedValue,
721699 /* RecordReloc=*/ true , Contents);
722700 }
723- } else if (F.getKind () == MCFragment::FT_Align) {
724- // For RISC-V linker relaxation, an alignment relocation might be
725- // needed.
726- if (F.hasAlignEmitNops ())
727- getBackend ().shouldInsertFixupForCodeAlign (*this , F);
728701 }
729702 }
730703 }
@@ -975,7 +948,32 @@ void MCAssembler::layoutSection(MCSection &Sec) {
975948 uint64_t Offset = 0 ;
976949 for (MCFragment &F : Sec) {
977950 F.Offset = Offset;
978- Offset += computeFragmentSize (F);
951+ if (F.getKind () == MCFragment::FT_Align) {
952+ Offset += F.getFixedSize ();
953+ unsigned Size = offsetToAlignment (Offset, F.getAlignment ());
954+ // In the nops mode, RISC-V style linker relaxation might adjust the size
955+ // and add a fixup, even if `Size` is originally 0.
956+ bool AlignFixup = false ;
957+ if (F.hasAlignEmitNops ()) {
958+ AlignFixup = getBackend ().relaxAlign (F, Size);
959+ // If the backend does not handle the fragment specially, pad with nops,
960+ // but ensure that the padding is larger than the minimum nop size.
961+ if (!AlignFixup)
962+ while (Size % getBackend ().getMinimumNopSize ())
963+ Size += F.getAlignment ().value ();
964+ }
965+ if (!AlignFixup && Size > F.getAlignMaxBytesToEmit ())
966+ Size = 0 ;
967+ // Update the variable tail size. The content is ignored.
968+ assert (F.VarContentStart == 0 &&
969+ " VarContentStart should not be modified" );
970+ F.VarContentEnd = Size;
971+ if (F.VarContentEnd > F.getParent ()->ContentStorage .size ())
972+ F.getParent ()->ContentStorage .resize (F.VarContentEnd );
973+ Offset += Size;
974+ } else {
975+ Offset += computeFragmentSize (F);
976+ }
979977 }
980978}
981979
0 commit comments