1 //===-- llvm/MC/MCObjectWriter.h - Object File Writer Interface -*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef LLVM_MC_MCOBJECTWRITER_H 11 #define LLVM_MC_MCOBJECTWRITER_H 12 13 #include "llvm/Support/raw_ostream.h" 14 #include "llvm/Support/DataTypes.h" 15 #include <cassert> 16 17 namespace llvm { 18 class MCAsmLayout; 19 class MCAssembler; 20 class MCFixup; 21 class MCFragment; 22 class MCSymbolData; 23 class MCSymbolRefExpr; 24 class MCValue; 25 26 /// MCObjectWriter - Defines the object file and target independent interfaces 27 /// used by the assembler backend to write native file format object files. 28 /// 29 /// The object writer contains a few callbacks used by the assembler to allow 30 /// the object writer to modify the assembler data structures at appropriate 31 /// points. Once assembly is complete, the object writer is given the 32 /// MCAssembler instance, which contains all the symbol and section data which 33 /// should be emitted as part of WriteObject(). 34 /// 35 /// The object writer also contains a number of helper methods for writing 36 /// binary data to the output stream. 37 class MCObjectWriter { 38 MCObjectWriter(const MCObjectWriter &); // DO NOT IMPLEMENT 39 void operator=(const MCObjectWriter &); // DO NOT IMPLEMENT 40 41 protected: 42 raw_ostream &OS; 43 44 unsigned IsLittleEndian : 1; 45 46 protected: // Can only create subclasses. 47 MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian) 48 : OS(_OS), IsLittleEndian(_IsLittleEndian) {} 49 50 public: 51 virtual ~MCObjectWriter(); 52 53 bool isLittleEndian() const { return IsLittleEndian; } 54 55 raw_ostream &getStream() { return OS; } 56 57 /// @name High-Level API 58 /// @{ 59 60 /// Perform any late binding of symbols (for example, to assign symbol indices 61 /// for use when generating relocations). 62 /// 63 /// This routine is called by the assembler after layout and relaxation is 64 /// complete. 65 virtual void ExecutePostLayoutBinding(MCAssembler &Asm, 66 const MCAsmLayout &Layout) = 0; 67 68 /// Record a relocation entry. 69 /// 70 /// This routine is called by the assembler after layout and relaxation, and 71 /// post layout binding. The implementation is responsible for storing 72 /// information about the relocation so that it can be emitted during 73 /// WriteObject(). 74 virtual void RecordRelocation(const MCAssembler &Asm, 75 const MCAsmLayout &Layout, 76 const MCFragment *Fragment, 77 const MCFixup &Fixup, MCValue Target, 78 uint64_t &FixedValue) = 0; 79 80 /// \brief Check whether the difference (A - B) between two symbol 81 /// references is fully resolved. 82 /// 83 /// Clients are not required to answer precisely and may conservatively return 84 /// false, even when a difference is fully resolved. 85 bool 86 IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm, 87 const MCSymbolRefExpr *A, 88 const MCSymbolRefExpr *B, 89 bool InSet) const; 90 91 virtual bool 92 IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, 93 const MCSymbolData &DataA, 94 const MCFragment &FB, 95 bool InSet, 96 bool IsPCRel) const; 97 98 99 /// Write the object file. 100 /// 101 /// This routine is called by the assembler after layout and relaxation is 102 /// complete, fixups have been evaluated and applied, and relocations 103 /// generated. 104 virtual void WriteObject(MCAssembler &Asm, 105 const MCAsmLayout &Layout) = 0; 106 107 /// @} 108 /// @name Binary Output 109 /// @{ 110 111 void Write8(uint8_t Value) { 112 OS << char(Value); 113 } 114 115 void WriteLE16(uint16_t Value) { 116 Write8(uint8_t(Value >> 0)); 117 Write8(uint8_t(Value >> 8)); 118 } 119 120 void WriteLE32(uint32_t Value) { 121 WriteLE16(uint16_t(Value >> 0)); 122 WriteLE16(uint16_t(Value >> 16)); 123 } 124 125 void WriteLE64(uint64_t Value) { 126 WriteLE32(uint32_t(Value >> 0)); 127 WriteLE32(uint32_t(Value >> 32)); 128 } 129 130 void WriteBE16(uint16_t Value) { 131 Write8(uint8_t(Value >> 8)); 132 Write8(uint8_t(Value >> 0)); 133 } 134 135 void WriteBE32(uint32_t Value) { 136 WriteBE16(uint16_t(Value >> 16)); 137 WriteBE16(uint16_t(Value >> 0)); 138 } 139 140 void WriteBE64(uint64_t Value) { 141 WriteBE32(uint32_t(Value >> 32)); 142 WriteBE32(uint32_t(Value >> 0)); 143 } 144 145 void Write16(uint16_t Value) { 146 if (IsLittleEndian) 147 WriteLE16(Value); 148 else 149 WriteBE16(Value); 150 } 151 152 void Write32(uint32_t Value) { 153 if (IsLittleEndian) 154 WriteLE32(Value); 155 else 156 WriteBE32(Value); 157 } 158 159 void Write64(uint64_t Value) { 160 if (IsLittleEndian) 161 WriteLE64(Value); 162 else 163 WriteBE64(Value); 164 } 165 166 void WriteZeros(unsigned N) { 167 const char Zeros[16] = { 0 }; 168 169 for (unsigned i = 0, e = N / 16; i != e; ++i) 170 OS << StringRef(Zeros, 16); 171 172 OS << StringRef(Zeros, N % 16); 173 } 174 175 void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) { 176 assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) && 177 "data size greater than fill size, unexpected large write will occur"); 178 OS << Str; 179 if (ZeroFillSize) 180 WriteZeros(ZeroFillSize - Str.size()); 181 } 182 183 /// @} 184 185 /// Utility function to encode a SLEB128 value. 186 static void EncodeSLEB128(int64_t Value, raw_ostream &OS); 187 /// Utility function to encode a ULEB128 value. 188 static void EncodeULEB128(uint64_t Value, raw_ostream &OS, 189 unsigned Padding = 0); 190 }; 191 192 } // End llvm namespace 193 194 #endif 195