forked from OSchip/llvm-project
Devirtualize and pack MCFragment to reduce memory usage.
MCFragment didn't really need vtables. The majority of virtual methods were just getters and setters. This removes the vtables and uses dispatch on the kind to do things like delete which needs to get the appropriate class. This reduces memory on the verify use list order test case by about 2MB out of 800MB. Reviewed by Rafael Espíndola llvm-svn: 239952
This commit is contained in:
parent
6cac62797f
commit
e0d4037c6a
|
@ -49,7 +49,7 @@ class MCFragment : public ilist_node<MCFragment> {
|
|||
void operator=(const MCFragment &) = delete;
|
||||
|
||||
public:
|
||||
enum FragmentType {
|
||||
enum FragmentType : uint8_t {
|
||||
FT_Align,
|
||||
FT_Data,
|
||||
FT_CompactEncodedInst,
|
||||
|
@ -65,6 +65,18 @@ public:
|
|||
private:
|
||||
FragmentType Kind;
|
||||
|
||||
protected:
|
||||
bool HasInstructions;
|
||||
|
||||
private:
|
||||
/// \brief 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;
|
||||
|
||||
/// The data for the section this fragment is in.
|
||||
MCSection *Parent;
|
||||
|
||||
|
@ -81,18 +93,25 @@ private:
|
|||
/// initialized.
|
||||
uint64_t Offset;
|
||||
|
||||
/// LayoutOrder - The layout order of this fragment.
|
||||
unsigned LayoutOrder;
|
||||
|
||||
/// @}
|
||||
|
||||
protected:
|
||||
MCFragment(FragmentType Kind, MCSection *Parent = nullptr);
|
||||
MCFragment(FragmentType Kind, bool HasInstructions,
|
||||
uint8_t BundlePadding, MCSection *Parent = nullptr);
|
||||
|
||||
~MCFragment();
|
||||
private:
|
||||
|
||||
// This is a friend so that the sentinal can be created.
|
||||
friend struct ilist_sentinel_traits<MCFragment>;
|
||||
MCFragment();
|
||||
|
||||
public:
|
||||
// Only for sentinel.
|
||||
MCFragment();
|
||||
virtual ~MCFragment();
|
||||
/// Destroys the current fragment.
|
||||
///
|
||||
/// This must be used instead of delete as MCFragment is non-virtual.
|
||||
/// This method will dispatch to the appropriate subclass.
|
||||
void destroy();
|
||||
|
||||
FragmentType getKind() const { return Kind; }
|
||||
|
||||
|
@ -107,22 +126,22 @@ public:
|
|||
|
||||
/// \brief Does this fragment have instructions emitted into it? By default
|
||||
/// this is false, but specific fragment types may set it to true.
|
||||
virtual bool hasInstructions() const { return false; }
|
||||
bool hasInstructions() const { return HasInstructions; }
|
||||
|
||||
/// \brief Should this fragment be placed at the end of an aligned bundle?
|
||||
virtual bool alignToBundleEnd() const { return false; }
|
||||
virtual void setAlignToBundleEnd(bool V) {}
|
||||
bool alignToBundleEnd() const { return AlignToBundleEnd; }
|
||||
void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
|
||||
|
||||
/// \brief Get the padding size that must be inserted before this fragment.
|
||||
/// Used for bundling. By default, no padding is inserted.
|
||||
/// Note that padding size is restricted to 8 bits. This is an optimization
|
||||
/// to reduce the amount of space used for each fragment. In practice, larger
|
||||
/// padding should never be required.
|
||||
virtual uint8_t getBundlePadding() const { return 0; }
|
||||
uint8_t getBundlePadding() const { return BundlePadding; }
|
||||
|
||||
/// \brief Set the padding size for this fragment. By default it's a no-op,
|
||||
/// and only some fragments have a meaningful implementation.
|
||||
virtual void setBundlePadding(uint8_t N) {}
|
||||
void setBundlePadding(uint8_t N) { BundlePadding = N; }
|
||||
|
||||
void dump();
|
||||
};
|
||||
|
@ -131,22 +150,12 @@ public:
|
|||
/// data.
|
||||
///
|
||||
class MCEncodedFragment : public MCFragment {
|
||||
virtual void anchor();
|
||||
|
||||
uint8_t BundlePadding;
|
||||
protected:
|
||||
MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions,
|
||||
MCSection *Sec)
|
||||
: MCFragment(FType, HasInstructions, 0, Sec) {}
|
||||
|
||||
public:
|
||||
MCEncodedFragment(MCFragment::FragmentType FType, MCSection *Sec = nullptr)
|
||||
: MCFragment(FType, Sec), BundlePadding(0) {}
|
||||
~MCEncodedFragment() override;
|
||||
|
||||
virtual SmallVectorImpl<char> &getContents() = 0;
|
||||
virtual const SmallVectorImpl<char> &getContents() const = 0;
|
||||
|
||||
uint8_t getBundlePadding() const override { return BundlePadding; }
|
||||
|
||||
void setBundlePadding(uint8_t N) override { BundlePadding = N; }
|
||||
|
||||
static bool classof(const MCFragment *F) {
|
||||
MCFragment::FragmentType Kind = F->getKind();
|
||||
switch (Kind) {
|
||||
|
@ -161,28 +170,52 @@ public:
|
|||
};
|
||||
|
||||
/// Interface implemented by fragments that contain encoded instructions and/or
|
||||
/// data and also have fixups registered.
|
||||
/// data.
|
||||
///
|
||||
class MCEncodedFragmentWithFixups : public MCEncodedFragment {
|
||||
void anchor() override;
|
||||
template<unsigned ContentsSize>
|
||||
class MCEncodedFragmentWithContents : public MCEncodedFragment {
|
||||
SmallVector<char, ContentsSize> Contents;
|
||||
|
||||
protected:
|
||||
MCEncodedFragmentWithContents(MCFragment::FragmentType FType,
|
||||
bool HasInstructions,
|
||||
MCSection *Sec)
|
||||
: MCEncodedFragment(FType, HasInstructions, Sec) {}
|
||||
|
||||
public:
|
||||
SmallVectorImpl<char> &getContents() { return Contents; }
|
||||
const SmallVectorImpl<char> &getContents() const { return Contents; }
|
||||
};
|
||||
|
||||
/// Interface implemented by fragments that contain encoded instructions and/or
|
||||
/// data and also have fixups registered.
|
||||
///
|
||||
template<unsigned ContentsSize, unsigned FixupsSize>
|
||||
class MCEncodedFragmentWithFixups :
|
||||
public MCEncodedFragmentWithContents<ContentsSize> {
|
||||
|
||||
/// Fixups - The list of fixups in this fragment.
|
||||
SmallVector<MCFixup, FixupsSize> Fixups;
|
||||
|
||||
protected:
|
||||
MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
|
||||
MCSection *Sec = nullptr)
|
||||
: MCEncodedFragment(FType, Sec) {}
|
||||
|
||||
~MCEncodedFragmentWithFixups() override;
|
||||
bool HasInstructions,
|
||||
MCSection *Sec)
|
||||
: MCEncodedFragmentWithContents<ContentsSize>(FType, HasInstructions,
|
||||
Sec) {}
|
||||
|
||||
public:
|
||||
typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator;
|
||||
typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator;
|
||||
|
||||
virtual SmallVectorImpl<MCFixup> &getFixups() = 0;
|
||||
virtual const SmallVectorImpl<MCFixup> &getFixups() const = 0;
|
||||
SmallVectorImpl<MCFixup> &getFixups() { return Fixups; }
|
||||
const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; }
|
||||
|
||||
virtual fixup_iterator fixup_begin() = 0;
|
||||
virtual const_fixup_iterator fixup_begin() const = 0;
|
||||
virtual fixup_iterator fixup_end() = 0;
|
||||
virtual const_fixup_iterator fixup_end() const = 0;
|
||||
fixup_iterator fixup_begin() { return Fixups.begin(); }
|
||||
const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
|
||||
|
||||
fixup_iterator fixup_end() { return Fixups.end(); }
|
||||
const_fixup_iterator fixup_end() const { return Fixups.end(); }
|
||||
|
||||
static bool classof(const MCFragment *F) {
|
||||
MCFragment::FragmentType Kind = F->getKind();
|
||||
|
@ -192,43 +225,12 @@ public:
|
|||
|
||||
/// Fragment for data and encoded instructions.
|
||||
///
|
||||
class MCDataFragment : public MCEncodedFragmentWithFixups {
|
||||
void anchor() override;
|
||||
|
||||
/// \brief Does this fragment contain encoded instructions anywhere in it?
|
||||
bool HasInstructions;
|
||||
|
||||
/// \brief Should this fragment be aligned to the end of a bundle?
|
||||
bool AlignToBundleEnd;
|
||||
|
||||
SmallVector<char, 32> Contents;
|
||||
|
||||
/// Fixups - The list of fixups in this fragment.
|
||||
SmallVector<MCFixup, 4> Fixups;
|
||||
|
||||
class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
|
||||
public:
|
||||
MCDataFragment(MCSection *Sec = nullptr)
|
||||
: MCEncodedFragmentWithFixups(FT_Data, Sec), HasInstructions(false),
|
||||
AlignToBundleEnd(false) {}
|
||||
: MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {}
|
||||
|
||||
SmallVectorImpl<char> &getContents() override { return Contents; }
|
||||
const SmallVectorImpl<char> &getContents() const override { return Contents; }
|
||||
|
||||
SmallVectorImpl<MCFixup> &getFixups() override { return Fixups; }
|
||||
|
||||
const SmallVectorImpl<MCFixup> &getFixups() const override { return Fixups; }
|
||||
|
||||
bool hasInstructions() const override { return HasInstructions; }
|
||||
virtual void setHasInstructions(bool V) { HasInstructions = V; }
|
||||
|
||||
bool alignToBundleEnd() const override { return AlignToBundleEnd; }
|
||||
void setAlignToBundleEnd(bool V) override { AlignToBundleEnd = V; }
|
||||
|
||||
fixup_iterator fixup_begin() override { return Fixups.begin(); }
|
||||
const_fixup_iterator fixup_begin() const override { return Fixups.begin(); }
|
||||
|
||||
fixup_iterator fixup_end() override { return Fixups.end(); }
|
||||
const_fixup_iterator fixup_end() const override { return Fixups.end(); }
|
||||
void setHasInstructions(bool V) { HasInstructions = V; }
|
||||
|
||||
static bool classof(const MCFragment *F) {
|
||||
return F->getKind() == MCFragment::FT_Data;
|
||||
|
@ -240,27 +242,12 @@ public:
|
|||
/// it can be used instead of MCDataFragment and lead to lower memory
|
||||
/// consumption.
|
||||
///
|
||||
class MCCompactEncodedInstFragment : public MCEncodedFragment {
|
||||
void anchor() override;
|
||||
|
||||
/// \brief Should this fragment be aligned to the end of a bundle?
|
||||
bool AlignToBundleEnd;
|
||||
|
||||
SmallVector<char, 4> Contents;
|
||||
|
||||
class MCCompactEncodedInstFragment : public MCEncodedFragmentWithContents<4> {
|
||||
public:
|
||||
MCCompactEncodedInstFragment(MCSection *Sec = nullptr)
|
||||
: MCEncodedFragment(FT_CompactEncodedInst, Sec), AlignToBundleEnd(false) {
|
||||
: MCEncodedFragmentWithContents(FT_CompactEncodedInst, true, Sec) {
|
||||
}
|
||||
|
||||
bool hasInstructions() const override { return true; }
|
||||
|
||||
SmallVectorImpl<char> &getContents() override { return Contents; }
|
||||
const SmallVectorImpl<char> &getContents() const override { return Contents; }
|
||||
|
||||
bool alignToBundleEnd() const override { return AlignToBundleEnd; }
|
||||
void setAlignToBundleEnd(bool V) override { AlignToBundleEnd = V; }
|
||||
|
||||
static bool classof(const MCFragment *F) {
|
||||
return F->getKind() == MCFragment::FT_CompactEncodedInst;
|
||||
}
|
||||
|
@ -269,8 +256,7 @@ public:
|
|||
/// A relaxable fragment holds on to its MCInst, since it may need to be
|
||||
/// relaxed during the assembler layout and relaxation stage.
|
||||
///
|
||||
class MCRelaxableFragment : public MCEncodedFragmentWithFixups {
|
||||
void anchor() override;
|
||||
class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
|
||||
|
||||
/// Inst - The instruction this is a fragment for.
|
||||
MCInst Inst;
|
||||
|
@ -280,48 +266,32 @@ class MCRelaxableFragment : public MCEncodedFragmentWithFixups {
|
|||
/// in the assembler are not seen here.
|
||||
const MCSubtargetInfo STI;
|
||||
|
||||
/// Contents - Binary data for the currently encoded instruction.
|
||||
SmallVector<char, 8> Contents;
|
||||
|
||||
/// Fixups - The list of fixups in this fragment.
|
||||
SmallVector<MCFixup, 1> Fixups;
|
||||
|
||||
public:
|
||||
MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI,
|
||||
MCSection *Sec = nullptr)
|
||||
: MCEncodedFragmentWithFixups(FT_Relaxable, Sec), Inst(Inst), STI(STI) {}
|
||||
|
||||
SmallVectorImpl<char> &getContents() override { return Contents; }
|
||||
const SmallVectorImpl<char> &getContents() const override { return Contents; }
|
||||
: MCEncodedFragmentWithFixups(FT_Relaxable, true, Sec),
|
||||
Inst(Inst), STI(STI) {}
|
||||
|
||||
const MCInst &getInst() const { return Inst; }
|
||||
void setInst(const MCInst &Value) { Inst = Value; }
|
||||
|
||||
const MCSubtargetInfo &getSubtargetInfo() { return STI; }
|
||||
|
||||
SmallVectorImpl<MCFixup> &getFixups() override { return Fixups; }
|
||||
|
||||
const SmallVectorImpl<MCFixup> &getFixups() const override { return Fixups; }
|
||||
|
||||
bool hasInstructions() const override { return true; }
|
||||
|
||||
fixup_iterator fixup_begin() override { return Fixups.begin(); }
|
||||
const_fixup_iterator fixup_begin() const override { return Fixups.begin(); }
|
||||
|
||||
fixup_iterator fixup_end() override { return Fixups.end(); }
|
||||
const_fixup_iterator fixup_end() const override { return Fixups.end(); }
|
||||
|
||||
static bool classof(const MCFragment *F) {
|
||||
return F->getKind() == MCFragment::FT_Relaxable;
|
||||
}
|
||||
};
|
||||
|
||||
class MCAlignFragment : public MCFragment {
|
||||
virtual void anchor();
|
||||
|
||||
/// Alignment - The alignment to ensure, in bytes.
|
||||
unsigned Alignment;
|
||||
|
||||
/// EmitNops - Flag to indicate that (optimal) NOPs should be emitted instead
|
||||
/// of using the provided value. The exact interpretation of this flag is
|
||||
/// target dependent.
|
||||
bool EmitNops : 1;
|
||||
|
||||
/// Value - Value to use for filling padding bytes.
|
||||
int64_t Value;
|
||||
|
||||
|
@ -332,16 +302,12 @@ class MCAlignFragment : public MCFragment {
|
|||
/// cannot be satisfied in this width then this fragment is ignored.
|
||||
unsigned MaxBytesToEmit;
|
||||
|
||||
/// EmitNops - Flag to indicate that (optimal) NOPs should be emitted instead
|
||||
/// of using the provided value. The exact interpretation of this flag is
|
||||
/// target dependent.
|
||||
bool EmitNops : 1;
|
||||
|
||||
public:
|
||||
MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize,
|
||||
unsigned MaxBytesToEmit, MCSection *Sec = nullptr)
|
||||
: MCFragment(FT_Align, Sec), Alignment(Alignment), Value(Value),
|
||||
ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit), EmitNops(false) {}
|
||||
: MCFragment(FT_Align, false, 0, Sec), Alignment(Alignment),
|
||||
EmitNops(false), Value(Value),
|
||||
ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
|
||||
|
||||
/// \name Accessors
|
||||
/// @{
|
||||
|
@ -365,7 +331,6 @@ public:
|
|||
};
|
||||
|
||||
class MCFillFragment : public MCFragment {
|
||||
virtual void anchor();
|
||||
|
||||
/// Value - Value to use for filling bytes.
|
||||
int64_t Value;
|
||||
|
@ -380,7 +345,7 @@ class MCFillFragment : public MCFragment {
|
|||
public:
|
||||
MCFillFragment(int64_t Value, unsigned ValueSize, uint64_t Size,
|
||||
MCSection *Sec = nullptr)
|
||||
: MCFragment(FT_Fill, Sec), Value(Value), ValueSize(ValueSize),
|
||||
: MCFragment(FT_Fill, false, 0, Sec), Value(Value), ValueSize(ValueSize),
|
||||
Size(Size) {
|
||||
assert((!ValueSize || (Size % ValueSize) == 0) &&
|
||||
"Fill size must be a multiple of the value size!");
|
||||
|
@ -403,7 +368,6 @@ public:
|
|||
};
|
||||
|
||||
class MCOrgFragment : public MCFragment {
|
||||
virtual void anchor();
|
||||
|
||||
/// Offset - The offset this fragment should start at.
|
||||
const MCExpr *Offset;
|
||||
|
@ -413,7 +377,7 @@ class MCOrgFragment : public MCFragment {
|
|||
|
||||
public:
|
||||
MCOrgFragment(const MCExpr &Offset, int8_t Value, MCSection *Sec = nullptr)
|
||||
: MCFragment(FT_Org, Sec), Offset(&Offset), Value(Value) {}
|
||||
: MCFragment(FT_Org, false, 0, Sec), Offset(&Offset), Value(Value) {}
|
||||
|
||||
/// \name Accessors
|
||||
/// @{
|
||||
|
@ -430,7 +394,6 @@ public:
|
|||
};
|
||||
|
||||
class MCLEBFragment : public MCFragment {
|
||||
virtual void anchor();
|
||||
|
||||
/// Value - The value this fragment should contain.
|
||||
const MCExpr *Value;
|
||||
|
@ -442,7 +405,7 @@ class MCLEBFragment : public MCFragment {
|
|||
|
||||
public:
|
||||
MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr)
|
||||
: MCFragment(FT_LEB, Sec), Value(&Value_), IsSigned(IsSigned_) {
|
||||
: MCFragment(FT_LEB, false, 0, Sec), Value(&Value_), IsSigned(IsSigned_) {
|
||||
Contents.push_back(0);
|
||||
}
|
||||
|
||||
|
@ -464,7 +427,6 @@ public:
|
|||
};
|
||||
|
||||
class MCDwarfLineAddrFragment : public MCFragment {
|
||||
virtual void anchor();
|
||||
|
||||
/// LineDelta - the value of the difference between the two line numbers
|
||||
/// between two .loc dwarf directives.
|
||||
|
@ -479,7 +441,8 @@ class MCDwarfLineAddrFragment : public MCFragment {
|
|||
public:
|
||||
MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta,
|
||||
MCSection *Sec = nullptr)
|
||||
: MCFragment(FT_Dwarf, Sec), LineDelta(LineDelta), AddrDelta(&AddrDelta) {
|
||||
: MCFragment(FT_Dwarf, false, 0, Sec), LineDelta(LineDelta),
|
||||
AddrDelta(&AddrDelta) {
|
||||
Contents.push_back(0);
|
||||
}
|
||||
|
||||
|
@ -501,7 +464,6 @@ public:
|
|||
};
|
||||
|
||||
class MCDwarfCallFrameFragment : public MCFragment {
|
||||
virtual void anchor();
|
||||
|
||||
/// AddrDelta - The expression for the difference of the two symbols that
|
||||
/// make up the address delta between two .cfi_* dwarf directives.
|
||||
|
@ -511,7 +473,7 @@ class MCDwarfCallFrameFragment : public MCFragment {
|
|||
|
||||
public:
|
||||
MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr)
|
||||
: MCFragment(FT_DwarfFrame, Sec), AddrDelta(&AddrDelta) {
|
||||
: MCFragment(FT_DwarfFrame, false, 0, Sec), AddrDelta(&AddrDelta) {
|
||||
Contents.push_back(0);
|
||||
}
|
||||
|
||||
|
@ -531,13 +493,11 @@ public:
|
|||
};
|
||||
|
||||
class MCSafeSEHFragment : public MCFragment {
|
||||
virtual void anchor();
|
||||
|
||||
const MCSymbol *Sym;
|
||||
|
||||
public:
|
||||
MCSafeSEHFragment(const MCSymbol *Sym, MCSection *Sec = nullptr)
|
||||
: MCFragment(FT_SafeSEH, Sec), Sym(Sym) {}
|
||||
: MCFragment(FT_SafeSEH, false, 0, Sec), Sym(Sym) {}
|
||||
|
||||
/// \name Accessors
|
||||
/// @{
|
||||
|
|
|
@ -93,7 +93,7 @@ private:
|
|||
void fixSymbolsInTLSFixups(const MCExpr *expr);
|
||||
|
||||
/// \brief Merge the content of the fragment \p EF into the fragment \p DF.
|
||||
void mergeFragment(MCDataFragment *, MCEncodedFragmentWithFixups *);
|
||||
void mergeFragment(MCDataFragment *, MCDataFragment *);
|
||||
|
||||
bool SeenIdent;
|
||||
|
||||
|
|
|
@ -31,6 +31,18 @@ class MCSection;
|
|||
class MCSymbol;
|
||||
class raw_ostream;
|
||||
|
||||
template<>
|
||||
struct ilist_node_traits<MCFragment> {
|
||||
MCFragment *createNode(const MCFragment &V);
|
||||
static void deleteNode(MCFragment *V);
|
||||
|
||||
void addNodeToList(MCFragment *) {}
|
||||
void removeNodeFromList(MCFragment *) {}
|
||||
void transferNodesFromList(ilist_node_traits & /*SrcTraits*/,
|
||||
ilist_iterator<MCFragment> /*first*/,
|
||||
ilist_iterator<MCFragment> /*last*/) {}
|
||||
};
|
||||
|
||||
/// Instances of this class represent a uniqued identifier for a section in the
|
||||
/// current translation unit. The MCContext class uniques and creates these.
|
||||
class MCSection {
|
||||
|
|
|
@ -262,26 +262,64 @@ uint64_t llvm::computeBundlePadding(const MCAssembler &Assembler,
|
|||
|
||||
/* *** */
|
||||
|
||||
MCFragment::MCFragment() : Kind(FragmentType(~0)) {
|
||||
void ilist_node_traits<MCFragment>::deleteNode(MCFragment *V) {
|
||||
V->destroy();
|
||||
}
|
||||
|
||||
MCFragment::~MCFragment() {
|
||||
MCFragment::MCFragment() : Kind(FragmentType(~0)), HasInstructions(false),
|
||||
AlignToBundleEnd(false), BundlePadding(0) {
|
||||
}
|
||||
|
||||
MCFragment::MCFragment(FragmentType Kind, MCSection *Parent)
|
||||
: Kind(Kind), Parent(Parent), Atom(nullptr), Offset(~UINT64_C(0)) {
|
||||
MCFragment::~MCFragment() { }
|
||||
|
||||
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)) {
|
||||
if (Parent)
|
||||
Parent->getFragmentList().push_back(this);
|
||||
}
|
||||
|
||||
/* *** */
|
||||
|
||||
MCEncodedFragment::~MCEncodedFragment() {
|
||||
void MCFragment::destroy() {
|
||||
// First check if we are the sentinal.
|
||||
if (Kind == FragmentType(~0)) {
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
/* *** */
|
||||
|
||||
MCEncodedFragmentWithFixups::~MCEncodedFragmentWithFixups() {
|
||||
switch (Kind) {
|
||||
case FT_Align:
|
||||
delete cast<MCAlignFragment>(this);
|
||||
return;
|
||||
case FT_Data:
|
||||
delete cast<MCDataFragment>(this);
|
||||
return;
|
||||
case FT_CompactEncodedInst:
|
||||
delete cast<MCCompactEncodedInstFragment>(this);
|
||||
return;
|
||||
case FT_Fill:
|
||||
delete cast<MCFillFragment>(this);
|
||||
return;
|
||||
case FT_Relaxable:
|
||||
delete cast<MCRelaxableFragment>(this);
|
||||
return;
|
||||
case FT_Org:
|
||||
delete cast<MCOrgFragment>(this);
|
||||
return;
|
||||
case FT_Dwarf:
|
||||
delete cast<MCDwarfLineAddrFragment>(this);
|
||||
return;
|
||||
case FT_DwarfFrame:
|
||||
delete cast<MCDwarfCallFrameFragment>(this);
|
||||
return;
|
||||
case FT_LEB:
|
||||
delete cast<MCLEBFragment>(this);
|
||||
return;
|
||||
case FT_SafeSEH:
|
||||
delete cast<MCSafeSEHFragment>(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* *** */
|
||||
|
@ -454,9 +492,11 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
|
|||
const MCFragment &F) const {
|
||||
switch (F.getKind()) {
|
||||
case MCFragment::FT_Data:
|
||||
return cast<MCDataFragment>(F).getContents().size();
|
||||
case MCFragment::FT_Relaxable:
|
||||
return cast<MCRelaxableFragment>(F).getContents().size();
|
||||
case MCFragment::FT_CompactEncodedInst:
|
||||
return cast<MCEncodedFragment>(F).getContents().size();
|
||||
return cast<MCCompactEncodedInstFragment>(F).getContents().size();
|
||||
case MCFragment::FT_Fill:
|
||||
return cast<MCFillFragment>(F).getSize();
|
||||
|
||||
|
@ -562,13 +602,6 @@ void MCAsmLayout::layoutFragment(MCFragment *F) {
|
|||
}
|
||||
}
|
||||
|
||||
/// \brief Write the contents of a fragment to the given object writer. Expects
|
||||
/// a MCEncodedFragment.
|
||||
static void writeFragmentContents(const MCFragment &F, MCObjectWriter *OW) {
|
||||
const MCEncodedFragment &EF = cast<MCEncodedFragment>(F);
|
||||
OW->writeBytes(EF.getContents());
|
||||
}
|
||||
|
||||
void MCAssembler::registerSymbol(const MCSymbol &Symbol, bool *Created) {
|
||||
bool New = !Symbol.isRegistered();
|
||||
if (Created)
|
||||
|
@ -671,17 +704,17 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
|||
|
||||
case MCFragment::FT_Data:
|
||||
++stats::EmittedDataFragments;
|
||||
writeFragmentContents(F, OW);
|
||||
OW->writeBytes(cast<MCDataFragment>(F).getContents());
|
||||
break;
|
||||
|
||||
case MCFragment::FT_Relaxable:
|
||||
++stats::EmittedRelaxableFragments;
|
||||
writeFragmentContents(F, OW);
|
||||
OW->writeBytes(cast<MCRelaxableFragment>(F).getContents());
|
||||
break;
|
||||
|
||||
case MCFragment::FT_CompactEncodedInst:
|
||||
++stats::EmittedCompactEncodedInstFragments;
|
||||
writeFragmentContents(F, OW);
|
||||
OW->writeBytes(cast<MCCompactEncodedInstFragment>(F).getContents());
|
||||
break;
|
||||
|
||||
case MCFragment::FT_Fill: {
|
||||
|
@ -870,18 +903,29 @@ void MCAssembler::Finish() {
|
|||
for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it) {
|
||||
for (MCSection::iterator it2 = it->begin(), ie2 = it->end(); it2 != ie2;
|
||||
++it2) {
|
||||
MCEncodedFragmentWithFixups *F =
|
||||
dyn_cast<MCEncodedFragmentWithFixups>(it2);
|
||||
if (F) {
|
||||
for (MCEncodedFragmentWithFixups::fixup_iterator it3 = F->fixup_begin(),
|
||||
ie3 = F->fixup_end(); it3 != ie3; ++it3) {
|
||||
MCFixup &Fixup = *it3;
|
||||
MCEncodedFragment *F = dyn_cast<MCEncodedFragment>(it2);
|
||||
// Data and relaxable fragments both have fixups. So only process
|
||||
// those here.
|
||||
// FIXME: Is there a better way to do this? MCEncodedFragmentWithFixups
|
||||
// being templated makes this tricky.
|
||||
if (!F || isa<MCCompactEncodedInstFragment>(F))
|
||||
continue;
|
||||
ArrayRef<MCFixup> Fixups;
|
||||
MutableArrayRef<char> Contents;
|
||||
if (auto *FragWithFixups = dyn_cast<MCDataFragment>(F)) {
|
||||
Fixups = FragWithFixups->getFixups();
|
||||
Contents = FragWithFixups->getContents();
|
||||
} else if (auto *FragWithFixups = dyn_cast<MCRelaxableFragment>(F)) {
|
||||
Fixups = FragWithFixups->getFixups();
|
||||
Contents = FragWithFixups->getContents();
|
||||
} else
|
||||
llvm_unreachable("Unknow fragment with fixups!");
|
||||
for (const MCFixup &Fixup : Fixups) {
|
||||
uint64_t FixedValue;
|
||||
bool IsPCRel;
|
||||
std::tie(FixedValue, IsPCRel) = handleFixup(Layout, *F, Fixup);
|
||||
getBackend().applyFixup(Fixup, F->getContents().data(),
|
||||
F->getContents().size(), FixedValue, IsPCRel);
|
||||
}
|
||||
getBackend().applyFixup(Fixup, Contents.data(),
|
||||
Contents.size(), FixedValue, IsPCRel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1218,17 +1262,3 @@ void MCAssembler::dump() {
|
|||
OS << "]>\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
// anchors for MC*Fragment vtables
|
||||
void MCEncodedFragment::anchor() { }
|
||||
void MCEncodedFragmentWithFixups::anchor() { }
|
||||
void MCDataFragment::anchor() { }
|
||||
void MCCompactEncodedInstFragment::anchor() { }
|
||||
void MCRelaxableFragment::anchor() { }
|
||||
void MCAlignFragment::anchor() { }
|
||||
void MCFillFragment::anchor() { }
|
||||
void MCOrgFragment::anchor() { }
|
||||
void MCLEBFragment::anchor() { }
|
||||
void MCSafeSEHFragment::anchor() { }
|
||||
void MCDwarfLineAddrFragment::anchor() { }
|
||||
void MCDwarfCallFrameFragment::anchor() { }
|
||||
|
|
|
@ -45,7 +45,7 @@ MCELFStreamer::~MCELFStreamer() {
|
|||
}
|
||||
|
||||
void MCELFStreamer::mergeFragment(MCDataFragment *DF,
|
||||
MCEncodedFragmentWithFixups *EF) {
|
||||
MCDataFragment *EF) {
|
||||
MCAssembler &Assembler = getAssembler();
|
||||
|
||||
if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) {
|
||||
|
|
Loading…
Reference in New Issue