1 //===-- llvm/CodeGen/BinaryObject.h - Binary Object. -----------*- 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 // This file defines a Binary Object Aka. "blob" for holding data from code 11 // generators, ready for data to the object module code writters. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CODEGEN_BINARYOBJECT_H 16 #define LLVM_CODEGEN_BINARYOBJECT_H 17 18 #include "llvm/CodeGen/MachineRelocation.h" 19 #include "llvm/Support/DataTypes.h" 20 21 #include <string> 22 #include <vector> 23 24 namespace llvm { 25 26 typedef std::vector<uint8_t> BinaryData; 27 28 class BinaryObject { 29 protected: 30 std::string Name; 31 bool IsLittleEndian; 32 bool Is64Bit; 33 BinaryData Data; 34 std::vector<MachineRelocation> Relocations; 35 36 public: 37 /// Constructors and destructor BinaryObject()38 BinaryObject() {} 39 BinaryObject(bool isLittleEndian,bool is64Bit)40 BinaryObject(bool isLittleEndian, bool is64Bit) 41 : IsLittleEndian(isLittleEndian), Is64Bit(is64Bit) {} 42 BinaryObject(const std::string & name,bool isLittleEndian,bool is64Bit)43 BinaryObject(const std::string &name, bool isLittleEndian, bool is64Bit) 44 : Name(name), IsLittleEndian(isLittleEndian), Is64Bit(is64Bit) {} 45 ~BinaryObject()46 ~BinaryObject() {} 47 48 /// getName - get name of BinaryObject getName()49 inline std::string getName() const { return Name; } 50 51 /// get size of binary data size()52 size_t size() const { 53 return Data.size(); 54 } 55 56 /// get binary data getData()57 BinaryData& getData() { 58 return Data; 59 } 60 61 /// get machine relocations getRelocations()62 const std::vector<MachineRelocation>& getRelocations() const { 63 return Relocations; 64 } 65 66 /// hasRelocations - Return true if 'Relocations' is not empty hasRelocations()67 bool hasRelocations() const { 68 return !Relocations.empty(); 69 } 70 71 /// emitZeros - This callback is invoked to emit a arbitrary number 72 /// of zero bytes to the data stream. emitZeros(unsigned Size)73 inline void emitZeros(unsigned Size) { 74 for (unsigned i=0; i < Size; ++i) 75 emitByte(0); 76 } 77 78 /// emitByte - This callback is invoked when a byte needs to be 79 /// written to the data stream. emitByte(uint8_t B)80 inline void emitByte(uint8_t B) { 81 Data.push_back(B); 82 } 83 84 /// emitWord16 - This callback is invoked when a 16-bit word needs to be 85 /// written to the data stream in correct endian format and correct size. emitWord16(uint16_t W)86 inline void emitWord16(uint16_t W) { 87 if (IsLittleEndian) 88 emitWord16LE(W); 89 else 90 emitWord16BE(W); 91 } 92 93 /// emitWord16LE - This callback is invoked when a 16-bit word needs to be 94 /// written to the data stream in correct endian format and correct size. emitWord16LE(uint16_t W)95 inline void emitWord16LE(uint16_t W) { 96 Data.push_back((uint8_t)(W >> 0)); 97 Data.push_back((uint8_t)(W >> 8)); 98 } 99 100 /// emitWord16BE - This callback is invoked when a 16-bit word needs to be 101 /// written to the data stream in correct endian format and correct size. emitWord16BE(uint16_t W)102 inline void emitWord16BE(uint16_t W) { 103 Data.push_back((uint8_t)(W >> 8)); 104 Data.push_back((uint8_t)(W >> 0)); 105 } 106 107 /// emitWord - This callback is invoked when a word needs to be 108 /// written to the data stream in correct endian format and correct size. emitWord(uint64_t W)109 inline void emitWord(uint64_t W) { 110 if (!Is64Bit) 111 emitWord32(W); 112 else 113 emitWord64(W); 114 } 115 116 /// emitWord32 - This callback is invoked when a 32-bit word needs to be 117 /// written to the data stream in correct endian format. emitWord32(uint32_t W)118 inline void emitWord32(uint32_t W) { 119 if (IsLittleEndian) 120 emitWordLE(W); 121 else 122 emitWordBE(W); 123 } 124 125 /// emitWord64 - This callback is invoked when a 32-bit word needs to be 126 /// written to the data stream in correct endian format. emitWord64(uint64_t W)127 inline void emitWord64(uint64_t W) { 128 if (IsLittleEndian) 129 emitDWordLE(W); 130 else 131 emitDWordBE(W); 132 } 133 134 /// emitWord64 - This callback is invoked when a x86_fp80 needs to be 135 /// written to the data stream in correct endian format. emitWordFP80(const uint64_t * W,unsigned PadSize)136 inline void emitWordFP80(const uint64_t *W, unsigned PadSize) { 137 if (IsLittleEndian) { 138 emitWord64(W[0]); 139 emitWord16(W[1]); 140 } else { 141 emitWord16(W[1]); 142 emitWord64(W[0]); 143 } 144 emitZeros(PadSize); 145 } 146 147 /// emitWordLE - This callback is invoked when a 32-bit word needs to be 148 /// written to the data stream in little-endian format. emitWordLE(uint32_t W)149 inline void emitWordLE(uint32_t W) { 150 Data.push_back((uint8_t)(W >> 0)); 151 Data.push_back((uint8_t)(W >> 8)); 152 Data.push_back((uint8_t)(W >> 16)); 153 Data.push_back((uint8_t)(W >> 24)); 154 } 155 156 /// emitWordBE - This callback is invoked when a 32-bit word needs to be 157 /// written to the data stream in big-endian format. 158 /// emitWordBE(uint32_t W)159 inline void emitWordBE(uint32_t W) { 160 Data.push_back((uint8_t)(W >> 24)); 161 Data.push_back((uint8_t)(W >> 16)); 162 Data.push_back((uint8_t)(W >> 8)); 163 Data.push_back((uint8_t)(W >> 0)); 164 } 165 166 /// emitDWordLE - This callback is invoked when a 64-bit word needs to be 167 /// written to the data stream in little-endian format. emitDWordLE(uint64_t W)168 inline void emitDWordLE(uint64_t W) { 169 Data.push_back((uint8_t)(W >> 0)); 170 Data.push_back((uint8_t)(W >> 8)); 171 Data.push_back((uint8_t)(W >> 16)); 172 Data.push_back((uint8_t)(W >> 24)); 173 Data.push_back((uint8_t)(W >> 32)); 174 Data.push_back((uint8_t)(W >> 40)); 175 Data.push_back((uint8_t)(W >> 48)); 176 Data.push_back((uint8_t)(W >> 56)); 177 } 178 179 /// emitDWordBE - This callback is invoked when a 64-bit word needs to be 180 /// written to the data stream in big-endian format. emitDWordBE(uint64_t W)181 inline void emitDWordBE(uint64_t W) { 182 Data.push_back((uint8_t)(W >> 56)); 183 Data.push_back((uint8_t)(W >> 48)); 184 Data.push_back((uint8_t)(W >> 40)); 185 Data.push_back((uint8_t)(W >> 32)); 186 Data.push_back((uint8_t)(W >> 24)); 187 Data.push_back((uint8_t)(W >> 16)); 188 Data.push_back((uint8_t)(W >> 8)); 189 Data.push_back((uint8_t)(W >> 0)); 190 } 191 192 /// fixByte - This callback is invoked when a byte needs to be 193 /// fixup the buffer. fixByte(uint8_t B,uint32_t offset)194 inline void fixByte(uint8_t B, uint32_t offset) { 195 Data[offset] = B; 196 } 197 198 /// fixWord16 - This callback is invoked when a 16-bit word needs to 199 /// fixup the data stream in correct endian format. fixWord16(uint16_t W,uint32_t offset)200 inline void fixWord16(uint16_t W, uint32_t offset) { 201 if (IsLittleEndian) 202 fixWord16LE(W, offset); 203 else 204 fixWord16BE(W, offset); 205 } 206 207 /// emitWord16LE - This callback is invoked when a 16-bit word needs to 208 /// fixup the data stream in little endian format. fixWord16LE(uint16_t W,uint32_t offset)209 inline void fixWord16LE(uint16_t W, uint32_t offset) { 210 Data[offset] = (uint8_t)(W >> 0); 211 Data[++offset] = (uint8_t)(W >> 8); 212 } 213 214 /// fixWord16BE - This callback is invoked when a 16-bit word needs to 215 /// fixup data stream in big endian format. fixWord16BE(uint16_t W,uint32_t offset)216 inline void fixWord16BE(uint16_t W, uint32_t offset) { 217 Data[offset] = (uint8_t)(W >> 8); 218 Data[++offset] = (uint8_t)(W >> 0); 219 } 220 221 /// emitWord - This callback is invoked when a word needs to 222 /// fixup the data in correct endian format and correct size. fixWord(uint64_t W,uint32_t offset)223 inline void fixWord(uint64_t W, uint32_t offset) { 224 if (!Is64Bit) 225 fixWord32(W, offset); 226 else 227 fixWord64(W, offset); 228 } 229 230 /// fixWord32 - This callback is invoked when a 32-bit word needs to 231 /// fixup the data in correct endian format. fixWord32(uint32_t W,uint32_t offset)232 inline void fixWord32(uint32_t W, uint32_t offset) { 233 if (IsLittleEndian) 234 fixWord32LE(W, offset); 235 else 236 fixWord32BE(W, offset); 237 } 238 239 /// fixWord32LE - This callback is invoked when a 32-bit word needs to 240 /// fixup the data in little endian format. fixWord32LE(uint32_t W,uint32_t offset)241 inline void fixWord32LE(uint32_t W, uint32_t offset) { 242 Data[offset] = (uint8_t)(W >> 0); 243 Data[++offset] = (uint8_t)(W >> 8); 244 Data[++offset] = (uint8_t)(W >> 16); 245 Data[++offset] = (uint8_t)(W >> 24); 246 } 247 248 /// fixWord32BE - This callback is invoked when a 32-bit word needs to 249 /// fixup the data in big endian format. fixWord32BE(uint32_t W,uint32_t offset)250 inline void fixWord32BE(uint32_t W, uint32_t offset) { 251 Data[offset] = (uint8_t)(W >> 24); 252 Data[++offset] = (uint8_t)(W >> 16); 253 Data[++offset] = (uint8_t)(W >> 8); 254 Data[++offset] = (uint8_t)(W >> 0); 255 } 256 257 /// fixWord64 - This callback is invoked when a 64-bit word needs to 258 /// fixup the data in correct endian format. fixWord64(uint64_t W,uint32_t offset)259 inline void fixWord64(uint64_t W, uint32_t offset) { 260 if (IsLittleEndian) 261 fixWord64LE(W, offset); 262 else 263 fixWord64BE(W, offset); 264 } 265 266 /// fixWord64BE - This callback is invoked when a 64-bit word needs to 267 /// fixup the data in little endian format. fixWord64LE(uint64_t W,uint32_t offset)268 inline void fixWord64LE(uint64_t W, uint32_t offset) { 269 Data[offset] = (uint8_t)(W >> 0); 270 Data[++offset] = (uint8_t)(W >> 8); 271 Data[++offset] = (uint8_t)(W >> 16); 272 Data[++offset] = (uint8_t)(W >> 24); 273 Data[++offset] = (uint8_t)(W >> 32); 274 Data[++offset] = (uint8_t)(W >> 40); 275 Data[++offset] = (uint8_t)(W >> 48); 276 Data[++offset] = (uint8_t)(W >> 56); 277 } 278 279 /// fixWord64BE - This callback is invoked when a 64-bit word needs to 280 /// fixup the data in big endian format. fixWord64BE(uint64_t W,uint32_t offset)281 inline void fixWord64BE(uint64_t W, uint32_t offset) { 282 Data[offset] = (uint8_t)(W >> 56); 283 Data[++offset] = (uint8_t)(W >> 48); 284 Data[++offset] = (uint8_t)(W >> 40); 285 Data[++offset] = (uint8_t)(W >> 32); 286 Data[++offset] = (uint8_t)(W >> 24); 287 Data[++offset] = (uint8_t)(W >> 16); 288 Data[++offset] = (uint8_t)(W >> 8); 289 Data[++offset] = (uint8_t)(W >> 0); 290 } 291 292 /// emitAlignment - Pad the data to the specified alignment. 293 void emitAlignment(unsigned Alignment, uint8_t fill = 0) { 294 if (Alignment <= 1) return; 295 unsigned PadSize = -Data.size() & (Alignment-1); 296 for (unsigned i = 0; i<PadSize; ++i) 297 Data.push_back(fill); 298 } 299 300 /// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be 301 /// written to the data stream. emitULEB128Bytes(uint64_t Value)302 void emitULEB128Bytes(uint64_t Value) { 303 do { 304 uint8_t Byte = (uint8_t)(Value & 0x7f); 305 Value >>= 7; 306 if (Value) Byte |= 0x80; 307 emitByte(Byte); 308 } while (Value); 309 } 310 311 /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be 312 /// written to the data stream. emitSLEB128Bytes(int64_t Value)313 void emitSLEB128Bytes(int64_t Value) { 314 int Sign = Value >> (8 * sizeof(Value) - 1); 315 bool IsMore; 316 317 do { 318 uint8_t Byte = (uint8_t)(Value & 0x7f); 319 Value >>= 7; 320 IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; 321 if (IsMore) Byte |= 0x80; 322 emitByte(Byte); 323 } while (IsMore); 324 } 325 326 /// emitString - This callback is invoked when a String needs to be 327 /// written to the data stream. emitString(const std::string & String)328 void emitString(const std::string &String) { 329 for (unsigned i = 0, N = static_cast<unsigned>(String.size()); i<N; ++i) { 330 unsigned char C = String[i]; 331 emitByte(C); 332 } 333 emitByte(0); 334 } 335 336 /// getCurrentPCOffset - Return the offset from the start of the emitted 337 /// buffer that we are currently writing to. getCurrentPCOffset()338 uintptr_t getCurrentPCOffset() const { 339 return Data.size(); 340 } 341 342 /// addRelocation - Whenever a relocatable address is needed, it should be 343 /// noted with this interface. addRelocation(const MachineRelocation & relocation)344 void addRelocation(const MachineRelocation& relocation) { 345 Relocations.push_back(relocation); 346 } 347 348 }; 349 350 } // end namespace llvm 351 352 #endif 353 354