blob: 185fac1d0369a6db4c70f378f49a77464f25737a [file] [log] [blame]
Chris Lattner44430192004-01-10 18:56:59 +00001//===-- 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
22namespace 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//
28static 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
51static 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//
64static 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
78static 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
92static 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
100static 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//
110static 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
115static 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 Lattner44e38032004-01-14 18:41:38 +0000125static inline void output_data(const void *Ptr, const void *End,
Chris Lattner44430192004-01-10 18:56:59 +0000126 std::deque<unsigned char> &Out,
127 bool Align = false) {
128#ifdef ENDIAN_LITTLE
Chris Lattner44e38032004-01-14 18:41:38 +0000129 Out.insert(Out.end(), (const unsigned char*)Ptr, (const unsigned char*)End);
Chris Lattner44430192004-01-10 18:56:59 +0000130#else
Chris Lattner44e38032004-01-14 18:41:38 +0000131 const unsigned char *E = (const unsigned char *)End;
Chris Lattner44430192004-01-10 18:56:59 +0000132 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