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