/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/include/llvm/Support/LEB128.h
Line | Count | Source |
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. |
23 | | inline void encodeSLEB128(int64_t Value, raw_ostream &OS, |
24 | 117k | unsigned PadTo = 0) { |
25 | 117k | bool More; |
26 | 117k | unsigned Count = 0; |
27 | 190k | do { |
28 | 190k | uint8_t Byte = Value & 0x7f; |
29 | 190k | // NOTE: this assumes that this signed shift is an arithmetic right shift. |
30 | 190k | Value >>= 7; |
31 | 67.4k | More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) || |
32 | 134k | ((Value == -1) && 134k ((Byte & 0x40) != 0)74.2k ))); |
33 | 190k | Count++; |
34 | 190k | if (More || 190k Count < PadTo117k ) |
35 | 72.5k | Byte |= 0x80; // Mark this byte to show that more bytes will follow. |
36 | 190k | OS << char(Byte); |
37 | 190k | } while (More); |
38 | 117k | |
39 | 117k | // Pad with 0x80 and emit a terminating byte at the end. |
40 | 117k | if (Count < PadTo117k ) { |
41 | 10 | uint8_t PadValue = Value < 0 ? 0x7f4 : 0x006 ; |
42 | 15 | for (; Count < PadTo - 115 ; ++Count5 ) |
43 | 5 | OS << char(PadValue | 0x80); |
44 | 10 | OS << char(PadValue); |
45 | 10 | } |
46 | 117k | } |
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; |
53 | | bool More; |
54 | | do { |
55 | | uint8_t Byte = Value & 0x7f; |
56 | | // NOTE: this assumes that this signed shift is an arithmetic right shift. |
57 | | Value >>= 7; |
58 | | More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) || |
59 | | ((Value == -1) && ((Byte & 0x40) != 0)))); |
60 | | Count++; |
61 | | if (More || Count < PadTo) |
62 | | Byte |= 0x80; // Mark this byte to show that more bytes will follow. |
63 | | *p++ = Byte; |
64 | | } while (More); |
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); |
74 | | } |
75 | | |
76 | | /// Utility function to encode a ULEB128 value to an output stream. |
77 | | inline void encodeULEB128(uint64_t Value, raw_ostream &OS, |
78 | 10.6M | unsigned PadTo = 0) { |
79 | 10.6M | unsigned Count = 0; |
80 | 17.2M | do { |
81 | 17.2M | uint8_t Byte = Value & 0x7f; |
82 | 17.2M | Value >>= 7; |
83 | 17.2M | Count++; |
84 | 17.2M | if (Value != 0 || 17.2M Count < PadTo10.6M ) |
85 | 6.60M | Byte |= 0x80; // Mark this byte to show that more bytes will follow. |
86 | 17.2M | OS << char(Byte); |
87 | 17.2M | } while (Value != 0); |
88 | 10.6M | |
89 | 10.6M | // Pad with 0x80 and emit a null byte at the end. |
90 | 10.6M | if (Count < PadTo10.6M ) { |
91 | 3.13k | for (; Count < PadTo - 13.13k ; ++Count1.15k ) |
92 | 1.15k | OS << '\x80'; |
93 | 1.98k | OS << '\x00'; |
94 | 1.98k | Count++; |
95 | 1.98k | } |
96 | 10.6M | } |
97 | | |
98 | | /// Utility function to encode a ULEB128 value to a buffer. Returns |
99 | | /// the length in bytes of the encoded value. |
100 | | inline unsigned encodeULEB128(uint64_t Value, uint8_t *p, |
101 | 51.8k | unsigned PadTo = 0) { |
102 | 51.8k | uint8_t *orig_p = p; |
103 | 51.8k | unsigned Count = 0; |
104 | 73.0k | do { |
105 | 73.0k | uint8_t Byte = Value & 0x7f; |
106 | 73.0k | Value >>= 7; |
107 | 73.0k | Count++; |
108 | 73.0k | if (Value != 0 || 73.0k Count < PadTo51.8k ) |
109 | 21.1k | Byte |= 0x80; // Mark this byte to show that more bytes will follow. |
110 | 73.0k | *p++ = Byte; |
111 | 73.0k | } while (Value != 0); |
112 | 51.8k | |
113 | 51.8k | // Pad with 0x80 and emit a null byte at the end. |
114 | 51.8k | if (Count < PadTo51.8k ) { |
115 | 9 | for (; Count < PadTo - 19 ; ++Count3 ) |
116 | 3 | *p++ = '\x80'; |
117 | 6 | *p++ = '\x00'; |
118 | 6 | } |
119 | 51.8k | |
120 | 51.8k | return (unsigned)(p - orig_p); |
121 | 51.8k | } |
122 | | |
123 | | /// Utility function to decode a ULEB128 value. |
124 | | inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr, |
125 | | const uint8_t *end = nullptr, |
126 | 25.9M | const char **error = nullptr) { |
127 | 25.9M | const uint8_t *orig_p = p; |
128 | 25.9M | uint64_t Value = 0; |
129 | 25.9M | unsigned Shift = 0; |
130 | 25.9M | if (error) |
131 | 496 | *error = nullptr; |
132 | 33.5M | do { |
133 | 33.5M | if (end && 33.5M p == end709 ) { |
134 | 3 | if (error) |
135 | 3 | *error = "malformed uleb128, extends past end"; |
136 | 3 | if (n) |
137 | 3 | *n = (unsigned)(p - orig_p); |
138 | 3 | return 0; |
139 | 3 | } |
140 | 33.5M | uint64_t Slice = *p & 0x7f; |
141 | 33.5M | if (Shift >= 64 || 33.5M Slice << Shift >> Shift != Slice33.5M ) { |
142 | 2 | if (error) |
143 | 2 | *error = "uleb128 too big for uint64"; |
144 | 2 | if (n) |
145 | 2 | *n = (unsigned)(p - orig_p); |
146 | 2 | return 0; |
147 | 2 | } |
148 | 33.5M | Value += uint64_t(*p & 0x7f) << Shift; |
149 | 33.5M | Shift += 7; |
150 | 33.5M | } while (*p++ >= 128); |
151 | 25.9M | if (25.9M n25.9M ) |
152 | 25.9M | *n = (unsigned)(p - orig_p); |
153 | 25.9M | return Value; |
154 | 25.9M | } |
155 | | |
156 | | /// Utility function to decode a SLEB128 value. |
157 | | inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr, |
158 | | const uint8_t *end = nullptr, |
159 | | const char **error = nullptr) { |
160 | | const uint8_t *orig_p = p; |
161 | | int64_t Value = 0; |
162 | | unsigned Shift = 0; |
163 | | uint8_t Byte; |
164 | | do { |
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 | | } |
172 | | Byte = *p++; |
173 | | Value |= (int64_t(Byte & 0x7f) << Shift); |
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 | | |
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 | | |
190 | | } // namespace llvm |
191 | | |
192 | | #endif // LLVM_SYSTEM_LEB128_H |