From 5aa2e182f12d17e8dcdd7f8e3df68616c3e61b5a Mon Sep 17 00:00:00 2001 From: Thomas Lively <7121787+tlively@users.noreply.github.com> Date: Mon, 11 Jul 2022 15:14:51 -0700 Subject: [Parser] Start to parse instructions (#4789) Update gen-s-parser.py to produce a second version of its parsing code that works with the new wat parser. The new version automatically replaces the `s` element argument in the existing parser with the `ctx` and `in` arguments used by the new parser, so adding new instructions will not require any additional work in gen-s-parser.py after this change. Also add stub `make***` functions to the new wat parser, with a few filled out, namely `makeNop`, `makeUnreachable`, `makeConst`, and `makeRefNull`. Update the `global` parser to parse global initializer instructions and update wat-kitchen-sink.wast to demonstrate that the instructions are parsed correctly. Adding new instruction classes will require adding a new `make***` function to wat-parser.cpp in additional to wasm-s-parser.{h,cpp} after this change, but adding a trivial failing implementation is good enough for the time being, so I don't expect this to appreciably increase our maintenance burden in the near term. The infrastructure for parsing folded instructions, instructions with operands, and control flow instructions will be implemented in future PRs. --- src/gen-s-parser.inc | 5834 +++++++++++++++++++++++++++++++++++++++++++++++ src/wasm/wat-parser.cpp | 918 +++++++- 2 files changed, 6724 insertions(+), 28 deletions(-) (limited to 'src') 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 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, 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; using GlobalTypeT = GlobalType; + using InstrT = Ok; + using InstrsT = Ok; + using ExprT = Ok; + Module& wasm; const std::vector& types; @@ -394,7 +416,38 @@ template inline constexpr bool parsingModuleTypes = std::is_same_v; -// 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; + using ExprT = Expression*; + + Module& wasm; + + Builder builder; + + const std::vector& 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& types, + const IndexMap& typeIndices) + : wasm(wasm), builder(wasm), types(types), typeIndices(typeIndices) {} +}; + +template +inline constexpr bool parsingDefs = std::is_same_v; // ================ // Parser Functions @@ -421,6 +474,205 @@ template MaybeResult structtype(Ctx&, ParseInput&); template MaybeResult arraytype(Ctx&, ParseInput&); +template +Result globaltype(Ctx&, ParseInput&); + +// Instructions +template +MaybeResult instr(Ctx&, ParseInput&); +template Result instrs(Ctx&, ParseInput&); +template Result expr(Ctx&, ParseInput&); +template Result makeUnreachable(Ctx&); +template Result makeNop(Ctx&); +template +Result makeBinary(Ctx&, ParseInput&, BinaryOp op); +template +Result makeUnary(Ctx&, ParseInput&, UnaryOp op); +template +Result makeSelect(Ctx&, ParseInput&); +template Result makeDrop(Ctx&, ParseInput&); +template +Result makeMemorySize(Ctx&, ParseInput&); +template +Result makeMemoryGrow(Ctx&, ParseInput&); +template +Result makeLocalGet(Ctx&, ParseInput&); +template +Result makeLocalTee(Ctx&, ParseInput&); +template +Result makeLocalSet(Ctx&, ParseInput&); +template +Result makeGlobalGet(Ctx&, ParseInput&); +template +Result makeGlobalSet(Ctx&, ParseInput&); +template +Result makeBlock(Ctx&, ParseInput&); +template +Result makeThenOrElse(Ctx&, ParseInput&); +template +Result makeConst(Ctx&, ParseInput&, Type type); +template +Result +makeLoad(Ctx&, ParseInput&, Type type, bool isAtomic); +template +Result +makeStore(Ctx&, ParseInput&, Type type, bool isAtomic); +template +Result +makeAtomicRMWOrCmpxchg(Ctx&, ParseInput&, Type type); +template +Result +makeAtomicRMW(Ctx&, ParseInput&, Type type, uint8_t bytes, const char* extra); +template +Result makeAtomicCmpxchg( + Ctx&, ParseInput&, Type type, uint8_t bytes, const char* extra); +template +Result makeAtomicWait(Ctx&, ParseInput&, Type type); +template +Result makeAtomicNotify(Ctx&, ParseInput&); +template +Result makeAtomicFence(Ctx&, ParseInput&); +template +Result +makeSIMDExtract(Ctx&, ParseInput&, SIMDExtractOp op, size_t lanes); +template +Result +makeSIMDReplace(Ctx&, ParseInput&, SIMDReplaceOp op, size_t lanes); +template +Result makeSIMDShuffle(Ctx&, ParseInput&); +template +Result +makeSIMDTernary(Ctx&, ParseInput&, SIMDTernaryOp op); +template +Result makeSIMDShift(Ctx&, ParseInput&, SIMDShiftOp op); +template +Result makeSIMDLoad(Ctx&, ParseInput&, SIMDLoadOp op); +template +Result +makeSIMDLoadStoreLane(Ctx&, ParseInput&, SIMDLoadStoreLaneOp op); +template +Result makeMemoryInit(Ctx&, ParseInput&); +template +Result makeDataDrop(Ctx&, ParseInput&); +template +Result makeMemoryCopy(Ctx&, ParseInput&); +template +Result makeMemoryFill(Ctx&, ParseInput&); +template Result makePush(Ctx&, ParseInput&); +template Result makePop(Ctx&, ParseInput&); +template Result makeIf(Ctx&, ParseInput&); +template +Result +makeMaybeBlock(Ctx&, ParseInput&, size_t i, Type type); +template Result makeLoop(Ctx&, ParseInput&); +template +Result makeCall(Ctx&, ParseInput&, bool isReturn); +template +Result makeCallIndirect(Ctx&, ParseInput&, bool isReturn); +template +Result makeBreak(Ctx&, ParseInput&); +template +Result makeBreakTable(Ctx&, ParseInput&); +template +Result makeReturn(Ctx&, ParseInput&); +template +Result makeRefNull(Ctx&, ParseInput&); +template +Result makeRefIs(Ctx&, ParseInput&, RefIsOp op); +template +Result makeRefFunc(Ctx&, ParseInput&); +template +Result makeRefEq(Ctx&, ParseInput&); +template +Result makeTableGet(Ctx&, ParseInput&); +template +Result makeTableSet(Ctx&, ParseInput&); +template +Result makeTableSize(Ctx&, ParseInput&); +template +Result makeTableGrow(Ctx&, ParseInput&); +template Result makeTry(Ctx&, ParseInput&); +template +Result +makeTryOrCatchBody(Ctx&, ParseInput&, Type type, bool isTry); +template +Result makeThrow(Ctx&, ParseInput&); +template +Result makeRethrow(Ctx&, ParseInput&); +template +Result makeTupleMake(Ctx&, ParseInput&); +template +Result makeTupleExtract(Ctx&, ParseInput&); +template +Result makeCallRef(Ctx&, ParseInput&, bool isReturn); +template +Result makeI31New(Ctx&, ParseInput&); +template +Result makeI31Get(Ctx&, ParseInput&, bool signed_); +template +Result makeRefTest(Ctx&, ParseInput&); +template +Result makeRefTestStatic(Ctx&, ParseInput&); +template +Result makeRefCast(Ctx&, ParseInput&); +template +Result makeRefCastStatic(Ctx&, ParseInput&); +template +Result makeRefCastNopStatic(Ctx&, ParseInput&); +template +Result makeBrOn(Ctx&, ParseInput&, BrOnOp op); +template +Result makeBrOnStatic(Ctx&, ParseInput&, BrOnOp op); +template +Result makeRttCanon(Ctx&, ParseInput&); +template +Result makeRttSub(Ctx&, ParseInput&); +template +Result makeRttFreshSub(Ctx&, ParseInput&); +template +Result makeStructNew(Ctx&, ParseInput&, bool default_); +template +Result +makeStructNewStatic(Ctx&, ParseInput&, bool default_); +template +Result +makeStructGet(Ctx&, ParseInput&, bool signed_ = false); +template +Result makeStructSet(Ctx&, ParseInput&); +template +Result makeArrayNew(Ctx&, ParseInput&, bool default_); +template +Result +makeArrayNewStatic(Ctx&, ParseInput&, bool default_); +template +Result makeArrayInit(Ctx&, ParseInput&); +template +Result makeArrayInitStatic(Ctx&, ParseInput&); +template +Result +makeArrayGet(Ctx&, ParseInput&, bool signed_ = false); +template +Result makeArraySet(Ctx&, ParseInput&); +template +Result makeArrayLen(Ctx&, ParseInput&); +template +Result makeArrayCopy(Ctx&, ParseInput&); +template +Result makeRefAs(Ctx&, ParseInput&, RefAsOp op); +template +Result makeStringNew(Ctx&, ParseInput&, StringNewOp op); +template +Result makeStringConst(Ctx&, ParseInput&); +template +Result +makeStringMeasure(Ctx&, ParseInput&, StringMeasureOp op); +template +Result +makeStringEncode(Ctx&, ParseInput&, StringEncodeOp op); +template +Result makeStringConcat(Ctx&, ParseInput&); +template +Result makeStringEq(Ctx&, ParseInput&); // Modules template @@ -813,6 +1065,602 @@ Result globaltype(Ctx& ctx, ParseInput& in) { RETURN_OR_OK((GlobalType{Immutable, *type})); } +// ============ +// Instructions +// ============ + +template +MaybeResult instr(Ctx& ctx, ParseInput& in) { + auto keyword = in.takeKeyword(); + if (!keyword) { + return {}; + } + + auto op = *keyword; + +#define NEW_INSTRUCTION_PARSER +#define NEW_WAT_PARSER +#include +} + +template +Result instrs(Ctx& ctx, ParseInput& in) { + // TODO: Folded instructions. + std::vector insts; + while (auto inst = instr(ctx, in)) { + CHECK_ERR(inst); + if constexpr (parsingDefs) { + insts.push_back(*inst); + } + } + if constexpr (parsingDefs) { + return insts; + } else { + return Ok{}; + } +} + +template +Result expr(Ctx& ctx, ParseInput& in) { + auto insts = instrs(ctx, in); + CHECK_ERR(insts); + if constexpr (parsingDefs) { + switch (insts->size()) { + case 0: + return ctx.builder.makeNop(); + case 1: + return insts->front(); + default: + return ctx.builder.makeBlock(*insts); + } + } else { + return Ok{}; + } +} + +template Result makeUnreachable(Ctx& ctx) { + if constexpr (parsingDefs) { + return ctx.builder.makeUnreachable(); + } else { + return Ok{}; + } +} + +template Result makeNop(Ctx& ctx) { + if constexpr (parsingDefs) { + return ctx.builder.makeNop(); + } else { + return Ok{}; + } +} + +template +Result makeBinary(Ctx& ctx, ParseInput& in, BinaryOp op) { + return in.err("unimplemented instruction"); +} + +template +Result makeUnary(Ctx& ctx, ParseInput& in, UnaryOp op) { + return in.err("unimplemented instruction"); +} + +template +Result makeSelect(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeDrop(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeMemorySize(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeMemoryGrow(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeLocalGet(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeLocalTee(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeLocalSet(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeGlobalGet(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeGlobalSet(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeBlock(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeThenOrElse(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeConst(Ctx& ctx, ParseInput& in, Type type) { + assert(type.isBasic()); + switch (type.getBasic()) { + case Type::i32: + if (auto c = in.takeI32()) { + if constexpr (parsingDefs) { + 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) { + 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) { + 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) { + 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 +Result +makeLoad(Ctx& ctx, ParseInput& in, Type type, bool isAtomic) { + return in.err("unimplemented instruction"); +} + +template +Result +makeStore(Ctx& ctx, ParseInput& in, Type type, bool isAtomic) { + return in.err("unimplemented instruction"); +} + +template +Result +makeAtomicRMWOrCmpxchg(Ctx& ctx, ParseInput& in, Type type) { + return in.err("unimplemented instruction"); +} + +template +Result makeAtomicRMW( + Ctx& ctx, ParseInput& in, Type type, uint8_t bytes, const char* extra) { + return in.err("unimplemented instruction"); +} + +template +Result makeAtomicCmpxchg( + Ctx& ctx, ParseInput& in, Type type, uint8_t bytes, const char* extra) { + return in.err("unimplemented instruction"); +} + +template +Result +makeAtomicWait(Ctx& ctx, ParseInput& in, Type type) { + return in.err("unimplemented instruction"); +} + +template +Result makeAtomicNotify(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeAtomicFence(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result +makeSIMDExtract(Ctx& ctx, ParseInput& in, SIMDExtractOp op, size_t lanes) { + return in.err("unimplemented instruction"); +} + +template +Result +makeSIMDReplace(Ctx& ctx, ParseInput& in, SIMDReplaceOp op, size_t lanes) { + return in.err("unimplemented instruction"); +} + +template +Result makeSIMDShuffle(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result +makeSIMDTernary(Ctx& ctx, ParseInput& in, SIMDTernaryOp op) { + return in.err("unimplemented instruction"); +} + +template +Result +makeSIMDShift(Ctx& ctx, ParseInput& in, SIMDShiftOp op) { + return in.err("unimplemented instruction"); +} + +template +Result +makeSIMDLoad(Ctx& ctx, ParseInput& in, SIMDLoadOp op) { + return in.err("unimplemented instruction"); +} + +template +Result +makeSIMDLoadStoreLane(Ctx& ctx, ParseInput& in, SIMDLoadStoreLaneOp op) { + return in.err("unimplemented instruction"); +} + +template +Result makeMemoryInit(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeDataDrop(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeMemoryCopy(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeMemoryFill(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makePush(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makePop(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeIf(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result +makeMaybeBlock(Ctx& ctx, ParseInput& in, size_t i, Type type) { + return in.err("unimplemented instruction"); +} + +template +Result makeLoop(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeCall(Ctx& ctx, ParseInput& in, bool isReturn) { + return in.err("unimplemented instruction"); +} + +template +Result +makeCallIndirect(Ctx& ctx, ParseInput& in, bool isReturn) { + return in.err("unimplemented instruction"); +} + +template +Result makeBreak(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeBreakTable(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeReturn(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeRefNull(Ctx& ctx, ParseInput& in) { + auto t = heaptype(ctx, in); + CHECK_ERR(t); + if constexpr (parsingDefs) { + return ctx.builder.makeRefNull(*t); + } else { + return Ok{}; + } +} + +template +Result makeRefIs(Ctx& ctx, ParseInput& in, RefIsOp op) { + return in.err("unimplemented instruction"); +} + +template +Result makeRefFunc(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeRefEq(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeTableGet(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeTableSet(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeTableSize(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeTableGrow(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeTry(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result +makeTryOrCatchBody(Ctx& ctx, ParseInput& in, Type type, bool isTry) { + return in.err("unimplemented instruction"); +} + +template +Result makeThrow(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeRethrow(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeTupleMake(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeTupleExtract(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result +makeCallRef(Ctx& ctx, ParseInput& in, bool isReturn) { + return in.err("unimplemented instruction"); +} + +template +Result makeI31New(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result +makeI31Get(Ctx& ctx, ParseInput& in, bool signed_) { + return in.err("unimplemented instruction"); +} + +template +Result makeRefTest(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeRefTestStatic(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeRefCast(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeRefCastStatic(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeRefCastNopStatic(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeBrOn(Ctx& ctx, ParseInput& in, BrOnOp op) { + return in.err("unimplemented instruction"); +} + +template +Result +makeBrOnStatic(Ctx& ctx, ParseInput& in, BrOnOp op) { + return in.err("unimplemented instruction"); +} + +template +Result makeRttCanon(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeRttSub(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeRttFreshSub(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result +makeStructNew(Ctx& ctx, ParseInput& in, bool default_) { + return in.err("unimplemented instruction"); +} + +template +Result +makeStructNewStatic(Ctx& ctx, ParseInput& in, bool default_) { + return in.err("unimplemented instruction"); +} + +template +Result +makeStructGet(Ctx& ctx, ParseInput& in, bool signed_) { + return in.err("unimplemented instruction"); +} + +template +Result makeStructSet(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result +makeArrayNew(Ctx& ctx, ParseInput& in, bool default_) { + return in.err("unimplemented instruction"); +} + +template +Result +makeArrayNewStatic(Ctx& ctx, ParseInput& in, bool default_) { + return in.err("unimplemented instruction"); +} + +template +Result makeArrayInit(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeArrayInitStatic(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result +makeArrayGet(Ctx& ctx, ParseInput& in, bool signed_) { + return in.err("unimplemented instruction"); +} + +template +Result makeArraySet(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeArrayLen(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeArrayCopy(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeRefAs(Ctx& ctx, ParseInput& in, RefAsOp op) { + return in.err("unimplemented instruction"); +} + +template +Result +makeStringNew(Ctx& ctx, ParseInput& in, StringNewOp op) { + return in.err("unimplemented instruction"); +} + +template +Result makeStringConst(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result +makeStringMeasure(Ctx& ctx, ParseInput& in, StringMeasureOp op) { + return in.err("unimplemented instruction"); +} + +template +Result +makeStringEncode(Ctx& ctx, ParseInput& in, StringEncodeOp op) { + return in.err("unimplemented instruction"); +} + +template +Result makeStringConcat(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + +template +Result makeStringEq(Ctx& ctx, ParseInput& in) { + return in.err("unimplemented instruction"); +} + // ======= // Modules // ======= @@ -1035,28 +1883,37 @@ template 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 exp; + if (!import) { + auto e = expr(ctx, in); + CHECK_ERR(e); + *exp = *e; + } - if constexpr (parsingDecls) { - 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) { - 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) { + 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) { + auto& g = ctx.wasm.globals[ctx.index]; + g->mutable_ = type->mutability; + g->type = type->type; + } else if constexpr (parsingDefs) { + 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{}; } -- cgit v1.2.3