LEB128.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- llvm/Support/LEB128.h - [SU]LEB128 utility functions -----*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file declares some utility functions for encoding SLEB128 and
  15. // ULEB128 values.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_SUPPORT_LEB128_H
  19. #define LLVM_SUPPORT_LEB128_H
  20. #include "llvm/Support/raw_ostream.h"
  21. namespace llvm {
  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. // 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. Count++;
  46. }
  47. return Count;
  48. }
  49. /// Utility function to encode a SLEB128 value to a buffer. Returns
  50. /// the length in bytes of the encoded value.
  51. inline unsigned encodeSLEB128(int64_t Value, uint8_t *p, unsigned PadTo = 0) {
  52. uint8_t *orig_p = p;
  53. unsigned Count = 0;
  54. bool More;
  55. do {
  56. uint8_t Byte = Value & 0x7f;
  57. // NOTE: this assumes that this signed shift is an arithmetic right shift.
  58. Value >>= 7;
  59. More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
  60. ((Value == -1) && ((Byte & 0x40) != 0))));
  61. Count++;
  62. if (More || Count < PadTo)
  63. Byte |= 0x80; // Mark this byte to show that more bytes will follow.
  64. *p++ = Byte;
  65. } while (More);
  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. /// Utility function to encode a ULEB128 value to an output stream. Returns
  76. /// the length in bytes of the encoded value.
  77. inline unsigned 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. // Pad with 0x80 and emit a null byte at the end.
  89. if (Count < PadTo) {
  90. for (; Count < PadTo - 1; ++Count)
  91. OS << '\x80';
  92. OS << '\x00';
  93. Count++;
  94. }
  95. return Count;
  96. }
  97. /// Utility function to encode a ULEB128 value to a buffer. Returns
  98. /// the length in bytes of the encoded value.
  99. inline unsigned encodeULEB128(uint64_t Value, uint8_t *p,
  100. unsigned PadTo = 0) {
  101. uint8_t *orig_p = p;
  102. unsigned Count = 0;
  103. do {
  104. uint8_t Byte = Value & 0x7f;
  105. Value >>= 7;
  106. Count++;
  107. if (Value != 0 || Count < PadTo)
  108. Byte |= 0x80; // Mark this byte to show that more bytes will follow.
  109. *p++ = Byte;
  110. } while (Value != 0);
  111. // Pad with 0x80 and emit a null byte at the end.
  112. if (Count < PadTo) {
  113. for (; Count < PadTo - 1; ++Count)
  114. *p++ = '\x80';
  115. *p++ = '\x00';
  116. }
  117. return (unsigned)(p - orig_p);
  118. }
  119. /// Utility function to decode a ULEB128 value.
  120. inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr,
  121. const uint8_t *end = nullptr,
  122. const char **error = nullptr) {
  123. const uint8_t *orig_p = p;
  124. uint64_t Value = 0;
  125. unsigned Shift = 0;
  126. if (error)
  127. *error = nullptr;
  128. do {
  129. if (p == end) {
  130. if (error)
  131. *error = "malformed uleb128, extends past end";
  132. if (n)
  133. *n = (unsigned)(p - orig_p);
  134. return 0;
  135. }
  136. uint64_t Slice = *p & 0x7f;
  137. if ((Shift >= 64 && Slice != 0) || Slice << Shift >> Shift != Slice) {
  138. if (error)
  139. *error = "uleb128 too big for uint64";
  140. if (n)
  141. *n = (unsigned)(p - orig_p);
  142. return 0;
  143. }
  144. Value += Slice << Shift;
  145. Shift += 7;
  146. } while (*p++ >= 128);
  147. if (n)
  148. *n = (unsigned)(p - orig_p);
  149. return Value;
  150. }
  151. /// Utility function to decode a SLEB128 value.
  152. inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr,
  153. const uint8_t *end = nullptr,
  154. const char **error = nullptr) {
  155. const uint8_t *orig_p = p;
  156. int64_t Value = 0;
  157. unsigned Shift = 0;
  158. uint8_t Byte;
  159. if (error)
  160. *error = nullptr;
  161. do {
  162. if (p == end) {
  163. if (error)
  164. *error = "malformed sleb128, extends past end";
  165. if (n)
  166. *n = (unsigned)(p - orig_p);
  167. return 0;
  168. }
  169. Byte = *p;
  170. uint64_t Slice = Byte & 0x7f;
  171. if ((Shift >= 64 && Slice != (Value < 0 ? 0x7f : 0x00)) ||
  172. (Shift == 63 && Slice != 0 && Slice != 0x7f)) {
  173. if (error)
  174. *error = "sleb128 too big for int64";
  175. if (n)
  176. *n = (unsigned)(p - orig_p);
  177. return 0;
  178. }
  179. Value |= Slice << Shift;
  180. Shift += 7;
  181. ++p;
  182. } while (Byte >= 128);
  183. // Sign extend negative numbers if needed.
  184. if (Shift < 64 && (Byte & 0x40))
  185. Value |= (-1ULL) << Shift;
  186. if (n)
  187. *n = (unsigned)(p - orig_p);
  188. return Value;
  189. }
  190. /// Utility function to get the size of the ULEB128-encoded value.
  191. extern unsigned getULEB128Size(uint64_t Value);
  192. /// Utility function to get the size of the SLEB128-encoded value.
  193. extern unsigned getSLEB128Size(int64_t Value);
  194. } // namespace llvm
  195. #endif // LLVM_SUPPORT_LEB128_H
  196. #ifdef __GNUC__
  197. #pragma GCC diagnostic pop
  198. #endif