]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/Support/LEB128.h
Merge lld trunk r321414 to contrib/llvm/tools/lld.
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / Support / LEB128.h
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                           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;
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                           unsigned PadTo = 0) {
79   unsigned Count = 0;
80   do {
81     uint8_t Byte = Value & 0x7f;
82     Value >>= 7;
83     Count++;
84     if (Value != 0 || Count < PadTo)
85       Byte |= 0x80; // Mark this byte to show that more bytes will follow.
86     OS << char(Byte);
87   } while (Value != 0);
88
89   // Pad with 0x80 and emit a null byte at the end.
90   if (Count < PadTo) {
91     for (; Count < PadTo - 1; ++Count)
92       OS << '\x80';
93     OS << '\x00';
94     Count++;
95   }
96 }
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                               unsigned PadTo = 0) {
102   uint8_t *orig_p = p;
103   unsigned Count = 0;
104   do {
105     uint8_t Byte = Value & 0x7f;
106     Value >>= 7;
107     Count++;
108     if (Value != 0 || Count < PadTo)
109       Byte |= 0x80; // Mark this byte to show that more bytes will follow.
110     *p++ = Byte;
111   } while (Value != 0);
112
113   // Pad with 0x80 and emit a null byte at the end.
114   if (Count < PadTo) {
115     for (; Count < PadTo - 1; ++Count)
116       *p++ = '\x80';
117     *p++ = '\x00';
118   }
119
120   return (unsigned)(p - orig_p);
121 }
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                               const char **error = nullptr) {
127   const uint8_t *orig_p = p;
128   uint64_t Value = 0;
129   unsigned Shift = 0;
130   if (error)
131     *error = nullptr;
132   do {
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     }
148     Value += uint64_t(*p & 0x7f) << Shift;
149     Shift += 7;
150   } while (*p++ >= 128);
151   if (n)
152     *n = (unsigned)(p - orig_p);
153   return Value;
154 }
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