Browse Source

Change encodeU/SLEB128 to pad to certain number of bytes

Previously the 'Padding' argument was the number of padding
bytes to add. However most callers that use 'Padding' know
how many overall bytes they need to write.  With the previous
code this would mean encoding the LEB once to find out how
many bytes it would occupy and then using this to calulate
the 'Padding' value.

See: https://reviews.llvm.org/D36595

Differential Revision: https://reviews.llvm.org/D37494

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313393 91177308-0d34-0410-b5e6-96231b3b80d8
Sam Clegg 8 năm trước cách đây
mục cha
commit
fa690d4e1c

+ 6 - 2
include/llvm/CodeGen/AsmPrinter.h

@@ -487,8 +487,12 @@ public:
   void EmitSLEB128(int64_t Value, const char *Desc = nullptr) const;
   void EmitSLEB128(int64_t Value, const char *Desc = nullptr) const;
 
 
   /// Emit the specified unsigned leb128 value.
   /// Emit the specified unsigned leb128 value.
-  void EmitULEB128(uint64_t Value, const char *Desc = nullptr,
-                   unsigned PadTo = 0) const;
+  void EmitULEB128(uint64_t Value, const char *Desc = nullptr) const;
+
+  /// Emit the specified unsigned leb128 value padded to a specific number
+  /// bytes
+  void EmitPaddedULEB128(uint64_t Value, unsigned PadTo,
+                         const char *Desc = nullptr) const;
 
 
   /// Emit a .byte 42 directive that corresponds to an encoding.  If verbose
   /// Emit a .byte 42 directive that corresponds to an encoding.  If verbose
   /// assembly output is enabled, we output comments describing the encoding.
   /// assembly output is enabled, we output comments describing the encoding.

+ 5 - 1
include/llvm/MC/MCStreamer.h

@@ -578,7 +578,11 @@ public:
 
 
   /// \brief Special case of EmitULEB128Value that avoids the client having to
   /// \brief Special case of EmitULEB128Value that avoids the client having to
   /// pass in a MCExpr for constant integers.
   /// pass in a MCExpr for constant integers.
-  void EmitULEB128IntValue(uint64_t Value, unsigned Padding = 0);
+  void EmitULEB128IntValue(uint64_t Value);
+
+  /// \brief Like EmitULEB128Value but pads the output to specific number of
+  /// bytes.
+  void EmitPaddedULEB128IntValue(uint64_t Value, unsigned PadTo);
 
 
   /// \brief Special case of EmitSLEB128Value that avoids the client having to
   /// \brief Special case of EmitSLEB128Value that avoids the client having to
   /// pass in a MCExpr for constant integers.
   /// pass in a MCExpr for constant integers.

+ 26 - 16
include/llvm/Support/LEB128.h

@@ -21,23 +21,25 @@ namespace llvm {
 
 
 /// Utility function to encode a SLEB128 value to an output stream.
 /// Utility function to encode a SLEB128 value to an output stream.
 inline void encodeSLEB128(int64_t Value, raw_ostream &OS,
 inline void encodeSLEB128(int64_t Value, raw_ostream &OS,
-                          unsigned Padding = 0) {
+                          unsigned PadTo = 0) {
   bool More;
   bool More;
+  unsigned Count = 0;
   do {
   do {
     uint8_t Byte = Value & 0x7f;
     uint8_t Byte = Value & 0x7f;
     // NOTE: this assumes that this signed shift is an arithmetic right shift.
     // NOTE: this assumes that this signed shift is an arithmetic right shift.
     Value >>= 7;
     Value >>= 7;
     More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
     More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
               ((Value == -1) && ((Byte & 0x40) != 0))));
               ((Value == -1) && ((Byte & 0x40) != 0))));
-    if (More || Padding != 0)
+    Count++;
+    if (More || Count < PadTo)
       Byte |= 0x80; // Mark this byte to show that more bytes will follow.
       Byte |= 0x80; // Mark this byte to show that more bytes will follow.
     OS << char(Byte);
     OS << char(Byte);
   } while (More);
   } while (More);
 
 
   // Pad with 0x80 and emit a terminating byte at the end.
   // Pad with 0x80 and emit a terminating byte at the end.
