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 193