From 9885a59108ea44a71fd6e7cbeb516072c5cad362 Mon Sep 17 00:00:00 2001 From: Nick Kledzik Date: Mon, 15 Sep 2014 21:51:49 +0000 Subject: [PATCH] [Support] add decodeSLEB128() We already have routines to encode SLEB128 as well as encode/decode ULEB128. This last function fills out the matrix. I'll need this for some llvm-objdump work I am doing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217830 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/LEB128.h | 20 ++++++++++++++++++ unittests/Support/LEB128Test.cpp | 36 ++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/include/llvm/Support/LEB128.h b/include/llvm/Support/LEB128.h index 4dbc5e91a2c..9e229fbf9cf 100644 --- a/include/llvm/Support/LEB128.h +++ b/include/llvm/Support/LEB128.h @@ -90,6 +90,26 @@ inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr) { return Value; } +/// Utility function to decode a SLEB128 value. +inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr) { + const uint8_t *orig_p = p; + int64_t Value = 0; + unsigned Shift = 0; + uint8_t Byte; + do { + Byte = *p++; + Value |= ((Byte & 0x7f) << Shift); + Shift += 7; + } while (Byte >= 128); + // Sign extend negative numbers. + if (Byte & 0x40) + Value |= (-1LL) << Shift; + if (n) + *n = (unsigned)(p - orig_p); + return Value; +} + + /// Utility function to get the size of the ULEB128-encoded value. extern unsigned getULEB128Size(uint64_t Value); diff --git a/unittests/Support/LEB128Test.cpp b/unittests/Support/LEB128Test.cpp index 14a6d3ff5ad..76b63e5a838 100644 --- a/unittests/Support/LEB128Test.cpp +++ b/unittests/Support/LEB128Test.cpp @@ -119,6 +119,42 @@ TEST(LEB128Test, DecodeULEB128) { #undef EXPECT_DECODE_ULEB128_EQ } +TEST(LEB128Test, DecodeSLEB128) { +#define EXPECT_DECODE_SLEB128_EQ(EXPECTED, VALUE) \ + do { \ + unsigned ActualSize = 0; \ + int64_t Actual = decodeSLEB128(reinterpret_cast(VALUE), \ + &ActualSize); \ + EXPECT_EQ(sizeof(VALUE) - 1, ActualSize); \ + EXPECT_EQ(EXPECTED, Actual); \ + } while (0) + + // Decode SLEB128 + EXPECT_DECODE_SLEB128_EQ(0L, "\x00"); + EXPECT_DECODE_SLEB128_EQ(1L, "\x01"); + EXPECT_DECODE_SLEB128_EQ(63L, "\x3f"); + EXPECT_DECODE_SLEB128_EQ(-64L, "\x40"); + EXPECT_DECODE_SLEB128_EQ(-63L, "\x41"); + EXPECT_DECODE_SLEB128_EQ(-1L, "\x7f"); + EXPECT_DECODE_SLEB128_EQ(128L, "\x80\x01"); + EXPECT_DECODE_SLEB128_EQ(129L, "\x81\x01"); + EXPECT_DECODE_SLEB128_EQ(-129L, "\xff\x7e"); + EXPECT_DECODE_SLEB128_EQ(-128L, "\x80\x7f"); + EXPECT_DECODE_SLEB128_EQ(-127L, "\x81\x7f"); + EXPECT_DECODE_SLEB128_EQ(64L, "\xc0\x00"); + EXPECT_DECODE_SLEB128_EQ(-12345L, "\xc7\x9f\x7f"); + + // Decode unnormalized SLEB128 with extra padding bytes. + EXPECT_DECODE_SLEB128_EQ(0L, "\x80\x00"); + EXPECT_DECODE_SLEB128_EQ(0L, "\x80\x80\x00"); + EXPECT_DECODE_SLEB128_EQ(0x7fL, "\xff\x00"); + EXPECT_DECODE_SLEB128_EQ(0x7fL, "\xff\x80\x00"); + EXPECT_DECODE_SLEB128_EQ(0x80L, "\x80\x81\x00"); + EXPECT_DECODE_SLEB128_EQ(0x80L, "\x80\x81\x80\x00"); + +#undef EXPECT_DECODE_SLEB128_EQ +} + TEST(LEB128Test, SLEB128Size) { // Positive Value Testing Plan: // (1) 128 ^ n - 1 ........ need (n+1) bytes -- 2.34.1