-  if (Padding != 0) {
+  if (Count < PadTo) {
     uint8_t PadValue = Value < 0 ? 0x7f : 0x00;
     uint8_t PadValue = Value < 0 ? 0x7f : 0x00;
-    for (; Padding != 1; --Padding)
+    for (; Count < PadTo - 1; ++Count)
       OS << char(PadValue | 0x80);
       OS << char(PadValue | 0x80);
     OS << char(PadValue);
     OS << char(PadValue);
   }
   }
@@ -45,8 +47,9 @@ inline void encodeSLEB128(int64_t Value, raw_ostream &OS,
 
 
 /// Utility function to encode a SLEB128 value to a buffer. Returns
 /// Utility function to encode a SLEB128 value to a buffer. Returns
 /// the length in bytes of the encoded value.
 /// the length in bytes of the encoded value.
-inline unsigned encodeSLEB128(int64_t Value, uint8_t *p, unsigned Padding = 0) {
+inline unsigned encodeSLEB128(int64_t Value, uint8_t *p, unsigned PadTo = 0) {
   uint8_t *orig_p = p;
   uint8_t *orig_p = p;
+  unsigned Count = 0;
   bool More;
   bool More;
   do {
   do {
     uint8_t Byte = Value & 0x7f;
     uint8_t Byte = Value & 0x7f;
@@ -54,15 +57,16 @@ inline unsigned encodeSLEB128(int64_t Value, uint8_t *p, unsigned Padding = 0) {
     Value >>= 7;
     Value >>= 7;
     More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
     More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
               ((Value == -1) && ((Byte & 0x40) != 0))));
               ((Value == -1) && ((Byte & 0x40) != 0))));
-    if (More || Padding != 0)
+    Count++;
+    if (More || Count < PadTo)
       Byte |= 0x80; // Mark this byte to show that more bytes will follow.
       Byte |= 0x80; // Mark this byte to show that more bytes will follow.
     *p++ = Byte;
     *p++ = Byte;
   } while (More);
   } while (More);
 
 
   // Pad with 0x80 and emit a terminating byte at the end.
   // Pad with 0x80 and emit a terminating byte at the end.
-  if (Padding != 0) {
+  if (Count < PadTo) {
     uint8_t PadValue = Value < 0 ? 0x7f : 0x00;
     uint8_t PadValue = Value < 0 ? 0x7f : 0x00;
-    for (; Padding != 1; --Padding)
+    for (; Count < PadTo - 1; ++Count)
       *p++ = (PadValue | 0x80);
       *p++ = (PadValue | 0x80);
     *p++ = PadValue;
     *p++ = PadValue;
   }
   }
