]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/Support/LEB128.h
Merge clang 7.0.1 and several follow-up changes
[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. Returns
23 /// the length in bytes of the encoded value.
24 inline unsigned encodeSLEB128(int64_t Value, raw_ostream &OS,
25                               unsigned PadTo = 0) {
26   bool More;
27   unsigned Count = 0;
28   do {
29     uint8_t Byte = Value & 0x7f;
30     // NOTE: this assumes that this signed shift is an arithmetic right shift.
31     Value >>= 7;
32     More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
33               ((Value == -1) && ((Byte & 0x40) != 0))));
34     Count++;
35     if (More || Count < PadTo)
36       Byte |= 0x80; // Mark this byte to show that more bytes will follow.
37     OS << char(Byte);
38   } while (More);
39
40   // Pad with 0x80 and emit a terminating byte at the end.
41   if (Count < PadTo) {
42     uint8_t PadValue = Value < 0 ? 0x7f : 0x00;
43     for (; Count < PadTo - 1; ++Count)
44       OS << char(PadValue | 0x80);
45     OS << char(PadValue);
46     Count++;
47   }
48   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 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   do {
58     uint8_t Byte = Value & 0x7f;
59     // NOTE: this assumes that this signed shift is an arithmetic right shift.
60     Value >>= 7;
61     More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
62               ((Value == -1) && ((Byte & 0x40) != 0))));
63     Count++;
64     if (More || Count < PadTo)
65       Byte |= 0x80; // Mark this byte to show that more bytes will follow.
66     *p++ = Byte;
67   } while (More);
68
69   // Pad with 0x80 and emit a terminating byte at the end.
70   if (Count < PadTo) {
71     uint8_t PadValue = Value < 0 ? 0x7f : 0x00;
72     for (; Count < PadTo - 1; ++Count)
73       *p++ = (PadValue | 0x80);
74     *p++ = PadValue;
75   }
76   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 inline unsigned encodeULEB128(uint64_t Value, raw_ostream &OS,
82                               unsigned PadTo = 0) {
83   unsigned Count = 0;
84   do {
85     uint8_t Byte = Value & 0x7f;
86     Value >>= 7;
87     Count++;
88     if (Value != 0 || Count < PadTo)
89       Byte |= 0x80; // Mark this byte to show that more bytes will follow.
90     OS << char(Byte);
91   } while (Value != 0);
92
93   // Pad with 0x80 and emit a null byte at the end.
94   if (Count < PadTo) {
95     for (; Count < PadTo - 1; ++Count)
96       OS << '\x80';
97     OS << '\x00';
98     Count++;
99   }
100   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 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     uint8_t Byte = Value & 0x7f;
111     Value >>= 7;
112     Count++;
113     if (Value != 0 || Count < PadTo)
114       Byte |= 0x80; // Mark this byte to show that more bytes will follow.
115     *p++ = Byte;
116   } while (Value != 0);
117
118   // Pad with 0x80 and emit a null byte at the end.
119   if (Count < PadTo) {
120     for (; Count < PadTo - 1; ++Count)
121       *p++ = '\x80';
122     *p++ = '\x00';
123   }
124
125   return (unsigned)(p - orig_p);
126 }
127
128 /// Utility function to decode a ULEB128 value.
129 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   if (error)
136     *error = nullptr;
137   do {
138     if (end && p == end) {
139       if (error)
140         *error = "malformed uleb128, extends past end";
141       if (n)
142         *n = (unsigned)(p - orig_p);
143       return 0;
144     }
145     uint64_t Slice = *p & 0x7f;
146     if (Shift >= 64 || Slice << Shift >> Shift != Slice) {
147       if (error)
148         *error = "uleb128 too big for uint64";
149       if (n)
150         *n = (unsigned)(p - orig_p);
151       return 0;
152     }
153     Value += uint64_t(*p & 0x7f) << Shift;
154     Shift += 7;
155   } while (*p++ >= 128);
156   if (n)
157     *n = (unsigned)(p - orig_p);
158   return Value;
159 }
160
161 /// Utility function to decode a SLEB128 value.
162 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     if (end && p == end) {
171       if (error)
172         *error = "malformed sleb128, extends past end";
173       if (n)
174         *n = (unsigned)(p - orig_p);
175       return 0;
176     }
177     Byte = *p++;
178     Value |= (int64_t(Byte & 0x7f) << Shift);
179     Shift += 7;
180   } while (Byte >= 128);
181   // Sign extend negative numbers.
182   if (Byte & 0x40)
183     Value |= (-1ULL) << Shift;
184   if (n)
185     *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