1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

[MC] Move bundling and MCSubtargetInfo to MCEncodedFragment [NFC]

Instruction bundling is only supported on descendants of the
MCEncodedFragment type. By moving the bundling functionality and
MCSubtargetInfo to this class it makes it easier to set and extract the
MCSubtargetInfo when it is necessary.

This is a refactoring change that will make it easier to pass the
MCSubtargetInfo through to writeNops when nop padding is required.

Differential Revision: https://reviews.llvm.org/D45959

llvm-svn: 334814
This commit is contained in:
Peter Smith 2018-06-15 09:48:18 +00:00
parent d3ce5d4b09
commit d93c0f957b
5 changed files with 92 additions and 89 deletions

View File

@ -442,7 +442,7 @@ public:
/// Write the necessary bundle padding to \p OS.
/// Expects a fragment \p F containing instructions and its size \p FSize.
void writeFragmentPadding(raw_ostream &OS, const MCFragment &F,
void writeFragmentPadding(raw_ostream &OS, const MCEncodedFragment &F,
uint64_t FSize) const;
/// @}
@ -453,8 +453,9 @@ public:
/// Compute the amount of padding required before the fragment \p F to
/// obey bundling restrictions, where \p FOffset is the fragment's offset in
/// its section and \p FSize is the fragment's size.
uint64_t computeBundlePadding(const MCAssembler &Assembler, const MCFragment *F,
uint64_t FOffset, uint64_t FSize);
uint64_t computeBundlePadding(const MCAssembler &Assembler,
const MCEncodedFragment *F, uint64_t FOffset,
uint64_t FSize);
} // end namespace llvm

View File

