Refactored output buffer methods from MachO and ELF writers.
[oota-llvm.git] / include / llvm / Support / OutputBuffer.h
1 //=== OutputBuffer.h - Output Buffer ----------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Bill Wendling and is distributed under the
6 // University of Illinois Open Source 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 <vector>
18
19 namespace llvm {
20   
21   class OutputBuffer {
22     /// Output buffer.
23     std::vector<unsigned char> &Output;
24
25     /// is64Bit/isLittleEndian - This information is inferred from the target
26     /// machine directly, indicating what header values and flags to set.
27     bool is64Bit, isLittleEndian;
28   public:
29     OutputBuffer(const TargetMachine& TM,
30                  std::vector<unsigned char> &Out) : Output(Out) {
31       is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64;
32       isLittleEndian = TM.getTargetData()->isLittleEndian();
33     }
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 alitypedef std::vector<unsigned char> DataBuffer;gn 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(std::string &S, unsigned Length) {
111       unsigned len_to_copy = S.length() < Length ? S.length() : Length;
112       unsigned len_to_fill = S.length() < Length ? Length - S.length() : 0;
113       
114       for (unsigned i = 0; i < len_to_copy; ++i)
115         outbyte(S[i]);
116       
117       for (unsigned i = 0; i < len_to_fill; ++i)
118         outbyte(0);
119     }
120
121     //===------------------------------------------------------------------===//
122     // Fix Functions - Replace an existing entry at an offset.
123
124     void fixhalf(unsigned short X, unsigned Offset) {
125       unsigned char *P = &Output[Offset];
126       P[0] = (X >> (isLittleEndian ?  0 : 8)) & 255;
127       P[1] = (X >> (isLittleEndian ?  8 : 0)) & 255;
128     }
129     void fixword(unsigned X, unsigned Offset) {
130       unsigned char *P = &Output[Offset];
131       P[0] = (X >> (isLittleEndian ?  0 : 24)) & 255;
132       P[1] = (X >> (isLittleEndian ?  8 : 16)) & 255;
133       P[2] = (X >> (isLittleEndian ? 16 :  8)) & 255;
134       P[3] = (X >> (isLittleEndian ? 24 :  0)) & 255;
135     }
136     void fixaddr(uint64_t X, unsigned Offset) {
137       if (!is64Bit)
138         fixword((unsigned)X, Offset);
139       else
140         assert(0 && "Emission of 64-bit data not implemented yet!");
141     }
142   };
143   
144 } // end llvm namespace
145
146 #endif // LLVM_SUPPORT_OUTPUTBUFFER_H