diff options
author | Jim Grosbach <grosbach@apple.com> | 2012-08-14 19:06:05 +0000 |
---|---|---|
committer | Jim Grosbach <grosbach@apple.com> | 2012-08-14 19:06:05 +0000 |
commit | fc1a161d76f5cc0204bed3bce3e27cf36ac76d22 (patch) | |
tree | 69aeac2bd5434ab916120625dec8e86678d4d203 /include | |
parent | d7a85b17bdbb4cb3c3551e533d7b01984ad28a2f (diff) | |
download | external_llvm-fc1a161d76f5cc0204bed3bce3e27cf36ac76d22.zip external_llvm-fc1a161d76f5cc0204bed3bce3e27cf36ac76d22.tar.gz external_llvm-fc1a161d76f5cc0204bed3bce3e27cf36ac76d22.tar.bz2 |
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
Diffstat (limited to 'include')
-rw-r--r-- | include/llvm/MC/MCFixedLenDisassembler.h | 32 | ||||
-rw-r--r-- | include/llvm/Support/LEB128.h | 41 |
2 files changed, 71 insertions, 2 deletions
diff --git a/include/llvm/MC/MCFixedLenDisassembler.h b/include/llvm/MC/MCFixedLenDisassembler.h new file mode 100644 index 0000000..22b3c32 --- /dev/null +++ b/include/llvm/MC/MCFixedLenDisassembler.h @@ -0,0 +1,32 @@ +//===-- llvm/MC/MCFixedLenDisassembler.h - Decoder driver -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Fixed length disassembler decoder state machine driver. +//===----------------------------------------------------------------------===// +#ifndef MCFIXEDLENDISASSEMBLER_H +#define MCFIXEDLENDISASSEMBLER_H + +namespace llvm { + +namespace MCD { +// Disassembler state machine opcodes. +enum DecoderOps { + OPC_ExtractField = 1, // OPC_ExtractField(uint8_t Start, uint8_t Len) + OPC_FilterValue, // OPC_FilterValue(uleb128 Val, uint16_t NumToSkip) + OPC_CheckField, // OPC_CheckField(uint8_t Start, uint8_t Len, + // uleb128 Val, uint16_t NumToSkip) + OPC_CheckPredicate, // OPC_CheckPredicate(uleb128 PIdx, uint16_t NumToSkip) + OPC_Decode, // OPC_Decode(uleb128 Opcode, uleb128 DIdx) + OPC_SoftFail, // OPC_SoftFail(uleb128 PMask, uleb128 NMask) + OPC_Fail // OPC_Fail() +}; + +} // namespace MCDecode +} // namespace llvm + +#endif diff --git a/include/llvm/Support/LEB128.h b/include/llvm/Support/LEB128.h index 00c7eea..410edd4 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 |