From 1eed7e080e0c25ca7280d124b36f4f767e5f0510 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Tue, 12 Jul 2022 00:43:59 -0700 Subject: [PATCH] Revert "Merge branch '4598' into improve_remove" This reverts commit 79886826265a44b5b4930967c821004c5670f225, reversing changes made to 0da2d8c0f1c1a8f7b84e41623e0f9ea1a39bd4c6. --- CMakeLists.txt | 2 - README.md | 4 - scripts/fuzz_opt.py | 20 +- scripts/gen-s-parser.py | 35 +- scripts/update_lit_checks.py | 2 +- src/gen-s-parser.inc | 5879 +---------------- src/ir/ReFinalize.cpp | 4 - src/ir/bits.h | 10 +- src/ir/boolean.h | 38 - src/ir/cost.h | 13 - src/ir/effects.h | 13 - src/ir/possible-contents.cpp | 16 - src/ir/properties.h | 9 + src/passes/OptimizeInstructions.cpp | 1 - src/passes/Print.cpp | 37 - src/wasm-binary.h | 13 +- src/wasm-builder.h | 30 - src/wasm-delegations-fields.def | 29 - src/wasm-delegations.def | 4 - src/wasm-interpreter.h | 14 +- src/wasm-s-parser.h | 4 - src/wasm.h | 60 - src/wasm/wasm-binary.cpp | 93 +- src/wasm/wasm-s-parser.cpp | 43 - src/wasm/wasm-stack.cpp | 78 +- src/wasm/wasm.cpp | 32 - src/wasm/wat-parser.cpp | 1253 +--- src/wasm2js.h | 16 - test/lit/isorecursive-good.wast | 53 +- test/lit/isorecursive-output-ordering.wast | 77 +- test/lit/isorecursive-singleton-group.wast | 6 +- test/lit/isorecursive-whole-group.wast | 10 +- test/lit/nominal-to-isorecursive.wast | 29 +- test/lit/passes/gufa-refs.wast | 1 + test/lit/passes/gufa.wast | 4 +- test/lit/passes/optimize-instructions-gc.wast | 66 - test/lit/strings.wast | 145 - test/lit/types-function-references.wast | 529 -- test/lit/wat-kitchen-sink.wast | 139 +- test/typed-function-references.wast | 44 + test/typed-function-references.wast.from-wast | 65 + .../typed-function-references.wast.fromBinary | 96 + ...ion-references.wast.fromBinary.noDebugInfo | 96 + 43 files changed, 634 insertions(+), 8478 deletions(-) delete mode 100644 src/ir/boolean.h delete mode 100644 test/lit/types-function-references.wast create mode 100644 test/typed-function-references.wast create mode 100644 test/typed-function-references.wast.from-wast create mode 100644 test/typed-function-references.wast.fromBinary create mode 100644 test/typed-function-references.wast.fromBinary.noDebugInfo diff --git a/CMakeLists.txt b/CMakeLists.txt index 41c7429436a..53c511baf0f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -405,7 +405,6 @@ if(EMSCRIPTEN) target_link_libraries(binaryen_wasm "-s NODERAWFS=0") target_link_libraries(binaryen_wasm "-s EXPORT_NAME=Binaryen") target_link_libraries(binaryen_wasm "-s EXPORT_ES6=1") - target_link_libraries(binaryen_wasm "-sEXPORTED_RUNTIME_METHODS=allocate") target_link_libraries(binaryen_wasm "--post-js ${CMAKE_CURRENT_SOURCE_DIR}/src/js/binaryen.js-post.js") target_link_libraries(binaryen_wasm "--extern-pre-js ${CMAKE_CURRENT_SOURCE_DIR}/src/js/binaryen.js-extern-pre.js") target_link_libraries(binaryen_wasm optimized "--closure 1") @@ -440,7 +439,6 @@ if(EMSCRIPTEN) else() target_link_libraries(binaryen_js "-s EXPORT_ES6=1") endif() - target_link_libraries(binaryen_js "-sEXPORTED_RUNTIME_METHODS=allocate") target_link_libraries(binaryen_js "--post-js ${CMAKE_CURRENT_SOURCE_DIR}/src/js/binaryen.js-post.js") # js_of_ocaml needs a specified variable with special comment to provide the library to consumers if(JS_OF_OCAML) diff --git a/README.md b/README.md index 84dd2748197..574e8d1c4a4 100644 --- a/README.md +++ b/README.md @@ -561,10 +561,6 @@ The `check.py` script supports some options: tool cannot be found, and you'll see a warning. * We have tests from upstream in `tests/spec`, in git submodules. Running `./check.py` should update those. - -Note that we are trying to gradually port the legacy wasm-opt tests to use `lit` and `filecheck` as we modify them. -For `passes` tests that output wast, this can be done automatically with `scripts/port_passes_tests_to_lit.py` and for non-`passes` tests that output wast, see -https://github.com/WebAssembly/binaryen/pull/4779 for an example of how to do a simple manual port. ### Setting up dependencies diff --git a/scripts/fuzz_opt.py b/scripts/fuzz_opt.py index e43d40deceb..04a8fd5c21f 100755 --- a/scripts/fuzz_opt.py +++ b/scripts/fuzz_opt.py @@ -263,18 +263,7 @@ def is_git_repo(): # not all relaxed SIMD instructions are implemented in the interpreter 'relaxed-simd.wast', # TODO fuzzer and interpreter support for strings - 'strings.wast', - # ignore DWARF because it is incompatible with multivalue atm - 'zlib.wasm', - 'cubescript.wasm', - 'class_with_dwarf_noprint.wasm', - 'fib2_dwarf.wasm', - 'fib_nonzero-low-pc_dwarf.wasm', - 'inlined_to_start_dwarf.wasm', - 'fannkuch3_manyopts_dwarf.wasm', - 'fib2_emptylocspan_dwarf.wasm', - 'fannkuch3_dwarf.wasm', - 'multi_unit_abbrev_noprint.wasm', + 'strings.wast' ] @@ -361,6 +350,9 @@ def pick_initial_contents(): # ) # ) '--disable-multivalue', + # DWARF is incompatible with multivalue atm; it's more important to + # fuzz multivalue since we aren't actually fuzzing DWARF here + '--strip-dwarf', ] # the given wasm may not work with the chosen feature opts. for example, if @@ -831,8 +823,8 @@ def handle_pair(self, input, before_wasm, after_wasm, opts): b1 = open('b1.wasm', 'rb').read() b2 = open('b2.wasm', 'rb').read() if (b1 != b2): - run([in_bin('wasm-dis'), 'b1.wasm', '-o', 'b1.wat'] + FEATURE_OPTS) - run([in_bin('wasm-dis'), 'b2.wasm', '-o', 'b2.wat'] + FEATURE_OPTS) + run([in_bin('wasm-dis'), 'b1.wasm', '-o', 'b1.wat', FEATURE_OPTS]) + run([in_bin('wasm-dis'), 'b2.wasm', '-o', 'b2.wat', FEATURE_OPTS]) t1 = open('b1.wat', 'r').read() t2 = open('b2.wat', 'r').read() compare(t1, t2, 'Output must be deterministic.', verbose=False) diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py index eb921a6b92d..1c7936320ac 100755 --- a/scripts/gen-s-parser.py +++ b/scripts/gen-s-parser.py @@ -617,13 +617,6 @@ ("string.new_wtf8", "makeStringNew(s, StringNewWTF8)"), ("string.new_wtf16", "makeStringNew(s, StringNewWTF16)"), ("string.const", "makeStringConst(s)"), - ("string.measure_wtf8", "makeStringMeasure(s, StringMeasureWTF8)"), - ("string.measure_wtf16", "makeStringMeasure(s, StringMeasureWTF16)"), - ("string.is_usv_sequence", "makeStringMeasure(s, StringMeasureIsUSV)"), - ("string.encode_wtf8", "makeStringEncode(s, StringEncodeWTF8)"), - ("string.encode_wtf16", "makeStringEncode(s, StringEncodeWTF16)"), - ("string.concat", "makeStringConcat(s)"), - ("string.eq", "makeStringEq(s)"), ] @@ -693,7 +686,7 @@ def insert(self, inst, expr): self.do_insert(inst, inst, expr) -def instruction_parser(new_parser=False): +def instruction_parser(): """Build a trie out of all the instructions, then emit it as C++ code.""" trie = Node() inst_length = 0 @@ -703,23 +696,12 @@ def instruction_parser(new_parser=False): printer = CodePrinter() - 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)) + 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): - 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("if (strcmp(op, \"{inst}\") == 0) {{ return {expr}; }}" + .format(inst=inst, expr=expr)) printer.print_line("goto parse_error;") def emit(node, idx=0): @@ -748,10 +730,7 @@ def emit(node, idx=0): emit(trie) printer.print_line("parse_error:") with printer.indent(): - if new_parser: - printer.print_line("return in.err(\"unrecognized instruction\");") - else: - printer.print_line("throw ParseException(std::string(op), s.line, s.col);") + printer.print_line("throw ParseException(std::string(op), s.line, s.col);") def print_header(): @@ -777,8 +756,6 @@ 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/scripts/update_lit_checks.py b/scripts/update_lit_checks.py index b7b836e57cc..20a585145da 100755 --- a/scripts/update_lit_checks.py +++ b/scripts/update_lit_checks.py @@ -40,7 +40,7 @@ ALL_ITEMS = '|'.join(['type', 'import', 'global', 'memory', 'data', 'table', 'elem', 'tag', 'export', 'start', 'func']) ITEM_NAME = r'\$?[^\s()]*|"[^\s()]*"' -ITEM_RE = re.compile(r'(?:^\s*\(rec\s*)?(^\s*)\((' + ALL_ITEMS + r')\s+(' + ITEM_NAME + ').*$', +ITEM_RE = re.compile(r'(^\s*)\((' + ALL_ITEMS + r')\s+(' + ITEM_NAME + ').*$', re.MULTILINE) FUZZ_EXEC_FUNC = re.compile(r'^\[fuzz-exec\] calling (?P\S*)$') diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index 809fa783768..84fc66520be 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -3129,50 +3129,9 @@ switch (op[0]) { switch (op[3]) { case 'i': { switch (op[7]) { - case 'c': { - switch (op[10]) { - case 'c': - if (strcmp(op, "string.concat") == 0) { return makeStringConcat(s); } - goto parse_error; - case 's': - if (strcmp(op, "string.const") == 0) { return makeStringConst(s); } - goto parse_error; - default: goto parse_error; - } - } - case 'e': { - switch (op[8]) { - case 'n': { - switch (op[17]) { - case '1': - if (strcmp(op, "string.encode_wtf16") == 0) { return makeStringEncode(s, StringEncodeWTF16); } - goto parse_error; - case '8': - if (strcmp(op, "string.encode_wtf8") == 0) { return makeStringEncode(s, StringEncodeWTF8); } - goto parse_error; - default: goto parse_error; - } - } - case 'q': - if (strcmp(op, "string.eq") == 0) { return makeStringEq(s); } - goto parse_error; - default: goto parse_error; - } - } - case 'i': - if (strcmp(op, "string.is_usv_sequence") == 0) { return makeStringMeasure(s, StringMeasureIsUSV); } + case 'c': + if (strcmp(op, "string.const") == 0) { return makeStringConst(s); } goto parse_error; - case 'm': { - switch (op[18]) { - case '1': - if (strcmp(op, "string.measure_wtf16") == 0) { return makeStringMeasure(s, StringMeasureWTF16); } - goto parse_error; - case '8': - if (strcmp(op, "string.measure_wtf8") == 0) { return makeStringMeasure(s, StringMeasureWTF8); } - goto parse_error; - default: goto parse_error; - } - } case 'n': { switch (op[14]) { case '1': @@ -3478,5838 +3437,4 @@ 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/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp index f509ab2619e..6b3e8863e24 100644 --- a/src/ir/ReFinalize.cpp +++ b/src/ir/ReFinalize.cpp @@ -174,10 +174,6 @@ void ReFinalize::visitArrayCopy(ArrayCopy* curr) { curr->finalize(); } void ReFinalize::visitRefAs(RefAs* curr) { curr->finalize(); } void ReFinalize::visitStringNew(StringNew* curr) { curr->finalize(); } void ReFinalize::visitStringConst(StringConst* curr) { curr->finalize(); } -void ReFinalize::visitStringMeasure(StringMeasure* curr) { curr->finalize(); } -void ReFinalize::visitStringEncode(StringEncode* curr) { curr->finalize(); } -void ReFinalize::visitStringConcat(StringConcat* curr) { curr->finalize(); } -void ReFinalize::visitStringEq(StringEq* curr) { curr->finalize(); } void ReFinalize::visitFunction(Function* curr) { // we may have changed the body from unreachable to none, which might be bad diff --git a/src/ir/bits.h b/src/ir/bits.h index 96b36a846e7..21146b3d1ea 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -17,11 +17,10 @@ #ifndef wasm_ir_bits_h #define wasm_ir_bits_h -#include "ir/boolean.h" #include "ir/literal-utils.h" -#include "ir/load-utils.h" #include "support/bits.h" #include "wasm-builder.h" +#include namespace wasm::Bits { @@ -126,9 +125,6 @@ struct DummyLocalInfoProvider { template Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider = nullptr) { - if (Properties::emitsBoolean(curr)) { - return 1; - } if (auto* c = curr->dynCast()) { switch (curr->type.getBasic()) { case Type::i32: @@ -367,7 +363,7 @@ Index getMaxBits(Expression* curr, case LeFloat64: case GtFloat64: case GeFloat64: - WASM_UNREACHABLE("relationals handled before"); + return 1; default: { } } @@ -383,7 +379,7 @@ Index getMaxBits(Expression* curr, return 7; case EqZInt32: case EqZInt64: - WASM_UNREACHABLE("relationals handled before"); + return 1; case WrapInt64: case ExtendUInt32: return std::min(Index(32), getMaxBits(unary->value, localInfoProvider)); diff --git a/src/ir/boolean.h b/src/ir/boolean.h deleted file mode 100644 index 58601c2ce4a..00000000000 --- a/src/ir/boolean.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2022 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wasm_ir_boolean_h -#define wasm_ir_boolean_h - -#include "wasm.h" - -namespace wasm::Properties { - -inline bool emitsBoolean(Expression* curr) { - if (auto* unary = curr->dynCast()) { - return unary->isRelational(); - } else if (auto* binary = curr->dynCast()) { - return binary->isRelational(); - } else if (curr->is() || curr->is() || curr->is() || - curr->is()) { - return true; - } - return false; -} - -} // namespace wasm::Properties - -#endif // wasm_ir_boolean_h diff --git a/src/ir/cost.h b/src/ir/cost.h index ea07e61097c..2b918bf3855 100644 --- a/src/ir/cost.h +++ b/src/ir/cost.h @@ -675,19 +675,6 @@ struct CostAnalyzer : public OverriddenVisitor { return 4 + visit(curr->ptr) + visit(curr->length); } CostType visitStringConst(StringConst* curr) { return 4; } - CostType visitStringMeasure(StringMeasure* curr) { - return 6 + visit(curr->ref); - } - CostType visitStringEncode(StringEncode* curr) { - return 6 + visit(curr->ref) + visit(curr->ptr); - } - CostType visitStringConcat(StringConcat* curr) { - return 10 + visit(curr->left) + visit(curr->right); - } - CostType visitStringEq(StringEq* curr) { - // "3" is chosen since strings might or might not be interned in the engine. - return 3 + visit(curr->left) + visit(curr->right); - } private: CostType nullCheckCost(Expression* ref) { diff --git a/src/ir/effects.h b/src/ir/effects.h index 0dd0902b104..f023b547ab2 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -734,19 +734,6 @@ class EffectAnalyzer { } void visitStringNew(StringNew* curr) {} void visitStringConst(StringConst* curr) {} - void visitStringMeasure(StringMeasure* curr) { - // traps when ref is null. - parent.implicitTrap = true; - } - void visitStringEncode(StringEncode* curr) { - // traps when ref is null or we write out of bounds. - parent.implicitTrap = true; - } - void visitStringConcat(StringConcat* curr) { - // traps when an input is null. - parent.implicitTrap = true; - } - void visitStringEq(StringEq* curr) {} }; public: diff --git a/src/ir/possible-contents.cpp b/src/ir/possible-contents.cpp index c557ba07b34..f2467158c0d 100644 --- a/src/ir/possible-contents.cpp +++ b/src/ir/possible-contents.cpp @@ -688,22 +688,6 @@ struct InfoCollector void visitStringConst(StringConst* curr) { addRoot(curr, PossibleContents::exactType(curr->type)); } - void visitStringMeasure(StringMeasure* curr) { - // TODO: optimize when possible - addRoot(curr); - } - void visitStringEncode(StringEncode* curr) { - // TODO: optimize when possible - addRoot(curr); - } - void visitStringConcat(StringConcat* curr) { - // TODO: optimize when possible - addRoot(curr); - } - void visitStringEq(StringEq* curr) { - // TODO: optimize when possible - addRoot(curr); - } // TODO: Model which throws can go to which catches. For now, anything thrown // is sent to the location of that tag, and any catch of that tag can diff --git a/src/ir/properties.h b/src/ir/properties.h index 3278d9e4128..4f7fb96ca75 100644 --- a/src/ir/properties.h +++ b/src/ir/properties.h @@ -24,6 +24,15 @@ namespace wasm::Properties { +inline bool emitsBoolean(Expression* curr) { + if (auto* unary = curr->dynCast()) { + return unary->isRelational(); + } else if (auto* binary = curr->dynCast()) { + return binary->isRelational(); + } + return false; +} + inline bool isSymmetric(Binary* binary) { switch (binary->op) { case AddInt32: diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 5f18beb73be..a88e2a87fa8 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include #include diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index ec9926a3028..e766917ecb0 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -2242,43 +2242,6 @@ struct PrintExpressionContents o << curr->string.str; o << '"'; } - void visitStringMeasure(StringMeasure* curr) { - switch (curr->op) { - case StringMeasureUTF8: - printMedium(o, "string.measure_wtf8 utf8"); - break; - case StringMeasureWTF8: - printMedium(o, "string.measure_wtf8 wtf8"); - break; - case StringMeasureWTF16: - printMedium(o, "string.measure_wtf16"); - break; - case StringMeasureIsUSV: - printMedium(o, "string.is_usv_sequence"); - break; - default: - WASM_UNREACHABLE("invalid string.measure*"); - } - } - void visitStringEncode(StringEncode* curr) { - switch (curr->op) { - case StringEncodeUTF8: - printMedium(o, "string.encode_wtf8 utf8"); - break; - case StringEncodeWTF8: - printMedium(o, "string.encode_wtf8 wtf8"); - break; - case StringEncodeWTF16: - printMedium(o, "string.encode_wtf16"); - break; - default: - WASM_UNREACHABLE("invalid string.encode*"); - } - } - void visitStringConcat(StringConcat* curr) { - printMedium(o, "string.concat"); - } - void visitStringEq(StringEq* curr) { printMedium(o, "string.eq"); } }; // Prints an expression in s-expr format, including both the diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 97f6bc24e02..c88aa38954b 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1140,13 +1140,6 @@ enum ASTNodes { StringNewWTF8 = 0x80, StringNewWTF16 = 0x81, StringConst = 0x82, - StringMeasureWTF8 = 0x84, - StringMeasureWTF16 = 0x85, - StringEncodeWTF8 = 0x86, - StringEncodeWTF16 = 0x87, - StringConcat = 0x88, - StringEq = 0x89, - StringIsUSV = 0x8a, }; enum MemoryAccess { @@ -1157,7 +1150,7 @@ enum MemoryAccess { enum MemoryFlags { HasMaximum = 1 << 0, IsShared = 1 << 1, Is64 = 1 << 2 }; -enum StringPolicy { +enum StringNewPolicy { UTF8 = 0x00, WTF8 = 0x01, Replace = 0x02, @@ -1729,10 +1722,6 @@ class WasmBinaryBuilder { bool maybeVisitArrayCopy(Expression*& out, uint32_t code); bool maybeVisitStringNew(Expression*& out, uint32_t code); bool maybeVisitStringConst(Expression*& out, uint32_t code); - bool maybeVisitStringMeasure(Expression*& out, uint32_t code); - bool maybeVisitStringEncode(Expression*& out, uint32_t code); - bool maybeVisitStringConcat(Expression*& out, uint32_t code); - bool maybeVisitStringEq(Expression*& out, uint32_t code); void visitSelect(Select* curr, uint8_t code); void visitReturn(Return* curr); void visitMemorySize(MemorySize* curr); diff --git a/src/wasm-builder.h b/src/wasm-builder.h index 507aa510b78..238f7d738c9 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -1004,36 +1004,6 @@ class Builder { ret->finalize(); return ret; } - StringMeasure* makeStringMeasure(StringMeasureOp op, Expression* ref) { - auto* ret = wasm.allocator.alloc(); - ret->op = op; - ret->ref = ref; - ret->finalize(); - return ret; - } - StringEncode* - makeStringEncode(StringEncodeOp op, Expression* ref, Expression* ptr) { - auto* ret = wasm.allocator.alloc(); - ret->op = op; - ret->ref = ref; - ret->ptr = ptr; - ret->finalize(); - return ret; - } - StringConcat* makeStringConcat(Expression* left, Expression* right) { - auto* ret = wasm.allocator.alloc(); - ret->left = left; - ret->right = right; - ret->finalize(); - return ret; - } - StringEq* makeStringEq(Expression* left, Expression* right) { - auto* ret = wasm.allocator.alloc(); - ret->left = left; - ret->right = right; - ret->finalize(); - return ret; - } // Additional helpers diff --git a/src/wasm-delegations-fields.def b/src/wasm-delegations-fields.def index 0ac154726b1..a7f39c3c7f6 100644 --- a/src/wasm-delegations-fields.def +++ b/src/wasm-delegations-fields.def @@ -727,35 +727,6 @@ switch (DELEGATE_ID) { DELEGATE_END(StringConst); break; } - case Expression::Id::StringMeasureId: { - DELEGATE_START(StringMeasure); - DELEGATE_FIELD_INT(StringMeasure, op); - DELEGATE_FIELD_CHILD(StringMeasure, ref); - DELEGATE_END(StringMeasure); - break; - } - case Expression::Id::StringEncodeId: { - DELEGATE_START(StringEncode); - DELEGATE_FIELD_INT(StringEncode, op); - DELEGATE_FIELD_CHILD(StringEncode, ptr); - DELEGATE_FIELD_CHILD(StringEncode, ref); - DELEGATE_END(StringEncode); - break; - } - case Expression::Id::StringConcatId: { - DELEGATE_START(StringConcat); - DELEGATE_FIELD_CHILD(StringConcat, right); - DELEGATE_FIELD_CHILD(StringConcat, left); - DELEGATE_END(StringConcat); - break; - } - case Expression::Id::StringEqId: { - DELEGATE_START(StringEq); - DELEGATE_FIELD_CHILD(StringEq, right); - DELEGATE_FIELD_CHILD(StringEq, left); - DELEGATE_END(StringEq); - break; - } } #undef DELEGATE_ID diff --git a/src/wasm-delegations.def b/src/wasm-delegations.def index c5cfa693271..ba47d9cf5e4 100644 --- a/src/wasm-delegations.def +++ b/src/wasm-delegations.def @@ -87,9 +87,5 @@ DELEGATE(ArrayCopy); DELEGATE(RefAs); DELEGATE(StringNew); DELEGATE(StringConst); -DELEGATE(StringMeasure); -DELEGATE(StringEncode); -DELEGATE(StringConcat); -DELEGATE(StringEq); #undef DELEGATE diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 02c95957dc3..1cbbd7689a8 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1959,19 +1959,7 @@ class ExpressionRunner : public OverriddenVisitor { WASM_UNREACHABLE("unimplemented string.new"); } Flow visitStringConst(StringConst* curr) { - WASM_UNREACHABLE("unimplemented string.const"); - } - Flow visitStringMeasure(StringMeasure* curr) { - WASM_UNREACHABLE("unimplemented string.measure"); - } - Flow visitStringEncode(StringEncode* curr) { - WASM_UNREACHABLE("unimplemented string.encode"); - } - Flow visitStringConcat(StringConcat* curr) { - WASM_UNREACHABLE("unimplemented string.concat"); - } - Flow visitStringEq(StringEq* curr) { - WASM_UNREACHABLE("unimplemented string.eq"); + WASM_UNREACHABLE("unimplemented string.new"); } virtual void trap(const char* why) { WASM_UNREACHABLE("unimp"); } diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 777d33e308f..0eb4680afd8 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -305,10 +305,6 @@ class SExpressionWasmBuilder { Expression* makeRefAs(Element& s, RefAsOp op); Expression* makeStringNew(Element& s, StringNewOp op); Expression* makeStringConst(Element& s); - Expression* makeStringMeasure(Element& s, StringMeasureOp op); - Expression* makeStringEncode(Element& s, StringEncodeOp op); - Expression* makeStringConcat(Element& s); - Expression* makeStringEq(Element& s); // Helper functions Type parseOptionalResultType(Element& s, Index& i); diff --git a/src/wasm.h b/src/wasm.h index 42de60a9894..3032b4ac185 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -590,19 +590,6 @@ enum StringNewOp { StringNewWTF16 }; -enum StringMeasureOp { - StringMeasureUTF8, - StringMeasureWTF8, - StringMeasureWTF16, - StringMeasureIsUSV, -}; - -enum StringEncodeOp { - StringEncodeUTF8, - StringEncodeWTF8, - StringEncodeWTF16, -}; - // // Expressions // @@ -700,10 +687,6 @@ class Expression { RefAsId, StringNewId, StringConstId, - StringMeasureId, - StringEncodeId, - StringConcatId, - StringEqId, NumExpressionIds }; Id _id; @@ -1694,49 +1677,6 @@ class StringConst : public SpecificExpression { void finalize(); }; -class StringMeasure : public SpecificExpression { -public: - StringMeasure(MixedArena& allocator) {} - - StringMeasureOp op; - - Expression* ref; - - void finalize(); -}; - -class StringEncode : public SpecificExpression { -public: - StringEncode(MixedArena& allocator) {} - - StringEncodeOp op; - - Expression* ref; - Expression* ptr; - - void finalize(); -}; - -class StringConcat : public SpecificExpression { -public: - StringConcat(MixedArena& allocator) {} - - Expression* left; - Expression* right; - - void finalize(); -}; - -class StringEq : public SpecificExpression { -public: - StringEq(MixedArena& allocator) {} - - Expression* left; - Expression* right; - - void finalize(); -}; - // Globals struct Named { diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 0ae17f47cbd..16950f88fcc 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -3924,18 +3924,6 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { if (maybeVisitStringConst(curr, opcode)) { break; } - if (maybeVisitStringMeasure(curr, opcode)) { - break; - } - if (maybeVisitStringEncode(curr, opcode)) { - break; - } - if (maybeVisitStringConcat(curr, opcode)) { - break; - } - if (maybeVisitStringEq(curr, opcode)) { - break; - } if (opcode == BinaryConsts::RefIsFunc || opcode == BinaryConsts::RefIsData || opcode == BinaryConsts::RefIsI31) { @@ -7139,13 +7127,13 @@ bool WasmBinaryBuilder::maybeVisitStringNew(Expression*& out, uint32_t code) { if (code == BinaryConsts::StringNewWTF8) { auto policy = getU32LEB(); switch (policy) { - case BinaryConsts::StringPolicy::UTF8: + case BinaryConsts::StringNewPolicy::UTF8: op = StringNewUTF8; break; - case BinaryConsts::StringPolicy::WTF8: + case BinaryConsts::StringNewPolicy::WTF8: op = StringNewWTF8; break; - case BinaryConsts::StringPolicy::Replace: + case BinaryConsts::StringNewPolicy::Replace: op = StringNewReplace; break; default: @@ -7174,81 +7162,6 @@ bool WasmBinaryBuilder::maybeVisitStringConst(Expression*& out, uint32_t code) { return true; } -bool WasmBinaryBuilder::maybeVisitStringMeasure(Expression*& out, - uint32_t code) { - StringMeasureOp op; - if (code == BinaryConsts::StringMeasureWTF8) { - auto policy = getU32LEB(); - switch (policy) { - case BinaryConsts::StringPolicy::UTF8: - op = StringMeasureUTF8; - break; - case BinaryConsts::StringPolicy::WTF8: - op = StringMeasureWTF8; - break; - default: - throwError("bad policy for string.measure"); - } - } else if (code == BinaryConsts::StringMeasureWTF16) { - op = StringMeasureWTF16; - } else if (code == BinaryConsts::StringIsUSV) { - op = StringMeasureIsUSV; - } else { - return false; - } - auto* ref = popNonVoidExpression(); - out = Builder(wasm).makeStringMeasure(op, ref); - return true; -} - -bool WasmBinaryBuilder::maybeVisitStringEncode(Expression*& out, - uint32_t code) { - StringEncodeOp op; - // TODO: share this code with string.measure? - if (code == BinaryConsts::StringEncodeWTF8) { - auto policy = getU32LEB(); - switch (policy) { - case BinaryConsts::StringPolicy::UTF8: - op = StringEncodeUTF8; - break; - case BinaryConsts::StringPolicy::WTF8: - op = StringEncodeWTF8; - break; - default: - throwError("bad policy for string.encode"); - } - } else if (code == BinaryConsts::StringEncodeWTF16) { - op = StringEncodeWTF16; - } else { - return false; - } - auto* ptr = popNonVoidExpression(); - auto* ref = popNonVoidExpression(); - out = Builder(wasm).makeStringEncode(op, ref, ptr); - return true; -} - -bool WasmBinaryBuilder::maybeVisitStringConcat(Expression*& out, - uint32_t code) { - if (code != BinaryConsts::StringConcat) { - return false; - } - auto* right = popNonVoidExpression(); - auto* left = popNonVoidExpression(); - out = Builder(wasm).makeStringConcat(left, right); - return true; -} - -bool WasmBinaryBuilder::maybeVisitStringEq(Expression*& out, uint32_t code) { - if (code != BinaryConsts::StringEq) { - return false; - } - auto* right = popNonVoidExpression(); - auto* left = popNonVoidExpression(); - out = Builder(wasm).makeStringEq(left, right); - return true; -} - void WasmBinaryBuilder::visitRefAs(RefAs* curr, uint8_t code) { BYN_TRACE("zz node: RefAs\n"); switch (code) { diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index ecb8c243209..cd6c167c031 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -2957,49 +2957,6 @@ Expression* SExpressionWasmBuilder::makeStringConst(Element& s) { return Builder(wasm).makeStringConst(s[1]->str()); } -Expression* SExpressionWasmBuilder::makeStringMeasure(Element& s, - StringMeasureOp op) { - size_t i = 1; - if (op == StringMeasureWTF8) { - const char* str = s[i++]->c_str(); - if (strncmp(str, "utf8", 4) == 0) { - op = StringMeasureUTF8; - } else if (strncmp(str, "wtf8", 4) == 0) { - op = StringMeasureWTF8; - } else { - throw ParseException("bad string.new op", s.line, s.col); - } - } - return Builder(wasm).makeStringMeasure(op, parseExpression(s[i])); -} - -Expression* SExpressionWasmBuilder::makeStringEncode(Element& s, - StringEncodeOp op) { - size_t i = 1; - if (op == StringEncodeWTF8) { - const char* str = s[i++]->c_str(); - if (strncmp(str, "utf8", 4) == 0) { - op = StringEncodeUTF8; - } else if (strncmp(str, "wtf8", 4) == 0) { - op = StringEncodeWTF8; - } else { - throw ParseException("bad string.new op", s.line, s.col); - } - } - return Builder(wasm).makeStringEncode( - op, parseExpression(s[i]), parseExpression(s[i + 1])); -} - -Expression* SExpressionWasmBuilder::makeStringConcat(Element& s) { - return Builder(wasm).makeStringConcat(parseExpression(s[1]), - parseExpression(s[2])); -} - -Expression* SExpressionWasmBuilder::makeStringEq(Element& s) { - return Builder(wasm).makeStringEq(parseExpression(s[1]), - parseExpression(s[2])); -} - // converts an s-expression string representing binary data into an output // sequence of raw bytes this appends to data, which may already contain // content. diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index e1b093b26aa..e131ab207a8 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2239,15 +2239,15 @@ void BinaryInstWriter::visitStringNew(StringNew* curr) { switch (curr->op) { case StringNewUTF8: o << U32LEB(BinaryConsts::StringNewWTF8) - << U32LEB(BinaryConsts::StringPolicy::UTF8); + << U32LEB(BinaryConsts::StringNewPolicy::UTF8); break; case StringNewWTF8: o << U32LEB(BinaryConsts::StringNewWTF8) - << U32LEB(BinaryConsts::StringPolicy::WTF8); + << U32LEB(BinaryConsts::StringNewPolicy::WTF8); break; case StringNewReplace: o << U32LEB(BinaryConsts::StringNewWTF8) - << U32LEB(BinaryConsts::StringPolicy::Replace); + << U32LEB(BinaryConsts::StringNewPolicy::Replace); break; case StringNewWTF16: o << U32LEB(BinaryConsts::StringNewWTF16); @@ -2262,55 +2262,6 @@ void BinaryInstWriter::visitStringConst(StringConst* curr) { << U32LEB(parent.getStringIndex(curr->string)); } -void BinaryInstWriter::visitStringMeasure(StringMeasure* curr) { - o << int8_t(BinaryConsts::GCPrefix); - switch (curr->op) { - case StringMeasureUTF8: - o << U32LEB(BinaryConsts::StringMeasureWTF8) - << U32LEB(BinaryConsts::StringPolicy::UTF8); - break; - case StringMeasureWTF8: - o << U32LEB(BinaryConsts::StringMeasureWTF8) - << U32LEB(BinaryConsts::StringPolicy::WTF8); - break; - case StringMeasureWTF16: - o << U32LEB(BinaryConsts::StringMeasureWTF16); - break; - case StringMeasureIsUSV: - o << U32LEB(BinaryConsts::StringIsUSV); - break; - default: - WASM_UNREACHABLE("invalid string.new*"); - } -} - -void BinaryInstWriter::visitStringEncode(StringEncode* curr) { - o << int8_t(BinaryConsts::GCPrefix); - switch (curr->op) { - case StringEncodeUTF8: - o << U32LEB(BinaryConsts::StringEncodeWTF8) - << U32LEB(BinaryConsts::StringPolicy::UTF8); - break; - case StringEncodeWTF8: - o << U32LEB(BinaryConsts::StringEncodeWTF8) - << U32LEB(BinaryConsts::StringPolicy::WTF8); - break; - case StringEncodeWTF16: - o << U32LEB(BinaryConsts::StringEncodeWTF16); - break; - default: - WASM_UNREACHABLE("invalid string.new*"); - } -} - -void BinaryInstWriter::visitStringConcat(StringConcat* curr) { - o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::StringConcat); -} - -void BinaryInstWriter::visitStringEq(StringEq* curr) { - o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::StringEq); -} - void BinaryInstWriter::emitScopeEnd(Expression* curr) { assert(!breakStack.empty()); breakStack.pop_back(); @@ -2357,29 +2308,6 @@ void BinaryInstWriter::mapLocalsAndEmitHeader() { } } countScratchLocals(); - - if (parent.getModule()->features.hasReferenceTypes()) { - // Sort local types in a way that keeps all MVP types together and all - // reference types together. E.g. it is helpful to avoid a block of i32s in - // between blocks of different reference types, since clearing out reference - // types may require different work. - // - // See https://github.com/WebAssembly/binaryen/issues/4773 - // - // In order to decide whether to put MVP types or reference types first, - // look at the type of the first local. In an optimized binary we will have - // sorted the locals by frequency of uses, so this way we'll keep the most - // commonly-used local at the top, which should work well in many cases. - bool refsFirst = !localTypes.empty() && localTypes[0].isRef(); - std::stable_sort(localTypes.begin(), localTypes.end(), [&](Type a, Type b) { - if (refsFirst) { - return a.isRef() && !b.isRef(); - } else { - return !a.isRef() && b.isRef(); - } - }); - } - std::unordered_map currLocalsByType; for (Index i = func->getVarIndexBase(); i < func->getNumLocals(); i++) { Index j = 0; diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index 5e316d4f4f5..86eed184f25 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -1184,38 +1184,6 @@ void StringNew::finalize() { void StringConst::finalize() { type = Type(HeapType::string, NonNullable); } -void StringMeasure::finalize() { - if (ref->type == Type::unreachable) { - type = Type::unreachable; - } else { - type = Type::i32; - } -} - -void StringEncode::finalize() { - if (ref->type == Type::unreachable || ptr->type == Type::unreachable) { - type = Type::unreachable; - } else { - type = Type::i32; - } -} - -void StringConcat::finalize() { - if (left->type == Type::unreachable || right->type == Type::unreachable) { - type = Type::unreachable; - } else { - type = Type(HeapType::string, NonNullable); - } -} - -void StringEq::finalize() { - if (left->type == Type::unreachable || right->type == Type::unreachable) { - type = Type::unreachable; - } else { - type = Type::i32; - } -} - size_t Function::getNumParams() { return getParams().size(); } size_t Function::getNumVars() { return vars.size(); } diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp index aa059b1db7e..54aa1dc7d46 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. // -// The fifth and final phase parses the remaining contents of all module -// elements, including instructions. +// In the fifth and final phase, not yet implemented, 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,16 +127,6 @@ struct ParseInput { return {}; } - std::optional takeKeyword() { - if (auto t = peek()) { - if (auto keyword = t->getKeyword()) { - ++lexer; - return *keyword; - } - } - return {}; - } - bool takeKeyword(std::string_view expected) { if (auto t = peek()) { if (auto keyword = t->getKeyword()) { @@ -306,7 +296,6 @@ struct ParseDeclsCtx { // At this stage we only look at types to find implicit type definitions, // which are inserted directly in to the context. We cannot materialize or // validate any types because we don't know what types exist yet. - using IndexT = Ok; using HeapTypeT = Ok; using TypeT = Ok; using ParamsT = Ok; @@ -318,17 +307,12 @@ 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; // The module element definitions we are parsing in this phase. std::vector typeDefs; - std::vector subtypeDefs; std::vector globalDefs; // Counters used for generating names for module elements. @@ -345,7 +329,6 @@ inline constexpr bool parsingDecls = std::is_same_v; // Phase 2: Parse type definitions into a TypeBuilder. struct ParseTypeDefsCtx { - using IndexT = Index; using HeapTypeT = HeapType; using TypeT = Type; using ParamsT = std::vector; @@ -356,10 +339,6 @@ struct ParseTypeDefsCtx { using StructT = std::pair, Struct>; using ArrayT = Array; - using InstrT = Ok; - using InstrsT = Ok; - using ExprT = Ok; - // We update slots in this builder as we parse type definitions. TypeBuilder& builder; @@ -369,7 +348,7 @@ struct ParseTypeDefsCtx { // Parse the names of types and fields as we go. std::vector names; - // The index of the subtype definition we are parsing. + // The index of the type definition we are parsing. Index index = 0; ParseTypeDefsCtx(TypeBuilder& builder, const IndexMap& typeIndices) @@ -385,17 +364,12 @@ inline constexpr bool parsingTypeDefs = std::is_same_v; struct ParseModuleTypesCtx { // In this phase we have constructed all the types, so we can materialize and // validate them when they are used. - using IndexT = Index; using HeapTypeT = HeapType; using TypeT = Type; using ParamsT = std::vector; using ResultsT = std::vector; using GlobalTypeT = GlobalType; - using InstrT = Ok; - using InstrsT = Ok; - using ExprT = Ok; - Module& wasm; const std::vector& types; @@ -416,38 +390,7 @@ template inline constexpr bool parsingModuleTypes = std::is_same_v; -// Phase 5: Parse module element definitions, including instructions. -struct ParseDefsCtx { - using IndexT = Index; - using TypeT = Type; - using HeapTypeT = HeapType; - // TODO: This could be Ok, but then we wouldn't be able to use RETURN_OR_OK. - using GlobalTypeT = GlobalType; - - using InstrT = Expression*; - using InstrsT = std::vector; - using ExprT = Expression*; - - Module& wasm; - - Builder builder; - - const std::vector& types; - - // Map heap type names to their indices. - const IndexMap& typeIndices; - - // The index of the current module element. - Index index = 0; - - ParseDefsCtx(Module& wasm, - const std::vector& types, - const IndexMap& typeIndices) - : wasm(wasm), builder(wasm), types(types), typeIndices(typeIndices) {} -}; - -template -inline constexpr bool parsingDefs = std::is_same_v; +// TODO: Phase 5: ParseDefsCtx // ================ // Parser Functions @@ -474,217 +417,13 @@ template MaybeResult structtype(Ctx&, ParseInput&); template MaybeResult arraytype(Ctx&, ParseInput&); -template -Result globaltype(Ctx&, ParseInput&); - -// Instructions -template -MaybeResult instr(Ctx&, ParseInput&); -template Result instrs(Ctx&, ParseInput&); -template Result expr(Ctx&, ParseInput&); -template Result makeUnreachable(Ctx&); -template Result makeNop(Ctx&); -template -Result makeBinary(Ctx&, ParseInput&, BinaryOp op); -template -Result makeUnary(Ctx&, ParseInput&, UnaryOp op); -template -Result makeSelect(Ctx&, ParseInput&); -template Result makeDrop(Ctx&, ParseInput&); -template -Result makeMemorySize(Ctx&, ParseInput&); -template -Result makeMemoryGrow(Ctx&, ParseInput&); -template -Result makeLocalGet(Ctx&, ParseInput&); -template -Result makeLocalTee(Ctx&, ParseInput&); -template -Result makeLocalSet(Ctx&, ParseInput&); -template -Result makeGlobalGet(Ctx&, ParseInput&); -template -Result makeGlobalSet(Ctx&, ParseInput&); -template -Result makeBlock(Ctx&, ParseInput&); -template -Result makeThenOrElse(Ctx&, ParseInput&); -template -Result makeConst(Ctx&, ParseInput&, Type type); -template -Result -makeLoad(Ctx&, ParseInput&, Type type, bool isAtomic); -template -Result -makeStore(Ctx&, ParseInput&, Type type, bool isAtomic); -template -Result -makeAtomicRMWOrCmpxchg(Ctx&, ParseInput&, Type type); -template -Result -makeAtomicRMW(Ctx&, ParseInput&, Type type, uint8_t bytes, const char* extra); -template -Result makeAtomicCmpxchg( - Ctx&, ParseInput&, Type type, uint8_t bytes, const char* extra); -template -Result makeAtomicWait(Ctx&, ParseInput&, Type type); -template -Result makeAtomicNotify(Ctx&, ParseInput&); -template -Result makeAtomicFence(Ctx&, ParseInput&); -template -Result -makeSIMDExtract(Ctx&, ParseInput&, SIMDExtractOp op, size_t lanes); -template -Result -makeSIMDReplace(Ctx&, ParseInput&, SIMDReplaceOp op, size_t lanes); -template -Result makeSIMDShuffle(Ctx&, ParseInput&); -template -Result -makeSIMDTernary(Ctx&, ParseInput&, SIMDTernaryOp op); -template -Result makeSIMDShift(Ctx&, ParseInput&, SIMDShiftOp op); -template -Result makeSIMDLoad(Ctx&, ParseInput&, SIMDLoadOp op); -template -Result -makeSIMDLoadStoreLane(Ctx&, ParseInput&, SIMDLoadStoreLaneOp op); -template -Result makeMemoryInit(Ctx&, ParseInput&); -template -Result makeDataDrop(Ctx&, ParseInput&); -template -Result makeMemoryCopy(Ctx&, ParseInput&); -template -Result makeMemoryFill(Ctx&, ParseInput&); -template Result makePush(Ctx&, ParseInput&); -template Result makePop(Ctx&, ParseInput&); -template Result makeIf(Ctx&, ParseInput&); -template -Result -makeMaybeBlock(Ctx&, ParseInput&, size_t i, Type type); -template Result makeLoop(Ctx&, ParseInput&); -template -Result makeCall(Ctx&, ParseInput&, bool isReturn); -template -Result makeCallIndirect(Ctx&, ParseInput&, bool isReturn); -template -Result makeBreak(Ctx&, ParseInput&); -template -Result makeBreakTable(Ctx&, ParseInput&); -template -Result makeReturn(Ctx&, ParseInput&); -template -Result makeRefNull(Ctx&, ParseInput&); -template -Result makeRefIs(Ctx&, ParseInput&, RefIsOp op); -template -Result makeRefFunc(Ctx&, ParseInput&); -template -Result makeRefEq(Ctx&, ParseInput&); -template -Result makeTableGet(Ctx&, ParseInput&); -template -Result makeTableSet(Ctx&, ParseInput&); -template -Result makeTableSize(Ctx&, ParseInput&); -template -Result makeTableGrow(Ctx&, ParseInput&); -template Result makeTry(Ctx&, ParseInput&); -template -Result -makeTryOrCatchBody(Ctx&, ParseInput&, Type type, bool isTry); -template -Result makeThrow(Ctx&, ParseInput&); -template -Result makeRethrow(Ctx&, ParseInput&); -template -Result makeTupleMake(Ctx&, ParseInput&); -template -Result makeTupleExtract(Ctx&, ParseInput&); -template -Result makeCallRef(Ctx&, ParseInput&, bool isReturn); -template -Result makeI31New(Ctx&, ParseInput&); -template -Result makeI31Get(Ctx&, ParseInput&, bool signed_); -template -Result makeRefTest(Ctx&, ParseInput&); -template -Result makeRefTestStatic(Ctx&, ParseInput&); -template -Result makeRefCast(Ctx&, ParseInput&); -template -Result makeRefCastStatic(Ctx&, ParseInput&); -template -Result makeRefCastNopStatic(Ctx&, ParseInput&); -template -Result makeBrOn(Ctx&, ParseInput&, BrOnOp op); -template -Result makeBrOnStatic(Ctx&, ParseInput&, BrOnOp op); -template -Result makeRttCanon(Ctx&, ParseInput&); -template -Result makeRttSub(Ctx&, ParseInput&); -template -Result makeRttFreshSub(Ctx&, ParseInput&); -template -Result makeStructNew(Ctx&, ParseInput&, bool default_); -template -Result -makeStructNewStatic(Ctx&, ParseInput&, bool default_); -template -Result -makeStructGet(Ctx&, ParseInput&, bool signed_ = false); -template -Result makeStructSet(Ctx&, ParseInput&); -template -Result makeArrayNew(Ctx&, ParseInput&, bool default_); -template -Result -makeArrayNewStatic(Ctx&, ParseInput&, bool default_); -template -Result makeArrayInit(Ctx&, ParseInput&); -template -Result makeArrayInitStatic(Ctx&, ParseInput&); -template -Result -makeArrayGet(Ctx&, ParseInput&, bool signed_ = false); -template -Result makeArraySet(Ctx&, ParseInput&); -template -Result makeArrayLen(Ctx&, ParseInput&); -template -Result makeArrayCopy(Ctx&, ParseInput&); -template -Result makeRefAs(Ctx&, ParseInput&, RefAsOp op); -template -Result makeStringNew(Ctx&, ParseInput&, StringNewOp op); -template -Result makeStringConst(Ctx&, ParseInput&); -template -Result -makeStringMeasure(Ctx&, ParseInput&, StringMeasureOp op); -template -Result -makeStringEncode(Ctx&, ParseInput&, StringEncodeOp op); -template -Result makeStringConcat(Ctx&, ParseInput&); -template -Result makeStringEq(Ctx&, ParseInput&); // Modules template -MaybeResult maybeTypeidx(Ctx& ctx, ParseInput& in); -template Result typeidx(Ctx&, ParseInput&); MaybeResult inlineImport(ParseInput&); Result> inlineExports(ParseInput&); -template Result<> strtype(Ctx&, ParseInput&); -template -MaybeResult subtype(Ctx&, ParseInput&); -template MaybeResult<> deftype(Ctx&, ParseInput&); +template MaybeResult<> strtype(Ctx&, ParseInput&); template MaybeResult<> global(Ctx&, ParseInput&); MaybeResult<> modulefield(ParseDeclsCtx&, ParseInput&); Result<> module(ParseDeclsCtx&, ParseInput&); @@ -1065,855 +804,184 @@ Result globaltype(Ctx& ctx, ParseInput& in) { RETURN_OR_OK((GlobalType{Immutable, *type})); } -// ============ -// Instructions -// ============ - -template -MaybeResult instr(Ctx& ctx, ParseInput& in) { - auto keyword = in.takeKeyword(); - if (!keyword) { - return {}; - } - - auto op = *keyword; - -#define NEW_INSTRUCTION_PARSER -#define NEW_WAT_PARSER -#include -} +// ======= +// Modules +// ======= +// typeidx ::= x:u32 => x +// | v:id => x (if types[x] = v) template -Result instrs(Ctx& ctx, ParseInput& in) { - // TODO: Folded instructions. - std::vector insts; - while (auto inst = instr(ctx, in)) { - CHECK_ERR(inst); - if constexpr (parsingDefs) { - insts.push_back(*inst); +Result typeidx(Ctx& ctx, ParseInput& in) { + [[maybe_unused]] Index index; + if (auto x = in.takeU32()) { + index = *x; + } else if (auto id = in.takeID()) { + if constexpr (!parsingDecls) { + auto it = ctx.typeIndices.find(*id); + if (it == ctx.typeIndices.end()) { + return in.err("unknown type identifier"); + } + index = it->second; } - } - if constexpr (parsingDefs) { - return insts; } else { - return Ok{}; + return in.err("expected type index or identifier"); } -} -template -Result expr(Ctx& ctx, ParseInput& in) { - auto insts = instrs(ctx, in); - CHECK_ERR(insts); - if constexpr (parsingDefs) { - switch (insts->size()) { - case 0: - return ctx.builder.makeNop(); - case 1: - return insts->front(); - default: - return ctx.builder.makeBlock(*insts); + if constexpr (parsingDecls) { + return Ok{}; + } else if constexpr (parsingTypeDefs) { + if (index >= ctx.builder.size()) { + return in.err("type index out of bounds"); } + return ctx.builder[index]; } else { - return Ok{}; + if (index >= ctx.types.size()) { + return in.err("type index out of bounds"); + } + return ctx.types[index]; } } -template Result makeUnreachable(Ctx& ctx) { - if constexpr (parsingDefs) { - return ctx.builder.makeUnreachable(); - } else { - return Ok{}; +// ('(' 'import' mod:name nm:name ')')? +MaybeResult inlineImport(ParseInput& in) { + if (!in.takeSExprStart("import"sv)) { + return {}; + } + auto mod = in.takeName(); + if (!mod) { + return in.err("expected import module"); + } + auto nm = in.takeName(); + if (!nm) { + return in.err("expected import name"); } + if (!in.takeRParen()) { + return in.err("expected end of import"); + } + return {{*mod, *nm}}; } -template Result makeNop(Ctx& ctx) { - if constexpr (parsingDefs) { - return ctx.builder.makeNop(); - } else { - return Ok{}; +// ('(' 'export' name ')')* +Result> inlineExports(ParseInput& in) { + std::vector exports; + while (in.takeSExprStart("export"sv)) { + auto name = in.takeName(); + if (!name) { + return in.err("expected export name"); + } + if (!in.takeRParen()) { + return in.err("expected end of import"); + } + exports.push_back(*name); } + return exports; } -template -Result makeBinary(Ctx& ctx, ParseInput& in, BinaryOp op) { - return in.err("unimplemented instruction"); -} +// strtype ::= '(' 'type' id? ft:functype ')' => ft +// | '(' 'type' id? st:structtype ')' => st +// | '(' 'type' id? at:arraytype ')' => at +template MaybeResult<> strtype(Ctx& ctx, ParseInput& in) { + [[maybe_unused]] auto start = in.getPos(); -template -Result makeUnary(Ctx& ctx, ParseInput& in, UnaryOp op) { - return in.err("unimplemented instruction"); -} + if (!in.takeSExprStart("type"sv)) { + return {}; + } -template -Result makeSelect(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} + Name name; + if (auto id = in.takeID()) { + name = *id; + if constexpr (parsingTypeDefs) { + ctx.names[ctx.index].name = name; + } + } -template -Result makeDrop(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} + if (auto type = functype(ctx, in)) { + CHECK_ERR(type); + if constexpr (parsingTypeDefs) { + ctx.builder[ctx.index] = *type; + } + } else if (auto type = structtype(ctx, in)) { + CHECK_ERR(type); + if constexpr (parsingTypeDefs) { + auto& [fieldNames, str] = *type; + ctx.builder[ctx.index] = str; + for (Index i = 0; i < fieldNames.size(); ++i) { + if (auto name = fieldNames[i]; name.is()) { + ctx.names[ctx.index].fieldNames[i] = name; + } + } + } + } else if (auto type = arraytype(ctx, in)) { + CHECK_ERR(type); + if constexpr (parsingTypeDefs) { + ctx.builder[ctx.index] = *type; + } + } else { + return in.err("expected type description"); + } -template -Result makeMemorySize(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} + if (!in.takeRParen()) { + return in.err("expected end of type definition"); + } -template -Result makeMemoryGrow(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); + if constexpr (parsingDecls) { + ctx.typeDefs.push_back({name, start}); + } + return Ok{}; } -template -Result makeLocalGet(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} +// subtype ::= '(' 'sub' typeidx? strtype ')' +// | strtype +// TODO -template -Result makeLocalTee(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} +// deftype ::= '(' 'rec' subtype* ')' +// | subtype +// TODO: -template -Result makeLocalSet(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} +// global ::= '(' 'global' id? ('(' 'export' name ')')* gt:globaltype e:expr ')' +// | '(' 'global' id? '(' 'import' mod:name nm:name ')' +// gt:globaltype ')' +template MaybeResult<> global(Ctx& ctx, ParseInput& in) { + [[maybe_unused]] auto pos = in.getPos(); + if (!in.takeSExprStart("global"sv)) { + return {}; + } + Name name; + if (auto id = in.takeID()) { + name = *id; + } -template -Result makeGlobalGet(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} + auto exports = inlineExports(in); + CHECK_ERR(exports); -template -Result makeGlobalSet(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} + auto import = inlineImport(in); + CHECK_ERR(import); -template -Result makeBlock(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeThenOrElse(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeConst(Ctx& ctx, ParseInput& in, Type type) { - assert(type.isBasic()); - switch (type.getBasic()) { - case Type::i32: - if (auto c = in.takeI32()) { - if constexpr (parsingDefs) { - return ctx.builder.makeConst(Literal(*c)); - } else { - return Ok{}; - } - } - return in.err("expected i32"); - case Type::i64: - if (auto c = in.takeI64()) { - if constexpr (parsingDefs) { - return ctx.builder.makeConst(Literal(*c)); - } else { - return Ok{}; - } - } - return in.err("expected i64"); - case Type::f32: - if (auto f = in.takeF32()) { - if constexpr (parsingDefs) { - return ctx.builder.makeConst(Literal(*f)); - } else { - return Ok{}; - } - } - return in.err("expected f32"); - case Type::f64: - if (auto f = in.takeF64()) { - if constexpr (parsingDefs) { - return ctx.builder.makeConst(Literal(*f)); - } else { - return Ok{}; - } - } - return in.err("expected f64"); - case Type::v128: - return in.err("unimplemented instruction"); - case Type::none: - case Type::unreachable: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: - break; - } - WASM_UNREACHABLE("unexpected type"); -} - -template -Result -makeLoad(Ctx& ctx, ParseInput& in, Type type, bool isAtomic) { - return in.err("unimplemented instruction"); -} - -template -Result -makeStore(Ctx& ctx, ParseInput& in, Type type, bool isAtomic) { - return in.err("unimplemented instruction"); -} - -template -Result -makeAtomicRMWOrCmpxchg(Ctx& ctx, ParseInput& in, Type type) { - return in.err("unimplemented instruction"); -} - -template -Result makeAtomicRMW( - Ctx& ctx, ParseInput& in, Type type, uint8_t bytes, const char* extra) { - return in.err("unimplemented instruction"); -} - -template -Result makeAtomicCmpxchg( - Ctx& ctx, ParseInput& in, Type type, uint8_t bytes, const char* extra) { - return in.err("unimplemented instruction"); -} - -template -Result -makeAtomicWait(Ctx& ctx, ParseInput& in, Type type) { - return in.err("unimplemented instruction"); -} - -template -Result makeAtomicNotify(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeAtomicFence(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result -makeSIMDExtract(Ctx& ctx, ParseInput& in, SIMDExtractOp op, size_t lanes) { - return in.err("unimplemented instruction"); -} - -template -Result -makeSIMDReplace(Ctx& ctx, ParseInput& in, SIMDReplaceOp op, size_t lanes) { - return in.err("unimplemented instruction"); -} - -template -Result makeSIMDShuffle(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result -makeSIMDTernary(Ctx& ctx, ParseInput& in, SIMDTernaryOp op) { - return in.err("unimplemented instruction"); -} - -template -Result -makeSIMDShift(Ctx& ctx, ParseInput& in, SIMDShiftOp op) { - return in.err("unimplemented instruction"); -} - -template -Result -makeSIMDLoad(Ctx& ctx, ParseInput& in, SIMDLoadOp op) { - return in.err("unimplemented instruction"); -} - -template -Result -makeSIMDLoadStoreLane(Ctx& ctx, ParseInput& in, SIMDLoadStoreLaneOp op) { - return in.err("unimplemented instruction"); -} - -template -Result makeMemoryInit(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeDataDrop(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeMemoryCopy(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeMemoryFill(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makePush(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makePop(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeIf(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result -makeMaybeBlock(Ctx& ctx, ParseInput& in, size_t i, Type type) { - return in.err("unimplemented instruction"); -} - -template -Result makeLoop(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeCall(Ctx& ctx, ParseInput& in, bool isReturn) { - return in.err("unimplemented instruction"); -} - -template -Result -makeCallIndirect(Ctx& ctx, ParseInput& in, bool isReturn) { - return in.err("unimplemented instruction"); -} - -template -Result makeBreak(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeBreakTable(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeReturn(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeRefNull(Ctx& ctx, ParseInput& in) { - auto t = heaptype(ctx, in); - CHECK_ERR(t); - if constexpr (parsingDefs) { - return ctx.builder.makeRefNull(*t); - } else { - return Ok{}; - } -} - -template -Result makeRefIs(Ctx& ctx, ParseInput& in, RefIsOp op) { - return in.err("unimplemented instruction"); -} - -template -Result makeRefFunc(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeRefEq(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeTableGet(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeTableSet(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeTableSize(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeTableGrow(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeTry(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result -makeTryOrCatchBody(Ctx& ctx, ParseInput& in, Type type, bool isTry) { - return in.err("unimplemented instruction"); -} - -template -Result makeThrow(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeRethrow(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeTupleMake(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeTupleExtract(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result -makeCallRef(Ctx& ctx, ParseInput& in, bool isReturn) { - return in.err("unimplemented instruction"); -} - -template -Result makeI31New(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result -makeI31Get(Ctx& ctx, ParseInput& in, bool signed_) { - return in.err("unimplemented instruction"); -} - -template -Result makeRefTest(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeRefTestStatic(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeRefCast(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeRefCastStatic(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeRefCastNopStatic(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeBrOn(Ctx& ctx, ParseInput& in, BrOnOp op) { - return in.err("unimplemented instruction"); -} - -template -Result -makeBrOnStatic(Ctx& ctx, ParseInput& in, BrOnOp op) { - return in.err("unimplemented instruction"); -} - -template -Result makeRttCanon(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeRttSub(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeRttFreshSub(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result -makeStructNew(Ctx& ctx, ParseInput& in, bool default_) { - return in.err("unimplemented instruction"); -} - -template -Result -makeStructNewStatic(Ctx& ctx, ParseInput& in, bool default_) { - return in.err("unimplemented instruction"); -} - -template -Result -makeStructGet(Ctx& ctx, ParseInput& in, bool signed_) { - return in.err("unimplemented instruction"); -} - -template -Result makeStructSet(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result -makeArrayNew(Ctx& ctx, ParseInput& in, bool default_) { - return in.err("unimplemented instruction"); -} - -template -Result -makeArrayNewStatic(Ctx& ctx, ParseInput& in, bool default_) { - return in.err("unimplemented instruction"); -} - -template -Result makeArrayInit(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeArrayInitStatic(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result -makeArrayGet(Ctx& ctx, ParseInput& in, bool signed_) { - return in.err("unimplemented instruction"); -} - -template -Result makeArraySet(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeArrayLen(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeArrayCopy(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeRefAs(Ctx& ctx, ParseInput& in, RefAsOp op) { - return in.err("unimplemented instruction"); -} - -template -Result -makeStringNew(Ctx& ctx, ParseInput& in, StringNewOp op) { - return in.err("unimplemented instruction"); -} - -template -Result makeStringConst(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result -makeStringMeasure(Ctx& ctx, ParseInput& in, StringMeasureOp op) { - return in.err("unimplemented instruction"); -} - -template -Result -makeStringEncode(Ctx& ctx, ParseInput& in, StringEncodeOp op) { - return in.err("unimplemented instruction"); -} - -template -Result makeStringConcat(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template -Result makeStringEq(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -// ======= -// Modules -// ======= - -// typeidx ::= x:u32 => x -// | v:id => x (if types[x] = v) -template -MaybeResult maybeTypeidx(Ctx& ctx, ParseInput& in) { - if (auto x = in.takeU32()) { - RETURN_OR_OK(*x); - } - if (auto id = in.takeID()) { - if constexpr (parsingDecls) { - return Ok{}; - } else { - auto it = ctx.typeIndices.find(*id); - if (it == ctx.typeIndices.end()) { - return in.err("unknown type identifier"); - } - return it->second; - } - } - return {}; -} - -template -Result typeidx(Ctx& ctx, ParseInput& in) { - if (auto index = maybeTypeidx(ctx, in)) { - CHECK_ERR(index); - if constexpr (parsingDecls) { - return Ok{}; - } else if constexpr (parsingTypeDefs) { - if (*index >= ctx.builder.size()) { - return in.err("type index out of bounds"); - } - return ctx.builder[*index]; - } else { - if (*index >= ctx.types.size()) { - return in.err("type index out of bounds"); - } - return ctx.types[*index]; - } - } - return in.err("expected type index or identifier"); -} - -// ('(' 'import' mod:name nm:name ')')? -MaybeResult inlineImport(ParseInput& in) { - if (!in.takeSExprStart("import"sv)) { - return {}; - } - auto mod = in.takeName(); - if (!mod) { - return in.err("expected import module"); - } - auto nm = in.takeName(); - if (!nm) { - return in.err("expected import name"); - } - if (!in.takeRParen()) { - return in.err("expected end of import"); - } - return {{*mod, *nm}}; -} + auto type = globaltype(ctx, in); + CHECK_ERR(type); -// ('(' 'export' name ')')* -Result> inlineExports(ParseInput& in) { - std::vector exports; - while (in.takeSExprStart("export"sv)) { - auto name = in.takeName(); - if (!name) { - return in.err("expected export name"); - } + if (import) { if (!in.takeRParen()) { - return in.err("expected end of import"); + return in.err("expected end of global"); } - exports.push_back(*name); - } - return exports; -} -// strtype ::= ft:functype => ft -// | st:structtype => st -// | at:arraytype => at -template Result<> strtype(Ctx& ctx, ParseInput& in) { - if (auto type = functype(ctx, in)) { - CHECK_ERR(type); - if constexpr (parsingTypeDefs) { - ctx.builder[ctx.index] = *type; - } - return Ok{}; - } - if (auto type = structtype(ctx, in)) { - CHECK_ERR(type); - if constexpr (parsingTypeDefs) { - auto& [fieldNames, str] = *type; - ctx.builder[ctx.index] = str; - for (Index i = 0; i < fieldNames.size(); ++i) { - if (auto name = fieldNames[i]; name.is()) { - ctx.names[ctx.index].fieldNames[i] = name; - } + if constexpr (parsingDecls) { + if (ctx.hasNonImport) { + return in.err("import after non-import"); } + auto g = addGlobalDecl(ctx, in, name, *import); + CHECK_ERR(g); + CHECK_ERR(addExports(in, ctx.wasm, *g, *exports, ExternalKind::Global)); + ctx.globalDefs.push_back({name, pos}); + } else if constexpr (parsingModuleTypes) { + auto& g = ctx.wasm.globals[ctx.index]; + g->mutable_ = type->mutability; + g->type = type->type; } return Ok{}; } - if (auto type = arraytype(ctx, in)) { - CHECK_ERR(type); - if constexpr (parsingTypeDefs) { - ctx.builder[ctx.index] = *type; - } - return Ok{}; - } - return in.err("expected type description"); -} - -// subtype ::= '(' 'type' id? '(' 'sub' typeidx? strtype ')' ')' -// | '(' 'type' id? strtype ')' -template MaybeResult<> subtype(Ctx& ctx, ParseInput& in) { - [[maybe_unused]] auto pos = in.getPos(); - - if (!in.takeSExprStart("type"sv)) { - return {}; - } - - Name name; - if (auto id = in.takeID()) { - name = *id; - if constexpr (parsingTypeDefs) { - ctx.names[ctx.index].name = name; - } - } - - if (in.takeSExprStart("sub"sv)) { - if (auto super = maybeTypeidx(ctx, in)) { - CHECK_ERR(super); - if constexpr (parsingTypeDefs) { - if (*super >= ctx.builder.size()) { - return in.err("supertype index out of bounds"); - } - ctx.builder[ctx.index].subTypeOf(ctx.builder[*super]); - } - } - - CHECK_ERR(strtype(ctx, in)); - - if (!in.takeRParen()) { - return in.err("expected end of subtype definition"); - } - } else { - CHECK_ERR(strtype(ctx, in)); - } - - if (!in.takeRParen()) { - return in.err("expected end of type definition"); - } - - if constexpr (parsingDecls) { - ctx.subtypeDefs.push_back({name, pos}); - } - if constexpr (parsingTypeDefs) { - ++ctx.index; - } - - return Ok{}; -} - -// deftype ::= '(' 'rec' subtype* ')' -// | subtype -template MaybeResult<> deftype(Ctx& ctx, ParseInput& in) { - [[maybe_unused]] auto pos = in.getPos(); - - if (in.takeSExprStart("rec"sv)) { - [[maybe_unused]] size_t startIndex = 0; - if constexpr (parsingTypeDefs) { - startIndex = ctx.index; - } - size_t groupLen = 0; - while (auto type = subtype(ctx, in)) { - CHECK_ERR(type); - ++groupLen; - } - if (!in.takeRParen()) { - return in.err("expected type definition or end of recursion group"); - } - if constexpr (parsingTypeDefs) { - ctx.builder.createRecGroup(startIndex, groupLen); - } - } else if (auto type = subtype(ctx, in)) { - CHECK_ERR(type); - } else { - return {}; - } - - if constexpr (parsingDecls) { - ctx.typeDefs.push_back({{}, pos}); - } - - return Ok{}; -} - -// global ::= '(' 'global' id? ('(' 'export' name ')')* gt:globaltype e:expr ')' -// | '(' 'global' id? '(' 'import' mod:name nm:name ')' -// gt:globaltype ')' -template MaybeResult<> global(Ctx& ctx, ParseInput& in) { - [[maybe_unused]] auto pos = in.getPos(); - if (!in.takeSExprStart("global"sv)) { - return {}; - } - Name name; - if (auto id = in.takeID()) { - name = *id; - } - auto exports = inlineExports(in); - CHECK_ERR(exports); - - auto import = inlineImport(in); - CHECK_ERR(import); - - auto type = globaltype(ctx, in); - CHECK_ERR(type); - - std::optional exp; - if (!import) { - auto e = expr(ctx, in); - CHECK_ERR(e); - *exp = *e; - } - - if (!in.takeRParen()) { - return in.err("expected end of global"); - } - - if constexpr (parsingDecls) { - if (ctx.hasNonImport) { - return in.err("import after non-import"); - } - auto imp = import ? std::make_optional(*import) : std::nullopt; - auto g = addGlobalDecl(ctx, in, name, imp); - CHECK_ERR(g); - CHECK_ERR(addExports(in, ctx.wasm, *g, *exports, ExternalKind::Global)); - ctx.globalDefs.push_back({name, pos}); - } else if constexpr (parsingModuleTypes) { - auto& g = ctx.wasm.globals[ctx.index]; - g->mutable_ = type->mutability; - g->type = type->type; - } else if constexpr (parsingDefs) { - if (!import) { - ctx.wasm.globals[ctx.index]->init = *exp; - } - } - - return Ok{}; + return in.err("TODO: non-imported globals"); } // modulefield ::= deftype @@ -1930,7 +998,8 @@ MaybeResult<> modulefield(ParseDeclsCtx& ctx, ParseInput& in) { if (auto t = in.peek(); !t || t->isRParen()) { return {}; } - if (auto res = deftype(ctx, in)) { + // TODO: Replace strtype with deftype. + if (auto res = strtype(ctx, in)) { CHECK_ERR(res); return Ok{}; } @@ -2063,18 +1132,15 @@ Result<> parseModule(Module& wasm, std::string_view input) { } } - auto typeIndices = createIndexMap(input, decls.subtypeDefs); + auto typeIndices = createIndexMap(input, decls.typeDefs); CHECK_ERR(typeIndices); // Parse type definitions. std::vector types; { - TypeBuilder builder(decls.subtypeDefs.size()); + TypeBuilder builder(decls.typeDefs.size()); ParseTypeDefsCtx ctx(builder, *typeIndices); - for (auto& typeDef : decls.typeDefs) { - ParseInput in(input, typeDef.pos); - CHECK_ERR(deftype(ctx, in)); - } + CHECK_ERR(parseDefs(ctx, input, decls.typeDefs, strtype)); auto built = builder.build(); if (auto* err = built.getError()) { std::stringstream msg; @@ -2093,18 +1159,13 @@ 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. - } - { - // Parse definitions. - // TODO: Parallelize this. - ParseDefsCtx ctx(wasm, types, *typeIndices); - CHECK_ERR(parseDefs(ctx, input, decls.globalDefs, global)); - } + // 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. return Ok{}; } diff --git a/src/wasm2js.h b/src/wasm2js.h index f8179379d9d..ad373074d59 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -2311,22 +2311,6 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, unimplemented(curr); WASM_UNREACHABLE("unimp"); } - Ref visitStringMeasure(StringMeasure* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } - Ref visitStringEncode(StringEncode* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } - Ref visitStringConcat(StringConcat* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } - Ref visitStringEq(StringEq* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } Ref visitRefAs(RefAs* curr) { unimplemented(curr); WASM_UNREACHABLE("unimp"); diff --git a/test/lit/isorecursive-good.wast b/test/lit/isorecursive-good.wast index da14b38c8ce..7ced0d8d31c 100644 --- a/test/lit/isorecursive-good.wast +++ b/test/lit/isorecursive-good.wast @@ -1,4 +1,4 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. +;; TODO: Autogenerate these checks! The current script cannot handle `rec`. ;; RUN: wasm-opt %s -all --hybrid -S -o - | filecheck %s --check-prefix HYBRID ;; RUN: wasm-opt %s -all --hybrid --roundtrip -S -o - | filecheck %s --check-prefix HYBRID @@ -6,63 +6,46 @@ (module +;; HYBRID: (rec +;; HYBRID-NEXT: (type $super-struct (struct_subtype (field i32) data)) +;; HYBRID-NEXT: (type $sub-struct (struct_subtype (field i32) (field i64) $super-struct)) +;; HYBRID-NEXT: ) + +;; HYBRID: (rec +;; HYBRID-NEXT: (type $super-array (array_subtype (ref $super-struct) data)) +;; HYBRID-NEXT: (type $sub-array (array_subtype (ref $sub-struct) $super-array)) +;; HYBRID-NEXT: ) + +;; NOMINAL-NOT: rec + +;; NOMINAL: (type $super-struct (struct_subtype (field i32) data)) +;; NOMINAL-NEXT: (type $sub-struct (struct_subtype (field i32) (field i64) $super-struct)) + +;; NOMINAL: (type $super-array (array_subtype (ref $super-struct) data)) +;; NOMINAL-NEXT: (type $sub-array (array_subtype (ref $sub-struct) $super-array)) (rec - ;; HYBRID: (rec - ;; HYBRID-NEXT: (type $super-struct (struct_subtype (field i32) data)) - ;; NOMINAL: (type $super-struct (struct_subtype (field i32) data)) (type $super-struct (struct i32)) - ;; HYBRID: (type $sub-struct (struct_subtype (field i32) (field i64) $super-struct)) - ;; NOMINAL: (type $sub-struct (struct_subtype (field i32) (field i64) $super-struct)) (type $sub-struct (struct_subtype i32 i64 $super-struct)) ) (rec - ;; HYBRID: (rec - ;; HYBRID-NEXT: (type $super-array (array_subtype (ref $super-struct) data)) - ;; NOMINAL: (type $super-array (array_subtype (ref $super-struct) data)) (type $super-array (array (ref $super-struct))) - ;; HYBRID: (type $sub-array (array_subtype (ref $sub-struct) $super-array)) - ;; NOMINAL: (type $sub-array (array_subtype (ref $sub-struct) $super-array)) (type $sub-array (array_subtype (ref $sub-struct) $super-array)) ) - ;; HYBRID: (func $make-super-struct (type $none_=>_ref|$super-struct|) (result (ref $super-struct)) - ;; HYBRID-NEXT: (call $make-sub-struct) - ;; HYBRID-NEXT: ) - ;; NOMINAL: (func $make-super-struct (type $none_=>_ref|$super-struct|) (result (ref $super-struct)) - ;; NOMINAL-NEXT: (call $make-sub-struct) - ;; NOMINAL-NEXT: ) (func $make-super-struct (result (ref $super-struct)) (call $make-sub-struct) ) - ;; HYBRID: (func $make-sub-struct (type $none_=>_ref|$sub-struct|) (result (ref $sub-struct)) - ;; HYBRID-NEXT: (unreachable) - ;; HYBRID-NEXT: ) - ;; NOMINAL: (func $make-sub-struct (type $none_=>_ref|$sub-struct|) (result (ref $sub-struct)) - ;; NOMINAL-NEXT: (unreachable) - ;; NOMINAL-NEXT: ) (func $make-sub-struct (result (ref $sub-struct)) (unreachable) ) - ;; HYBRID: (func $make-super-array (type $none_=>_ref|$super-array|) (result (ref $super-array)) - ;; HYBRID-NEXT: (call $make-sub-array) - ;; HYBRID-NEXT: ) - ;; NOMINAL: (func $make-super-array (type $none_=>_ref|$super-array|) (result (ref $super-array)) - ;; NOMINAL-NEXT: (call $make-sub-array) - ;; NOMINAL-NEXT: ) (func $make-super-array (result (ref $super-array)) (call $make-sub-array) ) - ;; HYBRID: (func $make-sub-array (type $none_=>_ref|$sub-array|) (result (ref $sub-array)) - ;; HYBRID-NEXT: (unreachable) - ;; HYBRID-NEXT: ) - ;; NOMINAL: (func $make-sub-array (type $none_=>_ref|$sub-array|) (result (ref $sub-array)) - ;; NOMINAL-NEXT: (unreachable) - ;; NOMINAL-NEXT: ) (func $make-sub-array (result (ref $sub-array)) (unreachable) ) diff --git a/test/lit/isorecursive-output-ordering.wast b/test/lit/isorecursive-output-ordering.wast index acca0496971..ae965123f61 100644 --- a/test/lit/isorecursive-output-ordering.wast +++ b/test/lit/isorecursive-output-ordering.wast @@ -1,4 +1,4 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. +;; TODO: Autogenerate these checks! The current script cannot handle `rec`. ;; RUN: foreach %s %t wasm-opt -all --hybrid -S -o - | filecheck %s ;; RUN: foreach %s %t wasm-opt -all --hybrid --roundtrip -S -o - | filecheck %s @@ -6,25 +6,26 @@ (module ;; Test that we order groups by average uses. + ;; CHECK: (rec + ;; CHECK-NEXT: (type $unused-6 (struct_subtype data)) + ;; CHECK-NEXT: (type $used-a-bit (struct_subtype data)) + ;; CHECK-NEXT: ) - (rec - ;; CHECK: (rec - ;; CHECK-NEXT: (type $unused-6 (struct_subtype data)) - - ;; CHECK: (type $used-a-bit (struct_subtype data)) + ;; CHECK-NEXT: (rec + ;; CHECK-NEXT: (type $unused-1 (struct_subtype data)) + ;; CHECK-NEXT: (type $unused-2 (struct_subtype data)) + ;; CHECK-NEXT: (type $unused-3 (struct_subtype data)) + ;; CHECK-NEXT: (type $unused-4 (struct_subtype data)) + ;; CHECK-NEXT: (type $used-a-lot (struct_subtype data)) + ;; CHECK-NEXT: (type $unused-5 (struct_subtype data)) + ;; CHECK-NEXT: ) - ;; CHECK: (rec - ;; CHECK-NEXT: (type $unused-1 (struct_subtype data)) + (rec (type $unused-1 (struct_subtype data)) - ;; CHECK: (type $unused-2 (struct_subtype data)) (type $unused-2 (struct_subtype data)) - ;; CHECK: (type $unused-3 (struct_subtype data)) (type $unused-3 (struct_subtype data)) - ;; CHECK: (type $unused-4 (struct_subtype data)) (type $unused-4 (struct_subtype data)) - ;; CHECK: (type $used-a-lot (struct_subtype data)) (type $used-a-lot (struct_subtype data)) - ;; CHECK: (type $unused-5 (struct_subtype data)) (type $unused-5 (struct_subtype data)) ) @@ -33,9 +34,6 @@ (type $used-a-bit (struct_subtype data)) ) - ;; CHECK: (func $use (type $ref|$used-a-lot|_ref|$used-a-lot|_ref|$used-a-lot|_ref|$used-a-lot|_ref|$used-a-lot|_ref|$used-a-lot|_=>_ref|$used-a-bit|_ref|$used-a-bit|_ref|$used-a-bit|_ref|$used-a-bit|) (param $0 (ref $used-a-lot)) (param $1 (ref $used-a-lot)) (param $2 (ref $used-a-lot)) (param $3 (ref $used-a-lot)) (param $4 (ref $used-a-lot)) (param $5 (ref $used-a-lot)) (result (ref $used-a-bit) (ref $used-a-bit) (ref $used-a-bit) (ref $used-a-bit)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) (func $use (param (ref $used-a-lot) (ref $used-a-lot) (ref $used-a-lot) (ref $used-a-lot) (ref $used-a-lot) (ref $used-a-lot)) (result (ref $used-a-bit) (ref $used-a-bit) (ref $used-a-bit) (ref $used-a-bit)) (unreachable) ) @@ -44,25 +42,33 @@ (module ;; Test that we respect dependencies between groups before considering counts. + ;; CHECK: (rec + ;; CHECK-NEXT: (type $leaf (struct_subtype data)) + ;; CHECK-NEXT: (type $unused (struct_subtype data)) + ;; CHECK-NEXT: ) + + ;; CHECK-NEXT: (rec + ;; CHECK-NEXT: (type $shrub (struct_subtype $leaf)) + ;; CHECK-NEXT: (type $used-a-ton (struct_subtype data)) + ;; CHECK-NEXT: ) + + ;; CHECK-NEXT: (rec + ;; CHECK-NEXT: (type $twig (struct_subtype data)) + ;; CHECK-NEXT: (type $used-a-bit (struct_subtype (field (ref $leaf)) data)) + ;; CHECK-NEXT: ) + + ;; CHECK-NEXT: (rec + ;; CHECK-NEXT: (type $root (struct_subtype data)) + ;; CHECK-NEXT: (type $used-a-lot (struct_subtype $twig)) + ;; CHECK-NEXT: ) (rec - ;; CHECK: (rec - ;; CHECK-NEXT: (type $leaf (struct_subtype data)) (type $leaf (struct_subtype data)) - ;; CHECK: (type $unused (struct_subtype data)) (type $unused (struct_subtype data)) ) (rec - ;; CHECK: (rec - ;; CHECK-NEXT: (type $shrub (struct_subtype $leaf)) - - ;; CHECK: (type $used-a-ton (struct_subtype data)) - - ;; CHECK: (rec - ;; CHECK-NEXT: (type $twig (struct_subtype data)) (type $twig (struct_subtype data)) - ;; CHECK: (type $used-a-bit (struct_subtype (field (ref $leaf)) data)) (type $used-a-bit (struct_subtype (ref $leaf) data)) ) @@ -72,23 +78,10 @@ ) (rec - ;; CHECK: (rec - ;; CHECK-NEXT: (type $root (struct_subtype data)) (type $root (struct_subtype data)) - ;; CHECK: (type $used-a-lot (struct_subtype $twig)) (type $used-a-lot (struct_subtype $twig)) ) - ;; CHECK: (func $use (type $ref|$used-a-lot|_ref|$used-a-lot|_ref|$used-a-lot|_ref|$used-a-lot|_ref|$used-a-lot|_ref|$used-a-lot|_=>_ref|$used-a-bit|_ref|$used-a-bit|_ref|$used-a-bit|) (param $0 (ref $used-a-lot)) (param $1 (ref $used-a-lot)) (param $2 (ref $used-a-lot)) (param $3 (ref $used-a-lot)) (param $4 (ref $used-a-lot)) (param $5 (ref $used-a-lot)) (result (ref $used-a-bit) (ref $used-a-bit) (ref $used-a-bit)) - ;; CHECK-NEXT: (local $6 (ref null $used-a-ton)) - ;; CHECK-NEXT: (local $7 (ref null $used-a-ton)) - ;; CHECK-NEXT: (local $8 (ref null $used-a-ton)) - ;; CHECK-NEXT: (local $9 (ref null $used-a-ton)) - ;; CHECK-NEXT: (local $10 (ref null $used-a-ton)) - ;; CHECK-NEXT: (local $11 (ref null $used-a-ton)) - ;; CHECK-NEXT: (local $12 (ref null $used-a-ton)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) (func $use (param (ref $used-a-lot) (ref $used-a-lot) (ref $used-a-lot) (ref $used-a-lot) (ref $used-a-lot) (ref $used-a-lot)) (result (ref $used-a-bit) (ref $used-a-bit) (ref $used-a-bit)) (local (ref null $used-a-ton) (ref null $used-a-ton) (ref null $used-a-ton) (ref null $used-a-ton) (ref null $used-a-ton) (ref null $used-a-ton) (ref null $used-a-ton)) (unreachable) @@ -99,13 +92,9 @@ ;; Test that basic heap type children do not trigger assertions. (rec - ;; CHECK: (type $contains-basic (struct_subtype (field (ref any)) data)) (type $contains-basic (struct_subtype (ref any) data)) ) - ;; CHECK: (func $use (type $ref|$contains-basic|_=>_none) (param $0 (ref $contains-basic)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) (func $use (param (ref $contains-basic)) (unreachable) ) diff --git a/test/lit/isorecursive-singleton-group.wast b/test/lit/isorecursive-singleton-group.wast index c36717376a9..eeb92ac0993 100644 --- a/test/lit/isorecursive-singleton-group.wast +++ b/test/lit/isorecursive-singleton-group.wast @@ -1,4 +1,4 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. +;; TODO: Autogenerate these checks! The current script cannot handle `rec`. ;; RUN: wasm-opt %s -all --hybrid -S -o - | filecheck %s ;; RUN: wasm-opt %s -all --hybrid --roundtrip -S -o - | filecheck %s @@ -8,13 +8,13 @@ (module +;; CHECK-NOT: rec +;; CHECK: (type $singleton (struct_subtype data)) (rec - ;; CHECK: (type $singleton (struct_subtype data)) (type $singleton (struct_subtype data)) ) ;; Use the type so it appears in the output. - ;; CHECK: (global $g (ref null $singleton) (ref.null $singleton)) (global $g (ref null $singleton) (ref.null $singleton)) ) diff --git a/test/lit/isorecursive-whole-group.wast b/test/lit/isorecursive-whole-group.wast index f2a60deda36..4d349a3cb63 100644 --- a/test/lit/isorecursive-whole-group.wast +++ b/test/lit/isorecursive-whole-group.wast @@ -1,4 +1,4 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. +;; TODO: Autogenerate these checks! The current script cannot handle `rec`. ;; RUN: wasm-opt %s -all --hybrid -S -o - | filecheck %s ;; RUN: wasm-opt %s -all --hybrid --roundtrip -S -o - | filecheck %s @@ -8,15 +8,15 @@ (module +;; CHECK: (rec +;; CHECK-NEXT: (type $used (struct_subtype data)) +;; CHECK-NEXT: (type $unused (struct_subtype data)) +;; CHECK-NEXT: ) (rec - ;; CHECK: (rec - ;; CHECK-NEXT: (type $used (struct_subtype data)) (type $used (struct_subtype data)) - ;; CHECK: (type $unused (struct_subtype data)) (type $unused (struct_subtype data)) ) - ;; CHECK: (global $g (ref null $used) (ref.null $used)) (global $g (ref null $used) (ref.null $used)) ) diff --git a/test/lit/nominal-to-isorecursive.wast b/test/lit/nominal-to-isorecursive.wast index beb0aaee9ad..c1deadb546e 100644 --- a/test/lit/nominal-to-isorecursive.wast +++ b/test/lit/nominal-to-isorecursive.wast @@ -1,4 +1,4 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. +;; TODO: Autogenerate these checks! The current script cannot handle `rec`. ;; RUN: wasm-as %s -all --nominal -g -o %t.wasm ;; RUN: wasm-dis %t.wasm -all --hybrid -o - | filecheck %s @@ -6,29 +6,30 @@ ;; Check that the nominal binary format is parseable as isorecursive with a ;; single recursion group. +;; CHECK: (module +;; CHECK-NEXT: (rec +;; CHECK-NEXT: (type $make-super-t (func_subtype (result (ref $super)) func)) +;; CHECK-NEXT: (type $make-sub-t (func_subtype (result (ref $sub)) func)) +;; CHECK-NEXT: (type $super (struct_subtype (field i32) data)) +;; CHECK-NEXT: (type $sub (struct_subtype (field i32) $super)) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (func $make-super (type $make-super-t) (result (ref $super)) +;; CHECK-NEXT: (unreachable) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (func $make-sub (type $make-sub-t) (result (ref $sub)) +;; CHECK-NEXT: (unreachable) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) (module - ;; CHECK: (rec - ;; CHECK-NEXT: (type $make-super-t (func_subtype (result (ref $super)) func)) - - ;; CHECK: (type $make-sub-t (func_subtype (result (ref $sub)) func)) - - ;; CHECK: (type $super (struct_subtype (field i32) data)) (type $super (struct i32)) - ;; CHECK: (type $sub (struct_subtype (field i32) $super)) (type $sub (struct_subtype i32 $super)) (type $make-super-t (func (result (ref $super)))) (type $make-sub-t (func (result (ref $sub)))) - ;; CHECK: (func $make-super (type $make-super-t) (result (ref $super)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) (func $make-super (type $make-super-t) (unreachable) ) - ;; CHECK: (func $make-sub (type $make-sub-t) (result (ref $sub)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) (func $make-sub (type $make-sub-t) (unreachable) ) diff --git a/test/lit/passes/gufa-refs.wast b/test/lit/passes/gufa-refs.wast index cc62c01716e..3dff38be80c 100644 --- a/test/lit/passes/gufa-refs.wast +++ b/test/lit/passes/gufa-refs.wast @@ -3362,6 +3362,7 @@ (struct.new $struct (i32.const 10) ) + (i32.const 11) ) ;; Write to that global here. This can only affect $struct, and *not* ;; $substruct, thanks to the exact type. diff --git a/test/lit/passes/gufa.wast b/test/lit/passes/gufa.wast index 01b83ce064c..e7caa6f2c5f 100644 --- a/test/lit/passes/gufa.wast +++ b/test/lit/passes/gufa.wast @@ -55,8 +55,8 @@ ;; Both arms of the select have identical values, 1. Inlining + ;; OptimizeInstructions could of course discover that in this case, but ;; GUFA can do so even without inlining. As a result the select will be - ;; dropped (due to the call which may have effects, we keep it), and at the - ;; end we emit the constant 1 for the value. + ;; dropped (due to the call which may have effects, we keep it), and after + ;; the select we emit the constant 1 for the value. (drop (select (call $foo) diff --git a/test/lit/passes/optimize-instructions-gc.wast b/test/lit/passes/optimize-instructions-gc.wast index 643aad5edaa..2c6498ec3f9 100644 --- a/test/lit/passes/optimize-instructions-gc.wast +++ b/test/lit/passes/optimize-instructions-gc.wast @@ -2876,70 +2876,4 @@ ) ) ) - - ;; CHECK: (func $ref-boolean (param $x eqref) (param $y eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.is_func - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.test_static $A - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-boolean (type $eqref_eqref_=>_none) (param $x eqref) (param $y eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.eq - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.is_func - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.test_static $A - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-boolean (param $x eqref) (param $y eqref) - ;; ref.eq returns a boolean, so &1 on it is not needed. - (drop - (i32.and - (ref.eq - (local.get $x) - (local.get $y) - ) - (i32.const 1) - ) - ) - ;; likewise ref.is and ref.test - (drop - (i32.and - (ref.is_func - (local.get $x) - ) - (i32.const 1) - ) - ) - (drop - (i32.and - (ref.test_static $A - (local.get $x) - ) - (i32.const 1) - ) - ) - ) ) diff --git a/test/lit/strings.wast b/test/lit/strings.wast index d1a9fd0535d..7436a04b93f 100644 --- a/test/lit/strings.wast +++ b/test/lit/strings.wast @@ -5,10 +5,6 @@ ;; RUN: foreach %s %t wasm-opt --enable-strings --enable-reference-types --roundtrip -S -o - | filecheck %s (module - ;; CHECK: (type $ref?|string|_=>_none (func (param stringref))) - - ;; CHECK: (type $ref?|string|_ref?|string|_=>_none (func (param stringref stringref))) - ;; CHECK: (type $ref?|string|_ref?|stringview_wtf8|_ref?|stringview_wtf16|_ref?|stringview_iter|_ref?|string|_ref?|stringview_wtf8|_ref?|stringview_wtf16|_ref?|stringview_iter|_ref|string|_ref|stringview_wtf8|_ref|stringview_wtf16|_ref|stringview_iter|_=>_none (func (param stringref stringview_wtf8 stringview_wtf16 stringview_iter stringref stringview_wtf8 stringview_wtf16 stringview_iter (ref string) (ref stringview_wtf8) (ref stringview_wtf16) (ref stringview_iter)))) ;; CHECK: (type $none_=>_none (func)) @@ -103,145 +99,4 @@ (string.const "bar") ) ) - - ;; CHECK: (func $string.measure (param $ref stringref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (string.measure_wtf8 wtf8 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (string.measure_wtf8 utf8 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (string.measure_wtf16 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $string.measure (param $ref stringref) - (drop - (i32.eqz ;; validate the output is i32 - (string.measure_wtf8 wtf8 - (local.get $ref) - ) - ) - ) - (drop - (string.measure_wtf8 utf8 - (local.get $ref) - ) - ) - (drop - (string.measure_wtf16 - (local.get $ref) - ) - ) - ) - - ;; CHECK: (func $string.encode (param $ref stringref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (string.encode_wtf8 wtf8 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (string.encode_wtf8 utf8 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (string.encode_wtf16 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $string.encode (param $ref stringref) - (drop - (i32.eqz ;; validate the output is i32 - (string.encode_wtf8 wtf8 - (local.get $ref) - (i32.const 10) - ) - ) - ) - (drop - (string.encode_wtf8 utf8 - (local.get $ref) - (i32.const 20) - ) - ) - (drop - (string.encode_wtf16 - (local.get $ref) - (i32.const 30) - ) - ) - ) - - ;; CHECK: (func $string.concat (param $a stringref) (param $b stringref) - ;; CHECK-NEXT: (local.set $a - ;; CHECK-NEXT: (string.concat - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $b) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $string.concat (param $a stringref) (param $b stringref) - (local.set $a ;; validate the output is a stringref - (string.concat - (local.get $a) - (local.get $b) - ) - ) - ) - - ;; CHECK: (func $string.eq (param $a stringref) (param $b stringref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (string.eq - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $b) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $string.eq (param $a stringref) (param $b stringref) - (drop - (i32.eqz ;; validate the output is an i32 - (string.eq - (local.get $a) - (local.get $b) - ) - ) - ) - ) - - ;; CHECK: (func $string.is_usv_sequence (param $ref stringref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (string.is_usv_sequence - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $string.is_usv_sequence (param $ref stringref) - (drop - (i32.eqz ;; validate the output is i32 - (string.is_usv_sequence - (local.get $ref) - ) - ) - ) - ) ) diff --git a/test/lit/types-function-references.wast b/test/lit/types-function-references.wast deleted file mode 100644 index db465acea3b..00000000000 --- a/test/lit/types-function-references.wast +++ /dev/null @@ -1,529 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. - -;; RUN: wasm-as %s -all -g -o %t.wasm -;; RUN: wasm-dis %t.wasm -all -o %t.wast -;; RUN: wasm-as %s -all -o %t.nodebug.wasm -;; RUN: wasm-dis %t.nodebug.wasm -all -o %t.nodebug.wast -;; RUN: wasm-opt %t.wast -all -o %t.text.wast -g -S -;; RUN: cat %t.wast | filecheck %s --check-prefix=CHECK-BINARY -;; RUN: cat %t.nodebug.wast | filecheck %s --check-prefix=CHECK-NODEBUG -;; RUN: cat %t.text.wast | filecheck %s --check-prefix=CHECK-TEXT - -(module - ;; inline ref type in result - (type $_=>_eqref (func (result eqref))) - ;; CHECK-BINARY: (type $mixed_results (func (result anyref f32 anyref f32))) - - ;; CHECK-BINARY: (type $none_=>_none (func)) - - ;; CHECK-BINARY: (type $i32-i32 (func (param i32) (result i32))) - - ;; CHECK-BINARY: (type $=>eqref (func (result eqref))) - - ;; CHECK-BINARY: (type $ref|$i32-i32|_=>_i32 (func (param (ref $i32-i32)) (result i32))) - - ;; CHECK-BINARY: (type $ref?|$i32-i32|_=>_i32 (func (param (ref null $i32-i32)) (result i32))) - - ;; CHECK-BINARY: (type $none_=>_i32 (func (result i32))) - - ;; CHECK-BINARY: (type $f64_=>_ref_null<_->_eqref> (func (param f64) (result (ref null $=>eqref)))) - ;; CHECK-TEXT: (type $mixed_results (func (result anyref f32 anyref f32))) - - ;; CHECK-TEXT: (type $none_=>_none (func)) - - ;; CHECK-TEXT: (type $i32-i32 (func (param i32) (result i32))) - - ;; CHECK-TEXT: (type $=>eqref (func (result eqref))) - - ;; CHECK-TEXT: (type $ref|$i32-i32|_=>_i32 (func (param (ref $i32-i32)) (result i32))) - - ;; CHECK-TEXT: (type $ref?|$i32-i32|_=>_i32 (func (param (ref null $i32-i32)) (result i32))) - - ;; CHECK-TEXT: (type $none_=>_i32 (func (result i32))) - - ;; CHECK-TEXT: (type $f64_=>_ref_null<_->_eqref> (func (param f64) (result (ref null $=>eqref)))) - (type $f64_=>_ref_null<_->_eqref> (func (param f64) (result (ref null $_=>_eqref)))) - (type $=>eqref (func (result eqref))) - ;; CHECK-BINARY: (type $=>anyref (func (result anyref))) - ;; CHECK-TEXT: (type $=>anyref (func (result anyref))) - (type $=>anyref (func (result anyref))) - (type $mixed_results (func (result anyref f32 anyref f32))) - - (type $i32-i32 (func (param i32) (result i32))) - - ;; CHECK-BINARY: (type $none_=>_i32_ref?|$mixed_results|_f64 (func (result i32 (ref null $mixed_results) f64))) - - ;; CHECK-BINARY: (type $ref?|$mixed_results|_=>_none (func (param (ref null $mixed_results)))) - - ;; CHECK-BINARY: (elem declare func $call-ref $call-ref-more) - - ;; CHECK-BINARY: (func $call-ref - ;; CHECK-BINARY-NEXT: (call_ref - ;; CHECK-BINARY-NEXT: (ref.func $call-ref) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (type $none_=>_i32_ref?|$mixed_results|_f64 (func (result i32 (ref null $mixed_results) f64))) - - ;; CHECK-TEXT: (type $ref?|$mixed_results|_=>_none (func (param (ref null $mixed_results)))) - - ;; CHECK-TEXT: (elem declare func $call-ref $call-ref-more) - - ;; CHECK-TEXT: (func $call-ref - ;; CHECK-TEXT-NEXT: (call_ref - ;; CHECK-TEXT-NEXT: (ref.func $call-ref) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $call-ref - (call_ref (ref.func $call-ref)) - ) - ;; CHECK-BINARY: (func $return-call-ref - ;; CHECK-BINARY-NEXT: (return_call_ref - ;; CHECK-BINARY-NEXT: (ref.func $call-ref) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $return-call-ref - ;; CHECK-TEXT-NEXT: (return_call_ref - ;; CHECK-TEXT-NEXT: (ref.func $call-ref) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $return-call-ref - (return_call_ref (ref.func $call-ref)) - ) - ;; CHECK-BINARY: (func $call-ref-more (param $0 i32) (result i32) - ;; CHECK-BINARY-NEXT: (call_ref - ;; CHECK-BINARY-NEXT: (i32.const 42) - ;; CHECK-BINARY-NEXT: (ref.func $call-ref-more) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $call-ref-more (param $0 i32) (result i32) - ;; CHECK-TEXT-NEXT: (call_ref - ;; CHECK-TEXT-NEXT: (i32.const 42) - ;; CHECK-TEXT-NEXT: (ref.func $call-ref-more) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $call-ref-more (param i32) (result i32) - (call_ref (i32.const 42) (ref.func $call-ref-more)) - ) - ;; CHECK-BINARY: (func $call_from-param (param $f (ref $i32-i32)) (result i32) - ;; CHECK-BINARY-NEXT: (call_ref - ;; CHECK-BINARY-NEXT: (i32.const 42) - ;; CHECK-BINARY-NEXT: (local.get $f) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $call_from-param (param $f (ref $i32-i32)) (result i32) - ;; CHECK-TEXT-NEXT: (call_ref - ;; CHECK-TEXT-NEXT: (i32.const 42) - ;; CHECK-TEXT-NEXT: (local.get $f) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $call_from-param (param $f (ref $i32-i32)) (result i32) - (call_ref (i32.const 42) (local.get $f)) - ) - ;; CHECK-BINARY: (func $call_from-param-null (param $f (ref null $i32-i32)) (result i32) - ;; CHECK-BINARY-NEXT: (call_ref - ;; CHECK-BINARY-NEXT: (i32.const 42) - ;; CHECK-BINARY-NEXT: (local.get $f) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $call_from-param-null (param $f (ref null $i32-i32)) (result i32) - ;; CHECK-TEXT-NEXT: (call_ref - ;; CHECK-TEXT-NEXT: (i32.const 42) - ;; CHECK-TEXT-NEXT: (local.get $f) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $call_from-param-null (param $f (ref null $i32-i32)) (result i32) - (call_ref (i32.const 42) (local.get $f)) - ) - ;; CHECK-BINARY: (func $call_from-local-null (result i32) - ;; CHECK-BINARY-NEXT: (local $f (ref null $i32-i32)) - ;; CHECK-BINARY-NEXT: (local.set $f - ;; CHECK-BINARY-NEXT: (ref.func $call-ref-more) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: (call_ref - ;; CHECK-BINARY-NEXT: (i32.const 42) - ;; CHECK-BINARY-NEXT: (local.get $f) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $call_from-local-null (result i32) - ;; CHECK-TEXT-NEXT: (local $f (ref null $i32-i32)) - ;; CHECK-TEXT-NEXT: (local.set $f - ;; CHECK-TEXT-NEXT: (ref.func $call-ref-more) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: (call_ref - ;; CHECK-TEXT-NEXT: (i32.const 42) - ;; CHECK-TEXT-NEXT: (local.get $f) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $call_from-local-null (result i32) - (local $f (ref null $i32-i32)) - (local.set $f (ref.func $call-ref-more)) - (call_ref (i32.const 42) (local.get $f)) - ) - ;; CHECK-BINARY: (func $ref-in-sig (param $0 f64) (result (ref null $=>eqref)) - ;; CHECK-BINARY-NEXT: (ref.null $=>eqref) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $ref-in-sig (param $0 f64) (result (ref null $=>eqref)) - ;; CHECK-TEXT-NEXT: (ref.null $=>eqref) - ;; CHECK-TEXT-NEXT: ) - (func $ref-in-sig (param $0 f64) (result (ref null $=>eqref)) - (ref.null $=>eqref) - ) - ;; CHECK-BINARY: (func $type-only-in-tuple-local - ;; CHECK-BINARY-NEXT: (local $x i32) - ;; CHECK-BINARY-NEXT: (local $1 f64) - ;; CHECK-BINARY-NEXT: (local $2 (ref null $=>anyref)) - ;; CHECK-BINARY-NEXT: (nop) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $type-only-in-tuple-local - ;; CHECK-TEXT-NEXT: (local $x i32) - ;; CHECK-TEXT-NEXT: (local $1 f64) - ;; CHECK-TEXT-NEXT: (local $2 (ref null $=>anyref)) - ;; CHECK-TEXT-NEXT: (nop) - ;; CHECK-TEXT-NEXT: ) - (func $type-only-in-tuple-local - (local $x (i32 (ref null $=>anyref) f64)) - ) - ;; CHECK-BINARY: (func $type-only-in-tuple-block - ;; CHECK-BINARY-NEXT: (local $0 (i32 (ref null $mixed_results) f64)) - ;; CHECK-BINARY-NEXT: (local $1 (ref null $mixed_results)) - ;; CHECK-BINARY-NEXT: (local $2 i32) - ;; CHECK-BINARY-NEXT: (local.set $0 - ;; CHECK-BINARY-NEXT: (block $label$1 (result i32 (ref null $mixed_results) f64) - ;; CHECK-BINARY-NEXT: (unreachable) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: (drop - ;; CHECK-BINARY-NEXT: (block (result i32) - ;; CHECK-BINARY-NEXT: (local.set $2 - ;; CHECK-BINARY-NEXT: (tuple.extract 0 - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: (drop - ;; CHECK-BINARY-NEXT: (block (result (ref null $mixed_results)) - ;; CHECK-BINARY-NEXT: (local.set $1 - ;; CHECK-BINARY-NEXT: (tuple.extract 1 - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: (drop - ;; CHECK-BINARY-NEXT: (tuple.extract 2 - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: (local.get $1) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: (local.get $2) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $type-only-in-tuple-block - ;; CHECK-TEXT-NEXT: (local $0 (i32 (ref null $mixed_results) f64)) - ;; CHECK-TEXT-NEXT: (local $1 (ref null $mixed_results)) - ;; CHECK-TEXT-NEXT: (local $2 i32) - ;; CHECK-TEXT-NEXT: (local.set $0 - ;; CHECK-TEXT-NEXT: (block $label$1 (result i32 (ref null $mixed_results) f64) - ;; CHECK-TEXT-NEXT: (unreachable) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: (drop - ;; CHECK-TEXT-NEXT: (block $block (result i32) - ;; CHECK-TEXT-NEXT: (local.set $2 - ;; CHECK-TEXT-NEXT: (tuple.extract 0 - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: (drop - ;; CHECK-TEXT-NEXT: (block $block0 (result (ref null $mixed_results)) - ;; CHECK-TEXT-NEXT: (local.set $1 - ;; CHECK-TEXT-NEXT: (tuple.extract 1 - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: (drop - ;; CHECK-TEXT-NEXT: (tuple.extract 2 - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: (local.get $1) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: (local.get $2) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $type-only-in-tuple-block - (drop - (block (result i32 (ref null $mixed_results) f64) - (unreachable) - ) - ) - ) - ;; CHECK-BINARY: (func $ref-types-first - ;; CHECK-BINARY-NEXT: (local $r1 (ref null $mixed_results)) - ;; CHECK-BINARY-NEXT: (local $r2 (ref null $mixed_results)) - ;; CHECK-BINARY-NEXT: (local $r3 anyref) - ;; CHECK-BINARY-NEXT: (local $r4 anyref) - ;; CHECK-BINARY-NEXT: (local $r5 anyref) - ;; CHECK-BINARY-NEXT: (local $r6 funcref) - ;; CHECK-BINARY-NEXT: (local $i1 i32) - ;; CHECK-BINARY-NEXT: (local $i2 i64) - ;; CHECK-BINARY-NEXT: (local $i3 i64) - ;; CHECK-BINARY-NEXT: (nop) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $ref-types-first - ;; CHECK-TEXT-NEXT: (local $r1 (ref null $mixed_results)) - ;; CHECK-TEXT-NEXT: (local $r2 (ref null $mixed_results)) - ;; CHECK-TEXT-NEXT: (local $r3 anyref) - ;; CHECK-TEXT-NEXT: (local $r4 anyref) - ;; CHECK-TEXT-NEXT: (local $r5 anyref) - ;; CHECK-TEXT-NEXT: (local $r6 funcref) - ;; CHECK-TEXT-NEXT: (local $i1 i32) - ;; CHECK-TEXT-NEXT: (local $i2 i64) - ;; CHECK-TEXT-NEXT: (local $i3 i64) - ;; CHECK-TEXT-NEXT: (nop) - ;; CHECK-TEXT-NEXT: ) - (func $ref-types-first - ;; 6 reference types and 3 MVP types. The binary format should emit all the - ;; reference types first since a reference type appears first. In addition, - ;; types should be emitted in blocks there, that is, locals of identical - ;; types should be adjacent. - (local $r1 (ref null $mixed_results)) - (local $r2 (ref null $mixed_results)) - (local $i1 i32) - (local $r3 anyref) - (local $i2 i64) - (local $r4 anyref) - (local $i3 i64) - (local $r5 anyref) - (local $r6 funcref) - ) - ;; CHECK-BINARY: (func $mvp-types-first - ;; CHECK-BINARY-NEXT: (local $i1 i32) - ;; CHECK-BINARY-NEXT: (local $i2 i64) - ;; CHECK-BINARY-NEXT: (local $i3 i64) - ;; CHECK-BINARY-NEXT: (local $r1 (ref null $mixed_results)) - ;; CHECK-BINARY-NEXT: (local $r2 (ref null $mixed_results)) - ;; CHECK-BINARY-NEXT: (local $r3 anyref) - ;; CHECK-BINARY-NEXT: (local $r4 anyref) - ;; CHECK-BINARY-NEXT: (local $r5 anyref) - ;; CHECK-BINARY-NEXT: (local $r6 funcref) - ;; CHECK-BINARY-NEXT: (nop) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $mvp-types-first - ;; CHECK-TEXT-NEXT: (local $i1 i32) - ;; CHECK-TEXT-NEXT: (local $i2 i64) - ;; CHECK-TEXT-NEXT: (local $i3 i64) - ;; CHECK-TEXT-NEXT: (local $r1 (ref null $mixed_results)) - ;; CHECK-TEXT-NEXT: (local $r2 (ref null $mixed_results)) - ;; CHECK-TEXT-NEXT: (local $r3 anyref) - ;; CHECK-TEXT-NEXT: (local $r4 anyref) - ;; CHECK-TEXT-NEXT: (local $r5 anyref) - ;; CHECK-TEXT-NEXT: (local $r6 funcref) - ;; CHECK-TEXT-NEXT: (nop) - ;; CHECK-TEXT-NEXT: ) - (func $mvp-types-first - ;; Reversed from before, now an MVP type appears first, so they should all - ;; be before reference types in the binary format. - (local $i1 i32) ;; only this local was moved up. - (local $r1 (ref null $mixed_results)) - (local $r2 (ref null $mixed_results)) - (local $r3 anyref) - (local $i2 i64) - (local $r4 anyref) - (local $i3 i64) - (local $r5 anyref) - (local $r6 funcref) - ) - ;; CHECK-BINARY: (func $mvp-types-first-param (param $r0 (ref null $mixed_results)) - ;; CHECK-BINARY-NEXT: (local $i1 i32) - ;; CHECK-BINARY-NEXT: (local $i2 i64) - ;; CHECK-BINARY-NEXT: (local $i3 i64) - ;; CHECK-BINARY-NEXT: (local $r1 (ref null $mixed_results)) - ;; CHECK-BINARY-NEXT: (local $r2 (ref null $mixed_results)) - ;; CHECK-BINARY-NEXT: (local $r3 anyref) - ;; CHECK-BINARY-NEXT: (local $r4 anyref) - ;; CHECK-BINARY-NEXT: (local $r5 anyref) - ;; CHECK-BINARY-NEXT: (local $r6 funcref) - ;; CHECK-BINARY-NEXT: (nop) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $mvp-types-first-param (param $r0 (ref null $mixed_results)) - ;; CHECK-TEXT-NEXT: (local $i1 i32) - ;; CHECK-TEXT-NEXT: (local $i2 i64) - ;; CHECK-TEXT-NEXT: (local $i3 i64) - ;; CHECK-TEXT-NEXT: (local $r1 (ref null $mixed_results)) - ;; CHECK-TEXT-NEXT: (local $r2 (ref null $mixed_results)) - ;; CHECK-TEXT-NEXT: (local $r3 anyref) - ;; CHECK-TEXT-NEXT: (local $r4 anyref) - ;; CHECK-TEXT-NEXT: (local $r5 anyref) - ;; CHECK-TEXT-NEXT: (local $r6 funcref) - ;; CHECK-TEXT-NEXT: (nop) - ;; CHECK-TEXT-NEXT: ) - (func $mvp-types-first-param (param $r0 (ref null $mixed_results)) - ;; As before, but now there is a reference type *parameter*. We should - ;; ignore that and sort as in the last function. - (local $i1 i32) ;; only this local was moved up. - (local $r1 (ref null $mixed_results)) - (local $r2 (ref null $mixed_results)) - (local $r3 anyref) - (local $i2 i64) - (local $r4 anyref) - (local $i3 i64) - (local $r5 anyref) - (local $r6 funcref) - ) -) -;; CHECK-NODEBUG: (type $none_=>_anyref_f32_anyref_f32 (func (result anyref f32 anyref f32))) - -;; CHECK-NODEBUG: (type $none_=>_none (func)) - -;; CHECK-NODEBUG: (type $i32_=>_i32 (func (param i32) (result i32))) - -;; CHECK-NODEBUG: (type $none_=>_eqref (func (result eqref))) - -;; CHECK-NODEBUG: (type $ref|i32_->_i32|_=>_i32 (func (param (ref $i32_=>_i32)) (result i32))) - -;; CHECK-NODEBUG: (type $ref?|i32_->_i32|_=>_i32 (func (param (ref null $i32_=>_i32)) (result i32))) - -;; CHECK-NODEBUG: (type $none_=>_i32 (func (result i32))) - -;; CHECK-NODEBUG: (type $f64_=>_ref?|none_->_eqref| (func (param f64) (result (ref null $none_=>_eqref)))) - -;; CHECK-NODEBUG: (type $none_=>_anyref (func (result anyref))) - -;; CHECK-NODEBUG: (type $none_=>_i32_ref?|none_->_anyref_f32_anyref_f32|_f64 (func (result i32 (ref null $none_=>_anyref_f32_anyref_f32) f64))) - -;; CHECK-NODEBUG: (type $ref?|none_->_anyref_f32_anyref_f32|_=>_none (func (param (ref null $none_=>_anyref_f32_anyref_f32)))) - -;; CHECK-NODEBUG: (elem declare func $0 $2) - -;; CHECK-NODEBUG: (func $0 -;; CHECK-NODEBUG-NEXT: (call_ref -;; CHECK-NODEBUG-NEXT: (ref.func $0) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $1 -;; CHECK-NODEBUG-NEXT: (return_call_ref -;; CHECK-NODEBUG-NEXT: (ref.func $0) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $2 (param $0 i32) (result i32) -;; CHECK-NODEBUG-NEXT: (call_ref -;; CHECK-NODEBUG-NEXT: (i32.const 42) -;; CHECK-NODEBUG-NEXT: (ref.func $2) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $3 (param $0 (ref $i32_=>_i32)) (result i32) -;; CHECK-NODEBUG-NEXT: (call_ref -;; CHECK-NODEBUG-NEXT: (i32.const 42) -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $4 (param $0 (ref null $i32_=>_i32)) (result i32) -;; CHECK-NODEBUG-NEXT: (call_ref -;; CHECK-NODEBUG-NEXT: (i32.const 42) -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $5 (result i32) -;; CHECK-NODEBUG-NEXT: (local $0 (ref null $i32_=>_i32)) -;; CHECK-NODEBUG-NEXT: (local.set $0 -;; CHECK-NODEBUG-NEXT: (ref.func $2) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: (call_ref -;; CHECK-NODEBUG-NEXT: (i32.const 42) -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $6 (param $0 f64) (result (ref null $none_=>_eqref)) -;; CHECK-NODEBUG-NEXT: (ref.null $none_=>_eqref) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $7 -;; CHECK-NODEBUG-NEXT: (local $0 i32) -;; CHECK-NODEBUG-NEXT: (local $1 f64) -;; CHECK-NODEBUG-NEXT: (local $2 (ref null $none_=>_anyref)) -;; CHECK-NODEBUG-NEXT: (nop) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $8 -;; CHECK-NODEBUG-NEXT: (local $0 (i32 (ref null $none_=>_anyref_f32_anyref_f32) f64)) -;; CHECK-NODEBUG-NEXT: (local $1 (ref null $none_=>_anyref_f32_anyref_f32)) -;; CHECK-NODEBUG-NEXT: (local $2 i32) -;; CHECK-NODEBUG-NEXT: (local.set $0 -;; CHECK-NODEBUG-NEXT: (block $label$1 (result i32 (ref null $none_=>_anyref_f32_anyref_f32) f64) -;; CHECK-NODEBUG-NEXT: (unreachable) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: (drop -;; CHECK-NODEBUG-NEXT: (block (result i32) -;; CHECK-NODEBUG-NEXT: (local.set $2 -;; CHECK-NODEBUG-NEXT: (tuple.extract 0 -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: (drop -;; CHECK-NODEBUG-NEXT: (block (result (ref null $none_=>_anyref_f32_anyref_f32)) -;; CHECK-NODEBUG-NEXT: (local.set $1 -;; CHECK-NODEBUG-NEXT: (tuple.extract 1 -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: (drop -;; CHECK-NODEBUG-NEXT: (tuple.extract 2 -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: (local.get $2) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $9 -;; CHECK-NODEBUG-NEXT: (local $0 (ref null $none_=>_anyref_f32_anyref_f32)) -;; CHECK-NODEBUG-NEXT: (local $1 (ref null $none_=>_anyref_f32_anyref_f32)) -;; CHECK-NODEBUG-NEXT: (local $2 anyref) -;; CHECK-NODEBUG-NEXT: (local $3 anyref) -;; CHECK-NODEBUG-NEXT: (local $4 anyref) -;; CHECK-NODEBUG-NEXT: (local $5 funcref) -;; CHECK-NODEBUG-NEXT: (local $6 i32) -;; CHECK-NODEBUG-NEXT: (local $7 i64) -;; CHECK-NODEBUG-NEXT: (local $8 i64) -;; CHECK-NODEBUG-NEXT: (nop) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $10 -;; CHECK-NODEBUG-NEXT: (local $0 i32) -;; CHECK-NODEBUG-NEXT: (local $1 i64) -;; CHECK-NODEBUG-NEXT: (local $2 i64) -;; CHECK-NODEBUG-NEXT: (local $3 (ref null $none_=>_anyref_f32_anyref_f32)) -;; CHECK-NODEBUG-NEXT: (local $4 (ref null $none_=>_anyref_f32_anyref_f32)) -;; CHECK-NODEBUG-NEXT: (local $5 anyref) -;; CHECK-NODEBUG-NEXT: (local $6 anyref) -;; CHECK-NODEBUG-NEXT: (local $7 anyref) -;; CHECK-NODEBUG-NEXT: (local $8 funcref) -;; CHECK-NODEBUG-NEXT: (nop) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $11 (param $0 (ref null $none_=>_anyref_f32_anyref_f32)) -;; CHECK-NODEBUG-NEXT: (local $1 i32) -;; CHECK-NODEBUG-NEXT: (local $2 i64) -;; CHECK-NODEBUG-NEXT: (local $3 i64) -;; CHECK-NODEBUG-NEXT: (local $4 (ref null $none_=>_anyref_f32_anyref_f32)) -;; CHECK-NODEBUG-NEXT: (local $5 (ref null $none_=>_anyref_f32_anyref_f32)) -;; CHECK-NODEBUG-NEXT: (local $6 anyref) -;; CHECK-NODEBUG-NEXT: (local $7 anyref) -;; CHECK-NODEBUG-NEXT: (local $8 anyref) -;; CHECK-NODEBUG-NEXT: (local $9 funcref) -;; CHECK-NODEBUG-NEXT: (nop) -;; CHECK-NODEBUG-NEXT: ) diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast index ddb974ed670..1520003a67f 100644 --- a/test/lit/wat-kitchen-sink.wast +++ b/test/lit/wat-kitchen-sink.wast @@ -1,110 +1,99 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: wasm-opt --new-wat-parser --hybrid -all %s -S -o - | filecheck %s +;; RUN: wasm-opt --new-wat-parser -all %s -S -o - | filecheck %s (module $parse ;; types - (rec - ;; CHECK: (rec - ;; CHECK-NEXT: (type $s0 (struct_subtype data)) - (type $s0 (sub (struct))) - ;; CHECK: (type $s1 (struct_subtype data)) - (type $s1 (struct (field))) - ) + ;; CHECK: (type $s0 (struct )) - (rec) + ;; CHECK: (type $void (func)) + (type $void (func)) + ;; CHECK: (type $many (func (param i32 i64 f32 f64) (result anyref (ref func)))) + (type $many (func (param $x i32) (param i64 f32) (param) (param $y f64) + (result anyref (ref func)))) - ;; CHECK: (type $s2 (struct_subtype (field i32) data)) + (type $s0 (struct)) + (type $s1 (struct (field))) + ;; CHECK: (type $s2 (struct (field i32))) (type $s2 (struct i32)) - ;; CHECK: (type $s3 (struct_subtype (field i64) data)) + ;; CHECK: (type $s3 (struct (field i64))) (type $s3 (struct (field i64))) - ;; CHECK: (type $s4 (struct_subtype (field $x f32) data)) + ;; CHECK: (type $s4 (struct (field $x f32))) (type $s4 (struct (field $x f32))) - ;; CHECK: (type $s5 (struct_subtype (field i32) (field i64) data)) + ;; CHECK: (type $s5 (struct (field i32) (field i64))) (type $s5 (struct i32 i64)) - ;; CHECK: (type $s6 (struct_subtype (field i64) (field f32) data)) + ;; CHECK: (type $s6 (struct (field i64) (field f32))) (type $s6 (struct (field i64 f32))) - ;; CHECK: (type $s7 (struct_subtype (field $x f32) (field $y f64) data)) + ;; CHECK: (type $s7 (struct (field $x f32) (field $y f64))) (type $s7 (struct (field $x f32) (field $y f64))) - ;; CHECK: (type $s8 (struct_subtype (field i32) (field i64) (field $z f32) (field f64) (field (mut i32)) data)) + ;; CHECK: (type $s8 (struct (field i32) (field i64) (field $z f32) (field f64) (field (mut i32)))) (type $s8 (struct i32 (field) i64 (field $z f32) (field f64 (mut i32)))) - ;; CHECK: (type $a0 (array_subtype i32 data)) + ;; CHECK: (type $a0 (array i32)) (type $a0 (array i32)) - ;; CHECK: (type $a1 (array_subtype i64 data)) + ;; CHECK: (type $a1 (array i64)) (type $a1 (array (field i64))) - ;; CHECK: (type $a2 (array_subtype (mut f32) data)) + ;; CHECK: (type $a2 (array (mut f32))) (type $a2 (array (mut f32))) - ;; CHECK: (type $a3 (array_subtype (mut f64) data)) + ;; CHECK: (type $a3 (array (mut f64))) (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 $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))))) - ;; globals (global $g1 (export "g1") (export "g1.1") (import "mod" "g1") i32) (global $g2 (import "mod" "g2") (mut i64)) (global (import "" "g3") (ref 0)) (global (import "mod" "") (ref null $many)) - (global i32 i32.const 0) - ;; CHECK: (import "mod" "g1" (global $g1 i32)) + ;; 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))) +) +;; CHECK: (import "mod" "g1" (global $g1 i32)) - ;; CHECK: (import "mod" "g2" (global $g2 (mut i64))) +;; CHECK: (import "mod" "g2" (global $g2 (mut i64))) - ;; CHECK: (import "" "g3" (global $gimport$0 (ref $s0))) +;; CHECK: (import "" "g3" (global $gimport$0 (ref $void))) - ;; CHECK: (import "mod" "" (global $gimport$1 (ref null $many))) +;; CHECK: (import "mod" "" (global $gimport$1 (ref null $many))) - ;; CHECK: (global $2 i32 (i32.const 0)) +;; CHECK: (import "mod" "s0" (global $s0 (mut (ref $s0)))) - ;; CHECK: (global $i32 i32 (i32.const 42)) - (global $i32 i32 i32.const 42) +;; CHECK: (import "mod" "s1" (global $s1 (mut (ref $s0)))) + +;; CHECK: (import "mod" "s2" (global $s2 (mut (ref $s2)))) + +;; CHECK: (import "mod" "s3" (global $s3 (mut (ref $s3)))) + +;; CHECK: (import "mod" "s4" (global $s4 (mut (ref $s4)))) + +;; CHECK: (import "mod" "s5" (global $s5 (mut (ref $s5)))) + +;; CHECK: (import "mod" "s6" (global $s6 (mut (ref $s6)))) + +;; CHECK: (import "mod" "s7" (global $s7 (mut (ref $s7)))) + +;; 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)))) - ;; 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)) diff --git a/test/typed-function-references.wast b/test/typed-function-references.wast new file mode 100644 index 00000000000..1057d44878c --- /dev/null +++ b/test/typed-function-references.wast @@ -0,0 +1,44 @@ +(module + ;; inline ref type in result + (type $_=>_eqref (func (result eqref))) + (type $f64_=>_ref_null<_->_eqref> (func (param f64) (result (ref null $_=>_eqref)))) + (type $=>eqref (func (result eqref))) + (type $=>anyref (func (result anyref))) + (type $mixed_results (func (result anyref f32 anyref f32))) + + (type $i32-i32 (func (param i32) (result i32))) + + (func $call-ref + (call_ref (ref.func $call-ref)) + ) + (func $return-call-ref + (return_call_ref (ref.func $call-ref)) + ) + (func $call-ref-more (param i32) (result i32) + (call_ref (i32.const 42) (ref.func $call-ref-more)) + ) + (func $call_from-param (param $f (ref $i32-i32)) (result i32) + (call_ref (i32.const 42) (local.get $f)) + ) + (func $call_from-param-null (param $f (ref null $i32-i32)) (result i32) + (call_ref (i32.const 42) (local.get $f)) + ) + (func $call_from-local-null (result i32) + (local $f (ref null $i32-i32)) + (local.set $f (ref.func $call-ref-more)) + (call_ref (i32.const 42) (local.get $f)) + ) + (func $ref-in-sig (param $0 f64) (result (ref null $=>eqref)) + (ref.null $=>eqref) + ) + (func $type-only-in-tuple-local + (local $x (i32 (ref null $=>anyref) f64)) + ) + (func $type-only-in-tuple-block + (drop + (block (result i32 (ref null $mixed_results) f64) + (unreachable) + ) + ) + ) +) diff --git a/test/typed-function-references.wast.from-wast b/test/typed-function-references.wast.from-wast new file mode 100644 index 00000000000..cb9dd56716d --- /dev/null +++ b/test/typed-function-references.wast.from-wast @@ -0,0 +1,65 @@ +(module + (type $none_=>_none (func)) + (type $i32-i32 (func (param i32) (result i32))) + (type $=>eqref (func (result eqref))) + (type $ref|$i32-i32|_=>_i32 (func (param (ref $i32-i32)) (result i32))) + (type $ref?|$i32-i32|_=>_i32 (func (param (ref null $i32-i32)) (result i32))) + (type $none_=>_i32 (func (result i32))) + (type $f64_=>_ref_null<_->_eqref> (func (param f64) (result (ref null $=>eqref)))) + (type $=>anyref (func (result anyref))) + (type $none_=>_i32_ref?|$mixed_results|_f64 (func (result i32 (ref null $mixed_results) f64))) + (type $mixed_results (func (result anyref f32 anyref f32))) + (elem declare func $call-ref $call-ref-more) + (func $call-ref + (call_ref + (ref.func $call-ref) + ) + ) + (func $return-call-ref + (return_call_ref + (ref.func $call-ref) + ) + ) + (func $call-ref-more (param $0 i32) (result i32) + (call_ref + (i32.const 42) + (ref.func $call-ref-more) + ) + ) + (func $call_from-param (param $f (ref $i32-i32)) (result i32) + (call_ref + (i32.const 42) + (local.get $f) + ) + ) + (func $call_from-param-null (param $f (ref null $i32-i32)) (result i32) + (call_ref + (i32.const 42) + (local.get $f) + ) + ) + (func $call_from-local-null (result i32) + (local $f (ref null $i32-i32)) + (local.set $f + (ref.func $call-ref-more) + ) + (call_ref + (i32.const 42) + (local.get $f) + ) + ) + (func $ref-in-sig (param $0 f64) (result (ref null $=>eqref)) + (ref.null $=>eqref) + ) + (func $type-only-in-tuple-local + (local $x (i32 (ref null $=>anyref) f64)) + (nop) + ) + (func $type-only-in-tuple-block + (drop + (block $block (result i32 (ref null $mixed_results) f64) + (unreachable) + ) + ) + ) +) diff --git a/test/typed-function-references.wast.fromBinary b/test/typed-function-references.wast.fromBinary new file mode 100644 index 00000000000..e3839f33d09 --- /dev/null +++ b/test/typed-function-references.wast.fromBinary @@ -0,0 +1,96 @@ +(module + (type $none_=>_none (func)) + (type $i32-i32 (func (param i32) (result i32))) + (type $mixed_results (func (result anyref f32 anyref f32))) + (type $=>eqref (func (result eqref))) + (type $ref|$i32-i32|_=>_i32 (func (param (ref $i32-i32)) (result i32))) + (type $ref?|$i32-i32|_=>_i32 (func (param (ref null $i32-i32)) (result i32))) + (type $none_=>_i32 (func (result i32))) + (type $f64_=>_ref_null<_->_eqref> (func (param f64) (result (ref null $=>eqref)))) + (type $=>anyref (func (result anyref))) + (type $none_=>_i32_ref?|$mixed_results|_f64 (func (result i32 (ref null $mixed_results) f64))) + (elem declare func $call-ref $call-ref-more) + (func $call-ref + (call_ref + (ref.func $call-ref) + ) + ) + (func $return-call-ref + (return_call_ref + (ref.func $call-ref) + ) + ) + (func $call-ref-more (param $0 i32) (result i32) + (call_ref + (i32.const 42) + (ref.func $call-ref-more) + ) + ) + (func $call_from-param (param $f (ref $i32-i32)) (result i32) + (call_ref + (i32.const 42) + (local.get $f) + ) + ) + (func $call_from-param-null (param $f (ref null $i32-i32)) (result i32) + (call_ref + (i32.const 42) + (local.get $f) + ) + ) + (func $call_from-local-null (result i32) + (local $f (ref null $i32-i32)) + (local.set $f + (ref.func $call-ref-more) + ) + (call_ref + (i32.const 42) + (local.get $f) + ) + ) + (func $ref-in-sig (param $0 f64) (result (ref null $=>eqref)) + (ref.null $=>eqref) + ) + (func $type-only-in-tuple-local + (local $x i32) + (local $1 (ref null $=>anyref)) + (local $2 f64) + (nop) + ) + (func $type-only-in-tuple-block + (local $0 (i32 (ref null $mixed_results) f64)) + (local $1 (ref null $mixed_results)) + (local $2 i32) + (local.set $0 + (block $label$1 (result i32 (ref null $mixed_results) f64) + (unreachable) + ) + ) + (drop + (block (result i32) + (local.set $2 + (tuple.extract 0 + (local.get $0) + ) + ) + (drop + (block (result (ref null $mixed_results)) + (local.set $1 + (tuple.extract 1 + (local.get $0) + ) + ) + (drop + (tuple.extract 2 + (local.get $0) + ) + ) + (local.get $1) + ) + ) + (local.get $2) + ) + ) + ) +) + diff --git a/test/typed-function-references.wast.fromBinary.noDebugInfo b/test/typed-function-references.wast.fromBinary.noDebugInfo new file mode 100644 index 00000000000..cf462ffba73 --- /dev/null +++ b/test/typed-function-references.wast.fromBinary.noDebugInfo @@ -0,0 +1,96 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_anyref_f32_anyref_f32 (func (result anyref f32 anyref f32))) + (type $none_=>_eqref (func (result eqref))) + (type $ref|i32_->_i32|_=>_i32 (func (param (ref $i32_=>_i32)) (result i32))) + (type $ref?|i32_->_i32|_=>_i32 (func (param (ref null $i32_=>_i32)) (result i32))) + (type $none_=>_i32 (func (result i32))) + (type $f64_=>_ref?|none_->_eqref| (func (param f64) (result (ref null $none_=>_eqref)))) + (type $none_=>_anyref (func (result anyref))) + (type $none_=>_i32_ref?|none_->_anyref_f32_anyref_f32|_f64 (func (result i32 (ref null $none_=>_anyref_f32_anyref_f32) f64))) + (elem declare func $0 $2) + (func $0 + (call_ref + (ref.func $0) + ) + ) + (func $1 + (return_call_ref + (ref.func $0) + ) + ) + (func $2 (param $0 i32) (result i32) + (call_ref + (i32.const 42) + (ref.func $2) + ) + ) + (func $3 (param $0 (ref $i32_=>_i32)) (result i32) + (call_ref + (i32.const 42) + (local.get $0) + ) + ) + (func $4 (param $0 (ref null $i32_=>_i32)) (result i32) + (call_ref + (i32.const 42) + (local.get $0) + ) + ) + (func $5 (result i32) + (local $0 (ref null $i32_=>_i32)) + (local.set $0 + (ref.func $2) + ) + (call_ref + (i32.const 42) + (local.get $0) + ) + ) + (func $6 (param $0 f64) (result (ref null $none_=>_eqref)) + (ref.null $none_=>_eqref) + ) + (func $7 + (local $0 i32) + (local $1 (ref null $none_=>_anyref)) + (local $2 f64) + (nop) + ) + (func $8 + (local $0 (i32 (ref null $none_=>_anyref_f32_anyref_f32) f64)) + (local $1 (ref null $none_=>_anyref_f32_anyref_f32)) + (local $2 i32) + (local.set $0 + (block $label$1 (result i32 (ref null $none_=>_anyref_f32_anyref_f32) f64) + (unreachable) + ) + ) + (drop + (block (result i32) + (local.set $2 + (tuple.extract 0 + (local.get $0) + ) + ) + (drop + (block (result (ref null $none_=>_anyref_f32_anyref_f32)) + (local.set $1 + (tuple.extract 1 + (local.get $0) + ) + ) + (drop + (tuple.extract 2 + (local.get $0) + ) + ) + (local.get $1) + ) + ) + (local.get $2) + ) + ) + ) +) +