Home | History | Annotate | Download | only in TableGen
      1 //===- WebAssemblyDisassemblerEmitter.cpp - Disassembler tables -*- 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 // This file is part of the WebAssembly Disassembler Emitter.
     11 // It contains the implementation of the disassembler tables.
     12 // Documentation for the disassembler emitter in general can be found in
     13 // WebAssemblyDisassemblerEmitter.h.
     14 //
     15 //===----------------------------------------------------------------------===//
     16 
     17 #include "WebAssemblyDisassemblerEmitter.h"
     18 #include "llvm/TableGen/Record.h"
     19 
     20 namespace llvm {
     21 
     22 void emitWebAssemblyDisassemblerTables(
     23     raw_ostream &OS,
     24     const ArrayRef<const CodeGenInstruction *> &NumberedInstructions) {
     25   // First lets organize all opcodes by (prefix) byte. Prefix 0 is the
     26   // starting table.
     27   std::map<unsigned,
     28            std::map<unsigned, std::pair<unsigned, const CodeGenInstruction *>>>
     29       OpcodeTable;
     30   for (unsigned I = 0; I != NumberedInstructions.size(); ++I) {
     31     auto &CGI = *NumberedInstructions[I];
     32     auto &Def = *CGI.TheDef;
     33     if (!Def.getValue("Inst"))
     34       continue;
     35     auto &Inst = *Def.getValueAsBitsInit("Inst");
     36     auto Opc = static_cast<unsigned>(
     37         reinterpret_cast<IntInit *>(Inst.convertInitializerTo(IntRecTy::get()))
     38             ->getValue());
     39     if (Opc == 0xFFFFFFFF)
     40       continue; // No opcode defined.
     41     assert(Opc <= 0xFFFF);
     42     auto Prefix = Opc >> 8;
     43     Opc = Opc & 0xFF;
     44     auto &CGIP = OpcodeTable[Prefix][Opc];
     45     if (!CGIP.second ||
     46         // Make sure we store the variant with the least amount of operands,
     47         // which is the one without explicit registers. Only few instructions
     48         // have these currently, would be good to have for all of them.
     49         // FIXME: this picks the first of many typed variants, which is
     50         // currently the except_ref one, though this shouldn't matter for
     51         // disassembly purposes.
     52         CGIP.second->Operands.OperandList.size() >
     53             CGI.Operands.OperandList.size()) {
     54       CGIP = std::make_pair(I, &CGI);
     55     }
     56   }
     57   OS << "#include \"MCTargetDesc/WebAssemblyMCTargetDesc.h\"\n";
     58   OS << "\n";
     59   OS << "namespace llvm {\n\n";
     60   OS << "enum EntryType : uint8_t { ";
     61   OS << "ET_Unused, ET_Prefix, ET_Instruction };\n\n";
     62   OS << "struct WebAssemblyInstruction {\n";
     63   OS << "  uint16_t Opcode;\n";
     64   OS << "  EntryType ET;\n";
     65   OS << "  uint8_t NumOperands;\n";
     66   OS << "  uint8_t Operands[4];\n";
     67   OS << "};\n\n";
     68   // Output one table per prefix.
     69   for (auto &PrefixPair : OpcodeTable) {
     70     if (PrefixPair.second.empty())
     71       continue;
     72     OS << "WebAssemblyInstruction InstructionTable" << PrefixPair.first;
     73     OS << "[] = {\n";
     74     for (unsigned I = 0; I <= 0xFF; I++) {
     75       auto InstIt = PrefixPair.second.find(I);
     76       if (InstIt != PrefixPair.second.end()) {
     77         // Regular instruction.
     78         assert(InstIt->second.second);
     79         auto &CGI = *InstIt->second.second;
     80         OS << "  // 0x";
     81         OS.write_hex(static_cast<unsigned long long>(I));
     82         OS << ": " << CGI.AsmString << "\n";
     83         OS << "  { " << InstIt->second.first << ", ET_Instruction, ";
     84         OS << CGI.Operands.OperandList.size() << ", {\n";
     85         for (auto &Op : CGI.Operands.OperandList) {
     86           OS << "      " << Op.OperandType << ",\n";
     87         }
     88         OS << "    }\n";
     89       } else {
     90         auto PrefixIt = OpcodeTable.find(I);
     91         // If we have a non-empty table for it that's not 0, this is a prefix.
     92         if (PrefixIt != OpcodeTable.end() && I && !PrefixPair.first) {
     93           OS << "  { 0, ET_Prefix, 0, {}";
     94         } else {
     95           OS << "  { 0, ET_Unused, 0, {}";
     96         }
     97       }
     98       OS << "  },\n";
     99     }
    100     OS << "};\n\n";
    101   }
    102   // Create a table of all extension tables:
    103   OS << "struct { uint8_t Prefix; const WebAssemblyInstruction *Table; }\n";
    104   OS << "PrefixTable[] = {\n";
    105   for (auto &PrefixPair : OpcodeTable) {
    106     if (PrefixPair.second.empty() || !PrefixPair.first)
    107       continue;
    108     OS << "  { " << PrefixPair.first << ", InstructionTable"
    109        << PrefixPair.first;
    110     OS << " },\n";
    111   }
    112   OS << "  { 0, nullptr }\n};\n\n";
    113   OS << "} // End llvm namespace\n";
    114 }
    115 
    116 } // namespace llvm
    117