]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / utils / TableGen / WebAssemblyDisassemblerEmitter.cpp
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