[ThinLTO] Enable in-place symbol changes for exporting module
[oota-llvm.git] / include / llvm / MC / MCObjectWriter.h
index f0e86a7cc83dfe18f79496b70c51e9592c71f945..63c833ac20d6d09543880af10238c7e37f2ad914 100644 (file)
@@ -22,18 +22,17 @@ class MCAsmLayout;
 class MCAssembler;
 class MCFixup;
 class MCFragment;
-class MCSymbolData;
 class MCSymbolRefExpr;
 class MCValue;
 
-/// MCObjectWriter - Defines the object file and target independent interfaces
-/// used by the assembler backend to write native file format object files.
+/// Defines the object file and target independent interfaces used by the
+/// assembler backend to write native file format object files.
 ///
 /// The object writer contains a few callbacks used by the assembler to allow
 /// the object writer to modify the assembler data structures at appropriate
 /// points. Once assembly is complete, the object writer is given the
 /// MCAssembler instance, which contains all the symbol and section data which
-/// should be emitted as part of WriteObject().
+/// should be emitted as part of writeObject().
 ///
 /// The object writer also contains a number of helper methods for writing
 /// binary data to the output stream.
@@ -41,155 +40,162 @@ class MCObjectWriter {
   MCObjectWriter(const MCObjectWriter &) = delete;
   void operator=(const MCObjectWriter &) = delete;
 
-protected:
-  raw_ostream &OS;
+  raw_pwrite_stream *OS;
 
+protected:
   unsigned IsLittleEndian : 1;
 
 protected: // Can only create subclasses.
-  MCObjectWriter(raw_ostream &OS, bool IsLittleEndian)
-      : OS(OS), IsLittleEndian(IsLittleEndian) {}
+  MCObjectWriter(raw_pwrite_stream &OS, bool IsLittleEndian)
+      : OS(&OS), IsLittleEndian(IsLittleEndian) {}
+
+  unsigned getInitialOffset() {
+    return OS->tell();
+  }
 
 public:
   virtual ~MCObjectWriter();
 
   /// lifetime management
-  virtual void reset() { }
+  virtual void reset() {}
 
   bool isLittleEndian() const { return IsLittleEndian; }
 
-  raw_ostream &getStream() { return OS; }
+  raw_pwrite_stream &getStream() { return *OS; }
+  void setStream(raw_pwrite_stream &NewOS) { OS = &NewOS; }
 
-  /// @name High-Level API
+  /// \name High-Level API
   /// @{
 
-  /// \brief Perform any late binding of symbols (for example, to assign symbol
+  /// Perform any late binding of symbols (for example, to assign symbol
   /// indices for use when generating relocations).
   ///
   /// This routine is called by the assembler after layout and relaxation is
   /// complete.
-  virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
+  virtual void executePostLayoutBinding(MCAssembler &Asm,
                                         const MCAsmLayout &Layout) = 0;
 
-  /// \brief Record a relocation entry.
+  /// Record a relocation entry.
   ///
   /// This routine is called by the assembler after layout and relaxation, and
   /// post layout binding. The implementation is responsible for storing
   /// information about the relocation so that it can be emitted during
-  /// WriteObject().
-  virtual void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
+  /// writeObject().
+  virtual void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
                                 const MCFragment *Fragment,
                                 const MCFixup &Fixup, MCValue Target,
                                 bool &IsPCRel, uint64_t &FixedValue) = 0;
 
-  /// \brief Check whether the difference (A - B) between two symbol
-  /// references is fully resolved.
+  /// Check whether the difference (A - B) between two symbol references is
+  /// fully resolved.
   ///
   /// Clients are not required to answer precisely and may conservatively return
   /// false, even when a difference is fully resolved.
-  bool IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
+  bool isSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
                                           const MCSymbolRefExpr *A,
                                           const MCSymbolRefExpr *B,
                                           bool InSet) const;
 
-  virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
-                                                      const MCSymbolData &DataA,
-                                                      const MCSymbolData *DataB,
+  virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
+                                                      const MCSymbol &A,
+                                                      const MCSymbol &B,
+                                                      bool InSet) const;
+
+  virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
+                                                      const MCSymbol &SymA,
                                                       const MCFragment &FB,
                                                       bool InSet,
                                                       bool IsPCRel) const;
 
-  /// \brief True if this symbol (which is a variable) is weak. This is not
+  /// True if this symbol (which is a variable) is weak. This is not
   /// just STB_WEAK, but more generally whether or not we can evaluate
   /// past it.
