[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