1239310Sdim//===- llvm/Support/LEB128.h - [SU]LEB128 utility functions -----*- C++ -*-===// 2239310Sdim// 3239310Sdim// The LLVM Compiler Infrastructure 4239310Sdim// 5239310Sdim// This file is distributed under the University of Illinois Open Source 6239310Sdim// License. See LICENSE.TXT for details. 7239310Sdim// 8239310Sdim//===----------------------------------------------------------------------===// 9239310Sdim// 10239310Sdim// This file declares some utility functions for encoding SLEB128 and 11239310Sdim// ULEB128 values. 12239310Sdim// 13239310Sdim//===----------------------------------------------------------------------===// 14239310Sdim 15252723Sdim#ifndef LLVM_SUPPORT_LEB128_H 16252723Sdim#define LLVM_SUPPORT_LEB128_H 17239310Sdim 18245431Sdim#include "llvm/Support/raw_ostream.h" 19239310Sdim 20239310Sdimnamespace llvm { 21239310Sdim 22239462Sdim/// Utility function to encode a SLEB128 value to an output stream. 23263509Sdiminline void encodeSLEB128(int64_t Value, raw_ostream &OS) { 24239310Sdim bool More; 25239310Sdim do { 26239310Sdim uint8_t Byte = Value & 0x7f; 27239310Sdim // NOTE: this assumes that this signed shift is an arithmetic right shift. 28239310Sdim Value >>= 7; 29239310Sdim More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) || 30239310Sdim ((Value == -1) && ((Byte & 0x40) != 0)))); 31239310Sdim if (More) 32263509Sdim Byte |= 0x80; // Mark this byte to show that more bytes will follow. 33239310Sdim OS << char(Byte); 34239310Sdim } while (More); 35239310Sdim} 36239310Sdim 37239462Sdim/// Utility function to encode a ULEB128 value to an output stream. 38263509Sdiminline void encodeULEB128(uint64_t Value, raw_ostream &OS, 39263509Sdim unsigned Padding = 0) { 40239310Sdim do { 41239310Sdim uint8_t Byte = Value & 0x7f; 42239310Sdim Value >>= 7; 43239310Sdim if (Value != 0 || Padding != 0) 44263509Sdim Byte |= 0x80; // Mark this byte to show that more bytes will follow. 45239310Sdim OS << char(Byte); 46239310Sdim } while (Value != 0); 47239310Sdim 48239310Sdim // Pad with 0x80 and emit a null byte at the end. 49239310Sdim if (Padding != 0) { 50239310Sdim for (; Padding != 1; --Padding) 51239310Sdim OS << '\x80'; 52239310Sdim OS << '\x00'; 53239310Sdim } 54239310Sdim} 55239310Sdim 56239462Sdim/// Utility function to encode a ULEB128 value to a buffer. Returns 57239462Sdim/// the length in bytes of the encoded value. 58263509Sdiminline unsigned encodeULEB128(uint64_t Value, uint8_t *p, 59263509Sdim unsigned Padding = 0) { 60239462Sdim uint8_t *orig_p = p; 61239462Sdim do { 62239462Sdim uint8_t Byte = Value & 0x7f; 63239462Sdim Value >>= 7; 64239462Sdim if (Value != 0 || Padding != 0) 65263509Sdim Byte |= 0x80; // Mark this byte to show that more bytes will follow. 66239462Sdim *p++ = Byte; 67239462Sdim } while (Value != 0); 68239462Sdim 69239462Sdim // Pad with 0x80 and emit a null byte at the end. 70239462Sdim if (Padding != 0) { 71239462Sdim for (; Padding != 1; --Padding) 72239462Sdim *p++ = '\x80'; 73239462Sdim *p++ = '\x00'; 74239462Sdim } 75239462Sdim return (unsigned)(p - orig_p); 76239462Sdim} 77239462Sdim 78239462Sdim 79239462Sdim/// Utility function to decode a ULEB128 value. 80263509Sdiminline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = 0) { 81239462Sdim const uint8_t *orig_p = p; 82239462Sdim uint64_t Value = 0; 83239462Sdim unsigned Shift = 0; 84239462Sdim do { 85239462Sdim Value += (*p & 0x7f) << Shift; 86239462Sdim Shift += 7; 87239462Sdim } while (*p++ >= 128); 88239462Sdim if (n) 89239462Sdim *n = (unsigned)(p - orig_p); 90239462Sdim return Value; 91239462Sdim} 92239462Sdim 93239310Sdim} // namespace llvm 94239310Sdim 95239310Sdim#endif // LLVM_SYSTEM_LEB128_H 96