Devirtualize and pack MCFragment to reduce memory usage.
authorPete Cooper <peter_cooper@apple.com>
Wed, 17 Jun 2015 22:01:28 +0000 (22:01 +0000)
committerPete Cooper <peter_cooper@apple.com>
Wed, 17 Jun 2015 22:01:28 +0000 (22:01 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239952 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCAssembler.h
include/llvm/MC/MCELFStreamer.h
include/llvm/MC/MCSection.h
lib/MC/MCAssembler.cpp
lib/MC/MCELFStreamer.cpp

index 484f370515ab8346e2a97436fad7e7a43b913aee..0642af837e7e983c76f389e42bd4bc730b473090 100644 (file)
@@ -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);
 
-public:
-  // Only for sentinel.
+  ~MCFragment();
+private:
+
+  // This is a friend so that the sentinal can be created.
+  friend struct ilist_sentinel_traits<MCFragment>;
   MCFragment();
-  virtual ~MCFragment();
+
+public:
+  /// 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:
-  MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
-                              MCSection *Sec = nullptr)
-      : MCEncodedFragment(FType, Sec) {}
+  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> {
 
-  ~MCEncodedFragmentWithFixups() override;
+  /// Fixups - The list of fixups in this fragment.
+  SmallVector<MCFixup, FixupsSize> Fixups;
 
+protected:
+  MCEncodedFragmentWithFixups(MCFragment::FragmentType FType,
+                              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; }
+
+  fixup_iterator fixup_begin() { return Fixups.begin(); }
+  const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
 
-  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_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) {}
-
-  SmallVectorImpl<char> &getContents() override { return Contents; }
-  const SmallVectorImpl<char> &getContents() const override { return Contents; }
-
-  SmallVectorImpl<MCFixup> &getFixups() override { return Fixups; }
+      : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {}
 
-  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
   /// @{
index 241db0dc9cdee538b9162bc0c6624c31ed7e8238..a5b257f5958b624cd305789f153445ba45c12cd0 100644 (file)
@@ -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;
 
index 5f6e8ec1d50659298f074f95425e51b738751eba..2d0d4dfc59137dded9bfff83134b4a253b0603d7 100644 (file)
@@ -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 {
index df416710182e9d9656b9f8b3373d97af8a6768bd..76be67cafc5656022f9824bd05a1da92c17f0a4d 100644 (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)
-    : 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;
-          uint64_t FixedValue;
-          bool IsPCRel;
-          std::tie(FixedValue, IsPCRel) = handleFixup(Layout, *F, Fixup);
-          getBackend().applyFixup(Fixup, F->getContents().data(),
-                                  F->getContents().size(), FixedValue, IsPCRel);
-        }
+      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, 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() { }
index e0f4a2ae16a36652c3893f6e5c5dfca11f9f7557..fe9ac21e17fc5a6c00792f90dcdc30ddc264c69c 100644 (file)
@@ -45,7 +45,7 @@ MCELFStreamer::~MCELFStreamer() {
 }
 
 void MCELFStreamer::mergeFragment(MCDataFragment *DF,
-                                  MCEncodedFragmentWithFixups *EF) {
+                                  MCDataFragment *EF) {
   MCAssembler &Assembler = getAssembler();
 
   if (Assembler.isBundlingEnabled() && Assembler.getRelaxAll()) {