diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 | 
| commit | d8e91e46262bc44006913e6796843909f1ac7bcd (patch) | |
| tree | 7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp | |
| parent | b7eb8e35e481a74962664b63dfb09483b200209a (diff) | |
Notes
Diffstat (limited to 'lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp')
| -rw-r--r-- | lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp | 104 | 
1 files changed, 78 insertions, 26 deletions
diff --git a/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp b/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp index 2f0960271e30c..6acc9b20eed20 100644 --- a/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp +++ b/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp @@ -16,7 +16,6 @@  //===----------------------------------------------------------------------===//  #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" -#include "WebAssembly.h"  #include "llvm/MC/MCContext.h"  #include "llvm/MC/MCDisassembler/MCDisassembler.h"  #include "llvm/MC/MCFixedLenDisassembler.h" @@ -37,6 +36,8 @@ using DecodeStatus = MCDisassembler::DecodeStatus;  #include "WebAssemblyGenDisassemblerTables.inc"  namespace { +static constexpr int WebAssemblyInstructionTableSize = 256; +  class WebAssemblyDisassembler final : public MCDisassembler {    std::unique_ptr<const MCInstrInfo> MCII; @@ -75,31 +76,43 @@ static int nextByte(ArrayRef<uint8_t> Bytes, uint64_t &Size) {    return V;  } -static bool parseLEBImmediate(MCInst &MI, uint64_t &Size, -                              ArrayRef<uint8_t> Bytes, bool Signed) { +static bool nextLEB(int64_t &Val, ArrayRef<uint8_t> Bytes, uint64_t &Size, +                    bool Signed = false) {    unsigned N = 0;    const char *Error = nullptr; -  auto Val = Signed ? decodeSLEB128(Bytes.data() + Size, &N, -                                    Bytes.data() + Bytes.size(), &Error) -                    : static_cast<int64_t>( -                          decodeULEB128(Bytes.data() + Size, &N, -                                        Bytes.data() + Bytes.size(), &Error)); +  Val = Signed ? decodeSLEB128(Bytes.data() + Size, &N, +                               Bytes.data() + Bytes.size(), &Error) +               : static_cast<int64_t>(decodeULEB128(Bytes.data() + Size, &N, +                                                    Bytes.data() + Bytes.size(), +                                                    &Error));    if (Error)      return false;    Size += N; +  return true; +} + +static bool parseLEBImmediate(MCInst &MI, uint64_t &Size, +                              ArrayRef<uint8_t> Bytes, bool Signed) { +  int64_t Val; +  if (!nextLEB(Val, Bytes, Size, Signed)) +    return false;    MI.addOperand(MCOperand::createImm(Val));    return true;  }  template <typename T> -bool parseFPImmediate(MCInst &MI, uint64_t &Size, ArrayRef<uint8_t> Bytes) { +bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef<uint8_t> Bytes) {    if (Size + sizeof(T) > Bytes.size())      return false;    T Val;    memcpy(&Val, Bytes.data() + Size, sizeof(T));    support::endian::byte_swap<T, support::endianness::little>(Val);    Size += sizeof(T); -  MI.addOperand(MCOperand::createFPImm(static_cast<double>(Val))); +  if (std::is_floating_point<T>::value) { +    MI.addOperand(MCOperand::createFPImm(static_cast<double>(Val))); +  } else { +    MI.addOperand(MCOperand::createImm(static_cast<int64_t>(Val))); +  }    return true;  } @@ -108,7 +121,7 @@ MCDisassembler::DecodeStatus WebAssemblyDisassembler::getInstruction(      raw_ostream & /*OS*/, raw_ostream &CS) const {    CommentStream = &CS;    Size = 0; -  auto Opc = nextByte(Bytes, Size); +  int Opc = nextByte(Bytes, Size);    if (Opc < 0)      return MCDisassembler::Fail;    const auto *WasmInst = &InstructionTable0[Opc]; @@ -124,10 +137,12 @@ MCDisassembler::DecodeStatus WebAssemblyDisassembler::getInstruction(      }      if (!WasmInst)        return MCDisassembler::Fail; -    Opc = nextByte(Bytes, Size); -    if (Opc < 0) +    int64_t PrefixedOpc; +    if (!nextLEB(PrefixedOpc, Bytes, Size))        return MCDisassembler::Fail; -    WasmInst += Opc; +    if (PrefixedOpc < 0 || PrefixedOpc >= WebAssemblyInstructionTableSize) +      return MCDisassembler::Fail; +    WasmInst += PrefixedOpc;    }    if (WasmInst->ET == ET_Unused)      return MCDisassembler::Fail; @@ -136,7 +151,8 @@ MCDisassembler::DecodeStatus WebAssemblyDisassembler::getInstruction(    MI.setOpcode(WasmInst->Opcode);    // Parse any operands.    for (uint8_t OPI = 0; OPI < WasmInst->NumOperands; OPI++) { -    switch (WasmInst->Operands[OPI]) { +    auto OT = OperandTable[WasmInst->OperandStart + OPI]; +    switch (OT) {      // ULEB operands:      case WebAssembly::OPERAND_BASIC_BLOCK:      case WebAssembly::OPERAND_LOCAL: @@ -152,32 +168,68 @@ MCDisassembler::DecodeStatus WebAssemblyDisassembler::getInstruction(      }      // SLEB operands:      case WebAssembly::OPERAND_I32IMM: -    case WebAssembly::OPERAND_I64IMM: -    case WebAssembly::OPERAND_SIGNATURE: { +    case WebAssembly::OPERAND_I64IMM: {        if (!parseLEBImmediate(MI, Size, Bytes, true))          return MCDisassembler::Fail;        break;      } +    // block_type operands (uint8_t). +    case WebAssembly::OPERAND_SIGNATURE: { +      if (!parseImmediate<uint8_t>(MI, Size, Bytes)) +        return MCDisassembler::Fail; +      break; +    }      // FP operands.      case WebAssembly::OPERAND_F32IMM: { -      if (!parseFPImmediate<float>(MI, Size, Bytes)) +      if (!parseImmediate<float>(MI, Size, Bytes))          return MCDisassembler::Fail;        break;      }      case WebAssembly::OPERAND_F64IMM: { -      if (!parseFPImmediate<double>(MI, Size, Bytes)) +      if (!parseImmediate<double>(MI, Size, Bytes))          return MCDisassembler::Fail;        break;      } -    case MCOI::OPERAND_REGISTER: { -      // These are NOT actually in the instruction stream, but MC is going to -      // expect operands to be present for them! -      // FIXME: can MC re-generate register assignments or do we have to -      // do this? Since this function decodes a single instruction, we don't -      // have the proper context for tracking an operand stack here. -      MI.addOperand(MCOperand::createReg(0)); +    // Vector lane operands (not LEB encoded). +    case WebAssembly::OPERAND_VEC_I8IMM: { +      if (!parseImmediate<uint8_t>(MI, Size, Bytes)) +        return MCDisassembler::Fail; +      break; +    } +    case WebAssembly::OPERAND_VEC_I16IMM: { +      if (!parseImmediate<uint16_t>(MI, Size, Bytes)) +        return MCDisassembler::Fail; +      break; +    } +    case WebAssembly::OPERAND_VEC_I32IMM: { +      if (!parseImmediate<uint32_t>(MI, Size, Bytes)) +        return MCDisassembler::Fail; +      break; +    } +    case WebAssembly::OPERAND_VEC_I64IMM: { +      if (!parseImmediate<uint64_t>(MI, Size, Bytes)) +        return MCDisassembler::Fail; +      break; +    } +    case WebAssembly::OPERAND_BRLIST: { +      int64_t TargetTableLen; +      if (!nextLEB(TargetTableLen, Bytes, Size, false)) +        return MCDisassembler::Fail; +      for (int64_t I = 0; I < TargetTableLen; I++) { +        if (!parseLEBImmediate(MI, Size, Bytes, false)) +          return MCDisassembler::Fail; +      } +      // Default case. +      if (!parseLEBImmediate(MI, Size, Bytes, false)) +        return MCDisassembler::Fail;        break;      } +    case MCOI::OPERAND_REGISTER: +      // The tablegen header currently does not have any register operands since +      // we use only the stack (_S) instructions. +      // If you hit this that probably means a bad instruction definition in +      // tablegen. +      llvm_unreachable("Register operand in WebAssemblyDisassembler");      default:        llvm_unreachable("Unknown operand type in WebAssemblyDisassembler");      }  | 
