Skip to content

Commit 17b511e

Browse files
committed
MC: Encode FT_Align in fragment's variable-size tail
Follow-up to llvm#148544 Pull Request: llvm#149030
1 parent 39c8cfb commit 17b511e

File tree

15 files changed

+171
-196
lines changed

15 files changed

+171
-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/MCObjectStreamer.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,6 @@ class MCObjectStreamer : public MCStreamer {
7878

7979
protected:
8080
bool changeSectionImpl(MCSection *Section, uint32_t Subsection);
81-
MCAlignFragment *createAlignFragment(Align Alignment, int64_t Fill,
82-
uint8_t FillLen,
83-
unsigned MaxBytesToEmit);
8481

8582
public:
8683
void visitUsedSymbol(const MCSymbol &Sym) override;

llvm/include/llvm/MC/MCSection.h

Lines changed: 46 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:
@@ -440,6 +454,38 @@ class MCFragment {
440454
llvm::copy(Inst, S.begin() + u.relax.OperandStart);
441455
}
442456

457+
//== FT_Align functions
458+
void makeAlign(Align Alignment, int64_t Fill, uint8_t FillLen,
459+
unsigned MaxBytesToEmit) {
460+
Kind = FT_Align;
461+
u.align.EmitNops = false;
462+
u.align.Alignment = Alignment;
463+
u.align.Fill = Fill;
464+
u.align.FillLen = FillLen;
465+
u.align.MaxBytesToEmit = MaxBytesToEmit;
466+
}
467+
468+
Align getAlignment() const {
469+
assert(Kind == FT_Align);
470+
return u.align.Alignment;
471+
}
472+
int64_t getAlignFill() const {
473+
assert(Kind == FT_Align);
474+
return u.align.Fill;
475+
}
476+
uint8_t getAlignFillLen() const {
477+
assert(Kind == FT_Align);
478+
return u.align.FillLen;
479+
}
480+
unsigned getAlignMaxBytesToEmit() const {
481+
assert(Kind == FT_Align);
482+
return u.align.MaxBytesToEmit;
483+
}
484+
bool hasAlignEmitNops() const {
485+
assert(Kind == FT_Align);
486+
return u.align.EmitNops;
487+
}
488+
443489
//== FT_LEB functions
444490
void makeLEB(bool IsSigned, const MCExpr *Value) {
445491
assert(Kind == FT_Data);
@@ -487,52 +533,6 @@ class MCEncodedFragment : public MCFragment {
487533
: MCFragment(FType, HasInstructions) {}
488534
};
489535

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-
536536
class MCFillFragment : public MCFragment {
537537
uint8_t ValueSize;
538538
/// 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
@@ -227,25 +227,24 @@ uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const {
227227
return 4;
228228

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

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

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

251250
case MCFragment::FT_Org: {
@@ -419,6 +418,7 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
419418
switch (F.getKind()) {
420419
case MCFragment::FT_Data:
421420
case MCFragment::FT_Relaxable:
421+
case MCFragment::FT_Align:
422422
case MCFragment::FT_LEB:
423423
case MCFragment::FT_Dwarf:
424424
case MCFragment::FT_DwarfFrame:
@@ -431,48 +431,46 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
431431
const auto &EF = cast<MCFragment>(F);
432432
OS << StringRef(EF.getContents().data(), EF.getContents().size());
433433
OS << StringRef(EF.getVarContents().data(), EF.getVarContents().size());
434-
break;
435-
}
436-
case MCFragment::FT_Align: {
437-
++stats::EmittedAlignFragments;
438-
const MCAlignFragment &AF = cast<MCAlignFragment>(F);
439-
assert(AF.getFillLen() && "Invalid virtual align in concrete fragment!");
440-
441-
uint64_t Count = FragmentSize / AF.getFillLen();
442-
assert(FragmentSize % AF.getFillLen() == 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 fill
446-
// the Count bytes. Then if that did not fill any bytes or there are any
447-
// bytes left to fill use the Value and ValueSize to fill the rest.
448-
// If we are aligning with nops, ask that target to emit the right data.
449-
if (AF.hasEmitNops()) {
450-
if (!Asm.getBackend().writeNopData(OS, Count, AF.getSubtargetInfo()))
451-
report_fatal_error("unable to write nop sequence of " +
452-
Twine(Count) + " bytes");
453-
break;
454-
}
455-
456-
// Otherwise, write out in multiples of the value size.
457-
for (uint64_t i = 0; i != Count; ++i) {
458-
switch (AF.getFillLen()) {
459-
default: llvm_unreachable("Invalid size!");
460-
case 1:
461-
OS << char(AF.getFill());
462-
break;
463-
case 2:
464-
support::endian::write<uint16_t>(OS, AF.getFill(), Endian);
465-
break;
466-
case 4:
467-
support::endian::write<uint32_t>(OS, AF.getFill(), Endian);
468-
break;
469-
case 8:
470-
support::endian::write<uint64_t>(OS, AF.getFill(), Endian);
471-
break;
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+
}
470+
}
472471
}
473472
}
474-
break;
475-
}
473+
} break;
476474

477475
case MCFragment::FT_Fill: {
478476
++stats::EmittedFillFragments;
@@ -610,9 +608,7 @@ void MCAssembler::writeSectionData(raw_ostream &OS,
610608
case MCFragment::FT_Align:
611609
// Check that we aren't trying to write a non-zero value into a virtual
612610
// section.
613-
assert((cast<MCAlignFragment>(F).getFillLen() == 0 ||
614-
cast<MCAlignFragment>(F).getFill() == 0) &&
615-
"Invalid align in virtual section!");
611+
assert(F.getAlignFill() == 0 && "Invalid align in virtual section!");
616612
break;
617613
case MCFragment::FT_Fill:
618614
assert((cast<MCFillFragment>(F).getValue() == 0) &&
@@ -722,34 +718,30 @@ void MCAssembler::layout() {
722718
for (MCSection &Sec : *this) {
723719
for (MCFragment &F : Sec) {
724720
// Process fragments with fixups here.
725-
if (F.isEncoded()) {
726-
auto Contents = F.getContents();
727-
for (MCFixup &Fixup : F.getFixups()) {
721+
auto Contents = F.getContents();
722+
for (MCFixup &Fixup : F.getFixups()) {
723+
uint64_t FixedValue;
724+
MCValue Target;
725+
evaluateFixup(F, Fixup, Target, FixedValue,
726+
/*RecordReloc=*/true, Contents);
727+
}
728+
if (F.getVarFixups().size()) {
729+
// In the variable part, fixup offsets are relative to the fixed part's
730+
// start. Extend the variable contents to the left to account for the
731+
// fixed part size.
732+
Contents = MutableArrayRef(F.getParent()->ContentStorage)
733+
.slice(F.VarContentStart - Contents.size(), F.getSize());
734+
for (MCFixup &Fixup : F.getVarFixups()) {
728735
uint64_t FixedValue;
729736
MCValue Target;
730737
evaluateFixup(F, Fixup, Target, FixedValue,
731738
/*RecordReloc=*/true, Contents);
732739
}
733-
// In the variable part, fixup offsets are relative to the fixed part's
734-
// start. Extend the variable contents to the left to account for the
735-
// fixed part size.
736-
auto VarFixups = F.getVarFixups();
737-
if (VarFixups.size()) {
738-
Contents =
739-
MutableArrayRef(F.getParent()->ContentStorage)
740-
.slice(F.VarContentStart - Contents.size(), F.getSize());
741-
for (MCFixup &Fixup : VarFixups) {
742-
uint64_t FixedValue;
743-
MCValue Target;
744-
evaluateFixup(F, Fixup, Target, FixedValue,
745-
/*RecordReloc=*/true, Contents);
746-
}
747-
}
748-
} else if (auto *AF = dyn_cast<MCAlignFragment>(&F)) {
740+
} else if (F.getKind() == MCFragment::FT_Align) {
749741
// For RISC-V linker relaxation, an alignment relocation might be
750742
// needed.
751-
if (AF->hasEmitNops())
752-
getBackend().shouldInsertFixupForCodeAlign(*this, *AF);
743+
if (F.hasAlignEmitNops())
744+
getBackend().shouldInsertFixupForCodeAlign(*this, F);
753745
}
754746
}
755747
}

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();

0 commit comments

Comments
 (0)