Skip to content

Commit c3dca21

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 cfddb40 commit c3dca21

File tree

14 files changed

+174
-197
lines changed

14 files changed

+174
-197
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
@@ -255,6 +255,19 @@ class MCFragment {
255255
uint32_t OperandStart;
256256
uint32_t OperandSize;
257257
} relax;
258+
struct {
259+
// The alignment to ensure, in bytes.
260+
Align Alignment;
261+
// The size of the integer (in bytes) of \p Value.
262+
uint8_t FillLen;
263+
// If true, fill with target-specific nop instructions.
264+
bool EmitNops;
265+
// The maximum number of bytes to emit; if the alignment
266+
// cannot be satisfied in this width then this fragment is ignored.
267+
unsigned MaxBytesToEmit;
268+
// Value to use for filling padding bytes.
269+
int64_t Fill;
270+
} align;
258271
struct {
259272
// True if this is a sleb128, false if uleb128.
260273
bool IsSigned;
@@ -284,6 +297,7 @@ class MCFragment {
284297
return false;
285298
case MCFragment::FT_Relaxable:
286299
case MCFragment::FT_Data:
300+
case MCFragment::FT_Align:
287301
case MCFragment::FT_Dwarf:
288302
case MCFragment::FT_DwarfFrame:
289303
case MCFragment::FT_LEB:
@@ -442,6 +456,43 @@ class MCFragment {
442456
llvm::copy(Inst, S.begin() + u.relax.OperandStart);
443457
}
444458

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

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