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 | |
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.
-rwxr-xr-x | scripts/gen-s-parser.py | 28 | ||||
-rw-r--r-- | src/gen-s-parser.inc | 5834 | ||||
-rw-r--r-- | src/wasm/wat-parser.cpp | 918 | ||||
-rw-r--r-- | test/lit/wat-kitchen-sink.wast | 109 |
4 files changed, 6796 insertions, 93 deletions
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py index d0848622f..eb921a6b9 100755 --- a/scripts/gen-s-parser.py +++ b/scripts/gen-s-parser.py @@ -693,7 +693,7 @@ class Node: self.do_insert(inst, inst, expr) -def instruction_parser(): +def instruction_parser(new_parser=False): """Build a trie out of all the instructions, then emit it as C++ code.""" trie = Node() inst_length = 0 @@ -703,12 +703,23 @@ def instruction_parser(): printer = CodePrinter() - printer.print_line("char op[{}] = {{'\\0'}};".format(inst_length + 1)) - printer.print_line("strncpy(op, s[0]->c_str(), {});".format(inst_length)) + if not new_parser: + printer.print_line("char op[{}] = {{'\\0'}};".format(inst_length + 1)) + printer.print_line("strncpy(op, s[0]->c_str(), {});".format(inst_length)) def print_leaf(expr, inst): - printer.print_line("if (strcmp(op, \"{inst}\") == 0) {{ return {expr}; }}" - .format(inst=inst, expr=expr)) + if new_parser: + expr = expr.replace("()", "(ctx)") + expr = expr.replace("(s", "(ctx, in") + printer.print_line("if (op == \"{inst}\"sv) {{".format(inst=inst)) + with printer.indent(): + printer.print_line("auto ret = {expr};".format(expr=expr)) + printer.print_line("CHECK_ERR(ret);") + printer.print_line("return *ret;") + printer.print_line("}") + else: + printer.print_line("if (strcmp(op, \"{inst}\") == 0) {{ return {expr}; }}" + .format(inst=inst, expr=expr)) printer.print_line("goto parse_error;") def emit(node, idx=0): @@ -737,7 +748,10 @@ def instruction_parser(): emit(trie) printer.print_line("parse_error:") with printer.indent(): - printer.print_line("throw ParseException(std::string(op), s.line, s.col);") + if new_parser: + printer.print_line("return in.err(\"unrecognized instruction\");") + else: + printer.print_line("throw ParseException(std::string(op), s.line, s.col);") def print_header(): @@ -763,6 +777,8 @@ def main(): sys.exit(1) print_header() generate_with_guard(instruction_parser, "INSTRUCTION_PARSER") + print() + generate_with_guard(lambda: instruction_parser(True), "NEW_INSTRUCTION_PARSER") print_footer() 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{}; } diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast index 9ec1b7c5d..ddb974ed6 100644 --- a/test/lit/wat-kitchen-sink.wast +++ b/test/lit/wat-kitchen-sink.wast @@ -5,14 +5,6 @@ (module $parse ;; types (rec - ;; CHECK: (type $void (func_subtype func)) - (type $void (func)) - ) - ;; CHECK: (type $many (func_subtype (param i32 i64 f32 f64) (result anyref (ref func)) func)) - (type $many (func (param $x i32) (param i64 f32) (param) (param $y f64) - (result anyref (ref func)))) - - (rec ;; CHECK: (rec ;; CHECK-NEXT: (type $s0 (struct_subtype data)) (type $s0 (sub (struct))) @@ -46,8 +38,17 @@ ;; CHECK: (type $a3 (array_subtype (mut f64) data)) (type $a3 (array (field $x (mut f64)))) + (rec + ;; CHECK: (type $void (func_subtype func)) + (type $void (func)) + ) + ;; CHECK: (type $subvoid (func_subtype $void)) - (type $subvoid (sub 0 (func))) + (type $subvoid (sub $void (func))) + + ;; CHECK: (type $many (func_subtype (param i32 i64 f32 f64) (result anyref (ref func)) func)) + (type $many (func (param $x i32) (param i64 f32) (param) (param $y f64) + (result anyref (ref func)))) ;; CHECK: (type $submany (func_subtype (param i32 i64 f32 f64) (result anyref (ref func)) $many)) (type $submany (sub $many (func (param i32 i64 f32 f64) (result anyref (ref func))))) @@ -58,62 +59,52 @@ (global (import "" "g3") (ref 0)) (global (import "mod" "") (ref null $many)) - ;; uninteresting globals just to use the types - ;; TODO: replace these with a function. - (global $s0 (import "mod" "s0") (mut (ref $s0))) - (global $s1 (import "mod" "s1") (mut (ref $s1))) - (global $s2 (import "mod" "s2") (mut (ref $s2))) - (global $s3 (import "mod" "s3") (mut (ref $s3))) - (global $s4 (import "mod" "s4") (mut (ref $s4))) - (global $s5 (import "mod" "s5") (mut (ref $s5))) - (global $s6 (import "mod" "s6") (mut (ref $s6))) - (global $s7 (import "mod" "s7") (mut (ref $s7))) - (global $s8 (import "mod" "s8") (mut (ref $s8))) - (global $a0 (import "mod" "a0") (mut (ref $a0))) - (global $a1 (import "mod" "a1") (mut (ref $a1))) - (global $a2 (import "mod" "a2") (mut (ref $a2))) - (global $a3 (import "mod" "a3") (mut (ref $a3))) - (global $sub0 (import "mod" "sub0") (mut (ref $subvoid))) - (global $sub1 (import "mod" "sub1") (mut (ref $submany))) -) -;; CHECK: (import "mod" "g1" (global $g1 i32)) - -;; CHECK: (import "mod" "g2" (global $g2 (mut i64))) - -;; CHECK: (import "" "g3" (global $gimport$0 (ref $void))) - -;; CHECK: (import "mod" "" (global $gimport$1 (ref null $many))) - -;; CHECK: (import "mod" "s0" (global $s0 (mut (ref $s0)))) - -;; CHECK: (import "mod" "s1" (global $s1 (mut (ref $s1)))) - -;; CHECK: (import "mod" "s2" (global $s2 (mut (ref $s2)))) - -;; CHECK: (import "mod" "s3" (global $s3 (mut (ref $s3)))) + (global i32 i32.const 0) + ;; CHECK: (import "mod" "g1" (global $g1 i32)) -;; CHECK: (import "mod" "s4" (global $s4 (mut (ref $s4)))) + ;; CHECK: (import "mod" "g2" (global $g2 (mut i64))) -;; CHECK: (import "mod" "s5" (global $s5 (mut (ref $s5)))) + ;; CHECK: (import "" "g3" (global $gimport$0 (ref $s0))) -;; CHECK: (import "mod" "s6" (global $s6 (mut (ref $s6)))) + ;; CHECK: (import "mod" "" (global $gimport$1 (ref null $many))) -;; CHECK: (import "mod" "s7" (global $s7 (mut (ref $s7)))) + ;; CHECK: (global $2 i32 (i32.const 0)) -;; CHECK: (import "mod" "s8" (global $s8 (mut (ref $s8)))) - -;; CHECK: (import "mod" "a0" (global $a0 (mut (ref $a0)))) - -;; CHECK: (import "mod" "a1" (global $a1 (mut (ref $a1)))) - -;; CHECK: (import "mod" "a2" (global $a2 (mut (ref $a2)))) - -;; CHECK: (import "mod" "a3" (global $a3 (mut (ref $a3)))) - -;; CHECK: (import "mod" "sub0" (global $sub0 (mut (ref $subvoid)))) - -;; CHECK: (import "mod" "sub1" (global $sub1 (mut (ref $submany)))) + ;; CHECK: (global $i32 i32 (i32.const 42)) + (global $i32 i32 i32.const 42) + ;; uninteresting globals just to use the types + ;; CHECK: (global $s0 (mut (ref null $s0)) (ref.null $s0)) + (global $s0 (mut (ref null $s0)) ref.null $s0) + ;; CHECK: (global $s1 (mut (ref null $s1)) (ref.null $s1)) + (global $s1 (mut (ref null $s1)) ref.null $s1) + ;; CHECK: (global $s2 (mut (ref null $s2)) (ref.null $s2)) + (global $s2 (mut (ref null $s2)) ref.null $s2) + ;; CHECK: (global $s3 (mut (ref null $s3)) (ref.null $s3)) + (global $s3 (mut (ref null $s3)) ref.null $s3) + ;; CHECK: (global $s4 (mut (ref null $s4)) (ref.null $s4)) + (global $s4 (mut (ref null $s4)) ref.null $s4) + ;; CHECK: (global $s5 (mut (ref null $s5)) (ref.null $s5)) + (global $s5 (mut (ref null $s5)) ref.null $s5) + ;; CHECK: (global $s6 (mut (ref null $s6)) (ref.null $s6)) + (global $s6 (mut (ref null $s6)) ref.null $s6) + ;; CHECK: (global $s7 (mut (ref null $s7)) (ref.null $s7)) + (global $s7 (mut (ref null $s7)) ref.null $s7) + ;; CHECK: (global $s8 (mut (ref null $s8)) (ref.null $s8)) + (global $s8 (mut (ref null $s8)) ref.null $s8) + ;; CHECK: (global $a0 (mut (ref null $a0)) (ref.null $a0)) + (global $a0 (mut (ref null $a0)) ref.null $a0) + ;; CHECK: (global $a1 (mut (ref null $a1)) (ref.null $a1)) + (global $a1 (mut (ref null $a1)) ref.null $a1) + ;; CHECK: (global $a2 (mut (ref null $a2)) (ref.null $a2)) + (global $a2 (mut (ref null $a2)) ref.null $a2) + ;; CHECK: (global $a3 (mut (ref null $a3)) (ref.null $a3)) + (global $a3 (mut (ref null $a3)) ref.null $a3) + ;; CHECK: (global $sub0 (mut (ref null $subvoid)) (ref.null $subvoid)) + (global $sub0 (mut (ref null $subvoid)) ref.null $subvoid) + ;; CHECK: (global $sub1 (mut (ref null $submany)) (ref.null $submany)) + (global $sub1 (mut (ref null $submany)) ref.null $submany) +) ;; CHECK: (export "g1" (global $g1)) ;; CHECK: (export "g1.1" (global $g1)) |