1 //===-- llvm/Bytecode/Primitives.h - Bytecode file format prims --*- C++ -*--=//
3 // This header defines some basic functions for reading and writing basic
4 // primitive types to a bytecode stream.
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.
10 //===----------------------------------------------------------------------===//
12 #ifndef LLVM_BYTECODE_PRIMITIVES_H
13 #define LLVM_BYTECODE_PRIMITIVES_H
15 #include "Support/DataTypes.h"
19 //===----------------------------------------------------------------------===//
21 //===----------------------------------------------------------------------===//
23 static inline bool read(const unsigned char *&Buf, const unsigned char *EndBuf,
25 if (Buf+4 > EndBuf) return true;
27 Result = *(unsigned*)Buf;
29 Result = Buf[0] | (Buf[1] << 8) | (Buf[2] << 16) | (Buf[3] << 24);
35 static inline bool read(const unsigned char *&Buf, const unsigned char *EndBuf,
37 if (Buf+8 > EndBuf) return true;
40 Result = *(uint64_t*)Buf;
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);
49 static inline bool read(const unsigned char *&Buf, const unsigned char *EndBuf,
51 return read(Buf, EndBuf, (unsigned &)Result);
54 static inline bool read(const unsigned char *&Buf, const unsigned char *EndBuf,
56 return read(Buf, EndBuf, (uint64_t &)Result);
60 // read_vbr - Read an unsigned integer encoded in variable bitrate format.
62 static inline bool read_vbr(const unsigned char *&Buf,
63 const unsigned char *EndBuf, unsigned &Result) {
64 unsigned Shift = Result = 0;
67 Result |= (unsigned)((*Buf++) & 0x7F) << Shift;
69 } while (Buf[-1] & 0x80 && Buf < EndBuf);
74 static inline bool read_vbr(const unsigned char *&Buf,
75 const unsigned char *EndBuf, uint64_t &Result) {
76 unsigned Shift = 0; Result = 0;
79 Result |= (uint64_t)((*Buf++) & 0x7F) << Shift;
81 } while (Buf[-1] & 0x80 && Buf < EndBuf);
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) {
89 if (read_vbr(Buf, EndBuf, R)) return true;
91 Result = -(int)(R >> 1);
93 Result = (int)(R >> 1);
99 static inline bool read_vbr(const unsigned char *&Buf,
100 const unsigned char *EndBuf, int64_t &Result) {
102 if (read_vbr(Buf, EndBuf, R)) return true;
104 Result = -(int64_t)(R >> 1);
106 Result = (int64_t)(R >> 1);
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));
118 static inline bool read(const unsigned char *&Buf, const unsigned char *EndBuf,
119 std::string &Result, bool Aligned = true) {
121 if (read_vbr(Buf, EndBuf, Size)) return true; // Failure reading size?
122 if (Buf+Size > EndBuf) return true; // Size invalid?
124 Result = std::string((char*)Buf, Size);
127 if (Aligned) // If we should stay aligned do so...
128 if (align32(Buf, EndBuf)) return true; // Failure aligning?
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;
140 std::copy(Buf, Buf+Amount, Start);
143 unsigned char *E = (unsigned char *)End;
148 if (Align) return align32(Buf, EndBuf);
152 //===----------------------------------------------------------------------===//
153 // Writing Primitives
154 //===----------------------------------------------------------------------===//
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...
160 static inline void output(unsigned i, std::deque<unsigned char> &Out,
164 Out.insert(Out.end(), (unsigned char*)&i, (unsigned char*)&i+4);
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);
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));
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);
183 static inline void output(int i, std::deque<unsigned char> &Out) {
184 output((unsigned)i, Out);
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...
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...
194 // Note that using this may cause the output buffer to become unaligned...
196 static inline void output_vbr(uint64_t i, std::deque<unsigned char> &out) {
198 if (i < 0x80) { // done?
199 out.push_back((unsigned char)i); // We know the high bit is clear...
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...
210 static inline void output_vbr(unsigned i, std::deque<unsigned char> &out) {
212 if (i < 0x80) { // done?
213 out.push_back((unsigned char)i); // We know the high bit is clear...
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...
224 static inline void output_vbr(int64_t i, std::deque<unsigned char> &out) {
226 output_vbr(((uint64_t)(-i) << 1) | 1, out); // Set low order sign bit...
228 output_vbr((uint64_t)i << 1, out); // Low order bit is clear.
232 static inline void output_vbr(int i, std::deque<unsigned char> &out) {
234 output_vbr(((unsigned)(-i) << 1) | 1, out); // Set low order sign bit...
236 output_vbr((unsigned)i << 1, out); // Low order bit is clear.
239 // align32 - emit the minimal number of bytes that will bring us to 32 bit
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);
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());
254 align32(Out); // Make sure we are now aligned...
257 static inline void output_data(void *Ptr, void *End,
258 std::deque<unsigned char> &Out,
259 bool Align = false) {
261 Out.insert(Out.end(), (unsigned char*)Ptr, (unsigned char*)End);
263 unsigned char *E = (unsigned char *)End;
268 if (Align) align32(Out);