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) { |
Chris Lattner | 4443019 | 2004-01-10 18:56:59 +0000 | [diff] [blame] | 30 | if (pos == -1) { // Be endian clean, little endian is our friend |
| 31 | Out.push_back((unsigned char)i); |
| 32 | Out.push_back((unsigned char)(i >> 8)); |
| 33 | Out.push_back((unsigned char)(i >> 16)); |
| 34 | Out.push_back((unsigned char)(i >> 24)); |
| 35 | } else { |
| 36 | Out[pos ] = (unsigned char)i; |
| 37 | Out[pos+1] = (unsigned char)(i >> 8); |
| 38 | Out[pos+2] = (unsigned char)(i >> 16); |
| 39 | Out[pos+3] = (unsigned char)(i >> 24); |
| 40 | } |
Chris Lattner | 4443019 | 2004-01-10 18:56:59 +0000 | [diff] [blame] | 41 | } |
| 42 | |
| 43 | static inline void output(int i, std::deque<unsigned char> &Out) { |
| 44 | output((unsigned)i, Out); |
| 45 | } |
| 46 | |
| 47 | // output_vbr - Output an unsigned value, by using the least number of bytes |
| 48 | // possible. This is useful because many of our "infinite" values are really |
| 49 | // very small most of the time... but can be large a few times... |
| 50 | // |
| 51 | // Data format used: If you read a byte with the night bit set, use the low |
| 52 | // seven bits as data and then read another byte... |
| 53 | // |
| 54 | // Note that using this may cause the output buffer to become unaligned... |
| 55 | // |
| 56 | static inline void output_vbr(uint64_t i, std::deque<unsigned char> &out) { |
| 57 | while (1) { |
| 58 | if (i < 0x80) { // done? |
| 59 | out.push_back((unsigned char)i); // We know the high bit is clear... |
| 60 | return; |
| 61 | } |
| 62 | |
| 63 | // Nope, we are bigger than a character, output the next 7 bits and set the |
| 64 | // high bit to say that there is more coming... |
| 65 | out.push_back(0x80 | (i & 0x7F)); |
| 66 | i >>= 7; // Shift out 7 bits now... |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | static inline void output_vbr(unsigned i, std::deque<unsigned char> &out) { |
| 71 | while (1) { |
| 72 | if (i < 0x80) { // done? |
| 73 | out.push_back((unsigned char)i); // We know the high bit is clear... |
| 74 | return; |
| 75 | } |
| 76 | |
| 77 | // Nope, we are bigger than a character, output the next 7 bits and set the |
| 78 | // high bit to say that there is more coming... |
| 79 | out.push_back(0x80 | (i & 0x7F)); |
| 80 | i >>= 7; // Shift out 7 bits now... |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | static inline void output_vbr(int64_t i, std::deque<unsigned char> &out) { |
| 85 | if (i < 0) |
| 86 | output_vbr(((uint64_t)(-i) << 1) | 1, out); // Set low order sign bit... |
| 87 | else |
| 88 | output_vbr((uint64_t)i << 1, out); // Low order bit is clear. |
| 89 | } |
| 90 | |
| 91 | |
| 92 | static inline void output_vbr(int i, std::deque<unsigned char> &out) { |
| 93 | if (i < 0) |
| 94 | output_vbr(((unsigned)(-i) << 1) | 1, out); // Set low order sign bit... |
| 95 | else |
| 96 | output_vbr((unsigned)i << 1, out); // Low order bit is clear. |
| 97 | } |
| 98 | |
| 99 | // align32 - emit the minimal number of bytes that will bring us to 32 bit |
| 100 | // alignment... |
| 101 | // |
| 102 | static inline void align32(std::deque<unsigned char> &Out) { |
| 103 | int NumPads = (4-(Out.size() & 3)) & 3; // Bytes to get padding to 32 bits |
| 104 | while (NumPads--) Out.push_back((unsigned char)0xAB); |
| 105 | } |
| 106 | |
| 107 | static inline void output(const std::string &s, std::deque<unsigned char> &Out, |
| 108 | bool Aligned = true) { |
| 109 | unsigned Len = s.length(); |
| 110 | output_vbr(Len, Out); // Strings may have an arbitrary length... |
| 111 | Out.insert(Out.end(), s.begin(), s.end()); |
| 112 | |
| 113 | if (Aligned) |
| 114 | align32(Out); // Make sure we are now aligned... |
| 115 | } |
| 116 | |
Chris Lattner | 44e3803 | 2004-01-14 18:41:38 +0000 | [diff] [blame] | 117 | static inline void output_data(const void *Ptr, const void *End, |
Chris Lattner | 0a3a27b | 2004-01-14 18:50:28 +0000 | [diff] [blame] | 118 | std::deque<unsigned char> &Out) { |
Chris Lattner | 44e3803 | 2004-01-14 18:41:38 +0000 | [diff] [blame] | 119 | Out.insert(Out.end(), (const unsigned char*)Ptr, (const unsigned char*)End); |
Chris Lattner | 4443019 | 2004-01-10 18:56:59 +0000 | [diff] [blame] | 120 | } |
| 121 | |
| 122 | } // End llvm namespace |
| 123 | |
| 124 | #endif |