@@ -71,42 +75,48 @@ inline unsigned encodeSLEB128(int64_t Value, uint8_t *p, unsigned Padding = 0) {
 
 
 /// Utility function to encode a ULEB128 value to an output stream.
 /// Utility function to encode a ULEB128 value to an output stream.
 inline void encodeULEB128(uint64_t Value, raw_ostream &OS,
 inline void encodeULEB128(uint64_t Value, raw_ostream &OS,
-                          unsigned Padding = 0) {
+                          unsigned PadTo = 0) {
+  unsigned Count = 0;
   do {
   do {
     uint8_t Byte = Value & 0x7f;
     uint8_t Byte = Value & 0x7f;
     Value >>= 7;
     Value >>= 7;
-    if (Value != 0 || Padding != 0)
+    Count++;
+    if (Value != 0 || Count < PadTo)
       Byte |= 0x80; // Mark this byte to show that more bytes will follow.
       Byte |= 0x80; // Mark this byte to show that more bytes will follow.
     OS << char(Byte);
     OS << char(Byte);
   } while (Value != 0);
   } while (Value != 0);
 
 
   // Pad with 0x80 and emit a null byte at the end.
   // Pad with 0x80 and emit a null byte at the end.
-  if (Padding != 0) {
-    for (; Padding != 1; --Padding)
+  if (Count < PadTo) {
+    for (; Count < PadTo - 1; ++Count)
       OS << '\x80';
       OS << '\x80';
     OS << '\x00';
     OS << '\x00';
+    Count++;
   }
   }
 }
 }
 
 
 /// Utility function to encode a ULEB128 value to a buffer. Returns
 /// Utility function to encode a ULEB128 value to a buffer. Returns
 /// the length in bytes of the encoded value.
 /// the length in bytes of the encoded value.
 inline unsigned encodeULEB128(uint64_t Value, uint8_t *p,
 inline unsigned encodeULEB128(uint64_t Value, uint8_t *p,
-                              unsigned Padding = 0) {
+                              unsigned PadTo = 0) {
   uint8_t *orig_p = p;
   uint8_t *orig_p = p;
+  unsigned Count = 0;
   do {
   do {
     uint8_t Byte = Value & 0x7f;
     uint8_t Byte = Value & 0x7f;
     Value >>= 7;
     Value >>= 7;
-    if (Value != 0 || Padding != 0)
+    Count++;
+    if (Value != 0 || Count < PadTo)
       Byte |= 0x80; // Mark this byte to show that more bytes will follow.
       Byte |= 0x80; // Mark this byte to show that more bytes will follow.
     *p++ = Byte;
     *p++ = Byte;
   } while (Value != 0);
   } while (Value != 0);
 
 
   // Pad with 0x80 and emit a null byte at the end.
   // Pad with 0x80 and emit a null byte at the end.
-  if (Padding != 0) {
-    for (; Padding != 1; --Padding)
+  if (Count < PadTo) {
+    for (; Count < PadTo - 1; ++Count)
       *p++ = '\x80';
       *p++ = '\x80';
     *p++ = '\x00';
     *p++ = '\x00';
   }
   }
+
   return (unsigned)(p - orig_p);
   return (unsigned)(p - orig_p);
 }
 }
 
 

+ 10 - 3
lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp

@@ -48,12 +48,19 @@ void AsmPrinter::EmitSLEB128(int64_t Value, const char *Desc) const {
 }
 }
 
 
 /// EmitULEB128 - emit the specified unsigned leb128 value.
 /// EmitULEB128 - emit the specified unsigned leb128 value.
