MC: Split MCObjectWriter out of MCAssembler.cpp.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98949 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index ad42364..ae8ca4b 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -11,6 +11,7 @@
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCAsmLayout.h"
 #include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCObjectWriter.h"
 #include "llvm/MC/MCSectionMachO.h"
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/MCValue.h"
@@ -42,10 +43,6 @@
 // object file, which may truncate it. We should detect that truncation where
 // invalid and report errors back.
 
-class MCObjectWriter;
-static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
-                          MCObjectWriter *MOW);
-
 /// isVirtualSection - Check if this is a section which does not actually exist
 /// in the object file.
 static bool isVirtualSection(const MCSection &Section) {
@@ -78,105 +75,6 @@
   }
 }
 
-class MCObjectWriter {
-  MCObjectWriter(const MCObjectWriter &); // DO NOT IMPLEMENT
-  void operator=(const MCObjectWriter &); // DO NOT IMPLEMENT
-
-protected:
-  raw_ostream &OS;
-
-  unsigned IsLittleEndian : 1;
-
-protected: // Can only create subclasses.
-  MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian)
-    : OS(_OS), IsLittleEndian(_IsLittleEndian) {}
-  virtual ~MCObjectWriter();
-
-public:
-
-  bool isLittleEndian() { return IsLittleEndian; }
-
-  raw_ostream &getStream() { return OS; }
-
-  /// @name Binary Output Methods
-  /// @{
-
-  void Write8(uint8_t Value) {
-    OS << char(Value);
-  }
-
-  void WriteLE16(uint16_t Value) {
-    Write8(uint8_t(Value >> 0));
-    Write8(uint8_t(Value >> 8));
-  }
-
-  void WriteLE32(uint32_t Value) {
-    WriteLE16(uint16_t(Value >> 0));
-    WriteLE16(uint16_t(Value >> 16));
-  }
-
-  void WriteLE64(uint64_t Value) {
-    WriteLE32(uint32_t(Value >> 0));
-    WriteLE32(uint32_t(Value >> 32));
-  }
-
-  void WriteBE16(uint16_t Value) {
-    Write8(uint8_t(Value >> 8));
-    Write8(uint8_t(Value >> 0));
-  }
-
-  void WriteBE32(uint32_t Value) {
-    WriteBE16(uint16_t(Value >> 16));
-    WriteBE16(uint16_t(Value >> 0));
-  }
-
-  void WriteBE64(uint64_t Value) {
-    WriteBE32(uint32_t(Value >> 32));
-    WriteBE32(uint32_t(Value >> 0));
-  }
-
-  void Write16(uint16_t Value) {
-    if (IsLittleEndian)
-      WriteLE16(Value);
-    else
-      WriteBE16(Value);
-  }
-
-  void Write32(uint32_t Value) {
-    if (IsLittleEndian)
-      WriteLE32(Value);
-    else
-      WriteBE32(Value);
-  }
-
-  void Write64(uint64_t Value) {
-    if (IsLittleEndian)
-      WriteLE64(Value);
-    else
-      WriteBE64(Value);
-  }
-
-  void WriteZeros(unsigned N) {
-    const char Zeros[16] = { 0 };
-
-    for (unsigned i = 0, e = N / 16; i != e; ++i)
-      OS << StringRef(Zeros, 16);
-
-    OS << StringRef(Zeros, N % 16);
-  }
-
-  void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
-    OS << Str;
-    if (ZeroFillSize)
-      WriteZeros(ZeroFillSize - Str.size());
-  }
-
-  /// @}
-};
-
-MCObjectWriter::~MCObjectWriter() {
-}
-
 class MachObjectWriter : public MCObjectWriter {
   // See <mach-o/loader.h>.
   enum {
@@ -362,8 +260,9 @@
     assert(OS.tell() - Start == SegmentLoadCommandSize);
   }
 
-  void WriteSection(const MCSectionData &SD, uint64_t FileOffset,
-                    uint64_t RelocationsStart, unsigned NumRelocations) {
+  void WriteSection(const MCAssembler &Asm, const MCSectionData &SD,
+                    uint64_t FileOffset, uint64_t RelocationsStart,
+                    unsigned NumRelocations) {
     // The offset is unused for virtual sections.
     if (isVirtualSection(SD.getSection())) {
       assert(SD.getFileSize() == 0 && "Invalid file size!");
@@ -527,7 +426,8 @@
       Write32(Address);
   }
 
-  void RecordScatteredRelocation(MCAssembler &Asm, MCFragment &Fragment,
+  void RecordScatteredRelocation(const MCAssembler &Asm,
+                                 const MCFragment &Fragment,
                                  const MCAsmFixup &Fixup, MCValue Target,
                                  uint64_t &FixedValue) {
     uint32_t Address = Fragment.getOffset() + Fixup.Offset;
@@ -584,9 +484,10 @@
     Relocations[Fragment.getParent()].push_back(MRE);
   }
 
-  void RecordRelocation(MCAssembler &Asm, MCDataFragment &Fragment,
-                        const MCAsmFixup &Fixup, MCValue Target,
-                        uint64_t &FixedValue) {
+  virtual void RecordRelocation(const MCAssembler &Asm,
+                                const MCDataFragment &Fragment,
+                                const MCAsmFixup &Fixup, MCValue Target,
+                                uint64_t &FixedValue) {
     unsigned IsPCRel = isFixupKindPCRel(Fixup.Kind);
     unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind);
 
@@ -629,7 +530,7 @@
         //
         // FIXME: O(N)
         Index = 1;
-        MCAssembler::iterator it = Asm.begin(), ie = Asm.end();
+        MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end();
         for (; it != ie; ++it, ++Index)
           if (&*it == SD->getFragment()->getParent())
             break;
@@ -807,7 +708,7 @@
       StringTable += '\x00';
   }
 
-  void ExecutePostLayoutBinding(MCAssembler &Asm) {
+  virtual void ExecutePostLayoutBinding(MCAssembler &Asm) {
     // Create symbol data for any indirect symbols.
     BindIndirectSymbols(Asm);
 
@@ -816,7 +717,7 @@
                        UndefinedSymbolData);
   }
 
-  void WriteObject(const MCAssembler &Asm) {
+  virtual void WriteObject(const MCAssembler &Asm) {
     unsigned NumSections = Asm.size();
 
     // The section data starts after the header, the segment load command (and
@@ -916,7 +817,7 @@
     // Write the actual section data.
     for (MCAssembler::const_iterator it = Asm.begin(),
            ie = Asm.end(); it != ie; ++it)
-      WriteFileData(OS, *it, this);
+      Asm.WriteSectionData(it, this);
 
     // Write the extra padding.
     WriteZeros(SectionDataPadding);
@@ -1357,10 +1258,9 @@
   return Count;
 }
 
-/// WriteFileData - Write the \arg F data to the output file.
-static void WriteFileData(raw_ostream &OS, const MCFragment &F,
-                          MCObjectWriter *OW) {
-  uint64_t Start = OS.tell();
+/// WriteFragmentData - Write the \arg F data to the output file.
+static void WriteFragmentData(const MCFragment &F, MCObjectWriter *OW) {
+  uint64_t Start = OW->getStream().tell();
   (void) Start;
 
   ++EmittedFragments;
@@ -1402,7 +1302,7 @@
   }
 
   case MCFragment::FT_Data: {
-    OS << cast<MCDataFragment>(F).getContents().str();
+    OW->WriteBytes(cast<MCDataFragment>(F).getContents().str());
     break;
   }
 
@@ -1436,30 +1336,29 @@
   }
   }
 
-  assert(OS.tell() - Start == F.getFileSize());
+  assert(OW->getStream().tell() - Start == F.getFileSize());
 }
 
-/// WriteFileData - Write the \arg SD data to the output file.
-static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
-                          MCObjectWriter *OW) {
+void MCAssembler::WriteSectionData(const MCSectionData *SD,
+                                   MCObjectWriter *OW) const {
   // Ignore virtual sections.
-  if (isVirtualSection(SD.getSection())) {
-    assert(SD.getFileSize() == 0);
+  if (isVirtualSection(SD->getSection())) {
+    assert(SD->getFileSize() == 0);
     return;
   }
 
-  uint64_t Start = OS.tell();
+  uint64_t Start = OW->getStream().tell();
   (void) Start;
 
-  for (MCSectionData::const_iterator it = SD.begin(),
-         ie = SD.end(); it != ie; ++it)
-    WriteFileData(OS, *it, OW);
+  for (MCSectionData::const_iterator it = SD->begin(),
+         ie = SD->end(); it != ie; ++it)
+    WriteFragmentData(*it, OW);
 
   // Add section padding.
-  assert(SD.getFileSize() >= SD.getSize() && "Invalid section sizes!");
-  OW->WriteZeros(SD.getFileSize() - SD.getSize());
+  assert(SD->getFileSize() >= SD->getSize() && "Invalid section sizes!");
+  OW->WriteZeros(SD->getFileSize() - SD->getSize());
 
-  assert(OS.tell() - Start == SD.getFileSize());
+  assert(OW->getStream().tell() - Start == SD->getFileSize());
 }
 
 void MCAssembler::Finish() {