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
21namespace 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:
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.
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
52    void outbyte(unsigned char X) {
53      Output.push_back(X);
54    }
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    }
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    }
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    }
98    void outaddr32(unsigned X) {
99      outword(X);
100    }
101    void outaddr64(uint64_t X) {
102      outxword(X);
103    }
104    void outaddr(uint64_t X) {
105      if (!is64Bit)
106        outword((unsigned)X);
107      else
108        outxword(X);
109    }
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
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    }
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    }
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    }
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