-void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc,
-                             unsigned PadTo) const {
+void AsmPrinter::EmitPaddedULEB128(uint64_t Value, unsigned PadTo,
+                                   const char *Desc) const {
   if (isVerbose() && Desc)
   if (isVerbose() && Desc)
     OutStreamer->AddComment(Desc);
     OutStreamer->AddComment(Desc);
 
 
-  OutStreamer->EmitULEB128IntValue(Value, PadTo);
+  OutStreamer->EmitPaddedULEB128IntValue(Value, PadTo);
+}
+
+void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc) const {
+  if (isVerbose() && Desc)
+    OutStreamer->AddComment(Desc);
+
+  OutStreamer->EmitULEB128IntValue(Value);
 }
 }
 
 
 static const char *DecodeDWARFEncoding(unsigned Encoding) {
 static const char *DecodeDWARFEncoding(unsigned Encoding) {

+ 10 - 5
lib/CodeGen/AsmPrinter/EHStreamer.cpp

@@ -478,13 +478,14 @@ void EHStreamer::emitExceptionTable() {
     sizeof(int8_t) +                            // TType format
     sizeof(int8_t) +                            // TType format
     (HaveTTData ? TTypeBaseOffsetSize : 0) +    // TType base offset size
     (HaveTTData ? TTypeBaseOffsetSize : 0) +    // TType base offset size
     TTypeBaseOffset;                            // TType base offset
     TTypeBaseOffset;                            // TType base offset
-  unsigned SizeAlign = (4 - TotalSize) & 3;
+  unsigned PadBytes = (4 - TotalSize) & 3;
 
 
   if (HaveTTData) {
   if (HaveTTData) {
     // Account for any extra padding that will be added to the call site table
     // Account for any extra padding that will be added to the call site table
     // length.
     // length.
-    Asm->EmitULEB128(TTypeBaseOffset, "@TType base offset", SizeAlign);
-    SizeAlign = 0;
+    Asm->EmitPaddedULEB128(TTypeBaseOffset, TTypeBaseOffsetSize + PadBytes,
+                           "@TType base offset");
+    PadBytes = 0;
   }
   }
 
 
   bool VerboseAsm = Asm->OutStreamer->isVerboseAsm();
   bool VerboseAsm = Asm->OutStreamer->isVerboseAsm();
@@ -494,7 +495,9 @@ void EHStreamer::emitExceptionTable() {
     Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
     Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
 
 
     // Add extra padding if it wasn't added to the TType base offset.
     // Add extra padding if it wasn't added to the TType base offset.
-    Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign);
+    Asm->EmitPaddedULEB128(CallSiteTableLength,
+                           CallSiteTableLengthSize + PadBytes,
+                           "Call site table length");
 
 
     // Emit the landing pad site information.
     // Emit the landing pad site information.
     unsigned idx = 0;
     unsigned idx = 0;
@@ -547,7 +550,9 @@ void EHStreamer::emitExceptionTable() {
     Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
     Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
 
 
     // Add extra padding if it wasn't added to the TType base offset.
     // Add extra padding if it wasn't added to the TType base offset.
-    Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign);
+    Asm->EmitPaddedULEB128(CallSiteTableLength,
+                           CallSiteTableLengthSize + PadBytes,
+                           "Call site table length");
 
 
     unsigned Entry = 0;
     unsigned Entry = 0;
     for (SmallVectorImpl<CallSiteEntry>::const_iterator
     for (SmallVectorImpl<CallSiteEntry>::const_iterator

+ 6 - 2
lib/MC/MCStreamer.cpp

@@ -105,13 +105,17 @@ void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size) {
 
 
 /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the
 /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the
 /// client having to pass in a MCExpr for constant integers.
 /// client having to pass in a MCExpr for constant integers.
-void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned Padding) {
+void MCStreamer::EmitPaddedULEB128IntValue(uint64_t Value, unsigned PadTo) {
   SmallString<128> Tmp;
   SmallString<128> Tmp;
   raw_svector_ostream OSE(Tmp);
   raw_svector_ostream OSE(Tmp);
-  encodeULEB128(Value, OSE, Padding);
+  encodeULEB128(Value, OSE, PadTo);
   EmitBytes(OSE.str());
   EmitBytes(OSE.str());
 }
 }
 
 
+void MCStreamer::EmitULEB128IntValue(uint64_t Value) {
+  EmitPaddedULEB128IntValue(Value, 0);
+}
+
 /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the
 /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the
 /// client having to pass in a MCExpr for constant integers.
 /// client having to pass in a MCExpr for constant integers.
 void MCStreamer::EmitSLEB128IntValue(int64_t Value) {
 void MCStreamer::EmitSLEB128IntValue(int64_t Value) {

+ 3 - 16
lib/MC/WasmObjectWriter.cpp

@@ -297,16 +297,6 @@ private:
 
 
 WasmObjectWriter::~WasmObjectWriter() {}
 WasmObjectWriter::~WasmObjectWriter() {}
 
 
-// Return the padding size to write a 32-bit value into a 5-byte ULEB128.
-static unsigned PaddingFor5ByteULEB128(uint32_t X) {
-  return X == 0 ? 4 : (4u - (31u - countLeadingZeros(X)) / 7u);
-}
-
-// Return the padding size to write a 32-bit value into a 5-byte SLEB128.
-static unsigned PaddingFor5ByteSLEB128(int32_t X) {
-  return 5 - getSLEB128Size(X);
-}
-
 // Write out a section header and a patchable section size field.
 // Write out a section header and a patchable section size field.
 void WasmObjectWriter::startSection(SectionBookkeeping &Section,
 void WasmObjectWriter::startSection(SectionBookkeeping &Section,
                                     unsigned SectionId,
                                     unsigned SectionId,
@@ -341,12 +331,11 @@ void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
     report_fatal_error("section size does not fit in a uint32_t");
     report_fatal_error("section size does not fit in a uint32_t");
 
 
   DEBUG(dbgs() << "endSection size=" << Size << "\n");
   DEBUG(dbgs() << "endSection size=" << Size << "\n");
-  unsigned Padding = PaddingFor5ByteULEB128(Size);
 
 
   // Write the final section size to the payload_len field, which follows
   // Write the final section size to the payload_len field, which follows
   // the section id byte.
   // the section id byte.
   uint8_t Buffer[16];
   uint8_t Buffer[16];
-  unsigned SizeLen = encodeULEB128(Size, Buffer, Padding);
+  unsigned SizeLen = encodeULEB128(Size, Buffer, 5);
   assert(SizeLen == 5);
   assert(SizeLen == 5);
   getStream().pwrite((char *)Buffer, SizeLen, Section.SizeOffset);
   getStream().pwrite((char *)Buffer, SizeLen, Section.SizeOffset);
 }
 }
@@ -453,8 +442,7 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
 static void
 static void
 WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
 WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
   uint8_t Buffer[5];
   uint8_t Buffer[5];
-  unsigned Padding = PaddingFor5ByteULEB128(X);
-  unsigned SizeLen = encodeULEB128(X, Buffer, Padding);
+  unsigned SizeLen = encodeULEB128(X, Buffer, 5);
   assert(SizeLen == 5);
   assert(SizeLen == 5);
   Stream.pwrite((char *)Buffer, SizeLen, Offset);
   Stream.pwrite((char *)Buffer, SizeLen, Offset);
 }
 }
@@ -464,8 +452,7 @@ WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
 static void
 static void
 WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, uint64_t Offset) {
 WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, uint64_t Offset) {
   uint8_t Buffer[5];
   uint8_t Buffer[5];
-  unsigned Padding = PaddingFor5ByteSLEB128(X);
-  unsigned SizeLen = encodeSLEB128(X, Buffer, Padding);
+  unsigned SizeLen = encodeSLEB128(X, Buffer, 5);
   assert(SizeLen == 5);
   assert(SizeLen == 5);
   Stream.pwrite((char *)Buffer, SizeLen, Offset);
   Stream.pwrite((char *)Buffer, SizeLen, Offset);
 }
 }

+ 2 - 5
lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp

@@ -116,10 +116,9 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
     } else if (MO.isExpr()) {
     } else if (MO.isExpr()) {
       const MCOperandInfo &Info = Desc.OpInfo[i];
       const MCOperandInfo &Info = Desc.OpInfo[i];
       llvm::MCFixupKind FixupKind;
       llvm::MCFixupKind FixupKind;
-      size_t PaddedSize;
+      size_t PaddedSize = 5;
       if (Info.OperandType == WebAssembly::OPERAND_I32IMM) {
       if (Info.OperandType == WebAssembly::OPERAND_I32IMM) {
         FixupKind = MCFixupKind(WebAssembly::fixup_code_sleb128_i32);
         FixupKind = MCFixupKind(WebAssembly::fixup_code_sleb128_i32);
-        PaddedSize = 5;
       } else if (Info.OperandType == WebAssembly::OPERAND_I64IMM) {
       } else if (Info.OperandType == WebAssembly::OPERAND_I64IMM) {
         FixupKind = MCFixupKind(WebAssembly::fixup_code_sleb128_i64);
         FixupKind = MCFixupKind(WebAssembly::fixup_code_sleb128_i64);
         PaddedSize = 10;
         PaddedSize = 10;
@@ -127,10 +126,8 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
                  Info.OperandType == WebAssembly::OPERAND_OFFSET32 ||
                  Info.OperandType == WebAssembly::OPERAND_OFFSET32 ||
                  Info.OperandType == WebAssembly::OPERAND_TYPEINDEX) {
                  Info.OperandType == WebAssembly::OPERAND_TYPEINDEX) {
         FixupKind = MCFixupKind(WebAssembly::fixup_code_uleb128_i32);
         FixupKind = MCFixupKind(WebAssembly::fixup_code_uleb128_i32);
-        PaddedSize = 5;
       } else if (Info.OperandType == WebAssembly::OPERAND_GLOBAL) {
       } else if (Info.OperandType == WebAssembly::OPERAND_GLOBAL) {
         FixupKind = MCFixupKind(WebAssembly::fixup_code_global_index);
         FixupKind = MCFixupKind(WebAssembly::fixup_code_global_index);
-        PaddedSize = 5;
       } else {
       } else {
         llvm_unreachable("unexpected symbolic operand kind");
         llvm_unreachable("unexpected symbolic operand kind");
       }
       }
@@ -138,7 +135,7 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
           OS.tell() - Start, MO.getExpr(),
           OS.tell() - Start, MO.getExpr(),
           FixupKind, MI.getLoc()));
           FixupKind, MI.getLoc()));
       ++MCNumFixups;
       ++MCNumFixups;
