Skip to content

Commit 5790066

Browse files
MaskRaycachemeifyoucan
authored andcommitted
MC: Encode FT_Align in fragment's variable-size tail
Follow-up to llvm#148544 Pull Request: llvm#149030
1 parent ea0a12d commit 5790066

File tree

15 files changed

+170
-193
lines changed

15 files changed

+170
-193
lines changed

llvm/include/llvm/MC/MCAsmBackend.h

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

2222
namespace llvm {
2323

24-
class MCAlignFragment;
2524
class MCFragment;
26-
class MCLEBFragment;
2725
class MCSymbol;
2826
class MCAssembler;
2927
class MCContext;
@@ -129,15 +127,14 @@ class LLVM_ABI MCAsmBackend {
129127
/// Hook to check if extra nop bytes must be inserted for alignment directive.
130128
/// For some targets this may be necessary in order to support linker
131129
/// relaxation. The number of bytes to insert are returned in Size.
132-
virtual bool shouldInsertExtraNopBytesForCodeAlign(const MCAlignFragment &AF,
130+
virtual bool shouldInsertExtraNopBytesForCodeAlign(const MCFragment &AF,
133131
unsigned &Size) {
134132
return false;
135133
}
136134

137135
/// Hook which indicates if the target requires a fixup to be generated when
138136
/// handling an align directive in an executable section
139-
virtual bool shouldInsertFixupForCodeAlign(MCAssembler &Asm,
140-
MCAlignFragment &AF) {
137+
virtual bool shouldInsertFixupForCodeAlign(MCAssembler &Asm, MCFragment &AF) {
141138
return false;
142139
}
143140

llvm/include/llvm/MC/MCObjectStreamer.h

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

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

8481
public:
8582
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
@@ -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:
@@ -441,6 +455,38 @@ 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+
444490
//== FT_LEB functions
445491
void makeLEB(bool IsSigned, const MCExpr *Value) {
446492
assert(Kind == FT_Data);
@@ -488,52 +534,6 @@ class MCEncodedFragment : public MCFragment {
488534
: MCFragment(FType, HasInstructions) {}
489535
};
490536

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

llvm/lib/MC/MCAssembler.cpp

Lines changed: 66 additions & 72 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;
@@ -703,34 +701,30 @@ void MCAssembler::layout() {
703701
for (MCSection &Sec : *this) {
704702
for (MCFragment &F : Sec) {
705703
// Process fragments with fixups here.
706-
if (F.isEncoded()) {
707-
auto Contents = F.getContents();
708-
for (MCFixup &Fixup : F.getFixups()) {
704+
auto Contents = F.getContents();
705+
for (MCFixup &Fixup : F.getFixups()) {
706+
uint64_t FixedValue;
707+
MCValue Target;
708+
evaluateFixup(F, Fixup, Target, FixedValue,
709+
/*RecordReloc=*/true, Contents);
710+
}
711+
if (F.getVarFixups().size()) {
712+
// In the variable part, fixup offsets are relative to the fixed part's
713+
// start. Extend the variable contents to the left to account for the
714+
// fixed part size.
715+
Contents = MutableArrayRef(F.getParent()->ContentStorage)
716+
.slice(F.VarContentStart - Contents.size(), F.getSize());
717+
for (MCFixup &Fixup : F.getVarFixups()) {
709718
uint64_t FixedValue;
710719
MCValue Target;
711720
evaluateFixup(F, Fixup, Target, FixedValue,
712721
/*RecordReloc=*/true, Contents);
713722
}
714-
// In the variable part, fixup offsets are relative to the fixed part's
715-
// start. Extend the variable contents to the left to account for the
716-
// fixed part size.
717-
auto VarFixups = F.getVarFixups();
718-
if (VarFixups.size()) {
719-
Contents =
720-
MutableArrayRef(F.getParent()->ContentStorage)
721-
.slice(F.VarContentStart - Contents.size(), F.getSize());
722-
for (MCFixup &Fixup : VarFixups) {
723-
uint64_t FixedValue;
724-
MCValue Target;
725-
evaluateFixup(F, Fixup, Target, FixedValue,
726-
/*RecordReloc=*/true, Contents);
727-
}
728-
}
729-
} else if (auto *AF = dyn_cast<MCAlignFragment>(&F)) {
723+
} else if (F.getKind() == MCFragment::FT_Align) {
730724
// For RISC-V linker relaxation, an alignment relocation might be
731725
// needed.
732-
if (AF->hasEmitNops())
733-
getBackend().shouldInsertFixupForCodeAlign(*this, *AF);
726+
if (F.hasAlignEmitNops())
727+
getBackend().shouldInsertFixupForCodeAlign(*this, F);
734728
}
735729
}
736730
}

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
@@ -72,17 +72,9 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
7272
};
7373

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

0 commit comments

Comments
 (0)