0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1 //===- llvm/Support/LEB128.h - [SU]LEB128 utility functions -----*- C++ -*-===//
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
2 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
3 // The LLVM Compiler Infrastructure
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
4 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
5 // This file is distributed under the University of Illinois Open Source
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
6 // License. See LICENSE.TXT for details.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
7 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
8 //===----------------------------------------------------------------------===//
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
9 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
10 // This file declares some utility functions for encoding SLEB128 and
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
11 // ULEB128 values.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
12 //
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
13 //===----------------------------------------------------------------------===//
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
14
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
15 #ifndef LLVM_SUPPORT_LEB128_H
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
16 #define LLVM_SUPPORT_LEB128_H
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
17
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
18 #include "llvm/Support/raw_ostream.h"
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
19
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
20 namespace llvm {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
21
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
22 /// Utility function to encode a SLEB128 value to an output stream.
|
121
|
23 inline void encodeSLEB128(int64_t Value, raw_ostream &OS,
|
|
24 unsigned PadTo = 0) {
|
|
25 bool More;
|
|
26 unsigned Count = 0;
|
|
27 do {
|
|
28 uint8_t Byte = Value & 0x7f;
|
|
29 // NOTE: this assumes that this signed shift is an arithmetic right shift.
|
|
30 Value >>= 7;
|
|
31 More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
|
|
32 ((Value == -1) && ((Byte & 0x40) != 0))));
|
|
33 Count++;
|
|
34 if (More || Count < PadTo)
|
|
35 Byte |= 0x80; // Mark this byte to show that more bytes will follow.
|
|
36 OS << char(Byte);
|
|
37 } while (More);
|
|
38
|
|
39 // Pad with 0x80 and emit a terminating byte at the end.
|
|
40 if (Count < PadTo) {
|
|
41 uint8_t PadValue = Value < 0 ? 0x7f : 0x00;
|
|
42 for (; Count < PadTo - 1; ++Count)
|
|
43 OS << char(PadValue | 0x80);
|
|
44 OS << char(PadValue);
|
|
45 }
|
|
46 }
|
|
47
|
|
48 /// Utility function to encode a SLEB128 value to a buffer. Returns
|
|
49 /// the length in bytes of the encoded value.
|
|
50 inline unsigned encodeSLEB128(int64_t Value, uint8_t *p, unsigned PadTo = 0) {
|
|
51 uint8_t *orig_p = p;
|
|
52 unsigned Count = 0;
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
53 bool More;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
54 do {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
55 uint8_t Byte = Value & 0x7f;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
56 // NOTE: this assumes that this signed shift is an arithmetic right shift.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
57 Value >>= 7;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
58 More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
59 ((Value == -1) && ((Byte & 0x40) != 0))));
|
121
|
60 Count++;
|
|
61 if (More || Count < PadTo)
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
62 Byte |= 0x80; // Mark this byte to show that more bytes will follow.
|
121
|
63 *p++ = Byte;
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
64 } while (More);
|
121
|
65
|
|
66 // Pad with 0x80 and emit a terminating byte at the end.
|
|
67 if (Count < PadTo) {
|
|
68 uint8_t PadValue = Value < 0 ? 0x7f : 0x00;
|
|
69 for (; Count < PadTo - 1; ++Count)
|
|
70 *p++ = (PadValue | 0x80);
|
|
71 *p++ = PadValue;
|
|
72 }
|
|
73 return (unsigned)(p - orig_p);
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
74 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
75
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
76 /// Utility function to encode a ULEB128 value to an output stream.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
77 inline void encodeULEB128(uint64_t Value, raw_ostream &OS,
|
121
|
78 unsigned PadTo = 0) {
|
|
79 unsigned Count = 0;
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
80 do {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
81 uint8_t Byte = Value & 0x7f;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
82 Value >>= 7;
|
121
|
83 Count++;
|
|
84 if (Value != 0 || Count < PadTo)
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
85 Byte |= 0x80; // Mark this byte to show that more bytes will follow.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
86 OS << char(Byte);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
87 } while (Value != 0);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
88
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
89 // Pad with 0x80 and emit a null byte at the end.
|
121
|
90 if (Count < PadTo) {
|
|
91 for (; Count < PadTo - 1; ++Count)
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
92 OS << '\x80';
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
93 OS << '\x00';
|
121
|
94 Count++;
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
95 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
96 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
97
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
98 /// Utility function to encode a ULEB128 value to a buffer. Returns
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
99 /// the length in bytes of the encoded value.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
100 inline unsigned encodeULEB128(uint64_t Value, uint8_t *p,
|
121
|
101 unsigned PadTo = 0) {
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
102 uint8_t *orig_p = p;
|
121
|
103 unsigned Count = 0;
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
104 do {
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
105 uint8_t Byte = Value & 0x7f;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
106 Value >>= 7;
|
121
|
107 Count++;
|
|
108 if (Value != 0 || Count < PadTo)
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
109 Byte |= 0x80; // Mark this byte to show that more bytes will follow.
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
110 *p++ = Byte;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
111 } while (Value != 0);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
112
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
113 // Pad with 0x80 and emit a null byte at the end.
|
121
|
114 if (Count < PadTo) {
|
|
115 for (; Count < PadTo - 1; ++Count)
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
116 *p++ = '\x80';
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
117 *p++ = '\x00';
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
118 }
|
121
|
119
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
120 return (unsigned)(p - orig_p);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
121 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
122
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
123 /// Utility function to decode a ULEB128 value.
|
121
|
124 inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr,
|
|
125 const uint8_t *end = nullptr,
|
|
126 const char **error = nullptr) {
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
127 const uint8_t *orig_p = p;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
128 uint64_t Value = 0;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
129 unsigned Shift = 0;
|
121
|
130 if (error)
|
|
131 *error = nullptr;
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
132 do {
|
121
|
133 if (end && p == end) {
|
|
134 if (error)
|
|
135 *error = "malformed uleb128, extends past end";
|
|
136 if (n)
|
|
137 *n = (unsigned)(p - orig_p);
|
|
138 return 0;
|
|
139 }
|
|
140 uint64_t Slice = *p & 0x7f;
|
|
141 if (Shift >= 64 || Slice << Shift >> Shift != Slice) {
|
|
142 if (error)
|
|
143 *error = "uleb128 too big for uint64";
|
|
144 if (n)
|
|
145 *n = (unsigned)(p - orig_p);
|
|
146 return 0;
|
|
147 }
|
77
|
148 Value += uint64_t(*p & 0x7f) << Shift;
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
149 Shift += 7;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
150 } while (*p++ >= 128);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
151 if (n)
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
152 *n = (unsigned)(p - orig_p);
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
153 return Value;
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
154 }
|
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
155
|
83
|
156 /// Utility function to decode a SLEB128 value.
|
121
|
157 inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr,
|
|
158 const uint8_t *end = nullptr,
|
|
159 const char **error = nullptr) {
|
83
|
160 const uint8_t *orig_p = p;
|
|
161 int64_t Value = 0;
|
|
162 unsigned Shift = 0;
|
|
163 uint8_t Byte;
|
|
164 do {
|
121
|
165 if (end && p == end) {
|
|
166 if (error)
|
|
167 *error = "malformed sleb128, extends past end";
|
|
168 if (n)
|
|
169 *n = (unsigned)(p - orig_p);
|
|
170 return 0;
|
|
171 }
|
83
|
172 Byte = *p++;
|
121
|
173 Value |= (int64_t(Byte & 0x7f) << Shift);
|
83
|
174 Shift += 7;
|
|
175 } while (Byte >= 128);
|
|
176 // Sign extend negative numbers.
|
|
177 if (Byte & 0x40)
|
|
178 Value |= (-1ULL) << Shift;
|
|
179 if (n)
|
|
180 *n = (unsigned)(p - orig_p);
|
|
181 return Value;
|
|
182 }
|
|
183
|
77
|
184 /// Utility function to get the size of the ULEB128-encoded value.
|
|
185 extern unsigned getULEB128Size(uint64_t Value);
|
|
186
|
|
187 /// Utility function to get the size of the SLEB128-encoded value.
|
|
188 extern unsigned getSLEB128Size(int64_t Value);
|
|
189
|
121
|
190 } // namespace llvm
|
0
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
191
|
121
|
192 #endif // LLVM_SYSTEM_LEB128_H
|