-      encodeULEB128(0, OS, PaddedSize - 1);
+      encodeULEB128(0, OS, PaddedSize);
     } else {
     } else {
       llvm_unreachable("unexpected operand kind");
       llvm_unreachable("unexpected operand kind");
     }
     }

+ 17 - 16
unittests/Support/LEB128Test.cpp

@@ -46,16 +46,17 @@ TEST(LEB128Test, EncodeSLEB128) {
   EXPECT_SLEB128_EQ("\xc0\x00", 64, 0);
   EXPECT_SLEB128_EQ("\xc0\x00", 64, 0);
 
 
   // Encode SLEB128 with some extra padding bytes
   // Encode SLEB128 with some extra padding bytes
-  EXPECT_SLEB128_EQ("\x80\x00", 0, 1);
-  EXPECT_SLEB128_EQ("\x80\x80\x00", 0, 2);
-  EXPECT_SLEB128_EQ("\xff\x80\x00", 0x7f, 1);
-  EXPECT_SLEB128_EQ("\xff\x80\x80\x00", 0x7f, 2);
-  EXPECT_SLEB128_EQ("\x80\x81\x00", 0x80, 1);
-  EXPECT_SLEB128_EQ("\x80\x81\x80\x00", 0x80, 2);
-  EXPECT_SLEB128_EQ("\xc0\x7f", -0x40, 1);
-  EXPECT_SLEB128_EQ("\xc0\xff\x7f", -0x40, 2);
-  EXPECT_SLEB128_EQ("\x80\xff\x7f", -0x80, 1);
-  EXPECT_SLEB128_EQ("\x80\xff\xff\x7f", -0x80, 2);
+  EXPECT_SLEB128_EQ("\x80\x00", 0, 2);
+  EXPECT_SLEB128_EQ("\x80\x80\x00", 0, 3);
+  EXPECT_SLEB128_EQ("\xff\x80\x00", 0x7f, 3);
+  EXPECT_SLEB128_EQ("\xff\x80\x80\x00", 0x7f, 4);
+  EXPECT_SLEB128_EQ("\x80\x81\x00", 0x80, 3);
+  EXPECT_SLEB128_EQ("\x80\x81\x80\x00", 0x80, 4);
+  EXPECT_SLEB128_EQ("\xc0\x7f", -0x40, 2);
+
+  EXPECT_SLEB128_EQ("\xc0\xff\x7f", -0x40, 3);
+  EXPECT_SLEB128_EQ("\x80\xff\x7f", -0x80, 3);
+  EXPECT_SLEB128_EQ("\x80\xff\xff\x7f", -0x80, 4);
 
 
 #undef EXPECT_SLEB128_EQ
 #undef EXPECT_SLEB128_EQ
 }
 }
