LLVM API Documentation

MCObjectWriter.h
Go to the documentation of this file.
00001 //===-- llvm/MC/MCObjectWriter.h - Object File Writer Interface -*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #ifndef LLVM_MC_MCOBJECTWRITER_H
00011 #define LLVM_MC_MCOBJECTWRITER_H
00012 
00013 #include "llvm/ADT/SmallVector.h"
00014 #include "llvm/Support/Compiler.h"
00015 #include "llvm/Support/DataTypes.h"
00016 #include "llvm/Support/raw_ostream.h"
00017 #include <cassert>
00018 
00019 namespace llvm {
00020 class MCAsmLayout;
00021 class MCAssembler;
00022 class MCFixup;
00023 class MCFragment;
00024 class MCSymbolData;
00025 class MCSymbolRefExpr;
00026 class MCValue;
00027 
00028 /// MCObjectWriter - Defines the object file and target independent interfaces
00029 /// used by the assembler backend to write native file format object files.
00030 ///
00031 /// The object writer contains a few callbacks used by the assembler to allow
00032 /// the object writer to modify the assembler data structures at appropriate
00033 /// points. Once assembly is complete, the object writer is given the
00034 /// MCAssembler instance, which contains all the symbol and section data which
00035 /// should be emitted as part of WriteObject().
00036 ///
00037 /// The object writer also contains a number of helper methods for writing
00038 /// binary data to the output stream.
00039 class MCObjectWriter {
00040   MCObjectWriter(const MCObjectWriter &) LLVM_DELETED_FUNCTION;
00041   void operator=(const MCObjectWriter &) LLVM_DELETED_FUNCTION;
00042 
00043 protected:
00044   raw_ostream &OS;
00045 
00046   unsigned IsLittleEndian : 1;
00047 
00048 protected: // Can only create subclasses.
00049   MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian)
00050     : OS(_OS), IsLittleEndian(_IsLittleEndian) {}
00051 
00052 public:
00053   virtual ~MCObjectWriter();
00054 
00055   /// lifetime management
00056   virtual void reset() { }
00057 
00058   bool isLittleEndian() const { return IsLittleEndian; }
00059 
00060   raw_ostream &getStream() { return OS; }
00061 
00062   /// @name High-Level API
00063   /// @{
00064 
00065   /// \brief Perform any late binding of symbols (for example, to assign symbol
00066   /// indices for use when generating relocations).
00067   ///
00068   /// This routine is called by the assembler after layout and relaxation is
00069   /// complete.
00070   virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
00071                                         const MCAsmLayout &Layout) = 0;
00072 
00073   /// \brief Record a relocation entry.
00074   ///
00075   /// This routine is called by the assembler after layout and relaxation, and
00076   /// post layout binding. The implementation is responsible for storing
00077   /// information about the relocation so that it can be emitted during
00078   /// WriteObject().
00079   virtual void RecordRelocation(const MCAssembler &Asm,
00080                                 const MCAsmLayout &Layout,
00081                                 const MCFragment *Fragment,
00082                                 const MCFixup &Fixup, MCValue Target,
00083                                 bool &IsPCRel,
00084                                 uint64_t &FixedValue) = 0;
00085 
00086   /// \brief Check whether the difference (A - B) between two symbol
00087   /// references is fully resolved.
00088   ///
00089   /// Clients are not required to answer precisely and may conservatively return
00090   /// false, even when a difference is fully resolved.
00091   bool
00092   IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
00093                                      const MCSymbolRefExpr *A,
00094                                      const MCSymbolRefExpr *B,
00095                                      bool InSet) const;
00096 
00097   virtual bool
00098   IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
00099                                          const MCSymbolData &DataA,
00100                                          const MCFragment &FB,
00101                                          bool InSet,
00102                                          bool IsPCRel) const;
00103 
00104   /// \brief Write the object file.
00105   ///
00106   /// This routine is called by the assembler after layout and relaxation is
00107   /// complete, fixups have been evaluated and applied, and relocations
00108   /// generated.
00109   virtual void WriteObject(MCAssembler &Asm,
00110                            const MCAsmLayout &Layout) = 0;
00111 
00112   /// @}
00113   /// @name Binary Output
00114   /// @{
00115 
00116   void Write8(uint8_t Value) {
00117     OS << char(Value);
00118   }
00119 
00120   void WriteLE16(uint16_t Value) {
00121     Write8(uint8_t(Value >> 0));
00122     Write8(uint8_t(Value >> 8));
00123   }
00124 
00125   void WriteLE32(uint32_t Value) {
00126     WriteLE16(uint16_t(Value >> 0));
00127     WriteLE16(uint16_t(Value >> 16));
00128   }
00129 
00130   void WriteLE64(uint64_t Value) {
00131     WriteLE32(uint32_t(Value >> 0));
00132     WriteLE32(uint32_t(Value >> 32));
00133   }
00134 
00135   void WriteBE16(uint16_t Value) {
00136     Write8(uint8_t(Value >> 8));
00137     Write8(uint8_t(Value >> 0));
00138   }
00139 
00140   void WriteBE32(uint32_t Value) {
00141     WriteBE16(uint16_t(Value >> 16));
00142     WriteBE16(uint16_t(Value >> 0));
00143   }
00144 
00145   void WriteBE64(uint64_t Value) {
00146     WriteBE32(uint32_t(Value >> 32));
00147     WriteBE32(uint32_t(Value >> 0));
00148   }
00149 
00150   void Write16(uint16_t Value) {
00151     if (IsLittleEndian)
00152       WriteLE16(Value);
00153     else
00154       WriteBE16(Value);
00155   }
00156 
00157   void Write32(uint32_t Value) {
00158     if (IsLittleEndian)
00159       WriteLE32(Value);
00160     else
00161       WriteBE32(Value);
00162   }
00163 
00164   void Write64(uint64_t Value) {
00165     if (IsLittleEndian)
00166       WriteLE64(Value);
00167     else
00168       WriteBE64(Value);
00169   }
00170 
00171   void WriteZeros(unsigned N) {
00172     const char Zeros[16] = { 0 };
00173 
00174     for (unsigned i = 0, e = N / 16; i != e; ++i)
00175       OS << StringRef(Zeros, 16);
00176 
00177     OS << StringRef(Zeros, N % 16);
00178   }
00179 
00180   void WriteBytes(const SmallVectorImpl<char> &ByteVec, unsigned ZeroFillSize = 0) {
00181     WriteBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize);
00182   }
00183 
00184   void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
00185     // TODO: this version may need to go away once all fragment contents are
00186     // converted to SmallVector<char, N>
00187     assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) &&
00188       "data size greater than fill size, unexpected large write will occur");
00189     OS << Str;
00190     if (ZeroFillSize)
00191       WriteZeros(ZeroFillSize - Str.size());
00192   }
00193 
00194   /// @}
00195 
00196 };
00197 
00198 } // End llvm namespace
00199 
00200 #endif