[Mlir-commits] [mlir] 1ef8ba9 - [MLIR][WasmSSA] Instruction parser refactoring of WasmSSA importer (#195500)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Fri Jul 17 19:59:24 PDT 2026


Author: Luc Forget
Date: 2026-07-18T11:59:18+09:00
New Revision: 1ef8ba9a00e16423d711ddbf16c7a45fb7fd570b

URL: https://github.com/llvm/llvm-project/commit/1ef8ba9a00e16423d711ddbf16c7a45fb7fd570b
DIFF: https://github.com/llvm/llvm-project/commit/1ef8ba9a00e16423d711ddbf16c7a45fb7fd570b.diff

LOG: [MLIR][WasmSSA] Instruction parser refactoring of WasmSSA importer (#195500)

Refactored WasmSSA importer mechanism to dispatch control flow to
relevant parser based on op code.
This is to prepare for instructions with multi-bytes opcodes (e.g.
vector instruction and some scalar instructions extensions) which will
be able to reuse the same mechanism.

It also replaces the bit tree to find the address by a jump table.

---------

Co-authored-by: Luc Forget <lforg37 at users.noreply.github.com>
Co-authored-by: Ferdinand Lemaire <ferdinand.lemaire at woven-planet.global>
Co-authored-by: Ferdinand Lemaire <flscminecraft at gmail.com>

Added: 
    

Modified: 
    mlir/lib/Target/Wasm/TranslateFromWasm.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/lib/Target/Wasm/TranslateFromWasm.cpp b/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
index 1a0d53f1207f6..cea6bd2816dc1 100644
--- a/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
+++ b/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
@@ -27,6 +27,7 @@
 #include "llvm/Support/LEB128.h"
 #include "llvm/Support/LogicalResult.h"
 
+#include <cassert>
 #include <cstddef>
 #include <cstdint>
 #include <variant>
@@ -237,6 +238,15 @@ class ValueStack {
 
 using local_val_t = TypedValue<wasmssa::LocalRefType>;
 
+template <size_t... IS>
+constexpr ByteSequence<std::byte{IS}...>
+    castIndexSequenceToBytes(std::index_sequence<IS...>) {
+  return {};
+}
+
+constexpr auto all8bitsBytes =
+    castIndexSequenceToBytes(std::make_index_sequence<256>());
+
 class ExpressionParser {
 public:
   using locals_t = SmallVector<local_val_t>;
@@ -245,9 +255,6 @@ class ExpressionParser {
       : parser{parser}, symbols{symbols}, locals{initLocal} {}
 
 private:
-  template <std::byte opCode>
-  inline parsed_inst_t parseSpecificInstruction(OpBuilder &builder);
-
   template <typename valueT>
   parsed_inst_t
   parseConstInst(OpBuilder &builder,
@@ -280,38 +287,8 @@ class ExpressionParser {
             typename... extraArgsT>
   inline parsed_inst_t buildConvertOp(OpBuilder &builder, extraArgsT...);
 
-  /// This function generates a dispatch tree to associate an opcode with a
-  /// parser. Parsers are registered by specialising the
-  /// `parseSpecificInstruction` function for the op code to handle.
-  ///
-  /// The dispatcher is generated by recursively creating all possible patterns
-  /// for an opcode and calling the relevant parser on the leaf.
-  ///
-  /// @tparam patternBitSize is the first bit for which the pattern is not fixed
-  ///
-  /// @tparam highBitPattern is the fixed pattern that this instance handles for
-  /// the 8-patternBitSize bits
-  template <size_t patternBitSize = 0, std::byte highBitPattern = std::byte{0}>
   inline parsed_inst_t dispatchToInstParser(std::byte opCode,
-                                            OpBuilder &builder) {
-    static_assert(patternBitSize <= 8,
-                  "PatternBitSize is outside of range of opcode space! "
-                  "(expected at most 8 bits)");
-    if constexpr (patternBitSize < 8) {
-      constexpr std::byte bitSelect{1 << (7 - patternBitSize)};
-      constexpr std::byte nextHighBitPatternStem = highBitPattern << 1;
-      constexpr size_t nextPatternBitSize = patternBitSize + 1;
-      if ((opCode & bitSelect) != std::byte{0})
-        return dispatchToInstParser<nextPatternBitSize,
-                                    nextHighBitPatternStem | std::byte{1}>(
-            opCode, builder);
-      return dispatchToInstParser<nextPatternBitSize, nextHighBitPatternStem>(
-          opCode, builder);
-    } else {
-      return parseSpecificInstruction<highBitPattern>(builder);
-    }
-  }
-
+                                            OpBuilder &builder);
   ///
   /// RAII guard class for creating a nesting level
   ///
@@ -444,6 +421,22 @@ class ExpressionParser {
   template <typename OpToCreate>
   parsed_inst_t parseBlockLikeOp(OpBuilder &);
 
+  Location getCurrentOpLoc() {
+    assert(currentOpLoc.has_value() &&
+           "expects current opcode location to be set");
+    return *currentOpLoc;
+  }
+
+  class TopLevelInstParserRegistry {
+  public:
+    template <std::byte opCode>
+    static constexpr bool hasParserForOpcode = false;
+
+    template <std::byte opCode>
+    static parsed_inst_t parseInstrWithOpCode(OpBuilder &,
+                                              ExpressionParser &) = delete;
+  };
+
 private:
   std::optional<Location> currentOpLoc;
   ParserHead &parser;
@@ -452,6 +445,70 @@ class ExpressionParser {
   ValueStack valueStack;
 };
 
+static inline parsed_inst_t
+unreachableHandler(OpBuilder &, ExpressionParser &expressionParser) {
+  llvm_unreachable("Failure in opcode parser dispatch logic.");
+  return mlir::failure();
+}
+
+template <typename ParserRegistry>
+class InstDispatcher {
+private:
+  using dispatch_t = parsed_inst_t (*)(OpBuilder &, ExpressionParser &);
+
+  template <std::byte opCode>
+  static constexpr dispatch_t getHandlerForOpCode() {
+    if constexpr (ParserRegistry::template hasParserForOpcode<opCode>)
+      return ParserRegistry::template parseInstrWithOpCode<opCode>;
+    else
+      return unreachableHandler;
+  }
+
+public:
+  template <std::byte opCode>
+  static constexpr bool isValidInst =
+      ParserRegistry::template hasParserForOpcode<opCode>;
+
+private:
+  static inline parsed_inst_t
+  invalidOpcodeDiag(OpBuilder &, ExpressionParser &expressionParser,
+                    std::byte opCode) {
+    return emitError(expressionParser.getCurrentOpLoc(),
+                     "unknown instruction opcode: ")
+           << static_cast<int>(opCode);
+  }
+
+  template <std::byte... opCodes>
+  static inline parsed_inst_t dispatchImpl(std::byte opCode, OpBuilder &builder,
+                                           ExpressionParser &exprParser,
+                                           ByteSequence<opCodes...>) {
+    static constexpr std::array<bool, 256> opcodeValidityMap{
+        isValidInst<opCodes>...};
+    static constexpr std::array<dispatch_t, 256> dispatchTable{
+        getHandlerForOpCode<opCodes>()...};
+    if (opcodeValidityMap[static_cast<size_t>(opCode)]) {
+      return dispatchTable[static_cast<size_t>(opCode)](builder, exprParser);
+    }
+    return invalidOpcodeDiag(builder, exprParser, opCode);
+  }
+
+public:
+  ///
+  /// @brief dispatch control flow to the sub parser registered for opCode in
+  /// `ParserRegistry`
+  ///
+  /// @param opCode opCode of the instruction to be Parsed
+  /// @param builder builder that will be passed to the parser
+  /// @param exprParser the generic parser passed to the sub parser
+  ///
+  /// @return the result of the parser or an error if there is no parser
+  /// registered for the opcode (emits a diagnostic)
+  static parsed_inst_t dispatch(std::byte opCode, OpBuilder &builder,
+                                ExpressionParser &exprParser) {
+    return dispatchImpl(opCode, builder, exprParser, all8bitsBytes);
+  }
+};
+
 class ParserHead {
 public:
   ParserHead(StringRef src, StringAttr name) : head{src}, locName{name} {}
@@ -850,12 +907,6 @@ inline FailureOr<int64_t> ParserHead::parseI64() {
   return parseLiteral<int64_t>();
 }
 
-template <std::byte opCode>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction(OpBuilder &) {
-  return emitError(*currentOpLoc, "unknown instruction opcode: ")
-         << static_cast<int>(opCode);
-}
-
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
 void ValueStack::dump() const {
   llvm::dbgs() << "================= Wasm ValueStack =======================\n";
@@ -1008,34 +1059,46 @@ parsed_inst_t ExpressionParser::parseBlockLikeOp(OpBuilder &builder) {
   return {ValueRange{successor->getArguments()}};
 }
 
-template <>
-inline parsed_inst_t
-ExpressionParser::parseSpecificInstruction<WasmBinaryEncoding::OpCode::block>(
-    OpBuilder &builder) {
-  return parseBlockLikeOp<BlockOp>(builder);
+// We can't use SFINAE in combination with deleted default instantiation
+// to identify which parsers are registered due to GCC < 14.1 bug, so we
+// use a constexpr variable to register them.
+// This is in order to avoid having to have only one "registration" of the
+// opcode.
+#define REGISTER_PARSER_OPCODE_PARSER(parserType, opcode, builderName,         \
+                                      parserName)                              \
+  template <>                                                                  \
+  constexpr bool parserType::hasParserForOpcode<opcode> = true;                \
+  template <>                                                                  \
+  inline parsed_inst_t parserType::parseInstrWithOpCode<opcode>(               \
+      OpBuilder & (builderName), ExpressionParser & (parserName))
+
+#define REGISTER_PRIMARY_WASM_INST_PARSER(opcode, builderName, parserName)     \
+  REGISTER_PARSER_OPCODE_PARSER(ExpressionParser::TopLevelInstParserRegistry,  \
+                                opcode, builderName, parserName)
+
+REGISTER_PRIMARY_WASM_INST_PARSER(WasmBinaryEncoding::OpCode::block, builder,
+                                  exprParser) {
+  return exprParser.parseBlockLikeOp<BlockOp>(builder);
 }
 
-template <>
-inline parsed_inst_t
-ExpressionParser::parseSpecificInstruction<WasmBinaryEncoding::OpCode::loop>(
-    OpBuilder &builder) {
-  return parseBlockLikeOp<LoopOp>(builder);
+REGISTER_PRIMARY_WASM_INST_PARSER(WasmBinaryEncoding::OpCode::loop, builder,
+                                  exprParser) {
+  return exprParser.parseBlockLikeOp<LoopOp>(builder);
 }
 
-template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::ifOpCode>(OpBuilder &builder) {
-  auto opLoc = currentOpLoc;
-  auto funcType = parseBlockFuncType(builder);
+REGISTER_PRIMARY_WASM_INST_PARSER(WasmBinaryEncoding::OpCode::ifOpCode, builder,
+                                  exprParser) {
+  auto opLoc = exprParser.currentOpLoc;
+  auto funcType = exprParser.parseBlockFuncType(builder);
   if (failed(funcType))
     return failure();
 
   LDBG() << "Parsing an if instruction of type " << *funcType;
   auto inputTypes = funcType->getInputs();
-  auto conditionValue = popOperands(builder.getI32Type());
+  auto conditionValue = exprParser.popOperands(builder.getI32Type());
   if (failed(conditionValue))
     return failure();
-  auto inputOps = popOperands(inputTypes);
+  auto inputOps = exprParser.popOperands(inputTypes);
   if (failed(inputOps))
     return failure();
 
@@ -1043,25 +1106,25 @@ inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
   Region *curRegion = curBlock->getParent();
   auto resTypes = funcType->getResults();
   llvm::SmallVector<Location> locations{};
-  locations.resize(resTypes.size(), *currentOpLoc);
+  locations.resize(resTypes.size(), exprParser.getCurrentOpLoc());
   auto *successor =
       builder.createBlock(curRegion, curRegion->end(), resTypes, locations);
   builder.setInsertionPointToEnd(curBlock);
-  auto ifOp = IfOp::create(builder, *currentOpLoc, conditionValue->front(),
-                           *inputOps, successor);
+  auto ifOp = IfOp::create(builder, exprParser.getCurrentOpLoc(),
+                           conditionValue->front(), *inputOps, successor);
   auto *ifEntryBlock = ifOp.createIfBlock();
   constexpr auto ifElseFilter =
       ByteSequence<WasmBinaryEncoding::endByte,
                    WasmBinaryEncoding::OpCode::elseOpCode>{};
-  auto parseIfRes = parseBlockContent(builder, ifEntryBlock, resTypes, *opLoc,
-                                      ifOp, ifElseFilter);
+  auto parseIfRes = exprParser.parseBlockContent(
+      builder, ifEntryBlock, resTypes, *opLoc, ifOp, ifElseFilter);
   if (failed(parseIfRes))
     return failure();
   if (*parseIfRes == WasmBinaryEncoding::OpCode::elseOpCode) {
     LDBG() << "  else block is present.";
     Block *elseEntryBlock = ifOp.createElseBlock();
-    auto parseElseRes =
-        parseBlockContent(builder, elseEntryBlock, resTypes, *opLoc, ifOp);
+    auto parseElseRes = exprParser.parseBlockContent(builder, elseEntryBlock,
+                                                     resTypes, *opLoc, ifOp);
     if (failed(parseElseRes))
       return failure();
   }
@@ -1069,17 +1132,16 @@ inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
   return {ValueRange{successor->getArguments()}};
 }
 
-template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::branchIf>(OpBuilder &builder) {
-  auto level = parser.parseLiteral<uint32_t>();
+REGISTER_PRIMARY_WASM_INST_PARSER(WasmBinaryEncoding::OpCode::branchIf, builder,
+                                  exprParser) {
+  auto level = exprParser.parser.parseLiteral<uint32_t>();
   if (failed(level))
     return failure();
   Block *curBlock = builder.getBlock();
   Region *curRegion = curBlock->getParent();
   auto sip = builder.saveInsertionPoint();
   Block *elseBlock = builder.createBlock(curRegion, curRegion->end());
-  auto condition = popOperands(builder.getI32Type());
+  auto condition = exprParser.popOperands(builder.getI32Type());
   if (failed(condition))
     return failure();
   builder.restoreInsertionPoint(sip);
@@ -1088,30 +1150,28 @@ inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
   if (failed(targetOp))
     return failure();
   auto inputTypes = targetOp->getLabelTarget()->getArgumentTypes();
-  auto branchArgs = popOperands(inputTypes);
+  auto branchArgs = exprParser.popOperands(inputTypes);
   if (failed(branchArgs))
     return failure();
-  BranchIfOp::create(builder, *currentOpLoc, condition->front(),
+  BranchIfOp::create(builder, exprParser.getCurrentOpLoc(), condition->front(),
                      builder.getUI32IntegerAttr(*level), *branchArgs,
                      elseBlock);
   builder.setInsertionPointToStart(elseBlock);
   return {*branchArgs};
 }
 
-template <>
-inline parsed_inst_t
-ExpressionParser::parseSpecificInstruction<WasmBinaryEncoding::OpCode::call>(
-    OpBuilder &builder) {
-  auto loc = *currentOpLoc;
-  auto funcIdx = parser.parseLiteral<uint32_t>();
+REGISTER_PRIMARY_WASM_INST_PARSER(WasmBinaryEncoding::OpCode::call, builder,
+                                  exprParser) {
+  auto loc = *exprParser.currentOpLoc;
+  auto funcIdx = exprParser.parser.parseLiteral<uint32_t>();
   if (failed(funcIdx))
     return failure();
-  if (*funcIdx >= symbols.funcSymbols.size())
+  if (*funcIdx >= exprParser.symbols.funcSymbols.size())
     return emitError(loc, "Invalid function index: ") << *funcIdx;
-  auto callee = symbols.funcSymbols[*funcIdx];
+  auto callee = exprParser.symbols.funcSymbols[*funcIdx];
   llvm::ArrayRef<Type> inTypes = callee.functionType.getInputs();
   llvm::ArrayRef<Type> resTypes = callee.functionType.getResults();
-  parsed_inst_t inOperands = popOperands(inTypes);
+  parsed_inst_t inOperands = exprParser.popOperands(inTypes);
   if (failed(inOperands))
     return failure();
   auto callOp =
@@ -1119,31 +1179,31 @@ ExpressionParser::parseSpecificInstruction<WasmBinaryEncoding::OpCode::call>(
   return {callOp.getResults()};
 }
 
-template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::localGet>(OpBuilder &builder) {
-  FailureOr<uint32_t> id = parser.parseLiteral<uint32_t>();
-  Location instLoc = *currentOpLoc;
+REGISTER_PRIMARY_WASM_INST_PARSER(WasmBinaryEncoding::OpCode::localGet, builder,
+                                  exprParser) {
+  FailureOr<uint32_t> id = exprParser.parser.parseLiteral<uint32_t>();
+  Location instLoc = *exprParser.currentOpLoc;
   if (failed(id))
     return failure();
-  if (*id >= locals.size())
+  if (*id >= exprParser.locals.size())
     return emitError(instLoc, "invalid local index. function has ")
-           << locals.size() << " accessible locals, received index " << *id;
-  return {{LocalGetOp::create(builder, instLoc, locals[*id]).getResult()}};
+           << exprParser.locals.size() << " accessible locals, received index "
+           << *id;
+  return {{LocalGetOp::create(builder, instLoc, exprParser.locals[*id])
+               .getResult()}};
 }
 
-template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::globalGet>(OpBuilder &builder) {
-  FailureOr<uint32_t> id = parser.parseLiteral<uint32_t>();
-  Location instLoc = *currentOpLoc;
+REGISTER_PRIMARY_WASM_INST_PARSER(WasmBinaryEncoding::OpCode::globalGet,
+                                  builder, exprParser) {
+  FailureOr<uint32_t> id = exprParser.parser.parseLiteral<uint32_t>();
+  Location instLoc = *exprParser.currentOpLoc;
   if (failed(id))
     return failure();
-  if (*id >= symbols.globalSymbols.size())
+  if (*id >= exprParser.symbols.globalSymbols.size())
     return emitError(instLoc, "invalid global index. function has ")
-           << symbols.globalSymbols.size()
+           << exprParser.symbols.globalSymbols.size()
            << " accessible globals, received index " << *id;
-  GlobalSymbolRefContainer globalVar = symbols.globalSymbols[*id];
+  GlobalSymbolRefContainer globalVar = exprParser.symbols.globalSymbols[*id];
   auto globalOp = GlobalGetOp::create(builder, instLoc, globalVar.globalType,
                                       globalVar.symbol);
 
@@ -1171,16 +1231,14 @@ parsed_inst_t ExpressionParser::parseSetOrTee(OpBuilder &builder) {
           ->getResults()};
 }
 
-template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::localSet>(OpBuilder &builder) {
-  return parseSetOrTee<LocalSetOp>(builder);
+REGISTER_PRIMARY_WASM_INST_PARSER(WasmBinaryEncoding::OpCode::localSet, builder,
+                                  exprParser) {
+  return exprParser.parseSetOrTee<LocalSetOp>(builder);
 }
 
-template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::localTee>(OpBuilder &builder) {
-  return parseSetOrTee<LocalTeeOp>(builder);
+REGISTER_PRIMARY_WASM_INST_PARSER(WasmBinaryEncoding::OpCode::localTee, builder,
+                                  exprParser) {
+  return exprParser.parseSetOrTee<LocalTeeOp>(builder);
 }
 
 template <typename T>
@@ -1251,28 +1309,24 @@ parsed_inst_t ExpressionParser::parseConstInst(
   return {{constOp.getResult()}};
 }
 
-template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::constI32>(OpBuilder &builder) {
-  return parseConstInst<int32_t>(builder);
+REGISTER_PRIMARY_WASM_INST_PARSER(WasmBinaryEncoding::OpCode::constI32, builder,
+                                  exprParser) {
+  return exprParser.parseConstInst<int32_t>(builder);
 }
 
-template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::constI64>(OpBuilder &builder) {
-  return parseConstInst<int64_t>(builder);
+REGISTER_PRIMARY_WASM_INST_PARSER(WasmBinaryEncoding::OpCode::constI64, builder,
+                                  exprParser) {
+  return exprParser.parseConstInst<int64_t>(builder);
 }
 
-template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::constFP32>(OpBuilder &builder) {
-  return parseConstInst<float>(builder);
+REGISTER_PRIMARY_WASM_INST_PARSER(WasmBinaryEncoding::OpCode::constFP32,
+                                  builder, exprParser) {
+  return exprParser.parseConstInst<float>(builder);
 }
 
-template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::constFP64>(OpBuilder &builder) {
-  return parseConstInst<double>(builder);
+REGISTER_PRIMARY_WASM_INST_PARSER(WasmBinaryEncoding::OpCode::constFP64,
+                                  builder, exprParser) {
+  return exprParser.parseConstInst<double>(builder);
 }
 
 template <typename opcode, typename valueType, unsigned int numOperands>
@@ -1295,9 +1349,13 @@ inline parsed_inst_t ExpressionParser::buildNumericOp(
 // Convenience macro for generating numerical operations.
 #define BUILD_NUMERIC_OP(OP_NAME, N_ARGS, PREFIX, SUFFIX, TYPE)                \
   template <>                                                                  \
-  inline parsed_inst_t ExpressionParser::parseSpecificInstruction<             \
-      WasmBinaryEncoding::OpCode::PREFIX##SUFFIX>(OpBuilder & builder) {       \
-    return buildNumericOp<OP_NAME, TYPE, N_ARGS>(builder);                     \
+  constexpr bool ExpressionParser::TopLevelInstParserRegistry::                \
+      hasParserForOpcode<WasmBinaryEncoding::OpCode::PREFIX##SUFFIX> = true;   \
+  template <>                                                                  \
+  inline parsed_inst_t ExpressionParser::TopLevelInstParserRegistry::          \
+      parseInstrWithOpCode<WasmBinaryEncoding::OpCode::PREFIX##SUFFIX>(        \
+          OpBuilder & builder, ExpressionParser & exprParser) {                \
+    return exprParser.buildNumericOp<OP_NAME, TYPE, N_ARGS>(builder);          \
   }
 
 // Macro to define binops that only support integer types.
@@ -1398,24 +1456,25 @@ inline parsed_inst_t ExpressionParser::buildConvertOp(OpBuilder &builder,
   return {{op.getResult()}};
 }
 
-template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::demoteF64ToF32>(OpBuilder &builder) {
-  return buildConvertOp<DemoteOp, double, float>(builder);
+REGISTER_PRIMARY_WASM_INST_PARSER(WasmBinaryEncoding::OpCode::demoteF64ToF32,
+                                  builder, exprParser) {
+  return exprParser.buildConvertOp<DemoteOp, double, float>(builder);
 }
 
-template <>
-inline parsed_inst_t
-ExpressionParser::parseSpecificInstruction<WasmBinaryEncoding::OpCode::wrap>(
-    OpBuilder &builder) {
-  return buildConvertOp<WrapOp, int64_t, int32_t>(builder);
+REGISTER_PRIMARY_WASM_INST_PARSER(WasmBinaryEncoding::OpCode::wrap, builder,
+                                  exprParser) {
+  return exprParser.buildConvertOp<WrapOp, int64_t, int32_t>(builder);
 }
 
 #define BUILD_CONVERSION_OP(IN_T, OUT_T, SOURCE_OP, TARGET_OP)                 \
   template <>                                                                  \
-  inline parsed_inst_t ExpressionParser::parseSpecificInstruction<             \
-      WasmBinaryEncoding::OpCode::SOURCE_OP>(OpBuilder & builder) {            \
-    return buildConvertOp<TARGET_OP, IN_T, OUT_T>(builder);                    \
+  constexpr bool ExpressionParser::TopLevelInstParserRegistry::                \
+      hasParserForOpcode<WasmBinaryEncoding::OpCode::SOURCE_OP> = true;        \
+  template <>                                                                  \
+  inline parsed_inst_t ExpressionParser::TopLevelInstParserRegistry::          \
+      parseInstrWithOpCode<WasmBinaryEncoding::OpCode::SOURCE_OP>(             \
+          OpBuilder & builder, ExpressionParser & exprParser) {                \
+    return exprParser.buildConvertOp<TARGET_OP, IN_T, OUT_T>(builder);         \
   }
 
 #define BUILD_CONVERT_OP_FOR(DEST_T, WIDTH)                                    \
@@ -1447,12 +1506,19 @@ BUILD_CONVERSION_OP(int32_t, int64_t, extendU, ExtendUI32Op)
 
 #define BUILD_SLICE_EXTEND_PARSER(IT_WIDTH, EXTRACT_WIDTH)                     \
   template <>                                                                  \
-  parsed_inst_t ExpressionParser::parseSpecificInstruction<                    \
+  constexpr bool                                                               \
+      ExpressionParser::TopLevelInstParserRegistry::hasParserForOpcode<        \
+          WasmBinaryEncoding::OpCode::extendI##IT_WIDTH##EXTRACT_WIDTH##S> =   \
+          true;                                                                \
+  template <>                                                                  \
+  parsed_inst_t                                                                \
+  ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<          \
       WasmBinaryEncoding::OpCode::extendI##IT_WIDTH##EXTRACT_WIDTH##S>(        \
-      OpBuilder & builder) {                                                   \
+      OpBuilder & builder, ExpressionParser & exprParser) {                    \
     using inout_t = int##IT_WIDTH##_t;                                         \
     auto attr = builder.getUI32IntegerAttr(EXTRACT_WIDTH);                     \
-    return buildConvertOp<ExtendLowBitsSOp, inout_t, inout_t>(builder, attr);  \
+    return exprParser.buildConvertOp<ExtendLowBitsSOp, inout_t, inout_t>(      \
+        builder, attr);                                                        \
   }
 
 BUILD_SLICE_EXTEND_PARSER(32, 8)
@@ -1463,25 +1529,36 @@ BUILD_SLICE_EXTEND_PARSER(64, 32)
 
 #undef BUILD_SLICE_EXTEND_PARSER
 
-template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::promoteF32ToF64>(OpBuilder &builder) {
-  return buildConvertOp<PromoteOp, float, double>(builder);
+REGISTER_PRIMARY_WASM_INST_PARSER(WasmBinaryEncoding::OpCode::promoteF32ToF64,
+                                  builder, exprParser) {
+  return exprParser.buildConvertOp<PromoteOp, float, double>(builder);
 }
 
 #define BUILD_REINTERPRET_PARSER(WIDTH, FP_TYPE)                               \
   template <>                                                                  \
-  inline parsed_inst_t ExpressionParser::parseSpecificInstruction<             \
-      WasmBinaryEncoding::OpCode::reinterpretF##WIDTH##AsI##WIDTH>(OpBuilder & \
-                                                                   builder) {  \
-    return buildConvertOp<ReinterpretOp, FP_TYPE, int##WIDTH##_t>(builder);    \
+  constexpr bool                                                               \
+      ExpressionParser::TopLevelInstParserRegistry::hasParserForOpcode<        \
+          WasmBinaryEncoding::OpCode::reinterpretF##WIDTH##AsI##WIDTH> = true; \
+  template <>                                                                  \
+  inline parsed_inst_t                                                         \
+  ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<          \
+      WasmBinaryEncoding::OpCode::reinterpretF##WIDTH##AsI##WIDTH>(            \
+      OpBuilder & builder, ExpressionParser & exprParser) {                    \
+    return exprParser.buildConvertOp<ReinterpretOp, FP_TYPE, int##WIDTH##_t>(  \
+        builder);                                                              \
   }                                                                            \
                                                                                \
   template <>                                                                  \
-  inline parsed_inst_t ExpressionParser::parseSpecificInstruction<             \
-      WasmBinaryEncoding::OpCode::reinterpretI##WIDTH##AsF##WIDTH>(OpBuilder & \
-                                                                   builder) {  \
-    return buildConvertOp<ReinterpretOp, int##WIDTH##_t, FP_TYPE>(builder);    \
+  constexpr bool                                                               \
+      ExpressionParser::TopLevelInstParserRegistry::hasParserForOpcode<        \
+          WasmBinaryEncoding::OpCode::reinterpretI##WIDTH##AsF##WIDTH> = true; \
+  template <>                                                                  \
+  inline parsed_inst_t                                                         \
+  ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<          \
+      WasmBinaryEncoding::OpCode::reinterpretI##WIDTH##AsF##WIDTH>(            \
+      OpBuilder & builder, ExpressionParser & exprParser) {                    \
+    return exprParser.buildConvertOp<ReinterpretOp, int##WIDTH##_t, FP_TYPE>(  \
+        builder);                                                              \
   }
 
 BUILD_REINTERPRET_PARSER(32, float)
@@ -1489,6 +1566,11 @@ BUILD_REINTERPRET_PARSER(64, double)
 
 #undef BUILD_REINTERPRET_PARSER
 
+inline parsed_inst_t
+ExpressionParser::dispatchToInstParser(std::byte opCode, OpBuilder &builder) {
+  return InstDispatcher<ExpressionParser::TopLevelInstParserRegistry>::dispatch(
+      opCode, builder, *this);
+}
 class WasmBinaryParser {
 private:
   struct SectionRegistry {


        


More information about the Mlir-commits mailing list