LCOV - code coverage report
Current view: top level - lib/Target/WebAssembly/Disassembler - WebAssemblyDisassembler.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 43 51 84.3 %
Date: 2018-10-20 13:21:21 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : /// 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 "MCTargetDesc/WebAssemblyMCTargetDesc.h"
      19             : #include "llvm/MC/MCContext.h"
      20             : #include "llvm/MC/MCDisassembler/MCDisassembler.h"
      21             : #include "llvm/MC/MCFixedLenDisassembler.h"
      22             : #include "llvm/MC/MCInst.h"
      23             : #include "llvm/MC/MCInstrInfo.h"
      24             : #include "llvm/MC/MCSubtargetInfo.h"
      25             : #include "llvm/MC/MCSymbol.h"
      26             : #include "llvm/Support/Endian.h"
      27             : #include "llvm/Support/LEB128.h"
      28             : #include "llvm/Support/TargetRegistry.h"
      29             : 
      30             : using namespace llvm;
      31             : 
      32             : #define DEBUG_TYPE "wasm-disassembler"
      33             : 
      34             : using DecodeStatus = MCDisassembler::DecodeStatus;
      35             : 
      36             : #include "WebAssemblyGenDisassemblerTables.inc"
      37             : 
      38             : namespace {
      39             : class WebAssemblyDisassembler final : public MCDisassembler {
      40             :   std::unique_ptr<const MCInstrInfo> MCII;
      41             : 
      42             :   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
      43             :                               ArrayRef<uint8_t> Bytes, uint64_t Address,
      44             :                               raw_ostream &VStream,
      45             :                               raw_ostream &CStream) const override;
      46             : 
      47             : public:
      48             :   WebAssemblyDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
      49             :                           std::unique_ptr<const MCInstrInfo> MCII)
      50           4 :       : MCDisassembler(STI, Ctx), MCII(std::move(MCII)) {}
      51             : };
      52             : } // end anonymous namespace
      53             : 
      54           2 : static MCDisassembler *createWebAssemblyDisassembler(const Target &T,
      55             :                                                      const MCSubtargetInfo &STI,
      56             :                                                      MCContext &Ctx) {
      57           2 :   std::unique_ptr<const MCInstrInfo> MCII(T.createMCInstrInfo());
      58           2 :   return new WebAssemblyDisassembler(STI, Ctx, std::move(MCII));
      59             : }
      60             : 
      61       10844 : extern "C" void LLVMInitializeWebAssemblyDisassembler() {
      62             :   // Register the disassembler for each target.
      63       10844 :   TargetRegistry::RegisterMCDisassembler(getTheWebAssemblyTarget32(),
      64             :                                          createWebAssemblyDisassembler);
      65       10844 :   TargetRegistry::RegisterMCDisassembler(getTheWebAssemblyTarget64(),
      66             :                                          createWebAssemblyDisassembler);
      67       10844 : }
      68             : 
      69             : static int nextByte(ArrayRef<uint8_t> Bytes, uint64_t &Size) {
      70           3 :   if (Size >= Bytes.size())
      71             :     return -1;
      72          16 :   auto V = Bytes[Size];
      73          16 :   Size++;
      74          13 :   return V;
      75             : }
      76             : 
      77          10 : static bool parseLEBImmediate(MCInst &MI, uint64_t &Size,
      78             :                               ArrayRef<uint8_t> Bytes, bool Signed) {
      79          10 :   unsigned N = 0;
      80          10 :   const char *Error = nullptr;
      81          17 :   auto Val = Signed ? decodeSLEB128(Bytes.data() + Size, &N,
      82             :                                     Bytes.data() + Bytes.size(), &Error)
      83             :                     : static_cast<int64_t>(
      84           7 :                           decodeULEB128(Bytes.data() + Size, &N,
      85             :                                         Bytes.data() + Bytes.size(), &Error));
      86          10 :   if (Error)
      87             :     return false;
      88          10 :   Size += N;
      89          10 :   MI.addOperand(MCOperand::createImm(Val));
      90          10 :   return true;
      91             : }
      92             : 
      93             : template <typename T>
      94             : bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef<uint8_t> Bytes) {
      95          32 :   if (Size + sizeof(T) > Bytes.size())
      96             :     return false;
      97             :   T Val;
      98          32 :   memcpy(&Val, Bytes.data() + Size, sizeof(T));
      99             :   support::endian::byte_swap<T, support::endianness::little>(Val);
     100          32 :   Size += sizeof(T);
     101             :   if (std::is_floating_point<T>::value) {
     102           0 :     MI.addOperand(MCOperand::createFPImm(static_cast<double>(Val)));
     103             :   } else {
     104          32 :     MI.addOperand(MCOperand::createImm(static_cast<int64_t>(Val)));
     105             :   }
     106             :   return true;
     107             : }
     108             : 
     109          13 : MCDisassembler::DecodeStatus WebAssemblyDisassembler::getInstruction(
     110             :     MCInst &MI, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t /*Address*/,
     111             :     raw_ostream & /*OS*/, raw_ostream &CS) const {
     112          13 :   CommentStream = &CS;
     113          13 :   Size = 0;
     114             :   auto Opc = nextByte(Bytes, Size);
     115             :   if (Opc < 0)
     116             :     return MCDisassembler::Fail;
     117          13 :   const auto *WasmInst = &InstructionTable0[Opc];
     118             :   // If this is a prefix byte, indirect to another table.
     119          13 :   if (WasmInst->ET == ET_Prefix) {
     120             :     WasmInst = nullptr;
     121             :     // Linear search, so far only 2 entries.
     122           5 :     for (auto PT = PrefixTable; PT->Table; PT++) {
     123           5 :       if (PT->Prefix == Opc) {
     124             :         WasmInst = PT->Table;
     125             :         break;
     126             :       }
     127             :     }
     128           3 :     if (!WasmInst)
     129             :       return MCDisassembler::Fail;
     130             :     Opc = nextByte(Bytes, Size);
     131             :     if (Opc < 0)
     132             :       return MCDisassembler::Fail;
     133           3 :     WasmInst += Opc;
     134             :   }
     135          13 :   if (WasmInst->ET == ET_Unused)
     136             :     return MCDisassembler::Fail;
     137             :   // At this point we must have a valid instruction to decode.
     138             :   assert(WasmInst->ET == ET_Instruction);
     139          13 :   MI.setOpcode(WasmInst->Opcode);
     140             :   // Parse any operands.
     141          55 :   for (uint8_t OPI = 0; OPI < WasmInst->NumOperands; OPI++) {
     142          42 :     switch (OperandTable[WasmInst->OperandStart + OPI]) {
     143             :     // ULEB operands:
     144           7 :     case WebAssembly::OPERAND_BASIC_BLOCK:
     145             :     case WebAssembly::OPERAND_LOCAL:
     146             :     case WebAssembly::OPERAND_GLOBAL:
     147             :     case WebAssembly::OPERAND_FUNCTION32:
     148             :     case WebAssembly::OPERAND_OFFSET32:
     149             :     case WebAssembly::OPERAND_P2ALIGN:
     150             :     case WebAssembly::OPERAND_TYPEINDEX:
     151             :     case MCOI::OPERAND_IMMEDIATE: {
     152           7 :       if (!parseLEBImmediate(MI, Size, Bytes, false))
     153             :         return MCDisassembler::Fail;
     154             :       break;
     155             :     }
     156             :     // SLEB operands:
     157           3 :     case WebAssembly::OPERAND_I32IMM:
     158             :     case WebAssembly::OPERAND_I64IMM:
     159             :     case WebAssembly::OPERAND_SIGNATURE: {
     160           3 :       if (!parseLEBImmediate(MI, Size, Bytes, true))
     161             :         return MCDisassembler::Fail;
     162             :       break;
     163             :     }
     164             :     // FP operands.
     165           0 :     case WebAssembly::OPERAND_F32IMM: {
     166             :       if (!parseImmediate<float>(MI, Size, Bytes))
     167             :         return MCDisassembler::Fail;
     168             :       break;
     169             :     }
     170           0 :     case WebAssembly::OPERAND_F64IMM: {
     171             :       if (!parseImmediate<double>(MI, Size, Bytes))
     172             :         return MCDisassembler::Fail;
     173             :       break;
     174             :     }
     175             :     // Vector lane operands (not LEB encoded).
     176          32 :     case WebAssembly::OPERAND_VEC_I8IMM: {
     177             :       if (!parseImmediate<uint8_t>(MI, Size, Bytes))
     178             :         return MCDisassembler::Fail;
     179             :       break;
     180             :     }
     181           0 :     case WebAssembly::OPERAND_VEC_I16IMM: {
     182             :       if (!parseImmediate<uint16_t>(MI, Size, Bytes))
     183             :         return MCDisassembler::Fail;
     184             :       break;
     185             :     }
     186           0 :     case WebAssembly::OPERAND_VEC_I32IMM: {
     187             :       if (!parseImmediate<uint32_t>(MI, Size, Bytes))
     188             :         return MCDisassembler::Fail;
     189             :       break;
     190             :     }
     191           0 :     case WebAssembly::OPERAND_VEC_I64IMM: {
     192             :       if (!parseImmediate<uint64_t>(MI, Size, Bytes))
     193             :         return MCDisassembler::Fail;
     194             :       break;
     195             :     }
     196             :     case MCOI::OPERAND_REGISTER:
     197             :       // The tablegen header currently does not have any register operands since
     198             :       // we use only the stack (_S) instructions.
     199             :       // If you hit this that probably means a bad instruction definition in
     200             :       // tablegen.
     201             :       llvm_unreachable("Register operand in WebAssemblyDisassembler");
     202           0 :     default:
     203           0 :       llvm_unreachable("Unknown operand type in WebAssemblyDisassembler");
     204             :     }
     205             :   }
     206             :   return MCDisassembler::Success;
     207             : }

Generated by: LCOV version 1.13