LLVM API Documentation
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