LEB128.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. #ifndef LLVM_SUPPORT_LEB128_H
  15. #define LLVM_SUPPORT_LEB128_H
  16. #include "llvm/Support/raw_ostream.h"
  17. namespace llvm {
  18. /// Utility function to encode a SLEB128 value to an output stream.
  19. inline void encodeSLEB128(int64_t Value, raw_ostream &OS) {
  20. bool More;
  21. do {
  22. uint8_t Byte = Value & 0x7f;
  23. // NOTE: this assumes that this signed shift is an arithmetic right shift.
  24. Value >>= 7;
  25. More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
  26. ((Value == -1) && ((Byte & 0x40) != 0))));
  27. if (More)
  28. Byte |= 0x80; // Mark this byte to show that more bytes will follow.
  29. OS << char(Byte);
  30. } while (More);
  31. }
  32. /// Utility function to encode a ULEB128 value to an output stream.
  33. inline void encodeULEB128(uint64_t Value, raw_ostream &OS,
  34. unsigned Padding = 0) {
  35. do {
  36. uint8_t Byte = Value & 0x7f;
  37. Value >>= 7;
  38. if (Value != 0 || Padding != 0)
  39. Byte |= 0x80; // Mark this byte to show that more bytes will follow.
  40. OS << char(Byte);
  41. } while (Value != 0);
  42. // Pad with 0x80 and emit a null byte at the end.
  43. if (Padding != 0) {
  44. for (; Padding != 1; --Padding)
  45. OS << '\x80';
  46. OS << '\x00';
  47. }
  48. }
  49. /// Utility function to encode a ULEB128 value to a buffer. Returns
  50. /// the length in bytes of the encoded value.
  51. inline unsigned encodeULEB128(uint64_t Value, uint8_t *p,
  52. unsigned Padding = 0) {
  53. uint8_t *orig_p = p;
  54. do {
  55. uint8_t Byte = Value & 0x7f;
  56. Value >>= 7;
  57. if (Value != 0 || Padding != 0)
  58. Byte |= 0x80; // Mark this byte to show that more bytes will follow.
  59. *p++ = Byte;
  60. } while (Value != 0);
  61. // Pad with 0x80 and emit a null byte at the end.
  62. if (Padding != 0) {
  63. for (; Padding != 1; --Padding)
  64. *p++ = '\x80';
  65. *p++ = '\x00';
  66. }
  67. return (unsigned)(p - orig_p);
  68. }
  69. /// Utility function to decode a ULEB128 value.
  70. inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr) {
  71. const uint8_t *orig_p = p;
  72. uint64_t Value = 0;
  73. unsigned Shift = 0;
  74. do {
  75. Value += uint64_t(*p & 0x7f) << Shift;
  76. Shift += 7;
  77. } while (*p++ >= 128);
  78. if (n)
  79. *n = (unsigned)(p - orig_p);
  80. return Value;
  81. }
  82. /// Utility function to decode a SLEB128 value.
  83. inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr) {
  84. const uint8_t *orig_p = p;
  85. int64_t Value = 0;
  86. unsigned Shift = 0;
  87. uint8_t Byte;
  88. do {
  89. Byte = *p++;
  90. Value |= (((uint64_t)(Byte & 0x7f)) << Shift); // HLSL Change - use 64 bits before casting, not after
  91. Shift += 7;
  92. } while (Byte >= 128);
  93. // Sign extend negative numbers.
  94. if (Byte & 0x40)
  95. Value |= (-1ULL) << Shift;
  96. if (n)
  97. *n = (unsigned)(p - orig_p);
  98. return Value;
  99. }
  100. /// Utility function to get the size of the ULEB128-encoded value.
  101. extern unsigned getULEB128Size(uint64_t Value);
  102. /// Utility function to get the size of the SLEB128-encoded value.
  103. extern unsigned getSLEB128Size(int64_t Value);
  104. } // namespace llvm
  105. #endif // LLVM_SYSTEM_LEB128_H