LLVM API Documentation
00001 //=== OutputBuffer.h - Output Buffer ----------------------------*- 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 // Methods to output values to a data buffer. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_SUPPORT_OUTPUTBUFFER_H 00015 #define LLVM_SUPPORT_OUTPUTBUFFER_H 00016 00017 #include <cassert> 00018 #include <string> 00019 #include <vector> 00020 00021 namespace llvm { 00022 00023 class OutputBuffer { 00024 /// Output buffer. 00025 std::vector<unsigned char> &Output; 00026 00027 /// is64Bit/isLittleEndian - This information is inferred from the target 00028 /// machine directly, indicating what header values and flags to set. 00029 bool is64Bit, isLittleEndian; 00030 public: 00031 OutputBuffer(std::vector<unsigned char> &Out, 00032 bool is64bit, bool le) 00033 : Output(Out), is64Bit(is64bit), isLittleEndian(le) {} 00034 00035 // align - Emit padding into the file until the current output position is 00036 // aligned to the specified power of two boundary. 00037 void align(unsigned Boundary) { 00038 assert(Boundary && (Boundary & (Boundary - 1)) == 0 && 00039 "Must align to 2^k boundary"); 00040 size_t Size = Output.size(); 00041 00042 if (Size & (Boundary - 1)) { 00043 // Add padding to get alignment to the correct place. 00044 size_t Pad = Boundary - (Size & (Boundary - 1)); 00045 Output.resize(Size + Pad); 00046 } 00047 } 00048 00049 //===------------------------------------------------------------------===// 00050 // Out Functions - Output the specified value to the data buffer. 00051 00052 void outbyte(unsigned char X) { 00053 Output.push_back(X); 00054 } 00055 void outhalf(unsigned short X) { 00056 if (isLittleEndian) { 00057 Output.push_back(X & 255); 00058 Output.push_back(X >> 8); 00059 } else { 00060 Output.push_back(X >> 8); 00061 Output.push_back(X & 255); 00062 } 00063 } 00064 void outword(unsigned X) { 00065 if (isLittleEndian) { 00066 Output.push_back((X >> 0) & 255); 00067 Output.push_back((X >> 8) & 255); 00068 Output.push_back((X >> 16) & 255); 00069 Output.push_back((X >> 24) & 255); 00070 } else { 00071 Output.push_back((X >> 24) & 255); 00072 Output.push_back((X >> 16) & 255); 00073 Output.push_back((X >> 8) & 255); 00074 Output.push_back((X >> 0) & 255); 00075 } 00076 } 00077 void outxword(uint64_t X) { 00078 if (isLittleEndian) { 00079 Output.push_back(unsigned(X >> 0) & 255); 00080 Output.push_back(unsigned(X >> 8) & 255); 00081 Output.push_back(unsigned(X >> 16) & 255); 00082 Output.push_back(unsigned(X >> 24) & 255); 00083 Output.push_back(unsigned(X >> 32) & 255); 00084 Output.push_back(unsigned(X >> 40) & 255); 00085 Output.push_back(unsigned(X >> 48) & 255); 00086 Output.push_back(unsigned(X >> 56) & 255); 00087 } else { 00088 Output.push_back(unsigned(X >> 56) & 255); 00089 Output.push_back(unsigned(X >> 48) & 255); 00090 Output.push_back(unsigned(X >> 40) & 255); 00091 Output.push_back(unsigned(X >> 32) & 255); 00092 Output.push_back(unsigned(X >> 24) & 255); 00093 Output.push_back(unsigned(X >> 16) & 255); 00094 Output.push_back(unsigned(X >> 8) & 255); 00095 Output.push_back(unsigned(X >> 0) & 255); 00096 } 00097 } 00098 void outaddr32(unsigned X) { 00099 outword(X); 00100 } 00101 void outaddr64(uint64_t X) { 00102 outxword(X); 00103 } 00104 void outaddr(uint64_t X) { 00105 if (!is64Bit) 00106 outword((unsigned)X); 00107 else 00108 outxword(X); 00109 } 00110 void outstring(const std::string &S, unsigned Length) { 00111 unsigned len_to_copy = static_cast<unsigned>(S.length()) < Length 00112 ? static_cast<unsigned>(S.length()) : Length; 00113 unsigned len_to_fill = static_cast<unsigned>(S.length()) < Length 00114 ? Length - static_cast<unsigned>(S.length()) : 0; 00115 00116 for (unsigned i = 0; i < len_to_copy; ++i) 00117 outbyte(S[i]); 00118 00119 for (unsigned i = 0; i < len_to_fill; ++i) 00120 outbyte(0); 00121 } 00122 00123 //===------------------------------------------------------------------===// 00124 // Fix Functions - Replace an existing entry at an offset. 00125 00126 void fixhalf(unsigned short X, unsigned Offset) { 00127 unsigned char *P = &Output[Offset]; 00128 P[0] = (X >> (isLittleEndian ? 0 : 8)) & 255; 00129 P[1] = (X >> (isLittleEndian ? 8 : 0)) & 255; 00130 } 00131 void fixword(unsigned X, unsigned Offset) { 00132 unsigned char *P = &Output[Offset]; 00133 P[0] = (X >> (isLittleEndian ? 0 : 24)) & 255; 00134 P[1] = (X >> (isLittleEndian ? 8 : 16)) & 255; 00135 P[2] = (X >> (isLittleEndian ? 16 : 8)) & 255; 00136 P[3] = (X >> (isLittleEndian ? 24 : 0)) & 255; 00137 } 00138 void fixxword(uint64_t X, unsigned Offset) { 00139 unsigned char *P = &Output[Offset]; 00140 P[0] = (X >> (isLittleEndian ? 0 : 56)) & 255; 00141 P[1] = (X >> (isLittleEndian ? 8 : 48)) & 255; 00142 P[2] = (X >> (isLittleEndian ? 16 : 40)) & 255; 00143 P[3] = (X >> (isLittleEndian ? 24 : 32)) & 255; 00144 P[4] = (X >> (isLittleEndian ? 32 : 24)) & 255; 00145 P[5] = (X >> (isLittleEndian ? 40 : 16)) & 255; 00146 P[6] = (X >> (isLittleEndian ? 48 : 8)) & 255; 00147 P[7] = (X >> (isLittleEndian ? 56 : 0)) & 255; 00148 } 00149 void fixaddr(uint64_t X, unsigned Offset) { 00150 if (!is64Bit) 00151 fixword((unsigned)X, Offset); 00152 else 00153 fixxword(X, Offset); 00154 } 00155 00156 unsigned char &operator[](unsigned Index) { 00157 return Output[Index]; 00158 } 00159 const unsigned char &operator[](unsigned Index) const { 00160 return Output[Index]; 00161 } 00162 }; 00163 00164 } // end llvm namespace 00165 00166 #endif // LLVM_SUPPORT_OUTPUTBUFFER_H