From fc1a161d76f5cc0204bed3bce3e27cf36ac76d22 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Tue, 14 Aug 2012 19:06:05 +0000 Subject: Switch the fixed-length disassembler to be table-driven. Refactor the TableGen'erated fixed length disassemblmer to use a table-driven state machine rather than a massive set of nested switch() statements. As a result, the ARM Disassembler (ARMDisassembler.cpp) builds much more quickly and generates a smaller end result. For a Release+Asserts build on a 16GB 3.4GHz i7 iMac w/ SSD: Time to compile at -O2 (averaged w/ hot caches): Previous: 35.5s New: 8.9s TEXT size: Previous: 447,251 New: 297,661 Builds in 25% of the time previously required and generates code 66% of the size. Execution time of the disassembler is only slightly slower (7% disassembling 10 million ARM instructions, 19.6s vs 21.0s). The new implementation has not yet been tuned, however, so the performance should almost certainly be recoverable should it become a concern. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161888 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/LEB128.h | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) (limited to 'include/llvm/Support/LEB128.h') diff --git a/include/llvm/Support/LEB128.h b/include/llvm/Support/LEB128.h index 00c7eeaebc..410edd4dc7 100644 --- a/include/llvm/Support/LEB128.h +++ b/include/llvm/Support/LEB128.h @@ -19,7 +19,7 @@ namespace llvm { -/// Utility function to encode a SLEB128 value. +/// Utility function to encode a SLEB128 value to an output stream. static inline void encodeSLEB128(int64_t Value, raw_ostream &OS) { bool More; do { @@ -34,7 +34,7 @@ static inline void encodeSLEB128(int64_t Value, raw_ostream &OS) { } while (More); } -/// Utility function to encode a ULEB128 value. +/// Utility function to encode a ULEB128 value to an output stream. static inline void encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned Padding = 0) { do { @@ -53,6 +53,43 @@ static inline void encodeULEB128(uint64_t Value, raw_ostream &OS, } } +/// Utility function to encode a ULEB128 value to a buffer. Returns +/// the length in bytes of the encoded value. +static inline unsigned encodeULEB128(uint64_t Value, uint8_t *p, + unsigned Padding = 0) { + uint8_t *orig_p = p; + do { + uint8_t Byte = Value & 0x7f; + Value >>= 7; + if (Value != 0 || Padding != 0) + Byte |= 0x80; // Mark this byte that that more bytes will follow. + *p++ = Byte; + } while (Value != 0); + + // Pad with 0x80 and emit a null byte at the end. + if (Padding != 0) { + for (; Padding != 1; --Padding) + *p++ = '\x80'; + *p++ = '\x00'; + } + return (unsigned)(p - orig_p); +} + + +/// Utility function to decode a ULEB128 value. +static inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = 0) { + const uint8_t *orig_p = p; + uint64_t Value = 0; + unsigned Shift = 0; + do { + Value += (*p & 0x7f) << Shift; + Shift += 7; + } while (*p++ >= 128); + if (n) + *n = (unsigned)(p - orig_p); + return Value; +} + } // namespace llvm #endif // LLVM_SYSTEM_LEB128_H -- cgit v1.2.3