-  virtual bool isWeak(const MCSymbolData &SD) const;
+  virtual bool isWeak(const MCSymbol &Sym) const;
 
-  /// \brief Write the object file.
+  /// Write the object file.
   ///
   /// This routine is called by the assembler after layout and relaxation is
   /// complete, fixups have been evaluated and applied, and relocations
   /// generated.
-  virtual void WriteObject(MCAssembler &Asm,
-                           const MCAsmLayout &Layout) = 0;
+  virtual void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) = 0;
 
   /// @}
-  /// @name Binary Output
+  /// \name Binary Output
   /// @{
 
-  void Write8(uint8_t Value) {
-    OS << char(Value);
-  }
+  void write8(uint8_t Value) { *OS << char(Value); }
 
-  void WriteLE16(uint16_t Value) {
-    support::endian::Writer<support::little>(OS).write(Value);
+  void writeLE16(uint16_t Value) {
+    support::endian::Writer<support::little>(*OS).write(Value);
   }
 
-  void WriteLE32(uint32_t Value) {
-    support::endian::Writer<support::little>(OS).write(Value);
+  void writeLE32(uint32_t Value) {
+    support::endian::Writer<support::little>(*OS).write(Value);
   }
 
-  void WriteLE64(uint64_t Value) {
-    support::endian::Writer<support::little>(OS).write(Value);
+  void writeLE64(uint64_t Value) {
+    support::endian::Writer<support::little>(*OS).write(Value);
   }
 
-  void WriteBE16(uint16_t Value) {
-    support::endian::Writer<support::big>(OS).write(Value);
+  void writeBE16(uint16_t Value) {
+    support::endian::Writer<support::big>(*OS).write(Value);
   }
 
-  void WriteBE32(uint32_t Value) {
-    support::endian::Writer<support::big>(OS).write(Value);
+  void writeBE32(uint32_t Value) {
+    support::endian::Writer<support::big>(*OS).write(Value);
   }
 
-  void WriteBE64(uint64_t Value) {
-    support::endian::Writer<support::big>(OS).write(Value);
+  void writeBE64(uint64_t Value) {
+    support::endian::Writer<support::big>(*OS).write(Value);
   }
 
-  void Write16(uint16_t Value) {
+  void write16(uint16_t Value) {
     if (IsLittleEndian)
-      WriteLE16(Value);
+      writeLE16(Value);
     else
-      WriteBE16(Value);
+      writeBE16(Value);
   }
 
-  void Write32(uint32_t Value) {
+  void write32(uint32_t Value) {
     if (IsLittleEndian)
-      WriteLE32(Value);
+      writeLE32(Value);
     else
-      WriteBE32(Value);
+      writeBE32(Value);
   }
 
-  void Write64(uint64_t Value) {
+  void write64(uint64_t Value) {
     if (IsLittleEndian)
-      WriteLE64(Value);
+      writeLE64(Value);
     else
-      WriteBE64(Value);
+      writeBE64(Value);
   }
 
   void WriteZeros(unsigned N) {
-    const char Zeros[16] = { 0 };
+    const char Zeros[16] = {0};
 
     for (unsigned i = 0, e = N / 16; i != e; ++i)
-      OS << StringRef(Zeros, 16);
+      *OS << StringRef(Zeros, 16);
 
-    OS << StringRef(Zeros, N % 16);
+    *OS << StringRef(Zeros, N % 16);
   }
 
-  void WriteBytes(const SmallVectorImpl<char> &ByteVec, unsigned ZeroFillSize = 0) {
-    WriteBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize);
+  void writeBytes(const SmallVectorImpl<char> &ByteVec,
+                  unsigned ZeroFillSize = 0) {
+    writeBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize);
   }
 
-  void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
+  void writeBytes(StringRef Str, unsigned ZeroFillSize = 0) {
     // TODO: this version may need to go away once all fragment contents are
     // converted to SmallVector<char, N>
-    assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) &&
-      "data size greater than fill size, unexpected large write will occur");
-    OS << Str;
+    assert(
+        (ZeroFillSize == 0 || Str.size() <= ZeroFillSize) &&
+        "data size greater than fill size, unexpected large write will occur");
+    *OS << Str;
     if (ZeroFillSize)
       WriteZeros(ZeroFillSize - Str.size());
   }
 
   /// @}
-
 };
 
 } // End llvm namespace