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