Changed the LITTLE_ENDIAN and BIG_ENDIAN macros to ENDIAN_LITTLE and ENDIAN_BIG.
[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 "Support/DataTypes.h"
16 #include <string>
17 #include <deque>
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 ENDIAN_LITTLE
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 ENDIAN_LITTLE
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                         std::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 = std::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 ENDIAN_LITTLE
140   std::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, std::deque<unsigned char> &Out,
161                           int pos = -1) {
162 #ifdef ENDIAN_LITTLE
163   if (pos == -1) 
164     Out.insert(Out.end(), (unsigned char*)&i, (unsigned char*)&i+4);
165   else
166     // This cannot use block copy because deques are not guaranteed contiguous!
167     std::copy((unsigned char*)&i, 4+(unsigned char*)&i, Out.begin()+pos);
168 #else
169   if (pos == -1) { // Be endian clean, little endian is our friend
170     Out.push_back((unsigned char)i); 
171     Out.push_back((unsigned char)(i >> 8));
172     Out.push_back((unsigned char)(i >> 16));
173     Out.push_back((unsigned char)(i >> 24));
174   } else {
175     Out[pos  ] = (unsigned char)i;
176     Out[pos+1] = (unsigned char)(i >> 8);
177     Out[pos+2] = (unsigned char)(i >> 16);
178     Out[pos+3] = (unsigned char)(i >> 24);
179   }
180 #endif
181 }
182
183 static inline void output(int i, std::deque<unsigned char> &Out) {
184   output((unsigned)i, Out);
185 }
186
187 // output_vbr - Output an unsigned value, by using the least number of bytes
188 // possible.  This is useful because many of our "infinite" values are really
189 // very small most of the time... but can be large a few times...
190 //
191 // Data format used:  If you read a byte with the night bit set, use the low 
192 // seven bits as data and then read another byte...
193 //
194 // Note that using this may cause the output buffer to become unaligned...
195 //
196 static inline void output_vbr(uint64_t i, std::deque<unsigned char> &out) {
197   while (1) {
198     if (i < 0x80) { // done?
199       out.push_back((unsigned char)i);   // We know the high bit is clear...
200       return;
201     }
202     
203     // Nope, we are bigger than a character, output the next 7 bits and set the
204     // high bit to say that there is more coming...
205     out.push_back(0x80 | (i & 0x7F));
206     i >>= 7;  // Shift out 7 bits now...
207   }
208 }
209
210 static inline void output_vbr(unsigned i, std::deque<unsigned char> &out) {
211   while (1) {
212     if (i < 0x80) { // done?
213       out.push_back((unsigned char)i);   // We know the high bit is clear...
214       return;
215     }
216     
217     // Nope, we are bigger than a character, output the next 7 bits and set the
218     // high bit to say that there is more coming...
219     out.push_back(0x80 | (i & 0x7F));
220     i >>= 7;  // Shift out 7 bits now...
221   }
222 }
223
224 static inline void output_vbr(int64_t i, std::deque<unsigned char> &out) {
225   if (i < 0) 
226     output_vbr(((uint64_t)(-i) << 1) | 1, out); // Set low order sign bit...
227   else
228     output_vbr((uint64_t)i << 1, out);          // Low order bit is clear.
229 }
230
231
232 static inline void output_vbr(int i, std::deque<unsigned char> &out) {
233   if (i < 0) 
234     output_vbr(((unsigned)(-i) << 1) | 1, out); // Set low order sign bit...
235   else
236     output_vbr((unsigned)i << 1, out);          // Low order bit is clear.
237 }
238
239 // align32 - emit the minimal number of bytes that will bring us to 32 bit 
240 // alignment...
241 //
242 static inline void align32(std::deque<unsigned char> &Out) {
243   int NumPads = (4-(Out.size() & 3)) & 3; // Bytes to get padding to 32 bits
244   while (NumPads--) Out.push_back((unsigned char)0xAB);
245 }
246
247 static inline void output(const std::string &s, std::deque<unsigned char> &Out, 
248                           bool Aligned = true) {
249   unsigned Len = s.length();
250   output_vbr(Len, Out);             // Strings may have an arbitrary length...
251   Out.insert(Out.end(), s.begin(), s.end());
252
253   if (Aligned)
254     align32(Out);                   // Make sure we are now aligned...
255 }
256
257 static inline void output_data(void *Ptr, void *End,
258                                std::deque<unsigned char> &Out,
259                                bool Align = false) {
260 #ifdef ENDIAN_LITTLE
261   Out.insert(Out.end(), (unsigned char*)Ptr, (unsigned char*)End);
262 #else
263   unsigned char *E = (unsigned char *)End;
264   while (Ptr != E)
265     Out.push_back(*--E);
266 #endif
267
268   if (Align) align32(Out);
269 }
270
271 #endif