Skip to content

Commit 2beff29

Browse files
committed
MC: Restructure MCAlignFragment as a fixed part and an alignment tail
Follow-up to llvm#148544 Pull Request: llvm#149030
1 parent 52a9c49 commit 2beff29

File tree

14 files changed

+174
-196
lines changed

14 files changed

+174
-196
lines changed

llvm/include/llvm/MC/MCAsmBackend.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@
1818

1919
namespace llvm {
2020

21-
class MCAlignFragment;
2221
class MCFragment;
23-
class MCLEBFragment;
2422
class MCSymbol;
2523
class MCAssembler;
2624
class MCContext;
@@ -108,15 +106,14 @@ class LLVM_ABI MCAsmBackend {
108106
/// Hook to check if extra nop bytes must be inserted for alignment directive.
109107
/// For some targets this may be necessary in order to support linker
110108
/// relaxation. The number of bytes to insert are returned in Size.
111-
virtual bool shouldInsertExtraNopBytesForCodeAlign(const MCAlignFragment &AF,
109+
virtual bool shouldInsertExtraNopBytesForCodeAlign(const MCFragment &AF,
112110
unsigned &Size) {
113111
return false;
114112
}
115113

116114
/// Hook which indicates if the target requires a fixup to be generated when
117115
/// handling an align directive in an executable section
118-
virtual bool shouldInsertFixupForCodeAlign(MCAssembler &Asm,
119-
MCAlignFragment &AF) {
116+
virtual bool shouldInsertFixupForCodeAlign(MCAssembler &Asm, MCFragment &AF) {
120117
return false;
121118
}
122119

llvm/include/llvm/MC/MCSection.h

Lines changed: 51 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,19 @@ class MCFragment {
254254
uint32_t OperandStart;
255255
uint32_t OperandSize;
256256
} relax;
257+
struct {
258+
// The alignment to ensure, in bytes.
259+
Align Alignment;
260+
// The size of the integer (in bytes) of \p Value.
261+
uint8_t FillLen;
262+
// If true, fill with target-specific nop instructions.
263+
bool EmitNops;
264+
// The maximum number of bytes to emit; if the alignment
265+
// cannot be satisfied in this width then this fragment is ignored.
266+
unsigned MaxBytesToEmit;
267+
// Value to use for filling padding bytes.
268+
int64_t Fill;
269+
} align;
257270
struct {
258271
// True if this is a sleb128, false if uleb128.
259272
bool IsSigned;
@@ -283,6 +296,7 @@ class MCFragment {
283296
return false;
284297
case MCFragment::FT_Relaxable:
285298
case MCFragment::FT_Data:
299+
case MCFragment::FT_Align:
286300
case MCFragment::FT_Dwarf:
287301
case MCFragment::FT_DwarfFrame:
288302
case MCFragment::FT_LEB:
@@ -441,6 +455,43 @@ class MCFragment {
441455
llvm::copy(Inst, S.begin() + u.relax.OperandStart);
442456
}
443457

458+
//== FT_Align functions
459+
void makeAlign(Align Alignment, int64_t Fill, uint8_t FillLen,
460+
unsigned MaxBytesToEmit) {
461+
Kind = FT_Align;
462+
u.align.EmitNops = false;
463+
u.align.Alignment = Alignment;
464+
u.align.Fill = Fill;
465+
u.align.FillLen = FillLen;
466+
u.align.MaxBytesToEmit = MaxBytesToEmit;
467+
}
468+
469+
Align getAlignment() const {
470+
assert(Kind == FT_Align);
471+
return u.align.Alignment;
472+
}
473+
int64_t getAlignFill() const {
474+
assert(Kind == FT_Align);
475+
return u.align.Fill;
476+
}
477+
uint8_t getAlignFillLen() const {
478+
assert(Kind == FT_Align);
479+
return u.align.FillLen;
480+
}
481+
unsigned getAlignMaxBytesToEmit() const {
482+
assert(Kind == FT_Align);
483+
return u.align.MaxBytesToEmit;
484+
}
485+
bool hasAlignEmitNops() const {
486+
assert(Kind == FT_Align);
487+
return u.align.EmitNops;
488+
}
489+
void setAlignEmitNops(bool Value, const MCSubtargetInfo *STI) {
490+
assert(Kind == FT_Align);
491+
u.align.EmitNops = Value;
492+
this->STI = STI;
493+
}
494+
444495
//== FT_LEB functions
445496
const MCExpr &getLEBValue() const {
446497
assert(Kind == FT_LEB);
@@ -486,52 +537,6 @@ class MCEncodedFragment : public MCFragment {
486537
: MCFragment(FType, HasInstructions) {}
487538
};
488539

489-
class MCAlignFragment : public MCFragment {
490-
/// Flag to indicate that (optimal) NOPs should be emitted instead
491-
/// of using the provided value. The exact interpretation of this flag is
492-
/// target dependent.
493-
bool EmitNops : 1;
494-
495-
/// The alignment to ensure, in bytes.
496-
Align Alignment;
497-
498-
/// The size of the integer (in bytes) of \p Value.
499-
uint8_t FillLen;
500-
501-
/// The maximum number of bytes to emit; if the alignment
502-
/// cannot be satisfied in this width then this fragment is ignored.
503-
unsigned MaxBytesToEmit;
504-
505-
/// Value to use for filling padding bytes.
506-
int64_t Fill;
507-
508-
/// When emitting Nops some subtargets have specific nop encodings.
509-
const MCSubtargetInfo *STI = nullptr;
510-
511-
public:
512-
MCAlignFragment(Align Alignment, int64_t Fill, uint8_t FillLen,
513-
unsigned MaxBytesToEmit)
514-
: MCFragment(FT_Align, false), EmitNops(false), Alignment(Alignment),
515-
FillLen(FillLen), MaxBytesToEmit(MaxBytesToEmit), Fill(Fill) {}
516-
517-
Align getAlignment() const { return Alignment; }
518-
int64_t getFill() const { return Fill; }
519-
uint8_t getFillLen() const { return FillLen; }
520-
unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; }
521-
522-
bool hasEmitNops() const { return EmitNops; }
523-
void setEmitNops(bool Value, const MCSubtargetInfo *STI) {
524-
EmitNops = Value;
525-
this->STI = STI;
526-
}
527-
528-
const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
529-
530-
static bool classof(const MCFragment *F) {
531-
return F->getKind() == MCFragment::FT_Align;
532-
}
533-
};
534-
535540
class MCFillFragment : public MCFragment {
536541
uint8_t ValueSize;
537542
/// Value to use for filling bytes.

llvm/lib/MC/MCAssembler.cpp

Lines changed: 67 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -228,25 +228,24 @@ uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const {
228228
return 4;
229229

230230
case MCFragment::FT_Align: {
231-
const MCAlignFragment &AF = cast<MCAlignFragment>(F);
232-
unsigned Offset = getFragmentOffset(AF);
233-
unsigned Size = offsetToAlignment(Offset, AF.getAlignment());
231+
unsigned Offset = F.Offset + F.getFixedSize();
232+
unsigned Size = offsetToAlignment(Offset, F.getAlignment());
234233

235234
// Insert extra Nops for code alignment if the target define
236235
// shouldInsertExtraNopBytesForCodeAlign target hook.
237-
if (AF.getParent()->useCodeAlign() && AF.hasEmitNops() &&
238-
getBackend().shouldInsertExtraNopBytesForCodeAlign(AF, Size))
239-
return Size;
236+
if (F.getParent()->useCodeAlign() && F.hasAlignEmitNops() &&
237+
getBackend().shouldInsertExtraNopBytesForCodeAlign(F, Size))
238+
return F.getFixedSize() + Size;
240239

241240
// If we are padding with nops, force the padding to be larger than the
242241
// minimum nop size.
243-
if (Size > 0 && AF.hasEmitNops()) {
242+
if (Size > 0 && F.hasAlignEmitNops()) {
244243
while (Size % getBackend().getMinimumNopSize())
245-
Size += AF.getAlignment().value();
244+
Size += F.getAlignment().value();
246245
}
247-
if (Size > AF.getMaxBytesToEmit())
248-
return 0;
249-
return Size;
246+
if (Size > F.getAlignMaxBytesToEmit())
247+
Size = 0;
248+
return F.getFixedSize() + Size;
250249
}
251250

252251
case MCFragment::FT_Org: {
@@ -420,6 +419,7 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
420419
switch (F.getKind()) {
421420
case MCFragment::FT_Data:
422421
case MCFragment::FT_Relaxable:
422+
case MCFragment::FT_Align:
423423
case MCFragment::FT_LEB:
424424
case MCFragment::FT_Dwarf:
425425
case MCFragment::FT_DwarfFrame:
@@ -433,48 +433,46 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
433433
const auto &EF = cast<MCFragment>(F);
434434
OS << StringRef(EF.getContents().data(), EF.getContents().size());
435435
OS << StringRef(EF.getVarContents().data(), EF.getVarContents().size());
436-
break;
437-
}
438-
case MCFragment::FT_Align: {
439-
++stats::EmittedAlignFragments;
440-
const MCAlignFragment &AF = cast<MCAlignFragment>(F);
441-
assert(AF.getFillLen() && "Invalid virtual align in concrete fragment!");
442-
443-
uint64_t Count = FragmentSize / AF.getFillLen();
444-
assert(FragmentSize % AF.getFillLen() == 0 &&
445-
"computeFragmentSize computed size is incorrect");
446-
447-
// See if we are aligning with nops, and if so do that first to try to fill
448-
// the Count bytes. Then if that did not fill any bytes or there are any
449-
// bytes left to fill use the Value and ValueSize to fill the rest.
450-
// If we are aligning with nops, ask that target to emit the right data.
451-
if (AF.hasEmitNops()) {
452-
if (!Asm.getBackend().writeNopData(OS, Count, AF.getSubtargetInfo()))
453-
report_fatal_error("unable to write nop sequence of " +
454-
Twine(Count) + " bytes");
455-
break;
456-
}
457-
458-
// Otherwise, write out in multiples of the value size.
459-
for (uint64_t i = 0; i != Count; ++i) {
460-
switch (AF.getFillLen()) {
461-
default: llvm_unreachable("Invalid size!");
462-
case 1:
463-
OS << char(AF.getFill());
464-
break;
465-
case 2:
466-
support::endian::write<uint16_t>(OS, AF.getFill(), Endian);
467-
break;
468-
case 4:
469-
support::endian::write<uint32_t>(OS, AF.getFill(), Endian);
470-
break;
471-
case 8:
472-
support::endian::write<uint64_t>(OS, AF.getFill(), Endian);
473-
break;
436+
if (F.getKind() == MCFragment::FT_Align) {
437+
++stats::EmittedAlignFragments;
438+
assert(F.getAlignFillLen() &&
439+
"Invalid virtual align in concrete fragment!");
440+
441+
uint64_t Count = (FragmentSize - F.getFixedSize()) / F.getAlignFillLen();
442+
assert((FragmentSize - F.getFixedSize()) % F.getAlignFillLen() == 0 &&
443+
"computeFragmentSize computed size is incorrect");
444+
445+
// See if we are aligning with nops, and if so do that first to try to
446+
// fill the Count bytes. Then if that did not fill any bytes or there are
447+
// any bytes left to fill use the Value and ValueSize to fill the rest. If
448+
// we are aligning with nops, ask that target to emit the right data.
449+
if (F.hasAlignEmitNops()) {
450+
if (!Asm.getBackend().writeNopData(OS, Count, F.getSubtargetInfo()))
451+
report_fatal_error("unable to write nop sequence of " + Twine(Count) +
452+
" bytes");
453+
} else {
454+
// Otherwise, write out in multiples of the value size.
455+
for (uint64_t i = 0; i != Count; ++i) {
456+
switch (F.getAlignFillLen()) {
457+
default:
458+
llvm_unreachable("Invalid size!");
459+
case 1:
460+
OS << char(F.getAlignFill());
461+
break;
462+
case 2:
463+
support::endian::write<uint16_t>(OS, F.getAlignFill(), Endian);
464+
break;
465+
case 4:
466+
support::endian::write<uint32_t>(OS, F.getAlignFill(), Endian);
467+
break;
468+
case 8:
469+
support::endian::write<uint64_t>(OS, F.getAlignFill(), Endian);
470+
break;
471+
}
472+
}
474473
}
475474
}
476-
break;
477-
}
475+
} break;
478476

479477
case MCFragment::FT_Fill: {
480478
++stats::EmittedFillFragments;
@@ -612,9 +610,7 @@ void MCAssembler::writeSectionData(raw_ostream &OS,
612610
case MCFragment::FT_Align:
613611
// Check that we aren't trying to write a non-zero value into a virtual
614612
// section.
615-
assert((cast<MCAlignFragment>(F).getFillLen() == 0 ||
616-
cast<MCAlignFragment>(F).getFill() == 0) &&
617-
"Invalid align in virtual section!");
613+
assert(F.getAlignFill() == 0 && "Invalid align in virtual section!");
618614
break;
619615
case MCFragment::FT_Fill:
620616
assert((cast<MCFillFragment>(F).getValue() == 0) &&
@@ -724,34 +720,30 @@ void MCAssembler::layout() {
724720
for (MCSection &Sec : *this) {
725721
for (MCFragment &F : Sec) {
726722
// Process fragments with fixups here.
727-
if (F.isEncoded()) {
728-
auto Contents = F.getContents();
729-
for (MCFixup &Fixup : F.getFixups()) {
723+
auto Contents = F.getContents();
724+
for (MCFixup &Fixup : F.getFixups()) {
725+
uint64_t FixedValue;
726+
MCValue Target;
727+
evaluateFixup(F, Fixup, Target, FixedValue,
728+
/*RecordReloc=*/true, Contents);
729+
}
730+
if (F.getVarFixups().size()) {
731+
// In the variable part, fixup offsets are relative to the fixed part's
732+
// start. Extend the variable contents to the left to account for the
733+
// fixed part size.
734+
Contents = MutableArrayRef(F.getParent()->ContentStorage)
735+
.slice(F.VarContentStart - Contents.size(), F.getSize());
736+
for (MCFixup &Fixup : F.getVarFixups()) {
730737
uint64_t FixedValue;
731738
MCValue Target;
732739
evaluateFixup(F, Fixup, Target, FixedValue,
733740
/*RecordReloc=*/true, Contents);
734741
}
735-
// In the variable part, fixup offsets are relative to the fixed part's
736-
// start. Extend the variable contents to the left to account for the
737-
// fixed part size.
738-
auto VarFixups = F.getVarFixups();
739-
if (VarFixups.size()) {
740-
Contents =
741-
MutableArrayRef(F.getParent()->ContentStorage)
742-
.slice(F.VarContentStart - Contents.size(), F.getSize());
743-
for (MCFixup &Fixup : VarFixups) {
744-
uint64_t FixedValue;
745-
MCValue Target;
746-
evaluateFixup(F, Fixup, Target, FixedValue,
747-
/*RecordReloc=*/true, Contents);
748-
}
749-
}
750-
} else if (auto *AF = dyn_cast<MCAlignFragment>(&F)) {
742+
} else if (F.getKind() == MCFragment::FT_Align) {
751743
// For RISC-V linker relaxation, an alignment relocation might be
752744
// needed.
753-
if (AF->hasEmitNops())
754-
getBackend().shouldInsertFixupForCodeAlign(*this, *AF);
745+
if (F.hasAlignEmitNops())
746+
getBackend().shouldInsertFixupForCodeAlign(*this, F);
755747
}
756748
}
757749
}

llvm/lib/MC/MCExpr.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -379,11 +379,11 @@ static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm,
379379
// After layout, during relocation generation, it can be treated as a
380380
// data fragment.
381381
Displacement += F->getSize();
382-
} else if (auto *AF = dyn_cast<MCAlignFragment>(F);
383-
AF && Layout && AF->hasEmitNops() &&
382+
} else if (F->getKind() == MCFragment::FT_Align && Layout &&
383+
F->hasAlignEmitNops() &&
384384
!Asm->getBackend().shouldInsertExtraNopBytesForCodeAlign(
385-
*AF, Count)) {
386-
Displacement += Asm->computeFragmentSize(*AF);
385+
*F, Count)) {
386+
Displacement += Asm->computeFragmentSize(*F);
387387
} else if (auto *FF = dyn_cast<MCFillFragment>(F);
388388
FF && FF->getNumValues().evaluateAsAbsolute(Num)) {
389389
Displacement += Num * FF->getValueSize();

llvm/lib/MC/MCFragment.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,17 +73,9 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
7373
};
7474

7575
switch (getKind()) {
76-
case MCFragment::FT_Align: {
77-
const auto *AF = cast<MCAlignFragment>(this);
78-
OS << " Align:" << AF->getAlignment().value() << " Fill:" << AF->getFill()
79-
<< " FillLen:" << unsigned(AF->getFillLen())
80-
<< " MaxBytesToEmit:" << AF->getMaxBytesToEmit();
81-
if (AF->hasEmitNops())
82-
OS << " Nops";
83-
break;
84-
}
8576
case MCFragment::FT_Data:
8677
case MCFragment::FT_Relaxable:
78+
case MCFragment::FT_Align:
8779
case MCFragment::FT_LEB:
8880
case MCFragment::FT_Dwarf:
8981
case MCFragment::FT_DwarfFrame: {
@@ -112,6 +104,13 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
112104
OS << ' ';
113105
getInst().dump_pretty(OS);
114106
break;
107+
case MCFragment::FT_Align:
108+
OS << "\n Align:" << getAlignment().value() << " Fill:" << getAlignFill()
109+
<< " FillLen:" << unsigned(getAlignFillLen())
110+
<< " MaxBytesToEmit:" << getAlignMaxBytesToEmit();
111+
if (hasAlignEmitNops())
112+
OS << " Nops";
113+
break;
115114
case MCFragment::FT_LEB: {
116115
OS << " Value:";
117116
getLEBValue().print(OS, nullptr);

0 commit comments

Comments
 (0)