1 //===- llvm/Support/LEB128.h - [SU]LEB128 utility functions -----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file declares some utility functions for encoding SLEB128 and
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_SUPPORT_LEB128_H
16 #define LLVM_SUPPORT_LEB128_H
18 #include "llvm/Support/raw_ostream.h"
22 /// Utility function to encode a SLEB128 value to an output stream.
23 inline void encodeSLEB128(int64_t Value, raw_ostream &OS,
28 uint8_t Byte = Value & 0x7f;
29 // NOTE: this assumes that this signed shift is an arithmetic right shift.
31 More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
32 ((Value == -1) && ((Byte & 0x40) != 0))));
34 if (More || Count < PadTo)
35 Byte |= 0x80; // Mark this byte to show that more bytes will follow.
39 // Pad with 0x80 and emit a terminating byte at the end.
41 uint8_t PadValue = Value < 0 ? 0x7f : 0x00;
42 for (; Count < PadTo - 1; ++Count)
43 OS << char(PadValue | 0x80);
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) {
55 uint8_t Byte = Value & 0x7f;
56 // NOTE: this assumes that this signed shift is an arithmetic right shift.
58 More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
59 ((Value == -1) && ((Byte & 0x40) != 0))));
61 if (More || Count < PadTo)
62 Byte |= 0x80; // Mark this byte to show that more bytes will follow.
66 // Pad with 0x80 and emit a terminating byte at the end.
68 uint8_t PadValue = Value < 0 ? 0x7f : 0x00;
69 for (; Count < PadTo - 1; ++Count)
70 *p++ = (PadValue | 0x80);
73 return (unsigned)(p - orig_p);
76 /// Utility function to encode a ULEB128 value to an output stream.
77 inline void encodeULEB128(uint64_t Value, raw_ostream &OS,
81 uint8_t Byte = Value & 0x7f;
84 if (Value != 0 || Count < PadTo)
85 Byte |= 0x80; // Mark this byte to show that more bytes will follow.
89 // Pad with 0x80 and emit a null byte at the end.
91 for (; Count < PadTo - 1; ++Count)
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 unsigned PadTo = 0) {
105 uint8_t Byte = Value & 0x7f;
108 if (Value != 0 || Count < PadTo)
109 Byte |= 0x80; // Mark this byte to show that more bytes will follow.
111 } while (Value != 0);
113 // Pad with 0x80 and emit a null byte at the end.
115 for (; Count < PadTo - 1; ++Count)
120 return (unsigned)(p - orig_p);
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 const char **error = nullptr) {
127 const uint8_t *orig_p = p;
133 if (end && p == end) {
135 *error = "malformed uleb128, extends past end";
137 *n = (unsigned)(p - orig_p);
140 uint64_t Slice = *p & 0x7f;
141 if (Shift >= 64 || Slice << Shift >> Shift != Slice) {
143 *error = "uleb128 too big for uint64";
145 *n = (unsigned)(p - orig_p);
148 Value += uint64_t(*p & 0x7f) << Shift;
150 } while (*p++ >= 128);
152 *n = (unsigned)(p - orig_p);
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;
165 if (end && p == end) {
167 *error = "malformed sleb128, extends past end";
169 *n = (unsigned)(p - orig_p);
173 Value |= (int64_t(Byte & 0x7f) << Shift);
175 } while (Byte >= 128);
176 // Sign extend negative numbers.
178 Value |= (-1ULL) << Shift;
180 *n = (unsigned)(p - orig_p);
184 /// Utility function to get the size of the ULEB128-encoded value.
185 extern unsigned getULEB128Size(uint64_t Value);
187 /// Utility function to get the size of the SLEB128-encoded value.
188 extern unsigned getSLEB128Size(int64_t Value);
192 #endif // LLVM_SYSTEM_LEB128_H