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

Luc Forget llvmlistbot at llvm.org
Sun May 3 03:32:40 PDT 2026


https://github.com/lforg37 updated https://github.com/llvm/llvm-project/pull/195500

>From 1b1b49f5d325b4c43ceb51e856925317bd4eeeb9 Mon Sep 17 00:00:00 2001
From: Luc Forget <dev at alias.lforget.fr>
Date: Sun, 3 May 2026 14:42:38 +0900
Subject: [PATCH] [MLIR][WasmSSA] Instruction parser refactoring of WasmSSA
 importer

Refactored the WasmSSA importer mechanism which dispatches control
flow to the relevant instruction 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.
---
 mlir/lib/Target/Wasm/TranslateFromWasm.cpp | 354 +++++++++++++--------
 1 file changed, 224 insertions(+), 130 deletions(-)

diff --git a/mlir/lib/Target/Wasm/TranslateFromWasm.cpp b/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
index 048e964037558..5a5b2e204dd4f 100644
--- a/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
+++ b/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
@@ -237,6 +237,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 +254,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 +286,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 +420,15 @@ class ExpressionParser {
   template <typename OpToCreate>
   parsed_inst_t parseBlockLikeOp(OpBuilder &);
 
+  std::optional<Location> getCurrentOpLoc() { return currentOpLoc; }
+
+  class TopLevelInstParserRegistry {
+  public:
+    template <std::byte opCode>
+    static parsed_inst_t parseInstrWithOpCode(OpBuilder &,
+                                              ExpressionParser &) = delete;
+  };
+
 private:
   std::optional<Location> currentOpLoc;
   ParserHead &parser;
@@ -452,6 +437,78 @@ 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:
+  /// used to check if a parser is registered in the parser registry for a
+  /// given opcode.
+  /// Default to unreachable handler.
+  template <std::byte opCode, typename = void>
+  struct ParserInfo : std::false_type {
+    static constexpr auto handler = unreachableHandler;
+  };
+  template <std::byte opCode>
+  struct ParserInfo<
+      opCode,
+      std::void_t<
+          decltype(&ParserRegistry::template parseInstrWithOpCode<opCode>)>>
+      : std::true_type {
+    static constexpr auto handler =
+        ParserRegistry::template parseInstrWithOpCode<opCode>;
+  };
+
+public:
+  template <std::byte opCode>
+  static constexpr bool isValidInst = ParserInfo<opCode>::value;
+
+private:
+  static inline parsed_inst_t
+  invalidOpcodeDiag(OpBuilder &, ExpressionParser &expressionParser,
+                    std::byte opCode) {
+    return emitError(*(expressionParser.getCurrentOpLoc()),
+                     "unknown instruction opcode: ")
+           << static_cast<int>(opCode);
+  }
+
+  using dispatch_t = parsed_inst_t (*)(OpBuilder &, ExpressionParser &);
+
+  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{
+        ParserInfo<opCodes>::handler...};
+    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";
@@ -1010,32 +1061,36 @@ parsed_inst_t ExpressionParser::parseBlockLikeOp(OpBuilder &builder) {
 
 template <>
 inline parsed_inst_t
-ExpressionParser::parseSpecificInstruction<WasmBinaryEncoding::OpCode::block>(
-    OpBuilder &builder) {
-  return parseBlockLikeOp<BlockOp>(builder);
+ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<
+    WasmBinaryEncoding::OpCode::block>(OpBuilder &builder,
+                                       ExpressionParser &exprParser) {
+  return exprParser.parseBlockLikeOp<BlockOp>(builder);
 }
 
 template <>
 inline parsed_inst_t
-ExpressionParser::parseSpecificInstruction<WasmBinaryEncoding::OpCode::loop>(
-    OpBuilder &builder) {
-  return parseBlockLikeOp<LoopOp>(builder);
+ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<
+    WasmBinaryEncoding::OpCode::loop>(OpBuilder &builder,
+                                      ExpressionParser &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);
+inline parsed_inst_t
+ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<
+    WasmBinaryEncoding::OpCode::ifOpCode>(OpBuilder &builder,
+                                          ExpressionParser &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 +1098,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();
   }
@@ -1070,16 +1125,18 @@ inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
 }
 
 template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::branchIf>(OpBuilder &builder) {
-  auto level = parser.parseLiteral<uint32_t>();
+inline parsed_inst_t
+ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<
+    WasmBinaryEncoding::OpCode::branchIf>(OpBuilder &builder,
+                                          ExpressionParser &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,10 +1145,10 @@ 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);
@@ -1100,18 +1157,19 @@ inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
 
 template <>
 inline parsed_inst_t
-ExpressionParser::parseSpecificInstruction<WasmBinaryEncoding::OpCode::call>(
-    OpBuilder &builder) {
-  auto loc = *currentOpLoc;
-  auto funcIdx = parser.parseLiteral<uint32_t>();
+ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<
+    WasmBinaryEncoding::OpCode::call>(OpBuilder &builder,
+                                      ExpressionParser &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 =
@@ -1120,30 +1178,36 @@ ExpressionParser::parseSpecificInstruction<WasmBinaryEncoding::OpCode::call>(
 }
 
 template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::localGet>(OpBuilder &builder) {
-  FailureOr<uint32_t> id = parser.parseLiteral<uint32_t>();
-  Location instLoc = *currentOpLoc;
+inline parsed_inst_t
+ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<
+    WasmBinaryEncoding::OpCode::localGet>(OpBuilder &builder,
+                                          ExpressionParser &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;
+inline parsed_inst_t
+ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<
+    WasmBinaryEncoding::OpCode::globalGet>(OpBuilder &builder,
+                                           ExpressionParser &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);
 
@@ -1172,15 +1236,19 @@ parsed_inst_t ExpressionParser::parseSetOrTee(OpBuilder &builder) {
 }
 
 template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::localSet>(OpBuilder &builder) {
-  return parseSetOrTee<LocalSetOp>(builder);
+inline parsed_inst_t
+ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<
+    WasmBinaryEncoding::OpCode::localSet>(OpBuilder &builder,
+                                          ExpressionParser &exprParser) {
+  return exprParser.parseSetOrTee<LocalSetOp>(builder);
 }
 
 template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::localTee>(OpBuilder &builder) {
-  return parseSetOrTee<LocalTeeOp>(builder);
+inline parsed_inst_t
+ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<
+    WasmBinaryEncoding::OpCode::localTee>(OpBuilder &builder,
+                                          ExpressionParser &exprParser) {
+  return exprParser.parseSetOrTee<LocalTeeOp>(builder);
 }
 
 template <typename T>
@@ -1252,27 +1320,35 @@ parsed_inst_t ExpressionParser::parseConstInst(
 }
 
 template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::constI32>(OpBuilder &builder) {
-  return parseConstInst<int32_t>(builder);
+inline parsed_inst_t
+ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<
+    WasmBinaryEncoding::OpCode::constI32>(OpBuilder &builder,
+                                          ExpressionParser &exprParser) {
+  return exprParser.parseConstInst<int32_t>(builder);
 }
 
 template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::constI64>(OpBuilder &builder) {
-  return parseConstInst<int64_t>(builder);
+inline parsed_inst_t
+ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<
+    WasmBinaryEncoding::OpCode::constI64>(OpBuilder &builder,
+                                          ExpressionParser &exprParser) {
+  return exprParser.parseConstInst<int64_t>(builder);
 }
 
 template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::constFP32>(OpBuilder &builder) {
-  return parseConstInst<float>(builder);
+inline parsed_inst_t
+ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<
+    WasmBinaryEncoding::OpCode::constFP32>(OpBuilder &builder,
+                                           ExpressionParser &exprParser) {
+  return exprParser.parseConstInst<float>(builder);
 }
 
 template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::constFP64>(OpBuilder &builder) {
-  return parseConstInst<double>(builder);
+inline parsed_inst_t
+ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<
+    WasmBinaryEncoding::OpCode::constFP64>(OpBuilder &builder,
+                                           ExpressionParser &exprParser) {
+  return exprParser.parseConstInst<double>(builder);
 }
 
 template <typename opcode, typename valueType, unsigned int numOperands>
@@ -1295,9 +1371,10 @@ 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);                     \
+  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,23 +1475,27 @@ inline parsed_inst_t ExpressionParser::buildConvertOp(OpBuilder &builder,
 }
 
 template <>
-inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
-    WasmBinaryEncoding::OpCode::demoteF64ToF32>(OpBuilder &builder) {
-  return buildConvertOp<DemoteOp, double, float>(builder);
+inline parsed_inst_t
+ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<
+    WasmBinaryEncoding::OpCode::demoteF64ToF32>(OpBuilder &builder,
+                                                ExpressionParser &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);
+ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<
+    WasmBinaryEncoding::OpCode::wrap>(OpBuilder &builder,
+                                      ExpressionParser &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);                    \
+  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)                                    \
@@ -1435,12 +1516,14 @@ BUILD_CONVERSION_OP(int32_t, int64_t, extendU, ExtendUI32Op)
 
 #define BUILD_SLICE_EXTEND_PARSER(IT_WIDTH, EXTRACT_WIDTH)                     \
   template <>                                                                  \
-  parsed_inst_t ExpressionParser::parseSpecificInstruction<                    \
+  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)
@@ -1452,24 +1535,30 @@ 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);
+inline parsed_inst_t
+ExpressionParser::TopLevelInstParserRegistry::parseInstrWithOpCode<
+    WasmBinaryEncoding::OpCode::promoteF32ToF64>(OpBuilder &builder,
+                                                 ExpressionParser &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);    \
+  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);    \
+  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)
@@ -1477,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