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:
Pete Cooper 2015-06-17 22:01:28 +00:00
parent 6cac62797f
commit e0d4037c6a
5 changed files with 188 additions and 186 deletions

View File

@ -49,7 +49,7 @@ class MCFragment : public ilist_node<MCFragment> {
void operator=(const MCFragment &) = delete; void operator=(const MCFragment &) = delete;
public: public:
enum FragmentType { enum FragmentType : uint8_t {
FT_Align, FT_Align,
FT_Data, FT_Data,
FT_CompactEncodedInst, FT_CompactEncodedInst,
@ -65,6 +65,18 @@ public:
private: private:
FragmentType Kind; 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. /// The data for the section this fragment is in.
MCSection *Parent; MCSection *Parent;
@ -81,18 +93,25 @@ private:
/// initialized. /// initialized.
uint64_t Offset; uint64_t Offset;
/// LayoutOrder - The layout order of this fragment.
unsigned LayoutOrder;
/// @} /// @}
protected: 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: public:
// Only for sentinel. /// Destroys the current fragment.
MCFragment(); ///
virtual ~MCFragment(); /// 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; } FragmentType getKind() const { return Kind; }
@ -107,22 +126,22 @@ public:
/// \brief Does this fragment have instructions emitted into it? By default /// \brief Does this fragment have instructions emitted into it? By default
/// this is false, but specific fragment types may set it to true. /// 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? /// \brief Should this fragment be placed at the end of an aligned bundle?
virtual bool alignToBundleEnd() const { return false; } bool alignToBundleEnd() const { return AlignToBundleEnd; }
virtual void setAlignToBundleEnd(bool V) {} void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
/// \brief Get the padding size that must be inserted before this fragment. /// \brief Get the padding size that must be inserted before this fragment.
/// Used for bundling. By default, no padding is inserted. /// Used for bundling. By default, no padding is inserted.
/// Note that padding size is restricted to 8 bits. This is an optimization /// 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 /// to reduce the amount of space used for each fragment. In practice, larger
/// padding should never be required. /// 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, /// \brief Set the padding size for this fragment. By default it's a no-op,
/// and only some fragments have a meaningful implementation. /// and only some fragments have a meaningful implementation.
virtual void setBundlePadding(uint8_t N) {} void setBundlePadding(uint8_t N) { BundlePadding = N; }
void dump(); void dump();
}; };
@ -131,22 +150,12 @@ public:
/// data. /// data.
/// ///
class MCEncodedFragment : public MCFragment { class MCEncodedFragment : public MCFragment {
virtual void anchor(); protected:
MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions,
uint8_t BundlePadding; MCSection *Sec)
: MCFragment(FType, HasInstructions, 0, Sec) {}
public: 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) { static bool classof(const MCFragment *F) {
MCFragment::FragmentType Kind = F->getKind(); MCFragment::FragmentType Kind = F->getKind();
switch (Kind) { switch (Kind) {
@ -161,28 +170,52 @@ public:
}; };
/// Interface implemented by fragments that contain encoded instructions and/or /// Interface implemented by fragments that contain encoded instructions and/or
/// data and also have fixups registered. /// data.
/// ///
class MCEncodedFragmentWithFixups : public MCEncodedFragment { template<unsigned ContentsSize>
void anchor() override; class MCEncodedFragmentWithContents : public MCEncodedFragment {
SmallVector<char, ContentsSize> Contents;
protected:
MCEncodedFragmentWithContents(MCFragment::FragmentType FType,
bool HasInstructions,
MCSection *Sec)
: MCEncodedFragment(FType, HasInstructions, Sec) {}
public: 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, MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
MCSection *Sec = nullptr) bool HasInstructions,
: MCEncodedFragment(FType, Sec) {} MCSection *Sec)
: MCEncodedFragmentWithContents<ContentsSize>(FType, HasInstructions,
~MCEncodedFragmentWithFixups() override; Sec) {}
public:
typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator; typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator;
typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator; typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator;
virtual SmallVectorImpl<MCFixup> &getFixups() = 0; SmallVectorImpl<MCFixup> &getFixups() { return Fixups; }
virtual const SmallVectorImpl<MCFixup> &getFixups() const = 0; const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; }
virtual fixup_iterator fixup_begin() = 0; fixup_iterator fixup_begin() { return Fixups.begin(); }
virtual const_fixup_iterator fixup_begin() const = 0; const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
virtual fixup_iterator fixup_end() = 0;
virtual const_fixup_iterator fixup_end() const = 0; fixup_iterator fixup_end() { return Fixups.end(); }
const_fixup_iterator fixup_end() const { return Fixups.end(); }
static bool classof(const MCFragment *F) { static bool classof(const MCFragment *F) {
MCFragment::FragmentType Kind = F->getKind(); MCFragment::FragmentType Kind = F->getKind();
@ -192,43 +225,12 @@ public:
/// Fragment for data and encoded instructions. /// Fragment for data and encoded instructions.
/// ///
class MCDataFragment : public MCEncodedFragmentWithFixups { class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> {
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;
public: public:
MCDataFragment(MCSection *Sec = nullptr) MCDataFragment(MCSection *Sec = nullptr)
: MCEncodedFragmentWithFixups(FT_Data, Sec), HasInstructions(false), : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {}
AlignToBundleEnd(false) {}
SmallVectorImpl<char> &getContents() override { return Contents; } void setHasInstructions(bool V) { HasInstructions = V; }
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(); }
static bool classof(const MCFragment *F) { static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_Data; return F->getKind() == MCFragment::FT_Data;
@ -240,27 +242,12 @@ public:
/// it can be used instead of MCDataFragment and lead to lower memory /// it can be used instead of MCDataFragment and lead to lower memory
/// consumption. /// consumption.
/// ///
class MCCompactEncodedInstFragment : public MCEncodedFragment { class MCCompactEncodedInstFragment : public MCEncodedFragmentWithContents<4> {
void anchor() override;
/// \brief Should this fragment be aligned to the end of a bundle?
bool AlignToBundleEnd;
SmallVector<char, 4> Contents;
public: public:
MCCompactEncodedInstFragment(MCSection *Sec = nullptr) 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) { static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_CompactEncodedInst; 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 /// A relaxable fragment holds on to its MCInst, since it may need to be
/// relaxed during the assembler layout and relaxation stage. /// relaxed during the assembler layout and relaxation stage.
/// ///
class MCRelaxableFragment : public MCEncodedFragmentWithFixups { class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> {
void anchor() override;
/// Inst - The instruction this is a fragment for. /// Inst - The instruction this is a fragment for.
MCInst Inst; MCInst Inst;
@ -280,48 +266,32 @@ class MCRelaxableFragment : public MCEncodedFragmentWithFixups {
/// in the assembler are not seen here. /// in the assembler are not seen here.
const MCSubtargetInfo STI; 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: public:
MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI, MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI,
MCSection *Sec = nullptr) MCSection *Sec = nullptr)
: MCEncodedFragmentWithFixups(FT_Relaxable, Sec), Inst(Inst), STI(STI) {} : MCEncodedFragmentWithFixups(FT_Relaxable, true, Sec),
Inst(Inst), STI(STI) {}
SmallVectorImpl<char> &getContents() override { return Contents; }
const SmallVectorImpl<char> &getContents() const override { return Contents; }
const MCInst &getInst() const { return Inst; } const MCInst &getInst() const { return Inst; }
void setInst(const MCInst &Value) { Inst = Value; } void setInst(const MCInst &Value) { Inst = Value; }
const MCSubtargetInfo &getSubtargetInfo() { return STI; } 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) { static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_Relaxable; return F->getKind() == MCFragment::FT_Relaxable;
} }
}; };
class MCAlignFragment : public MCFragment { class MCAlignFragment : public MCFragment {
virtual void anchor();
/// Alignment - The alignment to ensure, in bytes. /// Alignment - The alignment to ensure, in bytes.
unsigned Alignment; 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. /// Value - Value to use for filling padding bytes.
int64_t Value; int64_t Value;
@ -332,16 +302,12 @@ class MCAlignFragment : public MCFragment {
/// cannot be satisfied in this width then this fragment is ignored. /// cannot be satisfied in this width then this fragment is ignored.
unsigned MaxBytesToEmit; 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: public:
MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize, MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize,
unsigned MaxBytesToEmit, MCSection *Sec = nullptr) unsigned MaxBytesToEmit, MCSection *Sec = nullptr)
: MCFragment(FT_Align, Sec), Alignment(Alignment), Value(Value), : MCFragment(FT_Align, false, 0, Sec), Alignment(Alignment),
ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit), EmitNops(false) {} EmitNops(false), Value(Value),
ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {}
/// \name Accessors /// \name Accessors
/// @{ /// @{
@ -365,7 +331,6 @@ public:
}; };
class MCFillFragment : public MCFragment { class MCFillFragment : public MCFragment {
virtual void anchor();
/// Value - Value to use for filling bytes. /// Value - Value to use for filling bytes.
int64_t Value; int64_t Value;
@ -380,7 +345,7 @@ class MCFillFragment : public MCFragment {
public: public:
MCFillFragment(int64_t Value, unsigned ValueSize, uint64_t Size, MCFillFragment(int64_t Value, unsigned ValueSize, uint64_t Size,
MCSection *Sec = nullptr) MCSection *Sec = nullptr)
: MCFragment(FT_Fill, Sec), Value(Value), ValueSize(ValueSize), : MCFragment(FT_Fill, false, 0, Sec), Value(Value), ValueSize(ValueSize),
Size(Size) { Size(Size) {
assert((!ValueSize || (Size % ValueSize) == 0) && assert((!ValueSize || (Size % ValueSize) == 0) &&
"Fill size must be a multiple of the value size!"); "Fill size must be a multiple of the value size!");
@ -403,7 +368,6 @@ public:
}; };
class MCOrgFragment : public MCFragment { class MCOrgFragment : public MCFragment {
virtual void anchor();
/// Offset - The offset this fragment should start at. /// Offset - The offset this fragment should start at.
const MCExpr *Offset; const MCExpr *Offset;
@ -413,7 +377,7 @@ class MCOrgFragment : public MCFragment {
public: public:
MCOrgFragment(const MCExpr &Offset, int8_t Value, MCSection *Sec = nullptr) 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 /// \name Accessors
/// @{ /// @{
@ -430,7 +394,6 @@ public:
}; };
class MCLEBFragment : public MCFragment { class MCLEBFragment : public MCFragment {
virtual void anchor();
/// Value - The value this fragment should contain. /// Value - The value this fragment should contain.
const MCExpr *Value; const MCExpr *Value;
@ -442,7 +405,7 @@ class MCLEBFragment : public MCFragment {
public: public:
MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr) 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); Contents.push_back(0);
} }
@ -464,7 +427,6 @@ public:
}; };
class MCDwarfLineAddrFragment : public MCFragment { class MCDwarfLineAddrFragment : public MCFragment {
virtual void anchor();
/// LineDelta - the value of the difference between the two line numbers /// LineDelta - the value of the difference between the two line numbers
/// between two .loc dwarf directives. /// between two .loc dwarf directives.
@ -479,7 +441,8 @@ class MCDwarfLineAddrFragment : public MCFragment {
public: public:
MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta, MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta,
MCSection *Sec = nullptr) 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); Contents.push_back(0);
} }
@ -501,7 +464,6 @@ public:
}; };
class MCDwarfCallFrameFragment : public MCFragment { class MCDwarfCallFrameFragment : public MCFragment {
virtual void anchor();
/// AddrDelta - The expression for the difference of the two symbols that /// AddrDelta - The expression for the difference of the two symbols that
/// make up the address delta between two .cfi_* dwarf directives. /// make up the address delta between two .cfi_* dwarf directives.
@ -511,7 +473,7 @@ class MCDwarfCallFrameFragment : public MCFragment {
public: public:
MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr) 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); Contents.push_back(0);
} }
@ -531,13 +493,11 @@ public:
}; };
class MCSafeSEHFragment : public MCFragment { class MCSafeSEHFragment : public MCFragment {
virtual void anchor();
const MCSymbol *Sym; const MCSymbol *Sym;
public: public:
MCSafeSEHFragment(const MCSymbol *Sym, MCSection *Sec = nullptr) MCSafeSEHFragment(const MCSymbol *Sym, MCSection *Sec = nullptr)
: MCFragment(FT_SafeSEH, Sec), Sym(Sym) {} : MCFragment(FT_SafeSEH, false, 0, Sec), Sym(Sym) {}
/// \name Accessors /// \name Accessors
/// @{ /// @{

View File

@ -93,7 +93,7 @@ private:
void fixSymbolsInTLSFixups(const MCExpr *expr); void fixSymbolsInTLSFixups(const MCExpr *expr);
/// \brief Merge the content of the fragment \p EF into the fragment \p DF. /// \brief Merge the content of the fragment \p EF into the fragment \p DF.
void mergeFragment(MCDataFragment *, MCEncodedFragmentWithFixups *); void mergeFragment(MCDataFragment *, MCDataFragment *);
bool SeenIdent; bool SeenIdent;

View File

@ -31,6 +31,18 @@ class MCSection;
class MCSymbol; class MCSymbol;
class raw_ostream; 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 /// Instances of this class represent a uniqued identifier for a section in the
/// current translation unit. The MCContext class uniques and creates these. /// current translation unit. The MCContext class uniques and creates these.
class MCSection { class MCSection {

View File

@ -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) MCFragment::~MCFragment() { }
: Kind(Kind), Parent(Parent), Atom(nullptr), Offset(~UINT64_C(0)) {
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) if (Parent)
Parent->getFragmentList().push_back(this); Parent->getFragmentList().push_back(this);
} }
/* *** */ void MCFragment::destroy() {
// First check if we are the sentinal.
if (Kind == FragmentType(~0)) {
delete this;
return;
}
MCEncodedFragment::~MCEncodedFragment() { switch (Kind) {
} case FT_Align:
delete cast<MCAlignFragment>(this);
/* *** */ return;
case FT_Data:
MCEncodedFragmentWithFixups::~MCEncodedFragmentWithFixups() { 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 { const MCFragment &F) const {
switch (F.getKind()) { switch (F.getKind()) {
case MCFragment::FT_Data: case MCFragment::FT_Data:
return cast<MCDataFragment>(F).getContents().size();
case MCFragment::FT_Relaxable: case MCFragment::FT_Relaxable:
return cast<MCRelaxableFragment>(F).getContents().size();
case MCFragment::FT_CompactEncodedInst: case MCFragment::FT_CompactEncodedInst:
return cast<MCEncodedFragment>(F).getContents().size(); return cast<MCCompactEncodedInstFragment>(F).getContents().size();
case MCFragment::FT_Fill: case MCFragment::FT_Fill:
return cast<MCFillFragment>(F).getSize(); 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) { void MCAssembler::registerSymbol(const MCSymbol &Symbol, bool *Created) {
bool New = !Symbol.isRegistered(); bool New = !Symbol.isRegistered();
if (Created) if (Created)
@ -671,17 +704,17 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
case MCFragment::FT_Data: case MCFragment::FT_Data:
++stats::EmittedDataFragments; ++stats::EmittedDataFragments;
writeFragmentContents(F, OW); OW->writeBytes(cast<MCDataFragment>(F).getContents());
break; break;
case MCFragment::FT_Relaxable: case MCFragment::FT_Relaxable:
++stats::EmittedRelaxableFragments; ++stats::EmittedRelaxableFragments;
writeFragmentContents(F, OW); OW->writeBytes(cast<MCRelaxableFragment>(F).getContents());
break; break;
case MCFragment::FT_CompactEncodedInst: case MCFragment::FT_CompactEncodedInst:
++stats::EmittedCompactEncodedInstFragments; ++stats::EmittedCompactEncodedInstFragments;
writeFragmentContents(F, OW); OW->writeBytes(cast<MCCompactEncodedInstFragment>(F).getContents());
break; break;
case MCFragment::FT_Fill: { case MCFragment::FT_Fill: {
@ -870,18 +903,29 @@ void MCAssembler::Finish() {
for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it) { for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it) {
for (MCSection::iterator it2 = it->begin(), ie2 = it->end(); it2 != ie2; for (MCSection::iterator it2 = it->begin(), ie2 = it->end(); it2 != ie2;
++it2) { ++it2) {
MCEncodedFragmentWithFixups *F = MCEncodedFragment *F = dyn_cast<MCEncodedFragment>(it2);
dyn_cast<MCEncodedFragmentWithFixups>(it2); // Data and relaxable fragments both have fixups. So only process
if (F) { // those here.
for (MCEncodedFragmentWithFixups::fixup_iterator it3 = F->fixup_begin(), // FIXME: Is there a better way to do this? MCEncodedFragmentWithFixups
ie3 = F->fixup_end(); it3 != ie3; ++it3) { // being templated makes this tricky.
MCFixup &Fixup = *it3; if (!F || isa<MCCompactEncodedInstFragment>(F))
uint64_t FixedValue; continue;
bool IsPCRel; ArrayRef<MCFixup> Fixups;
std::tie(FixedValue, IsPCRel) = handleFixup(Layout, *F, Fixup); MutableArrayRef<char> Contents;
getBackend().applyFixup(Fixup, F->getContents().data(), if (auto *FragWithFixups = dyn_cast<MCDataFragment>(F)) {
F->getContents().size(), FixedValue, IsPCRel); 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, Contents.data(),
Contents.size(), FixedValue, IsPCRel);
} }
} }
} }
@ -1218,17 +1262,3 @@ void MCAssembler::dump() {
OS << "]>\n"; OS << "]>\n";
} }
#endif #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() { }

View File

@ -45,7 +45,7 @@ MCELFStreamer::~MCELFStreamer() {
} }
void MCELFStreamer::mergeFragment(MCDataFragment *DF, void MCELFStreamer::mergeFragment(MCDataFragment *DF,
MCEncodedFragmentWithFixups *EF) { MCDataFragment *EF) {
MCAssembler &Assembler = getAssembler(); MCAssembler &Assembler = getAssembler();
if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) { if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) {