@ -56,11 +56,6 @@ protected:
bool HasInstructions;
private:
/// Should this fragment be aligned to the end of a bundle?
bool AlignToBundleEnd;
uint8_t BundlePadding;
/// LayoutOrder - The layout order of this fragment.
unsigned LayoutOrder;
@ -84,7 +79,7 @@ private:
protected:
MCFragment(FragmentType Kind, bool HasInstructions,
uint8_t BundlePadding, MCSection *Parent = nullptr);
MCSection *Parent = nullptr);
~MCFragment();
@ -114,6 +109,50 @@ public:
/// this is false, but specific fragment types may set it to true.
bool hasInstructions() const { return HasInstructions; }
/// Return true if given frgment has FT_Dummy type.
bool isDummy() const { return Kind == FT_Dummy; }
void dump() const;
};
class MCDummyFragment : public MCFragment {
public:
explicit MCDummyFragment(MCSection *Sec) : MCFragment(FT_Dummy, false, Sec) {}
static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; }
};
/// Interface implemented by fragments that contain encoded instructions and/or
/// data.
///
class MCEncodedFragment : public MCFragment {
/// Should this fragment be aligned to the end of a bundle?
bool AlignToBundleEnd = false;
uint8_t BundlePadding = 0;
protected:
MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions,
MCSection *Sec)
: MCFragment(FType, HasInstructions, Sec) {}
/// STI - The MCSubtargetInfo in effect when the instruction was encoded.
/// must be non-null for instructions.
const MCSubtargetInfo *STI = nullptr;
public:
static bool classof(const MCFragment *F) {
MCFragment::FragmentType Kind = F->getKind();
switch (Kind) {
default:
return false;
case MCFragment::FT_Relaxable:
case MCFragment::FT_CompactEncodedInst:
case MCFragment::FT_Data:
return true;
}
}
/// Should this fragment be placed at the end of an aligned bundle?
bool alignToBundleEnd() const { return AlignToBundleEnd; }
void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
@ -129,40 +168,15 @@ public:
/// and only some fragments have a meaningful implementation.
void setBundlePadding(uint8_t N) { BundlePadding = N; }
/// Return true if given frgment has FT_Dummy type.
bool isDummy() const { return Kind == FT_Dummy; }
/// Retrieve the MCSubTargetInfo in effect when the instruction was encoded.
/// Guaranteed to be non-null if hasInstructions() == true
const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
void dump() const;
};
class MCDummyFragment : public MCFragment {
public:
explicit MCDummyFragment(MCSection *Sec)
: MCFragment(FT_Dummy, false, 0, Sec) {}
static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; }
};
/// Interface implemented by fragments that contain encoded instructions and/or
/// data.
///
class MCEncodedFragment : public MCFragment {
protected:
MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions,
MCSection *Sec)
: MCFragment(FType, HasInstructions, 0, Sec) {}
public:
static bool classof(const MCFragment *F) {
MCFragment::FragmentType Kind = F->getKind();
switch (Kind) {
default:
return false;
case MCFragment::FT_Relaxable:
case MCFragment::FT_CompactEncodedInst:
case MCFragment::FT_Data:
return true;
}
/// Record that the fragment contains instructions with the MCSubtargetInfo in
/// effect when the instruction was encoded.
void setHasInstructions(const MCSubtargetInfo &STI) {
HasInstructions = true;
this->STI = &STI;
}
};
@ -201,16 +215,8 @@ protected:
: MCEncodedFragmentWithContents<ContentsSize>(FType, HasInstructions,
Sec) {}
/// STI - The MCSubtargetInfo in effect when the instruction was encoded.
/// must be non-null for instructions.
const MCSubtargetInfo *STI = nullptr;
public:
/// Retrieve the MCSubTargetInfo in effect when the instruction was encoded.
/// Guaranteed to be non-null if hasInstructions() == true
const MCSubtargetInfo *getSubtargetInfo() const { return STI; }
using const_fixup_iterator = SmallVectorImpl<MCFixup>::const_iterator;
using fixup_iterator = SmallVectorImpl<MCFixup>::iterator;
@ -237,13 +243,6 @@ public:
MCDataFragment(MCSection *Sec = nullptr)
: MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {}
/// Record that the fragment contains instructions with the MCSubtargetInfo in
/// effect when the instruction was encoded.
void setHasInstructions(const MCSubtargetInfo &STI) {
HasInstructions = true;
this->STI = &STI;
}
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_Data;
}
@ -309,9 +308,8 @@ class MCAlignFragment : public MCFragment {
public:
MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize,
unsigned MaxBytesToEmit, MCSection *Sec = nullptr)
: MCFragment(FT_Align, false, 0, Sec), Alignment(Alignment),
EmitNops(false), Value(Value),
ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
: MCFragment(FT_Align, false, Sec), Alignment(Alignment), EmitNops(false),
Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
/// \name Accessors
/// @{
@ -379,7 +377,7 @@ public:
};
MCPaddingFragment(MCSection *Sec = nullptr)
: MCFragment(FT_Padding, false, 0, Sec), PaddingPoliciesMask(PFK_None),
: MCFragment(FT_Padding, false, Sec), PaddingPoliciesMask(PFK_None),
IsInsertionPoint(false), Size(UINT64_C(0)),
InstInfo({false, MCInst(), false, {0}}) {}
@ -439,7 +437,7 @@ class MCFillFragment : public MCFragment {
public:
MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues,
SMLoc Loc, MCSection *Sec = nullptr)
: MCFragment(FT_Fill, false, 0, Sec), Value(Value), ValueSize(VSize),
: MCFragment(FT_Fill, false, Sec), Value(Value), ValueSize(VSize),
NumValues(NumValues), Loc(Loc) {}
uint64_t getValue() const { return Value; }
@ -466,7 +464,7 @@ class MCOrgFragment : public MCFragment {
public:
MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc,
MCSection *Sec = nullptr)
: MCFragment(FT_Org, false, 0, Sec), Offset(&Offset), Value(Value), Loc(Loc) {}
: MCFragment(FT_Org, false, Sec), Offset(&Offset), Value(Value), Loc(Loc) {}
/// \name Accessors
/// @{
@ -495,7 +493,7 @@ class MCLEBFragment : public MCFragment {
public:
MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr)
: MCFragment(FT_LEB, false, 0, Sec), Value(&Value_), IsSigned(IsSigned_) {
: MCFragment(FT_LEB, false, Sec), Value(&Value_), IsSigned(IsSigned_) {
Contents.push_back(0);
}
@ -530,7 +528,7 @@ class MCDwarfLineAddrFragment : public MCFragment {
public:
MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta,
MCSection *Sec = nullptr)
: MCFragment(FT_Dwarf, false, 0, Sec), LineDelta(LineDelta),
: MCFragment(FT_Dwarf, false, Sec), LineDelta(LineDelta),
AddrDelta(&AddrDelta) {
Contents.push_back(0);
}
@ -561,7 +559,7 @@ class MCDwarfCallFrameFragment : public MCFragment {
public:
MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr)
: MCFragment(FT_DwarfFrame, false, 0, Sec), AddrDelta(&AddrDelta) {
: MCFragment(FT_DwarfFrame, false, Sec), AddrDelta(&AddrDelta) {
Contents.push_back(0);
}
@ -586,7 +584,7 @@ class MCSymbolIdFragment : public MCFragment {
public:
MCSymbolIdFragment(const MCSymbol *Sym, MCSection *Sec = nullptr)
: MCFragment(FT_SymbolId, false, 0, Sec), Sym(Sym) {}
: MCFragment(FT_SymbolId, false, Sec), Sym(Sym) {}
/// \name Accessors
/// @{
@ -620,7 +618,7 @@ public:
unsigned StartLineNum, const MCSymbol *FnStartSym,
const MCSymbol *FnEndSym,
MCSection *Sec = nullptr)
: MCFragment(FT_CVInlineLines, false, 0, Sec), SiteFuncId(SiteFuncId),
: MCFragment(FT_CVInlineLines, false, Sec), SiteFuncId(SiteFuncId),
StartFileId(StartFileId), StartLineNum(StartLineNum),
FnStartSym(FnStartSym), FnEndSym(FnEndSym) {}

View File

@ -426,17 +426,18 @@ void MCAsmLayout::layoutFragment(MCFragment *F) {
if (Assembler.isBundlingEnabled() && F->hasInstructions()) {
assert(isa<MCEncodedFragment>(F) &&
"Only MCEncodedFragment implementations have instructions");
uint64_t FSize = Assembler.computeFragmentSize(*this, *F);
MCEncodedFragment *EF = cast<MCEncodedFragment>(F);
uint64_t FSize = Assembler.computeFragmentSize(*this, *EF);
if (!Assembler.getRelaxAll() && FSize > Assembler.getBundleAlignSize())
report_fatal_error("Fragment can't be larger than a bundle size");
uint64_t RequiredBundlePadding = computeBundlePadding(Assembler, F,
F->Offset, FSize);
uint64_t RequiredBundlePadding =
computeBundlePadding(Assembler, EF, EF->Offset, FSize);
if (RequiredBundlePadding > UINT8_MAX)
report_fatal_error("Padding cannot exceed 255 bytes");
F->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding));
F->Offset += RequiredBundlePadding;
EF->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding));
EF->Offset += RequiredBundlePadding;
}
}
@ -450,19 +451,20 @@ void MCAssembler::registerSymbol(const MCSymbol &Symbol, bool *Created) {
}
}
void MCAssembler::writeFragmentPadding(raw_ostream &OS, const MCFragment &F,
void MCAssembler::writeFragmentPadding(raw_ostream &OS,
const MCEncodedFragment &EF,
uint64_t FSize) const {
assert(getBackendPtr() && "Expected assembler backend");
// Should NOP padding be written out before this fragment?
unsigned BundlePadding = F.getBundlePadding();
unsigned BundlePadding = EF.getBundlePadding();
if (BundlePadding > 0) {
assert(isBundlingEnabled() &&
"Writing bundle padding with disabled bundling");
assert(F.hasInstructions() &&
assert(EF.hasInstructions() &&
"Writing bundle padding for a fragment without instructions");
unsigned TotalLength = BundlePadding + static_cast<unsigned>(FSize);
if (F.alignToBundleEnd() && TotalLength > getBundleAlignSize()) {
if (EF.alignToBundleEnd() && TotalLength > getBundleAlignSize()) {
// If the padding itself crosses a bundle boundary, it must be emitted
// in 2 pieces, since even nop instructions must not cross boundaries.
// v--------------v <- BundleAlignSize
@ -473,8 +475,8 @@ void MCAssembler::writeFragmentPadding(raw_ostream &OS, const MCFragment &F,
// ^-------------------^ <- TotalLength
unsigned DistanceToBoundary = TotalLength - getBundleAlignSize();
if (!getBackend().writeNopData(OS, DistanceToBoundary))
report_fatal_error("unable to write NOP sequence of " +
Twine(DistanceToBoundary) + " bytes");
report_fatal_error("unable to write NOP sequence of " +
Twine(DistanceToBoundary) + " bytes");
BundlePadding -= DistanceToBoundary;
}
if (!getBackend().writeNopData(OS, BundlePadding))
@ -491,7 +493,8 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
support::endianness Endian = Asm.getBackend().Endian;
Asm.writeFragmentPadding(OS, F, FragmentSize);
if (const MCEncodedFragment *EF = dyn_cast<MCEncodedFragment>(&F))
Asm.writeFragmentPadding(OS, *EF, FragmentSize);
// This variable (and its dummy usage) is to participate in the assert at
// the end of the function.

View File

@ -557,6 +557,7 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst,
MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment();
insert(CEIF);
CEIF->getContents().append(Code.begin(), Code.end());
CEIF->setHasInstructions(STI);
return;
} else {
DF = new MCDataFragment();

View File

@ -189,7 +189,7 @@ uint64_t MCAsmLayout::getSectionFileSize(const MCSection *Sec) const {
}
uint64_t llvm::computeBundlePadding(const MCAssembler &Assembler,
const MCFragment *F,
const MCEncodedFragment *F,
uint64_t FOffset, uint64_t FSize) {
uint64_t BundleSize = Assembler.getBundleAlignSize();
assert(BundleSize > 0 &&
@ -236,10 +236,9 @@ void ilist_alloc_traits<MCFragment>::deleteNode(MCFragment *V) { V->destroy(); }
MCFragment::~MCFragment() = default;
MCFragment::MCFragment(FragmentType Kind, bool HasInstructions,
uint8_t BundlePadding, MCSection *Parent)
: Kind(Kind), HasInstructions(HasInstructions), AlignToBundleEnd(false),
BundlePadding(BundlePadding), Parent(Parent), Atom(nullptr),
Offset(~UINT64_C(0)) {
MCSection *Parent)
: Kind(Kind), HasInstructions(HasInstructions), Parent(Parent),
Atom(nullptr), Offset(~UINT64_C(0)) {
if (Parent && !isDummy())
Parent->getFragmentList().push_back(this);
}
@ -333,10 +332,11 @@ LLVM_DUMP_METHOD void MCFragment::dump() const {
case MCFragment::FT_Dummy: OS << "MCDummyFragment"; break;
}
OS << "<MCFragment " << (const void*) this << " LayoutOrder:" << LayoutOrder
<< " Offset:" << Offset
<< " HasInstructions:" << hasInstructions()
<< " BundlePadding:" << static_cast<unsigned>(getBundlePadding()) << ">";
OS << "<MCFragment " << (const void *)this << " LayoutOrder:" << LayoutOrder
<< " Offset:" << Offset << " HasInstructions:" << hasInstructions();
if (const MCEncodedFragment *EF = cast<MCEncodedFragment>(this))
OS << " BundlePadding:" << static_cast<unsigned>(EF->getBundlePadding());
OS << ">";
switch (getKind()) {
case MCFragment::FT_Align: {