[Support] add decodeSLEB128()
authorNick Kledzik <kledzik@apple.com>
Mon, 15 Sep 2014 21:51:49 +0000 (21:51 +0000)
committerNick Kledzik <kledzik@apple.com>
Mon, 15 Sep 2014 21:51:49 +0000 (21:51 +0000)
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
unittests/Support/LEB128Test.cpp

index 4dbc5e91a2cdcd9b0a161aaa755b6ba63a5534c6..9e229fbf9cf8d0d14e16c020e9a93ec8bd1704de 100644 (file)
@@ -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);
 
index 14a6d3ff5ad764504f9e8a62ee5c174a73ef1536..76b63e5a8381777e40b0beff961a1a77b5131bf7 100644 (file)
@@ -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<const uint8_t *>(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