| //=== OutputBuffer.h - Output Buffer ----------------------------*- C++ -*-===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // Methods to output values to a data buffer. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #ifndef LLVM_SUPPORT_OUTPUTBUFFER_H | |
| #define LLVM_SUPPORT_OUTPUTBUFFER_H | |
| #include <cassert> | |
| #include <string> | |
| #include <vector> | |
| namespace llvm { | |
| class OutputBuffer { | |
| /// Output buffer. | |
| std::vector<unsigned char> &Output; | |
| /// is64Bit/isLittleEndian - This information is inferred from the target | |
| /// machine directly, indicating what header values and flags to set. | |
| bool is64Bit, isLittleEndian; | |
| public: | |
| OutputBuffer(std::vector<unsigned char> &Out, | |
| bool is64bit, bool le) | |
| : Output(Out), is64Bit(is64bit), isLittleEndian(le) {} | |
| // align - Emit padding into the file until the current output position is | |
| // aligned to the specified power of two boundary. | |
| void align(unsigned Boundary) { | |
| assert(Boundary && (Boundary & (Boundary - 1)) == 0 && | |
| "Must align to 2^k boundary"); | |
| size_t Size = Output.size(); | |
| if (Size & (Boundary - 1)) { | |
| // Add padding to get alignment to the correct place. | |
| size_t Pad = Boundary - (Size & (Boundary - 1)); | |
| Output.resize(Size + Pad); | |
| } | |
| } | |
| //===------------------------------------------------------------------===// | |
| // Out Functions - Output the specified value to the data buffer. | |
| void outbyte(unsigned char X) { | |
| Output.push_back(X); | |
| } | |
| void outhalf(unsigned short X) { | |
| if (isLittleEndian) { | |
| Output.push_back(X & 255); | |
| Output.push_back(X >> 8); | |
| } else { | |
| Output.push_back(X >> 8); | |
| Output.push_back(X & 255); | |
| } | |
| } | |
| void outword(unsigned X) { | |
| if (isLittleEndian) { | |
| Output.push_back((X >> 0) & 255); | |
| Output.push_back((X >> 8) & 255); | |
| Output.push_back((X >> 16) & 255); | |
| Output.push_back((X >> 24) & 255); | |
| } else { | |
| Output.push_back((X >> 24) & 255); | |
| Output.push_back((X >> 16) & 255); | |
| Output.push_back((X >> 8) & 255); | |
| Output.push_back((X >> 0) & 255); | |
| } | |
| } | |
| void outxword(uint64_t X) { | |
| if (isLittleEndian) { | |
| Output.push_back(unsigned(X >> 0) & 255); | |
| Output.push_back(unsigned(X >> 8) & 255); | |
| Output.push_back(unsigned(X >> 16) & 255); | |
| Output.push_back(unsigned(X >> 24) & 255); | |
| Output.push_back(unsigned(X >> 32) & 255); | |
| Output.push_back(unsigned(X >> 40) & 255); | |
| Output.push_back(unsigned(X >> 48) & 255); | |
| Output.push_back(unsigned(X >> 56) & 255); | |
| } else { | |
| Output.push_back(unsigned(X >> 56) & 255); | |
| Output.push_back(unsigned(X >> 48) & 255); | |
| Output.push_back(unsigned(X >> 40) & 255); | |
| Output.push_back(unsigned(X >> 32) & 255); | |
| Output.push_back(unsigned(X >> 24) & 255); | |
| Output.push_back(unsigned(X >> 16) & 255); | |
| Output.push_back(unsigned(X >> 8) & 255); | |
| Output.push_back(unsigned(X >> 0) & 255); | |
| } | |
| } | |
| void outaddr32(unsigned X) { | |
| outword(X); | |
| } | |
| void outaddr64(uint64_t X) { | |
| outxword(X); | |
| } | |
| void outaddr(uint64_t X) { | |
| if (!is64Bit) | |
| outword((unsigned)X); | |
| else | |
| outxword(X); | |
| } | |
| void outstring(const std::string &S, unsigned Length) { | |
| unsigned len_to_copy = static_cast<unsigned>(S.length()) < Length | |
| ? static_cast<unsigned>(S.length()) : Length; | |
| unsigned len_to_fill = static_cast<unsigned>(S.length()) < Length | |
| ? Length - static_cast<unsigned>(S.length()) : 0; | |
| for (unsigned i = 0; i < len_to_copy; ++i) | |
| outbyte(S[i]); | |
| for (unsigned i = 0; i < len_to_fill; ++i) | |
| outbyte(0); | |
| } | |
| //===------------------------------------------------------------------===// | |
| // Fix Functions - Replace an existing entry at an offset. | |
| void fixhalf(unsigned short X, unsigned Offset) { | |
| unsigned char *P = &Output[Offset]; | |
| P[0] = (X >> (isLittleEndian ? 0 : 8)) & 255; | |
| P[1] = (X >> (isLittleEndian ? 8 : 0)) & 255; | |
| } | |
| void fixword(unsigned X, unsigned Offset) { | |
| unsigned char *P = &Output[Offset]; | |
| P[0] = (X >> (isLittleEndian ? 0 : 24)) & 255; | |
| P[1] = (X >> (isLittleEndian ? 8 : 16)) & 255; | |
| P[2] = (X >> (isLittleEndian ? 16 : 8)) & 255; | |
| P[3] = (X >> (isLittleEndian ? 24 : 0)) & 255; | |
| } | |
| void fixxword(uint64_t X, unsigned Offset) { | |
| unsigned char *P = &Output[Offset]; | |
| P[0] = (X >> (isLittleEndian ? 0 : 56)) & 255; | |
| P[1] = (X >> (isLittleEndian ? 8 : 48)) & 255; | |
| P[2] = (X >> (isLittleEndian ? 16 : 40)) & 255; | |
| P[3] = (X >> (isLittleEndian ? 24 : 32)) & 255; | |
| P[4] = (X >> (isLittleEndian ? 32 : 24)) & 255; | |
| P[5] = (X >> (isLittleEndian ? 40 : 16)) & 255; | |
| P[6] = (X >> (isLittleEndian ? 48 : 8)) & 255; | |
| P[7] = (X >> (isLittleEndian ? 56 : 0)) & 255; | |
| } | |
| void fixaddr(uint64_t X, unsigned Offset) { | |
| if (!is64Bit) | |
| fixword((unsigned)X, Offset); | |
| else | |
| fixxword(X, Offset); | |
| } | |
| unsigned char &operator[](unsigned Index) { | |
| return Output[Index]; | |
| } | |
| const unsigned char &operator[](unsigned Index) const { | |
| return Output[Index]; | |
| } | |
| }; | |
| } // end llvm namespace | |
| #endif // LLVM_SUPPORT_OUTPUTBUFFER_H |