LLVM  4.0.0
WebAssemblyDisassembler.cpp
Go to the documentation of this file.
1 //==- WebAssemblyDisassembler.cpp - Disassembler for WebAssembly -*- C++ -*-==//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief This file is part of the WebAssembly Disassembler.
12 ///
13 /// It contains code to translate the data produced by the decoder into
14 /// MCInsts.
15 ///
16 //===----------------------------------------------------------------------===//
17 
18 #include "WebAssembly.h"
20 #include "llvm/MC/MCContext.h"
22 #include "llvm/MC/MCInst.h"
23 #include "llvm/MC/MCInstrInfo.h"
25 #include "llvm/MC/MCSymbol.h"
26 #include "llvm/Support/Endian.h"
28 using namespace llvm;
29 
30 #define DEBUG_TYPE "wasm-disassembler"
31 
32 namespace {
33 class WebAssemblyDisassembler final : public MCDisassembler {
34  std::unique_ptr<const MCInstrInfo> MCII;
35 
36  DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
37  ArrayRef<uint8_t> Bytes, uint64_t Address,
38  raw_ostream &VStream,
39  raw_ostream &CStream) const override;
40 
41 public:
42  WebAssemblyDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
43  std::unique_ptr<const MCInstrInfo> MCII)
44  : MCDisassembler(STI, Ctx), MCII(std::move(MCII)) {}
45 };
46 } // end anonymous namespace
47 
49  const MCSubtargetInfo &STI,
50  MCContext &Ctx) {
51  std::unique_ptr<const MCInstrInfo> MCII(T.createMCInstrInfo());
52  return new WebAssemblyDisassembler(STI, Ctx, std::move(MCII));
53 }
54 
56  // Register the disassembler for each target.
61 }
62 
63 MCDisassembler::DecodeStatus WebAssemblyDisassembler::getInstruction(
64  MCInst &MI, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t /*Address*/,
65  raw_ostream &OS, raw_ostream &CS) const {
66  Size = 0;
67  uint64_t Pos = 0;
68 
69  // Read the opcode.
70  if (Pos + sizeof(uint64_t) > Bytes.size())
71  return MCDisassembler::Fail;
72  uint64_t Opcode = support::endian::read64le(Bytes.data() + Pos);
73  Pos += sizeof(uint64_t);
74 
75  if (Opcode >= WebAssembly::INSTRUCTION_LIST_END)
76  return MCDisassembler::Fail;
77 
78  MI.setOpcode(Opcode);
79  const MCInstrDesc &Desc = MCII->get(Opcode);
80  unsigned NumFixedOperands = Desc.NumOperands;
81 
82  // If it's variadic, read the number of extra operands.
83  unsigned NumExtraOperands = 0;
84  if (Desc.isVariadic()) {
85  if (Pos + sizeof(uint64_t) > Bytes.size())
86  return MCDisassembler::Fail;
87  NumExtraOperands = support::endian::read64le(Bytes.data() + Pos);
88  Pos += sizeof(uint64_t);
89  }
90 
91  // Read the fixed operands. These are described by the MCInstrDesc.
92  for (unsigned i = 0; i < NumFixedOperands; ++i) {
93  const MCOperandInfo &Info = Desc.OpInfo[i];
94  switch (Info.OperandType) {
99  if (Pos + sizeof(uint64_t) > Bytes.size())
100  return MCDisassembler::Fail;
101  uint64_t Imm = support::endian::read64le(Bytes.data() + Pos);
102  Pos += sizeof(uint64_t);
104  break;
105  }
106  case MCOI::OPERAND_REGISTER: {
107  if (Pos + sizeof(uint64_t) > Bytes.size())
108  return MCDisassembler::Fail;
109  uint64_t Reg = support::endian::read64le(Bytes.data() + Pos);
110  Pos += sizeof(uint64_t);
112  break;
113  }
116  // TODO: MC converts all floating point immediate operands to double.
117  // This is fine for numeric values, but may cause NaNs to change bits.
118  if (Pos + sizeof(uint64_t) > Bytes.size())
119  return MCDisassembler::Fail;
120  uint64_t Bits = support::endian::read64le(Bytes.data() + Pos);
121  Pos += sizeof(uint64_t);
122  double Imm;
123  memcpy(&Imm, &Bits, sizeof(Imm));
125  break;
126  }
127  default:
128  llvm_unreachable("unimplemented operand kind");
129  }
130  }
131 
132  // Read the extra operands.
133  assert(NumExtraOperands == 0 || Desc.isVariadic());
134  for (unsigned i = 0; i < NumExtraOperands; ++i) {
135  if (Pos + sizeof(uint64_t) > Bytes.size())
136  return MCDisassembler::Fail;
138  // Decode extra immediate operands.
139  uint64_t Imm = support::endian::read64le(Bytes.data() + Pos);
141  } else {
142  // Decode extra register operands.
143  uint64_t Reg = support::endian::read64le(Bytes.data() + Pos);
145  }
146  Pos += sizeof(uint64_t);
147  }
148 
149  Size = Pos;
151 }
32-bit floating-point immediates.
size_t i
void LLVMInitializeWebAssemblyDisassembler()
DecodeStatus
Ternary decode status.
Superclass for all disassemblers.
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:163
MachineInstrBuilder MachineInstrBuilder &DefMI const MCInstrDesc & Desc
Basic block label in a branch construct.
static void RegisterMCDisassembler(Target &T, Target::MCDisassemblerCtorTy Fn)
RegisterMCDisassembler - Register a MCDisassembler implementation for the given target.
bool isVariadic() const
Return true if this instruction can have a variable number of operands.
Definition: MCInstrDesc.h:225
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
MCInstrInfo * createMCInstrInfo() const
createMCInstrInfo - Create a MCInstrInfo implementation.
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:111
Reg
All possible values of the reg field in the ModR/M byte.
Context object for machine code objects.
Definition: MCContext.h:51
uint8_t OperandType
Information about the type of the operand.
Definition: MCInstrDesc.h:82
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:141
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:150
unsigned short NumOperands
Definition: MCInstrDesc.h:166
This file provides WebAssembly-specific target descriptions.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void setOpcode(unsigned Op)
Definition: MCInst.h:158
static MCOperand createFPImm(double Val)
Definition: MCInst.h:123
Target - Wrapper for Target specific information.
64-bit floating-point immediates.
static MCDisassembler * createWebAssemblyDisassembler(const Target &T, const MCSubtargetInfo &STI, MCContext &Ctx)
uint64_t read64le(const void *P)
Definition: Endian.h:319
p2align immediate for load and store address alignment.
MCSubtargetInfo - Generic base class for all target subtargets.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const MCOperandInfo * OpInfo
Definition: MCInstrDesc.h:174
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:44
IRTranslator LLVM IR MI
void addOperand(const MCOperand &Op)
Definition: MCInst.h:168
Target & getTheWebAssemblyTarget32()
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition: MCInstrDesc.h:70
Target & getTheWebAssemblyTarget64()
const T * data() const
Definition: ArrayRef.h:138
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:117