diff options
-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)) |