diff options
author | Fangrui Song <maskray@google.com> | 2020-01-11 15:06:02 -0800 |
---|---|---|
committer | Fangrui Song <maskray@google.com> | 2020-01-11 15:43:26 -0800 |
commit | 1e8ce7492e91aa6db269334d12187c7ae854dccb (patch) | |
tree | ac03314f1d730c66584f5ab7a783c5fd685259f5 | |
parent | 6fdd6a7b3f696972edc244488f59532d05136a27 (diff) | |
download | bcm5719-llvm-1e8ce7492e91aa6db269334d12187c7ae854dccb.tar.gz bcm5719-llvm-1e8ce7492e91aa6db269334d12187c7ae854dccb.zip |
[X86][Disassembler] Optimize argument passing and immediate reading
3 files changed, 41 insertions, 74 deletions
diff --git a/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp b/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp index be03dd77745..4e929d586d8 100644 --- a/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp +++ b/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp @@ -177,33 +177,35 @@ MCDisassembler::DecodeStatus X86GenericDisassembler::getInstruction( raw_ostream &CStream) const { CommentStream = &CStream; - InternalInstruction InternalInstr; + InternalInstruction Insn; + memset(&Insn, 0, sizeof(InternalInstruction)); + Insn.bytes = Bytes; + Insn.startLocation = Address; + Insn.readerCursor = Address; + Insn.mode = fMode; - std::pair<ArrayRef<uint8_t>, uint64_t> R(Bytes, Address); - - int Ret = decodeInstruction(&InternalInstr, &R, (const void *)MII.get(), - Address, fMode); + int Ret = decodeInstruction(&Insn, MII.get()); if (Ret) { - Size = InternalInstr.readerCursor - Address; + Size = Insn.readerCursor - Address; return Fail; } else { - Size = InternalInstr.length; - bool Ret = translateInstruction(Instr, InternalInstr, this); + Size = Insn.length; + bool Ret = translateInstruction(Instr, Insn, this); if (!Ret) { unsigned Flags = X86::IP_NO_PREFIX; - if (InternalInstr.hasAdSize) + if (Insn.hasAdSize) Flags |= X86::IP_HAS_AD_SIZE; - if (!InternalInstr.mandatoryPrefix) { - if (InternalInstr.hasOpSize) + if (!Insn.mandatoryPrefix) { + if (Insn.hasOpSize) Flags |= X86::IP_HAS_OP_SIZE; - if (InternalInstr.repeatPrefix == 0xf2) + if (Insn.repeatPrefix == 0xf2) Flags |= X86::IP_HAS_REPEAT_NE; - else if (InternalInstr.repeatPrefix == 0xf3 && + else if (Insn.repeatPrefix == 0xf3 && // It should not be 'pause' f3 90 - InternalInstr.opcode != 0x90) + Insn.opcode != 0x90) Flags |= X86::IP_HAS_REPEAT; - if (InternalInstr.hasLockPrefix) + if (Insn.hasLockPrefix) Flags |= X86::IP_HAS_LOCK; } Instr.setFlags(Flags); diff --git a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp index cf0f474eea0..7ab9e8f60f7 100644 --- a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp +++ b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp @@ -18,11 +18,13 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include <cassert> #include <cstdarg> /* for va_*() */ #include <cstdio> /* for vsnprintf() */ #include <cstdlib> /* for exit() */ #include <cstring> /* for memset() */ +using namespace llvm; using namespace llvm::X86Disassembler; #define DEBUG_TYPE "x86-disassembler" @@ -196,12 +198,11 @@ static const struct InstructionSpecifier *specifierForUID(InstrUID uid) { } static bool peek(struct InternalInstruction *insn, uint8_t &byte) { - auto *r = static_cast<const std::pair<llvm::ArrayRef<uint8_t>, uint64_t> *>( - insn->readerArg); - uint64_t offset = insn->readerCursor - r->second; - if (offset >= r->first.size()) + auto r = insn->bytes; + uint64_t offset = insn->readerCursor - insn->startLocation; + if (offset >= r.size()) return true; - byte = r->first[offset]; + byte = r[offset]; return false; } @@ -211,14 +212,13 @@ static void unconsumeByte(struct InternalInstruction* insn) { template <typename T> static bool consume(InternalInstruction *insn, T &ptr) { - auto *r = static_cast<const std::pair<llvm::ArrayRef<uint8_t>, uint64_t> *>( - insn->readerArg); - uint64_t offset = insn->readerCursor - r->second; - if (offset + sizeof(T) > r->first.size()) + auto r = insn->bytes; + uint64_t offset = insn->readerCursor - insn->startLocation; + if (offset + sizeof(T) > r.size()) return true; T ret = 0; for (unsigned i = 0; i < sizeof(T); ++i) - ret |= (uint64_t)r->first[offset + i] << (i * 8); + ret |= (uint64_t)r[offset + i] << (i * 8); ptr = ret; insn->readerCursor += sizeof(T); return false; @@ -774,7 +774,7 @@ static bool is64Bit(const char *name) { * @return - 0 if the ModR/M could be read when needed or was not needed; * nonzero otherwise. */ -static int getID(struct InternalInstruction* insn, const void *miiArg) { +static int getID(struct InternalInstruction* insn, const MCInstrInfo *miiArg) { uint16_t attrMask; uint16_t instructionID; @@ -1553,15 +1553,9 @@ static int readImmediate(struct InternalInstruction* insn, uint8_t size) { dbgprintf(insn, "readImmediate()"); - if (insn->numImmediatesConsumed == 2) { - debug("Already consumed two immediates"); - return -1; - } + assert(insn->numImmediatesConsumed < 2 && "Already consumed two immediates"); - if (size == 0) - size = insn->immediateSize; - else - insn->immediateSize = size; + insn->immediateSize = size; insn->immediateOffset = insn->readerCursor - insn->startLocation; switch (size) { @@ -1585,6 +1579,8 @@ static int readImmediate(struct InternalInstruction* insn, uint8_t size) { return -1; insn->immediates[insn->numImmediatesConsumed] = imm64; break; + default: + llvm_unreachable("invalid size"); } insn->numImmediatesConsumed++; @@ -1811,36 +1807,13 @@ static int readOperands(struct InternalInstruction* insn) { * decodeInstruction - Reads and interprets a full instruction provided by the * user. * - * @param insn - A pointer to the instruction to be populated. Must be - * pre-allocated. - * @param reader - The function to be used to read the instruction's bytes. - * @param readerArg - A generic argument to be passed to the reader to store - * any internal state. - * @param startLoc - The address (in the reader's address space) of the first - * byte in the instruction. - * @param mode - The mode (real mode, IA-32e, or IA-32e in 64-bit mode) to - * decode the instruction in. * @return - 0 if the instruction's memory could be read; nonzero if * not. */ int llvm::X86Disassembler::decodeInstruction(struct InternalInstruction *insn, - const void *readerArg, - const void *miiArg, - uint64_t startLoc, - DisassemblerMode mode) { - memset(insn, 0, sizeof(struct InternalInstruction)); - - insn->readerArg = readerArg; - insn->startLocation = startLoc; - insn->readerCursor = startLoc; - insn->mode = mode; - insn->numImmediatesConsumed = 0; - - if (readPrefixes(insn) || - readOpcode(insn) || - getID(insn, miiArg) || - insn->instructionID == 0 || - readOperands(insn)) + const MCInstrInfo *mii) { + if (readPrefixes(insn) || readOpcode(insn) || getID(insn, mii) || + insn->instructionID == 0 || readOperands(insn)) return -1; insn->operands = x86OperandSets[insn->spec->operands]; @@ -1848,7 +1821,7 @@ int llvm::X86Disassembler::decodeInstruction(struct InternalInstruction *insn, insn->length = insn->readerCursor - insn->startLocation; dbgprintf(insn, "Read from 0x%llx to 0x%llx: length %zu", - startLoc, insn->readerCursor, insn->length); + insn->startLocation, insn->readerCursor, insn->length); if (insn->length > 15) dbgprintf(insn, "Instruction exceeds 15-byte limit"); diff --git a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h index a1e036ca7ba..df4085edb81 100644 --- a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h +++ b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h @@ -19,6 +19,9 @@ #include "llvm/Support/X86DisassemblerDecoderCommon.h" namespace llvm { + +class MCInstrInfo; + namespace X86Disassembler { // Accessor functions for various fields of an Intel instruction @@ -530,7 +533,7 @@ struct InstructionSpecifier { /// The x86 internal instruction, which is produced by the decoder. struct InternalInstruction { // Opaque value passed to the reader - const void* readerArg; + llvm::ArrayRef<uint8_t> bytes; // The address of the next byte to read via the reader uint64_t readerCursor; @@ -652,19 +655,8 @@ struct InternalInstruction { /// Decode one instruction and store the decoding results in /// a buffer provided by the consumer. -/// \param insn The buffer to store the instruction in. Allocated by the -/// consumer. -/// \param readerArg An argument to pass to the reader for storing context -/// specific to the consumer. May be NULL. -/// \param startLoc The address (in the reader's address space) of the first -/// byte in the instruction. -/// \param mode The mode (16-bit, 32-bit, 64-bit) to decode in. /// \return Nonzero if there was an error during decode, 0 otherwise. -int decodeInstruction(InternalInstruction *insn, - const void *readerArg, - const void *miiArg, - uint64_t startLoc, - DisassemblerMode mode); +int decodeInstruction(InternalInstruction *insn, const MCInstrInfo *mii); /// Print a message to debugs() /// \param file The name of the file printing the debug message. |