summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gen-s-parser.inc5834
-rw-r--r--src/wasm/wat-parser.cpp918
2 files changed, 6724 insertions, 28 deletions
diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc
index 7001cb10b..809fa7837 100644
--- a/src/gen-s-parser.inc
+++ b/src/gen-s-parser.inc
@@ -3478,4 +3478,5838 @@ parse_error:
throw ParseException(std::string(op), s.line, s.col);
#endif // INSTRUCTION_PARSER
+#ifdef NEW_INSTRUCTION_PARSER
+#undef NEW_INSTRUCTION_PARSER
+switch (op[0]) {
+ case 'a': {
+ switch (op[1]) {
+ case 'r': {
+ switch (op[6]) {
+ case 'c':
+ if (op == "array.copy"sv) {
+ auto ret = makeArrayCopy(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'g': {
+ switch (op[9]) {
+ case '\0':
+ if (op == "array.get"sv) {
+ auto ret = makeArrayGet(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_': {
+ switch (op[10]) {
+ case 's':
+ if (op == "array.get_s"sv) {
+ auto ret = makeArrayGet(ctx, in, true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "array.get_u"sv) {
+ auto ret = makeArrayGet(ctx, in, false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'i': {
+ switch (op[10]) {
+ case '\0':
+ if (op == "array.init"sv) {
+ auto ret = makeArrayInit(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_':
+ if (op == "array.init_static"sv) {
+ auto ret = makeArrayInitStatic(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'l':
+ if (op == "array.len"sv) {
+ auto ret = makeArrayLen(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n': {
+ switch (op[9]) {
+ case '\0':
+ if (op == "array.new"sv) {
+ auto ret = makeArrayNewStatic(ctx, in, false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_': {
+ switch (op[10]) {
+ case 'd': {
+ switch (op[17]) {
+ case '\0':
+ if (op == "array.new_default"sv) {
+ auto ret = makeArrayNewStatic(ctx, in, true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_':
+ if (op == "array.new_default_with_rtt"sv) {
+ auto ret = makeArrayNew(ctx, in, true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'w':
+ if (op == "array.new_with_rtt"sv) {
+ auto ret = makeArrayNew(ctx, in, false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 's':
+ if (op == "array.set"sv) {
+ auto ret = makeArraySet(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 't':
+ if (op == "atomic.fence"sv) {
+ auto ret = makeAtomicFence(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'b': {
+ switch (op[1]) {
+ case 'l':
+ if (op == "block"sv) {
+ auto ret = makeBlock(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r': {
+ switch (op[2]) {
+ case '\0':
+ if (op == "br"sv) {
+ auto ret = makeBreak(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_': {
+ switch (op[3]) {
+ case 'i':
+ if (op == "br_if"sv) {
+ auto ret = makeBreak(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o': {
+ switch (op[6]) {
+ case 'c': {
+ switch (op[10]) {
+ case '\0':
+ if (op == "br_on_cast"sv) {
+ auto ret = makeBrOn(ctx, in, BrOnCast);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_': {
+ switch (op[11]) {
+ case 'f':
+ if (op == "br_on_cast_fail"sv) {
+ auto ret = makeBrOn(ctx, in, BrOnCastFail);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's': {
+ switch (op[17]) {
+ case '\0':
+ if (op == "br_on_cast_static"sv) {
+ auto ret = makeBrOnStatic(ctx, in, BrOnCast);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_':
+ if (op == "br_on_cast_static_fail"sv) {
+ auto ret = makeBrOnStatic(ctx, in, BrOnCastFail);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'd':
+ if (op == "br_on_data"sv) {
+ auto ret = makeBrOn(ctx, in, BrOnData);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'f':
+ if (op == "br_on_func"sv) {
+ auto ret = makeBrOn(ctx, in, BrOnFunc);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'i':
+ if (op == "br_on_i31"sv) {
+ auto ret = makeBrOn(ctx, in, BrOnI31);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n': {
+ switch (op[7]) {
+ case 'o': {
+ switch (op[10]) {
+ case 'd':
+ if (op == "br_on_non_data"sv) {
+ auto ret = makeBrOn(ctx, in, BrOnNonData);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'f':
+ if (op == "br_on_non_func"sv) {
+ auto ret = makeBrOn(ctx, in, BrOnNonFunc);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'i':
+ if (op == "br_on_non_i31"sv) {
+ auto ret = makeBrOn(ctx, in, BrOnNonI31);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n':
+ if (op == "br_on_non_null"sv) {
+ auto ret = makeBrOn(ctx, in, BrOnNonNull);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'u':
+ if (op == "br_on_null"sv) {
+ auto ret = makeBrOn(ctx, in, BrOnNull);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 't':
+ if (op == "br_table"sv) {
+ auto ret = makeBreakTable(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'c': {
+ switch (op[4]) {
+ case '\0':
+ if (op == "call"sv) {
+ auto ret = makeCall(ctx, in, /*isReturn=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_': {
+ switch (op[5]) {
+ case 'i':
+ if (op == "call_indirect"sv) {
+ auto ret = makeCallIndirect(ctx, in, /*isReturn=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r':
+ if (op == "call_ref"sv) {
+ auto ret = makeCallRef(ctx, in, /*isReturn=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'd': {
+ switch (op[1]) {
+ case 'a':
+ if (op == "data.drop"sv) {
+ auto ret = makeDataDrop(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r':
+ if (op == "drop"sv) {
+ auto ret = makeDrop(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'e':
+ if (op == "else"sv) {
+ auto ret = makeThenOrElse(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'f': {
+ switch (op[1]) {
+ case '3': {
+ switch (op[3]) {
+ case '.': {
+ switch (op[4]) {
+ case 'a': {
+ switch (op[5]) {
+ case 'b':
+ if (op == "f32.abs"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::AbsFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'd':
+ if (op == "f32.add"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AddFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'c': {
+ switch (op[5]) {
+ case 'e':
+ if (op == "f32.ceil"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::CeilFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o': {
+ switch (op[6]) {
+ case 'n': {
+ switch (op[7]) {
+ case 's':
+ if (op == "f32.const"sv) {
+ auto ret = makeConst(ctx, in, Type::f32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'v': {
+ switch (op[13]) {
+ case '3': {
+ switch (op[16]) {
+ case 's':
+ if (op == "f32.convert_i32_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ConvertSInt32ToFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "f32.convert_i32_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ConvertUInt32ToFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case '6': {
+ switch (op[16]) {
+ case 's':
+ if (op == "f32.convert_i64_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ConvertSInt64ToFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "f32.convert_i64_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ConvertUInt64ToFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'p':
+ if (op == "f32.copysign"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::CopySignFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'd': {
+ switch (op[5]) {
+ case 'e':
+ if (op == "f32.demote_f64"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::DemoteFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'i':
+ if (op == "f32.div"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::DivFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'e':
+ if (op == "f32.eq"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::EqFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'f':
+ if (op == "f32.floor"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::FloorFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'g': {
+ switch (op[5]) {
+ case 'e':
+ if (op == "f32.ge"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GeFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't':
+ if (op == "f32.gt"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GtFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[5]) {
+ case 'e':
+ if (op == "f32.le"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LeFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "f32.load"sv) {
+ auto ret = makeLoad(ctx, in, Type::f32, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't':
+ if (op == "f32.lt"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LtFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'm': {
+ switch (op[5]) {
+ case 'a':
+ if (op == "f32.max"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MaxFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'i':
+ if (op == "f32.min"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MinFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "f32.mul"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MulFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'n': {
+ switch (op[6]) {
+ case '\0':
+ if (op == "f32.ne"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::NeFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'a':
+ if (op == "f32.nearest"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::NearestFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'g':
+ if (op == "f32.neg"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::NegFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'r':
+ if (op == "f32.reinterpret_i32"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ReinterpretInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's': {
+ switch (op[5]) {
+ case 'q':
+ if (op == "f32.sqrt"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::SqrtFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't':
+ if (op == "f32.store"sv) {
+ auto ret = makeStore(ctx, in, Type::f32, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "f32.sub"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::SubFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 't':
+ if (op == "f32.trunc"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'x': {
+ switch (op[6]) {
+ case 'a': {
+ switch (op[7]) {
+ case 'b':
+ if (op == "f32x4.abs"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::AbsVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'd':
+ if (op == "f32x4.add"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AddVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'c': {
+ switch (op[7]) {
+ case 'e':
+ if (op == "f32x4.ceil"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::CeilVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o': {
+ switch (op[20]) {
+ case 's':
+ if (op == "f32x4.convert_i32x4_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ConvertSVecI32x4ToVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "f32x4.convert_i32x4_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ConvertUVecI32x4ToVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'd': {
+ switch (op[7]) {
+ case 'e':
+ if (op == "f32x4.demote_f64x2_zero"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::DemoteZeroVecF64x2ToVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'i':
+ if (op == "f32x4.div"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::DivVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'e': {
+ switch (op[7]) {
+ case 'q':
+ if (op == "f32x4.eq"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::EqVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'x':
+ if (op == "f32x4.extract_lane"sv) {
+ auto ret = makeSIMDExtract(ctx, in, SIMDExtractOp::ExtractLaneVecF32x4, 4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'f':
+ if (op == "f32x4.floor"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::FloorVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'g': {
+ switch (op[7]) {
+ case 'e':
+ if (op == "f32x4.ge"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GeVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't':
+ if (op == "f32x4.gt"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GtVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[7]) {
+ case 'e':
+ if (op == "f32x4.le"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LeVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't':
+ if (op == "f32x4.lt"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LtVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'm': {
+ switch (op[7]) {
+ case 'a':
+ if (op == "f32x4.max"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MaxVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'i':
+ if (op == "f32x4.min"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MinVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "f32x4.mul"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MulVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'n': {
+ switch (op[8]) {
+ case '\0':
+ if (op == "f32x4.ne"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::NeVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'a':
+ if (op == "f32x4.nearest"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::NearestVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'g':
+ if (op == "f32x4.neg"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::NegVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'p': {
+ switch (op[8]) {
+ case 'a':
+ if (op == "f32x4.pmax"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::PMaxVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'i':
+ if (op == "f32x4.pmin"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::PMinVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'r': {
+ switch (op[8]) {
+ case 'l': {
+ switch (op[14]) {
+ case 'f': {
+ switch (op[16]) {
+ case 'a':
+ if (op == "f32x4.relaxed_fma"sv) {
+ auto ret = makeSIMDTernary(ctx, in, SIMDTernaryOp::RelaxedFmaVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "f32x4.relaxed_fms"sv) {
+ auto ret = makeSIMDTernary(ctx, in, SIMDTernaryOp::RelaxedFmsVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'm': {
+ switch (op[15]) {
+ case 'a':
+ if (op == "f32x4.relaxed_max"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::RelaxedMaxVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'i':
+ if (op == "f32x4.relaxed_min"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::RelaxedMinVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'p':
+ if (op == "f32x4.replace_lane"sv) {
+ auto ret = makeSIMDReplace(ctx, in, SIMDReplaceOp::ReplaceLaneVecF32x4, 4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 's': {
+ switch (op[7]) {
+ case 'p':
+ if (op == "f32x4.splat"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::SplatVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'q':
+ if (op == "f32x4.sqrt"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::SqrtVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "f32x4.sub"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::SubVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 't':
+ if (op == "f32x4.trunc"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncVecF32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case '6': {
+ switch (op[3]) {
+ case '.': {
+ switch (op[4]) {
+ case 'a': {
+ switch (op[5]) {
+ case 'b':
+ if (op == "f64.abs"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::AbsFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'd':
+ if (op == "f64.add"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AddFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'c': {
+ switch (op[5]) {
+ case 'e':
+ if (op == "f64.ceil"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::CeilFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o': {
+ switch (op[6]) {
+ case 'n': {
+ switch (op[7]) {
+ case 's':
+ if (op == "f64.const"sv) {
+ auto ret = makeConst(ctx, in, Type::f64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'v': {
+ switch (op[13]) {
+ case '3': {
+ switch (op[16]) {
+ case 's':
+ if (op == "f64.convert_i32_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ConvertSInt32ToFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "f64.convert_i32_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ConvertUInt32ToFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case '6': {
+ switch (op[16]) {
+ case 's':
+ if (op == "f64.convert_i64_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ConvertSInt64ToFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "f64.convert_i64_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ConvertUInt64ToFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'p':
+ if (op == "f64.copysign"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::CopySignFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'd':
+ if (op == "f64.div"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::DivFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'e':
+ if (op == "f64.eq"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::EqFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'f':
+ if (op == "f64.floor"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::FloorFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'g': {
+ switch (op[5]) {
+ case 'e':
+ if (op == "f64.ge"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GeFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't':
+ if (op == "f64.gt"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GtFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[5]) {
+ case 'e':
+ if (op == "f64.le"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LeFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "f64.load"sv) {
+ auto ret = makeLoad(ctx, in, Type::f64, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't':
+ if (op == "f64.lt"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LtFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'm': {
+ switch (op[5]) {
+ case 'a':
+ if (op == "f64.max"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MaxFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'i':
+ if (op == "f64.min"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MinFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "f64.mul"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MulFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'n': {
+ switch (op[6]) {
+ case '\0':
+ if (op == "f64.ne"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::NeFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'a':
+ if (op == "f64.nearest"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::NearestFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'g':
+ if (op == "f64.neg"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::NegFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'p':
+ if (op == "f64.promote_f32"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::PromoteFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r':
+ if (op == "f64.reinterpret_i64"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ReinterpretInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's': {
+ switch (op[5]) {
+ case 'q':
+ if (op == "f64.sqrt"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::SqrtFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't':
+ if (op == "f64.store"sv) {
+ auto ret = makeStore(ctx, in, Type::f64, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "f64.sub"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::SubFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 't':
+ if (op == "f64.trunc"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'x': {
+ switch (op[6]) {
+ case 'a': {
+ switch (op[7]) {
+ case 'b':
+ if (op == "f64x2.abs"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::AbsVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'd':
+ if (op == "f64x2.add"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AddVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'c': {
+ switch (op[7]) {
+ case 'e':
+ if (op == "f64x2.ceil"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::CeilVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o': {
+ switch (op[24]) {
+ case 's':
+ if (op == "f64x2.convert_low_i32x4_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ConvertLowSVecI32x4ToVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "f64x2.convert_low_i32x4_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ConvertLowUVecI32x4ToVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'd':
+ if (op == "f64x2.div"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::DivVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'e': {
+ switch (op[7]) {
+ case 'q':
+ if (op == "f64x2.eq"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::EqVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'x':
+ if (op == "f64x2.extract_lane"sv) {
+ auto ret = makeSIMDExtract(ctx, in, SIMDExtractOp::ExtractLaneVecF64x2, 2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'f':
+ if (op == "f64x2.floor"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::FloorVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'g': {
+ switch (op[7]) {
+ case 'e':
+ if (op == "f64x2.ge"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GeVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't':
+ if (op == "f64x2.gt"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GtVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[7]) {
+ case 'e':
+ if (op == "f64x2.le"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LeVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't':
+ if (op == "f64x2.lt"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LtVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'm': {
+ switch (op[7]) {
+ case 'a':
+ if (op == "f64x2.max"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MaxVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'i':
+ if (op == "f64x2.min"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MinVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "f64x2.mul"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MulVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'n': {
+ switch (op[8]) {
+ case '\0':
+ if (op == "f64x2.ne"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::NeVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'a':
+ if (op == "f64x2.nearest"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::NearestVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'g':
+ if (op == "f64x2.neg"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::NegVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'p': {
+ switch (op[7]) {
+ case 'm': {
+ switch (op[8]) {
+ case 'a':
+ if (op == "f64x2.pmax"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::PMaxVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'i':
+ if (op == "f64x2.pmin"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::PMinVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'r':
+ if (op == "f64x2.promote_low_f32x4"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::PromoteLowVecF32x4ToVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'r': {
+ switch (op[8]) {
+ case 'l': {
+ switch (op[14]) {
+ case 'f': {
+ switch (op[16]) {
+ case 'a':
+ if (op == "f64x2.relaxed_fma"sv) {
+ auto ret = makeSIMDTernary(ctx, in, SIMDTernaryOp::RelaxedFmaVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "f64x2.relaxed_fms"sv) {
+ auto ret = makeSIMDTernary(ctx, in, SIMDTernaryOp::RelaxedFmsVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'm': {
+ switch (op[15]) {
+ case 'a':
+ if (op == "f64x2.relaxed_max"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::RelaxedMaxVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'i':
+ if (op == "f64x2.relaxed_min"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::RelaxedMinVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'p':
+ if (op == "f64x2.replace_lane"sv) {
+ auto ret = makeSIMDReplace(ctx, in, SIMDReplaceOp::ReplaceLaneVecF64x2, 2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 's': {
+ switch (op[7]) {
+ case 'p':
+ if (op == "f64x2.splat"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::SplatVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'q':
+ if (op == "f64x2.sqrt"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::SqrtVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "f64x2.sub"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::SubVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 't':
+ if (op == "f64x2.trunc"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncVecF64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'g': {
+ switch (op[7]) {
+ case 'g':
+ if (op == "global.get"sv) {
+ auto ret = makeGlobalGet(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "global.set"sv) {
+ auto ret = makeGlobalSet(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'i': {
+ switch (op[1]) {
+ case '1': {
+ switch (op[6]) {
+ case 'a': {
+ switch (op[7]) {
+ case 'b':
+ if (op == "i16x8.abs"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::AbsVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'd': {
+ switch (op[9]) {
+ case '\0':
+ if (op == "i16x8.add"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AddVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_': {
+ switch (op[14]) {
+ case 's':
+ if (op == "i16x8.add_sat_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AddSatSVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i16x8.add_sat_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AddSatUVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'l':
+ if (op == "i16x8.all_true"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::AllTrueVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'v':
+ if (op == "i16x8.avgr_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AvgrUVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'b':
+ if (op == "i16x8.bitmask"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::BitmaskVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'd':
+ if (op == "i16x8.dot_i8x16_i7x16_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::DotI8x16I7x16SToVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'e': {
+ switch (op[7]) {
+ case 'q':
+ if (op == "i16x8.eq"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::EqVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'x': {
+ switch (op[9]) {
+ case 'a': {
+ switch (op[28]) {
+ case 's':
+ if (op == "i16x8.extadd_pairwise_i8x16_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtAddPairwiseSVecI8x16ToI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i16x8.extadd_pairwise_i8x16_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtAddPairwiseUVecI8x16ToI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'e': {
+ switch (op[13]) {
+ case 'h': {
+ switch (op[24]) {
+ case 's':
+ if (op == "i16x8.extend_high_i8x16_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendHighSVecI8x16ToVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i16x8.extend_high_i8x16_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendHighUVecI8x16ToVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[23]) {
+ case 's':
+ if (op == "i16x8.extend_low_i8x16_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendLowSVecI8x16ToVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i16x8.extend_low_i8x16_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendLowUVecI8x16ToVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'm': {
+ switch (op[13]) {
+ case 'h': {
+ switch (op[24]) {
+ case 's':
+ if (op == "i16x8.extmul_high_i8x16_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ExtMulHighSVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i16x8.extmul_high_i8x16_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ExtMulHighUVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[23]) {
+ case 's':
+ if (op == "i16x8.extmul_low_i8x16_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ExtMulLowSVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i16x8.extmul_low_i8x16_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ExtMulLowUVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'r': {
+ switch (op[19]) {
+ case 's':
+ if (op == "i16x8.extract_lane_s"sv) {
+ auto ret = makeSIMDExtract(ctx, in, SIMDExtractOp::ExtractLaneSVecI16x8, 8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i16x8.extract_lane_u"sv) {
+ auto ret = makeSIMDExtract(ctx, in, SIMDExtractOp::ExtractLaneUVecI16x8, 8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'g': {
+ switch (op[7]) {
+ case 'e': {
+ switch (op[9]) {
+ case 's':
+ if (op == "i16x8.ge_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GeSVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i16x8.ge_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GeUVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[9]) {
+ case 's':
+ if (op == "i16x8.gt_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GtSVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i16x8.gt_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GtUVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[7]) {
+ case 'a':
+ if (op == "i16x8.laneselect"sv) {
+ auto ret = makeSIMDTernary(ctx, in, SIMDTernaryOp::LaneselectI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'e': {
+ switch (op[9]) {
+ case 's':
+ if (op == "i16x8.le_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LeSVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i16x8.le_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LeUVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[9]) {
+ case 's':
+ if (op == "i16x8.lt_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LtSVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i16x8.lt_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LtUVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'm': {
+ switch (op[7]) {
+ case 'a': {
+ switch (op[10]) {
+ case 's':
+ if (op == "i16x8.max_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MaxSVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i16x8.max_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MaxUVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'i': {
+ switch (op[10]) {
+ case 's':
+ if (op == "i16x8.min_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MinSVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i16x8.min_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MinUVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'u':
+ if (op == "i16x8.mul"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MulVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'n': {
+ switch (op[7]) {
+ case 'a': {
+ switch (op[19]) {
+ case 's':
+ if (op == "i16x8.narrow_i32x4_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::NarrowSVecI32x4ToVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i16x8.narrow_i32x4_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::NarrowUVecI32x4ToVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'e': {
+ switch (op[8]) {
+ case '\0':
+ if (op == "i16x8.ne"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::NeVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'g':
+ if (op == "i16x8.neg"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::NegVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'q':
+ if (op == "i16x8.q15mulr_sat_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::Q15MulrSatSVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r': {
+ switch (op[8]) {
+ case 'l':
+ if (op == "i16x8.relaxed_q15mulr_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::RelaxedQ15MulrSVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'p':
+ if (op == "i16x8.replace_lane"sv) {
+ auto ret = makeSIMDReplace(ctx, in, SIMDReplaceOp::ReplaceLaneVecI16x8, 8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 's': {
+ switch (op[7]) {
+ case 'h': {
+ switch (op[8]) {
+ case 'l':
+ if (op == "i16x8.shl"sv) {
+ auto ret = makeSIMDShift(ctx, in, SIMDShiftOp::ShlVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r': {
+ switch (op[10]) {
+ case 's':
+ if (op == "i16x8.shr_s"sv) {
+ auto ret = makeSIMDShift(ctx, in, SIMDShiftOp::ShrSVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i16x8.shr_u"sv) {
+ auto ret = makeSIMDShift(ctx, in, SIMDShiftOp::ShrUVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'p':
+ if (op == "i16x8.splat"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::SplatVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u': {
+ switch (op[9]) {
+ case '\0':
+ if (op == "i16x8.sub"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::SubVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_': {
+ switch (op[14]) {
+ case 's':
+ if (op == "i16x8.sub_sat_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::SubSatSVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i16x8.sub_sat_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::SubSatUVecI16x8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case '3': {
+ switch (op[2]) {
+ case '1': {
+ switch (op[4]) {
+ case 'g': {
+ switch (op[8]) {
+ case 's':
+ if (op == "i31.get_s"sv) {
+ auto ret = makeI31Get(ctx, in, true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i31.get_u"sv) {
+ auto ret = makeI31Get(ctx, in, false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'n':
+ if (op == "i31.new"sv) {
+ auto ret = makeI31New(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case '2': {
+ switch (op[3]) {
+ case '.': {
+ switch (op[4]) {
+ case 'a': {
+ switch (op[5]) {
+ case 'd':
+ if (op == "i32.add"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AddInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n':
+ if (op == "i32.and"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AndInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't': {
+ switch (op[11]) {
+ case 'l': {
+ switch (op[15]) {
+ case '\0':
+ if (op == "i32.atomic.load"sv) {
+ auto ret = makeLoad(ctx, in, Type::i32, /*isAtomic=*/true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '1':
+ if (op == "i32.atomic.load16_u"sv) {
+ auto ret = makeLoad(ctx, in, Type::i32, /*isAtomic=*/true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '8':
+ if (op == "i32.atomic.load8_u"sv) {
+ auto ret = makeLoad(ctx, in, Type::i32, /*isAtomic=*/true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'r': {
+ switch (op[14]) {
+ case '.': {
+ switch (op[15]) {
+ case 'a': {
+ switch (op[16]) {
+ case 'd':
+ if (op == "i32.atomic.rmw.add"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n':
+ if (op == "i32.atomic.rmw.and"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'c':
+ if (op == "i32.atomic.rmw.cmpxchg"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i32.atomic.rmw.or"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "i32.atomic.rmw.sub"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'x': {
+ switch (op[16]) {
+ case 'c':
+ if (op == "i32.atomic.rmw.xchg"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i32.atomic.rmw.xor"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case '1': {
+ switch (op[17]) {
+ case 'a': {
+ switch (op[18]) {
+ case 'd':
+ if (op == "i32.atomic.rmw16.add_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n':
+ if (op == "i32.atomic.rmw16.and_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'c':
+ if (op == "i32.atomic.rmw16.cmpxchg_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i32.atomic.rmw16.or_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "i32.atomic.rmw16.sub_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'x': {
+ switch (op[18]) {
+ case 'c':
+ if (op == "i32.atomic.rmw16.xchg_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i32.atomic.rmw16.xor_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case '8': {
+ switch (op[16]) {
+ case 'a': {
+ switch (op[17]) {
+ case 'd':
+ if (op == "i32.atomic.rmw8.add_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n':
+ if (op == "i32.atomic.rmw8.and_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'c':
+ if (op == "i32.atomic.rmw8.cmpxchg_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i32.atomic.rmw8.or_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "i32.atomic.rmw8.sub_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'x': {
+ switch (op[17]) {
+ case 'c':
+ if (op == "i32.atomic.rmw8.xchg_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i32.atomic.rmw8.xor_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 's': {
+ switch (op[16]) {
+ case '\0':
+ if (op == "i32.atomic.store"sv) {
+ auto ret = makeStore(ctx, in, Type::i32, /*isAtomic=*/true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '1':
+ if (op == "i32.atomic.store16"sv) {
+ auto ret = makeStore(ctx, in, Type::i32, /*isAtomic=*/true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '8':
+ if (op == "i32.atomic.store8"sv) {
+ auto ret = makeStore(ctx, in, Type::i32, /*isAtomic=*/true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'c': {
+ switch (op[5]) {
+ case 'l':
+ if (op == "i32.clz"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ClzInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i32.const"sv) {
+ auto ret = makeConst(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't':
+ if (op == "i32.ctz"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::CtzInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'd': {
+ switch (op[8]) {
+ case 's':
+ if (op == "i32.div_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::DivSInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32.div_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::DivUInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'e': {
+ switch (op[5]) {
+ case 'q': {
+ switch (op[6]) {
+ case '\0':
+ if (op == "i32.eq"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::EqInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'z':
+ if (op == "i32.eqz"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::EqZInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'x': {
+ switch (op[10]) {
+ case '1':
+ if (op == "i32.extend16_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendS16Int32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '8':
+ if (op == "i32.extend8_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendS8Int32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'g': {
+ switch (op[5]) {
+ case 'e': {
+ switch (op[7]) {
+ case 's':
+ if (op == "i32.ge_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GeSInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32.ge_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GeUInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[7]) {
+ case 's':
+ if (op == "i32.gt_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GtSInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32.gt_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GtUInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[5]) {
+ case 'e': {
+ switch (op[7]) {
+ case 's':
+ if (op == "i32.le_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LeSInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32.le_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LeUInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'o': {
+ switch (op[8]) {
+ case '\0':
+ if (op == "i32.load"sv) {
+ auto ret = makeLoad(ctx, in, Type::i32, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '1': {
+ switch (op[11]) {
+ case 's':
+ if (op == "i32.load16_s"sv) {
+ auto ret = makeLoad(ctx, in, Type::i32, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32.load16_u"sv) {
+ auto ret = makeLoad(ctx, in, Type::i32, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case '8': {
+ switch (op[10]) {
+ case 's':
+ if (op == "i32.load8_s"sv) {
+ auto ret = makeLoad(ctx, in, Type::i32, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32.load8_u"sv) {
+ auto ret = makeLoad(ctx, in, Type::i32, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[7]) {
+ case 's':
+ if (op == "i32.lt_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LtSInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32.lt_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LtUInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'm':
+ if (op == "i32.mul"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MulInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n':
+ if (op == "i32.ne"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::NeInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i32.or"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::OrInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'p':
+ if (op == "i32.popcnt"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::PopcntInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r': {
+ switch (op[5]) {
+ case 'e': {
+ switch (op[6]) {
+ case 'i':
+ if (op == "i32.reinterpret_f32"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ReinterpretFloat32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'm': {
+ switch (op[8]) {
+ case 's':
+ if (op == "i32.rem_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::RemSInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32.rem_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::RemUInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'o': {
+ switch (op[7]) {
+ case 'l':
+ if (op == "i32.rotl"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::RotLInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r':
+ if (op == "i32.rotr"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::RotRInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 's': {
+ switch (op[5]) {
+ case 'h': {
+ switch (op[6]) {
+ case 'l':
+ if (op == "i32.shl"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ShlInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r': {
+ switch (op[8]) {
+ case 's':
+ if (op == "i32.shr_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ShrSInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32.shr_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ShrUInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[9]) {
+ case '\0':
+ if (op == "i32.store"sv) {
+ auto ret = makeStore(ctx, in, Type::i32, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '1':
+ if (op == "i32.store16"sv) {
+ auto ret = makeStore(ctx, in, Type::i32, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '8':
+ if (op == "i32.store8"sv) {
+ auto ret = makeStore(ctx, in, Type::i32, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'u':
+ if (op == "i32.sub"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::SubInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[10]) {
+ case 'f': {
+ switch (op[11]) {
+ case '3': {
+ switch (op[14]) {
+ case 's':
+ if (op == "i32.trunc_f32_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncSFloat32ToInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32.trunc_f32_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncUFloat32ToInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case '6': {
+ switch (op[14]) {
+ case 's':
+ if (op == "i32.trunc_f64_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncSFloat64ToInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32.trunc_f64_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncUFloat64ToInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 's': {
+ switch (op[15]) {
+ case '3': {
+ switch (op[18]) {
+ case 's':
+ if (op == "i32.trunc_sat_f32_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncSatSFloat32ToInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32.trunc_sat_f32_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncSatUFloat32ToInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case '6': {
+ switch (op[18]) {
+ case 's':
+ if (op == "i32.trunc_sat_f64_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncSatSFloat64ToInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32.trunc_sat_f64_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncSatUFloat64ToInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'w':
+ if (op == "i32.wrap_i64"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::WrapInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'x':
+ if (op == "i32.xor"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::XorInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'x': {
+ switch (op[6]) {
+ case 'a': {
+ switch (op[7]) {
+ case 'b':
+ if (op == "i32x4.abs"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::AbsVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'd':
+ if (op == "i32x4.add"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AddVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'l':
+ if (op == "i32x4.all_true"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::AllTrueVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'b':
+ if (op == "i32x4.bitmask"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::BitmaskVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'd': {
+ switch (op[11]) {
+ case '1':
+ if (op == "i32x4.dot_i16x8_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::DotSVecI16x8ToVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '8':
+ if (op == "i32x4.dot_i8x16_i7x16_add_s"sv) {
+ auto ret = makeSIMDTernary(ctx, in, SIMDTernaryOp::DotI8x16I7x16AddSToVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'e': {
+ switch (op[7]) {
+ case 'q':
+ if (op == "i32x4.eq"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::EqVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'x': {
+ switch (op[9]) {
+ case 'a': {
+ switch (op[28]) {
+ case 's':
+ if (op == "i32x4.extadd_pairwise_i16x8_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtAddPairwiseSVecI16x8ToI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32x4.extadd_pairwise_i16x8_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtAddPairwiseUVecI16x8ToI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'e': {
+ switch (op[13]) {
+ case 'h': {
+ switch (op[24]) {
+ case 's':
+ if (op == "i32x4.extend_high_i16x8_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendHighSVecI16x8ToVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32x4.extend_high_i16x8_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendHighUVecI16x8ToVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[23]) {
+ case 's':
+ if (op == "i32x4.extend_low_i16x8_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendLowSVecI16x8ToVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32x4.extend_low_i16x8_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendLowUVecI16x8ToVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'm': {
+ switch (op[13]) {
+ case 'h': {
+ switch (op[24]) {
+ case 's':
+ if (op == "i32x4.extmul_high_i16x8_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ExtMulHighSVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32x4.extmul_high_i16x8_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ExtMulHighUVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[23]) {
+ case 's':
+ if (op == "i32x4.extmul_low_i16x8_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ExtMulLowSVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32x4.extmul_low_i16x8_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ExtMulLowUVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'r':
+ if (op == "i32x4.extract_lane"sv) {
+ auto ret = makeSIMDExtract(ctx, in, SIMDExtractOp::ExtractLaneVecI32x4, 4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'g': {
+ switch (op[7]) {
+ case 'e': {
+ switch (op[9]) {
+ case 's':
+ if (op == "i32x4.ge_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GeSVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32x4.ge_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GeUVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[9]) {
+ case 's':
+ if (op == "i32x4.gt_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GtSVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32x4.gt_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GtUVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[7]) {
+ case 'a':
+ if (op == "i32x4.laneselect"sv) {
+ auto ret = makeSIMDTernary(ctx, in, SIMDTernaryOp::LaneselectI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'e': {
+ switch (op[9]) {
+ case 's':
+ if (op == "i32x4.le_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LeSVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32x4.le_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LeUVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[9]) {
+ case 's':
+ if (op == "i32x4.lt_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LtSVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32x4.lt_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LtUVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'm': {
+ switch (op[7]) {
+ case 'a': {
+ switch (op[10]) {
+ case 's':
+ if (op == "i32x4.max_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MaxSVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32x4.max_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MaxUVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'i': {
+ switch (op[10]) {
+ case 's':
+ if (op == "i32x4.min_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MinSVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32x4.min_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MinUVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'u':
+ if (op == "i32x4.mul"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MulVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'n': {
+ switch (op[8]) {
+ case '\0':
+ if (op == "i32x4.ne"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::NeVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'g':
+ if (op == "i32x4.neg"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::NegVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'r': {
+ switch (op[8]) {
+ case 'l': {
+ switch (op[21]) {
+ case '3': {
+ switch (op[26]) {
+ case 's':
+ if (op == "i32x4.relaxed_trunc_f32x4_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::RelaxedTruncSVecF32x4ToVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32x4.relaxed_trunc_f32x4_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::RelaxedTruncUVecF32x4ToVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case '6': {
+ switch (op[26]) {
+ case 's':
+ if (op == "i32x4.relaxed_trunc_f64x2_s_zero"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::RelaxedTruncZeroSVecF64x2ToVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32x4.relaxed_trunc_f64x2_u_zero"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::RelaxedTruncZeroUVecF64x2ToVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'p':
+ if (op == "i32x4.replace_lane"sv) {
+ auto ret = makeSIMDReplace(ctx, in, SIMDReplaceOp::ReplaceLaneVecI32x4, 4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 's': {
+ switch (op[7]) {
+ case 'h': {
+ switch (op[8]) {
+ case 'l':
+ if (op == "i32x4.shl"sv) {
+ auto ret = makeSIMDShift(ctx, in, SIMDShiftOp::ShlVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r': {
+ switch (op[10]) {
+ case 's':
+ if (op == "i32x4.shr_s"sv) {
+ auto ret = makeSIMDShift(ctx, in, SIMDShiftOp::ShrSVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32x4.shr_u"sv) {
+ auto ret = makeSIMDShift(ctx, in, SIMDShiftOp::ShrUVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'p':
+ if (op == "i32x4.splat"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::SplatVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32x4.sub"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::SubVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[17]) {
+ case '3': {
+ switch (op[22]) {
+ case 's':
+ if (op == "i32x4.trunc_sat_f32x4_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncSatSVecF32x4ToVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32x4.trunc_sat_f32x4_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncSatUVecF32x4ToVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case '6': {
+ switch (op[22]) {
+ case 's':
+ if (op == "i32x4.trunc_sat_f64x2_s_zero"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncSatZeroSVecF64x2ToVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i32x4.trunc_sat_f64x2_u_zero"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncSatZeroUVecF64x2ToVecI32x4);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case '6': {
+ switch (op[3]) {
+ case '.': {
+ switch (op[4]) {
+ case 'a': {
+ switch (op[5]) {
+ case 'd':
+ if (op == "i64.add"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AddInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n':
+ if (op == "i64.and"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AndInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't': {
+ switch (op[11]) {
+ case 'l': {
+ switch (op[15]) {
+ case '\0':
+ if (op == "i64.atomic.load"sv) {
+ auto ret = makeLoad(ctx, in, Type::i64, /*isAtomic=*/true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '1':
+ if (op == "i64.atomic.load16_u"sv) {
+ auto ret = makeLoad(ctx, in, Type::i64, /*isAtomic=*/true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '3':
+ if (op == "i64.atomic.load32_u"sv) {
+ auto ret = makeLoad(ctx, in, Type::i64, /*isAtomic=*/true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '8':
+ if (op == "i64.atomic.load8_u"sv) {
+ auto ret = makeLoad(ctx, in, Type::i64, /*isAtomic=*/true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'r': {
+ switch (op[14]) {
+ case '.': {
+ switch (op[15]) {
+ case 'a': {
+ switch (op[16]) {
+ case 'd':
+ if (op == "i64.atomic.rmw.add"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n':
+ if (op == "i64.atomic.rmw.and"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'c':
+ if (op == "i64.atomic.rmw.cmpxchg"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i64.atomic.rmw.or"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "i64.atomic.rmw.sub"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'x': {
+ switch (op[16]) {
+ case 'c':
+ if (op == "i64.atomic.rmw.xchg"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i64.atomic.rmw.xor"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case '1': {
+ switch (op[17]) {
+ case 'a': {
+ switch (op[18]) {
+ case 'd':
+ if (op == "i64.atomic.rmw16.add_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n':
+ if (op == "i64.atomic.rmw16.and_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'c':
+ if (op == "i64.atomic.rmw16.cmpxchg_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i64.atomic.rmw16.or_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "i64.atomic.rmw16.sub_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'x': {
+ switch (op[18]) {
+ case 'c':
+ if (op == "i64.atomic.rmw16.xchg_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i64.atomic.rmw16.xor_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case '3': {
+ switch (op[17]) {
+ case 'a': {
+ switch (op[18]) {
+ case 'd':
+ if (op == "i64.atomic.rmw32.add_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n':
+ if (op == "i64.atomic.rmw32.and_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'c':
+ if (op == "i64.atomic.rmw32.cmpxchg_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i64.atomic.rmw32.or_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "i64.atomic.rmw32.sub_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'x': {
+ switch (op[18]) {
+ case 'c':
+ if (op == "i64.atomic.rmw32.xchg_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i64.atomic.rmw32.xor_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case '8': {
+ switch (op[16]) {
+ case 'a': {
+ switch (op[17]) {
+ case 'd':
+ if (op == "i64.atomic.rmw8.add_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n':
+ if (op == "i64.atomic.rmw8.and_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'c':
+ if (op == "i64.atomic.rmw8.cmpxchg_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i64.atomic.rmw8.or_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "i64.atomic.rmw8.sub_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'x': {
+ switch (op[17]) {
+ case 'c':
+ if (op == "i64.atomic.rmw8.xchg_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i64.atomic.rmw8.xor_u"sv) {
+ auto ret = makeAtomicRMWOrCmpxchg(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 's': {
+ switch (op[16]) {
+ case '\0':
+ if (op == "i64.atomic.store"sv) {
+ auto ret = makeStore(ctx, in, Type::i64, /*isAtomic=*/true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '1':
+ if (op == "i64.atomic.store16"sv) {
+ auto ret = makeStore(ctx, in, Type::i64, /*isAtomic=*/true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '3':
+ if (op == "i64.atomic.store32"sv) {
+ auto ret = makeStore(ctx, in, Type::i64, /*isAtomic=*/true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '8':
+ if (op == "i64.atomic.store8"sv) {
+ auto ret = makeStore(ctx, in, Type::i64, /*isAtomic=*/true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'c': {
+ switch (op[5]) {
+ case 'l':
+ if (op == "i64.clz"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ClzInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i64.const"sv) {
+ auto ret = makeConst(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't':
+ if (op == "i64.ctz"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::CtzInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'd': {
+ switch (op[8]) {
+ case 's':
+ if (op == "i64.div_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::DivSInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64.div_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::DivUInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'e': {
+ switch (op[5]) {
+ case 'q': {
+ switch (op[6]) {
+ case '\0':
+ if (op == "i64.eq"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::EqInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'z':
+ if (op == "i64.eqz"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::EqZInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'x': {
+ switch (op[10]) {
+ case '1':
+ if (op == "i64.extend16_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendS16Int64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '3':
+ if (op == "i64.extend32_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendS32Int64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '8':
+ if (op == "i64.extend8_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendS8Int64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_': {
+ switch (op[15]) {
+ case 's':
+ if (op == "i64.extend_i32_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendSInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64.extend_i32_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendUInt32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'g': {
+ switch (op[5]) {
+ case 'e': {
+ switch (op[7]) {
+ case 's':
+ if (op == "i64.ge_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GeSInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64.ge_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GeUInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[7]) {
+ case 's':
+ if (op == "i64.gt_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GtSInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64.gt_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GtUInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[5]) {
+ case 'e': {
+ switch (op[7]) {
+ case 's':
+ if (op == "i64.le_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LeSInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64.le_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LeUInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'o': {
+ switch (op[8]) {
+ case '\0':
+ if (op == "i64.load"sv) {
+ auto ret = makeLoad(ctx, in, Type::i64, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '1': {
+ switch (op[11]) {
+ case 's':
+ if (op == "i64.load16_s"sv) {
+ auto ret = makeLoad(ctx, in, Type::i64, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64.load16_u"sv) {
+ auto ret = makeLoad(ctx, in, Type::i64, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case '3': {
+ switch (op[11]) {
+ case 's':
+ if (op == "i64.load32_s"sv) {
+ auto ret = makeLoad(ctx, in, Type::i64, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64.load32_u"sv) {
+ auto ret = makeLoad(ctx, in, Type::i64, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case '8': {
+ switch (op[10]) {
+ case 's':
+ if (op == "i64.load8_s"sv) {
+ auto ret = makeLoad(ctx, in, Type::i64, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64.load8_u"sv) {
+ auto ret = makeLoad(ctx, in, Type::i64, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[7]) {
+ case 's':
+ if (op == "i64.lt_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LtSInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64.lt_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LtUInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'm':
+ if (op == "i64.mul"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MulInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n':
+ if (op == "i64.ne"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::NeInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "i64.or"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::OrInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'p':
+ if (op == "i64.popcnt"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::PopcntInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r': {
+ switch (op[5]) {
+ case 'e': {
+ switch (op[6]) {
+ case 'i':
+ if (op == "i64.reinterpret_f64"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ReinterpretFloat64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'm': {
+ switch (op[8]) {
+ case 's':
+ if (op == "i64.rem_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::RemSInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64.rem_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::RemUInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'o': {
+ switch (op[7]) {
+ case 'l':
+ if (op == "i64.rotl"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::RotLInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r':
+ if (op == "i64.rotr"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::RotRInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 's': {
+ switch (op[5]) {
+ case 'h': {
+ switch (op[6]) {
+ case 'l':
+ if (op == "i64.shl"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ShlInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r': {
+ switch (op[8]) {
+ case 's':
+ if (op == "i64.shr_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ShrSInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64.shr_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ShrUInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[9]) {
+ case '\0':
+ if (op == "i64.store"sv) {
+ auto ret = makeStore(ctx, in, Type::i64, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '1':
+ if (op == "i64.store16"sv) {
+ auto ret = makeStore(ctx, in, Type::i64, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '3':
+ if (op == "i64.store32"sv) {
+ auto ret = makeStore(ctx, in, Type::i64, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '8':
+ if (op == "i64.store8"sv) {
+ auto ret = makeStore(ctx, in, Type::i64, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'u':
+ if (op == "i64.sub"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::SubInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[10]) {
+ case 'f': {
+ switch (op[11]) {
+ case '3': {
+ switch (op[14]) {
+ case 's':
+ if (op == "i64.trunc_f32_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncSFloat32ToInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64.trunc_f32_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncUFloat32ToInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case '6': {
+ switch (op[14]) {
+ case 's':
+ if (op == "i64.trunc_f64_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncSFloat64ToInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64.trunc_f64_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncUFloat64ToInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 's': {
+ switch (op[15]) {
+ case '3': {
+ switch (op[18]) {
+ case 's':
+ if (op == "i64.trunc_sat_f32_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncSatSFloat32ToInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64.trunc_sat_f32_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncSatUFloat32ToInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case '6': {
+ switch (op[18]) {
+ case 's':
+ if (op == "i64.trunc_sat_f64_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncSatSFloat64ToInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64.trunc_sat_f64_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::TruncSatUFloat64ToInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'x':
+ if (op == "i64.xor"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::XorInt64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'x': {
+ switch (op[6]) {
+ case 'a': {
+ switch (op[7]) {
+ case 'b':
+ if (op == "i64x2.abs"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::AbsVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'd':
+ if (op == "i64x2.add"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AddVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'l':
+ if (op == "i64x2.all_true"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::AllTrueVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'b':
+ if (op == "i64x2.bitmask"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::BitmaskVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'e': {
+ switch (op[7]) {
+ case 'q':
+ if (op == "i64x2.eq"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::EqVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'x': {
+ switch (op[9]) {
+ case 'e': {
+ switch (op[13]) {
+ case 'h': {
+ switch (op[24]) {
+ case 's':
+ if (op == "i64x2.extend_high_i32x4_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendHighSVecI32x4ToVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64x2.extend_high_i32x4_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendHighUVecI32x4ToVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[23]) {
+ case 's':
+ if (op == "i64x2.extend_low_i32x4_s"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendLowSVecI32x4ToVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64x2.extend_low_i32x4_u"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::ExtendLowUVecI32x4ToVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'm': {
+ switch (op[13]) {
+ case 'h': {
+ switch (op[24]) {
+ case 's':
+ if (op == "i64x2.extmul_high_i32x4_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ExtMulHighSVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64x2.extmul_high_i32x4_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ExtMulHighUVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[23]) {
+ case 's':
+ if (op == "i64x2.extmul_low_i32x4_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ExtMulLowSVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64x2.extmul_low_i32x4_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::ExtMulLowUVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'r':
+ if (op == "i64x2.extract_lane"sv) {
+ auto ret = makeSIMDExtract(ctx, in, SIMDExtractOp::ExtractLaneVecI64x2, 2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'g': {
+ switch (op[7]) {
+ case 'e':
+ if (op == "i64x2.ge_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GeSVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't':
+ if (op == "i64x2.gt_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GtSVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[7]) {
+ case 'a':
+ if (op == "i64x2.laneselect"sv) {
+ auto ret = makeSIMDTernary(ctx, in, SIMDTernaryOp::LaneselectI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'e':
+ if (op == "i64x2.le_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LeSVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't':
+ if (op == "i64x2.lt_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LtSVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'm':
+ if (op == "i64x2.mul"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MulVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n': {
+ switch (op[8]) {
+ case '\0':
+ if (op == "i64x2.ne"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::NeVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'g':
+ if (op == "i64x2.neg"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::NegVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'r':
+ if (op == "i64x2.replace_lane"sv) {
+ auto ret = makeSIMDReplace(ctx, in, SIMDReplaceOp::ReplaceLaneVecI64x2, 2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's': {
+ switch (op[7]) {
+ case 'h': {
+ switch (op[8]) {
+ case 'l':
+ if (op == "i64x2.shl"sv) {
+ auto ret = makeSIMDShift(ctx, in, SIMDShiftOp::ShlVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r': {
+ switch (op[10]) {
+ case 's':
+ if (op == "i64x2.shr_s"sv) {
+ auto ret = makeSIMDShift(ctx, in, SIMDShiftOp::ShrSVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64x2.shr_u"sv) {
+ auto ret = makeSIMDShift(ctx, in, SIMDShiftOp::ShrUVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'p':
+ if (op == "i64x2.splat"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::SplatVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i64x2.sub"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::SubVecI64x2);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case '8': {
+ switch (op[6]) {
+ case 'a': {
+ switch (op[7]) {
+ case 'b':
+ if (op == "i8x16.abs"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::AbsVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'd': {
+ switch (op[9]) {
+ case '\0':
+ if (op == "i8x16.add"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AddVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_': {
+ switch (op[14]) {
+ case 's':
+ if (op == "i8x16.add_sat_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AddSatSVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i8x16.add_sat_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AddSatUVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'l':
+ if (op == "i8x16.all_true"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::AllTrueVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'v':
+ if (op == "i8x16.avgr_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AvgrUVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'b':
+ if (op == "i8x16.bitmask"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::BitmaskVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'e': {
+ switch (op[7]) {
+ case 'q':
+ if (op == "i8x16.eq"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::EqVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'x': {
+ switch (op[19]) {
+ case 's':
+ if (op == "i8x16.extract_lane_s"sv) {
+ auto ret = makeSIMDExtract(ctx, in, SIMDExtractOp::ExtractLaneSVecI8x16, 16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i8x16.extract_lane_u"sv) {
+ auto ret = makeSIMDExtract(ctx, in, SIMDExtractOp::ExtractLaneUVecI8x16, 16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'g': {
+ switch (op[7]) {
+ case 'e': {
+ switch (op[9]) {
+ case 's':
+ if (op == "i8x16.ge_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GeSVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i8x16.ge_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GeUVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[9]) {
+ case 's':
+ if (op == "i8x16.gt_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GtSVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i8x16.gt_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::GtUVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[7]) {
+ case 'a':
+ if (op == "i8x16.laneselect"sv) {
+ auto ret = makeSIMDTernary(ctx, in, SIMDTernaryOp::LaneselectI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'e': {
+ switch (op[9]) {
+ case 's':
+ if (op == "i8x16.le_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LeSVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i8x16.le_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LeUVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[9]) {
+ case 's':
+ if (op == "i8x16.lt_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LtSVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i8x16.lt_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::LtUVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'm': {
+ switch (op[7]) {
+ case 'a': {
+ switch (op[10]) {
+ case 's':
+ if (op == "i8x16.max_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MaxSVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i8x16.max_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MaxUVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'i': {
+ switch (op[10]) {
+ case 's':
+ if (op == "i8x16.min_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MinSVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i8x16.min_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::MinUVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'n': {
+ switch (op[7]) {
+ case 'a': {
+ switch (op[19]) {
+ case 's':
+ if (op == "i8x16.narrow_i16x8_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::NarrowSVecI16x8ToVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i8x16.narrow_i16x8_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::NarrowUVecI16x8ToVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'e': {
+ switch (op[8]) {
+ case '\0':
+ if (op == "i8x16.ne"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::NeVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'g':
+ if (op == "i8x16.neg"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::NegVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'p':
+ if (op == "i8x16.popcnt"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::PopcntVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r': {
+ switch (op[8]) {
+ case 'l':
+ if (op == "i8x16.relaxed_swizzle"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::RelaxedSwizzleVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'p':
+ if (op == "i8x16.replace_lane"sv) {
+ auto ret = makeSIMDReplace(ctx, in, SIMDReplaceOp::ReplaceLaneVecI8x16, 16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 's': {
+ switch (op[7]) {
+ case 'h': {
+ switch (op[8]) {
+ case 'l':
+ if (op == "i8x16.shl"sv) {
+ auto ret = makeSIMDShift(ctx, in, SIMDShiftOp::ShlVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r': {
+ switch (op[10]) {
+ case 's':
+ if (op == "i8x16.shr_s"sv) {
+ auto ret = makeSIMDShift(ctx, in, SIMDShiftOp::ShrSVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i8x16.shr_u"sv) {
+ auto ret = makeSIMDShift(ctx, in, SIMDShiftOp::ShrUVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'u':
+ if (op == "i8x16.shuffle"sv) {
+ auto ret = makeSIMDShuffle(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'p':
+ if (op == "i8x16.splat"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::SplatVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u': {
+ switch (op[9]) {
+ case '\0':
+ if (op == "i8x16.sub"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::SubVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_': {
+ switch (op[14]) {
+ case 's':
+ if (op == "i8x16.sub_sat_s"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::SubSatSVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "i8x16.sub_sat_u"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::SubSatUVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'w':
+ if (op == "i8x16.swizzle"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::SwizzleVecI8x16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'f':
+ if (op == "if"sv) {
+ auto ret = makeIf(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[2]) {
+ case 'c': {
+ switch (op[6]) {
+ case 'g':
+ if (op == "local.get"sv) {
+ auto ret = makeLocalGet(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "local.set"sv) {
+ auto ret = makeLocalSet(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't':
+ if (op == "local.tee"sv) {
+ auto ret = makeLocalTee(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'o':
+ if (op == "loop"sv) {
+ auto ret = makeLoop(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'm': {
+ switch (op[7]) {
+ case 'a': {
+ switch (op[14]) {
+ case 'n':
+ if (op == "memory.atomic.notify"sv) {
+ auto ret = makeAtomicNotify(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'w': {
+ switch (op[18]) {
+ case '3':
+ if (op == "memory.atomic.wait32"sv) {
+ auto ret = makeAtomicWait(ctx, in, Type::i32);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '6':
+ if (op == "memory.atomic.wait64"sv) {
+ auto ret = makeAtomicWait(ctx, in, Type::i64);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'c':
+ if (op == "memory.copy"sv) {
+ auto ret = makeMemoryCopy(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'f':
+ if (op == "memory.fill"sv) {
+ auto ret = makeMemoryFill(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'g':
+ if (op == "memory.grow"sv) {
+ auto ret = makeMemoryGrow(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'i':
+ if (op == "memory.init"sv) {
+ auto ret = makeMemoryInit(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "memory.size"sv) {
+ auto ret = makeMemorySize(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'n':
+ if (op == "nop"sv) {
+ auto ret = makeNop(ctx);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'p':
+ if (op == "pop"sv) {
+ auto ret = makePop(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r': {
+ switch (op[1]) {
+ case 'e': {
+ switch (op[2]) {
+ case 'f': {
+ switch (op[4]) {
+ case 'a': {
+ switch (op[7]) {
+ case 'd':
+ if (op == "ref.as_data"sv) {
+ auto ret = makeRefAs(ctx, in, RefAsData);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'f':
+ if (op == "ref.as_func"sv) {
+ auto ret = makeRefAs(ctx, in, RefAsFunc);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'i':
+ if (op == "ref.as_i31"sv) {
+ auto ret = makeRefAs(ctx, in, RefAsI31);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n':
+ if (op == "ref.as_non_null"sv) {
+ auto ret = makeRefAs(ctx, in, RefAsNonNull);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'c': {
+ switch (op[8]) {
+ case '\0':
+ if (op == "ref.cast"sv) {
+ auto ret = makeRefCast(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_': {
+ switch (op[9]) {
+ case 'n':
+ if (op == "ref.cast_nop_static"sv) {
+ auto ret = makeRefCastNopStatic(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "ref.cast_static"sv) {
+ auto ret = makeRefCastStatic(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'e':
+ if (op == "ref.eq"sv) {
+ auto ret = makeRefEq(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'f':
+ if (op == "ref.func"sv) {
+ auto ret = makeRefFunc(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'i': {
+ switch (op[7]) {
+ case 'd':
+ if (op == "ref.is_data"sv) {
+ auto ret = makeRefIs(ctx, in, RefIsData);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'f':
+ if (op == "ref.is_func"sv) {
+ auto ret = makeRefIs(ctx, in, RefIsFunc);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'i':
+ if (op == "ref.is_i31"sv) {
+ auto ret = makeRefIs(ctx, in, RefIsI31);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n':
+ if (op == "ref.is_null"sv) {
+ auto ret = makeRefIs(ctx, in, RefIsNull);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'n':
+ if (op == "ref.null"sv) {
+ auto ret = makeRefNull(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't': {
+ switch (op[8]) {
+ case '\0':
+ if (op == "ref.test"sv) {
+ auto ret = makeRefTest(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_':
+ if (op == "ref.test_static"sv) {
+ auto ret = makeRefTestStatic(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[3]) {
+ case 'h':
+ if (op == "rethrow"sv) {
+ auto ret = makeRethrow(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u': {
+ switch (op[6]) {
+ case '\0':
+ if (op == "return"sv) {
+ auto ret = makeReturn(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_': {
+ switch (op[11]) {
+ case '\0':
+ if (op == "return_call"sv) {
+ auto ret = makeCall(ctx, in, /*isReturn=*/true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_': {
+ switch (op[12]) {
+ case 'i':
+ if (op == "return_call_indirect"sv) {
+ auto ret = makeCallIndirect(ctx, in, /*isReturn=*/true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r':
+ if (op == "return_call_ref"sv) {
+ auto ret = makeCallRef(ctx, in, /*isReturn=*/true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[4]) {
+ case 'c':
+ if (op == "rtt.canon"sv) {
+ auto ret = makeRttCanon(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'f':
+ if (op == "rtt.fresh_sub"sv) {
+ auto ret = makeRttFreshSub(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "rtt.sub"sv) {
+ auto ret = makeRttSub(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 's': {
+ switch (op[1]) {
+ case 'e':
+ if (op == "select"sv) {
+ auto ret = makeSelect(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 't': {
+ switch (op[3]) {
+ case 'i': {
+ switch (op[7]) {
+ case 'c': {
+ switch (op[10]) {
+ case 'c':
+ if (op == "string.concat"sv) {
+ auto ret = makeStringConcat(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "string.const"sv) {
+ auto ret = makeStringConst(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'e': {
+ switch (op[8]) {
+ case 'n': {
+ switch (op[17]) {
+ case '1':
+ if (op == "string.encode_wtf16"sv) {
+ auto ret = makeStringEncode(ctx, in, StringEncodeWTF16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '8':
+ if (op == "string.encode_wtf8"sv) {
+ auto ret = makeStringEncode(ctx, in, StringEncodeWTF8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'q':
+ if (op == "string.eq"sv) {
+ auto ret = makeStringEq(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'i':
+ if (op == "string.is_usv_sequence"sv) {
+ auto ret = makeStringMeasure(ctx, in, StringMeasureIsUSV);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'm': {
+ switch (op[18]) {
+ case '1':
+ if (op == "string.measure_wtf16"sv) {
+ auto ret = makeStringMeasure(ctx, in, StringMeasureWTF16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '8':
+ if (op == "string.measure_wtf8"sv) {
+ auto ret = makeStringMeasure(ctx, in, StringMeasureWTF8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'n': {
+ switch (op[14]) {
+ case '1':
+ if (op == "string.new_wtf16"sv) {
+ auto ret = makeStringNew(ctx, in, StringNewWTF16);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '8':
+ if (op == "string.new_wtf8"sv) {
+ auto ret = makeStringNew(ctx, in, StringNewWTF8);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'u': {
+ switch (op[7]) {
+ case 'g': {
+ switch (op[10]) {
+ case '\0':
+ if (op == "struct.get"sv) {
+ auto ret = makeStructGet(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_': {
+ switch (op[11]) {
+ case 's':
+ if (op == "struct.get_s"sv) {
+ auto ret = makeStructGet(ctx, in, true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "struct.get_u"sv) {
+ auto ret = makeStructGet(ctx, in, false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'n': {
+ switch (op[10]) {
+ case '\0':
+ if (op == "struct.new"sv) {
+ auto ret = makeStructNewStatic(ctx, in, false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_': {
+ switch (op[11]) {
+ case 'd': {
+ switch (op[18]) {
+ case '\0':
+ if (op == "struct.new_default"sv) {
+ auto ret = makeStructNewStatic(ctx, in, true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '_':
+ if (op == "struct.new_default_with_rtt"sv) {
+ auto ret = makeStructNew(ctx, in, true);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'w':
+ if (op == "struct.new_with_rtt"sv) {
+ auto ret = makeStructNew(ctx, in, false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 's':
+ if (op == "struct.set"sv) {
+ auto ret = makeStructSet(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[1]) {
+ case 'a': {
+ switch (op[6]) {
+ case 'g': {
+ switch (op[7]) {
+ case 'e':
+ if (op == "table.get"sv) {
+ auto ret = makeTableGet(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r':
+ if (op == "table.grow"sv) {
+ auto ret = makeTableGrow(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 's': {
+ switch (op[7]) {
+ case 'e':
+ if (op == "table.set"sv) {
+ auto ret = makeTableSet(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'i':
+ if (op == "table.size"sv) {
+ auto ret = makeTableSize(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'h': {
+ switch (op[2]) {
+ case 'e':
+ if (op == "then"sv) {
+ auto ret = makeThenOrElse(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'r':
+ if (op == "throw"sv) {
+ auto ret = makeThrow(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'r':
+ if (op == "try"sv) {
+ auto ret = makeTry(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u': {
+ switch (op[6]) {
+ case 'e':
+ if (op == "tuple.extract"sv) {
+ auto ret = makeTupleExtract(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'm':
+ if (op == "tuple.make"sv) {
+ auto ret = makeTupleMake(ctx, in);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'u':
+ if (op == "unreachable"sv) {
+ auto ret = makeUnreachable(ctx);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'v': {
+ switch (op[5]) {
+ case 'a': {
+ switch (op[7]) {
+ case 'd': {
+ switch (op[8]) {
+ case '\0':
+ if (op == "v128.and"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AndVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'n':
+ if (op == "v128.andnot"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::AndNotVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'y':
+ if (op == "v128.any_true"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::AnyTrueVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'b':
+ if (op == "v128.bitselect"sv) {
+ auto ret = makeSIMDTernary(ctx, in, SIMDTernaryOp::Bitselect);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'c':
+ if (op == "v128.const"sv) {
+ auto ret = makeConst(ctx, in, Type::v128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'l': {
+ switch (op[9]) {
+ case '\0':
+ if (op == "v128.load"sv) {
+ auto ret = makeLoad(ctx, in, Type::v128, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '1': {
+ switch (op[11]) {
+ case '_': {
+ switch (op[12]) {
+ case 'l':
+ if (op == "v128.load16_lane"sv) {
+ auto ret = makeSIMDLoadStoreLane(ctx, in, SIMDLoadStoreLaneOp::Load16LaneVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "v128.load16_splat"sv) {
+ auto ret = makeSIMDLoad(ctx, in, SIMDLoadOp::Load16SplatVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'x': {
+ switch (op[14]) {
+ case 's':
+ if (op == "v128.load16x4_s"sv) {
+ auto ret = makeSIMDLoad(ctx, in, SIMDLoadOp::Load16x4SVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "v128.load16x4_u"sv) {
+ auto ret = makeSIMDLoad(ctx, in, SIMDLoadOp::Load16x4UVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case '3': {
+ switch (op[11]) {
+ case '_': {
+ switch (op[12]) {
+ case 'l':
+ if (op == "v128.load32_lane"sv) {
+ auto ret = makeSIMDLoadStoreLane(ctx, in, SIMDLoadStoreLaneOp::Load32LaneVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "v128.load32_splat"sv) {
+ auto ret = makeSIMDLoad(ctx, in, SIMDLoadOp::Load32SplatVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'z':
+ if (op == "v128.load32_zero"sv) {
+ auto ret = makeSIMDLoad(ctx, in, SIMDLoadOp::Load32ZeroVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'x': {
+ switch (op[14]) {
+ case 's':
+ if (op == "v128.load32x2_s"sv) {
+ auto ret = makeSIMDLoad(ctx, in, SIMDLoadOp::Load32x2SVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "v128.load32x2_u"sv) {
+ auto ret = makeSIMDLoad(ctx, in, SIMDLoadOp::Load32x2UVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case '6': {
+ switch (op[12]) {
+ case 'l':
+ if (op == "v128.load64_lane"sv) {
+ auto ret = makeSIMDLoadStoreLane(ctx, in, SIMDLoadStoreLaneOp::Load64LaneVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "v128.load64_splat"sv) {
+ auto ret = makeSIMDLoad(ctx, in, SIMDLoadOp::Load64SplatVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'z':
+ if (op == "v128.load64_zero"sv) {
+ auto ret = makeSIMDLoad(ctx, in, SIMDLoadOp::Load64ZeroVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case '8': {
+ switch (op[10]) {
+ case '_': {
+ switch (op[11]) {
+ case 'l':
+ if (op == "v128.load8_lane"sv) {
+ auto ret = makeSIMDLoadStoreLane(ctx, in, SIMDLoadStoreLaneOp::Load8LaneVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's':
+ if (op == "v128.load8_splat"sv) {
+ auto ret = makeSIMDLoad(ctx, in, SIMDLoadOp::Load8SplatVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'x': {
+ switch (op[13]) {
+ case 's':
+ if (op == "v128.load8x8_s"sv) {
+ auto ret = makeSIMDLoad(ctx, in, SIMDLoadOp::Load8x8SVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'u':
+ if (op == "v128.load8x8_u"sv) {
+ auto ret = makeSIMDLoad(ctx, in, SIMDLoadOp::Load8x8UVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'n':
+ if (op == "v128.not"sv) {
+ auto ret = makeUnary(ctx, in, UnaryOp::NotVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 'o':
+ if (op == "v128.or"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::OrVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case 's': {
+ switch (op[10]) {
+ case '\0':
+ if (op == "v128.store"sv) {
+ auto ret = makeStore(ctx, in, Type::v128, /*isAtomic=*/false);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '1':
+ if (op == "v128.store16_lane"sv) {
+ auto ret = makeSIMDLoadStoreLane(ctx, in, SIMDLoadStoreLaneOp::Store16LaneVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '3':
+ if (op == "v128.store32_lane"sv) {
+ auto ret = makeSIMDLoadStoreLane(ctx, in, SIMDLoadStoreLaneOp::Store32LaneVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '6':
+ if (op == "v128.store64_lane"sv) {
+ auto ret = makeSIMDLoadStoreLane(ctx, in, SIMDLoadStoreLaneOp::Store64LaneVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ case '8':
+ if (op == "v128.store8_lane"sv) {
+ auto ret = makeSIMDLoadStoreLane(ctx, in, SIMDLoadStoreLaneOp::Store8LaneVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case 'x':
+ if (op == "v128.xor"sv) {
+ auto ret = makeBinary(ctx, in, BinaryOp::XorVec128);
+ CHECK_ERR(ret);
+ return *ret;
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+}
+parse_error:
+ return in.err("unrecognized instruction");
+#endif // NEW_INSTRUCTION_PARSER
+
// clang-format on
diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp
index bb756159b..aa059b1db 100644
--- a/src/wasm/wat-parser.cpp
+++ b/src/wasm/wat-parser.cpp
@@ -48,8 +48,8 @@
// before we parse instructions because they determine the types of instructions
// such as global.get and ref.func.
//
-// In the fifth and final phase, not yet implemented, parses the remaining
-// contents of all module elements, including instructions.
+// The fifth and final phase parses the remaining contents of all module
+// elements, including instructions.
//
// Each phase of parsing gets its own context type that is passed to the
// individual parsing functions. There is a parsing function for each element of
@@ -127,6 +127,16 @@ struct ParseInput {
return {};
}
+ std::optional<std::string_view> takeKeyword() {
+ if (auto t = peek()) {
+ if (auto keyword = t->getKeyword()) {
+ ++lexer;
+ return *keyword;
+ }
+ }
+ return {};
+ }
+
bool takeKeyword(std::string_view expected) {
if (auto t = peek()) {
if (auto keyword = t->getKeyword()) {
@@ -308,6 +318,10 @@ struct ParseDeclsCtx {
using ArrayT = Ok;
using GlobalTypeT = Ok;
+ using InstrT = Ok;
+ using InstrsT = Ok;
+ using ExprT = Ok;
+
// Declared module elements are inserted into the module, but their bodies are
// not filled out until later parsing phases.
Module& wasm;
@@ -342,6 +356,10 @@ struct ParseTypeDefsCtx {
using StructT = std::pair<std::vector<Name>, Struct>;
using ArrayT = Array;
+ using InstrT = Ok;
+ using InstrsT = Ok;
+ using ExprT = Ok;
+
// We update slots in this builder as we parse type definitions.
TypeBuilder& builder;
@@ -374,6 +392,10 @@ struct ParseModuleTypesCtx {
using ResultsT = std::vector<Type>;
using GlobalTypeT = GlobalType;
+ using InstrT = Ok;
+ using InstrsT = Ok;
+ using ExprT = Ok;
+
Module& wasm;
const std::vector<HeapType>& types;
@@ -394,7 +416,38 @@ template<typename Ctx>
inline constexpr bool parsingModuleTypes =
std::is_same_v<Ctx, ParseModuleTypesCtx>;
-// TODO: Phase 5: ParseDefsCtx
+// Phase 5: Parse module element definitions, including instructions.
+struct ParseDefsCtx {
+ using IndexT = Index;
+ using TypeT = Type;
+ using HeapTypeT = HeapType;
+ // TODO: This could be Ok, but then we wouldn't be able to use RETURN_OR_OK.
+ using GlobalTypeT = GlobalType;
+
+ using InstrT = Expression*;
+ using InstrsT = std::vector<Expression*>;
+ using ExprT = Expression*;
+
+ Module& wasm;
+
+ Builder builder;
+
+ const std::vector<HeapType>& types;
+
+ // Map heap type names to their indices.
+ const IndexMap& typeIndices;
+
+ // The index of the current module element.
+ Index index = 0;
+
+ ParseDefsCtx(Module& wasm,
+ const std::vector<HeapType>& types,
+ const IndexMap& typeIndices)
+ : wasm(wasm), builder(wasm), types(types), typeIndices(typeIndices) {}
+};
+
+template<typename Ctx>
+inline constexpr bool parsingDefs = std::is_same_v<Ctx, ParseDefsCtx>;
// ================
// Parser Functions
@@ -421,6 +474,205 @@ template<typename Ctx>
MaybeResult<typename Ctx::StructT> structtype(Ctx&, ParseInput&);
template<typename Ctx>
MaybeResult<typename Ctx::ArrayT> arraytype(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::GlobalTypeT> globaltype(Ctx&, ParseInput&);
+
+// Instructions
+template<typename Ctx>
+MaybeResult<typename Ctx::InstrT> instr(Ctx&, ParseInput&);
+template<typename Ctx> Result<typename Ctx::InstrsT> instrs(Ctx&, ParseInput&);
+template<typename Ctx> Result<typename Ctx::ExprT> expr(Ctx&, ParseInput&);
+template<typename Ctx> Result<typename Ctx::InstrT> makeUnreachable(Ctx&);
+template<typename Ctx> Result<typename Ctx::InstrT> makeNop(Ctx&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeBinary(Ctx&, ParseInput&, BinaryOp op);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeUnary(Ctx&, ParseInput&, UnaryOp op);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeSelect(Ctx&, ParseInput&);
+template<typename Ctx> Result<typename Ctx::InstrT> makeDrop(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeMemorySize(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeMemoryGrow(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeLocalGet(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeLocalTee(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeLocalSet(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeGlobalGet(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeGlobalSet(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeBlock(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeThenOrElse(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeConst(Ctx&, ParseInput&, Type type);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeLoad(Ctx&, ParseInput&, Type type, bool isAtomic);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeStore(Ctx&, ParseInput&, Type type, bool isAtomic);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeAtomicRMWOrCmpxchg(Ctx&, ParseInput&, Type type);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeAtomicRMW(Ctx&, ParseInput&, Type type, uint8_t bytes, const char* extra);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeAtomicCmpxchg(
+ Ctx&, ParseInput&, Type type, uint8_t bytes, const char* extra);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeAtomicWait(Ctx&, ParseInput&, Type type);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeAtomicNotify(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeAtomicFence(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeSIMDExtract(Ctx&, ParseInput&, SIMDExtractOp op, size_t lanes);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeSIMDReplace(Ctx&, ParseInput&, SIMDReplaceOp op, size_t lanes);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeSIMDShuffle(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeSIMDTernary(Ctx&, ParseInput&, SIMDTernaryOp op);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeSIMDShift(Ctx&, ParseInput&, SIMDShiftOp op);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeSIMDLoad(Ctx&, ParseInput&, SIMDLoadOp op);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeSIMDLoadStoreLane(Ctx&, ParseInput&, SIMDLoadStoreLaneOp op);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeMemoryInit(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeDataDrop(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeMemoryCopy(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeMemoryFill(Ctx&, ParseInput&);
+template<typename Ctx> Result<typename Ctx::InstrT> makePush(Ctx&, ParseInput&);
+template<typename Ctx> Result<typename Ctx::InstrT> makePop(Ctx&, ParseInput&);
+template<typename Ctx> Result<typename Ctx::InstrT> makeIf(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeMaybeBlock(Ctx&, ParseInput&, size_t i, Type type);
+template<typename Ctx> Result<typename Ctx::InstrT> makeLoop(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeCall(Ctx&, ParseInput&, bool isReturn);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeCallIndirect(Ctx&, ParseInput&, bool isReturn);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeBreak(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeBreakTable(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeReturn(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefNull(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefIs(Ctx&, ParseInput&, RefIsOp op);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefFunc(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefEq(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeTableGet(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeTableSet(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeTableSize(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeTableGrow(Ctx&, ParseInput&);
+template<typename Ctx> Result<typename Ctx::InstrT> makeTry(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeTryOrCatchBody(Ctx&, ParseInput&, Type type, bool isTry);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeThrow(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRethrow(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeTupleMake(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeTupleExtract(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeCallRef(Ctx&, ParseInput&, bool isReturn);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeI31New(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeI31Get(Ctx&, ParseInput&, bool signed_);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefTest(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefTestStatic(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefCast(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefCastStatic(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefCastNopStatic(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeBrOn(Ctx&, ParseInput&, BrOnOp op);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeBrOnStatic(Ctx&, ParseInput&, BrOnOp op);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRttCanon(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRttSub(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRttFreshSub(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeStructNew(Ctx&, ParseInput&, bool default_);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeStructNewStatic(Ctx&, ParseInput&, bool default_);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeStructGet(Ctx&, ParseInput&, bool signed_ = false);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeStructSet(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeArrayNew(Ctx&, ParseInput&, bool default_);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeArrayNewStatic(Ctx&, ParseInput&, bool default_);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeArrayInit(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeArrayInitStatic(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeArrayGet(Ctx&, ParseInput&, bool signed_ = false);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeArraySet(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeArrayLen(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeArrayCopy(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefAs(Ctx&, ParseInput&, RefAsOp op);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeStringNew(Ctx&, ParseInput&, StringNewOp op);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeStringConst(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeStringMeasure(Ctx&, ParseInput&, StringMeasureOp op);
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeStringEncode(Ctx&, ParseInput&, StringEncodeOp op);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeStringConcat(Ctx&, ParseInput&);
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeStringEq(Ctx&, ParseInput&);
// Modules
template<typename Ctx>
@@ -813,6 +1065,602 @@ Result<typename Ctx::GlobalTypeT> globaltype(Ctx& ctx, ParseInput& in) {
RETURN_OR_OK((GlobalType{Immutable, *type}));
}
+// ============
+// Instructions
+// ============
+
+template<typename Ctx>
+MaybeResult<typename Ctx::InstrT> instr(Ctx& ctx, ParseInput& in) {
+ auto keyword = in.takeKeyword();
+ if (!keyword) {
+ return {};
+ }
+
+ auto op = *keyword;
+
+#define NEW_INSTRUCTION_PARSER
+#define NEW_WAT_PARSER
+#include <gen-s-parser.inc>
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrsT> instrs(Ctx& ctx, ParseInput& in) {
+ // TODO: Folded instructions.
+ std::vector<Expression*> insts;
+ while (auto inst = instr(ctx, in)) {
+ CHECK_ERR(inst);
+ if constexpr (parsingDefs<Ctx>) {
+ insts.push_back(*inst);
+ }
+ }
+ if constexpr (parsingDefs<Ctx>) {
+ return insts;
+ } else {
+ return Ok{};
+ }
+}
+
+template<typename Ctx>
+Result<typename Ctx::ExprT> expr(Ctx& ctx, ParseInput& in) {
+ auto insts = instrs(ctx, in);
+ CHECK_ERR(insts);
+ if constexpr (parsingDefs<Ctx>) {
+ switch (insts->size()) {
+ case 0:
+ return ctx.builder.makeNop();
+ case 1:
+ return insts->front();
+ default:
+ return ctx.builder.makeBlock(*insts);
+ }
+ } else {
+ return Ok{};
+ }
+}
+
+template<typename Ctx> Result<typename Ctx::InstrT> makeUnreachable(Ctx& ctx) {
+ if constexpr (parsingDefs<Ctx>) {
+ return ctx.builder.makeUnreachable();
+ } else {
+ return Ok{};
+ }
+}
+
+template<typename Ctx> Result<typename Ctx::InstrT> makeNop(Ctx& ctx) {
+ if constexpr (parsingDefs<Ctx>) {
+ return ctx.builder.makeNop();
+ } else {
+ return Ok{};
+ }
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeBinary(Ctx& ctx, ParseInput& in, BinaryOp op) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeUnary(Ctx& ctx, ParseInput& in, UnaryOp op) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeSelect(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeDrop(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeMemorySize(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeMemoryGrow(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeLocalGet(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeLocalTee(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeLocalSet(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeGlobalGet(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeGlobalSet(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeBlock(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeThenOrElse(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeConst(Ctx& ctx, ParseInput& in, Type type) {
+ assert(type.isBasic());
+ switch (type.getBasic()) {
+ case Type::i32:
+ if (auto c = in.takeI32()) {
+ if constexpr (parsingDefs<Ctx>) {
+ return ctx.builder.makeConst(Literal(*c));
+ } else {
+ return Ok{};
+ }
+ }
+ return in.err("expected i32");
+ case Type::i64:
+ if (auto c = in.takeI64()) {
+ if constexpr (parsingDefs<Ctx>) {
+ return ctx.builder.makeConst(Literal(*c));
+ } else {
+ return Ok{};
+ }
+ }
+ return in.err("expected i64");
+ case Type::f32:
+ if (auto f = in.takeF32()) {
+ if constexpr (parsingDefs<Ctx>) {
+ return ctx.builder.makeConst(Literal(*f));
+ } else {
+ return Ok{};
+ }
+ }
+ return in.err("expected f32");
+ case Type::f64:
+ if (auto f = in.takeF64()) {
+ if constexpr (parsingDefs<Ctx>) {
+ return ctx.builder.makeConst(Literal(*f));
+ } else {
+ return Ok{};
+ }
+ }
+ return in.err("expected f64");
+ case Type::v128:
+ return in.err("unimplemented instruction");
+ case Type::none:
+ case Type::unreachable:
+ case Type::funcref:
+ case Type::anyref:
+ case Type::eqref:
+ case Type::i31ref:
+ case Type::dataref:
+ break;
+ }
+ WASM_UNREACHABLE("unexpected type");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeLoad(Ctx& ctx, ParseInput& in, Type type, bool isAtomic) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeStore(Ctx& ctx, ParseInput& in, Type type, bool isAtomic) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeAtomicRMWOrCmpxchg(Ctx& ctx, ParseInput& in, Type type) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeAtomicRMW(
+ Ctx& ctx, ParseInput& in, Type type, uint8_t bytes, const char* extra) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeAtomicCmpxchg(
+ Ctx& ctx, ParseInput& in, Type type, uint8_t bytes, const char* extra) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeAtomicWait(Ctx& ctx, ParseInput& in, Type type) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeAtomicNotify(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeAtomicFence(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeSIMDExtract(Ctx& ctx, ParseInput& in, SIMDExtractOp op, size_t lanes) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeSIMDReplace(Ctx& ctx, ParseInput& in, SIMDReplaceOp op, size_t lanes) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeSIMDShuffle(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeSIMDTernary(Ctx& ctx, ParseInput& in, SIMDTernaryOp op) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeSIMDShift(Ctx& ctx, ParseInput& in, SIMDShiftOp op) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeSIMDLoad(Ctx& ctx, ParseInput& in, SIMDLoadOp op) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeSIMDLoadStoreLane(Ctx& ctx, ParseInput& in, SIMDLoadStoreLaneOp op) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeMemoryInit(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeDataDrop(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeMemoryCopy(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeMemoryFill(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makePush(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makePop(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeIf(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeMaybeBlock(Ctx& ctx, ParseInput& in, size_t i, Type type) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeLoop(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeCall(Ctx& ctx, ParseInput& in, bool isReturn) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeCallIndirect(Ctx& ctx, ParseInput& in, bool isReturn) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeBreak(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeBreakTable(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeReturn(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefNull(Ctx& ctx, ParseInput& in) {
+ auto t = heaptype(ctx, in);
+ CHECK_ERR(t);
+ if constexpr (parsingDefs<Ctx>) {
+ return ctx.builder.makeRefNull(*t);
+ } else {
+ return Ok{};
+ }
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefIs(Ctx& ctx, ParseInput& in, RefIsOp op) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefFunc(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefEq(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeTableGet(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeTableSet(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeTableSize(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeTableGrow(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeTry(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeTryOrCatchBody(Ctx& ctx, ParseInput& in, Type type, bool isTry) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeThrow(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRethrow(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeTupleMake(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeTupleExtract(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeCallRef(Ctx& ctx, ParseInput& in, bool isReturn) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeI31New(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeI31Get(Ctx& ctx, ParseInput& in, bool signed_) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefTest(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefTestStatic(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefCast(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefCastStatic(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefCastNopStatic(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeBrOn(Ctx& ctx, ParseInput& in, BrOnOp op) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeBrOnStatic(Ctx& ctx, ParseInput& in, BrOnOp op) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRttCanon(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRttSub(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRttFreshSub(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeStructNew(Ctx& ctx, ParseInput& in, bool default_) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeStructNewStatic(Ctx& ctx, ParseInput& in, bool default_) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeStructGet(Ctx& ctx, ParseInput& in, bool signed_) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeStructSet(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeArrayNew(Ctx& ctx, ParseInput& in, bool default_) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeArrayNewStatic(Ctx& ctx, ParseInput& in, bool default_) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeArrayInit(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeArrayInitStatic(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeArrayGet(Ctx& ctx, ParseInput& in, bool signed_) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeArraySet(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeArrayLen(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeArrayCopy(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeRefAs(Ctx& ctx, ParseInput& in, RefAsOp op) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeStringNew(Ctx& ctx, ParseInput& in, StringNewOp op) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeStringConst(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeStringMeasure(Ctx& ctx, ParseInput& in, StringMeasureOp op) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeStringEncode(Ctx& ctx, ParseInput& in, StringEncodeOp op) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeStringConcat(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT> makeStringEq(Ctx& ctx, ParseInput& in) {
+ return in.err("unimplemented instruction");
+}
+
// =======
// Modules
// =======
@@ -1035,28 +1883,37 @@ template<typename Ctx> MaybeResult<> global(Ctx& ctx, ParseInput& in) {
auto type = globaltype(ctx, in);
CHECK_ERR(type);
- if (import) {
- if (!in.takeRParen()) {
- return in.err("expected end of global");
- }
+ std::optional<typename Ctx::ExprT> exp;
+ if (!import) {
+ auto e = expr(ctx, in);
+ CHECK_ERR(e);
+ *exp = *e;
+ }
- if constexpr (parsingDecls<Ctx>) {
- if (ctx.hasNonImport) {
- return in.err("import after non-import");
- }
- auto g = addGlobalDecl(ctx, in, name, *import);
- CHECK_ERR(g);
- CHECK_ERR(addExports(in, ctx.wasm, *g, *exports, ExternalKind::Global));
- ctx.globalDefs.push_back({name, pos});
- } else if constexpr (parsingModuleTypes<Ctx>) {
- auto& g = ctx.wasm.globals[ctx.index];
- g->mutable_ = type->mutability;
- g->type = type->type;
+ if (!in.takeRParen()) {
+ return in.err("expected end of global");
+ }
+
+ if constexpr (parsingDecls<Ctx>) {
+ if (ctx.hasNonImport) {
+ return in.err("import after non-import");
+ }
+ auto imp = import ? std::make_optional(*import) : std::nullopt;
+ auto g = addGlobalDecl(ctx, in, name, imp);
+ CHECK_ERR(g);
+ CHECK_ERR(addExports(in, ctx.wasm, *g, *exports, ExternalKind::Global));
+ ctx.globalDefs.push_back({name, pos});
+ } else if constexpr (parsingModuleTypes<Ctx>) {
+ auto& g = ctx.wasm.globals[ctx.index];
+ g->mutable_ = type->mutability;
+ g->type = type->type;
+ } else if constexpr (parsingDefs<Ctx>) {
+ if (!import) {
+ ctx.wasm.globals[ctx.index]->init = *exp;
}
- return Ok{};
}
- return in.err("TODO: non-imported globals");
+ return Ok{};
}
// modulefield ::= deftype
@@ -1236,13 +2093,18 @@ Result<> parseModule(Module& wasm, std::string_view input) {
// TODO: Parse implicit type definitions.
- // Parse module-level types.
- ParseModuleTypesCtx ctx(wasm, types, *typeIndices);
- CHECK_ERR(parseDefs(ctx, input, decls.globalDefs, global));
-
- // TODO: Parse types of other module elements.
-
- // TODO: Parse definitions.
+ {
+ // Parse module-level types.
+ ParseModuleTypesCtx ctx(wasm, types, *typeIndices);
+ CHECK_ERR(parseDefs(ctx, input, decls.globalDefs, global));
+ // TODO: Parse types of other module elements.
+ }
+ {
+ // Parse definitions.
+ // TODO: Parallelize this.
+ ParseDefsCtx ctx(wasm, types, *typeIndices);
+ CHECK_ERR(parseDefs(ctx, input, decls.globalDefs, global));
+ }
return Ok{};
}