@@ -93,12 +94,12 @@ TEST(LEB128Test, EncodeULEB128) {
   EXPECT_ULEB128_EQ("\x81\x02", 0x101, 0);
   EXPECT_ULEB128_EQ("\x81\x02", 0x101, 0);
 
 
   // Encode ULEB128 with some extra padding bytes
   // Encode ULEB128 with some extra padding bytes
-  EXPECT_ULEB128_EQ("\x80\x00", 0, 1);
-  EXPECT_ULEB128_EQ("\x80\x80\x00", 0, 2);
-  EXPECT_ULEB128_EQ("\xff\x00", 0x7f, 1);
-  EXPECT_ULEB128_EQ("\xff\x80\x00", 0x7f, 2);
-  EXPECT_ULEB128_EQ("\x80\x81\x00", 0x80, 1);
-  EXPECT_ULEB128_EQ("\x80\x81\x80\x00", 0x80, 2);
+  EXPECT_ULEB128_EQ("\x80\x00", 0, 2);
+  EXPECT_ULEB128_EQ("\x80\x80\x00", 0, 3);
+  EXPECT_ULEB128_EQ("\xff\x00", 0x7f, 2);
+  EXPECT_ULEB128_EQ("\xff\x80\x00", 0x7f, 3);
+  EXPECT_ULEB128_EQ("\x80\x81\x00", 0x80, 3);
+  EXPECT_ULEB128_EQ("\x80\x81\x80\x00", 0x80, 4);
 
 
 #undef EXPECT_ULEB128_EQ
 #undef EXPECT_ULEB128_EQ
 }
 }