[llvm] 1e8ce74 - [X86][Disassembler] Optimize argument passing and immediate reading
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sat Jan 11 15:58:13 PST 2020
Author: Fangrui Song
Date: 2020-01-11T15:43:26-08:00
New Revision: 1e8ce7492e91aa6db269334d12187c7ae854dccb
URL: https://github.com/llvm/llvm-project/commit/1e8ce7492e91aa6db269334d12187c7ae854dccb
DIFF: https://github.com/llvm/llvm-project/commit/1e8ce7492e91aa6db269334d12187c7ae854dccb.diff
LOG: [X86][Disassembler] Optimize argument passing and immediate reading
Added:
Modified:
llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp
llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h
Removed:
################################################################################
diff --git a/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp b/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp
index be03dd777457..4e929d586d82 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 cf0f474eea04..7ab9e8f60f78 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 a1e036ca7ba1..df4085edb818 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.
More information about the llvm-commits
mailing list