1 //=== OutputBuffer.h - Output Buffer ----------------------------*- 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 // Methods to output values to a data buffer. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_SUPPORT_OUTPUTBUFFER_H 15 #define LLVM_SUPPORT_OUTPUTBUFFER_H 16 17 #include <cassert> 18 #include <string> 19 #include <vector> 20 21 namespace llvm { 22 23 class OutputBuffer { 24 /// Output buffer. 25 std::vector<unsigned char> &Output; 26 27 /// is64Bit/isLittleEndian - This information is inferred from the target 28 /// machine directly, indicating what header values and flags to set. 29 bool is64Bit, isLittleEndian; 30 public: OutputBuffer(std::vector<unsigned char> & Out,bool is64bit,bool le)31 OutputBuffer(std::vector<unsigned char> &Out, 32 bool is64bit, bool le) 33 : Output(Out), is64Bit(is64bit), isLittleEndian(le) {} 34 35 // align - Emit padding into the file until the current output position is 36 // aligned to the specified power of two boundary. align(unsigned Boundary)37 void align(unsigned Boundary) { 38 assert(Boundary && (Boundary & (Boundary - 1)) == 0 && 39 "Must align to 2^k boundary"); 40 size_t Size = Output.size(); 41 42 if (Size & (Boundary - 1)) { 43 // Add padding to get alignment to the correct place. 44 size_t Pad = Boundary - (Size & (Boundary - 1)); 45 Output.resize(Size + Pad); 46 } 47 } 48 49 //===------------------------------------------------------------------===// 50 // Out Functions - Output the specified value to the data buffer. 51 outbyte(unsigned char X)52 void outbyte(unsigned char X) { 53 Output.push_back(X); 54 } outhalf(unsigned short X)55 void outhalf(unsigned short X) { 56 if (isLittleEndian) { 57 Output.push_back(X & 255); 58 Output.push_back(X >> 8); 59 } else { 60 Output.push_back(X >> 8); 61 Output.push_back(X & 255); 62 } 63 } outword(unsigned X)64 void outword(unsigned X) { 65 if (isLittleEndian) { 66 Output.push_back((X >> 0) & 255); 67 Output.push_back((X >> 8) & 255); 68 Output.push_back((X >> 16) & 255); 69 Output.push_back((X >> 24) & 255); 70 } else { 71 Output.push_back((X >> 24) & 255); 72 Output.push_back((X >> 16) & 255); 73 Output.push_back((X >> 8) & 255); 74 Output.push_back((X >> 0) & 255); 75 } 76 } outxword(uint64_t X)77 void outxword(uint64_t X) { 78 if (isLittleEndian) { 79 Output.push_back(unsigned(X >> 0) & 255); 80 Output.push_back(unsigned(X >> 8) & 255); 81 Output.push_back(unsigned(X >> 16) & 255); 82 Output.push_back(unsigned(X >> 24) & 255); 83 Output.push_back(unsigned(X >> 32) & 255); 84 Output.push_back(unsigned(X >> 40) & 255); 85 Output.push_back(unsigned(X >> 48) & 255); 86 Output.push_back(unsigned(X >> 56) & 255); 87 } else { 88 Output.push_back(unsigned(X >> 56) & 255); 89 Output.push_back(unsigned(X >> 48) & 255); 90 Output.push_back(unsigned(X >> 40) & 255); 91 Output.push_back(unsigned(X >> 32) & 255); 92 Output.push_back(unsigned(X >> 24) & 255); 93 Output.push_back(unsigned(X >> 16) & 255); 94 Output.push_back(unsigned(X >> 8) & 255); 95 Output.push_back(unsigned(X >> 0) & 255); 96 } 97 } outaddr32(unsigned X)98 void outaddr32(unsigned X) { 99 outword(X); 100 } outaddr64(uint64_t X)101 void outaddr64(uint64_t X) { 102 outxword(X); 103 } outaddr(uint64_t X)104 void outaddr(uint64_t X) { 105 if (!is64Bit) 106 outword((unsigned)X); 107 else 108 outxword(X); 109 } outstring(const std::string & S,unsigned Length)110 void outstring(const std::string &S, unsigned Length) { 111 unsigned len_to_copy = static_cast<unsigned>(S.length()) < Length 112 ? static_cast<unsigned>(S.length()) : Length; 113 unsigned len_to_fill = static_cast<unsigned>(S.length()) < Length 114 ? Length - static_cast<unsigned>(S.length()) : 0; 115 116 for (unsigned i = 0; i < len_to_copy; ++i) 117 outbyte(S[i]); 118 119 for (unsigned i = 0; i < len_to_fill; ++i) 120 outbyte(0); 121 } 122 123 //===------------------------------------------------------------------===// 124 // Fix Functions - Replace an existing entry at an offset. 125 fixhalf(unsigned short X,unsigned Offset)126 void fixhalf(unsigned short X, unsigned Offset) { 127 unsigned char *P = &Output[Offset]; 128 P[0] = (X >> (isLittleEndian ? 0 : 8)) & 255; 129 P[1] = (X >> (isLittleEndian ? 8 : 0)) & 255; 130 } fixword(unsigned X,unsigned Offset)131 void fixword(unsigned X, unsigned Offset) { 132 unsigned char *P = &Output[Offset]; 133 P[0] = (X >> (isLittleEndian ? 0 : 24)) & 255; 134 P[1] = (X >> (isLittleEndian ? 8 : 16)) & 255; 135 P[2] = (X >> (isLittleEndian ? 16 : 8)) & 255; 136 P[3] = (X >> (isLittleEndian ? 24 : 0)) & 255; 137 } fixxword(uint64_t X,unsigned Offset)138 void fixxword(uint64_t X, unsigned Offset) { 139 unsigned char *P = &Output[Offset]; 140 P[0] = (X >> (isLittleEndian ? 0 : 56)) & 255; 141 P[1] = (X >> (isLittleEndian ? 8 : 48)) & 255; 142 P[2] = (X >> (isLittleEndian ? 16 : 40)) & 255; 143 P[3] = (X >> (isLittleEndian ? 24 : 32)) & 255; 144 P[4] = (X >> (isLittleEndian ? 32 : 24)) & 255; 145 P[5] = (X >> (isLittleEndian ? 40 : 16)) & 255; 146 P[6] = (X >> (isLittleEndian ? 48 : 8)) & 255; 147 P[7] = (X >> (isLittleEndian ? 56 : 0)) & 255; 148 } fixaddr(uint64_t X,unsigned Offset)149 void fixaddr(uint64_t X, unsigned Offset) { 150 if (!is64Bit) 151 fixword((unsigned)X, Offset); 152 else 153 fixxword(X, Offset); 154 } 155 156 unsigned char &operator[](unsigned Index) { 157 return Output[Index]; 158 } 159 const unsigned char &operator[](unsigned Index) const { 160 return Output[Index]; 161 } 162 }; 163 164 } // end llvm namespace 165 166 #endif // LLVM_SUPPORT_OUTPUTBUFFER_H 167