1193323Sed//=== OutputBuffer.h - Output Buffer ----------------------------*- C++ -*-===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// Methods to output values to a data buffer.
11193323Sed//
12193323Sed//===----------------------------------------------------------------------===//
13193323Sed
14193323Sed#ifndef LLVM_SUPPORT_OUTPUTBUFFER_H
15193323Sed#define LLVM_SUPPORT_OUTPUTBUFFER_H
16193323Sed
17198953Srdivacky#include <cassert>
18193323Sed#include <string>
19193323Sed#include <vector>
20193323Sed
21193323Sednamespace llvm {
22193323Sed
23193323Sed  class OutputBuffer {
24193323Sed    /// Output buffer.
25193323Sed    std::vector<unsigned char> &Output;
26193323Sed
27193323Sed    /// is64Bit/isLittleEndian - This information is inferred from the target
28193323Sed    /// machine directly, indicating what header values and flags to set.
29193323Sed    bool is64Bit, isLittleEndian;
30193323Sed  public:
31193323Sed    OutputBuffer(std::vector<unsigned char> &Out,
32193323Sed                 bool is64bit, bool le)
33193323Sed      : Output(Out), is64Bit(is64bit), isLittleEndian(le) {}
34193323Sed
35193323Sed    // align - Emit padding into the file until the current output position is
36193323Sed    // aligned to the specified power of two boundary.
37193323Sed    void align(unsigned Boundary) {
38193323Sed      assert(Boundary && (Boundary & (Boundary - 1)) == 0 &&
39193323Sed             "Must align to 2^k boundary");
40193323Sed      size_t Size = Output.size();
41193323Sed
42193323Sed      if (Size & (Boundary - 1)) {
43193323Sed        // Add padding to get alignment to the correct place.
44193323Sed        size_t Pad = Boundary - (Size & (Boundary - 1));
45193323Sed        Output.resize(Size + Pad);
46193323Sed      }
47193323Sed    }
48193323Sed
49193323Sed    //===------------------------------------------------------------------===//
50193323Sed    // Out Functions - Output the specified value to the data buffer.
51193323Sed
52193323Sed    void outbyte(unsigned char X) {
53193323Sed      Output.push_back(X);
54193323Sed    }
55193323Sed    void outhalf(unsigned short X) {
56193323Sed      if (isLittleEndian) {
57193323Sed        Output.push_back(X & 255);
58193323Sed        Output.push_back(X >> 8);
59193323Sed      } else {
60193323Sed        Output.push_back(X >> 8);
61193323Sed        Output.push_back(X & 255);
62193323Sed      }
63193323Sed    }
64193323Sed    void outword(unsigned X) {
65193323Sed      if (isLittleEndian) {
66193323Sed        Output.push_back((X >>  0) & 255);
67193323Sed        Output.push_back((X >>  8) & 255);
68193323Sed        Output.push_back((X >> 16) & 255);
69193323Sed        Output.push_back((X >> 24) & 255);
70193323Sed      } else {
71193323Sed        Output.push_back((X >> 24) & 255);
72193323Sed        Output.push_back((X >> 16) & 255);
73193323Sed        Output.push_back((X >>  8) & 255);
74193323Sed        Output.push_back((X >>  0) & 255);
75193323Sed      }
76193323Sed    }
77193323Sed    void outxword(uint64_t X) {
78193323Sed      if (isLittleEndian) {
79193323Sed        Output.push_back(unsigned(X >>  0) & 255);
80193323Sed        Output.push_back(unsigned(X >>  8) & 255);
81193323Sed        Output.push_back(unsigned(X >> 16) & 255);
82193323Sed        Output.push_back(unsigned(X >> 24) & 255);
83193323Sed        Output.push_back(unsigned(X >> 32) & 255);
84193323Sed        Output.push_back(unsigned(X >> 40) & 255);
85193323Sed        Output.push_back(unsigned(X >> 48) & 255);
86193323Sed        Output.push_back(unsigned(X >> 56) & 255);
87193323Sed      } else {
88193323Sed        Output.push_back(unsigned(X >> 56) & 255);
89193323Sed        Output.push_back(unsigned(X >> 48) & 255);
90193323Sed        Output.push_back(unsigned(X >> 40) & 255);
91193323Sed        Output.push_back(unsigned(X >> 32) & 255);
92193323Sed        Output.push_back(unsigned(X >> 24) & 255);
93193323Sed        Output.push_back(unsigned(X >> 16) & 255);
94193323Sed        Output.push_back(unsigned(X >>  8) & 255);
95193323Sed        Output.push_back(unsigned(X >>  0) & 255);
96193323Sed      }
97193323Sed    }
98193323Sed    void outaddr32(unsigned X) {
99193323Sed      outword(X);
100193323Sed    }
101193323Sed    void outaddr64(uint64_t X) {
102193323Sed      outxword(X);
103193323Sed    }
104193323Sed    void outaddr(uint64_t X) {
105193323Sed      if (!is64Bit)
106193323Sed        outword((unsigned)X);
107193323Sed      else
108193323Sed        outxword(X);
109193323Sed    }
110193323Sed    void outstring(const std::string &S, unsigned Length) {
111193323Sed      unsigned len_to_copy = static_cast<unsigned>(S.length()) < Length
112193323Sed        ? static_cast<unsigned>(S.length()) : Length;
113193323Sed      unsigned len_to_fill = static_cast<unsigned>(S.length()) < Length
114193323Sed        ? Length - static_cast<unsigned>(S.length()) : 0;
115193323Sed
116193323Sed      for (unsigned i = 0; i < len_to_copy; ++i)
117193323Sed        outbyte(S[i]);
118193323Sed
119193323Sed      for (unsigned i = 0; i < len_to_fill; ++i)
120193323Sed        outbyte(0);
121193323Sed    }
122193323Sed
123193323Sed    //===------------------------------------------------------------------===//
124193323Sed    // Fix Functions - Replace an existing entry at an offset.
125193323Sed
126193323Sed    void fixhalf(unsigned short X, unsigned Offset) {
127193323Sed      unsigned char *P = &Output[Offset];
128193323Sed      P[0] = (X >> (isLittleEndian ?  0 : 8)) & 255;
129193323Sed      P[1] = (X >> (isLittleEndian ?  8 : 0)) & 255;
130193323Sed    }
131193323Sed    void fixword(unsigned X, unsigned Offset) {
132193323Sed      unsigned char *P = &Output[Offset];
133193323Sed      P[0] = (X >> (isLittleEndian ?  0 : 24)) & 255;
134193323Sed      P[1] = (X >> (isLittleEndian ?  8 : 16)) & 255;
135193323Sed      P[2] = (X >> (isLittleEndian ? 16 :  8)) & 255;
136193323Sed      P[3] = (X >> (isLittleEndian ? 24 :  0)) & 255;
137193323Sed    }
138193724Sed    void fixxword(uint64_t X, unsigned Offset) {
139193724Sed      unsigned char *P = &Output[Offset];
140193724Sed      P[0] = (X >> (isLittleEndian ?  0 : 56)) & 255;
141193724Sed      P[1] = (X >> (isLittleEndian ?  8 : 48)) & 255;
142193724Sed      P[2] = (X >> (isLittleEndian ? 16 : 40)) & 255;
143193724Sed      P[3] = (X >> (isLittleEndian ? 24 : 32)) & 255;
144193724Sed      P[4] = (X >> (isLittleEndian ? 32 : 24)) & 255;
145193724Sed      P[5] = (X >> (isLittleEndian ? 40 : 16)) & 255;
146193724Sed      P[6] = (X >> (isLittleEndian ? 48 :  8)) & 255;
147193724Sed      P[7] = (X >> (isLittleEndian ? 56 :  0)) & 255;
148193724Sed    }
149193323Sed    void fixaddr(uint64_t X, unsigned Offset) {
150193323Sed      if (!is64Bit)
151193323Sed        fixword((unsigned)X, Offset);
152193323Sed      else
153193724Sed        fixxword(X, Offset);
154193323Sed    }
155193323Sed
156193323Sed    unsigned char &operator[](unsigned Index) {
157193323Sed      return Output[Index];
158193323Sed    }
159193323Sed    const unsigned char &operator[](unsigned Index) const {
160193323Sed      return Output[Index];
161193323Sed    }
162193323Sed  };
163193323Sed
164193323Sed} // end llvm namespace
165193323Sed
166193323Sed#endif // LLVM_SUPPORT_OUTPUTBUFFER_H
167