Skip to content

[NFC][TableGen] Code cleanup in Wasm disassember emitter #135992

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ using DecodeStatus = MCDisassembler::DecodeStatus;

#include "WebAssemblyGenDisassemblerTables.inc"

namespace {
static constexpr int WebAssemblyInstructionTableSize = 256;

namespace {
class WebAssemblyDisassembler final : public MCDisassembler {
std::unique_ptr<const MCInstrInfo> MCII;

Expand Down Expand Up @@ -171,10 +171,10 @@ MCDisassembler::DecodeStatus WebAssemblyDisassembler::getInstruction(
// If this is a prefix byte, indirect to another table.
if (WasmInst->ET == ET_Prefix) {
WasmInst = nullptr;
// Linear search, so far only 2 entries.
for (auto PT = PrefixTable; PT->Table; PT++) {
if (PT->Prefix == Opc) {
WasmInst = PT->Table;
// Linear search, so far only 4 entries.
for (const auto &[Prefix, Table] : PrefixTable) {
if (Prefix == Opc) {
WasmInst = Table;
break;
}
}
Expand Down
89 changes: 42 additions & 47 deletions llvm/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===- WebAssemblyDisassemblerEmitter.cpp - Disassembler tables -*- C++ -*-===//
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand All @@ -16,10 +16,11 @@
#include "WebAssemblyDisassemblerEmitter.h"
#include "Common/CodeGenInstruction.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Record.h"

static constexpr int WebAssemblyInstructionTableSize = 256;
constexpr int WebAssemblyInstructionTableSize = 256;

void llvm::emitWebAssemblyDisassemblerTables(
raw_ostream &OS,
Expand All @@ -29,8 +30,8 @@ void llvm::emitWebAssemblyDisassemblerTables(
std::map<unsigned,
std::map<unsigned, std::pair<unsigned, const CodeGenInstruction *>>>
OpcodeTable;
for (unsigned I = 0; I != NumberedInstructions.size(); ++I) {
const CodeGenInstruction &CGI = *NumberedInstructions[I];
for (const auto &[Idx, CGI] :
enumerate(make_pointee_range(NumberedInstructions))) {
const Record &Def = *CGI.TheDef;
if (!Def.getValue("Inst"))
continue;
Expand Down Expand Up @@ -75,27 +76,31 @@ void llvm::emitWebAssemblyDisassemblerTables(
}
}
// Set this instruction as the one to use.
CGIP = {I, &CGI};
CGIP = {Idx, &CGI};
}
OS << "#include \"MCTargetDesc/WebAssemblyMCTargetDesc.h\"\n";
OS << "\n";
OS << "namespace llvm {\n\n";
OS << "static constexpr int WebAssemblyInstructionTableSize = ";
OS << WebAssemblyInstructionTableSize << ";\n\n";
OS << "enum EntryType : uint8_t { ";
OS << "ET_Unused, ET_Prefix, ET_Instruction };\n\n";
OS << "struct WebAssemblyInstruction {\n";
OS << " uint16_t Opcode;\n";
OS << " EntryType ET;\n";
OS << " uint8_t NumOperands;\n";
OS << " uint16_t OperandStart;\n";
OS << "};\n\n";

OS << R"(
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"

namespace {
enum EntryType : uint8_t { ET_Unused, ET_Prefix, ET_Instruction };

struct WebAssemblyInstruction {
uint16_t Opcode;
EntryType ET;
uint8_t NumOperands;
uint16_t OperandStart;
};
} // end anonymous namespace

)";

std::vector<std::string> OperandTable, CurOperandList;
// Output one table per prefix.
for (const auto &[Prefix, Table] : OpcodeTable) {
if (Table.empty())
continue;
OS << "WebAssemblyInstruction InstructionTable" << Prefix;
OS << "constexpr WebAssemblyInstruction InstructionTable" << Prefix;
OS << "[] = {\n";
for (unsigned I = 0; I < WebAssemblyInstructionTableSize; I++) {
auto InstIt = Table.find(I);
Expand All @@ -116,53 +121,43 @@ void llvm::emitWebAssemblyDisassemblerTables(
}
// See if we already have stored this sequence before. This is not
// strictly necessary but makes the table really small.
size_t OperandStart = OperandTable.size();
if (CurOperandList.size() <= OperandTable.size()) {
for (size_t J = 0; J <= OperandTable.size() - CurOperandList.size();
++J) {
size_t K = 0;
for (; K < CurOperandList.size(); ++K) {
if (OperandTable[J + K] != CurOperandList[K])
break;
}
if (K == CurOperandList.size()) {
OperandStart = J;
break;
}
}
}
auto SearchI =
std::search(OperandTable.begin(), OperandTable.end(),
CurOperandList.begin(), CurOperandList.end());
OS << std::distance(OperandTable.begin(), SearchI);
// Store operands if no prior occurrence.
if (OperandStart == OperandTable.size()) {
if (SearchI == OperandTable.end())
llvm::append_range(OperandTable, CurOperandList);
}
OS << OperandStart;
} else {
auto PrefixIt = OpcodeTable.find(I);
// If we have a non-empty table for it that's not 0, this is a prefix.
if (PrefixIt != OpcodeTable.end() && I && !Prefix) {
if (PrefixIt != OpcodeTable.end() && I && !Prefix)
OS << " { 0, ET_Prefix, 0, 0";
} else {
else
OS << " { 0, ET_Unused, 0, 0";
}
}
OS << " },\n";
}
OS << "};\n\n";
}
// Create a table of all operands:
OS << "const uint8_t OperandTable[] = {\n";
for (auto &Op : OperandTable) {
OS << "constexpr uint8_t OperandTable[] = {\n";
for (const auto &Op : OperandTable)
OS << " " << Op << ",\n";
}
OS << "};\n\n";

// Create a table of all extension tables:
OS << "struct { uint8_t Prefix; const WebAssemblyInstruction *Table; }\n";
OS << "PrefixTable[] = {\n";
OS << R"(
constexpr struct {
uint8_t Prefix;
const WebAssemblyInstruction *Table;
} PrefixTable[] = {
)";

for (const auto &[Prefix, Table] : OpcodeTable) {
if (Table.empty() || !Prefix)
continue;
OS << " { " << Prefix << ", InstructionTable" << Prefix << " },\n";
}
OS << " { 0, nullptr }\n};\n\n";
OS << "} // end namespace llvm\n";
OS << "};\n";
}
Loading