Chris Lattner | 4443019 | 2004-01-10 18:56:59 +0000 | [diff] [blame] | 1 | //===-- WriterPrimitives.h - Bytecode writer file format prims --*- C++ -*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file was developed by the LLVM research group and is distributed under |
| 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This header defines some basic functions for writing basic primitive types to |
| 11 | // a bytecode stream. |
| 12 | // |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
| 15 | #ifndef WRITERPRIMITIVES_H |
| 16 | #define WRITERPRIMITIVES_H |
| 17 | |
| 18 | #include "Support/DataTypes.h" |
| 19 | #include <string> |
| 20 | #include <deque> |
| 21 | |
| 22 | namespace llvm { |
| 23 | |
| 24 | // output - If a position is specified, it must be in the valid portion of the |
| 25 | // string... note that this should be inlined always so only the relevant IF |
| 26 | // body should be included... |
| 27 | // |
| 28 | static inline void output(unsigned i, std::deque<unsigned char> &Out, |
| 29 | int pos = -1) { |
| 30 | #ifdef ENDIAN_LITTLE |
| 31 | if (pos == -1) |
| 32 | Out.insert(Out.end(), (unsigned char*)&i, (unsigned char*)&i+4); |
| 33 | else |
| 34 | // This cannot use block copy because deques are not guaranteed contiguous! |
| 35 | std::copy((unsigned char*)&i, 4+(unsigned char*)&i, Out.begin()+pos); |
| 36 | #else |
| 37 | if (pos == -1) { // Be endian clean, little endian is our friend |
| 38 | Out.push_back((unsigned char)i); |
| 39 | Out.push_back((unsigned char)(i >> 8)); |
| 40 | Out.push_back((unsigned char)(i >> 16)); |
| 41 | Out.push_back((unsigned char)(i >> 24)); |
| 42 | } else { |
| 43 | Out[pos ] = (unsigned char)i; |
| 44 | Out[pos+1] = (unsigned char)(i >> 8); |
| 45 | Out[pos+2] = (unsigned char)(i >> 16); |
| 46 | Out[pos+3] = (unsigned char)(i >> 24); |
| 47 | } |
| 48 | #endif |
| 49 | } |
| 50 | |
| 51 | static inline void output(int i, std::deque<unsigned char> &Out) { |
| 52 | output((unsigned)i, Out); |
| 53 | } |
| 54 | |
| 55 | // output_vbr - Output an unsigned value, by using the least number of bytes |
| 56 | // possible. This is useful because many of our "infinite" values are really |
| 57 | // very small most of the time... but can be large a few times... |
| 58 | // |
| 59 | // Data format used: If you read a byte with the night bit set, use the low |
| 60 | // seven bits as data and then read another byte... |
| 61 | // |
| 62 | // Note that using this may cause the output buffer to become unaligned... |
| 63 | // |
| 64 | static inline void output_vbr(uint64_t i, std::deque<unsigned char> &out) { |
| 65 | while (1) { |
| 66 | if (i < 0x80) { // done? |
| 67 | out.push_back((unsigned char)i); // We know the high bit is clear... |
| 68 | return; |
| 69 | } |
| 70 | |
| 71 | // Nope, we are bigger than a character, output the next 7 bits and set the |
| 72 | // high bit to say that there is more coming... |
| 73 | out.push_back(0x80 | (i & 0x7F)); |
| 74 | i >>= 7; // Shift out 7 bits now... |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | static inline void output_vbr(unsigned i, std::deque<unsigned char> &out) { |
| 79 | while (1) { |
| 80 | if (i < 0x80) { // done? |
| 81 | out.push_back((unsigned char)i); // We know the high bit is clear... |
| 82 | return; |
| 83 | } |
| 84 | |
| 85 | // Nope, we are bigger than a character, output the next 7 bits and set the |
| 86 | // high bit to say that there is more coming... |
| 87 | out.push_back(0x80 | (i & 0x7F)); |
| 88 | i >>= 7; // Shift out 7 bits now... |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | static inline void output_vbr(int64_t i, std::deque<unsigned char> &out) { |
| 93 | if (i < 0) |
| 94 | output_vbr(((uint64_t)(-i) << 1) | 1, out); // Set low order sign bit... |
| 95 | else |
| 96 | output_vbr((uint64_t)i << 1, out); // Low order bit is clear. |
| 97 | } |
| 98 | |
| 99 | |
| 100 | static inline void output_vbr(int i, std::deque<unsigned char> &out) { |
| 101 | if (i < 0) |
| 102 | output_vbr(((unsigned)(-i) << 1) | 1, out); // Set low order sign bit... |
| 103 | else |
| 104 | output_vbr((unsigned)i << 1, out); // Low order bit is clear. |
| 105 | } |
| 106 | |
| 107 | // align32 - emit the minimal number of bytes that will bring us to 32 bit |
| 108 | // alignment... |
| 109 | // |
| 110 | static inline void align32(std::deque<unsigned char> &Out) { |
| 111 | int NumPads = (4-(Out.size() & 3)) & 3; // Bytes to get padding to 32 bits |
| 112 | while (NumPads--) Out.push_back((unsigned char)0xAB); |
| 113 | } |
| 114 | |
| 115 | static inline void output(const std::string &s, std::deque<unsigned char> &Out, |
| 116 | bool Aligned = true) { |
| 117 | unsigned Len = s.length(); |
| 118 | output_vbr(Len, Out); // Strings may have an arbitrary length... |
| 119 | Out.insert(Out.end(), s.begin(), s.end()); |
| 120 | |
| 121 | if (Aligned) |
| 122 | align32(Out); // Make sure we are now aligned... |
| 123 | } |
| 124 | |
Chris Lattner | 44e3803 | 2004-01-14 18:41:38 +0000 | [diff] [blame^] | 125 | static inline void output_data(const void *Ptr, const void *End, |
Chris Lattner | 4443019 | 2004-01-10 18:56:59 +0000 | [diff] [blame] | 126 | std::deque<unsigned char> &Out, |
| 127 | bool Align = false) { |
| 128 | #ifdef ENDIAN_LITTLE |
Chris Lattner | 44e3803 | 2004-01-14 18:41:38 +0000 | [diff] [blame^] | 129 | Out.insert(Out.end(), (const unsigned char*)Ptr, (const unsigned char*)End); |
Chris Lattner | 4443019 | 2004-01-10 18:56:59 +0000 | [diff] [blame] | 130 | #else |
Chris Lattner | 44e3803 | 2004-01-14 18:41:38 +0000 | [diff] [blame^] | 131 | const unsigned char *E = (const unsigned char *)End; |
Chris Lattner | 4443019 | 2004-01-10 18:56:59 +0000 | [diff] [blame] | 132 | while (Ptr != E) |
| 133 | Out.push_back(*--E); |
| 134 | #endif |
| 135 | |
| 136 | if (Align) align32(Out); |
| 137 | } |
| 138 | |
| 139 | } // End llvm namespace |
| 140 | |
| 141 | #endif |