d687fb8185953ff3fdeaf8e4d7bde3f64c5ead43
[oota-llvm.git] / include / llvm / Bytecode / Primitives.h
1 //===-- llvm/Bytecode/Primitives.h - Bytecode file format prims --*- C++ -*--=//
2 //
3 // This header defines some basic functions for reading and writing basic 
4 // primitive types to a bytecode stream.
5 //
6 // Using the routines defined in this file does not require linking to any 
7 // libraries, as all of the services are small self contained units that are to
8 // be inlined as neccesary.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #ifndef LLVM_BYTECODE_PRIMITIVES_H
13 #define LLVM_BYTECODE_PRIMITIVES_H
14
15 #include "llvm/Support/DataTypes.h"
16 #include <string>
17 #include <vector>
18
19 //===----------------------------------------------------------------------===//
20 //                             Reading Primitives
21 //===----------------------------------------------------------------------===//
22
23 static inline bool read(const unsigned char *&Buf, const unsigned char *EndBuf,
24                         unsigned &Result) {
25   if (Buf+4 > EndBuf) return true;
26 #ifdef LITTLE_ENDIAN
27   Result = *(unsigned*)Buf;
28 #else
29   Result = Buf[0] | (Buf[1] << 8) | (Buf[2] << 16) | (Buf[3] << 24);
30 #endif
31   Buf += 4;
32   return false;
33 }
34
35 static inline bool read(const unsigned char *&Buf, const unsigned char *EndBuf,
36                         uint64_t &Result) {
37   if (Buf+8 > EndBuf) return true;
38
39 #ifdef LITTLE_ENDIAN
40   Result = *(uint64_t*)Buf;
41 #else
42   Result = Buf[0] | (Buf[1] << 8) | (Buf[2] << 16) | (Buf[3] << 24) |
43     ((uint64_t)(Buf[4] | (Buf[5] << 8) | (Buf[6] << 16) | (Buf[7] << 24)) <<32);
44 #endif
45   Buf += 8;
46   return false;
47 }
48
49 static inline bool read(const unsigned char *&Buf, const unsigned char *EndBuf,
50                         int &Result) {
51   return read(Buf, EndBuf, (unsigned &)Result);
52 }
53
54 static inline bool read(const unsigned char *&Buf, const unsigned char *EndBuf,
55                         int64_t &Result) {
56   return read(Buf, EndBuf, (uint64_t &)Result);
57 }
58
59
60 // read_vbr - Read an unsigned integer encoded in variable bitrate format.
61 //
62 static inline bool read_vbr(const unsigned char *&Buf, 
63                             const unsigned char *EndBuf, unsigned &Result) {
64   unsigned Shift = Result = 0;
65
66   do {
67     Result |= (unsigned)((*Buf++) & 0x7F) << Shift;
68     Shift += 7;
69   } while (Buf[-1] & 0x80 && Buf < EndBuf);
70
71   return Buf > EndBuf;
72 }
73
74 static inline bool read_vbr(const unsigned char *&Buf, 
75                             const unsigned char *EndBuf, uint64_t &Result) {
76   unsigned Shift = 0; Result = 0;
77
78   do {
79     Result |= (uint64_t)((*Buf++) & 0x7F) << Shift;
80     Shift += 7;
81   } while (Buf[-1] & 0x80 && Buf < EndBuf);
82   return Buf > EndBuf;
83 }
84
85 // read_vbr (signed) - Read a signed number stored in sign-magnitude format
86 static inline bool read_vbr(const unsigned char *&Buf, 
87                             const unsigned char *EndBuf, int &Result) {
88   unsigned R;
89   if (read_vbr(Buf, EndBuf, R)) return true;
90   if (R & 1)
91     Result = -(int)(R >> 1);
92   else
93     Result =  (int)(R >> 1);
94   
95   return false;
96 }
97
98
99 static inline bool read_vbr(const unsigned char *&Buf, 
100                             const unsigned char *EndBuf, int64_t &Result) {
101   uint64_t R;
102   if (read_vbr(Buf, EndBuf, R)) return true;
103   if (R & 1)
104     Result = -(int64_t)(R >> 1);
105   else
106     Result =  (int64_t)(R >> 1);
107   
108   return false;
109 }
110
111 // align32 - Round up to multiple of 32 bits...
112 static inline bool align32(const unsigned char *&Buf, 
113                            const unsigned char *EndBuf) {
114   Buf = (const unsigned char *)((unsigned long)(Buf+3) & (~3UL));
115   return Buf > EndBuf;
116 }
117
118 static inline bool read(const unsigned char *&Buf, const unsigned char *EndBuf, 
119                         string &Result, bool Aligned = true) {
120   unsigned Size;
121   if (read_vbr(Buf, EndBuf, Size)) return true;   // Failure reading size?
122   if (Buf+Size > EndBuf) return true;             // Size invalid?
123
124   Result = string((char*)Buf, Size);
125   Buf += Size;
126
127   if (Aligned)        // If we should stay aligned do so...
128     if (align32(Buf, EndBuf)) return true;        // Failure aligning?
129
130   return false;
131 }
132
133 static inline bool input_data(const unsigned char *&Buf,
134                               const unsigned char *EndBuf, 
135                               void *Ptr, void *End, bool Align = false) {
136   unsigned char *Start = (unsigned char *)Ptr;
137   unsigned Amount = (unsigned char *)End - Start;
138   if (Buf+Amount > EndBuf) return true;
139 #ifdef LITTLE_ENDIAN
140   copy(Buf, Buf+Amount, Start);
141   Buf += Amount;
142 #else
143   unsigned char *E = (unsigned char *)End;
144   while (Ptr != E)
145     *--E = *Buf++;
146 #endif
147
148   if (Align) return align32(Buf, EndBuf);
149   return false;
150 }
151
152 //===----------------------------------------------------------------------===//
153 //                             Writing Primitives
154 //===----------------------------------------------------------------------===//
155
156 // output - If a position is specified, it must be in the valid portion of the
157 // string... note that this should be inlined always so only the relevant IF 
158 // body should be included...
159 //
160 static inline void output(unsigned i, vector<unsigned char> &Out, int pos = -1){
161 #ifdef LITTLE_ENDIAN
162   if (pos == -1) 
163     Out.insert(Out.end(), (unsigned char*)&i, (unsigned char*)&i+4);
164   else
165     *(unsigned*)&Out[pos] = i;
166 #else
167   if (pos == -1) { // Be endian clean, little endian is our friend
168     Out.push_back((unsigned char)i); 
169     Out.push_back((unsigned char)(i >> 8));
170     Out.push_back((unsigned char)(i >> 16));
171     Out.push_back((unsigned char)(i >> 24));
172   } else {
173     Out[pos  ] = (unsigned char)i;
174     Out[pos+1] = (unsigned char)(i >> 8);
175     Out[pos+2] = (unsigned char)(i >> 16);
176     Out[pos+3] = (unsigned char)(i >> 24);
177   }
178 #endif
179 }
180
181 static inline void output(int i, vector<unsigned char> &Out) {
182   output((unsigned)i, Out);
183 }
184
185 // output_vbr - Output an unsigned value, by using the least number of bytes
186 // possible.  This is useful because many of our "infinite" values are really
187 // very small most of the time... but can be large a few times...
188 //
189 // Data format used:  If you read a byte with the night bit set, use the low 
190 // seven bits as data and then read another byte...
191 //
192 // Note that using this may cause the output buffer to become unaligned...
193 //
194 static inline void output_vbr(uint64_t i, vector<unsigned char> &out) {
195   while (1) {
196     if (i < 0x80) { // done?
197       out.push_back((unsigned char)i);   // We know the high bit is clear...
198       return;
199     }
200     
201     // Nope, we are bigger than a character, output the next 7 bits and set the
202     // high bit to say that there is more coming...
203     out.push_back(0x80 | (i & 0x7F));
204     i >>= 7;  // Shift out 7 bits now...
205   }
206 }
207
208 static inline void output_vbr(unsigned i, vector<unsigned char> &out) {
209   while (1) {
210     if (i < 0x80) { // done?
211       out.push_back((unsigned char)i);   // We know the high bit is clear...
212       return;
213     }
214     
215     // Nope, we are bigger than a character, output the next 7 bits and set the
216     // high bit to say that there is more coming...
217     out.push_back(0x80 | (i & 0x7F));
218     i >>= 7;  // Shift out 7 bits now...
219   }
220 }
221
222 static inline void output_vbr(int64_t i, vector<unsigned char> &out) {
223   if (i < 0) 
224     output_vbr(((uint64_t)(-i) << 1) | 1, out); // Set low order sign bit...
225   else
226     output_vbr((uint64_t)i << 1, out);          // Low order bit is clear.
227 }
228
229
230 static inline void output_vbr(int i, vector<unsigned char> &out) {
231   if (i < 0) 
232     output_vbr(((unsigned)(-i) << 1) | 1, out); // Set low order sign bit...
233   else
234     output_vbr((unsigned)i << 1, out);          // Low order bit is clear.
235 }
236
237 // align32 - emit the minimal number of bytes that will bring us to 32 bit 
238 // alignment...
239 //
240 static inline void align32(vector<unsigned char> &Out) {
241   int NumPads = (4-(Out.size() & 3)) & 3; // Bytes to get padding to 32 bits
242   while (NumPads--) Out.push_back((unsigned char)0xAB);
243 }
244
245 static inline void output(const string &s, vector<unsigned char> &Out, 
246                           bool Aligned = true) {
247   unsigned Len = s.length();
248   output_vbr(Len, Out);             // Strings may have an arbitrary length...
249   Out.insert(Out.end(), s.begin(), s.end());
250
251   if (Aligned)
252     align32(Out);                   // Make sure we are now aligned...
253 }
254
255 static inline void output_data(void *Ptr, void *End,
256                                vector<unsigned char> &Out, bool Align = false) {
257 #ifdef LITTLE_ENDIAN
258   Out.insert(Out.end(), (unsigned char*)Ptr, (unsigned char*)End);
259 #else
260   unsigned char *E = (unsigned char *)End;
261   while (Ptr != E)
262     Out.push_back(*--E);
263 #endif
264
265   if (Align) align32(Out);
266 }
267
268 #endif