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