blob: 6b98e99e28e06face9cbef5997206ee4d9e5a5a5 [file] [log] [blame]
//=== 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