diff --git a/lib/Runtime/Library/WabtInterface.cpp b/lib/Runtime/Library/WabtInterface.cpp index a3c8b577ae7..e79f94e9664 100644 --- a/lib/Runtime/Library/WabtInterface.cpp +++ b/lib/Runtime/Library/WabtInterface.cpp @@ -35,7 +35,7 @@ char16* NarrowStringToWide(Context* ctx, const char* src, const size_t* srcSize return dst; } -static PropertyId propertyMap[ChakraWabt::PropertyIds::COUNT] = { +static PropertyId propertyMap[] = { Js::PropertyIds::as, Js::PropertyIds::action, Js::PropertyIds::args, @@ -53,6 +53,7 @@ static PropertyId propertyMap[ChakraWabt::PropertyIds::COUNT] = { bool SetProperty(Js::Var obj, PropertyId id, Js::Var value, void* user_data) { + CompileAssert((sizeof(propertyMap)/sizeof(PropertyId)) == ChakraWabt::PropertyIds::COUNT); Context* ctx = (Context*)user_data; Assert(id < ChakraWabt::PropertyIds::COUNT); return !!JavascriptOperators::OP_SetProperty(obj, propertyMap[id], value, ctx->scriptContext); @@ -92,7 +93,7 @@ Js::Var StringToVar(const char* src, uint length, void* user_data) return JavascriptString::NewCopyBuffer(buf, (charcount_t)bufSize, ctx->scriptContext); } -Js::Var CreateBuffer(const char* buf, uint size, void* user_data) +Js::Var CreateBuffer(const uint8* buf, uint size, void* user_data) { Context* ctx = (Context*)user_data; ArrayBuffer* arrayBuffer = ctx->scriptContext->GetLibrary()->CreateArrayBuffer(size); diff --git a/lib/WasmReader/WasmBinaryReader.cpp b/lib/WasmReader/WasmBinaryReader.cpp index e130b33f310..844dc5f289d 100644 --- a/lib/WasmReader/WasmBinaryReader.cpp +++ b/lib/WasmReader/WasmBinaryReader.cpp @@ -649,8 +649,6 @@ void WasmBinaryReader::ReadSignatureTypeSection() // signatures table for (uint32 i = 0; i < numTypes; i++) { - TRACE_WASM_DECODER(_u("Signature #%u"), i); - WasmSignature* sig = m_module->GetSignature(i); sig->SetSignatureId(i); int8 form = ReadConst(); @@ -684,6 +682,14 @@ void WasmBinaryReader::ReadSignatureTypeSection() sig->SetResultType(type); } sig->FinalizeSignature(); +#ifdef ENABLE_DEBUG_CONFIG_OPTIONS + if (DO_WASM_TRACE_DECODER) + { + Output::Print(_u("Signature #%u: "), i); + sig->Dump(); + Output::Print(_u("\n")); + } +#endif } } diff --git a/lib/wabt/.gitignore b/lib/wabt/.gitignore index b9725634c17..26e2e218dc4 100644 --- a/lib/wabt/.gitignore +++ b/lib/wabt/.gitignore @@ -1,8 +1,10 @@ -.gclient_entries +/bin /out -/third_party/gecko-dev* -/third_party/v8/depot_tools /fuzz-out /emscripten *.pyc -/built + +.gitmodules +/test +/tests +/third_party \ No newline at end of file diff --git a/lib/wabt/CMakeLists.txt b/lib/wabt/CMakeLists.txt index 7ada506a155..ed92b85a658 100644 --- a/lib/wabt/CMakeLists.txt +++ b/lib/wabt/CMakeLists.txt @@ -30,6 +30,10 @@ check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF) check_symbol_exists(sysconf "unistd.h" HAVE_SYSCONF) check_symbol_exists(strcasecmp "strings.h" HAVE_STRCASECMP) +if (WIN32) + check_symbol_exists(ENABLE_VIRTUAL_TERMINAL_PROCESSING "windows.h" HAVE_WIN32_VT100) +endif () + include(CheckTypeSize) check_type_size(ssize_t SSIZE_T) check_type_size(size_t SIZEOF_SIZE_T) @@ -67,7 +71,7 @@ if (COMPILER_IS_CLANG) add_definitions(-fcolor-diagnostics) endif () -set(AST_PARSER_GEN_C src/prebuilt/wast-parser-gen.cc) + include_directories(src/prebuilt) if (COMPILER_IS_CLANG OR COMPILER_IS_GNU) @@ -81,46 +85,51 @@ if (COMPILER_IS_CLANG OR COMPILER_IS_GNU) endif () set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${WABT_SOURCE_DIR}/cmake) -set(AST_LEXER_GEN_C src/prebuilt/wast-lexer-gen.cc) +set(WAST_LEXER_GEN_CC src/prebuilt/wast-lexer-gen.cc) add_custom_target(everything) add_library(libwabt OBJECT - ${AST_LEXER_GEN_C} - ${AST_PARSER_GEN_C} - src/apply-names.cc - src/binary-error-handler.cc - src/binary-reader-ir.cc - src/binary-reader-logging.cc - src/binary-reader-objdump.cc - src/binary-reader-opcnt.cc + src/opcode.cc + src/error-handler.cc + src/hash-util.cc + src/string-view.cc + src/ir.cc + src/expr-visitor.cc + src/lexer-source.cc + src/lexer-source-line-finder.cc + src/wast-parser-lexer-shared.cc + ${WAST_LEXER_GEN_CC} + src/wast-parser.cc + src/type-checker.cc + src/validator.cc + src/binary-reader.cc - src/binary-writer-spec.cc + src/binary-reader-logging.cc src/binary-writer.cc - src/binary.cc + src/binary-writer-spec.cc + src/binary-reader-ir.cc src/binding-hash.cc + src/wat-writer.cc + src/interpreter.cc + src/binary-reader-interpreter.cc + src/apply-names.cc + src/generate-names.cc + src/resolve-names.cc + + src/binary.cc + src/color.cc src/common.cc src/config.cc - src/emscripten-helpers.cc - src/expr-visitor.cc - src/generate-names.cc - src/hash-util.cc - src/ir.cc - src/lexer-source-line-finder.cc - src/lexer-source.cc + src/feature.cc src/literal.cc - src/opcode.cc src/option-parser.cc - src/resolve-names.cc - src/source-error-handler.cc src/stream.cc - src/string-view.cc - src/type-checker.cc + src/tracing.cc src/utf8.cc - src/validator.cc - src/wast-parser-lexer-shared.cc - src/wat-writer.cc src/writer.cc chakra/wabtapi.cc + + ) diff --git a/lib/wabt/README.md b/lib/wabt/README.md index 7ee00f0ebe7..2d6cd2b106b 100644 --- a/lib/wabt/README.md +++ b/lib/wabt/README.md @@ -2,46 +2,56 @@ # WABT: The WebAssembly Binary Toolkit -WABT (we pronounce it "wabbit") is suite of tools for WebAssembly, including: +WABT (we pronounce it "wabbit") is a suite of tools for WebAssembly, including: - - **wast2wasm**: translate from [s-expressions](https://github.com/WebAssembly/spec) to the WebAssembly [binary-encoding](https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md) - - **wasm2wast**: the inverse of wast2wasm, translate from the binary encoding back to an s-expression source file (also known as a .wast) + - **wast2wasm**: translate from [WebAssembly text format](http://webassembly.github.io/spec/text/index.html) to the [WebAssembly binary format](http://webassembly.github.io/spec/binary/index.html) + - **wasm2wast**: the inverse of wast2wasm, translate from the binary format back to the text format (also known as a .wast) + - **wasm-objdump**: print information about a wasm binary. Similiar to objdump. - **wasm-interp**: decode and run a WebAssembly binary file using a stack-based interpreter - **wast-desugar**: parse .wast text form as supported by the spec interpreter (s-expressions, flat syntax, or mixed) and print "canonical" flat format + - **wasm-link**: simple linker for merging multiple wasm files. These tools are intended for use in (or for development of) toolchains or other systems that want to manipulate WebAssembly files. Unlike the WebAssembly spec interpreter (which is written to be as simple, declarative and "speccy" as -possible), they are written in C (possibly C++ in the future) and designed for -easier integration into other systems. Unlike -[Binaryen](https://github.com/WebAssembly/binaryen) these tools do not aim to -provide an optimization platform or a higher-level compiler target; instead -they aim for full fidelity and compliance with the spec (e.g. 1:1 round-trips -with no changes to instructions). +possible), they are written in C/C++ and designed for easier integration into +other systems. Unlike [Binaryen](https://github.com/WebAssembly/binaryen) these +tools do not aim to provide an optimization platform or a higher-level compiler +target; instead they aim for full fidelity and compliance with the spec (e.g. +1:1 round-trips with no changes to instructions). + +## Online Demos + +Wabt has been compiled to JavaScript via emscripten. Some of the functionality is available in the following demos: + +- [index](https://cdn.rawgit.com/WebAssembly/wabt/013802ca01035365e2459c70f0508481393ac075/demo/index.html) +- [wast2wasm](https://cdn.rawgit.com/WebAssembly/wabt/013802ca01035365e2459c70f0508481393ac075/demo/wast2wasm/) +- [wasm2wast](https://cdn.rawgit.com/WebAssembly/wabt/013802ca01035365e2459c70f0508481393ac075/demo/wasm2wast/) ## Cloning Clone as normal, but don't forget to get the submodules as well: -``` +```console $ git clone --recursive https://github.com/WebAssembly/wabt $ cd wabt ``` This will fetch the testsuite and gtest repos, which are needed for some tests. -## Building +## Building (macOS and Linux) You'll need [CMake](https://cmake.org). If you just run `make`, it will run CMake for you, and put the result in `out/clang/Debug/` by default: -``` +> Note: If you are on macOS, you will need to use CMake version 3.2 or higher + +```console $ make ``` This will build the default version of the tools: a debug build using the Clang -compiler. It will also create a symlinks to the built binaries in the `out/` -directory. +compiler. There are many make targets available for other configurations as well. They are generated from every combination of a compiler, build type and @@ -49,43 +59,81 @@ configuration. - compilers: `gcc`, `clang`, `gcc-i686`, `gcc-fuzz` - build types: `debug`, `release` - - configurations: empty, `asan`, `msan`, `lsan`, `ubsan`, `no-re2c-bison`, + - configurations: empty, `asan`, `msan`, `lsan`, `ubsan`, `no-re2c`, `no-tests` They are combined with dashes, for example: -``` +```console $ make clang-debug $ make gcc-i686-release $ make clang-debug-lsan -$ make gcc-debug-no-re2c-bison +$ make gcc-debug-no-re2c ``` You can also run CMake yourself, the normal way: -``` +```console $ mkdir build $ cd build $ cmake .. ... ``` -If you make changes to `src/ast-parser.y`, you'll need to install Bison. -Before you upload your PR, please run `make update-bison` to update the -prebuilt C sources in `src/prebuilt/`. +## Building (Windows) + +You'll need [CMake](https://cmake.org). You'll also need +[Visual Studio](https://www.visualstudio.com/) (2015 or newer) or +[MinGW](http://www.mingw.org/). + +You can run CMake from the command prompt, or use the CMake GUI tool. See +[Running CMake](https://cmake.org/runningcmake/) for more information. + +When running from the commandline, create a new directory for the build +artifacts, then run cmake from this directory: + +```console +> cd [build dir] +> cmake [wabt project root] -DCMAKE_BUILD_TYPE=[config] -DCMAKE_INSTALL_PREFIX=[install directory] -G [generator] +``` + +The `[config]` parameter should be a CMake build type, typically `DEBUG` or `RELEASE`. + +The `[generator]` parameter should be the type of project you want to generate, +for example `"Visual Studio 14 2015"`. You can see the list of available +generators by running `cmake --help`. + +To build the project, you can use Visual Studio, or you can tell CMake to do it: + +```console +> cmake --build [wabt project root] --config [config] --target install +``` + +This will build and install to the installation directory you provided above. + +So, for example, if you want to build the debug configuration on Visual Studio 2015: + +```console +> mkdir build +> cd build +> cmake .. -DCMAKE_BUILD_TYPE=DEBUG -DCMAKE_INSTALL_PREFIX=..\bin -G "Visual Studio 14 2015" +> cmake --build .. --config DEBUG --target install +``` + +## Changing the lexer -If you make changes to `src/ast-lexer.c`, you'll need to install +If you make changes to `src/wast-lexer.cc`, you'll need to install [re2c](http://re2c.org). Before you upload your PR, please run `make update-re2c` to update the prebuilt C sources in `src/prebuilt/`. -CMake will detect if you don't have re2c or Bison installed and use the -prebuilt source files instead. +CMake will detect if you don't have re2c installed and use the prebuilt source +files instead. ## Running wast2wasm Some examples: -``` +```sh # parse and typecheck test.wast $ out/wast2wasm test.wast @@ -103,17 +151,17 @@ $ out/wast2wasm spec-test.wast --spec -o spec-test.json You can use `-h` to get additional help: -``` +```console $ out/wast2wasm -h ``` -Or try the [online demo](https://cdn.rawgit.com/WebAssembly/wabt/e528a622caa77702209bf0c3654ca78456c41a52/demo/index.html). +Or try the [online demo](https://cdn.rawgit.com/WebAssembly/wabt/013802ca01035365e2459c70f0508481393ac075/demo/wast2wasm/). ## Running wasm2wast Some examples: -``` +```sh # parse binary file test.wasm and write s-expression file test.wast $ out/wasm2wast test.wasm -o test.wast @@ -123,15 +171,17 @@ $ out/wasm2wast test.wasm -o test.wast You can use `-h` to get additional help: -``` +```console $ out/wasm2wast -h ``` +Or try the [online demo](https://cdn.rawgit.com/WebAssembly/wabt/013802ca01035365e2459c70f0508481393ac075/demo/wasm2wast/). + ## Running wasm-interp Some examples: -``` +```sh # parse binary file test.wasm, and type-check it $ out/wasm-interp test.wasm @@ -152,188 +202,28 @@ $ out/wasm-interp test.wasm -V 100 --run-all-exports As a convenience, you can use `test/run-interp.py` to convert a .wast file to binary first, then run it in the interpreter: -``` +```console $ test/run-interp.py --spec spec-test.wast 20/20 tests.passed. ``` You can use `-h` to get additional help: -``` +```console $ out/wasm-interp -h $ out/run-interp.py -h ``` ## Running the test suite -To run all the tests with default configuration: - -``` -$ make test -``` - -Every make target has a matching `test-*` target. - -``` -$ make gcc-debug-asan -$ make test-gcc-debug-asan -$ make clang-release -$ make test-clang-release -... -``` - -You can also run the Python test runner script directly: - -``` -$ test/run-tests.py -``` - -To run a subset of the tests, use a glob-like syntax: - -``` -$ test/run-tests.py const -v -+ dump/const.txt (0.002s) -+ parse/assert/bad-assertreturn-non-const.txt (0.003s) -+ parse/expr/bad-const-i32-overflow.txt (0.002s) -+ parse/expr/bad-const-f32-trailing.txt (0.004s) -+ parse/expr/bad-const-i32-garbage.txt (0.005s) -+ parse/expr/bad-const-i32-trailing.txt (0.003s) -+ parse/expr/bad-const-i32-underflow.txt (0.003s) -+ parse/expr/bad-const-i64-overflow.txt (0.002s) -+ parse/expr/bad-const-i32-just-negative-sign.txt (0.004s) -+ parse/expr/const.txt (0.002s) -[+10|-0|%100] (0.11s) - -$ test/run-tests.py expr*const*i32 -+ parse/expr/bad-const-i32-just-negative-sign.txt (0.002s) -+ parse/expr/bad-const-i32-overflow.txt (0.003s) -+ parse/expr/bad-const-i32-underflow.txt (0.002s) -+ parse/expr/bad-const-i32-garbage.txt (0.004s) -+ parse/expr/bad-const-i32-trailing.txt (0.002s) -[+5|-0|%100] (0.11s) -``` - -When tests are broken, they will give you the expected stdout/stderr as a diff: - -``` -$ -$ test/run-tests.py interp/binary -- interp/binary.txt - STDOUT MISMATCH: - --- expected - +++ actual - @@ -1,4 +1,4 @@ - -i32_add() => i32:3 - +i32_add() => i32:4294967295 - i32_sub() => i32:16 - i32_mul() => i32:21 - i32_div_s() => i32:4294967294 - -**** FAILED ****************************************************************** -- interp/binary.txt -[+0|-1|%100] (0.13s) -``` - -## Writing New Tests - -Tests must be placed in the test/ directory, and must have the extension -`.txt`. The directory structure is mostly for convenience, so for example you -can type `test/run-tests.py interp` to run all the interpreter tests. -There's otherwise no logic attached to a test being in a given directory. - -That being said, try to make the test names self explanatory, and try to test -only one thing. Also make sure that tests that are expected to fail start with -`bad-`. - -The test format is straightforward: - -``` -;;; KEY1: VALUE1A VALUE1B... -;;; KEY2: VALUE2A VALUE2B... -(input (to) - (the executable)) -(;; STDOUT ;;; -expected stdout -;;; STDOUT ;;) -(;; STDERR ;;; -expected stderr -;;; STDERR ;;) -``` - -The test runner will copy the input to a temporary file and pass it as an -argument to the executable (which by default is `out/wast2wasm`). - -The currently supported list of keys: - -- `TOOL`: a set of preconfigured keys, see below. -- `EXE`: the executable to run, defaults to out/wast2wasm -- `STDIN_FILE`: the file to use for STDIN instead of the contents of this file. -- `FLAGS`: additional flags to pass to the executable -- `ERROR`: the expected return value from the executable, defaults to 0 -- `SLOW`: if defined, this test's timeout is doubled. -- `SKIP`: if defined, this test is not run. You can use the value as a comment. -- `TODO`,`NOTE`: useful place to put additional info about the test. - -The currently supported list of tools: - -- `wast2wasm`: runs `wast2wasm` -- `run-roundtrip`: runs the `run-roundtrip.py` script. This does a roundtrip - conversion using `wast2wasm` and `wasm2wast`, making sure the .wasm results - are identical. -- `run-interp`: runs the `run-interp.py` script, running all exported functions -- `run-interp-spec`: runs the `run-interp.py` script with the `--spec` flag - -When you first write a test, it's easiest if you omit the expected stdout and -stderr. You can have the test harness fill it in for you automatically. First -let's write our test: - -``` -$ cat > test/my-awesome-test.txt << HERE -;;; TOOL: run-interp-spec -(module - (export "add2" 0) - (func (param i32) (result i32) - (i32.add (get_local 0) (i32.const 2)))) -(assert_return (invoke "add2" (i32.const 4)) (i32.const 6)) -(assert_return (invoke "add2" (i32.const -2)) (i32.const 0)) -HERE -``` - -If we run it, it will fail: - -``` -- my-awesome-test.txt - STDOUT MISMATCH: - --- expected - +++ actual - @@ -0,0 +1 @@ - +2/2 tests passed. - -**** FAILED ****************************************************************** -- my-awesome-test.txt -[+0|-1|%100] (0.03s) -``` - -We can rebase it automatically with the `-r` flag. Running the test again shows -that the expected stdout has been added: - -``` -$ test/run-tests.py my-awesome-test -r -[+1|-0|%100] (0.03s) -$ test/run-tests.py my-awesome-test -[+1|-0|%100] (0.03s) -$ tail -n 3 test/my-awesome-test.txt -(;; STDOUT ;;; -2/2 tests passed. -;;; STDOUT ;;) -``` +See [test/README.md](test/README.md). ## Sanitizers To build with the [LLVM sanitizers](https://github.com/google/sanitizers), append the sanitizer name to the target: -``` +```console $ make clang-debug-asan $ make clang-debug-msan $ make clang-debug-lsan @@ -350,13 +240,13 @@ finds undefined behavior (surprise!). Typically, you'll just want to run all the tests for a given sanitizer: -``` +```console $ make test-asan ``` You can also run the tests for a release build: -``` +```console $ make test-clang-release-asan ... ``` @@ -364,13 +254,13 @@ $ make test-clang-release-asan The Travis bots run all of these tests (and more). Before you land a change, you should run them too. One easy way is to use the `test-everything` target: -``` +```console $ make test-everything ``` To run everything the Travis bots do, you can use the following scripts: -``` +```console $ CC=gcc scripts/travis-build.sh $ CC=gcc scripts/travis-test.sh $ CC=clang scripts/travis-build.sh diff --git a/lib/wabt/chakra/wabtapi.cc b/lib/wabt/chakra/wabtapi.cc index 457c9dbe87b..4a4a25f9a7e 100644 --- a/lib/wabt/chakra/wabtapi.cc +++ b/lib/wabt/chakra/wabtapi.cc @@ -11,21 +11,23 @@ #include "wast-lexer.h" #include "resolve-names.h" #include "binary-writer.h" -#include "source-error-handler.h" +#include "error-handler.h" #include "ir.h" +#include "cast.h" #pragma warning(pop) using namespace wabt; using namespace ChakraWabt; -class MySourceErrorHandler : public SourceErrorHandler +class MyErrorHandler : public ErrorHandler { public: + MyErrorHandler() : ErrorHandler(Location::Type::Text) {} - virtual bool OnError(const Location* loc, const std::string& error, const std::string& source_line, size_t source_line_column_offset) override + virtual bool OnError(const Location& loc, const std::string& error, const std::string& source_line, size_t source_line_column_offset) override { - int colStart = loc->first_column - 1 - (int)source_line_column_offset; - int sourceErrorLength = (loc->last_column - loc->first_column) - 2; + int colStart = loc.first_column - 1 - (int)source_line_column_offset; + int sourceErrorLength = (loc.last_column - loc.first_column) - 2; if (sourceErrorLength < 0) { // -2 probably overflowed @@ -33,16 +35,15 @@ class MySourceErrorHandler : public SourceErrorHandler } char buf[4096]; wabt_snprintf(buf, 4096, "Wast Parsing error:%u:%u:\n%s\n%s\n%*s^%*s^", - loc->line, - loc->first_column, - error.c_str(), - source_line.c_str(), - colStart, "", - sourceErrorLength, ""); + loc.line, + loc.first_column, + error.c_str(), + source_line.c_str(), + colStart, "", + sourceErrorLength, ""); throw Error(buf); } - virtual size_t source_line_max_length() const override { return 256; @@ -95,15 +96,15 @@ void write_int64(Context* ctx, Js::Var obj, PropertyId id, int64 value) set_property(ctx, obj, id, line, "Unable to write number"); } -void write_string(Context* ctx, Js::Var obj, PropertyId id, StringSlice src) +void write_string(Context* ctx, Js::Var obj, PropertyId id, const char* src, size_t length = 0xFFFFFFFF) { - Js::Var str = ctx->spec->stringToVar(src.start, TruncSizeT(src.length), ctx->user_data); + Js::Var str = ctx->spec->stringToVar(src, TruncSizeT(length == 0xFFFFFFFF ? strlen(src) : length), ctx->user_data); set_property(ctx, obj, id, str, "Unable to write string"); } -void write_string(Context* ctx, Js::Var obj, PropertyId id, const char* src) +void write_string(Context* ctx, Js::Var obj, PropertyId id, std::string src) { - write_string(ctx, obj, id, {src, strlen(src)}); + write_string(ctx, obj, id, src.c_str(), src.size()); } void write_location(Context* ctx, Js::Var obj, const Location* loc) @@ -113,14 +114,14 @@ void write_location(Context* ctx, Js::Var obj, const Location* loc) void write_var(Context* ctx, Js::Var obj, PropertyId id, const Var* var) { - if (var->type == VarType::Index) + if (var->is_index()) { - write_int64(ctx, obj, id, var->index); + write_int64(ctx, obj, id, var->index()); } else { - assert(var->type == VarType::Name); - write_string(ctx, obj, id, var->name); + assert(var->is_name()); + write_string(ctx, obj, id, var->name()); } } @@ -132,8 +133,6 @@ void write_command_type(Context* ctx, CommandType type, Js::Var cmdObj) "register", "assert_malformed", "assert_invalid", - nullptr, /* ASSERT_INVALID_NON_BINARY, this command will never be - written */ "assert_unlinkable", "assert_uninstantiable", "assert_return", @@ -142,7 +141,7 @@ void write_command_type(Context* ctx, CommandType type, Js::Var cmdObj) "assert_trap", "assert_exhaustion", }; - WABT_STATIC_ASSERT(sizeof(s_command_names)/sizeof(char*) == (int)CommandType::Last + 1); + WABT_STATIC_ASSERT(sizeof(s_command_names) / sizeof(char*) == (int)CommandType::Last + 1); uint i = (uint)type; if (i > (uint)CommandType::Last) { @@ -199,10 +198,7 @@ void write_const_vector(Context* ctx, Js::Var obj, PropertyId id, const ConstVec Js::Var create_type_object(Context* ctx, Type type) { Js::Var typeObj = ctx->spec->createObject(ctx->user_data); - StringSlice str; - str.start = get_type_name(type); - str.length = strlen(str.start); - write_string(ctx, typeObj, PropertyIds::type, str); + write_string(ctx, typeObj, PropertyIds::type, GetTypeName(type)); return typeObj; } @@ -247,28 +243,20 @@ void write_action(Context* ctx, Js::Var obj, const Action* action) Js::Var actionObj = ctx->spec->createObject(ctx->user_data); set_property(ctx, obj, PropertyIds::action, actionObj, "Unable to set action"); - if (action->type == ActionType::Invoke) - { - write_string(ctx, actionObj, PropertyIds::type, "invoke"); - } - else - { - assert(action->type == ActionType::Get); - write_string(ctx, actionObj, PropertyIds::type, "get"); - } - - if (action->module_var.type != VarType::Index) + if (action->module_var.is_name()) { write_var(ctx, actionObj, PropertyIds::module, &action->module_var); } if (action->type == ActionType::Invoke) { + write_string(ctx, actionObj, PropertyIds::type, "invoke"); write_string(ctx, actionObj, PropertyIds::field, action->name); write_const_vector(ctx, actionObj, PropertyIds::args, &action->invoke->args); - } else { + assert(action->type == ActionType::Get); + write_string(ctx, actionObj, PropertyIds::type, "get"); write_string(ctx, actionObj, PropertyIds::field, action->name); } } @@ -281,13 +269,13 @@ Js::Var create_module(Context* ctx, Module* module) } MemoryWriter writer; MemoryWriterContext context{ &writer, ctx }; - WriteBinaryOptions s_write_binary_options = { nullptr, true, false, false }; - Result result = write_binary_module(&writer, module, &s_write_binary_options); - if (!WABT_SUCCEEDED(result)) + WriteBinaryOptions s_write_binary_options; + Result result = WriteBinaryModule(&writer, module, &s_write_binary_options); + if (!Succeeded(result)) { throw Error("Error while writing module"); } - const char* data = (const char*)writer.output_buffer().data.data(); + const uint8_t* data = writer.output_buffer().data.data(); const size_t size = writer.output_buffer().size(); return ctx->createBuffer(data, TruncSizeT(size), ctx->user_data); } @@ -298,7 +286,7 @@ void write_module(Context* ctx, Js::Var obj, Module* module) set_property(ctx, obj, PropertyIds::buffer, buffer, "Unable to set module"); } -static void write_invalid_module(Context* ctx, Js::Var obj, const ScriptModule* module, StringSlice text) +static void write_invalid_module(Context* ctx, Js::Var obj, const ScriptModule* module, std::string text) { write_location(ctx, obj, &module->GetLocation()); write_string(ctx, obj, PropertyIds::text, text); @@ -309,13 +297,13 @@ static void write_invalid_module(Context* ctx, Js::Var obj, const ScriptModule* break; case ScriptModule::Type::Binary: { - Js::Var buffer = ctx->createBuffer(module->binary.data, TruncSizeT(module->binary.size), ctx->user_data); + Js::Var buffer = ctx->createBuffer(module->binary.data.data(), TruncSizeT(module->binary.data.size()), ctx->user_data); set_property(ctx, obj, PropertyIds::buffer, buffer, "Unable to set invalid module"); break; } case ScriptModule::Type::Quoted: { - Js::Var buffer = ctx->createBuffer(module->quoted.data, TruncSizeT(module->quoted.size), ctx->user_data); + Js::Var buffer = ctx->createBuffer(module->quoted.data.data(), TruncSizeT(module->quoted.data.size()), ctx->user_data); set_property(ctx, obj, PropertyIds::buffer, buffer, "Unable to set invalid module"); break; } @@ -325,26 +313,29 @@ static void write_invalid_module(Context* ctx, Js::Var obj, const ScriptModule* } } -Js::Var write_commands(Context* ctx, Script* script) { +Js::Var write_commands(Context* ctx, Script* script) +{ Js::Var resultObj = ctx->spec->createObject(ctx->user_data); Js::Var commandsArr = ctx->spec->createArray(ctx->user_data); set_property(ctx, resultObj, PropertyIds::commands, commandsArr, "Unable to set commands"); - wabt::Index last_module_index = (wabt::Index)-1; - for (wabt::Index i = 0; i < script->commands.size(); ++i) { + wabt::Index last_module_index = (wabt::Index) - 1; + for (wabt::Index i = 0; i < script->commands.size(); ++i) + { const Command* command = script->commands[i].get(); - if (command->type == CommandType::AssertInvalidNonBinary) - continue; Js::Var cmdObj = ctx->spec->createObject(ctx->user_data); ctx->spec->push(commandsArr, cmdObj, ctx->user_data); write_command_type(ctx, command->type, cmdObj); - switch (command->type) { - case CommandType::Module: { - Module* module = command->module; + switch (command->type) + { + case CommandType::Module: + { + Module* module = cast(command)->module; write_location(ctx, cmdObj, &module->loc); - if (module->name.start) { + if (!module->name.empty()) + { write_string(ctx, cmdObj, PropertyIds::name, module->name); } write_module(ctx, cmdObj, module); @@ -353,73 +344,100 @@ Js::Var write_commands(Context* ctx, Script* script) { } case CommandType::Action: - write_location(ctx, cmdObj, &command->action->loc); - write_action(ctx, cmdObj, command->action); + { + const Action* action = cast(command)->action; + write_location(ctx, cmdObj, &action->loc); + write_action(ctx, cmdObj, action); break; - + } case CommandType::Register: - write_location(ctx, cmdObj, &command->register_.var.loc); - if (command->register_.var.type == VarType::Name) { - write_var(ctx, cmdObj, PropertyIds::name, &command->register_.var); - } else { + { + auto* register_command = cast(command); + write_location(ctx, cmdObj, ®ister_command->var.loc); + if (register_command->var.is_name()) + { + write_var(ctx, cmdObj, PropertyIds::name, ®ister_command->var); + } + else + { /* If we're not registering by name, then we should only be * registering the last module. */ WABT_USE(last_module_index); - assert(command->register_.var.index == last_module_index); + assert(register_command->var.index() == last_module_index); } - write_string(ctx, cmdObj, PropertyIds::as, command->register_.module_name); + write_string(ctx, cmdObj, PropertyIds::as, register_command->module_name); break; - + } case CommandType::AssertMalformed: - write_invalid_module(ctx, cmdObj, command->assert_malformed.module, - command->assert_malformed.text); + { + auto* assert_malformed_command = cast(command); + write_invalid_module(ctx, cmdObj, assert_malformed_command->module, + assert_malformed_command->text); break; - + } case CommandType::AssertInvalid: - write_invalid_module(ctx, cmdObj, command->assert_invalid.module, - command->assert_invalid.text); + { + auto* assert_invalid_command = cast(command); + write_invalid_module(ctx, cmdObj, assert_invalid_command->module, + assert_invalid_command->text); break; - + } case CommandType::AssertUnlinkable: - write_invalid_module(ctx, cmdObj, command->assert_unlinkable.module, - command->assert_unlinkable.text); + { + auto* assert_unlinkable_command = cast(command); + write_invalid_module(ctx, cmdObj, assert_unlinkable_command->module, + assert_unlinkable_command->text); break; - + } case CommandType::AssertUninstantiable: - write_invalid_module(ctx, cmdObj, command->assert_uninstantiable.module, - command->assert_uninstantiable.text); + { + auto* assert_uninstantiable_command = cast(command); + write_invalid_module(ctx, cmdObj, assert_uninstantiable_command->module, + assert_uninstantiable_command->text); break; - + } case CommandType::AssertReturn: - write_location(ctx, cmdObj, &command->assert_return.action->loc); - write_action(ctx, cmdObj, command->assert_return.action); - write_const_vector(ctx, cmdObj, PropertyIds::expected, command->assert_return.expected); + { + auto* assert_return_command = cast(command); + write_location(ctx, cmdObj, &assert_return_command->action->loc); + write_action(ctx, cmdObj, assert_return_command->action); + write_const_vector(ctx, cmdObj, PropertyIds::expected, assert_return_command->expected); break; - + } case CommandType::AssertReturnCanonicalNan: + { + auto* assert_return_canonical_nan_command = cast(command); + write_location(ctx, cmdObj, &assert_return_canonical_nan_command->action->loc); + write_action(ctx, cmdObj, assert_return_canonical_nan_command->action); + write_action_result_type(ctx, cmdObj, PropertyIds::expected, script, + assert_return_canonical_nan_command->action); + break; + } case CommandType::AssertReturnArithmeticNan: - WABT_STATIC_ASSERT(offsetof(Command, assert_return_canonical_nan) == offsetof(Command, assert_return_arithmetic_nan)); - write_location(ctx, cmdObj, &command->assert_return_canonical_nan.action->loc); - write_action(ctx, cmdObj, command->assert_return_canonical_nan.action); + { + auto* assert_return_arithmetic_nan_command = cast(command); + write_location(ctx, cmdObj, &assert_return_arithmetic_nan_command->action->loc); + write_action(ctx, cmdObj, assert_return_arithmetic_nan_command->action); write_action_result_type(ctx, cmdObj, PropertyIds::expected, script, - command->assert_return_canonical_nan.action); + assert_return_arithmetic_nan_command->action); break; - + } case CommandType::AssertTrap: - write_location(ctx, cmdObj, &command->assert_trap.action->loc); - write_action(ctx, cmdObj, command->assert_trap.action); - write_string(ctx, cmdObj, PropertyIds::text, command->assert_trap.text); + { + auto* assert_trap_command = cast(command); + write_location(ctx, cmdObj, &assert_trap_command->action->loc); + write_action(ctx, cmdObj, assert_trap_command->action); + write_string(ctx, cmdObj, PropertyIds::text, assert_trap_command->text); break; - + } case CommandType::AssertExhaustion: - write_location(ctx, cmdObj, &command->assert_trap.action->loc); - write_action(ctx, cmdObj, command->assert_trap.action); - break; - - case CommandType::AssertInvalidNonBinary: - assert(0); + { + auto* assert_exhaustion_command = cast(command); + write_location(ctx, cmdObj, &assert_exhaustion_command->action->loc); + write_action(ctx, cmdObj, assert_exhaustion_command->action); break; } + } } return resultObj; } @@ -447,18 +465,18 @@ Js::Var ChakraWabt::ConvertWast2Wasm(Context& ctx, char* buffer, uint bufferSize std::unique_ptr lexer = WastLexer::CreateBufferLexer("", buffer, (size_t)bufferSize); - MySourceErrorHandler s_error_handler; + MyErrorHandler s_error_handler; Script* script; - Result result = parse_wast(lexer.get(), &script, &s_error_handler); + Result result = ParseWast(lexer.get(), &script, &s_error_handler); AutoCleanScript autoCleanScript = { script }; - if (!WABT_SUCCEEDED(result)) + if (!Succeeded(result)) { throw Error("Invalid wast script"); } - result = resolve_names_script(lexer.get(), script, &s_error_handler); - if (!WABT_SUCCEEDED(result)) + result = ResolveNamesScript(lexer.get(), script, &s_error_handler); + if (!Succeeded(result)) { throw Error("Unable to resolve script's names"); } diff --git a/lib/wabt/chakra/wabtapi.h b/lib/wabt/chakra/wabtapi.h index bc3e367e723..7c86efca22b 100644 --- a/lib/wabt/chakra/wabtapi.h +++ b/lib/wabt/chakra/wabtapi.h @@ -60,7 +60,7 @@ namespace ChakraWabt PushFn push; }; - typedef Js::Var(*CreateBufferFn)(const char* start, uint size, void* user_data); + typedef Js::Var(*CreateBufferFn)(const unsigned char* start, uint size, void* user_data); typedef void*(*AllocatorFn)(uint size, void* user_data); struct Context { diff --git a/lib/wabt/src/apply-names.cc b/lib/wabt/src/apply-names.cc index b1c77299d0e..1616ea2d483 100644 --- a/lib/wabt/src/apply-names.cc +++ b/lib/wabt/src/apply-names.cc @@ -22,10 +22,11 @@ #include "expr-visitor.h" #include "ir.h" +#include "string-view.h" #define CHECK_RESULT(expr) \ do { \ - if (WABT_FAILED(expr)) \ + if (Failed(expr)) \ return Result::Error; \ } while (0) @@ -40,33 +41,39 @@ class NameApplier : public ExprVisitor::DelegateNop { Result VisitModule(Module* module); // Implementation of ExprVisitor::DelegateNop. - Result BeginBlockExpr(Expr*) override; - Result EndBlockExpr(Expr*) override; - Result OnBrExpr(Expr*) override; - Result OnBrIfExpr(Expr*) override; - Result OnBrTableExpr(Expr*) override; - Result OnCallExpr(Expr*) override; - Result OnCallIndirectExpr(Expr*) override; - Result OnGetGlobalExpr(Expr*) override; - Result OnGetLocalExpr(Expr*) override; - Result BeginIfExpr(Expr*) override; - Result EndIfExpr(Expr*) override; - Result BeginLoopExpr(Expr*) override; - Result EndLoopExpr(Expr*) override; - Result OnSetGlobalExpr(Expr*) override; - Result OnSetLocalExpr(Expr*) override; - Result OnTeeLocalExpr(Expr*) override; + Result BeginBlockExpr(BlockExpr*) override; + Result EndBlockExpr(BlockExpr*) override; + Result OnBrExpr(BrExpr*) override; + Result OnBrIfExpr(BrIfExpr*) override; + Result OnBrTableExpr(BrTableExpr*) override; + Result OnCallExpr(CallExpr*) override; + Result OnCallIndirectExpr(CallIndirectExpr*) override; + Result OnGetGlobalExpr(GetGlobalExpr*) override; + Result OnGetLocalExpr(GetLocalExpr*) override; + Result BeginIfExpr(IfExpr*) override; + Result EndIfExpr(IfExpr*) override; + Result BeginLoopExpr(LoopExpr*) override; + Result EndLoopExpr(LoopExpr*) override; + Result OnSetGlobalExpr(SetGlobalExpr*) override; + Result OnSetLocalExpr(SetLocalExpr*) override; + Result OnTeeLocalExpr(TeeLocalExpr*) override; + Result BeginTryExpr(TryExpr*) override; + Result EndTryExpr(TryExpr*) override; + Result OnCatchExpr(TryExpr*, Catch*) override; + Result OnThrowExpr(ThrowExpr*) override; + Result OnRethrowExpr(RethrowExpr*) override; private: - void PushLabel(Label* label); + void PushLabel(const std::string& label); void PopLabel(); - Label* FindLabelByVar(Var* var); - void UseNameForVar(StringSlice* name, Var* var); - Result UseNameForFuncTypeVar(Module* module, Var* var); - Result UseNameForFuncVar(Module* module, Var* var); - Result UseNameForGlobalVar(Module* module, Var* var); - Result UseNameForTableVar(Module* module, Var* var); - Result UseNameForMemoryVar(Module* module, Var* var); + string_view FindLabelByVar(Var* var); + void UseNameForVar(string_view name, Var* var); + Result UseNameForFuncTypeVar(Var* var); + Result UseNameForFuncVar(Var* var); + Result UseNameForGlobalVar(Var* var); + Result UseNameForTableVar(Var* var); + Result UseNameForMemoryVar(Var* var); + Result UseNameForExceptVar(Var* var); Result UseNameForParamAndLocalVar(Func* func, Var* var); Result VisitFunc(Index func_index, Func* func); Result VisitExport(Index export_index, Export* export_); @@ -79,12 +86,12 @@ class NameApplier : public ExprVisitor::DelegateNop { /* mapping from param index to its name, if any, for the current func */ std::vector param_index_to_name_; std::vector local_index_to_name_; - std::vector labels_; + std::vector labels_; }; NameApplier::NameApplier() : visitor_(this) {} -void NameApplier::PushLabel(Label* label) { +void NameApplier::PushLabel(const std::string& label) { labels_.push_back(label); } @@ -92,69 +99,76 @@ void NameApplier::PopLabel() { labels_.pop_back(); } -Label* NameApplier::FindLabelByVar(Var* var) { - if (var->type == VarType::Name) { +string_view NameApplier::FindLabelByVar(Var* var) { + if (var->is_name()) { for (int i = labels_.size() - 1; i >= 0; --i) { - Label* label = labels_[i]; - if (string_slices_are_equal(label, &var->name)) + const std::string& label = labels_[i]; + if (label == var->name()) return label; } - return nullptr; + return string_view(); } else { - if (var->index >= labels_.size()) - return nullptr; - return labels_[labels_.size() - 1 - var->index]; + if (var->index() >= labels_.size()) + return string_view(); + return labels_[labels_.size() - 1 - var->index()]; } } -void NameApplier::UseNameForVar(StringSlice* name, Var* var) { - if (var->type == VarType::Name) { - assert(string_slices_are_equal(name, &var->name)); +void NameApplier::UseNameForVar(string_view name, Var* var) { + if (var->is_name()) { + assert(name == var->name()); + return; } - if (name && name->start) { - var->type = VarType::Name; - var->name = dup_string_slice(*name); - } + if (!name.empty()) + var->set_name(name); } -Result NameApplier::UseNameForFuncTypeVar(Module* module, Var* var) { - FuncType* func_type = module->GetFuncType(*var); +Result NameApplier::UseNameForFuncTypeVar(Var* var) { + FuncType* func_type = module_->GetFuncType(*var); if (!func_type) return Result::Error; - UseNameForVar(&func_type->name, var); + UseNameForVar(func_type->name, var); return Result::Ok; } -Result NameApplier::UseNameForFuncVar(Module* module, Var* var) { - Func* func = module->GetFunc(*var); +Result NameApplier::UseNameForFuncVar(Var* var) { + Func* func = module_->GetFunc(*var); if (!func) return Result::Error; - UseNameForVar(&func->name, var); + UseNameForVar(func->name, var); return Result::Ok; } -Result NameApplier::UseNameForGlobalVar(Module* module, Var* var) { - Global* global = module->GetGlobal(*var); +Result NameApplier::UseNameForGlobalVar(Var* var) { + Global* global = module_->GetGlobal(*var); if (!global) return Result::Error; - UseNameForVar(&global->name, var); + UseNameForVar(global->name, var); return Result::Ok; } -Result NameApplier::UseNameForTableVar(Module* module, Var* var) { - Table* table = module->GetTable(*var); +Result NameApplier::UseNameForTableVar(Var* var) { + Table* table = module_->GetTable(*var); if (!table) return Result::Error; - UseNameForVar(&table->name, var); + UseNameForVar(table->name, var); return Result::Ok; } -Result NameApplier::UseNameForMemoryVar(Module* module, Var* var) { - Memory* memory = module->GetMemory(*var); +Result NameApplier::UseNameForMemoryVar(Var* var) { + Memory* memory = module_->GetMemory(*var); if (!memory) return Result::Error; - UseNameForVar(&memory->name, var); + UseNameForVar(memory->name, var); + return Result::Ok; +} + +Result NameApplier::UseNameForExceptVar(Var* var) { + Exception* except = module_->GetExcept(*var); + if (!except) + return Result::Error; + UseNameForVar(except->name, var); return Result::Ok; } @@ -176,112 +190,138 @@ Result NameApplier::UseNameForParamAndLocalVar(Func* func, Var* var) { name = &local_index_to_name_[local_index]; } - if (var->type == VarType::Name) { - assert(*name == string_slice_to_string(var->name)); + if (var->is_name()) { + assert(*name == var->name()); return Result::Ok; } if (!name->empty()) { - var->type = VarType::Name; - var->name = dup_string_slice(string_to_string_slice(*name)); - return var->name.start ? Result::Ok : Result::Error; + var->set_name(*name); } return Result::Ok; } -Result NameApplier::BeginBlockExpr(Expr* expr) { - PushLabel(&expr->block->label); +Result NameApplier::BeginBlockExpr(BlockExpr* expr) { + PushLabel(expr->block->label); return Result::Ok; } -Result NameApplier::EndBlockExpr(Expr* expr) { +Result NameApplier::EndBlockExpr(BlockExpr* expr) { PopLabel(); return Result::Ok; } -Result NameApplier::BeginLoopExpr(Expr* expr) { - PushLabel(&expr->loop->label); +Result NameApplier::BeginLoopExpr(LoopExpr* expr) { + PushLabel(expr->block->label); return Result::Ok; } -Result NameApplier::EndLoopExpr(Expr* expr) { +Result NameApplier::EndLoopExpr(LoopExpr* expr) { PopLabel(); return Result::Ok; } -Result NameApplier::OnBrExpr(Expr* expr) { - Label* label = FindLabelByVar(&expr->br.var); - UseNameForVar(label, &expr->br.var); +Result NameApplier::OnBrExpr(BrExpr* expr) { + string_view label = FindLabelByVar(&expr->var); + UseNameForVar(label, &expr->var); return Result::Ok; } -Result NameApplier::OnBrIfExpr(Expr* expr) { - Label* label = FindLabelByVar(&expr->br_if.var); - UseNameForVar(label, &expr->br_if.var); +Result NameApplier::OnBrIfExpr(BrIfExpr* expr) { + string_view label = FindLabelByVar(&expr->var); + UseNameForVar(label, &expr->var); return Result::Ok; } -Result NameApplier::OnBrTableExpr(Expr* expr) { - VarVector& targets = *expr->br_table.targets; +Result NameApplier::OnBrTableExpr(BrTableExpr* expr) { + VarVector& targets = *expr->targets; for (Var& target : targets) { - Label* label = FindLabelByVar(&target); + string_view label = FindLabelByVar(&target); UseNameForVar(label, &target); } - Label* label = FindLabelByVar(&expr->br_table.default_target); - UseNameForVar(label, &expr->br_table.default_target); + string_view label = FindLabelByVar(&expr->default_target); + UseNameForVar(label, &expr->default_target); + return Result::Ok; +} + +Result NameApplier::BeginTryExpr(TryExpr* expr) { + PushLabel(expr->block->label); + return Result::Ok; +} + +Result NameApplier::EndTryExpr(TryExpr*) { + PopLabel(); + return Result::Ok; +} + +Result NameApplier::OnCatchExpr(TryExpr*, Catch* expr) { + if (!expr->IsCatchAll()) { + CHECK_RESULT(UseNameForExceptVar(&expr->var)); + } + return Result::Ok; +} + +Result NameApplier::OnThrowExpr(ThrowExpr* expr) { + CHECK_RESULT(UseNameForExceptVar(&expr->var)); + return Result::Ok; +} + +Result NameApplier::OnRethrowExpr(RethrowExpr* expr) { + string_view label = FindLabelByVar(&expr->var); + UseNameForVar(label, &expr->var); return Result::Ok; } -Result NameApplier::OnCallExpr(Expr* expr) { - CHECK_RESULT(UseNameForFuncVar(module_, &expr->call.var)); +Result NameApplier::OnCallExpr(CallExpr* expr) { + CHECK_RESULT(UseNameForFuncVar(&expr->var)); return Result::Ok; } -Result NameApplier::OnCallIndirectExpr(Expr* expr) { - CHECK_RESULT(UseNameForFuncTypeVar(module_, &expr->call_indirect.var)); +Result NameApplier::OnCallIndirectExpr(CallIndirectExpr* expr) { + CHECK_RESULT(UseNameForFuncTypeVar(&expr->var)); return Result::Ok; } -Result NameApplier::OnGetGlobalExpr(Expr* expr) { - CHECK_RESULT(UseNameForGlobalVar(module_, &expr->get_global.var)); +Result NameApplier::OnGetGlobalExpr(GetGlobalExpr* expr) { + CHECK_RESULT(UseNameForGlobalVar(&expr->var)); return Result::Ok; } -Result NameApplier::OnGetLocalExpr(Expr* expr) { - CHECK_RESULT(UseNameForParamAndLocalVar(current_func_, &expr->get_local.var)); +Result NameApplier::OnGetLocalExpr(GetLocalExpr* expr) { + CHECK_RESULT(UseNameForParamAndLocalVar(current_func_, &expr->var)); return Result::Ok; } -Result NameApplier::BeginIfExpr(Expr* expr) { - PushLabel(&expr->if_.true_->label); +Result NameApplier::BeginIfExpr(IfExpr* expr) { + PushLabel(expr->true_->label); return Result::Ok; } -Result NameApplier::EndIfExpr(Expr* expr) { +Result NameApplier::EndIfExpr(IfExpr* expr) { PopLabel(); return Result::Ok; } -Result NameApplier::OnSetGlobalExpr(Expr* expr) { - CHECK_RESULT(UseNameForGlobalVar(module_, &expr->set_global.var)); +Result NameApplier::OnSetGlobalExpr(SetGlobalExpr* expr) { + CHECK_RESULT(UseNameForGlobalVar(&expr->var)); return Result::Ok; } -Result NameApplier::OnSetLocalExpr(Expr* expr) { - CHECK_RESULT(UseNameForParamAndLocalVar(current_func_, &expr->set_local.var)); +Result NameApplier::OnSetLocalExpr(SetLocalExpr* expr) { + CHECK_RESULT(UseNameForParamAndLocalVar(current_func_, &expr->var)); return Result::Ok; } -Result NameApplier::OnTeeLocalExpr(Expr* expr) { - CHECK_RESULT(UseNameForParamAndLocalVar(current_func_, &expr->tee_local.var)); +Result NameApplier::OnTeeLocalExpr(TeeLocalExpr* expr) { + CHECK_RESULT(UseNameForParamAndLocalVar(current_func_, &expr->var)); return Result::Ok; } Result NameApplier::VisitFunc(Index func_index, Func* func) { current_func_ = func; if (func->decl.has_func_type) { - CHECK_RESULT(UseNameForFuncTypeVar(module_, &func->decl.type_var)); + CHECK_RESULT(UseNameForFuncTypeVar(&func->decl.type_var)); } MakeTypeBindingReverseMapping(func->decl.sig.param_types, @@ -297,23 +337,23 @@ Result NameApplier::VisitFunc(Index func_index, Func* func) { Result NameApplier::VisitExport(Index export_index, Export* export_) { if (export_->kind == ExternalKind::Func) { - UseNameForFuncVar(module_, &export_->var); + UseNameForFuncVar(&export_->var); } return Result::Ok; } Result NameApplier::VisitElemSegment(Index elem_segment_index, ElemSegment* segment) { - CHECK_RESULT(UseNameForTableVar(module_, &segment->table_var)); + CHECK_RESULT(UseNameForTableVar(&segment->table_var)); for (Var& var : segment->vars) { - CHECK_RESULT(UseNameForFuncVar(module_, &var)); + CHECK_RESULT(UseNameForFuncVar(&var)); } return Result::Ok; } Result NameApplier::VisitDataSegment(Index data_segment_index, DataSegment* segment) { - CHECK_RESULT(UseNameForMemoryVar(module_, &segment->memory_var)); + CHECK_RESULT(UseNameForMemoryVar(&segment->memory_var)); return Result::Ok; } @@ -331,9 +371,9 @@ Result NameApplier::VisitModule(Module* module) { return Result::Ok; } -} // namespace +} // end anonymous namespace -Result apply_names(Module* module) { +Result ApplyNames(Module* module) { NameApplier applier; return applier.VisitModule(module); } diff --git a/lib/wabt/src/apply-names.h b/lib/wabt/src/apply-names.h index eeb0f0ee9df..3088608cf1d 100644 --- a/lib/wabt/src/apply-names.h +++ b/lib/wabt/src/apply-names.h @@ -38,7 +38,7 @@ struct Module; * ... * (call $foo ...) */ -Result apply_names(struct Module*); +Result ApplyNames(struct Module*); } // namespace wabt diff --git a/lib/wabt/src/binary-error-handler.cc b/lib/wabt/src/binary-error-handler.cc deleted file mode 100644 index 4b3c0a23087..00000000000 --- a/lib/wabt/src/binary-error-handler.cc +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2017 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. - */ - -#include "binary-error-handler.h" - -#include "common.h" - -namespace wabt { - -std::string BinaryErrorHandler::DefaultErrorMessage(Offset offset, - const std::string& error) { - if (offset == kInvalidOffset) - return string_printf("error: %s\n", error.c_str()); - else - return string_printf("error: @0x%08" PRIzx ": %s\n", offset, error.c_str()); -} - -BinaryErrorHandlerFile::BinaryErrorHandlerFile(FILE* file, - const std::string& header, - PrintHeader print_header) - : file_(file), header_(header), print_header_(print_header) {} - -bool BinaryErrorHandlerFile::OnError(Offset offset, const std::string& error) { - PrintErrorHeader(); - std::string message = DefaultErrorMessage(offset, error); - fwrite(message.data(), 1, message.size(), file_); - fflush(file_); - return true; -} - -void BinaryErrorHandlerFile::PrintErrorHeader() { - if (header_.empty()) - return; - - switch (print_header_) { - case PrintHeader::Never: - break; - - case PrintHeader::Once: - print_header_ = PrintHeader::Never; - // Fallthrough. - - case PrintHeader::Always: - fprintf(file_, "%s:\n", header_.c_str()); - break; - } - // If there's a header, indent the following message. - fprintf(file_, " "); -} - -bool BinaryErrorHandlerBuffer::OnError(Offset offset, - const std::string& error) { - buffer_ += DefaultErrorMessage(offset, error); - return true; -} - -} // namespace wabt diff --git a/lib/wabt/src/binary-error-handler.h b/lib/wabt/src/binary-error-handler.h deleted file mode 100644 index e4644dd2e57..00000000000 --- a/lib/wabt/src/binary-error-handler.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2017 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 WABT_BINARY_ERROR_HANDLER_H_ -#define WABT_BINARY_ERROR_HANDLER_H_ - -#include -#include -#include - -#include "common.h" - -namespace wabt { - -class BinaryErrorHandler { - public: - virtual ~BinaryErrorHandler() {} - - // Returns true if the error was handled. - virtual bool OnError(Offset offset, const std::string& error) = 0; - - std::string DefaultErrorMessage(Offset offset, const std::string& error); -}; - -class BinaryErrorHandlerFile : public BinaryErrorHandler { - public: - enum class PrintHeader { - Never, - Once, - Always, - }; - - BinaryErrorHandlerFile(FILE* file = stderr, - const std::string& header = std::string(), - PrintHeader print_header = PrintHeader::Never); - - bool OnError(Offset offset, const std::string& error) override; - - private: - void PrintErrorHeader(); - - FILE* file_; - std::string header_; - PrintHeader print_header_; -}; - -class BinaryErrorHandlerBuffer : public BinaryErrorHandler { - public: - BinaryErrorHandlerBuffer() = default; - - bool OnError(Offset offset, const std::string& error) override; - - const std::string& buffer() const { return buffer_; } - - private: - std::string buffer_; -}; - -} // namespace wabt - -#endif // WABT_BINARY_ERROR_HANDLER_H_ diff --git a/lib/wabt/src/binary-reader-interpreter.cc b/lib/wabt/src/binary-reader-interpreter.cc index 53e83c46cb0..b369b2f8590 100644 --- a/lib/wabt/src/binary-reader-interpreter.cc +++ b/lib/wabt/src/binary-reader-interpreter.cc @@ -22,15 +22,15 @@ #include #include -#include "binary-error-handler.h" #include "binary-reader-nop.h" +#include "error-handler.h" #include "interpreter.h" #include "type-checker.h" #include "writer.h" #define CHECK_RESULT(expr) \ do { \ - if (WABT_FAILED(expr)) \ + if (Failed(expr)) \ return wabt::Result::Error; \ } while (0) @@ -76,7 +76,7 @@ class BinaryReaderInterpreter : public BinaryReaderNop { BinaryReaderInterpreter(Environment* env, DefinedModule* module, std::unique_ptr istream, - BinaryErrorHandler* error_handler); + ErrorHandler* error_handler); wabt::Result ReadBinary(DefinedModule* out_module); @@ -96,27 +96,27 @@ class BinaryReaderInterpreter : public BinaryReaderNop { wabt::Result OnImportCount(Index count) override; wabt::Result OnImport(Index index, - StringSlice module_name, - StringSlice field_name) override; + string_view module_name, + string_view field_name) override; wabt::Result OnImportFunc(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index func_index, Index sig_index) override; wabt::Result OnImportTable(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index table_index, Type elem_type, const Limits* elem_limits) override; wabt::Result OnImportMemory(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index memory_index, const Limits* page_limits) override; wabt::Result OnImportGlobal(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index global_index, Type type, bool mutable_) override; @@ -137,7 +137,7 @@ class BinaryReaderInterpreter : public BinaryReaderNop { wabt::Result OnExport(Index index, ExternalKind kind, Index item_index, - StringSlice name) override; + string_view name) override; wabt::Result OnStartFunction(Index func_index) override; @@ -257,11 +257,11 @@ class BinaryReaderInterpreter : public BinaryReaderNop { wabt::Result AppendExport(Module* module, ExternalKind kind, Index item_index, - StringSlice name); + string_view name); HostImportDelegate::ErrorCallback MakePrintErrorCallback(); - BinaryErrorHandler* error_handler = nullptr; + ErrorHandler* error_handler = nullptr; Environment* env = nullptr; DefinedModule* module = nullptr; DefinedFunc* current_func = nullptr; @@ -298,7 +298,7 @@ BinaryReaderInterpreter::BinaryReaderInterpreter( Environment* env, DefinedModule* module, std::unique_ptr istream, - BinaryErrorHandler* error_handler) + ErrorHandler* error_handler) : error_handler(error_handler), env(env), module(module), @@ -474,8 +474,8 @@ wabt::Result BinaryReaderInterpreter::GetBrDropKeepCount( wabt::Result BinaryReaderInterpreter::GetReturnDropKeepCount( Index* out_drop_count, Index* out_keep_count) { - if (WABT_FAILED(GetBrDropKeepCount(label_stack.size() - 1, out_drop_count, - out_keep_count))) { + if (Failed(GetBrDropKeepCount(label_stack.size() - 1, out_drop_count, + out_keep_count))) { return wabt::Result::Error; } @@ -555,15 +555,15 @@ wabt::Result BinaryReaderInterpreter::OnImportCount(Index count) { } wabt::Result BinaryReaderInterpreter::OnImport(Index index, - StringSlice module_name, - StringSlice field_name) { + string_view module_name, + string_view field_name) { Import* import = &module->imports[index]; - import->module_name = dup_string_slice(module_name); - import->field_name = dup_string_slice(field_name); + import->module_name = module_name.to_string(); + import->field_name = field_name.to_string(); Module* module = env->FindRegisteredModule(import->module_name); if (!module) { - PrintError("unknown import module \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG(import->module_name)); + PrintError("unknown import module \"" PRIstringview "\"", + WABT_PRINTF_STRING_VIEW_ARG(import->module_name)); return wabt::Result::Error; } if (module->is_host) { @@ -575,8 +575,8 @@ wabt::Result BinaryReaderInterpreter::OnImport(Index index, } else { Export* export_ = module->GetExport(import->field_name); if (!export_) { - PrintError("unknown module field \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG(import->field_name)); + PrintError("unknown module field \"" PRIstringview "\"", + WABT_PRINTF_STRING_VIEW_ARG(import->field_name)); return wabt::Result::Error; } @@ -611,11 +611,11 @@ wabt::Result BinaryReaderInterpreter::CheckImportKind( Import* import, ExternalKind expected_kind) { if (import->kind != expected_kind) { - PrintError("expected import \"" PRIstringslice "." PRIstringslice + PrintError("expected import \"" PRIstringview "." PRIstringview "\" to have kind %s, not %s", - WABT_PRINTF_STRING_SLICE_ARG(import->module_name), - WABT_PRINTF_STRING_SLICE_ARG(import->field_name), - get_kind_name(expected_kind), get_kind_name(import->kind)); + WABT_PRINTF_STRING_VIEW_ARG(import->module_name), + WABT_PRINTF_STRING_VIEW_ARG(import->field_name), + GetKindName(expected_kind), GetKindName(import->kind)); return wabt::Result::Error; } return wabt::Result::Ok; @@ -648,17 +648,17 @@ wabt::Result BinaryReaderInterpreter::CheckImportLimits( wabt::Result BinaryReaderInterpreter::AppendExport(Module* module, ExternalKind kind, Index item_index, - StringSlice name) { + string_view name) { if (module->export_bindings.FindIndex(name) != kInvalidIndex) { - PrintError("duplicate export \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG(name)); + PrintError("duplicate export \"" PRIstringview "\"", + WABT_PRINTF_STRING_VIEW_ARG(name)); return wabt::Result::Error; } - module->exports.emplace_back(dup_string_slice(name), kind, item_index); + module->exports.emplace_back(name, kind, item_index); Export* export_ = &module->exports.back(); - module->export_bindings.emplace(string_slice_to_string(export_->name), + module->export_bindings.emplace(export_->name, Binding(module->exports.size() - 1)); return wabt::Result::Ok; } @@ -669,8 +669,8 @@ BinaryReaderInterpreter::MakePrintErrorCallback() { } wabt::Result BinaryReaderInterpreter::OnImportFunc(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index func_index, Index sig_index) { Import* import = &module->imports[import_index]; @@ -706,8 +706,8 @@ wabt::Result BinaryReaderInterpreter::OnImportFunc(Index import_index, } wabt::Result BinaryReaderInterpreter::OnImportTable(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index table_index, Type elem_type, const Limits* elem_limits) { @@ -742,8 +742,8 @@ wabt::Result BinaryReaderInterpreter::OnImportTable(Index import_index, wabt::Result BinaryReaderInterpreter::OnImportMemory( Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index memory_index, const Limits* page_limits) { if (module->memory_index != kInvalidIndex) { @@ -776,8 +776,8 @@ wabt::Result BinaryReaderInterpreter::OnImportMemory( } wabt::Result BinaryReaderInterpreter::OnImportGlobal(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index global_index, Type type, bool mutable_) { @@ -859,8 +859,8 @@ wabt::Result BinaryReaderInterpreter::EndGlobalInitExpr(Index index) { Global* global = GetGlobalByModuleIndex(index); if (init_expr_value.type != global->typed_value.type) { PrintError("type mismatch in global, expected %s but got %s.", - get_type_name(global->typed_value.type), - get_type_name(init_expr_value.type)); + GetTypeName(global->typed_value.type), + GetTypeName(init_expr_value.type)); return wabt::Result::Error; } global->typed_value = init_expr_value; @@ -916,7 +916,7 @@ wabt::Result BinaryReaderInterpreter::OnInitExprI64ConstExpr(Index index, wabt::Result BinaryReaderInterpreter::OnExport(Index index, ExternalKind kind, Index item_index, - StringSlice name) { + string_view name) { switch (kind) { case ExternalKind::Func: item_index = TranslateFuncIndexToEnv(item_index); @@ -967,7 +967,7 @@ wabt::Result BinaryReaderInterpreter::OnStartFunction(Index func_index) { wabt::Result BinaryReaderInterpreter::EndElemSegmentInitExpr(Index index) { if (init_expr_value.type != Type::I32) { PrintError("type mismatch in elem segment, expected i32 but got %s", - get_type_name(init_expr_value.type)); + GetTypeName(init_expr_value.type)); return wabt::Result::Error; } table_offset = init_expr_value.value.i32; @@ -1004,7 +1004,7 @@ wabt::Result BinaryReaderInterpreter::OnDataSegmentData(Index index, Memory* memory = env->GetMemory(module->memory_index); if (init_expr_value.type != Type::I32) { PrintError("type mismatch in data segment, expected i32 but got %s", - get_type_name(init_expr_value.type)); + GetTypeName(init_expr_value.type)); return wabt::Result::Error; } Address address = init_expr_value.value.i32; @@ -1102,8 +1102,7 @@ wabt::Result BinaryReaderInterpreter::OnLocalDecl(Index decl_index, wabt::Result BinaryReaderInterpreter::CheckHasMemory(wabt::Opcode opcode) { if (module->memory_index == kInvalidIndex) { - PrintError("%s requires an imported or defined memory.", - get_opcode_name(opcode)); + PrintError("%s requires an imported or defined memory.", opcode.GetName()); return wabt::Result::Error; } return wabt::Result::Ok; @@ -1374,7 +1373,7 @@ wabt::Result BinaryReaderInterpreter::OnLoadExpr(wabt::Opcode opcode, uint32_t alignment_log2, Address offset) { CHECK_RESULT(CheckHasMemory(opcode)); - CHECK_RESULT(CheckAlign(alignment_log2, get_opcode_memory_size(opcode))); + CHECK_RESULT(CheckAlign(alignment_log2, opcode.GetMemorySize())); CHECK_RESULT(typechecker.OnLoad(opcode)); CHECK_RESULT(EmitOpcode(opcode)); CHECK_RESULT(EmitI32(module->memory_index)); @@ -1386,7 +1385,7 @@ wabt::Result BinaryReaderInterpreter::OnStoreExpr(wabt::Opcode opcode, uint32_t alignment_log2, Address offset) { CHECK_RESULT(CheckHasMemory(opcode)); - CHECK_RESULT(CheckAlign(alignment_log2, get_opcode_memory_size(opcode))); + CHECK_RESULT(CheckAlign(alignment_log2, opcode.GetMemorySize())); CHECK_RESULT(typechecker.OnStore(opcode)); CHECK_RESULT(EmitOpcode(opcode)); CHECK_RESULT(EmitI32(module->memory_index)); @@ -1437,14 +1436,14 @@ wabt::Result BinaryReaderInterpreter::EndModule() { return wabt::Result::Ok; } -} // namespace +} // end anonymous namespace -wabt::Result read_binary_interpreter(Environment* env, - const void* data, - size_t size, - const ReadBinaryOptions* options, - BinaryErrorHandler* error_handler, - DefinedModule** out_module) { +wabt::Result ReadBinaryInterpreter(Environment* env, + const void* data, + size_t size, + const ReadBinaryOptions* options, + ErrorHandler* error_handler, + DefinedModule** out_module) { // Need to mark before taking ownership of env->istream. Environment::MarkPoint mark = env->Mark(); @@ -1456,10 +1455,10 @@ wabt::Result read_binary_interpreter(Environment* env, error_handler); env->EmplaceBackModule(module); - wabt::Result result = read_binary(data, size, &reader, options); + wabt::Result result = ReadBinary(data, size, &reader, options); env->SetIstream(reader.ReleaseOutputBuffer()); - if (WABT_SUCCEEDED(result)) { + if (Succeeded(result)) { module->istream_start = istream_offset; module->istream_end = env->istream().size(); *out_module = module; diff --git a/lib/wabt/src/binary-reader-interpreter.h b/lib/wabt/src/binary-reader-interpreter.h index 1c70d3bfec2..bf2013a9d13 100644 --- a/lib/wabt/src/binary-reader-interpreter.h +++ b/lib/wabt/src/binary-reader-interpreter.h @@ -28,15 +28,15 @@ class Environment; } // namespace interpreter -class BinaryErrorHandler; +class ErrorHandler; struct ReadBinaryOptions; -Result read_binary_interpreter(interpreter::Environment* env, - const void* data, - size_t size, - const ReadBinaryOptions* options, - BinaryErrorHandler*, - interpreter::DefinedModule** out_module); +Result ReadBinaryInterpreter(interpreter::Environment* env, + const void* data, + size_t size, + const ReadBinaryOptions* options, + ErrorHandler*, + interpreter::DefinedModule** out_module); } // namespace wabt diff --git a/lib/wabt/src/binary-reader-ir.cc b/lib/wabt/src/binary-reader-ir.cc index 5094b710cea..96e228f14a8 100644 --- a/lib/wabt/src/binary-reader-ir.cc +++ b/lib/wabt/src/binary-reader-ir.cc @@ -23,15 +23,16 @@ #include #include -#include "binary-error-handler.h" #include "binary-reader-nop.h" +#include "cast.h" #include "common.h" +#include "error-handler.h" #include "ir.h" -#define CHECK_RESULT(expr) \ - do { \ - if (WABT_FAILED(expr)) \ - return Result::Error; \ +#define CHECK_RESULT(expr) \ + do { \ + if (Failed(expr)) \ + return Result::Error; \ } while (0) namespace wabt { @@ -39,19 +40,22 @@ namespace wabt { namespace { struct LabelNode { - LabelNode(LabelType, Expr** first); + LabelNode(LabelType, ExprList* exprs); LabelType label_type; - Expr** first; - Expr* last; + ExprList* exprs; + Expr* context; }; -LabelNode::LabelNode(LabelType label_type, Expr** first) - : label_type(label_type), first(first), last(nullptr) {} +LabelNode::LabelNode(LabelType label_type, ExprList* exprs) + : label_type(label_type), exprs(exprs), context(nullptr) {} + class BinaryReaderIR : public BinaryReaderNop { public: - BinaryReaderIR(Module* out_module, BinaryErrorHandler* error_handler); + BinaryReaderIR(Module* out_module, + const char* filename, + ErrorHandler* error_handler); bool OnError(const char* message) override; @@ -64,30 +68,35 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnImportCount(Index count) override; Result OnImport(Index index, - StringSlice module_name, - StringSlice field_name) override; + string_view module_name, + string_view field_name) override; Result OnImportFunc(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index func_index, Index sig_index) override; Result OnImportTable(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index table_index, Type elem_type, const Limits* elem_limits) override; Result OnImportMemory(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index memory_index, const Limits* page_limits) override; Result OnImportGlobal(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index global_index, Type type, bool mutable_) override; + Result OnImportException(Index import_index, + string_view module_name, + string_view field_name, + Index except_index, + TypeVector& sig) override; Result OnFunctionCount(Index count) override; Result OnFunction(Index index, Index sig_index) override; @@ -109,7 +118,7 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnExport(Index index, ExternalKind kind, Index item_index, - StringSlice name) override; + string_view name) override; Result OnStartFunction(Index func_index) override; @@ -125,6 +134,8 @@ class BinaryReaderIR : public BinaryReaderNop { Index* target_depths, Index default_target_depth) override; Result OnCallExpr(Index func_index) override; + Result OnCatchExpr(Index except_index) override; + Result OnCatchAllExpr() override; Result OnCallIndirectExpr(Index sig_index) override; Result OnCompareExpr(Opcode opcode) override; Result OnConvertExpr(Opcode opcode) override; @@ -145,6 +156,7 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnLoopExpr(Index num_types, Type* sig_types) override; Result OnCurrentMemoryExpr() override; Result OnNopExpr() override; + Result OnRethrowExpr(Index depth) override; Result OnReturnExpr() override; Result OnSelectExpr() override; Result OnSetGlobalExpr(Index global_index) override; @@ -152,7 +164,9 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnStoreExpr(Opcode opcode, uint32_t alignment_log2, Address offset) override; + Result OnThrowExpr(Index except_index) override; Result OnTeeLocalExpr(Index local_index) override; + Result OnTryExpr(Index num_types, Type* sig_types) override; Result OnUnaryExpr(Opcode opcode) override; Result OnUnreachableExpr() override; Result EndFunctionBody(Index index) override; @@ -176,12 +190,17 @@ class BinaryReaderIR : public BinaryReaderNop { Result OnFunctionNamesCount(Index num_functions) override; Result OnFunctionName(Index function_index, - StringSlice function_name) override; + string_view function_name) override; Result OnLocalNameLocalCount(Index function_index, Index num_locals) override; Result OnLocalName(Index function_index, Index local_index, - StringSlice local_name) override; + string_view local_name) override; + + Result BeginExceptionSection(Offset size) override { return Result::Ok; } + Result OnExceptionCount(Index count) override { return Result::Ok; } + Result OnExceptionType(Index index, TypeVector& types) override; + Result EndExceptionSection() override { return Result::Ok; } Result OnInitExprF32ConstExpr(Index index, uint32_t value) override; Result OnInitExprF64ConstExpr(Index index, uint64_t value) override; @@ -191,24 +210,35 @@ class BinaryReaderIR : public BinaryReaderNop { private: bool HandleError(Offset offset, const char* message); + Location GetLocation() const; void PrintError(const char* format, ...); - void PushLabel(LabelType label_type, Expr** first); + void PushLabel(LabelType label_type, ExprList* first); Result PopLabel(); Result GetLabelAt(LabelNode** label, Index depth); Result TopLabel(LabelNode** label); Result AppendExpr(Expr* expr); + Result AppendCatch(Catch* catch_); - BinaryErrorHandler* error_handler = nullptr; + ErrorHandler* error_handler = nullptr; Module* module = nullptr; Func* current_func = nullptr; std::vector label_stack; - Expr** current_init_expr = nullptr; + ExprList* current_init_expr = nullptr; + const char* filename_; }; BinaryReaderIR::BinaryReaderIR(Module* out_module, - BinaryErrorHandler* error_handler) - : error_handler(error_handler), module(out_module) {} + const char* filename, + ErrorHandler* error_handler) + : error_handler(error_handler), module(out_module), filename_(filename) {} + +Location BinaryReaderIR::GetLocation() const { + Location loc; + loc.filename = filename_; + loc.offset = state->offset; + return loc; +} void WABT_PRINTF_FORMAT(2, 3) BinaryReaderIR::PrintError(const char* format, ...) { @@ -216,7 +246,7 @@ void WABT_PRINTF_FORMAT(2, 3) BinaryReaderIR::PrintError(const char* format, HandleError(kInvalidOffset, buffer); } -void BinaryReaderIR::PushLabel(LabelType label_type, Expr** first) { +void BinaryReaderIR::PushLabel(LabelType label_type, ExprList* first) { label_stack.emplace_back(label_type, first); } @@ -246,17 +276,15 @@ Result BinaryReaderIR::TopLabel(LabelNode** label) { } Result BinaryReaderIR::AppendExpr(Expr* expr) { + // TODO(binji): Probably should be set in the Expr constructor instead. + expr->loc = GetLocation(); + LabelNode* label; - if (WABT_FAILED(TopLabel(&label))) { + if (Failed(TopLabel(&label))) { delete expr; return Result::Error; } - if (*label->first) { - label->last->next = expr; - label->last = expr; - } else { - *label->first = label->last = expr; - } + label->exprs->push_back(expr); return Result::Ok; } @@ -278,14 +306,11 @@ Result BinaryReaderIR::OnType(Index index, Type* param_types, Index result_count, Type* result_types) { - ModuleField* field = module->AppendField(); - field->type = ModuleFieldType::FuncType; - field->func_type = new FuncType(); - - FuncType* func_type = field->func_type; + auto func_type = new FuncType(); func_type->sig.param_types.assign(param_types, param_types + param_count); func_type->sig.result_types.assign(result_types, result_types + result_count); module->func_types.push_back(func_type); + module->fields.push_back(new FuncTypeModuleField(func_type, GetLocation())); return Result::Ok; } @@ -295,22 +320,19 @@ Result BinaryReaderIR::OnImportCount(Index count) { } Result BinaryReaderIR::OnImport(Index index, - StringSlice module_name, - StringSlice field_name) { - ModuleField* field = module->AppendField(); - field->type = ModuleFieldType::Import; - field->import = new Import(); - - Import* import = field->import; - import->module_name = dup_string_slice(module_name); - import->field_name = dup_string_slice(field_name); + string_view module_name, + string_view field_name) { + auto import = new Import(); + import->module_name = module_name.to_string(); + import->field_name = field_name.to_string(); module->imports.push_back(import); + module->fields.push_back(new ImportModuleField(import, GetLocation())); return Result::Ok; } Result BinaryReaderIR::OnImportFunc(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index func_index, Index sig_index) { assert(import_index == module->imports.size() - 1); @@ -319,8 +341,7 @@ Result BinaryReaderIR::OnImportFunc(Index import_index, import->kind = ExternalKind::Func; import->func = new Func(); import->func->decl.has_func_type = true; - import->func->decl.type_var.type = VarType::Index; - import->func->decl.type_var.index = sig_index; + import->func->decl.type_var = Var(sig_index, GetLocation()); import->func->decl.sig = module->func_types[sig_index]->sig; module->funcs.push_back(import->func); @@ -329,8 +350,8 @@ Result BinaryReaderIR::OnImportFunc(Index import_index, } Result BinaryReaderIR::OnImportTable(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index table_index, Type elem_type, const Limits* elem_limits) { @@ -345,8 +366,8 @@ Result BinaryReaderIR::OnImportTable(Index import_index, } Result BinaryReaderIR::OnImportMemory(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index memory_index, const Limits* page_limits) { assert(import_index == module->imports.size() - 1); @@ -360,8 +381,8 @@ Result BinaryReaderIR::OnImportMemory(Index import_index, } Result BinaryReaderIR::OnImportGlobal(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index global_index, Type type, bool mutable_) { @@ -376,23 +397,32 @@ Result BinaryReaderIR::OnImportGlobal(Index import_index, return Result::Ok; } +Result BinaryReaderIR::OnImportException(Index import_index, + string_view module_name, + string_view field_name, + Index except_index, + TypeVector& sig) { + assert(import_index == module->imports.size() - 1); + Import* import = module->imports[import_index]; + import->kind = ExternalKind::Except; + import->except = new Exception(sig); + module->excepts.push_back(import->except); + return Result::Ok; +} + Result BinaryReaderIR::OnFunctionCount(Index count) { module->funcs.reserve(module->num_func_imports + count); return Result::Ok; } Result BinaryReaderIR::OnFunction(Index index, Index sig_index) { - ModuleField* field = module->AppendField(); - field->type = ModuleFieldType::Func; - field->func = new Func(); - - Func* func = field->func; + auto func = new Func(); func->decl.has_func_type = true; - func->decl.type_var.type = VarType::Index; - func->decl.type_var.index = sig_index; + func->decl.type_var = Var(sig_index, GetLocation()); func->decl.sig = module->func_types[sig_index]->sig; module->funcs.push_back(func); + module->fields.push_back(new FuncModuleField(func, GetLocation())); return Result::Ok; } @@ -404,11 +434,10 @@ Result BinaryReaderIR::OnTableCount(Index count) { Result BinaryReaderIR::OnTable(Index index, Type elem_type, const Limits* elem_limits) { - ModuleField* field = module->AppendField(); - field->type = ModuleFieldType::Table; - field->table = new Table(); - field->table->elem_limits = *elem_limits; - module->tables.push_back(field->table); + auto table = new Table(); + table->elem_limits = *elem_limits; + module->tables.push_back(table); + module->fields.push_back(new TableModuleField(table, GetLocation())); return Result::Ok; } @@ -418,11 +447,10 @@ Result BinaryReaderIR::OnMemoryCount(Index count) { } Result BinaryReaderIR::OnMemory(Index index, const Limits* page_limits) { - ModuleField* field = module->AppendField(); - field->type = ModuleFieldType::Memory; - field->memory = new Memory(); - field->memory->page_limits = *page_limits; - module->memories.push_back(field->memory); + auto memory = new Memory(); + memory->page_limits = *page_limits; + module->memories.push_back(memory); + module->fields.push_back(new MemoryModuleField(memory, GetLocation())); return Result::Ok; } @@ -432,12 +460,11 @@ Result BinaryReaderIR::OnGlobalCount(Index count) { } Result BinaryReaderIR::BeginGlobal(Index index, Type type, bool mutable_) { - ModuleField* field = module->AppendField(); - field->type = ModuleFieldType::Global; - field->global = new Global(); - field->global->type = type; - field->global->mutable_ = mutable_; - module->globals.push_back(field->global); + auto global = new Global(); + global->type = type; + global->mutable_ = mutable_; + module->globals.push_back(global); + module->fields.push_back(new GlobalModuleField(global, GetLocation())); return Result::Ok; } @@ -461,13 +488,9 @@ Result BinaryReaderIR::OnExportCount(Index count) { Result BinaryReaderIR::OnExport(Index index, ExternalKind kind, Index item_index, - StringSlice name) { - ModuleField* field = module->AppendField(); - field->type = ModuleFieldType::Export; - field->export_ = new Export(); - - Export* export_ = field->export_; - export_->name = dup_string_slice(name); + string_view name) { + auto export_ = new Export(); + export_->name = name.to_string(); switch (kind) { case ExternalKind::Func: assert(item_index < module->funcs.size()); @@ -482,25 +505,20 @@ Result BinaryReaderIR::OnExport(Index index, assert(item_index < module->globals.size()); break; case ExternalKind::Except: - WABT_FATAL("OnExport(except) not implemented\n"); + // Note: Can't check if index valid, exceptions section comes later. break; } - export_->var.type = VarType::Index; - export_->var.index = item_index; + export_->var = Var(item_index, GetLocation()); export_->kind = kind; module->exports.push_back(export_); + module->fields.push_back(new ExportModuleField(export_, GetLocation())); return Result::Ok; } Result BinaryReaderIR::OnStartFunction(Index func_index) { - ModuleField* field = module->AppendField(); - field->type = ModuleFieldType::Start; - - field->start.type = VarType::Index; assert(func_index < module->funcs.size()); - field->start.index = func_index; - - module->start = &field->start; + Var start(func_index, GetLocation()); + module->fields.push_back(new StartModuleField(start, GetLocation())); return Result::Ok; } @@ -511,7 +529,7 @@ Result BinaryReaderIR::OnFunctionBodyCount(Index count) { Result BinaryReaderIR::BeginFunctionBody(Index index) { current_func = module->funcs[index]; - PushLabel(LabelType::Func, ¤t_func->first_expr); + PushLabel(LabelType::Func, ¤t_func->exprs); return Result::Ok; } @@ -524,25 +542,26 @@ Result BinaryReaderIR::OnLocalDecl(Index decl_index, Index count, Type type) { } Result BinaryReaderIR::OnBinaryExpr(Opcode opcode) { - Expr* expr = Expr::CreateBinary(opcode); + auto expr = new BinaryExpr(opcode); return AppendExpr(expr); } Result BinaryReaderIR::OnBlockExpr(Index num_types, Type* sig_types) { - Expr* expr = Expr::CreateBlock(new Block()); + auto expr = new BlockExpr(new Block()); expr->block->sig.assign(sig_types, sig_types + num_types); - AppendExpr(expr); - PushLabel(LabelType::Block, &expr->block->first); + if (Failed(AppendExpr(expr))) + return Result::Error; + PushLabel(LabelType::Block, &expr->block->exprs); return Result::Ok; } Result BinaryReaderIR::OnBrExpr(Index depth) { - Expr* expr = Expr::CreateBr(Var(depth)); + auto expr = new BrExpr(Var(depth, GetLocation())); return AppendExpr(expr); } Result BinaryReaderIR::OnBrIfExpr(Index depth) { - Expr* expr = Expr::CreateBrIf(Var(depth)); + auto expr = new BrIfExpr(Var(depth, GetLocation())); return AppendExpr(expr); } @@ -554,39 +573,40 @@ Result BinaryReaderIR::OnBrTableExpr(Index num_targets, for (Index i = 0; i < num_targets; ++i) { (*targets)[i] = Var(target_depths[i]); } - Expr* expr = Expr::CreateBrTable(targets, Var(default_target_depth)); + auto expr = new BrTableExpr(targets, + Var(default_target_depth, GetLocation())); return AppendExpr(expr); } Result BinaryReaderIR::OnCallExpr(Index func_index) { assert(func_index < module->funcs.size()); - Expr* expr = Expr::CreateCall(Var(func_index)); + auto expr = new CallExpr(Var(func_index, GetLocation())); return AppendExpr(expr); } Result BinaryReaderIR::OnCallIndirectExpr(Index sig_index) { assert(sig_index < module->func_types.size()); - Expr* expr = Expr::CreateCallIndirect(Var(sig_index)); + auto expr = new CallIndirectExpr(Var(sig_index, GetLocation())); return AppendExpr(expr); } Result BinaryReaderIR::OnCompareExpr(Opcode opcode) { - Expr* expr = Expr::CreateCompare(opcode); + auto expr = new CompareExpr(opcode); return AppendExpr(expr); } Result BinaryReaderIR::OnConvertExpr(Opcode opcode) { - Expr* expr = Expr::CreateConvert(opcode); + auto expr = new ConvertExpr(opcode); return AppendExpr(expr); } Result BinaryReaderIR::OnCurrentMemoryExpr() { - Expr* expr = Expr::CreateCurrentMemory(); + auto expr = new CurrentMemoryExpr(); return AppendExpr(expr); } Result BinaryReaderIR::OnDropExpr() { - Expr* expr = Expr::CreateDrop(); + auto expr = new DropExpr(); return AppendExpr(expr); } @@ -600,11 +620,9 @@ Result BinaryReaderIR::OnElseExpr() { LabelNode* parent_label; CHECK_RESULT(GetLabelAt(&parent_label, 1)); - assert(parent_label->last->type == ExprType::If); label->label_type = LabelType::Else; - label->first = &parent_label->last->if_.false_; - label->last = nullptr; + label->exprs = &cast(&parent_label->exprs->back())->false_; return Result::Ok; } @@ -613,108 +631,161 @@ Result BinaryReaderIR::OnEndExpr() { } Result BinaryReaderIR::OnF32ConstExpr(uint32_t value_bits) { - Expr* expr = Expr::CreateConst(Const(Const::F32(), value_bits)); + auto expr = new ConstExpr(Const(Const::F32(), value_bits, GetLocation())); return AppendExpr(expr); } Result BinaryReaderIR::OnF64ConstExpr(uint64_t value_bits) { - Expr* expr = Expr::CreateConst(Const(Const::F64(), value_bits)); + auto expr = new ConstExpr(Const(Const::F64(), value_bits, GetLocation())); return AppendExpr(expr); } Result BinaryReaderIR::OnGetGlobalExpr(Index global_index) { - Expr* expr = Expr::CreateGetGlobal(Var(global_index)); + auto expr = new GetGlobalExpr(Var(global_index, GetLocation())); return AppendExpr(expr); } Result BinaryReaderIR::OnGetLocalExpr(Index local_index) { - Expr* expr = Expr::CreateGetLocal(Var(local_index)); + auto expr = new GetLocalExpr(Var(local_index, GetLocation())); return AppendExpr(expr); } Result BinaryReaderIR::OnGrowMemoryExpr() { - Expr* expr = Expr::CreateGrowMemory(); + auto expr = new GrowMemoryExpr(); return AppendExpr(expr); } Result BinaryReaderIR::OnI32ConstExpr(uint32_t value) { - Expr* expr = Expr::CreateConst(Const(Const::I32(), value)); + auto expr = new ConstExpr(Const(Const::I32(), value, GetLocation())); return AppendExpr(expr); } Result BinaryReaderIR::OnI64ConstExpr(uint64_t value) { - Expr* expr = Expr::CreateConst(Const(Const::I64(), value)); + auto expr = new ConstExpr(Const(Const::I64(), value, GetLocation())); return AppendExpr(expr); } Result BinaryReaderIR::OnIfExpr(Index num_types, Type* sig_types) { - Expr* expr = Expr::CreateIf(new Block()); - expr->if_.true_->sig.assign(sig_types, sig_types + num_types); - expr->if_.false_ = nullptr; - AppendExpr(expr); - PushLabel(LabelType::If, &expr->if_.true_->first); + auto expr = new IfExpr(new Block()); + expr->true_->sig.assign(sig_types, sig_types + num_types); + if (Failed(AppendExpr(expr))) + return Result::Error; + PushLabel(LabelType::If, &expr->true_->exprs); return Result::Ok; } Result BinaryReaderIR::OnLoadExpr(Opcode opcode, uint32_t alignment_log2, Address offset) { - Expr* expr = Expr::CreateLoad(opcode, 1 << alignment_log2, offset); + auto expr = new LoadExpr(opcode, 1 << alignment_log2, offset); return AppendExpr(expr); } Result BinaryReaderIR::OnLoopExpr(Index num_types, Type* sig_types) { - Expr* expr = Expr::CreateLoop(new Block()); - expr->loop->sig.assign(sig_types, sig_types + num_types); - AppendExpr(expr); - PushLabel(LabelType::Loop, &expr->loop->first); + auto expr = new LoopExpr(new Block()); + expr->block->sig.assign(sig_types, sig_types + num_types); + if (Failed(AppendExpr(expr))) + return Result::Error; + PushLabel(LabelType::Loop, &expr->block->exprs); return Result::Ok; } Result BinaryReaderIR::OnNopExpr() { - Expr* expr = Expr::CreateNop(); + auto expr = new NopExpr(); return AppendExpr(expr); } +Result BinaryReaderIR::OnRethrowExpr(Index depth) { + return AppendExpr(new RethrowExpr(Var(depth, GetLocation()))); +} + Result BinaryReaderIR::OnReturnExpr() { - Expr* expr = Expr::CreateReturn(); + auto expr = new ReturnExpr(); return AppendExpr(expr); } Result BinaryReaderIR::OnSelectExpr() { - Expr* expr = Expr::CreateSelect(); + auto expr = new SelectExpr(); return AppendExpr(expr); } Result BinaryReaderIR::OnSetGlobalExpr(Index global_index) { - Expr* expr = Expr::CreateSetGlobal(Var(global_index)); + auto expr = new SetGlobalExpr(Var(global_index, GetLocation())); return AppendExpr(expr); } Result BinaryReaderIR::OnSetLocalExpr(Index local_index) { - Expr* expr = Expr::CreateSetLocal(Var(local_index)); + auto expr = new SetLocalExpr(Var(local_index, GetLocation())); return AppendExpr(expr); } Result BinaryReaderIR::OnStoreExpr(Opcode opcode, uint32_t alignment_log2, Address offset) { - Expr* expr = Expr::CreateStore(opcode, 1 << alignment_log2, offset); + auto expr = new StoreExpr(opcode, 1 << alignment_log2, offset); return AppendExpr(expr); } +Result BinaryReaderIR::OnThrowExpr(Index except_index) { + return AppendExpr(new ThrowExpr(Var(except_index, GetLocation()))); +} + Result BinaryReaderIR::OnTeeLocalExpr(Index local_index) { - Expr* expr = Expr::CreateTeeLocal(Var(local_index)); + auto expr = new TeeLocalExpr(Var(local_index, GetLocation())); return AppendExpr(expr); } +Result BinaryReaderIR::OnTryExpr(Index num_types, Type* sig_types) { + auto expr = new TryExpr(); + expr->block = new Block(); + expr->block->sig.assign(sig_types, sig_types + num_types); + if (Failed(AppendExpr(expr))) + return Result::Error; + PushLabel(LabelType::Try, &expr->block->exprs); + LabelNode* label = nullptr; + { Result result = TopLabel(&label); + (void) result; + assert(Succeeded(result)); + } + label->context = expr; + return Result::Ok; +} + +Result BinaryReaderIR::AppendCatch(Catch* catch_) { + LabelNode* label = nullptr; + if (Succeeded(TopLabel(&label)) && label->label_type == LabelType::Try) { + if (auto try_ = dyn_cast(label->context)) { + // TODO(karlschimpf) Probably should be set in the Catch constructor. + catch_->loc = GetLocation(); + try_->catches.push_back(catch_); + label->exprs = &catch_->exprs; + return Result::Ok; + } + } + if (label != nullptr) + PrintError("catch not inside try block"); + delete catch_; + return Result::Error; +} + +Result BinaryReaderIR::OnCatchExpr(Index except_index) { + ExprList empty; + return AppendCatch(new Catch(Var(except_index, GetLocation()))); + return Result::Error; +} + +Result BinaryReaderIR::OnCatchAllExpr() { + ExprList empty; + return AppendCatch(new Catch()); +} + Result BinaryReaderIR::OnUnaryExpr(Opcode opcode) { - Expr* expr = Expr::CreateUnary(opcode); + auto expr = new UnaryExpr(opcode); return AppendExpr(expr); } Result BinaryReaderIR::OnUnreachableExpr() { - Expr* expr = Expr::CreateUnreachable(); + auto expr = new UnreachableExpr(); return AppendExpr(expr); } @@ -730,12 +801,10 @@ Result BinaryReaderIR::OnElemSegmentCount(Index count) { } Result BinaryReaderIR::BeginElemSegment(Index index, Index table_index) { - ModuleField* field = module->AppendField(); - field->type = ModuleFieldType::ElemSegment; - field->elem_segment = new ElemSegment(); - field->elem_segment->table_var.type = VarType::Index; - field->elem_segment->table_var.index = table_index; - module->elem_segments.push_back(field->elem_segment); + auto elem_segment = new ElemSegment(); + elem_segment->table_var = Var(table_index, GetLocation()); + module->elem_segments.push_back(elem_segment); + module->fields.push_back(new ElemSegmentModuleField(elem_segment, GetLocation())); return Result::Ok; } @@ -765,8 +834,7 @@ Result BinaryReaderIR::OnElemSegmentFunctionIndex(Index segment_index, ElemSegment* segment = module->elem_segments[segment_index]; segment->vars.emplace_back(); Var* var = &segment->vars.back(); - var->type = VarType::Index; - var->index = func_index; + *var = Var(func_index, GetLocation()); return Result::Ok; } @@ -776,12 +844,10 @@ Result BinaryReaderIR::OnDataSegmentCount(Index count) { } Result BinaryReaderIR::BeginDataSegment(Index index, Index memory_index) { - ModuleField* field = module->AppendField(); - field->type = ModuleFieldType::DataSegment; - field->data_segment = new DataSegment(); - field->data_segment->memory_var.type = VarType::Index; - field->data_segment->memory_var.index = memory_index; - module->data_segments.push_back(field->data_segment); + auto data_segment = new DataSegment(); + data_segment->memory_var = Var(memory_index, GetLocation()); + module->data_segments.push_back(data_segment); + module->fields.push_back(new DataSegmentModuleField(data_segment, GetLocation())); return Result::Ok; } @@ -802,9 +868,9 @@ Result BinaryReaderIR::OnDataSegmentData(Index index, Address size) { assert(index == module->data_segments.size() - 1); DataSegment* segment = module->data_segments[index]; - segment->data = new char[size]; - segment->size = size; - memcpy(segment->data, data, size); + segment->data.resize(size); + if (size > 0) + memcpy(segment->data.data(), data, size); return Result::Ok; } @@ -818,13 +884,18 @@ Result BinaryReaderIR::OnFunctionNamesCount(Index count) { return Result::Ok; } -Result BinaryReaderIR::OnFunctionName(Index index, StringSlice name) { - if (string_slice_is_empty(&name)) +Result BinaryReaderIR::OnFunctionName(Index index, string_view name) { + if (name.empty()) return Result::Ok; Func* func = module->funcs[index]; - std::string dollar_name = std::string("$") + string_slice_to_string(name); - func->name = dup_string_slice(string_to_string_slice(dollar_name)); + std::string dollar_name = std::string("$") + name.to_string(); + int counter = 1; + std::string orig_name = dollar_name; + while (module->func_bindings.count(dollar_name) != 0) { + dollar_name = orig_name + "." + std::to_string(counter++); + } + func->name = dollar_name; module->func_bindings.emplace(dollar_name, Binding(index)); return Result::Ok; } @@ -843,35 +914,45 @@ Result BinaryReaderIR::OnLocalNameLocalCount(Index index, Index count) { } Result BinaryReaderIR::OnInitExprF32ConstExpr(Index index, uint32_t value) { - *current_init_expr = Expr::CreateConst(Const(Const::F32(), value)); + auto expr = new ConstExpr(Const(Const::F32(), value, GetLocation())); + expr->loc = GetLocation(); + current_init_expr->push_back(expr); return Result::Ok; } Result BinaryReaderIR::OnInitExprF64ConstExpr(Index index, uint64_t value) { - *current_init_expr = Expr::CreateConst(Const(Const::F64(), value)); + auto expr = new ConstExpr(Const(Const::F64(), value, GetLocation())); + expr->loc = GetLocation(); + current_init_expr->push_back(expr); return Result::Ok; } Result BinaryReaderIR::OnInitExprGetGlobalExpr(Index index, Index global_index) { - *current_init_expr = Expr::CreateGetGlobal(Var(global_index)); + auto expr = new GetGlobalExpr(Var(global_index, GetLocation())); + expr->loc = GetLocation(); + current_init_expr->push_back(expr); return Result::Ok; } Result BinaryReaderIR::OnInitExprI32ConstExpr(Index index, uint32_t value) { - *current_init_expr = Expr::CreateConst(Const(Const::I32(), value)); + auto expr = new ConstExpr(Const(Const::I32(), value, GetLocation())); + expr->loc = GetLocation(); + current_init_expr->push_back(expr); return Result::Ok; } Result BinaryReaderIR::OnInitExprI64ConstExpr(Index index, uint64_t value) { - *current_init_expr = Expr::CreateConst(Const(Const::I64(), value)); + auto expr = new ConstExpr(Const(Const::I64(), value, GetLocation())); + expr->loc = GetLocation(); + current_init_expr->push_back(expr); return Result::Ok; } Result BinaryReaderIR::OnLocalName(Index func_index, Index local_index, - StringSlice name) { - if (string_slice_is_empty(&name)) + string_view name) { + if (name.empty()) return Result::Ok; Func* func = module->funcs[func_index]; @@ -887,20 +968,27 @@ Result BinaryReaderIR::OnLocalName(Index func_index, bindings = &func->local_bindings; index = local_index - num_params; } - bindings->emplace(std::string("$") + string_slice_to_string(name), - Binding(index)); + bindings->emplace(std::string("$") + name.to_string(), Binding(index)); + return Result::Ok; +} + +Result BinaryReaderIR::OnExceptionType(Index index, TypeVector& sig) { + auto except = new Exception(sig); + module->excepts.push_back(except); + module->fields.push_back(new ExceptionModuleField(except)); return Result::Ok; } -} // namespace +} // end anonymous namespace -Result read_binary_ir(const void* data, - size_t size, - const ReadBinaryOptions* options, - BinaryErrorHandler* error_handler, - struct Module* out_module) { - BinaryReaderIR reader(out_module, error_handler); - Result result = read_binary(data, size, &reader, options); +Result ReadBinaryIr(const char* filename, + const void* data, + size_t size, + const ReadBinaryOptions* options, + ErrorHandler* error_handler, + struct Module* out_module) { + BinaryReaderIR reader(out_module, filename, error_handler); + Result result = ReadBinary(data, size, &reader, options); return result; } diff --git a/lib/wabt/src/binary-reader-ir.h b/lib/wabt/src/binary-reader-ir.h index 50a95a0dc05..227663b7b48 100644 --- a/lib/wabt/src/binary-reader-ir.h +++ b/lib/wabt/src/binary-reader-ir.h @@ -21,15 +21,16 @@ namespace wabt { +class ErrorHandler; struct Module; struct ReadBinaryOptions; -class BinaryErrorHandler; -Result read_binary_ir(const void* data, - size_t size, - const ReadBinaryOptions* options, - BinaryErrorHandler*, - Module* out_module); +Result ReadBinaryIr(const char* filename, + const void* data, + size_t size, + const ReadBinaryOptions* options, + ErrorHandler*, + Module* out_module); } // namespace wabt diff --git a/lib/wabt/src/binary-reader-linker.cc b/lib/wabt/src/binary-reader-linker.cc index add37f6155e..065569db9db 100644 --- a/lib/wabt/src/binary-reader-linker.cc +++ b/lib/wabt/src/binary-reader-linker.cc @@ -35,19 +35,19 @@ class BinaryReaderLinker : public BinaryReaderNop { Result BeginSection(BinarySection section_type, Offset size) override; Result OnImportFunc(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index func_index, Index sig_index) override; Result OnImportGlobal(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index global_index, Type type, bool mutable_) override; Result OnImportMemory(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index memory_index, const Limits* page_limits) override; @@ -62,7 +62,7 @@ class BinaryReaderLinker : public BinaryReaderNop { Result OnExport(Index index, ExternalKind kind, Index item_index, - StringSlice name) override; + string_view name) override; Result OnElemSegmentFunctionIndexCount(Index index, Index count) override; @@ -75,11 +75,11 @@ class BinaryReaderLinker : public BinaryReaderNop { Result BeginNamesSection(Offset size) override; Result OnFunctionName(Index function_index, - StringSlice function_name) override; + string_view function_name) override; Result OnRelocCount(Index count, BinarySection section_code, - StringSlice section_name) override; + string_view section_name) override; Result OnReloc(RelocType type, Offset offset, Index index, @@ -99,7 +99,7 @@ BinaryReaderLinker::BinaryReaderLinker(LinkerInputBinary* binary) Result BinaryReaderLinker::OnRelocCount(Index count, BinarySection section_code, - StringSlice section_name) { + string_view section_name) { if (section_code == BinarySection::Custom) { WABT_FATAL("relocation for custom sections not yet supported\n"); } @@ -129,14 +129,14 @@ Result BinaryReaderLinker::OnReloc(RelocType type, } Result BinaryReaderLinker::OnImportFunc(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index global_index, Index sig_index) { binary_->function_imports.emplace_back(); FunctionImport* import = &binary_->function_imports.back(); - import->module_name = module_name; - import->name = field_name; + import->module_name = module_name.to_string(); + import->name = field_name.to_string(); import->sig_index = sig_index; import->active = true; binary_->active_function_imports++; @@ -144,15 +144,15 @@ Result BinaryReaderLinker::OnImportFunc(Index import_index, } Result BinaryReaderLinker::OnImportGlobal(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index global_index, Type type, bool mutable_) { binary_->global_imports.emplace_back(); GlobalImport* import = &binary_->global_imports.back(); - import->module_name = module_name; - import->name = field_name; + import->module_name = module_name.to_string(); + import->name = field_name.to_string(); import->type = type; import->mutable_ = mutable_; binary_->active_global_imports++; @@ -160,8 +160,8 @@ Result BinaryReaderLinker::OnImportGlobal(Index import_index, } Result BinaryReaderLinker::OnImportMemory(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index memory_index, const Limits* page_limits) { WABT_FATAL("Linker does not support imported memories"); @@ -185,8 +185,10 @@ Result BinaryReaderLinker::BeginSection(BinarySection section_code, if (sec->section_code != BinarySection::Custom && sec->section_code != BinarySection::Start) { - size_t bytes_read = read_u32_leb128( - &binary_->data[sec->offset], &binary_->data[binary_->size], &sec->count); + const uint8_t* start = &binary_->data[sec->offset]; + // Must point to one-past-the-end, but we can't dereference end(). + const uint8_t* end = &binary_->data.back() + 1; + size_t bytes_read = ReadU32Leb128(start, end, &sec->count); if (bytes_read == 0) WABT_FATAL("error reading section element count\n"); sec->payload_offset = sec->offset + bytes_read; @@ -256,13 +258,13 @@ Result BinaryReaderLinker::OnDataSegmentData(Index index, Result BinaryReaderLinker::OnExport(Index index, ExternalKind kind, Index item_index, - StringSlice name) { + string_view name) { if (kind == ExternalKind::Memory) { WABT_FATAL("Linker does not support exported memories"); } binary_->exports.emplace_back(); Export* export_ = &binary_->exports.back(); - export_->name = name; + export_->name = name.to_string(); export_->kind = kind; export_->index = item_index; return Result::Ok; @@ -274,21 +276,21 @@ Result BinaryReaderLinker::BeginNamesSection(Offset size) { return Result::Ok; } -Result BinaryReaderLinker::OnFunctionName(Index index, StringSlice name) { - binary_->debug_names[index] = string_slice_to_string(name); +Result BinaryReaderLinker::OnFunctionName(Index index, string_view name) { + binary_->debug_names[index] = name.to_string(); return Result::Ok; } -} // namespace +} // end anonymous namespace -Result read_binary_linker(LinkerInputBinary* input_info, LinkOptions* options) { +Result ReadBinaryLinker(LinkerInputBinary* input_info, LinkOptions* options) { BinaryReaderLinker reader(input_info); - ReadBinaryOptions read_options = WABT_READ_BINARY_OPTIONS_DEFAULT; + ReadBinaryOptions read_options; read_options.read_debug_names = true; read_options.log_stream = options->log_stream; - return read_binary(input_info->data, input_info->size, &reader, - &read_options); + return ReadBinary(DataOrNull(input_info->data), input_info->data.size(), + &reader, &read_options); } } // namespace link diff --git a/lib/wabt/src/binary-reader-linker.h b/lib/wabt/src/binary-reader-linker.h index 84b0f3c9a2b..73ae2f223bb 100644 --- a/lib/wabt/src/binary-reader-linker.h +++ b/lib/wabt/src/binary-reader-linker.h @@ -32,8 +32,7 @@ struct LinkOptions { Stream* log_stream; }; -Result read_binary_linker(LinkerInputBinary* input_info, - LinkOptions* options); +Result ReadBinaryLinker(LinkerInputBinary* input_info, LinkOptions* options); } // namespace link } // namespace wabt diff --git a/lib/wabt/src/binary-reader-logging.cc b/lib/wabt/src/binary-reader-logging.cc index 6cdc7ad5fdd..8af5212519d 100644 --- a/lib/wabt/src/binary-reader-logging.cc +++ b/lib/wabt/src/binary-reader-logging.cc @@ -34,7 +34,7 @@ namespace wabt { namespace { -void sprint_limits(char* dst, size_t size, const Limits* limits) { +void SPrintLimits(char* dst, size_t size, const Limits* limits) { int result; if (limits->has_max) { result = wabt_snprintf(dst, size, "initial: %" PRIu64 ", max: %" PRIu64, @@ -46,7 +46,7 @@ void sprint_limits(char* dst, size_t size, const Limits* limits) { assert(static_cast(result) < size); } -} // namespace +} // end anonymous namespace BinaryReaderLogging::BinaryReaderLogging(Stream* stream, BinaryReaderDelegate* forward) @@ -79,13 +79,17 @@ void BinaryReaderLogging::WriteIndent() { void BinaryReaderLogging::LogTypes(Index type_count, Type* types) { LOGF_NOINDENT("["); for (Index i = 0; i < type_count; ++i) { - LOGF_NOINDENT("%s", get_type_name(types[i])); + LOGF_NOINDENT("%s", GetTypeName(types[i])); if (i != type_count - 1) LOGF_NOINDENT(", "); } LOGF_NOINDENT("]"); } +void BinaryReaderLogging::LogTypes(TypeVector& types) { + LogTypes(types.size(), types.data()); +} + bool BinaryReaderLogging::OnError(const char* message) { return reader->OnError(message); } @@ -107,9 +111,9 @@ Result BinaryReaderLogging::BeginSection(BinarySection section_type, } Result BinaryReaderLogging::BeginCustomSection(Offset size, - StringSlice section_name) { - LOGF("BeginCustomSection('" PRIstringslice "', size: %" PRIzd ")\n", - WABT_PRINTF_STRING_SLICE_ARG(section_name), size); + string_view section_name) { + LOGF("BeginCustomSection('" PRIstringview "', size: %" PRIzd ")\n", + WABT_PRINTF_STRING_VIEW_ARG(section_name), size); Indent(); return reader->BeginCustomSection(size, section_name); } @@ -129,18 +133,18 @@ Result BinaryReaderLogging::OnType(Index index, } Result BinaryReaderLogging::OnImport(Index index, - StringSlice module_name, - StringSlice field_name) { - LOGF("OnImport(index: %" PRIindex ", module: \"" PRIstringslice - "\", field: \"" PRIstringslice "\")\n", - index, WABT_PRINTF_STRING_SLICE_ARG(module_name), - WABT_PRINTF_STRING_SLICE_ARG(field_name)); + string_view module_name, + string_view field_name) { + LOGF("OnImport(index: %" PRIindex ", module: \"" PRIstringview + "\", field: \"" PRIstringview "\")\n", + index, WABT_PRINTF_STRING_VIEW_ARG(module_name), + WABT_PRINTF_STRING_VIEW_ARG(field_name)); return reader->OnImport(index, module_name, field_name); } Result BinaryReaderLogging::OnImportFunc(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index func_index, Index sig_index) { LOGF("OnImportFunc(import_index: %" PRIindex ", func_index: %" PRIindex @@ -151,27 +155,27 @@ Result BinaryReaderLogging::OnImportFunc(Index import_index, } Result BinaryReaderLogging::OnImportTable(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index table_index, Type elem_type, const Limits* elem_limits) { char buf[100]; - sprint_limits(buf, sizeof(buf), elem_limits); + SPrintLimits(buf, sizeof(buf), elem_limits); LOGF("OnImportTable(import_index: %" PRIindex ", table_index: %" PRIindex ", elem_type: %s, %s)\n", - import_index, table_index, get_type_name(elem_type), buf); + import_index, table_index, GetTypeName(elem_type), buf); return reader->OnImportTable(import_index, module_name, field_name, table_index, elem_type, elem_limits); } Result BinaryReaderLogging::OnImportMemory(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index memory_index, const Limits* page_limits) { char buf[100]; - sprint_limits(buf, sizeof(buf), page_limits); + SPrintLimits(buf, sizeof(buf), page_limits); LOGF("OnImportMemory(import_index: %" PRIindex ", memory_index: %" PRIindex ", %s)\n", import_index, memory_index, buf); @@ -180,54 +184,64 @@ Result BinaryReaderLogging::OnImportMemory(Index import_index, } Result BinaryReaderLogging::OnImportGlobal(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index global_index, Type type, bool mutable_) { LOGF("OnImportGlobal(import_index: %" PRIindex ", global_index: %" PRIindex ", type: %s, mutable: " "%s)\n", - import_index, global_index, get_type_name(type), + import_index, global_index, GetTypeName(type), mutable_ ? "true" : "false"); return reader->OnImportGlobal(import_index, module_name, field_name, global_index, type, mutable_); } +Result BinaryReaderLogging::OnImportException(Index import_index, + string_view module_name, + string_view field_name, + Index except_index, + TypeVector& sig) { + LOGF("OnImportException(import_index: %" PRIindex ", except_index: %" PRIindex + ", sig: ", + import_index, except_index); + LogTypes(sig); + LOGF_NOINDENT(")\n"); + return reader->OnImportException(import_index, module_name, field_name, + except_index, sig); +} + Result BinaryReaderLogging::OnTable(Index index, Type elem_type, const Limits* elem_limits) { char buf[100]; - sprint_limits(buf, sizeof(buf), elem_limits); + SPrintLimits(buf, sizeof(buf), elem_limits); LOGF("OnTable(index: %" PRIindex ", elem_type: %s, %s)\n", index, - get_type_name(elem_type), buf); + GetTypeName(elem_type), buf); return reader->OnTable(index, elem_type, elem_limits); } -Result BinaryReaderLogging::OnMemory(Index index, - const Limits* page_limits) { +Result BinaryReaderLogging::OnMemory(Index index, const Limits* page_limits) { char buf[100]; - sprint_limits(buf, sizeof(buf), page_limits); + SPrintLimits(buf, sizeof(buf), page_limits); LOGF("OnMemory(index: %" PRIindex ", %s)\n", index, buf); return reader->OnMemory(index, page_limits); } -Result BinaryReaderLogging::BeginGlobal(Index index, - Type type, - bool mutable_) { +Result BinaryReaderLogging::BeginGlobal(Index index, Type type, bool mutable_) { LOGF("BeginGlobal(index: %" PRIindex ", type: %s, mutable: %s)\n", index, - get_type_name(type), mutable_ ? "true" : "false"); + GetTypeName(type), mutable_ ? "true" : "false"); return reader->BeginGlobal(index, type, mutable_); } Result BinaryReaderLogging::OnExport(Index index, ExternalKind kind, Index item_index, - StringSlice name) { + string_view name) { LOGF("OnExport(index: %" PRIindex ", kind: %s, item_index: %" PRIindex - ", name: \"" PRIstringslice "\")\n", - index, get_kind_name(kind), item_index, - WABT_PRINTF_STRING_SLICE_ARG(name)); + ", name: \"" PRIstringview "\")\n", + index, GetKindName(kind), item_index, WABT_PRINTF_STRING_VIEW_ARG(name)); return reader->OnExport(index, kind, item_index, name); } @@ -235,7 +249,7 @@ Result BinaryReaderLogging::OnLocalDecl(Index decl_index, Index count, Type type) { LOGF("OnLocalDecl(index: %" PRIindex ", count: %" PRIindex ", type: %s)\n", - decl_index, count, get_type_name(type)); + decl_index, count, GetTypeName(type)); return reader->OnLocalDecl(decl_index, count, type); } @@ -270,6 +284,13 @@ Result BinaryReaderLogging::OnBrTableExpr(Index num_targets, default_target_depth); } +Result BinaryReaderLogging::OnExceptionType(Index index, TypeVector& sig) { + LOGF("OnType(index: %" PRIindex ", values: ", index); + LogTypes(sig); + LOGF_NOINDENT(")\n"); + return reader->OnExceptionType(index, sig); +} + Result BinaryReaderLogging::OnF32ConstExpr(uint32_t value_bits) { float value; memcpy(&value, &value_bits, sizeof(value)); @@ -306,8 +327,7 @@ Result BinaryReaderLogging::OnLoadExpr(Opcode opcode, Address offset) { LOGF("OnLoadExpr(opcode: \"%s\" (%u), align log2: %u, offset: %" PRIaddress ")\n", - get_opcode_name(opcode), static_cast(opcode), alignment_log2, - offset); + opcode.GetName(), opcode.GetCode(), alignment_log2, offset); return reader->OnLoadExpr(opcode, alignment_log2, offset); } @@ -323,11 +343,17 @@ Result BinaryReaderLogging::OnStoreExpr(Opcode opcode, Address offset) { LOGF("OnStoreExpr(opcode: \"%s\" (%u), align log2: %u, offset: %" PRIaddress ")\n", - get_opcode_name(opcode), static_cast(opcode), alignment_log2, - offset); + opcode.GetName(), opcode.GetCode(), alignment_log2, offset); return reader->OnStoreExpr(opcode, alignment_log2, offset); } +Result BinaryReaderLogging::OnTryExpr(Index num_types, Type* sig_types) { + LOGF("OnTryExpr(sig: "); + LogTypes(num_types, sig_types); + LOGF_NOINDENT(")\n"); + return reader->OnTryExpr(num_types, sig_types); +} + Result BinaryReaderLogging::OnDataSegmentData(Index index, const void* data, Address size) { @@ -345,9 +371,9 @@ Result BinaryReaderLogging::OnFunctionNameSubsection(Index index, return reader->OnFunctionNameSubsection(index, name_type, subsection_size); } -Result BinaryReaderLogging::OnFunctionName(Index index, StringSlice name) { - LOGF("OnFunctionName(index: %" PRIindex ", name: \"" PRIstringslice "\")\n", - index, WABT_PRINTF_STRING_SLICE_ARG(name)); +Result BinaryReaderLogging::OnFunctionName(Index index, string_view name) { + LOGF("OnFunctionName(index: %" PRIindex ", name: \"" PRIstringview "\")\n", + index, WABT_PRINTF_STRING_VIEW_ARG(name)); return reader->OnFunctionName(index, name); } @@ -362,10 +388,10 @@ Result BinaryReaderLogging::OnLocalNameSubsection(Index index, Result BinaryReaderLogging::OnLocalName(Index func_index, Index local_index, - StringSlice name) { + string_view name) { LOGF("OnLocalName(func_index: %" PRIindex ", local_index: %" PRIindex - ", name: \"" PRIstringslice "\")\n", - func_index, local_index, WABT_PRINTF_STRING_SLICE_ARG(name)); + ", name: \"" PRIstringview "\")\n", + func_index, local_index, WABT_PRINTF_STRING_VIEW_ARG(name)); return reader->OnLocalName(func_index, local_index, name); } @@ -404,11 +430,11 @@ Result BinaryReaderLogging::OnInitExprI64ConstExpr(Index index, Result BinaryReaderLogging::OnRelocCount(Index count, BinarySection section_code, - StringSlice section_name) { + string_view section_name) { LOGF("OnRelocCount(count: %" PRIindex - ", section: %s, section_name: " PRIstringslice ")\n", - count, get_section_name(section_code), - WABT_PRINTF_STRING_SLICE_ARG(section_name)); + ", section: %s, section_name: " PRIstringview ")\n", + count, GetSectionName(section_code), + WABT_PRINTF_STRING_VIEW_ARG(section_name)); return reader->OnRelocCount(count, section_code, section_name); } @@ -419,10 +445,16 @@ Result BinaryReaderLogging::OnReloc(RelocType type, int32_t signed_addend = static_cast(addend); LOGF("OnReloc(type: %s, offset: %" PRIzd ", index: %" PRIindex ", addend: %d)\n", - get_reloc_type_name(type), offset, index, signed_addend); + GetRelocTypeName(type), offset, index, signed_addend); return reader->OnReloc(type, offset, index, addend); } +Result BinaryReaderLogging::OnSymbolInfo(string_view name, uint32_t flags) { + LOGF("(OnSymbolInfo name: " PRIstringview ", flags: 0x%x)\n", + WABT_PRINTF_STRING_VIEW_ARG(name), flags); + return reader->OnSymbolInfo(name, flags); +} + #define DEFINE_BEGIN(name) \ Result BinaryReaderLogging::name(Offset size) { \ LOGF(#name "(%" PRIzd ")\n", size); \ @@ -456,11 +488,10 @@ Result BinaryReaderLogging::OnReloc(RelocType type, return reader->name(value0, value1); \ } -#define DEFINE_OPCODE(name) \ - Result BinaryReaderLogging::name(Opcode opcode) { \ - LOGF(#name "(\"%s\" (%u))\n", get_opcode_name(opcode), \ - static_cast(opcode)); \ - return reader->name(opcode); \ +#define DEFINE_OPCODE(name) \ + Result BinaryReaderLogging::name(Opcode opcode) { \ + LOGF(#name "(\"%s\" (%u))\n", opcode.GetName(), opcode.GetCode()); \ + return reader->name(opcode); \ } #define DEFINE0(name) \ @@ -517,6 +548,8 @@ DEFINE_INDEX(OnLocalDeclCount) DEFINE_OPCODE(OnBinaryExpr) DEFINE_INDEX_DESC(OnCallExpr, "func_index") DEFINE_INDEX_DESC(OnCallIndirectExpr, "sig_index") +DEFINE_INDEX_DESC(OnCatchExpr, "except_index"); +DEFINE0(OnCatchAllExpr) DEFINE_OPCODE(OnCompareExpr) DEFINE_OPCODE(OnConvertExpr) DEFINE0(OnCurrentMemoryExpr) @@ -527,11 +560,13 @@ DEFINE_INDEX_DESC(OnGetGlobalExpr, "index") DEFINE_INDEX_DESC(OnGetLocalExpr, "index") DEFINE0(OnGrowMemoryExpr) DEFINE0(OnNopExpr) +DEFINE_INDEX_DESC(OnRethrowExpr, "depth"); DEFINE0(OnReturnExpr) DEFINE0(OnSelectExpr) DEFINE_INDEX_DESC(OnSetGlobalExpr, "index") DEFINE_INDEX_DESC(OnSetLocalExpr, "index") DEFINE_INDEX_DESC(OnTeeLocalExpr, "index") +DEFINE_INDEX_DESC(OnThrowExpr, "except_index") DEFINE0(OnUnreachableExpr) DEFINE_OPCODE(OnUnaryExpr) DEFINE_END(EndCodeSection) @@ -564,6 +599,16 @@ DEFINE_BEGIN(BeginRelocSection) DEFINE_END(EndRelocSection) DEFINE_INDEX_INDEX(OnInitExprGetGlobalExpr, "index", "global_index") +DEFINE_BEGIN(BeginLinkingSection) +DEFINE_INDEX(OnSymbolInfoCount) +DEFINE_INDEX(OnStackGlobal) +DEFINE_END(EndLinkingSection) + +DEFINE_BEGIN(BeginExceptionSection); +DEFINE_INDEX(OnExceptionCount); + +DEFINE_END(EndExceptionSection); + // We don't need to log these (the individual opcodes are logged instead), but // we still need to forward the calls. Result BinaryReaderLogging::OnOpcode(Opcode opcode) { diff --git a/lib/wabt/src/binary-reader-logging.h b/lib/wabt/src/binary-reader-logging.h index db868d13ce7..c7eef65283e 100644 --- a/lib/wabt/src/binary-reader-logging.h +++ b/lib/wabt/src/binary-reader-logging.h @@ -35,7 +35,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Result BeginSection(BinarySection section_type, Offset size) override; - Result BeginCustomSection(Offset size, StringSlice section_name) override; + Result BeginCustomSection(Offset size, string_view section_name) override; Result EndCustomSection() override; Result BeginTypeSection(Offset size) override; @@ -50,30 +50,35 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Result BeginImportSection(Offset size) override; Result OnImportCount(Index count) override; Result OnImport(Index index, - StringSlice module_name, - StringSlice field_name) override; + string_view module_name, + string_view field_name) override; Result OnImportFunc(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index func_index, Index sig_index) override; Result OnImportTable(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index table_index, Type elem_type, const Limits* elem_limits) override; Result OnImportMemory(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index memory_index, const Limits* page_limits) override; Result OnImportGlobal(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index global_index, Type type, bool mutable_) override; + Result OnImportException(Index import_index, + string_view module_name, + string_view field_name, + Index except_index, + TypeVector& sig) override; Result EndImportSection() override; Result BeginFunctionSection(Offset size) override; @@ -106,7 +111,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Result OnExport(Index index, ExternalKind kind, Index item_index, - StringSlice name) override; + string_view name) override; Result EndExportSection() override; Result BeginStartSection(Offset size) override; @@ -136,6 +141,8 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Index* target_depths, Index default_target_depth) override; Result OnCallExpr(Index func_index) override; + Result OnCatchExpr(Index except_index) override; + Result OnCatchAllExpr() override; Result OnCallIndirectExpr(Index sig_index) override; Result OnCompareExpr(Opcode opcode) override; Result OnConvertExpr(Opcode opcode) override; @@ -157,6 +164,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Address offset) override; Result OnLoopExpr(Index num_types, Type* sig_types) override; Result OnNopExpr() override; + Result OnRethrowExpr(Index depth) override; Result OnReturnExpr() override; Result OnSelectExpr() override; Result OnSetGlobalExpr(Index global_index) override; @@ -165,6 +173,8 @@ class BinaryReaderLogging : public BinaryReaderDelegate { uint32_t alignment_log2, Address offset) override; Result OnTeeLocalExpr(Index local_index) override; + Result OnThrowExpr(Index except_index) override; + Result OnTryExpr(Index num_types, Type* sig_types) override; Result OnUnaryExpr(Opcode opcode) override; Result OnUnreachableExpr() override; Result EndFunctionBody(Index index) override; @@ -199,7 +209,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Offset subsection_size) override; Result OnFunctionNamesCount(Index num_functions) override; Result OnFunctionName(Index function_index, - StringSlice function_name) override; + string_view function_name) override; Result OnLocalNameSubsection(Index index, uint32_t name_type, Offset subsection_size) override; @@ -208,19 +218,30 @@ class BinaryReaderLogging : public BinaryReaderDelegate { Index num_locals) override; Result OnLocalName(Index function_index, Index local_index, - StringSlice local_name) override; + string_view local_name) override; Result EndNamesSection() override; Result BeginRelocSection(Offset size) override; Result OnRelocCount(Index count, BinarySection section_code, - StringSlice section_name) override; + string_view section_name) override; Result OnReloc(RelocType type, Offset offset, Index index, uint32_t addend) override; Result EndRelocSection() override; + Result BeginLinkingSection(Offset size) override; + Result OnStackGlobal(Index stack_global) override; + Result OnSymbolInfo(string_view name, uint32_t flags) override; + Result OnSymbolInfoCount(Index count) override; + Result EndLinkingSection() override; + + Result BeginExceptionSection(Offset size) override; + Result OnExceptionCount(Index count) override; + Result OnExceptionType(Index index, TypeVector& sig) override; + Result EndExceptionSection() override; + Result OnInitExprF32ConstExpr(Index index, uint32_t value) override; Result OnInitExprF64ConstExpr(Index index, uint64_t value) override; Result OnInitExprGetGlobalExpr(Index index, @@ -233,6 +254,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate { void Dedent(); void WriteIndent(); void LogTypes(Index type_count, Type* types); + void LogTypes(TypeVector& types); Stream* stream; BinaryReaderDelegate* reader; diff --git a/lib/wabt/src/binary-reader-nop.h b/lib/wabt/src/binary-reader-nop.h index 7af11f7b02f..a85e79aa0a3 100644 --- a/lib/wabt/src/binary-reader-nop.h +++ b/lib/wabt/src/binary-reader-nop.h @@ -34,7 +34,7 @@ class BinaryReaderNop : public BinaryReaderDelegate { } /* Custom section */ - Result BeginCustomSection(Offset size, StringSlice section_name) override { + Result BeginCustomSection(Offset size, string_view section_name) override { return Result::Ok; } Result EndCustomSection() override { return Result::Ok; } @@ -55,40 +55,47 @@ class BinaryReaderNop : public BinaryReaderDelegate { Result BeginImportSection(Offset size) override { return Result::Ok; } Result OnImportCount(Index count) override { return Result::Ok; } Result OnImport(Index index, - StringSlice module_name, - StringSlice field_name) override { + string_view module_name, + string_view field_name) override { return Result::Ok; } Result OnImportFunc(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index func_index, Index sig_index) override { return Result::Ok; } Result OnImportTable(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index table_index, Type elem_type, const Limits* elem_limits) override { return Result::Ok; } Result OnImportMemory(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index memory_index, const Limits* page_limits) override { return Result::Ok; } Result OnImportGlobal(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index global_index, Type type, bool mutable_) override { return Result::Ok; } + Result OnImportException(Index import_index, + string_view module_name, + string_view field_name, + Index except_index, + TypeVector& sig) override { + return Result::Ok; + } Result EndImportSection() override { return Result::Ok; } /* Function section */ @@ -134,7 +141,7 @@ class BinaryReaderNop : public BinaryReaderDelegate { Result OnExport(Index index, ExternalKind kind, Index item_index, - StringSlice name) override { + string_view name) override { return Result::Ok; } Result EndExportSection() override { return Result::Ok; } @@ -181,6 +188,8 @@ class BinaryReaderNop : public BinaryReaderDelegate { } Result OnCallExpr(Index func_index) override { return Result::Ok; } Result OnCallIndirectExpr(Index sig_index) override { return Result::Ok; } + Result OnCatchExpr(Index except_index) override { return Result::Ok; } + Result OnCatchAllExpr() override { return Result::Ok; } Result OnCompareExpr(Opcode opcode) override { return Result::Ok; } Result OnConvertExpr(Opcode opcode) override { return Result::Ok; } Result OnCurrentMemoryExpr() override { return Result::Ok; } @@ -207,6 +216,7 @@ class BinaryReaderNop : public BinaryReaderDelegate { return Result::Ok; } Result OnNopExpr() override { return Result::Ok; } + Result OnRethrowExpr(Index depth) override { return Result::Ok; } Result OnReturnExpr() override { return Result::Ok; } Result OnSelectExpr() override { return Result::Ok; } Result OnSetGlobalExpr(Index global_index) override { return Result::Ok; } @@ -217,6 +227,10 @@ class BinaryReaderNop : public BinaryReaderDelegate { return Result::Ok; } Result OnTeeLocalExpr(Index local_index) override { return Result::Ok; } + Result OnThrowExpr(Index depth) override { return Result::Ok; } + Result OnTryExpr(Index num_types, Type* sig_types) override { + return Result::Ok; + } Result OnUnaryExpr(Opcode opcode) override { return Result::Ok; } Result OnUnreachableExpr() override { return Result::Ok; } Result EndFunctionBody(Index index) override { return Result::Ok; } @@ -266,7 +280,7 @@ class BinaryReaderNop : public BinaryReaderDelegate { return Result::Ok; } Result OnFunctionName(Index function_index, - StringSlice function_name) override { + string_view function_name) override { return Result::Ok; } Result OnLocalNameSubsection(Index index, @@ -283,7 +297,7 @@ class BinaryReaderNop : public BinaryReaderDelegate { } Result OnLocalName(Index function_index, Index local_index, - StringSlice local_name) override { + string_view local_name) override { return Result::Ok; } Result EndNamesSection() override { return Result::Ok; } @@ -292,7 +306,7 @@ class BinaryReaderNop : public BinaryReaderDelegate { Result BeginRelocSection(Offset size) override { return Result::Ok; } Result OnRelocCount(Index count, BinarySection section_code, - StringSlice section_name) override { + string_view section_name) override { return Result::Ok; } Result OnReloc(RelocType type, @@ -303,6 +317,23 @@ class BinaryReaderNop : public BinaryReaderDelegate { } Result EndRelocSection() override { return Result::Ok; } + /* Exception section */ + Result BeginExceptionSection(Offset size) override { return Result::Ok; } + Result OnExceptionCount(Index count) override { return Result::Ok; } + Result OnExceptionType(Index index, TypeVector& sig) override { + return Result::Ok; + } + Result EndExceptionSection() override { return Result::Ok; } + + /* Linking section */ + Result BeginLinkingSection(Offset size) override { return Result::Ok; } + Result OnStackGlobal(Index stack_global) override { return Result::Ok; } + Result OnSymbolInfoCount(Index count) override { return Result::Ok; } + Result OnSymbolInfo(string_view name, uint32_t flags) override { + return Result::Ok; + } + Result EndLinkingSection() override { return Result::Ok; } + /* InitExpr - used by elem, data and global sections; these functions are * only called between calls to Begin*InitExpr and End*InitExpr */ Result OnInitExprF32ConstExpr(Index index, uint32_t value) override { diff --git a/lib/wabt/src/binary-reader-objdump.cc b/lib/wabt/src/binary-reader-objdump.cc index f80248ba14d..ad8f600f10d 100644 --- a/lib/wabt/src/binary-reader-objdump.cc +++ b/lib/wabt/src/binary-reader-objdump.cc @@ -42,10 +42,14 @@ class BinaryReaderObjdumpBase : public BinaryReaderNop { Result OnRelocCount(Index count, BinarySection section_code, - StringSlice section_name) override; + string_view section_name) override; protected: - const char* GetFunctionName(Index index); + const char* GetFunctionName(Index index) const; + void PrintRelocation(const Reloc& reloc, Offset offset) const; + Offset GetSectionStart(BinarySection section_code) const { + return section_starts[static_cast(section_code)]; + } ObjdumpOptions* options; ObjdumpState* objdump_state; @@ -65,7 +69,7 @@ BinaryReaderObjdumpBase::BinaryReaderObjdumpBase(const uint8_t* data, objdump_state(objdump_state), data(data), size(size) { - WABT_ZERO_MEMORY(section_starts); + ZeroMemory(section_starts); } Result BinaryReaderObjdumpBase::BeginSection(BinarySection section_code, @@ -112,7 +116,7 @@ Result BinaryReaderObjdumpBase::BeginModule(uint32_t version) { return Result::Ok; } -const char* BinaryReaderObjdumpBase::GetFunctionName(Index index) { +const char* BinaryReaderObjdumpBase::GetFunctionName(Index index) const { if (index >= objdump_state->function_names.size() || objdump_state->function_names[index].empty()) return nullptr; @@ -120,9 +124,29 @@ const char* BinaryReaderObjdumpBase::GetFunctionName(Index index) { return objdump_state->function_names[index].c_str(); } +void BinaryReaderObjdumpBase::PrintRelocation(const Reloc& reloc, + Offset offset) const { + printf(" %06" PRIzx ": %-18s %" PRIindex "", offset, + GetRelocTypeName(reloc.type), reloc.index); + switch (reloc.type) { + case RelocType::GlobalAddressLEB: + case RelocType::GlobalAddressSLEB: + case RelocType::GlobalAddressI32: + printf(" + %d", reloc.addend); + break; + case RelocType::FuncIndexLEB: + if (const char* name = GetFunctionName(reloc.index)) { + printf(" <%s>", name); + } + default: + break; + } + printf("\n"); +} + Result BinaryReaderObjdumpBase::OnRelocCount(Index count, BinarySection section_code, - StringSlice section_name) { + string_view section_name) { reloc_section = section_code; return Result::Ok; } @@ -132,7 +156,7 @@ class BinaryReaderObjdumpPrepass : public BinaryReaderObjdumpBase { using BinaryReaderObjdumpBase::BinaryReaderObjdumpBase; Result OnFunctionName(Index function_index, - StringSlice function_name) override; + string_view function_name) override; Result OnReloc(RelocType type, Offset offset, Index index, @@ -140,9 +164,9 @@ class BinaryReaderObjdumpPrepass : public BinaryReaderObjdumpBase { }; Result BinaryReaderObjdumpPrepass::OnFunctionName(Index index, - StringSlice name) { + string_view name) { objdump_state->function_names.resize(index + 1); - objdump_state->function_names[index] = string_slice_to_string(name); + objdump_state->function_names[index] = name.to_string(); return Result::Ok; } @@ -153,6 +177,8 @@ Result BinaryReaderObjdumpPrepass::OnReloc(RelocType type, BinaryReaderObjdumpBase::OnReloc(type, offset, index, addend); if (reloc_section == BinarySection::Code) { objdump_state->code_relocations.emplace_back(type, offset, index, addend); + } else if (reloc_section == BinarySection::Data) { + objdump_state->data_relocations.emplace_back(type, offset, index, addend); } return Result::Ok; } @@ -184,24 +210,24 @@ class BinaryReaderObjdumpDisassemble : public BinaryReaderObjdumpBase { Opcode current_opcode = Opcode::Unreachable; Offset current_opcode_offset = 0; - size_t last_opcode_end = 0; + Offset last_opcode_end = 0; int indent_level = 0; Index next_reloc = 0; }; Result BinaryReaderObjdumpDisassemble::OnOpcode(Opcode opcode) { if (options->debug) { - const char* opcode_name = get_opcode_name(opcode); + const char* opcode_name = opcode.GetName(); printf("on_opcode: %#" PRIzx ": %s\n", state->offset, opcode_name); } if (last_opcode_end) { - if (state->offset != last_opcode_end + 1) { - uint8_t missing_opcode = data[last_opcode_end]; - const char* opcode_name = - get_opcode_name(static_cast(missing_opcode)); - fprintf(stderr, "warning: %#" PRIzx " missing opcode callback at %#" PRIzx - " (%#02x=%s)\n", + if (state->offset != last_opcode_end + opcode.GetLength()) { + Opcode missing_opcode = Opcode::FromCode(data[last_opcode_end]); + const char* opcode_name = missing_opcode.GetName(); + fprintf(stderr, + "warning: %#" PRIzx " missing opcode callback at %#" PRIzx + " (%#02x=%s)\n", state->offset, last_opcode_end + 1, data[last_opcode_end], opcode_name); return Result::Error; @@ -216,32 +242,41 @@ Result BinaryReaderObjdumpDisassemble::OnOpcode(Opcode opcode) { #define IMMEDIATE_OCTET_COUNT 9 void BinaryReaderObjdumpDisassemble::LogOpcode(const uint8_t* data, - size_t data_size, - const char* fmt, - ...) { + size_t data_size, + const char* fmt, + ...) { Offset offset = current_opcode_offset; // Print binary data - printf(" %06" PRIzx ": %02x", offset - 1, - static_cast(current_opcode)); + printf(" %06" PRIzx ":", offset - 1); + if (current_opcode.HasPrefix()) + printf(" %02x", current_opcode.GetPrefix()); + printf(" %02x", current_opcode.GetCode()); for (size_t i = 0; i < data_size && i < IMMEDIATE_OCTET_COUNT; i++, offset++) { printf(" %02x", data[offset]); } - for (size_t i = data_size + 1; i < IMMEDIATE_OCTET_COUNT; i++) { + for (size_t i = data_size + current_opcode.GetLength(); + i < IMMEDIATE_OCTET_COUNT; i++) { printf(" "); } printf(" | "); // Print disassemble int indent_level = this->indent_level; - if (current_opcode == Opcode::Else) - indent_level--; + switch (current_opcode) { + case Opcode::Else: + case Opcode::Catch: + case Opcode::CatchAll: + indent_level--; + default: + break; + } for (int j = 0; j < indent_level; j++) { printf(" "); } - const char* opcode_name = get_opcode_name(current_opcode); + const char* opcode_name = current_opcode.GetName(); printf("%s", opcode_name); if (fmt) { printf(" "); @@ -256,27 +291,11 @@ void BinaryReaderObjdumpDisassemble::LogOpcode(const uint8_t* data, last_opcode_end = current_opcode_offset + data_size; if (options->relocs && next_reloc < objdump_state->code_relocations.size()) { - Reloc* reloc = &objdump_state->code_relocations[next_reloc]; - Offset code_start = - section_starts[static_cast(BinarySection::Code)]; - Offset abs_offset = code_start + reloc->offset; + const Reloc& reloc = objdump_state->code_relocations[next_reloc]; + Offset code_start = GetSectionStart(BinarySection::Code); + Offset abs_offset = code_start + reloc.offset; if (last_opcode_end > abs_offset) { - printf(" %06" PRIzx ": %-18s %" PRIindex "", abs_offset, - get_reloc_type_name(reloc->type), reloc->index); - switch (reloc->type) { - case RelocType::GlobalAddressLEB: - case RelocType::GlobalAddressSLEB: - case RelocType::GlobalAddressI32: - printf(" + %d", reloc->addend); - break; - case RelocType::FuncIndexLEB: - if (const char* name = GetFunctionName(reloc->index)) { - printf(" <%s>", name); - } - default: - break; - } - printf("\n"); + PrintRelocation(reloc, abs_offset); next_reloc++; } } @@ -319,7 +338,7 @@ Result BinaryReaderObjdumpDisassemble::OnOpcodeUint64(uint64_t value) { Result BinaryReaderObjdumpDisassemble::OnOpcodeF32(uint32_t value) { Offset immediate_len = state->offset - current_opcode_offset; char buffer[WABT_MAX_FLOAT_HEX]; - write_float_hex(buffer, sizeof(buffer), value); + WriteFloatHex(buffer, sizeof(buffer), value); LogOpcode(data, immediate_len, buffer); return Result::Ok; } @@ -327,7 +346,7 @@ Result BinaryReaderObjdumpDisassemble::OnOpcodeF32(uint32_t value) { Result BinaryReaderObjdumpDisassemble::OnOpcodeF64(uint64_t value) { Offset immediate_len = state->offset - current_opcode_offset; char buffer[WABT_MAX_DOUBLE_HEX]; - write_double_hex(buffer, sizeof(buffer), value); + WriteDoubleHex(buffer, sizeof(buffer), value); LogOpcode(data, immediate_len, buffer); return Result::Ok; } @@ -395,6 +414,25 @@ Result BinaryReaderObjdumpDisassemble::OnOpcodeBlockSig(Index num_types, return Result::Ok; } +enum class InitExprType { + I32, + F32, + I64, + F64, + Global, +}; + +struct InitExpr { + InitExprType type; + union { + Index global; + uint32_t i32; + uint32_t f32; + uint64_t i64; + uint64_t f64; + } value; +}; + class BinaryReaderObjdump : public BinaryReaderObjdumpBase { public: BinaryReaderObjdump(const uint8_t* data, @@ -404,7 +442,7 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { Result EndModule() override; Result BeginSection(BinarySection section_type, Offset size) override; - Result BeginCustomSection(Offset size, StringSlice section_name) override; + Result BeginCustomSection(Offset size, string_view section_name) override; Result OnTypeCount(Index count) override; Result OnType(Index index, @@ -415,27 +453,33 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { Result OnImportCount(Index count) override; Result OnImportFunc(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index func_index, Index sig_index) override; Result OnImportTable(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index table_index, Type elem_type, const Limits* elem_limits) override; Result OnImportMemory(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index memory_index, const Limits* page_limits) override; Result OnImportGlobal(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index global_index, Type type, bool mutable_) override; + Result OnImportException(Index import_index, + string_view module_name, + string_view field_name, + Index except_index, + TypeVector& sig) override; + Result OnFunctionCount(Index count) override; Result OnFunction(Index index, Index sig_index) override; @@ -455,7 +499,7 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { Result OnExport(Index index, ExternalKind kind, Index item_index, - StringSlice name) override; + string_view name) override; Result OnStartFunction(Index func_index) override; @@ -466,6 +510,14 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { Result OnElemSegmentFunctionIndex(Index segment_index, Index func_index) override; + Result BeginDataSection(Offset size) override { + in_data_section_ = true; + return Result::Ok; + } + Result EndDataSection() override { + in_data_section_ = false; + return Result::Ok; + } Result OnDataSegmentCount(Index count) override; Result BeginDataSegment(Index index, Index memory_index) override; Result OnDataSegmentData(Index index, @@ -473,10 +525,10 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { Address size) override; Result OnFunctionName(Index function_index, - StringSlice function_name) override; + string_view function_name) override; Result OnLocalName(Index function_index, Index local_index, - StringSlice local_name) override; + string_view local_name) override; Result OnInitExprF32ConstExpr(Index index, uint32_t value) override; Result OnInitExprF64ConstExpr(Index index, uint64_t value) override; @@ -486,19 +538,30 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { Result OnRelocCount(Index count, BinarySection section_code, - StringSlice section_name) override; + string_view section_name) override; Result OnReloc(RelocType type, Offset offset, Index index, uint32_t addend) override; + Result OnStackGlobal(Index stack_global) override; + Result OnSymbolInfoCount(Index count) override; + Result OnSymbolInfo(string_view name, uint32_t flags) override; + + Result OnExceptionCount(Index count) override; + Result OnExceptionType(Index index, TypeVector& sig) override; + private: bool ShouldPrintDetails(); void PrintDetails(const char* fmt, ...); + void PrintInitExpr(const InitExpr &expr); Result OnCount(Index count); std::unique_ptr out_stream_; Index elem_index_ = 0; + Index next_data_reloc_ = 0; + bool in_data_section_ = false; + InitExpr data_init_expr_; }; BinaryReaderObjdump::BinaryReaderObjdump(const uint8_t* data, @@ -509,12 +572,12 @@ BinaryReaderObjdump::BinaryReaderObjdump(const uint8_t* data, out_stream_(FileStream::CreateStdout()) {} Result BinaryReaderObjdump::BeginCustomSection(Offset size, - StringSlice section_name) { - PrintDetails(" - name: \"" PRIstringslice "\"\n", - WABT_PRINTF_STRING_SLICE_ARG(section_name)); + string_view section_name) { + PrintDetails(" - name: \"" PRIstringview "\"\n", + WABT_PRINTF_STRING_VIEW_ARG(section_name)); if (options->mode == ObjdumpMode::Headers) { - printf("\"" PRIstringslice "\"\n", - WABT_PRINTF_STRING_SLICE_ARG(section_name)); + printf("\"" PRIstringview "\"\n", + WABT_PRINTF_STRING_VIEW_ARG(section_name)); } return Result::Ok; } @@ -523,7 +586,7 @@ Result BinaryReaderObjdump::BeginSection(BinarySection section_code, Offset size) { BinaryReaderObjdumpBase::BeginSection(section_code, size); - const char* name = get_section_name(section_code); + const char* name = GetSectionName(section_code); bool section_match = !options->section_name || !strcasecmp(options->section_name, name); @@ -549,7 +612,7 @@ Result BinaryReaderObjdump::BeginSection(BinarySection section_code, if (section_match) { printf("\nContents of section %s:\n", name); out_stream_->WriteMemoryDump(data + state->offset, size, state->offset, - nullptr, nullptr, PrintChars::Yes); + PrintChars::Yes); } break; case ObjdumpMode::Prepass: @@ -584,10 +647,17 @@ Result BinaryReaderObjdump::OnCount(Index count) { Result BinaryReaderObjdump::EndModule() { if (options->section_name && !section_found) { - printf("Section not found: %s\n", options->section_name); + fprintf(stderr, "Section not found: %s\n", options->section_name); return Result::Error; } + if (options->relocs) { + if (next_data_reloc_ != objdump_state->data_relocations.size()) { + fprintf(stderr, "Data reloctions outside of segments\n"); + return Result::Error; + } + } + return Result::Ok; } @@ -648,56 +718,73 @@ Result BinaryReaderObjdump::OnImportCount(Index count) { } Result BinaryReaderObjdump::OnImportFunc(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index func_index, Index sig_index) { PrintDetails(" - func[%" PRIindex "] sig=%" PRIindex, func_index, sig_index); if (const char* name = GetFunctionName(func_index)) PrintDetails(" <%s>", name); - PrintDetails(" <- " PRIstringslice "." PRIstringslice "\n", - WABT_PRINTF_STRING_SLICE_ARG(module_name), - WABT_PRINTF_STRING_SLICE_ARG(field_name)); + PrintDetails(" <- " PRIstringview "." PRIstringview "\n", + WABT_PRINTF_STRING_VIEW_ARG(module_name), + WABT_PRINTF_STRING_VIEW_ARG(field_name)); return Result::Ok; } Result BinaryReaderObjdump::OnImportTable(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index table_index, Type elem_type, const Limits* elem_limits) { - PrintDetails(" - " PRIstringslice "." PRIstringslice + PrintDetails(" - " PRIstringview "." PRIstringview " -> table elem_type=%s init=%" PRId64 " max=%" PRId64 "\n", - WABT_PRINTF_STRING_SLICE_ARG(module_name), - WABT_PRINTF_STRING_SLICE_ARG(field_name), - get_type_name(elem_type), elem_limits->initial, - elem_limits->max); + WABT_PRINTF_STRING_VIEW_ARG(module_name), + WABT_PRINTF_STRING_VIEW_ARG(field_name), GetTypeName(elem_type), + elem_limits->initial, elem_limits->max); return Result::Ok; } Result BinaryReaderObjdump::OnImportMemory(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index memory_index, const Limits* page_limits) { - PrintDetails(" - " PRIstringslice "." PRIstringslice " -> memory\n", - WABT_PRINTF_STRING_SLICE_ARG(module_name), - WABT_PRINTF_STRING_SLICE_ARG(field_name)); + PrintDetails(" - " PRIstringview "." PRIstringview " -> memory\n", + WABT_PRINTF_STRING_VIEW_ARG(module_name), + WABT_PRINTF_STRING_VIEW_ARG(field_name)); return Result::Ok; } Result BinaryReaderObjdump::OnImportGlobal(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index global_index, Type type, bool mutable_) { - PrintDetails(" - global[%" PRIindex "] %s mutable=%d <- " PRIstringslice - "." PRIstringslice "\n", - global_index, get_type_name(type), mutable_, - WABT_PRINTF_STRING_SLICE_ARG(module_name), - WABT_PRINTF_STRING_SLICE_ARG(field_name)); + PrintDetails(" - global[%" PRIindex "] %s mutable=%d <- " PRIstringview + "." PRIstringview "\n", + global_index, GetTypeName(type), mutable_, + WABT_PRINTF_STRING_VIEW_ARG(module_name), + WABT_PRINTF_STRING_VIEW_ARG(field_name)); + return Result::Ok; +} + +Result BinaryReaderObjdump::OnImportException(Index import_index, + string_view module_name, + string_view field_name, + Index except_index, + TypeVector& sig) { + PrintDetails(" - except[%" PRIindex "] (", except_index); + for (Index i = 0; i < sig.size(); ++i) { + if (i != 0) { + PrintDetails(", "); + } + PrintDetails("%s", type_name(sig[i])); + } + PrintDetails(") <- " PRIstringview "." PRIstringview "\n", + WABT_PRINTF_STRING_VIEW_ARG(module_name), + WABT_PRINTF_STRING_VIEW_ARG(field_name)); return Result::Ok; } @@ -722,7 +809,7 @@ Result BinaryReaderObjdump::OnTable(Index index, Type elem_type, const Limits* elem_limits) { PrintDetails(" - table[%" PRIindex "] type=%s initial=%" PRId64, index, - get_type_name(elem_type), elem_limits->initial); + GetTypeName(elem_type), elem_limits->initial); if (elem_limits->has_max) PrintDetails(" max=%" PRId64, elem_limits->max); PrintDetails("\n"); @@ -736,15 +823,15 @@ Result BinaryReaderObjdump::OnExportCount(Index count) { Result BinaryReaderObjdump::OnExport(Index index, ExternalKind kind, Index item_index, - StringSlice name) { - PrintDetails(" - %s[%" PRIindex "]", get_kind_name(kind), item_index); + string_view name) { + PrintDetails(" - %s[%" PRIindex "]", GetKindName(kind), item_index); if (kind == ExternalKind::Func) { if (const char* name = GetFunctionName(item_index)) PrintDetails(" <%s>", name); } - PrintDetails(" -> \"" PRIstringslice "\"\n", - WABT_PRINTF_STRING_SLICE_ARG(name)); + PrintDetails(" -> \"" PRIstringview "\"\n", + WABT_PRINTF_STRING_VIEW_ARG(name)); return Result::Ok; } @@ -776,57 +863,114 @@ Result BinaryReaderObjdump::OnGlobalCount(Index count) { Result BinaryReaderObjdump::BeginGlobal(Index index, Type type, bool mutable_) { PrintDetails(" - global[%" PRIindex "] %s mutable=%d", index, - get_type_name(type), mutable_); + GetTypeName(type), mutable_); return Result::Ok; } +void BinaryReaderObjdump::PrintInitExpr(const InitExpr& expr) { + switch (expr.type) { + case InitExprType::I32: + PrintDetails(" - init i32=%d\n", expr.value.i32); + break; + case InitExprType::I64: + PrintDetails(" - init i64=%" PRId64 "\n", expr.value.i64); + break; + case InitExprType::F64: { + char buffer[WABT_MAX_DOUBLE_HEX]; + WriteFloatHex(buffer, sizeof(buffer), expr.value.f64); + PrintDetails(" - init f64=%s\n", buffer); + break; + } + case InitExprType::F32: { + char buffer[WABT_MAX_FLOAT_HEX]; + WriteFloatHex(buffer, sizeof(buffer), expr.value.f32); + PrintDetails(" - init f32=%s\n", buffer); + break; + } + case InitExprType::Global: + PrintDetails(" - init global=%" PRIindex "\n", expr.value.global); + break; + } +} + Result BinaryReaderObjdump::OnInitExprF32ConstExpr(Index index, uint32_t value) { - char buffer[WABT_MAX_FLOAT_HEX]; - write_float_hex(buffer, sizeof(buffer), value); - PrintDetails(" - init f32=%s\n", buffer); + InitExpr expr; + expr.type = InitExprType::F32; + expr.value.f32 = value; + if (in_data_section_) { + data_init_expr_ = expr; + } else { + PrintInitExpr(expr); + } return Result::Ok; } Result BinaryReaderObjdump::OnInitExprF64ConstExpr(Index index, uint64_t value) { - char buffer[WABT_MAX_DOUBLE_HEX]; - write_float_hex(buffer, sizeof(buffer), value); - PrintDetails(" - init f64=%s\n", buffer); + InitExpr expr; + expr.type = InitExprType::F64; + expr.value.f64 = value; + if (in_data_section_) { + data_init_expr_ = expr; + } else { + PrintInitExpr(expr); + } return Result::Ok; } Result BinaryReaderObjdump::OnInitExprGetGlobalExpr(Index index, Index global_index) { - PrintDetails(" - init global=%" PRIindex "\n", global_index); + InitExpr expr; + expr.type = InitExprType::Global; + expr.value.global = global_index; + if (in_data_section_) { + data_init_expr_ = expr; + } else { + PrintInitExpr(expr); + } return Result::Ok; } Result BinaryReaderObjdump::OnInitExprI32ConstExpr(Index index, uint32_t value) { - PrintDetails(" - init i32=%d\n", value); + InitExpr expr; + expr.type = InitExprType::I32; + expr.value.i32 = value; + if (in_data_section_) { + data_init_expr_ = expr; + } else { + PrintInitExpr(expr); + } return Result::Ok; } Result BinaryReaderObjdump::OnInitExprI64ConstExpr(Index index, uint64_t value) { - PrintDetails(" - init i64=%" PRId64 "\n", value); + InitExpr expr; + expr.type = InitExprType::I64; + expr.value.i64 = value; + if (in_data_section_) { + data_init_expr_ = expr; + } else { + PrintInitExpr(expr); + } return Result::Ok; } -Result BinaryReaderObjdump::OnFunctionName(Index index, StringSlice name) { - PrintDetails(" - func[%" PRIindex "] " PRIstringslice "\n", index, - WABT_PRINTF_STRING_SLICE_ARG(name)); +Result BinaryReaderObjdump::OnFunctionName(Index index, string_view name) { + PrintDetails(" - func[%" PRIindex "] " PRIstringview "\n", index, + WABT_PRINTF_STRING_VIEW_ARG(name)); return Result::Ok; } Result BinaryReaderObjdump::OnLocalName(Index func_index, Index local_index, - StringSlice name) { - if (name.length) { - PrintDetails(" - func[%" PRIindex "] local[%" PRIindex "] " PRIstringslice + string_view name) { + if (!name.empty()) { + PrintDetails(" - func[%" PRIindex "] local[%" PRIindex "] " PRIstringview "\n", - func_index, local_index, WABT_PRINTF_STRING_SLICE_ARG(name)); + func_index, local_index, WABT_PRINTF_STRING_VIEW_ARG(name)); } return Result::Ok; } @@ -836,25 +980,62 @@ Result BinaryReaderObjdump::OnDataSegmentCount(Index count) { } Result BinaryReaderObjdump::BeginDataSegment(Index index, Index memory_index) { - PrintDetails(" - memory[%" PRIindex "]", memory_index); + // TODO(sbc): Display memory_index once multiple memories become a thing + //PrintDetails(" - memory[%" PRIindex "]", memory_index); return Result::Ok; } Result BinaryReaderObjdump::OnDataSegmentData(Index index, const void* src_data, Address size) { - if (ShouldPrintDetails()) { - out_stream_->WriteMemoryDump(src_data, size, state->offset - size, " - ", - nullptr, PrintChars::Yes); + if (!ShouldPrintDetails()) + return Result::Ok; + + PrintDetails(" - segment[%" PRIindex "] size=%" PRIaddress, index, size); + PrintInitExpr(data_init_expr_); + + size_t voffset = 0; + switch (data_init_expr_.type) { + case InitExprType::I32: + voffset = data_init_expr_.value.i32; + break; + case InitExprType::Global: + break; + case InitExprType::I64: + case InitExprType::F32: + case InitExprType::F64: + fprintf(stderr, "Segment offset must be an i32 init expr"); + return Result::Error; + break; + } + + out_stream_->WriteMemoryDump(src_data, size, voffset, PrintChars::Yes, + " - "); + + // Print relocations from this segment. + if (!options->relocs) + return Result::Ok; + + Offset data_start = GetSectionStart(BinarySection::Data); + Offset segment_start = state->offset - size; + Offset segment_offset = segment_start - data_start; + while (next_data_reloc_ < objdump_state->data_relocations.size()) { + const Reloc& reloc = objdump_state->data_relocations[next_data_reloc_]; + Offset abs_offset = data_start + reloc.offset; + if (abs_offset > state->offset) + break; + PrintRelocation(reloc, reloc.offset - segment_offset + voffset); + next_data_reloc_++; } + return Result::Ok; } Result BinaryReaderObjdump::OnRelocCount(Index count, BinarySection section_code, - StringSlice section_name) { + string_view section_name) { BinaryReaderObjdumpBase::OnRelocCount(count, section_code, section_name); - PrintDetails(" - section: %s\n", get_section_name(section_code)); + PrintDetails(" - section: %s\n", GetSectionName(section_code)); return Result::Ok; } @@ -862,11 +1043,10 @@ Result BinaryReaderObjdump::OnReloc(RelocType type, Offset offset, Index index, uint32_t addend) { - Offset total_offset = - section_starts[static_cast(reloc_section)] + offset; + Offset total_offset = GetSectionStart(reloc_section) + offset; PrintDetails(" - %-18s offset=%#08" PRIoffset "(file=%#08" PRIoffset ") index=%" PRIindex, - get_reloc_type_name(type), offset, total_offset, index); + GetRelocTypeName(type), offset, total_offset, index); if (addend) { int32_t signed_addend = static_cast(addend); if (signed_addend < 0) { @@ -881,28 +1061,64 @@ Result BinaryReaderObjdump::OnReloc(RelocType type, return Result::Ok; } -} // namespace +Result BinaryReaderObjdump::OnStackGlobal(Index stack_global) { + PrintDetails(" - stack pointer global: %d\n", stack_global); + return Result::Ok; +} + +Result BinaryReaderObjdump::OnSymbolInfoCount(Index count) { + PrintDetails(" - symbol info [count=%d]\n", count); + return Result::Ok; +} + +Result BinaryReaderObjdump::OnSymbolInfo(string_view name, uint32_t flags) { + PrintDetails(" - <" PRIstringview "> flags=0x%x\n", + WABT_PRINTF_STRING_VIEW_ARG(name), flags); + return Result::Ok; +} + +Result BinaryReaderObjdump::OnExceptionCount(Index count) { + return OnCount(count); +} + +Result BinaryReaderObjdump::OnExceptionType( + Index index, TypeVector& sig) { + if (!ShouldPrintDetails()) + return Result::Ok; + printf(" - except[%" PRIindex "] (", index); + for (Index i = 0; i < sig.size(); ++i) { + if (i != 0) { + printf(", "); + } + printf("%s", type_name(sig[i])); + } + printf(")\n"); + return Result::Ok; +} + +} // end anonymous namespace -Result read_binary_objdump(const uint8_t* data, - size_t size, - ObjdumpOptions* options, - ObjdumpState* state) { - ReadBinaryOptions read_options = WABT_READ_BINARY_OPTIONS_DEFAULT; +Result ReadBinaryObjdump(const uint8_t* data, + size_t size, + ObjdumpOptions* options, + ObjdumpState* state) { + ReadBinaryOptions read_options; read_options.read_debug_names = true; read_options.log_stream = options->log_stream; + read_options.features = options->features; switch (options->mode) { case ObjdumpMode::Prepass: { BinaryReaderObjdumpPrepass reader(data, size, options, state); - return read_binary(data, size, &reader, &read_options); + return ReadBinary(data, size, &reader, &read_options); } case ObjdumpMode::Disassemble: { BinaryReaderObjdumpDisassemble reader(data, size, options, state); - return read_binary(data, size, &reader, &read_options); + return ReadBinary(data, size, &reader, &read_options); } default: { BinaryReaderObjdump reader(data, size, options, state); - return read_binary(data, size, &reader, &read_options); + return ReadBinary(data, size, &reader, &read_options); } } } diff --git a/lib/wabt/src/binary-reader-objdump.h b/lib/wabt/src/binary-reader-objdump.h index 5c1048230e2..32585995024 100644 --- a/lib/wabt/src/binary-reader-objdump.h +++ b/lib/wabt/src/binary-reader-objdump.h @@ -21,6 +21,7 @@ #include #include "common.h" +#include "feature.h" #include "stream.h" namespace wabt { @@ -44,6 +45,7 @@ struct ObjdumpOptions { bool disassemble; bool debug; bool relocs; + Features features; ObjdumpMode mode; const char* filename; const char* section_name; @@ -53,13 +55,14 @@ struct ObjdumpOptions { // and use it to display more useful information. struct ObjdumpState { std::vector code_relocations; + std::vector data_relocations; std::vector function_names; }; -Result read_binary_objdump(const uint8_t* data, - size_t size, - ObjdumpOptions* options, - ObjdumpState* state); +Result ReadBinaryObjdump(const uint8_t* data, + size_t size, + ObjdumpOptions* options, + ObjdumpState* state); } // namespace wabt diff --git a/lib/wabt/src/binary-reader-opcnt.cc b/lib/wabt/src/binary-reader-opcnt.cc index d87472f24a0..40f68d2268b 100644 --- a/lib/wabt/src/binary-reader-opcnt.cc +++ b/lib/wabt/src/binary-reader-opcnt.cc @@ -24,111 +24,252 @@ #include "binary-reader-nop.h" #include "common.h" +#include "literal.h" +#include "stream.h" namespace wabt { +OpcodeInfo::OpcodeInfo(Opcode opcode, Kind kind) + : opcode_(opcode), kind_(kind) {} + +template +OpcodeInfo::OpcodeInfo(Opcode opcode, Kind kind, T* data, size_t count) + : OpcodeInfo(opcode, kind) { + if (count > 0) { + data_.resize(sizeof(T) * count); + memcpy(data_.data(), data, data_.size()); + } +} + +template +OpcodeInfo::OpcodeInfo(Opcode opcode, Kind kind, T* data, size_t count, T extra) + : OpcodeInfo(opcode, kind, data, count) { + data_.resize(data_.size() + sizeof(T)); + memcpy(data_.data() + data_.size() - sizeof(T), &extra, sizeof(T)); +} + +template +std::pair OpcodeInfo::GetDataArray() const { + if (data_.empty()) { + return std::pair(nullptr, 0); + } + + assert(data_.size() % sizeof(T) == 0); + return std::make_pair(reinterpret_cast(data_.data()), + data_.size() / sizeof(T)); +} + +template +const T* OpcodeInfo::GetData(size_t expected_size) const { + auto pair = GetDataArray(); + assert(pair.second == expected_size); + return pair.first; +} + +template +void OpcodeInfo::WriteArray(Stream& stream, F&& write_func) { + auto pair = GetDataArray(); + for (size_t i = 0; i < pair.second; ++i) { + // Write an initial space (to separate from the opcode name) first, then + // comma-separate. + stream.Writef("%s", i == 0 ? " " : ", "); + write_func(pair.first[i]); + } +} + +void OpcodeInfo::Write(Stream& stream) { + stream.Writef("%s", opcode_.GetName()); + + switch (kind_) { + case Kind::Bare: + break; + + case Kind::Uint32: + stream.Writef(" %u (0x%x)", *GetData(), *GetData()); + break; + + case Kind::Uint64: + stream.Writef(" %" PRIu64 " (0x%" PRIx64 ")", *GetData(), + *GetData()); + break; + + case Kind::Index: + stream.Writef(" %" PRIindex, *GetData()); + break; + + case Kind::Float32: { + stream.Writef(" %g", *GetData()); + char buffer[WABT_MAX_FLOAT_HEX + 1]; + WriteFloatHex(buffer, sizeof(buffer), *GetData()); + stream.Writef(" (%s)", buffer); + break; + } + + case Kind::Float64: { + stream.Writef(" %g", *GetData()); + char buffer[WABT_MAX_DOUBLE_HEX + 1]; + WriteDoubleHex(buffer, sizeof(buffer), *GetData()); + stream.Writef(" (%s)", buffer); + break; + } + + case Kind::Uint32Uint32: + WriteArray( + stream, [&stream](uint32_t value) { stream.Writef("%u", value); }); + break; + + case Kind::BlockSig: + WriteArray(stream, [&stream](Type type) { + stream.Writef("%s", GetTypeName(type)); + }); + break; + + case Kind::BrTable: { + WriteArray(stream, [&stream](Index index) { + stream.Writef("%" PRIindex, index); + }); + break; + } + } +} + +bool operator==(const OpcodeInfo& lhs, const OpcodeInfo& rhs) { + return lhs.opcode_ == rhs.opcode_ && lhs.kind_ == rhs.kind_ && + lhs.data_ == rhs.data_; +} + +bool operator!=(const OpcodeInfo& lhs, const OpcodeInfo& rhs) { + return !(lhs == rhs); +} + +bool operator<(const OpcodeInfo& lhs, const OpcodeInfo& rhs) { + if (lhs.opcode_ < rhs.opcode_) return true; + if (lhs.opcode_ > rhs.opcode_) return false; + if (lhs.kind_ < rhs.kind_) return true; + if (lhs.kind_ > rhs.kind_) return false; + if (lhs.data_ < rhs.data_) return true; + if (lhs.data_ > rhs.data_) return false; + return false; +} + +bool operator<=(const OpcodeInfo& lhs, const OpcodeInfo& rhs) { + return lhs < rhs || lhs == rhs; +} + +bool operator>(const OpcodeInfo& lhs, const OpcodeInfo& rhs) { + return !(lhs <= rhs); +} + +bool operator>=(const OpcodeInfo& lhs, const OpcodeInfo& rhs) { + return !(lhs < rhs); +} + namespace { class BinaryReaderOpcnt : public BinaryReaderNop { public: - explicit BinaryReaderOpcnt(OpcntData* data); + explicit BinaryReaderOpcnt(OpcodeInfoCounts* counts); Result OnOpcode(Opcode opcode) override; - Result OnI32ConstExpr(uint32_t value) override; - Result OnGetLocalExpr(Index local_index) override; - Result OnSetLocalExpr(Index local_index) override; - Result OnTeeLocalExpr(Index local_index) override; - Result OnLoadExpr(Opcode opcode, - uint32_t alignment_log2, - Address offset) override; - Result OnStoreExpr(Opcode opcode, - uint32_t alignment_log2, - Address offset) override; + Result OnOpcodeBare() override; + Result OnOpcodeUint32(uint32_t value) override; + Result OnOpcodeIndex(Index value) override; + Result OnOpcodeUint32Uint32(uint32_t value, uint32_t value2) override; + Result OnOpcodeUint64(uint64_t value) override; + Result OnOpcodeF32(uint32_t value) override; + Result OnOpcodeF64(uint64_t value) override; + Result OnOpcodeBlockSig(Index num_types, Type* sig_types) override; + Result OnBrTableExpr(Index num_targets, + Index* target_depths, + Index default_target_depth) override; + Result OnEndExpr() override; + Result OnEndFunc() override; private: - OpcntData* opcnt_data; + template + Result Emplace(Args&&... args); + + OpcodeInfoCounts* opcode_counts_; + Opcode current_opcode_; }; -static Result AddIntCounterValue(IntCounterVector* vec, intmax_t value) { - for (IntCounter& counter : *vec) { - if (counter.value == value) { - ++counter.count; - return Result::Ok; - } - } - vec->emplace_back(value, 1); - return Result::Ok; -} +template +Result BinaryReaderOpcnt::Emplace(Args&&... args) { + auto pair = opcode_counts_->emplace( + std::piecewise_construct, std::make_tuple(std::forward(args)...), + std::make_tuple(0)); -static Result AddIntPairCounterValue(IntPairCounterVector* vec, - intmax_t first, - intmax_t second) { - for (IntPairCounter& pair : *vec) { - if (pair.first == first && pair.second == second) { - ++pair.count; - return Result::Ok; - } - } - vec->emplace_back(first, second, 1); + auto& count = pair.first->second; + count++; return Result::Ok; } -BinaryReaderOpcnt::BinaryReaderOpcnt(OpcntData* data) : opcnt_data(data) {} +BinaryReaderOpcnt::BinaryReaderOpcnt(OpcodeInfoCounts* counts) + : opcode_counts_(counts) {} Result BinaryReaderOpcnt::OnOpcode(Opcode opcode) { - IntCounterVector& opcnt_vec = opcnt_data->opcode_vec; - while (static_cast(opcode) >= opcnt_vec.size()) { - opcnt_vec.emplace_back(opcnt_vec.size(), 0); - } - ++opcnt_vec[static_cast(opcode)].count; + current_opcode_ = opcode; return Result::Ok; } -Result BinaryReaderOpcnt::OnI32ConstExpr(uint32_t value) { - return AddIntCounterValue(&opcnt_data->i32_const_vec, - static_cast(value)); +Result BinaryReaderOpcnt::OnOpcodeBare() { + return Emplace(current_opcode_, OpcodeInfo::Kind::Bare); } -Result BinaryReaderOpcnt::OnGetLocalExpr(Index local_index) { - return AddIntCounterValue(&opcnt_data->get_local_vec, local_index); +Result BinaryReaderOpcnt::OnOpcodeUint32(uint32_t value) { + return Emplace(current_opcode_, OpcodeInfo::Kind::Uint32, &value); } -Result BinaryReaderOpcnt::OnSetLocalExpr(Index local_index) { - return AddIntCounterValue(&opcnt_data->set_local_vec, local_index); +Result BinaryReaderOpcnt::OnOpcodeIndex(Index value) { + return Emplace(current_opcode_, OpcodeInfo::Kind::Index, &value); } -Result BinaryReaderOpcnt::OnTeeLocalExpr(Index local_index) { - return AddIntCounterValue(&opcnt_data->tee_local_vec, local_index); +Result BinaryReaderOpcnt::OnOpcodeUint32Uint32(uint32_t value0, + uint32_t value1) { + uint32_t array[2] = {value0, value1}; + return Emplace(current_opcode_, OpcodeInfo::Kind::Uint32Uint32, array, 2); } -Result BinaryReaderOpcnt::OnLoadExpr(Opcode opcode, - uint32_t alignment_log2, - Address offset) { - if (opcode == Opcode::I32Load) { - return AddIntPairCounterValue(&opcnt_data->i32_load_vec, alignment_log2, - offset); - } - return Result::Ok; +Result BinaryReaderOpcnt::OnOpcodeUint64(uint64_t value) { + return Emplace(current_opcode_, OpcodeInfo::Kind::Uint64, &value); } -Result BinaryReaderOpcnt::OnStoreExpr(Opcode opcode, - uint32_t alignment_log2, - Address offset) { - if (opcode == Opcode::I32Store) { - return AddIntPairCounterValue(&opcnt_data->i32_store_vec, alignment_log2, - offset); - } - return Result::Ok; +Result BinaryReaderOpcnt::OnOpcodeF32(uint32_t value) { + return Emplace(current_opcode_, OpcodeInfo::Kind::Float32, &value); +} + +Result BinaryReaderOpcnt::OnOpcodeF64(uint64_t value) { + return Emplace(current_opcode_, OpcodeInfo::Kind::Float64, &value); +} + +Result BinaryReaderOpcnt::OnOpcodeBlockSig(Index num_types, Type* sig_types) { + return Emplace(current_opcode_, OpcodeInfo::Kind::BlockSig, sig_types, + num_types); +} + +Result BinaryReaderOpcnt::OnBrTableExpr(Index num_targets, + Index* target_depths, + Index default_target_depth) { + return Emplace(current_opcode_, OpcodeInfo::Kind::BrTable, target_depths, + num_targets, default_target_depth); +} + +Result BinaryReaderOpcnt::OnEndExpr() { + return Emplace(Opcode::End, OpcodeInfo::Kind::Bare); +} + +Result BinaryReaderOpcnt::OnEndFunc() { + return Emplace(Opcode::End, OpcodeInfo::Kind::Bare); } -} // namespace +} // end anonymous namespace -Result read_binary_opcnt(const void* data, - size_t size, - const struct ReadBinaryOptions* options, - OpcntData* opcnt_data) { - BinaryReaderOpcnt reader(opcnt_data); - return read_binary(data, size, &reader, options); +Result ReadBinaryOpcnt(const void* data, + size_t size, + const struct ReadBinaryOptions* options, + OpcodeInfoCounts* counts) { + BinaryReaderOpcnt reader(counts); + return ReadBinary(data, size, &reader, options); } } // namespace wabt diff --git a/lib/wabt/src/binary-reader-opcnt.h b/lib/wabt/src/binary-reader-opcnt.h index 5404622af24..28bcca32252 100644 --- a/lib/wabt/src/binary-reader-opcnt.h +++ b/lib/wabt/src/binary-reader-opcnt.h @@ -17,50 +17,76 @@ #ifndef WABT_BINARY_READER_OPCNT_H_ #define WABT_BINARY_READER_OPCNT_H_ -#include "common.h" - +#include #include +#include "common.h" +#include "opcode.h" + namespace wabt { struct Module; struct ReadBinaryOptions; +class Stream; -struct IntCounter { - IntCounter(intmax_t value, size_t count) : value(value), count(count) {} +class OpcodeInfo { + public: + enum class Kind { + Bare, + Uint32, + Uint64, + Index, + Float32, + Float64, + Uint32Uint32, + BlockSig, + BrTable, + }; - intmax_t value; - size_t count; -}; -typedef std::vector IntCounterVector; + explicit OpcodeInfo(Opcode, Kind); + template + OpcodeInfo(Opcode, Kind, T* data, size_t count = 1); + template + OpcodeInfo(Opcode, Kind, T* data, size_t count, T extra); -struct IntPairCounter { - IntPairCounter(intmax_t first, intmax_t second, size_t count) - : first(first), second(second), count(count) {} + Opcode opcode() const { return opcode_; } - intmax_t first; - intmax_t second; - size_t count; -}; -typedef std::vector IntPairCounterVector; - -struct OpcntData { - IntCounterVector opcode_vec; - IntCounterVector i32_const_vec; - IntCounterVector get_local_vec; - IntCounterVector set_local_vec; - IntCounterVector tee_local_vec; - IntPairCounterVector i32_load_vec; - IntPairCounterVector i32_store_vec; + void Write(Stream&); + + private: + template + std::pair GetDataArray() const; + template + const T* GetData(size_t expected_size = 1) const; + + template + void WriteArray(Stream& stream, F&& write_func); + + Opcode opcode_; + Kind kind_; + std::vector data_; + + friend bool operator==(const OpcodeInfo&, const OpcodeInfo&); + friend bool operator!=(const OpcodeInfo&, const OpcodeInfo&); + friend bool operator<(const OpcodeInfo&, const OpcodeInfo&); + friend bool operator<=(const OpcodeInfo&, const OpcodeInfo&); + friend bool operator>(const OpcodeInfo&, const OpcodeInfo&); + friend bool operator>=(const OpcodeInfo&, const OpcodeInfo&); }; -void init_opcnt_data(OpcntData* data); -void destroy_opcnt_data(OpcntData* data); +bool operator==(const OpcodeInfo&, const OpcodeInfo&); +bool operator!=(const OpcodeInfo&, const OpcodeInfo&); +bool operator<(const OpcodeInfo&, const OpcodeInfo&); +bool operator<=(const OpcodeInfo&, const OpcodeInfo&); +bool operator>(const OpcodeInfo&, const OpcodeInfo&); +bool operator>=(const OpcodeInfo&, const OpcodeInfo&); + +typedef std::map OpcodeInfoCounts; -Result read_binary_opcnt(const void* data, - size_t size, - const struct ReadBinaryOptions* options, - OpcntData* opcnt_data); +Result ReadBinaryOpcnt(const void* data, + size_t size, + const struct ReadBinaryOptions* options, + OpcodeInfoCounts* opcode_counts); } // namespace wabt diff --git a/lib/wabt/src/binary-reader.cc b/lib/wabt/src/binary-reader.cc index 7effa8bc08c..07feafaeaa8 100644 --- a/lib/wabt/src/binary-reader.cc +++ b/lib/wabt/src/binary-reader.cc @@ -36,7 +36,7 @@ #define CHECK_RESULT(expr) \ do { \ - if (WABT_FAILED(expr)) \ + if (Failed(expr)) \ return Result::Error; \ } while (0) @@ -48,13 +48,18 @@ } \ } while (0) -#define CALLBACK0(member) \ - ERROR_UNLESS(WABT_SUCCEEDED(delegate_->member()), #member \ - " callback " \ - "failed") +#define ERROR_UNLESS_OPCODE_ENABLED(opcode) \ + do { \ + if (!opcode.IsEnabled(options_->features)) \ + return ReportUnexpectedOpcode(opcode); \ + } while (0) + +#define CALLBACK0(member) \ + ERROR_UNLESS(Succeeded(delegate_->member()), #member \ + " callback failed") -#define CALLBACK(member, ...) \ - ERROR_UNLESS(WABT_SUCCEEDED(delegate_->member(__VA_ARGS__)), \ +#define CALLBACK(member, ...) \ + ERROR_UNLESS(Succeeded(delegate_->member(__VA_ARGS__)), \ #member " callback failed") namespace wabt { @@ -78,9 +83,9 @@ namespace wabt { SHIFT_AMOUNT(type, sign_bit)) // TODO(binji): move LEB functions elsewhere -size_t read_u32_leb128(const uint8_t* p, - const uint8_t* end, - uint32_t* out_value) { +size_t ReadU32Leb128(const uint8_t* p, + const uint8_t* end, + uint32_t* out_value) { if (p < end && (p[0] & 0x80) == 0) { *out_value = LEB128_1(uint32_t); return 1; @@ -106,9 +111,9 @@ size_t read_u32_leb128(const uint8_t* p, } } -size_t read_i32_leb128(const uint8_t* p, - const uint8_t* end, - uint32_t* out_value) { +size_t ReadI32Leb128(const uint8_t* p, + const uint8_t* end, + uint32_t* out_value) { if (p < end && (p[0] & 0x80) == 0) { uint32_t result = LEB128_1(uint32_t); *out_value = SIGN_EXTEND(int32_t, result, 6); @@ -155,6 +160,7 @@ class BinaryReader { private: void WABT_PRINTF_FORMAT(2, 3) PrintError(const char* format, ...); + Result ReadOpcode(Opcode* out_value, const char* desc) WABT_WARN_UNUSED; Result ReadU8(uint8_t* out_value, const char* desc) WABT_WARN_UNUSED; Result ReadU32(uint32_t* out_value, const char* desc) WABT_WARN_UNUSED; Result ReadF32(uint32_t* out_value, const char* desc) WABT_WARN_UNUSED; @@ -163,7 +169,7 @@ class BinaryReader { Result ReadI32Leb128(uint32_t* out_value, const char* desc) WABT_WARN_UNUSED; Result ReadI64Leb128(uint64_t* out_value, const char* desc) WABT_WARN_UNUSED; Result ReadType(Type* out_value, const char* desc) WABT_WARN_UNUSED; - Result ReadStr(StringSlice* out_str, const char* desc) WABT_WARN_UNUSED; + Result ReadStr(string_view* out_str, const char* desc) WABT_WARN_UNUSED; Result ReadBytes(const void** out_data, Address* out_data_size, const char* desc) WABT_WARN_UNUSED; @@ -180,9 +186,11 @@ class BinaryReader { Limits* out_elem_limits) WABT_WARN_UNUSED; Result ReadMemory(Limits* out_page_limits) WABT_WARN_UNUSED; Result ReadGlobalHeader(Type* out_type, bool* out_mutable) WABT_WARN_UNUSED; + Result ReadExceptionType(TypeVector& sig) WABT_WARN_UNUSED; Result ReadFunctionBody(Offset end_offset) WABT_WARN_UNUSED; Result ReadNamesSection(Offset section_size) WABT_WARN_UNUSED; Result ReadRelocSection(Offset section_size) WABT_WARN_UNUSED; + Result ReadLinkingSection(Offset section_size) WABT_WARN_UNUSED; Result ReadCustomSection(Offset section_size) WABT_WARN_UNUSED; Result ReadTypeSection(Offset section_size) WABT_WARN_UNUSED; Result ReadImportSection(Offset section_size) WABT_WARN_UNUSED; @@ -195,7 +203,9 @@ class BinaryReader { Result ReadElemSection(Offset section_size) WABT_WARN_UNUSED; Result ReadCodeSection(Offset section_size) WABT_WARN_UNUSED; Result ReadDataSection(Offset section_size) WABT_WARN_UNUSED; + Result ReadExceptionSection(Offset section_size) WABT_WARN_UNUSED; Result ReadSections() WABT_WARN_UNUSED; + Result ReportUnexpectedOpcode(Opcode opcode, const char* message = nullptr); size_t read_end_ = 0; /* Either the section end or data_size. */ BinaryReaderDelegate::State state_; @@ -211,12 +221,14 @@ class BinaryReader { Index num_table_imports_ = 0; Index num_memory_imports_ = 0; Index num_global_imports_ = 0; + Index num_exception_imports_ = 0; Index num_function_signatures_ = 0; Index num_tables_ = 0; Index num_memories_ = 0; Index num_globals_ = 0; Index num_exports_ = 0; Index num_function_bodies_ = 0; + Index num_exceptions_ = 0; }; BinaryReader::BinaryReader(const void* data, @@ -252,6 +264,36 @@ void WABT_PRINTF_FORMAT(2, 3) BinaryReader::PrintError(const char* format, state_.offset += sizeof(type); \ return Result::Ok +Result BinaryReader::ReportUnexpectedOpcode(Opcode opcode, + const char* message) { + const char* maybe_space = " "; + if (!message) + message = maybe_space = ""; + if (opcode.HasPrefix()) { + PrintError("unexpected opcode%s%s: %d %d (0x%x 0x%x)", maybe_space, message, + opcode.GetPrefix(), opcode.GetCode(), opcode.GetPrefix(), + opcode.GetCode()); + } else { + PrintError("unexpected opcode%s%s: %d (0x%x)", + maybe_space, message, opcode.GetCode(), opcode.GetCode()); + } + return Result::Error; +} + +Result BinaryReader::ReadOpcode(Opcode* out_value, const char* desc) { + uint8_t value = 0; + CHECK_RESULT(ReadU8(&value, desc)); + + if (Opcode::IsPrefixByte(value)) { + uint32_t code; + CHECK_RESULT(ReadU32Leb128(&code, desc)); + *out_value = Opcode::FromCode(value, code); + } else { + *out_value = Opcode::FromCode(value); + } + return Result::Ok; +} + Result BinaryReader::ReadU8(uint8_t* out_value, const char* desc) { IN_SIZE(uint8_t); } @@ -273,7 +315,7 @@ Result BinaryReader::ReadF64(uint64_t* out_value, const char* desc) { Result BinaryReader::ReadU32Leb128(uint32_t* out_value, const char* desc) { const uint8_t* p = state_.data + state_.offset; const uint8_t* end = state_.data + read_end_; - size_t bytes_read = read_u32_leb128(p, end, out_value); + size_t bytes_read = wabt::ReadU32Leb128(p, end, out_value); ERROR_UNLESS(bytes_read > 0, "unable to read u32 leb128: %s", desc); state_.offset += bytes_read; return Result::Ok; @@ -282,7 +324,7 @@ Result BinaryReader::ReadU32Leb128(uint32_t* out_value, const char* desc) { Result BinaryReader::ReadI32Leb128(uint32_t* out_value, const char* desc) { const uint8_t* p = state_.data + state_.offset; const uint8_t* end = state_.data + read_end_; - size_t bytes_read = read_i32_leb128(p, end, out_value); + size_t bytes_read = wabt::ReadI32Leb128(p, end, out_value); ERROR_UNLESS(bytes_read > 0, "unable to read i32 leb128: %s", desc); state_.offset += bytes_read; return Result::Ok; @@ -373,18 +415,18 @@ Result BinaryReader::ReadType(Type* out_value, const char* desc) { return Result::Ok; } -Result BinaryReader::ReadStr(StringSlice* out_str, const char* desc) { +Result BinaryReader::ReadStr(string_view* out_str, const char* desc) { uint32_t str_len = 0; CHECK_RESULT(ReadU32Leb128(&str_len, "string length")); ERROR_UNLESS(state_.offset + str_len <= read_end_, "unable to read string: %s", desc); - out_str->start = reinterpret_cast(state_.data) + state_.offset; - out_str->length = str_len; + *out_str = string_view( + reinterpret_cast(state_.data) + state_.offset, str_len); state_.offset += str_len; - ERROR_UNLESS(is_valid_utf8(out_str->start, out_str->length), + ERROR_UNLESS(IsValidUtf8(out_str->data(), out_str->length()), "invalid utf-8 encoding: %s", desc); return Result::Ok; } @@ -456,9 +498,9 @@ Index BinaryReader::NumTotalGlobals() { } Result BinaryReader::ReadInitExpr(Index index) { - uint8_t opcode = 0; - CHECK_RESULT(ReadU8(&opcode, "opcode")); - switch (static_cast(opcode)) { + Opcode opcode; + CHECK_RESULT(ReadOpcode(&opcode, "opcode")); + switch (opcode) { case Opcode::I32Const: { uint32_t value = 0; CHECK_RESULT(ReadI32Leb128(&value, "init_expr i32.const value")); @@ -498,13 +540,11 @@ Result BinaryReader::ReadInitExpr(Index index) { return Result::Ok; default: - PrintError("unexpected opcode in initializer expression: %d (0x%x)", - opcode, opcode); - return Result::Error; + return ReportUnexpectedOpcode(opcode, "in initializer expression"); } - CHECK_RESULT(ReadU8(&opcode, "opcode")); - ERROR_UNLESS(static_cast(opcode) == Opcode::End, + CHECK_RESULT(ReadOpcode(&opcode, "opcode")); + ERROR_UNLESS(opcode == Opcode::End, "expected END opcode after initializer expression"); return Result::Ok; } @@ -570,9 +610,8 @@ Result BinaryReader::ReadGlobalHeader(Type* out_type, bool* out_mutable) { Result BinaryReader::ReadFunctionBody(Offset end_offset) { bool seen_end_opcode = false; while (state_.offset < end_offset) { - uint8_t opcode_u8 = 0; - CHECK_RESULT(ReadU8(&opcode_u8, "opcode")); - Opcode opcode = static_cast(opcode_u8); + Opcode opcode; + CHECK_RESULT(ReadOpcode(&opcode, "opcode")); CALLBACK(OnOpcode, opcode); switch (opcode) { case Opcode::Unreachable: @@ -980,10 +1019,67 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) { CALLBACK0(OnOpcodeBare); break; + case Opcode::Try: { + ERROR_UNLESS_OPCODE_ENABLED(opcode); + Type sig_type; + CHECK_RESULT(ReadType(&sig_type, "try signature type")); + ERROR_UNLESS(is_inline_sig_type(sig_type), + "expected valid block signature type"); + Index num_types = sig_type == Type::Void ? 0 : 1; + CALLBACK(OnTryExpr, num_types, &sig_type); + CALLBACK(OnOpcodeBlockSig, num_types, &sig_type); + break; + } + + case Opcode::Catch: { + ERROR_UNLESS_OPCODE_ENABLED(opcode); + Index index; + CHECK_RESULT(ReadIndex(&index, "exception index")); + CALLBACK(OnCatchExpr, index); + CALLBACK(OnOpcodeIndex, index); + break; + } + + case Opcode::CatchAll: { + ERROR_UNLESS_OPCODE_ENABLED(opcode); + CALLBACK(OnCatchAllExpr); + CALLBACK0(OnOpcodeBare); + break; + } + + case Opcode::Rethrow: { + ERROR_UNLESS_OPCODE_ENABLED(opcode); + Index depth; + CHECK_RESULT(ReadIndex(&depth, "catch depth")); + CALLBACK(OnRethrowExpr, depth); + CALLBACK(OnOpcodeIndex, depth); + break; + } + + case Opcode::Throw: { + ERROR_UNLESS_OPCODE_ENABLED(opcode); + Index index; + CHECK_RESULT(ReadIndex(&index, "exception index")); + CALLBACK(OnThrowExpr, index); + CALLBACK(OnOpcodeIndex, index); + break; + } + + case Opcode::I32TruncSSatF32: + case Opcode::I32TruncUSatF32: + case Opcode::I32TruncSSatF64: + case Opcode::I32TruncUSatF64: + case Opcode::I64TruncSSatF32: + case Opcode::I64TruncUSatF32: + case Opcode::I64TruncSSatF64: + case Opcode::I64TruncUSatF64: + ERROR_UNLESS_OPCODE_ENABLED(opcode); + CALLBACK(OnConvertExpr, opcode); + CALLBACK0(OnOpcodeBare); + break; + default: - PrintError("unexpected opcode: %d (0x%x)", static_cast(opcode), - static_cast(opcode)); - return Result::Error; + return ReportUnexpectedOpcode(opcode); } } ERROR_UNLESS(state_.offset == end_offset, @@ -1025,7 +1121,7 @@ Result BinaryReader::ReadNamesSection(Offset section_size) { for (Index j = 0; j < num_names; ++j) { Index function_index; - StringSlice function_name; + string_view function_name; CHECK_RESULT(ReadIndex(&function_index, "function index")); ERROR_UNLESS(function_index != last_function_index, @@ -1064,7 +1160,7 @@ Result BinaryReader::ReadNamesSection(Offset section_size) { Index last_local_index = kInvalidIndex; for (Index k = 0; k < num_locals; ++k) { Index local_index; - StringSlice local_name; + string_view local_name; CHECK_RESULT(ReadIndex(&local_index, "named index")); ERROR_UNLESS(local_index != last_local_index, @@ -1098,8 +1194,7 @@ Result BinaryReader::ReadRelocSection(Offset section_size) { CALLBACK(BeginRelocSection, section_size); uint32_t section; CHECK_RESULT(ReadU32Leb128(§ion, "section")); - StringSlice section_name; - WABT_ZERO_MEMORY(section_name); + string_view section_name; if (static_cast(section) == BinarySection::Custom) CHECK_RESULT(ReadStr(§ion_name, "section name")); Index num_relocs; @@ -1129,19 +1224,100 @@ Result BinaryReader::ReadRelocSection(Offset section_size) { return Result::Ok; } +Result BinaryReader::ReadLinkingSection(Offset section_size) { + CALLBACK(BeginLinkingSection, section_size); + Offset previous_read_end = read_end_; + while (state_.offset < read_end_) { + uint32_t linking_type; + Offset subsection_size; + CHECK_RESULT(ReadU32Leb128(&linking_type, "type")); + CHECK_RESULT(ReadOffset(&subsection_size, "subsection size")); + size_t subsection_end = state_.offset + subsection_size; + ERROR_UNLESS(subsection_end <= read_end_, + "invalid sub-section size: extends past end"); + read_end_ = subsection_end; + + switch (static_cast(linking_type)) { + case LinkingEntryType::StackPointer: { + uint32_t stack_ptr; + CHECK_RESULT(ReadU32Leb128(&stack_ptr, "stack pointer index")); + CALLBACK(OnStackGlobal, stack_ptr); + break; + } + case LinkingEntryType::SymbolInfo: { + uint32_t info_count; + CHECK_RESULT(ReadU32Leb128(&info_count, "info count")); + CALLBACK(OnSymbolInfoCount, info_count); + while (info_count--) { + string_view name; + uint32_t info; + CHECK_RESULT(ReadStr(&name, "symbol name")); + CHECK_RESULT(ReadU32Leb128(&info, "sym flags")); + CALLBACK(OnSymbolInfo, name, info); + } + break; + } + default: + /* unknown subsection, skip it */ + state_.offset = subsection_end; + break; + } + ERROR_UNLESS(state_.offset == subsection_end, + "unfinished sub-section (expected end: 0x%" PRIzx ")", + subsection_end); + read_end_ = previous_read_end; + } + CALLBACK0(EndLinkingSection); + return Result::Ok; +} + +Result BinaryReader::ReadExceptionType(TypeVector& sig) { + Index num_values; + CHECK_RESULT(ReadIndex(&num_values, "exception type count")); + sig.resize(num_values); + for (Index j = 0; j < num_values; ++j) { + Type value_type; + CHECK_RESULT(ReadType(&value_type, "exception value type")); + ERROR_UNLESS(is_concrete_type(value_type), + "excepted valid exception value type (got %d)", + static_cast(value_type)); + sig[j] = value_type; + } + return Result::Ok; +} + +Result BinaryReader::ReadExceptionSection(Offset section_size) { + CALLBACK(BeginExceptionSection, section_size); + CHECK_RESULT(ReadIndex(&num_exceptions_, "exception count")); + CALLBACK(OnExceptionCount, num_exceptions_); + + for (Index i = 0; i < num_exceptions_; ++i) { + TypeVector sig; + CHECK_RESULT(ReadExceptionType(sig)); + CALLBACK(OnExceptionType, i, sig); + } + + CALLBACK(EndExceptionSection); + return Result::Ok; +} + Result BinaryReader::ReadCustomSection(Offset section_size) { - StringSlice section_name; + string_view section_name; CHECK_RESULT(ReadStr(§ion_name, "section name")); CALLBACK(BeginCustomSection, section_size, section_name); bool name_section_ok = last_known_section_ >= BinarySection::Import; if (options_->read_debug_names && name_section_ok && - strncmp(section_name.start, WABT_BINARY_SECTION_NAME, - section_name.length) == 0) { + section_name == WABT_BINARY_SECTION_NAME) { CHECK_RESULT(ReadNamesSection(section_size)); - } else if (strncmp(section_name.start, WABT_BINARY_SECTION_RELOC, - strlen(WABT_BINARY_SECTION_RELOC)) == 0) { + } else if (section_name.rfind(WABT_BINARY_SECTION_RELOC, 0) == 0) { + // Reloc sections always begin with "reloc." CHECK_RESULT(ReadRelocSection(section_size)); + } else if (section_name == WABT_BINARY_SECTION_LINKING) { + CHECK_RESULT(ReadLinkingSection(section_size)); + } else if (options_->features.exceptions_enabled() && + section_name == WABT_BINARY_SECTION_EXCEPTION) { + CHECK_RESULT(ReadExceptionSection(section_size)); } else { /* This is an unknown custom section, skip it. */ state_.offset = read_end_; @@ -1200,9 +1376,9 @@ Result BinaryReader::ReadImportSection(Offset section_size) { CHECK_RESULT(ReadIndex(&num_imports_, "import count")); CALLBACK(OnImportCount, num_imports_); for (Index i = 0; i < num_imports_; ++i) { - StringSlice module_name; + string_view module_name; CHECK_RESULT(ReadStr(&module_name, "import module name")); - StringSlice field_name; + string_view field_name; CHECK_RESULT(ReadStr(&field_name, "import field name")); uint32_t kind; @@ -1252,6 +1428,18 @@ Result BinaryReader::ReadImportSection(Offset section_size) { break; } + case ExternalKind::Except: { + ERROR_UNLESS(options_->features.exceptions_enabled(), + "invalid import exception kind: exceptions not allowed"); + TypeVector sig; + CHECK_RESULT(ReadExceptionType(sig)); + CALLBACK(OnImport, i, module_name, field_name); + CALLBACK(OnImportException, i, module_name, field_name, + num_exception_imports_, sig); + num_exception_imports_++; + break; + } + default: PrintError("invalid import kind: %d", kind); return Result::Error; @@ -1334,7 +1522,7 @@ Result BinaryReader::ReadExportSection(Offset section_size) { CHECK_RESULT(ReadIndex(&num_exports_, "export count")); CALLBACK(OnExportCount, num_exports_); for (Index i = 0; i < num_exports_; ++i) { - StringSlice name; + string_view name; CHECK_RESULT(ReadStr(&name, "export item name")); uint8_t external_kind = 0; @@ -1362,8 +1550,9 @@ Result BinaryReader::ReadExportSection(Offset section_size) { "invalid export global index: %" PRIindex, item_index); break; case ExternalKind::Except: - // TODO(karlschimpf) Define. - WABT_FATAL("read export except not implemented"); + // Note: Can't check if index valid, exceptions section comes later. + ERROR_UNLESS(options_->features.exceptions_enabled(), + "invalid export exception kind: exceptions not allowed"); break; } @@ -1500,7 +1689,7 @@ Result BinaryReader::ReadSections() { ERROR_UNLESS(last_known_section_ == BinarySection::Invalid || section == BinarySection::Custom || section > last_known_section_, - "section %s out of order", get_section_name(section)); + "section %s out of order", GetSectionName(section)); CALLBACK(BeginSection, section, section_size); @@ -1545,12 +1734,12 @@ Result BinaryReader::ReadModule() { return Result::Ok; } -} // namespace +} // end anonymous namespace -Result read_binary(const void* data, - size_t size, - BinaryReaderDelegate* delegate, - const ReadBinaryOptions* options) { +Result ReadBinary(const void* data, + size_t size, + BinaryReaderDelegate* delegate, + const ReadBinaryOptions* options) { BinaryReader reader(data, size, delegate, options); return reader.ReadModule(); } diff --git a/lib/wabt/src/binary-reader.h b/lib/wabt/src/binary-reader.h index 2c72f6d898d..b510bce891c 100644 --- a/lib/wabt/src/binary-reader.h +++ b/lib/wabt/src/binary-reader.h @@ -22,18 +22,26 @@ #include "binary.h" #include "common.h" +#include "feature.h" #include "opcode.h" - -#define WABT_READ_BINARY_OPTIONS_DEFAULT \ - { nullptr, false } +#include "string-view.h" namespace wabt { class Stream; struct ReadBinaryOptions { - Stream* log_stream; - bool read_debug_names; + ReadBinaryOptions() = default; + ReadBinaryOptions(const Features& features, + Stream* log_stream, + bool read_debug_names) + : features(features), + log_stream(log_stream), + read_debug_names(read_debug_names) {} + + Features features; + Stream* log_stream = nullptr; + bool read_debug_names = false; }; class BinaryReaderDelegate { @@ -59,7 +67,7 @@ class BinaryReaderDelegate { virtual Result BeginSection(BinarySection section_type, Offset size) = 0; /* Custom section */ - virtual Result BeginCustomSection(Offset size, StringSlice section_name) = 0; + virtual Result BeginCustomSection(Offset size, string_view section_name) = 0; virtual Result EndCustomSection() = 0; /* Type section */ @@ -76,30 +84,35 @@ class BinaryReaderDelegate { virtual Result BeginImportSection(Offset size) = 0; virtual Result OnImportCount(Index count) = 0; virtual Result OnImport(Index index, - StringSlice module_name, - StringSlice field_name) = 0; + string_view module_name, + string_view field_name) = 0; virtual Result OnImportFunc(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index func_index, Index sig_index) = 0; virtual Result OnImportTable(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index table_index, Type elem_type, const Limits* elem_limits) = 0; virtual Result OnImportMemory(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index memory_index, const Limits* page_limits) = 0; virtual Result OnImportGlobal(Index import_index, - StringSlice module_name, - StringSlice field_name, + string_view module_name, + string_view field_name, Index global_index, Type type, bool mutable_) = 0; + virtual Result OnImportException(Index import_index, + string_view module_name, + string_view field_name, + Index except_index, + TypeVector& sig) = 0; virtual Result EndImportSection() = 0; /* Function section */ @@ -137,7 +150,7 @@ class BinaryReaderDelegate { virtual Result OnExport(Index index, ExternalKind kind, Index item_index, - StringSlice name) = 0; + string_view name) = 0; virtual Result EndExportSection() = 0; /* Start section */ @@ -172,6 +185,8 @@ class BinaryReaderDelegate { Index default_target_depth) = 0; virtual Result OnCallExpr(Index func_index) = 0; virtual Result OnCallIndirectExpr(Index sig_index) = 0; + virtual Result OnCatchExpr(Index except_index) = 0; + virtual Result OnCatchAllExpr() = 0; virtual Result OnCompareExpr(Opcode opcode) = 0; virtual Result OnConvertExpr(Opcode opcode) = 0; virtual Result OnCurrentMemoryExpr() = 0; @@ -192,6 +207,7 @@ class BinaryReaderDelegate { Address offset) = 0; virtual Result OnLoopExpr(Index num_types, Type* sig_types) = 0; virtual Result OnNopExpr() = 0; + virtual Result OnRethrowExpr(Index depth) = 0; virtual Result OnReturnExpr() = 0; virtual Result OnSelectExpr() = 0; virtual Result OnSetGlobalExpr(Index global_index) = 0; @@ -200,6 +216,9 @@ class BinaryReaderDelegate { uint32_t alignment_log2, Address offset) = 0; virtual Result OnTeeLocalExpr(Index local_index) = 0; + virtual Result OnThrowExpr(Index except_index) = 0; + virtual Result OnTryExpr(Index num_types, Type* sig_types) = 0; + virtual Result OnUnaryExpr(Opcode opcode) = 0; virtual Result OnUnreachableExpr() = 0; virtual Result EndFunctionBody(Index index) = 0; @@ -236,7 +255,7 @@ class BinaryReaderDelegate { Offset subsection_size) = 0; virtual Result OnFunctionNamesCount(Index num_functions) = 0; virtual Result OnFunctionName(Index function_index, - StringSlice function_name) = 0; + string_view function_name) = 0; virtual Result OnLocalNameSubsection(Index index, uint32_t name_type, Offset subsection_size) = 0; @@ -245,20 +264,33 @@ class BinaryReaderDelegate { Index num_locals) = 0; virtual Result OnLocalName(Index function_index, Index local_index, - StringSlice local_name) = 0; + string_view local_name) = 0; virtual Result EndNamesSection() = 0; /* Reloc section */ virtual Result BeginRelocSection(Offset size) = 0; virtual Result OnRelocCount(Index count, BinarySection section_code, - StringSlice section_name) = 0; + string_view section_name) = 0; virtual Result OnReloc(RelocType type, Offset offset, Index index, uint32_t addend) = 0; virtual Result EndRelocSection() = 0; + /* Linking section */ + virtual Result BeginLinkingSection(Offset size) = 0; + virtual Result OnStackGlobal(Index stack_global) = 0; + virtual Result OnSymbolInfoCount(Index count) = 0; + virtual Result OnSymbolInfo(string_view name, uint32_t flags) = 0; + virtual Result EndLinkingSection() = 0; + + /* Exception section */ + virtual Result BeginExceptionSection(Offset size) = 0; + virtual Result OnExceptionCount(Index count) = 0; + virtual Result OnExceptionType(Index index, TypeVector& sig) = 0; + virtual Result EndExceptionSection() = 0; + /* InitExpr - used by elem, data and global sections; these functions are * only called between calls to Begin*InitExpr and End*InitExpr */ virtual Result OnInitExprF32ConstExpr(Index index, uint32_t value) = 0; @@ -270,18 +302,18 @@ class BinaryReaderDelegate { const State* state = nullptr; }; -Result read_binary(const void* data, - size_t size, - BinaryReaderDelegate* reader, - const ReadBinaryOptions* options); +Result ReadBinary(const void* data, + size_t size, + BinaryReaderDelegate* reader, + const ReadBinaryOptions* options); -size_t read_u32_leb128(const uint8_t* ptr, - const uint8_t* end, - uint32_t* out_value); +size_t ReadU32Leb128(const uint8_t* ptr, + const uint8_t* end, + uint32_t* out_value); -size_t read_i32_leb128(const uint8_t* ptr, - const uint8_t* end, - uint32_t* out_value); +size_t ReadI32Leb128(const uint8_t* ptr, + const uint8_t* end, + uint32_t* out_value); } // namespace wabt diff --git a/lib/wabt/src/binary-writer-spec.cc b/lib/wabt/src/binary-writer-spec.cc index 3289bea5848..088878522b6 100644 --- a/lib/wabt/src/binary-writer-spec.cc +++ b/lib/wabt/src/binary-writer-spec.cc @@ -21,67 +21,40 @@ #include "binary.h" #include "binary-writer.h" +#include "cast.h" #include "config.h" #include "ir.h" #include "stream.h" +#include "string-view.h" #include "writer.h" namespace wabt { -static void convert_backslash_to_slash(char* s, size_t length) { - for (size_t i = 0; i < length; ++i) - if (s[i] == '\\') - s[i] = '/'; -} - -static StringSlice strip_extension(const char* s) { - /* strip .json or .wasm, but leave other extensions, e.g.: - * - * s = "foo", => "foo" - * s = "foo.json" => "foo" - * s = "foo.wasm" => "foo" - * s = "foo.bar" => "foo.bar" - */ - if (!s) { - StringSlice result; - result.start = nullptr; - result.length = 0; - return result; - } - - size_t slen = strlen(s); - const char* ext_start = strrchr(s, '.'); - if (!ext_start) - ext_start = s + slen; - - StringSlice result; - result.start = s; - - if (strcmp(ext_start, ".json") == 0 || strcmp(ext_start, ".wasm") == 0) { - result.length = ext_start - s; - } else { - result.length = slen; - } +static string_view strip_extension(string_view s) { + // Strip .json or .wasm, but leave other extensions, e.g.: + // + // s = "foo", => "foo" + // s = "foo.json" => "foo" + // s = "foo.wasm" => "foo" + // s = "foo.bar" => "foo.bar" + string_view ext = s.substr(s.find_last_of('.')); + string_view result = s; + + if (ext == ".json" || ext == ".wasm") + result.remove_suffix(ext.length()); return result; } -static StringSlice get_basename(const char* s) { - /* strip everything up to and including the last slash, e.g.: - * - * s = "/foo/bar/baz", => "baz" - * s = "/usr/local/include/stdio.h", => "stdio.h" - * s = "foo.bar", => "foo.bar" - */ - size_t slen = strlen(s); - const char* start = s; - const char* last_slash = strrchr(s, '/'); - if (last_slash) - start = last_slash + 1; - - StringSlice result; - result.start = start; - result.length = s + slen - start; - return result; +static string_view get_basename(string_view s) { + // Strip everything up to and including the last slash, e.g.: + // + // s = "/foo/bar/baz", => "baz" + // s = "/usr/local/include/stdio.h", => "stdio.h" + // s = "foo.bar", => "foo.bar" + size_t last_slash = s.find_last_of('/'); + if (last_slash != string_view::npos) + return s.substr(last_slash + 1); + return s; } namespace { @@ -94,11 +67,11 @@ class BinaryWriterSpec { Result WriteScript(Script* script); private: - char* GetModuleFilename(const char* extension); + std::string GetModuleFilename(const char* extension); void WriteString(const char* s); void WriteKey(const char* key); void WriteSeparator(); - void WriteEscapedStringSlice(StringSlice ss); + void WriteEscapedString(string_view); void WriteCommandType(const Command& command); void WriteLocation(const Location* loc); void WriteVar(const Var* var); @@ -107,14 +80,15 @@ class BinaryWriterSpec { void WriteConstVector(const ConstVector& consts); void WriteAction(const Action* action); void WriteActionResultType(Script* script, const Action* action); - void WriteModule(char* filename, const Module* module); - void WriteScriptModule(char* filename, const ScriptModule* script_module); - void WriteInvalidModule(const ScriptModule* module, StringSlice text); + void WriteModule(string_view filename, const Module* module); + void WriteScriptModule(string_view filename, + const ScriptModule* script_module); + void WriteInvalidModule(const ScriptModule* module, string_view text); void WriteCommands(Script* script); MemoryStream json_stream_; - StringSlice source_filename_; - StringSlice module_filename_noext_; + std::string source_filename_; + std::string module_filename_noext_; bool write_modules_ = false; /* Whether to write the modules files. */ const WriteBinarySpecOptions* spec_options_ = nullptr; Result result_ = Result::Ok; @@ -132,23 +106,21 @@ const char* BinaryWriterSpec::kWastExtension = ".wast"; BinaryWriterSpec::BinaryWriterSpec(const char* source_filename, const WriteBinarySpecOptions* spec_options) : spec_options_(spec_options) { - source_filename_.start = source_filename; - source_filename_.length = strlen(source_filename); + source_filename_ = source_filename; module_filename_noext_ = strip_extension(spec_options_->json_filename ? spec_options_->json_filename - : source_filename); + : source_filename) + .to_string(); write_modules_ = !!spec_options_->json_filename; } -char* BinaryWriterSpec::GetModuleFilename(const char* extension) { - size_t buflen = module_filename_noext_.length + 20; - char* str = new char[buflen]; - size_t length = - wabt_snprintf(str, buflen, PRIstringslice ".%" PRIzd "%s", - WABT_PRINTF_STRING_SLICE_ARG(module_filename_noext_), - num_modules_, extension); - convert_backslash_to_slash(str, length); - return str; +std::string BinaryWriterSpec::GetModuleFilename(const char* extension) { + std::string result = module_filename_noext_; + result += '.'; + result += std::to_string(num_modules_); + result += extension; + ConvertBackslashToSlash(&result); + return result; } void BinaryWriterSpec::WriteString(const char* s) { @@ -163,10 +135,10 @@ void BinaryWriterSpec::WriteSeparator() { json_stream_.Writef(", "); } -void BinaryWriterSpec::WriteEscapedStringSlice(StringSlice ss) { +void BinaryWriterSpec::WriteEscapedString(string_view s) { json_stream_.WriteChar('"'); - for (size_t i = 0; i < ss.length; ++i) { - uint8_t c = ss.start[i]; + for (size_t i = 0; i < s.length(); ++i) { + uint8_t c = s[i]; if (c < 0x20 || c == '\\' || c == '"' || c > 0x7f) { json_stream_.Writef("\\u%04x", c); } else { @@ -183,8 +155,6 @@ void BinaryWriterSpec::WriteCommandType(const Command& command) { "register", "assert_malformed", "assert_invalid", - nullptr, /* ASSERT_INVALID_NON_BINARY, this command will never be - written */ "assert_unlinkable", "assert_uninstantiable", "assert_return", @@ -206,16 +176,16 @@ void BinaryWriterSpec::WriteLocation(const Location* loc) { } void BinaryWriterSpec::WriteVar(const Var* var) { - if (var->type == VarType::Index) - json_stream_.Writef("\"%" PRIindex "\"", var->index); + if (var->is_index()) + json_stream_.Writef("\"%" PRIindex "\"", var->index()); else - WriteEscapedStringSlice(var->name); + WriteEscapedString(var->name()); } void BinaryWriterSpec::WriteTypeObject(Type type) { json_stream_.Writef("{"); WriteKey("type"); - WriteString(get_type_name(type)); + WriteString(GetTypeName(type)); json_stream_.Writef("}"); } @@ -287,20 +257,20 @@ void BinaryWriterSpec::WriteAction(const Action* action) { WriteString("get"); } WriteSeparator(); - if (action->module_var.type != VarType::Index) { + if (action->module_var.is_name()) { WriteKey("module"); WriteVar(&action->module_var); WriteSeparator(); } if (action->type == ActionType::Invoke) { WriteKey("field"); - WriteEscapedStringSlice(action->name); + WriteEscapedString(action->name); WriteSeparator(); WriteKey("args"); WriteConstVector(action->invoke->args); } else { WriteKey("field"); - WriteEscapedStringSlice(action->name); + WriteEscapedString(action->name); } json_stream_.Writef("}"); } @@ -332,15 +302,15 @@ void BinaryWriterSpec::WriteActionResultType(Script* script, json_stream_.Writef("]"); } -void BinaryWriterSpec::WriteModule(char* filename, const Module* module) { +void BinaryWriterSpec::WriteModule(string_view filename, const Module* module) { MemoryStream memory_stream; - result_ = write_binary_module(&memory_stream.writer(), module, - &spec_options_->write_binary_options); - if (WABT_SUCCEEDED(result_) && write_modules_) + result_ = WriteBinaryModule(&memory_stream.writer(), module, + &spec_options_->write_binary_options); + if (Succeeded(result_) && write_modules_) result_ = memory_stream.WriteToFile(filename); } -void BinaryWriterSpec::WriteScriptModule(char* filename, +void BinaryWriterSpec::WriteScriptModule(string_view filename, const ScriptModule* script_module) { switch (script_module->type) { case ScriptModule::Type::Text: @@ -351,8 +321,7 @@ void BinaryWriterSpec::WriteScriptModule(char* filename, if (write_modules_) { FileStream file_stream(filename); if (file_stream.is_open()) { - file_stream.WriteData(script_module->binary.data, - script_module->binary.size, ""); + file_stream.WriteData(script_module->binary.data, ""); result_ = file_stream.result(); } else { result_ = Result::Error; @@ -364,8 +333,7 @@ void BinaryWriterSpec::WriteScriptModule(char* filename, if (write_modules_) { FileStream file_stream(filename); if (file_stream.is_open()) { - file_stream.WriteData(script_module->quoted.data, - script_module->quoted.size, ""); + file_stream.WriteData(script_module->quoted.data, ""); result_ = file_stream.result(); } else { result_ = Result::Error; @@ -376,7 +344,7 @@ void BinaryWriterSpec::WriteScriptModule(char* filename, } void BinaryWriterSpec::WriteInvalidModule(const ScriptModule* module, - StringSlice text) { + string_view text) { const char* extension = ""; const char* module_type = ""; switch (module->type) { @@ -398,29 +366,25 @@ void BinaryWriterSpec::WriteInvalidModule(const ScriptModule* module, WriteLocation(&module->GetLocation()); WriteSeparator(); - char* filename = GetModuleFilename(extension); + std::string filename = GetModuleFilename(extension); WriteKey("filename"); - WriteEscapedStringSlice(get_basename(filename)); + WriteEscapedString(get_basename(filename)); WriteSeparator(); WriteKey("text"); - WriteEscapedStringSlice(text); + WriteEscapedString(text); WriteSeparator(); WriteKey("module_type"); WriteString(module_type); WriteScriptModule(filename, module); - delete [] filename; } void BinaryWriterSpec::WriteCommands(Script* script) { json_stream_.Writef("{\"source_filename\": "); - WriteEscapedStringSlice(source_filename_); + WriteEscapedString(source_filename_); json_stream_.Writef(",\n \"commands\": [\n"); Index last_module_index = kInvalidIndex; for (size_t i = 0; i < script->commands.size(); ++i) { - const Command& command = *script->commands[i].get(); - - if (command.type == CommandType::AssertInvalidNonBinary) - continue; + const Command* command = script->commands[i].get(); if (i != 0) { WriteSeparator(); @@ -428,123 +392,146 @@ void BinaryWriterSpec::WriteCommands(Script* script) { } json_stream_.Writef(" {"); - WriteCommandType(command); + WriteCommandType(*command); WriteSeparator(); - switch (command.type) { + switch (command->type) { case CommandType::Module: { - Module* module = command.module; - char* filename = GetModuleFilename(kWasmExtension); + Module* module = cast(command)->module; + std::string filename = GetModuleFilename(kWasmExtension); WriteLocation(&module->loc); WriteSeparator(); - if (module->name.start) { + if (!module->name.empty()) { WriteKey("name"); - WriteEscapedStringSlice(module->name); + WriteEscapedString(module->name); WriteSeparator(); } WriteKey("filename"); - WriteEscapedStringSlice(get_basename(filename)); + WriteEscapedString(get_basename(filename)); WriteModule(filename, module); - delete [] filename; num_modules_++; last_module_index = i; break; } - case CommandType::Action: - WriteLocation(&command.action->loc); + case CommandType::Action: { + const Action* action = cast(command)->action; + WriteLocation(&action->loc); WriteSeparator(); - WriteAction(command.action); + WriteAction(action); break; + } - case CommandType::Register: - WriteLocation(&command.register_.var.loc); + case CommandType::Register: { + auto* register_command = cast(command); + const Var& var = register_command->var; + WriteLocation(&var.loc); WriteSeparator(); - if (command.register_.var.type == VarType::Name) { + if (var.is_name()) { WriteKey("name"); - WriteVar(&command.register_.var); + WriteVar(&var); WriteSeparator(); } else { /* If we're not registering by name, then we should only be * registering the last module. */ WABT_USE(last_module_index); - assert(command.register_.var.index == last_module_index); + assert(var.index() == last_module_index); } WriteKey("as"); - WriteEscapedStringSlice(command.register_.module_name); + WriteEscapedString(register_command->module_name); break; + } - case CommandType::AssertMalformed: - WriteInvalidModule(command.assert_malformed.module, - command.assert_malformed.text); + case CommandType::AssertMalformed: { + auto* assert_malformed_command = cast(command); + WriteInvalidModule(assert_malformed_command->module, + assert_malformed_command->text); num_modules_++; break; + } - case CommandType::AssertInvalid: - WriteInvalidModule(command.assert_invalid.module, - command.assert_invalid.text); + case CommandType::AssertInvalid: { + auto* assert_invalid_command = cast(command); + WriteInvalidModule(assert_invalid_command->module, + assert_invalid_command->text); num_modules_++; break; + } - case CommandType::AssertUnlinkable: - WriteInvalidModule(command.assert_unlinkable.module, - command.assert_unlinkable.text); + case CommandType::AssertUnlinkable: { + auto* assert_unlinkable_command = + cast(command); + WriteInvalidModule(assert_unlinkable_command->module, + assert_unlinkable_command->text); num_modules_++; break; + } - case CommandType::AssertUninstantiable: - WriteInvalidModule(command.assert_uninstantiable.module, - command.assert_uninstantiable.text); + case CommandType::AssertUninstantiable: { + auto* assert_uninstantiable_command = + cast(command); + WriteInvalidModule(assert_uninstantiable_command->module, + assert_uninstantiable_command->text); num_modules_++; break; + } - case CommandType::AssertReturn: - WriteLocation(&command.assert_return.action->loc); + case CommandType::AssertReturn: { + auto* assert_return_command = cast(command); + WriteLocation(&assert_return_command->action->loc); WriteSeparator(); - WriteAction(command.assert_return.action); + WriteAction(assert_return_command->action); WriteSeparator(); WriteKey("expected"); - WriteConstVector(*command.assert_return.expected); + WriteConstVector(*assert_return_command->expected); break; + } - case CommandType::AssertReturnCanonicalNan: - WriteLocation(&command.assert_return_canonical_nan.action->loc); + case CommandType::AssertReturnCanonicalNan: { + auto* assert_return_canonical_nan_command = + cast(command); + WriteLocation(&assert_return_canonical_nan_command->action->loc); WriteSeparator(); - WriteAction(command.assert_return_canonical_nan.action); + WriteAction(assert_return_canonical_nan_command->action); WriteSeparator(); WriteKey("expected"); WriteActionResultType(script, - command.assert_return_canonical_nan.action); + assert_return_canonical_nan_command->action); break; + } - case CommandType::AssertReturnArithmeticNan: - WriteLocation(&command.assert_return_arithmetic_nan.action->loc); + case CommandType::AssertReturnArithmeticNan: { + auto* assert_return_arithmetic_nan_command = + cast(command); + WriteLocation(&assert_return_arithmetic_nan_command->action->loc); WriteSeparator(); - WriteAction(command.assert_return_arithmetic_nan.action); + WriteAction(assert_return_arithmetic_nan_command->action); WriteSeparator(); WriteKey("expected"); WriteActionResultType(script, - command.assert_return_arithmetic_nan.action); + assert_return_arithmetic_nan_command->action); break; + } - case CommandType::AssertTrap: - WriteLocation(&command.assert_trap.action->loc); + case CommandType::AssertTrap: { + auto* assert_trap_command = cast(command); + WriteLocation(&assert_trap_command->action->loc); WriteSeparator(); - WriteAction(command.assert_trap.action); + WriteAction(assert_trap_command->action); WriteSeparator(); WriteKey("text"); - WriteEscapedStringSlice(command.assert_trap.text); + WriteEscapedString(assert_trap_command->text); break; + } - case CommandType::AssertExhaustion: - WriteLocation(&command.assert_trap.action->loc); + case CommandType::AssertExhaustion: { + auto* assert_exhaustion_command = + cast(command); + WriteLocation(&assert_exhaustion_command->action->loc); WriteSeparator(); - WriteAction(command.assert_trap.action); - break; - - case CommandType::AssertInvalidNonBinary: - assert(0); + WriteAction(assert_exhaustion_command->action); break; + } } json_stream_.Writef("}"); @@ -560,11 +547,11 @@ Result BinaryWriterSpec::WriteScript(Script* script) { return result_; } -} // namespace +} // end anonymous namespace -Result write_binary_spec_script(Script* script, - const char* source_filename, - const WriteBinarySpecOptions* spec_options) { +Result WriteBinarySpecScript(Script* script, + const char* source_filename, + const WriteBinarySpecOptions* spec_options) { assert(source_filename); BinaryWriterSpec binary_writer_spec(source_filename, spec_options); return binary_writer_spec.WriteScript(script); diff --git a/lib/wabt/src/binary-writer-spec.h b/lib/wabt/src/binary-writer-spec.h index 3266342ef22..e0efb768de8 100644 --- a/lib/wabt/src/binary-writer-spec.h +++ b/lib/wabt/src/binary-writer-spec.h @@ -23,17 +23,14 @@ namespace wabt { -#define WABT_WRITE_BINARY_SPEC_OPTIONS_DEFAULT \ - { nullptr, WABT_WRITE_BINARY_OPTIONS_DEFAULT } - struct WriteBinarySpecOptions { - const char* json_filename; + const char* json_filename = nullptr; WriteBinaryOptions write_binary_options; }; -Result write_binary_spec_script(struct Script*, - const char* source_filename, - const WriteBinarySpecOptions*); +Result WriteBinarySpecScript(struct Script*, + const char* source_filename, + const WriteBinarySpecOptions*); } // namespace wabt diff --git a/lib/wabt/src/binary-writer.cc b/lib/wabt/src/binary-writer.cc index 3abc12b7d3b..2a8e04da00c 100644 --- a/lib/wabt/src/binary-writer.cc +++ b/lib/wabt/src/binary-writer.cc @@ -25,8 +25,10 @@ #include #include "binary.h" +#include "cast.h" #include "ir.h" #include "stream.h" +#include "string-view.h" #include "writer.h" #define PRINT_HEADER_NO_INDEX -1 @@ -37,7 +39,7 @@ namespace wabt { // TODO(binji): move the LEB128 functions somewhere else. -Offset u32_leb128_length(uint32_t value) { +Offset U32Leb128Length(uint32_t value) { uint32_t size = 0; do { value >>= 7; @@ -58,36 +60,36 @@ Offset u32_leb128_length(uint32_t value) { } \ } while (1) -Offset write_fixed_u32_leb128_at(Stream* stream, - Offset offset, - uint32_t value, - const char* desc) { +Offset WriteFixedU32Leb128At(Stream* stream, + Offset offset, + uint32_t value, + const char* desc) { uint8_t data[MAX_U32_LEB128_BYTES]; Offset length = - write_fixed_u32_leb128_raw(data, data + MAX_U32_LEB128_BYTES, value); + WriteFixedU32Leb128Raw(data, data + MAX_U32_LEB128_BYTES, value); stream->WriteDataAt(offset, data, length, desc); return length; } -void write_u32_leb128(Stream* stream, uint32_t value, const char* desc) { +void WriteU32Leb128(Stream* stream, uint32_t value, const char* desc) { uint8_t data[MAX_U32_LEB128_BYTES]; Offset length = 0; LEB128_LOOP_UNTIL(value == 0); stream->WriteData(data, length, desc); } -void write_fixed_u32_leb128(Stream* stream, uint32_t value, const char* desc) { +void WriteFixedU32Leb128(Stream* stream, uint32_t value, const char* desc) { uint8_t data[MAX_U32_LEB128_BYTES]; Offset length = - write_fixed_u32_leb128_raw(data, data + MAX_U32_LEB128_BYTES, value); + WriteFixedU32Leb128Raw(data, data + MAX_U32_LEB128_BYTES, value); stream->WriteData(data, length, desc); } /* returns the length of the leb128 */ -Offset write_u32_leb128_at(Stream* stream, - Offset offset, - uint32_t value, - const char* desc) { +Offset WriteU32Leb128At(Stream* stream, + Offset offset, + uint32_t value, + const char* desc) { uint8_t data[MAX_U32_LEB128_BYTES]; Offset length = 0; LEB128_LOOP_UNTIL(value == 0); @@ -95,7 +97,7 @@ Offset write_u32_leb128_at(Stream* stream, return length; } -Offset write_fixed_u32_leb128_raw(uint8_t* data, uint8_t* end, uint32_t value) { +Offset WriteFixedU32Leb128Raw(uint8_t* data, uint8_t* end, uint32_t value) { if (end - data < MAX_U32_LEB128_BYTES) return 0; data[0] = (value & 0x7f) | 0x80; @@ -106,7 +108,7 @@ Offset write_fixed_u32_leb128_raw(uint8_t* data, uint8_t* end, uint32_t value) { return MAX_U32_LEB128_BYTES; } -void write_i32_leb128(Stream* stream, int32_t value, const char* desc) { +void WriteI32Leb128(Stream* stream, int32_t value, const char* desc) { uint8_t data[MAX_U32_LEB128_BYTES]; Offset length = 0; if (value < 0) @@ -117,7 +119,7 @@ void write_i32_leb128(Stream* stream, int32_t value, const char* desc) { stream->WriteData(data, length, desc); } -static void write_i64_leb128(Stream* stream, int64_t value, const char* desc) { +static void WriteI64Leb128(Stream* stream, int64_t value, const char* desc) { uint8_t data[MAX_U64_LEB128_BYTES]; Offset length = 0; if (value < 0) @@ -131,41 +133,43 @@ static void write_i64_leb128(Stream* stream, int64_t value, const char* desc) { #undef LEB128_LOOP_UNTIL -void write_str(Stream* stream, - const char* s, - size_t length, - const char* desc, - PrintChars print_chars) { - write_u32_leb128(stream, length, "string length"); - stream->WriteData(s, length, desc, print_chars); +void WriteStr(Stream* stream, + string_view s, + const char* desc, + PrintChars print_chars) { + WriteU32Leb128(stream, s.length(), "string length"); + stream->WriteData(s.data(), s.length(), desc, print_chars); } -void write_opcode(Stream* stream, Opcode opcode) { - stream->WriteU8Enum(opcode, get_opcode_name(opcode)); +void WriteOpcode(Stream* stream, Opcode opcode) { + if (opcode.HasPrefix()) { + stream->WriteU8(opcode.GetPrefix(), "prefix"); + WriteU32Leb128(stream, opcode.GetCode(), opcode.GetName()); + } else { + stream->WriteU8(opcode.GetCode(), opcode.GetName()); + } } -void write_type(Stream* stream, Type type) { - write_i32_leb128_enum(stream, type, get_type_name(type)); +void WriteType(Stream* stream, Type type) { + WriteI32Leb128Enum(stream, type, GetTypeName(type)); } -void write_limits(Stream* stream, const Limits* limits) { +void WriteLimits(Stream* stream, const Limits* limits) { uint32_t flags = limits->has_max ? WABT_BINARY_LIMITS_HAS_MAX_FLAG : 0; - write_u32_leb128(stream, flags, "limits: flags"); - write_u32_leb128(stream, limits->initial, "limits: initial"); + WriteU32Leb128(stream, flags, "limits: flags"); + WriteU32Leb128(stream, limits->initial, "limits: initial"); if (limits->has_max) - write_u32_leb128(stream, limits->max, "limits: max"); + WriteU32Leb128(stream, limits->max, "limits: max"); } -void write_debug_name(Stream* stream, - StringSlice name, - const char* desc) { - if (name.length > 0) { +void WriteDebugName(Stream* stream, string_view name, const char* desc) { + string_view stripped_name = name; + if (!stripped_name.empty()) { // Strip leading $ from name - assert(*name.start == '$'); - name.start++; - name.length--; + assert(stripped_name.front() == '$'); + stripped_name.remove_prefix(1); } - write_str(stream, name.start, name.length, desc, PrintChars::Yes); + WriteStr(stream, stripped_name, desc, PrintChars::Yes); } namespace { @@ -208,14 +212,17 @@ class BinaryWriter { void BeginSubsection(const char* name, size_t leb_size_guess); void EndSubsection(); Index GetLabelVarDepth(const Var* var); + Index GetExceptVarDepth(const Var* var); Index GetLocalIndex(const Func* func, const Var& var); void AddReloc(RelocType reloc_type, Index index); void WriteU32Leb128WithReloc(Index index, const char* desc, RelocType reloc_type); void WriteExpr(const Module* module, const Func* func, const Expr* expr); - void WriteExprList(const Module* module, const Func* func, const Expr* first); - void WriteInitExpr(const Module* module, const Expr* expr); + void WriteExprList(const Module* module, + const Func* func, + const ExprList& exprs); + void WriteInitExpr(const Module* module, const ExprList& expr); void WriteFuncLocals(const Module* module, const Func* func, const TypeVector& local_types); @@ -223,6 +230,7 @@ class BinaryWriter { void WriteTable(const Table* table); void WriteMemory(const Memory* memory); void WriteGlobalHeader(const Global* global); + void WriteExceptType(const TypeVector* except_types); void WriteRelocSection(const RelocSection* reloc_section); Stream stream_; @@ -280,19 +288,19 @@ Offset BinaryWriter::WriteFixupU32Leb128Size(Offset offset, const char* desc) { if (options_->canonicalize_lebs) { Offset size = stream_.offset() - offset - leb_size_guess; - Offset leb_size = u32_leb128_length(size); + Offset leb_size = U32Leb128Length(size); Offset delta = leb_size - leb_size_guess; if (delta != 0) { Offset src_offset = offset + leb_size_guess; Offset dst_offset = offset + leb_size; stream_.MoveData(dst_offset, src_offset, size); } - write_u32_leb128_at(&stream_, offset, size, desc); + WriteU32Leb128At(&stream_, offset, size, desc); stream_.AddOffset(delta); return delta; } else { Offset size = stream_.offset() - offset - MAX_U32_LEB128_BYTES; - write_fixed_u32_leb128_at(&stream_, offset, size, desc); + WriteFixedU32Leb128At(&stream_, offset, size, desc); return 0; } } @@ -300,9 +308,9 @@ Offset BinaryWriter::WriteFixupU32Leb128Size(Offset offset, static void write_inline_signature_type(Stream* stream, const BlockSignature& sig) { if (sig.size() == 0) { - write_type(stream, Type::Void); + WriteType(stream, Type::Void); } else if (sig.size() == 1) { - write_type(stream, sig[0]); + WriteType(stream, sig[0]); } else { /* this is currently unrepresentable */ stream->WriteU8(0xff, "INVALID INLINE SIGNATURE"); @@ -314,7 +322,7 @@ void BinaryWriter::BeginKnownSection(BinarySection section_code, assert(last_section_leb_size_guess_ == 0); char desc[100]; wabt_snprintf(desc, sizeof(desc), "section \"%s\" (%u)", - get_section_name(section_code), + GetSectionName(section_code), static_cast(section_code)); WriteHeader(desc, PRINT_HEADER_NO_INDEX); stream_.WriteU8Enum(section_code, "section code"); @@ -336,8 +344,7 @@ void BinaryWriter::BeginCustomSection(const char* name, size_t leb_size_guess) { last_section_offset_ = WriteU32Leb128Space(leb_size_guess, "section size (guess)"); last_section_payload_offset_ = stream_.offset(); - write_str(&stream_, name, strlen(name), "custom section name", - PrintChars::Yes); + WriteStr(&stream_, name, "custom section name", PrintChars::Yes); } void BinaryWriter::EndSection() { @@ -368,15 +375,18 @@ void BinaryWriter::EndSubsection() { } Index BinaryWriter::GetLabelVarDepth(const Var* var) { - assert(var->type == VarType::Index); - return var->index; + return var->index(); +} + +Index BinaryWriter::GetExceptVarDepth(const Var* var) { + return var->index(); } void BinaryWriter::AddReloc(RelocType reloc_type, Index index) { // Add a new reloc section if needed if (!current_reloc_section_ || current_reloc_section_->section_code != last_section_type_) { - reloc_sections_.emplace_back(get_section_name(last_section_type_), + reloc_sections_.emplace_back(GetSectionName(last_section_type_), last_section_type_); current_reloc_section_ = &reloc_sections_.back(); } @@ -391,9 +401,9 @@ void BinaryWriter::WriteU32Leb128WithReloc(Index index, RelocType reloc_type) { if (options_->relocatable) { AddReloc(reloc_type, index); - write_fixed_u32_leb128(&stream_, index, desc); + WriteFixedU32Leb128(&stream_, index, desc); } else { - write_u32_leb128(&stream_, index, desc); + WriteU32Leb128(&stream_, index, desc); } } @@ -402,8 +412,8 @@ Index BinaryWriter::GetLocalIndex(const Func* func, const Var& var) { // init_expr. if (func) { return func->GetLocalIndex(var); - } else if (var.type == VarType::Index) { - return var.index; + } else if (var.is_index()) { + return var.index(); } else { return kInvalidIndex; } @@ -414,206 +424,220 @@ void BinaryWriter::WriteExpr(const Module* module, const Expr* expr) { switch (expr->type) { case ExprType::Binary: - write_opcode(&stream_, expr->binary.opcode); + WriteOpcode(&stream_, cast(expr)->opcode); break; case ExprType::Block: - write_opcode(&stream_, Opcode::Block); - write_inline_signature_type(&stream_, expr->block->sig); - WriteExprList(module, func, expr->block->first); - write_opcode(&stream_, Opcode::End); + WriteOpcode(&stream_, Opcode::Block); + write_inline_signature_type(&stream_, cast(expr)->block->sig); + WriteExprList(module, func, cast(expr)->block->exprs); + WriteOpcode(&stream_, Opcode::End); break; case ExprType::Br: - write_opcode(&stream_, Opcode::Br); - write_u32_leb128(&stream_, GetLabelVarDepth(&expr->br.var), - "break depth"); + WriteOpcode(&stream_, Opcode::Br); + WriteU32Leb128(&stream_, GetLabelVarDepth(&cast(expr)->var), + "break depth"); break; case ExprType::BrIf: - write_opcode(&stream_, Opcode::BrIf); - write_u32_leb128(&stream_, GetLabelVarDepth(&expr->br_if.var), - "break depth"); + WriteOpcode(&stream_, Opcode::BrIf); + WriteU32Leb128(&stream_, GetLabelVarDepth(&cast(expr)->var), + "break depth"); break; case ExprType::BrTable: { - write_opcode(&stream_, Opcode::BrTable); - write_u32_leb128(&stream_, expr->br_table.targets->size(), "num targets"); + auto br_table_expr = cast(expr); + WriteOpcode(&stream_, Opcode::BrTable); + WriteU32Leb128(&stream_, br_table_expr->targets->size(), "num targets"); Index depth; - for (const Var& var : *expr->br_table.targets) { + for (const Var& var : *br_table_expr->targets) { depth = GetLabelVarDepth(&var); - write_u32_leb128(&stream_, depth, "break depth"); + WriteU32Leb128(&stream_, depth, "break depth"); } - depth = GetLabelVarDepth(&expr->br_table.default_target); - write_u32_leb128(&stream_, depth, "break depth for default"); + depth = GetLabelVarDepth(&br_table_expr->default_target); + WriteU32Leb128(&stream_, depth, "break depth for default"); break; } case ExprType::Call: { - Index index = module->GetFuncIndex(expr->call.var); - write_opcode(&stream_, Opcode::Call); + Index index = module->GetFuncIndex(cast(expr)->var); + WriteOpcode(&stream_, Opcode::Call); WriteU32Leb128WithReloc(index, "function index", RelocType::FuncIndexLEB); break; } case ExprType::CallIndirect: { - Index index = module->GetFuncTypeIndex(expr->call_indirect.var); - write_opcode(&stream_, Opcode::CallIndirect); - WriteU32Leb128WithReloc(index, "signature index", RelocType::TypeIndexLEB); - write_u32_leb128(&stream_, 0, "call_indirect reserved"); + Index index = module->GetFuncTypeIndex(cast(expr)->var); + WriteOpcode(&stream_, Opcode::CallIndirect); + WriteU32Leb128WithReloc(index, "signature index", + RelocType::TypeIndexLEB); + WriteU32Leb128(&stream_, 0, "call_indirect reserved"); break; } - case ExprType::Catch: - // TODO(karlschimpf): Define - WABT_FATAL("Catch: Don't know how to write\n"); - break; - case ExprType::CatchAll: - // TODO(karlschimpf): Define - WABT_FATAL("CatchAll: Don't know how to write\n"); - break; case ExprType::Compare: - write_opcode(&stream_, expr->compare.opcode); + WriteOpcode(&stream_, cast(expr)->opcode); break; - case ExprType::Const: - switch (expr->const_.type) { + case ExprType::Const: { + const Const& const_ = cast(expr)->const_; + switch (const_.type) { case Type::I32: { - write_opcode(&stream_, Opcode::I32Const); - write_i32_leb128(&stream_, expr->const_.u32, "i32 literal"); + WriteOpcode(&stream_, Opcode::I32Const); + WriteI32Leb128(&stream_, const_.u32, "i32 literal"); break; } case Type::I64: - write_opcode(&stream_, Opcode::I64Const); - write_i64_leb128(&stream_, expr->const_.u64, "i64 literal"); + WriteOpcode(&stream_, Opcode::I64Const); + WriteI64Leb128(&stream_, const_.u64, "i64 literal"); break; case Type::F32: - write_opcode(&stream_, Opcode::F32Const); - stream_.WriteU32(expr->const_.f32_bits, "f32 literal"); + WriteOpcode(&stream_, Opcode::F32Const); + stream_.WriteU32(const_.f32_bits, "f32 literal"); break; case Type::F64: - write_opcode(&stream_, Opcode::F64Const); - stream_.WriteU64(expr->const_.f64_bits, "f64 literal"); + WriteOpcode(&stream_, Opcode::F64Const); + stream_.WriteU64(const_.f64_bits, "f64 literal"); break; default: assert(0); } break; + } case ExprType::Convert: - write_opcode(&stream_, expr->convert.opcode); + WriteOpcode(&stream_, cast(expr)->opcode); break; case ExprType::CurrentMemory: - write_opcode(&stream_, Opcode::CurrentMemory); - write_u32_leb128(&stream_, 0, "current_memory reserved"); + WriteOpcode(&stream_, Opcode::CurrentMemory); + WriteU32Leb128(&stream_, 0, "current_memory reserved"); break; case ExprType::Drop: - write_opcode(&stream_, Opcode::Drop); + WriteOpcode(&stream_, Opcode::Drop); break; case ExprType::GetGlobal: { - Index index = module->GetGlobalIndex(expr->get_global.var); - write_opcode(&stream_, Opcode::GetGlobal); + Index index = module->GetGlobalIndex(cast(expr)->var); + WriteOpcode(&stream_, Opcode::GetGlobal); WriteU32Leb128WithReloc(index, "global index", RelocType::GlobalIndexLEB); break; } case ExprType::GetLocal: { - Index index = GetLocalIndex(func, expr->get_local.var); - write_opcode(&stream_, Opcode::GetLocal); - write_u32_leb128(&stream_, index, "local index"); + Index index = GetLocalIndex(func, cast(expr)->var); + WriteOpcode(&stream_, Opcode::GetLocal); + WriteU32Leb128(&stream_, index, "local index"); break; } case ExprType::GrowMemory: - write_opcode(&stream_, Opcode::GrowMemory); - write_u32_leb128(&stream_, 0, "grow_memory reserved"); + WriteOpcode(&stream_, Opcode::GrowMemory); + WriteU32Leb128(&stream_, 0, "grow_memory reserved"); break; - case ExprType::If: - write_opcode(&stream_, Opcode::If); - write_inline_signature_type(&stream_, expr->if_.true_->sig); - WriteExprList(module, func, expr->if_.true_->first); - if (expr->if_.false_) { - write_opcode(&stream_, Opcode::Else); - WriteExprList(module, func, expr->if_.false_); + case ExprType::If: { + auto if_expr = cast(expr); + WriteOpcode(&stream_, Opcode::If); + write_inline_signature_type(&stream_, if_expr->true_->sig); + WriteExprList(module, func, if_expr->true_->exprs); + if (!if_expr->false_.empty()) { + WriteOpcode(&stream_, Opcode::Else); + WriteExprList(module, func, if_expr->false_); } - write_opcode(&stream_, Opcode::End); + WriteOpcode(&stream_, Opcode::End); break; + } case ExprType::Load: { - write_opcode(&stream_, expr->load.opcode); - Address align = get_opcode_alignment(expr->load.opcode, expr->load.align); + auto load_expr = cast(expr); + WriteOpcode(&stream_, load_expr->opcode); + Address align = load_expr->opcode.GetAlignment(load_expr->align); stream_.WriteU8(log2_u32(align), "alignment"); - write_u32_leb128(&stream_, expr->load.offset, "load offset"); + WriteU32Leb128(&stream_, load_expr->offset, "load offset"); break; } case ExprType::Loop: - write_opcode(&stream_, Opcode::Loop); - write_inline_signature_type(&stream_, expr->loop->sig); - WriteExprList(module, func, expr->loop->first); - write_opcode(&stream_, Opcode::End); + WriteOpcode(&stream_, Opcode::Loop); + write_inline_signature_type(&stream_, cast(expr)->block->sig); + WriteExprList(module, func, cast(expr)->block->exprs); + WriteOpcode(&stream_, Opcode::End); break; case ExprType::Nop: - write_opcode(&stream_, Opcode::Nop); + WriteOpcode(&stream_, Opcode::Nop); break; case ExprType::Rethrow: - // TODO(karlschimpf): Define - WABT_FATAL("Rethrow: Don't know how to write\n"); + WriteOpcode(&stream_, Opcode::Rethrow); + WriteU32Leb128(&stream_, GetLabelVarDepth(&cast(expr)->var), + "rethrow depth"); break; case ExprType::Return: - write_opcode(&stream_, Opcode::Return); + WriteOpcode(&stream_, Opcode::Return); break; case ExprType::Select: - write_opcode(&stream_, Opcode::Select); + WriteOpcode(&stream_, Opcode::Select); break; case ExprType::SetGlobal: { - Index index = module->GetGlobalIndex(expr->get_global.var); - write_opcode(&stream_, Opcode::SetGlobal); + Index index = module->GetGlobalIndex(cast(expr)->var); + WriteOpcode(&stream_, Opcode::SetGlobal); WriteU32Leb128WithReloc(index, "global index", RelocType::GlobalIndexLEB); break; } case ExprType::SetLocal: { - Index index = GetLocalIndex(func, expr->get_local.var); - write_opcode(&stream_, Opcode::SetLocal); - write_u32_leb128(&stream_, index, "local index"); + Index index = GetLocalIndex(func, cast(expr)->var); + WriteOpcode(&stream_, Opcode::SetLocal); + WriteU32Leb128(&stream_, index, "local index"); break; } case ExprType::Store: { - write_opcode(&stream_, expr->store.opcode); - Address align = - get_opcode_alignment(expr->store.opcode, expr->store.align); + auto store_expr = cast(expr); + WriteOpcode(&stream_, store_expr->opcode); + Address align = store_expr->opcode.GetAlignment(store_expr->align); stream_.WriteU8(log2_u32(align), "alignment"); - write_u32_leb128(&stream_, expr->store.offset, "store offset"); + WriteU32Leb128(&stream_, store_expr->offset, "store offset"); break; } case ExprType::TeeLocal: { - Index index = GetLocalIndex(func, expr->get_local.var); - write_opcode(&stream_, Opcode::TeeLocal); - write_u32_leb128(&stream_, index, "local index"); + Index index = GetLocalIndex(func, cast(expr)->var); + WriteOpcode(&stream_, Opcode::TeeLocal); + WriteU32Leb128(&stream_, index, "local index"); break; } case ExprType::Throw: - // TODO(karlschimpf): Define - WABT_FATAL("Throw: Don't know how to write\n"); + WriteOpcode(&stream_, Opcode::Throw); + WriteU32Leb128(&stream_, GetExceptVarDepth(&cast(expr)->var), + "throw exception"); break; - case ExprType::TryBlock: - // TODO(karlschimpf): Define - WABT_FATAL("TryBlock: Don't know how to write\n"); + case ExprType::TryBlock: { + auto try_expr = cast(expr); + WriteOpcode(&stream_, Opcode::Try); + write_inline_signature_type(&stream_, try_expr->block->sig); + WriteExprList(module, func, try_expr->block->exprs); + for (Catch* catch_ : try_expr->catches) { + if (catch_->IsCatchAll()) { + WriteOpcode(&stream_, Opcode::CatchAll); + } else { + WriteOpcode(&stream_, Opcode::Catch); + WriteU32Leb128(&stream_, GetExceptVarDepth(&catch_->var), + "catch exception"); + } + WriteExprList(module, func, catch_->exprs); + } + WriteOpcode(&stream_, Opcode::End); break; + } case ExprType::Unary: - write_opcode(&stream_, expr->unary.opcode); + WriteOpcode(&stream_, cast(expr)->opcode); break; case ExprType::Unreachable: - write_opcode(&stream_, Opcode::Unreachable); + WriteOpcode(&stream_, Opcode::Unreachable); break; } } void BinaryWriter::WriteExprList(const Module* module, const Func* func, - const Expr* first) { - for (const Expr* expr = first; expr; expr = expr->next) - WriteExpr(module, func, expr); + const ExprList& exprs) { + for (const Expr& expr : exprs) + WriteExpr(module, func, &expr); } -void BinaryWriter::WriteInitExpr(const Module* module, const Expr* expr) { - if (expr) - WriteExprList(module, nullptr, expr); - write_opcode(&stream_, Opcode::End); +void BinaryWriter::WriteInitExpr(const Module* module, const ExprList& expr) { + WriteExprList(module, nullptr, expr); + WriteOpcode(&stream_, Opcode::End); } void BinaryWriter::WriteFuncLocals(const Module* module, const Func* func, const TypeVector& local_types) { if (local_types.size() == 0) { - write_u32_leb128(&stream_, 0, "local decl count"); + WriteU32Leb128(&stream_, 0, "local decl count"); return; } @@ -635,7 +659,7 @@ void BinaryWriter::WriteFuncLocals(const Module* module, } /* loop through again to write everything out */ - write_u32_leb128(&stream_, local_decl_count, "local decl count"); + WriteU32Leb128(&stream_, local_decl_count, "local decl count"); current_type = GET_LOCAL_TYPE(FIRST_LOCAL_INDEX); Index local_type_count = 1; for (Index i = FIRST_LOCAL_INDEX + 1; i <= LAST_LOCAL_INDEX; ++i) { @@ -644,8 +668,8 @@ void BinaryWriter::WriteFuncLocals(const Module* module, if (current_type == type) { local_type_count++; } else { - write_u32_leb128(&stream_, local_type_count, "local type count"); - write_type(&stream_, current_type); + WriteU32Leb128(&stream_, local_type_count, "local type count"); + WriteType(&stream_, current_type); local_type_count = 1; current_type = type; } @@ -654,43 +678,49 @@ void BinaryWriter::WriteFuncLocals(const Module* module, void BinaryWriter::WriteFunc(const Module* module, const Func* func) { WriteFuncLocals(module, func, func->local_types); - WriteExprList(module, func, func->first_expr); - write_opcode(&stream_, Opcode::End); + WriteExprList(module, func, func->exprs); + WriteOpcode(&stream_, Opcode::End); } void BinaryWriter::WriteTable(const Table* table) { - write_type(&stream_, Type::Anyfunc); - write_limits(&stream_, &table->elem_limits); + WriteType(&stream_, Type::Anyfunc); + WriteLimits(&stream_, &table->elem_limits); } void BinaryWriter::WriteMemory(const Memory* memory) { - write_limits(&stream_, &memory->page_limits); + WriteLimits(&stream_, &memory->page_limits); } void BinaryWriter::WriteGlobalHeader(const Global* global) { - write_type(&stream_, global->type); + WriteType(&stream_, global->type); stream_.WriteU8(global->mutable_, "global mutability"); } +void BinaryWriter::WriteExceptType(const TypeVector* except_types) { + WriteU32Leb128(&stream_, except_types->size(), "exception type count"); + for (Type ty : *except_types) + WriteType(&stream_, ty); +} + void BinaryWriter::WriteRelocSection(const RelocSection* reloc_section) { char section_name[128]; wabt_snprintf(section_name, sizeof(section_name), "%s.%s", WABT_BINARY_SECTION_RELOC, reloc_section->name); BeginCustomSection(section_name, LEB_SECTION_SIZE_GUESS); - write_u32_leb128_enum(&stream_, reloc_section->section_code, - "reloc section type"); + WriteU32Leb128Enum(&stream_, reloc_section->section_code, + "reloc section type"); const std::vector& relocs = reloc_section->relocations; - write_u32_leb128(&stream_, relocs.size(), "num relocs"); + WriteU32Leb128(&stream_, relocs.size(), "num relocs"); for (const Reloc& reloc : relocs) { - write_u32_leb128_enum(&stream_, reloc.type, "reloc type"); - write_u32_leb128(&stream_, reloc.offset, "reloc offset"); - write_u32_leb128(&stream_, reloc.index, "reloc index"); + WriteU32Leb128Enum(&stream_, reloc.type, "reloc type"); + WriteU32Leb128(&stream_, reloc.offset, "reloc offset"); + WriteU32Leb128(&stream_, reloc.index, "reloc index"); switch (reloc.type) { case RelocType::GlobalAddressLEB: case RelocType::GlobalAddressSLEB: case RelocType::GlobalAddressI32: - write_u32_leb128(&stream_, reloc.addend, "reloc addend"); + WriteU32Leb128(&stream_, reloc.addend, "reloc addend"); break; default: break; @@ -706,43 +736,42 @@ Result BinaryWriter::WriteModule(const Module* module) { if (module->func_types.size()) { BeginKnownSection(BinarySection::Type, LEB_SECTION_SIZE_GUESS); - write_u32_leb128(&stream_, module->func_types.size(), "num types"); + WriteU32Leb128(&stream_, module->func_types.size(), "num types"); for (size_t i = 0; i < module->func_types.size(); ++i) { const FuncType* func_type = module->func_types[i]; const FuncSignature* sig = &func_type->sig; WriteHeader("type", i); - write_type(&stream_, Type::Func); + WriteType(&stream_, Type::Func); Index num_params = sig->param_types.size(); Index num_results = sig->result_types.size(); - write_u32_leb128(&stream_, num_params, "num params"); + WriteU32Leb128(&stream_, num_params, "num params"); for (size_t j = 0; j < num_params; ++j) - write_type(&stream_, sig->param_types[j]); + WriteType(&stream_, sig->param_types[j]); - write_u32_leb128(&stream_, num_results, "num results"); + WriteU32Leb128(&stream_, num_results, "num results"); for (size_t j = 0; j < num_results; ++j) - write_type(&stream_, sig->result_types[j]); + WriteType(&stream_, sig->result_types[j]); } EndSection(); } if (module->imports.size()) { BeginKnownSection(BinarySection::Import, LEB_SECTION_SIZE_GUESS); - write_u32_leb128(&stream_, module->imports.size(), "num imports"); + WriteU32Leb128(&stream_, module->imports.size(), "num imports"); for (size_t i = 0; i < module->imports.size(); ++i) { const Import* import = module->imports[i]; WriteHeader("import header", i); - write_str(&stream_, import->module_name.start, import->module_name.length, - "import module name", PrintChars::Yes); - write_str(&stream_, import->field_name.start, import->field_name.length, - "import field name", PrintChars::Yes); + WriteStr(&stream_, import->module_name, "import module name", + PrintChars::Yes); + WriteStr(&stream_, import->field_name, "import field name", + PrintChars::Yes); stream_.WriteU8Enum(import->kind, "import kind"); switch (import->kind) { case ExternalKind::Func: - write_u32_leb128(&stream_, - module->GetFuncTypeIndex(import->func->decl), - "import signature index"); + WriteU32Leb128(&stream_, module->GetFuncTypeIndex(import->func->decl), + "import signature index"); break; case ExternalKind::Table: WriteTable(import->table); @@ -754,8 +783,7 @@ Result BinaryWriter::WriteModule(const Module* module) { WriteGlobalHeader(import->global); break; case ExternalKind::Except: - // TODO(karlschimpf) Define. - WABT_FATAL("write import except not implemented\n"); + WriteExceptType(&import->except->sig); break; } } @@ -766,14 +794,14 @@ Result BinaryWriter::WriteModule(const Module* module) { Index num_funcs = module->funcs.size() - module->num_func_imports; if (num_funcs) { BeginKnownSection(BinarySection::Function, LEB_SECTION_SIZE_GUESS); - write_u32_leb128(&stream_, num_funcs, "num functions"); + WriteU32Leb128(&stream_, num_funcs, "num functions"); for (size_t i = 0; i < num_funcs; ++i) { const Func* func = module->funcs[i + module->num_func_imports]; char desc[100]; wabt_snprintf(desc, sizeof(desc), "function %" PRIzd " signature index", i); - write_u32_leb128(&stream_, module->GetFuncTypeIndex(func->decl), desc); + WriteU32Leb128(&stream_, module->GetFuncTypeIndex(func->decl), desc); } EndSection(); } @@ -782,7 +810,7 @@ Result BinaryWriter::WriteModule(const Module* module) { Index num_tables = module->tables.size() - module->num_table_imports; if (num_tables) { BeginKnownSection(BinarySection::Table, LEB_SECTION_SIZE_GUESS); - write_u32_leb128(&stream_, num_tables, "num tables"); + WriteU32Leb128(&stream_, num_tables, "num tables"); for (size_t i = 0; i < num_tables; ++i) { const Table* table = module->tables[i + module->num_table_imports]; WriteHeader("table", i); @@ -795,7 +823,7 @@ Result BinaryWriter::WriteModule(const Module* module) { Index num_memories = module->memories.size() - module->num_memory_imports; if (num_memories) { BeginKnownSection(BinarySection::Memory, LEB_SECTION_SIZE_GUESS); - write_u32_leb128(&stream_, num_memories, "num memories"); + WriteU32Leb128(&stream_, num_memories, "num memories"); for (size_t i = 0; i < num_memories; ++i) { const Memory* memory = module->memories[i + module->num_memory_imports]; WriteHeader("memory", i); @@ -808,7 +836,7 @@ Result BinaryWriter::WriteModule(const Module* module) { Index num_globals = module->globals.size() - module->num_global_imports; if (num_globals) { BeginKnownSection(BinarySection::Global, LEB_SECTION_SIZE_GUESS); - write_u32_leb128(&stream_, num_globals, "num globals"); + WriteU32Leb128(&stream_, num_globals, "num globals"); for (size_t i = 0; i < num_globals; ++i) { const Global* global = module->globals[i + module->num_global_imports]; @@ -820,37 +848,37 @@ Result BinaryWriter::WriteModule(const Module* module) { if (module->exports.size()) { BeginKnownSection(BinarySection::Export, LEB_SECTION_SIZE_GUESS); - write_u32_leb128(&stream_, module->exports.size(), "num exports"); + WriteU32Leb128(&stream_, module->exports.size(), "num exports"); for (const Export* export_ : module->exports) { - write_str(&stream_, export_->name.start, export_->name.length, - "export name", PrintChars::Yes); + WriteStr(&stream_, export_->name, "export name", PrintChars::Yes); stream_.WriteU8Enum(export_->kind, "export kind"); switch (export_->kind) { case ExternalKind::Func: { Index index = module->GetFuncIndex(export_->var); - write_u32_leb128(&stream_, index, "export func index"); + WriteU32Leb128(&stream_, index, "export func index"); break; } case ExternalKind::Table: { Index index = module->GetTableIndex(export_->var); - write_u32_leb128(&stream_, index, "export table index"); + WriteU32Leb128(&stream_, index, "export table index"); break; } case ExternalKind::Memory: { Index index = module->GetMemoryIndex(export_->var); - write_u32_leb128(&stream_, index, "export memory index"); + WriteU32Leb128(&stream_, index, "export memory index"); break; } case ExternalKind::Global: { Index index = module->GetGlobalIndex(export_->var); - write_u32_leb128(&stream_, index, "export global index"); + WriteU32Leb128(&stream_, index, "export global index"); break; } - case ExternalKind::Except: - // TODO(karlschimpf) Define. - WABT_FATAL("write export except not implemented\n"); + case ExternalKind::Except: { + Index index = module->GetExceptIndex(export_->var); + WriteU32Leb128(&stream_, index, "export exception index"); break; + } } } EndSection(); @@ -860,22 +888,21 @@ Result BinaryWriter::WriteModule(const Module* module) { Index start_func_index = module->GetFuncIndex(*module->start); if (start_func_index != kInvalidIndex) { BeginKnownSection(BinarySection::Start, LEB_SECTION_SIZE_GUESS); - write_u32_leb128(&stream_, start_func_index, "start func index"); + WriteU32Leb128(&stream_, start_func_index, "start func index"); EndSection(); } } if (module->elem_segments.size()) { BeginKnownSection(BinarySection::Elem, LEB_SECTION_SIZE_GUESS); - write_u32_leb128(&stream_, module->elem_segments.size(), - "num elem segments"); + WriteU32Leb128(&stream_, module->elem_segments.size(), "num elem segments"); for (size_t i = 0; i < module->elem_segments.size(); ++i) { ElemSegment* segment = module->elem_segments[i]; Index table_index = module->GetTableIndex(segment->table_var); WriteHeader("elem segment header", i); - write_u32_leb128(&stream_, table_index, "table index"); + WriteU32Leb128(&stream_, table_index, "table index"); WriteInitExpr(module, segment->offset); - write_u32_leb128(&stream_, segment->vars.size(), "num function indices"); + WriteU32Leb128(&stream_, segment->vars.size(), "num function indices"); for (const Var& var : segment->vars) { Index index = module->GetFuncIndex(var); WriteU32Leb128WithReloc(index, "function index", @@ -885,9 +912,20 @@ Result BinaryWriter::WriteModule(const Module* module) { EndSection(); } + assert(module->excepts.size() >= module->num_except_imports); + Index num_exceptions = module->excepts.size() - module->num_except_imports; + if (num_exceptions) { + BeginCustomSection("exception", LEB_SECTION_SIZE_GUESS); + WriteU32Leb128(&stream_, num_exceptions, "exception count"); + for (Index i = module->num_except_imports; i < num_exceptions; ++i) { + WriteExceptType(&module->excepts[i]->sig); + } + EndSection(); + } + if (num_funcs) { BeginKnownSection(BinarySection::Code, LEB_SECTION_SIZE_GUESS); - write_u32_leb128(&stream_, num_funcs, "num functions"); + WriteU32Leb128(&stream_, num_funcs, "num functions"); for (size_t i = 0; i < num_funcs; ++i) { WriteHeader("function body", i); @@ -906,17 +944,16 @@ Result BinaryWriter::WriteModule(const Module* module) { if (module->data_segments.size()) { BeginKnownSection(BinarySection::Data, LEB_SECTION_SIZE_GUESS); - write_u32_leb128(&stream_, module->data_segments.size(), - "num data segments"); + WriteU32Leb128(&stream_, module->data_segments.size(), "num data segments"); for (size_t i = 0; i < module->data_segments.size(); ++i) { const DataSegment* segment = module->data_segments[i]; WriteHeader("data segment header", i); Index memory_index = module->GetMemoryIndex(segment->memory_var); - write_u32_leb128(&stream_, memory_index, "memory index"); + WriteU32Leb128(&stream_, memory_index, "memory index"); WriteInitExpr(module, segment->offset); - write_u32_leb128(&stream_, segment->size, "data segment size"); + WriteU32Leb128(&stream_, segment->data.size(), "data segment size"); WriteHeader("data segment data", i); - stream_.WriteData(segment->data, segment->size, "data segment data"); + stream_.WriteData(segment->data, "data segment data"); } EndSection(); } @@ -929,46 +966,46 @@ Result BinaryWriter::WriteModule(const Module* module) { size_t named_functions = 0; for (const Func* func : module->funcs) { - if (func->name.length > 0) + if (!func->name.empty()) named_functions++; } if (named_functions > 0) { - write_u32_leb128(&stream_, 1, "function name type"); + WriteU32Leb128(&stream_, 1, "function name type"); BeginSubsection("function name subsection", LEB_SECTION_SIZE_GUESS); - write_u32_leb128(&stream_, named_functions, "num functions"); + WriteU32Leb128(&stream_, named_functions, "num functions"); for (size_t i = 0; i < module->funcs.size(); ++i) { const Func* func = module->funcs[i]; - if (func->name.length == 0) + if (func->name.empty()) continue; - write_u32_leb128(&stream_, i, "function index"); + WriteU32Leb128(&stream_, i, "function index"); wabt_snprintf(desc, sizeof(desc), "func name %" PRIzd, i); - write_debug_name(&stream_, func->name, desc); + WriteDebugName(&stream_, func->name, desc); } EndSubsection(); } - write_u32_leb128(&stream_, 2, "local name type"); + WriteU32Leb128(&stream_, 2, "local name type"); BeginSubsection("local name subsection", LEB_SECTION_SIZE_GUESS); - write_u32_leb128(&stream_, module->funcs.size(), "num functions"); + WriteU32Leb128(&stream_, module->funcs.size(), "num functions"); for (size_t i = 0; i < module->funcs.size(); ++i) { const Func* func = module->funcs[i]; Index num_params = func->GetNumParams(); Index num_locals = func->local_types.size(); Index num_params_and_locals = func->GetNumParamsAndLocals(); - write_u32_leb128(&stream_, i, "function index"); - write_u32_leb128(&stream_, num_params_and_locals, "num locals"); + WriteU32Leb128(&stream_, i, "function index"); + WriteU32Leb128(&stream_, num_params_and_locals, "num locals"); MakeTypeBindingReverseMapping(func->decl.sig.param_types, func->param_bindings, &index_to_name); for (size_t j = 0; j < num_params; ++j) { const std::string& name = index_to_name[j]; wabt_snprintf(desc, sizeof(desc), "local name %" PRIzd, j); - write_u32_leb128(&stream_, j, "local index"); - write_debug_name(&stream_, string_to_string_slice(name), desc); + WriteU32Leb128(&stream_, j, "local index"); + WriteDebugName(&stream_, name, desc); } MakeTypeBindingReverseMapping(func->local_types, func->local_bindings, @@ -976,8 +1013,8 @@ Result BinaryWriter::WriteModule(const Module* module) { for (size_t j = 0; j < num_locals; ++j) { const std::string& name = index_to_name[j]; wabt_snprintf(desc, sizeof(desc), "local name %" PRIzd, num_params + j); - write_u32_leb128(&stream_, num_params + j, "local index"); - write_debug_name(&stream_, string_to_string_slice(name), desc); + WriteU32Leb128(&stream_, num_params + j, "local index"); + WriteDebugName(&stream_, name, desc); } } EndSubsection(); @@ -990,14 +1027,15 @@ Result BinaryWriter::WriteModule(const Module* module) { } } + return stream_.result(); } -} // namespace +} // end anonymous namespace -Result write_binary_module(Writer* writer, - const Module* module, - const WriteBinaryOptions* options) { +Result WriteBinaryModule(Writer* writer, + const Module* module, + const WriteBinaryOptions* options) { BinaryWriter binary_writer(writer, options); return binary_writer.WriteModule(module); } diff --git a/lib/wabt/src/binary-writer.h b/lib/wabt/src/binary-writer.h index e94b5819309..2ddb01787e2 100644 --- a/lib/wabt/src/binary-writer.h +++ b/lib/wabt/src/binary-writer.h @@ -27,55 +27,51 @@ class Writer; struct Module; struct Script; -#define WABT_WRITE_BINARY_OPTIONS_DEFAULT \ - { nullptr, true, false, false } - struct WriteBinaryOptions { - Stream* log_stream; - bool canonicalize_lebs; - bool relocatable; - bool write_debug_names; + Stream* log_stream = nullptr; + bool canonicalize_lebs = true; + bool relocatable = false; + bool write_debug_names = false; }; -Result write_binary_module(Writer*, const Module*, const WriteBinaryOptions*); +Result WriteBinaryModule(Writer*, const Module*, const WriteBinaryOptions*); /* returns the length of the leb128 */ -Offset u32_leb128_length(uint32_t value); +Offset U32Leb128Length(uint32_t value); -void write_u32_leb128(Stream* stream, uint32_t value, const char* desc); +void WriteU32Leb128(Stream* stream, uint32_t value, const char* desc); -void write_i32_leb128(Stream* stream, int32_t value, const char* desc); +void WriteI32Leb128(Stream* stream, int32_t value, const char* desc); -void write_fixed_u32_leb128(Stream* stream, uint32_t value, const char* desc); +void WriteFixedU32Leb128(Stream* stream, uint32_t value, const char* desc); -Offset write_fixed_u32_leb128_at(Stream* stream, - Offset offset, - uint32_t value, - const char* desc); +Offset WriteFixedU32Leb128At(Stream* stream, + Offset offset, + uint32_t value, + const char* desc); -Offset write_fixed_u32_leb128_raw(uint8_t* data, uint8_t* end, uint32_t value); +Offset WriteFixedU32Leb128Raw(uint8_t* data, uint8_t* end, uint32_t value); -void write_type(Stream* stream, Type type); +void WriteType(Stream* stream, Type type); -void write_str(Stream* stream, - const char* s, - size_t length, - const char* desc, - PrintChars print_chars = PrintChars::No); +void WriteStr(Stream* stream, + string_view s, + const char* desc, + PrintChars print_chars = PrintChars::No); -void write_opcode(Stream* stream, Opcode opcode); +void WriteOpcode(Stream* stream, Opcode opcode); -void write_limits(Stream* stream, const Limits* limits); +void WriteLimits(Stream* stream, const Limits* limits); /* Convenience functions for writing enums as LEB128s. */ template -void write_u32_leb128_enum(Stream* stream, T value, const char* desc) { - write_u32_leb128(stream, static_cast(value), desc); +void WriteU32Leb128Enum(Stream* stream, T value, const char* desc) { + WriteU32Leb128(stream, static_cast(value), desc); } template -void write_i32_leb128_enum(Stream* stream, T value, const char* desc) { - write_i32_leb128(stream, static_cast(value), desc); +void WriteI32Leb128Enum(Stream* stream, T value, const char* desc) { + WriteI32Leb128(stream, static_cast(value), desc); } } // namespace wabt diff --git a/lib/wabt/src/binary.h b/lib/wabt/src/binary.h index 4e64f2b178b..d784fff1eae 100644 --- a/lib/wabt/src/binary.h +++ b/lib/wabt/src/binary.h @@ -25,6 +25,8 @@ #define WABT_BINARY_SECTION_NAME "name" #define WABT_BINARY_SECTION_RELOC "reloc" +#define WABT_BINARY_SECTION_LINKING "linking" +#define WABT_BINARY_SECTION_EXCEPTION "exception" #define WABT_FOREACH_BINARY_SECTION(V) \ V(Custom, custom, 0) \ @@ -57,7 +59,7 @@ static const int kBinarySectionCount = WABT_ENUM_COUNT(BinarySection); extern const char* g_section_name[]; -static WABT_INLINE const char* get_section_name(BinarySection sec) { +static WABT_INLINE const char* GetSectionName(BinarySection sec) { assert(static_cast(sec) < kBinarySectionCount); return g_section_name[static_cast(sec)]; } diff --git a/lib/wabt/src/binding-hash.cc b/lib/wabt/src/binding-hash.cc index d1297d926ed..0eed179d21e 100644 --- a/lib/wabt/src/binding-hash.cc +++ b/lib/wabt/src/binding-hash.cc @@ -33,9 +33,9 @@ void BindingHash::FindDuplicates(DuplicateCallback callback) const { } Index BindingHash::FindIndex(const Var& var) const { - if (var.type == VarType::Name) - return FindIndex(var.name); - return var.index; + if (var.is_name()) + return FindIndex(var.name()); + return var.index(); } void BindingHash::CreateDuplicatesVector( diff --git a/lib/wabt/src/binding-hash.h b/lib/wabt/src/binding-hash.h index 3b4cd7eb4ad..04de1afd552 100644 --- a/lib/wabt/src/binding-hash.h +++ b/lib/wabt/src/binding-hash.h @@ -23,15 +23,14 @@ #include #include "common.h" +#include "string-view.h" namespace wabt { struct Var; struct Binding { - explicit Binding(Index index) : index(index) { - WABT_ZERO_MEMORY(loc); - } + explicit Binding(Index index) : index(index) {} Binding(const Location& loc, Index index) : loc(loc), index(index) {} Location loc; @@ -50,11 +49,13 @@ class BindingHash : public std::unordered_multimap { Index FindIndex(const Var&) const; - Index FindIndex(const StringSlice& name) const { - auto iter = find(string_slice_to_string(name)); - if (iter != end()) - return iter->second.index; - return kInvalidIndex; + Index FindIndex(const std::string& name) const { + auto iter = find(name); + return iter != end() ? iter->second.index : kInvalidIndex; + } + + Index FindIndex(string_view name) const { + return FindIndex(name.to_string()); } private: diff --git a/lib/wabt/src/cast.h b/lib/wabt/src/cast.h new file mode 100644 index 00000000000..1b5d7350cac --- /dev/null +++ b/lib/wabt/src/cast.h @@ -0,0 +1,93 @@ +/* + * Copyright 2017 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 WABT_CAST_H_ +#define WABT_CAST_H_ + +#include + +#include "common.h" + +// Modeled after LLVM's dynamic casts: +// http://llvm.org/docs/ProgrammersManual.html#the-isa-cast-and-dyn-cast-templates +// +// Use isa(foo) to check whether foo is a T*: +// +// if (isa(car)) { +// ... +// } +// +// Use cast(foo) when you know that foo is a T* -- it will assert that the +// type matches: +// +// switch (car.type) { +// case CarType::Minivan: { +// auto minivan = cast(car); +// ... +// } +// } +// +// Use dyn_cast(foo) as a combination if isa and cast, it will return +// nullptr if the type doesn't match: +// +// if (auto minivan = dyn_cast(car)) { +// ... +// } +// +// +// To use these classes in a type hierarchy, you must implement classof: +// +// enum CarType { Minivan, ... }; +// struct Car { CarType type; ... }; +// struct Minivan : Car { +// static bool classof(const Car* car) { return car->type == Minivan; } +// ... +// }; +// + +namespace wabt { + +template +bool isa(const Base* base) { + WABT_STATIC_ASSERT((std::is_base_of::value)); + return Derived::classof(base); +} + +template +const Derived* cast(const Base* base) { + assert(isa(base)); + return static_cast(base); +}; + +template +Derived* cast(Base* base) { + assert(isa(base)); + return static_cast(base); +}; + +template +const Derived* dyn_cast(const Base* base) { + return isa(base) ? static_cast(base) : nullptr; +}; + +template +Derived* dyn_cast(Base* base) { + return isa(base) ? static_cast(base) : nullptr; +}; + +} // namespace wabt + +#endif // WABT_CAST_H_ diff --git a/lib/wabt/src/circular-array.h b/lib/wabt/src/circular-array.h new file mode 100644 index 00000000000..265410e8b86 --- /dev/null +++ b/lib/wabt/src/circular-array.h @@ -0,0 +1,116 @@ +/* + * Copyright 2017 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 WABT_CIRCULAR_ARRAY_H_ +#define WABT_CIRCULAR_ARRAY_H_ + +#include +#include +#include +#include + +namespace wabt { + +// TODO(karlschimpf) Complete the API +// TODO(karlschimpf) Apply constructors/destructors on base type T +// as collection size changes (if not POD). +// Note: Capacity must be a power of 2. +template +class CircularArray { + public: + typedef T value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + CircularArray() : size_(0), front_(0), mask_(kCapacity - 1) { + static_assert(kCapacity && ((kCapacity & (kCapacity - 1)) == 0), + "Capacity must be a power of 2."); + } + + reference at(size_type index) { + assert(index < size_); + return (*this)[index]; + } + + const_reference at(size_type index) const { + assert(index < size_); + return (*this)[index]; + } + + reference operator[](size_type index) { + return contents_[position(index)]; + } + + const_reference operator[](size_type index) const { + return contents_[position(index)]; + } + + reference back() { + return at(size_ - 1); + } + + const_reference back() const { + return at(size_ - 1); + } + + bool empty() const { return size_ == 0; } + + reference front() { + return at(0); + } + + const_reference front() const { + return at(0); + } + + size_type max_size() const { return kCapacity; } + + void pop_back() { + assert(size_ > 0); + --size_; + } + + void pop_front() { + assert(size_ > 0); + front_ = (front_ + 1) & mask_; + --size_; + } + + void push_back(const value_type& value) { + assert(size_ < kCapacity); + contents_[position(size_++)] = value; + } + + size_type size() const { return size_; } + + void clear() { + size_ = 0; + } + + private: + std::array contents_; + size_type size_; + size_type front_; + size_type mask_; + + size_t position(size_t index) const { return (front_ + index) & mask_; } +}; + +} + +#endif // WABT_CIRCULAR_ARRAY_H_ diff --git a/lib/wabt/src/color.cc b/lib/wabt/src/color.cc new file mode 100644 index 00000000000..e104dd989be --- /dev/null +++ b/lib/wabt/src/color.cc @@ -0,0 +1,84 @@ +/* + * Copyright 2017 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. + */ + +#include "color.h" + +#include + +#include "common.h" + +#if _WIN32 +#include +#include +#elif HAVE_UNISTD_H +#include +#endif + +namespace wabt { + +Color::Color(FILE* file, bool enabled) : file_(file) { + enabled_ = enabled && SupportsColor(file_); +} + +// static +bool Color::SupportsColor(FILE* file) { + char* force = getenv("FORCE_COLOR"); + if (force) { + return atoi(force) != 0; + } + +#if _WIN32 + + { +#if HAVE_WIN32_VT100 + HANDLE handle; + if (file == stdout) { + handle = GetStdHandle(STD_OUTPUT_HANDLE); + } else if (file == stderr) { + handle = GetStdHandle(STD_ERROR_HANDLE); + } else { + return false; + } + DWORD mode; + if (!_isatty(_fileno(file)) || !GetConsoleMode(handle, &mode) || + !SetConsoleMode(handle, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) { + return false; + } + return true; +#else + // TODO(binji): Support older Windows by using SetConsoleTextAttribute? + return false; +#endif + } + +#elif HAVE_UNISTD_H + + return isatty(fileno(file)); + +#else + + return false; + +#endif +} + +void Color::WriteCode(const char* code) const { + if (enabled_) { + fputs(code, file_); + } +} + +} // namespace wabt diff --git a/lib/wabt/src/color.h b/lib/wabt/src/color.h new file mode 100644 index 00000000000..ba64e5d2c4a --- /dev/null +++ b/lib/wabt/src/color.h @@ -0,0 +1,71 @@ +/* + * Copyright 2017 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 WABT_COLOR_H_ +#define WABT_COLOR_H_ + +#include + +namespace wabt { + +#define WABT_FOREACH_COLOR_CODE(V) \ + V(Default, "\x1b[0m") \ + V(Bold, "\x1b[1m") \ + V(NoBold, "\x1b[22m") \ + V(Black, "\x1b[30m") \ + V(Red, "\x1b[31m") \ + V(Green, "\x1b[32m") \ + V(Yellow, "\x1b[33m") \ + V(Blue, "\x1b[34m") \ + V(Magenta, "\x1b[35m") \ + V(Cyan, "\x1b[36m") \ + V(White, "\x1b[37m") + +class Color { + public: + Color(FILE*, bool enabled = true); + + // Write the given color to the file, if enabled. +#define WABT_COLOR(Name, code) \ + void Name() const { WriteCode(Name##Code()); } + WABT_FOREACH_COLOR_CODE(WABT_COLOR) +#undef WABT_COLOR + + // Get the color code as a string, if enabled. +#define WABT_COLOR(Name, code) \ + const char* Maybe##Name##Code() const { return enabled_ ? Name##Code() : ""; } + WABT_FOREACH_COLOR_CODE(WABT_COLOR) +#undef WABT_COLOR + + // Get the color code as a string. +#define WABT_COLOR(Name, code) \ + static const char* Name##Code() { return code; } + WABT_FOREACH_COLOR_CODE(WABT_COLOR) +#undef WABT_COLOR + + private: + static bool SupportsColor(FILE*); + void WriteCode(const char*) const; + + FILE* file_; + bool enabled_; +}; + +#undef WABT_FOREACH_COLOR_CODE + +} // namespace wabt + +#endif // WABT_COLOR_H_ diff --git a/lib/wabt/src/common.cc b/lib/wabt/src/common.cc index 634d3a6c4ce..2187c715bf2 100644 --- a/lib/wabt/src/common.cc +++ b/lib/wabt/src/common.cc @@ -48,53 +48,7 @@ const char* g_reloc_type_name[] = {"R_FUNC_INDEX_LEB", }; WABT_STATIC_ASSERT(WABT_ARRAY_SIZE(g_reloc_type_name) == kRelocTypeCount); -StringSlice empty_string_slice(void) { - StringSlice result; - result.start = ""; - result.length = 0; - return result; -} - -bool string_slice_eq_cstr(const StringSlice* s1, const char* s2) { - size_t s2_len = strlen(s2); - if (s2_len != s1->length) - return false; - - return strncmp(s1->start, s2, s2_len) == 0; -} - -bool string_slice_startswith(const StringSlice* s1, const char* s2) { - size_t s2_len = strlen(s2); - if (s2_len > s1->length) - return false; - - return strncmp(s1->start, s2, s2_len) == 0; -} - -StringSlice string_slice_from_cstr(const char* string) { - StringSlice result; - result.start = string; - result.length = strlen(string); - return result; -} - -bool string_slice_is_empty(const StringSlice* str) { - assert(str); - return !str->start || str->length == 0; -} - -bool string_slices_are_equal(const StringSlice* a, const StringSlice* b) { - assert(a && b); - return a->start && b->start && a->length == b->length && - memcmp(a->start, b->start, a->length) == 0; -} - -void destroy_string_slice(StringSlice* str) { - assert(str); - delete [] str->start; -} - -Result read_file(const char* filename, char** out_data, size_t* out_size) { +Result ReadFile(const char* filename, std::vector* out_data) { FILE* infile = fopen(filename, "rb"); if (!infile) { const char format[] = "unable to read file %s"; @@ -106,33 +60,35 @@ Result read_file(const char* filename, char** out_data, size_t* out_size) { if (fseek(infile, 0, SEEK_END) < 0) { perror("fseek to end failed"); + fclose(infile); return Result::Error; } long size = ftell(infile); if (size < 0) { perror("ftell failed"); + fclose(infile); return Result::Error; } if (fseek(infile, 0, SEEK_SET) < 0) { perror("fseek to beginning failed"); + fclose(infile); return Result::Error; } - char* data = new char [size]; - if (size != 0 && fread(data, size, 1, infile) != 1) { + out_data->resize(size); + if (size != 0 && fread(out_data->data(), size, 1, infile) != 1) { perror("fread failed"); + fclose(infile); return Result::Error; } - *out_data = data; - *out_size = size; fclose(infile); return Result::Ok; } -void init_stdio() { +void InitStdio() { #if COMPILER_IS_MSVC int result = _setmode(_fileno(stdout), _O_BINARY); if (result == -1) diff --git a/lib/wabt/src/common.h b/lib/wabt/src/common.h index 3b4d5a54573..d65306bc177 100644 --- a/lib/wabt/src/common.h +++ b/lib/wabt/src/common.h @@ -17,6 +17,7 @@ #ifndef WABT_COMMON_H_ #define WABT_COMMON_H_ +#include #include #include #include @@ -24,18 +25,16 @@ #include #include #include +#include #include #include #include #include "config.h" +#include "string-view.h" #define WABT_FATAL(...) fprintf(stderr, __VA_ARGS__), exit(1) #define WABT_ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) -#define WABT_ZERO_MEMORY(var) \ - WABT_STATIC_ASSERT( \ - std::is_pod::type>::value); \ - memset(static_cast(&(var)), 0, sizeof(var)) #define WABT_USE(x) static_cast(x) @@ -45,8 +44,9 @@ #define WABT_ALIGN_UP_TO_PAGE(x) \ (((x) + WABT_PAGE_SIZE - 1) & ~(WABT_PAGE_SIZE - 1)) -#define PRIstringslice "%.*s" -#define WABT_PRINTF_STRING_SLICE_ARG(x) static_cast((x).length), (x).start +#define PRIstringview "%.*s" +#define WABT_PRINTF_STRING_VIEW_ARG(x) \ + static_cast((x).length()), (x).data() #define WABT_DEFAULT_SNPRINTF_ALLOCA_BUFSIZE 128 #define WABT_SNPRINTF_ALLOCA(buffer, len, format) \ @@ -102,11 +102,43 @@ enum class Result { Error, }; -#define WABT_SUCCEEDED(x) ((x) == ::wabt::Result::Ok) -#define WABT_FAILED(x) ((x) == ::wabt::Result::Error) +template +void ZeroMemory(T& v) { + WABT_STATIC_ASSERT(std::is_pod::value); + memset(&v, 0, sizeof(v)); +} + +// Placement construct +template +void Construct(T& placement, Args&&... args) { + new (&placement) T(std::forward(args)...); +} + +// Placement destruct +template +void Destruct(T& placement) { + placement.~T(); +} + +template +std::unique_ptr make_unique(Args&&... args) { + return std::unique_ptr(new T(std::forward(args)...)); +} + +// Calls data() on vector, string, etc. but will return nullptr if the +// container is empty. +// TODO(binji): this should probably be removed when there is a more direct way +// to represent a memory slice (e.g. something similar to GSL's span) +template +typename T::value_type* DataOrNull(T& container) { + return container.empty() ? nullptr : container.data(); +} + +inline bool Succeeded(Result result) { return result == Result::Ok; } +inline bool Failed(Result result) { return result == Result::Error; } inline std::string WABT_PRINTF_FORMAT(1, 2) - string_printf(const char* format, ...) { + StringPrintf(const char* format, ...) { va_list args; va_list args_copy; va_start(args, format); @@ -125,22 +157,41 @@ enum class LabelType { Loop, If, Else, + Try, + Catch, First = Func, - Last = Else, + Last = Catch, }; static const int kLabelTypeCount = WABT_ENUM_COUNT(LabelType); -struct StringSlice { - const char* start; - size_t length; -}; - struct Location { - const char* filename; - int line; - int first_column; - int last_column; + enum class Type { + Text, + Binary, + }; + + Location() : line(0), first_column(0), last_column(0) {} + Location(const char* filename, int line, int first_column, int last_column) + : filename(filename), + line(line), + first_column(first_column), + last_column(last_column) {} + explicit Location(size_t offset) : offset(offset) {} + + const char* filename = nullptr; + union { + // For text files. + struct { + int line; + int first_column; + int last_column; + }; + // For binary files. + struct { + size_t offset; + }; + }; }; /* matches binary format, do not change */ @@ -181,6 +232,11 @@ struct Reloc { int32_t addend; }; +enum class LinkingEntryType { + StackPointer = 1, + SymbolInfo = 2, +}; + /* matches binary format, do not change */ enum class ExternalKind { Func = 0, @@ -202,74 +258,20 @@ struct Limits { enum { WABT_USE_NATURAL_ALIGNMENT = 0xFFFFFFFF }; -enum class LiteralType { - Int, - Float, - Hexfloat, - Infinity, - Nan, -}; - -struct Literal { - LiteralType type; - StringSlice text; -}; - enum class NameSectionSubsection { Function = 1, Local = 2, }; -static WABT_INLINE char* wabt_strndup(const char* s, size_t len) { - size_t real_len = 0; - const char* p = s; - while (real_len < len && *p) { - p++; - real_len++; - } - - char* new_s = new char[real_len + 1]; - memcpy(new_s, s, real_len); - new_s[real_len] = 0; - return new_s; -} - -static WABT_INLINE StringSlice dup_string_slice(StringSlice str) { - StringSlice result; - char* new_data = new char[str.length]; - memcpy(new_data, str.start, str.length); - result.start = new_data; - result.length = str.length; - return result; -} - -StringSlice empty_string_slice(void); -bool string_slice_eq_cstr(const StringSlice* s1, const char* s2); -bool string_slice_startswith(const StringSlice* s1, const char* s2); -StringSlice string_slice_from_cstr(const char* string); -bool string_slice_is_empty(const StringSlice*); -bool string_slices_are_equal(const StringSlice*, const StringSlice*); -void destroy_string_slice(StringSlice*); -Result read_file(const char* filename, char** out_data, size_t* out_size); - -inline std::string string_slice_to_string(const StringSlice& ss) { - return std::string(ss.start, ss.length); -} - -inline StringSlice string_to_string_slice(const std::string& s) { - StringSlice ss; - ss.start = s.data(); - ss.length = s.length(); - return ss; -} +Result ReadFile(const char* filename, std::vector* out_data); -void init_stdio(); +void InitStdio(); /* external kind */ extern const char* g_kind_name[]; -static WABT_INLINE const char* get_kind_name(ExternalKind kind) { +static WABT_INLINE const char* GetKindName(ExternalKind kind) { assert(static_cast(kind) < kExternalKindCount); return g_kind_name[static_cast(kind)]; } @@ -278,14 +280,14 @@ static WABT_INLINE const char* get_kind_name(ExternalKind kind) { extern const char* g_reloc_type_name[]; -static WABT_INLINE const char* get_reloc_type_name(RelocType reloc) { +static WABT_INLINE const char* GetRelocTypeName(RelocType reloc) { assert(static_cast(reloc) < kRelocTypeCount); return g_reloc_type_name[static_cast(reloc)]; } /* type */ -static WABT_INLINE const char* get_type_name(Type type) { +static WABT_INLINE const char* GetTypeName(Type type) { switch (type) { case Type::I32: return "i32"; @@ -308,6 +310,23 @@ static WABT_INLINE const char* get_type_name(Type type) { } } -} // namespace +template +void ConvertBackslashToSlash(T begin, T end) { + std::replace(begin, end, '\\', '/'); +} + +inline void ConvertBackslashToSlash(char* s, size_t length) { + ConvertBackslashToSlash(s, s + length); +} + +inline void ConvertBackslashToSlash(char* s) { + ConvertBackslashToSlash(s, strlen(s)); +} + +inline void ConvertBackslashToSlash(std::string* s) { + ConvertBackslashToSlash(s->begin(), s->end()); +} + +} // end anonymous namespace #endif /* WABT_COMMON_H_ */ diff --git a/lib/wabt/src/config.h.in b/lib/wabt/src/config.h.in index b2dc04b4c1b..cb6af59807e 100644 --- a/lib/wabt/src/config.h.in +++ b/lib/wabt/src/config.h.in @@ -37,6 +37,9 @@ /* Whether strcasecmp is defined by strings.h */ #cmakedefine01 HAVE_STRCASECMP +/* Whether ENABLE_VIRTUAL_TERMINAL_PROCESSING is defined by windows.h */ +#cmakedefine01 HAVE_WIN32_VT100 + #cmakedefine01 COMPILER_IS_CLANG #cmakedefine01 COMPILER_IS_GNU #cmakedefine01 COMPILER_IS_MSVC diff --git a/lib/wabt/src/emscripten-exported.json b/lib/wabt/src/emscripten-exported.json index 6c0ed71dfe4..4e1e481fc7f 100644 --- a/lib/wabt/src/emscripten-exported.json +++ b/lib/wabt/src/emscripten-exported.json @@ -1,21 +1,16 @@ [ "_malloc", "_wabt_apply_names_module", -"_wabt_binary_error_handler_buffer_get_data", -"_wabt_binary_error_handler_buffer_get_size", -"_wabt_destroy_binary_error_handler_buffer", "_wabt_destroy_module", "_wabt_destroy_output_buffer", "_wabt_destroy_parse_wast_result", "_wabt_destroy_read_binary_result", "_wabt_destroy_script", -"_wabt_destroy_source_error_handler_buffer", +"_wabt_destroy_error_handler_buffer", "_wabt_destroy_wast_lexer", "_wabt_destroy_write_module_result", "_wabt_generate_names_module", "_wabt_get_first_module", -"_wabt_new_binary_error_handler_buffer", -"_wabt_new_source_error_handler_buffer", "_wabt_new_wast_buffer_lexer", "_wabt_output_buffer_get_data", "_wabt_output_buffer_get_size", @@ -26,8 +21,8 @@ "_wabt_read_binary_result_get_result", "_wabt_read_binary_result_release_module", "_wabt_resolve_names_script", -"_wabt_source_error_handler_buffer_get_data", -"_wabt_source_error_handler_buffer_get_size", +"_wabt_error_handler_buffer_get_data", +"_wabt_error_handler_buffer_get_size", "_wabt_validate_script", "_wabt_write_binary_module", "_wabt_write_module_result_get_result", diff --git a/lib/wabt/src/emscripten-helpers.cc b/lib/wabt/src/emscripten-helpers.cc index 6bf63fa031d..d1e53f5d0d9 100644 --- a/lib/wabt/src/emscripten-helpers.cc +++ b/lib/wabt/src/emscripten-helpers.cc @@ -25,12 +25,11 @@ #include "binary-reader.h" #include "binary-reader-ir.h" #include "binary-writer.h" -#include "binary-error-handler.h" #include "common.h" +#include "error-handler.h" #include "ir.h" #include "generate-names.h" #include "resolve-names.h" -#include "source-error-handler.h" #include "stream.h" #include "validator.h" #include "wast-lexer.h" @@ -64,12 +63,11 @@ wabt::WastLexer* wabt_new_wast_buffer_lexer(const char* filename, return lexer.release(); } -WabtParseWastResult* wabt_parse_wast( - wabt::WastLexer* lexer, - wabt::SourceErrorHandlerBuffer* error_handler) { +WabtParseWastResult* wabt_parse_wast(wabt::WastLexer* lexer, + wabt::ErrorHandlerBuffer* error_handler) { WabtParseWastResult* result = new WabtParseWastResult(); wabt::Script* script = nullptr; - result->result = wabt::parse_wast(lexer, &script, error_handler); + result->result = wabt::ParseWast(lexer, &script, error_handler); result->script.reset(script); return result; } @@ -78,15 +76,17 @@ WabtReadBinaryResult* wabt_read_binary( const void* data, size_t size, int read_debug_names, - wabt::BinaryErrorHandlerBuffer* error_handler) { + wabt::ErrorHandlerBuffer* error_handler) { wabt::ReadBinaryOptions options; options.log_stream = nullptr; options.read_debug_names = read_debug_names; WabtReadBinaryResult* result = new WabtReadBinaryResult(); wabt::Module* module = new wabt::Module(); + // TODO(binji): Pass through from wabt_read_binary parameter. + const char* filename = ""; result->result = - wabt::read_binary_ir(data, size, &options, error_handler, module); + wabt::ReadBinaryIr(filename, data, size, &options, error_handler, module); result->module.reset(module); return result; } @@ -94,30 +94,29 @@ WabtReadBinaryResult* wabt_read_binary( wabt::Result wabt_resolve_names_script( wabt::WastLexer* lexer, wabt::Script* script, - wabt::SourceErrorHandlerBuffer* error_handler) { - return resolve_names_script(lexer, script, error_handler); + wabt::ErrorHandlerBuffer* error_handler) { + return ResolveNamesScript(lexer, script, error_handler); } wabt::Result wabt_resolve_names_module( wabt::WastLexer* lexer, wabt::Module* module, - wabt::SourceErrorHandlerBuffer* error_handler) { - return resolve_names_module(lexer, module, error_handler); + wabt::ErrorHandlerBuffer* error_handler) { + return ResolveNamesModule(lexer, module, error_handler); } -wabt::Result wabt_validate_script( - wabt::WastLexer* lexer, - wabt::Script* script, - wabt::SourceErrorHandlerBuffer* error_handler) { - return validate_script(lexer, script, error_handler); +wabt::Result wabt_validate_script(wabt::WastLexer* lexer, + wabt::Script* script, + wabt::ErrorHandlerBuffer* error_handler) { + return ValidateScript(lexer, script, error_handler); } wabt::Result wabt_apply_names_module(wabt::Module* module) { - return apply_names(module); + return ApplyNames(module); } wabt::Result wabt_generate_names_module(wabt::Module* module) { - return generate_names(module); + return GenerateNames(module); } wabt::Module* wabt_get_first_module(wabt::Script* script) { @@ -138,7 +137,7 @@ WabtWriteModuleResult* wabt_write_binary_module(wabt::Module* module, wabt::MemoryWriter writer; WabtWriteModuleResult* result = new WabtWriteModuleResult(); - result->result = write_binary_module(&writer, module, &options); + result->result = WriteBinaryModule(&writer, module, &options); if (result->result == wabt::Result::Ok) { result->buffer = writer.ReleaseOutputBuffer(); result->log_buffer = log ? stream.ReleaseOutputBuffer() : nullptr; @@ -156,7 +155,7 @@ WabtWriteModuleResult* wabt_write_text_module(wabt::Module* module, wabt::MemoryWriter writer; WabtWriteModuleResult* result = new WabtWriteModuleResult(); - result->result = write_wat(&writer, module, &options); + result->result = WriteWat(&writer, module, &options); if (result->result == wabt::Result::Ok) { result->buffer = writer.ReleaseOutputBuffer(); } @@ -175,43 +174,27 @@ void wabt_destroy_wast_lexer(wabt::WastLexer* lexer) { delete lexer; } -// SourceErrorHandlerBuffer -wabt::SourceErrorHandlerBuffer* wabt_new_source_error_handler_buffer(void) { - return new wabt::SourceErrorHandlerBuffer(); -} - -const void* wabt_source_error_handler_buffer_get_data( - wabt::SourceErrorHandlerBuffer* error_handler) { - return error_handler->buffer().data(); -} - -size_t wabt_source_error_handler_buffer_get_size( - wabt::SourceErrorHandlerBuffer* error_handler) { - return error_handler->buffer().size(); -} - -void wabt_destroy_source_error_handler_buffer( - wabt::SourceErrorHandlerBuffer* error_handler) { - delete error_handler; +// ErrorHandlerBuffer +wabt::ErrorHandlerBuffer* wabt_new_text_error_handler_buffer(void) { + return new wabt::ErrorHandlerBuffer(wabt::Location::Type::Text); } -// BinaryErrorHandlerBuffer -wabt::BinaryErrorHandlerBuffer* wabt_new_binary_error_handler_buffer(void) { - return new wabt::BinaryErrorHandlerBuffer(); +wabt::ErrorHandlerBuffer* wabt_new_binary_error_handler_buffer(void) { + return new wabt::ErrorHandlerBuffer(wabt::Location::Type::Binary); } -const void* wabt_binary_error_handler_buffer_get_data( - wabt::BinaryErrorHandlerBuffer* error_handler) { +const void* wabt_error_handler_buffer_get_data( + wabt::ErrorHandlerBuffer* error_handler) { return error_handler->buffer().data(); } -size_t wabt_binary_error_handler_buffer_get_size( - wabt::BinaryErrorHandlerBuffer* error_handler) { +size_t wabt_error_handler_buffer_get_size( + wabt::ErrorHandlerBuffer* error_handler) { return error_handler->buffer().size(); } -void wabt_destroy_binary_error_handler_buffer( - wabt::BinaryErrorHandlerBuffer* error_handler) { +void wabt_destroy_error_handler_buffer( + wabt::ErrorHandlerBuffer* error_handler) { delete error_handler; } diff --git a/lib/wabt/src/error-handler.cc b/lib/wabt/src/error-handler.cc new file mode 100644 index 00000000000..86d42b9a54d --- /dev/null +++ b/lib/wabt/src/error-handler.cc @@ -0,0 +1,138 @@ +/* + * Copyright 2017 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. + */ + +#include "error-handler.h" + +#include + +namespace wabt { + +ErrorHandler::ErrorHandler(Location::Type location_type) + : location_type_(location_type) {} + +std::string ErrorHandler::DefaultErrorMessage(const Color& color, + const Location& loc, + const std::string& error, + const std::string& source_line, + size_t source_line_column_offset, + int indent) { + std::string indent_str(indent, ' '); + std::string result = indent_str; + + result += color.MaybeBoldCode(); + + if (loc.filename) { + result += loc.filename; + result += ":"; + } + + if (location_type_ == Location::Type::Text) { + result += StringPrintf("%d:%d: ", loc.line, loc.first_column); + } else if (loc.offset != kInvalidOffset) { + result += StringPrintf("%07" PRIzx ": ", loc.offset); + } + + result += color.MaybeRedCode(); + result += "error: "; + result += color.MaybeDefaultCode(); + + result += error; + result += '\n'; + + if (!source_line.empty()) { + result += indent_str; + result += source_line; + result += '\n'; + result += indent_str; + + size_t num_spaces = (loc.first_column - 1) - source_line_column_offset; + size_t num_carets = loc.last_column - loc.first_column; + num_carets = std::min(num_carets, source_line.size() - num_spaces); + num_carets = std::max(num_carets, 1); + result.append(num_spaces, ' '); + result += color.MaybeBoldCode(); + result += color.MaybeGreenCode(); + result.append(num_carets, '^'); + result += color.MaybeDefaultCode(); + result += '\n'; + } + + return result; +} + +ErrorHandlerNop::ErrorHandlerNop() + // The Location::Type is irrelevant since we never display an error. + : ErrorHandler(Location::Type::Text) {} + +ErrorHandlerFile::ErrorHandlerFile(Location::Type location_type, + FILE* file, + const std::string& header, + PrintHeader print_header, + size_t source_line_max_length) + : ErrorHandler(location_type), + file_(file), + header_(header), + print_header_(print_header), + source_line_max_length_(source_line_max_length), + color_(file) {} + +bool ErrorHandlerFile::OnError(const Location& loc, + const std::string& error, + const std::string& source_line, + size_t source_line_column_offset) { + PrintErrorHeader(); + int indent = header_.empty() ? 0 : 2; + + std::string message = DefaultErrorMessage(color_, loc, error, source_line, + source_line_column_offset, indent); + fwrite(message.data(), 1, message.size(), file_); + return true; +} + +void ErrorHandlerFile::PrintErrorHeader() { + if (header_.empty()) + return; + + switch (print_header_) { + case PrintHeader::Never: + break; + + case PrintHeader::Once: + print_header_ = PrintHeader::Never; + // Fallthrough. + + case PrintHeader::Always: + fprintf(file_, "%s:\n", header_.c_str()); + break; + } +} + +ErrorHandlerBuffer::ErrorHandlerBuffer(Location::Type location_type, + size_t source_line_max_length) + : ErrorHandler(location_type), + source_line_max_length_(source_line_max_length), + color_(nullptr, false) {} + +bool ErrorHandlerBuffer::OnError(const Location& loc, + const std::string& error, + const std::string& source_line, + size_t source_line_column_offset) { + buffer_ += DefaultErrorMessage(color_, loc, error, source_line, + source_line_column_offset, 0); + return true; +} + +} // namespace wabt diff --git a/lib/wabt/src/source-error-handler.h b/lib/wabt/src/error-handler.h similarity index 65% rename from lib/wabt/src/source-error-handler.h rename to lib/wabt/src/error-handler.h index 3da6c9f4b33..6d99983dd06 100644 --- a/lib/wabt/src/source-error-handler.h +++ b/lib/wabt/src/error-handler.h @@ -14,38 +14,52 @@ * limitations under the License. */ -#ifndef WABT_SOURCE_ERROR_HANDLER_H_ -#define WABT_SOURCE_ERROR_HANDLER_H_ +#ifndef WABT_ERROR_HANDLER_H_ +#define WABT_ERROR_HANDLER_H_ #include +#include "color.h" #include "common.h" namespace wabt { -class SourceErrorHandler { +class ErrorHandler { public: - virtual ~SourceErrorHandler() {} + explicit ErrorHandler(Location::Type); + + virtual ~ErrorHandler() {} // Returns true if the error was handled. - virtual bool OnError(const Location*, + virtual bool OnError(const Location&, const std::string& error, const std::string& source_line, size_t source_line_column_offset) = 0; + // Helper function for binary locations. + bool OnError(size_t offset, const std::string& error) { + return OnError(Location(offset), error, std::string(), 0); + } + // OnError will be called with with source_line trimmed to this length. virtual size_t source_line_max_length() const = 0; - std::string DefaultErrorMessage(const Location*, + std::string DefaultErrorMessage(const Color&, + const Location&, const std::string& error, const std::string& source_line, size_t source_line_column_offset, int indent); + + protected: + Location::Type location_type_; }; -class SourceErrorHandlerNop : public SourceErrorHandler { +class ErrorHandlerNop : public ErrorHandler { public: - bool OnError(const Location*, + ErrorHandlerNop(); + + bool OnError(const Location&, const std::string& error, const std::string& source_line, size_t source_line_column_offset) override { @@ -55,7 +69,7 @@ class SourceErrorHandlerNop : public SourceErrorHandler { size_t source_line_max_length() const override { return 80; } }; -class SourceErrorHandlerFile : public SourceErrorHandler { +class ErrorHandlerFile : public ErrorHandler { public: enum class PrintHeader { Never, @@ -63,12 +77,13 @@ class SourceErrorHandlerFile : public SourceErrorHandler { Always, }; - SourceErrorHandlerFile(FILE* file = stderr, - const std::string& header = std::string(), - PrintHeader print_header = PrintHeader::Never, - size_t source_line_max_length = 80); + explicit ErrorHandlerFile(Location::Type, + FILE* file = stderr, + const std::string& header = std::string(), + PrintHeader print_header = PrintHeader::Never, + size_t source_line_max_length = 80); - bool OnError(const Location*, + bool OnError(const Location&, const std::string& error, const std::string& source_line, size_t source_line_column_offset) override; @@ -79,19 +94,20 @@ class SourceErrorHandlerFile : public SourceErrorHandler { private: void PrintErrorHeader(); - void PrintSourceError(); FILE* file_; std::string header_; PrintHeader print_header_; size_t source_line_max_length_; + Color color_; }; -class SourceErrorHandlerBuffer : public SourceErrorHandler { +class ErrorHandlerBuffer : public ErrorHandler { public: - explicit SourceErrorHandlerBuffer(size_t source_line_max_length = 80); + explicit ErrorHandlerBuffer(Location::Type, + size_t source_line_max_length = 80); - bool OnError(const Location*, + bool OnError(const Location&, const std::string& error, const std::string& source_line, size_t source_line_column_offset) override; @@ -105,8 +121,9 @@ class SourceErrorHandlerBuffer : public SourceErrorHandler { private: size_t source_line_max_length_; std::string buffer_; + Color color_; }; } // namespace wabt -#endif // WABT_SOURCE_ERROR_HANDLER_H_ +#endif // WABT_ERROR_HANDLER_H_ diff --git a/lib/wabt/src/expr-visitor.cc b/lib/wabt/src/expr-visitor.cc index 961e91f9ce7..af8d16a5226 100644 --- a/lib/wabt/src/expr-visitor.cc +++ b/lib/wabt/src/expr-visitor.cc @@ -16,11 +16,12 @@ #include "expr-visitor.h" +#include "cast.h" #include "ir.h" #define CHECK_RESULT(expr) \ do { \ - if (WABT_FAILED((expr))) \ + if (Failed((expr))) \ return Result::Error; \ } while (0) @@ -31,159 +32,160 @@ ExprVisitor::ExprVisitor(Delegate* delegate) : delegate_(delegate) {} Result ExprVisitor::VisitExpr(Expr* expr) { switch (expr->type) { case ExprType::Binary: - CHECK_RESULT(delegate_->OnBinaryExpr(expr)); + CHECK_RESULT(delegate_->OnBinaryExpr(cast(expr))); break; - case ExprType::Block: - CHECK_RESULT(delegate_->BeginBlockExpr(expr)); - CHECK_RESULT(VisitExprList(expr->block->first)); - CHECK_RESULT(delegate_->EndBlockExpr(expr)); + case ExprType::Block: { + auto block_expr = cast(expr); + CHECK_RESULT(delegate_->BeginBlockExpr(block_expr)); + CHECK_RESULT(VisitExprList(block_expr->block->exprs)); + CHECK_RESULT(delegate_->EndBlockExpr(block_expr)); break; + } case ExprType::Br: - CHECK_RESULT(delegate_->OnBrExpr(expr)); + CHECK_RESULT(delegate_->OnBrExpr(cast(expr))); break; case ExprType::BrIf: - CHECK_RESULT(delegate_->OnBrIfExpr(expr)); + CHECK_RESULT(delegate_->OnBrIfExpr(cast(expr))); break; case ExprType::BrTable: - CHECK_RESULT(delegate_->OnBrTableExpr(expr)); + CHECK_RESULT(delegate_->OnBrTableExpr(cast(expr))); break; case ExprType::Call: - CHECK_RESULT(delegate_->OnCallExpr(expr)); + CHECK_RESULT(delegate_->OnCallExpr(cast(expr))); break; case ExprType::CallIndirect: - CHECK_RESULT(delegate_->OnCallIndirectExpr(expr)); + CHECK_RESULT(delegate_->OnCallIndirectExpr(cast(expr))); break; - case ExprType::Catch: - // TODO(karlschimpf): Define - WABT_FATAL("Catch: don't know how to visit\n"); - return Result::Error; - - case ExprType::CatchAll: - // TODO(karlschimpf): Define - WABT_FATAL("CatchAll: don't know how to visit\n"); - return Result::Error; - case ExprType::Compare: - CHECK_RESULT(delegate_->OnCompareExpr(expr)); + CHECK_RESULT(delegate_->OnCompareExpr(cast(expr))); break; case ExprType::Const: - CHECK_RESULT(delegate_->OnConstExpr(expr)); + CHECK_RESULT(delegate_->OnConstExpr(cast(expr))); break; case ExprType::Convert: - CHECK_RESULT(delegate_->OnConvertExpr(expr)); + CHECK_RESULT(delegate_->OnConvertExpr(cast(expr))); break; case ExprType::CurrentMemory: - CHECK_RESULT(delegate_->OnCurrentMemoryExpr(expr)); + CHECK_RESULT( + delegate_->OnCurrentMemoryExpr(cast(expr))); break; case ExprType::Drop: - CHECK_RESULT(delegate_->OnDropExpr(expr)); + CHECK_RESULT(delegate_->OnDropExpr(cast(expr))); break; case ExprType::GetGlobal: - CHECK_RESULT(delegate_->OnGetGlobalExpr(expr)); + CHECK_RESULT(delegate_->OnGetGlobalExpr(cast(expr))); break; case ExprType::GetLocal: - CHECK_RESULT(delegate_->OnGetLocalExpr(expr)); + CHECK_RESULT(delegate_->OnGetLocalExpr(cast(expr))); break; case ExprType::GrowMemory: - CHECK_RESULT(delegate_->OnGrowMemoryExpr(expr)); + CHECK_RESULT(delegate_->OnGrowMemoryExpr(cast(expr))); break; - case ExprType::If: - CHECK_RESULT(delegate_->BeginIfExpr(expr)); - CHECK_RESULT(VisitExprList(expr->if_.true_->first)); - CHECK_RESULT(delegate_->AfterIfTrueExpr(expr)); - CHECK_RESULT(VisitExprList(expr->if_.false_)); - CHECK_RESULT(delegate_->EndIfExpr(expr)); + case ExprType::If: { + auto if_expr = cast(expr); + CHECK_RESULT(delegate_->BeginIfExpr(if_expr)); + CHECK_RESULT(VisitExprList(if_expr->true_->exprs)); + CHECK_RESULT(delegate_->AfterIfTrueExpr(if_expr)); + CHECK_RESULT(VisitExprList(if_expr->false_)); + CHECK_RESULT(delegate_->EndIfExpr(if_expr)); break; + } case ExprType::Load: - CHECK_RESULT(delegate_->OnLoadExpr(expr)); + CHECK_RESULT(delegate_->OnLoadExpr(cast(expr))); break; - case ExprType::Loop: - CHECK_RESULT(delegate_->BeginLoopExpr(expr)); - CHECK_RESULT(VisitExprList(expr->loop->first)); - CHECK_RESULT(delegate_->EndLoopExpr(expr)); + case ExprType::Loop: { + auto loop_expr = cast(expr); + CHECK_RESULT(delegate_->BeginLoopExpr(loop_expr)); + CHECK_RESULT(VisitExprList(loop_expr->block->exprs)); + CHECK_RESULT(delegate_->EndLoopExpr(loop_expr)); break; + } case ExprType::Nop: - CHECK_RESULT(delegate_->OnNopExpr(expr)); + CHECK_RESULT(delegate_->OnNopExpr(cast(expr))); break; case ExprType::Rethrow: - // TODO(karlschimpf): Define - WABT_FATAL("Rethrow: don't know how to visit\n"); - return Result::Error; + CHECK_RESULT(delegate_->OnRethrowExpr(cast(expr))); + break; case ExprType::Return: - CHECK_RESULT(delegate_->OnReturnExpr(expr)); + CHECK_RESULT(delegate_->OnReturnExpr(cast(expr))); break; case ExprType::Select: - CHECK_RESULT(delegate_->OnSelectExpr(expr)); + CHECK_RESULT(delegate_->OnSelectExpr(cast(expr))); break; case ExprType::SetGlobal: - CHECK_RESULT(delegate_->OnSetGlobalExpr(expr)); + CHECK_RESULT(delegate_->OnSetGlobalExpr(cast(expr))); break; case ExprType::SetLocal: - CHECK_RESULT(delegate_->OnSetLocalExpr(expr)); + CHECK_RESULT(delegate_->OnSetLocalExpr(cast(expr))); break; case ExprType::Store: - CHECK_RESULT(delegate_->OnStoreExpr(expr)); + CHECK_RESULT(delegate_->OnStoreExpr(cast(expr))); break; case ExprType::TeeLocal: - CHECK_RESULT(delegate_->OnTeeLocalExpr(expr)); + CHECK_RESULT(delegate_->OnTeeLocalExpr(cast(expr))); break; case ExprType::Throw: - // TODO(karlschimpf): Define - WABT_FATAL("Throw: don't know how to visit\n"); - return Result::Error; + CHECK_RESULT(delegate_->OnThrowExpr(cast(expr))); + break; - case ExprType::TryBlock: - // TODO(karlschimpf): Define - WABT_FATAL("TryBlock: don't know how to visit\n"); - return Result::Error; + case ExprType::TryBlock: { + auto try_expr = cast(expr); + CHECK_RESULT(delegate_->BeginTryExpr(try_expr)); + CHECK_RESULT(VisitExprList(try_expr->block->exprs)); + for (Catch* catch_ : try_expr->catches) { + CHECK_RESULT(delegate_->OnCatchExpr(try_expr, catch_)); + CHECK_RESULT(VisitExprList(catch_->exprs)); + } + CHECK_RESULT(delegate_->EndTryExpr(try_expr)); break; + } case ExprType::Unary: - CHECK_RESULT(delegate_->OnUnaryExpr(expr)); + CHECK_RESULT(delegate_->OnUnaryExpr(cast(expr))); break; case ExprType::Unreachable: - CHECK_RESULT(delegate_->OnUnreachableExpr(expr)); + CHECK_RESULT(delegate_->OnUnreachableExpr(cast(expr))); break; } return Result::Ok; } -Result ExprVisitor::VisitExprList(Expr* first) { - for (Expr* expr = first; expr; expr = expr->next) - CHECK_RESULT(VisitExpr(expr)); +Result ExprVisitor::VisitExprList(ExprList& exprs) { + for (Expr& expr : exprs) + CHECK_RESULT(VisitExpr(&expr)); return Result::Ok; } Result ExprVisitor::VisitFunc(Func* func) { - return VisitExprList(func->first_expr); + return VisitExprList(func->exprs); } } // namespace wabt diff --git a/lib/wabt/src/expr-visitor.h b/lib/wabt/src/expr-visitor.h index 11103d5eccf..249fccc47b1 100644 --- a/lib/wabt/src/expr-visitor.h +++ b/lib/wabt/src/expr-visitor.h @@ -18,12 +18,10 @@ #define WABT_EXPR_VISITOR_H_ #include "common.h" +#include "ir.h" namespace wabt { -struct Expr; -struct Func; - class ExprVisitor { public: class Delegate; @@ -32,7 +30,7 @@ class ExprVisitor { explicit ExprVisitor(Delegate* delegate); Result VisitExpr(Expr*); - Result VisitExprList(Expr*); + Result VisitExprList(ExprList&); Result VisitFunc(Func*); private: @@ -43,72 +41,82 @@ class ExprVisitor::Delegate { public: virtual ~Delegate() {} - virtual Result OnBinaryExpr(Expr*) = 0; - virtual Result BeginBlockExpr(Expr*) = 0; - virtual Result EndBlockExpr(Expr*) = 0; - virtual Result OnBrExpr(Expr*) = 0; - virtual Result OnBrIfExpr(Expr*) = 0; - virtual Result OnBrTableExpr(Expr*) = 0; - virtual Result OnCallExpr(Expr*) = 0; - virtual Result OnCallIndirectExpr(Expr*) = 0; - virtual Result OnCompareExpr(Expr*) = 0; - virtual Result OnConstExpr(Expr*) = 0; - virtual Result OnConvertExpr(Expr*) = 0; - virtual Result OnCurrentMemoryExpr(Expr*) = 0; - virtual Result OnDropExpr(Expr*) = 0; - virtual Result OnGetGlobalExpr(Expr*) = 0; - virtual Result OnGetLocalExpr(Expr*) = 0; - virtual Result OnGrowMemoryExpr(Expr*) = 0; - virtual Result BeginIfExpr(Expr*) = 0; - virtual Result AfterIfTrueExpr(Expr*) = 0; - virtual Result EndIfExpr(Expr*) = 0; - virtual Result OnLoadExpr(Expr*) = 0; - virtual Result BeginLoopExpr(Expr*) = 0; - virtual Result EndLoopExpr(Expr*) = 0; - virtual Result OnNopExpr(Expr*) = 0; - virtual Result OnReturnExpr(Expr*) = 0; - virtual Result OnSelectExpr(Expr*) = 0; - virtual Result OnSetGlobalExpr(Expr*) = 0; - virtual Result OnSetLocalExpr(Expr*) = 0; - virtual Result OnStoreExpr(Expr*) = 0; - virtual Result OnTeeLocalExpr(Expr*) = 0; - virtual Result OnUnaryExpr(Expr*) = 0; - virtual Result OnUnreachableExpr(Expr*) = 0; + virtual Result OnBinaryExpr(BinaryExpr*) = 0; + virtual Result BeginBlockExpr(BlockExpr*) = 0; + virtual Result EndBlockExpr(BlockExpr*) = 0; + virtual Result OnBrExpr(BrExpr*) = 0; + virtual Result OnBrIfExpr(BrIfExpr*) = 0; + virtual Result OnBrTableExpr(BrTableExpr*) = 0; + virtual Result OnCallExpr(CallExpr*) = 0; + virtual Result OnCallIndirectExpr(CallIndirectExpr*) = 0; + virtual Result OnCompareExpr(CompareExpr*) = 0; + virtual Result OnConstExpr(ConstExpr*) = 0; + virtual Result OnConvertExpr(ConvertExpr*) = 0; + virtual Result OnCurrentMemoryExpr(CurrentMemoryExpr*) = 0; + virtual Result OnDropExpr(DropExpr*) = 0; + virtual Result OnGetGlobalExpr(GetGlobalExpr*) = 0; + virtual Result OnGetLocalExpr(GetLocalExpr*) = 0; + virtual Result OnGrowMemoryExpr(GrowMemoryExpr*) = 0; + virtual Result BeginIfExpr(IfExpr*) = 0; + virtual Result AfterIfTrueExpr(IfExpr*) = 0; + virtual Result EndIfExpr(IfExpr*) = 0; + virtual Result OnLoadExpr(LoadExpr*) = 0; + virtual Result BeginLoopExpr(LoopExpr*) = 0; + virtual Result EndLoopExpr(LoopExpr*) = 0; + virtual Result OnNopExpr(NopExpr*) = 0; + virtual Result OnReturnExpr(ReturnExpr*) = 0; + virtual Result OnSelectExpr(SelectExpr*) = 0; + virtual Result OnSetGlobalExpr(SetGlobalExpr*) = 0; + virtual Result OnSetLocalExpr(SetLocalExpr*) = 0; + virtual Result OnStoreExpr(StoreExpr*) = 0; + virtual Result OnTeeLocalExpr(TeeLocalExpr*) = 0; + virtual Result OnUnaryExpr(UnaryExpr*) = 0; + virtual Result OnUnreachableExpr(UnreachableExpr*) = 0; + virtual Result BeginTryExpr(TryExpr*) = 0; + virtual Result EndTryExpr(TryExpr*) = 0; + virtual Result OnCatchExpr(TryExpr*, Catch*) = 0; + virtual Result OnThrowExpr(ThrowExpr*) = 0; + virtual Result OnRethrowExpr(RethrowExpr*) = 0; }; class ExprVisitor::DelegateNop : public ExprVisitor::Delegate { public: - Result OnBinaryExpr(Expr*) override { return Result::Ok; } - Result BeginBlockExpr(Expr*) override { return Result::Ok; } - Result EndBlockExpr(Expr*) override { return Result::Ok; } - Result OnBrExpr(Expr*) override { return Result::Ok; } - Result OnBrIfExpr(Expr*) override { return Result::Ok; } - Result OnBrTableExpr(Expr*) override { return Result::Ok; } - Result OnCallExpr(Expr*) override { return Result::Ok; } - Result OnCallIndirectExpr(Expr*) override { return Result::Ok; } - Result OnCompareExpr(Expr*) override { return Result::Ok; } - Result OnConstExpr(Expr*) override { return Result::Ok; } - Result OnConvertExpr(Expr*) override { return Result::Ok; } - Result OnCurrentMemoryExpr(Expr*) override { return Result::Ok; } - Result OnDropExpr(Expr*) override { return Result::Ok; } - Result OnGetGlobalExpr(Expr*) override { return Result::Ok; } - Result OnGetLocalExpr(Expr*) override { return Result::Ok; } - Result OnGrowMemoryExpr(Expr*) override { return Result::Ok; } - Result BeginIfExpr(Expr*) override { return Result::Ok; } - Result AfterIfTrueExpr(Expr*) override { return Result::Ok; } - Result EndIfExpr(Expr*) override { return Result::Ok; } - Result OnLoadExpr(Expr*) override { return Result::Ok; } - Result BeginLoopExpr(Expr*) override { return Result::Ok; } - Result EndLoopExpr(Expr*) override { return Result::Ok; } - Result OnNopExpr(Expr*) override { return Result::Ok; } - Result OnReturnExpr(Expr*) override { return Result::Ok; } - Result OnSelectExpr(Expr*) override { return Result::Ok; } - Result OnSetGlobalExpr(Expr*) override { return Result::Ok; } - Result OnSetLocalExpr(Expr*) override { return Result::Ok; } - Result OnStoreExpr(Expr*) override { return Result::Ok; } - Result OnTeeLocalExpr(Expr*) override { return Result::Ok; } - Result OnUnaryExpr(Expr*) override { return Result::Ok; } - Result OnUnreachableExpr(Expr*) override { return Result::Ok; } + Result OnBinaryExpr(BinaryExpr*) override { return Result::Ok; } + Result BeginBlockExpr(BlockExpr*) override { return Result::Ok; } + Result EndBlockExpr(BlockExpr*) override { return Result::Ok; } + Result OnBrExpr(BrExpr*) override { return Result::Ok; } + Result OnBrIfExpr(BrIfExpr*) override { return Result::Ok; } + Result OnBrTableExpr(BrTableExpr*) override { return Result::Ok; } + Result OnCallExpr(CallExpr*) override { return Result::Ok; } + Result OnCallIndirectExpr(CallIndirectExpr*) override { return Result::Ok; } + Result OnCompareExpr(CompareExpr*) override { return Result::Ok; } + Result OnConstExpr(ConstExpr*) override { return Result::Ok; } + Result OnConvertExpr(ConvertExpr*) override { return Result::Ok; } + Result OnCurrentMemoryExpr(CurrentMemoryExpr*) override { return Result::Ok; } + Result OnDropExpr(DropExpr*) override { return Result::Ok; } + Result OnGetGlobalExpr(GetGlobalExpr*) override { return Result::Ok; } + Result OnGetLocalExpr(GetLocalExpr*) override { return Result::Ok; } + Result OnGrowMemoryExpr(GrowMemoryExpr*) override { return Result::Ok; } + Result BeginIfExpr(IfExpr*) override { return Result::Ok; } + Result AfterIfTrueExpr(IfExpr*) override { return Result::Ok; } + Result EndIfExpr(IfExpr*) override { return Result::Ok; } + Result OnLoadExpr(LoadExpr*) override { return Result::Ok; } + Result BeginLoopExpr(LoopExpr*) override { return Result::Ok; } + Result EndLoopExpr(LoopExpr*) override { return Result::Ok; } + Result OnNopExpr(NopExpr*) override { return Result::Ok; } + Result OnReturnExpr(ReturnExpr*) override { return Result::Ok; } + Result OnSelectExpr(SelectExpr*) override { return Result::Ok; } + Result OnSetGlobalExpr(SetGlobalExpr*) override { return Result::Ok; } + Result OnSetLocalExpr(SetLocalExpr*) override { return Result::Ok; } + Result OnStoreExpr(StoreExpr*) override { return Result::Ok; } + Result OnTeeLocalExpr(TeeLocalExpr*) override { return Result::Ok; } + Result OnUnaryExpr(UnaryExpr*) override { return Result::Ok; } + Result OnUnreachableExpr(UnreachableExpr*) override { return Result::Ok; } + Result BeginTryExpr(TryExpr*) override { return Result::Ok; } + Result EndTryExpr(TryExpr*) override { return Result::Ok; } + Result OnCatchExpr(TryExpr*, Catch*) override { return Result::Ok; } + Result OnThrowExpr(ThrowExpr*) override { return Result::Ok; } + Result OnRethrowExpr(RethrowExpr*) override { return Result::Ok; } }; } // namespace wabt diff --git a/lib/wabt/src/feature.cc b/lib/wabt/src/feature.cc new file mode 100644 index 00000000000..c6df92c2d0c --- /dev/null +++ b/lib/wabt/src/feature.cc @@ -0,0 +1,32 @@ +/* + * Copyright 2017 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. + */ + +#include "feature.h" + +#include "option-parser.h" + +namespace wabt { + +void Features::AddOptions(OptionParser* parser) { +#define WABT_FEATURE(variable, flag, help) \ + parser->AddOption("enable-" flag, help, \ + [this]() { variable##_enabled_ = true; }); + +#include "feature.def" +#undef WABT_FEATURE +} + +} // namespace wabt diff --git a/lib/wabt/src/feature.def b/lib/wabt/src/feature.def new file mode 100644 index 00000000000..eb2f2625c16 --- /dev/null +++ b/lib/wabt/src/feature.def @@ -0,0 +1,26 @@ +/* + * Copyright 2017 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 WABT_FEATURE +#error "You must define WABT_FEATURE before including this file." +#endif + +/* + * variable flag help + * ========================================================================= */ + +WABT_FEATURE(exceptions, "exceptions", "Experimental exception handling") +WABT_FEATURE(sat_float_to_int, "saturating-float-to-int", "Saturating float-to-int operators") diff --git a/lib/wabt/src/feature.h b/lib/wabt/src/feature.h new file mode 100644 index 00000000000..b406ae1bf81 --- /dev/null +++ b/lib/wabt/src/feature.h @@ -0,0 +1,44 @@ +/* + * Copyright 2017 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 WABT_FEATURE_H_ +#define WABT_FEATURE_H_ + +#include "common.h" + +namespace wabt { + +class OptionParser; + +class Features { + public: + void AddOptions(OptionParser*); + +#define WABT_FEATURE(variable, flag, help) \ + bool variable##_enabled() const { return variable##_enabled_; } +#include "feature.def" +#undef WABT_FEATURE + + private: +#define WABT_FEATURE(variable, flag, help) \ + bool variable##_enabled_ = false; +#include "feature.def" +#undef WABT_FEATURE +}; + +} // namespace wabt + +#endif // WABT_FEATURE_H_ diff --git a/lib/wabt/src/generate-names.cc b/lib/wabt/src/generate-names.cc index 258d9b0515f..c495e565345 100644 --- a/lib/wabt/src/generate-names.cc +++ b/lib/wabt/src/generate-names.cc @@ -26,7 +26,7 @@ #define CHECK_RESULT(expr) \ do { \ - if (WABT_FAILED(expr)) \ + if (Failed(expr)) \ return Result::Error; \ } while (0) @@ -41,30 +41,33 @@ class NameGenerator : public ExprVisitor::DelegateNop { Result VisitModule(Module* module); // Implementation of ExprVisitor::DelegateNop. - Result BeginBlockExpr(Expr* expr) override; - Result BeginLoopExpr(Expr* expr) override; - Result BeginIfExpr(Expr* expr) override; + Result BeginBlockExpr(BlockExpr* expr) override; + Result BeginLoopExpr(LoopExpr* expr) override; + Result BeginIfExpr(IfExpr* expr) override; private: - static bool HasName(StringSlice* str); - static void GenerateName(const char* prefix, Index index, StringSlice* str); + static bool HasName(const std::string& str); + static void GenerateName(const char* prefix, + Index index, + std::string* out_str); static void MaybeGenerateName(const char* prefix, Index index, - StringSlice* str); + std::string* out_str); static void GenerateAndBindName(BindingHash* bindings, const char* prefix, Index index, - StringSlice* str); + std::string* out_str); static void MaybeGenerateAndBindName(BindingHash* bindings, const char* prefix, Index index, - StringSlice* str); + std::string* out_str); void GenerateAndBindLocalNames(BindingHash* bindings, const char* prefix); Result VisitFunc(Index func_index, Func* func); Result VisitGlobal(Index global_index, Global* global); Result VisitFuncType(Index func_type_index, FuncType* func_type); Result VisitTable(Index table_index, Table* table); Result VisitMemory(Index memory_index, Memory* memory); + Result VisitExcept(Index except_index, Exception* except); Module* module_ = nullptr; ExprVisitor visitor_; @@ -75,30 +78,26 @@ class NameGenerator : public ExprVisitor::DelegateNop { NameGenerator::NameGenerator() : visitor_(this) {} // static -bool NameGenerator::HasName(StringSlice* str) { - return str->length > 0; +bool NameGenerator::HasName(const std::string& str) { + return !str.empty(); } // static void NameGenerator::GenerateName(const char* prefix, Index index, - StringSlice* str) { + std::string* str) { size_t prefix_len = strlen(prefix); size_t buffer_len = prefix_len + 20; /* add space for the number */ char* buffer = static_cast(alloca(buffer_len)); int actual_len = wabt_snprintf(buffer, buffer_len, "%s%u", prefix, index); - - StringSlice buf; - buf.length = actual_len; - buf.start = buffer; - *str = dup_string_slice(buf); + str->assign(buffer, actual_len); } // static void NameGenerator::MaybeGenerateName(const char* prefix, Index index, - StringSlice* str) { - if (!HasName(str)) + std::string* str) { + if (!HasName(*str)) GenerateName(prefix, index, str); } @@ -106,17 +105,17 @@ void NameGenerator::MaybeGenerateName(const char* prefix, void NameGenerator::GenerateAndBindName(BindingHash* bindings, const char* prefix, Index index, - StringSlice* str) { + std::string* str) { GenerateName(prefix, index, str); - bindings->emplace(string_slice_to_string(*str), Binding(index)); + bindings->emplace(*str, Binding(index)); } // static void NameGenerator::MaybeGenerateAndBindName(BindingHash* bindings, const char* prefix, Index index, - StringSlice* str) { - if (!HasName(str)) + std::string* str) { + if (!HasName(*str)) GenerateAndBindName(bindings, prefix, index, str); } @@ -127,25 +126,24 @@ void NameGenerator::GenerateAndBindLocalNames(BindingHash* bindings, if (!old_name.empty()) continue; - StringSlice new_name; + std::string new_name; GenerateAndBindName(bindings, prefix, i, &new_name); - index_to_name_[i] = string_slice_to_string(new_name); - destroy_string_slice(&new_name); + index_to_name_[i] = new_name; } } -Result NameGenerator::BeginBlockExpr(Expr* expr) { +Result NameGenerator::BeginBlockExpr(BlockExpr* expr) { MaybeGenerateName("$B", label_count_++, &expr->block->label); return Result::Ok; } -Result NameGenerator::BeginLoopExpr(Expr* expr) { - MaybeGenerateName("$L", label_count_++, &expr->loop->label); +Result NameGenerator::BeginLoopExpr(LoopExpr* expr) { + MaybeGenerateName("$L", label_count_++, &expr->block->label); return Result::Ok; } -Result NameGenerator::BeginIfExpr(Expr* expr) { - MaybeGenerateName("$I", label_count_++, &expr->if_.true_->label); +Result NameGenerator::BeginIfExpr(IfExpr* expr) { + MaybeGenerateName("$I", label_count_++, &expr->true_->label); return Result::Ok; } @@ -191,6 +189,12 @@ Result NameGenerator::VisitMemory(Index memory_index, Memory* memory) { return Result::Ok; } +Result NameGenerator::VisitExcept(Index except_index, Exception* except) { + MaybeGenerateAndBindName(&module_->except_bindings, "$e", except_index, + &except->name); + return Result::Ok; +} + Result NameGenerator::VisitModule(Module* module) { module_ = module; for (Index i = 0; i < module->globals.size(); ++i) @@ -203,13 +207,15 @@ Result NameGenerator::VisitModule(Module* module) { CHECK_RESULT(VisitTable(i, module->tables[i])); for (Index i = 0; i < module->memories.size(); ++i) CHECK_RESULT(VisitMemory(i, module->memories[i])); + for (Index i = 0; i < module->excepts.size(); ++i) + CHECK_RESULT(VisitExcept(i, module->excepts[i])); module_ = nullptr; return Result::Ok; } -} // namespace +} // end anonymous namespace -Result generate_names(Module* module) { +Result GenerateNames(Module* module) { NameGenerator generator; return generator.VisitModule(module); } diff --git a/lib/wabt/src/generate-names.h b/lib/wabt/src/generate-names.h index e2013c07341..9a95628411b 100644 --- a/lib/wabt/src/generate-names.h +++ b/lib/wabt/src/generate-names.h @@ -23,7 +23,7 @@ namespace wabt { struct Module; -Result generate_names(struct Module*); +Result GenerateNames(struct Module*); } // namespace wabt diff --git a/lib/wabt/src/hash-util.cc b/lib/wabt/src/hash-util.cc index c0c55a21e70..ab22bd05b84 100644 --- a/lib/wabt/src/hash-util.cc +++ b/lib/wabt/src/hash-util.cc @@ -23,7 +23,7 @@ namespace wabt { // Hash combiner from: // http://stackoverflow.com/questions/4948780/magic-number-in-boosthash-combine -hash_code hash_combine(hash_code seed, hash_code y) { +hash_code HashCombine(hash_code seed, hash_code y) { #if SIZEOF_SIZE_T == 4 constexpr hash_code magic = 0x9e3779b9; #elif SIZEOF_SIZE_T == 8 diff --git a/lib/wabt/src/hash-util.h b/lib/wabt/src/hash-util.h index 0cf687580a8..21d965626c0 100644 --- a/lib/wabt/src/hash-util.h +++ b/lib/wabt/src/hash-util.h @@ -24,20 +24,20 @@ namespace wabt { typedef std::size_t hash_code; -inline hash_code hash_combine() { return 0; } -inline hash_code hash_combine(hash_code seed) { return seed; } -hash_code hash_combine(hash_code x, hash_code y); +inline hash_code HashCombine() { return 0; } +inline hash_code HashCombine(hash_code seed) { return seed; } +hash_code HashCombine(hash_code x, hash_code y); template -inline hash_code hash_combine(const T& first, const U&... rest) { - return hash_combine(hash_combine(rest...), std::hash()(first)); +inline hash_code HashCombine(const T& first, const U&... rest) { + return HashCombine(HashCombine(rest...), std::hash()(first)); } template -inline hash_code hash_range(It first, It last) { +inline hash_code HashRange(It first, It last) { hash_code result = 0; for (auto iter = first; iter != last; ++iter) { - result = hash_combine(result, *iter); + result = HashCombine(result, *iter); } return result; } diff --git a/lib/wabt/src/interpreter-opcode.def b/lib/wabt/src/interpreter-opcode.def index 72569337d37..787307041d7 100644 --- a/lib/wabt/src/interpreter-opcode.def +++ b/lib/wabt/src/interpreter-opcode.def @@ -27,12 +27,12 @@ * Name: used to generate the opcode enum * text: a string of the opcode name in the text format * - * tr t1 t2 m code Name text + * tr t1 t2 m prefix code Name text * ============================================================ */ #include "opcode.def" -WABT_OPCODE(___, ___, ___, 0, 0xc0, Alloca, "alloca") -WABT_OPCODE(___, ___, ___, 0, 0xc1, BrUnless, "br_unless") -WABT_OPCODE(___, ___, ___, 0, 0xc2, CallHost, "call_host") -WABT_OPCODE(___, ___, ___, 0, 0xc3, Data, "data") -WABT_OPCODE(___, ___, ___, 0, 0xc4, DropKeep, "drop_keep") +WABT_OPCODE(___, ___, ___, 0, 0, 0xc0, Alloca, "alloca") +WABT_OPCODE(___, ___, ___, 0, 0, 0xc1, BrUnless, "br_unless") +WABT_OPCODE(___, ___, ___, 0, 0, 0xc2, CallHost, "call_host") +WABT_OPCODE(___, ___, ___, 0, 0, 0xc3, Data, "data") +WABT_OPCODE(___, ___, ___, 0, 0, 0xc4, DropKeep, "drop_keep") diff --git a/lib/wabt/src/interpreter.cc b/lib/wabt/src/interpreter.cc index 29a6ee5353c..793d1aefbc8 100644 --- a/lib/wabt/src/interpreter.cc +++ b/lib/wabt/src/interpreter.cc @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include "stream.h" @@ -27,12 +29,13 @@ namespace wabt { namespace interpreter { -static const char* s_opcode_name[256] = { - -#define WABT_OPCODE(rtype, type1, type2, mem_size, code, NAME, text) text, +static const char* s_opcode_name[] = { +#define WABT_OPCODE(rtype, type1, type2, mem_size, prefix, code, NAME, text) \ + text, #include "interpreter-opcode.def" #undef WABT_OPCODE + "", }; #define CHECK_RESULT(expr) \ @@ -41,26 +44,40 @@ static const char* s_opcode_name[256] = { return Result::Error; \ } while (0) -static const char* get_opcode_name(Opcode opcode) { - return s_opcode_name[static_cast(opcode)]; +// Differs from CHECK_RESULT since it can return different traps, not just +// Error. Also uses __VA_ARGS__ so templates can be passed without surrounding +// parentheses. +#define CHECK_TRAP(...) \ + do { \ + Result result = (__VA_ARGS__); \ + if (result != Result::Ok) { \ + return result; \ + } \ + } while (0) + +static const char* GetOpcodeName(Opcode opcode) { + int value = static_cast(opcode); + return value < static_cast(WABT_ARRAY_SIZE(s_opcode_name)) + ? s_opcode_name[value] + : ""; } Environment::Environment() : istream_(new OutputBuffer()) {} -Index Environment::FindModuleIndex(StringSlice name) const { - auto iter = module_bindings_.find(string_slice_to_string(name)); +Index Environment::FindModuleIndex(string_view name) const { + auto iter = module_bindings_.find(name.to_string()); if (iter == module_bindings_.end()) return kInvalidIndex; return iter->second.index; } -Module* Environment::FindModule(StringSlice name) { +Module* Environment::FindModule(string_view name) { Index index = FindModuleIndex(name); return index == kInvalidIndex ? nullptr : modules_[index].get(); } -Module* Environment::FindRegisteredModule(StringSlice name) { - auto iter = registered_module_bindings_.find(string_slice_to_string(name)); +Module* Environment::FindRegisteredModule(string_view name) { + auto iter = registered_module_bindings_.find(name.to_string()); if (iter == registered_module_bindings_.end()) return nullptr; return modules_[iter->second.index].get(); @@ -91,9 +108,7 @@ FuncSignature::FuncSignature(Index param_count, result_types(result_types, result_types + result_count) {} Import::Import() : kind(ExternalKind::Func) { - WABT_ZERO_MEMORY(module_name); - WABT_ZERO_MEMORY(field_name); - WABT_ZERO_MEMORY(func.sig_index); + func.sig_index = kInvalidIndex; } Import::Import(Import&& other) { @@ -102,10 +117,8 @@ Import::Import(Import&& other) { Import& Import::operator=(Import&& other) { kind = other.kind; - module_name = other.module_name; - WABT_ZERO_MEMORY(other.module_name); - field_name = other.field_name; - WABT_ZERO_MEMORY(other.field_name); + module_name = std::move(other.module_name); + field_name = std::move(other.field_name); switch (kind) { case ExternalKind::Func: func.sig_index = other.func.sig_index; @@ -128,46 +141,18 @@ Import& Import::operator=(Import&& other) { return *this; } -Import::~Import() { - destroy_string_slice(&module_name); - destroy_string_slice(&field_name); -} - -Export::Export(Export&& other) - : name(other.name), kind(other.kind), index(other.index) { - WABT_ZERO_MEMORY(other.name); -} - -Export& Export::operator=(Export&& other) { - name = other.name; - kind = other.kind; - index = other.index; - WABT_ZERO_MEMORY(other.name); - return *this; -} - -Export::~Export() { - destroy_string_slice(&name); -} - Module::Module(bool is_host) : memory_index(kInvalidIndex), table_index(kInvalidIndex), - is_host(is_host) { - WABT_ZERO_MEMORY(name); -} + is_host(is_host) {} -Module::Module(const StringSlice& name, bool is_host) - : name(name), +Module::Module(string_view name, bool is_host) + : name(name.to_string()), memory_index(kInvalidIndex), table_index(kInvalidIndex), is_host(is_host) {} -Module::~Module() { - destroy_string_slice(&name); -} - -Export* Module::GetExport(StringSlice name) { +Export* Module::GetExport(string_view name) { int field_index = export_bindings.FindIndex(name); if (field_index < 0) return nullptr; @@ -180,7 +165,7 @@ DefinedModule::DefinedModule() istream_start(kInvalidIstreamOffset), istream_end(kInvalidIstreamOffset) {} -HostModule::HostModule(const StringSlice& name) : Module(name, true) {} +HostModule::HostModule(string_view name) : Module(name, true) {} Environment::MarkPoint Environment::Mark() { MarkPoint mark; @@ -197,9 +182,9 @@ Environment::MarkPoint Environment::Mark() { void Environment::ResetToMarkPoint(const MarkPoint& mark) { // Destroy entries in the binding hash. for (size_t i = mark.modules_size; i < modules_.size(); ++i) { - const StringSlice* name = &modules_[i]->name; - if (!string_slice_is_empty(name)) - module_bindings_.erase(string_slice_to_string(*name)); + std::string name = modules_[i]->name; + if (!name.empty()) + module_bindings_.erase(name); } // registered_module_bindings_ maps from an arbitrary name to a module index, @@ -221,21 +206,14 @@ void Environment::ResetToMarkPoint(const MarkPoint& mark) { istream_->data.resize(mark.istream_size); } -HostModule* Environment::AppendHostModule(StringSlice name) { - HostModule* module = new HostModule(dup_string_slice(name)); +HostModule* Environment::AppendHostModule(string_view name) { + HostModule* module = new HostModule(name); modules_.emplace_back(module); - registered_module_bindings_.emplace(string_slice_to_string(name), + registered_module_bindings_.emplace(name.to_string(), Binding(modules_.size() - 1)); return module; } -Result Thread::PushValue(Value value) { - if (value_stack_top_ >= value_stack_end_) - return Result::TrapValueStackExhausted; - *value_stack_top_++ = value; - return Result::Ok; -} - Result Thread::PushArgs(const FuncSignature* sig, const std::vector& args) { if (sig->param_types.size() != args.size()) @@ -245,7 +223,7 @@ Result Thread::PushArgs(const FuncSignature* sig, if (sig->param_types[i] != args[i].type) return interpreter::Result::ArgumentTypeMismatch; - interpreter::Result iresult = PushValue(args[i].value); + interpreter::Result iresult = Push(args[i].value); if (iresult != interpreter::Result::Ok) { value_stack_top_ = value_stack_.data(); return iresult; @@ -266,6 +244,44 @@ void Thread::CopyResults(const FuncSignature* sig, out_results->emplace_back(sig->result_types[i], value_stack_[i]); } +template +Dst Bitcast(Src value) { + static_assert(sizeof(Src) == sizeof(Dst), "Bitcast sizes must match."); + Dst result; + memcpy(&result, &value, sizeof(result)); + return result; +} + +uint32_t ToRep(bool x) { return x ? 1 : 0; } +uint32_t ToRep(uint32_t x) { return x; } +uint64_t ToRep(uint64_t x) { return x; } +uint32_t ToRep(int32_t x) { return Bitcast(x); } +uint64_t ToRep(int64_t x) { return Bitcast(x); } +uint32_t ToRep(float x) { return Bitcast(x); } +uint64_t ToRep(double x) { return Bitcast(x); } + +template +Dst FromRep(Src x); + +template <> +uint32_t FromRep(uint32_t x) { return x; } +template <> +uint64_t FromRep(uint64_t x) { return x; } +template <> +int32_t FromRep(uint32_t x) { return Bitcast(x); } +template <> +int64_t FromRep(uint64_t x) { return Bitcast(x); } +template <> +float FromRep(uint32_t x) { return Bitcast(x); } +template <> +double FromRep(uint64_t x) { return Bitcast(x); } + +template +struct FloatTraits; + +template +bool IsConversionInRange(ValueTypeRep bits); + /* 3 32222222 222...00 * 1 09876543 210...10 * ------------------- @@ -290,54 +306,68 @@ void Thread::CopyResults(const FuncSignature* sig, * 1 11111111 111...11 => 0xffffffff => -nan(0x7fffff) */ -#define F32_MAX 0x7f7fffffU -#define F32_INF 0x7f800000U -#define F32_NEG_MAX 0xff7fffffU -#define F32_NEG_INF 0xff800000U -#define F32_NEG_ONE 0xbf800000U -#define F32_NEG_ZERO 0x80000000U -#define F32_QUIET_NAN 0x7fc00000U -#define F32_QUIET_NEG_NAN 0xffc00000U -#define F32_QUIET_NAN_BIT 0x00400000U -#define F32_SIG_BITS 23 -#define F32_SIG_MASK 0x7fffff -#define F32_SIGN_MASK 0x80000000U +template <> +struct FloatTraits { + static const uint32_t kMax = 0x7f7fffffU; + static const uint32_t kInf = 0x7f800000U; + static const uint32_t kNegMax = 0xff7fffffU; + static const uint32_t kNegInf = 0xff800000U; + static const uint32_t kNegOne = 0xbf800000U; + static const uint32_t kNegZero =0x80000000U; + static const uint32_t kQuietNan = 0x7fc00000U; + static const uint32_t kQuietNegNan = 0xffc00000U; + static const uint32_t kQuietNanBit = 0x00400000U; + static const int kSigBits = 23; + static const uint32_t kSigMask = 0x7fffff; + static const uint32_t kSignMask = 0x80000000U; + + static bool IsNan(uint32_t bits) { + return (bits > kInf && bits < kNegZero) || (bits > kNegInf); + } -static bool is_nan_f32(uint32_t f32_bits) { - return (f32_bits > F32_INF && f32_bits < F32_NEG_ZERO) || - (f32_bits > F32_NEG_INF); -} + static bool IsZero(uint32_t bits) { + return bits == 0 || bits == kNegZero; + } -bool is_canonical_nan_f32(uint32_t f32_bits) { - return f32_bits == F32_QUIET_NAN || f32_bits == F32_QUIET_NEG_NAN; -} + static bool IsCanonicalNan(uint32_t bits) { + return bits == kQuietNan || bits == kQuietNegNan; + } -bool is_arithmetic_nan_f32(uint32_t f32_bits) { - return (f32_bits & F32_QUIET_NAN) == F32_QUIET_NAN; + static bool IsArithmeticNan(uint32_t bits) { + return (bits & kQuietNan) == kQuietNan; + } +}; + +bool IsCanonicalNan(uint32_t bits) { + return FloatTraits::IsCanonicalNan(bits); } -static WABT_INLINE bool is_zero_f32(uint32_t f32_bits) { - return f32_bits == 0 || f32_bits == F32_NEG_ZERO; +bool IsArithmeticNan(uint32_t bits) { + return FloatTraits::IsArithmeticNan(bits); } -static WABT_INLINE bool is_in_range_i32_trunc_s_f32(uint32_t f32_bits) { - return (f32_bits < 0x4f000000U) || - (f32_bits >= F32_NEG_ZERO && f32_bits <= 0xcf000000U); +template <> +bool IsConversionInRange(uint32_t bits) { + return (bits < 0x4f000000U) || + (bits >= FloatTraits::kNegZero && bits <= 0xcf000000U); } -static WABT_INLINE bool is_in_range_i64_trunc_s_f32(uint32_t f32_bits) { - return (f32_bits < 0x5f000000U) || - (f32_bits >= F32_NEG_ZERO && f32_bits <= 0xdf000000U); +template <> +bool IsConversionInRange(uint32_t bits) { + return (bits < 0x5f000000U) || + (bits >= FloatTraits::kNegZero && bits <= 0xdf000000U); } -static WABT_INLINE bool is_in_range_i32_trunc_u_f32(uint32_t f32_bits) { - return (f32_bits < 0x4f800000U) || - (f32_bits >= F32_NEG_ZERO && f32_bits < F32_NEG_ONE); +template <> +bool IsConversionInRange(uint32_t bits) { + return (bits < 0x4f800000U) || (bits >= FloatTraits::kNegZero && + bits < FloatTraits::kNegOne); } -static WABT_INLINE bool is_in_range_i64_trunc_u_f32(uint32_t f32_bits) { - return (f32_bits < 0x5f800000U) || - (f32_bits >= F32_NEG_ZERO && f32_bits < F32_NEG_ONE); +template <> +bool IsConversionInRange(uint32_t bits) { + return (bits < 0x5f800000U) || (bits >= FloatTraits::kNegZero && + bits < FloatTraits::kNegOne); } /* @@ -366,152 +396,172 @@ static WABT_INLINE bool is_in_range_i64_trunc_u_f32(uint32_t f32_bits) { * 1 11111111111 1111..1..111111...111 0xffffffffffffffff => -nan(0xfff...) */ -#define F64_INF 0x7ff0000000000000ULL -#define F64_NEG_INF 0xfff0000000000000ULL -#define F64_NEG_ONE 0xbff0000000000000ULL -#define F64_NEG_ZERO 0x8000000000000000ULL -#define F64_QUIET_NAN 0x7ff8000000000000ULL -#define F64_QUIET_NEG_NAN 0xfff8000000000000ULL -#define F64_QUIET_NAN_BIT 0x0008000000000000ULL -#define F64_SIG_BITS 52 -#define F64_SIG_MASK 0xfffffffffffffULL -#define F64_SIGN_MASK 0x8000000000000000ULL +template <> +struct FloatTraits { + static const uint64_t kInf = 0x7ff0000000000000ULL; + static const uint64_t kNegInf = 0xfff0000000000000ULL; + static const uint64_t kNegOne = 0xbff0000000000000ULL; + static const uint64_t kNegZero = 0x8000000000000000ULL; + static const uint64_t kQuietNan = 0x7ff8000000000000ULL; + static const uint64_t kQuietNegNan = 0xfff8000000000000ULL; + static const uint64_t kQuietNanBit = 0x0008000000000000ULL; + static const int kSigBits = 52; + static const uint64_t kSigMask = 0xfffffffffffffULL; + static const uint64_t kSignMask = 0x8000000000000000ULL; + + static bool IsNan(uint64_t bits) { + return (bits > kInf && bits < kNegZero) || (bits > kNegInf); + } + + static bool IsZero(uint64_t bits) { + return bits == 0 || bits == kNegZero; + } + + static bool IsCanonicalNan(uint64_t bits) { + return bits == kQuietNan || bits == kQuietNegNan; + } + + static bool IsArithmeticNan(uint64_t bits) { + return (bits & kQuietNan) == kQuietNan; + } +}; -static bool is_nan_f64(uint64_t f64_bits) { - return (f64_bits > F64_INF && f64_bits < F64_NEG_ZERO) || - (f64_bits > F64_NEG_INF); +bool IsCanonicalNan(uint64_t bits) { + return FloatTraits::IsCanonicalNan(bits); } -bool is_canonical_nan_f64(uint64_t f64_bits) { - return f64_bits == F64_QUIET_NAN || f64_bits == F64_QUIET_NEG_NAN; +bool IsArithmeticNan(uint64_t bits) { + return FloatTraits::IsArithmeticNan(bits); } -bool is_arithmetic_nan_f64(uint64_t f64_bits) { - return (f64_bits & F64_QUIET_NAN) == F64_QUIET_NAN; +template <> +bool IsConversionInRange(uint64_t bits) { + return (bits <= 0x41dfffffffc00000ULL) || + (bits >= FloatTraits::kNegZero && + bits <= 0xc1e0000000000000ULL); } -static WABT_INLINE bool is_zero_f64(uint64_t f64_bits) { - return f64_bits == 0 || f64_bits == F64_NEG_ZERO; +template <> +bool IsConversionInRange(uint64_t bits) { + return (bits < 0x43e0000000000000ULL) || + (bits >= FloatTraits::kNegZero && + bits <= 0xc3e0000000000000ULL); } -static WABT_INLINE bool is_in_range_i32_trunc_s_f64(uint64_t f64_bits) { - return (f64_bits <= 0x41dfffffffc00000ULL) || - (f64_bits >= F64_NEG_ZERO && f64_bits <= 0xc1e0000000000000ULL); +template <> +bool IsConversionInRange(uint64_t bits) { + return (bits <= 0x41efffffffe00000ULL) || + (bits >= FloatTraits::kNegZero && + bits < FloatTraits::kNegOne); } -static WABT_INLINE bool is_in_range_i32_trunc_u_f64(uint64_t f64_bits) { - return (f64_bits <= 0x41efffffffe00000ULL) || - (f64_bits >= F64_NEG_ZERO && f64_bits < F64_NEG_ONE); +template <> +bool IsConversionInRange(uint64_t bits) { + return (bits < 0x43f0000000000000ULL) || + (bits >= FloatTraits::kNegZero && + bits < FloatTraits::kNegOne); } -static WABT_INLINE bool is_in_range_i64_trunc_s_f64(uint64_t f64_bits) { - return (f64_bits < 0x43e0000000000000ULL) || - (f64_bits >= F64_NEG_ZERO && f64_bits <= 0xc3e0000000000000ULL); +template <> +bool IsConversionInRange(uint64_t bits) { + return (bits <= 0x47efffffe0000000ULL) || + (bits >= FloatTraits::kNegZero && + bits <= 0xc7efffffe0000000ULL); } -static WABT_INLINE bool is_in_range_i64_trunc_u_f64(uint64_t f64_bits) { - return (f64_bits < 0x43f0000000000000ULL) || - (f64_bits >= F64_NEG_ZERO && f64_bits < F64_NEG_ONE); +// The WebAssembly rounding mode means that these values (which are > F32_MAX) +// should be rounded to F32_MAX and not set to infinity. Unfortunately, UBSAN +// complains that the value is not representable as a float, so we'll special +// case them. +bool IsInRangeF64DemoteF32RoundToF32Max(uint64_t bits) { + return bits > 0x47efffffe0000000ULL && bits < 0x47effffff0000000ULL; } -static WABT_INLINE bool is_in_range_f64_demote_f32(uint64_t f64_bits) { - return (f64_bits <= 0x47efffffe0000000ULL) || - (f64_bits >= F64_NEG_ZERO && f64_bits <= 0xc7efffffe0000000ULL); +bool IsInRangeF64DemoteF32RoundToNegF32Max(uint64_t bits) { + return bits > 0xc7efffffe0000000ULL && bits < 0xc7effffff0000000ULL; } -/* The WebAssembly rounding mode means that these values (which are > F32_MAX) - * should be rounded to F32_MAX and not set to infinity. Unfortunately, UBSAN - * complains that the value is not representable as a float, so we'll special - * case them. */ -static WABT_INLINE bool is_in_range_f64_demote_f32_round_to_f32_max( - uint64_t f64_bits) { - return f64_bits > 0x47efffffe0000000ULL && f64_bits < 0x47effffff0000000ULL; +template struct ExtendMemType; +template<> struct ExtendMemType { typedef uint32_t type; }; +template<> struct ExtendMemType { typedef int32_t type; }; +template<> struct ExtendMemType { typedef uint32_t type; }; +template<> struct ExtendMemType { typedef int32_t type; }; +template<> struct ExtendMemType { typedef uint32_t type; }; +template<> struct ExtendMemType { typedef int32_t type; }; +template<> struct ExtendMemType { typedef uint64_t type; }; +template<> struct ExtendMemType { typedef int64_t type; }; +template<> struct ExtendMemType { typedef uint64_t type; }; +template<> struct ExtendMemType { typedef int64_t type; }; +template<> struct ExtendMemType { typedef uint64_t type; }; +template<> struct ExtendMemType { typedef int64_t type; }; +template<> struct ExtendMemType { typedef uint64_t type; }; +template<> struct ExtendMemType { typedef int64_t type; }; +template<> struct ExtendMemType { typedef float type; }; +template<> struct ExtendMemType { typedef double type; }; + +template struct WrapMemType; +template<> struct WrapMemType { typedef uint8_t type; }; +template<> struct WrapMemType { typedef uint16_t type; }; +template<> struct WrapMemType { typedef uint32_t type; }; +template<> struct WrapMemType { typedef uint8_t type; }; +template<> struct WrapMemType { typedef uint16_t type; }; +template<> struct WrapMemType { typedef uint32_t type; }; +template<> struct WrapMemType { typedef uint64_t type; }; +template<> struct WrapMemType { typedef uint32_t type; }; +template<> struct WrapMemType { typedef uint64_t type; }; + +template +Value MakeValue(ValueTypeRep); + +template <> +Value MakeValue(uint32_t v) { + Value result; + result.i32 = v; + return result; } -static WABT_INLINE bool is_in_range_f64_demote_f32_round_to_neg_f32_max( - uint64_t f64_bits) { - return f64_bits > 0xc7efffffe0000000ULL && f64_bits < 0xc7effffff0000000ULL; +template <> +Value MakeValue(uint32_t v) { + Value result; + result.i32 = v; + return result; } -#define IS_NAN_F32 is_nan_f32 -#define IS_NAN_F64 is_nan_f64 -#define IS_ZERO_F32 is_zero_f32 -#define IS_ZERO_F64 is_zero_f64 +template <> +Value MakeValue(uint64_t v) { + Value result; + result.i64 = v; + return result; +} -#define DEFINE_BITCAST(name, src, dst) \ - static WABT_INLINE dst name(src x) { \ - dst result; \ - memcpy(&result, &x, sizeof(dst)); \ - return result; \ - } +template <> +Value MakeValue(uint64_t v) { + Value result; + result.i64 = v; + return result; +} -DEFINE_BITCAST(bitcast_u32_to_i32, uint32_t, int32_t) -DEFINE_BITCAST(bitcast_u64_to_i64, uint64_t, int64_t) -DEFINE_BITCAST(bitcast_f32_to_u32, float, uint32_t) -DEFINE_BITCAST(bitcast_u32_to_f32, uint32_t, float) -DEFINE_BITCAST(bitcast_f64_to_u64, double, uint64_t) -DEFINE_BITCAST(bitcast_u64_to_f64, uint64_t, double) - -#define bitcast_i32_to_u32(x) (static_cast(x)) -#define bitcast_i64_to_u64(x) (static_cast(x)) - -#define VALUE_TYPE_I32 uint32_t -#define VALUE_TYPE_I64 uint64_t -#define VALUE_TYPE_F32 uint32_t -#define VALUE_TYPE_F64 uint64_t - -#define VALUE_TYPE_SIGNED_MAX_I32 (0x80000000U) -#define VALUE_TYPE_UNSIGNED_MAX_I32 (0xFFFFFFFFU) -#define VALUE_TYPE_SIGNED_MAX_I64 static_cast(0x8000000000000000ULL) -#define VALUE_TYPE_UNSIGNED_MAX_I64 static_cast(0xFFFFFFFFFFFFFFFFULL) - -#define FLOAT_TYPE_F32 float -#define FLOAT_TYPE_F64 double - -#define MEM_TYPE_I8 int8_t -#define MEM_TYPE_U8 uint8_t -#define MEM_TYPE_I16 int16_t -#define MEM_TYPE_U16 uint16_t -#define MEM_TYPE_I32 int32_t -#define MEM_TYPE_U32 uint32_t -#define MEM_TYPE_I64 int64_t -#define MEM_TYPE_U64 uint64_t -#define MEM_TYPE_F32 uint32_t -#define MEM_TYPE_F64 uint64_t - -#define MEM_TYPE_EXTEND_I32_I8 int32_t -#define MEM_TYPE_EXTEND_I32_U8 uint32_t -#define MEM_TYPE_EXTEND_I32_I16 int32_t -#define MEM_TYPE_EXTEND_I32_U16 uint32_t -#define MEM_TYPE_EXTEND_I32_I32 int32_t -#define MEM_TYPE_EXTEND_I32_U32 uint32_t - -#define MEM_TYPE_EXTEND_I64_I8 int64_t -#define MEM_TYPE_EXTEND_I64_U8 uint64_t -#define MEM_TYPE_EXTEND_I64_I16 int64_t -#define MEM_TYPE_EXTEND_I64_U16 uint64_t -#define MEM_TYPE_EXTEND_I64_I32 int64_t -#define MEM_TYPE_EXTEND_I64_U32 uint64_t -#define MEM_TYPE_EXTEND_I64_I64 int64_t -#define MEM_TYPE_EXTEND_I64_U64 uint64_t - -#define MEM_TYPE_EXTEND_F32_F32 uint32_t -#define MEM_TYPE_EXTEND_F64_F64 uint64_t - -#define BITCAST_I32_TO_SIGNED bitcast_u32_to_i32 -#define BITCAST_I64_TO_SIGNED bitcast_u64_to_i64 -#define BITCAST_I32_TO_UNSIGNED bitcast_i32_to_u32 -#define BITCAST_I64_TO_UNSIGNED bitcast_i64_to_u64 - -#define BITCAST_TO_F32 bitcast_u32_to_f32 -#define BITCAST_TO_F64 bitcast_u64_to_f64 -#define BITCAST_FROM_F32 bitcast_f32_to_u32 -#define BITCAST_FROM_F64 bitcast_f64_to_u64 - -#define TYPE_FIELD_NAME_I32 i32 -#define TYPE_FIELD_NAME_I64 i64 -#define TYPE_FIELD_NAME_F32 f32_bits -#define TYPE_FIELD_NAME_F64 f64_bits +template <> +Value MakeValue(uint32_t v) { + Value result; + result.f32_bits = v; + return result; +} + +template <> +Value MakeValue(uint64_t v) { + Value result; + result.f64_bits = v; + return result; +} + +template ValueTypeRep GetValue(Value); +template<> uint32_t GetValue(Value v) { return v.i32; } +template<> uint32_t GetValue(Value v) { return v.i32; } +template<> uint64_t GetValue(Value v) { return v.i64; } +template<> uint64_t GetValue(Value v) { return v.i64; } +template<> uint32_t GetValue(Value v) { return v.f32_bits; } +template<> uint64_t GetValue(Value v) { return v.f64_bits; } #define TRAP(type) return Result::Trap##type #define TRAP_UNLESS(cond, type) TRAP_IF(!(cond), type) @@ -526,234 +576,12 @@ DEFINE_BITCAST(bitcast_u64_to_f64, uint64_t, double) #define PUSH_NEG_1_AND_BREAK_IF(cond) \ if (WABT_UNLIKELY(cond)) { \ - PUSH_I32(-1); \ + CHECK_TRAP(Push(-1)); \ break; \ } -#define PUSH(v) \ - do { \ - CHECK_STACK(); \ - (*value_stack_top_++) = (v); \ - } while (0) - -#define PUSH_TYPE(type, v) \ - do { \ - CHECK_STACK(); \ - (*value_stack_top_++).TYPE_FIELD_NAME_##type = \ - static_cast(v); \ - } while (0) - -#define PUSH_I32(v) PUSH_TYPE(I32, (v)) -#define PUSH_I64(v) PUSH_TYPE(I64, (v)) -#define PUSH_F32(v) PUSH_TYPE(F32, (v)) -#define PUSH_F64(v) PUSH_TYPE(F64, (v)) - -#define PICK(depth) (*(value_stack_top_ - (depth))) -#define TOP() (PICK(1)) -#define POP() (*--value_stack_top_) -#define POP_I32() (POP().i32) -#define POP_I64() (POP().i64) -#define POP_F32() (POP().f32_bits) -#define POP_F64() (POP().f64_bits) -#define DROP_KEEP(drop, keep) \ - do { \ - assert((keep) <= 1); \ - if ((keep) == 1) \ - PICK((drop) + 1) = TOP(); \ - value_stack_top_ -= (drop); \ - } while (0) - #define GOTO(offset) pc = &istream[offset] -#define PUSH_CALL() \ - do { \ - TRAP_IF(call_stack_top_ >= call_stack_end_, CallStackExhausted); \ - (*call_stack_top_++) = (pc - istream); \ - } while (0) - -#define POP_CALL() (*--call_stack_top_) - -#define GET_MEMORY(var) \ - Index memory_index = read_u32(&pc); \ - Memory* var = &env_->memories_[memory_index] - -#define LOAD(type, mem_type) \ - do { \ - GET_MEMORY(memory); \ - uint64_t offset = static_cast(POP_I32()) + read_u32(&pc); \ - MEM_TYPE_##mem_type value; \ - TRAP_IF(offset + sizeof(value) > memory->data.size(), \ - MemoryAccessOutOfBounds); \ - void* src = memory->data.data() + static_cast(offset); \ - memcpy(&value, src, sizeof(MEM_TYPE_##mem_type)); \ - PUSH_##type(static_cast(value)); \ - } while (0) - -#define STORE(type, mem_type) \ - do { \ - GET_MEMORY(memory); \ - VALUE_TYPE_##type value = POP_##type(); \ - uint64_t offset = static_cast(POP_I32()) + read_u32(&pc); \ - MEM_TYPE_##mem_type src = static_cast(value); \ - TRAP_IF(offset + sizeof(src) > memory->data.size(), \ - MemoryAccessOutOfBounds); \ - void* dst = memory->data.data() + static_cast(offset); \ - memcpy(dst, &src, sizeof(MEM_TYPE_##mem_type)); \ - } while (0) - -#define BINOP(rtype, type, op) \ - do { \ - VALUE_TYPE_##type rhs = POP_##type(); \ - VALUE_TYPE_##type lhs = POP_##type(); \ - PUSH_##rtype(lhs op rhs); \ - } while (0) - -#define BINOP_SIGNED(rtype, type, op) \ - do { \ - VALUE_TYPE_##type rhs = POP_##type(); \ - VALUE_TYPE_##type lhs = POP_##type(); \ - PUSH_##rtype(BITCAST_##type##_TO_SIGNED(lhs) \ - op BITCAST_##type##_TO_SIGNED(rhs)); \ - } while (0) - -#define SHIFT_MASK_I32 31 -#define SHIFT_MASK_I64 63 - -#define BINOP_SHIFT(type, op, sign) \ - do { \ - VALUE_TYPE_##type rhs = POP_##type(); \ - VALUE_TYPE_##type lhs = POP_##type(); \ - PUSH_##type(BITCAST_##type##_TO_##sign(lhs) op(rhs& SHIFT_MASK_##type)); \ - } while (0) - -#define ROT_LEFT_0_SHIFT_OP << -#define ROT_LEFT_1_SHIFT_OP >> -#define ROT_RIGHT_0_SHIFT_OP >> -#define ROT_RIGHT_1_SHIFT_OP << - -#define BINOP_ROT(type, dir) \ - do { \ - VALUE_TYPE_##type rhs = POP_##type(); \ - VALUE_TYPE_##type lhs = POP_##type(); \ - uint32_t amount = rhs & SHIFT_MASK_##type; \ - if (WABT_LIKELY(amount != 0)) { \ - PUSH_##type( \ - (lhs ROT_##dir##_0_SHIFT_OP amount) | \ - (lhs ROT_##dir##_1_SHIFT_OP((SHIFT_MASK_##type + 1) - amount))); \ - } else { \ - PUSH_##type(lhs); \ - } \ - } while (0) - -#define BINOP_DIV_REM_U(type, op) \ - do { \ - VALUE_TYPE_##type rhs = POP_##type(); \ - VALUE_TYPE_##type lhs = POP_##type(); \ - TRAP_IF(rhs == 0, IntegerDivideByZero); \ - PUSH_##type(BITCAST_##type##_TO_UNSIGNED(lhs) \ - op BITCAST_##type##_TO_UNSIGNED(rhs)); \ - } while (0) - -/* {i32,i64}.{div,rem}_s are special-cased because they trap when dividing the - * max signed value by -1. The modulo operation on x86 uses the same - * instruction to generate the quotient and the remainder. */ -#define BINOP_DIV_S(type) \ - do { \ - VALUE_TYPE_##type rhs = POP_##type(); \ - VALUE_TYPE_##type lhs = POP_##type(); \ - TRAP_IF(rhs == 0, IntegerDivideByZero); \ - TRAP_IF(lhs == VALUE_TYPE_SIGNED_MAX_##type && \ - rhs == VALUE_TYPE_UNSIGNED_MAX_##type, \ - IntegerOverflow); \ - PUSH_##type(BITCAST_##type##_TO_SIGNED(lhs) / \ - BITCAST_##type##_TO_SIGNED(rhs)); \ - } while (0) - -#define BINOP_REM_S(type) \ - do { \ - VALUE_TYPE_##type rhs = POP_##type(); \ - VALUE_TYPE_##type lhs = POP_##type(); \ - TRAP_IF(rhs == 0, IntegerDivideByZero); \ - if (WABT_UNLIKELY(lhs == VALUE_TYPE_SIGNED_MAX_##type && \ - rhs == VALUE_TYPE_UNSIGNED_MAX_##type)) { \ - PUSH_##type(0); \ - } else { \ - PUSH_##type(BITCAST_##type##_TO_SIGNED(lhs) % \ - BITCAST_##type##_TO_SIGNED(rhs)); \ - } \ - } while (0) - -#define UNOP_FLOAT(type, func) \ - do { \ - FLOAT_TYPE_##type value = BITCAST_TO_##type(POP_##type()); \ - VALUE_TYPE_##type result = BITCAST_FROM_##type(func(value)); \ - if (WABT_UNLIKELY(IS_NAN_##type(result))) { \ - result |= type##_QUIET_NAN_BIT; \ - } \ - PUSH_##type(result); \ - break; \ - } while (0) - -#define BINOP_FLOAT(type, op) \ - do { \ - FLOAT_TYPE_##type rhs = BITCAST_TO_##type(POP_##type()); \ - FLOAT_TYPE_##type lhs = BITCAST_TO_##type(POP_##type()); \ - PUSH_##type(BITCAST_FROM_##type(lhs op rhs)); \ - } while (0) - -#define BINOP_FLOAT_DIV(type) \ - do { \ - VALUE_TYPE_##type rhs = POP_##type(); \ - VALUE_TYPE_##type lhs = POP_##type(); \ - if (WABT_UNLIKELY(IS_ZERO_##type(rhs))) { \ - if (IS_NAN_##type(lhs)) { \ - PUSH_##type(lhs | type##_QUIET_NAN); \ - } else if (IS_ZERO_##type(lhs)) { \ - PUSH_##type(type##_QUIET_NAN); \ - } else { \ - VALUE_TYPE_##type sign = \ - (lhs & type##_SIGN_MASK) ^ (rhs & type##_SIGN_MASK); \ - PUSH_##type(sign | type##_INF); \ - } \ - } else { \ - PUSH_##type(BITCAST_FROM_##type(BITCAST_TO_##type(lhs) / \ - BITCAST_TO_##type(rhs))); \ - } \ - } while (0) - -#define BINOP_FLOAT_COMPARE(type, op) \ - do { \ - FLOAT_TYPE_##type rhs = BITCAST_TO_##type(POP_##type()); \ - FLOAT_TYPE_##type lhs = BITCAST_TO_##type(POP_##type()); \ - PUSH_I32(lhs op rhs); \ - } while (0) - -#define MIN_OP < -#define MAX_OP > - -#define MINMAX_FLOAT(type, op) \ - do { \ - VALUE_TYPE_##type rhs = POP_##type(); \ - VALUE_TYPE_##type lhs = POP_##type(); \ - VALUE_TYPE_##type result; \ - if (WABT_UNLIKELY(IS_NAN_##type(lhs))) { \ - result = lhs | type##_QUIET_NAN_BIT; \ - } else if (WABT_UNLIKELY(IS_NAN_##type(rhs))) { \ - result = rhs | type##_QUIET_NAN_BIT; \ - } else if ((lhs ^ rhs) & type##_SIGN_MASK) { \ - /* min(-0.0, 0.0) => -0.0; since we know the sign bits are different, we \ - * can just use the inverse integer comparison (because the sign bit is \ - * set when the value is negative) */ \ - result = !(lhs op##_OP rhs) ? lhs : rhs; \ - } else { \ - FLOAT_TYPE_##type float_rhs = BITCAST_TO_##type(rhs); \ - FLOAT_TYPE_##type float_lhs = BITCAST_TO_##type(lhs); \ - result = BITCAST_FROM_##type(float_lhs op##_OP float_rhs ? float_lhs \ - : float_rhs); \ - } \ - PUSH_##type(result); \ - } while (0) - static WABT_INLINE uint32_t read_u32_at(const uint8_t* pc) { uint32_t result; memcpy(&result, pc, sizeof(uint32_t)); @@ -787,6 +615,462 @@ static WABT_INLINE void read_table_entry_at(const uint8_t* pc, *out_keep = *(pc + WABT_TABLE_ENTRY_KEEP_OFFSET); } +Memory* Thread::ReadMemory(const uint8_t** pc) { + Index memory_index = read_u32(pc); + return &env_->memories_[memory_index]; +} + +Value& Thread::Top() { + return Pick(1); +} + +Value& Thread::Pick(Index depth) { + return *(value_stack_top_ - depth); +} + +Result Thread::Push(Value value) { + CHECK_STACK(); + *value_stack_top_++ = value; + return Result::Ok; +} + +Value Thread::Pop() { + return *--value_stack_top_; +} + +template +Result Thread::Push(T value) { + return PushRep(ToRep(value)); +} + +template +T Thread::Pop() { + return FromRep(PopRep()); +} + +template +Result Thread::PushRep(ValueTypeRep value) { + return Push(MakeValue(value)); +} + +template +ValueTypeRep Thread::PopRep() { + return GetValue(Pop()); +} + +void Thread::DropKeep(uint32_t drop_count, uint8_t keep_count) { + assert(keep_count <= 1); + if (keep_count == 1) + Pick(drop_count + 1) = Top(); + value_stack_top_ -= drop_count; +} + +Result Thread::PushCall(const uint8_t* pc) { + TRAP_IF(call_stack_top_ >= call_stack_end_, CallStackExhausted); + *call_stack_top_++ = pc - GetIstream(); + return Result::Ok; +} + +IstreamOffset Thread::PopCall() { + return *--call_stack_top_; +} + +template +Result Thread::Load(const uint8_t** pc) { + typedef typename ExtendMemType::type ExtendedType; + static_assert(std::is_floating_point::value == + std::is_floating_point::value, + "Extended type should be float iff MemType is float"); + + Memory* memory = ReadMemory(pc); + uint64_t offset = static_cast(Pop()) + read_u32(pc); + MemType value; + TRAP_IF(offset + sizeof(value) > memory->data.size(), + MemoryAccessOutOfBounds); + void* src = memory->data.data() + static_cast(offset); + memcpy(&value, src, sizeof(value)); + return Push(static_cast(value)); +} + +template +Result Thread::Store(const uint8_t** pc) { + typedef typename WrapMemType::type WrappedType; + Memory* memory = ReadMemory(pc); + WrappedType value = PopRep(); + uint64_t offset = static_cast(Pop()) + read_u32(pc); + TRAP_IF(offset + sizeof(value) > memory->data.size(), + MemoryAccessOutOfBounds); + void* dst = memory->data.data() + static_cast(offset); + memcpy(dst, &value, sizeof(value)); + return Result::Ok; +} + +template +Result Thread::Unop(UnopFunc func) { + auto value = PopRep(); + return PushRep(func(value)); +} + +template +Result Thread::UnopTrap(UnopTrapFunc func) { + auto value = PopRep(); + ValueTypeRep result_value; + CHECK_TRAP(func(value, &result_value)); + return PushRep(result_value); +} + +template +Result Thread::Binop(BinopFunc func) { + auto rhs_rep = PopRep(); + auto lhs_rep = PopRep(); + return PushRep(func(lhs_rep, rhs_rep)); +} + +template +Result Thread::BinopTrap(BinopTrapFunc func) { + auto rhs_rep = PopRep(); + auto lhs_rep = PopRep(); + ValueTypeRep result_value; + CHECK_TRAP(func(lhs_rep, rhs_rep, &result_value)); + return PushRep(result_value); +} + +// {i,f}{32,64}.add +template +ValueTypeRep Add(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + return ToRep(FromRep(lhs_rep) + FromRep(rhs_rep)); +} + +// {i,f}{32,64}.sub +template +ValueTypeRep Sub(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + return ToRep(FromRep(lhs_rep) - FromRep(rhs_rep)); +} + +// {i,f}{32,64}.mul +template +ValueTypeRep Mul(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + return ToRep(FromRep(lhs_rep) * FromRep(rhs_rep)); +} + +// i{32,64}.{div,rem}_s are special-cased because they trap when dividing the +// max signed value by -1. The modulo operation on x86 uses the same +// instruction to generate the quotient and the remainder. +template +bool IsNormalDivRemS(T lhs, T rhs) { + static_assert(std::is_signed::value, "T should be a signed type."); + return !(lhs == std::numeric_limits::min() && rhs == -1); +} + +// i{32,64}.div_s +template +Result IntDivS(ValueTypeRep lhs_rep, + ValueTypeRep rhs_rep, + ValueTypeRep* out_result) { + auto lhs = FromRep(lhs_rep); + auto rhs = FromRep(rhs_rep); + TRAP_IF(rhs == 0, IntegerDivideByZero); + TRAP_UNLESS(IsNormalDivRemS(lhs, rhs), IntegerOverflow); + *out_result = ToRep(lhs / rhs); + return Result::Ok; +} + +// i{32,64}.rem_s +template +Result IntRemS(ValueTypeRep lhs_rep, + ValueTypeRep rhs_rep, + ValueTypeRep* out_result) { + auto lhs = FromRep(lhs_rep); + auto rhs = FromRep(rhs_rep); + TRAP_IF(rhs == 0, IntegerDivideByZero); + if (WABT_LIKELY(IsNormalDivRemS(lhs, rhs))) { + *out_result = ToRep(lhs % rhs); + } else { + *out_result = 0; + } + return Result::Ok; +} + +// i{32,64}.div_u +template +Result IntDivU(ValueTypeRep lhs_rep, + ValueTypeRep rhs_rep, + ValueTypeRep* out_result) { + auto lhs = FromRep(lhs_rep); + auto rhs = FromRep(rhs_rep); + TRAP_IF(rhs == 0, IntegerDivideByZero); + *out_result = ToRep(lhs / rhs); + return Result::Ok; +} + +// i{32,64}.rem_u +template +Result IntRemU(ValueTypeRep lhs_rep, + ValueTypeRep rhs_rep, + ValueTypeRep* out_result) { + auto lhs = FromRep(lhs_rep); + auto rhs = FromRep(rhs_rep); + TRAP_IF(rhs == 0, IntegerDivideByZero); + *out_result = ToRep(lhs % rhs); + return Result::Ok; +} + +// f{32,64}.div +template +ValueTypeRep FloatDiv(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + typedef FloatTraits Traits; + ValueTypeRep result; + if (WABT_UNLIKELY(Traits::IsZero(rhs_rep))) { + if (Traits::IsNan(lhs_rep)) { + result = lhs_rep | Traits::kQuietNan; + } else if (Traits::IsZero(lhs_rep)) { + result = Traits::kQuietNan; + } else { + auto sign = (lhs_rep & Traits::kSignMask) ^ (rhs_rep & Traits::kSignMask); + result = sign | Traits::kInf; + } + } else { + result = ToRep(FromRep(lhs_rep) / FromRep(rhs_rep)); + } + return result; +} + +// i{32,64}.and +template +ValueTypeRep IntAnd(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + return ToRep(FromRep(lhs_rep) & FromRep(rhs_rep)); +} + +// i{32,64}.or +template +ValueTypeRep IntOr(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + return ToRep(FromRep(lhs_rep) | FromRep(rhs_rep)); +} + +// i{32,64}.xor +template +ValueTypeRep IntXor(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + return ToRep(FromRep(lhs_rep) ^ FromRep(rhs_rep)); +} + +// i{32,64}.shl +template +ValueTypeRep IntShl(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + const int mask = sizeof(T) * 8 - 1; + return ToRep(FromRep(lhs_rep) << (FromRep(rhs_rep) & mask)); +} + +// i{32,64}.shr_{s,u} +template +ValueTypeRep IntShr(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + const int mask = sizeof(T) * 8 - 1; + return ToRep(FromRep(lhs_rep) >> (FromRep(rhs_rep) & mask)); +} + +// i{32,64}.rotl +template +ValueTypeRep IntRotl(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + const int mask = sizeof(T) * 8 - 1; + int amount = FromRep(rhs_rep) & mask; + auto lhs = FromRep(lhs_rep); + if (amount == 0) { + return ToRep(lhs); + } else { + return ToRep((lhs << amount) | (lhs >> (mask + 1 - amount))); + } +} + +// i{32,64}.rotr +template +ValueTypeRep IntRotr(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + const int mask = sizeof(T) * 8 - 1; + int amount = FromRep(rhs_rep) & mask; + auto lhs = FromRep(lhs_rep); + if (amount == 0) { + return ToRep(lhs); + } else { + return ToRep((lhs >> amount) | (lhs << (mask + 1 - amount))); + } +} + +// i{32,64}.eqz +template +ValueTypeRep IntEqz(ValueTypeRep v_rep) { + return ToRep(v_rep == 0); +} + +// f{32,64}.abs +template +ValueTypeRep FloatAbs(ValueTypeRep v_rep) { + return v_rep & ~FloatTraits::kSignMask; +} + +// f{32,64}.neg +template +ValueTypeRep FloatNeg(ValueTypeRep v_rep) { + return v_rep ^ FloatTraits::kSignMask; +} + +// f{32,64}.ceil +template +ValueTypeRep FloatCeil(ValueTypeRep v_rep) { + auto result = ToRep(std::ceil(FromRep(v_rep))); + if (WABT_UNLIKELY(FloatTraits::IsNan(result))) { + result |= FloatTraits::kQuietNanBit; + } + return result; +} + +// f{32,64}.floor +template +ValueTypeRep FloatFloor(ValueTypeRep v_rep) { + auto result = ToRep(std::floor(FromRep(v_rep))); + if (WABT_UNLIKELY(FloatTraits::IsNan(result))) { + result |= FloatTraits::kQuietNanBit; + } + return result; +} + +// f{32,64}.trunc +template +ValueTypeRep FloatTrunc(ValueTypeRep v_rep) { + auto result = ToRep(std::trunc(FromRep(v_rep))); + if (WABT_UNLIKELY(FloatTraits::IsNan(result))) { + result |= FloatTraits::kQuietNanBit; + } + return result; +} + +// f{32,64}.nearest +template +ValueTypeRep FloatNearest(ValueTypeRep v_rep) { + auto result = ToRep(std::nearbyint(FromRep(v_rep))); + if (WABT_UNLIKELY(FloatTraits::IsNan(result))) { + result |= FloatTraits::kQuietNanBit; + } + return result; +} + +// f{32,64}.sqrt +template +ValueTypeRep FloatSqrt(ValueTypeRep v_rep) { + auto result = ToRep(std::sqrt(FromRep(v_rep))); + if (WABT_UNLIKELY(FloatTraits::IsNan(result))) { + result |= FloatTraits::kQuietNanBit; + } + return result; +} + +// f{32,64}.min +template +ValueTypeRep FloatMin(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + typedef FloatTraits Traits; + + if (WABT_UNLIKELY(Traits::IsNan(lhs_rep))) { + return lhs_rep | Traits::kQuietNanBit; + } else if (WABT_UNLIKELY(Traits::IsNan(rhs_rep))) { + return rhs_rep | Traits::kQuietNanBit; + } else if (WABT_UNLIKELY(Traits::IsZero(lhs_rep) && + Traits::IsZero(rhs_rep))) { + // min(0.0, -0.0) == -0.0, but std::min won't produce the correct result. + // We can instead compare using the unsigned integer representation, but + // just max instead (since the sign bit makes the value larger). + return std::max(lhs_rep, rhs_rep); + } else { + return ToRep(std::min(FromRep(lhs_rep), FromRep(rhs_rep))); + } +} + +// f{32,64}.max +template +ValueTypeRep FloatMax(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + typedef FloatTraits Traits; + + if (WABT_UNLIKELY(Traits::IsNan(lhs_rep))) { + return lhs_rep | Traits::kQuietNanBit; + } else if (WABT_UNLIKELY(Traits::IsNan(rhs_rep))) { + return rhs_rep | Traits::kQuietNanBit; + } else if (WABT_UNLIKELY(Traits::IsZero(lhs_rep) && + Traits::IsZero(rhs_rep))) { + // min(0.0, -0.0) == -0.0, but std::min won't produce the correct result. + // We can instead compare using the unsigned integer representation, but + // just max instead (since the sign bit makes the value larger). + return std::min(lhs_rep, rhs_rep); + } else { + return ToRep(std::max(FromRep(lhs_rep), FromRep(rhs_rep))); + } +} + +// f{32,64}.copysign +template +ValueTypeRep FloatCopySign(ValueTypeRep lhs_rep, + ValueTypeRep rhs_rep) { + typedef FloatTraits Traits; + return (lhs_rep & ~Traits::kSignMask) | (rhs_rep & Traits::kSignMask); +} + +// {i,f}{32,64}.eq +template +uint32_t Eq(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + return ToRep(FromRep(lhs_rep) == FromRep(rhs_rep)); +} + +// {i,f}{32,64}.ne +template +uint32_t Ne(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + return ToRep(FromRep(lhs_rep) != FromRep(rhs_rep)); +} + +// f{32,64}.lt | i{32,64}.lt_{s,u} +template +uint32_t Lt(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + return ToRep(FromRep(lhs_rep) < FromRep(rhs_rep)); +} + +// f{32,64}.le | i{32,64}.le_{s,u} +template +uint32_t Le(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + return ToRep(FromRep(lhs_rep) <= FromRep(rhs_rep)); +} + +// f{32,64}.gt | i{32,64}.gt_{s,u} +template +uint32_t Gt(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + return ToRep(FromRep(lhs_rep) > FromRep(rhs_rep)); +} + +// f{32,64}.ge | i{32,64}.ge_{s,u} +template +uint32_t Ge(ValueTypeRep lhs_rep, ValueTypeRep rhs_rep) { + return ToRep(FromRep(lhs_rep) >= FromRep(rhs_rep)); +} + +// i{32,64}.trunc_{s,u}/f{32,64} +template +Result IntTrunc(ValueTypeRep v_rep, ValueTypeRep* out_result) { + TRAP_IF(FloatTraits::IsNan(v_rep), InvalidConversionToInteger); + TRAP_UNLESS((IsConversionInRange(v_rep)), IntegerOverflow); + *out_result = ToRep(static_cast(FromRep(v_rep))); + return Result::Ok; +} + +// i{32,64}.trunc_{s,u}:sat/f{32,64} +template +ValueTypeRep IntTruncSat(ValueTypeRep v_rep) { + typedef FloatTraits Traits; + if (WABT_UNLIKELY(Traits::IsNan(v_rep))) { + return 0; + } else if (WABT_UNLIKELY((!IsConversionInRange(v_rep)))) { + if (v_rep & Traits::kSignMask) { + return ToRep(std::numeric_limits::min()); + } else { + return ToRep(std::numeric_limits::max()); + } + } else { + return ToRep(static_cast(FromRep(v_rep))); + } +} + bool Environment::FuncSignaturesAreEqual(Index sig_index_0, Index sig_index_1) const { if (sig_index_0 == sig_index_1) @@ -880,7 +1164,7 @@ Result Thread::CallHost(HostFunc* func) { std::vector results(num_results + 1); for (size_t i = num_params; i > 0; --i) { - params[i - 1].value = POP(); + params[i - 1].value = Pop(); params[i - 1].type = sig->param_types[i - 1]; } @@ -891,7 +1175,7 @@ Result Thread::CallHost(HostFunc* func) { for (size_t i = 0; i < num_results; ++i) { TRAP_IF(results[i].type != sig->result_types[i], HostResultTypeMismatch); - PUSH(results[i].value); + CHECK_TRAP(Push(results[i].value)); } return Result::Ok; @@ -901,16 +1185,16 @@ Result Thread::Run(int num_instructions, IstreamOffset* call_stack_return_top) { Result result = Result::Ok; assert(call_stack_return_top < call_stack_end_); - const uint8_t* istream = env_->istream_->data.data(); + const uint8_t* istream = GetIstream(); const uint8_t* pc = &istream[pc_]; for (int i = 0; i < num_instructions; ++i) { Opcode opcode = static_cast(*pc++); switch (opcode) { case Opcode::Select: { - VALUE_TYPE_I32 cond = POP_I32(); - Value false_ = POP(); - Value true_ = POP(); - PUSH(cond ? true_ : false_); + uint32_t cond = Pop(); + Value false_ = Pop(); + Value true_ = Pop(); + CHECK_TRAP(Push(cond ? true_ : false_)); break; } @@ -920,7 +1204,7 @@ Result Thread::Run(int num_instructions, IstreamOffset* call_stack_return_top) { case Opcode::BrIf: { IstreamOffset new_pc = read_u32(&pc); - if (POP_I32()) + if (Pop()) GOTO(new_pc); break; } @@ -928,7 +1212,7 @@ Result Thread::Run(int num_instructions, IstreamOffset* call_stack_return_top) { case Opcode::BrTable: { Index num_targets = read_u32(&pc); IstreamOffset table_offset = read_u32(&pc); - VALUE_TYPE_I32 key = POP_I32(); + uint32_t key = Pop(); IstreamOffset key_offset = (key >= num_targets ? num_targets : key) * WABT_TABLE_ENTRY_SIZE; const uint8_t* entry = istream + table_offset + key_offset; @@ -936,7 +1220,7 @@ Result Thread::Run(int num_instructions, IstreamOffset* call_stack_return_top) { uint32_t drop_count; uint8_t keep_count; read_table_entry_at(entry, &new_pc, &drop_count, &keep_count); - DROP_KEEP(drop_count, keep_count); + DropKeep(drop_count, keep_count); GOTO(new_pc); break; } @@ -946,7 +1230,7 @@ Result Thread::Run(int num_instructions, IstreamOffset* call_stack_return_top) { result = Result::Returned; goto exit_loop; } - GOTO(POP_CALL()); + GOTO(PopCall()); break; case Opcode::Unreachable: @@ -954,54 +1238,54 @@ Result Thread::Run(int num_instructions, IstreamOffset* call_stack_return_top) { break; case Opcode::I32Const: - PUSH_I32(read_u32(&pc)); + CHECK_TRAP(Push(read_u32(&pc))); break; case Opcode::I64Const: - PUSH_I64(read_u64(&pc)); + CHECK_TRAP(Push(read_u64(&pc))); break; case Opcode::F32Const: - PUSH_F32(read_u32(&pc)); + CHECK_TRAP(PushRep(read_u32(&pc))); break; case Opcode::F64Const: - PUSH_F64(read_u64(&pc)); + CHECK_TRAP(PushRep(read_u64(&pc))); break; case Opcode::GetGlobal: { Index index = read_u32(&pc); assert(index < env_->globals_.size()); - PUSH(env_->globals_[index].typed_value.value); + CHECK_TRAP(Push(env_->globals_[index].typed_value.value)); break; } case Opcode::SetGlobal: { Index index = read_u32(&pc); assert(index < env_->globals_.size()); - env_->globals_[index].typed_value.value = POP(); + env_->globals_[index].typed_value.value = Pop(); break; } case Opcode::GetLocal: { - Value value = PICK(read_u32(&pc)); - PUSH(value); + Value value = Pick(read_u32(&pc)); + CHECK_TRAP(Push(value)); break; } case Opcode::SetLocal: { - Value value = POP(); - PICK(read_u32(&pc)) = value; + Value value = Pop(); + Pick(read_u32(&pc)) = value; break; } case Opcode::TeeLocal: - PICK(read_u32(&pc)) = TOP(); + Pick(read_u32(&pc)) = Top(); break; case Opcode::Call: { IstreamOffset offset = read_u32(&pc); - PUSH_CALL(); + CHECK_TRAP(PushCall(pc)); GOTO(offset); break; } @@ -1010,7 +1294,7 @@ Result Thread::Run(int num_instructions, IstreamOffset* call_stack_return_top) { Index table_index = read_u32(&pc); Table* table = &env_->tables_[table_index]; Index sig_index = read_u32(&pc); - VALUE_TYPE_I32 entry_index = POP_I32(); + Index entry_index = Pop(); TRAP_IF(entry_index >= table->func_indexes.size(), UndefinedTableIndex); Index func_index = table->func_indexes[entry_index]; TRAP_IF(func_index == kInvalidIndex, UninitializedTableElement); @@ -1020,7 +1304,7 @@ Result Thread::Run(int num_instructions, IstreamOffset* call_stack_return_top) { if (func->is_host) { CallHost(func->as_host()); } else { - PUSH_CALL(); + CHECK_TRAP(PushCall(pc)); GOTO(func->as_defined()->offset); } break; @@ -1033,107 +1317,105 @@ Result Thread::Run(int num_instructions, IstreamOffset* call_stack_return_top) { } case Opcode::I32Load8S: - LOAD(I32, I8); + CHECK_TRAP(Load(&pc)); break; case Opcode::I32Load8U: - LOAD(I32, U8); + CHECK_TRAP(Load(&pc)); break; case Opcode::I32Load16S: - LOAD(I32, I16); + CHECK_TRAP(Load(&pc)); break; case Opcode::I32Load16U: - LOAD(I32, U16); + CHECK_TRAP(Load(&pc)); break; case Opcode::I64Load8S: - LOAD(I64, I8); + CHECK_TRAP(Load(&pc)); break; case Opcode::I64Load8U: - LOAD(I64, U8); + CHECK_TRAP(Load(&pc)); break; case Opcode::I64Load16S: - LOAD(I64, I16); + CHECK_TRAP(Load(&pc)); break; case Opcode::I64Load16U: - LOAD(I64, U16); + CHECK_TRAP(Load(&pc)); break; case Opcode::I64Load32S: - LOAD(I64, I32); + CHECK_TRAP(Load(&pc)); break; case Opcode::I64Load32U: - LOAD(I64, U32); + CHECK_TRAP(Load(&pc)); break; case Opcode::I32Load: - LOAD(I32, U32); + CHECK_TRAP(Load(&pc)); break; case Opcode::I64Load: - LOAD(I64, U64); + CHECK_TRAP(Load(&pc)); break; case Opcode::F32Load: - LOAD(F32, F32); + CHECK_TRAP(Load(&pc)); break; case Opcode::F64Load: - LOAD(F64, F64); + CHECK_TRAP(Load(&pc)); break; case Opcode::I32Store8: - STORE(I32, U8); + CHECK_TRAP(Store(&pc)); break; case Opcode::I32Store16: - STORE(I32, U16); + CHECK_TRAP(Store(&pc)); break; case Opcode::I64Store8: - STORE(I64, U8); + CHECK_TRAP(Store(&pc)); break; case Opcode::I64Store16: - STORE(I64, U16); + CHECK_TRAP(Store(&pc)); break; case Opcode::I64Store32: - STORE(I64, U32); + CHECK_TRAP(Store(&pc)); break; case Opcode::I32Store: - STORE(I32, U32); + CHECK_TRAP(Store(&pc)); break; case Opcode::I64Store: - STORE(I64, U64); + CHECK_TRAP(Store(&pc)); break; case Opcode::F32Store: - STORE(F32, F32); + CHECK_TRAP(Store(&pc)); break; case Opcode::F64Store: - STORE(F64, F64); + CHECK_TRAP(Store(&pc)); break; - case Opcode::CurrentMemory: { - GET_MEMORY(memory); - PUSH_I32(memory->page_limits.initial); + case Opcode::CurrentMemory: + CHECK_TRAP(Push(ReadMemory(&pc)->page_limits.initial)); break; - } case Opcode::GrowMemory: { - GET_MEMORY(memory); + Memory* memory = ReadMemory(&pc); uint32_t old_page_size = memory->page_limits.initial; - VALUE_TYPE_I32 grow_pages = POP_I32(); + uint32_t grow_pages = Pop(); uint32_t new_page_size = old_page_size + grow_pages; uint32_t max_page_size = memory->page_limits.has_max ? memory->page_limits.max @@ -1143,607 +1425,564 @@ Result Thread::Run(int num_instructions, IstreamOffset* call_stack_return_top) { static_cast(new_page_size) * WABT_PAGE_SIZE > UINT32_MAX); memory->data.resize(new_page_size * WABT_PAGE_SIZE); memory->page_limits.initial = new_page_size; - PUSH_I32(old_page_size); + CHECK_TRAP(Push(old_page_size)); break; } case Opcode::I32Add: - BINOP(I32, I32, +); + CHECK_TRAP(Binop(Add)); break; case Opcode::I32Sub: - BINOP(I32, I32, -); + CHECK_TRAP(Binop(Sub)); break; case Opcode::I32Mul: - BINOP(I32, I32, *); + CHECK_TRAP(Binop(Mul)); break; case Opcode::I32DivS: - BINOP_DIV_S(I32); + CHECK_TRAP(BinopTrap(IntDivS)); break; case Opcode::I32DivU: - BINOP_DIV_REM_U(I32, /); + CHECK_TRAP(BinopTrap(IntDivU)); break; case Opcode::I32RemS: - BINOP_REM_S(I32); + CHECK_TRAP(BinopTrap(IntRemS)); break; case Opcode::I32RemU: - BINOP_DIV_REM_U(I32, %); + CHECK_TRAP(BinopTrap(IntRemU)); break; case Opcode::I32And: - BINOP(I32, I32, &); + CHECK_TRAP(Binop(IntAnd)); break; case Opcode::I32Or: - BINOP(I32, I32, |); + CHECK_TRAP(Binop(IntOr)); break; case Opcode::I32Xor: - BINOP(I32, I32, ^); + CHECK_TRAP(Binop(IntXor)); break; case Opcode::I32Shl: - BINOP_SHIFT(I32, <<, UNSIGNED); + CHECK_TRAP(Binop(IntShl)); break; case Opcode::I32ShrU: - BINOP_SHIFT(I32, >>, UNSIGNED); + CHECK_TRAP(Binop(IntShr)); break; case Opcode::I32ShrS: - BINOP_SHIFT(I32, >>, SIGNED); + CHECK_TRAP(Binop(IntShr)); break; case Opcode::I32Eq: - BINOP(I32, I32, ==); + CHECK_TRAP(Binop(Eq)); break; case Opcode::I32Ne: - BINOP(I32, I32, !=); + CHECK_TRAP(Binop(Ne)); break; case Opcode::I32LtS: - BINOP_SIGNED(I32, I32, <); + CHECK_TRAP(Binop(Lt)); break; case Opcode::I32LeS: - BINOP_SIGNED(I32, I32, <=); + CHECK_TRAP(Binop(Le)); break; case Opcode::I32LtU: - BINOP(I32, I32, <); + CHECK_TRAP(Binop(Lt)); break; case Opcode::I32LeU: - BINOP(I32, I32, <=); + CHECK_TRAP(Binop(Le)); break; case Opcode::I32GtS: - BINOP_SIGNED(I32, I32, >); + CHECK_TRAP(Binop(Gt)); break; case Opcode::I32GeS: - BINOP_SIGNED(I32, I32, >=); + CHECK_TRAP(Binop(Ge)); break; case Opcode::I32GtU: - BINOP(I32, I32, >); + CHECK_TRAP(Binop(Gt)); break; case Opcode::I32GeU: - BINOP(I32, I32, >=); + CHECK_TRAP(Binop(Ge)); break; case Opcode::I32Clz: { - VALUE_TYPE_I32 value = POP_I32(); - PUSH_I32(value != 0 ? wabt_clz_u32(value) : 32); + uint32_t value = Pop(); + CHECK_TRAP(Push(value != 0 ? wabt_clz_u32(value) : 32)); break; } case Opcode::I32Ctz: { - VALUE_TYPE_I32 value = POP_I32(); - PUSH_I32(value != 0 ? wabt_ctz_u32(value) : 32); + uint32_t value = Pop(); + CHECK_TRAP(Push(value != 0 ? wabt_ctz_u32(value) : 32)); break; } case Opcode::I32Popcnt: { - VALUE_TYPE_I32 value = POP_I32(); - PUSH_I32(wabt_popcount_u32(value)); + uint32_t value = Pop(); + CHECK_TRAP(Push(wabt_popcount_u32(value))); break; } - case Opcode::I32Eqz: { - VALUE_TYPE_I32 value = POP_I32(); - PUSH_I32(value == 0); + case Opcode::I32Eqz: + CHECK_TRAP(Unop(IntEqz)); break; - } case Opcode::I64Add: - BINOP(I64, I64, +); + CHECK_TRAP(Binop(Add)); break; case Opcode::I64Sub: - BINOP(I64, I64, -); + CHECK_TRAP(Binop(Sub)); break; case Opcode::I64Mul: - BINOP(I64, I64, *); + CHECK_TRAP(Binop(Mul)); break; case Opcode::I64DivS: - BINOP_DIV_S(I64); + CHECK_TRAP(BinopTrap(IntDivS)); break; case Opcode::I64DivU: - BINOP_DIV_REM_U(I64, /); + CHECK_TRAP(BinopTrap(IntDivU)); break; case Opcode::I64RemS: - BINOP_REM_S(I64); + CHECK_TRAP(BinopTrap(IntRemS)); break; case Opcode::I64RemU: - BINOP_DIV_REM_U(I64, %); + CHECK_TRAP(BinopTrap(IntRemU)); break; case Opcode::I64And: - BINOP(I64, I64, &); + CHECK_TRAP(Binop(IntAnd)); break; case Opcode::I64Or: - BINOP(I64, I64, |); + CHECK_TRAP(Binop(IntOr)); break; case Opcode::I64Xor: - BINOP(I64, I64, ^); + CHECK_TRAP(Binop(IntXor)); break; case Opcode::I64Shl: - BINOP_SHIFT(I64, <<, UNSIGNED); + CHECK_TRAP(Binop(IntShl)); break; case Opcode::I64ShrU: - BINOP_SHIFT(I64, >>, UNSIGNED); + CHECK_TRAP(Binop(IntShr)); break; case Opcode::I64ShrS: - BINOP_SHIFT(I64, >>, SIGNED); + CHECK_TRAP(Binop(IntShr)); break; case Opcode::I64Eq: - BINOP(I32, I64, ==); + CHECK_TRAP(Binop(Eq)); break; case Opcode::I64Ne: - BINOP(I32, I64, !=); + CHECK_TRAP(Binop(Ne)); break; case Opcode::I64LtS: - BINOP_SIGNED(I32, I64, <); + CHECK_TRAP(Binop(Lt)); break; case Opcode::I64LeS: - BINOP_SIGNED(I32, I64, <=); + CHECK_TRAP(Binop(Le)); break; case Opcode::I64LtU: - BINOP(I32, I64, <); + CHECK_TRAP(Binop(Lt)); break; case Opcode::I64LeU: - BINOP(I32, I64, <=); + CHECK_TRAP(Binop(Le)); break; case Opcode::I64GtS: - BINOP_SIGNED(I32, I64, >); + CHECK_TRAP(Binop(Gt)); break; case Opcode::I64GeS: - BINOP_SIGNED(I32, I64, >=); + CHECK_TRAP(Binop(Ge)); break; case Opcode::I64GtU: - BINOP(I32, I64, >); + CHECK_TRAP(Binop(Gt)); break; case Opcode::I64GeU: - BINOP(I32, I64, >=); + CHECK_TRAP(Binop(Ge)); break; case Opcode::I64Clz: { - VALUE_TYPE_I64 value = POP_I64(); - PUSH_I64(value != 0 ? wabt_clz_u64(value) : 64); + uint64_t value = Pop(); + CHECK_TRAP(Push(value != 0 ? wabt_clz_u64(value) : 64)); break; } case Opcode::I64Ctz: { - VALUE_TYPE_I64 value = POP_I64(); - PUSH_I64(value != 0 ? wabt_ctz_u64(value) : 64); + uint64_t value = Pop(); + CHECK_TRAP(Push(value != 0 ? wabt_ctz_u64(value) : 64)); break; } - case Opcode::I64Popcnt: { - VALUE_TYPE_I64 value = POP_I64(); - PUSH_I64(wabt_popcount_u64(value)); + case Opcode::I64Popcnt: + CHECK_TRAP(Push(wabt_popcount_u64(Pop()))); break; - } case Opcode::F32Add: - BINOP_FLOAT(F32, +); + CHECK_TRAP(Binop(Add)); break; case Opcode::F32Sub: - BINOP_FLOAT(F32, -); + CHECK_TRAP(Binop(Sub)); break; case Opcode::F32Mul: - BINOP_FLOAT(F32, *); + CHECK_TRAP(Binop(Mul)); break; case Opcode::F32Div: - BINOP_FLOAT_DIV(F32); + CHECK_TRAP(Binop(FloatDiv)); break; case Opcode::F32Min: - MINMAX_FLOAT(F32, MIN); + CHECK_TRAP(Binop(FloatMin)); break; case Opcode::F32Max: - MINMAX_FLOAT(F32, MAX); + CHECK_TRAP(Binop(FloatMax)); break; case Opcode::F32Abs: - TOP().f32_bits &= ~F32_SIGN_MASK; + CHECK_TRAP(Unop(FloatAbs)); break; case Opcode::F32Neg: - TOP().f32_bits ^= F32_SIGN_MASK; + CHECK_TRAP(Unop(FloatNeg)); break; - case Opcode::F32Copysign: { - VALUE_TYPE_F32 rhs = POP_F32(); - VALUE_TYPE_F32 lhs = POP_F32(); - PUSH_F32((lhs & ~F32_SIGN_MASK) | (rhs & F32_SIGN_MASK)); + case Opcode::F32Copysign: + CHECK_TRAP(Binop(FloatCopySign)); break; - } case Opcode::F32Ceil: - UNOP_FLOAT(F32, ceilf); + CHECK_TRAP(Unop(FloatCeil)); break; case Opcode::F32Floor: - UNOP_FLOAT(F32, floorf); + CHECK_TRAP(Unop(FloatFloor)); break; case Opcode::F32Trunc: - UNOP_FLOAT(F32, truncf); + CHECK_TRAP(Unop(FloatTrunc)); break; case Opcode::F32Nearest: - UNOP_FLOAT(F32, nearbyintf); + CHECK_TRAP(Unop(FloatNearest)); break; case Opcode::F32Sqrt: - UNOP_FLOAT(F32, sqrtf); + CHECK_TRAP(Unop(FloatSqrt)); break; case Opcode::F32Eq: - BINOP_FLOAT_COMPARE(F32, ==); + CHECK_TRAP(Binop(Eq)); break; case Opcode::F32Ne: - BINOP_FLOAT_COMPARE(F32, !=); + CHECK_TRAP(Binop(Ne)); break; case Opcode::F32Lt: - BINOP_FLOAT_COMPARE(F32, <); + CHECK_TRAP(Binop(Lt)); break; case Opcode::F32Le: - BINOP_FLOAT_COMPARE(F32, <=); + CHECK_TRAP(Binop(Le)); break; case Opcode::F32Gt: - BINOP_FLOAT_COMPARE(F32, >); + CHECK_TRAP(Binop(Gt)); break; case Opcode::F32Ge: - BINOP_FLOAT_COMPARE(F32, >=); + CHECK_TRAP(Binop(Ge)); break; case Opcode::F64Add: - BINOP_FLOAT(F64, +); + CHECK_TRAP(Binop(Add)); break; case Opcode::F64Sub: - BINOP_FLOAT(F64, -); + CHECK_TRAP(Binop(Sub)); break; case Opcode::F64Mul: - BINOP_FLOAT(F64, *); + CHECK_TRAP(Binop(Mul)); break; case Opcode::F64Div: - BINOP_FLOAT_DIV(F64); + CHECK_TRAP(Binop(FloatDiv)); break; case Opcode::F64Min: - MINMAX_FLOAT(F64, MIN); + CHECK_TRAP(Binop(FloatMin)); break; case Opcode::F64Max: - MINMAX_FLOAT(F64, MAX); + CHECK_TRAP(Binop(FloatMax)); break; case Opcode::F64Abs: - TOP().f64_bits &= ~F64_SIGN_MASK; + CHECK_TRAP(Unop(FloatAbs)); break; case Opcode::F64Neg: - TOP().f64_bits ^= F64_SIGN_MASK; + CHECK_TRAP(Unop(FloatNeg)); break; - case Opcode::F64Copysign: { - VALUE_TYPE_F64 rhs = POP_F64(); - VALUE_TYPE_F64 lhs = POP_F64(); - PUSH_F64((lhs & ~F64_SIGN_MASK) | (rhs & F64_SIGN_MASK)); + case Opcode::F64Copysign: + CHECK_TRAP(Binop(FloatCopySign)); break; - } case Opcode::F64Ceil: - UNOP_FLOAT(F64, ceil); + CHECK_TRAP(Unop(FloatCeil)); break; case Opcode::F64Floor: - UNOP_FLOAT(F64, floor); + CHECK_TRAP(Unop(FloatFloor)); break; case Opcode::F64Trunc: - UNOP_FLOAT(F64, trunc); + CHECK_TRAP(Unop(FloatTrunc)); break; case Opcode::F64Nearest: - UNOP_FLOAT(F64, nearbyint); + CHECK_TRAP(Unop(FloatNearest)); break; case Opcode::F64Sqrt: - UNOP_FLOAT(F64, sqrt); + CHECK_TRAP(Unop(FloatSqrt)); break; case Opcode::F64Eq: - BINOP_FLOAT_COMPARE(F64, ==); + CHECK_TRAP(Binop(Eq)); break; case Opcode::F64Ne: - BINOP_FLOAT_COMPARE(F64, !=); + CHECK_TRAP(Binop(Ne)); break; case Opcode::F64Lt: - BINOP_FLOAT_COMPARE(F64, <); + CHECK_TRAP(Binop(Lt)); break; case Opcode::F64Le: - BINOP_FLOAT_COMPARE(F64, <=); + CHECK_TRAP(Binop(Le)); break; case Opcode::F64Gt: - BINOP_FLOAT_COMPARE(F64, >); + CHECK_TRAP(Binop(Gt)); break; case Opcode::F64Ge: - BINOP_FLOAT_COMPARE(F64, >=); + CHECK_TRAP(Binop(Ge)); break; - case Opcode::I32TruncSF32: { - VALUE_TYPE_F32 value = POP_F32(); - TRAP_IF(is_nan_f32(value), InvalidConversionToInteger); - TRAP_UNLESS(is_in_range_i32_trunc_s_f32(value), IntegerOverflow); - PUSH_I32(static_cast(BITCAST_TO_F32(value))); + case Opcode::I32TruncSF32: + CHECK_TRAP(UnopTrap(IntTrunc)); break; - } - case Opcode::I32TruncSF64: { - VALUE_TYPE_F64 value = POP_F64(); - TRAP_IF(is_nan_f64(value), InvalidConversionToInteger); - TRAP_UNLESS(is_in_range_i32_trunc_s_f64(value), IntegerOverflow); - PUSH_I32(static_cast(BITCAST_TO_F64(value))); + case Opcode::I32TruncSSatF32: + CHECK_TRAP(Unop(IntTruncSat)); break; - } - case Opcode::I32TruncUF32: { - VALUE_TYPE_F32 value = POP_F32(); - TRAP_IF(is_nan_f32(value), InvalidConversionToInteger); - TRAP_UNLESS(is_in_range_i32_trunc_u_f32(value), IntegerOverflow); - PUSH_I32(static_cast(BITCAST_TO_F32(value))); + case Opcode::I32TruncSF64: + CHECK_TRAP(UnopTrap(IntTrunc)); break; - } - case Opcode::I32TruncUF64: { - VALUE_TYPE_F64 value = POP_F64(); - TRAP_IF(is_nan_f64(value), InvalidConversionToInteger); - TRAP_UNLESS(is_in_range_i32_trunc_u_f64(value), IntegerOverflow); - PUSH_I32(static_cast(BITCAST_TO_F64(value))); + case Opcode::I32TruncSSatF64: + CHECK_TRAP(Unop(IntTruncSat)); break; - } - case Opcode::I32WrapI64: { - VALUE_TYPE_I64 value = POP_I64(); - PUSH_I32(static_cast(value)); + case Opcode::I32TruncUF32: + CHECK_TRAP(UnopTrap(IntTrunc)); break; - } - case Opcode::I64TruncSF32: { - VALUE_TYPE_F32 value = POP_F32(); - TRAP_IF(is_nan_f32(value), InvalidConversionToInteger); - TRAP_UNLESS(is_in_range_i64_trunc_s_f32(value), IntegerOverflow); - PUSH_I64(static_cast(BITCAST_TO_F32(value))); + case Opcode::I32TruncUSatF32: + CHECK_TRAP(Unop(IntTruncSat)); + break; + + case Opcode::I32TruncUF64: + CHECK_TRAP(UnopTrap(IntTrunc)); break; - } - case Opcode::I64TruncSF64: { - VALUE_TYPE_F64 value = POP_F64(); - TRAP_IF(is_nan_f64(value), InvalidConversionToInteger); - TRAP_UNLESS(is_in_range_i64_trunc_s_f64(value), IntegerOverflow); - PUSH_I64(static_cast(BITCAST_TO_F64(value))); + case Opcode::I32TruncUSatF64: + CHECK_TRAP(Unop(IntTruncSat)); break; - } - case Opcode::I64TruncUF32: { - VALUE_TYPE_F32 value = POP_F32(); - TRAP_IF(is_nan_f32(value), InvalidConversionToInteger); - TRAP_UNLESS(is_in_range_i64_trunc_u_f32(value), IntegerOverflow); - PUSH_I64(static_cast(BITCAST_TO_F32(value))); + case Opcode::I32WrapI64: + CHECK_TRAP(Push(Pop())); break; - } - case Opcode::I64TruncUF64: { - VALUE_TYPE_F64 value = POP_F64(); - TRAP_IF(is_nan_f64(value), InvalidConversionToInteger); - TRAP_UNLESS(is_in_range_i64_trunc_u_f64(value), IntegerOverflow); - PUSH_I64(static_cast(BITCAST_TO_F64(value))); + case Opcode::I64TruncSF32: + CHECK_TRAP(UnopTrap(IntTrunc)); break; - } - case Opcode::I64ExtendSI32: { - VALUE_TYPE_I32 value = POP_I32(); - PUSH_I64(static_cast(BITCAST_I32_TO_SIGNED(value))); + case Opcode::I64TruncSSatF32: + CHECK_TRAP(Unop(IntTruncSat)); break; - } - case Opcode::I64ExtendUI32: { - VALUE_TYPE_I32 value = POP_I32(); - PUSH_I64(static_cast(value)); + case Opcode::I64TruncSF64: + CHECK_TRAP(UnopTrap(IntTrunc)); break; - } - case Opcode::F32ConvertSI32: { - VALUE_TYPE_I32 value = POP_I32(); - PUSH_F32( - BITCAST_FROM_F32(static_cast(BITCAST_I32_TO_SIGNED(value)))); + case Opcode::I64TruncSSatF64: + CHECK_TRAP(Unop(IntTruncSat)); break; - } - case Opcode::F32ConvertUI32: { - VALUE_TYPE_I32 value = POP_I32(); - PUSH_F32(BITCAST_FROM_F32(static_cast(value))); + case Opcode::I64TruncUF32: + CHECK_TRAP(UnopTrap(IntTrunc)); break; - } - case Opcode::F32ConvertSI64: { - VALUE_TYPE_I64 value = POP_I64(); - PUSH_F32( - BITCAST_FROM_F32(static_cast(BITCAST_I64_TO_SIGNED(value)))); + case Opcode::I64TruncUSatF32: + CHECK_TRAP(Unop(IntTruncSat)); break; - } - case Opcode::F32ConvertUI64: { - VALUE_TYPE_I64 value = POP_I64(); - PUSH_F32(BITCAST_FROM_F32(wabt_convert_uint64_to_float(value))); + case Opcode::I64TruncUF64: + CHECK_TRAP(UnopTrap(IntTrunc)); + break; + + case Opcode::I64TruncUSatF64: + CHECK_TRAP(Unop(IntTruncSat)); + break; + + case Opcode::I64ExtendSI32: + CHECK_TRAP(Push(Pop())); + break; + + case Opcode::I64ExtendUI32: + CHECK_TRAP(Push(Pop())); + break; + + case Opcode::F32ConvertSI32: + CHECK_TRAP(Push(Pop())); + break; + + case Opcode::F32ConvertUI32: + CHECK_TRAP(Push(Pop())); + break; + + case Opcode::F32ConvertSI64: + CHECK_TRAP(Push(Pop())); + break; + + case Opcode::F32ConvertUI64: + CHECK_TRAP(Push(wabt_convert_uint64_to_float(Pop()))); break; - } case Opcode::F32DemoteF64: { - VALUE_TYPE_F64 value = POP_F64(); - if (WABT_LIKELY(is_in_range_f64_demote_f32(value))) { - PUSH_F32(BITCAST_FROM_F32(static_cast(BITCAST_TO_F64(value)))); - } else if (is_in_range_f64_demote_f32_round_to_f32_max(value)) { - PUSH_F32(F32_MAX); - } else if (is_in_range_f64_demote_f32_round_to_neg_f32_max(value)) { - PUSH_F32(F32_NEG_MAX); + typedef FloatTraits F32Traits; + typedef FloatTraits F64Traits; + + uint64_t value = PopRep(); + if (WABT_LIKELY((IsConversionInRange(value)))) { + CHECK_TRAP(Push(FromRep(value))); + } else if (IsInRangeF64DemoteF32RoundToF32Max(value)) { + CHECK_TRAP(PushRep(F32Traits::kMax)); + } else if (IsInRangeF64DemoteF32RoundToNegF32Max(value)) { + CHECK_TRAP(PushRep(F32Traits::kNegMax)); } else { - uint32_t sign = (value >> 32) & F32_SIGN_MASK; + uint32_t sign = (value >> 32) & F32Traits::kSignMask; uint32_t tag = 0; - if (IS_NAN_F64(value)) { - tag = F32_QUIET_NAN_BIT | - ((value >> (F64_SIG_BITS - F32_SIG_BITS)) & F32_SIG_MASK); + if (F64Traits::IsNan(value)) { + tag = F32Traits::kQuietNanBit | + ((value >> (F64Traits::kSigBits - F32Traits::kSigBits)) & + F32Traits::kSigMask); } - PUSH_F32(sign | F32_INF | tag); + CHECK_TRAP(PushRep(sign | F32Traits::kInf | tag)); } break; } - case Opcode::F32ReinterpretI32: { - VALUE_TYPE_I32 value = POP_I32(); - PUSH_F32(value); + case Opcode::F32ReinterpretI32: + CHECK_TRAP(PushRep(Pop())); break; - } - case Opcode::F64ConvertSI32: { - VALUE_TYPE_I32 value = POP_I32(); - PUSH_F64(BITCAST_FROM_F64( - static_cast(BITCAST_I32_TO_SIGNED(value)))); + case Opcode::F64ConvertSI32: + CHECK_TRAP(Push(Pop())); break; - } - case Opcode::F64ConvertUI32: { - VALUE_TYPE_I32 value = POP_I32(); - PUSH_F64(BITCAST_FROM_F64(static_cast(value))); + case Opcode::F64ConvertUI32: + CHECK_TRAP(Push(Pop())); break; - } - case Opcode::F64ConvertSI64: { - VALUE_TYPE_I64 value = POP_I64(); - PUSH_F64(BITCAST_FROM_F64( - static_cast(BITCAST_I64_TO_SIGNED(value)))); + case Opcode::F64ConvertSI64: + CHECK_TRAP(Push(Pop())); break; - } - case Opcode::F64ConvertUI64: { - VALUE_TYPE_I64 value = POP_I64(); - PUSH_F64(BITCAST_FROM_F64(wabt_convert_uint64_to_double(value))); + case Opcode::F64ConvertUI64: + CHECK_TRAP( + Push(wabt_convert_uint64_to_double(Pop()))); break; - } - case Opcode::F64PromoteF32: { - VALUE_TYPE_F32 value = POP_F32(); - PUSH_F64(BITCAST_FROM_F64(static_cast(BITCAST_TO_F32(value)))); + case Opcode::F64PromoteF32: + CHECK_TRAP(Push(Pop())); break; - } - case Opcode::F64ReinterpretI64: { - VALUE_TYPE_I64 value = POP_I64(); - PUSH_F64(value); + case Opcode::F64ReinterpretI64: + CHECK_TRAP(PushRep(Pop())); break; - } - case Opcode::I32ReinterpretF32: { - VALUE_TYPE_F32 value = POP_F32(); - PUSH_I32(value); + case Opcode::I32ReinterpretF32: + CHECK_TRAP(Push(PopRep())); break; - } - case Opcode::I64ReinterpretF64: { - VALUE_TYPE_F64 value = POP_F64(); - PUSH_I64(value); + case Opcode::I64ReinterpretF64: + CHECK_TRAP(Push(PopRep())); break; - } case Opcode::I32Rotr: - BINOP_ROT(I32, RIGHT); + CHECK_TRAP(Binop(IntRotr)); break; case Opcode::I32Rotl: - BINOP_ROT(I32, LEFT); + CHECK_TRAP(Binop(IntRotl)); break; case Opcode::I64Rotr: - BINOP_ROT(I64, RIGHT); + CHECK_TRAP(Binop(IntRotr)); break; case Opcode::I64Rotl: - BINOP_ROT(I64, LEFT); + CHECK_TRAP(Binop(IntRotl)); break; - case Opcode::I64Eqz: { - VALUE_TYPE_I64 value = POP_I64(); - PUSH_I64(value == 0); + case Opcode::I64Eqz: + CHECK_TRAP(Unop(IntEqz)); break; - } case Opcode::Alloca: { Value* old_value_stack_top = value_stack_top_; @@ -1756,19 +1995,19 @@ Result Thread::Run(int num_instructions, IstreamOffset* call_stack_return_top) { case Opcode::BrUnless: { IstreamOffset new_pc = read_u32(&pc); - if (!POP_I32()) + if (!Pop()) GOTO(new_pc); break; } case Opcode::Drop: - (void)POP(); + (void)Pop(); break; case Opcode::DropKeep: { uint32_t drop_count = read_u32(&pc); uint8_t keep_count = *pc++; - DROP_KEEP(drop_count, keep_count); + DropKeep(drop_count, keep_count); break; } @@ -1792,37 +2031,36 @@ Result Thread::Run(int num_instructions, IstreamOffset* call_stack_return_top) { } void Thread::Trace(Stream* stream) { - const uint8_t* istream = env_->istream_->data.data(); + const uint8_t* istream = GetIstream(); const uint8_t* pc = &istream[pc_]; size_t value_stack_depth = value_stack_top_ - value_stack_.data(); size_t call_stack_depth = call_stack_top_ - call_stack_.data(); stream->Writef("#%" PRIzd ". %4" PRIzd ": V:%-3" PRIzd "| ", call_stack_depth, - pc - env_->istream_->data.data(), value_stack_depth); + pc - istream, value_stack_depth); Opcode opcode = static_cast(*pc++); switch (opcode) { case Opcode::Select: - stream->Writef("%s %u, %" PRIu64 ", %" PRIu64 "\n", - get_opcode_name(opcode), PICK(3).i32, PICK(2).i64, - PICK(1).i64); + stream->Writef("%s %u, %" PRIu64 ", %" PRIu64 "\n", GetOpcodeName(opcode), + Pick(3).i32, Pick(2).i64, Pick(1).i64); break; case Opcode::Br: - stream->Writef("%s @%u\n", get_opcode_name(opcode), read_u32_at(pc)); + stream->Writef("%s @%u\n", GetOpcodeName(opcode), read_u32_at(pc)); break; case Opcode::BrIf: - stream->Writef("%s @%u, %u\n", get_opcode_name(opcode), read_u32_at(pc), - TOP().i32); + stream->Writef("%s @%u, %u\n", GetOpcodeName(opcode), read_u32_at(pc), + Top().i32); break; case Opcode::BrTable: { Index num_targets = read_u32_at(pc); IstreamOffset table_offset = read_u32_at(pc + 4); - VALUE_TYPE_I32 key = TOP().i32; + uint32_t key = Top().i32; stream->Writef("%s %u, $#%" PRIindex ", table:$%u\n", - get_opcode_name(opcode), key, num_targets, table_offset); + GetOpcodeName(opcode), key, num_targets, table_offset); break; } @@ -1830,58 +2068,58 @@ void Thread::Trace(Stream* stream) { case Opcode::Return: case Opcode::Unreachable: case Opcode::Drop: - stream->Writef("%s\n", get_opcode_name(opcode)); + stream->Writef("%s\n", GetOpcodeName(opcode)); break; case Opcode::CurrentMemory: { Index memory_index = read_u32(&pc); - stream->Writef("%s $%" PRIindex "\n", get_opcode_name(opcode), + stream->Writef("%s $%" PRIindex "\n", GetOpcodeName(opcode), memory_index); break; } case Opcode::I32Const: - stream->Writef("%s $%u\n", get_opcode_name(opcode), read_u32_at(pc)); + stream->Writef("%s $%u\n", GetOpcodeName(opcode), read_u32_at(pc)); break; case Opcode::I64Const: - stream->Writef("%s $%" PRIu64 "\n", get_opcode_name(opcode), + stream->Writef("%s $%" PRIu64 "\n", GetOpcodeName(opcode), read_u64_at(pc)); break; case Opcode::F32Const: - stream->Writef("%s $%g\n", get_opcode_name(opcode), - bitcast_u32_to_f32(read_u32_at(pc))); + stream->Writef("%s $%g\n", GetOpcodeName(opcode), + Bitcast(read_u32_at(pc))); break; case Opcode::F64Const: - stream->Writef("%s $%g\n", get_opcode_name(opcode), - bitcast_u64_to_f64(read_u64_at(pc))); + stream->Writef("%s $%g\n", GetOpcodeName(opcode), + Bitcast(read_u64_at(pc))); break; case Opcode::GetLocal: case Opcode::GetGlobal: - stream->Writef("%s $%u\n", get_opcode_name(opcode), read_u32_at(pc)); + stream->Writef("%s $%u\n", GetOpcodeName(opcode), read_u32_at(pc)); break; case Opcode::SetLocal: case Opcode::SetGlobal: case Opcode::TeeLocal: - stream->Writef("%s $%u, %u\n", get_opcode_name(opcode), read_u32_at(pc), - TOP().i32); + stream->Writef("%s $%u, %u\n", GetOpcodeName(opcode), read_u32_at(pc), + Top().i32); break; case Opcode::Call: - stream->Writef("%s @%u\n", get_opcode_name(opcode), read_u32_at(pc)); + stream->Writef("%s @%u\n", GetOpcodeName(opcode), read_u32_at(pc)); break; case Opcode::CallIndirect: - stream->Writef("%s $%u, %u\n", get_opcode_name(opcode), read_u32_at(pc), - TOP().i32); + stream->Writef("%s $%u, %u\n", GetOpcodeName(opcode), read_u32_at(pc), + Top().i32); break; case Opcode::CallHost: - stream->Writef("%s $%u\n", get_opcode_name(opcode), read_u32_at(pc)); + stream->Writef("%s $%u\n", GetOpcodeName(opcode), read_u32_at(pc)); break; case Opcode::I32Load8S: @@ -1899,8 +2137,8 @@ void Thread::Trace(Stream* stream) { case Opcode::F32Load: case Opcode::F64Load: { Index memory_index = read_u32(&pc); - stream->Writef("%s $%" PRIindex ":%u+$%u\n", get_opcode_name(opcode), - memory_index, TOP().i32, read_u32_at(pc)); + stream->Writef("%s $%" PRIindex ":%u+$%u\n", GetOpcodeName(opcode), + memory_index, Top().i32, read_u32_at(pc)); break; } @@ -1908,8 +2146,8 @@ void Thread::Trace(Stream* stream) { case Opcode::I32Store16: case Opcode::I32Store: { Index memory_index = read_u32(&pc); - stream->Writef("%s $%" PRIindex ":%u+$%u, %u\n", get_opcode_name(opcode), - memory_index, PICK(2).i32, read_u32_at(pc), PICK(1).i32); + stream->Writef("%s $%" PRIindex ":%u+$%u, %u\n", GetOpcodeName(opcode), + memory_index, Pick(2).i32, read_u32_at(pc), Pick(1).i32); break; } @@ -1919,31 +2157,31 @@ void Thread::Trace(Stream* stream) { case Opcode::I64Store: { Index memory_index = read_u32(&pc); stream->Writef("%s $%" PRIindex ":%u+$%u, %" PRIu64 "\n", - get_opcode_name(opcode), memory_index, PICK(2).i32, - read_u32_at(pc), PICK(1).i64); + GetOpcodeName(opcode), memory_index, Pick(2).i32, + read_u32_at(pc), Pick(1).i64); break; } case Opcode::F32Store: { Index memory_index = read_u32(&pc); - stream->Writef("%s $%" PRIindex ":%u+$%u, %g\n", get_opcode_name(opcode), - memory_index, PICK(2).i32, read_u32_at(pc), - bitcast_u32_to_f32(PICK(1).f32_bits)); + stream->Writef("%s $%" PRIindex ":%u+$%u, %g\n", GetOpcodeName(opcode), + memory_index, Pick(2).i32, read_u32_at(pc), + Bitcast(Pick(1).f32_bits)); break; } case Opcode::F64Store: { Index memory_index = read_u32(&pc); - stream->Writef("%s $%" PRIindex ":%u+$%u, %g\n", get_opcode_name(opcode), - memory_index, PICK(2).i32, read_u32_at(pc), - bitcast_u64_to_f64(PICK(1).f64_bits)); + stream->Writef("%s $%" PRIindex ":%u+$%u, %g\n", GetOpcodeName(opcode), + memory_index, Pick(2).i32, read_u32_at(pc), + Bitcast(Pick(1).f64_bits)); break; } case Opcode::GrowMemory: { Index memory_index = read_u32(&pc); - stream->Writef("%s $%" PRIindex ":%u\n", get_opcode_name(opcode), - memory_index, TOP().i32); + stream->Writef("%s $%" PRIindex ":%u\n", GetOpcodeName(opcode), + memory_index, Top().i32); break; } @@ -1972,15 +2210,15 @@ void Thread::Trace(Stream* stream) { case Opcode::I32GeU: case Opcode::I32Rotr: case Opcode::I32Rotl: - stream->Writef("%s %u, %u\n", get_opcode_name(opcode), PICK(2).i32, - PICK(1).i32); + stream->Writef("%s %u, %u\n", GetOpcodeName(opcode), Pick(2).i32, + Pick(1).i32); break; case Opcode::I32Clz: case Opcode::I32Ctz: case Opcode::I32Popcnt: case Opcode::I32Eqz: - stream->Writef("%s %u\n", get_opcode_name(opcode), TOP().i32); + stream->Writef("%s %u\n", GetOpcodeName(opcode), Top().i32); break; case Opcode::I64Add: @@ -2008,15 +2246,15 @@ void Thread::Trace(Stream* stream) { case Opcode::I64GeU: case Opcode::I64Rotr: case Opcode::I64Rotl: - stream->Writef("%s %" PRIu64 ", %" PRIu64 "\n", get_opcode_name(opcode), - PICK(2).i64, PICK(1).i64); + stream->Writef("%s %" PRIu64 ", %" PRIu64 "\n", GetOpcodeName(opcode), + Pick(2).i64, Pick(1).i64); break; case Opcode::I64Clz: case Opcode::I64Ctz: case Opcode::I64Popcnt: case Opcode::I64Eqz: - stream->Writef("%s %" PRIu64 "\n", get_opcode_name(opcode), TOP().i64); + stream->Writef("%s %" PRIu64 "\n", GetOpcodeName(opcode), Top().i64); break; case Opcode::F32Add: @@ -2032,9 +2270,8 @@ void Thread::Trace(Stream* stream) { case Opcode::F32Le: case Opcode::F32Gt: case Opcode::F32Ge: - stream->Writef("%s %g, %g\n", get_opcode_name(opcode), - bitcast_u32_to_f32(PICK(2).i32), - bitcast_u32_to_f32(PICK(1).i32)); + stream->Writef("%s %g, %g\n", GetOpcodeName(opcode), + Bitcast(Pick(2).i32), Bitcast(Pick(1).i32)); break; case Opcode::F32Abs: @@ -2044,8 +2281,8 @@ void Thread::Trace(Stream* stream) { case Opcode::F32Trunc: case Opcode::F32Nearest: case Opcode::F32Sqrt: - stream->Writef("%s %g\n", get_opcode_name(opcode), - bitcast_u32_to_f32(TOP().i32)); + stream->Writef("%s %g\n", GetOpcodeName(opcode), + Bitcast(Top().i32)); break; case Opcode::F64Add: @@ -2061,9 +2298,9 @@ void Thread::Trace(Stream* stream) { case Opcode::F64Le: case Opcode::F64Gt: case Opcode::F64Ge: - stream->Writef("%s %g, %g\n", get_opcode_name(opcode), - bitcast_u64_to_f64(PICK(2).i64), - bitcast_u64_to_f64(PICK(1).i64)); + stream->Writef("%s %g, %g\n", GetOpcodeName(opcode), + Bitcast(Pick(2).i64), + Bitcast(Pick(1).i64)); break; case Opcode::F64Abs: @@ -2073,8 +2310,8 @@ void Thread::Trace(Stream* stream) { case Opcode::F64Trunc: case Opcode::F64Nearest: case Opcode::F64Sqrt: - stream->Writef("%s %g\n", get_opcode_name(opcode), - bitcast_u64_to_f64(TOP().i64)); + stream->Writef("%s %g\n", GetOpcodeName(opcode), + Bitcast(Top().i64)); break; case Opcode::I32TruncSF32: @@ -2083,8 +2320,12 @@ void Thread::Trace(Stream* stream) { case Opcode::I64TruncUF32: case Opcode::F64PromoteF32: case Opcode::I32ReinterpretF32: - stream->Writef("%s %g\n", get_opcode_name(opcode), - bitcast_u32_to_f32(TOP().i32)); + case Opcode::I32TruncSSatF32: + case Opcode::I32TruncUSatF32: + case Opcode::I64TruncSSatF32: + case Opcode::I64TruncUSatF32: + stream->Writef("%s %g\n", GetOpcodeName(opcode), + Bitcast(Top().i32)); break; case Opcode::I32TruncSF64: @@ -2093,8 +2334,12 @@ void Thread::Trace(Stream* stream) { case Opcode::I64TruncUF64: case Opcode::F32DemoteF64: case Opcode::I64ReinterpretF64: - stream->Writef("%s %g\n", get_opcode_name(opcode), - bitcast_u64_to_f64(TOP().i64)); + case Opcode::I32TruncSSatF64: + case Opcode::I32TruncUSatF64: + case Opcode::I64TruncSSatF64: + case Opcode::I64TruncUSatF64: + stream->Writef("%s %g\n", GetOpcodeName(opcode), + Bitcast(Top().i64)); break; case Opcode::I32WrapI64: @@ -2103,7 +2348,7 @@ void Thread::Trace(Stream* stream) { case Opcode::F64ConvertSI64: case Opcode::F64ConvertUI64: case Opcode::F64ReinterpretI64: - stream->Writef("%s %" PRIu64 "\n", get_opcode_name(opcode), TOP().i64); + stream->Writef("%s %" PRIu64 "\n", GetOpcodeName(opcode), Top().i64); break; case Opcode::I64ExtendSI32: @@ -2113,20 +2358,20 @@ void Thread::Trace(Stream* stream) { case Opcode::F32ReinterpretI32: case Opcode::F64ConvertSI32: case Opcode::F64ConvertUI32: - stream->Writef("%s %u\n", get_opcode_name(opcode), TOP().i32); + stream->Writef("%s %u\n", GetOpcodeName(opcode), Top().i32); break; case Opcode::Alloca: - stream->Writef("%s $%u\n", get_opcode_name(opcode), read_u32_at(pc)); + stream->Writef("%s $%u\n", GetOpcodeName(opcode), read_u32_at(pc)); break; case Opcode::BrUnless: - stream->Writef("%s @%u, %u\n", get_opcode_name(opcode), read_u32_at(pc), - TOP().i32); + stream->Writef("%s @%u, %u\n", GetOpcodeName(opcode), read_u32_at(pc), + Top().i32); break; case Opcode::DropKeep: - stream->Writef("%s $%u $%u\n", get_opcode_name(opcode), read_u32_at(pc), + stream->Writef("%s $%u $%u\n", GetOpcodeName(opcode), read_u32_at(pc), *(pc + 4)); break; @@ -2158,15 +2403,15 @@ void Environment::Disassemble(Stream* stream, Opcode opcode = static_cast(*pc++); switch (opcode) { case Opcode::Select: - stream->Writef("%s %%[-3], %%[-2], %%[-1]\n", get_opcode_name(opcode)); + stream->Writef("%s %%[-3], %%[-2], %%[-1]\n", GetOpcodeName(opcode)); break; case Opcode::Br: - stream->Writef("%s @%u\n", get_opcode_name(opcode), read_u32(&pc)); + stream->Writef("%s @%u\n", GetOpcodeName(opcode), read_u32(&pc)); break; case Opcode::BrIf: - stream->Writef("%s @%u, %%[-1]\n", get_opcode_name(opcode), + stream->Writef("%s @%u, %%[-1]\n", GetOpcodeName(opcode), read_u32(&pc)); break; @@ -2174,7 +2419,7 @@ void Environment::Disassemble(Stream* stream, Index num_targets = read_u32(&pc); IstreamOffset table_offset = read_u32(&pc); stream->Writef("%s %%[-1], $#%" PRIindex ", table:$%u\n", - get_opcode_name(opcode), num_targets, table_offset); + GetOpcodeName(opcode), num_targets, table_offset); break; } @@ -2182,60 +2427,60 @@ void Environment::Disassemble(Stream* stream, case Opcode::Return: case Opcode::Unreachable: case Opcode::Drop: - stream->Writef("%s\n", get_opcode_name(opcode)); + stream->Writef("%s\n", GetOpcodeName(opcode)); break; case Opcode::CurrentMemory: { Index memory_index = read_u32(&pc); - stream->Writef("%s $%" PRIindex "\n", get_opcode_name(opcode), + stream->Writef("%s $%" PRIindex "\n", GetOpcodeName(opcode), memory_index); break; } case Opcode::I32Const: - stream->Writef("%s $%u\n", get_opcode_name(opcode), read_u32(&pc)); + stream->Writef("%s $%u\n", GetOpcodeName(opcode), read_u32(&pc)); break; case Opcode::I64Const: - stream->Writef("%s $%" PRIu64 "\n", get_opcode_name(opcode), + stream->Writef("%s $%" PRIu64 "\n", GetOpcodeName(opcode), read_u64(&pc)); break; case Opcode::F32Const: - stream->Writef("%s $%g\n", get_opcode_name(opcode), - bitcast_u32_to_f32(read_u32(&pc))); + stream->Writef("%s $%g\n", GetOpcodeName(opcode), + Bitcast(read_u32(&pc))); break; case Opcode::F64Const: - stream->Writef("%s $%g\n", get_opcode_name(opcode), - bitcast_u64_to_f64(read_u64(&pc))); + stream->Writef("%s $%g\n", GetOpcodeName(opcode), + Bitcast(read_u64(&pc))); break; case Opcode::GetLocal: case Opcode::GetGlobal: - stream->Writef("%s $%u\n", get_opcode_name(opcode), read_u32(&pc)); + stream->Writef("%s $%u\n", GetOpcodeName(opcode), read_u32(&pc)); break; case Opcode::SetLocal: case Opcode::SetGlobal: case Opcode::TeeLocal: - stream->Writef("%s $%u, %%[-1]\n", get_opcode_name(opcode), + stream->Writef("%s $%u, %%[-1]\n", GetOpcodeName(opcode), read_u32(&pc)); break; case Opcode::Call: - stream->Writef("%s @%u\n", get_opcode_name(opcode), read_u32(&pc)); + stream->Writef("%s @%u\n", GetOpcodeName(opcode), read_u32(&pc)); break; case Opcode::CallIndirect: { Index table_index = read_u32(&pc); - stream->Writef("%s $%" PRIindex ":%u, %%[-1]\n", - get_opcode_name(opcode), table_index, read_u32(&pc)); + stream->Writef("%s $%" PRIindex ":%u, %%[-1]\n", GetOpcodeName(opcode), + table_index, read_u32(&pc)); break; } case Opcode::CallHost: - stream->Writef("%s $%u\n", get_opcode_name(opcode), read_u32(&pc)); + stream->Writef("%s $%u\n", GetOpcodeName(opcode), read_u32(&pc)); break; case Opcode::I32Load8S: @@ -2253,8 +2498,8 @@ void Environment::Disassemble(Stream* stream, case Opcode::F32Load: case Opcode::F64Load: { Index memory_index = read_u32(&pc); - stream->Writef("%s $%" PRIindex ":%%[-1]+$%u\n", - get_opcode_name(opcode), memory_index, read_u32(&pc)); + stream->Writef("%s $%" PRIindex ":%%[-1]+$%u\n", GetOpcodeName(opcode), + memory_index, read_u32(&pc)); break; } @@ -2269,7 +2514,7 @@ void Environment::Disassemble(Stream* stream, case Opcode::F64Store: { Index memory_index = read_u32(&pc); stream->Writef("%s %%[-2]+$%" PRIindex ", $%u:%%[-1]\n", - get_opcode_name(opcode), memory_index, read_u32(&pc)); + GetOpcodeName(opcode), memory_index, read_u32(&pc)); break; } @@ -2349,7 +2594,7 @@ void Environment::Disassemble(Stream* stream, case Opcode::F64Le: case Opcode::F64Gt: case Opcode::F64Ge: - stream->Writef("%s %%[-2], %%[-1]\n", get_opcode_name(opcode)); + stream->Writef("%s %%[-2], %%[-1]\n", GetOpcodeName(opcode)); break; case Opcode::I32Clz: @@ -2399,35 +2644,43 @@ void Environment::Disassemble(Stream* stream, case Opcode::F32ReinterpretI32: case Opcode::F64ConvertSI32: case Opcode::F64ConvertUI32: - stream->Writef("%s %%[-1]\n", get_opcode_name(opcode)); + case Opcode::I32TruncSSatF32: + case Opcode::I32TruncUSatF32: + case Opcode::I64TruncSSatF32: + case Opcode::I64TruncUSatF32: + case Opcode::I32TruncSSatF64: + case Opcode::I32TruncUSatF64: + case Opcode::I64TruncSSatF64: + case Opcode::I64TruncUSatF64: + stream->Writef("%s %%[-1]\n", GetOpcodeName(opcode)); break; case Opcode::GrowMemory: { Index memory_index = read_u32(&pc); - stream->Writef("%s $%" PRIindex ":%%[-1]\n", get_opcode_name(opcode), + stream->Writef("%s $%" PRIindex ":%%[-1]\n", GetOpcodeName(opcode), memory_index); break; } case Opcode::Alloca: - stream->Writef("%s $%u\n", get_opcode_name(opcode), read_u32(&pc)); + stream->Writef("%s $%u\n", GetOpcodeName(opcode), read_u32(&pc)); break; case Opcode::BrUnless: - stream->Writef("%s @%u, %%[-1]\n", get_opcode_name(opcode), + stream->Writef("%s @%u, %%[-1]\n", GetOpcodeName(opcode), read_u32(&pc)); break; case Opcode::DropKeep: { uint32_t drop = read_u32(&pc); uint8_t keep = *pc++; - stream->Writef("%s $%u $%u\n", get_opcode_name(opcode), drop, keep); + stream->Writef("%s $%u $%u\n", GetOpcodeName(opcode), drop, keep); break; } case Opcode::Data: { uint32_t num_bytes = read_u32(&pc); - stream->Writef("%s $%u\n", get_opcode_name(opcode), num_bytes); + stream->Writef("%s $%u\n", GetOpcodeName(opcode), num_bytes); /* for now, the only reason this is emitted is for br_table, so display * it as a list of table entries */ if (num_bytes % WABT_TABLE_ENTRY_SIZE == 0) { diff --git a/lib/wabt/src/interpreter.h b/lib/wabt/src/interpreter.h index cd5c6b5b0b2..fd1ac5e788b 100644 --- a/lib/wabt/src/interpreter.h +++ b/lib/wabt/src/interpreter.h @@ -93,17 +93,14 @@ static const IstreamOffset kInvalidIstreamOffset = ~0; #define WABT_TABLE_ENTRY_DROP_OFFSET sizeof(uint32_t) #define WABT_TABLE_ENTRY_KEEP_OFFSET (sizeof(IstreamOffset) + sizeof(uint32_t)) +// NOTE: These enumeration values do not match the standard binary encoding. enum class Opcode { -/* push space on the value stack for N entries */ -#define WABT_OPCODE(rtype, type1, type2, mem_size, code, Name, text) \ - Name = code, +#define WABT_OPCODE(rtype, type1, type2, mem_size, prefix, code, Name, text) \ + Name, #include "interpreter-opcode.def" #undef WABT_OPCODE - - First = static_cast(::wabt::Opcode::First), - Last = DropKeep, + Invalid, }; -static const int kOpcodeCount = WABT_ENUM_COUNT(Opcode); struct FuncSignature { FuncSignature() = default; @@ -125,7 +122,7 @@ struct Table { }; struct Memory { - Memory() { WABT_ZERO_MEMORY(page_limits); } + Memory() = default; explicit Memory(const Limits& limits) : page_limits(limits), data(limits.initial * WABT_PAGE_SIZE) {} @@ -133,11 +130,26 @@ struct Memory { std::vector data; }; +// ValueTypeRep converts from one type to its representation on the +// stack. For example, float -> uint32_t. See Value below. +template +struct ValueTypeRepT; + +template <> struct ValueTypeRepT { typedef uint32_t type; }; +template <> struct ValueTypeRepT { typedef uint32_t type; }; +template <> struct ValueTypeRepT { typedef uint64_t type; }; +template <> struct ValueTypeRepT { typedef uint64_t type; }; +template <> struct ValueTypeRepT { typedef uint32_t type; }; +template <> struct ValueTypeRepT { typedef uint64_t type; }; + +template +using ValueTypeRep = typename ValueTypeRepT::type; + union Value { uint32_t i32; uint64_t i64; - uint32_t f32_bits; - uint64_t f64_bits; + ValueTypeRep f32_bits; + ValueTypeRep f64_bits; }; struct TypedValue { @@ -163,10 +175,10 @@ struct Import { Import(); Import(Import&&); Import& operator=(Import&&); - ~Import(); + ~Import() = default; - StringSlice module_name; - StringSlice field_name; + std::string module_name; + std::string field_name; ExternalKind kind; union { struct { @@ -219,15 +231,13 @@ struct DefinedFunc : Func { }; struct HostFunc : Func { - HostFunc(const StringSlice& module_name, - const StringSlice& field_name, - Index sig_index) + HostFunc(string_view module_name, string_view field_name, Index sig_index) : Func(sig_index, true), - module_name(module_name), - field_name(field_name) {} + module_name(module_name.to_string()), + field_name(field_name.to_string()) {} - StringSlice module_name; - StringSlice field_name; + std::string module_name; + std::string field_name; HostFuncCallback callback; void* user_data; }; @@ -243,13 +253,10 @@ HostFunc* Func::as_host() { } struct Export { - Export(const StringSlice& name, ExternalKind kind, Index index) - : name(name), kind(kind), index(index) {} - Export(Export&&); - Export& operator=(Export&&); - ~Export(); + Export(string_view name, ExternalKind kind, Index index) + : name(name.to_string()), kind(kind), index(index) {} - StringSlice name; + std::string name; ExternalKind kind; Index index; }; @@ -271,15 +278,15 @@ class HostImportDelegate { struct Module { WABT_DISALLOW_COPY_AND_ASSIGN(Module); explicit Module(bool is_host); - Module(const StringSlice& name, bool is_host); - virtual ~Module(); + Module(string_view name, bool is_host); + virtual ~Module() = default; inline struct DefinedModule* as_defined(); inline struct HostModule* as_host(); - Export* GetExport(StringSlice name); + Export* GetExport(string_view name); - StringSlice name; + std::string name; std::vector exports; BindingHash export_bindings; Index memory_index; /* kInvalidIndex if not defined */ @@ -297,7 +304,7 @@ struct DefinedModule : Module { }; struct HostModule : Module { - explicit HostModule(const StringSlice& name); + explicit HostModule(string_view name); std::unique_ptr import_delegate; }; @@ -343,7 +350,7 @@ class Environment { Index GetLastModuleIndex() const { return modules_.empty() ? kInvalidIndex : modules_.size() - 1; } - Index FindModuleIndex(StringSlice name) const; + Index FindModuleIndex(string_view name) const; FuncSignature* GetFuncSignature(Index index) { return &sigs_[index]; } Func* GetFunc(Index index) { @@ -370,56 +377,56 @@ class Environment { Module* GetLastModule() { return modules_.empty() ? nullptr : modules_.back().get(); } - Module* FindModule(StringSlice name); - Module* FindRegisteredModule(StringSlice name); + Module* FindModule(string_view name); + Module* FindRegisteredModule(string_view name); template FuncSignature* EmplaceBackFuncSignature(Args&&... args) { - sigs_.emplace_back(args...); + sigs_.emplace_back(std::forward(args)...); return &sigs_.back(); } template Func* EmplaceBackFunc(Args&&... args) { - funcs_.emplace_back(args...); + funcs_.emplace_back(std::forward(args)...); return funcs_.back().get(); } template Global* EmplaceBackGlobal(Args&&... args) { - globals_.emplace_back(args...); + globals_.emplace_back(std::forward(args)...); return &globals_.back(); } template Table* EmplaceBackTable(Args&&... args) { - tables_.emplace_back(args...); + tables_.emplace_back(std::forward(args)...); return &tables_.back(); } template Memory* EmplaceBackMemory(Args&&... args) { - memories_.emplace_back(args...); + memories_.emplace_back(std::forward(args)...); return &memories_.back(); } template Module* EmplaceBackModule(Args&&... args) { - modules_.emplace_back(args...); + modules_.emplace_back(std::forward(args)...); return modules_.back().get(); } template void EmplaceModuleBinding(Args&&... args) { - module_bindings_.emplace(args...); + module_bindings_.emplace(std::forward(args)...); } template void EmplaceRegisteredModuleBinding(Args&&... args) { - registered_module_bindings_.emplace(args...); + registered_module_bindings_.emplace(std::forward(args)...); } - HostModule* AppendHostModule(StringSlice name); + HostModule* AppendHostModule(string_view name); bool FuncSignaturesAreEqual(Index sig_index_0, Index sig_index_1) const; @@ -472,13 +479,63 @@ class Thread { std::vector* out_results); private: - Result PushValue(Value); + const uint8_t* GetIstream() const { return env_->istream_->data.data(); } + Result PushArgs(const FuncSignature*, const std::vector& args); void CopyResults(const FuncSignature*, std::vector* out_results); Result Run(int num_instructions, IstreamOffset* call_stack_return_top); void Trace(Stream*); + Memory* ReadMemory(const uint8_t** pc); + + Value& Top(); + Value& Pick(Index depth); + + Result Push(Value) WABT_WARN_UNUSED; + Value Pop(); + + // Push/Pop values with conversions, e.g. Push will convert to the + // ValueTypeRep (uint32_t) and push that. Similarly, Pop will pop the + // value and convert to float. + template + Result Push(T) WABT_WARN_UNUSED; + template + T Pop(); + + // Push/Pop values without conversions, e.g. Push will take a uint32_t + // argument which is the integer representation of that float value. + // Similarly, PopRep will not convert the value to a float. + template + Result PushRep(ValueTypeRep) WABT_WARN_UNUSED; + template + ValueTypeRep PopRep(); + + void DropKeep(uint32_t drop_count, uint8_t keep_count); + + Result PushCall(const uint8_t* pc) WABT_WARN_UNUSED; + IstreamOffset PopCall(); + + template + Result Load(const uint8_t** pc) WABT_WARN_UNUSED; + template + Result Store(const uint8_t** pc) WABT_WARN_UNUSED; + + template using UnopFunc = R(T); + template using UnopTrapFunc = Result(T, R*); + template using BinopFunc = R(T, T); + template using BinopTrapFunc = Result(T, T, R*); + + template + Result Unop(UnopFunc func) WABT_WARN_UNUSED; + template + Result UnopTrap(UnopTrapFunc func) WABT_WARN_UNUSED; + + template + Result Binop(BinopFunc func) WABT_WARN_UNUSED; + template + Result BinopTrap(BinopTrapFunc func) WABT_WARN_UNUSED; + Result RunDefinedFunction(IstreamOffset); Result TraceDefinedFunction(IstreamOffset, Stream*); @@ -494,10 +551,10 @@ class Thread { IstreamOffset pc_; }; -bool is_canonical_nan_f32(uint32_t f32_bits); -bool is_canonical_nan_f64(uint64_t f64_bits); -bool is_arithmetic_nan_f32(uint32_t f32_bits); -bool is_arithmetic_nan_f64(uint64_t f64_bits); +bool IsCanonicalNan(uint32_t f32_bits); +bool IsCanonicalNan(uint64_t f64_bits); +bool IsArithmeticNan(uint32_t f32_bits); +bool IsArithmeticNan(uint64_t f64_bits); } // namespace interpreter } // namespace wabt diff --git a/lib/wabt/src/intrusive-list.h b/lib/wabt/src/intrusive-list.h new file mode 100644 index 00000000000..403442f43b8 --- /dev/null +++ b/lib/wabt/src/intrusive-list.h @@ -0,0 +1,625 @@ +/* + * Copyright 2017 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 WABT_INTRUSIVE_LIST_H_ +#define WABT_INTRUSIVE_LIST_H_ + +#include +#include + +// This uses a similar interface as std::list, but is missing the following +// features: +// +// * Add "extract_" functions that remove an element from the list and return +// it. +// * Only supports move-only operations +// * No allocator support +// * No initializer lists +// * Asserts instead of exceptions +// * Some functions are not implemented (merge, remove, remove_if, reverse, +// unique, sort, non-member comparison operators) + +namespace wabt { + +template +class intrusive_list; + +template +class intrusive_list_base { + private: + friend class intrusive_list; + + mutable T* next_ = nullptr; + mutable T* prev_ = nullptr; +}; + +template +class intrusive_list { + public: + // types: + typedef T value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + class iterator; + class const_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + // construct/copy/destroy: + intrusive_list(); + explicit intrusive_list(T* node); + explicit intrusive_list(T&& node); + intrusive_list(const intrusive_list&) = delete; + intrusive_list(intrusive_list&&); + ~intrusive_list(); + intrusive_list& operator=(const intrusive_list& other) = delete; + intrusive_list& operator=(intrusive_list&& other); + + // iterators: + iterator begin() noexcept; + const_iterator begin() const noexcept; + iterator end() noexcept; + const_iterator end() const noexcept; + + reverse_iterator rbegin() noexcept; + const_reverse_iterator rbegin() const noexcept; + reverse_iterator rend() noexcept; + const_reverse_iterator rend() const noexcept; + + const_iterator cbegin() const noexcept; + const_iterator cend() const noexcept; + const_reverse_iterator crbegin() const noexcept; + const_reverse_iterator crend() const noexcept; + + // capacity: + size_type size() const noexcept; + bool empty() const noexcept; + + // element access: + reference front(); + const_reference front() const; + reference back(); + const_reference back() const; + + // modifiers: + template + void emplace_front(Args&&... args); + template + void emplace_back(Args&&... args); + void push_front(T* node); + void push_front(T&& node); + void push_back(T* node); + void push_back(T&& node); + void pop_front(); + void pop_back(); + T* extract_front(); + T* extract_back(); + + template + iterator emplace(iterator pos, Args&&... args); + iterator insert(iterator pos, T* node); + iterator insert(iterator pos, T&& node); + T* extract(iterator it); + + iterator erase(iterator pos); + iterator erase(iterator first, iterator last); + void swap(intrusive_list&); + void clear() noexcept; + + void splice(iterator pos, intrusive_list& node); + void splice(iterator pos, intrusive_list&& node); + void splice(iterator pos, intrusive_list& node, iterator it); + void splice(iterator pos, + intrusive_list& node, + iterator first, + iterator last); + + private: + T* first_ = nullptr; + T* last_ = nullptr; + size_t size_ = 0; +}; + +/// iterator +template +class intrusive_list::iterator { + public: + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + typedef T value_type; + typedef T* pointer; + typedef T& reference; + + iterator(const intrusive_list& list, T* node) + : list_(&list), node_(node) {} + + reference operator*() const { + assert(node_); + return *node_; + } + + pointer operator->() const { + assert(node_); + return node_; + } + + iterator& operator++() { + assert(node_); + node_ = node_->next_; + return *this; + } + + iterator operator++(int) { + iterator tmp = *this; + operator++(); + return tmp; + } + + iterator& operator--() { + node_ = node_ ? node_->prev_ : list_->last_; + return *this; + } + + iterator operator--(int) { + iterator tmp = *this; + operator--(); + return tmp; + } + + bool operator==(iterator rhs) const { + assert(list_ == rhs.list_); + return node_ == rhs.node_; + } + + bool operator!=(iterator rhs) const { + assert(list_ == rhs.list_); + return node_ != rhs.node_; + } + + private: + friend class const_iterator; + + const intrusive_list* list_; + T* node_; +}; + +/// const_iterator +template +class intrusive_list::const_iterator { + public: + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + typedef T value_type; + typedef const T* pointer; + typedef const T& reference; + + const_iterator(const intrusive_list& list, T* node) + : list_(&list), node_(node) {} + + const_iterator(const iterator& other) + : list_(other.list_), node_(other.node_) {} + + reference operator*() const { + assert(node_); + return *node_; + } + + pointer operator->() const { + assert(node_); + return node_; + } + + const_iterator& operator++() { + assert(node_); + node_ = node_->next_; + return *this; + } + + const_iterator operator++(int) { + const_iterator tmp = *this; + operator++(); + return tmp; + } + + const_iterator& operator--() { + node_ = node_ ? node_->prev_ : list_->last_; + return *this; + } + + const_iterator operator--(int) { + const_iterator tmp = *this; + operator--(); + return tmp; + } + + bool operator==(const_iterator rhs) const { + assert(list_ == rhs.list_); + return node_ == rhs.node_; + } + + bool operator!=(const_iterator rhs) const { + assert(list_ == rhs.list_); + return node_ != rhs.node_; + } + + private: + const intrusive_list* list_; + T* node_; +}; + +template +inline intrusive_list::intrusive_list() {} + +template +inline intrusive_list::intrusive_list(T* node) { + push_back(node); +} + +template +inline intrusive_list::intrusive_list(T&& node) { + push_back(std::move(node)); +} + +template +inline intrusive_list::intrusive_list(intrusive_list&& other) + : first_(other.first_), last_(other.last_), size_(other.size_) { + other.first_ = other.last_ = nullptr; + other.size_ = 0; +} + +template +inline intrusive_list::~intrusive_list() { + clear(); +} + +template +inline intrusive_list& intrusive_list::operator=( + intrusive_list&& other) { + clear(); + first_ = other.first_; + last_ = other.last_; + size_ = other.size_; + other.first_ = other.last_ = nullptr; + other.size_ = 0; + return *this; +} + +template +inline typename intrusive_list::iterator +intrusive_list::begin() noexcept { + return iterator(*this, first_); +} + +template +inline typename intrusive_list::const_iterator intrusive_list::begin() + const noexcept { + return const_iterator(*this, first_); +} + +template +inline typename intrusive_list::iterator intrusive_list::end() noexcept { + return iterator(*this, nullptr); +} + +template +inline typename intrusive_list::const_iterator intrusive_list::end() const + noexcept { + return const_iterator(*this, nullptr); +} + +template +inline typename intrusive_list::reverse_iterator +intrusive_list::rbegin() noexcept { + return reverse_iterator(iterator(*this, nullptr)); +} + +template +inline typename intrusive_list::const_reverse_iterator +intrusive_list::rbegin() const noexcept { + return const_reverse_iterator(const_iterator(*this, nullptr)); +} + +template +inline typename intrusive_list::reverse_iterator +intrusive_list::rend() noexcept { + return reverse_iterator(iterator(*this, first_)); +} + +template +inline typename intrusive_list::const_reverse_iterator +intrusive_list::rend() const noexcept { + return const_reverse_iterator(const_iterator(*this, first_)); +} + +template +inline typename intrusive_list::const_iterator intrusive_list::cbegin() + const noexcept { + return const_iterator(*this, first_); +} + +template +inline typename intrusive_list::const_iterator intrusive_list::cend() + const noexcept { + return const_iterator(*this, nullptr); +} + +template +inline typename intrusive_list::const_reverse_iterator +intrusive_list::crbegin() const noexcept { + return const_reverse_iterator(const_iterator(*this, nullptr)); +} + +template +inline typename intrusive_list::const_reverse_iterator +intrusive_list::crend() const noexcept { + return const_reverse_iterator(const_iterator(*this, first_)); +} + +template +inline typename intrusive_list::size_type intrusive_list::size() const + noexcept { + return size_; +} + +template +inline bool intrusive_list::empty() const noexcept { + return size_ == 0; +} + +template +inline typename intrusive_list::reference intrusive_list::front() { + assert(!empty()); + return *first_; +} + +template +inline typename intrusive_list::const_reference intrusive_list::front() + const { + assert(!empty()); + return *first_; +} + +template +inline typename intrusive_list::reference intrusive_list::back() { + assert(!empty()); + return *last_; +} + +template +inline typename intrusive_list::const_reference intrusive_list::back() + const { + assert(!empty()); + return *last_; +} + +template +template +inline void intrusive_list::emplace_front(Args&&... args) { + push_front(new T(std::forward(args)...)); +} + +template +template +inline void intrusive_list::emplace_back(Args&&... args) { + push_back(new T(std::forward(args)...)); +} + +template +inline void intrusive_list::push_front(T* node) { + assert(node->prev_ == nullptr && + node->next_ == nullptr); + + if (first_) { + node->next_ = first_; + first_->prev_ = node; + } else { + last_ = node; + } + first_ = node; + size_++; +} + +template +inline void intrusive_list::push_front(T&& node) { + push_front(new T(std::move(node))); +} + +template +inline void intrusive_list::push_back(T* node) { + assert(node->prev_ == nullptr && + node->next_ == nullptr); + + if (last_) { + node->prev_ = last_; + last_->next_ = node; + } else { + first_ = node; + } + last_ = node; + size_++; +} + +template +inline void intrusive_list::push_back(T&& node) { + push_back(new T(std::move(node))); +} + +template +inline void intrusive_list::pop_front() { + delete extract_front(); +} + +template +inline void intrusive_list::pop_back() { + delete extract_back(); +} + +template +inline T* intrusive_list::extract_front() { + assert(!empty()); + T* node = first_; + if (first_ == last_) { + first_ = last_ = nullptr; + } else { + first_ = first_->next_; + first_->prev_ = nullptr; + } + node->next_ = node->prev_ = nullptr; + size_--; + return node; +} + +template +inline T* intrusive_list::extract_back() { + assert(!empty()); + T* node = last_; + if (first_ == last_) { + first_ = last_ = nullptr; + } else { + last_ = last_->prev_; + last_->next_ = nullptr; + } + node->next_ = node->prev_ = nullptr; + size_--; + return node; +} + +template +template +inline typename intrusive_list::iterator intrusive_list::emplace( + iterator pos, + Args&&... args) { + return insert(pos, new T(std::forward(args)...)); +} + +template +inline typename intrusive_list::iterator intrusive_list::insert( + iterator pos, + T* node) { + assert(node->prev_ == nullptr && + node->next_ == nullptr); + + if (pos == end()) { + push_back(node); + } else { + node->prev_ = pos->prev_; + node->next_ = &*pos; + if (pos->prev_) + pos->prev_->next_ = node; + else + first_ = node; + pos->prev_ = node; + size_++; + } + return iterator(*this, node); +} + +template +inline typename intrusive_list::iterator intrusive_list::insert( + iterator pos, + T&& node) { + return insert(pos, new T(std::move(node))); +} + +template +inline T* intrusive_list::extract(iterator pos) { + assert(!empty()); + assert(pos != end()); + T* node = &*pos; + if (first_ == last_) { + first_ = last_ = nullptr; + } else { + if (node->prev_) + node->prev_->next_ = node->next_; + else + first_ = node->next_; + + if (node->next_) + node->next_->prev_ = node->prev_; + else + last_ = node->prev_; + } + node->next_ = node->prev_ = nullptr; + size_--; + return node; +} + +template +inline typename intrusive_list::iterator intrusive_list::erase( + iterator pos) { + iterator next = std::next(pos); + delete extract(pos); + return next; +} + +template +inline typename intrusive_list::iterator intrusive_list::erase( + iterator first, + iterator last) { + while (first != last) + first = erase(first); + return first; +} + +template +inline void intrusive_list::swap(intrusive_list& other) { + std::swap(first_, other.first_); + std::swap(last_, other.last_); + std::swap(size_, other.size_); +} + +template +inline void intrusive_list::clear() noexcept { + for (T* iter = first_; iter;) { + T* next = iter->next_; + delete iter; + iter = next; + } + first_ = last_ = nullptr; + size_ = 0; +} + +template +inline void intrusive_list::splice(iterator pos, intrusive_list& other) { + splice(pos, other, other.begin(), other.end()); +} + +template +inline void intrusive_list::splice(iterator pos, intrusive_list&& other) { + splice(pos, other, other.begin(), other.end()); +} + +template +inline void intrusive_list::splice(iterator pos, + intrusive_list& other, + iterator it) { + insert(pos, other.extract(it)); +} + +template +inline void intrusive_list::splice(iterator pos, + intrusive_list& other, + iterator first, + iterator last) { + while (first != last) + insert(pos, other.extract(first++)); +} + +} // namespace wabt + +#endif // WABT_INTRUSIVE_LIST_H_ diff --git a/lib/wabt/src/ir.cc b/lib/wabt/src/ir.cc index 2e4d8b4a12a..df58768d173 100644 --- a/lib/wabt/src/ir.cc +++ b/lib/wabt/src/ir.cc @@ -19,13 +19,62 @@ #include #include +#include "cast.h" + +namespace { + +const char* ExprTypeName[] = { + "Binary", + "Block", + "Br", + "BrIf", + "BrTable", + "Call", + "CallIndirect", + "Compare", + "Const", + "Convert", + "CurrentMemory", + "Drop", + "GetGlobal", + "GetLocal", + "GrowMemory", + "If", + "Load", + "Loop", + "Nop", + "Rethrow", + "Return", + "Select", + "SetGlobal", + "SetLocal", + "Store", + "TeeLocal", + "Throw", + "TryBlock", + "Unary", + "Unreachable" +}; + +} // end of anonymous namespace + namespace wabt { +const char* GetExprTypeName(ExprType type) { + static_assert(WABT_ENUM_COUNT(ExprType) == WABT_ARRAY_SIZE(ExprTypeName), + "Malformed ExprTypeName array"); + return ExprTypeName[size_t(type)]; +} + +const char* GetExprTypeName(const Expr& expr) { + return GetExprTypeName(expr.type); +} + bool FuncSignature::operator==(const FuncSignature& rhs) const { return param_types == rhs.param_types && result_types == rhs.result_types; } -const Export* Module::GetExport(const StringSlice& name) const { +const Export* Module::GetExport(string_view name) const { Index index = export_bindings.FindIndex(name); if (index >= exports.size()) return nullptr; @@ -52,15 +101,19 @@ Index Module::GetFuncTypeIndex(const Var& var) const { return func_type_bindings.FindIndex(var); } +Index Module::GetExceptIndex(const Var& var) const { + return except_bindings.FindIndex(var); +} + Index Func::GetLocalIndex(const Var& var) const { - if (var.type == VarType::Index) - return var.index; + if (var.is_index()) + return var.index(); - Index result = param_bindings.FindIndex(var.name); + Index result = param_bindings.FindIndex(var); if (result != kInvalidIndex) return result; - result = local_bindings.FindIndex(var.name); + result = local_bindings.FindIndex(var); if (result == kInvalidIndex) return result; @@ -104,6 +157,13 @@ Memory* Module::GetMemory(const Var& var) { return memories[index]; } +Exception* Module::GetExcept(const Var& var) const { + Index index = GetExceptIndex(var); + if (index >= excepts.size()) + return nullptr; + return excepts[index]; +} + const FuncType* Module::GetFuncType(const Var& var) const { return const_cast(this)->GetFuncType(var); } @@ -131,526 +191,331 @@ Index Module::GetFuncTypeIndex(const FuncDeclaration& decl) const { } } -const Module* Script::GetFirstModule() const { - return const_cast(this)->GetFirstModule(); -} - -Module* Script::GetFirstModule() { - for (const std::unique_ptr& command : commands) { - if (command->type == CommandType::Module) - return command->module; - } - return nullptr; -} - -const Module* Script::GetModule(const Var& var) const { - Index index = module_bindings.FindIndex(var); - if (index >= commands.size()) - return nullptr; - const Command& command = *commands[index].get(); - assert(command.type == CommandType::Module); - return command.module; -} - -void MakeTypeBindingReverseMapping( - const TypeVector& types, - const BindingHash& bindings, - std::vector* out_reverse_mapping) { - out_reverse_mapping->clear(); - out_reverse_mapping->resize(types.size()); - for (const auto& pair : bindings) { - assert(static_cast(pair.second.index) < - out_reverse_mapping->size()); - (*out_reverse_mapping)[pair.second.index] = pair.first; - } -} - -ModuleField* Module::AppendField() { - ModuleField* result = new ModuleField(); - if (!first_field) - first_field = result; - else if (last_field) - last_field->next = result; - last_field = result; - return result; -} - -FuncType* Module::AppendImplicitFuncType(const Location& loc, - const FuncSignature& sig) { - ModuleField* field = AppendField(); - field->loc = loc; - field->type = ModuleFieldType::FuncType; - field->func_type = new FuncType(); - field->func_type->sig = sig; - - func_types.push_back(field->func_type); - return field->func_type; -} - -void DestroyExprList(Expr* first) { - Expr* expr = first; - while (expr) { - Expr* next = expr->next; - delete expr; - expr = next; - } +void Module::AppendField(DataSegmentModuleField* field) { + fields.push_back(field); + data_segments.push_back(field->data_segment); } -Var::Var(Index index) : type(VarType::Index), index(index) { - WABT_ZERO_MEMORY(loc); +void Module::AppendField(ElemSegmentModuleField* field) { + fields.push_back(field); + elem_segments.push_back(field->elem_segment); } -Var::Var(const StringSlice& name) : type(VarType::Name), name(name) { - WABT_ZERO_MEMORY(loc); +void Module::AppendField(ExceptionModuleField* field) { + auto except = field->except; + if (!except->name.empty()) + except_bindings.emplace(except->name, Binding(field->loc, excepts.size())); + excepts.push_back(except); + fields.push_back(field); } -Var::Var(Var&& rhs) : loc(rhs.loc), type(rhs.type) { - if (rhs.type == VarType::Index) { - index = rhs.index; - } else { - name = rhs.name; - rhs = Var(kInvalidIndex); - } +void Module::AppendField(ExportModuleField* field) { + // Exported names are allowed to be empty. + auto export_ = field->export_; + export_bindings.emplace(export_->name, Binding(field->loc, exports.size())); + exports.push_back(export_); + fields.push_back(field); } -Var::Var(const Var& rhs) : loc(rhs.loc), type(rhs.type) { - if (rhs.type == VarType::Index) { - index = rhs.index; - } else { - name = dup_string_slice(rhs.name); - } +void Module::AppendField(FuncModuleField* field) { + auto func = field->func; + if (!func->name.empty()) + func_bindings.emplace(func->name, Binding(field->loc, funcs.size())); + funcs.push_back(func); + fields.push_back(field); } -Var& Var::operator =(Var&& rhs) { - loc = rhs.loc; - type = rhs.type; - if (rhs.type == VarType::Index) { - index = rhs.index; - } else { - name = rhs.name; - rhs = Var(kInvalidIndex); +void Module::AppendField(FuncTypeModuleField* field) { + auto func_type = field->func_type; + if (!func_type->name.empty()) { + func_type_bindings.emplace(func_type->name, + Binding(field->loc, func_types.size())); } - return *this; + func_types.push_back(func_type); + fields.push_back(field); } -Var& Var::operator =(const Var& rhs) { - loc = rhs.loc; - type = rhs.type; - if (rhs.type == VarType::Index) { - index = rhs.index; - } else { - name = dup_string_slice(rhs.name); - } - return *this; +void Module::AppendField(GlobalModuleField* field) { + auto global = field->global; + if (!global->name.empty()) + global_bindings.emplace(global->name, Binding(field->loc, globals.size())); + globals.push_back(global); + fields.push_back(field); } -Var::~Var() { - if (type == VarType::Name) - destroy_string_slice(&name); -} +void Module::AppendField(ImportModuleField* field) { + auto import = field->import; + std::string* name = nullptr; + BindingHash* bindings = nullptr; + Index index = kInvalidIndex; -Const::Const(I32, uint32_t value) : type(Type::I32), u32(value) { - WABT_ZERO_MEMORY(loc); -} + switch (import->kind) { + case ExternalKind::Func: + name = &import->func->name; + bindings = &func_bindings; + index = funcs.size(); + funcs.push_back(import->func); + ++num_func_imports; + break; -Const::Const(I64, uint64_t value) : type(Type::I64), u64(value) { - WABT_ZERO_MEMORY(loc); -} + case ExternalKind::Table: + name = &import->table->name; + bindings = &table_bindings; + index = tables.size(); + tables.push_back(import->table); + ++num_table_imports; + break; -Const::Const(F32, uint32_t value) : type(Type::F32), f32_bits(value) { - WABT_ZERO_MEMORY(loc); -} + case ExternalKind::Memory: + name = &import->memory->name; + bindings = &memory_bindings; + index = memories.size(); + memories.push_back(import->memory); + ++num_memory_imports; + break; -Const::Const(F64, uint64_t value) : type(Type::F64), f64_bits(value) { - WABT_ZERO_MEMORY(loc); -} + case ExternalKind::Global: + name = &import->global->name; + bindings = &global_bindings; + index = globals.size(); + globals.push_back(import->global); + ++num_global_imports; + break; -Block::Block(): first(nullptr) { - WABT_ZERO_MEMORY(label); -} + case ExternalKind::Except: + name = &import->except->name; + bindings = &except_bindings; + index = excepts.size(); + excepts.push_back(import->except); + ++num_except_imports; + break; + } -Block::Block(Expr* first) : first(first) { - WABT_ZERO_MEMORY(label); + assert(name && bindings && index != kInvalidIndex); + if (!name->empty()) + bindings->emplace(*name, Binding(field->loc, index)); + imports.push_back(import); + fields.push_back(field); } -Block::~Block() { - destroy_string_slice(&label); - DestroyExprList(first); +void Module::AppendField(MemoryModuleField* field) { + auto memory = field->memory; + if (!memory->name.empty()) + memory_bindings.emplace(memory->name, Binding(field->loc, memories.size())); + memories.push_back(memory); + fields.push_back(field); } -Expr::Expr() : type(ExprType::Binary), next(nullptr) { - WABT_ZERO_MEMORY(loc); - binary.opcode = Opcode::Nop; +void Module::AppendField(StartModuleField* field) { + fields.push_back(field); + start = &field->start; } -Expr::Expr(ExprType type) : type(type), next(nullptr) { - WABT_ZERO_MEMORY(loc); +void Module::AppendField(TableModuleField* field) { + auto table = field->table; + if (!table->name.empty()) + table_bindings.emplace(table->name, Binding(field->loc, tables.size())); + tables.push_back(table); + fields.push_back(field); } -Expr::~Expr() { - switch (type) { - case ExprType::Block: - delete block; - break; - case ExprType::Br: - br.var.~Var(); - break; - case ExprType::BrIf: - br_if.var.~Var(); - break; - case ExprType::BrTable: - delete br_table.targets; - br_table.default_target.~Var(); - break; - case ExprType::Call: - call.var.~Var(); - break; - case ExprType::CallIndirect: - call_indirect.var.~Var(); - break; - case ExprType::Catch: - case ExprType::CatchAll: - catch_.var.~Var(); - DestroyExprList(catch_.first); - break; - case ExprType::GetGlobal: - get_global.var.~Var(); +void Module::AppendField(ModuleField* field) { + switch (field->type) { + case ModuleFieldType::Func: + AppendField(dyn_cast(field)); break; - case ExprType::GetLocal: - get_local.var.~Var(); + + case ModuleFieldType::Global: + AppendField(dyn_cast(field)); break; - case ExprType::If: - delete if_.true_; - DestroyExprList(if_.false_); + + case ModuleFieldType::Import: + AppendField(dyn_cast(field)); break; - case ExprType::Loop: - delete loop; + + case ModuleFieldType::Export: + AppendField(dyn_cast(field)); break; - case ExprType::Rethrow: - rethrow_.var.~Var(); + + case ModuleFieldType::FuncType: + AppendField(dyn_cast(field)); break; - case ExprType::SetGlobal: - set_global.var.~Var(); + + case ModuleFieldType::Table: + AppendField(dyn_cast(field)); break; - case ExprType::SetLocal: - set_local.var.~Var(); + + case ModuleFieldType::ElemSegment: + AppendField(dyn_cast(field)); break; - case ExprType::TeeLocal: - tee_local.var.~Var(); + + case ModuleFieldType::Memory: + AppendField(dyn_cast(field)); break; - case ExprType::Throw: - throw_.var.~Var(); + + case ModuleFieldType::DataSegment: + AppendField(dyn_cast(field)); break; - case ExprType::TryBlock: - delete try_block.block; - DestroyExprList(try_block.first_catch); + + case ModuleFieldType::Start: + AppendField(dyn_cast(field)); break; - case ExprType::Binary: - case ExprType::Compare: - case ExprType::Const: - case ExprType::Convert: - case ExprType::Drop: - case ExprType::CurrentMemory: - case ExprType::GrowMemory: - case ExprType::Load: - case ExprType::Nop: - case ExprType::Return: - case ExprType::Select: - case ExprType::Store: - case ExprType::Unary: - case ExprType::Unreachable: + + case ModuleFieldType::Except: + AppendField(dyn_cast(field)); break; } } -// static -Expr* Expr::CreateBinary(Opcode opcode) { - Expr* expr = new Expr(ExprType::Binary); - expr->binary.opcode = opcode; - return expr; -} - -// static -Expr* Expr::CreateBlock(Block* block) { - Expr* expr = new Expr(ExprType::Block); - expr->block = block; - return expr; -} - -// static -Expr* Expr::CreateBr(Var var) { - Expr* expr = new Expr(ExprType::Br); - expr->br.var = var; - return expr; -} - -// static -Expr* Expr::CreateBrIf(Var var) { - Expr* expr = new Expr(ExprType::BrIf); - expr->br_if.var = var; - return expr; -} - -// static -Expr* Expr::CreateBrTable(VarVector* targets, Var default_target) { - Expr* expr = new Expr(ExprType::BrTable); - expr->br_table.targets = targets; - expr->br_table.default_target = default_target; - return expr; -} - -// static -Expr* Expr::CreateCall(Var var) { - Expr* expr = new Expr(ExprType::Call); - expr->call.var = var; - return expr; -} - -// static -Expr* Expr::CreateCallIndirect(Var var) { - Expr* expr = new Expr(ExprType::CallIndirect); - expr->call_indirect.var = var; - return expr; -} - -// static -Expr* Expr::CreateCatch(Var var, Expr* first) { - Expr* expr = new Expr(ExprType::Catch); - expr->catch_.var = var; - expr->catch_.first = first; - return expr; -} - -// static -Expr* Expr::CreateCatchAll(Expr* first) { - Expr* expr = new Expr(ExprType::CatchAll); - expr->catch_.first = first; - return expr; +void Module::AppendFields(ModuleFieldList* fields) { + while (!fields->empty()) + AppendField(fields->extract_front()); } -// static -Expr* Expr::CreateCompare(Opcode opcode) { - Expr* expr = new Expr(ExprType::Compare); - expr->compare.opcode = opcode; - return expr; -} - -// static -Expr* Expr::CreateConst(const Const& const_) { - Expr* expr = new Expr(ExprType::Const); - expr->const_ = const_; - return expr; -} - -// static -Expr* Expr::CreateConvert(Opcode opcode) { - Expr* expr = new Expr(ExprType::Convert); - expr->convert.opcode = opcode; - return expr; -} - -// static -Expr* Expr::CreateCurrentMemory() { - return new Expr(ExprType::CurrentMemory); +const Module* Script::GetFirstModule() const { + return const_cast(this)->GetFirstModule(); } -// static -Expr* Expr::CreateDrop() { - return new Expr(ExprType::Drop); +Module* Script::GetFirstModule() { + for (const std::unique_ptr& command : commands) { + if (auto* module_command = dyn_cast(command.get())) + return module_command->module; + } + return nullptr; } -// static -Expr* Expr::CreateGetGlobal(Var var) { - Expr* expr = new Expr(ExprType::GetGlobal); - expr->get_global.var = var; - return expr; +const Module* Script::GetModule(const Var& var) const { + Index index = module_bindings.FindIndex(var); + if (index >= commands.size()) + return nullptr; + auto* command = cast(commands[index].get()); + return command->module; } -// static -Expr* Expr::CreateGetLocal(Var var) { - Expr* expr = new Expr(ExprType::GetLocal); - expr->get_local.var = var; - return expr; +void MakeTypeBindingReverseMapping( + const TypeVector& types, + const BindingHash& bindings, + std::vector* out_reverse_mapping) { + out_reverse_mapping->clear(); + out_reverse_mapping->resize(types.size()); + for (const auto& pair : bindings) { + assert(static_cast(pair.second.index) < + out_reverse_mapping->size()); + (*out_reverse_mapping)[pair.second.index] = pair.first; + } } -// static -Expr* Expr::CreateGrowMemory() { - return new Expr(ExprType::GrowMemory); -} +Var::Var(Index index, const Location& loc) + : loc(loc), type_(VarType::Index), index_(index) {} -// static -Expr* Expr::CreateIf(Block* true_, Expr* false_) { - Expr* expr = new Expr(ExprType::If); - expr->if_.true_ = true_; - expr->if_.false_ = false_; - return expr; -} +Var::Var(string_view name, const Location& loc) + : loc(loc), type_(VarType::Name), name_(name) {} -// static -Expr* Expr::CreateLoad(Opcode opcode, Address align, uint32_t offset) { - Expr* expr = new Expr(ExprType::Load); - expr->load.opcode = opcode; - expr->load.align = align; - expr->load.offset = offset; - return expr; +Var::Var(Var&& rhs) : Var(kInvalidIndex) { + *this = std::move(rhs); } -// static -Expr* Expr::CreateLoop(Block* block) { - Expr* expr = new Expr(ExprType::Loop); - expr->loop = block; - return expr; +Var::Var(const Var& rhs) : Var(kInvalidIndex) { + *this = rhs; } -// static -Expr* Expr::CreateNop() { - return new Expr(ExprType::Nop); +Var& Var::operator=(Var&& rhs) { + loc = rhs.loc; + if (rhs.is_index()) { + set_index(rhs.index_); + } else { + set_name(rhs.name_); + } + return *this; } -// static -Expr* Expr::CreateRethrow(Var var) { - Expr* expr = new Expr(ExprType::Rethrow); - expr->rethrow_.var = var; - return expr; +Var& Var::operator=(const Var& rhs) { + loc = rhs.loc; + if (rhs.is_index()) { + set_index(rhs.index_); + } else { + set_name(rhs.name_); + } + return *this; } -// static -Expr* Expr::CreateReturn() { - return new Expr(ExprType::Return); +Var::~Var() { + Destroy(); } -// static -Expr* Expr::CreateSelect() { - return new Expr(ExprType::Select); +void Var::set_index(Index index) { + Destroy(); + type_ = VarType::Index; + index_ = index; } -// static -Expr* Expr::CreateSetGlobal(Var var) { - Expr* expr = new Expr(ExprType::SetGlobal); - expr->set_global.var = var; - return expr; +void Var::set_name(std::string&& name) { + Destroy(); + type_ = VarType::Name; + Construct(name_, std::move(name)); } -// static -Expr* Expr::CreateSetLocal(Var var) { - Expr* expr = new Expr(ExprType::SetLocal); - expr->set_local.var = var; - return expr; +void Var::set_name(string_view name) { + set_name(name.to_string()); } -// static -Expr* Expr::CreateStore(Opcode opcode, Address align, uint32_t offset) { - Expr* expr = new Expr(ExprType::Store); - expr->store.opcode = opcode; - expr->store.align = align; - expr->store.offset = offset; - return expr; +void Var::Destroy() { + if (is_name()) + Destruct(name_); } -// static -Expr* Expr::CreateTeeLocal(Var var) { - Expr* expr = new Expr(ExprType::TeeLocal); - expr->tee_local.var = var; - return expr; +Const::Const(I32, uint32_t value, const Location& loc_) + : loc(loc_), type(Type::I32), u32(value) { } -// static -Expr* Expr::CreateThrow(Var var) { - Expr* expr = new Expr(ExprType::Throw); - expr->throw_.var = var; - return expr; +Const::Const(I64, uint64_t value, const Location& loc_) + : loc(loc_), type(Type::I64), u64(value) { } -// static -Expr* Expr::CreateTry(Block* block, Expr* first_catch) { - Expr* expr = new Expr(ExprType::TryBlock); - expr->try_block.block = block; - expr->try_block.first_catch = first_catch; - return expr; +Const::Const(F32, uint32_t value, const Location& loc_) + : loc(loc_), type(Type::F32), f32_bits(value) { } -// static -Expr* Expr::CreateUnary(Opcode opcode) { - Expr* expr = new Expr(ExprType::Unary); - expr->unary.opcode = opcode; - return expr; +Const::Const(F64, uint64_t value, const Location& loc_) + : loc(loc_), type(Type::F64), f64_bits(value) { } -// static -Expr* Expr::CreateUnreachable() { - return new Expr(ExprType::Unreachable); -} +Block::Block(ExprList exprs) : exprs(std::move(exprs)) {} -FuncType::FuncType() { - WABT_ZERO_MEMORY(name); -} +Catch::Catch() {} -FuncType::~FuncType() { - destroy_string_slice(&name); -} +Catch::Catch(const Var& var) : var(var) {} -FuncDeclaration::FuncDeclaration() - : has_func_type(false), type_var(kInvalidIndex) {} +Catch::Catch(ExprList exprs) : exprs(std::move(exprs)) {} -FuncDeclaration::~FuncDeclaration() {} +Catch::Catch(const Var& var, ExprList exprs) + : var(var), exprs(std::move(exprs)) {} -Func::Func() : first_expr(nullptr) { - WABT_ZERO_MEMORY(name); +IfExpr::~IfExpr() { + delete true_; } -Func::~Func() { - destroy_string_slice(&name); - DestroyExprList(first_expr); +TryExpr::~TryExpr() { + delete block; + for (Catch* catch_ : catches) + delete catch_; } -Global::Global() : type(Type::Void), mutable_(false), init_expr(nullptr) { - WABT_ZERO_MEMORY(name); -} +Expr::Expr(ExprType type) : type(type) {} -Global::~Global() { - destroy_string_slice(&name); - DestroyExprList(init_expr); -} +Expr::Expr(ExprType type, Location loc) : loc(loc), type(type) {} Table::Table() { - WABT_ZERO_MEMORY(name); - WABT_ZERO_MEMORY(elem_limits); -} - -Table::~Table() { - destroy_string_slice(&name); -} - -ElemSegment::ElemSegment() : table_var(kInvalidIndex), offset(nullptr) {} - -ElemSegment::~ElemSegment() { - DestroyExprList(offset); -} - -DataSegment::DataSegment() : offset(nullptr), data(nullptr), size(0) {} - -DataSegment::~DataSegment() { - DestroyExprList(offset); - delete[] data; + ZeroMemory(elem_limits); } Memory::Memory() { - WABT_ZERO_MEMORY(name); - WABT_ZERO_MEMORY(page_limits); + ZeroMemory(page_limits); } -Memory::~Memory() { - destroy_string_slice(&name); -} - -Import::Import() : kind(ExternalKind::Func), func(nullptr) { - WABT_ZERO_MEMORY(module_name); - WABT_ZERO_MEMORY(field_name); -} +Import::Import() : kind(ExternalKind::Func), func(nullptr) {} Import::~Import() { - destroy_string_slice(&module_name); - destroy_string_slice(&field_name); switch (kind) { case ExternalKind::Func: delete func; @@ -670,118 +535,50 @@ Import::~Import() { } } -Export::Export() { - WABT_ZERO_MEMORY(name); -} - -Export::~Export() { - destroy_string_slice(&name); -} +ModuleField::ModuleField(ModuleFieldType type, const Location& loc) + : loc(loc), type(type) {} -void destroy_memory(Memory* memory) { - destroy_string_slice(&memory->name); -} - -void destroy_table(Table* table) { - destroy_string_slice(&table->name); -} - -ModuleField::ModuleField() : ModuleField(ModuleFieldType::Start) {} - -ModuleField::ModuleField(ModuleFieldType type) - : type(type), next(nullptr), start(kInvalidIndex) { - WABT_ZERO_MEMORY(loc); -} - -ModuleField::~ModuleField() { +ScriptModule::ScriptModule(Type type) : type(type) { switch (type) { - case ModuleFieldType::Except: - delete except; - break; - case ModuleFieldType::Func: - delete func; - break; - case ModuleFieldType::Global: - delete global; - break; - case ModuleFieldType::Import: - delete import; - break; - case ModuleFieldType::Export: - delete export_; - break; - case ModuleFieldType::FuncType: - delete func_type; - break; - case ModuleFieldType::Table: - delete table; - break; - case ModuleFieldType::ElemSegment: - delete elem_segment; - break; - case ModuleFieldType::Memory: - delete memory; - break; - case ModuleFieldType::DataSegment: - delete data_segment; - break; - case ModuleFieldType::Start: - start.~Var(); + case ScriptModule::Type::Text: + text = nullptr; break; - } -} - -Module::Module() - : first_field(nullptr), - last_field(nullptr), - num_except_imports(0), - num_func_imports(0), - num_table_imports(0), - num_memory_imports(0), - num_global_imports(0), - start(0) { - WABT_ZERO_MEMORY(loc); - WABT_ZERO_MEMORY(name); -} -Module::~Module() { - destroy_string_slice(&name); + case ScriptModule::Type::Binary: + Construct(binary.loc); + Construct(binary.name); + Construct(binary.data); + break; - ModuleField* field = first_field; - while (field) { - ModuleField* next_field = field->next; - delete field; - field = next_field; + case ScriptModule::Type::Quoted: + Construct(quoted.loc); + Construct(quoted.name); + Construct(quoted.data); + break; } } -ScriptModule::ScriptModule() : type(ScriptModule::Type::Text), text(nullptr) {} - ScriptModule::~ScriptModule() { switch (type) { case ScriptModule::Type::Text: delete text; break; case ScriptModule::Type::Binary: - destroy_string_slice(&binary.name); - delete [] binary.data; + Destruct(binary.loc); + Destruct(binary.name); + Destruct(binary.data); break; case ScriptModule::Type::Quoted: - destroy_string_slice("ed.name); - delete [] binary.data; + Destruct(quoted.loc); + Destruct(quoted.name); + Destruct(quoted.data); break; } } -ActionInvoke::ActionInvoke() {} - -Action::Action() : type(ActionType::Get), module_var(kInvalidIndex) { - WABT_ZERO_MEMORY(loc); - WABT_ZERO_MEMORY(name); -} +Action::Action() : type(ActionType::Get), module_var(kInvalidIndex) {} Action::~Action() { - destroy_string_slice(&name); switch (type) { case ActionType::Invoke: delete invoke; @@ -791,55 +588,4 @@ Action::~Action() { } } -Command::Command() : type(CommandType::Module), module(nullptr) {} - -Command::~Command() { - switch (type) { - case CommandType::Module: - delete module; - break; - case CommandType::Action: - delete action; - break; - case CommandType::Register: - destroy_string_slice(®ister_.module_name); - register_.var.~Var(); - break; - case CommandType::AssertMalformed: - delete assert_malformed.module; - destroy_string_slice(&assert_malformed.text); - break; - case CommandType::AssertInvalid: - case CommandType::AssertInvalidNonBinary: - delete assert_invalid.module; - destroy_string_slice(&assert_invalid.text); - break; - case CommandType::AssertUnlinkable: - delete assert_unlinkable.module; - destroy_string_slice(&assert_unlinkable.text); - break; - case CommandType::AssertUninstantiable: - delete assert_uninstantiable.module; - destroy_string_slice(&assert_uninstantiable.text); - break; - case CommandType::AssertReturn: - delete assert_return.action; - delete assert_return.expected; - break; - case CommandType::AssertReturnCanonicalNan: - delete assert_return_arithmetic_nan.action; - break; - case CommandType::AssertReturnArithmeticNan: - delete assert_return_canonical_nan.action; - break; - case CommandType::AssertTrap: - case CommandType::AssertExhaustion: - delete assert_trap.action; - destroy_string_slice(&assert_trap.text); - break; - } -} - -Script::Script() {} - } // namespace wabt diff --git a/lib/wabt/src/ir.h b/lib/wabt/src/ir.h index 3d51c5129e2..9bd30ade64e 100644 --- a/lib/wabt/src/ir.h +++ b/lib/wabt/src/ir.h @@ -23,10 +23,13 @@ #include #include #include +#include #include "binding-hash.h" #include "common.h" +#include "intrusive-list.h" #include "opcode.h" +#include "string-view.h" namespace wabt { @@ -36,25 +39,38 @@ enum class VarType { }; struct Var { - explicit Var(Index index = kInvalidIndex); - explicit Var(const StringSlice& name); + explicit Var(Index index = kInvalidIndex, const Location& loc = Location()); + explicit Var(string_view name, const Location& loc = Location()); Var(Var&&); Var(const Var&); Var& operator =(const Var&); Var& operator =(Var&&); ~Var(); + VarType type() const { return type_; } + bool is_index() const { return type_ == VarType::Index; } + bool is_name() const { return type_ == VarType::Name; } + + Index index() const { assert(is_index()); return index_; } + const std::string& name() const { assert(is_name()); return name_; } + + void set_index(Index); + void set_name(std::string&&); + void set_name(string_view); + Location loc; - VarType type; + + private: + void Destroy(); + + VarType type_; union { - Index index; - StringSlice name; + Index index_; + std::string name_; }; }; typedef std::vector VarVector; -typedef StringSlice Label; - struct Const { // Struct tags to differentiate constructors. struct I32 {}; @@ -62,12 +78,11 @@ struct Const { struct F32 {}; struct F64 {}; - // Keep the default constructor trivial so it can be used as a union member. - Const() = default; - Const(I32, uint32_t); - Const(I64, uint64_t); - Const(F32, uint32_t); - Const(F64, uint64_t); + Const() : Const(I32(), 0, Location()) {} + Const(I32, uint32_t val = 0, const Location& loc = Location()); + Const(I64, uint64_t val = 0, const Location& loc = Location()); + Const(F32, uint32_t val = 0, const Location& loc = Location()); + Const(F64, uint64_t val = 0, const Location& loc = Location()); Location loc; Type type; @@ -88,8 +103,6 @@ enum class ExprType { BrTable, Call, CallIndirect, - Catch, - CatchAll, Compare, Const, Convert, @@ -113,85 +126,197 @@ enum class ExprType { TryBlock, Unary, Unreachable, + + First = Binary, + Last = Unreachable }; +const char* GetExprTypeName(ExprType type); + typedef TypeVector BlockSignature; -struct Expr; +class Expr; +typedef intrusive_list ExprList; struct Block { - WABT_DISALLOW_COPY_AND_ASSIGN(Block); - Block(); - explicit Block(Expr* first); - ~Block(); + Block() = default; + explicit Block(ExprList exprs); - Label label; + std::string label; BlockSignature sig; - Expr* first; + ExprList exprs; }; -struct Expr { +struct Catch { + WABT_DISALLOW_COPY_AND_ASSIGN(Catch); + Catch(); + explicit Catch(const Var& var); + explicit Catch(ExprList exprs); + Catch(const Var& var, ExprList exprs); + Location loc; + Var var; + ExprList exprs; + bool IsCatchAll() const { + return var.is_index() && var.index() == kInvalidIndex; + } +}; + +typedef std::vector CatchVector; + +class Expr : public intrusive_list_base { + public: WABT_DISALLOW_COPY_AND_ASSIGN(Expr); - Expr(); - explicit Expr(ExprType); - ~Expr(); - - static Expr* CreateBinary(Opcode); - static Expr* CreateBlock(Block*); - static Expr* CreateBr(Var); - static Expr* CreateBrIf(Var); - static Expr* CreateBrTable(VarVector* targets, Var default_target); - static Expr* CreateCall(Var); - static Expr* CreateCallIndirect(Var); - static Expr* CreateCatch(Var v, Expr* first); - static Expr* CreateCatchAll(Expr* first); - static Expr* CreateCompare(Opcode); - static Expr* CreateConst(const Const&); - static Expr* CreateConvert(Opcode); - static Expr* CreateCurrentMemory(); - static Expr* CreateDrop(); - static Expr* CreateGetGlobal(Var); - static Expr* CreateGetLocal(Var); - static Expr* CreateGrowMemory(); - static Expr* CreateIf(Block* true_, Expr* false_ = nullptr); - static Expr* CreateLoad(Opcode, Address align, uint32_t offset); - static Expr* CreateLoop(Block*); - static Expr* CreateNop(); - static Expr* CreateRethrow(Var); - static Expr* CreateReturn(); - static Expr* CreateSelect(); - static Expr* CreateSetGlobal(Var); - static Expr* CreateSetLocal(Var); - static Expr* CreateStore(Opcode, Address align, uint32_t offset); - static Expr* CreateTeeLocal(Var); - static Expr* CreateThrow(Var); - static Expr* CreateTry(Block* block, Expr* first_catch); - static Expr* CreateUnary(Opcode); - static Expr* CreateUnreachable(); + Expr() = delete; + virtual ~Expr() = default; Location loc; ExprType type; - Expr* next; - union { - struct { Opcode opcode; } binary, compare, convert, unary; - struct Block *block, *loop; - struct { Block* block; Expr* first_catch; } try_block; - struct { Var var; Expr* first; } catch_; - struct { Expr* first; } catch_all; - struct { Var var; } throw_, rethrow_; - struct { Var var; } br, br_if; - struct { VarVector* targets; Var default_target; } br_table; - struct { Var var; } call, call_indirect; - struct Const const_; - struct { Var var; } get_global, set_global; - struct { Var var; } get_local, set_local, tee_local; - struct { Block* true_; Expr* false_; } if_; - struct { Opcode opcode; Address align; uint32_t offset; } load, store; - }; + + protected: + explicit Expr(ExprType); + Expr(ExprType, Location); +}; + +const char* GetExprTypeName(const Expr& expr); + +template +class ExprMixin : public Expr { + public: + static bool classof(const Expr* expr) { return expr->type == TypeEnum; } + + ExprMixin() : Expr(TypeEnum) {} + explicit ExprMixin(Location loc) : Expr(TypeEnum, loc) {} +}; + +typedef ExprMixin CurrentMemoryExpr; +typedef ExprMixin DropExpr; +typedef ExprMixin GrowMemoryExpr; +typedef ExprMixin NopExpr; +typedef ExprMixin ReturnExpr; +typedef ExprMixin SelectExpr; +typedef ExprMixin UnreachableExpr; + +template +class OpcodeExpr : public ExprMixin { + public: + OpcodeExpr(Opcode opcode, const Location& loc = Location()) + : ExprMixin(loc), opcode(opcode) {} + + Opcode opcode; +}; + +typedef OpcodeExpr BinaryExpr; +typedef OpcodeExpr CompareExpr; +typedef OpcodeExpr ConvertExpr; +typedef OpcodeExpr UnaryExpr; + +template +class VarExpr : public ExprMixin { + public: + VarExpr(const Var& var, const Location& loc = Location()) + : ExprMixin(loc), var(var) {} + + Var var; +}; + +typedef VarExpr BrExpr; +typedef VarExpr BrIfExpr; +typedef VarExpr CallExpr; +typedef VarExpr CallIndirectExpr; +typedef VarExpr GetGlobalExpr; +typedef VarExpr GetLocalExpr; +typedef VarExpr RethrowExpr; +typedef VarExpr SetGlobalExpr; +typedef VarExpr SetLocalExpr; +typedef VarExpr TeeLocalExpr; +typedef VarExpr ThrowExpr; + +template +class BlockExprBase : public ExprMixin { + public: + explicit BlockExprBase(Block* block, const Location& loc = Location()) + : ExprMixin(loc), block(block) {} + ~BlockExprBase() { delete block; } + + Block* block; +}; + +typedef BlockExprBase BlockExpr; +typedef BlockExprBase LoopExpr; + +class IfExpr : public ExprMixin { + public: + explicit IfExpr(Block* true_block, + ExprList false_expr = ExprList(), + const Location& loc = Location()) + : ExprMixin(loc), + true_(true_block), + false_(std::move(false_expr)) {} + + ~IfExpr(); + + Block* true_; + ExprList false_; }; +class TryExpr : public ExprMixin { + public: + explicit TryExpr(const Location& loc = Location()) + : ExprMixin(loc), block(nullptr) {} + ~TryExpr(); + + Block* block; + CatchVector catches; +}; + +class BrTableExpr : public ExprMixin { + public: + BrTableExpr(VarVector* targets, + Var default_target, + const Location& loc = Location()) + : ExprMixin(loc), + targets(targets), + default_target(default_target) {} + ~BrTableExpr() { delete targets; } + + VarVector* targets; + Var default_target; +}; + +class ConstExpr : public ExprMixin { + public: + ConstExpr(const Const& c, const Location& loc = Location()) + : ExprMixin(loc), const_(c) {} + + Const const_; +}; + +template +class LoadStoreExpr : public ExprMixin { + public: + LoadStoreExpr(Opcode opcode, + Address align, + uint32_t offset, + const Location& loc = Location()) + : ExprMixin(loc), + opcode(opcode), + align(align), + offset(offset) {} + + Opcode opcode; + Address align; + uint32_t offset; +}; + +typedef LoadStoreExpr LoadExpr; +typedef LoadStoreExpr StoreExpr; + struct Exception { - StringSlice name; + Exception() = default; + Exception(const TypeVector& sig) : sig(sig) {} + Exception(string_view name, const TypeVector& sig) : name(name), sig(sig) {} + + std::string name; TypeVector sig; }; @@ -208,39 +333,27 @@ struct FuncSignature { }; struct FuncType { - WABT_DISALLOW_COPY_AND_ASSIGN(FuncType); - FuncType(); - ~FuncType(); - Index GetNumParams() const { return sig.GetNumParams(); } Index GetNumResults() const { return sig.GetNumResults(); } Type GetParamType(Index index) const { return sig.GetParamType(index); } Type GetResultType(Index index) const { return sig.GetResultType(index); } - StringSlice name; + std::string name; FuncSignature sig; }; struct FuncDeclaration { - WABT_DISALLOW_COPY_AND_ASSIGN(FuncDeclaration); - FuncDeclaration(); - ~FuncDeclaration(); - Index GetNumParams() const { return sig.GetNumParams(); } Index GetNumResults() const { return sig.GetNumResults(); } Type GetParamType(Index index) const { return sig.GetParamType(index); } Type GetResultType(Index index) const { return sig.GetResultType(index); } - bool has_func_type; + bool has_func_type = false; Var type_var; FuncSignature sig; }; struct Func { - WABT_DISALLOW_COPY_AND_ASSIGN(Func); - Func(); - ~Func(); - Type GetParamType(Index index) const { return decl.GetParamType(index); } Type GetResultType(Index index) const { return decl.GetResultType(index); } Index GetNumParams() const { return decl.GetNumParams(); } @@ -251,62 +364,45 @@ struct Func { Index GetNumResults() const { return decl.GetNumResults(); } Index GetLocalIndex(const Var&) const; - StringSlice name; + std::string name; FuncDeclaration decl; TypeVector local_types; BindingHash param_bindings; BindingHash local_bindings; - Expr* first_expr; + ExprList exprs; }; struct Global { - WABT_DISALLOW_COPY_AND_ASSIGN(Global); - Global(); - ~Global(); - - StringSlice name; - Type type; - bool mutable_; - Expr* init_expr; + std::string name; + Type type = Type::Void; + bool mutable_ = false; + ExprList init_expr; }; struct Table { - WABT_DISALLOW_COPY_AND_ASSIGN(Table); Table(); - ~Table(); - StringSlice name; + std::string name; Limits elem_limits; }; struct ElemSegment { - WABT_DISALLOW_COPY_AND_ASSIGN(ElemSegment); - ElemSegment(); - ~ElemSegment(); - Var table_var; - Expr* offset; + ExprList offset; VarVector vars; }; struct Memory { - WABT_DISALLOW_COPY_AND_ASSIGN(Memory); Memory(); - ~Memory(); - StringSlice name; + std::string name; Limits page_limits; }; struct DataSegment { - WABT_DISALLOW_COPY_AND_ASSIGN(DataSegment); - DataSegment(); - ~DataSegment(); - Var memory_var; - Expr* offset; - char* data; - size_t size; + ExprList offset; + std::vector data; }; struct Import { @@ -314,8 +410,8 @@ struct Import { Import(); ~Import(); - StringSlice module_name; - StringSlice field_name; + std::string module_name; + std::string field_name; ExternalKind kind; union { // An imported func has the type Func so it can be more easily included in @@ -330,11 +426,7 @@ struct Import { }; struct Export { - WABT_DISALLOW_COPY_AND_ASSIGN(Export); - Export(); - ~Export(); - - StringSlice name; + std::string name; ExternalKind kind; Var var; }; @@ -353,38 +445,144 @@ enum class ModuleFieldType { Except }; -struct ModuleField { +class ModuleField : public intrusive_list_base { + public: WABT_DISALLOW_COPY_AND_ASSIGN(ModuleField); - ModuleField(); - explicit ModuleField(ModuleFieldType); - ~ModuleField(); + ModuleField() = delete; + virtual ~ModuleField() {} Location loc; ModuleFieldType type; - ModuleField* next; - union { - Func* func; - Global* global; - Import* import; - Export* export_; - FuncType* func_type; - Table* table; - ElemSegment* elem_segment; - Memory* memory; - DataSegment* data_segment; - Exception* except; - Var start; - }; + + protected: + explicit ModuleField(ModuleFieldType, const Location& loc); }; -struct Module { - WABT_DISALLOW_COPY_AND_ASSIGN(Module); - Module(); - ~Module(); +typedef intrusive_list ModuleFieldList; + +template +class ModuleFieldMixin : public ModuleField { + public: + static bool classof(const ModuleField* field) { + return field->type == TypeEnum; + } - ModuleField* AppendField(); - FuncType* AppendImplicitFuncType(const Location&, const FuncSignature&); + explicit ModuleFieldMixin(const Location& loc) : ModuleField(TypeEnum, loc) {} +}; + +class FuncModuleField : public ModuleFieldMixin { + public: + explicit FuncModuleField(Func* func, const Location& loc = Location()) + : ModuleFieldMixin(loc), func(func) {} + ~FuncModuleField() { delete func; } + + Func* func; +}; + +class GlobalModuleField : public ModuleFieldMixin { + public: + explicit GlobalModuleField(Global* global, + const Location& loc = Location()) + : ModuleFieldMixin(loc), global(global) {} + ~GlobalModuleField() { delete global; } + + Global* global; +}; + +class ImportModuleField : public ModuleFieldMixin { + public: + explicit ImportModuleField(Import* import, + const Location& loc = Location()) + : ModuleFieldMixin(loc), import(import) {} + ~ImportModuleField() { delete import; } + + Import* import; +}; + +class ExportModuleField : public ModuleFieldMixin { + public: + explicit ExportModuleField(Export* export_, + const Location& loc = Location()) + : ModuleFieldMixin(loc), export_(export_) {} + ~ExportModuleField() { delete export_; } + + Export* export_; +}; + +class FuncTypeModuleField : public ModuleFieldMixin { + public: + explicit FuncTypeModuleField(FuncType* func_type, + const Location& loc = Location()) + : ModuleFieldMixin(loc), + func_type(func_type) {} + ~FuncTypeModuleField() { delete func_type; } + + FuncType* func_type; +}; + +class TableModuleField : public ModuleFieldMixin { + public: + explicit TableModuleField(Table* table, const Location& loc = Location()) + : ModuleFieldMixin(loc), table(table) {} + ~TableModuleField() { delete table; } + + Table* table; +}; + +class ElemSegmentModuleField + : public ModuleFieldMixin { + public: + explicit ElemSegmentModuleField(ElemSegment* elem_segment, + const Location& loc = Location()) + : ModuleFieldMixin(loc), + elem_segment(elem_segment) {} + ~ElemSegmentModuleField() { delete elem_segment; } + + ElemSegment* elem_segment; +}; + +class MemoryModuleField : public ModuleFieldMixin { + public: + explicit MemoryModuleField(Memory* memory, + const Location& loc = Location()) + : ModuleFieldMixin(loc), memory(memory) {} + ~MemoryModuleField() { delete memory; } + + Memory* memory; +}; + +class DataSegmentModuleField + : public ModuleFieldMixin { + public: + explicit DataSegmentModuleField(DataSegment* data_segment, + const Location& loc = Location()) + : ModuleFieldMixin(loc), + data_segment(data_segment) {} + ~DataSegmentModuleField() { delete data_segment; } + + DataSegment* data_segment; +}; + +class ExceptionModuleField : public ModuleFieldMixin { + public: + explicit ExceptionModuleField(Exception* except, + const Location& loc = Location()) + : ModuleFieldMixin(loc), except(except) {} + ~ExceptionModuleField() { delete except; } + + Exception* except; +}; + +class StartModuleField : public ModuleFieldMixin { + public: + explicit StartModuleField(Var start = Var(), + const Location& loc = Location()) + : ModuleFieldMixin(loc), start(start) {} + + Var start; +}; +struct Module { Index GetFuncTypeIndex(const Var&) const; Index GetFuncTypeIndex(const FuncDeclaration&) const; Index GetFuncTypeIndex(const FuncSignature&) const; @@ -400,18 +598,34 @@ struct Module { Index GetGlobalIndex(const Var&) const; const Global* GetGlobal(const Var&) const; Global* GetGlobal(const Var&); - const Export* GetExport(const StringSlice&) const; + const Export* GetExport(string_view) const; + Exception* GetExcept(const Var&) const; + Index GetExceptIndex(const Var&) const; + + // TODO(binji): move this into a builder class? + void AppendField(DataSegmentModuleField*); + void AppendField(ElemSegmentModuleField*); + void AppendField(ExceptionModuleField*); + void AppendField(ExportModuleField*); + void AppendField(FuncModuleField*); + void AppendField(FuncTypeModuleField*); + void AppendField(GlobalModuleField*); + void AppendField(ImportModuleField*); + void AppendField(MemoryModuleField*); + void AppendField(StartModuleField*); + void AppendField(TableModuleField*); + void AppendField(ModuleField*); + void AppendFields(ModuleFieldList*); Location loc; - StringSlice name; - ModuleField* first_field; - ModuleField* last_field; + std::string name; + ModuleFieldList fields; - Index num_except_imports; - Index num_func_imports; - Index num_table_imports; - Index num_memory_imports; - Index num_global_imports; + Index num_except_imports = 0; + Index num_func_imports = 0; + Index num_table_imports = 0; + Index num_memory_imports = 0; + Index num_global_imports = 0; // Cached for convenience; the pointers are shared with values that are // stored in either ModuleField or Import. @@ -425,7 +639,7 @@ struct Module { std::vector elem_segments; std::vector memories; std::vector data_segments; - Var* start; + Var* start = nullptr; BindingHash except_bindings; BindingHash func_bindings; @@ -446,7 +660,7 @@ struct ScriptModule { }; WABT_DISALLOW_COPY_AND_ASSIGN(ScriptModule); - ScriptModule(); + explicit ScriptModule(Type); ~ScriptModule(); const Location& GetLocation() const { @@ -464,9 +678,8 @@ struct ScriptModule { Module* text; struct { Location loc; - StringSlice name; - char* data; - size_t size; + std::string name; + std::vector data; } binary, quoted; }; }; @@ -478,7 +691,7 @@ enum class ActionType { struct ActionInvoke { WABT_DISALLOW_COPY_AND_ASSIGN(ActionInvoke); - ActionInvoke(); + ActionInvoke() = default; ConstVector args; }; @@ -491,7 +704,7 @@ struct Action { Location loc; ActionType type; Var module_var; - StringSlice name; + std::string name; union { ActionInvoke* invoke; struct {} get; @@ -504,9 +717,6 @@ enum class CommandType { Register, AssertMalformed, AssertInvalid, - /* This is a module that is invalid, but cannot be written as a binary module - * (e.g. it has unresolvable names.) */ - AssertInvalidNonBinary, AssertUnlinkable, AssertUninstantiable, AssertReturn, @@ -520,33 +730,112 @@ enum class CommandType { }; static const int kCommandTypeCount = WABT_ENUM_COUNT(CommandType); -struct Command { +class Command { + public: WABT_DISALLOW_COPY_AND_ASSIGN(Command); - Command(); - ~Command(); + Command() = delete; + virtual ~Command() {} CommandType type; - union { - Module* module; - Action* action; - struct { StringSlice module_name; Var var; } register_; - struct { Action* action; ConstVector* expected; } assert_return; - struct { - Action* action; - } assert_return_canonical_nan, assert_return_arithmetic_nan; - struct { Action* action; StringSlice text; } assert_trap; - struct { - ScriptModule* module; - StringSlice text; - } assert_malformed, assert_invalid, assert_unlinkable, - assert_uninstantiable; - }; + + protected: + explicit Command(CommandType type) : type(type) {} +}; + +template +class CommandMixin : public Command { + public: + static bool classof(const Command* cmd) { return cmd->type == TypeEnum; } + CommandMixin() : Command(TypeEnum) {} +}; + +class ModuleCommand : public CommandMixin { + public: + explicit ModuleCommand(Module* module) : module(module) {} + ~ModuleCommand() { delete module; } + + Module* module; +}; + +template +class ActionCommandBase : public CommandMixin { + public: + explicit ActionCommandBase(Action* action) : action(action) {} + ~ActionCommandBase() { delete action; } + + Action* action; +}; + +typedef ActionCommandBase ActionCommand; +typedef ActionCommandBase + AssertReturnCanonicalNanCommand; +typedef ActionCommandBase + AssertReturnArithmeticNanCommand; + +class RegisterCommand : public CommandMixin { + public: + RegisterCommand(string_view module_name, const Var& var) + : module_name(module_name), var(var) {} + + std::string module_name; + Var var; }; -typedef std::vector> CommandPtrVector; + +class AssertReturnCommand : public CommandMixin { + public: + AssertReturnCommand(Action* action, ConstVector* expected) + : action(action), expected(expected) {} + ~AssertReturnCommand() { + delete action; + delete expected; + } + + Action* action; + ConstVector* expected; +}; + +template +class AssertTrapCommandBase : public CommandMixin { + public: + AssertTrapCommandBase(Action* action, string_view text) + : action(action), text(text) {} + ~AssertTrapCommandBase() { + delete action; + } + + Action* action; + std::string text; +}; + +typedef AssertTrapCommandBase AssertTrapCommand; +typedef AssertTrapCommandBase + AssertExhaustionCommand; + +template +class AssertModuleCommand : public CommandMixin { + public: + AssertModuleCommand(ScriptModule* module, string_view text) + : module(module), text(text) {} + ~AssertModuleCommand() { delete module; } + + ScriptModule* module; + std::string text; +}; + +typedef AssertModuleCommand + AssertMalformedCommand; +typedef AssertModuleCommand AssertInvalidCommand; +typedef AssertModuleCommand + AssertUnlinkableCommand; +typedef AssertModuleCommand + AssertUninstantiableCommand; + +typedef std::unique_ptr CommandPtr; +typedef std::vector CommandPtrVector; struct Script { WABT_DISALLOW_COPY_AND_ASSIGN(Script); - Script(); + Script() = default; const Module* GetFirstModule() const; Module* GetFirstModule(); @@ -556,11 +845,9 @@ struct Script { BindingHash module_bindings; }; -void DestroyExprList(Expr*); - void MakeTypeBindingReverseMapping( - const TypeVector&, - const BindingHash&, + const TypeVector& types, + const BindingHash& bindings, std::vector* out_reverse_mapping); } // namespace wabt diff --git a/lib/wabt/src/lexer-source-line-finder.cc b/lib/wabt/src/lexer-source-line-finder.cc index a26a90c3701..6399795b96f 100644 --- a/lib/wabt/src/lexer-source-line-finder.cc +++ b/lib/wabt/src/lexer-source-line-finder.cc @@ -22,7 +22,7 @@ #define CHECK_RESULT(expr) \ do { \ - if (WABT_FAILED(expr)) \ + if (Failed(expr)) \ return Result::Error; \ } while (0) diff --git a/lib/wabt/src/lexer-source.cc b/lib/wabt/src/lexer-source.cc index 42b6e1ad7a2..7f90f3bf0c8 100644 --- a/lib/wabt/src/lexer-source.cc +++ b/lib/wabt/src/lexer-source.cc @@ -20,7 +20,7 @@ #define CHECK_RESULT(expr) \ do { \ - if (WABT_FAILED(expr)) \ + if (Failed(expr)) \ return Result::Error; \ } while (0) @@ -40,7 +40,7 @@ std::unique_ptr LexerSourceFile::Clone() { std::unique_ptr result(new LexerSourceFile(filename_)); Offset offset = 0; - if (WABT_FAILED(Tell(&offset)) || WABT_FAILED(result->Seek(offset))) + if (Failed(Tell(&offset)) || Failed(result->Seek(offset))) result.reset(); return std::move(result); diff --git a/lib/wabt/src/literal.cc b/lib/wabt/src/literal.cc index 1e1d1d99c23..bac59975855 100644 --- a/lib/wabt/src/literal.cc +++ b/lib/wabt/src/literal.cc @@ -22,56 +22,107 @@ #include #include -#define HEX_DIGIT_BITS 4 - -/* The PLUS_ONE values are used because normal IEEE floats have an implicit - * leading one, so they have an additional bit of precision. */ - -#define F32_SIGN_SHIFT 31 -#define F32_SIG_BITS 23 -#define F32_SIG_MASK 0x7fffff -#define F32_SIG_PLUS_ONE_BITS 24 -#define F32_SIG_PLUS_ONE_MASK 0xffffff -#define F32_EXP_MASK 0xff -#define F32_MIN_EXP -127 -#define F32_MAX_EXP 128 -#define F32_EXP_BIAS 127 -#define F32_QUIET_NAN_TAG 0x400000 - -#define F64_SIGN_SHIFT 63 -#define F64_SIG_BITS 52 -#define F64_SIG_MASK 0xfffffffffffffULL -#define F64_SIG_PLUS_ONE_BITS 53 -#define F64_SIG_PLUS_ONE_MASK 0x1fffffffffffffULL -#define F64_EXP_MASK 0x7ff -#define F64_MIN_EXP -1023 -#define F64_MAX_EXP 1024 -#define F64_EXP_BIAS 1023 -#define F64_QUIET_NAN_TAG 0x8000000000000ULL - namespace wabt { -static const char s_hex_digits[] = "0123456789abcdef"; +namespace { -Result parse_hexdigit(char c, uint32_t* out) { - if (static_cast(c - '0') <= 9) { - *out = c - '0'; - return Result::Ok; - } else if (static_cast(c - 'a') <= 6) { - *out = 10 + (c - 'a'); - return Result::Ok; - } else if (static_cast(c - 'A') <= 6) { - *out = 10 + (c - 'A'); - return Result::Ok; - } - return Result::Error; +int Clz(uint32_t value) { + return value == 0 ? 32 : wabt_clz_u32(value); } -/* return 1 if the non-NULL-terminated string starting with |start| and ending - with |end| starts with the NULL-terminated string |prefix|. */ -static bool string_starts_with(const char* start, +int Clz(uint64_t value) { + return value == 0 ? 64 : wabt_clz_u64(value); +} + +template +struct FloatTraitsBase {}; + +// The "PlusOne" values are used because normal IEEE floats have an implicit +// leading one, so they have an additional bit of precision. + +template <> +struct FloatTraitsBase { + typedef uint32_t Uint; + static constexpr int kBits = sizeof(Uint) * 8; + static constexpr int kSigBits = 23; + static constexpr float kHugeVal = HUGE_VALF; + static constexpr int kMaxHexBufferSize = WABT_MAX_FLOAT_HEX; + + static float Strto(const char* s, char** endptr) { return strtof(s, endptr); } +}; + +template <> +struct FloatTraitsBase { + typedef uint64_t Uint; + static constexpr int kBits = sizeof(Uint) * 8; + static constexpr int kSigBits = 52; + static constexpr float kHugeVal = HUGE_VAL; + static constexpr int kMaxHexBufferSize = WABT_MAX_DOUBLE_HEX; + + static double Strto(const char* s, char** endptr) { + return strtod(s, endptr); + } +}; + +template +struct FloatTraits : FloatTraitsBase { + typedef typename FloatTraitsBase::Uint Uint; + using FloatTraitsBase::kBits; + using FloatTraitsBase::kSigBits; + + static constexpr int kExpBits = kBits - kSigBits - 1; + static constexpr int kSignShift = kBits - 1; + static constexpr Uint kSigMask = (Uint(1) << kSigBits) - 1; + static constexpr int kSigPlusOneBits = kSigBits + 1; + static constexpr Uint kSigPlusOneMask = (Uint(1) << kSigPlusOneBits) - 1; + static constexpr int kExpMask = (1 << kExpBits) - 1; + static constexpr int kMaxExp = 1 << (kExpBits - 1); + static constexpr int kMinExp = -kMaxExp + 1; + static constexpr int kExpBias = -kMinExp; + static constexpr Uint kQuietNanTag = Uint(1) << (kSigBits - 1); +}; + +template +class FloatParser { + public: + typedef FloatTraits Traits; + typedef typename Traits::Uint Uint; + typedef T Float; + + static Result Parse(LiteralType, + const char* s, + const char* end, + Uint* out_bits); + + private: + static bool StringStartsWith(const char* start, const char* end, - const char* prefix) { + const char* prefix); + static Uint Make(bool sign, int exp, Uint sig); + static Uint ShiftAndRoundToNearest(Uint significand, int shift); + + static Result ParseFloat(const char* s, const char* end, Uint* out_bits); + static Result ParseNan(const char* s, const char* end, Uint* out_bits); + static Result ParseHex(const char* s, const char* end, Uint* out_bits); + static void ParseInfinity(const char* s, const char* end, Uint* out_bits); +}; + +template +class FloatWriter { + public: + typedef FloatTraits Traits; + typedef typename Traits::Uint Uint; + + static void WriteHex(char* out, size_t size, Uint bits); +}; + +// Return 1 if the non-NULL-terminated string starting with |start| and ending +// with |end| starts with the NULL-terminated string |prefix|. +template +// static +bool FloatParser::StringStartsWith(const char* start, + const char* end, + const char* prefix) { while (start < end && *prefix) { if (*start != *prefix) return false; @@ -81,116 +132,81 @@ static bool string_starts_with(const char* start, return *prefix == 0; } -Result parse_uint64(const char* s, const char* end, uint64_t* out) { - if (s == end) +// static +template +Result FloatParser::ParseFloat(const char* s, + const char* end, + Uint* out_bits) { + // Here is the normal behavior for strtof/strtod: + // + // input | errno | output | + // --------------------------------- + // overflow | ERANGE | +-HUGE_VAL | + // underflow | ERANGE | 0.0 | + // otherwise | 0 | value | + // + // So normally we need to clear errno before calling strto{f,d}, and check + // afterward whether it was set to ERANGE. + // + // glibc seems to have a bug where + // strtof("340282356779733661637539395458142568448") will return HUGE_VAL, + // but will not set errno to ERANGE. Since this function is only called when + // we know that we have parsed a "normal" number (i.e. not "inf"), we know + // that if we ever get HUGE_VAL, it must be overflow. + // + // The WebAssembly spec also ignores underflow, so we don't need to check for + // ERANGE at all. + + // WebAssembly floats can contain underscores, but strto* can't parse those, + // so remove them first. + assert(s <= end); + const size_t kBufferSize = end - s + 1; // +1 for \0. + char* buffer = static_cast(alloca(kBufferSize)); + auto buffer_end = + std::copy_if(s, end, buffer, [](char c) -> bool { return c != '_'; }); + assert(buffer_end < buffer + kBufferSize); + *buffer_end = 0; + + char* endptr; + Float value = Traits::Strto(buffer, &endptr); + if (endptr != buffer_end || + (value == Traits::kHugeVal || value == -Traits::kHugeVal)) { return Result::Error; - uint64_t value = 0; - if (*s == '0' && s + 1 < end && s[1] == 'x') { - s += 2; - if (s == end) - return Result::Error; - for (; s < end; ++s) { - uint32_t digit; - if (WABT_FAILED(parse_hexdigit(*s, &digit))) - return Result::Error; - uint64_t old_value = value; - value = value * 16 + digit; - /* check for overflow */ - if (old_value > value) - return Result::Error; - } - } else { - for (; s < end; ++s) { - uint32_t digit = (*s - '0'); - if (digit > 9) - return Result::Error; - uint64_t old_value = value; - value = value * 10 + digit; - /* check for overflow */ - if (old_value > value) - return Result::Error; - } } - if (s != end) - return Result::Error; - *out = value; - return Result::Ok; -} -Result parse_int64(const char* s, - const char* end, - uint64_t* out, - ParseIntType parse_type) { - bool has_sign = false; - if (*s == '-' || *s == '+') { - if (parse_type == ParseIntType::UnsignedOnly) - return Result::Error; - if (*s == '-') - has_sign = true; - s++; - } - uint64_t value = 0; - Result result = parse_uint64(s, end, &value); - if (has_sign) { - /* abs(INT64_MIN) == INT64_MAX + 1 */ - if (value > static_cast(INT64_MAX) + 1) - return Result::Error; - value = UINT64_MAX - value + 1; - } - *out = value; - return result; -} - -Result parse_int32(const char* s, - const char* end, - uint32_t* out, - ParseIntType parse_type) { - uint64_t value; - bool has_sign = false; - if (*s == '-' || *s == '+') { - if (parse_type == ParseIntType::UnsignedOnly) - return Result::Error; - if (*s == '-') - has_sign = true; - s++; - } - if (WABT_FAILED(parse_uint64(s, end, &value))) - return Result::Error; - - if (has_sign) { - /* abs(INT32_MIN) == INT32_MAX + 1 */ - if (value > static_cast(INT32_MAX) + 1) - return Result::Error; - value = UINT32_MAX - value + 1; - } else { - if (value > static_cast(UINT32_MAX)) - return Result::Error; - } - *out = static_cast(value); + memcpy(out_bits, &value, sizeof(value)); return Result::Ok; } -/* floats */ -static uint32_t make_float(bool sign, int exp, uint32_t sig) { - assert(exp >= F32_MIN_EXP && exp <= F32_MAX_EXP); - assert(sig <= F32_SIG_MASK); - return (static_cast(sign) << F32_SIGN_SHIFT) | - (static_cast(exp + F32_EXP_BIAS) << F32_SIG_BITS) | sig; +// static +template +typename FloatParser::Uint FloatParser::Make(bool sign, + int exp, + Uint sig) { + assert(exp >= Traits::kMinExp && exp <= Traits::kMaxExp); + assert(sig <= Traits::kSigMask); + return (Uint(sign) << Traits::kSignShift) | + (Uint(exp + Traits::kExpBias) << Traits::kSigBits) | sig; } -static uint32_t shift_float_and_round_to_nearest(uint32_t significand, - int shift) { +// static +template +typename FloatParser::Uint FloatParser::ShiftAndRoundToNearest( + Uint significand, + int shift) { assert(shift > 0); - /* round ties to even */ - if (significand & (1U << shift)) - significand += 1U << (shift - 1); + // Round ties to even. + if (significand & (Uint(1) << shift)) + significand += Uint(1) << (shift - 1); significand >>= shift; return significand; } -static Result parse_float_nan(const char* s, - const char* end, - uint32_t* out_bits) { +// static +template +Result FloatParser::ParseNan(const char* s, + const char* end, + Uint* out_bits) { bool is_neg = false; if (*s == '-') { is_neg = true; @@ -198,39 +214,41 @@ static Result parse_float_nan(const char* s, } else if (*s == '+') { s++; } - assert(string_starts_with(s, end, "nan")); + assert(StringStartsWith(s, end, "nan")); s += 3; - uint32_t tag; + Uint tag; if (s != end) { tag = 0; - assert(string_starts_with(s, end, ":0x")); + assert(StringStartsWith(s, end, ":0x")); s += 3; for (; s < end; ++s) { uint32_t digit; - if (WABT_FAILED(parse_hexdigit(*s, &digit))) + if (Failed(ParseHexdigit(*s, &digit))) return Result::Error; tag = tag * 16 + digit; - /* check for overflow */ - if (tag > F32_SIG_MASK) + // Check for overflow. + if (tag > Traits::kSigMask) return Result::Error; } - /* NaN cannot have a zero tag, that is reserved for infinity */ + // NaN cannot have a zero tag, that is reserved for infinity. if (tag == 0) return Result::Error; } else { - tag = F32_QUIET_NAN_TAG; + tag = Traits::kQuietNanTag; } - *out_bits = make_float(is_neg, F32_MAX_EXP, tag); + *out_bits = Make(is_neg, Traits::kMaxExp, tag); return Result::Ok; } -static void parse_float_hex(const char* s, - const char* end, - uint32_t* out_bits) { +// static +template +Result FloatParser::ParseHex(const char* s, + const char* end, + Uint* out_bits) { bool is_neg = false; if (*s == '-') { is_neg = true; @@ -238,65 +256,52 @@ static void parse_float_hex(const char* s, } else if (*s == '+') { s++; } - assert(string_starts_with(s, end, "0x")); + assert(StringStartsWith(s, end, "0x")); s += 2; - /* loop over the significand; everything up to the 'p'. - this code is a bit nasty because we want to support extra zeroes anywhere - without having to use many significand bits. - e.g. - 0x00000001.0p0 => significand = 1, significand_exponent = 0 - 0x10000000.0p0 => significand = 1, significand_exponent = 28 - 0x0.000001p0 => significand = 1, significand_exponent = -24 - */ + // Loop over the significand; everything up to the 'p'. + // This code is a bit nasty because we want to support extra zeroes anywhere + // without having to use many significand bits. + // e.g. + // 0x00000001.0p0 => significand = 1, significand_exponent = 0 + // 0x10000000.0p0 => significand = 1, significand_exponent = 28 + // 0x0.000001p0 => significand = 1, significand_exponent = -24 bool seen_dot = false; - uint32_t significand = 0; - /* how much to shift |significand| if a non-zero value is appended */ - int significand_shift = 0; - int significand_bits = 0; /* bits of |significand| */ - int significand_exponent = 0; /* exponent adjustment due to dot placement */ + Uint significand = 0; + int significand_exponent = 0; // Exponent adjustment due to dot placement. for (; s < end; ++s) { uint32_t digit; - if (*s == '.') { - if (significand != 0) - significand_exponent += significand_shift; - significand_shift = 0; - seen_dot = true; + if (*s == '_') { continue; - } else if (WABT_FAILED(parse_hexdigit(*s, &digit))) { + } else if (*s == '.') { + seen_dot = true; + } else if (Succeeded(ParseHexdigit(*s, &digit))) { + if (Traits::kBits - Clz(significand) <= Traits::kSigPlusOneBits) { + significand = (significand << 4) + digit; + if (seen_dot) + significand_exponent -= 4; + } else if (!seen_dot) { + significand_exponent += 4; + } + } else { break; } - significand_shift += HEX_DIGIT_BITS; - if (digit != 0 && (significand == 0 || - significand_bits + significand_shift <= - F32_SIG_BITS + 1 + HEX_DIGIT_BITS)) { - if (significand != 0) - significand <<= significand_shift; - if (seen_dot) - significand_exponent -= significand_shift; - significand += digit; - significand_shift = 0; - significand_bits += HEX_DIGIT_BITS; - } } - if (!seen_dot) - significand_exponent += significand_shift; - if (significand == 0) { - /* 0 or -0 */ - *out_bits = make_float(is_neg, F32_MIN_EXP, 0); - return; + // 0 or -0. + *out_bits = Make(is_neg, Traits::kMinExp, 0); + return Result::Ok; } int exponent = 0; bool exponent_is_neg = false; if (s < end) { - assert(*s == 'p'); + assert(*s == 'p' || *s == 'P'); s++; - /* exponent is always positive, but significand_exponent is signed. - significand_exponent_add is negated if exponent will be negative, so it can - be easily summed to see if the exponent is too large (see below) */ + // Exponent is always positive, but significand_exponent is signed. + // significand_exponent_add is negated if exponent will be negative, so it + // can be easily summed to see if the exponent is too large (see below). int significand_exponent_add = 0; if (*s == '-') { exponent_is_neg = true; @@ -308,10 +313,13 @@ static void parse_float_hex(const char* s, } for (; s < end; ++s) { + if (*s == '_') + continue; + uint32_t digit = (*s - '0'); assert(digit <= 9); exponent = exponent * 10 + digit; - if (exponent + significand_exponent_add >= F32_MAX_EXP) + if (exponent + significand_exponent_add >= Traits::kMaxExp) break; } } @@ -319,56 +327,63 @@ static void parse_float_hex(const char* s, if (exponent_is_neg) exponent = -exponent; - significand_bits = sizeof(uint32_t) * 8 - wabt_clz_u32(significand); - /* -1 for the implicit 1 bit of the significand */ + int significand_bits = Traits::kBits - Clz(significand); + // -1 for the implicit 1 bit of the significand. exponent += significand_exponent + significand_bits - 1; - if (exponent >= F32_MAX_EXP) { - /* inf or -inf */ - *out_bits = make_float(is_neg, F32_MAX_EXP, 0); - } else if (exponent <= F32_MIN_EXP) { - /* maybe subnormal */ - if (significand_bits > F32_SIG_BITS) { - significand = shift_float_and_round_to_nearest( - significand, significand_bits - F32_SIG_BITS); - } else if (significand_bits < F32_SIG_BITS) { - significand <<= (F32_SIG_BITS - significand_bits); + if (exponent <= Traits::kMinExp) { + // Maybe subnormal. + if (significand_bits > Traits::kSigBits) { + significand = ShiftAndRoundToNearest(significand, + significand_bits - Traits::kSigBits); + } else if (significand_bits < Traits::kSigBits) { + significand <<= (Traits::kSigBits - significand_bits); } - int shift = F32_MIN_EXP - exponent; - if (shift < F32_SIG_BITS) { + int shift = Traits::kMinExp - exponent; + if (shift < Traits::kSigBits) { if (shift) { significand = - shift_float_and_round_to_nearest(significand, shift) & F32_SIG_MASK; + ShiftAndRoundToNearest(significand, shift) & Traits::kSigMask; } - exponent = F32_MIN_EXP; + exponent = Traits::kMinExp; if (significand != 0) { - *out_bits = make_float(is_neg, exponent, significand); - return; + *out_bits = Make(is_neg, exponent, significand); + return Result::Ok; } } - /* not subnormal, too small; return 0 or -0 */ - *out_bits = make_float(is_neg, F32_MIN_EXP, 0); + // Not subnormal, too small; return 0 or -0. + *out_bits = Make(is_neg, Traits::kMinExp, 0); } else { - /* normal value */ - if (significand_bits > F32_SIG_PLUS_ONE_BITS) { - significand = shift_float_and_round_to_nearest( - significand, significand_bits - F32_SIG_PLUS_ONE_BITS); - if (significand > F32_SIG_PLUS_ONE_MASK) + // Maybe Normal value. + if (significand_bits > Traits::kSigPlusOneBits) { + significand = ShiftAndRoundToNearest( + significand, significand_bits - Traits::kSigPlusOneBits); + if (significand > Traits::kSigPlusOneMask) exponent++; - } else if (significand_bits < F32_SIG_PLUS_ONE_BITS) { - significand <<= (F32_SIG_PLUS_ONE_BITS - significand_bits); + } else if (significand_bits < Traits::kSigPlusOneBits) { + significand <<= (Traits::kSigPlusOneBits - significand_bits); } - *out_bits = make_float(is_neg, exponent, significand & F32_SIG_MASK); + if (exponent >= Traits::kMaxExp) { + // Would be inf or -inf, but the spec doesn't allow rounding hex-floats to + // infinity. + return Result::Error; + } + + *out_bits = Make(is_neg, exponent, significand & Traits::kSigMask); } + + return Result::Ok; } -static void parse_float_infinity(const char* s, - const char* end, - uint32_t* out_bits) { +// static +template +void FloatParser::ParseInfinity(const char* s, + const char* end, + Uint* out_bits) { bool is_neg = false; if (*s == '-') { is_neg = true; @@ -376,47 +391,36 @@ static void parse_float_infinity(const char* s, } else if (*s == '+') { s++; } - assert(string_starts_with(s, end, "inf")); - *out_bits = make_float(is_neg, F32_MAX_EXP, 0); + assert(StringStartsWith(s, end, "inf")); + *out_bits = Make(is_neg, Traits::kMaxExp, 0); } -Result parse_float(LiteralType literal_type, - const char* s, - const char* end, - uint32_t* out_bits) { +// static +template +Result FloatParser::Parse(LiteralType literal_type, + const char* s, + const char* end, + Uint* out_bits) { #if COMPILER_IS_MSVC - if (literal_type == LiteralType::Int && string_starts_with(s, end, "0x")) - { + if (literal_type == LiteralType::Int && StringStartsWith(s, end, "0x")) { // Some MSVC crt implementation of strtof doesn't support hex strings literal_type = LiteralType::Hexfloat; } #endif switch (literal_type) { case LiteralType::Int: - case LiteralType::Float: { - errno = 0; - char* endptr; - float value; - value = strtof(s, &endptr); - if (endptr != end || - ((value == 0 || value == HUGE_VALF || value == -HUGE_VALF) && - errno != 0)) - return Result::Error; - - memcpy(out_bits, &value, sizeof(value)); - return Result::Ok; - } + case LiteralType::Float: + return ParseFloat(s, end, out_bits); case LiteralType::Hexfloat: - parse_float_hex(s, end, out_bits); - return Result::Ok; + return ParseHex(s, end, out_bits); case LiteralType::Infinity: - parse_float_infinity(s, end, out_bits); + ParseInfinity(s, end, out_bits); return Result::Ok; case LiteralType::Nan: - return parse_float_nan(s, end, out_bits); + return ParseNan(s, end, out_bits); default: assert(0); @@ -424,38 +428,41 @@ Result parse_float(LiteralType literal_type, } } -void write_float_hex(char* out, size_t size, uint32_t bits) { - /* 1234567890123456 */ - /* -0x#.######p-### */ - /* -nan:0x###### */ - /* -inf */ - char buffer[WABT_MAX_FLOAT_HEX]; +// static +template +void FloatWriter::WriteHex(char* out, size_t size, Uint bits) { + static constexpr int kNumNybbles = Traits::kBits / 4; + static constexpr int kTopNybbleShift = Traits::kBits - 4; + static constexpr Uint kTopNybble = Uint(0xf) << kTopNybbleShift; + static const char s_hex_digits[] = "0123456789abcdef"; + + char buffer[Traits::kMaxHexBufferSize]; char* p = buffer; - bool is_neg = (bits >> F32_SIGN_SHIFT); - int exp = ((bits >> F32_SIG_BITS) & F32_EXP_MASK) - F32_EXP_BIAS; - uint32_t sig = bits & F32_SIG_MASK; + bool is_neg = (bits >> Traits::kSignShift); + int exp = ((bits >> Traits::kSigBits) & Traits::kExpMask) - Traits::kExpBias; + Uint sig = bits & Traits::kSigMask; if (is_neg) *p++ = '-'; - if (exp == F32_MAX_EXP) { - /* infinity or nan */ + if (exp == Traits::kMaxExp) { + // Infinity or nan. if (sig == 0) { strcpy(p, "inf"); p += 3; } else { strcpy(p, "nan"); p += 3; - if (sig != F32_QUIET_NAN_TAG) { + if (sig != Traits::kQuietNanTag) { strcpy(p, ":0x"); p += 3; - /* skip leading zeroes */ - int num_nybbles = sizeof(uint32_t) * 8 / 4; - while ((sig & 0xf0000000) == 0) { + // Skip leading zeroes. + int num_nybbles = kNumNybbles; + while ((sig & kTopNybble) == 0) { sig <<= 4; num_nybbles--; } while (num_nybbles) { - uint32_t nybble = (sig >> (sizeof(uint32_t) * 8 - 4)) & 0xf; + Uint nybble = (sig >> kTopNybbleShift) & 0xf; *p++ = s_hex_digits[nybble]; sig <<= 4; --num_nybbles; @@ -463,19 +470,19 @@ void write_float_hex(char* out, size_t size, uint32_t bits) { } } } else { - bool is_zero = sig == 0 && exp == F32_MIN_EXP; + bool is_zero = sig == 0 && exp == Traits::kMinExp; strcpy(p, "0x"); p += 2; *p++ = is_zero ? '0' : '1'; - /* shift sig up so the top 4-bits are at the top of the uint32 */ - sig <<= sizeof(uint32_t) * 8 - F32_SIG_BITS; + // Shift sig up so the top 4-bits are at the top of the Uint. + sig <<= Traits::kBits - Traits::kSigBits; if (sig) { - if (exp == F32_MIN_EXP) { - /* subnormal; shift the significand up, and shift out the implicit 1 */ - uint32_t leading_zeroes = wabt_clz_u32(sig); - if (leading_zeroes < 31) + if (exp == Traits::kMinExp) { + // Subnormal; shift the significand up, and shift out the implicit 1. + Uint leading_zeroes = Clz(sig); + if (leading_zeroes < Traits::kSignShift) sig <<= leading_zeroes + 1; else sig = 0; @@ -484,7 +491,7 @@ void write_float_hex(char* out, size_t size, uint32_t bits) { *p++ = '.'; while (sig) { - uint32_t nybble = (sig >> (sizeof(uint32_t) * 8 - 4)) & 0xf; + int nybble = (sig >> kTopNybbleShift) & 0xf; *p++ = s_hex_digits[nybble]; sig <<= 4; } @@ -500,8 +507,10 @@ void write_float_hex(char* out, size_t size, uint32_t bits) { } else { *p++ = '+'; } - if (exp >= 100) + if (exp >= 1000) *p++ = '1'; + if (exp >= 100) + *p++ = '0' + (exp / 100) % 10; if (exp >= 10) *p++ = '0' + (exp / 10) % 10; *p++ = '0' + exp % 10; @@ -515,347 +524,135 @@ void write_float_hex(char* out, size_t size, uint32_t bits) { out[len] = '\0'; } -/* doubles */ -static uint64_t make_double(bool sign, int exp, uint64_t sig) { - assert(exp >= F64_MIN_EXP && exp <= F64_MAX_EXP); - assert(sig <= F64_SIG_MASK); - return (static_cast(sign) << F64_SIGN_SHIFT) | - (static_cast(exp + F64_EXP_BIAS) << F64_SIG_BITS) | sig; -} - -static uint64_t shift_double_and_round_to_nearest(uint64_t significand, - int shift) { - assert(shift > 0); - /* round ties to even */ - if (significand & (static_cast(1) << shift)) - significand += static_cast(1) << (shift - 1); - significand >>= shift; - return significand; -} +} // end anonymous namespace -static Result parse_double_nan(const char* s, - const char* end, - uint64_t* out_bits) { - bool is_neg = false; - if (*s == '-') { - is_neg = true; - s++; - } else if (*s == '+') { - s++; +Result ParseHexdigit(char c, uint32_t* out) { + if (static_cast(c - '0') <= 9) { + *out = c - '0'; + return Result::Ok; + } else if (static_cast(c - 'a') <= 6) { + *out = 10 + (c - 'a'); + return Result::Ok; + } else if (static_cast(c - 'A') <= 6) { + *out = 10 + (c - 'A'); + return Result::Ok; } - assert(string_starts_with(s, end, "nan")); - s += 3; + return Result::Error; +} - uint64_t tag; - if (s != end) { - tag = 0; - if (!string_starts_with(s, end, ":0x")) +Result ParseUint64(const char* s, const char* end, uint64_t* out) { + if (s == end) + return Result::Error; + uint64_t value = 0; + if (*s == '0' && s + 1 < end && s[1] == 'x') { + s += 2; + if (s == end) return Result::Error; - s += 3; - for (; s < end; ++s) { uint32_t digit; - if (WABT_FAILED(parse_hexdigit(*s, &digit))) + if (*s == '_') + continue; + if (Failed(ParseHexdigit(*s, &digit))) return Result::Error; - tag = tag * 16 + digit; - /* check for overflow */ - if (tag > F64_SIG_MASK) + uint64_t old_value = value; + value = value * 16 + digit; + // Check for overflow. + if (old_value > value) return Result::Error; } - - /* NaN cannot have a zero tag, that is reserved for infinity */ - if (tag == 0) - return Result::Error; } else { - tag = F64_QUIET_NAN_TAG; + for (; s < end; ++s) { + if (*s == '_') + continue; + uint32_t digit = (*s - '0'); + if (digit > 9) + return Result::Error; + uint64_t old_value = value; + value = value * 10 + digit; + // Check for overflow. + if (old_value > value) + return Result::Error; + } } - - *out_bits = make_double(is_neg, F64_MAX_EXP, tag); + if (s != end) + return Result::Error; + *out = value; return Result::Ok; } -static void parse_double_hex(const char* s, - const char* end, - uint64_t* out_bits) { - bool is_neg = false; - if (*s == '-') { - is_neg = true; - s++; - } else if (*s == '+') { +Result ParseInt64(const char* s, + const char* end, + uint64_t* out, + ParseIntType parse_type) { + bool has_sign = false; + if (*s == '-' || *s == '+') { + if (parse_type == ParseIntType::UnsignedOnly) + return Result::Error; + if (*s == '-') + has_sign = true; s++; } - assert(string_starts_with(s, end, "0x")); - s += 2; - - /* see the similar comment in parse_float_hex */ - bool seen_dot = false; - uint64_t significand = 0; - /* how much to shift |significand| if a non-zero value is appended */ - int significand_shift = 0; - int significand_bits = 0; /* bits of |significand| */ - int significand_exponent = 0; /* exponent adjustment due to dot placement */ - for (; s < end; ++s) { - uint32_t digit; - if (*s == '.') { - if (significand != 0) - significand_exponent += significand_shift; - significand_shift = 0; - seen_dot = true; - continue; - } else if (WABT_FAILED(parse_hexdigit(*s, &digit))) { - break; - } - significand_shift += HEX_DIGIT_BITS; - if (digit != 0 && (significand == 0 || - significand_bits + significand_shift <= - F64_SIG_BITS + 1 + HEX_DIGIT_BITS)) { - if (significand != 0) - significand <<= significand_shift; - if (seen_dot) - significand_exponent -= significand_shift; - significand += digit; - significand_shift = 0; - significand_bits += HEX_DIGIT_BITS; - } - } - - if (!seen_dot) - significand_exponent += significand_shift; - - if (significand == 0) { - /* 0 or -0 */ - *out_bits = make_double(is_neg, F64_MIN_EXP, 0); - return; + uint64_t value = 0; + Result result = ParseUint64(s, end, &value); + if (has_sign) { + // abs(INT64_MIN) == INT64_MAX + 1. + if (value > static_cast(INT64_MAX) + 1) + return Result::Error; + value = UINT64_MAX - value + 1; } + *out = value; + return result; +} - int exponent = 0; - bool exponent_is_neg = false; - if (s < end) { - assert(*s == 'p'); +Result ParseInt32(const char* s, + const char* end, + uint32_t* out, + ParseIntType parse_type) { + uint64_t value; + bool has_sign = false; + if (*s == '-' || *s == '+') { + if (parse_type == ParseIntType::UnsignedOnly) + return Result::Error; + if (*s == '-') + has_sign = true; s++; - - /* exponent is always positive, but significand_exponent is signed. - significand_exponent_add is negated if exponent will be negative, so it can - be easily summed to see if the exponent is too large (see below) */ - int significand_exponent_add = 0; - if (*s == '-') { - exponent_is_neg = true; - significand_exponent_add = -significand_exponent; - s++; - } else if (*s == '+') { - s++; - significand_exponent_add = significand_exponent; - } - - for (; s < end; ++s) { - uint32_t digit = (*s - '0'); - assert(digit <= 9); - exponent = exponent * 10 + digit; - if (exponent + significand_exponent_add >= F64_MAX_EXP) - break; - } } + if (Failed(ParseUint64(s, end, &value))) + return Result::Error; - if (exponent_is_neg) - exponent = -exponent; - - significand_bits = sizeof(uint64_t) * 8 - wabt_clz_u64(significand); - /* -1 for the implicit 1 bit of the significand */ - exponent += significand_exponent + significand_bits - 1; - - if (exponent >= F64_MAX_EXP) { - /* inf or -inf */ - *out_bits = make_double(is_neg, F64_MAX_EXP, 0); - } else if (exponent <= F64_MIN_EXP) { - /* maybe subnormal */ - if (significand_bits > F64_SIG_BITS) { - significand = shift_double_and_round_to_nearest( - significand, significand_bits - F64_SIG_BITS); - } else if (significand_bits < F64_SIG_BITS) { - significand <<= (F64_SIG_BITS - significand_bits); - } - - int shift = F64_MIN_EXP - exponent; - if (shift < F64_SIG_BITS) { - if (shift) { - significand = shift_double_and_round_to_nearest(significand, shift) & - F64_SIG_MASK; - } - exponent = F64_MIN_EXP; - - if (significand != 0) { - *out_bits = make_double(is_neg, exponent, significand); - return; - } - } - - /* not subnormal, too small; return 0 or -0 */ - *out_bits = make_double(is_neg, F64_MIN_EXP, 0); + if (has_sign) { + // abs(INT32_MIN) == INT32_MAX + 1. + if (value > static_cast(INT32_MAX) + 1) + return Result::Error; + value = UINT32_MAX - value + 1; } else { - /* normal value */ - if (significand_bits > F64_SIG_PLUS_ONE_BITS) { - significand = shift_double_and_round_to_nearest( - significand, significand_bits - F64_SIG_PLUS_ONE_BITS); - if (significand > F64_SIG_PLUS_ONE_MASK) - exponent++; - } else if (significand_bits < F64_SIG_PLUS_ONE_BITS) { - significand <<= (F64_SIG_PLUS_ONE_BITS - significand_bits); - } - - *out_bits = make_double(is_neg, exponent, significand & F64_SIG_MASK); + if (value > static_cast(UINT32_MAX)) + return Result::Error; } + *out = static_cast(value); + return Result::Ok; } -static void parse_double_infinity(const char* s, - const char* end, - uint64_t* out_bits) { - bool is_neg = false; - if (*s == '-') { - is_neg = true; - s++; - } else if (*s == '+') { - s++; - } - assert(string_starts_with(s, end, "inf")); - *out_bits = make_double(is_neg, F64_MAX_EXP, 0); +Result ParseFloat(LiteralType literal_type, + const char* s, + const char* end, + uint32_t* out_bits) { + return FloatParser::Parse(literal_type, s, end, out_bits); } -Result parse_double(LiteralType literal_type, - const char* s, - const char* end, - uint64_t* out_bits) { - -#if COMPILER_IS_MSVC - if (literal_type == LiteralType::Int && string_starts_with(s, end, "0x")) - { - // Some MSVC crt implementation of strtod doesn't support hex strings - literal_type = LiteralType::Hexfloat; - } -#endif - switch (literal_type) { - case LiteralType::Int: - case LiteralType::Float: { - errno = 0; - char* endptr; - double value; - value = strtod(s, &endptr); - if (endptr != end || - ((value == 0 || value == HUGE_VAL || value == -HUGE_VAL) && - errno != 0)) - return Result::Error; - - memcpy(out_bits, &value, sizeof(value)); - return Result::Ok; - } - - case LiteralType::Hexfloat: - parse_double_hex(s, end, out_bits); - return Result::Ok; - - case LiteralType::Infinity: - parse_double_infinity(s, end, out_bits); - return Result::Ok; - - case LiteralType::Nan: - return parse_double_nan(s, end, out_bits); - - default: - assert(0); - return Result::Error; - } +Result ParseDouble(LiteralType literal_type, + const char* s, + const char* end, + uint64_t* out_bits) { + return FloatParser::Parse(literal_type, s, end, out_bits); } -void write_double_hex(char* out, size_t size, uint64_t bits) { - /* 123456789012345678901234 */ - /* -0x#.#############p-#### */ - /* -nan:0x############# */ - /* -inf */ - char buffer[WABT_MAX_DOUBLE_HEX]; - char* p = buffer; - bool is_neg = (bits >> F64_SIGN_SHIFT); - int exp = ((bits >> F64_SIG_BITS) & F64_EXP_MASK) - F64_EXP_BIAS; - uint64_t sig = bits & F64_SIG_MASK; - - if (is_neg) - *p++ = '-'; - if (exp == F64_MAX_EXP) { - /* infinity or nan */ - if (sig == 0) { - strcpy(p, "inf"); - p += 3; - } else { - strcpy(p, "nan"); - p += 3; - if (sig != F64_QUIET_NAN_TAG) { - strcpy(p, ":0x"); - p += 3; - /* skip leading zeroes */ - int num_nybbles = sizeof(uint64_t) * 8 / 4; - while ((sig & 0xf000000000000000ULL) == 0) { - sig <<= 4; - num_nybbles--; - } - while (num_nybbles) { - uint32_t nybble = (sig >> (sizeof(uint64_t) * 8 - 4)) & 0xf; - *p++ = s_hex_digits[nybble]; - sig <<= 4; - --num_nybbles; - } - } - } - } else { - bool is_zero = sig == 0 && exp == F64_MIN_EXP; - strcpy(p, "0x"); - p += 2; - *p++ = is_zero ? '0' : '1'; - - /* shift sig up so the top 4-bits are at the top of the uint32 */ - sig <<= sizeof(uint64_t) * 8 - F64_SIG_BITS; - - if (sig) { - if (exp == F64_MIN_EXP) { - /* subnormal; shift the significand up, and shift out the implicit 1 */ - uint32_t leading_zeroes = wabt_clz_u64(sig); - if (leading_zeroes < 63) - sig <<= leading_zeroes + 1; - else - sig = 0; - exp -= leading_zeroes; - } - - *p++ = '.'; - while (sig) { - uint32_t nybble = (sig >> (sizeof(uint64_t) * 8 - 4)) & 0xf; - *p++ = s_hex_digits[nybble]; - sig <<= 4; - } - } - *p++ = 'p'; - if (is_zero) { - strcpy(p, "+0"); - p += 2; - } else { - if (exp < 0) { - *p++ = '-'; - exp = -exp; - } else { - *p++ = '+'; - } - if (exp >= 1000) - *p++ = '1'; - if (exp >= 100) - *p++ = '0' + (exp / 100) % 10; - if (exp >= 10) - *p++ = '0' + (exp / 10) % 10; - *p++ = '0' + exp % 10; - } - } +void WriteFloatHex(char* buffer, size_t size, uint32_t bits) { + return FloatWriter::WriteHex(buffer, size, bits); +} - size_t len = p - buffer; - if (len >= size) - len = size - 1; - memcpy(out, buffer, len); - out[len] = '\0'; +void WriteDoubleHex(char* buffer, size_t size, uint64_t bits) { + return FloatWriter::WriteHex(buffer, size, bits); } } // namespace wabt diff --git a/lib/wabt/src/literal.h b/lib/wabt/src/literal.h index e1747c28920..f100d080b9d 100644 --- a/lib/wabt/src/literal.h +++ b/lib/wabt/src/literal.h @@ -30,6 +30,14 @@ namespace wabt { * result, the only validation that is done is for overflow, not for otherwise * bogus input. */ +enum class LiteralType { + Int, + Float, + Hexfloat, + Infinity, + Nan, +}; + enum class ParseIntType { UnsignedOnly = 0, SignedAndUnsigned = 1, @@ -39,27 +47,27 @@ enum class ParseIntType { #define WABT_MAX_FLOAT_HEX 20 #define WABT_MAX_DOUBLE_HEX 40 -Result parse_hexdigit(char c, uint32_t* out); -Result parse_int32(const char* s, - const char* end, - uint32_t* out, - ParseIntType parse_type); -Result parse_int64(const char* s, - const char* end, - uint64_t* out, - ParseIntType parse_type); -Result parse_uint64(const char* s, const char* end, uint64_t* out); -Result parse_float(LiteralType literal_type, +Result ParseHexdigit(char c, uint32_t* out); +Result ParseInt32(const char* s, + const char* end, + uint32_t* out, + ParseIntType parse_type); +Result ParseInt64(const char* s, + const char* end, + uint64_t* out, + ParseIntType parse_type); +Result ParseUint64(const char* s, const char* end, uint64_t* out); +Result ParseFloat(LiteralType literal_type, + const char* s, + const char* end, + uint32_t* out_bits); +Result ParseDouble(LiteralType literal_type, const char* s, const char* end, - uint32_t* out_bits); -Result parse_double(LiteralType literal_type, - const char* s, - const char* end, - uint64_t* out_bits); + uint64_t* out_bits); -void write_float_hex(char* buffer, size_t size, uint32_t bits); -void write_double_hex(char* buffer, size_t size, uint64_t bits); +void WriteFloatHex(char* buffer, size_t size, uint32_t bits); +void WriteDoubleHex(char* buffer, size_t size, uint64_t bits); } // namespace wabt diff --git a/lib/wabt/src/opcode.cc b/lib/wabt/src/opcode.cc index d74a058bd83..aee21f0166b 100644 --- a/lib/wabt/src/opcode.cc +++ b/lib/wabt/src/opcode.cc @@ -16,26 +16,88 @@ #include "opcode.h" +#include + +#include "feature.h" + namespace wabt { -OpcodeInfo g_opcode_info[kOpcodeCount] = { +// static +Opcode::Info Opcode::infos_[] = { +#define WABT_OPCODE(rtype, type1, type2, mem_size, prefix, code, Name, text) \ + {text, Type::rtype, Type::type1, Type::type2, \ + mem_size, prefix, code, PrefixCode(prefix, code)}, +#include "opcode.def" +#undef WABT_OPCODE +}; -#define WABT_OPCODE(rtype, type1, type2, mem_size, code, Name, text) \ - {text, Type::rtype, Type::type1, Type::type2, mem_size}, +#define WABT_OPCODE(rtype, type1, type2, mem_size, prefix, code, Name, text) \ + /* static */ Opcode Opcode::Name##_Opcode(Opcode::Name); #include "opcode.def" #undef WABT_OPCODE +// static +Opcode::Info Opcode::invalid_info_ = { + "", Type::Void, Type::Void, Type::Void, 0, 0, 0, 0, }; -bool is_naturally_aligned(Opcode opcode, Address alignment) { - Address opcode_align = get_opcode_memory_size(opcode); +// static +Opcode Opcode::FromCode(uint32_t code) { + return FromCode(0, code); +} + +// static +Opcode Opcode::FromCode(uint8_t prefix, uint32_t code) { + uint32_t prefix_code = PrefixCode(prefix, code); + auto iter = + std::lower_bound(infos_, infos_ + WABT_ARRAY_SIZE(infos_), prefix_code, + [](const Info& info, uint32_t prefix_code) { + return info.prefix_code < prefix_code; + }); + + if (iter->prefix_code != prefix_code) + return Opcode(Invalid); + + return Opcode(static_cast(iter - infos_)); +} + +Opcode::Info Opcode::GetInfo() const { + return enum_ < Invalid ? infos_[enum_] : invalid_info_; +} + +bool Opcode::IsNaturallyAligned(Address alignment) const { + Address opcode_align = GetMemorySize(); return alignment == WABT_USE_NATURAL_ALIGNMENT || alignment == opcode_align; } -Address get_opcode_alignment(Opcode opcode, Address alignment) { +Address Opcode::GetAlignment(Address alignment) const { if (alignment == WABT_USE_NATURAL_ALIGNMENT) - return get_opcode_memory_size(opcode); + return GetMemorySize(); return alignment; } -} // namespace +bool Opcode::IsEnabled(const Features& features) const { + switch (enum_) { + case Opcode::Try: + case Opcode::Catch: + case Opcode::Throw: + case Opcode::Rethrow: + case Opcode::CatchAll: + return features.exceptions_enabled(); + + case Opcode::I32TruncSSatF32: + case Opcode::I32TruncUSatF32: + case Opcode::I32TruncSSatF64: + case Opcode::I32TruncUSatF64: + case Opcode::I64TruncSSatF32: + case Opcode::I64TruncUSatF32: + case Opcode::I64TruncSSatF64: + case Opcode::I64TruncUSatF64: + return features.sat_float_to_int_enabled(); + + default: + return true; + } +} + +} // end anonymous namespace diff --git a/lib/wabt/src/opcode.def b/lib/wabt/src/opcode.def index 457108c04ef..9aa4c0ac1b2 100644 --- a/lib/wabt/src/opcode.def +++ b/lib/wabt/src/opcode.def @@ -19,206 +19,201 @@ #endif /* - * tr: result type - * t1: type of the 1st parameter - * t2: type of the 2nd parameter - * m: memory size of the operation, if any - * code: opcode - * Name: used to generate the opcode enum - * text: a string of the opcode name in the text format + * tr: result type + * t1: type of the 1st parameter + * t2: type of the 2nd parameter + * m: memory size of the operation, if any + * prefix: the 1-byte opcode prefix, if any + * code: opcode + * Name: used to generate the opcode enum + * text: a string of the opcode name in the text format * - * tr t1 t2 m code Name text - * ============================================================ */ + * tr t1 t2 m prefix code Name text + * ===================================================== */ -WABT_OPCODE(___, ___, ___, 0, 0x00, Unreachable, "unreachable") -WABT_OPCODE(___, ___, ___, 0, 0x01, Nop, "nop") -WABT_OPCODE(___, ___, ___, 0, 0x02, Block, "block") -WABT_OPCODE(___, ___, ___, 0, 0x03, Loop, "loop") -WABT_OPCODE(___, ___, ___, 0, 0x04, If, "if") -WABT_OPCODE(___, ___, ___, 0, 0x05, Else, "else") -WABT_OPCODE(___, ___, ___, 0, 0x06, Invalid_0x06, "") -WABT_OPCODE(___, ___, ___, 0, 0x07, Invalid_0x07, "") -WABT_OPCODE(___, ___, ___, 0, 0x08, Invalid_0x08, "") -WABT_OPCODE(___, ___, ___, 0, 0x09, Invalid_0x09, "") -WABT_OPCODE(___, ___, ___, 0, 0x0a, Invalid_0x0A, "") -WABT_OPCODE(___, ___, ___, 0, 0x0b, End, "end") -WABT_OPCODE(___, ___, ___, 0, 0x0c, Br, "br") -WABT_OPCODE(___, ___, ___, 0, 0x0d, BrIf, "br_if") -WABT_OPCODE(___, ___, ___, 0, 0x0e, BrTable, "br_table") -WABT_OPCODE(___, ___, ___, 0, 0x0f, Return, "return") -WABT_OPCODE(___, ___, ___, 0, 0x10, Call, "call") -WABT_OPCODE(___, ___, ___, 0, 0x11, CallIndirect, "call_indirect") -WABT_OPCODE(___, ___, ___, 0, 0x12, Invalid_0x12, "") -WABT_OPCODE(___, ___, ___, 0, 0x13, Invalid_0x13, "") -WABT_OPCODE(___, ___, ___, 0, 0x14, Invalid_0x14, "") -WABT_OPCODE(___, ___, ___, 0, 0x15, Invalid_0x15, "") -WABT_OPCODE(___, ___, ___, 0, 0x16, Invalid_0x16, "") -WABT_OPCODE(___, ___, ___, 0, 0x17, Invalid_0x17, "") -WABT_OPCODE(___, ___, ___, 0, 0x18, Invalid_0x18, "") -WABT_OPCODE(___, ___, ___, 0, 0x19, Invalid_0x19, "") -WABT_OPCODE(___, ___, ___, 0, 0x1a, Drop, "drop") -WABT_OPCODE(___, ___, ___, 0, 0x1b, Select, "select") -WABT_OPCODE(___, ___, ___, 0, 0x1c, Invalid_0x1c, "") -WABT_OPCODE(___, ___, ___, 0, 0x1d, Invalid_0x1d, "") -WABT_OPCODE(___, ___, ___, 0, 0x1e, Invalid_0x1e, "") -WABT_OPCODE(___, ___, ___, 0, 0x1f, Invalid_0x1f, "") -WABT_OPCODE(___, ___, ___, 0, 0x20, GetLocal, "get_local") -WABT_OPCODE(___, ___, ___, 0, 0x21, SetLocal, "set_local") -WABT_OPCODE(___, ___, ___, 0, 0x22, TeeLocal, "tee_local") -WABT_OPCODE(___, ___, ___, 0, 0x23, GetGlobal, "get_global") -WABT_OPCODE(___, ___, ___, 0, 0x24, SetGlobal, "set_global") -WABT_OPCODE(___, ___, ___, 0, 0x25, Invalid_0x25, "") -WABT_OPCODE(___, ___, ___, 0, 0x26, Invalid_0x26, "") -WABT_OPCODE(___, ___, ___, 0, 0x27, Invalid_0x27, "") -WABT_OPCODE(I32, I32, ___, 4, 0x28, I32Load, "i32.load") -WABT_OPCODE(I64, I32, ___, 8, 0x29, I64Load, "i64.load") -WABT_OPCODE(F32, I32, ___, 4, 0x2a, F32Load, "f32.load") -WABT_OPCODE(F64, I32, ___, 8, 0x2b, F64Load, "f64.load") -WABT_OPCODE(I32, I32, ___, 1, 0x2c, I32Load8S, "i32.load8_s") -WABT_OPCODE(I32, I32, ___, 1, 0x2d, I32Load8U, "i32.load8_u") -WABT_OPCODE(I32, I32, ___, 2, 0x2e, I32Load16S, "i32.load16_s") -WABT_OPCODE(I32, I32, ___, 2, 0x2f, I32Load16U, "i32.load16_u") -WABT_OPCODE(I64, I32, ___, 1, 0x30, I64Load8S, "i64.load8_s") -WABT_OPCODE(I64, I32, ___, 1, 0x31, I64Load8U, "i64.load8_u") -WABT_OPCODE(I64, I32, ___, 2, 0x32, I64Load16S, "i64.load16_s") -WABT_OPCODE(I64, I32, ___, 2, 0x33, I64Load16U, "i64.load16_u") -WABT_OPCODE(I64, I32, ___, 4, 0x34, I64Load32S, "i64.load32_s") -WABT_OPCODE(I64, I32, ___, 4, 0x35, I64Load32U, "i64.load32_u") -WABT_OPCODE(___, I32, I32, 4, 0x36, I32Store, "i32.store") -WABT_OPCODE(___, I32, I64, 8, 0x37, I64Store, "i64.store") -WABT_OPCODE(___, I32, F32, 4, 0x38, F32Store, "f32.store") -WABT_OPCODE(___, I32, F64, 8, 0x39, F64Store, "f64.store") -WABT_OPCODE(___, I32, I32, 1, 0x3a, I32Store8, "i32.store8") -WABT_OPCODE(___, I32, I32, 2, 0x3b, I32Store16, "i32.store16") -WABT_OPCODE(___, I32, I64, 1, 0x3c, I64Store8, "i64.store8") -WABT_OPCODE(___, I32, I64, 2, 0x3d, I64Store16, "i64.store16") -WABT_OPCODE(___, I32, I64, 4, 0x3e, I64Store32, "i64.store32") -WABT_OPCODE(I32, ___, ___, 0, 0x3f, CurrentMemory, "current_memory") -WABT_OPCODE(I32, I32, ___, 0, 0x40, GrowMemory, "grow_memory") -WABT_OPCODE(I32, ___, ___, 0, 0x41, I32Const, "i32.const") -WABT_OPCODE(I64, ___, ___, 0, 0x42, I64Const, "i64.const") -WABT_OPCODE(F32, ___, ___, 0, 0x43, F32Const, "f32.const") -WABT_OPCODE(F64, ___, ___, 0, 0x44, F64Const, "f64.const") -WABT_OPCODE(I32, I32, ___, 0, 0x45, I32Eqz, "i32.eqz") -WABT_OPCODE(I32, I32, I32, 0, 0x46, I32Eq, "i32.eq") -WABT_OPCODE(I32, I32, I32, 0, 0x47, I32Ne, "i32.ne") -WABT_OPCODE(I32, I32, I32, 0, 0x48, I32LtS, "i32.lt_s") -WABT_OPCODE(I32, I32, I32, 0, 0x49, I32LtU, "i32.lt_u") -WABT_OPCODE(I32, I32, I32, 0, 0x4a, I32GtS, "i32.gt_s") -WABT_OPCODE(I32, I32, I32, 0, 0x4b, I32GtU, "i32.gt_u") -WABT_OPCODE(I32, I32, I32, 0, 0x4c, I32LeS, "i32.le_s") -WABT_OPCODE(I32, I32, I32, 0, 0x4d, I32LeU, "i32.le_u") -WABT_OPCODE(I32, I32, I32, 0, 0x4e, I32GeS, "i32.ge_s") -WABT_OPCODE(I32, I32, I32, 0, 0x4f, I32GeU, "i32.ge_u") -WABT_OPCODE(I32, I64, ___, 0, 0x50, I64Eqz, "i64.eqz") -WABT_OPCODE(I32, I64, I64, 0, 0x51, I64Eq, "i64.eq") -WABT_OPCODE(I32, I64, I64, 0, 0x52, I64Ne, "i64.ne") -WABT_OPCODE(I32, I64, I64, 0, 0x53, I64LtS, "i64.lt_s") -WABT_OPCODE(I32, I64, I64, 0, 0x54, I64LtU, "i64.lt_u") -WABT_OPCODE(I32, I64, I64, 0, 0x55, I64GtS, "i64.gt_s") -WABT_OPCODE(I32, I64, I64, 0, 0x56, I64GtU, "i64.gt_u") -WABT_OPCODE(I32, I64, I64, 0, 0x57, I64LeS, "i64.le_s") -WABT_OPCODE(I32, I64, I64, 0, 0x58, I64LeU, "i64.le_u") -WABT_OPCODE(I32, I64, I64, 0, 0x59, I64GeS, "i64.ge_s") -WABT_OPCODE(I32, I64, I64, 0, 0x5a, I64GeU, "i64.ge_u") -WABT_OPCODE(I32, F32, F32, 0, 0x5b, F32Eq, "f32.eq") -WABT_OPCODE(I32, F32, F32, 0, 0x5c, F32Ne, "f32.ne") -WABT_OPCODE(I32, F32, F32, 0, 0x5d, F32Lt, "f32.lt") -WABT_OPCODE(I32, F32, F32, 0, 0x5e, F32Gt, "f32.gt") -WABT_OPCODE(I32, F32, F32, 0, 0x5f, F32Le, "f32.le") -WABT_OPCODE(I32, F32, F32, 0, 0x60, F32Ge, "f32.ge") -WABT_OPCODE(I32, F64, F64, 0, 0x61, F64Eq, "f64.eq") -WABT_OPCODE(I32, F64, F64, 0, 0x62, F64Ne, "f64.ne") -WABT_OPCODE(I32, F64, F64, 0, 0x63, F64Lt, "f64.lt") -WABT_OPCODE(I32, F64, F64, 0, 0x64, F64Gt, "f64.gt") -WABT_OPCODE(I32, F64, F64, 0, 0x65, F64Le, "f64.le") -WABT_OPCODE(I32, F64, F64, 0, 0x66, F64Ge, "f64.ge") -WABT_OPCODE(I32, I32, ___, 0, 0x67, I32Clz, "i32.clz") -WABT_OPCODE(I32, I32, ___, 0, 0x68, I32Ctz, "i32.ctz") -WABT_OPCODE(I32, I32, ___, 0, 0x69, I32Popcnt, "i32.popcnt") -WABT_OPCODE(I32, I32, I32, 0, 0x6a, I32Add, "i32.add") -WABT_OPCODE(I32, I32, I32, 0, 0x6b, I32Sub, "i32.sub") -WABT_OPCODE(I32, I32, I32, 0, 0x6c, I32Mul, "i32.mul") -WABT_OPCODE(I32, I32, I32, 0, 0x6d, I32DivS, "i32.div_s") -WABT_OPCODE(I32, I32, I32, 0, 0x6e, I32DivU, "i32.div_u") -WABT_OPCODE(I32, I32, I32, 0, 0x6f, I32RemS, "i32.rem_s") -WABT_OPCODE(I32, I32, I32, 0, 0x70, I32RemU, "i32.rem_u") -WABT_OPCODE(I32, I32, I32, 0, 0x71, I32And, "i32.and") -WABT_OPCODE(I32, I32, I32, 0, 0x72, I32Or, "i32.or") -WABT_OPCODE(I32, I32, I32, 0, 0x73, I32Xor, "i32.xor") -WABT_OPCODE(I32, I32, I32, 0, 0x74, I32Shl, "i32.shl") -WABT_OPCODE(I32, I32, I32, 0, 0x75, I32ShrS, "i32.shr_s") -WABT_OPCODE(I32, I32, I32, 0, 0x76, I32ShrU, "i32.shr_u") -WABT_OPCODE(I32, I32, I32, 0, 0x77, I32Rotl, "i32.rotl") -WABT_OPCODE(I32, I32, I32, 0, 0x78, I32Rotr, "i32.rotr") -WABT_OPCODE(I64, I64, ___, 0, 0x79, I64Clz, "i64.clz") -WABT_OPCODE(I64, I64, ___, 0, 0x7a, I64Ctz, "i64.ctz") -WABT_OPCODE(I64, I64, ___, 0, 0x7b, I64Popcnt, "i64.popcnt") -WABT_OPCODE(I64, I64, I64, 0, 0x7c, I64Add, "i64.add") -WABT_OPCODE(I64, I64, I64, 0, 0x7d, I64Sub, "i64.sub") -WABT_OPCODE(I64, I64, I64, 0, 0x7e, I64Mul, "i64.mul") -WABT_OPCODE(I64, I64, I64, 0, 0x7f, I64DivS, "i64.div_s") -WABT_OPCODE(I64, I64, I64, 0, 0x80, I64DivU, "i64.div_u") -WABT_OPCODE(I64, I64, I64, 0, 0x81, I64RemS, "i64.rem_s") -WABT_OPCODE(I64, I64, I64, 0, 0x82, I64RemU, "i64.rem_u") -WABT_OPCODE(I64, I64, I64, 0, 0x83, I64And, "i64.and") -WABT_OPCODE(I64, I64, I64, 0, 0x84, I64Or, "i64.or") -WABT_OPCODE(I64, I64, I64, 0, 0x85, I64Xor, "i64.xor") -WABT_OPCODE(I64, I64, I64, 0, 0x86, I64Shl, "i64.shl") -WABT_OPCODE(I64, I64, I64, 0, 0x87, I64ShrS, "i64.shr_s") -WABT_OPCODE(I64, I64, I64, 0, 0x88, I64ShrU, "i64.shr_u") -WABT_OPCODE(I64, I64, I64, 0, 0x89, I64Rotl, "i64.rotl") -WABT_OPCODE(I64, I64, I64, 0, 0x8a, I64Rotr, "i64.rotr") -WABT_OPCODE(F32, F32, F32, 0, 0x8b, F32Abs, "f32.abs") -WABT_OPCODE(F32, F32, F32, 0, 0x8c, F32Neg, "f32.neg") -WABT_OPCODE(F32, F32, F32, 0, 0x8d, F32Ceil, "f32.ceil") -WABT_OPCODE(F32, F32, F32, 0, 0x8e, F32Floor, "f32.floor") -WABT_OPCODE(F32, F32, F32, 0, 0x8f, F32Trunc, "f32.trunc") -WABT_OPCODE(F32, F32, F32, 0, 0x90, F32Nearest, "f32.nearest") -WABT_OPCODE(F32, F32, F32, 0, 0x91, F32Sqrt, "f32.sqrt") -WABT_OPCODE(F32, F32, F32, 0, 0x92, F32Add, "f32.add") -WABT_OPCODE(F32, F32, F32, 0, 0x93, F32Sub, "f32.sub") -WABT_OPCODE(F32, F32, F32, 0, 0x94, F32Mul, "f32.mul") -WABT_OPCODE(F32, F32, F32, 0, 0x95, F32Div, "f32.div") -WABT_OPCODE(F32, F32, F32, 0, 0x96, F32Min, "f32.min") -WABT_OPCODE(F32, F32, F32, 0, 0x97, F32Max, "f32.max") -WABT_OPCODE(F32, F32, F32, 0, 0x98, F32Copysign, "f32.copysign") -WABT_OPCODE(F64, F64, F64, 0, 0x99, F64Abs, "f64.abs") -WABT_OPCODE(F64, F64, F64, 0, 0x9a, F64Neg, "f64.neg") -WABT_OPCODE(F64, F64, F64, 0, 0x9b, F64Ceil, "f64.ceil") -WABT_OPCODE(F64, F64, F64, 0, 0x9c, F64Floor, "f64.floor") -WABT_OPCODE(F64, F64, F64, 0, 0x9d, F64Trunc, "f64.trunc") -WABT_OPCODE(F64, F64, F64, 0, 0x9e, F64Nearest, "f64.nearest") -WABT_OPCODE(F64, F64, F64, 0, 0x9f, F64Sqrt, "f64.sqrt") -WABT_OPCODE(F64, F64, F64, 0, 0xa0, F64Add, "f64.add") -WABT_OPCODE(F64, F64, F64, 0, 0xa1, F64Sub, "f64.sub") -WABT_OPCODE(F64, F64, F64, 0, 0xa2, F64Mul, "f64.mul") -WABT_OPCODE(F64, F64, F64, 0, 0xa3, F64Div, "f64.div") -WABT_OPCODE(F64, F64, F64, 0, 0xa4, F64Min, "f64.min") -WABT_OPCODE(F64, F64, F64, 0, 0xa5, F64Max, "f64.max") -WABT_OPCODE(F64, F64, F64, 0, 0xa6, F64Copysign, "f64.copysign") -WABT_OPCODE(I32, I64, ___, 0, 0xa7, I32WrapI64, "i32.wrap/i64") -WABT_OPCODE(I32, F32, ___, 0, 0xa8, I32TruncSF32, "i32.trunc_s/f32") -WABT_OPCODE(I32, F32, ___, 0, 0xa9, I32TruncUF32, "i32.trunc_u/f32") -WABT_OPCODE(I32, F64, ___, 0, 0xaa, I32TruncSF64, "i32.trunc_s/f64") -WABT_OPCODE(I32, F64, ___, 0, 0xab, I32TruncUF64, "i32.trunc_u/f64") -WABT_OPCODE(I64, I32, ___, 0, 0xac, I64ExtendSI32, "i64.extend_s/i32") -WABT_OPCODE(I64, I32, ___, 0, 0xad, I64ExtendUI32, "i64.extend_u/i32") -WABT_OPCODE(I64, F32, ___, 0, 0xae, I64TruncSF32, "i64.trunc_s/f32") -WABT_OPCODE(I64, F32, ___, 0, 0xaf, I64TruncUF32, "i64.trunc_u/f32") -WABT_OPCODE(I64, F64, ___, 0, 0xb0, I64TruncSF64, "i64.trunc_s/f64") -WABT_OPCODE(I64, F64, ___, 0, 0xb1, I64TruncUF64, "i64.trunc_u/f64") -WABT_OPCODE(F32, I32, ___, 0, 0xb2, F32ConvertSI32, "f32.convert_s/i32") -WABT_OPCODE(F32, I32, ___, 0, 0xb3, F32ConvertUI32, "f32.convert_u/i32") -WABT_OPCODE(F32, I64, ___, 0, 0xb4, F32ConvertSI64, "f32.convert_s/i64") -WABT_OPCODE(F32, I64, ___, 0, 0xb5, F32ConvertUI64, "f32.convert_u/i64") -WABT_OPCODE(F32, F64, ___, 0, 0xb6, F32DemoteF64, "f32.demote/f64") -WABT_OPCODE(F64, I32, ___, 0, 0xb7, F64ConvertSI32, "f64.convert_s/i32") -WABT_OPCODE(F64, I32, ___, 0, 0xb8, F64ConvertUI32, "f64.convert_u/i32") -WABT_OPCODE(F64, I64, ___, 0, 0xb9, F64ConvertSI64, "f64.convert_s/i64") -WABT_OPCODE(F64, I64, ___, 0, 0xba, F64ConvertUI64, "f64.convert_u/i64") -WABT_OPCODE(F64, F32, ___, 0, 0xbb, F64PromoteF32, "f64.promote/f32") -WABT_OPCODE(I32, F32, ___, 0, 0xbc, I32ReinterpretF32, "i32.reinterpret/f32") -WABT_OPCODE(I64, F64, ___, 0, 0xbd, I64ReinterpretF64, "i64.reinterpret/f64") -WABT_OPCODE(F32, I32, ___, 0, 0xbe, F32ReinterpretI32, "f32.reinterpret/i32") -WABT_OPCODE(F64, I64, ___, 0, 0xbf, F64ReinterpretI64, "f64.reinterpret/i64") +WABT_OPCODE(___, ___, ___, 0, 0, 0x00, Unreachable, "unreachable") +WABT_OPCODE(___, ___, ___, 0, 0, 0x01, Nop, "nop") +WABT_OPCODE(___, ___, ___, 0, 0, 0x02, Block, "block") +WABT_OPCODE(___, ___, ___, 0, 0, 0x03, Loop, "loop") +WABT_OPCODE(___, ___, ___, 0, 0, 0x04, If, "if") +WABT_OPCODE(___, ___, ___, 0, 0, 0x05, Else, "else") +WABT_OPCODE(___, ___, ___, 0, 0, 0x06, Try, "try") +WABT_OPCODE(___, ___, ___, 0, 0, 0x07, Catch, "catch") +WABT_OPCODE(___, ___, ___, 0, 0, 0x08, Throw, "throw") +WABT_OPCODE(___, ___, ___, 0, 0, 0x09, Rethrow, "rethrow") +WABT_OPCODE(___, ___, ___, 0, 0, 0x0a, CatchAll, "catch_all") +WABT_OPCODE(___, ___, ___, 0, 0, 0x0b, End, "end") +WABT_OPCODE(___, ___, ___, 0, 0, 0x0c, Br, "br") +WABT_OPCODE(___, ___, ___, 0, 0, 0x0d, BrIf, "br_if") +WABT_OPCODE(___, ___, ___, 0, 0, 0x0e, BrTable, "br_table") +WABT_OPCODE(___, ___, ___, 0, 0, 0x0f, Return, "return") +WABT_OPCODE(___, ___, ___, 0, 0, 0x10, Call, "call") +WABT_OPCODE(___, ___, ___, 0, 0, 0x11, CallIndirect, "call_indirect") +WABT_OPCODE(___, ___, ___, 0, 0, 0x1a, Drop, "drop") +WABT_OPCODE(___, ___, ___, 0, 0, 0x1b, Select, "select") +WABT_OPCODE(___, ___, ___, 0, 0, 0x20, GetLocal, "get_local") +WABT_OPCODE(___, ___, ___, 0, 0, 0x21, SetLocal, "set_local") +WABT_OPCODE(___, ___, ___, 0, 0, 0x22, TeeLocal, "tee_local") +WABT_OPCODE(___, ___, ___, 0, 0, 0x23, GetGlobal, "get_global") +WABT_OPCODE(___, ___, ___, 0, 0, 0x24, SetGlobal, "set_global") +WABT_OPCODE(I32, I32, ___, 4, 0, 0x28, I32Load, "i32.load") +WABT_OPCODE(I64, I32, ___, 8, 0, 0x29, I64Load, "i64.load") +WABT_OPCODE(F32, I32, ___, 4, 0, 0x2a, F32Load, "f32.load") +WABT_OPCODE(F64, I32, ___, 8, 0, 0x2b, F64Load, "f64.load") +WABT_OPCODE(I32, I32, ___, 1, 0, 0x2c, I32Load8S, "i32.load8_s") +WABT_OPCODE(I32, I32, ___, 1, 0, 0x2d, I32Load8U, "i32.load8_u") +WABT_OPCODE(I32, I32, ___, 2, 0, 0x2e, I32Load16S, "i32.load16_s") +WABT_OPCODE(I32, I32, ___, 2, 0, 0x2f, I32Load16U, "i32.load16_u") +WABT_OPCODE(I64, I32, ___, 1, 0, 0x30, I64Load8S, "i64.load8_s") +WABT_OPCODE(I64, I32, ___, 1, 0, 0x31, I64Load8U, "i64.load8_u") +WABT_OPCODE(I64, I32, ___, 2, 0, 0x32, I64Load16S, "i64.load16_s") +WABT_OPCODE(I64, I32, ___, 2, 0, 0x33, I64Load16U, "i64.load16_u") +WABT_OPCODE(I64, I32, ___, 4, 0, 0x34, I64Load32S, "i64.load32_s") +WABT_OPCODE(I64, I32, ___, 4, 0, 0x35, I64Load32U, "i64.load32_u") +WABT_OPCODE(___, I32, I32, 4, 0, 0x36, I32Store, "i32.store") +WABT_OPCODE(___, I32, I64, 8, 0, 0x37, I64Store, "i64.store") +WABT_OPCODE(___, I32, F32, 4, 0, 0x38, F32Store, "f32.store") +WABT_OPCODE(___, I32, F64, 8, 0, 0x39, F64Store, "f64.store") +WABT_OPCODE(___, I32, I32, 1, 0, 0x3a, I32Store8, "i32.store8") +WABT_OPCODE(___, I32, I32, 2, 0, 0x3b, I32Store16, "i32.store16") +WABT_OPCODE(___, I32, I64, 1, 0, 0x3c, I64Store8, "i64.store8") +WABT_OPCODE(___, I32, I64, 2, 0, 0x3d, I64Store16, "i64.store16") +WABT_OPCODE(___, I32, I64, 4, 0, 0x3e, I64Store32, "i64.store32") +WABT_OPCODE(I32, ___, ___, 0, 0, 0x3f, CurrentMemory, "current_memory") +WABT_OPCODE(I32, I32, ___, 0, 0, 0x40, GrowMemory, "grow_memory") +WABT_OPCODE(I32, ___, ___, 0, 0, 0x41, I32Const, "i32.const") +WABT_OPCODE(I64, ___, ___, 0, 0, 0x42, I64Const, "i64.const") +WABT_OPCODE(F32, ___, ___, 0, 0, 0x43, F32Const, "f32.const") +WABT_OPCODE(F64, ___, ___, 0, 0, 0x44, F64Const, "f64.const") +WABT_OPCODE(I32, I32, ___, 0, 0, 0x45, I32Eqz, "i32.eqz") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x46, I32Eq, "i32.eq") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x47, I32Ne, "i32.ne") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x48, I32LtS, "i32.lt_s") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x49, I32LtU, "i32.lt_u") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x4a, I32GtS, "i32.gt_s") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x4b, I32GtU, "i32.gt_u") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x4c, I32LeS, "i32.le_s") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x4d, I32LeU, "i32.le_u") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x4e, I32GeS, "i32.ge_s") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x4f, I32GeU, "i32.ge_u") +WABT_OPCODE(I32, I64, ___, 0, 0, 0x50, I64Eqz, "i64.eqz") +WABT_OPCODE(I32, I64, I64, 0, 0, 0x51, I64Eq, "i64.eq") +WABT_OPCODE(I32, I64, I64, 0, 0, 0x52, I64Ne, "i64.ne") +WABT_OPCODE(I32, I64, I64, 0, 0, 0x53, I64LtS, "i64.lt_s") +WABT_OPCODE(I32, I64, I64, 0, 0, 0x54, I64LtU, "i64.lt_u") +WABT_OPCODE(I32, I64, I64, 0, 0, 0x55, I64GtS, "i64.gt_s") +WABT_OPCODE(I32, I64, I64, 0, 0, 0x56, I64GtU, "i64.gt_u") +WABT_OPCODE(I32, I64, I64, 0, 0, 0x57, I64LeS, "i64.le_s") +WABT_OPCODE(I32, I64, I64, 0, 0, 0x58, I64LeU, "i64.le_u") +WABT_OPCODE(I32, I64, I64, 0, 0, 0x59, I64GeS, "i64.ge_s") +WABT_OPCODE(I32, I64, I64, 0, 0, 0x5a, I64GeU, "i64.ge_u") +WABT_OPCODE(I32, F32, F32, 0, 0, 0x5b, F32Eq, "f32.eq") +WABT_OPCODE(I32, F32, F32, 0, 0, 0x5c, F32Ne, "f32.ne") +WABT_OPCODE(I32, F32, F32, 0, 0, 0x5d, F32Lt, "f32.lt") +WABT_OPCODE(I32, F32, F32, 0, 0, 0x5e, F32Gt, "f32.gt") +WABT_OPCODE(I32, F32, F32, 0, 0, 0x5f, F32Le, "f32.le") +WABT_OPCODE(I32, F32, F32, 0, 0, 0x60, F32Ge, "f32.ge") +WABT_OPCODE(I32, F64, F64, 0, 0, 0x61, F64Eq, "f64.eq") +WABT_OPCODE(I32, F64, F64, 0, 0, 0x62, F64Ne, "f64.ne") +WABT_OPCODE(I32, F64, F64, 0, 0, 0x63, F64Lt, "f64.lt") +WABT_OPCODE(I32, F64, F64, 0, 0, 0x64, F64Gt, "f64.gt") +WABT_OPCODE(I32, F64, F64, 0, 0, 0x65, F64Le, "f64.le") +WABT_OPCODE(I32, F64, F64, 0, 0, 0x66, F64Ge, "f64.ge") +WABT_OPCODE(I32, I32, ___, 0, 0, 0x67, I32Clz, "i32.clz") +WABT_OPCODE(I32, I32, ___, 0, 0, 0x68, I32Ctz, "i32.ctz") +WABT_OPCODE(I32, I32, ___, 0, 0, 0x69, I32Popcnt, "i32.popcnt") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x6a, I32Add, "i32.add") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x6b, I32Sub, "i32.sub") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x6c, I32Mul, "i32.mul") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x6d, I32DivS, "i32.div_s") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x6e, I32DivU, "i32.div_u") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x6f, I32RemS, "i32.rem_s") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x70, I32RemU, "i32.rem_u") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x71, I32And, "i32.and") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x72, I32Or, "i32.or") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x73, I32Xor, "i32.xor") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x74, I32Shl, "i32.shl") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x75, I32ShrS, "i32.shr_s") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x76, I32ShrU, "i32.shr_u") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x77, I32Rotl, "i32.rotl") +WABT_OPCODE(I32, I32, I32, 0, 0, 0x78, I32Rotr, "i32.rotr") +WABT_OPCODE(I64, I64, ___, 0, 0, 0x79, I64Clz, "i64.clz") +WABT_OPCODE(I64, I64, ___, 0, 0, 0x7a, I64Ctz, "i64.ctz") +WABT_OPCODE(I64, I64, ___, 0, 0, 0x7b, I64Popcnt, "i64.popcnt") +WABT_OPCODE(I64, I64, I64, 0, 0, 0x7c, I64Add, "i64.add") +WABT_OPCODE(I64, I64, I64, 0, 0, 0x7d, I64Sub, "i64.sub") +WABT_OPCODE(I64, I64, I64, 0, 0, 0x7e, I64Mul, "i64.mul") +WABT_OPCODE(I64, I64, I64, 0, 0, 0x7f, I64DivS, "i64.div_s") +WABT_OPCODE(I64, I64, I64, 0, 0, 0x80, I64DivU, "i64.div_u") +WABT_OPCODE(I64, I64, I64, 0, 0, 0x81, I64RemS, "i64.rem_s") +WABT_OPCODE(I64, I64, I64, 0, 0, 0x82, I64RemU, "i64.rem_u") +WABT_OPCODE(I64, I64, I64, 0, 0, 0x83, I64And, "i64.and") +WABT_OPCODE(I64, I64, I64, 0, 0, 0x84, I64Or, "i64.or") +WABT_OPCODE(I64, I64, I64, 0, 0, 0x85, I64Xor, "i64.xor") +WABT_OPCODE(I64, I64, I64, 0, 0, 0x86, I64Shl, "i64.shl") +WABT_OPCODE(I64, I64, I64, 0, 0, 0x87, I64ShrS, "i64.shr_s") +WABT_OPCODE(I64, I64, I64, 0, 0, 0x88, I64ShrU, "i64.shr_u") +WABT_OPCODE(I64, I64, I64, 0, 0, 0x89, I64Rotl, "i64.rotl") +WABT_OPCODE(I64, I64, I64, 0, 0, 0x8a, I64Rotr, "i64.rotr") +WABT_OPCODE(F32, F32, F32, 0, 0, 0x8b, F32Abs, "f32.abs") +WABT_OPCODE(F32, F32, F32, 0, 0, 0x8c, F32Neg, "f32.neg") +WABT_OPCODE(F32, F32, F32, 0, 0, 0x8d, F32Ceil, "f32.ceil") +WABT_OPCODE(F32, F32, F32, 0, 0, 0x8e, F32Floor, "f32.floor") +WABT_OPCODE(F32, F32, F32, 0, 0, 0x8f, F32Trunc, "f32.trunc") +WABT_OPCODE(F32, F32, F32, 0, 0, 0x90, F32Nearest, "f32.nearest") +WABT_OPCODE(F32, F32, F32, 0, 0, 0x91, F32Sqrt, "f32.sqrt") +WABT_OPCODE(F32, F32, F32, 0, 0, 0x92, F32Add, "f32.add") +WABT_OPCODE(F32, F32, F32, 0, 0, 0x93, F32Sub, "f32.sub") +WABT_OPCODE(F32, F32, F32, 0, 0, 0x94, F32Mul, "f32.mul") +WABT_OPCODE(F32, F32, F32, 0, 0, 0x95, F32Div, "f32.div") +WABT_OPCODE(F32, F32, F32, 0, 0, 0x96, F32Min, "f32.min") +WABT_OPCODE(F32, F32, F32, 0, 0, 0x97, F32Max, "f32.max") +WABT_OPCODE(F32, F32, F32, 0, 0, 0x98, F32Copysign, "f32.copysign") +WABT_OPCODE(F64, F64, F64, 0, 0, 0x99, F64Abs, "f64.abs") +WABT_OPCODE(F64, F64, F64, 0, 0, 0x9a, F64Neg, "f64.neg") +WABT_OPCODE(F64, F64, F64, 0, 0, 0x9b, F64Ceil, "f64.ceil") +WABT_OPCODE(F64, F64, F64, 0, 0, 0x9c, F64Floor, "f64.floor") +WABT_OPCODE(F64, F64, F64, 0, 0, 0x9d, F64Trunc, "f64.trunc") +WABT_OPCODE(F64, F64, F64, 0, 0, 0x9e, F64Nearest, "f64.nearest") +WABT_OPCODE(F64, F64, F64, 0, 0, 0x9f, F64Sqrt, "f64.sqrt") +WABT_OPCODE(F64, F64, F64, 0, 0, 0xa0, F64Add, "f64.add") +WABT_OPCODE(F64, F64, F64, 0, 0, 0xa1, F64Sub, "f64.sub") +WABT_OPCODE(F64, F64, F64, 0, 0, 0xa2, F64Mul, "f64.mul") +WABT_OPCODE(F64, F64, F64, 0, 0, 0xa3, F64Div, "f64.div") +WABT_OPCODE(F64, F64, F64, 0, 0, 0xa4, F64Min, "f64.min") +WABT_OPCODE(F64, F64, F64, 0, 0, 0xa5, F64Max, "f64.max") +WABT_OPCODE(F64, F64, F64, 0, 0, 0xa6, F64Copysign, "f64.copysign") +WABT_OPCODE(I32, I64, ___, 0, 0, 0xa7, I32WrapI64, "i32.wrap/i64") +WABT_OPCODE(I32, F32, ___, 0, 0, 0xa8, I32TruncSF32, "i32.trunc_s/f32") +WABT_OPCODE(I32, F32, ___, 0, 0, 0xa9, I32TruncUF32, "i32.trunc_u/f32") +WABT_OPCODE(I32, F64, ___, 0, 0, 0xaa, I32TruncSF64, "i32.trunc_s/f64") +WABT_OPCODE(I32, F64, ___, 0, 0, 0xab, I32TruncUF64, "i32.trunc_u/f64") +WABT_OPCODE(I64, I32, ___, 0, 0, 0xac, I64ExtendSI32, "i64.extend_s/i32") +WABT_OPCODE(I64, I32, ___, 0, 0, 0xad, I64ExtendUI32, "i64.extend_u/i32") +WABT_OPCODE(I64, F32, ___, 0, 0, 0xae, I64TruncSF32, "i64.trunc_s/f32") +WABT_OPCODE(I64, F32, ___, 0, 0, 0xaf, I64TruncUF32, "i64.trunc_u/f32") +WABT_OPCODE(I64, F64, ___, 0, 0, 0xb0, I64TruncSF64, "i64.trunc_s/f64") +WABT_OPCODE(I64, F64, ___, 0, 0, 0xb1, I64TruncUF64, "i64.trunc_u/f64") +WABT_OPCODE(F32, I32, ___, 0, 0, 0xb2, F32ConvertSI32, "f32.convert_s/i32") +WABT_OPCODE(F32, I32, ___, 0, 0, 0xb3, F32ConvertUI32, "f32.convert_u/i32") +WABT_OPCODE(F32, I64, ___, 0, 0, 0xb4, F32ConvertSI64, "f32.convert_s/i64") +WABT_OPCODE(F32, I64, ___, 0, 0, 0xb5, F32ConvertUI64, "f32.convert_u/i64") +WABT_OPCODE(F32, F64, ___, 0, 0, 0xb6, F32DemoteF64, "f32.demote/f64") +WABT_OPCODE(F64, I32, ___, 0, 0, 0xb7, F64ConvertSI32, "f64.convert_s/i32") +WABT_OPCODE(F64, I32, ___, 0, 0, 0xb8, F64ConvertUI32, "f64.convert_u/i32") +WABT_OPCODE(F64, I64, ___, 0, 0, 0xb9, F64ConvertSI64, "f64.convert_s/i64") +WABT_OPCODE(F64, I64, ___, 0, 0, 0xba, F64ConvertUI64, "f64.convert_u/i64") +WABT_OPCODE(F64, F32, ___, 0, 0, 0xbb, F64PromoteF32, "f64.promote/f32") +WABT_OPCODE(I32, F32, ___, 0, 0, 0xbc, I32ReinterpretF32, "i32.reinterpret/f32") +WABT_OPCODE(I64, F64, ___, 0, 0, 0xbd, I64ReinterpretF64, "i64.reinterpret/f64") +WABT_OPCODE(F32, I32, ___, 0, 0, 0xbe, F32ReinterpretI32, "f32.reinterpret/i32") +WABT_OPCODE(F64, I64, ___, 0, 0, 0xbf, F64ReinterpretI64, "f64.reinterpret/i64") + +WABT_OPCODE(I32, F32, ___, 0, 0xfc, 0x00, I32TruncSSatF32, "i32.trunc_s:sat/f32") +WABT_OPCODE(I32, F32, ___, 0, 0xfc, 0x01, I32TruncUSatF32, "i32.trunc_u:sat/f32") +WABT_OPCODE(I32, F64, ___, 0, 0xfc, 0x02, I32TruncSSatF64, "i32.trunc_s:sat/f64") +WABT_OPCODE(I32, F64, ___, 0, 0xfc, 0x03, I32TruncUSatF64, "i32.trunc_u:sat/f64") +WABT_OPCODE(I64, F32, ___, 0, 0xfc, 0x04, I64TruncSSatF32, "i64.trunc_s:sat/f32") +WABT_OPCODE(I64, F32, ___, 0, 0xfc, 0x05, I64TruncUSatF32, "i64.trunc_u:sat/f32") +WABT_OPCODE(I64, F64, ___, 0, 0xfc, 0x06, I64TruncSSatF64, "i64.trunc_s:sat/f64") +WABT_OPCODE(I64, F64, ___, 0, 0xfc, 0x07, I64TruncUSatF64, "i64.trunc_u:sat/f64") diff --git a/lib/wabt/src/opcode.h b/lib/wabt/src/opcode.h index 2b0be32204e..fb876d94b16 100644 --- a/lib/wabt/src/opcode.h +++ b/lib/wabt/src/opcode.h @@ -21,61 +21,82 @@ namespace wabt { -enum class Opcode { +class Features; + +struct Opcode { + // Opcode enumerations. + // + // NOTE: this enum does not match the binary encoding. + // + enum Enum { +#define WABT_OPCODE(rtype, type1, type2, mem_size, prefix, code, Name, text) \ + Name, +#include "opcode.def" +#undef WABT_OPCODE + Invalid, + }; -#define WABT_OPCODE(rtype, type1, type2, mem_size, code, Name, text) \ - Name = code, + // Static opcode objects. +#define WABT_OPCODE(rtype, type1, type2, mem_size, prefix, code, Name, text) \ + static Opcode Name##_Opcode; #include "opcode.def" #undef WABT_OPCODE - First = Unreachable, - Last = F64ReinterpretI64, -}; -static const int kOpcodeCount = WABT_ENUM_COUNT(Opcode); - -struct OpcodeInfo { - const char* name; - Type result_type; - Type param1_type; - Type param2_type; - Address memory_size; + Opcode() = default; // Provided so Opcode can be member of a union. + Opcode(Enum e) : enum_(e) {} + operator Enum() const { return enum_; } + + static Opcode FromCode(uint32_t); + static Opcode FromCode(uint8_t prefix, uint32_t code); + bool HasPrefix() const { return GetInfo().prefix != 0; } + uint8_t GetPrefix() const { return GetInfo().prefix; } + uint32_t GetCode() const { return GetInfo().code; } + size_t GetLength() const { return HasPrefix() ? 2 : 1; } + const char* GetName() const { return GetInfo().name; } + Type GetResultType() const { return GetInfo().result_type; } + Type GetParamType1() const { return GetInfo().param1_type; } + Type GetParamType2() const { return GetInfo().param2_type; } + Address GetMemorySize() const { return GetInfo().memory_size; } + + // Return 1 if |alignment| matches the alignment of |opcode|, or if + // |alignment| is WABT_USE_NATURAL_ALIGNMENT. + bool IsNaturallyAligned(Address alignment) const; + + // If |alignment| is WABT_USE_NATURAL_ALIGNMENT, return the alignment of + // |opcode|, else return |alignment|. + Address GetAlignment(Address alignment) const; + + static bool IsPrefixByte(uint8_t byte) { return byte >= kFirstPrefix; } + + bool IsEnabled(const Features& features) const; + + private: + static const uint32_t kFirstPrefix = 0xfc; + + struct Info { + const char* name; + Type result_type; + Type param1_type; + Type param2_type; + Address memory_size; + uint8_t prefix; + uint32_t code; + uint32_t prefix_code; // See PrefixCode below. Used for fast lookup. + }; + + static uint32_t PrefixCode(uint8_t prefix, uint32_t code) { + // For now, 8 bits is enough for all codes. + assert(code < 0x100); + return (prefix << 8) | code; + } + + Info GetInfo() const; + static Info infos_[]; + static Info invalid_info_; + + Enum enum_; }; -// Return 1 if |alignment| matches the alignment of |opcode|, or if |alignment| -// is WABT_USE_NATURAL_ALIGNMENT. -bool is_naturally_aligned(Opcode opcode, Address alignment); - -// If |alignment| is WABT_USE_NATURAL_ALIGNMENT, return the alignment of -// |opcode|, else return |alignment|. -Address get_opcode_alignment(Opcode opcode, Address alignment); - -extern OpcodeInfo g_opcode_info[]; - -inline const char* get_opcode_name(Opcode opcode) { - assert(static_cast(opcode) < kOpcodeCount); - return g_opcode_info[static_cast(opcode)].name; -} - -inline Type get_opcode_result_type(Opcode opcode) { - assert(static_cast(opcode) < kOpcodeCount); - return g_opcode_info[static_cast(opcode)].result_type; -} - -inline Type get_opcode_param_type_1(Opcode opcode) { - assert(static_cast(opcode) < kOpcodeCount); - return g_opcode_info[static_cast(opcode)].param1_type; -} - -inline Type get_opcode_param_type_2(Opcode opcode) { - assert(static_cast(opcode) < kOpcodeCount); - return g_opcode_info[static_cast(opcode)].param2_type; -} - -inline int get_opcode_memory_size(Opcode opcode) { - assert(static_cast(opcode) < kOpcodeCount); - return g_opcode_info[static_cast(opcode)].memory_size; -} - -} // namespace +} // end anonymous namespace #endif // WABT_OPCODE_H_ diff --git a/lib/wabt/src/prebuilt/wast-lexer-gen.cc b/lib/wabt/src/prebuilt/wast-lexer-gen.cc index 042011ee5b6..b312e09f60f 100644 --- a/lib/wabt/src/prebuilt/wast-lexer-gen.cc +++ b/lib/wabt/src/prebuilt/wast-lexer-gen.cc @@ -23,39 +23,23 @@ #include "config.h" +#include "circular-array.h" +#include "error-handler.h" #include "lexer-source.h" #include "wast-parser.h" -#include "wast-parser-lexer-shared.h" - -/* must be included after so some typedefs will be defined */ -#include "wast-parser-gen.hh" #define YYMAXFILL 29 #define INITIAL_LEXER_BUFFER_SIZE (64 * 1024) -#define YY_USER_ACTION \ - { \ - loc->filename = filename_; \ - loc->line = line_; \ - loc->first_column = COLUMN(token_); \ - loc->last_column = COLUMN(cursor_); \ - } - -#define RETURN(name) \ - YY_USER_ACTION; \ - return WABT_TOKEN_TYPE_##name - -#define ERROR(...) \ - YY_USER_ACTION; \ - wast_parser_error(loc, this, parser, __VA_ARGS__) +#define ERROR(...) parser->Error(GetLocation(), __VA_ARGS__) #define BEGIN(c) cond = (c) -#define FILL(n) \ - do { \ - if (WABT_FAILED(Fill(loc, parser, (n)))) { \ - RETURN(EOF); \ - } \ +#define FILL(n) \ + do { \ + if (Failed(Fill((n)))) { \ + RETURN(Eof); \ + } \ } while (0) #define MAYBE_MALFORMED_UTF8(desc) \ @@ -64,8 +48,8 @@ } \ continue -#define yytext (token_) -#define yyleng (cursor_ - token_) +#define yytext (next_pos_) +#define yyleng (cursor_ - next_pos_) /* p must be a pointer somewhere in the lexer buffer */ #define FILE_OFFSET(p) ((p) - (buffer_) + buffer_file_offset_) @@ -78,25 +62,167 @@ line_file_offset_ = FILE_OFFSET(cursor_); \ } while (0) -#define TEXT \ - lval->text.start = yytext; \ - lval->text.length = yyleng +#define RETURN(token) return Token(GetLocation(), TokenType::token); -#define TEXT_AT(offset) \ - lval->text.start = yytext + offset; \ - lval->text.length = yyleng - offset +#define RETURN_LITERAL(token, literal) \ + return Token(GetLocation(), TokenType::token, \ + MakeLiteral(LiteralType::literal)) -#define TYPE(type_) lval->type = Type::type_ +#define RETURN_TYPE(token, type) \ + return Token(GetLocation(), TokenType::token, Type::type) -#define OPCODE(name) lval->opcode = Opcode::name +#define RETURN_OPCODE0(token) \ + return Token(GetLocation(), TokenType::token, Opcode::token) -#define LITERAL(type_) \ - lval->literal.type = LiteralType::type_; \ - lval->literal.text.start = yytext; \ - lval->literal.text.length = yyleng +#define RETURN_OPCODE(token, opcode) \ + return Token(GetLocation(), TokenType::token, Opcode::opcode) + +#define RETURN_TEXT(token) \ + return Token(GetLocation(), TokenType::token, GetText()) + +#define RETURN_TEXT_AT(token, at) \ + return Token(GetLocation(), TokenType::token, GetText(at)) namespace wabt { +const char* GetTokenTypeName(TokenType token_type) { + static const char* s_names[] = { + "Invalid", + "Reserved", + "EOF", + "(", + ")", + "NAT", + "INT", + "FLOAT", + "TEXT", + "VAR", + "VALUETYPE", + "anyfunc", + "mut", + "nop", + "drop", + "block", + "end", + "if", + "then", + "else", + "loop", + "br", + "br_if", + "br_table", + "try", + "catch", + "catch_all", + "throw", + "rethrow", + "call", + "call_indirect", + "return", + "get_local", + "set_local", + "tee_local", + "get_global", + "set_global", + "LOAD", + "STORE", + "offset=", + "align=", + "CONST", + "UNARY", + "BINARY", + "COMPARE", + "CONVERT", + "select", + "unreachable", + "current_memory", + "grow_memory", + "func", + "start", + "type", + "param", + "result", + "local", + "global", + "table", + "elem", + "memory", + "data", + "offset", + "import", + "export", + "except", + "module", + "bin", + "quote", + "register", + "invoke", + "get", + "assert_malformed", + "assert_invalid", + "assert_unlinkable", + "assert_return", + "assert_return_canonical_nan", + "assert_return_arithmetic_nan", + "assert_trap", + "assert_exhaustion", + }; + + static_assert( + WABT_ARRAY_SIZE(s_names) == WABT_ENUM_COUNT(TokenType), + "Expected TokenType names list length to match number of TokenTypes."); + + int x = static_cast(token_type); + if (x < WABT_ENUM_COUNT(TokenType)) + return s_names[x]; + + return "Invalid"; +} + +Token::Token(Location loc, TokenType token_type) + : loc(loc), token_type(token_type) {} + +Token::Token(Location loc, TokenType token_type, Type type) + : loc(loc), token_type(token_type), type(type) {} + +Token::Token(Location loc, TokenType token_type, StringTerminal text) + : loc(loc), token_type(token_type), text(text) {} + +Token::Token(Location loc, TokenType token_type, Opcode opcode) + : loc(loc), token_type(token_type), opcode(opcode) {} + +Token::Token(Location loc, TokenType token_type, LiteralTerminal literal) + : loc(loc), token_type(token_type), literal(literal) {} + +std::string Token::to_string() const { + switch (token_type) { + case TokenType::Nat: + case TokenType::Int: + case TokenType::Float: + return literal.text.to_string(); + + case TokenType::Reserved: + case TokenType::Text: + case TokenType::Var: + return text.to_string(); + + case TokenType::ValueType: + return GetTypeName(type); + + case TokenType::Load: + case TokenType::Store: + case TokenType::Const: + case TokenType::Unary: + case TokenType::Binary: + case TokenType::Compare: + case TokenType::Convert: + return opcode.GetName(); + + default: + return GetTokenTypeName(token_type); + } +} + WastLexer::WastLexer(std::unique_ptr source, const char* filename) : source_(std::move(source)), line_finder_(source_->Clone()), @@ -109,7 +235,7 @@ WastLexer::WastLexer(std::unique_ptr source, const char* filename) buffer_(nullptr), buffer_size_(0), marker_(nullptr), - token_(nullptr), + next_pos_(nullptr), cursor_(nullptr), limit_(nullptr) {} @@ -131,10 +257,22 @@ std::unique_ptr WastLexer::CreateBufferLexer(const char* filename, return std::unique_ptr(new WastLexer(std::move(source), filename)); } -Result WastLexer::Fill(Location* loc, WastParser* parser, size_t need) { +Location WastLexer::GetLocation() { + return Location(filename_, line_, COLUMN(next_pos_), COLUMN(cursor_)); +} + +LiteralTerminal WastLexer::MakeLiteral(LiteralType type) { + return LiteralTerminal(type, GetText()); +} + +StringTerminal WastLexer::GetText(size_t offset) { + return StringTerminal(yytext + offset, yyleng - offset); +} + +Result WastLexer::Fill(size_t need) { if (eof_) return Result::Error; - size_t free = token_ - buffer_; + size_t free = next_pos_ - buffer_; assert(static_cast(cursor_ - buffer_) >= free); // Our buffer is too small, need to realloc. if (free < need) { @@ -149,11 +287,11 @@ Result WastLexer::Fill(Location* loc, WastParser* parser, size_t need) { new_buffer_size *= 2; char* new_buffer = new char[new_buffer_size]; - if (limit_ > token_) - memmove(new_buffer, token_, limit_ - token_); + if (limit_ > next_pos_) + memmove(new_buffer, next_pos_, limit_ - next_pos_); buffer_ = new_buffer; buffer_size_ = new_buffer_size; - token_ = new_buffer + (token_ - old_buffer) - free; + next_pos_ = new_buffer + (next_pos_ - old_buffer) - free; marker_ = new_buffer + (marker_ - old_buffer) - free; cursor_ = new_buffer + (cursor_ - old_buffer) - free; limit_ = new_buffer + (limit_ - old_buffer) - free; @@ -162,9 +300,9 @@ Result WastLexer::Fill(Location* loc, WastParser* parser, size_t need) { delete[] old_buffer; } else { // Shift everything down to make more room in the buffer. - if (limit_ > token_) - memmove(buffer_, token_, limit_ - token_); - token_ -= free; + if (limit_ > next_pos_) + memmove(buffer_, next_pos_, limit_ - next_pos_); + next_pos_ -= free; marker_ -= free; cursor_ -= free; limit_ -= free; @@ -185,19 +323,23 @@ Result WastLexer::Fill(Location* loc, WastParser* parser, size_t need) { return Result::Ok; } -int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { - enum { - YYCOND_INIT, - YYCOND_BAD_TEXT, - YYCOND_LINE_COMMENT, - YYCOND_BLOCK_COMMENT, - YYCOND_i = YYCOND_INIT, - } cond = YYCOND_INIT; +Token WastLexer::GetToken(WastParser* parser) { +#line 328 "src/prebuilt/wast-lexer-gen.cc" + +enum YYCONDTYPE { + YYCOND_i, + YYCOND_BAD_TEXT, + YYCOND_LINE_COMMENT, + YYCOND_BLOCK_COMMENT, +}; + +#line 325 "src/wast-lexer.cc" + YYCONDTYPE cond = YYCOND_i; // i is the initial state. for (;;) { - token_ = cursor_; + next_pos_ = cursor_; -#line 201 "src/prebuilt/wast-lexer-gen.cc" +#line 343 "src/prebuilt/wast-lexer-gen.cc" { unsigned char yych; unsigned int yyaccept = 0; @@ -242,29 +384,29 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { } ++cursor_; yy4: -#line 251 "src/wast-lexer.cc" +#line 387 "src/wast-lexer.cc" { ERROR("illegal character in string"); continue; } -#line 249 "src/prebuilt/wast-lexer-gen.cc" +#line 391 "src/prebuilt/wast-lexer-gen.cc" yy5: ++cursor_; BEGIN(YYCOND_i); -#line 244 "src/wast-lexer.cc" +#line 380 "src/wast-lexer.cc" { ERROR("newline in string"); NEWLINE; continue; } -#line 257 "src/prebuilt/wast-lexer-gen.cc" +#line 399 "src/prebuilt/wast-lexer-gen.cc" yy7: ++cursor_; -#line 243 "src/wast-lexer.cc" +#line 379 "src/wast-lexer.cc" { continue; } -#line 262 "src/prebuilt/wast-lexer-gen.cc" +#line 404 "src/prebuilt/wast-lexer-gen.cc" yy9: ++cursor_; BEGIN(YYCOND_i); -#line 250 "src/wast-lexer.cc" - { TEXT; RETURN(TEXT); } -#line 268 "src/prebuilt/wast-lexer-gen.cc" +#line 386 "src/wast-lexer.cc" + { RETURN_TEXT(Text); } +#line 410 "src/prebuilt/wast-lexer-gen.cc" yy11: yyaccept = 0; yych = *(marker_ = ++cursor_); @@ -316,9 +458,9 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { yy12: ++cursor_; yy13: -#line 253 "src/wast-lexer.cc" +#line 389 "src/wast-lexer.cc" { MAYBE_MALFORMED_UTF8(" in string"); } -#line 322 "src/prebuilt/wast-lexer-gen.cc" +#line 464 "src/prebuilt/wast-lexer-gen.cc" yy14: yych = *++cursor_; if (yych <= 0x7F) goto yy13; @@ -357,11 +499,11 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { yy20: ++cursor_; yy21: -#line 247 "src/wast-lexer.cc" +#line 383 "src/wast-lexer.cc" { ERROR("bad escape \"%.*s\"", static_cast(yyleng), yytext); continue; } -#line 365 "src/prebuilt/wast-lexer-gen.cc" +#line 507 "src/prebuilt/wast-lexer-gen.cc" yy22: yych = *++cursor_; if (yych <= '@') { @@ -447,14 +589,14 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { yy34: ++cursor_; yy35: -#line 482 "src/wast-lexer.cc" +#line 624 "src/wast-lexer.cc" { continue; } -#line 453 "src/prebuilt/wast-lexer-gen.cc" +#line 595 "src/prebuilt/wast-lexer-gen.cc" yy36: ++cursor_; -#line 481 "src/wast-lexer.cc" +#line 623 "src/wast-lexer.cc" { NEWLINE; continue; } -#line 458 "src/prebuilt/wast-lexer-gen.cc" +#line 600 "src/prebuilt/wast-lexer-gen.cc" yy38: yych = *++cursor_; if (yych == ';') goto yy48; @@ -466,9 +608,9 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { yy40: ++cursor_; yy41: -#line 483 "src/wast-lexer.cc" +#line 625 "src/wast-lexer.cc" { MAYBE_MALFORMED_UTF8(" in block comment"); } -#line 472 "src/prebuilt/wast-lexer-gen.cc" +#line 614 "src/prebuilt/wast-lexer-gen.cc" yy42: yych = *++cursor_; if (yych <= 0x7F) goto yy41; @@ -501,16 +643,16 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { goto yy41; yy48: ++cursor_; -#line 477 "src/wast-lexer.cc" +#line 619 "src/wast-lexer.cc" { COMMENT_NESTING++; continue; } -#line 507 "src/prebuilt/wast-lexer-gen.cc" +#line 649 "src/prebuilt/wast-lexer-gen.cc" yy50: ++cursor_; -#line 478 "src/wast-lexer.cc" +#line 620 "src/wast-lexer.cc" { if (--COMMENT_NESTING == 0) - BEGIN(YYCOND_INIT); + BEGIN(YYCOND_i); continue; } -#line 514 "src/prebuilt/wast-lexer-gen.cc" +#line 656 "src/prebuilt/wast-lexer-gen.cc" yy52: yych = *++cursor_; if (yych <= 0x7F) goto yy53; @@ -563,7 +705,7 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { if ((limit_ - cursor_) < 2) FILL(2); yych = *cursor_; if (yybm[0+yych] & 128) { - goto yy58; + goto yy57; } if (yych <= 0xE0) { if (yych <= '\n') goto yy60; @@ -581,19 +723,15 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { } } yy57: -#line 475 "src/wast-lexer.cc" - { continue; } -#line 587 "src/prebuilt/wast-lexer-gen.cc" -yy58: yyaccept = 0; marker_ = ++cursor_; if (limit_ <= cursor_) FILL(1); yych = *cursor_; if (yybm[0+yych] & 128) { - goto yy58; + goto yy57; } if (yych <= 0xEF) { - if (yych <= 0xC1) goto yy57; + if (yych <= 0xC1) goto yy59; if (yych <= 0xDF) goto yy70; if (yych <= 0xE0) goto yy72; goto yy73; @@ -601,24 +739,27 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { if (yych <= 0xF0) goto yy74; if (yych <= 0xF3) goto yy75; if (yych <= 0xF4) goto yy76; - goto yy57; } +yy59: +#line 617 "src/wast-lexer.cc" + { continue; } +#line 747 "src/prebuilt/wast-lexer-gen.cc" yy60: ++cursor_; BEGIN(YYCOND_i); -#line 474 "src/wast-lexer.cc" +#line 616 "src/wast-lexer.cc" { NEWLINE; continue; } -#line 612 "src/prebuilt/wast-lexer-gen.cc" +#line 753 "src/prebuilt/wast-lexer-gen.cc" yy62: ++cursor_; yy63: -#line 490 "src/wast-lexer.cc" +#line 630 "src/wast-lexer.cc" { MAYBE_MALFORMED_UTF8(""); } -#line 618 "src/prebuilt/wast-lexer-gen.cc" +#line 759 "src/prebuilt/wast-lexer-gen.cc" yy64: yych = *++cursor_; if (yych <= 0x7F) goto yy63; - if (yych <= 0xBF) goto yy58; + if (yych <= 0xBF) goto yy57; goto yy63; yy65: yyaccept = 1; @@ -655,11 +796,11 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { if (limit_ <= cursor_) FILL(1); yych = *cursor_; if (yych <= 0x7F) goto yy71; - if (yych <= 0xBF) goto yy58; + if (yych <= 0xBF) goto yy57; yy71: cursor_ = marker_; if (yyaccept == 0) { - goto yy57; + goto yy59; } else { goto yy63; } @@ -835,9 +976,9 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { yy79: ++cursor_; yy80: -#line 489 "src/wast-lexer.cc" +#line 629 "src/wast-lexer.cc" { ERROR("unexpected char"); continue; } -#line 841 "src/prebuilt/wast-lexer-gen.cc" +#line 982 "src/prebuilt/wast-lexer-gen.cc" yy81: ++cursor_; if (limit_ <= cursor_) FILL(1); @@ -845,14 +986,14 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { if (yybm[0+yych] & 4) { goto yy81; } -#line 485 "src/wast-lexer.cc" +#line 627 "src/wast-lexer.cc" { continue; } -#line 851 "src/prebuilt/wast-lexer-gen.cc" +#line 992 "src/prebuilt/wast-lexer-gen.cc" yy84: ++cursor_; -#line 484 "src/wast-lexer.cc" +#line 626 "src/wast-lexer.cc" { NEWLINE; continue; } -#line 856 "src/prebuilt/wast-lexer-gen.cc" +#line 997 "src/prebuilt/wast-lexer-gen.cc" yy86: ++cursor_; if (limit_ <= cursor_) FILL(1); @@ -862,11 +1003,9 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { goto yy86; } yy88: -#line 486 "src/wast-lexer.cc" - { ERROR("unexpected token \"%.*s\"", - static_cast(yyleng), yytext); - continue; } -#line 870 "src/prebuilt/wast-lexer-gen.cc" +#line 628 "src/wast-lexer.cc" + { RETURN_TEXT(Reserved); } +#line 1009 "src/prebuilt/wast-lexer-gen.cc" yy89: yyaccept = 0; yych = *(marker_ = ++cursor_); @@ -876,9 +1015,9 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { if (yych <= 0xF4) goto yy129; yy90: BEGIN(YYCOND_BAD_TEXT); -#line 242 "src/wast-lexer.cc" +#line 378 "src/wast-lexer.cc" { continue; } -#line 882 "src/prebuilt/wast-lexer-gen.cc" +#line 1021 "src/prebuilt/wast-lexer-gen.cc" yy91: yych = *++cursor_; if (yych <= '\'') { @@ -898,14 +1037,14 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { yy92: ++cursor_; if ((yych = *cursor_) == ';') goto yy143; -#line 233 "src/wast-lexer.cc" - { RETURN(LPAR); } -#line 904 "src/prebuilt/wast-lexer-gen.cc" +#line 369 "src/wast-lexer.cc" + { RETURN(Lpar); } +#line 1043 "src/prebuilt/wast-lexer-gen.cc" yy94: ++cursor_; -#line 234 "src/wast-lexer.cc" - { RETURN(RPAR); } -#line 909 "src/prebuilt/wast-lexer-gen.cc" +#line 370 "src/wast-lexer.cc" + { RETURN(Rpar); } +#line 1048 "src/prebuilt/wast-lexer-gen.cc" yy96: yych = *++cursor_; if (yych <= 'h') { @@ -923,23 +1062,30 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { if (yybm[0+(yych = *cursor_)] & 16) { goto yy99; } - if (yych <= ':') { + if (yych <= ';') { if (yych <= '\'') { if (yych == '!') goto yy86; if (yych >= '#') goto yy86; } else { - if (yych <= ')') goto yy98; - if (yych == '.') goto yy151; - goto yy86; + if (yych <= '-') { + if (yych >= '*') goto yy86; + } else { + if (yych <= '.') goto yy151; + if (yych <= ':') goto yy86; + } } } else { if (yych <= 'd') { - if (yych <= ';') goto yy98; - if (yych == 'E') goto yy154; - goto yy86; + if (yych <= 'E') { + if (yych <= 'D') goto yy86; + goto yy153; + } else { + if (yych == '_') goto yy154; + goto yy86; + } } else { if (yych <= 'w') { - if (yych <= 'e') goto yy154; + if (yych <= 'e') goto yy153; goto yy86; } else { if (yych <= 'x') goto yy155; @@ -948,9 +1094,9 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { } } yy98: -#line 235 "src/wast-lexer.cc" - { LITERAL(Int); RETURN(NAT); } -#line 954 "src/prebuilt/wast-lexer-gen.cc" +#line 371 "src/wast-lexer.cc" + { RETURN_LITERAL(Nat, Int); } +#line 1100 "src/prebuilt/wast-lexer-gen.cc" yy99: ++cursor_; if ((limit_ - cursor_) < 3) FILL(3); @@ -958,25 +1104,30 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { if (yybm[0+yych] & 16) { goto yy99; } - if (yych <= '.') { - if (yych <= '"') { + if (yych <= ':') { + if (yych <= '\'') { if (yych == '!') goto yy86; - goto yy98; + if (yych <= '"') goto yy98; + goto yy86; } else { - if (yych <= '\'') goto yy86; if (yych <= ')') goto yy98; - if (yych <= '-') goto yy86; - goto yy151; + if (yych == '.') goto yy151; + goto yy86; } } else { - if (yych <= 'E') { - if (yych == ';') goto yy98; - if (yych <= 'D') goto yy86; - goto yy154; + if (yych <= '^') { + if (yych <= ';') goto yy98; + if (yych == 'E') goto yy153; + goto yy86; } else { - if (yych == 'e') goto yy154; - if (yych <= '~') goto yy86; - goto yy98; + if (yych <= 'd') { + if (yych <= '_') goto yy154; + goto yy86; + } else { + if (yych <= 'e') goto yy153; + if (yych <= '~') goto yy86; + goto yy98; + } } } yy101: @@ -1120,9 +1271,9 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { yy120: ++cursor_; yy121: -#line 490 "src/wast-lexer.cc" +#line 630 "src/wast-lexer.cc" { MAYBE_MALFORMED_UTF8(""); } -#line 1126 "src/prebuilt/wast-lexer-gen.cc" +#line 1277 "src/prebuilt/wast-lexer-gen.cc" yy122: yych = *++cursor_; if (yych <= 0x7F) goto yy121; @@ -1192,9 +1343,9 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { } yy131: ++cursor_; -#line 241 "src/wast-lexer.cc" - { TEXT; RETURN(TEXT); } -#line 1198 "src/prebuilt/wast-lexer-gen.cc" +#line 377 "src/wast-lexer.cc" + { RETURN_TEXT(Text); } +#line 1349 "src/prebuilt/wast-lexer-gen.cc" yy133: ++cursor_; if (limit_ <= cursor_) FILL(1); @@ -1289,77 +1440,92 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { if (yych <= ';') goto yy142; if (yych <= '}') goto yy86; yy142: -#line 471 "src/wast-lexer.cc" - { TEXT; RETURN(VAR); } -#line 1295 "src/prebuilt/wast-lexer-gen.cc" +#line 613 "src/wast-lexer.cc" + { RETURN_TEXT(Var); } +#line 1446 "src/prebuilt/wast-lexer-gen.cc" yy143: ++cursor_; BEGIN(YYCOND_BLOCK_COMMENT); -#line 476 "src/wast-lexer.cc" +#line 618 "src/wast-lexer.cc" { COMMENT_NESTING = 1; continue; } -#line 1301 "src/prebuilt/wast-lexer-gen.cc" +#line 1452 "src/prebuilt/wast-lexer-gen.cc" yy145: ++cursor_; - if ((yych = *cursor_) <= '9') { - if (yych <= '\'') { - if (yych == '!') goto yy86; - if (yych >= '#') goto yy86; + if ((yych = *cursor_) <= ':') { + if (yych <= ')') { + if (yych <= '!') { + if (yych >= '!') goto yy86; + } else { + if (yych <= '"') goto yy146; + if (yych <= '\'') goto yy86; + } } else { - if (yych <= '-') { - if (yych >= '*') goto yy86; + if (yych <= '.') { + if (yych <= '-') goto yy86; + goto yy151; } else { - if (yych <= '.') goto yy151; if (yych <= '/') goto yy86; - goto yy147; + if (yych <= '9') goto yy147; + goto yy86; } } } else { - if (yych <= 'd') { - if (yych <= ';') { - if (yych <= ':') goto yy86; + if (yych <= '_') { + if (yych <= 'D') { + if (yych >= '<') goto yy86; } else { - if (yych == 'E') goto yy154; - goto yy86; + if (yych <= 'E') goto yy153; + if (yych <= '^') goto yy86; + goto yy205; } } else { if (yych <= 'w') { - if (yych <= 'e') goto yy154; + if (yych == 'e') goto yy153; goto yy86; } else { - if (yych <= 'x') goto yy205; + if (yych <= 'x') goto yy206; if (yych <= '~') goto yy86; } } } yy146: -#line 236 "src/wast-lexer.cc" - { LITERAL(Int); RETURN(INT); } -#line 1338 "src/prebuilt/wast-lexer-gen.cc" +#line 372 "src/wast-lexer.cc" + { RETURN_LITERAL(Int, Int); } +#line 1495 "src/prebuilt/wast-lexer-gen.cc" yy147: ++cursor_; if ((limit_ - cursor_) < 3) FILL(3); yych = *cursor_; - if (yych <= '/') { + if (yych <= '9') { if (yych <= '\'') { if (yych == '!') goto yy86; if (yych <= '"') goto yy146; goto yy86; } else { - if (yych <= ')') goto yy146; - if (yych == '.') goto yy151; - goto yy86; + if (yych <= '-') { + if (yych <= ')') goto yy146; + goto yy86; + } else { + if (yych <= '.') goto yy151; + if (yych <= '/') goto yy86; + goto yy147; + } } } else { - if (yych <= 'D') { - if (yych <= '9') goto yy147; - if (yych == ';') goto yy146; - goto yy86; + if (yych <= '^') { + if (yych <= ';') { + if (yych <= ':') goto yy86; + goto yy146; + } else { + if (yych == 'E') goto yy153; + goto yy86; + } } else { if (yych <= 'd') { - if (yych <= 'E') goto yy154; + if (yych <= '_') goto yy205; goto yy86; } else { - if (yych <= 'e') goto yy154; + if (yych <= 'e') goto yy153; if (yych <= '~') goto yy86; goto yy146; } @@ -1367,7 +1533,7 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { } yy149: yych = *++cursor_; - if (yych == 'n') goto yy206; + if (yych == 'n') goto yy207; goto yy87; yy150: yych = *++cursor_; @@ -1375,73 +1541,107 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { goto yy87; yy151: ++cursor_; - if ((limit_ - cursor_) < 3) FILL(3); - yych = *cursor_; - if (yych <= '9') { + if ((yych = *cursor_) <= '9') { if (yych <= '"') { if (yych == '!') goto yy86; } else { if (yych <= '\'') goto yy86; - if (yych <= ')') goto yy153; + if (yych <= ')') goto yy152; if (yych <= '/') goto yy86; - goto yy151; + goto yy208; } } else { if (yych <= 'E') { - if (yych == ';') goto yy153; + if (yych == ';') goto yy152; if (yych <= 'D') goto yy86; - goto yy154; + goto yy153; } else { - if (yych == 'e') goto yy154; + if (yych == 'e') goto yy153; if (yych <= '~') goto yy86; } } +yy152: +#line 373 "src/wast-lexer.cc" + { RETURN_LITERAL(Float, Float); } +#line 1567 "src/prebuilt/wast-lexer-gen.cc" yy153: -#line 237 "src/wast-lexer.cc" - { LITERAL(Float); RETURN(FLOAT); } -#line 1403 "src/prebuilt/wast-lexer-gen.cc" -yy154: yych = *++cursor_; if (yych <= ',') { - if (yych == '+') goto yy207; + if (yych == '+') goto yy210; goto yy87; } else { - if (yych <= '-') goto yy207; + if (yych <= '-') goto yy210; if (yych <= '/') goto yy87; - if (yych <= '9') goto yy208; + if (yych <= '9') goto yy211; goto yy87; } +yy154: + ++cursor_; + if (limit_ <= cursor_) FILL(1); + yych = *cursor_; + if (yybm[0+yych] & 16) { + goto yy99; + } + if (yych <= '\'') { + if (yych == '!') goto yy86; + if (yych <= '"') goto yy88; + goto yy86; + } else { + if (yych <= ':') { + if (yych <= ')') goto yy88; + goto yy86; + } else { + if (yych <= ';') goto yy88; + if (yych <= '~') goto yy86; + goto yy88; + } + } yy155: - yych = *++cursor_; + ++cursor_; + if (limit_ <= cursor_) FILL(1); + yych = *cursor_; if (yybm[0+yych] & 128) { - goto yy210; + goto yy213; + } + if (yych <= '\'') { + if (yych == '!') goto yy86; + if (yych <= '"') goto yy88; + goto yy86; + } else { + if (yych <= ':') { + if (yych <= ')') goto yy88; + goto yy86; + } else { + if (yych <= ';') goto yy88; + if (yych <= '~') goto yy86; + goto yy88; + } } - goto yy87; yy156: ++cursor_; BEGIN(YYCOND_LINE_COMMENT); -#line 473 "src/wast-lexer.cc" +#line 615 "src/wast-lexer.cc" { continue; } -#line 1426 "src/prebuilt/wast-lexer-gen.cc" +#line 1626 "src/prebuilt/wast-lexer-gen.cc" yy158: yych = *++cursor_; - if (yych == 'i') goto yy212; + if (yych == 'i') goto yy215; goto yy87; yy159: yych = *++cursor_; - if (yych == 'y') goto yy213; + if (yych == 'y') goto yy216; goto yy87; yy160: yych = *++cursor_; - if (yych == 's') goto yy214; + if (yych == 's') goto yy217; goto yy87; yy161: yych = *++cursor_; - if (yych == 'n') goto yy215; + if (yych == 'n') goto yy218; goto yy87; yy162: yych = *++cursor_; - if (yych == 'o') goto yy216; + if (yych == 'o') goto yy219; goto yy87; yy163: ++cursor_; @@ -1456,174 +1656,174 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { if (yych <= '^') { if (yych != ';') goto yy86; } else { - if (yych <= '_') goto yy217; + if (yych <= '_') goto yy220; if (yych <= '~') goto yy86; } } yy164: -#line 266 "src/wast-lexer.cc" - { RETURN(BR); } -#line 1467 "src/prebuilt/wast-lexer-gen.cc" +#line 402 "src/wast-lexer.cc" + { RETURN_OPCODE0(Br); } +#line 1667 "src/prebuilt/wast-lexer-gen.cc" yy165: yych = *++cursor_; - if (yych == 'l') goto yy218; - if (yych == 't') goto yy219; + if (yych == 'l') goto yy221; + if (yych == 't') goto yy222; goto yy87; yy166: yych = *++cursor_; - if (yych == 'r') goto yy220; + if (yych == 'r') goto yy223; goto yy87; yy167: yych = *++cursor_; - if (yych == 't') goto yy221; + if (yych == 't') goto yy224; goto yy87; yy168: yych = *++cursor_; - if (yych == 'o') goto yy222; + if (yych == 'o') goto yy225; goto yy87; yy169: yych = *++cursor_; - if (yych == 'e') goto yy223; - if (yych == 's') goto yy224; + if (yych == 'e') goto yy226; + if (yych == 's') goto yy227; goto yy87; yy170: yych = *++cursor_; - if (yych == 'd') goto yy225; + if (yych == 'd') goto yy228; goto yy87; yy171: yych = *++cursor_; - if (yych == 'c') goto yy227; - if (yych == 'p') goto yy228; + if (yych == 'c') goto yy230; + if (yych == 'p') goto yy231; goto yy87; yy172: yych = *++cursor_; - if (yych == '2') goto yy229; + if (yych == '2') goto yy232; goto yy87; yy173: yych = *++cursor_; - if (yych == '4') goto yy231; + if (yych == '4') goto yy234; goto yy87; yy174: yych = *++cursor_; - if (yych == 'n') goto yy233; + if (yych == 'n') goto yy236; goto yy87; yy175: yych = *++cursor_; - if (yych == 't') goto yy234; + if (yych == 't') goto yy237; goto yy87; yy176: yych = *++cursor_; - if (yych == 'o') goto yy236; + if (yych == 'o') goto yy239; goto yy87; yy177: yych = *++cursor_; - if (yych == 'o') goto yy237; + if (yych == 'o') goto yy240; goto yy87; yy178: yych = *++cursor_; - if (yych == '2') goto yy238; + if (yych == '2') goto yy241; goto yy87; yy179: yych = *++cursor_; - if (yych == '4') goto yy240; + if (yych == '4') goto yy243; goto yy87; yy180: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 262 "src/wast-lexer.cc" - { RETURN(IF); } -#line 1538 "src/prebuilt/wast-lexer-gen.cc" +#line 398 "src/wast-lexer.cc" + { RETURN_OPCODE0(If); } +#line 1738 "src/prebuilt/wast-lexer-gen.cc" yy182: yych = *++cursor_; - if (yych == 'p') goto yy242; + if (yych == 'p') goto yy245; goto yy87; yy183: yych = *++cursor_; - if (yych == 'f') goto yy243; - if (yych == 'v') goto yy245; + if (yych == 'f') goto yy246; + if (yych == 'v') goto yy248; goto yy87; yy184: yych = *++cursor_; - if (yych == 'c') goto yy246; - if (yych == 'o') goto yy247; + if (yych == 'c') goto yy249; + if (yych == 'o') goto yy250; goto yy87; yy185: yych = *++cursor_; - if (yych == 'm') goto yy248; + if (yych == 'm') goto yy251; goto yy87; yy186: yych = *++cursor_; - if (yych == 'd') goto yy249; + if (yych == 'd') goto yy252; goto yy87; yy187: yych = *++cursor_; - if (yych == 't') goto yy250; + if (yych == 't') goto yy253; goto yy87; yy188: yych = *++cursor_; - if (yych == 'n') goto yy252; + if (yych == 'n') goto yy255; goto yy87; yy189: yych = *++cursor_; - if (yych == 'p') goto yy254; + if (yych == 'p') goto yy257; goto yy87; yy190: yych = *++cursor_; - if (yych == 'f') goto yy256; + if (yych == 'f') goto yy259; goto yy87; yy191: yych = *++cursor_; - if (yych == 'r') goto yy257; + if (yych == 'r') goto yy260; goto yy87; yy192: yych = *++cursor_; - if (yych == 'o') goto yy258; + if (yych == 'o') goto yy261; goto yy87; yy193: yych = *++cursor_; if (yych <= 'r') { - if (yych == 'g') goto yy259; + if (yych == 'g') goto yy262; goto yy87; } else { - if (yych <= 's') goto yy260; - if (yych <= 't') goto yy261; + if (yych <= 's') goto yy263; + if (yych <= 't') goto yy264; goto yy87; } yy194: yych = *++cursor_; - if (yych == 'l') goto yy262; - if (yych == 't') goto yy263; + if (yych == 'l') goto yy265; + if (yych == 't') goto yy266; goto yy87; yy195: yych = *++cursor_; - if (yych == 'a') goto yy264; + if (yych == 'a') goto yy267; goto yy87; yy196: yych = *++cursor_; - if (yych == 'b') goto yy265; + if (yych == 'b') goto yy268; goto yy87; yy197: yych = *++cursor_; - if (yych == 'e') goto yy266; + if (yych == 'e') goto yy269; goto yy87; yy198: yych = *++cursor_; - if (yych == 'e') goto yy267; - if (yych == 'r') goto yy268; + if (yych == 'e') goto yy270; + if (yych == 'r') goto yy271; goto yy87; yy199: yych = *++cursor_; - if (yych == 'y') goto yy269; + if (yych == 'y') goto yy272; goto yy87; yy200: yych = *++cursor_; - if (yych == 'p') goto yy271; + if (yych == 'p') goto yy274; goto yy87; yy201: yych = *++cursor_; - if (yych == 'r') goto yy272; + if (yych == 'r') goto yy275; goto yy87; yy202: yych = *++cursor_; @@ -1650,1453 +1850,1672 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { goto yy130; } yy205: - yych = *++cursor_; - if (yych <= '@') { - if (yych <= '/') goto yy87; - if (yych <= '9') goto yy273; - goto yy87; - } else { - if (yych <= 'F') goto yy273; - if (yych <= '`') goto yy87; - if (yych <= 'f') goto yy273; - goto yy87; - } -yy206: - yych = *++cursor_; - if (yych == 'f') goto yy243; - goto yy87; -yy207: - yych = *++cursor_; - if (yych <= '/') goto yy87; - if (yych >= ':') goto yy87; -yy208: ++cursor_; if (limit_ <= cursor_) FILL(1); yych = *cursor_; if (yych <= ')') { if (yych <= '!') { - if (yych <= ' ') goto yy153; + if (yych <= ' ') goto yy88; goto yy86; } else { - if (yych <= '"') goto yy153; + if (yych <= '"') goto yy88; if (yych <= '\'') goto yy86; - goto yy153; + goto yy88; } } else { if (yych <= ':') { if (yych <= '/') goto yy86; - if (yych <= '9') goto yy208; + if (yych <= '9') goto yy147; goto yy86; } else { - if (yych <= ';') goto yy153; + if (yych <= ';') goto yy88; if (yych <= '~') goto yy86; - goto yy153; + goto yy88; } } -yy210: +yy206: ++cursor_; - if ((limit_ - cursor_) < 3) FILL(3); + if (limit_ <= cursor_) FILL(1); yych = *cursor_; - if (yybm[0+yych] & 128) { - goto yy210; - } - if (yych <= '-') { + if (yych <= '9') { if (yych <= '"') { if (yych == '!') goto yy86; - goto yy98; + goto yy88; } else { if (yych <= '\'') goto yy86; - if (yych <= ')') goto yy98; - goto yy86; + if (yych <= ')') goto yy88; + if (yych <= '/') goto yy86; + goto yy276; } } else { - if (yych <= ';') { - if (yych <= '.') goto yy275; - if (yych <= ':') goto yy86; - goto yy98; + if (yych <= 'F') { + if (yych == ';') goto yy88; + if (yych <= '@') goto yy86; + goto yy276; } else { - if (yych == 'p') goto yy277; + if (yych <= '`') goto yy86; + if (yych <= 'f') goto yy276; if (yych <= '~') goto yy86; - goto yy98; + goto yy88; } } -yy212: - yych = *++cursor_; - if (yych == 'g') goto yy278; - goto yy87; -yy213: - yych = *++cursor_; - if (yych == 'f') goto yy279; - goto yy87; -yy214: - yych = *++cursor_; - if (yych == 'e') goto yy280; - goto yy87; -yy215: - yych = *++cursor_; - if (yych == 'a') goto yy281; - goto yy87; -yy216: - yych = *++cursor_; - if (yych == 'c') goto yy282; - goto yy87; -yy217: - yych = *++cursor_; - if (yych == 'i') goto yy283; - if (yych == 't') goto yy284; - goto yy87; -yy218: - yych = *++cursor_; - if (yych == 'l') goto yy285; - goto yy87; -yy219: - yych = *++cursor_; - if (yych == 'c') goto yy287; - goto yy87; -yy220: - yych = *++cursor_; - if (yych == 'r') goto yy288; - goto yy87; -yy221: +yy207: yych = *++cursor_; - if (yych == 'a') goto yy289; + if (yych == 'f') goto yy246; goto yy87; -yy222: - yych = *++cursor_; - if (yych == 'p') goto yy291; +yy208: + ++cursor_; + if ((limit_ - cursor_) < 2) FILL(2); + yych = *cursor_; + if (yych <= ':') { + if (yych <= '\'') { + if (yych == '!') goto yy86; + if (yych <= '"') goto yy152; + goto yy86; + } else { + if (yych <= ')') goto yy152; + if (yych <= '/') goto yy86; + if (yych <= '9') goto yy208; + goto yy86; + } + } else { + if (yych <= '^') { + if (yych <= ';') goto yy152; + if (yych == 'E') goto yy153; + goto yy86; + } else { + if (yych <= 'd') { + if (yych <= '_') goto yy278; + goto yy86; + } else { + if (yych <= 'e') goto yy153; + if (yych <= '~') goto yy86; + goto yy152; + } + } + } +yy210: + ++cursor_; + if (limit_ <= cursor_) FILL(1); + yych = *cursor_; + if (yych <= ')') { + if (yych <= '!') { + if (yych <= ' ') goto yy88; + goto yy86; + } else { + if (yych <= '"') goto yy88; + if (yych <= '\'') goto yy86; + goto yy88; + } + } else { + if (yych <= ':') { + if (yych <= '/') goto yy86; + if (yych >= ':') goto yy86; + } else { + if (yych <= ';') goto yy88; + if (yych <= '~') goto yy86; + goto yy88; + } + } +yy211: + ++cursor_; + if (limit_ <= cursor_) FILL(1); + yych = *cursor_; + if (yych <= '/') { + if (yych <= '"') { + if (yych == '!') goto yy86; + goto yy152; + } else { + if (yych <= '\'') goto yy86; + if (yych <= ')') goto yy152; + goto yy86; + } + } else { + if (yych <= ';') { + if (yych <= '9') goto yy211; + if (yych <= ':') goto yy86; + goto yy152; + } else { + if (yych == '_') goto yy210; + if (yych <= '~') goto yy86; + goto yy152; + } + } +yy213: + ++cursor_; + if ((limit_ - cursor_) < 3) FILL(3); + yych = *cursor_; + if (yybm[0+yych] & 128) { + goto yy213; + } + if (yych <= ':') { + if (yych <= '\'') { + if (yych == '!') goto yy86; + if (yych <= '"') goto yy98; + goto yy86; + } else { + if (yych <= ')') goto yy98; + if (yych == '.') goto yy279; + goto yy86; + } + } else { + if (yych <= '^') { + if (yych <= ';') goto yy98; + if (yych == 'P') goto yy281; + goto yy86; + } else { + if (yych <= 'o') { + if (yych <= '_') goto yy155; + goto yy86; + } else { + if (yych <= 'p') goto yy281; + if (yych <= '~') goto yy86; + goto yy98; + } + } + } +yy215: + yych = *++cursor_; + if (yych == 'g') goto yy282; + goto yy87; +yy216: + yych = *++cursor_; + if (yych == 'f') goto yy283; + goto yy87; +yy217: + yych = *++cursor_; + if (yych == 'e') goto yy284; + goto yy87; +yy218: + yych = *++cursor_; + if (yych == 'a') goto yy285; + goto yy87; +yy219: + yych = *++cursor_; + if (yych == 'c') goto yy286; + goto yy87; +yy220: + yych = *++cursor_; + if (yych == 'i') goto yy287; + if (yych == 't') goto yy288; + goto yy87; +yy221: + yych = *++cursor_; + if (yych == 'l') goto yy289; + goto yy87; +yy222: + yych = *++cursor_; + if (yych == 'c') goto yy291; goto yy87; yy223: yych = *++cursor_; - if (yych == 'm') goto yy293; + if (yych == 'r') goto yy292; goto yy87; yy224: yych = *++cursor_; - if (yych == 'e') goto yy295; + if (yych == 'a') goto yy293; goto yy87; yy225: + yych = *++cursor_; + if (yych == 'p') goto yy295; + goto yy87; +yy226: + yych = *++cursor_; + if (yych == 'm') goto yy297; + goto yy87; +yy227: + yych = *++cursor_; + if (yych == 'e') goto yy299; + goto yy87; +yy228: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 272 "src/wast-lexer.cc" - { RETURN(END); } -#line 1784 "src/prebuilt/wast-lexer-gen.cc" -yy227: +#line 408 "src/wast-lexer.cc" + { RETURN_OPCODE0(End); } +#line 2078 "src/prebuilt/wast-lexer-gen.cc" +yy230: yych = *++cursor_; - if (yych == 'e') goto yy297; + if (yych == 'e') goto yy301; goto yy87; -yy228: +yy231: yych = *++cursor_; - if (yych == 'o') goto yy298; + if (yych == 'o') goto yy302; goto yy87; -yy229: +yy232: ++cursor_; if ((yych = *cursor_) <= ')') { if (yych <= '!') { if (yych >= '!') goto yy86; } else { - if (yych <= '"') goto yy230; + if (yych <= '"') goto yy233; if (yych <= '\'') goto yy86; } } else { if (yych <= ':') { - if (yych == '.') goto yy299; + if (yych == '.') goto yy303; goto yy86; } else { - if (yych <= ';') goto yy230; + if (yych <= ';') goto yy233; if (yych <= '~') goto yy86; } } -yy230: -#line 256 "src/wast-lexer.cc" - { TYPE(F32); RETURN(VALUE_TYPE); } -#line 1814 "src/prebuilt/wast-lexer-gen.cc" -yy231: +yy233: +#line 392 "src/wast-lexer.cc" + { RETURN_TYPE(ValueType, F32); } +#line 2108 "src/prebuilt/wast-lexer-gen.cc" +yy234: ++cursor_; if ((yych = *cursor_) <= ')') { if (yych <= '!') { if (yych >= '!') goto yy86; } else { - if (yych <= '"') goto yy232; + if (yych <= '"') goto yy235; if (yych <= '\'') goto yy86; } } else { if (yych <= ':') { - if (yych == '.') goto yy300; + if (yych == '.') goto yy304; goto yy86; } else { - if (yych <= ';') goto yy232; + if (yych <= ';') goto yy235; if (yych <= '~') goto yy86; } } -yy232: -#line 257 "src/wast-lexer.cc" - { TYPE(F64); RETURN(VALUE_TYPE); } -#line 1836 "src/prebuilt/wast-lexer-gen.cc" -yy233: +yy235: +#line 393 "src/wast-lexer.cc" + { RETURN_TYPE(ValueType, F64); } +#line 2130 "src/prebuilt/wast-lexer-gen.cc" +yy236: yych = *++cursor_; - if (yych == 'c') goto yy301; + if (yych == 'c') goto yy305; goto yy87; -yy234: +yy237: ++cursor_; if ((yych = *cursor_) <= ')') { if (yych <= '!') { if (yych >= '!') goto yy86; } else { - if (yych <= '"') goto yy235; + if (yych <= '"') goto yy238; if (yych <= '\'') goto yy86; } } else { if (yych <= '^') { if (yych != ';') goto yy86; } else { - if (yych <= '_') goto yy303; + if (yych <= '_') goto yy307; if (yych <= '~') goto yy86; } } -yy235: -#line 455 "src/wast-lexer.cc" - { RETURN(GET); } -#line 1861 "src/prebuilt/wast-lexer-gen.cc" -yy236: +yy238: +#line 599 "src/wast-lexer.cc" + { RETURN(Get); } +#line 2155 "src/prebuilt/wast-lexer-gen.cc" +yy239: yych = *++cursor_; - if (yych == 'b') goto yy304; + if (yych == 'b') goto yy308; goto yy87; -yy237: +yy240: yych = *++cursor_; - if (yych == 'w') goto yy305; + if (yych == 'w') goto yy309; goto yy87; -yy238: +yy241: ++cursor_; if ((yych = *cursor_) <= ')') { if (yych <= '!') { if (yych >= '!') goto yy86; } else { - if (yych <= '"') goto yy239; + if (yych <= '"') goto yy242; if (yych <= '\'') goto yy86; } } else { if (yych <= ':') { - if (yych == '.') goto yy306; + if (yych == '.') goto yy310; goto yy86; } else { - if (yych <= ';') goto yy239; + if (yych <= ';') goto yy242; if (yych <= '~') goto yy86; } } -yy239: -#line 254 "src/wast-lexer.cc" - { TYPE(I32); RETURN(VALUE_TYPE); } -#line 1891 "src/prebuilt/wast-lexer-gen.cc" -yy240: +yy242: +#line 390 "src/wast-lexer.cc" + { RETURN_TYPE(ValueType, I32); } +#line 2185 "src/prebuilt/wast-lexer-gen.cc" +yy243: ++cursor_; if ((yych = *cursor_) <= ')') { if (yych <= '!') { if (yych >= '!') goto yy86; } else { - if (yych <= '"') goto yy241; + if (yych <= '"') goto yy244; if (yych <= '\'') goto yy86; } } else { if (yych <= ':') { - if (yych == '.') goto yy307; + if (yych == '.') goto yy311; goto yy86; } else { - if (yych <= ';') goto yy241; + if (yych <= ';') goto yy244; if (yych <= '~') goto yy86; } } -yy241: -#line 255 "src/wast-lexer.cc" - { TYPE(I64); RETURN(VALUE_TYPE); } -#line 1913 "src/prebuilt/wast-lexer-gen.cc" -yy242: +yy244: +#line 391 "src/wast-lexer.cc" + { RETURN_TYPE(ValueType, I64); } +#line 2207 "src/prebuilt/wast-lexer-gen.cc" +yy245: yych = *++cursor_; - if (yych == 'o') goto yy308; + if (yych == 'o') goto yy312; goto yy87; -yy243: +yy246: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 239 "src/wast-lexer.cc" - { LITERAL(Infinity); RETURN(FLOAT); } -#line 1925 "src/prebuilt/wast-lexer-gen.cc" -yy245: +#line 375 "src/wast-lexer.cc" + { RETURN_LITERAL(Float, Infinity); } +#line 2219 "src/prebuilt/wast-lexer-gen.cc" +yy248: yych = *++cursor_; - if (yych == 'o') goto yy309; + if (yych == 'o') goto yy313; goto yy87; -yy246: +yy249: yych = *++cursor_; - if (yych == 'a') goto yy310; + if (yych == 'a') goto yy314; goto yy87; -yy247: +yy250: yych = *++cursor_; - if (yych == 'p') goto yy311; + if (yych == 'p') goto yy315; goto yy87; -yy248: +yy251: yych = *++cursor_; - if (yych == 'o') goto yy313; + if (yych == 'o') goto yy317; goto yy87; -yy249: +yy252: yych = *++cursor_; - if (yych == 'u') goto yy314; + if (yych == 'u') goto yy318; goto yy87; -yy250: +yy253: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 259 "src/wast-lexer.cc" - { RETURN(MUT); } -#line 1953 "src/prebuilt/wast-lexer-gen.cc" -yy252: +#line 395 "src/wast-lexer.cc" + { RETURN(Mut); } +#line 2247 "src/prebuilt/wast-lexer-gen.cc" +yy255: ++cursor_; if ((yych = *cursor_) <= ')') { if (yych <= '!') { if (yych >= '!') goto yy86; } else { - if (yych <= '"') goto yy253; + if (yych <= '"') goto yy256; if (yych <= '\'') goto yy86; } } else { if (yych <= ':') { if (yych <= '9') goto yy86; - goto yy315; + goto yy319; } else { - if (yych <= ';') goto yy253; + if (yych <= ';') goto yy256; if (yych <= '~') goto yy86; } } -yy253: -#line 240 "src/wast-lexer.cc" - { LITERAL(Nan); RETURN(FLOAT); } -#line 1975 "src/prebuilt/wast-lexer-gen.cc" -yy254: +yy256: +#line 376 "src/wast-lexer.cc" + { RETURN_LITERAL(Float, Nan); } +#line 2269 "src/prebuilt/wast-lexer-gen.cc" +yy257: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 260 "src/wast-lexer.cc" - { RETURN(NOP); } -#line 1983 "src/prebuilt/wast-lexer-gen.cc" -yy256: - yych = *++cursor_; - if (yych == 's') goto yy316; - goto yy87; -yy257: - yych = *++cursor_; - if (yych == 'a') goto yy317; - goto yy87; -yy258: - yych = *++cursor_; - if (yych == 't') goto yy318; - goto yy87; +#line 396 "src/wast-lexer.cc" + { RETURN(Nop); } +#line 2277 "src/prebuilt/wast-lexer-gen.cc" yy259: yych = *++cursor_; - if (yych == 'i') goto yy319; + if (yych == 's') goto yy320; goto yy87; yy260: yych = *++cursor_; - if (yych == 'u') goto yy320; + if (yych == 'a') goto yy321; goto yy87; yy261: yych = *++cursor_; - if (yych == 'h') goto yy321; - if (yych == 'u') goto yy322; + if (yych == 't') goto yy322; goto yy87; yy262: yych = *++cursor_; - if (yych == 'e') goto yy323; + if (yych == 'i') goto yy323; goto yy87; yy263: yych = *++cursor_; - if (yych == '_') goto yy324; + if (yych == 'u') goto yy324; goto yy87; yy264: yych = *++cursor_; - if (yych == 'r') goto yy325; + if (yych == 'h') goto yy325; + if (yych == 'u') goto yy326; goto yy87; yy265: yych = *++cursor_; - if (yych == 'l') goto yy326; + if (yych == 'e') goto yy327; goto yy87; yy266: yych = *++cursor_; - if (yych == '_') goto yy327; + if (yych == '_') goto yy328; goto yy87; yy267: yych = *++cursor_; - if (yych == 'n') goto yy328; + if (yych == 'r') goto yy329; goto yy87; yy268: yych = *++cursor_; - if (yych == 'o') goto yy330; + if (yych == 'l') goto yy330; goto yy87; yy269: + yych = *++cursor_; + if (yych == '_') goto yy331; + goto yy87; +yy270: + yych = *++cursor_; + if (yych == 'n') goto yy332; + goto yy87; +yy271: + yych = *++cursor_; + if (yych == 'o') goto yy334; + goto yy87; +yy272: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 466 "src/wast-lexer.cc" - { RETURN(TRY); } -#line 2044 "src/prebuilt/wast-lexer-gen.cc" -yy271: +#line 608 "src/wast-lexer.cc" + { RETURN_OPCODE0(Try); } +#line 2338 "src/prebuilt/wast-lexer-gen.cc" +yy274: yych = *++cursor_; - if (yych == 'e') goto yy331; + if (yych == 'e') goto yy335; goto yy87; -yy272: +yy275: yych = *++cursor_; - if (yych == 'e') goto yy333; + if (yych == 'e') goto yy337; goto yy87; -yy273: +yy276: ++cursor_; if ((limit_ - cursor_) < 3) FILL(3); yych = *cursor_; - if (yych <= '9') { - if (yych <= '\'') { - if (yych == '!') goto yy86; - if (yych <= '"') goto yy146; - goto yy86; + if (yych <= ';') { + if (yych <= ')') { + if (yych <= '!') { + if (yych <= ' ') goto yy146; + goto yy86; + } else { + if (yych <= '"') goto yy146; + if (yych <= '\'') goto yy86; + goto yy146; + } } else { - if (yych <= '-') { - if (yych <= ')') goto yy146; + if (yych <= '/') { + if (yych == '.') goto yy279; goto yy86; } else { - if (yych <= '.') goto yy275; - if (yych <= '/') goto yy86; - goto yy273; + if (yych <= '9') goto yy276; + if (yych <= ':') goto yy86; + goto yy146; } } } else { - if (yych <= '`') { - if (yych <= ';') { - if (yych <= ':') goto yy86; - goto yy146; - } else { + if (yych <= '_') { + if (yych <= 'O') { if (yych <= '@') goto yy86; - if (yych <= 'F') goto yy273; + if (yych <= 'F') goto yy276; goto yy86; + } else { + if (yych <= 'P') goto yy281; + if (yych <= '^') goto yy86; + goto yy206; } } else { if (yych <= 'o') { - if (yych <= 'f') goto yy273; + if (yych <= '`') goto yy86; + if (yych <= 'f') goto yy276; goto yy86; } else { - if (yych <= 'p') goto yy277; + if (yych <= 'p') goto yy281; if (yych <= '~') goto yy86; goto yy146; } } } -yy275: +yy278: ++cursor_; - if ((limit_ - cursor_) < 3) FILL(3); + if (limit_ <= cursor_) FILL(1); yych = *cursor_; - if (yych <= ':') { - if (yych <= '\'') { - if (yych == '!') goto yy86; - if (yych <= '"') goto yy88; + if (yych <= ')') { + if (yych <= '!') { + if (yych <= ' ') goto yy88; goto yy86; } else { - if (yych <= ')') goto yy88; + if (yych <= '"') goto yy88; + if (yych <= '\'') goto yy86; + goto yy88; + } + } else { + if (yych <= ':') { if (yych <= '/') goto yy86; - if (yych <= '9') goto yy275; + if (yych <= '9') goto yy208; goto yy86; + } else { + if (yych <= ';') goto yy88; + if (yych <= '~') goto yy86; + goto yy88; + } + } +yy279: + ++cursor_; + if ((yych = *cursor_) <= ';') { + if (yych <= '\'') { + if (yych == '!') goto yy86; + if (yych >= '#') goto yy86; + } else { + if (yych <= '/') { + if (yych >= '*') goto yy86; + } else { + if (yych <= '9') goto yy338; + if (yych <= ':') goto yy86; + } } } else { if (yych <= '`') { - if (yych <= ';') goto yy88; - if (yych <= '@') goto yy86; - if (yych <= 'F') goto yy275; - goto yy86; + if (yych <= 'F') { + if (yych <= '@') goto yy86; + goto yy338; + } else { + if (yych == 'P') goto yy281; + goto yy86; + } } else { if (yych <= 'o') { - if (yych <= 'f') goto yy275; + if (yych <= 'f') goto yy338; goto yy86; } else { - if (yych <= 'p') goto yy277; + if (yych <= 'p') goto yy281; if (yych <= '~') goto yy86; - goto yy88; } } } -yy277: +yy280: +#line 374 "src/wast-lexer.cc" + { RETURN_LITERAL(Float, Hexfloat); } +#line 2454 "src/prebuilt/wast-lexer-gen.cc" +yy281: yych = *++cursor_; if (yych <= ',') { - if (yych == '+') goto yy334; + if (yych == '+') goto yy340; goto yy87; } else { - if (yych <= '-') goto yy334; + if (yych <= '-') goto yy340; if (yych <= '/') goto yy87; - if (yych <= '9') goto yy335; + if (yych <= '9') goto yy341; goto yy87; } -yy278: +yy282: yych = *++cursor_; - if (yych == 'n') goto yy338; + if (yych == 'n') goto yy343; goto yy87; -yy279: +yy283: yych = *++cursor_; - if (yych == 'u') goto yy339; + if (yych == 'u') goto yy344; goto yy87; -yy280: +yy284: yych = *++cursor_; - if (yych == 'r') goto yy340; + if (yych == 'r') goto yy345; goto yy87; -yy281: +yy285: yych = *++cursor_; - if (yych == 'r') goto yy341; + if (yych == 'r') goto yy346; goto yy87; -yy282: +yy286: yych = *++cursor_; - if (yych == 'k') goto yy342; + if (yych == 'k') goto yy347; goto yy87; -yy283: +yy287: yych = *++cursor_; - if (yych == 'f') goto yy344; + if (yych == 'f') goto yy349; goto yy87; -yy284: +yy288: yych = *++cursor_; - if (yych == 'a') goto yy346; + if (yych == 'a') goto yy351; goto yy87; -yy285: +yy289: ++cursor_; if ((yych = *cursor_) <= ')') { if (yych <= '!') { if (yych >= '!') goto yy86; } else { - if (yych <= '"') goto yy286; + if (yych <= '"') goto yy290; if (yych <= '\'') goto yy86; } } else { if (yych <= '^') { if (yych != ';') goto yy86; } else { - if (yych <= '_') goto yy347; + if (yych <= '_') goto yy352; if (yych <= '~') goto yy86; } } -yy286: -#line 269 "src/wast-lexer.cc" - { RETURN(CALL); } -#line 2184 "src/prebuilt/wast-lexer-gen.cc" -yy287: +yy290: +#line 405 "src/wast-lexer.cc" + { RETURN_OPCODE0(Call); } +#line 2514 "src/prebuilt/wast-lexer-gen.cc" +yy291: yych = *++cursor_; - if (yych == 'h') goto yy348; + if (yych == 'h') goto yy353; goto yy87; -yy288: +yy292: yych = *++cursor_; - if (yych == 'e') goto yy350; + if (yych == 'e') goto yy355; goto yy87; -yy289: +yy293: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 448 "src/wast-lexer.cc" - { RETURN(DATA); } -#line 2200 "src/prebuilt/wast-lexer-gen.cc" -yy291: +#line 592 "src/wast-lexer.cc" + { RETURN(Data); } +#line 2530 "src/prebuilt/wast-lexer-gen.cc" +yy295: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 271 "src/wast-lexer.cc" - { RETURN(DROP); } -#line 2208 "src/prebuilt/wast-lexer-gen.cc" -yy293: +#line 407 "src/wast-lexer.cc" + { RETURN_OPCODE0(Drop); } +#line 2538 "src/prebuilt/wast-lexer-gen.cc" +yy297: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 447 "src/wast-lexer.cc" - { RETURN(ELEM); } -#line 2216 "src/prebuilt/wast-lexer-gen.cc" -yy295: +#line 591 "src/wast-lexer.cc" + { RETURN(Elem); } +#line 2546 "src/prebuilt/wast-lexer-gen.cc" +yy299: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 264 "src/wast-lexer.cc" - { RETURN(ELSE); } -#line 2224 "src/prebuilt/wast-lexer-gen.cc" -yy297: +#line 400 "src/wast-lexer.cc" + { RETURN(Else); } +#line 2554 "src/prebuilt/wast-lexer-gen.cc" +yy301: yych = *++cursor_; - if (yych == 'p') goto yy351; + if (yych == 'p') goto yy356; goto yy87; -yy298: +yy302: yych = *++cursor_; - if (yych == 'r') goto yy352; + if (yych == 'r') goto yy357; goto yy87; -yy299: +yy303: yych = *++cursor_; switch (yych) { - case 'a': goto yy353; - case 'c': goto yy354; - case 'd': goto yy355; - case 'e': goto yy356; - case 'f': goto yy357; - case 'g': goto yy358; - case 'l': goto yy359; - case 'm': goto yy360; - case 'n': goto yy361; - case 'r': goto yy362; - case 's': goto yy363; - case 't': goto yy364; + case 'a': goto yy358; + case 'c': goto yy359; + case 'd': goto yy360; + case 'e': goto yy361; + case 'f': goto yy362; + case 'g': goto yy363; + case 'l': goto yy364; + case 'm': goto yy365; + case 'n': goto yy366; + case 'r': goto yy367; + case 's': goto yy368; + case 't': goto yy369; default: goto yy87; } -yy300: +yy304: yych = *++cursor_; switch (yych) { - case 'a': goto yy365; - case 'c': goto yy366; - case 'd': goto yy367; - case 'e': goto yy368; - case 'f': goto yy369; - case 'g': goto yy370; - case 'l': goto yy371; - case 'm': goto yy372; - case 'n': goto yy373; - case 'p': goto yy374; - case 'r': goto yy375; - case 's': goto yy376; - case 't': goto yy377; + case 'a': goto yy370; + case 'c': goto yy371; + case 'd': goto yy372; + case 'e': goto yy373; + case 'f': goto yy374; + case 'g': goto yy375; + case 'l': goto yy376; + case 'm': goto yy377; + case 'n': goto yy378; + case 'p': goto yy379; + case 'r': goto yy380; + case 's': goto yy381; + case 't': goto yy382; default: goto yy87; } -yy301: +yy305: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 436 "src/wast-lexer.cc" - { RETURN(FUNC); } -#line 2275 "src/prebuilt/wast-lexer-gen.cc" -yy303: +#line 580 "src/wast-lexer.cc" + { RETURN(Func); } +#line 2605 "src/prebuilt/wast-lexer-gen.cc" +yy307: yych = *++cursor_; - if (yych == 'g') goto yy378; - if (yych == 'l') goto yy379; + if (yych == 'g') goto yy383; + if (yych == 'l') goto yy384; goto yy87; -yy304: +yy308: yych = *++cursor_; - if (yych == 'a') goto yy380; + if (yych == 'a') goto yy385; goto yy87; -yy305: +yy309: yych = *++cursor_; - if (yych == '_') goto yy381; + if (yych == '_') goto yy386; goto yy87; -yy306: +yy310: yych = *++cursor_; switch (yych) { - case 'a': goto yy382; - case 'c': goto yy383; - case 'd': goto yy384; - case 'e': goto yy385; - case 'g': goto yy386; - case 'l': goto yy387; - case 'm': goto yy388; - case 'n': goto yy389; - case 'o': goto yy390; - case 'p': goto yy391; - case 'r': goto yy392; - case 's': goto yy393; - case 't': goto yy394; - case 'w': goto yy395; - case 'x': goto yy396; + case 'a': goto yy387; + case 'c': goto yy388; + case 'd': goto yy389; + case 'e': goto yy390; + case 'g': goto yy391; + case 'l': goto yy392; + case 'm': goto yy393; + case 'n': goto yy394; + case 'o': goto yy395; + case 'p': goto yy396; + case 'r': goto yy397; + case 's': goto yy398; + case 't': goto yy399; + case 'w': goto yy400; + case 'x': goto yy401; default: goto yy87; } -yy307: +yy311: yych = *++cursor_; switch (yych) { - case 'a': goto yy397; - case 'c': goto yy398; - case 'd': goto yy399; - case 'e': goto yy400; - case 'g': goto yy401; - case 'l': goto yy402; - case 'm': goto yy403; - case 'n': goto yy404; - case 'o': goto yy405; - case 'p': goto yy406; - case 'r': goto yy407; - case 's': goto yy408; - case 't': goto yy409; - case 'x': goto yy410; + case 'a': goto yy402; + case 'c': goto yy403; + case 'd': goto yy404; + case 'e': goto yy405; + case 'g': goto yy406; + case 'l': goto yy407; + case 'm': goto yy408; + case 'n': goto yy409; + case 'o': goto yy410; + case 'p': goto yy411; + case 'r': goto yy412; + case 's': goto yy413; + case 't': goto yy414; + case 'x': goto yy415; default: goto yy87; } -yy308: +yy312: yych = *++cursor_; - if (yych == 'r') goto yy411; + if (yych == 'r') goto yy416; goto yy87; -yy309: +yy313: yych = *++cursor_; - if (yych == 'k') goto yy412; + if (yych == 'k') goto yy417; goto yy87; -yy310: +yy314: yych = *++cursor_; - if (yych == 'l') goto yy413; + if (yych == 'l') goto yy418; goto yy87; -yy311: +yy315: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 265 "src/wast-lexer.cc" - { RETURN(LOOP); } -#line 2347 "src/prebuilt/wast-lexer-gen.cc" -yy313: - yych = *++cursor_; - if (yych == 'r') goto yy415; - goto yy87; -yy314: - yych = *++cursor_; - if (yych == 'l') goto yy416; - goto yy87; -yy315: - yych = *++cursor_; - if (yych == '0') goto yy417; - goto yy87; -yy316: - yych = *++cursor_; - if (yych == 'e') goto yy418; - goto yy87; +#line 401 "src/wast-lexer.cc" + { RETURN_OPCODE0(Loop); } +#line 2677 "src/prebuilt/wast-lexer-gen.cc" yy317: yych = *++cursor_; - if (yych == 'm') goto yy419; + if (yych == 'r') goto yy420; goto yy87; yy318: yych = *++cursor_; - if (yych == 'e') goto yy421; + if (yych == 'l') goto yy421; goto yy87; yy319: yych = *++cursor_; - if (yych == 's') goto yy423; + if (yych == '0') goto yy422; goto yy87; yy320: yych = *++cursor_; - if (yych == 'l') goto yy424; + if (yych == 'e') goto yy423; goto yy87; yy321: yych = *++cursor_; - if (yych == 'r') goto yy425; + if (yych == 'm') goto yy424; goto yy87; yy322: yych = *++cursor_; - if (yych == 'r') goto yy426; + if (yych == 'e') goto yy426; goto yy87; yy323: yych = *++cursor_; - if (yych == 'c') goto yy427; + if (yych == 's') goto yy428; goto yy87; yy324: yych = *++cursor_; - if (yych == 'g') goto yy428; if (yych == 'l') goto yy429; goto yy87; yy325: yych = *++cursor_; - if (yych == 't') goto yy430; + if (yych == 'r') goto yy430; goto yy87; yy326: yych = *++cursor_; - if (yych == 'e') goto yy432; + if (yych == 'r') goto yy431; goto yy87; yy327: yych = *++cursor_; - if (yych == 'l') goto yy434; + if (yych == 'c') goto yy432; goto yy87; yy328: + yych = *++cursor_; + if (yych == 'g') goto yy433; + if (yych == 'l') goto yy434; + goto yy87; +yy329: + yych = *++cursor_; + if (yych == 't') goto yy435; + goto yy87; +yy330: + yych = *++cursor_; + if (yych == 'e') goto yy437; + goto yy87; +yy331: + yych = *++cursor_; + if (yych == 'l') goto yy439; + goto yy87; +yy332: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 263 "src/wast-lexer.cc" - { RETURN(THEN); } -#line 2416 "src/prebuilt/wast-lexer-gen.cc" -yy330: +#line 399 "src/wast-lexer.cc" + { RETURN(Then); } +#line 2746 "src/prebuilt/wast-lexer-gen.cc" +yy334: yych = *++cursor_; - if (yych == 'w') goto yy435; + if (yych == 'w') goto yy440; goto yy87; -yy331: +yy335: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 435 "src/wast-lexer.cc" - { RETURN(TYPE); } -#line 2428 "src/prebuilt/wast-lexer-gen.cc" -yy333: +#line 579 "src/wast-lexer.cc" + { RETURN(Type); } +#line 2758 "src/prebuilt/wast-lexer-gen.cc" +yy337: yych = *++cursor_; - if (yych == 'a') goto yy437; + if (yych == 'a') goto yy442; goto yy87; -yy334: - yych = *++cursor_; - if (yych <= '/') goto yy87; - if (yych >= ':') goto yy87; -yy335: +yy338: + ++cursor_; + if ((limit_ - cursor_) < 2) FILL(2); + yych = *cursor_; + if (yych <= '@') { + if (yych <= ')') { + if (yych <= '!') { + if (yych <= ' ') goto yy280; + goto yy86; + } else { + if (yych <= '"') goto yy280; + if (yych <= '\'') goto yy86; + goto yy280; + } + } else { + if (yych <= '9') { + if (yych <= '/') goto yy86; + goto yy338; + } else { + if (yych == ';') goto yy280; + goto yy86; + } + } + } else { + if (yych <= '_') { + if (yych <= 'O') { + if (yych <= 'F') goto yy338; + goto yy86; + } else { + if (yych <= 'P') goto yy281; + if (yych <= '^') goto yy86; + goto yy443; + } + } else { + if (yych <= 'o') { + if (yych <= '`') goto yy86; + if (yych <= 'f') goto yy338; + goto yy86; + } else { + if (yych <= 'p') goto yy281; + if (yych <= '~') goto yy86; + goto yy280; + } + } + } +yy340: ++cursor_; if (limit_ <= cursor_) FILL(1); yych = *cursor_; if (yych <= ')') { if (yych <= '!') { - if (yych >= '!') goto yy86; + if (yych <= ' ') goto yy88; + goto yy86; } else { - if (yych <= '"') goto yy337; + if (yych <= '"') goto yy88; if (yych <= '\'') goto yy86; + goto yy88; } } else { if (yych <= ':') { if (yych <= '/') goto yy86; - if (yych <= '9') goto yy335; + if (yych >= ':') goto yy86; + } else { + if (yych <= ';') goto yy88; + if (yych <= '~') goto yy86; + goto yy88; + } + } +yy341: + ++cursor_; + if (limit_ <= cursor_) FILL(1); + yych = *cursor_; + if (yych <= '/') { + if (yych <= '"') { + if (yych == '!') goto yy86; + goto yy280; + } else { + if (yych <= '\'') goto yy86; + if (yych <= ')') goto yy280; goto yy86; + } + } else { + if (yych <= ';') { + if (yych <= '9') goto yy341; + if (yych <= ':') goto yy86; + goto yy280; } else { - if (yych <= ';') goto yy337; + if (yych == '_') goto yy340; if (yych <= '~') goto yy86; + goto yy280; } } -yy337: -#line 238 "src/wast-lexer.cc" - { LITERAL(Hexfloat); RETURN(FLOAT); } -#line 2461 "src/prebuilt/wast-lexer-gen.cc" -yy338: +yy343: yych = *++cursor_; - if (yych == '=') goto yy438; + if (yych == '=') goto yy444; goto yy87; -yy339: +yy344: yych = *++cursor_; - if (yych == 'n') goto yy439; + if (yych == 'n') goto yy445; goto yy87; -yy340: +yy345: yych = *++cursor_; - if (yych == 't') goto yy440; + if (yych == 't') goto yy446; goto yy87; -yy341: +yy346: yych = *++cursor_; - if (yych == 'y') goto yy441; + if (yych == 'y') goto yy447; goto yy87; -yy342: +yy347: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 261 "src/wast-lexer.cc" - { RETURN(BLOCK); } -#line 2485 "src/prebuilt/wast-lexer-gen.cc" -yy344: +#line 397 "src/wast-lexer.cc" + { RETURN(Block); } +#line 2878 "src/prebuilt/wast-lexer-gen.cc" +yy349: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 267 "src/wast-lexer.cc" - { RETURN(BR_IF); } -#line 2493 "src/prebuilt/wast-lexer-gen.cc" -yy346: +#line 403 "src/wast-lexer.cc" + { RETURN_OPCODE0(BrIf); } +#line 2886 "src/prebuilt/wast-lexer-gen.cc" +yy351: yych = *++cursor_; - if (yych == 'b') goto yy443; + if (yych == 'b') goto yy449; goto yy87; -yy347: +yy352: yych = *++cursor_; - if (yych == 'i') goto yy444; + if (yych == 'i') goto yy450; goto yy87; -yy348: +yy353: ++cursor_; if ((yych = *cursor_) <= ')') { if (yych <= '!') { if (yych >= '!') goto yy86; } else { - if (yych <= '"') goto yy349; + if (yych <= '"') goto yy354; if (yych <= '\'') goto yy86; } } else { if (yych <= '^') { if (yych != ';') goto yy86; } else { - if (yych <= '_') goto yy445; + if (yych <= '_') goto yy451; if (yych <= '~') goto yy86; } } -yy349: -#line 467 "src/wast-lexer.cc" - { RETURN(CATCH); } -#line 2522 "src/prebuilt/wast-lexer-gen.cc" -yy350: +yy354: +#line 609 "src/wast-lexer.cc" + { RETURN_OPCODE0(Catch); } +#line 2915 "src/prebuilt/wast-lexer-gen.cc" +yy355: yych = *++cursor_; - if (yych == 'n') goto yy446; + if (yych == 'n') goto yy452; goto yy87; -yy351: +yy356: yych = *++cursor_; - if (yych == 't') goto yy447; + if (yych == 't') goto yy453; goto yy87; -yy352: +yy357: yych = *++cursor_; - if (yych == 't') goto yy449; + if (yych == 't') goto yy455; goto yy87; -yy353: +yy358: yych = *++cursor_; - if (yych == 'b') goto yy451; - if (yych == 'd') goto yy452; + if (yych == 'b') goto yy457; + if (yych == 'd') goto yy458; goto yy87; -yy354: +yy359: yych = *++cursor_; - if (yych == 'e') goto yy453; - if (yych == 'o') goto yy454; + if (yych == 'e') goto yy459; + if (yych == 'o') goto yy460; goto yy87; -yy355: +yy360: yych = *++cursor_; - if (yych == 'e') goto yy455; - if (yych == 'i') goto yy456; + if (yych == 'e') goto yy461; + if (yych == 'i') goto yy462; goto yy87; -yy356: +yy361: yych = *++cursor_; - if (yych == 'q') goto yy457; + if (yych == 'q') goto yy463; goto yy87; -yy357: +yy362: yych = *++cursor_; - if (yych == 'l') goto yy459; + if (yych == 'l') goto yy465; goto yy87; -yy358: +yy363: yych = *++cursor_; - if (yych == 'e') goto yy460; - if (yych == 't') goto yy462; + if (yych == 'e') goto yy466; + if (yych == 't') goto yy468; goto yy87; -yy359: +yy364: yych = *++cursor_; if (yych <= 'n') { - if (yych == 'e') goto yy464; + if (yych == 'e') goto yy470; goto yy87; } else { - if (yych <= 'o') goto yy466; - if (yych == 't') goto yy467; + if (yych <= 'o') goto yy472; + if (yych == 't') goto yy473; goto yy87; } -yy360: +yy365: yych = *++cursor_; if (yych <= 'h') { - if (yych == 'a') goto yy469; + if (yych == 'a') goto yy475; goto yy87; } else { - if (yych <= 'i') goto yy470; - if (yych == 'u') goto yy471; + if (yych <= 'i') goto yy476; + if (yych == 'u') goto yy477; goto yy87; } -yy361: +yy366: yych = *++cursor_; - if (yych == 'e') goto yy472; + if (yych == 'e') goto yy478; goto yy87; -yy362: +yy367: yych = *++cursor_; - if (yych == 'e') goto yy474; + if (yych == 'e') goto yy480; goto yy87; -yy363: +yy368: yych = *++cursor_; if (yych <= 's') { - if (yych == 'q') goto yy475; + if (yych == 'q') goto yy481; goto yy87; } else { - if (yych <= 't') goto yy476; - if (yych <= 'u') goto yy477; + if (yych <= 't') goto yy482; + if (yych <= 'u') goto yy483; goto yy87; } -yy364: - yych = *++cursor_; - if (yych == 'r') goto yy478; - goto yy87; -yy365: - yych = *++cursor_; - if (yych == 'b') goto yy479; - if (yych == 'd') goto yy480; - goto yy87; -yy366: - yych = *++cursor_; - if (yych == 'e') goto yy481; - if (yych == 'o') goto yy482; - goto yy87; -yy367: - yych = *++cursor_; - if (yych == 'i') goto yy483; - goto yy87; -yy368: - yych = *++cursor_; - if (yych == 'q') goto yy484; - goto yy87; yy369: yych = *++cursor_; - if (yych == 'l') goto yy486; + if (yych == 'r') goto yy484; goto yy87; yy370: yych = *++cursor_; - if (yych == 'e') goto yy487; - if (yych == 't') goto yy489; + if (yych == 'b') goto yy485; + if (yych == 'd') goto yy486; goto yy87; yy371: yych = *++cursor_; - if (yych <= 'n') { - if (yych == 'e') goto yy491; - goto yy87; - } else { - if (yych <= 'o') goto yy493; - if (yych == 't') goto yy494; - goto yy87; - } + if (yych == 'e') goto yy487; + if (yych == 'o') goto yy488; + goto yy87; yy372: yych = *++cursor_; - if (yych <= 'h') { - if (yych == 'a') goto yy496; - goto yy87; - } else { - if (yych <= 'i') goto yy497; - if (yych == 'u') goto yy498; - goto yy87; - } + if (yych == 'i') goto yy489; + goto yy87; yy373: yych = *++cursor_; - if (yych == 'e') goto yy499; + if (yych == 'q') goto yy490; goto yy87; yy374: yych = *++cursor_; - if (yych == 'r') goto yy501; + if (yych == 'l') goto yy492; goto yy87; yy375: yych = *++cursor_; - if (yych == 'e') goto yy502; + if (yych == 'e') goto yy493; + if (yych == 't') goto yy495; goto yy87; yy376: yych = *++cursor_; - if (yych <= 's') { - if (yych == 'q') goto yy503; + if (yych <= 'n') { + if (yych == 'e') goto yy497; goto yy87; } else { - if (yych <= 't') goto yy504; - if (yych <= 'u') goto yy505; + if (yych <= 'o') goto yy499; + if (yych == 't') goto yy500; goto yy87; } yy377: yych = *++cursor_; - if (yych == 'r') goto yy506; - goto yy87; + if (yych <= 'h') { + if (yych == 'a') goto yy502; + goto yy87; + } else { + if (yych <= 'i') goto yy503; + if (yych == 'u') goto yy504; + goto yy87; + } yy378: yych = *++cursor_; - if (yych == 'l') goto yy507; + if (yych == 'e') goto yy505; goto yy87; yy379: yych = *++cursor_; - if (yych == 'o') goto yy508; + if (yych == 'r') goto yy507; goto yy87; yy380: yych = *++cursor_; - if (yych == 'l') goto yy509; + if (yych == 'e') goto yy508; goto yy87; yy381: yych = *++cursor_; - if (yych == 'm') goto yy511; - goto yy87; + if (yych <= 's') { + if (yych == 'q') goto yy509; + goto yy87; + } else { + if (yych <= 't') goto yy510; + if (yych <= 'u') goto yy511; + goto yy87; + } yy382: yych = *++cursor_; - if (yych == 'd') goto yy512; - if (yych == 'n') goto yy513; + if (yych == 'r') goto yy512; goto yy87; yy383: yych = *++cursor_; - if (yych <= 'n') { - if (yych == 'l') goto yy514; - goto yy87; - } else { - if (yych <= 'o') goto yy515; - if (yych == 't') goto yy516; - goto yy87; - } + if (yych == 'l') goto yy513; + goto yy87; yy384: yych = *++cursor_; - if (yych == 'i') goto yy517; + if (yych == 'o') goto yy514; goto yy87; yy385: yych = *++cursor_; - if (yych == 'q') goto yy518; + if (yych == 'l') goto yy515; goto yy87; yy386: yych = *++cursor_; - if (yych == 'e') goto yy520; - if (yych == 't') goto yy521; + if (yych == 'm') goto yy517; goto yy87; yy387: + yych = *++cursor_; + if (yych == 'd') goto yy518; + if (yych == 'n') goto yy519; + goto yy87; +yy388: yych = *++cursor_; if (yych <= 'n') { - if (yych == 'e') goto yy522; + if (yych == 'l') goto yy520; goto yy87; } else { - if (yych <= 'o') goto yy523; - if (yych == 't') goto yy524; + if (yych <= 'o') goto yy521; + if (yych == 't') goto yy522; goto yy87; } -yy388: - yych = *++cursor_; - if (yych == 'u') goto yy525; - goto yy87; yy389: yych = *++cursor_; - if (yych == 'e') goto yy526; + if (yych == 'i') goto yy523; goto yy87; yy390: yych = *++cursor_; - if (yych == 'r') goto yy528; + if (yych == 'q') goto yy524; goto yy87; yy391: yych = *++cursor_; - if (yych == 'o') goto yy530; + if (yych == 'e') goto yy526; + if (yych == 't') goto yy527; goto yy87; yy392: yych = *++cursor_; - if (yych == 'e') goto yy531; - if (yych == 'o') goto yy532; - goto yy87; -yy393: - yych = *++cursor_; - if (yych <= 's') { - if (yych == 'h') goto yy533; + if (yych <= 'n') { + if (yych == 'e') goto yy528; goto yy87; } else { - if (yych <= 't') goto yy534; - if (yych <= 'u') goto yy535; + if (yych <= 'o') goto yy529; + if (yych == 't') goto yy530; goto yy87; } +yy393: + yych = *++cursor_; + if (yych == 'u') goto yy531; + goto yy87; yy394: yych = *++cursor_; - if (yych == 'r') goto yy536; + if (yych == 'e') goto yy532; goto yy87; yy395: yych = *++cursor_; - if (yych == 'r') goto yy537; + if (yych == 'r') goto yy534; goto yy87; yy396: yych = *++cursor_; - if (yych == 'o') goto yy538; + if (yych == 'o') goto yy536; goto yy87; yy397: yych = *++cursor_; - if (yych == 'd') goto yy539; - if (yych == 'n') goto yy540; + if (yych == 'e') goto yy537; + if (yych == 'o') goto yy538; goto yy87; yy398: yych = *++cursor_; - if (yych <= 'n') { - if (yych == 'l') goto yy541; + if (yych <= 's') { + if (yych == 'h') goto yy539; goto yy87; } else { - if (yych <= 'o') goto yy542; - if (yych == 't') goto yy543; + if (yych <= 't') goto yy540; + if (yych <= 'u') goto yy541; goto yy87; } yy399: yych = *++cursor_; - if (yych == 'i') goto yy544; + if (yych == 'r') goto yy542; goto yy87; yy400: yych = *++cursor_; - if (yych == 'q') goto yy545; - if (yych == 'x') goto yy547; + if (yych == 'r') goto yy543; goto yy87; yy401: yych = *++cursor_; - if (yych == 'e') goto yy548; - if (yych == 't') goto yy549; + if (yych == 'o') goto yy544; goto yy87; yy402: + yych = *++cursor_; + if (yych == 'd') goto yy545; + if (yych == 'n') goto yy546; + goto yy87; +yy403: yych = *++cursor_; if (yych <= 'n') { - if (yych == 'e') goto yy550; + if (yych == 'l') goto yy547; goto yy87; } else { - if (yych <= 'o') goto yy551; - if (yych == 't') goto yy552; + if (yych <= 'o') goto yy548; + if (yych == 't') goto yy549; goto yy87; } -yy403: - yych = *++cursor_; - if (yych == 'u') goto yy553; - goto yy87; yy404: yych = *++cursor_; - if (yych == 'e') goto yy554; + if (yych == 'i') goto yy550; goto yy87; yy405: yych = *++cursor_; - if (yych == 'r') goto yy556; + if (yych == 'q') goto yy551; + if (yych == 'x') goto yy553; goto yy87; yy406: yych = *++cursor_; - if (yych == 'o') goto yy558; + if (yych == 'e') goto yy554; + if (yych == 't') goto yy555; goto yy87; yy407: yych = *++cursor_; - if (yych == 'e') goto yy559; - if (yych == 'o') goto yy560; - goto yy87; -yy408: - yych = *++cursor_; - if (yych <= 's') { - if (yych == 'h') goto yy561; + if (yych <= 'n') { + if (yych == 'e') goto yy556; goto yy87; } else { - if (yych <= 't') goto yy562; - if (yych <= 'u') goto yy563; + if (yych <= 'o') goto yy557; + if (yych == 't') goto yy558; goto yy87; } +yy408: + yych = *++cursor_; + if (yych == 'u') goto yy559; + goto yy87; yy409: yych = *++cursor_; - if (yych == 'r') goto yy564; + if (yych == 'e') goto yy560; goto yy87; yy410: yych = *++cursor_; - if (yych == 'o') goto yy565; + if (yych == 'r') goto yy562; goto yy87; yy411: yych = *++cursor_; - if (yych == 't') goto yy566; + if (yych == 'o') goto yy564; goto yy87; yy412: yych = *++cursor_; - if (yych == 'e') goto yy568; + if (yych == 'e') goto yy565; + if (yych == 'o') goto yy566; goto yy87; yy413: - ++cursor_; - if (yybm[0+(yych = *cursor_)] & 8) { - goto yy86; + yych = *++cursor_; + if (yych <= 's') { + if (yych == 'h') goto yy567; + goto yy87; + } else { + if (yych <= 't') goto yy568; + if (yych <= 'u') goto yy569; + goto yy87; } -#line 439 "src/wast-lexer.cc" - { RETURN(LOCAL); } -#line 2868 "src/prebuilt/wast-lexer-gen.cc" +yy414: + yych = *++cursor_; + if (yych == 'r') goto yy570; + goto yy87; yy415: yych = *++cursor_; - if (yych == 'y') goto yy570; + if (yych == 'o') goto yy571; goto yy87; yy416: yych = *++cursor_; - if (yych == 'e') goto yy572; + if (yych == 't') goto yy572; goto yy87; yy417: yych = *++cursor_; - if (yych == 'x') goto yy574; + if (yych == 'e') goto yy574; goto yy87; yy418: + ++cursor_; + if (yybm[0+(yych = *cursor_)] & 8) { + goto yy86; + } +#line 583 "src/wast-lexer.cc" + { RETURN(Local); } +#line 3261 "src/prebuilt/wast-lexer-gen.cc" +yy420: + yych = *++cursor_; + if (yych == 'y') goto yy576; + goto yy87; +yy421: + yych = *++cursor_; + if (yych == 'e') goto yy578; + goto yy87; +yy422: + yych = *++cursor_; + if (yych == 'x') goto yy580; + goto yy87; +yy423: yych = *++cursor_; - if (yych == 't') goto yy575; + if (yych == 't') goto yy581; goto yy87; -yy419: +yy424: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 437 "src/wast-lexer.cc" - { RETURN(PARAM); } -#line 2892 "src/prebuilt/wast-lexer-gen.cc" -yy421: +#line 581 "src/wast-lexer.cc" + { RETURN(Param); } +#line 3285 "src/prebuilt/wast-lexer-gen.cc" +yy426: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 443 "src/wast-lexer.cc" - { RETURN(QUOTE); } -#line 2900 "src/prebuilt/wast-lexer-gen.cc" -yy423: +#line 587 "src/wast-lexer.cc" + { RETURN(Quote); } +#line 3293 "src/prebuilt/wast-lexer-gen.cc" +yy428: yych = *++cursor_; - if (yych == 't') goto yy577; + if (yych == 't') goto yy583; goto yy87; -yy424: +yy429: yych = *++cursor_; - if (yych == 't') goto yy578; + if (yych == 't') goto yy584; goto yy87; -yy425: +yy430: yych = *++cursor_; - if (yych == 'o') goto yy580; + if (yych == 'o') goto yy586; goto yy87; -yy426: +yy431: yych = *++cursor_; - if (yych == 'n') goto yy581; + if (yych == 'n') goto yy587; goto yy87; -yy427: +yy432: yych = *++cursor_; - if (yych == 't') goto yy583; + if (yych == 't') goto yy589; goto yy87; -yy428: +yy433: yych = *++cursor_; - if (yych == 'l') goto yy585; + if (yych == 'l') goto yy591; goto yy87; -yy429: +yy434: yych = *++cursor_; - if (yych == 'o') goto yy586; + if (yych == 'o') goto yy592; goto yy87; -yy430: +yy435: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 446 "src/wast-lexer.cc" - { RETURN(START); } -#line 2936 "src/prebuilt/wast-lexer-gen.cc" -yy432: +#line 590 "src/wast-lexer.cc" + { RETURN(Start); } +#line 3329 "src/prebuilt/wast-lexer-gen.cc" +yy437: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 444 "src/wast-lexer.cc" - { RETURN(TABLE); } -#line 2944 "src/prebuilt/wast-lexer-gen.cc" -yy434: +#line 588 "src/wast-lexer.cc" + { RETURN(Table); } +#line 3337 "src/prebuilt/wast-lexer-gen.cc" +yy439: yych = *++cursor_; - if (yych == 'o') goto yy587; + if (yych == 'o') goto yy593; goto yy87; -yy435: +yy440: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 469 "src/wast-lexer.cc" - { RETURN(THROW); } -#line 2956 "src/prebuilt/wast-lexer-gen.cc" -yy437: - yych = *++cursor_; - if (yych == 'c') goto yy588; - goto yy87; -yy438: +#line 611 "src/wast-lexer.cc" + { RETURN_OPCODE0(Throw); } +#line 3349 "src/prebuilt/wast-lexer-gen.cc" +yy442: + yych = *++cursor_; + if (yych == 'c') goto yy594; + goto yy87; +yy443: + ++cursor_; + if (limit_ <= cursor_) FILL(1); + yych = *cursor_; + if (yych <= '9') { + if (yych <= '"') { + if (yych == '!') goto yy86; + goto yy88; + } else { + if (yych <= '\'') goto yy86; + if (yych <= ')') goto yy88; + if (yych <= '/') goto yy86; + goto yy338; + } + } else { + if (yych <= 'F') { + if (yych == ';') goto yy88; + if (yych <= '@') goto yy86; + goto yy338; + } else { + if (yych <= '`') goto yy86; + if (yych <= 'f') goto yy338; + if (yych <= '~') goto yy86; + goto yy88; + } + } +yy444: yych = *++cursor_; if (yych <= '/') goto yy87; - if (yych <= '0') goto yy589; - if (yych <= '9') goto yy591; + if (yych <= '0') goto yy595; + if (yych <= '9') goto yy597; goto yy87; -yy439: +yy445: yych = *++cursor_; - if (yych == 'c') goto yy593; + if (yych == 'c') goto yy599; goto yy87; -yy440: +yy446: yych = *++cursor_; - if (yych == '_') goto yy595; + if (yych == '_') goto yy601; goto yy87; -yy441: +yy447: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 442 "src/wast-lexer.cc" - { RETURN(BIN); } -#line 2982 "src/prebuilt/wast-lexer-gen.cc" -yy443: +#line 586 "src/wast-lexer.cc" + { RETURN(Bin); } +#line 3401 "src/prebuilt/wast-lexer-gen.cc" +yy449: yych = *++cursor_; - if (yych == 'l') goto yy596; + if (yych == 'l') goto yy602; goto yy87; -yy444: +yy450: yych = *++cursor_; - if (yych == 'n') goto yy597; + if (yych == 'n') goto yy603; goto yy87; -yy445: +yy451: yych = *++cursor_; - if (yych == 'a') goto yy598; + if (yych == 'a') goto yy604; goto yy87; -yy446: +yy452: yych = *++cursor_; - if (yych == 't') goto yy599; + if (yych == 't') goto yy605; goto yy87; -yy447: +yy453: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 452 "src/wast-lexer.cc" - { RETURN(EXCEPT); } -#line 3006 "src/prebuilt/wast-lexer-gen.cc" -yy449: +#line 596 "src/wast-lexer.cc" + { RETURN(Except); } +#line 3425 "src/prebuilt/wast-lexer-gen.cc" +yy455: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 451 "src/wast-lexer.cc" - { RETURN(EXPORT); } -#line 3014 "src/prebuilt/wast-lexer-gen.cc" -yy451: +#line 595 "src/wast-lexer.cc" + { RETURN(Export); } +#line 3433 "src/prebuilt/wast-lexer-gen.cc" +yy457: yych = *++cursor_; - if (yych == 's') goto yy600; + if (yych == 's') goto yy606; goto yy87; -yy452: +yy458: yych = *++cursor_; - if (yych == 'd') goto yy602; + if (yych == 'd') goto yy608; goto yy87; -yy453: +yy459: yych = *++cursor_; - if (yych == 'i') goto yy604; + if (yych == 'i') goto yy610; goto yy87; -yy454: +yy460: yych = *++cursor_; - if (yych == 'n') goto yy605; - if (yych == 'p') goto yy606; + if (yych == 'n') goto yy611; + if (yych == 'p') goto yy612; goto yy87; -yy455: +yy461: yych = *++cursor_; - if (yych == 'm') goto yy607; + if (yych == 'm') goto yy613; goto yy87; -yy456: +yy462: yych = *++cursor_; - if (yych == 'v') goto yy608; + if (yych == 'v') goto yy614; goto yy87; -yy457: +yy463: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 394 "src/wast-lexer.cc" - { OPCODE(F32Eq); RETURN(COMPARE); } -#line 3047 "src/prebuilt/wast-lexer-gen.cc" -yy459: +#line 530 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, F32Eq); } +#line 3466 "src/prebuilt/wast-lexer-gen.cc" +yy465: yych = *++cursor_; - if (yych == 'o') goto yy610; + if (yych == 'o') goto yy616; goto yy87; -yy460: +yy466: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 404 "src/wast-lexer.cc" - { OPCODE(F32Ge); RETURN(COMPARE); } -#line 3059 "src/prebuilt/wast-lexer-gen.cc" -yy462: +#line 540 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, F32Ge); } +#line 3478 "src/prebuilt/wast-lexer-gen.cc" +yy468: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 402 "src/wast-lexer.cc" - { OPCODE(F32Gt); RETURN(COMPARE); } -#line 3067 "src/prebuilt/wast-lexer-gen.cc" -yy464: +#line 538 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, F32Gt); } +#line 3486 "src/prebuilt/wast-lexer-gen.cc" +yy470: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 400 "src/wast-lexer.cc" - { OPCODE(F32Le); RETURN(COMPARE); } -#line 3075 "src/prebuilt/wast-lexer-gen.cc" -yy466: +#line 536 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, F32Le); } +#line 3494 "src/prebuilt/wast-lexer-gen.cc" +yy472: yych = *++cursor_; - if (yych == 'a') goto yy611; + if (yych == 'a') goto yy617; goto yy87; -yy467: +yy473: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 398 "src/wast-lexer.cc" - { OPCODE(F32Lt); RETURN(COMPARE); } -#line 3087 "src/prebuilt/wast-lexer-gen.cc" -yy469: +#line 534 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, F32Lt); } +#line 3506 "src/prebuilt/wast-lexer-gen.cc" +yy475: yych = *++cursor_; - if (yych == 'x') goto yy612; + if (yych == 'x') goto yy618; goto yy87; -yy470: +yy476: yych = *++cursor_; - if (yych == 'n') goto yy614; + if (yych == 'n') goto yy620; goto yy87; -yy471: +yy477: yych = *++cursor_; - if (yych == 'l') goto yy616; + if (yych == 'l') goto yy622; goto yy87; -yy472: +yy478: ++cursor_; if ((yych = *cursor_) <= ':') { if (yych <= '"') { @@ -3107,120 +3526,120 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { } } else { if (yych <= 'a') { - if (yych <= ';') goto yy473; + if (yych <= ';') goto yy479; if (yych <= '`') goto yy86; - goto yy618; + goto yy624; } else { - if (yych == 'g') goto yy619; + if (yych == 'g') goto yy625; if (yych <= '~') goto yy86; } } -yy473: -#line 396 "src/wast-lexer.cc" - { OPCODE(F32Ne); RETURN(COMPARE); } -#line 3122 "src/prebuilt/wast-lexer-gen.cc" -yy474: +yy479: +#line 532 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, F32Ne); } +#line 3541 "src/prebuilt/wast-lexer-gen.cc" +yy480: yych = *++cursor_; - if (yych == 'i') goto yy621; + if (yych == 'i') goto yy627; goto yy87; -yy475: +yy481: yych = *++cursor_; - if (yych == 'r') goto yy622; + if (yych == 'r') goto yy628; goto yy87; -yy476: +yy482: yych = *++cursor_; - if (yych == 'o') goto yy623; + if (yych == 'o') goto yy629; goto yy87; -yy477: +yy483: yych = *++cursor_; - if (yych == 'b') goto yy624; + if (yych == 'b') goto yy630; goto yy87; -yy478: +yy484: yych = *++cursor_; - if (yych == 'u') goto yy626; + if (yych == 'u') goto yy632; goto yy87; -yy479: +yy485: yych = *++cursor_; - if (yych == 's') goto yy627; + if (yych == 's') goto yy633; goto yy87; -yy480: +yy486: yych = *++cursor_; - if (yych == 'd') goto yy629; + if (yych == 'd') goto yy635; goto yy87; -yy481: +yy487: yych = *++cursor_; - if (yych == 'i') goto yy631; + if (yych == 'i') goto yy637; goto yy87; -yy482: +yy488: yych = *++cursor_; - if (yych == 'n') goto yy632; - if (yych == 'p') goto yy633; + if (yych == 'n') goto yy638; + if (yych == 'p') goto yy639; goto yy87; -yy483: +yy489: yych = *++cursor_; - if (yych == 'v') goto yy634; + if (yych == 'v') goto yy640; goto yy87; -yy484: +yy490: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 395 "src/wast-lexer.cc" - { OPCODE(F64Eq); RETURN(COMPARE); } -#line 3171 "src/prebuilt/wast-lexer-gen.cc" -yy486: +#line 531 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, F64Eq); } +#line 3590 "src/prebuilt/wast-lexer-gen.cc" +yy492: yych = *++cursor_; - if (yych == 'o') goto yy636; + if (yych == 'o') goto yy642; goto yy87; -yy487: +yy493: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 405 "src/wast-lexer.cc" - { OPCODE(F64Ge); RETURN(COMPARE); } -#line 3183 "src/prebuilt/wast-lexer-gen.cc" -yy489: +#line 541 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, F64Ge); } +#line 3602 "src/prebuilt/wast-lexer-gen.cc" +yy495: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 403 "src/wast-lexer.cc" - { OPCODE(F64Gt); RETURN(COMPARE); } -#line 3191 "src/prebuilt/wast-lexer-gen.cc" -yy491: +#line 539 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, F64Gt); } +#line 3610 "src/prebuilt/wast-lexer-gen.cc" +yy497: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 401 "src/wast-lexer.cc" - { OPCODE(F64Le); RETURN(COMPARE); } -#line 3199 "src/prebuilt/wast-lexer-gen.cc" -yy493: +#line 537 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, F64Le); } +#line 3618 "src/prebuilt/wast-lexer-gen.cc" +yy499: yych = *++cursor_; - if (yych == 'a') goto yy637; + if (yych == 'a') goto yy643; goto yy87; -yy494: +yy500: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 399 "src/wast-lexer.cc" - { OPCODE(F64Lt); RETURN(COMPARE); } -#line 3211 "src/prebuilt/wast-lexer-gen.cc" -yy496: +#line 535 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, F64Lt); } +#line 3630 "src/prebuilt/wast-lexer-gen.cc" +yy502: yych = *++cursor_; - if (yych == 'x') goto yy638; + if (yych == 'x') goto yy644; goto yy87; -yy497: +yy503: yych = *++cursor_; - if (yych == 'n') goto yy640; + if (yych == 'n') goto yy646; goto yy87; -yy498: +yy504: yych = *++cursor_; - if (yych == 'l') goto yy642; + if (yych == 'l') goto yy648; goto yy87; -yy499: +yy505: ++cursor_; if ((yych = *cursor_) <= ':') { if (yych <= '"') { @@ -3231,1312 +3650,1373 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { } } else { if (yych <= 'a') { - if (yych <= ';') goto yy500; + if (yych <= ';') goto yy506; if (yych <= '`') goto yy86; - goto yy644; + goto yy650; } else { - if (yych == 'g') goto yy645; + if (yych == 'g') goto yy651; if (yych <= '~') goto yy86; } } -yy500: -#line 397 "src/wast-lexer.cc" - { OPCODE(F64Ne); RETURN(COMPARE); } -#line 3246 "src/prebuilt/wast-lexer-gen.cc" -yy501: +yy506: +#line 533 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, F64Ne); } +#line 3665 "src/prebuilt/wast-lexer-gen.cc" +yy507: yych = *++cursor_; - if (yych == 'o') goto yy647; + if (yych == 'o') goto yy653; goto yy87; -yy502: +yy508: yych = *++cursor_; - if (yych == 'i') goto yy648; + if (yych == 'i') goto yy654; goto yy87; -yy503: +yy509: yych = *++cursor_; - if (yych == 'r') goto yy649; + if (yych == 'r') goto yy655; goto yy87; -yy504: +yy510: yych = *++cursor_; - if (yych == 'o') goto yy650; + if (yych == 'o') goto yy656; goto yy87; -yy505: +yy511: yych = *++cursor_; - if (yych == 'b') goto yy651; + if (yych == 'b') goto yy657; goto yy87; -yy506: +yy512: yych = *++cursor_; - if (yych == 'u') goto yy653; + if (yych == 'u') goto yy659; goto yy87; -yy507: +yy513: yych = *++cursor_; - if (yych == 'o') goto yy654; + if (yych == 'o') goto yy660; goto yy87; -yy508: +yy514: yych = *++cursor_; - if (yych == 'c') goto yy655; + if (yych == 'c') goto yy661; goto yy87; -yy509: +yy515: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 440 "src/wast-lexer.cc" - { RETURN(GLOBAL); } -#line 3286 "src/prebuilt/wast-lexer-gen.cc" -yy511: +#line 584 "src/wast-lexer.cc" + { RETURN(Global); } +#line 3705 "src/prebuilt/wast-lexer-gen.cc" +yy517: yych = *++cursor_; - if (yych == 'e') goto yy656; + if (yych == 'e') goto yy662; goto yy87; -yy512: +yy518: yych = *++cursor_; - if (yych == 'd') goto yy657; + if (yych == 'd') goto yy663; goto yy87; -yy513: +yy519: yych = *++cursor_; - if (yych == 'd') goto yy659; + if (yych == 'd') goto yy665; goto yy87; -yy514: +yy520: yych = *++cursor_; - if (yych == 'z') goto yy661; + if (yych == 'z') goto yy667; goto yy87; -yy515: +yy521: yych = *++cursor_; - if (yych == 'n') goto yy663; + if (yych == 'n') goto yy669; goto yy87; -yy516: +yy522: yych = *++cursor_; - if (yych == 'z') goto yy664; + if (yych == 'z') goto yy670; goto yy87; -yy517: +yy523: yych = *++cursor_; - if (yych == 'v') goto yy666; + if (yych == 'v') goto yy672; goto yy87; -yy518: +yy524: ++cursor_; if ((yych = *cursor_) <= ')') { if (yych <= '!') { if (yych >= '!') goto yy86; } else { - if (yych <= '"') goto yy519; + if (yych <= '"') goto yy525; if (yych <= '\'') goto yy86; } } else { if (yych <= 'y') { if (yych != ';') goto yy86; } else { - if (yych <= 'z') goto yy667; + if (yych <= 'z') goto yy673; if (yych <= '~') goto yy86; } } -yy519: -#line 374 "src/wast-lexer.cc" - { OPCODE(I32Eq); RETURN(COMPARE); } -#line 3335 "src/prebuilt/wast-lexer-gen.cc" -yy520: +yy525: +#line 510 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I32Eq); } +#line 3754 "src/prebuilt/wast-lexer-gen.cc" +yy526: yych = *++cursor_; - if (yych == '_') goto yy669; + if (yych == '_') goto yy675; goto yy87; -yy521: +yy527: yych = *++cursor_; - if (yych == '_') goto yy670; + if (yych == '_') goto yy676; goto yy87; -yy522: +yy528: yych = *++cursor_; - if (yych == '_') goto yy671; + if (yych == '_') goto yy677; goto yy87; -yy523: +yy529: yych = *++cursor_; - if (yych == 'a') goto yy672; + if (yych == 'a') goto yy678; goto yy87; -yy524: +yy530: yych = *++cursor_; - if (yych == '_') goto yy673; + if (yych == '_') goto yy679; goto yy87; -yy525: +yy531: yych = *++cursor_; - if (yych == 'l') goto yy674; + if (yych == 'l') goto yy680; goto yy87; -yy526: +yy532: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 376 "src/wast-lexer.cc" - { OPCODE(I32Ne); RETURN(COMPARE); } -#line 3367 "src/prebuilt/wast-lexer-gen.cc" -yy528: +#line 512 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I32Ne); } +#line 3786 "src/prebuilt/wast-lexer-gen.cc" +yy534: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 346 "src/wast-lexer.cc" - { OPCODE(I32Or); RETURN(BINARY); } -#line 3375 "src/prebuilt/wast-lexer-gen.cc" -yy530: +#line 482 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I32Or); } +#line 3794 "src/prebuilt/wast-lexer-gen.cc" +yy536: yych = *++cursor_; - if (yych == 'p') goto yy676; + if (yych == 'p') goto yy682; goto yy87; -yy531: +yy537: yych = *++cursor_; - if (yych == 'i') goto yy677; - if (yych == 'm') goto yy678; + if (yych == 'i') goto yy683; + if (yych == 'm') goto yy684; goto yy87; -yy532: +yy538: yych = *++cursor_; - if (yych == 't') goto yy679; + if (yych == 't') goto yy685; goto yy87; -yy533: +yy539: yych = *++cursor_; - if (yych == 'l') goto yy680; - if (yych == 'r') goto yy682; + if (yych == 'l') goto yy686; + if (yych == 'r') goto yy688; goto yy87; -yy534: +yy540: yych = *++cursor_; - if (yych == 'o') goto yy683; + if (yych == 'o') goto yy689; goto yy87; -yy535: +yy541: yych = *++cursor_; - if (yych == 'b') goto yy684; + if (yych == 'b') goto yy690; goto yy87; -yy536: +yy542: yych = *++cursor_; - if (yych == 'u') goto yy686; + if (yych == 'u') goto yy692; goto yy87; -yy537: +yy543: yych = *++cursor_; - if (yych == 'a') goto yy687; + if (yych == 'a') goto yy693; goto yy87; -yy538: +yy544: yych = *++cursor_; - if (yych == 'r') goto yy688; + if (yych == 'r') goto yy694; goto yy87; -yy539: +yy545: yych = *++cursor_; - if (yych == 'd') goto yy690; + if (yych == 'd') goto yy696; goto yy87; -yy540: +yy546: yych = *++cursor_; - if (yych == 'd') goto yy692; + if (yych == 'd') goto yy698; goto yy87; -yy541: +yy547: yych = *++cursor_; - if (yych == 'z') goto yy694; + if (yych == 'z') goto yy700; goto yy87; -yy542: +yy548: yych = *++cursor_; - if (yych == 'n') goto yy696; + if (yych == 'n') goto yy702; goto yy87; -yy543: +yy549: yych = *++cursor_; - if (yych == 'z') goto yy697; + if (yych == 'z') goto yy703; goto yy87; -yy544: +yy550: yych = *++cursor_; - if (yych == 'v') goto yy699; + if (yych == 'v') goto yy705; goto yy87; -yy545: +yy551: ++cursor_; if ((yych = *cursor_) <= ')') { if (yych <= '!') { if (yych >= '!') goto yy86; } else { - if (yych <= '"') goto yy546; + if (yych <= '"') goto yy552; if (yych <= '\'') goto yy86; } } else { if (yych <= 'y') { if (yych != ';') goto yy86; } else { - if (yych <= 'z') goto yy700; + if (yych <= 'z') goto yy706; if (yych <= '~') goto yy86; } } -yy546: -#line 375 "src/wast-lexer.cc" - { OPCODE(I64Eq); RETURN(COMPARE); } -#line 3458 "src/prebuilt/wast-lexer-gen.cc" -yy547: +yy552: +#line 511 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I64Eq); } +#line 3877 "src/prebuilt/wast-lexer-gen.cc" +yy553: yych = *++cursor_; - if (yych == 't') goto yy702; + if (yych == 't') goto yy708; goto yy87; -yy548: +yy554: yych = *++cursor_; - if (yych == '_') goto yy703; + if (yych == '_') goto yy709; goto yy87; -yy549: +yy555: yych = *++cursor_; - if (yych == '_') goto yy704; + if (yych == '_') goto yy710; goto yy87; -yy550: +yy556: yych = *++cursor_; - if (yych == '_') goto yy705; + if (yych == '_') goto yy711; goto yy87; -yy551: +yy557: yych = *++cursor_; - if (yych == 'a') goto yy706; + if (yych == 'a') goto yy712; goto yy87; -yy552: +yy558: yych = *++cursor_; - if (yych == '_') goto yy707; + if (yych == '_') goto yy713; goto yy87; -yy553: +yy559: yych = *++cursor_; - if (yych == 'l') goto yy708; + if (yych == 'l') goto yy714; goto yy87; -yy554: +yy560: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 377 "src/wast-lexer.cc" - { OPCODE(I64Ne); RETURN(COMPARE); } -#line 3494 "src/prebuilt/wast-lexer-gen.cc" -yy556: +#line 513 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I64Ne); } +#line 3913 "src/prebuilt/wast-lexer-gen.cc" +yy562: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 347 "src/wast-lexer.cc" - { OPCODE(I64Or); RETURN(BINARY); } -#line 3502 "src/prebuilt/wast-lexer-gen.cc" -yy558: +#line 483 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I64Or); } +#line 3921 "src/prebuilt/wast-lexer-gen.cc" +yy564: yych = *++cursor_; - if (yych == 'p') goto yy710; + if (yych == 'p') goto yy716; goto yy87; -yy559: +yy565: yych = *++cursor_; - if (yych == 'i') goto yy711; - if (yych == 'm') goto yy712; + if (yych == 'i') goto yy717; + if (yych == 'm') goto yy718; goto yy87; -yy560: +yy566: yych = *++cursor_; - if (yych == 't') goto yy713; + if (yych == 't') goto yy719; goto yy87; -yy561: +yy567: yych = *++cursor_; - if (yych == 'l') goto yy714; - if (yych == 'r') goto yy716; + if (yych == 'l') goto yy720; + if (yych == 'r') goto yy722; goto yy87; -yy562: +yy568: yych = *++cursor_; - if (yych == 'o') goto yy717; + if (yych == 'o') goto yy723; goto yy87; -yy563: +yy569: yych = *++cursor_; - if (yych == 'b') goto yy718; + if (yych == 'b') goto yy724; goto yy87; -yy564: +yy570: yych = *++cursor_; - if (yych == 'u') goto yy720; + if (yych == 'u') goto yy726; goto yy87; -yy565: +yy571: yych = *++cursor_; - if (yych == 'r') goto yy721; + if (yych == 'r') goto yy727; goto yy87; -yy566: +yy572: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 450 "src/wast-lexer.cc" - { RETURN(IMPORT); } -#line 3544 "src/prebuilt/wast-lexer-gen.cc" -yy568: +#line 594 "src/wast-lexer.cc" + { RETURN(Import); } +#line 3963 "src/prebuilt/wast-lexer-gen.cc" +yy574: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 454 "src/wast-lexer.cc" - { RETURN(INVOKE); } -#line 3552 "src/prebuilt/wast-lexer-gen.cc" -yy570: +#line 598 "src/wast-lexer.cc" + { RETURN(Invoke); } +#line 3971 "src/prebuilt/wast-lexer-gen.cc" +yy576: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 445 "src/wast-lexer.cc" - { RETURN(MEMORY); } -#line 3560 "src/prebuilt/wast-lexer-gen.cc" -yy572: +#line 589 "src/wast-lexer.cc" + { RETURN(Memory); } +#line 3979 "src/prebuilt/wast-lexer-gen.cc" +yy578: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 441 "src/wast-lexer.cc" - { RETURN(MODULE); } -#line 3568 "src/prebuilt/wast-lexer-gen.cc" -yy574: - yych = *++cursor_; - if (yych <= '@') { - if (yych <= '/') goto yy87; - if (yych <= '9') goto yy723; - goto yy87; +#line 585 "src/wast-lexer.cc" + { RETURN(Module); } +#line 3987 "src/prebuilt/wast-lexer-gen.cc" +yy580: + ++cursor_; + if (limit_ <= cursor_) FILL(1); + yych = *cursor_; + if (yych <= '9') { + if (yych <= '"') { + if (yych == '!') goto yy86; + goto yy88; + } else { + if (yych <= '\'') goto yy86; + if (yych <= ')') goto yy88; + if (yych <= '/') goto yy86; + goto yy729; + } } else { - if (yych <= 'F') goto yy723; - if (yych <= '`') goto yy87; - if (yych <= 'f') goto yy723; - goto yy87; + if (yych <= 'F') { + if (yych == ';') goto yy88; + if (yych <= '@') goto yy86; + goto yy729; + } else { + if (yych <= '`') goto yy86; + if (yych <= 'f') goto yy729; + if (yych <= '~') goto yy86; + goto yy88; + } } -yy575: +yy581: ++cursor_; if ((yych = *cursor_) <= ')') { if (yych <= '!') { if (yych >= '!') goto yy86; } else { - if (yych <= '"') goto yy576; + if (yych <= '"') goto yy582; if (yych <= '\'') goto yy86; } } else { if (yych <= '<') { if (yych != ';') goto yy86; } else { - if (yych <= '=') goto yy725; + if (yych <= '=') goto yy731; if (yych <= '~') goto yy86; } } -yy576: -#line 449 "src/wast-lexer.cc" - { RETURN(OFFSET); } -#line 3601 "src/prebuilt/wast-lexer-gen.cc" -yy577: +yy582: +#line 593 "src/wast-lexer.cc" + { RETURN(Offset); } +#line 4034 "src/prebuilt/wast-lexer-gen.cc" +yy583: yych = *++cursor_; - if (yych == 'e') goto yy726; + if (yych == 'e') goto yy732; goto yy87; -yy578: +yy584: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 438 "src/wast-lexer.cc" - { RETURN(RESULT); } -#line 3613 "src/prebuilt/wast-lexer-gen.cc" -yy580: +#line 582 "src/wast-lexer.cc" + { RETURN(Result); } +#line 4046 "src/prebuilt/wast-lexer-gen.cc" +yy586: yych = *++cursor_; - if (yych == 'w') goto yy727; + if (yych == 'w') goto yy733; goto yy87; -yy581: +yy587: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 273 "src/wast-lexer.cc" - { RETURN(RETURN); } -#line 3625 "src/prebuilt/wast-lexer-gen.cc" -yy583: +#line 409 "src/wast-lexer.cc" + { RETURN_OPCODE0(Return); } +#line 4058 "src/prebuilt/wast-lexer-gen.cc" +yy589: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 431 "src/wast-lexer.cc" - { RETURN(SELECT); } -#line 3633 "src/prebuilt/wast-lexer-gen.cc" -yy585: +#line 575 "src/wast-lexer.cc" + { RETURN_OPCODE0(Select); } +#line 4066 "src/prebuilt/wast-lexer-gen.cc" +yy591: yych = *++cursor_; - if (yych == 'o') goto yy729; + if (yych == 'o') goto yy735; goto yy87; -yy586: +yy592: yych = *++cursor_; - if (yych == 'c') goto yy730; + if (yych == 'c') goto yy736; goto yy87; -yy587: +yy593: yych = *++cursor_; - if (yych == 'c') goto yy731; + if (yych == 'c') goto yy737; goto yy87; -yy588: +yy594: yych = *++cursor_; - if (yych == 'h') goto yy732; + if (yych == 'h') goto yy738; goto yy87; -yy589: +yy595: ++cursor_; - if ((yych = *cursor_) <= '/') { + if ((yych = *cursor_) <= '9') { if (yych <= '"') { if (yych == '!') goto yy86; } else { if (yych <= '\'') goto yy86; - if (yych >= '*') goto yy86; + if (yych <= ')') goto yy596; + if (yych <= '/') goto yy86; + goto yy597; } } else { - if (yych <= ';') { - if (yych <= '9') goto yy591; - if (yych <= ':') goto yy86; + if (yych <= '_') { + if (yych == ';') goto yy596; + if (yych <= '^') goto yy86; + goto yy739; } else { - if (yych == 'x') goto yy733; + if (yych == 'x') goto yy740; if (yych <= '~') goto yy86; } } -yy590: -#line 303 "src/wast-lexer.cc" - { TEXT_AT(6); RETURN(ALIGN_EQ_NAT); } -#line 3671 "src/prebuilt/wast-lexer-gen.cc" -yy591: +yy596: +#line 439 "src/wast-lexer.cc" + { RETURN_TEXT_AT(AlignEqNat, 6); } +#line 4107 "src/prebuilt/wast-lexer-gen.cc" +yy597: ++cursor_; if (limit_ <= cursor_) FILL(1); yych = *cursor_; - if (yych <= ')') { - if (yych <= '!') { - if (yych <= ' ') goto yy590; - goto yy86; + if (yych <= '/') { + if (yych <= '"') { + if (yych == '!') goto yy86; + goto yy596; } else { - if (yych <= '"') goto yy590; if (yych <= '\'') goto yy86; - goto yy590; + if (yych <= ')') goto yy596; + goto yy86; } } else { - if (yych <= ':') { - if (yych <= '/') goto yy86; - if (yych <= '9') goto yy591; - goto yy86; + if (yych <= ';') { + if (yych <= '9') goto yy597; + if (yych <= ':') goto yy86; + goto yy596; } else { - if (yych <= ';') goto yy590; + if (yych == '_') goto yy739; if (yych <= '~') goto yy86; - goto yy590; + goto yy596; } } -yy593: +yy599: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 258 "src/wast-lexer.cc" - { RETURN(ANYFUNC); } -#line 3703 "src/prebuilt/wast-lexer-gen.cc" -yy595: +#line 394 "src/wast-lexer.cc" + { RETURN(Anyfunc); } +#line 4139 "src/prebuilt/wast-lexer-gen.cc" +yy601: yych = *++cursor_; switch (yych) { - case 'e': goto yy734; - case 'i': goto yy735; - case 'm': goto yy736; - case 'r': goto yy737; - case 't': goto yy738; - case 'u': goto yy739; + case 'e': goto yy741; + case 'i': goto yy742; + case 'm': goto yy743; + case 'r': goto yy744; + case 't': goto yy745; + case 'u': goto yy746; default: goto yy87; } -yy596: +yy602: yych = *++cursor_; - if (yych == 'e') goto yy740; + if (yych == 'e') goto yy747; goto yy87; -yy597: +yy603: yych = *++cursor_; - if (yych == 'd') goto yy742; + if (yych == 'd') goto yy749; goto yy87; -yy598: +yy604: yych = *++cursor_; - if (yych == 'l') goto yy743; + if (yych == 'l') goto yy750; goto yy87; -yy599: +yy605: yych = *++cursor_; - if (yych == '_') goto yy744; + if (yych == '_') goto yy751; goto yy87; -yy600: +yy606: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 318 "src/wast-lexer.cc" - { OPCODE(F32Abs); RETURN(UNARY); } -#line 3738 "src/prebuilt/wast-lexer-gen.cc" -yy602: +#line 454 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, F32Abs); } +#line 4174 "src/prebuilt/wast-lexer-gen.cc" +yy608: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 360 "src/wast-lexer.cc" - { OPCODE(F32Add); RETURN(BINARY); } -#line 3746 "src/prebuilt/wast-lexer-gen.cc" -yy604: +#line 496 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, F32Add); } +#line 4182 "src/prebuilt/wast-lexer-gen.cc" +yy610: yych = *++cursor_; - if (yych == 'l') goto yy745; + if (yych == 'l') goto yy752; goto yy87; -yy605: +yy611: yych = *++cursor_; - if (yych == 's') goto yy747; - if (yych == 'v') goto yy748; + if (yych == 's') goto yy754; + if (yych == 'v') goto yy755; goto yy87; -yy606: +yy612: yych = *++cursor_; - if (yych == 'y') goto yy749; + if (yych == 'y') goto yy756; goto yy87; -yy607: +yy613: yych = *++cursor_; - if (yych == 'o') goto yy750; + if (yych == 'o') goto yy757; goto yy87; -yy608: +yy614: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 366 "src/wast-lexer.cc" - { OPCODE(F32Div); RETURN(BINARY); } -#line 3771 "src/prebuilt/wast-lexer-gen.cc" -yy610: +#line 502 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, F32Div); } +#line 4207 "src/prebuilt/wast-lexer-gen.cc" +yy616: yych = *++cursor_; - if (yych == 'o') goto yy751; + if (yych == 'o') goto yy758; goto yy87; -yy611: +yy617: yych = *++cursor_; - if (yych == 'd') goto yy752; + if (yych == 'd') goto yy759; goto yy87; -yy612: +yy618: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 370 "src/wast-lexer.cc" - { OPCODE(F32Max); RETURN(BINARY); } -#line 3787 "src/prebuilt/wast-lexer-gen.cc" -yy614: +#line 506 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, F32Max); } +#line 4223 "src/prebuilt/wast-lexer-gen.cc" +yy620: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 368 "src/wast-lexer.cc" - { OPCODE(F32Min); RETURN(BINARY); } -#line 3795 "src/prebuilt/wast-lexer-gen.cc" -yy616: +#line 504 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, F32Min); } +#line 4231 "src/prebuilt/wast-lexer-gen.cc" +yy622: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 364 "src/wast-lexer.cc" - { OPCODE(F32Mul); RETURN(BINARY); } -#line 3803 "src/prebuilt/wast-lexer-gen.cc" -yy618: +#line 500 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, F32Mul); } +#line 4239 "src/prebuilt/wast-lexer-gen.cc" +yy624: yych = *++cursor_; - if (yych == 'r') goto yy754; + if (yych == 'r') goto yy761; goto yy87; -yy619: +yy625: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 316 "src/wast-lexer.cc" - { OPCODE(F32Neg); RETURN(UNARY); } -#line 3815 "src/prebuilt/wast-lexer-gen.cc" -yy621: +#line 452 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, F32Neg); } +#line 4251 "src/prebuilt/wast-lexer-gen.cc" +yy627: yych = *++cursor_; - if (yych == 'n') goto yy755; + if (yych == 'n') goto yy762; goto yy87; -yy622: +yy628: yych = *++cursor_; - if (yych == 't') goto yy756; + if (yych == 't') goto yy763; goto yy87; -yy623: +yy629: yych = *++cursor_; - if (yych == 'r') goto yy758; + if (yych == 'r') goto yy765; goto yy87; -yy624: +yy630: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 362 "src/wast-lexer.cc" - { OPCODE(F32Sub); RETURN(BINARY); } -#line 3835 "src/prebuilt/wast-lexer-gen.cc" -yy626: +#line 498 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, F32Sub); } +#line 4271 "src/prebuilt/wast-lexer-gen.cc" +yy632: yych = *++cursor_; - if (yych == 'n') goto yy759; + if (yych == 'n') goto yy766; goto yy87; -yy627: +yy633: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 319 "src/wast-lexer.cc" - { OPCODE(F64Abs); RETURN(UNARY); } -#line 3847 "src/prebuilt/wast-lexer-gen.cc" -yy629: +#line 455 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, F64Abs); } +#line 4283 "src/prebuilt/wast-lexer-gen.cc" +yy635: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 361 "src/wast-lexer.cc" - { OPCODE(F64Add); RETURN(BINARY); } -#line 3855 "src/prebuilt/wast-lexer-gen.cc" -yy631: +#line 497 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, F64Add); } +#line 4291 "src/prebuilt/wast-lexer-gen.cc" +yy637: yych = *++cursor_; - if (yych == 'l') goto yy760; + if (yych == 'l') goto yy767; goto yy87; -yy632: +yy638: yych = *++cursor_; - if (yych == 's') goto yy762; - if (yych == 'v') goto yy763; + if (yych == 's') goto yy769; + if (yych == 'v') goto yy770; goto yy87; -yy633: +yy639: yych = *++cursor_; - if (yych == 'y') goto yy764; + if (yych == 'y') goto yy771; goto yy87; -yy634: +yy640: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 367 "src/wast-lexer.cc" - { OPCODE(F64Div); RETURN(BINARY); } -#line 3876 "src/prebuilt/wast-lexer-gen.cc" -yy636: +#line 503 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, F64Div); } +#line 4312 "src/prebuilt/wast-lexer-gen.cc" +yy642: yych = *++cursor_; - if (yych == 'o') goto yy765; + if (yych == 'o') goto yy772; goto yy87; -yy637: +yy643: yych = *++cursor_; - if (yych == 'd') goto yy766; + if (yych == 'd') goto yy773; goto yy87; -yy638: +yy644: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 371 "src/wast-lexer.cc" - { OPCODE(F64Max); RETURN(BINARY); } -#line 3892 "src/prebuilt/wast-lexer-gen.cc" -yy640: +#line 507 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, F64Max); } +#line 4328 "src/prebuilt/wast-lexer-gen.cc" +yy646: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 369 "src/wast-lexer.cc" - { OPCODE(F64Min); RETURN(BINARY); } -#line 3900 "src/prebuilt/wast-lexer-gen.cc" -yy642: +#line 505 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, F64Min); } +#line 4336 "src/prebuilt/wast-lexer-gen.cc" +yy648: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 365 "src/wast-lexer.cc" - { OPCODE(F64Mul); RETURN(BINARY); } -#line 3908 "src/prebuilt/wast-lexer-gen.cc" -yy644: +#line 501 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, F64Mul); } +#line 4344 "src/prebuilt/wast-lexer-gen.cc" +yy650: yych = *++cursor_; - if (yych == 'r') goto yy768; + if (yych == 'r') goto yy775; goto yy87; -yy645: +yy651: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 317 "src/wast-lexer.cc" - { OPCODE(F64Neg); RETURN(UNARY); } -#line 3920 "src/prebuilt/wast-lexer-gen.cc" -yy647: +#line 453 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, F64Neg); } +#line 4356 "src/prebuilt/wast-lexer-gen.cc" +yy653: yych = *++cursor_; - if (yych == 'm') goto yy769; + if (yych == 'm') goto yy776; goto yy87; -yy648: +yy654: yych = *++cursor_; - if (yych == 'n') goto yy770; + if (yych == 'n') goto yy777; goto yy87; -yy649: +yy655: yych = *++cursor_; - if (yych == 't') goto yy771; + if (yych == 't') goto yy778; goto yy87; -yy650: +yy656: yych = *++cursor_; - if (yych == 'r') goto yy773; + if (yych == 'r') goto yy780; goto yy87; -yy651: +yy657: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 363 "src/wast-lexer.cc" - { OPCODE(F64Sub); RETURN(BINARY); } -#line 3944 "src/prebuilt/wast-lexer-gen.cc" -yy653: +#line 499 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, F64Sub); } +#line 4380 "src/prebuilt/wast-lexer-gen.cc" +yy659: yych = *++cursor_; - if (yych == 'n') goto yy774; + if (yych == 'n') goto yy781; goto yy87; -yy654: +yy660: yych = *++cursor_; - if (yych == 'b') goto yy775; + if (yych == 'b') goto yy782; goto yy87; -yy655: +yy661: yych = *++cursor_; - if (yych == 'a') goto yy776; + if (yych == 'a') goto yy783; goto yy87; -yy656: +yy662: yych = *++cursor_; - if (yych == 'm') goto yy777; + if (yych == 'm') goto yy784; goto yy87; -yy657: +yy663: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 330 "src/wast-lexer.cc" - { OPCODE(I32Add); RETURN(BINARY); } -#line 3968 "src/prebuilt/wast-lexer-gen.cc" -yy659: +#line 466 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I32Add); } +#line 4404 "src/prebuilt/wast-lexer-gen.cc" +yy665: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 344 "src/wast-lexer.cc" - { OPCODE(I32And); RETURN(BINARY); } -#line 3976 "src/prebuilt/wast-lexer-gen.cc" -yy661: +#line 480 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I32And); } +#line 4412 "src/prebuilt/wast-lexer-gen.cc" +yy667: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 310 "src/wast-lexer.cc" - { OPCODE(I32Clz); RETURN(UNARY); } -#line 3984 "src/prebuilt/wast-lexer-gen.cc" -yy663: +#line 446 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, I32Clz); } +#line 4420 "src/prebuilt/wast-lexer-gen.cc" +yy669: yych = *++cursor_; - if (yych == 's') goto yy778; + if (yych == 's') goto yy785; goto yy87; -yy664: +yy670: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 312 "src/wast-lexer.cc" - { OPCODE(I32Ctz); RETURN(UNARY); } -#line 3996 "src/prebuilt/wast-lexer-gen.cc" -yy666: +#line 448 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, I32Ctz); } +#line 4432 "src/prebuilt/wast-lexer-gen.cc" +yy672: yych = *++cursor_; - if (yych == '_') goto yy779; + if (yych == '_') goto yy786; goto yy87; -yy667: +yy673: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 308 "src/wast-lexer.cc" - { OPCODE(I32Eqz); RETURN(CONVERT); } -#line 4008 "src/prebuilt/wast-lexer-gen.cc" -yy669: +#line 444 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I32Eqz); } +#line 4444 "src/prebuilt/wast-lexer-gen.cc" +yy675: yych = *++cursor_; - if (yych == 's') goto yy780; - if (yych == 'u') goto yy782; + if (yych == 's') goto yy787; + if (yych == 'u') goto yy789; goto yy87; -yy670: +yy676: yych = *++cursor_; - if (yych == 's') goto yy784; - if (yych == 'u') goto yy786; + if (yych == 's') goto yy791; + if (yych == 'u') goto yy793; goto yy87; -yy671: +yy677: yych = *++cursor_; - if (yych == 's') goto yy788; - if (yych == 'u') goto yy790; + if (yych == 's') goto yy795; + if (yych == 'u') goto yy797; goto yy87; -yy672: +yy678: yych = *++cursor_; - if (yych == 'd') goto yy792; + if (yych == 'd') goto yy799; goto yy87; -yy673: +yy679: yych = *++cursor_; - if (yych == 's') goto yy794; - if (yych == 'u') goto yy796; + if (yych == 's') goto yy801; + if (yych == 'u') goto yy803; goto yy87; -yy674: +yy680: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 334 "src/wast-lexer.cc" - { OPCODE(I32Mul); RETURN(BINARY); } -#line 4040 "src/prebuilt/wast-lexer-gen.cc" -yy676: +#line 470 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I32Mul); } +#line 4476 "src/prebuilt/wast-lexer-gen.cc" +yy682: yych = *++cursor_; - if (yych == 'c') goto yy798; + if (yych == 'c') goto yy805; goto yy87; -yy677: +yy683: yych = *++cursor_; - if (yych == 'n') goto yy799; + if (yych == 'n') goto yy806; goto yy87; -yy678: +yy684: yych = *++cursor_; - if (yych == '_') goto yy800; + if (yych == '_') goto yy807; goto yy87; -yy679: +yy685: yych = *++cursor_; - if (yych == 'l') goto yy801; - if (yych == 'r') goto yy803; + if (yych == 'l') goto yy808; + if (yych == 'r') goto yy810; goto yy87; -yy680: +yy686: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 350 "src/wast-lexer.cc" - { OPCODE(I32Shl); RETURN(BINARY); } -#line 4065 "src/prebuilt/wast-lexer-gen.cc" -yy682: +#line 486 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I32Shl); } +#line 4501 "src/prebuilt/wast-lexer-gen.cc" +yy688: yych = *++cursor_; - if (yych == '_') goto yy805; + if (yych == '_') goto yy812; goto yy87; -yy683: +yy689: yych = *++cursor_; - if (yych == 'r') goto yy806; + if (yych == 'r') goto yy813; goto yy87; -yy684: +yy690: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 332 "src/wast-lexer.cc" - { OPCODE(I32Sub); RETURN(BINARY); } -#line 4081 "src/prebuilt/wast-lexer-gen.cc" -yy686: +#line 468 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I32Sub); } +#line 4517 "src/prebuilt/wast-lexer-gen.cc" +yy692: yych = *++cursor_; - if (yych == 'n') goto yy807; + if (yych == 'n') goto yy814; goto yy87; -yy687: +yy693: yych = *++cursor_; - if (yych == 'p') goto yy808; + if (yych == 'p') goto yy815; goto yy87; -yy688: +yy694: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 348 "src/wast-lexer.cc" - { OPCODE(I32Xor); RETURN(BINARY); } -#line 4097 "src/prebuilt/wast-lexer-gen.cc" -yy690: +#line 484 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I32Xor); } +#line 4533 "src/prebuilt/wast-lexer-gen.cc" +yy696: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 331 "src/wast-lexer.cc" - { OPCODE(I64Add); RETURN(BINARY); } -#line 4105 "src/prebuilt/wast-lexer-gen.cc" -yy692: +#line 467 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I64Add); } +#line 4541 "src/prebuilt/wast-lexer-gen.cc" +yy698: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 345 "src/wast-lexer.cc" - { OPCODE(I64And); RETURN(BINARY); } -#line 4113 "src/prebuilt/wast-lexer-gen.cc" -yy694: +#line 481 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I64And); } +#line 4549 "src/prebuilt/wast-lexer-gen.cc" +yy700: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 311 "src/wast-lexer.cc" - { OPCODE(I64Clz); RETURN(UNARY); } -#line 4121 "src/prebuilt/wast-lexer-gen.cc" -yy696: +#line 447 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, I64Clz); } +#line 4557 "src/prebuilt/wast-lexer-gen.cc" +yy702: yych = *++cursor_; - if (yych == 's') goto yy809; + if (yych == 's') goto yy816; goto yy87; -yy697: +yy703: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 313 "src/wast-lexer.cc" - { OPCODE(I64Ctz); RETURN(UNARY); } -#line 4133 "src/prebuilt/wast-lexer-gen.cc" -yy699: +#line 449 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, I64Ctz); } +#line 4569 "src/prebuilt/wast-lexer-gen.cc" +yy705: yych = *++cursor_; - if (yych == '_') goto yy810; + if (yych == '_') goto yy817; goto yy87; -yy700: +yy706: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 309 "src/wast-lexer.cc" - { OPCODE(I64Eqz); RETURN(CONVERT); } -#line 4145 "src/prebuilt/wast-lexer-gen.cc" -yy702: +#line 445 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I64Eqz); } +#line 4581 "src/prebuilt/wast-lexer-gen.cc" +yy708: yych = *++cursor_; - if (yych == 'e') goto yy811; + if (yych == 'e') goto yy818; goto yy87; -yy703: +yy709: yych = *++cursor_; - if (yych == 's') goto yy812; - if (yych == 'u') goto yy814; + if (yych == 's') goto yy819; + if (yych == 'u') goto yy821; goto yy87; -yy704: +yy710: yych = *++cursor_; - if (yych == 's') goto yy816; - if (yych == 'u') goto yy818; + if (yych == 's') goto yy823; + if (yych == 'u') goto yy825; goto yy87; -yy705: +yy711: yych = *++cursor_; - if (yych == 's') goto yy820; - if (yych == 'u') goto yy822; + if (yych == 's') goto yy827; + if (yych == 'u') goto yy829; goto yy87; -yy706: +yy712: yych = *++cursor_; - if (yych == 'd') goto yy824; + if (yych == 'd') goto yy831; goto yy87; -yy707: +yy713: yych = *++cursor_; - if (yych == 's') goto yy826; - if (yych == 'u') goto yy828; + if (yych == 's') goto yy833; + if (yych == 'u') goto yy835; goto yy87; -yy708: +yy714: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 335 "src/wast-lexer.cc" - { OPCODE(I64Mul); RETURN(BINARY); } -#line 4181 "src/prebuilt/wast-lexer-gen.cc" -yy710: +#line 471 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I64Mul); } +#line 4617 "src/prebuilt/wast-lexer-gen.cc" +yy716: yych = *++cursor_; - if (yych == 'c') goto yy830; + if (yych == 'c') goto yy837; goto yy87; -yy711: +yy717: yych = *++cursor_; - if (yych == 'n') goto yy831; + if (yych == 'n') goto yy838; goto yy87; -yy712: +yy718: yych = *++cursor_; - if (yych == '_') goto yy832; + if (yych == '_') goto yy839; goto yy87; -yy713: +yy719: yych = *++cursor_; - if (yych == 'l') goto yy833; - if (yych == 'r') goto yy835; + if (yych == 'l') goto yy840; + if (yych == 'r') goto yy842; goto yy87; -yy714: +yy720: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 351 "src/wast-lexer.cc" - { OPCODE(I64Shl); RETURN(BINARY); } -#line 4206 "src/prebuilt/wast-lexer-gen.cc" -yy716: +#line 487 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I64Shl); } +#line 4642 "src/prebuilt/wast-lexer-gen.cc" +yy722: yych = *++cursor_; - if (yych == '_') goto yy837; + if (yych == '_') goto yy844; goto yy87; -yy717: +yy723: yych = *++cursor_; - if (yych == 'r') goto yy838; + if (yych == 'r') goto yy845; goto yy87; -yy718: +yy724: + ++cursor_; + if (yybm[0+(yych = *cursor_)] & 8) { + goto yy86; + } +#line 469 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I64Sub); } +#line 4658 "src/prebuilt/wast-lexer-gen.cc" +yy726: + yych = *++cursor_; + if (yych == 'n') goto yy846; + goto yy87; +yy727: + ++cursor_; + if (yybm[0+(yych = *cursor_)] & 8) { + goto yy86; + } +#line 485 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I64Xor); } +#line 4670 "src/prebuilt/wast-lexer-gen.cc" +yy729: + ++cursor_; + if (limit_ <= cursor_) FILL(1); + yych = *cursor_; + if (yych <= ':') { + if (yych <= '\'') { + if (yych == '!') goto yy86; + if (yych <= '"') goto yy256; + goto yy86; + } else { + if (yych <= ')') goto yy256; + if (yych <= '/') goto yy86; + if (yych <= '9') goto yy729; + goto yy86; + } + } else { + if (yych <= '^') { + if (yych <= ';') goto yy256; + if (yych <= '@') goto yy86; + if (yych <= 'F') goto yy729; + goto yy86; + } else { + if (yych <= '`') { + if (yych <= '_') goto yy580; + goto yy86; + } else { + if (yych <= 'f') goto yy729; + if (yych <= '~') goto yy86; + goto yy256; + } + } + } +yy731: + yych = *++cursor_; + if (yych <= '/') goto yy87; + if (yych <= '0') goto yy847; + if (yych <= '9') goto yy849; + goto yy87; +yy732: + yych = *++cursor_; + if (yych == 'r') goto yy851; + goto yy87; +yy733: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 333 "src/wast-lexer.cc" - { OPCODE(I64Sub); RETURN(BINARY); } -#line 4222 "src/prebuilt/wast-lexer-gen.cc" -yy720: +#line 612 "src/wast-lexer.cc" + { RETURN_OPCODE0(Rethrow); } +#line 4720 "src/prebuilt/wast-lexer-gen.cc" +yy735: + yych = *++cursor_; + if (yych == 'b') goto yy853; + goto yy87; +yy736: + yych = *++cursor_; + if (yych == 'a') goto yy854; + goto yy87; +yy737: + yych = *++cursor_; + if (yych == 'a') goto yy855; + goto yy87; +yy738: yych = *++cursor_; - if (yych == 'n') goto yy839; + if (yych == 'a') goto yy856; goto yy87; -yy721: +yy739: ++cursor_; - if (yybm[0+(yych = *cursor_)] & 8) { - goto yy86; + if (limit_ <= cursor_) FILL(1); + yych = *cursor_; + if (yych <= ')') { + if (yych <= '!') { + if (yych <= ' ') goto yy88; + goto yy86; + } else { + if (yych <= '"') goto yy88; + if (yych <= '\'') goto yy86; + goto yy88; + } + } else { + if (yych <= ':') { + if (yych <= '/') goto yy86; + if (yych <= '9') goto yy597; + goto yy86; + } else { + if (yych <= ';') goto yy88; + if (yych <= '~') goto yy86; + goto yy88; + } } -#line 349 "src/wast-lexer.cc" - { OPCODE(I64Xor); RETURN(BINARY); } -#line 4234 "src/prebuilt/wast-lexer-gen.cc" -yy723: +yy740: ++cursor_; if (limit_ <= cursor_) FILL(1); yych = *cursor_; if (yych <= '9') { if (yych <= '"') { if (yych == '!') goto yy86; - goto yy253; + goto yy88; } else { if (yych <= '\'') goto yy86; - if (yych <= ')') goto yy253; + if (yych <= ')') goto yy88; if (yych <= '/') goto yy86; - goto yy723; + goto yy857; } } else { if (yych <= 'F') { - if (yych == ';') goto yy253; + if (yych == ';') goto yy88; if (yych <= '@') goto yy86; - goto yy723; + goto yy857; } else { if (yych <= '`') goto yy86; - if (yych <= 'f') goto yy723; + if (yych <= 'f') goto yy857; if (yych <= '~') goto yy86; - goto yy253; + goto yy88; } } -yy725: - yych = *++cursor_; - if (yych <= '/') goto yy87; - if (yych <= '0') goto yy840; - if (yych <= '9') goto yy842; - goto yy87; -yy726: - yych = *++cursor_; - if (yych == 'r') goto yy844; - goto yy87; -yy727: - ++cursor_; - if (yybm[0+(yych = *cursor_)] & 8) { - goto yy86; - } -#line 470 "src/wast-lexer.cc" - { RETURN(RETHROW); } -#line 4278 "src/prebuilt/wast-lexer-gen.cc" -yy729: - yych = *++cursor_; - if (yych == 'b') goto yy846; - goto yy87; -yy730: - yych = *++cursor_; - if (yych == 'a') goto yy847; - goto yy87; -yy731: - yych = *++cursor_; - if (yych == 'a') goto yy848; - goto yy87; -yy732: - yych = *++cursor_; - if (yych == 'a') goto yy849; - goto yy87; -yy733: - yych = *++cursor_; - if (yych <= '@') { - if (yych <= '/') goto yy87; - if (yych <= '9') goto yy850; - goto yy87; - } else { - if (yych <= 'F') goto yy850; - if (yych <= '`') goto yy87; - if (yych <= 'f') goto yy850; - goto yy87; - } -yy734: +yy741: yych = *++cursor_; - if (yych == 'x') goto yy852; + if (yych == 'x') goto yy859; goto yy87; -yy735: +yy742: yych = *++cursor_; - if (yych == 'n') goto yy853; + if (yych == 'n') goto yy860; goto yy87; -yy736: +yy743: yych = *++cursor_; - if (yych == 'a') goto yy854; + if (yych == 'a') goto yy861; goto yy87; -yy737: +yy744: yych = *++cursor_; - if (yych == 'e') goto yy855; + if (yych == 'e') goto yy862; goto yy87; -yy738: +yy745: yych = *++cursor_; - if (yych == 'r') goto yy856; + if (yych == 'r') goto yy863; goto yy87; -yy739: +yy746: yych = *++cursor_; - if (yych == 'n') goto yy857; + if (yych == 'n') goto yy864; goto yy87; -yy740: +yy747: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 268 "src/wast-lexer.cc" - { RETURN(BR_TABLE); } -#line 4338 "src/prebuilt/wast-lexer-gen.cc" -yy742: +#line 404 "src/wast-lexer.cc" + { RETURN_OPCODE0(BrTable); } +#line 4818 "src/prebuilt/wast-lexer-gen.cc" +yy749: yych = *++cursor_; - if (yych == 'i') goto yy858; + if (yych == 'i') goto yy865; goto yy87; -yy743: +yy750: yych = *++cursor_; - if (yych == 'l') goto yy859; + if (yych == 'l') goto yy866; goto yy87; -yy744: +yy751: yych = *++cursor_; - if (yych == 'm') goto yy861; + if (yych == 'm') goto yy868; goto yy87; -yy745: +yy752: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 322 "src/wast-lexer.cc" - { OPCODE(F32Ceil); RETURN(UNARY); } -#line 4358 "src/prebuilt/wast-lexer-gen.cc" -yy747: +#line 458 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, F32Ceil); } +#line 4838 "src/prebuilt/wast-lexer-gen.cc" +yy754: yych = *++cursor_; - if (yych == 't') goto yy862; + if (yych == 't') goto yy869; goto yy87; -yy748: +yy755: yych = *++cursor_; - if (yych == 'e') goto yy864; + if (yych == 'e') goto yy871; goto yy87; -yy749: +yy756: yych = *++cursor_; - if (yych == 's') goto yy865; + if (yych == 's') goto yy872; goto yy87; -yy750: +yy757: yych = *++cursor_; - if (yych == 't') goto yy866; + if (yych == 't') goto yy873; goto yy87; -yy751: +yy758: yych = *++cursor_; - if (yych == 'r') goto yy867; + if (yych == 'r') goto yy874; goto yy87; -yy752: +yy759: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 281 "src/wast-lexer.cc" - { OPCODE(F32Load); RETURN(LOAD); } -#line 4386 "src/prebuilt/wast-lexer-gen.cc" -yy754: +#line 417 "src/wast-lexer.cc" + { RETURN_OPCODE(Load, F32Load); } +#line 4866 "src/prebuilt/wast-lexer-gen.cc" +yy761: yych = *++cursor_; - if (yych == 'e') goto yy869; + if (yych == 'e') goto yy876; goto yy87; -yy755: +yy762: yych = *++cursor_; - if (yych == 't') goto yy870; + if (yych == 't') goto yy877; goto yy87; -yy756: +yy763: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 320 "src/wast-lexer.cc" - { OPCODE(F32Sqrt); RETURN(UNARY); } -#line 4402 "src/prebuilt/wast-lexer-gen.cc" -yy758: +#line 456 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, F32Sqrt); } +#line 4882 "src/prebuilt/wast-lexer-gen.cc" +yy765: yych = *++cursor_; - if (yych == 'e') goto yy871; + if (yych == 'e') goto yy878; goto yy87; -yy759: +yy766: yych = *++cursor_; - if (yych == 'c') goto yy873; + if (yych == 'c') goto yy880; goto yy87; -yy760: +yy767: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 323 "src/wast-lexer.cc" - { OPCODE(F64Ceil); RETURN(UNARY); } -#line 4418 "src/prebuilt/wast-lexer-gen.cc" -yy762: +#line 459 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, F64Ceil); } +#line 4898 "src/prebuilt/wast-lexer-gen.cc" +yy769: yych = *++cursor_; - if (yych == 't') goto yy875; + if (yych == 't') goto yy882; goto yy87; -yy763: +yy770: yych = *++cursor_; - if (yych == 'e') goto yy877; + if (yych == 'e') goto yy884; goto yy87; -yy764: +yy771: yych = *++cursor_; - if (yych == 's') goto yy878; + if (yych == 's') goto yy885; goto yy87; -yy765: +yy772: yych = *++cursor_; - if (yych == 'r') goto yy879; + if (yych == 'r') goto yy886; goto yy87; -yy766: +yy773: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 282 "src/wast-lexer.cc" - { OPCODE(F64Load); RETURN(LOAD); } -#line 4442 "src/prebuilt/wast-lexer-gen.cc" -yy768: +#line 418 "src/wast-lexer.cc" + { RETURN_OPCODE(Load, F64Load); } +#line 4922 "src/prebuilt/wast-lexer-gen.cc" +yy775: yych = *++cursor_; - if (yych == 'e') goto yy881; + if (yych == 'e') goto yy888; goto yy87; -yy769: +yy776: yych = *++cursor_; - if (yych == 'o') goto yy882; + if (yych == 'o') goto yy889; goto yy87; -yy770: +yy777: yych = *++cursor_; - if (yych == 't') goto yy883; + if (yych == 't') goto yy890; goto yy87; -yy771: +yy778: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 321 "src/wast-lexer.cc" - { OPCODE(F64Sqrt); RETURN(UNARY); } -#line 4462 "src/prebuilt/wast-lexer-gen.cc" -yy773: +#line 457 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, F64Sqrt); } +#line 4942 "src/prebuilt/wast-lexer-gen.cc" +yy780: yych = *++cursor_; - if (yych == 'e') goto yy884; + if (yych == 'e') goto yy891; goto yy87; -yy774: +yy781: yych = *++cursor_; - if (yych == 'c') goto yy886; + if (yych == 'c') goto yy893; goto yy87; -yy775: +yy782: yych = *++cursor_; - if (yych == 'a') goto yy888; + if (yych == 'a') goto yy895; goto yy87; -yy776: +yy783: yych = *++cursor_; - if (yych == 'l') goto yy889; + if (yych == 'l') goto yy896; goto yy87; -yy777: +yy784: yych = *++cursor_; - if (yych == 'o') goto yy891; + if (yych == 'o') goto yy898; goto yy87; -yy778: +yy785: yych = *++cursor_; - if (yych == 't') goto yy892; + if (yych == 't') goto yy899; goto yy87; -yy779: +yy786: yych = *++cursor_; - if (yych == 's') goto yy894; - if (yych == 'u') goto yy896; + if (yych == 's') goto yy901; + if (yych == 'u') goto yy903; goto yy87; -yy780: +yy787: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 390 "src/wast-lexer.cc" - { OPCODE(I32GeS); RETURN(COMPARE); } -#line 4499 "src/prebuilt/wast-lexer-gen.cc" -yy782: +#line 526 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I32GeS); } +#line 4979 "src/prebuilt/wast-lexer-gen.cc" +yy789: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 392 "src/wast-lexer.cc" - { OPCODE(I32GeU); RETURN(COMPARE); } -#line 4507 "src/prebuilt/wast-lexer-gen.cc" -yy784: +#line 528 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I32GeU); } +#line 4987 "src/prebuilt/wast-lexer-gen.cc" +yy791: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 386 "src/wast-lexer.cc" - { OPCODE(I32GtS); RETURN(COMPARE); } -#line 4515 "src/prebuilt/wast-lexer-gen.cc" -yy786: +#line 522 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I32GtS); } +#line 4995 "src/prebuilt/wast-lexer-gen.cc" +yy793: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 388 "src/wast-lexer.cc" - { OPCODE(I32GtU); RETURN(COMPARE); } -#line 4523 "src/prebuilt/wast-lexer-gen.cc" -yy788: +#line 524 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I32GtU); } +#line 5003 "src/prebuilt/wast-lexer-gen.cc" +yy795: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 382 "src/wast-lexer.cc" - { OPCODE(I32LeS); RETURN(COMPARE); } -#line 4531 "src/prebuilt/wast-lexer-gen.cc" -yy790: +#line 518 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I32LeS); } +#line 5011 "src/prebuilt/wast-lexer-gen.cc" +yy797: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 384 "src/wast-lexer.cc" - { OPCODE(I32LeU); RETURN(COMPARE); } -#line 4539 "src/prebuilt/wast-lexer-gen.cc" -yy792: +#line 520 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I32LeU); } +#line 5019 "src/prebuilt/wast-lexer-gen.cc" +yy799: ++cursor_; if ((yych = *cursor_) <= '0') { if (yych <= '"') { @@ -4547,553 +5027,562 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { } } else { if (yych <= '8') { - if (yych <= '1') goto yy898; + if (yych <= '1') goto yy905; if (yych <= '7') goto yy86; - goto yy899; + goto yy906; } else { - if (yych == ';') goto yy793; + if (yych == ';') goto yy800; if (yych <= '~') goto yy86; } } -yy793: -#line 279 "src/wast-lexer.cc" - { OPCODE(I32Load); RETURN(LOAD); } -#line 4562 "src/prebuilt/wast-lexer-gen.cc" -yy794: +yy800: +#line 415 "src/wast-lexer.cc" + { RETURN_OPCODE(Load, I32Load); } +#line 5042 "src/prebuilt/wast-lexer-gen.cc" +yy801: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 378 "src/wast-lexer.cc" - { OPCODE(I32LtS); RETURN(COMPARE); } -#line 4570 "src/prebuilt/wast-lexer-gen.cc" -yy796: +#line 514 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I32LtS); } +#line 5050 "src/prebuilt/wast-lexer-gen.cc" +yy803: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 380 "src/wast-lexer.cc" - { OPCODE(I32LtU); RETURN(COMPARE); } -#line 4578 "src/prebuilt/wast-lexer-gen.cc" -yy798: +#line 516 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I32LtU); } +#line 5058 "src/prebuilt/wast-lexer-gen.cc" +yy805: yych = *++cursor_; - if (yych == 'n') goto yy900; + if (yych == 'n') goto yy907; goto yy87; -yy799: +yy806: yych = *++cursor_; - if (yych == 't') goto yy901; + if (yych == 't') goto yy908; goto yy87; -yy800: +yy807: yych = *++cursor_; - if (yych == 's') goto yy902; - if (yych == 'u') goto yy904; + if (yych == 's') goto yy909; + if (yych == 'u') goto yy911; goto yy87; -yy801: +yy808: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 356 "src/wast-lexer.cc" - { OPCODE(I32Rotl); RETURN(BINARY); } -#line 4599 "src/prebuilt/wast-lexer-gen.cc" -yy803: +#line 492 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I32Rotl); } +#line 5079 "src/prebuilt/wast-lexer-gen.cc" +yy810: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 358 "src/wast-lexer.cc" - { OPCODE(I32Rotr); RETURN(BINARY); } -#line 4607 "src/prebuilt/wast-lexer-gen.cc" -yy805: +#line 494 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I32Rotr); } +#line 5087 "src/prebuilt/wast-lexer-gen.cc" +yy812: yych = *++cursor_; - if (yych == 's') goto yy906; - if (yych == 'u') goto yy908; + if (yych == 's') goto yy913; + if (yych == 'u') goto yy915; goto yy87; -yy806: +yy813: yych = *++cursor_; - if (yych == 'e') goto yy910; + if (yych == 'e') goto yy917; goto yy87; -yy807: +yy814: yych = *++cursor_; - if (yych == 'c') goto yy912; + if (yych == 'c') goto yy919; goto yy87; -yy808: +yy815: yych = *++cursor_; - if (yych == '/') goto yy913; + if (yych == '/') goto yy920; goto yy87; -yy809: +yy816: yych = *++cursor_; - if (yych == 't') goto yy914; + if (yych == 't') goto yy921; goto yy87; -yy810: +yy817: yych = *++cursor_; - if (yych == 's') goto yy916; - if (yych == 'u') goto yy918; + if (yych == 's') goto yy923; + if (yych == 'u') goto yy925; goto yy87; -yy811: +yy818: yych = *++cursor_; - if (yych == 'n') goto yy920; + if (yych == 'n') goto yy927; goto yy87; -yy812: +yy819: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 391 "src/wast-lexer.cc" - { OPCODE(I64GeS); RETURN(COMPARE); } -#line 4645 "src/prebuilt/wast-lexer-gen.cc" -yy814: +#line 527 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I64GeS); } +#line 5125 "src/prebuilt/wast-lexer-gen.cc" +yy821: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 393 "src/wast-lexer.cc" - { OPCODE(I64GeU); RETURN(COMPARE); } -#line 4653 "src/prebuilt/wast-lexer-gen.cc" -yy816: +#line 529 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I64GeU); } +#line 5133 "src/prebuilt/wast-lexer-gen.cc" +yy823: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 387 "src/wast-lexer.cc" - { OPCODE(I64GtS); RETURN(COMPARE); } -#line 4661 "src/prebuilt/wast-lexer-gen.cc" -yy818: +#line 523 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I64GtS); } +#line 5141 "src/prebuilt/wast-lexer-gen.cc" +yy825: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 389 "src/wast-lexer.cc" - { OPCODE(I64GtU); RETURN(COMPARE); } -#line 4669 "src/prebuilt/wast-lexer-gen.cc" -yy820: +#line 525 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I64GtU); } +#line 5149 "src/prebuilt/wast-lexer-gen.cc" +yy827: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 383 "src/wast-lexer.cc" - { OPCODE(I64LeS); RETURN(COMPARE); } -#line 4677 "src/prebuilt/wast-lexer-gen.cc" -yy822: +#line 519 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I64LeS); } +#line 5157 "src/prebuilt/wast-lexer-gen.cc" +yy829: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 385 "src/wast-lexer.cc" - { OPCODE(I64LeU); RETURN(COMPARE); } -#line 4685 "src/prebuilt/wast-lexer-gen.cc" -yy824: +#line 521 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I64LeU); } +#line 5165 "src/prebuilt/wast-lexer-gen.cc" +yy831: ++cursor_; if ((yych = *cursor_) <= '1') { if (yych <= '"') { if (yych == '!') goto yy86; } else { if (yych <= '\'') goto yy86; - if (yych <= ')') goto yy825; + if (yych <= ')') goto yy832; if (yych <= '0') goto yy86; - goto yy921; + goto yy928; } } else { if (yych <= '8') { - if (yych == '3') goto yy922; + if (yych == '3') goto yy929; if (yych <= '7') goto yy86; - goto yy923; + goto yy930; } else { - if (yych == ';') goto yy825; + if (yych == ';') goto yy832; if (yych <= '~') goto yy86; } } -yy825: -#line 280 "src/wast-lexer.cc" - { OPCODE(I64Load); RETURN(LOAD); } -#line 4710 "src/prebuilt/wast-lexer-gen.cc" -yy826: +yy832: +#line 416 "src/wast-lexer.cc" + { RETURN_OPCODE(Load, I64Load); } +#line 5190 "src/prebuilt/wast-lexer-gen.cc" +yy833: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 379 "src/wast-lexer.cc" - { OPCODE(I64LtS); RETURN(COMPARE); } -#line 4718 "src/prebuilt/wast-lexer-gen.cc" -yy828: +#line 515 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I64LtS); } +#line 5198 "src/prebuilt/wast-lexer-gen.cc" +yy835: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 381 "src/wast-lexer.cc" - { OPCODE(I64LtU); RETURN(COMPARE); } -#line 4726 "src/prebuilt/wast-lexer-gen.cc" -yy830: +#line 517 "src/wast-lexer.cc" + { RETURN_OPCODE(Compare, I64LtU); } +#line 5206 "src/prebuilt/wast-lexer-gen.cc" +yy837: yych = *++cursor_; - if (yych == 'n') goto yy924; + if (yych == 'n') goto yy931; goto yy87; -yy831: +yy838: yych = *++cursor_; - if (yych == 't') goto yy925; + if (yych == 't') goto yy932; goto yy87; -yy832: +yy839: yych = *++cursor_; - if (yych == 's') goto yy926; - if (yych == 'u') goto yy928; + if (yych == 's') goto yy933; + if (yych == 'u') goto yy935; goto yy87; -yy833: +yy840: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 357 "src/wast-lexer.cc" - { OPCODE(I64Rotl); RETURN(BINARY); } -#line 4747 "src/prebuilt/wast-lexer-gen.cc" -yy835: +#line 493 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I64Rotl); } +#line 5227 "src/prebuilt/wast-lexer-gen.cc" +yy842: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 359 "src/wast-lexer.cc" - { OPCODE(I64Rotr); RETURN(BINARY); } -#line 4755 "src/prebuilt/wast-lexer-gen.cc" -yy837: +#line 495 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I64Rotr); } +#line 5235 "src/prebuilt/wast-lexer-gen.cc" +yy844: yych = *++cursor_; - if (yych == 's') goto yy930; - if (yych == 'u') goto yy932; + if (yych == 's') goto yy937; + if (yych == 'u') goto yy939; goto yy87; -yy838: +yy845: yych = *++cursor_; - if (yych == 'e') goto yy934; + if (yych == 'e') goto yy941; goto yy87; -yy839: +yy846: yych = *++cursor_; - if (yych == 'c') goto yy936; + if (yych == 'c') goto yy943; goto yy87; -yy840: +yy847: ++cursor_; - if ((yych = *cursor_) <= '/') { + if ((yych = *cursor_) <= '9') { if (yych <= '"') { if (yych == '!') goto yy86; } else { if (yych <= '\'') goto yy86; - if (yych >= '*') goto yy86; + if (yych <= ')') goto yy848; + if (yych <= '/') goto yy86; + goto yy849; } } else { - if (yych <= ';') { - if (yych <= '9') goto yy842; - if (yych <= ':') goto yy86; + if (yych <= '_') { + if (yych == ';') goto yy848; + if (yych <= '^') goto yy86; + goto yy944; } else { - if (yych == 'x') goto yy937; + if (yych == 'x') goto yy945; if (yych <= '~') goto yy86; } } -yy841: -#line 302 "src/wast-lexer.cc" - { TEXT_AT(7); RETURN(OFFSET_EQ_NAT); } -#line 4790 "src/prebuilt/wast-lexer-gen.cc" -yy842: +yy848: +#line 438 "src/wast-lexer.cc" + { RETURN_TEXT_AT(OffsetEqNat, 7); } +#line 5273 "src/prebuilt/wast-lexer-gen.cc" +yy849: ++cursor_; if (limit_ <= cursor_) FILL(1); yych = *cursor_; - if (yych <= ')') { - if (yych <= '!') { - if (yych <= ' ') goto yy841; - goto yy86; + if (yych <= '/') { + if (yych <= '"') { + if (yych == '!') goto yy86; + goto yy848; } else { - if (yych <= '"') goto yy841; if (yych <= '\'') goto yy86; - goto yy841; + if (yych <= ')') goto yy848; + goto yy86; } } else { - if (yych <= ':') { - if (yych <= '/') goto yy86; - if (yych <= '9') goto yy842; - goto yy86; + if (yych <= ';') { + if (yych <= '9') goto yy849; + if (yych <= ':') goto yy86; + goto yy848; } else { - if (yych <= ';') goto yy841; + if (yych == '_') goto yy944; if (yych <= '~') goto yy86; - goto yy841; + goto yy848; } } -yy844: +yy851: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 453 "src/wast-lexer.cc" - { RETURN(REGISTER); } -#line 4822 "src/prebuilt/wast-lexer-gen.cc" -yy846: +#line 597 "src/wast-lexer.cc" + { RETURN(Register); } +#line 5305 "src/prebuilt/wast-lexer-gen.cc" +yy853: yych = *++cursor_; - if (yych == 'a') goto yy938; + if (yych == 'a') goto yy946; goto yy87; -yy847: +yy854: yych = *++cursor_; - if (yych == 'l') goto yy939; + if (yych == 'l') goto yy947; goto yy87; -yy848: +yy855: yych = *++cursor_; - if (yych == 'l') goto yy941; + if (yych == 'l') goto yy949; goto yy87; -yy849: +yy856: yych = *++cursor_; - if (yych == 'b') goto yy943; + if (yych == 'b') goto yy951; goto yy87; -yy850: +yy857: ++cursor_; if (limit_ <= cursor_) FILL(1); yych = *cursor_; - if (yych <= '9') { - if (yych <= '"') { + if (yych <= ':') { + if (yych <= '\'') { if (yych == '!') goto yy86; - goto yy590; + if (yych <= '"') goto yy596; + goto yy86; } else { - if (yych <= '\'') goto yy86; - if (yych <= ')') goto yy590; + if (yych <= ')') goto yy596; if (yych <= '/') goto yy86; - goto yy850; + if (yych <= '9') goto yy857; + goto yy86; } } else { - if (yych <= 'F') { - if (yych == ';') goto yy590; + if (yych <= '^') { + if (yych <= ';') goto yy596; if (yych <= '@') goto yy86; - goto yy850; + if (yych <= 'F') goto yy857; + goto yy86; } else { - if (yych <= '`') goto yy86; - if (yych <= 'f') goto yy850; - if (yych <= '~') goto yy86; - goto yy590; + if (yych <= '`') { + if (yych <= '_') goto yy740; + goto yy86; + } else { + if (yych <= 'f') goto yy857; + if (yych <= '~') goto yy86; + goto yy596; + } } } -yy852: +yy859: yych = *++cursor_; - if (yych == 'h') goto yy944; + if (yych == 'h') goto yy952; goto yy87; -yy853: +yy860: yych = *++cursor_; - if (yych == 'v') goto yy945; + if (yych == 'v') goto yy953; goto yy87; -yy854: +yy861: yych = *++cursor_; - if (yych == 'l') goto yy946; + if (yych == 'l') goto yy954; goto yy87; -yy855: +yy862: yych = *++cursor_; - if (yych == 't') goto yy947; + if (yych == 't') goto yy955; goto yy87; -yy856: +yy863: yych = *++cursor_; - if (yych == 'a') goto yy948; + if (yych == 'a') goto yy956; goto yy87; -yy857: +yy864: yych = *++cursor_; - if (yych == 'l') goto yy949; + if (yych == 'l') goto yy957; goto yy87; -yy858: +yy865: yych = *++cursor_; - if (yych == 'r') goto yy950; + if (yych == 'r') goto yy958; goto yy87; -yy859: +yy866: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 468 "src/wast-lexer.cc" - { RETURN(CATCH_ALL); } -#line 4900 "src/prebuilt/wast-lexer-gen.cc" -yy861: +#line 610 "src/wast-lexer.cc" + { RETURN_OPCODE0(CatchAll); } +#line 5389 "src/prebuilt/wast-lexer-gen.cc" +yy868: yych = *++cursor_; - if (yych == 'e') goto yy951; + if (yych == 'e') goto yy959; goto yy87; -yy862: +yy869: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 306 "src/wast-lexer.cc" - { TYPE(F32); RETURN(CONST); } -#line 4912 "src/prebuilt/wast-lexer-gen.cc" -yy864: +#line 442 "src/wast-lexer.cc" + { RETURN_OPCODE(Const, F32Const); } +#line 5401 "src/prebuilt/wast-lexer-gen.cc" +yy871: yych = *++cursor_; - if (yych == 'r') goto yy952; + if (yych == 'r') goto yy960; goto yy87; -yy865: +yy872: yych = *++cursor_; - if (yych == 'i') goto yy953; + if (yych == 'i') goto yy961; goto yy87; -yy866: +yy873: yych = *++cursor_; - if (yych == 'e') goto yy954; + if (yych == 'e') goto yy962; goto yy87; -yy867: +yy874: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 324 "src/wast-lexer.cc" - { OPCODE(F32Floor); RETURN(UNARY); } -#line 4932 "src/prebuilt/wast-lexer-gen.cc" -yy869: +#line 460 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, F32Floor); } +#line 5421 "src/prebuilt/wast-lexer-gen.cc" +yy876: yych = *++cursor_; - if (yych == 's') goto yy955; + if (yych == 's') goto yy963; goto yy87; -yy870: +yy877: yych = *++cursor_; - if (yych == 'e') goto yy956; + if (yych == 'e') goto yy964; goto yy87; -yy871: +yy878: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 285 "src/wast-lexer.cc" - { OPCODE(F32Store); RETURN(STORE); } -#line 4948 "src/prebuilt/wast-lexer-gen.cc" -yy873: +#line 421 "src/wast-lexer.cc" + { RETURN_OPCODE(Store, F32Store); } +#line 5437 "src/prebuilt/wast-lexer-gen.cc" +yy880: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 326 "src/wast-lexer.cc" - { OPCODE(F32Trunc); RETURN(UNARY); } -#line 4956 "src/prebuilt/wast-lexer-gen.cc" -yy875: +#line 462 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, F32Trunc); } +#line 5445 "src/prebuilt/wast-lexer-gen.cc" +yy882: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 307 "src/wast-lexer.cc" - { TYPE(F64); RETURN(CONST); } -#line 4964 "src/prebuilt/wast-lexer-gen.cc" -yy877: +#line 443 "src/wast-lexer.cc" + { RETURN_OPCODE(Const, F64Const); } +#line 5453 "src/prebuilt/wast-lexer-gen.cc" +yy884: yych = *++cursor_; - if (yych == 'r') goto yy957; + if (yych == 'r') goto yy965; goto yy87; -yy878: +yy885: yych = *++cursor_; - if (yych == 'i') goto yy958; + if (yych == 'i') goto yy966; goto yy87; -yy879: +yy886: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 325 "src/wast-lexer.cc" - { OPCODE(F64Floor); RETURN(UNARY); } -#line 4980 "src/prebuilt/wast-lexer-gen.cc" -yy881: +#line 461 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, F64Floor); } +#line 5469 "src/prebuilt/wast-lexer-gen.cc" +yy888: yych = *++cursor_; - if (yych == 's') goto yy959; + if (yych == 's') goto yy967; goto yy87; -yy882: +yy889: yych = *++cursor_; - if (yych == 't') goto yy960; + if (yych == 't') goto yy968; goto yy87; -yy883: +yy890: yych = *++cursor_; - if (yych == 'e') goto yy961; + if (yych == 'e') goto yy969; goto yy87; -yy884: +yy891: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 286 "src/wast-lexer.cc" - { OPCODE(F64Store); RETURN(STORE); } -#line 5000 "src/prebuilt/wast-lexer-gen.cc" -yy886: +#line 422 "src/wast-lexer.cc" + { RETURN_OPCODE(Store, F64Store); } +#line 5489 "src/prebuilt/wast-lexer-gen.cc" +yy893: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 327 "src/wast-lexer.cc" - { OPCODE(F64Trunc); RETURN(UNARY); } -#line 5008 "src/prebuilt/wast-lexer-gen.cc" -yy888: +#line 463 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, F64Trunc); } +#line 5497 "src/prebuilt/wast-lexer-gen.cc" +yy895: yych = *++cursor_; - if (yych == 'l') goto yy962; + if (yych == 'l') goto yy970; goto yy87; -yy889: +yy896: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 274 "src/wast-lexer.cc" - { RETURN(GET_LOCAL); } -#line 5020 "src/prebuilt/wast-lexer-gen.cc" -yy891: +#line 410 "src/wast-lexer.cc" + { RETURN_OPCODE0(GetLocal); } +#line 5509 "src/prebuilt/wast-lexer-gen.cc" +yy898: yych = *++cursor_; - if (yych == 'r') goto yy964; + if (yych == 'r') goto yy972; goto yy87; -yy892: +yy899: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 304 "src/wast-lexer.cc" - { TYPE(I32); RETURN(CONST); } -#line 5032 "src/prebuilt/wast-lexer-gen.cc" -yy894: +#line 440 "src/wast-lexer.cc" + { RETURN_OPCODE(Const, I32Const); } +#line 5521 "src/prebuilt/wast-lexer-gen.cc" +yy901: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 336 "src/wast-lexer.cc" - { OPCODE(I32DivS); RETURN(BINARY); } -#line 5040 "src/prebuilt/wast-lexer-gen.cc" -yy896: +#line 472 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I32DivS); } +#line 5529 "src/prebuilt/wast-lexer-gen.cc" +yy903: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 338 "src/wast-lexer.cc" - { OPCODE(I32DivU); RETURN(BINARY); } -#line 5048 "src/prebuilt/wast-lexer-gen.cc" -yy898: +#line 474 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I32DivU); } +#line 5537 "src/prebuilt/wast-lexer-gen.cc" +yy905: yych = *++cursor_; - if (yych == '6') goto yy965; + if (yych == '6') goto yy973; goto yy87; -yy899: +yy906: yych = *++cursor_; - if (yych == '_') goto yy966; + if (yych == '_') goto yy974; goto yy87; -yy900: +yy907: yych = *++cursor_; - if (yych == 't') goto yy967; + if (yych == 't') goto yy975; goto yy87; -yy901: +yy908: yych = *++cursor_; - if (yych == 'e') goto yy969; + if (yych == 'e') goto yy977; goto yy87; -yy902: +yy909: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 340 "src/wast-lexer.cc" - { OPCODE(I32RemS); RETURN(BINARY); } -#line 5072 "src/prebuilt/wast-lexer-gen.cc" -yy904: +#line 476 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I32RemS); } +#line 5561 "src/prebuilt/wast-lexer-gen.cc" +yy911: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 342 "src/wast-lexer.cc" - { OPCODE(I32RemU); RETURN(BINARY); } -#line 5080 "src/prebuilt/wast-lexer-gen.cc" -yy906: +#line 478 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I32RemU); } +#line 5569 "src/prebuilt/wast-lexer-gen.cc" +yy913: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 352 "src/wast-lexer.cc" - { OPCODE(I32ShrS); RETURN(BINARY); } -#line 5088 "src/prebuilt/wast-lexer-gen.cc" -yy908: +#line 488 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I32ShrS); } +#line 5577 "src/prebuilt/wast-lexer-gen.cc" +yy915: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 354 "src/wast-lexer.cc" - { OPCODE(I32ShrU); RETURN(BINARY); } -#line 5096 "src/prebuilt/wast-lexer-gen.cc" -yy910: +#line 490 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I32ShrU); } +#line 5585 "src/prebuilt/wast-lexer-gen.cc" +yy917: ++cursor_; if ((yych = *cursor_) <= '0') { if (yych <= '"') { @@ -5104,1454 +5593,1696 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { } } else { if (yych <= '8') { - if (yych <= '1') goto yy970; + if (yych <= '1') goto yy978; if (yych <= '7') goto yy86; - goto yy971; + goto yy979; } else { - if (yych == ';') goto yy911; + if (yych == ';') goto yy918; if (yych <= '~') goto yy86; } } -yy911: -#line 283 "src/wast-lexer.cc" - { OPCODE(I32Store); RETURN(STORE); } -#line 5119 "src/prebuilt/wast-lexer-gen.cc" -yy912: +yy918: +#line 419 "src/wast-lexer.cc" + { RETURN_OPCODE(Store, I32Store); } +#line 5608 "src/prebuilt/wast-lexer-gen.cc" +yy919: yych = *++cursor_; - if (yych == '_') goto yy973; + if (yych == '_') goto yy981; goto yy87; -yy913: +yy920: yych = *++cursor_; - if (yych == 'i') goto yy974; + if (yych == 'i') goto yy982; goto yy87; -yy914: +yy921: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 305 "src/wast-lexer.cc" - { TYPE(I64); RETURN(CONST); } -#line 5135 "src/prebuilt/wast-lexer-gen.cc" -yy916: +#line 441 "src/wast-lexer.cc" + { RETURN_OPCODE(Const, I64Const); } +#line 5624 "src/prebuilt/wast-lexer-gen.cc" +yy923: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 337 "src/wast-lexer.cc" - { OPCODE(I64DivS); RETURN(BINARY); } -#line 5143 "src/prebuilt/wast-lexer-gen.cc" -yy918: +#line 473 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I64DivS); } +#line 5632 "src/prebuilt/wast-lexer-gen.cc" +yy925: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 339 "src/wast-lexer.cc" - { OPCODE(I64DivU); RETURN(BINARY); } -#line 5151 "src/prebuilt/wast-lexer-gen.cc" -yy920: +#line 475 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I64DivU); } +#line 5640 "src/prebuilt/wast-lexer-gen.cc" +yy927: yych = *++cursor_; - if (yych == 'd') goto yy975; + if (yych == 'd') goto yy983; goto yy87; -yy921: +yy928: yych = *++cursor_; - if (yych == '6') goto yy976; + if (yych == '6') goto yy984; goto yy87; -yy922: +yy929: yych = *++cursor_; - if (yych == '2') goto yy977; + if (yych == '2') goto yy985; goto yy87; -yy923: +yy930: yych = *++cursor_; - if (yych == '_') goto yy978; + if (yych == '_') goto yy986; goto yy87; -yy924: +yy931: yych = *++cursor_; - if (yych == 't') goto yy979; + if (yych == 't') goto yy987; goto yy87; -yy925: +yy932: yych = *++cursor_; - if (yych == 'e') goto yy981; + if (yych == 'e') goto yy989; goto yy87; -yy926: +yy933: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 341 "src/wast-lexer.cc" - { OPCODE(I64RemS); RETURN(BINARY); } -#line 5183 "src/prebuilt/wast-lexer-gen.cc" -yy928: +#line 477 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I64RemS); } +#line 5672 "src/prebuilt/wast-lexer-gen.cc" +yy935: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 343 "src/wast-lexer.cc" - { OPCODE(I64RemU); RETURN(BINARY); } -#line 5191 "src/prebuilt/wast-lexer-gen.cc" -yy930: +#line 479 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I64RemU); } +#line 5680 "src/prebuilt/wast-lexer-gen.cc" +yy937: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 353 "src/wast-lexer.cc" - { OPCODE(I64ShrS); RETURN(BINARY); } -#line 5199 "src/prebuilt/wast-lexer-gen.cc" -yy932: +#line 489 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I64ShrS); } +#line 5688 "src/prebuilt/wast-lexer-gen.cc" +yy939: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 355 "src/wast-lexer.cc" - { OPCODE(I64ShrU); RETURN(BINARY); } -#line 5207 "src/prebuilt/wast-lexer-gen.cc" -yy934: +#line 491 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, I64ShrU); } +#line 5696 "src/prebuilt/wast-lexer-gen.cc" +yy941: ++cursor_; if ((yych = *cursor_) <= '1') { if (yych <= '"') { if (yych == '!') goto yy86; } else { if (yych <= '\'') goto yy86; - if (yych <= ')') goto yy935; + if (yych <= ')') goto yy942; if (yych <= '0') goto yy86; - goto yy982; + goto yy990; } } else { if (yych <= '8') { - if (yych == '3') goto yy983; + if (yych == '3') goto yy991; if (yych <= '7') goto yy86; - goto yy984; + goto yy992; } else { - if (yych == ';') goto yy935; + if (yych == ';') goto yy942; if (yych <= '~') goto yy86; } } -yy935: -#line 284 "src/wast-lexer.cc" - { OPCODE(I64Store); RETURN(STORE); } -#line 5232 "src/prebuilt/wast-lexer-gen.cc" -yy936: +yy942: +#line 420 "src/wast-lexer.cc" + { RETURN_OPCODE(Store, I64Store); } +#line 5721 "src/prebuilt/wast-lexer-gen.cc" +yy943: yych = *++cursor_; - if (yych == '_') goto yy986; + if (yych == '_') goto yy994; goto yy87; -yy937: - yych = *++cursor_; - if (yych <= '@') { - if (yych <= '/') goto yy87; - if (yych <= '9') goto yy987; - goto yy87; +yy944: + ++cursor_; + if (limit_ <= cursor_) FILL(1); + yych = *cursor_; + if (yych <= ')') { + if (yych <= '!') { + if (yych <= ' ') goto yy88; + goto yy86; + } else { + if (yych <= '"') goto yy88; + if (yych <= '\'') goto yy86; + goto yy88; + } } else { - if (yych <= 'F') goto yy987; - if (yych <= '`') goto yy87; - if (yych <= 'f') goto yy987; - goto yy87; + if (yych <= ':') { + if (yych <= '/') goto yy86; + if (yych <= '9') goto yy849; + goto yy86; + } else { + if (yych <= ';') goto yy88; + if (yych <= '~') goto yy86; + goto yy88; + } + } +yy945: + ++cursor_; + if (limit_ <= cursor_) FILL(1); + yych = *cursor_; + if (yych <= '9') { + if (yych <= '"') { + if (yych == '!') goto yy86; + goto yy88; + } else { + if (yych <= '\'') goto yy86; + if (yych <= ')') goto yy88; + if (yych <= '/') goto yy86; + goto yy995; + } + } else { + if (yych <= 'F') { + if (yych == ';') goto yy88; + if (yych <= '@') goto yy86; + goto yy995; + } else { + if (yych <= '`') goto yy86; + if (yych <= 'f') goto yy995; + if (yych <= '~') goto yy86; + goto yy88; + } } -yy938: +yy946: yych = *++cursor_; - if (yych == 'l') goto yy989; + if (yych == 'l') goto yy997; goto yy87; -yy939: +yy947: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 275 "src/wast-lexer.cc" - { RETURN(SET_LOCAL); } -#line 5260 "src/prebuilt/wast-lexer-gen.cc" -yy941: +#line 411 "src/wast-lexer.cc" + { RETURN_OPCODE0(SetLocal); } +#line 5787 "src/prebuilt/wast-lexer-gen.cc" +yy949: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 276 "src/wast-lexer.cc" - { RETURN(TEE_LOCAL); } -#line 5268 "src/prebuilt/wast-lexer-gen.cc" -yy943: +#line 412 "src/wast-lexer.cc" + { RETURN_OPCODE0(TeeLocal); } +#line 5795 "src/prebuilt/wast-lexer-gen.cc" +yy951: yych = *++cursor_; - if (yych == 'l') goto yy991; + if (yych == 'l') goto yy999; goto yy87; -yy944: +yy952: yych = *++cursor_; - if (yych == 'a') goto yy992; + if (yych == 'a') goto yy1000; goto yy87; -yy945: +yy953: yych = *++cursor_; - if (yych == 'a') goto yy993; + if (yych == 'a') goto yy1001; goto yy87; -yy946: +yy954: yych = *++cursor_; - if (yych == 'f') goto yy994; + if (yych == 'f') goto yy1002; goto yy87; -yy947: +yy955: yych = *++cursor_; - if (yych == 'u') goto yy995; + if (yych == 'u') goto yy1003; goto yy87; -yy948: +yy956: yych = *++cursor_; - if (yych == 'p') goto yy996; + if (yych == 'p') goto yy1004; goto yy87; -yy949: +yy957: yych = *++cursor_; - if (yych == 'i') goto yy998; + if (yych == 'i') goto yy1006; goto yy87; -yy950: +yy958: yych = *++cursor_; - if (yych == 'e') goto yy999; + if (yych == 'e') goto yy1007; goto yy87; -yy951: +yy959: yych = *++cursor_; - if (yych == 'm') goto yy1000; + if (yych == 'm') goto yy1008; goto yy87; -yy952: +yy960: yych = *++cursor_; - if (yych == 't') goto yy1001; + if (yych == 't') goto yy1009; goto yy87; -yy953: +yy961: yych = *++cursor_; - if (yych == 'g') goto yy1002; + if (yych == 'g') goto yy1010; goto yy87; -yy954: +yy962: yych = *++cursor_; - if (yych == '/') goto yy1003; + if (yych == '/') goto yy1011; goto yy87; -yy955: +yy963: yych = *++cursor_; - if (yych == 't') goto yy1004; + if (yych == 't') goto yy1012; goto yy87; -yy956: +yy964: yych = *++cursor_; - if (yych == 'r') goto yy1006; + if (yych == 'r') goto yy1014; goto yy87; -yy957: +yy965: yych = *++cursor_; - if (yych == 't') goto yy1007; + if (yych == 't') goto yy1015; goto yy87; -yy958: +yy966: yych = *++cursor_; - if (yych == 'g') goto yy1008; + if (yych == 'g') goto yy1016; goto yy87; -yy959: +yy967: yych = *++cursor_; - if (yych == 't') goto yy1009; + if (yych == 't') goto yy1017; goto yy87; -yy960: +yy968: yych = *++cursor_; - if (yych == 'e') goto yy1011; + if (yych == 'e') goto yy1019; goto yy87; -yy961: +yy969: yych = *++cursor_; - if (yych == 'r') goto yy1012; + if (yych == 'r') goto yy1020; goto yy87; -yy962: +yy970: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 277 "src/wast-lexer.cc" - { RETURN(GET_GLOBAL); } -#line 5352 "src/prebuilt/wast-lexer-gen.cc" -yy964: +#line 413 "src/wast-lexer.cc" + { RETURN_OPCODE0(GetGlobal); } +#line 5879 "src/prebuilt/wast-lexer-gen.cc" +yy972: yych = *++cursor_; - if (yych == 'y') goto yy1013; + if (yych == 'y') goto yy1021; goto yy87; -yy965: +yy973: yych = *++cursor_; - if (yych == '_') goto yy1015; + if (yych == '_') goto yy1023; goto yy87; -yy966: +yy974: yych = *++cursor_; - if (yych == 's') goto yy1016; - if (yych == 'u') goto yy1018; + if (yych == 's') goto yy1024; + if (yych == 'u') goto yy1026; goto yy87; -yy967: +yy975: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 314 "src/wast-lexer.cc" - { OPCODE(I32Popcnt); RETURN(UNARY); } -#line 5373 "src/prebuilt/wast-lexer-gen.cc" -yy969: +#line 450 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, I32Popcnt); } +#line 5900 "src/prebuilt/wast-lexer-gen.cc" +yy977: yych = *++cursor_; - if (yych == 'r') goto yy1020; + if (yych == 'r') goto yy1028; goto yy87; -yy970: +yy978: yych = *++cursor_; - if (yych == '6') goto yy1021; + if (yych == '6') goto yy1029; goto yy87; -yy971: +yy979: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 297 "src/wast-lexer.cc" - { OPCODE(I32Store8); RETURN(STORE); } -#line 5389 "src/prebuilt/wast-lexer-gen.cc" -yy973: +#line 433 "src/wast-lexer.cc" + { RETURN_OPCODE(Store, I32Store8); } +#line 5916 "src/prebuilt/wast-lexer-gen.cc" +yy981: yych = *++cursor_; - if (yych == 's') goto yy1023; - if (yych == 'u') goto yy1024; + if (yych == 's') goto yy1031; + if (yych == 'u') goto yy1032; goto yy87; -yy974: +yy982: yych = *++cursor_; - if (yych == '6') goto yy1025; + if (yych == '6') goto yy1033; goto yy87; -yy975: +yy983: yych = *++cursor_; - if (yych == '_') goto yy1026; + if (yych == '_') goto yy1034; goto yy87; -yy976: +yy984: yych = *++cursor_; - if (yych == '_') goto yy1027; + if (yych == '_') goto yy1035; goto yy87; -yy977: +yy985: yych = *++cursor_; - if (yych == '_') goto yy1028; + if (yych == '_') goto yy1036; goto yy87; -yy978: +yy986: yych = *++cursor_; - if (yych == 's') goto yy1029; - if (yych == 'u') goto yy1031; + if (yych == 's') goto yy1037; + if (yych == 'u') goto yy1039; goto yy87; -yy979: +yy987: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 315 "src/wast-lexer.cc" - { OPCODE(I64Popcnt); RETURN(UNARY); } -#line 5423 "src/prebuilt/wast-lexer-gen.cc" -yy981: +#line 451 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, I64Popcnt); } +#line 5950 "src/prebuilt/wast-lexer-gen.cc" +yy989: yych = *++cursor_; - if (yych == 'r') goto yy1033; + if (yych == 'r') goto yy1041; goto yy87; -yy982: +yy990: yych = *++cursor_; - if (yych == '6') goto yy1034; + if (yych == '6') goto yy1042; goto yy87; -yy983: +yy991: yych = *++cursor_; - if (yych == '2') goto yy1036; + if (yych == '2') goto yy1044; goto yy87; -yy984: +yy992: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 298 "src/wast-lexer.cc" - { OPCODE(I64Store8); RETURN(STORE); } -#line 5443 "src/prebuilt/wast-lexer-gen.cc" -yy986: +#line 434 "src/wast-lexer.cc" + { RETURN_OPCODE(Store, I64Store8); } +#line 5970 "src/prebuilt/wast-lexer-gen.cc" +yy994: yych = *++cursor_; - if (yych == 's') goto yy1038; - if (yych == 'u') goto yy1039; + if (yych == 's') goto yy1046; + if (yych == 'u') goto yy1047; goto yy87; -yy987: +yy995: ++cursor_; if (limit_ <= cursor_) FILL(1); yych = *cursor_; - if (yych <= '9') { - if (yych <= '"') { + if (yych <= ':') { + if (yych <= '\'') { if (yych == '!') goto yy86; - goto yy841; + if (yych <= '"') goto yy848; + goto yy86; } else { - if (yych <= '\'') goto yy86; - if (yych <= ')') goto yy841; + if (yych <= ')') goto yy848; if (yych <= '/') goto yy86; - goto yy987; + if (yych <= '9') goto yy995; + goto yy86; } } else { - if (yych <= 'F') { - if (yych == ';') goto yy841; + if (yych <= '^') { + if (yych <= ';') goto yy848; if (yych <= '@') goto yy86; - goto yy987; + if (yych <= 'F') goto yy995; + goto yy86; } else { - if (yych <= '`') goto yy86; - if (yych <= 'f') goto yy987; - if (yych <= '~') goto yy86; - goto yy841; + if (yych <= '`') { + if (yych <= '_') goto yy945; + goto yy86; + } else { + if (yych <= 'f') goto yy995; + if (yych <= '~') goto yy86; + goto yy848; + } } } -yy989: +yy997: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 278 "src/wast-lexer.cc" - { RETURN(SET_GLOBAL); } -#line 5482 "src/prebuilt/wast-lexer-gen.cc" -yy991: +#line 414 "src/wast-lexer.cc" + { RETURN_OPCODE0(SetGlobal); } +#line 6015 "src/prebuilt/wast-lexer-gen.cc" +yy999: yych = *++cursor_; - if (yych == 'e') goto yy1040; + if (yych == 'e') goto yy1048; goto yy87; -yy992: +yy1000: yych = *++cursor_; - if (yych == 'u') goto yy1042; + if (yych == 'u') goto yy1050; goto yy87; -yy993: +yy1001: yych = *++cursor_; - if (yych == 'l') goto yy1043; + if (yych == 'l') goto yy1051; goto yy87; -yy994: +yy1002: yych = *++cursor_; - if (yych == 'o') goto yy1044; + if (yych == 'o') goto yy1052; goto yy87; -yy995: +yy1003: yych = *++cursor_; - if (yych == 'r') goto yy1045; + if (yych == 'r') goto yy1053; goto yy87; -yy996: +yy1004: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 464 "src/wast-lexer.cc" - { RETURN(ASSERT_TRAP); } -#line 5510 "src/prebuilt/wast-lexer-gen.cc" -yy998: +#line 606 "src/wast-lexer.cc" + { RETURN(AssertTrap); } +#line 6043 "src/prebuilt/wast-lexer-gen.cc" +yy1006: yych = *++cursor_; - if (yych == 'n') goto yy1046; + if (yych == 'n') goto yy1054; goto yy87; -yy999: +yy1007: yych = *++cursor_; - if (yych == 'c') goto yy1047; + if (yych == 'c') goto yy1055; goto yy87; -yy1000: +yy1008: yych = *++cursor_; - if (yych == 'o') goto yy1048; + if (yych == 'o') goto yy1056; goto yy87; -yy1001: +yy1009: yych = *++cursor_; - if (yych == '_') goto yy1049; + if (yych == '_') goto yy1057; goto yy87; -yy1002: +yy1010: yych = *++cursor_; - if (yych == 'n') goto yy1050; + if (yych == 'n') goto yy1058; goto yy87; -yy1003: +yy1011: yych = *++cursor_; - if (yych == 'f') goto yy1052; + if (yych == 'f') goto yy1060; goto yy87; -yy1004: +yy1012: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 328 "src/wast-lexer.cc" - { OPCODE(F32Nearest); RETURN(UNARY); } -#line 5542 "src/prebuilt/wast-lexer-gen.cc" -yy1006: +#line 464 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, F32Nearest); } +#line 6075 "src/prebuilt/wast-lexer-gen.cc" +yy1014: yych = *++cursor_; - if (yych == 'p') goto yy1053; + if (yych == 'p') goto yy1061; goto yy87; -yy1007: +yy1015: yych = *++cursor_; - if (yych == '_') goto yy1054; + if (yych == '_') goto yy1062; goto yy87; -yy1008: +yy1016: yych = *++cursor_; - if (yych == 'n') goto yy1055; + if (yych == 'n') goto yy1063; goto yy87; -yy1009: +yy1017: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 329 "src/wast-lexer.cc" - { OPCODE(F64Nearest); RETURN(UNARY); } -#line 5562 "src/prebuilt/wast-lexer-gen.cc" -yy1011: +#line 465 "src/wast-lexer.cc" + { RETURN_OPCODE(Unary, F64Nearest); } +#line 6095 "src/prebuilt/wast-lexer-gen.cc" +yy1019: yych = *++cursor_; - if (yych == '/') goto yy1057; + if (yych == '/') goto yy1065; goto yy87; -yy1012: +yy1020: yych = *++cursor_; - if (yych == 'p') goto yy1058; + if (yych == 'p') goto yy1066; goto yy87; -yy1013: +yy1021: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 434 "src/wast-lexer.cc" - { RETURN(GROW_MEMORY); } -#line 5578 "src/prebuilt/wast-lexer-gen.cc" -yy1015: +#line 578 "src/wast-lexer.cc" + { RETURN_OPCODE0(GrowMemory); } +#line 6111 "src/prebuilt/wast-lexer-gen.cc" +yy1023: yych = *++cursor_; - if (yych == 's') goto yy1059; - if (yych == 'u') goto yy1061; + if (yych == 's') goto yy1067; + if (yych == 'u') goto yy1069; goto yy87; -yy1016: +yy1024: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 287 "src/wast-lexer.cc" - { OPCODE(I32Load8S); RETURN(LOAD); } -#line 5591 "src/prebuilt/wast-lexer-gen.cc" -yy1018: +#line 423 "src/wast-lexer.cc" + { RETURN_OPCODE(Load, I32Load8S); } +#line 6124 "src/prebuilt/wast-lexer-gen.cc" +yy1026: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 289 "src/wast-lexer.cc" - { OPCODE(I32Load8U); RETURN(LOAD); } -#line 5599 "src/prebuilt/wast-lexer-gen.cc" -yy1020: +#line 425 "src/wast-lexer.cc" + { RETURN_OPCODE(Load, I32Load8U); } +#line 6132 "src/prebuilt/wast-lexer-gen.cc" +yy1028: yych = *++cursor_; - if (yych == 'p') goto yy1063; + if (yych == 'p') goto yy1071; goto yy87; -yy1021: +yy1029: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 299 "src/wast-lexer.cc" - { OPCODE(I32Store16); RETURN(STORE); } -#line 5611 "src/prebuilt/wast-lexer-gen.cc" -yy1023: +#line 435 "src/wast-lexer.cc" + { RETURN_OPCODE(Store, I32Store16); } +#line 6144 "src/prebuilt/wast-lexer-gen.cc" +yy1031: yych = *++cursor_; - if (yych == '/') goto yy1064; + if (yych == '/') goto yy1072; + if (yych == ':') goto yy1073; goto yy87; -yy1024: +yy1032: yych = *++cursor_; - if (yych == '/') goto yy1065; + if (yych == '/') goto yy1074; + if (yych == ':') goto yy1075; goto yy87; -yy1025: +yy1033: yych = *++cursor_; - if (yych == '4') goto yy1066; + if (yych == '4') goto yy1076; goto yy87; -yy1026: +yy1034: yych = *++cursor_; - if (yych == 's') goto yy1068; - if (yych == 'u') goto yy1069; + if (yych == 's') goto yy1078; + if (yych == 'u') goto yy1079; goto yy87; -yy1027: +yy1035: yych = *++cursor_; - if (yych == 's') goto yy1070; - if (yych == 'u') goto yy1072; + if (yych == 's') goto yy1080; + if (yych == 'u') goto yy1082; goto yy87; -yy1028: +yy1036: yych = *++cursor_; - if (yych == 's') goto yy1074; - if (yych == 'u') goto yy1076; + if (yych == 's') goto yy1084; + if (yych == 'u') goto yy1086; goto yy87; -yy1029: +yy1037: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 288 "src/wast-lexer.cc" - { OPCODE(I64Load8S); RETURN(LOAD); } -#line 5646 "src/prebuilt/wast-lexer-gen.cc" -yy1031: +#line 424 "src/wast-lexer.cc" + { RETURN_OPCODE(Load, I64Load8S); } +#line 6181 "src/prebuilt/wast-lexer-gen.cc" +yy1039: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 290 "src/wast-lexer.cc" - { OPCODE(I64Load8U); RETURN(LOAD); } -#line 5654 "src/prebuilt/wast-lexer-gen.cc" -yy1033: +#line 426 "src/wast-lexer.cc" + { RETURN_OPCODE(Load, I64Load8U); } +#line 6189 "src/prebuilt/wast-lexer-gen.cc" +yy1041: yych = *++cursor_; - if (yych == 'p') goto yy1078; + if (yych == 'p') goto yy1088; goto yy87; -yy1034: +yy1042: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 300 "src/wast-lexer.cc" - { OPCODE(I64Store16); RETURN(STORE); } -#line 5666 "src/prebuilt/wast-lexer-gen.cc" -yy1036: +#line 436 "src/wast-lexer.cc" + { RETURN_OPCODE(Store, I64Store16); } +#line 6201 "src/prebuilt/wast-lexer-gen.cc" +yy1044: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 301 "src/wast-lexer.cc" - { OPCODE(I64Store32); RETURN(STORE); } -#line 5674 "src/prebuilt/wast-lexer-gen.cc" -yy1038: +#line 437 "src/wast-lexer.cc" + { RETURN_OPCODE(Store, I64Store32); } +#line 6209 "src/prebuilt/wast-lexer-gen.cc" +yy1046: yych = *++cursor_; - if (yych == '/') goto yy1079; + if (yych == '/') goto yy1089; + if (yych == ':') goto yy1090; goto yy87; -yy1039: +yy1047: yych = *++cursor_; - if (yych == '/') goto yy1080; + if (yych == '/') goto yy1091; + if (yych == ':') goto yy1092; goto yy87; -yy1040: +yy1048: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 432 "src/wast-lexer.cc" - { RETURN(UNREACHABLE); } -#line 5690 "src/prebuilt/wast-lexer-gen.cc" -yy1042: +#line 576 "src/wast-lexer.cc" + { RETURN_OPCODE0(Unreachable); } +#line 6227 "src/prebuilt/wast-lexer-gen.cc" +yy1050: yych = *++cursor_; - if (yych == 's') goto yy1081; + if (yych == 's') goto yy1093; goto yy87; -yy1043: +yy1051: yych = *++cursor_; - if (yych == 'i') goto yy1082; + if (yych == 'i') goto yy1094; goto yy87; -yy1044: +yy1052: yych = *++cursor_; - if (yych == 'r') goto yy1083; + if (yych == 'r') goto yy1095; goto yy87; -yy1045: +yy1053: yych = *++cursor_; - if (yych == 'n') goto yy1084; + if (yych == 'n') goto yy1096; goto yy87; -yy1046: +yy1054: yych = *++cursor_; - if (yych == 'k') goto yy1086; + if (yych == 'k') goto yy1098; goto yy87; -yy1047: +yy1055: yych = *++cursor_; - if (yych == 't') goto yy1087; + if (yych == 't') goto yy1099; goto yy87; -yy1048: +yy1056: yych = *++cursor_; - if (yych == 'r') goto yy1089; + if (yych == 'r') goto yy1101; goto yy87; -yy1049: +yy1057: yych = *++cursor_; - if (yych == 's') goto yy1090; - if (yych == 'u') goto yy1091; + if (yych == 's') goto yy1102; + if (yych == 'u') goto yy1103; goto yy87; -yy1050: +yy1058: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 372 "src/wast-lexer.cc" - { OPCODE(F32Copysign); RETURN(BINARY); } -#line 5731 "src/prebuilt/wast-lexer-gen.cc" -yy1052: +#line 508 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, F32Copysign); } +#line 6268 "src/prebuilt/wast-lexer-gen.cc" +yy1060: yych = *++cursor_; - if (yych == '6') goto yy1092; + if (yych == '6') goto yy1104; goto yy87; -yy1053: +yy1061: yych = *++cursor_; - if (yych == 'r') goto yy1093; + if (yych == 'r') goto yy1105; goto yy87; -yy1054: +yy1062: yych = *++cursor_; - if (yych == 's') goto yy1094; - if (yych == 'u') goto yy1095; + if (yych == 's') goto yy1106; + if (yych == 'u') goto yy1107; goto yy87; -yy1055: +yy1063: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 373 "src/wast-lexer.cc" - { OPCODE(F64Copysign); RETURN(BINARY); } -#line 5752 "src/prebuilt/wast-lexer-gen.cc" -yy1057: +#line 509 "src/wast-lexer.cc" + { RETURN_OPCODE(Binary, F64Copysign); } +#line 6289 "src/prebuilt/wast-lexer-gen.cc" +yy1065: yych = *++cursor_; - if (yych == 'f') goto yy1096; + if (yych == 'f') goto yy1108; goto yy87; -yy1058: +yy1066: yych = *++cursor_; - if (yych == 'r') goto yy1097; + if (yych == 'r') goto yy1109; goto yy87; -yy1059: +yy1067: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 291 "src/wast-lexer.cc" - { OPCODE(I32Load16S); RETURN(LOAD); } -#line 5768 "src/prebuilt/wast-lexer-gen.cc" -yy1061: +#line 427 "src/wast-lexer.cc" + { RETURN_OPCODE(Load, I32Load16S); } +#line 6305 "src/prebuilt/wast-lexer-gen.cc" +yy1069: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 293 "src/wast-lexer.cc" - { OPCODE(I32Load16U); RETURN(LOAD); } -#line 5776 "src/prebuilt/wast-lexer-gen.cc" -yy1063: +#line 429 "src/wast-lexer.cc" + { RETURN_OPCODE(Load, I32Load16U); } +#line 6313 "src/prebuilt/wast-lexer-gen.cc" +yy1071: yych = *++cursor_; - if (yych == 'r') goto yy1098; + if (yych == 'r') goto yy1110; goto yy87; -yy1064: +yy1072: yych = *++cursor_; - if (yych == 'f') goto yy1099; + if (yych == 'f') goto yy1111; goto yy87; -yy1065: +yy1073: yych = *++cursor_; - if (yych == 'f') goto yy1100; + if (yych == 's') goto yy1112; goto yy87; -yy1066: +yy1074: + yych = *++cursor_; + if (yych == 'f') goto yy1113; + goto yy87; +yy1075: + yych = *++cursor_; + if (yych == 's') goto yy1114; + goto yy87; +yy1076: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 408 "src/wast-lexer.cc" - { OPCODE(I32WrapI64); RETURN(CONVERT); } -#line 5796 "src/prebuilt/wast-lexer-gen.cc" -yy1068: +#line 544 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I32WrapI64); } +#line 6341 "src/prebuilt/wast-lexer-gen.cc" +yy1078: yych = *++cursor_; - if (yych == '/') goto yy1101; + if (yych == '/') goto yy1115; goto yy87; -yy1069: +yy1079: yych = *++cursor_; - if (yych == '/') goto yy1102; + if (yych == '/') goto yy1116; goto yy87; -yy1070: +yy1080: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 292 "src/wast-lexer.cc" - { OPCODE(I64Load16S); RETURN(LOAD); } -#line 5812 "src/prebuilt/wast-lexer-gen.cc" -yy1072: +#line 428 "src/wast-lexer.cc" + { RETURN_OPCODE(Load, I64Load16S); } +#line 6357 "src/prebuilt/wast-lexer-gen.cc" +yy1082: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 294 "src/wast-lexer.cc" - { OPCODE(I64Load16U); RETURN(LOAD); } -#line 5820 "src/prebuilt/wast-lexer-gen.cc" -yy1074: +#line 430 "src/wast-lexer.cc" + { RETURN_OPCODE(Load, I64Load16U); } +#line 6365 "src/prebuilt/wast-lexer-gen.cc" +yy1084: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 295 "src/wast-lexer.cc" - { OPCODE(I64Load32S); RETURN(LOAD); } -#line 5828 "src/prebuilt/wast-lexer-gen.cc" -yy1076: +#line 431 "src/wast-lexer.cc" + { RETURN_OPCODE(Load, I64Load32S); } +#line 6373 "src/prebuilt/wast-lexer-gen.cc" +yy1086: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 296 "src/wast-lexer.cc" - { OPCODE(I64Load32U); RETURN(LOAD); } -#line 5836 "src/prebuilt/wast-lexer-gen.cc" -yy1078: +#line 432 "src/wast-lexer.cc" + { RETURN_OPCODE(Load, I64Load32U); } +#line 6381 "src/prebuilt/wast-lexer-gen.cc" +yy1088: yych = *++cursor_; - if (yych == 'r') goto yy1103; + if (yych == 'r') goto yy1117; goto yy87; -yy1079: +yy1089: yych = *++cursor_; - if (yych == 'f') goto yy1104; + if (yych == 'f') goto yy1118; goto yy87; -yy1080: +yy1090: yych = *++cursor_; - if (yych == 'f') goto yy1105; + if (yych == 's') goto yy1119; goto yy87; -yy1081: +yy1091: yych = *++cursor_; - if (yych == 't') goto yy1106; + if (yych == 'f') goto yy1120; goto yy87; -yy1082: +yy1092: + yych = *++cursor_; + if (yych == 's') goto yy1121; + goto yy87; +yy1093: yych = *++cursor_; - if (yych == 'd') goto yy1107; + if (yych == 't') goto yy1122; goto yy87; -yy1083: +yy1094: yych = *++cursor_; - if (yych == 'm') goto yy1109; + if (yych == 'd') goto yy1123; goto yy87; -yy1084: +yy1095: + yych = *++cursor_; + if (yych == 'm') goto yy1125; + goto yy87; +yy1096: ++cursor_; if ((yych = *cursor_) <= ')') { if (yych <= '!') { if (yych >= '!') goto yy86; } else { - if (yych <= '"') goto yy1085; + if (yych <= '"') goto yy1097; if (yych <= '\'') goto yy86; } } else { if (yych <= '^') { if (yych != ';') goto yy86; } else { - if (yych <= '_') goto yy1110; + if (yych <= '_') goto yy1126; if (yych <= '~') goto yy86; } } -yy1085: -#line 459 "src/wast-lexer.cc" - { RETURN(ASSERT_RETURN); } -#line 5881 "src/prebuilt/wast-lexer-gen.cc" -yy1086: +yy1097: +#line 603 "src/wast-lexer.cc" + { RETURN(AssertReturn); } +#line 6434 "src/prebuilt/wast-lexer-gen.cc" +yy1098: yych = *++cursor_; - if (yych == 'a') goto yy1111; + if (yych == 'a') goto yy1127; goto yy87; -yy1087: +yy1099: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 270 "src/wast-lexer.cc" - { RETURN(CALL_INDIRECT); } -#line 5893 "src/prebuilt/wast-lexer-gen.cc" -yy1089: +#line 406 "src/wast-lexer.cc" + { RETURN_OPCODE0(CallIndirect); } +#line 6446 "src/prebuilt/wast-lexer-gen.cc" +yy1101: yych = *++cursor_; - if (yych == 'y') goto yy1112; + if (yych == 'y') goto yy1128; goto yy87; -yy1090: +yy1102: yych = *++cursor_; - if (yych == '/') goto yy1114; + if (yych == '/') goto yy1130; goto yy87; -yy1091: +yy1103: yych = *++cursor_; - if (yych == '/') goto yy1115; + if (yych == '/') goto yy1131; goto yy87; -yy1092: +yy1104: yych = *++cursor_; - if (yych == '4') goto yy1116; + if (yych == '4') goto yy1132; goto yy87; -yy1093: +yy1105: yych = *++cursor_; - if (yych == 'e') goto yy1118; + if (yych == 'e') goto yy1134; goto yy87; -yy1094: +yy1106: yych = *++cursor_; - if (yych == '/') goto yy1119; + if (yych == '/') goto yy1135; goto yy87; -yy1095: +yy1107: yych = *++cursor_; - if (yych == '/') goto yy1120; + if (yych == '/') goto yy1136; goto yy87; -yy1096: +yy1108: yych = *++cursor_; - if (yych == '3') goto yy1121; + if (yych == '3') goto yy1137; goto yy87; -yy1097: +yy1109: yych = *++cursor_; - if (yych == 'e') goto yy1122; + if (yych == 'e') goto yy1138; goto yy87; -yy1098: +yy1110: yych = *++cursor_; - if (yych == 'e') goto yy1123; + if (yych == 'e') goto yy1139; goto yy87; -yy1099: +yy1111: yych = *++cursor_; - if (yych == '3') goto yy1124; - if (yych == '6') goto yy1125; + if (yych == '3') goto yy1140; + if (yych == '6') goto yy1141; goto yy87; -yy1100: +yy1112: yych = *++cursor_; - if (yych == '3') goto yy1126; - if (yych == '6') goto yy1127; + if (yych == 'a') goto yy1142; goto yy87; -yy1101: +yy1113: yych = *++cursor_; - if (yych == 'i') goto yy1128; + if (yych == '3') goto yy1143; + if (yych == '6') goto yy1144; goto yy87; -yy1102: +yy1114: yych = *++cursor_; - if (yych == 'i') goto yy1129; + if (yych == 'a') goto yy1145; goto yy87; -yy1103: +yy1115: yych = *++cursor_; - if (yych == 'e') goto yy1130; + if (yych == 'i') goto yy1146; goto yy87; -yy1104: +yy1116: yych = *++cursor_; - if (yych == '3') goto yy1131; - if (yych == '6') goto yy1132; + if (yych == 'i') goto yy1147; goto yy87; -yy1105: +yy1117: yych = *++cursor_; - if (yych == '3') goto yy1133; - if (yych == '6') goto yy1134; + if (yych == 'e') goto yy1148; goto yy87; -yy1106: +yy1118: yych = *++cursor_; - if (yych == 'i') goto yy1135; + if (yych == '3') goto yy1149; + if (yych == '6') goto yy1150; goto yy87; -yy1107: +yy1119: + yych = *++cursor_; + if (yych == 'a') goto yy1151; + goto yy87; +yy1120: + yych = *++cursor_; + if (yych == '3') goto yy1152; + if (yych == '6') goto yy1153; + goto yy87; +yy1121: + yych = *++cursor_; + if (yych == 'a') goto yy1154; + goto yy87; +yy1122: + yych = *++cursor_; + if (yych == 'i') goto yy1155; + goto yy87; +yy1123: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 457 "src/wast-lexer.cc" - { RETURN(ASSERT_INVALID); } -#line 5977 "src/prebuilt/wast-lexer-gen.cc" -yy1109: +#line 601 "src/wast-lexer.cc" + { RETURN(AssertInvalid); } +#line 6546 "src/prebuilt/wast-lexer-gen.cc" +yy1125: yych = *++cursor_; - if (yych == 'e') goto yy1136; + if (yych == 'e') goto yy1156; goto yy87; -yy1110: +yy1126: yych = *++cursor_; - if (yych == 'a') goto yy1137; - if (yych == 'c') goto yy1138; + if (yych == 'a') goto yy1157; + if (yych == 'c') goto yy1158; goto yy87; -yy1111: +yy1127: yych = *++cursor_; - if (yych == 'b') goto yy1139; + if (yych == 'b') goto yy1159; goto yy87; -yy1112: +yy1128: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 433 "src/wast-lexer.cc" - { RETURN(CURRENT_MEMORY); } -#line 5998 "src/prebuilt/wast-lexer-gen.cc" -yy1114: +#line 577 "src/wast-lexer.cc" + { RETURN_OPCODE0(CurrentMemory); } +#line 6567 "src/prebuilt/wast-lexer-gen.cc" +yy1130: yych = *++cursor_; - if (yych == 'i') goto yy1140; + if (yych == 'i') goto yy1160; goto yy87; -yy1115: +yy1131: yych = *++cursor_; - if (yych == 'i') goto yy1141; + if (yych == 'i') goto yy1161; goto yy87; -yy1116: +yy1132: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 426 "src/wast-lexer.cc" - { OPCODE(F32DemoteF64); RETURN(CONVERT); } -#line 6014 "src/prebuilt/wast-lexer-gen.cc" -yy1118: +#line 570 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, F32DemoteF64); } +#line 6583 "src/prebuilt/wast-lexer-gen.cc" +yy1134: yych = *++cursor_; - if (yych == 't') goto yy1142; + if (yych == 't') goto yy1162; goto yy87; -yy1119: +yy1135: yych = *++cursor_; - if (yych == 'i') goto yy1143; + if (yych == 'i') goto yy1163; goto yy87; -yy1120: +yy1136: yych = *++cursor_; - if (yych == 'i') goto yy1144; + if (yych == 'i') goto yy1164; goto yy87; -yy1121: +yy1137: yych = *++cursor_; - if (yych == '2') goto yy1145; + if (yych == '2') goto yy1165; goto yy87; -yy1122: +yy1138: yych = *++cursor_; - if (yych == 't') goto yy1147; + if (yych == 't') goto yy1167; goto yy87; -yy1123: +yy1139: yych = *++cursor_; - if (yych == 't') goto yy1148; + if (yych == 't') goto yy1168; goto yy87; -yy1124: +yy1140: yych = *++cursor_; - if (yych == '2') goto yy1149; + if (yych == '2') goto yy1169; goto yy87; -yy1125: +yy1141: + yych = *++cursor_; + if (yych == '4') goto yy1171; + goto yy87; +yy1142: + yych = *++cursor_; + if (yych == 't') goto yy1173; + goto yy87; +yy1143: + yych = *++cursor_; + if (yych == '2') goto yy1174; + goto yy87; +yy1144: + yych = *++cursor_; + if (yych == '4') goto yy1176; + goto yy87; +yy1145: yych = *++cursor_; - if (yych == '4') goto yy1151; + if (yych == 't') goto yy1178; goto yy87; -yy1126: +yy1146: yych = *++cursor_; - if (yych == '2') goto yy1153; + if (yych == '3') goto yy1179; goto yy87; -yy1127: +yy1147: yych = *++cursor_; - if (yych == '4') goto yy1155; + if (yych == '3') goto yy1180; goto yy87; -yy1128: +yy1148: yych = *++cursor_; - if (yych == '3') goto yy1157; + if (yych == 't') goto yy1181; goto yy87; -yy1129: +yy1149: yych = *++cursor_; - if (yych == '3') goto yy1158; + if (yych == '2') goto yy1182; goto yy87; -yy1130: +yy1150: yych = *++cursor_; - if (yych == 't') goto yy1159; + if (yych == '4') goto yy1184; goto yy87; -yy1131: +yy1151: yych = *++cursor_; - if (yych == '2') goto yy1160; + if (yych == 't') goto yy1186; goto yy87; -yy1132: +yy1152: yych = *++cursor_; - if (yych == '4') goto yy1162; + if (yych == '2') goto yy1187; goto yy87; -yy1133: +yy1153: yych = *++cursor_; - if (yych == '2') goto yy1164; + if (yych == '4') goto yy1189; goto yy87; -yy1134: +yy1154: yych = *++cursor_; - if (yych == '4') goto yy1166; + if (yych == 't') goto yy1191; goto yy87; -yy1135: +yy1155: yych = *++cursor_; - if (yych == 'o') goto yy1168; + if (yych == 'o') goto yy1192; goto yy87; -yy1136: +yy1156: yych = *++cursor_; - if (yych == 'd') goto yy1169; + if (yych == 'd') goto yy1193; goto yy87; -yy1137: +yy1157: yych = *++cursor_; - if (yych == 'r') goto yy1171; + if (yych == 'r') goto yy1195; goto yy87; -yy1138: +yy1158: yych = *++cursor_; - if (yych == 'a') goto yy1172; + if (yych == 'a') goto yy1196; goto yy87; -yy1139: +yy1159: yych = *++cursor_; - if (yych == 'l') goto yy1173; + if (yych == 'l') goto yy1197; goto yy87; -yy1140: +yy1160: yych = *++cursor_; - if (yych == '3') goto yy1174; - if (yych == '6') goto yy1175; + if (yych == '3') goto yy1198; + if (yych == '6') goto yy1199; goto yy87; -yy1141: +yy1161: yych = *++cursor_; - if (yych == '3') goto yy1176; - if (yych == '6') goto yy1177; + if (yych == '3') goto yy1200; + if (yych == '6') goto yy1201; goto yy87; -yy1142: +yy1162: yych = *++cursor_; - if (yych == '/') goto yy1178; + if (yych == '/') goto yy1202; goto yy87; -yy1143: +yy1163: yych = *++cursor_; - if (yych == '3') goto yy1179; - if (yych == '6') goto yy1180; + if (yych == '3') goto yy1203; + if (yych == '6') goto yy1204; goto yy87; -yy1144: +yy1164: yych = *++cursor_; - if (yych == '3') goto yy1181; - if (yych == '6') goto yy1182; + if (yych == '3') goto yy1205; + if (yych == '6') goto yy1206; goto yy87; -yy1145: +yy1165: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 425 "src/wast-lexer.cc" - { OPCODE(F64PromoteF32); RETURN(CONVERT); } -#line 6134 "src/prebuilt/wast-lexer-gen.cc" -yy1147: +#line 569 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, F64PromoteF32); } +#line 6719 "src/prebuilt/wast-lexer-gen.cc" +yy1167: yych = *++cursor_; - if (yych == '/') goto yy1183; + if (yych == '/') goto yy1207; goto yy87; -yy1148: +yy1168: yych = *++cursor_; - if (yych == '/') goto yy1184; + if (yych == '/') goto yy1208; goto yy87; -yy1149: +yy1169: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 409 "src/wast-lexer.cc" - { OPCODE(I32TruncSF32); RETURN(CONVERT); } -#line 6150 "src/prebuilt/wast-lexer-gen.cc" -yy1151: +#line 545 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I32TruncSF32); } +#line 6735 "src/prebuilt/wast-lexer-gen.cc" +yy1171: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 411 "src/wast-lexer.cc" - { OPCODE(I32TruncSF64); RETURN(CONVERT); } -#line 6158 "src/prebuilt/wast-lexer-gen.cc" -yy1153: +#line 547 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I32TruncSF64); } +#line 6743 "src/prebuilt/wast-lexer-gen.cc" +yy1173: + yych = *++cursor_; + if (yych == '/') goto yy1209; + goto yy87; +yy1174: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 413 "src/wast-lexer.cc" - { OPCODE(I32TruncUF32); RETURN(CONVERT); } -#line 6166 "src/prebuilt/wast-lexer-gen.cc" -yy1155: +#line 549 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I32TruncUF32); } +#line 6755 "src/prebuilt/wast-lexer-gen.cc" +yy1176: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 415 "src/wast-lexer.cc" - { OPCODE(I32TruncUF64); RETURN(CONVERT); } -#line 6174 "src/prebuilt/wast-lexer-gen.cc" -yy1157: +#line 551 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I32TruncUF64); } +#line 6763 "src/prebuilt/wast-lexer-gen.cc" +yy1178: yych = *++cursor_; - if (yych == '2') goto yy1185; + if (yych == '/') goto yy1210; goto yy87; -yy1158: +yy1179: yych = *++cursor_; - if (yych == '2') goto yy1187; + if (yych == '2') goto yy1211; goto yy87; -yy1159: +yy1180: yych = *++cursor_; - if (yych == '/') goto yy1189; + if (yych == '2') goto yy1213; goto yy87; -yy1160: +yy1181: + yych = *++cursor_; + if (yych == '/') goto yy1215; + goto yy87; +yy1182: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 410 "src/wast-lexer.cc" - { OPCODE(I64TruncSF32); RETURN(CONVERT); } -#line 6194 "src/prebuilt/wast-lexer-gen.cc" -yy1162: +#line 546 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I64TruncSF32); } +#line 6787 "src/prebuilt/wast-lexer-gen.cc" +yy1184: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 412 "src/wast-lexer.cc" - { OPCODE(I64TruncSF64); RETURN(CONVERT); } -#line 6202 "src/prebuilt/wast-lexer-gen.cc" -yy1164: +#line 548 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I64TruncSF64); } +#line 6795 "src/prebuilt/wast-lexer-gen.cc" +yy1186: + yych = *++cursor_; + if (yych == '/') goto yy1216; + goto yy87; +yy1187: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 414 "src/wast-lexer.cc" - { OPCODE(I64TruncUF32); RETURN(CONVERT); } -#line 6210 "src/prebuilt/wast-lexer-gen.cc" -yy1166: +#line 550 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I64TruncUF32); } +#line 6807 "src/prebuilt/wast-lexer-gen.cc" +yy1189: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 416 "src/wast-lexer.cc" - { OPCODE(I64TruncUF64); RETURN(CONVERT); } -#line 6218 "src/prebuilt/wast-lexer-gen.cc" -yy1168: +#line 552 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I64TruncUF64); } +#line 6815 "src/prebuilt/wast-lexer-gen.cc" +yy1191: yych = *++cursor_; - if (yych == 'n') goto yy1190; + if (yych == '/') goto yy1217; goto yy87; -yy1169: +yy1192: + yych = *++cursor_; + if (yych == 'n') goto yy1218; + goto yy87; +yy1193: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 456 "src/wast-lexer.cc" - { RETURN(ASSERT_MALFORMED); } -#line 6230 "src/prebuilt/wast-lexer-gen.cc" -yy1171: +#line 600 "src/wast-lexer.cc" + { RETURN(AssertMalformed); } +#line 6831 "src/prebuilt/wast-lexer-gen.cc" +yy1195: yych = *++cursor_; - if (yych == 'i') goto yy1192; + if (yych == 'i') goto yy1220; goto yy87; -yy1172: +yy1196: yych = *++cursor_; - if (yych == 'n') goto yy1193; + if (yych == 'n') goto yy1221; goto yy87; -yy1173: +yy1197: yych = *++cursor_; - if (yych == 'e') goto yy1194; + if (yych == 'e') goto yy1222; goto yy87; -yy1174: +yy1198: yych = *++cursor_; - if (yych == '2') goto yy1196; + if (yych == '2') goto yy1224; goto yy87; -yy1175: +yy1199: yych = *++cursor_; - if (yych == '4') goto yy1198; + if (yych == '4') goto yy1226; goto yy87; -yy1176: +yy1200: yych = *++cursor_; - if (yych == '2') goto yy1200; + if (yych == '2') goto yy1228; goto yy87; -yy1177: +yy1201: yych = *++cursor_; - if (yych == '4') goto yy1202; + if (yych == '4') goto yy1230; goto yy87; -yy1178: +yy1202: yych = *++cursor_; - if (yych == 'i') goto yy1204; + if (yych == 'i') goto yy1232; goto yy87; -yy1179: +yy1203: yych = *++cursor_; - if (yych == '2') goto yy1205; + if (yych == '2') goto yy1233; goto yy87; -yy1180: +yy1204: yych = *++cursor_; - if (yych == '4') goto yy1207; + if (yych == '4') goto yy1235; goto yy87; -yy1181: +yy1205: yych = *++cursor_; - if (yych == '2') goto yy1209; + if (yych == '2') goto yy1237; goto yy87; -yy1182: +yy1206: yych = *++cursor_; - if (yych == '4') goto yy1211; + if (yych == '4') goto yy1239; goto yy87; -yy1183: +yy1207: yych = *++cursor_; - if (yych == 'i') goto yy1213; + if (yych == 'i') goto yy1241; goto yy87; -yy1184: +yy1208: yych = *++cursor_; - if (yych == 'f') goto yy1214; + if (yych == 'f') goto yy1242; goto yy87; -yy1185: +yy1209: + yych = *++cursor_; + if (yych == 'f') goto yy1243; + goto yy87; +yy1210: + yych = *++cursor_; + if (yych == 'f') goto yy1244; + goto yy87; +yy1211: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 406 "src/wast-lexer.cc" - { OPCODE(I64ExtendSI32); RETURN(CONVERT); } -#line 6294 "src/prebuilt/wast-lexer-gen.cc" -yy1187: +#line 542 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I64ExtendSI32); } +#line 6903 "src/prebuilt/wast-lexer-gen.cc" +yy1213: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 407 "src/wast-lexer.cc" - { OPCODE(I64ExtendUI32); RETURN(CONVERT); } -#line 6302 "src/prebuilt/wast-lexer-gen.cc" -yy1189: +#line 543 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I64ExtendUI32); } +#line 6911 "src/prebuilt/wast-lexer-gen.cc" +yy1215: + yych = *++cursor_; + if (yych == 'f') goto yy1245; + goto yy87; +yy1216: + yych = *++cursor_; + if (yych == 'f') goto yy1246; + goto yy87; +yy1217: yych = *++cursor_; - if (yych == 'f') goto yy1215; + if (yych == 'f') goto yy1247; goto yy87; -yy1190: +yy1218: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 465 "src/wast-lexer.cc" - { RETURN(ASSERT_EXHAUSTION); } -#line 6314 "src/prebuilt/wast-lexer-gen.cc" -yy1192: +#line 607 "src/wast-lexer.cc" + { RETURN(AssertExhaustion); } +#line 6931 "src/prebuilt/wast-lexer-gen.cc" +yy1220: yych = *++cursor_; - if (yych == 't') goto yy1216; + if (yych == 't') goto yy1248; goto yy87; -yy1193: +yy1221: yych = *++cursor_; - if (yych == 'o') goto yy1217; + if (yych == 'o') goto yy1249; goto yy87; -yy1194: +yy1222: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 458 "src/wast-lexer.cc" - { RETURN(ASSERT_UNLINKABLE); } -#line 6330 "src/prebuilt/wast-lexer-gen.cc" -yy1196: +#line 602 "src/wast-lexer.cc" + { RETURN(AssertUnlinkable); } +#line 6947 "src/prebuilt/wast-lexer-gen.cc" +yy1224: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 417 "src/wast-lexer.cc" - { OPCODE(F32ConvertSI32); RETURN(CONVERT); } -#line 6338 "src/prebuilt/wast-lexer-gen.cc" -yy1198: +#line 561 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, F32ConvertSI32); } +#line 6955 "src/prebuilt/wast-lexer-gen.cc" +yy1226: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 419 "src/wast-lexer.cc" - { OPCODE(F32ConvertSI64); RETURN(CONVERT); } -#line 6346 "src/prebuilt/wast-lexer-gen.cc" -yy1200: +#line 563 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, F32ConvertSI64); } +#line 6963 "src/prebuilt/wast-lexer-gen.cc" +yy1228: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 421 "src/wast-lexer.cc" - { OPCODE(F32ConvertUI32); RETURN(CONVERT); } -#line 6354 "src/prebuilt/wast-lexer-gen.cc" -yy1202: +#line 565 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, F32ConvertUI32); } +#line 6971 "src/prebuilt/wast-lexer-gen.cc" +yy1230: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 423 "src/wast-lexer.cc" - { OPCODE(F32ConvertUI64); RETURN(CONVERT); } -#line 6362 "src/prebuilt/wast-lexer-gen.cc" -yy1204: +#line 567 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, F32ConvertUI64); } +#line 6979 "src/prebuilt/wast-lexer-gen.cc" +yy1232: yych = *++cursor_; - if (yych == '3') goto yy1218; + if (yych == '3') goto yy1250; goto yy87; -yy1205: +yy1233: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 418 "src/wast-lexer.cc" - { OPCODE(F64ConvertSI32); RETURN(CONVERT); } -#line 6374 "src/prebuilt/wast-lexer-gen.cc" -yy1207: +#line 562 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, F64ConvertSI32); } +#line 6991 "src/prebuilt/wast-lexer-gen.cc" +yy1235: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 420 "src/wast-lexer.cc" - { OPCODE(F64ConvertSI64); RETURN(CONVERT); } -#line 6382 "src/prebuilt/wast-lexer-gen.cc" -yy1209: +#line 564 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, F64ConvertSI64); } +#line 6999 "src/prebuilt/wast-lexer-gen.cc" +yy1237: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 422 "src/wast-lexer.cc" - { OPCODE(F64ConvertUI32); RETURN(CONVERT); } -#line 6390 "src/prebuilt/wast-lexer-gen.cc" -yy1211: +#line 566 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, F64ConvertUI32); } +#line 7007 "src/prebuilt/wast-lexer-gen.cc" +yy1239: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 424 "src/wast-lexer.cc" - { OPCODE(F64ConvertUI64); RETURN(CONVERT); } -#line 6398 "src/prebuilt/wast-lexer-gen.cc" -yy1213: +#line 568 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, F64ConvertUI64); } +#line 7015 "src/prebuilt/wast-lexer-gen.cc" +yy1241: yych = *++cursor_; - if (yych == '6') goto yy1219; + if (yych == '6') goto yy1251; goto yy87; -yy1214: +yy1242: yych = *++cursor_; - if (yych == '3') goto yy1220; + if (yych == '3') goto yy1252; goto yy87; -yy1215: +yy1243: yych = *++cursor_; - if (yych == '6') goto yy1221; + if (yych == '3') goto yy1253; + if (yych == '6') goto yy1254; goto yy87; -yy1216: +yy1244: yych = *++cursor_; - if (yych == 'h') goto yy1222; + if (yych == '3') goto yy1255; + if (yych == '6') goto yy1256; goto yy87; -yy1217: +yy1245: yych = *++cursor_; - if (yych == 'n') goto yy1223; + if (yych == '6') goto yy1257; goto yy87; -yy1218: +yy1246: yych = *++cursor_; - if (yych == '2') goto yy1224; + if (yych == '3') goto yy1258; + if (yych == '6') goto yy1259; goto yy87; -yy1219: +yy1247: yych = *++cursor_; - if (yych == '4') goto yy1226; + if (yych == '3') goto yy1260; + if (yych == '6') goto yy1261; goto yy87; -yy1220: +yy1248: yych = *++cursor_; - if (yych == '2') goto yy1228; + if (yych == 'h') goto yy1262; goto yy87; -yy1221: +yy1249: yych = *++cursor_; - if (yych == '4') goto yy1230; + if (yych == 'n') goto yy1263; goto yy87; -yy1222: +yy1250: yych = *++cursor_; - if (yych == 'm') goto yy1232; + if (yych == '2') goto yy1264; goto yy87; -yy1223: +yy1251: yych = *++cursor_; - if (yych == 'i') goto yy1233; + if (yych == '4') goto yy1266; goto yy87; -yy1224: +yy1252: + yych = *++cursor_; + if (yych == '2') goto yy1268; + goto yy87; +yy1253: + yych = *++cursor_; + if (yych == '2') goto yy1270; + goto yy87; +yy1254: + yych = *++cursor_; + if (yych == '4') goto yy1272; + goto yy87; +yy1255: + yych = *++cursor_; + if (yych == '2') goto yy1274; + goto yy87; +yy1256: + yych = *++cursor_; + if (yych == '4') goto yy1276; + goto yy87; +yy1257: + yych = *++cursor_; + if (yych == '4') goto yy1278; + goto yy87; +yy1258: + yych = *++cursor_; + if (yych == '2') goto yy1280; + goto yy87; +yy1259: + yych = *++cursor_; + if (yych == '4') goto yy1282; + goto yy87; +yy1260: + yych = *++cursor_; + if (yych == '2') goto yy1284; + goto yy87; +yy1261: + yych = *++cursor_; + if (yych == '4') goto yy1286; + goto yy87; +yy1262: + yych = *++cursor_; + if (yych == 'm') goto yy1288; + goto yy87; +yy1263: + yych = *++cursor_; + if (yych == 'i') goto yy1289; + goto yy87; +yy1264: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 427 "src/wast-lexer.cc" - { OPCODE(F32ReinterpretI32); RETURN(CONVERT); } -#line 6450 "src/prebuilt/wast-lexer-gen.cc" -yy1226: +#line 571 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, F32ReinterpretI32); } +#line 7119 "src/prebuilt/wast-lexer-gen.cc" +yy1266: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 429 "src/wast-lexer.cc" - { OPCODE(F64ReinterpretI64); RETURN(CONVERT); } -#line 6458 "src/prebuilt/wast-lexer-gen.cc" -yy1228: +#line 573 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, F64ReinterpretI64); } +#line 7127 "src/prebuilt/wast-lexer-gen.cc" +yy1268: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 428 "src/wast-lexer.cc" - { OPCODE(I32ReinterpretF32); RETURN(CONVERT); } -#line 6466 "src/prebuilt/wast-lexer-gen.cc" -yy1230: +#line 572 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I32ReinterpretF32); } +#line 7135 "src/prebuilt/wast-lexer-gen.cc" +yy1270: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 430 "src/wast-lexer.cc" - { OPCODE(I64ReinterpretF64); RETURN(CONVERT); } -#line 6474 "src/prebuilt/wast-lexer-gen.cc" -yy1232: +#line 553 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I32TruncSSatF32); } +#line 7143 "src/prebuilt/wast-lexer-gen.cc" +yy1272: + ++cursor_; + if (yybm[0+(yych = *cursor_)] & 8) { + goto yy86; + } +#line 555 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I32TruncSSatF64); } +#line 7151 "src/prebuilt/wast-lexer-gen.cc" +yy1274: + ++cursor_; + if (yybm[0+(yych = *cursor_)] & 8) { + goto yy86; + } +#line 557 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I32TruncUSatF32); } +#line 7159 "src/prebuilt/wast-lexer-gen.cc" +yy1276: + ++cursor_; + if (yybm[0+(yych = *cursor_)] & 8) { + goto yy86; + } +#line 559 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I32TruncUSatF64); } +#line 7167 "src/prebuilt/wast-lexer-gen.cc" +yy1278: + ++cursor_; + if (yybm[0+(yych = *cursor_)] & 8) { + goto yy86; + } +#line 574 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I64ReinterpretF64); } +#line 7175 "src/prebuilt/wast-lexer-gen.cc" +yy1280: + ++cursor_; + if (yybm[0+(yych = *cursor_)] & 8) { + goto yy86; + } +#line 554 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I64TruncSSatF32); } +#line 7183 "src/prebuilt/wast-lexer-gen.cc" +yy1282: + ++cursor_; + if (yybm[0+(yych = *cursor_)] & 8) { + goto yy86; + } +#line 556 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I64TruncSSatF64); } +#line 7191 "src/prebuilt/wast-lexer-gen.cc" +yy1284: + ++cursor_; + if (yybm[0+(yych = *cursor_)] & 8) { + goto yy86; + } +#line 558 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I64TruncUSatF32); } +#line 7199 "src/prebuilt/wast-lexer-gen.cc" +yy1286: + ++cursor_; + if (yybm[0+(yych = *cursor_)] & 8) { + goto yy86; + } +#line 560 "src/wast-lexer.cc" + { RETURN_OPCODE(Convert, I64TruncUSatF64); } +#line 7207 "src/prebuilt/wast-lexer-gen.cc" +yy1288: yych = *++cursor_; - if (yych == 'e') goto yy1234; + if (yych == 'e') goto yy1290; goto yy87; -yy1233: +yy1289: yych = *++cursor_; - if (yych == 'c') goto yy1235; + if (yych == 'c') goto yy1291; goto yy87; -yy1234: +yy1290: yych = *++cursor_; - if (yych == 't') goto yy1236; + if (yych == 't') goto yy1292; goto yy87; -yy1235: +yy1291: yych = *++cursor_; - if (yych == 'a') goto yy1237; + if (yych == 'a') goto yy1293; goto yy87; -yy1236: +yy1292: yych = *++cursor_; - if (yych == 'i') goto yy1238; + if (yych == 'i') goto yy1294; goto yy87; -yy1237: +yy1293: yych = *++cursor_; - if (yych == 'l') goto yy1239; + if (yych == 'l') goto yy1295; goto yy87; -yy1238: +yy1294: yych = *++cursor_; - if (yych == 'c') goto yy1240; + if (yych == 'c') goto yy1296; goto yy87; -yy1239: +yy1295: yych = *++cursor_; - if (yych == '_') goto yy1241; + if (yych == '_') goto yy1297; goto yy87; -yy1240: +yy1296: yych = *++cursor_; - if (yych == '_') goto yy1242; + if (yych == '_') goto yy1298; goto yy87; -yy1241: +yy1297: yych = *++cursor_; - if (yych == 'n') goto yy1243; + if (yych == 'n') goto yy1299; goto yy87; -yy1242: +yy1298: yych = *++cursor_; - if (yych == 'n') goto yy1244; + if (yych == 'n') goto yy1300; goto yy87; -yy1243: +yy1299: yych = *++cursor_; - if (yych == 'a') goto yy1245; + if (yych == 'a') goto yy1301; goto yy87; -yy1244: +yy1300: yych = *++cursor_; - if (yych == 'a') goto yy1246; + if (yych == 'a') goto yy1302; goto yy87; -yy1245: +yy1301: yych = *++cursor_; - if (yych == 'n') goto yy1247; + if (yych == 'n') goto yy1303; goto yy87; -yy1246: +yy1302: yych = *++cursor_; - if (yych == 'n') goto yy1249; + if (yych == 'n') goto yy1305; goto yy87; -yy1247: +yy1303: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 460 "src/wast-lexer.cc" - { - RETURN(ASSERT_RETURN_CANONICAL_NAN); } -#line 6543 "src/prebuilt/wast-lexer-gen.cc" -yy1249: +#line 604 "src/wast-lexer.cc" + { RETURN(AssertReturnCanonicalNan); } +#line 7275 "src/prebuilt/wast-lexer-gen.cc" +yy1305: ++cursor_; if (yybm[0+(yych = *cursor_)] & 8) { goto yy86; } -#line 462 "src/wast-lexer.cc" - { - RETURN(ASSERT_RETURN_ARITHMETIC_NAN); } -#line 6552 "src/prebuilt/wast-lexer-gen.cc" +#line 605 "src/wast-lexer.cc" + { RETURN(AssertReturnArithmeticNan); } +#line 7283 "src/prebuilt/wast-lexer-gen.cc" } } -#line 491 "src/wast-lexer.cc" +#line 631 "src/wast-lexer.cc" } } diff --git a/lib/wabt/src/prebuilt/wast-parser-gen.cc b/lib/wabt/src/prebuilt/wast-parser-gen.cc deleted file mode 100644 index 0744dd331de..00000000000 --- a/lib/wabt/src/prebuilt/wast-parser-gen.cc +++ /dev/null @@ -1,5149 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.0.2. */ - -/* Bison implementation for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output. */ -#define YYBISON 1 - -/* Bison version. */ -#define YYBISON_VERSION "3.0.2" - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 1 - -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - -/* Substitute the type names. */ -#define YYSTYPE WABT_WAST_PARSER_STYPE -#define YYLTYPE WABT_WAST_PARSER_LTYPE -/* Substitute the variable and function names. */ -#define yyparse wabt_wast_parser_parse -#define yylex wabt_wast_parser_lex -#define yyerror wabt_wast_parser_error -#define yydebug wabt_wast_parser_debug -#define yynerrs wabt_wast_parser_nerrs - - -/* Copy the first part of user declarations. */ -#line 17 "src/wast-parser.y" /* yacc.c:339 */ - -#include -#include -#include -#include -#include -#include - -#include "binary-error-handler.h" -#include "binary-reader.h" -#include "binary-reader-ir.h" -#include "literal.h" -#include "wast-parser.h" -#include "wast-parser-lexer-shared.h" - -#define YYDEBUG 1 - -#define RELOCATE_STACK(type, array, stack_base, old_size, new_size) \ - do { \ - type* new_stack = new type[new_size](); \ - std::move((stack_base), (stack_base) + (old_size), (new_stack)); \ - if ((stack_base) != (array)) { \ - delete[](stack_base); \ - } else { \ - for (size_t i = 0; i < (old_size); ++i) { \ - (stack_base)[i].~type(); \ - } \ - } \ - /* Cache the pointer in the parser struct to be deleted later. */ \ - parser->array = (stack_base) = new_stack; \ - } while (0) - -#define yyoverflow(message, ss, ss_size, vs, vs_size, ls, ls_size, new_size) \ - do { \ - size_t old_size = *(new_size); \ - *(new_size) *= 2; \ - RELOCATE_STACK(yytype_int16, yyssa, *(ss), old_size, *(new_size)); \ - RELOCATE_STACK(YYSTYPE, yyvsa, *(vs), old_size, *(new_size)); \ - RELOCATE_STACK(YYLTYPE, yylsa, *(ls), old_size, *(new_size)); \ - } while (0) - -#define DUPTEXT(dst, src) \ - (dst).start = wabt_strndup((src).start, (src).length); \ - (dst).length = (src).length - -#define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (N) { \ - (Current).filename = YYRHSLOC(Rhs, 1).filename; \ - (Current).line = YYRHSLOC(Rhs, 1).line; \ - (Current).first_column = YYRHSLOC(Rhs, 1).first_column; \ - if (YYRHSLOC(Rhs, N).line == (Current).line) \ - (Current).last_column = YYRHSLOC(Rhs, N).last_column; \ - else \ - (Current).last_column = YYRHSLOC(Rhs, 1).last_column; \ - } else { \ - (Current).filename = nullptr; \ - (Current).line = YYRHSLOC(Rhs, 0).line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC(Rhs, 0).last_column; \ - } \ - while (0) - -#define CHECK_END_LABEL(loc, begin_label, end_label) \ - do { \ - if (!string_slice_is_empty(&(end_label))) { \ - if (string_slice_is_empty(&(begin_label))) { \ - wast_parser_error(&loc, lexer, parser, \ - "unexpected label \"" PRIstringslice "\"", \ - WABT_PRINTF_STRING_SLICE_ARG(end_label)); \ - } else if (!string_slices_are_equal(&(begin_label), &(end_label))) { \ - wast_parser_error(&loc, lexer, parser, \ - "mismatching label \"" PRIstringslice \ - "\" != \"" PRIstringslice "\"", \ - WABT_PRINTF_STRING_SLICE_ARG(begin_label), \ - WABT_PRINTF_STRING_SLICE_ARG(end_label)); \ - } \ - destroy_string_slice(&(end_label)); \ - } \ - } while (0) - -#define CHECK_ALLOW_EXCEPTIONS(loc, opcode_name) \ - do { \ - if (!parser->options->allow_exceptions) { \ - wast_parser_error(loc, lexer, parser, "opcode not allowed: %s", \ - opcode_name); \ - } \ - } while (0) - -#define YYMALLOC(size) new char [size] -#define YYFREE(p) delete [] (p) - -#define USE_NATURAL_ALIGNMENT (~0) - -namespace wabt { - -static bool is_power_of_two(uint32_t x) { - return x && ((x & (x - 1)) == 0); -} - -static ExprList join_exprs1(Location* loc, Expr* expr1); -static ExprList join_exprs2(Location* loc, ExprList* expr1, Expr* expr2); -static ExprList join_expr_lists(ExprList* expr1, ExprList* expr2); - -static Result parse_const(Type type, - LiteralType literal_type, - const char* s, - const char* end, - Const* out); -static void dup_text_list(TextList* text_list, - char** out_data, - size_t* out_size); - -static void reverse_bindings(TypeVector*, BindingHash*); - -static bool is_empty_signature(const FuncSignature* sig); - -static void check_import_ordering(Location* loc, - WastLexer* lexer, - WastParser* parser, - Module* module, - ModuleField* first); -static void append_module_fields(Module*, ModuleField*); - -class BinaryErrorHandlerModule : public BinaryErrorHandler { - public: - BinaryErrorHandlerModule(Location* loc, WastLexer* lexer, WastParser* parser); - bool OnError(Offset offset, const std::string& error) override; - - private: - Location* loc_; - WastLexer* lexer_; - WastParser* parser_; -}; - -#define wabt_wast_parser_lex(...) lexer->GetToken(__VA_ARGS__, parser) -#define wabt_wast_parser_error wast_parser_error - - -#line 214 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:339 */ - -# ifndef YY_NULLPTR -# if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULLPTR nullptr -# else -# define YY_NULLPTR 0 -# endif -# endif - -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 1 -#endif - -/* In a future release of Bison, this section will be replaced - by #include "wast-parser-gen.hh". */ -#ifndef YY_WABT_WAST_PARSER_SRC_PREBUILT_WAST_PARSER_GEN_HH_INCLUDED -# define YY_WABT_WAST_PARSER_SRC_PREBUILT_WAST_PARSER_GEN_HH_INCLUDED -/* Debug traces. */ -#ifndef WABT_WAST_PARSER_DEBUG -# if defined YYDEBUG -#if YYDEBUG -# define WABT_WAST_PARSER_DEBUG 1 -# else -# define WABT_WAST_PARSER_DEBUG 0 -# endif -# else /* ! defined YYDEBUG */ -# define WABT_WAST_PARSER_DEBUG 0 -# endif /* ! defined YYDEBUG */ -#endif /* ! defined WABT_WAST_PARSER_DEBUG */ -#if WABT_WAST_PARSER_DEBUG -extern int wabt_wast_parser_debug; -#endif - -/* Token type. */ -#ifndef WABT_WAST_PARSER_TOKENTYPE -# define WABT_WAST_PARSER_TOKENTYPE - enum wabt_wast_parser_tokentype - { - WABT_TOKEN_TYPE_EOF = 0, - WABT_TOKEN_TYPE_LPAR = 258, - WABT_TOKEN_TYPE_RPAR = 259, - WABT_TOKEN_TYPE_NAT = 260, - WABT_TOKEN_TYPE_INT = 261, - WABT_TOKEN_TYPE_FLOAT = 262, - WABT_TOKEN_TYPE_TEXT = 263, - WABT_TOKEN_TYPE_VAR = 264, - WABT_TOKEN_TYPE_VALUE_TYPE = 265, - WABT_TOKEN_TYPE_ANYFUNC = 266, - WABT_TOKEN_TYPE_MUT = 267, - WABT_TOKEN_TYPE_NOP = 268, - WABT_TOKEN_TYPE_DROP = 269, - WABT_TOKEN_TYPE_BLOCK = 270, - WABT_TOKEN_TYPE_END = 271, - WABT_TOKEN_TYPE_IF = 272, - WABT_TOKEN_TYPE_THEN = 273, - WABT_TOKEN_TYPE_ELSE = 274, - WABT_TOKEN_TYPE_LOOP = 275, - WABT_TOKEN_TYPE_BR = 276, - WABT_TOKEN_TYPE_BR_IF = 277, - WABT_TOKEN_TYPE_BR_TABLE = 278, - WABT_TOKEN_TYPE_TRY = 279, - WABT_TOKEN_TYPE_CATCH = 280, - WABT_TOKEN_TYPE_CATCH_ALL = 281, - WABT_TOKEN_TYPE_THROW = 282, - WABT_TOKEN_TYPE_RETHROW = 283, - WABT_TOKEN_TYPE_CALL = 284, - WABT_TOKEN_TYPE_CALL_INDIRECT = 285, - WABT_TOKEN_TYPE_RETURN = 286, - WABT_TOKEN_TYPE_GET_LOCAL = 287, - WABT_TOKEN_TYPE_SET_LOCAL = 288, - WABT_TOKEN_TYPE_TEE_LOCAL = 289, - WABT_TOKEN_TYPE_GET_GLOBAL = 290, - WABT_TOKEN_TYPE_SET_GLOBAL = 291, - WABT_TOKEN_TYPE_LOAD = 292, - WABT_TOKEN_TYPE_STORE = 293, - WABT_TOKEN_TYPE_OFFSET_EQ_NAT = 294, - WABT_TOKEN_TYPE_ALIGN_EQ_NAT = 295, - WABT_TOKEN_TYPE_CONST = 296, - WABT_TOKEN_TYPE_UNARY = 297, - WABT_TOKEN_TYPE_BINARY = 298, - WABT_TOKEN_TYPE_COMPARE = 299, - WABT_TOKEN_TYPE_CONVERT = 300, - WABT_TOKEN_TYPE_SELECT = 301, - WABT_TOKEN_TYPE_UNREACHABLE = 302, - WABT_TOKEN_TYPE_CURRENT_MEMORY = 303, - WABT_TOKEN_TYPE_GROW_MEMORY = 304, - WABT_TOKEN_TYPE_FUNC = 305, - WABT_TOKEN_TYPE_START = 306, - WABT_TOKEN_TYPE_TYPE = 307, - WABT_TOKEN_TYPE_PARAM = 308, - WABT_TOKEN_TYPE_RESULT = 309, - WABT_TOKEN_TYPE_LOCAL = 310, - WABT_TOKEN_TYPE_GLOBAL = 311, - WABT_TOKEN_TYPE_TABLE = 312, - WABT_TOKEN_TYPE_ELEM = 313, - WABT_TOKEN_TYPE_MEMORY = 314, - WABT_TOKEN_TYPE_DATA = 315, - WABT_TOKEN_TYPE_OFFSET = 316, - WABT_TOKEN_TYPE_IMPORT = 317, - WABT_TOKEN_TYPE_EXPORT = 318, - WABT_TOKEN_TYPE_EXCEPT = 319, - WABT_TOKEN_TYPE_MODULE = 320, - WABT_TOKEN_TYPE_BIN = 321, - WABT_TOKEN_TYPE_QUOTE = 322, - WABT_TOKEN_TYPE_REGISTER = 323, - WABT_TOKEN_TYPE_INVOKE = 324, - WABT_TOKEN_TYPE_GET = 325, - WABT_TOKEN_TYPE_ASSERT_MALFORMED = 326, - WABT_TOKEN_TYPE_ASSERT_INVALID = 327, - WABT_TOKEN_TYPE_ASSERT_UNLINKABLE = 328, - WABT_TOKEN_TYPE_ASSERT_RETURN = 329, - WABT_TOKEN_TYPE_ASSERT_RETURN_CANONICAL_NAN = 330, - WABT_TOKEN_TYPE_ASSERT_RETURN_ARITHMETIC_NAN = 331, - WABT_TOKEN_TYPE_ASSERT_TRAP = 332, - WABT_TOKEN_TYPE_ASSERT_EXHAUSTION = 333, - WABT_TOKEN_TYPE_LOW = 334 - }; -#endif - -/* Value type. */ -#if ! defined WABT_WAST_PARSER_STYPE && ! defined WABT_WAST_PARSER_STYPE_IS_DECLARED -typedef ::wabt::Token WABT_WAST_PARSER_STYPE; -# define WABT_WAST_PARSER_STYPE_IS_TRIVIAL 1 -# define WABT_WAST_PARSER_STYPE_IS_DECLARED 1 -#endif - -/* Location type. */ -#if ! defined WABT_WAST_PARSER_LTYPE && ! defined WABT_WAST_PARSER_LTYPE_IS_DECLARED -typedef struct WABT_WAST_PARSER_LTYPE WABT_WAST_PARSER_LTYPE; -struct WABT_WAST_PARSER_LTYPE -{ - int first_line; - int first_column; - int last_line; - int last_column; -}; -# define WABT_WAST_PARSER_LTYPE_IS_DECLARED 1 -# define WABT_WAST_PARSER_LTYPE_IS_TRIVIAL 1 -#endif - - - -int wabt_wast_parser_parse (::wabt::WastLexer* lexer, ::wabt::WastParser* parser); - -#endif /* !YY_WABT_WAST_PARSER_SRC_PREBUILT_WAST_PARSER_GEN_HH_INCLUDED */ - -/* Copy the second part of user declarations. */ - -#line 367 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:358 */ - -#ifdef short -# undef short -#endif - -#ifdef YYTYPE_UINT8 -typedef YYTYPE_UINT8 yytype_uint8; -#else -typedef unsigned char yytype_uint8; -#endif - -#ifdef YYTYPE_INT8 -typedef YYTYPE_INT8 yytype_int8; -#else -typedef signed char yytype_int8; -#endif - -#ifdef YYTYPE_UINT16 -typedef YYTYPE_UINT16 yytype_uint16; -#else -typedef unsigned short int yytype_uint16; -#endif - -#ifdef YYTYPE_INT16 -typedef YYTYPE_INT16 yytype_int16; -#else -typedef short int yytype_int16; -#endif - -#ifndef YYSIZE_T -# ifdef __SIZE_TYPE__ -# define YYSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define YYSIZE_T size_t -# elif ! defined YYSIZE_T -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# else -# define YYSIZE_T unsigned int -# endif -#endif - -#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) - -#ifndef YY_ -# if defined YYENABLE_NLS && YYENABLE_NLS -# if ENABLE_NLS -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_(Msgid) dgettext ("bison-runtime", Msgid) -# endif -# endif -# ifndef YY_ -# define YY_(Msgid) Msgid -# endif -#endif - -#ifndef YY_ATTRIBUTE -# if (defined __GNUC__ \ - && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ - || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C -# define YY_ATTRIBUTE(Spec) __attribute__(Spec) -# else -# define YY_ATTRIBUTE(Spec) /* empty */ -# endif -#endif - -#ifndef YY_ATTRIBUTE_PURE -# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) -#endif - -#ifndef YY_ATTRIBUTE_UNUSED -# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) -#endif - -#if !defined _Noreturn \ - && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) -# if defined _MSC_VER && 1200 <= _MSC_VER -# define _Noreturn __declspec (noreturn) -# else -# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) -# endif -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) -#else -# define YYUSE(E) /* empty */ -#endif - -#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ -/* Suppress an incorrect diagnostic about yylval being uninitialized. */ -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ - _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") -# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ - _Pragma ("GCC diagnostic pop") -#else -# define YY_INITIAL_VALUE(Value) Value -#endif -#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_END -#endif -#ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ -#endif - - -#if ! defined yyoverflow || YYERROR_VERBOSE - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# elif defined __BUILTIN_VA_ARG_INCR -# include /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define YYSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS -# include /* INFRINGES ON USER NAME SPACE */ - /* Use EXIT_SUCCESS as a witness for stdlib.h. */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's 'empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined EXIT_SUCCESS \ - && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if ! defined malloc && ! defined EXIT_SUCCESS -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if ! defined free && ! defined EXIT_SUCCESS -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ - - -#if (! defined yyoverflow \ - && (! defined __cplusplus \ - || (defined WABT_WAST_PARSER_LTYPE_IS_TRIVIAL && WABT_WAST_PARSER_LTYPE_IS_TRIVIAL \ - && defined WABT_WAST_PARSER_STYPE_IS_TRIVIAL && WABT_WAST_PARSER_STYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - yytype_int16 yyss_alloc; - YYSTYPE yyvs_alloc; - YYLTYPE yyls_alloc; -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ - + 2 * YYSTACK_GAP_MAXIMUM) - -# define YYCOPY_NEEDED 1 - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (0) - -#endif - -#if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from SRC to DST. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(Dst, Src, Count) \ - __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) -# else -# define YYCOPY(Dst, Src, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (Dst)[yyi] = (Src)[yyi]; \ - } \ - while (0) -# endif -# endif -#endif /* !YYCOPY_NEEDED */ - -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 52 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 1148 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 80 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 87 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 216 -/* YYNSTATES -- Number of states. */ -#define YYNSTATES 477 - -/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned - by yylex, with out-of-bounds checking. */ -#define YYUNDEFTOK 2 -#define YYMAXUTOK 334 - -#define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) - -/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, without out-of-bounds checking. */ -static const yytype_uint8 yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79 -}; - -#if WABT_WAST_PARSER_DEBUG - /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ -static const yytype_uint16 yyrline[] = -{ - 0, 262, 262, 268, 278, 279, 283, 301, 302, 308, - 311, 316, 324, 328, 329, 334, 343, 344, 352, 358, - 364, 369, 376, 382, 393, 397, 401, 408, 412, 420, - 421, 428, 429, 432, 436, 437, 441, 442, 458, 459, - 474, 475, 476, 480, 483, 486, 489, 492, 496, 500, - 504, 507, 511, 515, 519, 523, 527, 531, 535, 538, - 541, 554, 557, 560, 563, 566, 569, 572, 576, 583, - 588, 593, 598, 604, 612, 615, 620, 627, 632, 639, - 640, 646, 650, 653, 658, 663, 669, 677, 683, 687, - 691, 704, 707, 713, 721, 724, 728, 732, 736, 740, - 744, 751, 756, 762, 768, 769, 777, 778, 786, 791, - 799, 808, 822, 830, 835, 846, 854, 865, 872, 873, - 879, 889, 890, 899, 906, 907, 913, 923, 924, 933, - 940, 944, 949, 961, 964, 968, 978, 992, 1006, 1012, - 1020, 1028, 1048, 1058, 1072, 1086, 1091, 1099, 1107, 1131, - 1145, 1151, 1159, 1172, 1181, 1189, 1195, 1201, 1207, 1215, - 1225, 1233, 1239, 1245, 1251, 1257, 1265, 1274, 1284, 1291, - 1302, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, - 1320, 1321, 1325, 1326, 1330, 1335, 1343, 1363, 1370, 1373, - 1381, 1399, 1407, 1418, 1429, 1440, 1446, 1452, 1458, 1464, - 1470, 1475, 1480, 1486, 1495, 1500, 1501, 1506, 1516, 1520, - 1527, 1539, 1540, 1547, 1550, 1610, 1622 -}; -#endif - -#if WABT_WAST_PARSER_DEBUG || YYERROR_VERBOSE || 1 -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char *const yytname[] = -{ - "\"EOF\"", "error", "$undefined", "\"(\"", "\")\"", "NAT", "INT", - "FLOAT", "TEXT", "VAR", "VALUE_TYPE", "ANYFUNC", "MUT", "NOP", "DROP", - "BLOCK", "END", "IF", "THEN", "ELSE", "LOOP", "BR", "BR_IF", "BR_TABLE", - "TRY", "CATCH", "CATCH_ALL", "THROW", "RETHROW", "CALL", "CALL_INDIRECT", - "RETURN", "GET_LOCAL", "SET_LOCAL", "TEE_LOCAL", "GET_GLOBAL", - "SET_GLOBAL", "LOAD", "STORE", "OFFSET_EQ_NAT", "ALIGN_EQ_NAT", "CONST", - "UNARY", "BINARY", "COMPARE", "CONVERT", "SELECT", "UNREACHABLE", - "CURRENT_MEMORY", "GROW_MEMORY", "FUNC", "START", "TYPE", "PARAM", - "RESULT", "LOCAL", "GLOBAL", "TABLE", "ELEM", "MEMORY", "DATA", "OFFSET", - "IMPORT", "EXPORT", "EXCEPT", "MODULE", "BIN", "QUOTE", "REGISTER", - "INVOKE", "GET", "ASSERT_MALFORMED", "ASSERT_INVALID", - "ASSERT_UNLINKABLE", "ASSERT_RETURN", "ASSERT_RETURN_CANONICAL_NAN", - "ASSERT_RETURN_ARITHMETIC_NAN", "ASSERT_TRAP", "ASSERT_EXHAUSTION", - "LOW", "$accept", "text_list", "text_list_opt", "quoted_text", - "value_type_list", "elem_type", "global_type", "func_type", "func_sig", - "func_sig_result", "table_sig", "memory_sig", "limits", "type_use", - "nat", "literal", "var", "var_list", "bind_var_opt", "bind_var", - "labeling_opt", "offset_opt", "align_opt", "instr", "plain_instr", - "block_instr", "block_sig", "block", "catch_instr", "catch_instr_list", - "expr", "expr1", "try_", "try_instr_list", "catch_list", "if_block", - "if_", "rethrow_check", "throw_check", "try_check", "instr_list", - "expr_list", "const_expr", "exception", "exception_field", "func", - "func_fields", "func_fields_import", "func_fields_import1", - "func_fields_import_result", "func_fields_body", "func_fields_body1", - "func_result_body", "func_body", "func_body1", "offset", "elem", "table", - "table_fields", "data", "memory", "memory_fields", "global", - "global_fields", "import_desc", "import", "inline_import", "export_desc", - "export", "inline_export", "type_def", "start", "module_field", - "module_fields_opt", "module_fields", "module", "inline_module", - "script_var_opt", "script_module", "action", "assertion", "cmd", - "cmd_list", "const", "const_list", "script", "script_start", YY_NULLPTR -}; -#endif - -# ifdef YYPRINT -/* YYTOKNUM[NUM] -- (External) token number corresponding to the - (internal) symbol number NUM (which must be that of a token). */ -static const yytype_uint16 yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 328, 329, 330, 331, 332, 333, 334 -}; -# endif - -#define YYPACT_NINF -378 - -#define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-378))) - -#define YYTABLE_NINF -31 - -#define yytable_value_is_error(Yytable_value) \ - 0 - - /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -static const yytype_int16 yypact[] = -{ - 25, 1070, -378, -378, -378, -378, -378, -378, -378, -378, - -378, -378, -378, -378, -378, 36, -378, -378, -378, -378, - -378, -378, 52, -378, 84, 85, 134, 145, 85, 85, - 146, 85, 146, 107, 107, 85, 85, 107, 138, 138, - 162, 162, 162, 179, 179, 179, 211, 179, 148, -378, - 222, -378, -378, -378, 462, -378, -378, -378, -378, 224, - 185, 258, 242, 51, 118, 413, 261, -378, -378, 67, - 261, 271, -378, 107, 279, -378, 14, 138, -378, 107, - 107, 223, 107, 107, 107, 104, -378, 307, 311, 127, - 107, 107, 107, 369, -378, -378, 85, 85, 85, 134, - 134, -378, -378, -378, -378, 134, 134, -378, 134, 134, - 134, 134, 134, 281, 281, 151, -378, -378, -378, -378, - -378, -378, -378, -378, 499, 536, -378, -378, -378, 134, - 134, 85, -378, 317, -378, -378, -378, -378, -378, 319, - 462, -378, 320, -378, 322, 33, -378, 536, 323, 106, - 51, 131, -378, 325, -378, 324, 326, 329, 326, 118, - 85, 85, 85, 536, 327, 330, 85, -378, 126, 121, - -378, -378, 333, 326, 67, 271, -378, 331, 334, 338, - 159, 343, 27, 271, 271, 345, 36, 347, -378, 349, - 350, 351, 352, 264, -378, -378, 353, 354, 356, 134, - 85, -378, 85, 107, 107, -378, 573, 573, 573, -378, - -378, 134, -378, -378, -378, -378, -378, -378, -378, -378, - 328, 328, -378, -378, -378, -378, 758, -378, 1069, -378, - -378, -378, 573, -378, 200, 361, -378, -378, -378, -378, - 248, 370, -378, -378, 355, -378, -378, -378, 363, -378, - -378, 315, -378, -378, -378, -378, -378, 573, 373, 573, - 381, 327, -378, -378, 610, 232, -378, -378, 271, -378, - -378, -378, 384, -378, -378, 170, -378, 390, 134, 134, - 134, 134, 134, -378, -378, -378, 213, 240, -378, -378, - 282, -378, -378, -378, -378, 336, -378, -378, -378, -378, - -378, 391, 157, 398, 165, 176, 399, 107, 415, 957, - 573, 404, -378, 247, 409, 241, -378, -378, -378, 288, - 85, -378, 263, -378, 85, -378, -378, 425, -378, -378, - 919, 373, 435, -378, -378, -378, -378, -378, 881, 647, - 610, -378, -378, -378, -378, 448, -378, 85, 85, 85, - 85, -378, 449, 459, 460, 463, 464, -378, -378, -378, - 151, -378, 499, 465, 684, 721, 466, 467, -378, -378, - -378, 85, 85, 85, 85, 134, 536, 288, 423, 181, - 456, 191, 209, 468, 221, -378, 238, 536, -378, 1032, - 327, 469, 995, -378, -378, -378, 477, 106, 326, 326, - -378, -378, -378, -378, -378, 483, -378, 499, 801, -378, - 844, -378, 721, -378, 228, -378, -378, 536, -378, 536, - -378, -378, 85, 361, 484, 478, 320, 497, 512, -378, - 513, 536, -378, 515, 219, 520, 521, 534, 548, 550, - -378, -378, -378, -378, 539, -378, -378, -378, 361, 418, - -378, -378, 320, 507, -378, 559, 571, 288, -378, -378, - -378, -378, -378, -378, 85, -378, -378, 570, 588, -378, - 536, 579, 595, 536, -378, 608, -378 -}; - - /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE does not specify something else to do. Zero - means the default is an error. */ -static const yytype_uint8 yydefact[] = -{ - 213, 0, 110, 181, 175, 176, 173, 177, 174, 172, - 179, 180, 171, 178, 184, 187, 206, 215, 186, 204, - 205, 208, 214, 216, 0, 31, 0, 0, 31, 31, - 0, 31, 0, 0, 0, 31, 31, 0, 188, 188, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 185, - 0, 209, 1, 33, 104, 32, 23, 28, 27, 0, - 0, 0, 0, 0, 0, 0, 0, 134, 29, 0, - 0, 4, 6, 0, 0, 7, 182, 188, 189, 0, - 0, 0, 0, 0, 0, 0, 211, 0, 0, 0, - 0, 0, 0, 0, 44, 45, 34, 34, 34, 0, - 0, 29, 103, 102, 101, 0, 0, 50, 0, 0, - 0, 0, 0, 36, 36, 0, 61, 62, 63, 64, - 46, 43, 65, 66, 104, 104, 40, 41, 42, 0, - 0, 34, 130, 0, 113, 123, 124, 127, 129, 121, - 104, 170, 16, 168, 0, 0, 10, 104, 0, 0, - 0, 0, 9, 0, 138, 0, 20, 0, 0, 0, - 34, 34, 34, 104, 106, 0, 34, 29, 0, 0, - 145, 19, 0, 0, 0, 4, 2, 5, 0, 0, - 0, 0, 0, 0, 0, 0, 183, 0, 211, 0, - 0, 0, 0, 0, 200, 201, 0, 0, 0, 0, - 7, 7, 7, 0, 0, 35, 104, 104, 104, 47, - 48, 0, 51, 52, 53, 54, 55, 56, 57, 37, - 38, 38, 24, 25, 26, 60, 0, 112, 0, 105, - 68, 67, 104, 111, 0, 121, 115, 117, 118, 116, - 0, 0, 13, 169, 0, 108, 150, 149, 0, 151, - 152, 0, 18, 21, 137, 139, 140, 104, 0, 104, - 0, 106, 82, 81, 0, 0, 136, 30, 4, 144, - 146, 147, 0, 3, 143, 0, 158, 0, 0, 0, - 0, 0, 0, 166, 109, 8, 0, 0, 190, 207, - 0, 194, 195, 196, 197, 0, 199, 212, 198, 202, - 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 104, 0, 76, 0, 0, 49, 39, 58, 59, 0, - 7, 7, 0, 114, 7, 7, 12, 0, 29, 83, - 0, 0, 0, 85, 94, 84, 133, 107, 0, 0, - 0, 86, 88, 89, 135, 0, 142, 31, 31, 31, - 31, 159, 0, 0, 0, 0, 0, 191, 192, 193, - 0, 22, 104, 0, 104, 104, 0, 0, 167, 7, - 75, 34, 34, 34, 34, 0, 104, 79, 0, 0, - 0, 0, 0, 0, 0, 11, 0, 104, 93, 0, - 100, 0, 0, 90, 87, 148, 16, 0, 0, 0, - 161, 164, 162, 163, 165, 0, 125, 104, 0, 128, - 0, 131, 104, 160, 0, 69, 71, 104, 70, 104, - 78, 80, 34, 121, 0, 121, 16, 0, 16, 141, - 0, 104, 99, 91, 0, 0, 0, 0, 0, 0, - 210, 126, 132, 74, 0, 77, 73, 119, 121, 0, - 122, 14, 16, 0, 17, 96, 0, 0, 92, 154, - 153, 157, 155, 156, 34, 120, 15, 0, 98, 72, - 104, 0, 0, 104, 95, 0, 97 -}; - - /* YYPGOTO[NTERM-NUM]. */ -static const yytype_int16 yypgoto[] = -{ - -378, 135, -150, 80, -180, 437, -136, 564, -328, 201, - -147, -159, -63, -131, -54, 268, -23, -89, 31, 22, - -97, 522, 414, -212, -60, -378, -228, -184, -284, 272, - -28, -378, 332, 364, 230, 335, -378, -378, -378, -49, - -107, 412, 502, 523, -378, -378, 546, 474, -377, 275, - 586, -333, 359, -378, -322, 76, -378, -378, 578, -378, - -378, 565, -378, 590, -378, -378, -37, -378, -378, 28, - -378, -378, 4, -378, 670, -378, -378, 2, 92, 262, - -378, 725, -378, -378, 572, -378, -378 -}; - - /* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int16 yydefgoto[] = -{ - -1, 177, 178, 73, 182, 153, 147, 61, 241, 242, - 154, 170, 155, 124, 58, 225, 267, 168, 54, 205, - 206, 220, 317, 125, 126, 127, 310, 311, 391, 378, - 128, 165, 341, 342, 343, 333, 334, 129, 130, 131, - 132, 262, 246, 2, 3, 4, 133, 236, 237, 238, - 134, 135, 136, 137, 138, 68, 5, 6, 157, 7, - 8, 172, 9, 148, 277, 10, 139, 181, 11, 140, - 12, 13, 14, 185, 15, 16, 17, 79, 18, 19, - 20, 21, 22, 297, 193, 23, 24 -}; - - /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule whose - number is the opposite. If YYTABLE_NINF, syntax error. */ -static const yytype_int16 yytable[] = -{ - 207, 208, 67, 59, 67, 164, 171, 66, 235, 70, - 156, 255, 211, 249, 270, 156, 166, 48, 229, 49, - 302, 304, 305, 313, 314, 272, 149, 158, 1, 406, - 331, 284, 173, 164, 232, 377, 340, 285, 67, 48, - 245, 80, 67, 411, 166, 244, 447, 55, 319, 62, - 55, 55, 339, 55, 145, 50, 245, 55, 55, 63, - 64, 146, 69, 257, 258, 259, 75, 76, 435, 264, - 169, 465, 56, 329, 441, 335, 209, 210, 265, 187, - 183, 184, 212, 213, 52, 214, 215, 216, 217, 218, - 442, 150, 159, 377, 53, 203, 204, 174, 451, 312, - 312, 312, 253, 331, 156, 156, 230, 231, 71, 248, - 171, 171, 340, 149, 74, 72, 146, 77, 345, 156, - 156, 151, 158, 56, 466, 312, 370, 339, 339, 152, - 266, 56, 82, 83, 84, 57, 261, 173, 90, 56, - 379, 381, 167, 57, 382, 384, 175, 78, 60, 65, - 312, 56, 312, 179, 53, 57, 222, 223, 224, 188, - 189, 362, 190, 191, 192, 81, 164, 285, 164, 364, - 196, 197, 198, 38, 39, 285, 301, 166, 150, 166, - 365, 268, 85, 203, 204, 423, 285, 159, 315, 414, - 49, 285, 36, 203, 204, 425, 38, 39, 25, 26, - 27, 285, 174, 312, 28, 29, 30, 31, 32, 278, - 33, 34, 35, 426, 89, 279, 280, 357, 281, 285, - 347, 273, 303, 282, 306, 428, 348, 349, 141, 350, - 332, 285, 443, 261, 35, 142, 344, 56, 285, 386, - 439, 57, 429, 56, 358, 60, -30, 57, 273, 164, - -30, 438, 199, 320, 321, 352, 353, 354, 355, 356, - 166, 437, 143, 372, 65, 436, 373, 295, 296, 420, - 164, 199, 324, 325, 415, 416, 417, 418, 164, 176, - 430, 166, 180, 307, 308, 295, 359, 36, 36, 166, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 324, 325, 332, 390, 86, 87, 88, 91, 92, - 444, 194, 445, 375, 376, 195, 320, 321, 286, 287, - 219, 233, 234, 240, 456, 446, 243, 247, 251, 164, - 228, 56, 164, 254, 263, 152, 171, 269, 274, 273, - 166, 275, 380, 166, 156, 156, 383, 283, 164, 288, - 164, 289, 419, 291, 292, 293, 294, 298, 299, 166, - 300, 166, 432, 472, 322, 327, 475, 469, 316, 55, - 55, 55, 55, 328, 326, 244, 330, 360, 396, 397, - 398, 399, 94, 95, 160, 336, 161, 367, 346, 162, - 99, 100, 101, 102, 351, 361, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 363, 366, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 368, - 371, 199, 200, 201, 202, 374, 94, 95, 160, 385, - 161, 203, 204, 162, 99, 100, 101, 102, 389, 422, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 395, 400, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 401, 402, 93, 424, 403, 404, 407, - 412, 413, 321, 433, 163, 94, 95, 96, 427, 97, - 434, 449, 98, 99, 100, 101, 102, 440, 448, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 452, 226, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 94, 95, 96, 453, 97, 455, 457, 98, - 99, 100, 101, 102, 459, 460, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 461, 228, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 94, - 95, 96, 462, 97, 463, 464, 98, 99, 100, 101, - 102, 325, 467, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 468, 309, 115, 116, 117, - 118, 119, 120, 121, 122, 123, 94, 95, 96, 470, - 97, 471, 252, 98, 99, 100, 101, 102, 473, 474, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 476, 338, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 94, 95, 96, 144, 97, 405, 454, - 98, 99, 100, 101, 102, 318, 221, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 421, - 392, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 94, 95, 96, 458, 97, 260, 388, 98, 99, 100, - 101, 102, 394, 337, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 239, 408, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 94, 95, 96, - 450, 97, 276, 393, 98, 99, 100, 101, 102, 323, - 227, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 409, 410, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 94, 95, 96, 256, 97, 271, - 250, 98, 99, 100, 101, 102, 186, 51, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 290, 0, 115, 116, 117, 118, 119, 120, 121, 122, - 123, 94, 95, 160, 0, 161, 0, 0, 162, 99, - 100, 101, 102, 0, 0, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 0, 0, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 0, 0, - 0, 200, 201, 202, 94, 95, 160, 0, 161, 0, - 0, 162, 99, 100, 101, 102, 0, 0, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 0, 0, 115, 116, 117, 118, 119, 120, 121, 122, - 123, 0, 0, 0, 0, 201, 202, 94, 95, 160, - 0, 161, 0, 0, 162, 99, 100, 101, 102, 0, - 0, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 0, 0, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 94, 95, 160, 0, 161, 202, - 0, 162, 99, 100, 101, 102, 375, 376, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 0, 0, 115, 116, 117, 118, 119, 120, 121, 122, - 123, 0, 94, 95, 160, 369, 161, 387, 0, 162, - 99, 100, 101, 102, 0, 0, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 0, 0, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 0, - 94, 95, 160, 369, 161, 0, 0, 162, 99, 100, - 101, 102, 0, 0, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 0, 0, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 0, 94, 95, - 160, 369, 161, 0, 0, 162, 99, 100, 101, 102, - 375, 376, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 0, 0, 115, 116, 117, 118, - 119, 120, 121, 122, 123, 94, 95, 160, 0, 161, - 431, 0, 162, 99, 100, 101, 102, 0, 0, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 0, 0, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 94, 95, 160, 0, 161, 0, 0, 162, - 99, 100, 101, 102, 0, 0, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 0, 0, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 0, - 25, 26, 27, 0, 0, 0, 28, 29, 30, 31, - 32, 0, 33, 34, 35, 36, 0, 0, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47 -}; - -static const yytype_int16 yycheck[] = -{ - 97, 98, 30, 26, 32, 65, 69, 30, 139, 32, - 64, 158, 101, 149, 173, 69, 65, 3, 125, 15, - 200, 201, 202, 207, 208, 175, 63, 64, 3, 362, - 258, 4, 69, 93, 131, 319, 264, 10, 66, 3, - 147, 39, 70, 365, 93, 12, 423, 25, 232, 27, - 28, 29, 264, 31, 3, 3, 163, 35, 36, 28, - 29, 10, 31, 160, 161, 162, 35, 36, 396, 166, - 3, 448, 5, 257, 407, 259, 99, 100, 167, 77, - 66, 67, 105, 106, 0, 108, 109, 110, 111, 112, - 412, 63, 64, 377, 9, 62, 63, 69, 426, 206, - 207, 208, 156, 331, 158, 159, 129, 130, 32, 3, - 173, 174, 340, 150, 34, 8, 10, 37, 268, 173, - 174, 3, 159, 5, 452, 232, 310, 339, 340, 11, - 4, 5, 40, 41, 42, 9, 164, 174, 46, 5, - 320, 321, 66, 9, 324, 325, 70, 9, 3, 3, - 257, 5, 259, 73, 9, 9, 5, 6, 7, 79, - 80, 4, 82, 83, 84, 3, 226, 10, 228, 4, - 90, 91, 92, 69, 70, 10, 199, 226, 150, 228, - 4, 60, 3, 62, 63, 4, 10, 159, 211, 369, - 186, 10, 65, 62, 63, 4, 69, 70, 50, 51, - 52, 10, 174, 310, 56, 57, 58, 59, 60, 50, - 62, 63, 64, 4, 3, 56, 57, 4, 59, 10, - 50, 8, 200, 64, 202, 4, 56, 57, 4, 59, - 258, 10, 4, 261, 64, 50, 4, 5, 10, 328, - 399, 9, 4, 5, 4, 3, 5, 9, 8, 309, - 9, 398, 52, 53, 54, 278, 279, 280, 281, 282, - 309, 397, 4, 16, 3, 396, 19, 3, 4, 376, - 330, 52, 53, 54, 371, 372, 373, 374, 338, 8, - 387, 330, 3, 203, 204, 3, 4, 65, 65, 338, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 78, 53, 54, 331, 332, 43, 44, 45, 46, 47, - 417, 4, 419, 25, 26, 4, 53, 54, 183, 184, - 39, 4, 3, 3, 431, 422, 4, 4, 3, 389, - 3, 5, 392, 4, 4, 11, 399, 4, 4, 8, - 389, 3, 320, 392, 398, 399, 324, 4, 408, 4, - 410, 4, 375, 4, 4, 4, 4, 4, 4, 408, - 4, 410, 390, 470, 3, 10, 473, 464, 40, 347, - 348, 349, 350, 58, 4, 12, 3, 41, 347, 348, - 349, 350, 13, 14, 15, 4, 17, 307, 4, 20, - 21, 22, 23, 24, 4, 4, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 10, 10, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 4, - 16, 52, 53, 54, 55, 16, 13, 14, 15, 4, - 17, 62, 63, 20, 21, 22, 23, 24, 3, 16, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 4, 4, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 4, 4, 3, 10, 4, 4, 4, - 4, 4, 54, 4, 61, 13, 14, 15, 10, 17, - 3, 3, 20, 21, 22, 23, 24, 4, 4, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 4, 3, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 13, 14, 15, 3, 17, 4, 3, 20, - 21, 22, 23, 24, 4, 4, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 4, 3, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 13, - 14, 15, 4, 17, 4, 16, 20, 21, 22, 23, - 24, 54, 3, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 4, 3, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 13, 14, 15, 19, - 17, 3, 155, 20, 21, 22, 23, 24, 19, 4, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 4, 3, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 13, 14, 15, 62, 17, 360, 428, - 20, 21, 22, 23, 24, 221, 114, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 377, - 3, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 13, 14, 15, 433, 17, 163, 331, 20, 21, 22, - 23, 24, 340, 261, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 140, 3, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 13, 14, 15, - 425, 17, 179, 339, 20, 21, 22, 23, 24, 235, - 124, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 364, 3, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 13, 14, 15, 159, 17, 174, - 150, 20, 21, 22, 23, 24, 76, 22, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 188, -1, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 13, 14, 15, -1, 17, -1, -1, 20, 21, - 22, 23, 24, -1, -1, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, -1, -1, 41, - 42, 43, 44, 45, 46, 47, 48, 49, -1, -1, - -1, 53, 54, 55, 13, 14, 15, -1, 17, -1, - -1, 20, 21, 22, 23, 24, -1, -1, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - -1, -1, 41, 42, 43, 44, 45, 46, 47, 48, - 49, -1, -1, -1, -1, 54, 55, 13, 14, 15, - -1, 17, -1, -1, 20, 21, 22, 23, 24, -1, - -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, -1, -1, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 13, 14, 15, -1, 17, 55, - -1, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - -1, -1, 41, 42, 43, 44, 45, 46, 47, 48, - 49, -1, 13, 14, 15, 54, 17, 18, -1, 20, - 21, 22, 23, 24, -1, -1, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, -1, -1, - 41, 42, 43, 44, 45, 46, 47, 48, 49, -1, - 13, 14, 15, 54, 17, -1, -1, 20, 21, 22, - 23, 24, -1, -1, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, -1, -1, 41, 42, - 43, 44, 45, 46, 47, 48, 49, -1, 13, 14, - 15, 54, 17, -1, -1, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, -1, -1, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 13, 14, 15, -1, 17, - 18, -1, 20, 21, 22, 23, 24, -1, -1, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, -1, -1, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 13, 14, 15, -1, 17, -1, -1, 20, - 21, 22, 23, 24, -1, -1, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, -1, -1, - 41, 42, 43, 44, 45, 46, 47, 48, 49, -1, - 50, 51, 52, -1, -1, -1, 56, 57, 58, 59, - 60, -1, 62, 63, 64, 65, -1, -1, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, 78 -}; - - /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const yytype_uint8 yystos[] = -{ - 0, 3, 123, 124, 125, 136, 137, 139, 140, 142, - 145, 148, 150, 151, 152, 154, 155, 156, 158, 159, - 160, 161, 162, 165, 166, 50, 51, 52, 56, 57, - 58, 59, 60, 62, 63, 64, 65, 68, 69, 70, - 71, 72, 73, 74, 75, 76, 77, 78, 3, 152, - 3, 161, 0, 9, 98, 99, 5, 9, 94, 96, - 3, 87, 99, 98, 98, 3, 96, 110, 135, 98, - 96, 135, 8, 83, 83, 98, 98, 83, 9, 157, - 157, 3, 158, 158, 158, 3, 159, 159, 159, 3, - 158, 159, 159, 3, 13, 14, 15, 17, 20, 21, - 22, 23, 24, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 93, 103, 104, 105, 110, 117, - 118, 119, 120, 126, 130, 131, 132, 133, 134, 146, - 149, 4, 50, 4, 87, 3, 10, 86, 143, 146, - 149, 3, 11, 85, 90, 92, 94, 138, 146, 149, - 15, 17, 20, 61, 104, 111, 119, 135, 97, 3, - 91, 92, 141, 146, 149, 135, 8, 81, 82, 83, - 3, 147, 84, 66, 67, 153, 154, 157, 83, 83, - 83, 83, 83, 164, 4, 4, 83, 83, 83, 52, - 53, 54, 55, 62, 63, 99, 100, 100, 100, 96, - 96, 97, 96, 96, 96, 96, 96, 96, 96, 39, - 101, 101, 5, 6, 7, 95, 3, 130, 3, 120, - 96, 96, 100, 4, 3, 93, 127, 128, 129, 126, - 3, 88, 89, 4, 12, 120, 122, 4, 3, 86, - 143, 3, 85, 94, 4, 90, 138, 100, 100, 100, - 122, 110, 121, 4, 100, 97, 4, 96, 60, 4, - 91, 141, 82, 8, 4, 3, 123, 144, 50, 56, - 57, 59, 64, 4, 4, 10, 81, 81, 4, 4, - 164, 4, 4, 4, 4, 3, 4, 163, 4, 4, - 4, 96, 84, 99, 84, 84, 99, 83, 83, 3, - 106, 107, 120, 107, 107, 96, 40, 102, 102, 107, - 53, 54, 3, 127, 53, 54, 4, 10, 58, 107, - 3, 106, 110, 115, 116, 107, 4, 121, 3, 103, - 106, 112, 113, 114, 4, 82, 4, 50, 56, 57, - 59, 4, 96, 96, 96, 96, 96, 4, 4, 4, - 41, 4, 4, 10, 4, 4, 10, 83, 4, 54, - 107, 16, 16, 19, 16, 25, 26, 108, 109, 84, - 99, 84, 84, 99, 84, 4, 97, 18, 115, 3, - 110, 108, 3, 113, 112, 4, 98, 98, 98, 98, - 4, 4, 4, 4, 4, 95, 131, 4, 3, 132, - 3, 134, 4, 4, 84, 100, 100, 100, 100, 96, - 120, 109, 16, 4, 10, 4, 4, 10, 4, 4, - 120, 18, 110, 4, 3, 88, 93, 86, 90, 91, - 4, 131, 134, 4, 120, 120, 100, 128, 4, 3, - 129, 88, 4, 3, 89, 4, 120, 3, 114, 4, - 4, 4, 4, 4, 16, 128, 88, 3, 4, 100, - 19, 3, 120, 19, 4, 120, 4 -}; - - /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint8 yyr1[] = -{ - 0, 80, 81, 81, 82, 82, 83, 84, 84, 85, - 86, 86, 87, 88, 88, 88, 89, 89, 90, 91, - 92, 92, 93, 94, 95, 95, 95, 96, 96, 97, - 97, 98, 98, 99, 100, 100, 101, 101, 102, 102, - 103, 103, 103, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, - 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, - 105, 105, 105, 105, 106, 107, 107, 108, 108, 109, - 109, 110, 111, 111, 111, 111, 111, 112, 112, 113, - 113, 114, 114, 115, 115, 116, 116, 116, 116, 116, - 116, 117, 118, 119, 120, 120, 121, 121, 122, 123, - 124, 125, 126, 126, 126, 126, 126, 127, 128, 128, - 128, 129, 129, 130, 131, 131, 131, 132, 132, 133, - 134, 134, 134, 135, 135, 136, 136, 137, 138, 138, - 138, 138, 139, 139, 140, 141, 141, 141, 141, 142, - 143, 143, 143, 144, 144, 144, 144, 144, 144, 145, - 146, 147, 147, 147, 147, 147, 148, 149, 150, 150, - 151, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 152, 153, 153, 154, 154, 155, 156, 157, 157, - 158, 158, 158, 159, 159, 160, 160, 160, 160, 160, - 160, 160, 160, 160, 161, 161, 161, 161, 162, 162, - 163, 164, 164, 165, 165, 165, 166 -}; - - /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = -{ - 0, 2, 1, 2, 0, 1, 1, 0, 2, 1, - 1, 4, 4, 1, 5, 6, 0, 5, 2, 1, - 1, 2, 4, 1, 1, 1, 1, 1, 1, 0, - 2, 0, 1, 1, 0, 1, 0, 1, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, - 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, - 2, 1, 1, 1, 1, 1, 1, 2, 2, 5, - 5, 5, 8, 6, 4, 2, 1, 3, 2, 1, - 2, 3, 2, 3, 3, 3, 3, 2, 1, 1, - 2, 3, 4, 2, 1, 8, 4, 9, 5, 3, - 2, 1, 1, 1, 0, 2, 0, 2, 1, 5, - 1, 5, 2, 1, 3, 2, 2, 1, 1, 5, - 6, 0, 5, 1, 1, 5, 6, 1, 5, 1, - 1, 5, 6, 4, 1, 6, 5, 5, 1, 2, - 2, 5, 6, 5, 5, 1, 2, 2, 4, 5, - 2, 2, 2, 5, 5, 5, 5, 5, 1, 6, - 5, 4, 4, 4, 4, 4, 5, 4, 4, 5, - 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 1, 1, 2, 1, 1, 0, 1, - 5, 6, 6, 6, 5, 5, 5, 5, 5, 5, - 4, 4, 5, 5, 1, 1, 1, 5, 1, 2, - 4, 0, 2, 0, 1, 1, 1 -}; - - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab - - -#define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (&yylloc, lexer, parser, YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (0) - -/* Error token number */ -#define YYTERROR 1 -#define YYERRCODE 256 - - -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (N) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (0) -#endif - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) - - -/* Enable debugging if requested. */ -#if WABT_WAST_PARSER_DEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (0) - - -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ - -#ifndef YY_LOCATION_PRINT -# if defined WABT_WAST_PARSER_LTYPE_IS_TRIVIAL && WABT_WAST_PARSER_LTYPE_IS_TRIVIAL - -/* Print *YYLOCP on YYO. Private, do not rely on its existence. */ - -YY_ATTRIBUTE_UNUSED -static unsigned -yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp) -{ - unsigned res = 0; - int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; - if (0 <= yylocp->first_line) - { - res += YYFPRINTF (yyo, "%d", yylocp->first_line); - if (0 <= yylocp->first_column) - res += YYFPRINTF (yyo, ".%d", yylocp->first_column); - } - if (0 <= yylocp->last_line) - { - if (yylocp->first_line < yylocp->last_line) - { - res += YYFPRINTF (yyo, "-%d", yylocp->last_line); - if (0 <= end_col) - res += YYFPRINTF (yyo, ".%d", end_col); - } - else if (0 <= end_col && yylocp->first_column < end_col) - res += YYFPRINTF (yyo, "-%d", end_col); - } - return res; - } - -# define YY_LOCATION_PRINT(File, Loc) \ - yy_location_print_ (File, &(Loc)) - -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif -#endif - - -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Type, Value, Location, lexer, parser); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (0) - - -/*----------------------------------------. -| Print this symbol's value on YYOUTPUT. | -`----------------------------------------*/ - -static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, ::wabt::WastLexer* lexer, ::wabt::WastParser* parser) -{ - FILE *yyo = yyoutput; - YYUSE (yyo); - YYUSE (yylocationp); - YYUSE (lexer); - YYUSE (parser); - if (!yyvaluep) - return; -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# endif - YYUSE (yytype); -} - - -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ - -static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, ::wabt::WastLexer* lexer, ::wabt::WastParser* parser) -{ - YYFPRINTF (yyoutput, "%s %s (", - yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); - - YY_LOCATION_PRINT (yyoutput, *yylocationp); - YYFPRINTF (yyoutput, ": "); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, lexer, parser); - YYFPRINTF (yyoutput, ")"); -} - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -static void -yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) -{ - YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } - YYFPRINTF (stderr, "\n"); -} - -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (0) - - -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ - -static void -yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, ::wabt::WastLexer* lexer, ::wabt::WastParser* parser) -{ - unsigned long int yylno = yyrline[yyrule]; - int yynrhs = yyr2[yyrule]; - int yyi; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) - { - YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, - yystos[yyssp[yyi + 1 - yynrhs]], - &(yyvsp[(yyi + 1) - (yynrhs)]) - , &(yylsp[(yyi + 1) - (yynrhs)]) , lexer, parser); - YYFPRINTF (stderr, "\n"); - } -} - -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyssp, yyvsp, yylsp, Rule, lexer, parser); \ -} while (0) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !WABT_WAST_PARSER_DEBUG */ -# define YYDPRINTF(Args) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !WABT_WAST_PARSER_DEBUG */ - - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - -#if YYERROR_VERBOSE - -# ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -static YYSIZE_T -yystrlen (const char *yystr) -{ - YYSIZE_T yylen; - for (yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; -} -# endif -# endif - -# ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -static char * -yystpcpy (char *yydest, const char *yysrc) -{ - char *yyd = yydest; - const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -# endif - -# ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYSIZE_T -yytnamerr (char *yyres, const char *yystr) -{ - if (*yystr == '"') - { - YYSIZE_T yyn = 0; - char const *yyp = yystr; - - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes: ; - } - - if (! yyres) - return yystrlen (yystr); - - return yystpcpy (yyres, yystr) - yyres; -} -# endif - -/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message - about the unexpected token YYTOKEN for the state stack whose top is - YYSSP. - - Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is - not large enough to hold the message. In that case, also set - *YYMSG_ALLOC to the required number of bytes. Return 2 if the - required number of bytes is too large to store. */ -static int -yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, - yytype_int16 *yyssp, int yytoken) -{ - YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); - YYSIZE_T yysize = yysize0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - /* Internationalized format string. */ - const char *yyformat = YY_NULLPTR; - /* Arguments of yyformat. */ - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - /* Number of reported tokens (one for the "unexpected", one per - "expected"). */ - int yycount = 0; - - /* There are many possibilities here to consider: - - If this state is a consistent state with a default action, then - the only way this function was invoked is if the default action - is an error action. In that case, don't check for expected - tokens because there are none. - - The only way there can be no lookahead present (in yychar) is if - this state is a consistent state with a default action. Thus, - detecting the absence of a lookahead is sufficient to determine - that there is no unexpected or expected token to report. In that - case, just report a simple "syntax error". - - Don't assume there isn't a lookahead just because this state is a - consistent state with a default action. There might have been a - previous inconsistent state, consistent state with a non-default - action, or user semantic action that manipulated yychar. - - Of course, the expected token list depends on states to have - correct lookahead information, and it depends on the parser not - to perform extra reductions after fetching a lookahead from the - scanner and before detecting a syntax error. Thus, state merging - (from LALR or IELR) and default reductions corrupt the expected - token list. However, the list is correct for canonical LR with - one exception: it will still contain any token that will not be - accepted due to an error action in a later state. - */ - if (yytoken != YYEMPTY) - { - int yyn = yypact[*yyssp]; - yyarg[yycount++] = yytname[yytoken]; - if (!yypact_value_is_default (yyn)) - { - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. In other words, skip the first -YYN actions for - this state because they are default actions. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yyx; - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR - && !yytable_value_is_error (yytable[yyx + yyn])) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - break; - } - yyarg[yycount++] = yytname[yyx]; - { - YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } - } - } - } - - switch (yycount) - { -# define YYCASE_(N, S) \ - case N: \ - yyformat = S; \ - break - YYCASE_(0, YY_("syntax error")); - YYCASE_(1, YY_("syntax error, unexpected %s")); - YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); - YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); - YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); - YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); -# undef YYCASE_ - } - - { - YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; - } - - if (*yymsg_alloc < yysize) - { - *yymsg_alloc = 2 * yysize; - if (! (yysize <= *yymsg_alloc - && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) - *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; - return 1; - } - - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - { - char *yyp = *yymsg; - int yyi = 0; - while ((*yyp = *yyformat) != '\0') - if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyformat += 2; - } - else - { - yyp++; - yyformat++; - } - } - return 0; -} -#endif /* YYERROR_VERBOSE */ - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, ::wabt::WastLexer* lexer, ::wabt::WastParser* parser) -{ - YYUSE (yyvaluep); - YYUSE (yylocationp); - YYUSE (lexer); - YYUSE (parser); - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - switch (yytype) - { - case 5: /* NAT */ -#line 226 "src/wast-parser.y" /* yacc.c:1257 */ - {} -#line 1746 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 6: /* INT */ -#line 226 "src/wast-parser.y" /* yacc.c:1257 */ - {} -#line 1752 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 7: /* FLOAT */ -#line 226 "src/wast-parser.y" /* yacc.c:1257 */ - {} -#line 1758 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 8: /* TEXT */ -#line 226 "src/wast-parser.y" /* yacc.c:1257 */ - {} -#line 1764 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 9: /* VAR */ -#line 226 "src/wast-parser.y" /* yacc.c:1257 */ - {} -#line 1770 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 39: /* OFFSET_EQ_NAT */ -#line 226 "src/wast-parser.y" /* yacc.c:1257 */ - {} -#line 1776 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 40: /* ALIGN_EQ_NAT */ -#line 226 "src/wast-parser.y" /* yacc.c:1257 */ - {} -#line 1782 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 81: /* text_list */ -#line 246 "src/wast-parser.y" /* yacc.c:1257 */ - { destroy_text_list(&((*yyvaluep).text_list)); } -#line 1788 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 82: /* text_list_opt */ -#line 246 "src/wast-parser.y" /* yacc.c:1257 */ - { destroy_text_list(&((*yyvaluep).text_list)); } -#line 1794 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 83: /* quoted_text */ -#line 227 "src/wast-parser.y" /* yacc.c:1257 */ - { destroy_string_slice(&((*yyvaluep).text)); } -#line 1800 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 84: /* value_type_list */ -#line 247 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).types); } -#line 1806 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 86: /* global_type */ -#line 240 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).global); } -#line 1812 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 87: /* func_type */ -#line 239 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).func_sig); } -#line 1818 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 88: /* func_sig */ -#line 239 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).func_sig); } -#line 1824 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 89: /* func_sig_result */ -#line 239 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).func_sig); } -#line 1830 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 91: /* memory_sig */ -#line 242 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).memory); } -#line 1836 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 93: /* type_use */ -#line 248 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).var); } -#line 1842 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 95: /* literal */ -#line 228 "src/wast-parser.y" /* yacc.c:1257 */ - { destroy_string_slice(&((*yyvaluep).literal).text); } -#line 1848 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 96: /* var */ -#line 248 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).var); } -#line 1854 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 97: /* var_list */ -#line 249 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).vars); } -#line 1860 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 98: /* bind_var_opt */ -#line 227 "src/wast-parser.y" /* yacc.c:1257 */ - { destroy_string_slice(&((*yyvaluep).text)); } -#line 1866 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 99: /* bind_var */ -#line 227 "src/wast-parser.y" /* yacc.c:1257 */ - { destroy_string_slice(&((*yyvaluep).text)); } -#line 1872 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 100: /* labeling_opt */ -#line 227 "src/wast-parser.y" /* yacc.c:1257 */ - { destroy_string_slice(&((*yyvaluep).text)); } -#line 1878 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 103: /* instr */ -#line 236 "src/wast-parser.y" /* yacc.c:1257 */ - { DestroyExprList(((*yyvaluep).expr_list).first); } -#line 1884 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 104: /* plain_instr */ -#line 235 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).expr); } -#line 1890 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 105: /* block_instr */ -#line 235 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).expr); } -#line 1896 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 106: /* block_sig */ -#line 247 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).types); } -#line 1902 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 107: /* block */ -#line 230 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).block); } -#line 1908 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 108: /* catch_instr */ -#line 236 "src/wast-parser.y" /* yacc.c:1257 */ - { DestroyExprList(((*yyvaluep).expr_list).first); } -#line 1914 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 109: /* catch_instr_list */ -#line 236 "src/wast-parser.y" /* yacc.c:1257 */ - { DestroyExprList(((*yyvaluep).expr_list).first); } -#line 1920 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 110: /* expr */ -#line 236 "src/wast-parser.y" /* yacc.c:1257 */ - { DestroyExprList(((*yyvaluep).expr_list).first); } -#line 1926 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 111: /* expr1 */ -#line 236 "src/wast-parser.y" /* yacc.c:1257 */ - { DestroyExprList(((*yyvaluep).expr_list).first); } -#line 1932 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 112: /* try_ */ -#line 235 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).expr); } -#line 1938 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 113: /* try_instr_list */ -#line 235 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).expr); } -#line 1944 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 114: /* catch_list */ -#line 236 "src/wast-parser.y" /* yacc.c:1257 */ - { DestroyExprList(((*yyvaluep).expr_list).first); } -#line 1950 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 115: /* if_block */ -#line 236 "src/wast-parser.y" /* yacc.c:1257 */ - { DestroyExprList(((*yyvaluep).expr_list).first); } -#line 1956 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 116: /* if_ */ -#line 236 "src/wast-parser.y" /* yacc.c:1257 */ - { DestroyExprList(((*yyvaluep).expr_list).first); } -#line 1962 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 120: /* instr_list */ -#line 236 "src/wast-parser.y" /* yacc.c:1257 */ - { DestroyExprList(((*yyvaluep).expr_list).first); } -#line 1968 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 121: /* expr_list */ -#line 236 "src/wast-parser.y" /* yacc.c:1257 */ - { DestroyExprList(((*yyvaluep).expr_list).first); } -#line 1974 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 122: /* const_expr */ -#line 236 "src/wast-parser.y" /* yacc.c:1257 */ - { DestroyExprList(((*yyvaluep).expr_list).first); } -#line 1980 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 125: /* func */ -#line 237 "src/wast-parser.y" /* yacc.c:1257 */ - { destroy_module_field_list(&((*yyvaluep).module_fields)); } -#line 1986 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 126: /* func_fields */ -#line 237 "src/wast-parser.y" /* yacc.c:1257 */ - { destroy_module_field_list(&((*yyvaluep).module_fields)); } -#line 1992 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 127: /* func_fields_import */ -#line 238 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).func); } -#line 1998 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 128: /* func_fields_import1 */ -#line 238 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).func); } -#line 2004 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 129: /* func_fields_import_result */ -#line 238 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).func); } -#line 2010 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 130: /* func_fields_body */ -#line 238 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).func); } -#line 2016 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 131: /* func_fields_body1 */ -#line 238 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).func); } -#line 2022 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 132: /* func_result_body */ -#line 238 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).func); } -#line 2028 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 133: /* func_body */ -#line 238 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).func); } -#line 2034 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 134: /* func_body1 */ -#line 238 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).func); } -#line 2040 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 135: /* offset */ -#line 236 "src/wast-parser.y" /* yacc.c:1257 */ - { DestroyExprList(((*yyvaluep).expr_list).first); } -#line 2046 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 137: /* table */ -#line 237 "src/wast-parser.y" /* yacc.c:1257 */ - { destroy_module_field_list(&((*yyvaluep).module_fields)); } -#line 2052 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 138: /* table_fields */ -#line 237 "src/wast-parser.y" /* yacc.c:1257 */ - { destroy_module_field_list(&((*yyvaluep).module_fields)); } -#line 2058 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 140: /* memory */ -#line 237 "src/wast-parser.y" /* yacc.c:1257 */ - { destroy_module_field_list(&((*yyvaluep).module_fields)); } -#line 2064 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 141: /* memory_fields */ -#line 237 "src/wast-parser.y" /* yacc.c:1257 */ - { destroy_module_field_list(&((*yyvaluep).module_fields)); } -#line 2070 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 142: /* global */ -#line 237 "src/wast-parser.y" /* yacc.c:1257 */ - { destroy_module_field_list(&((*yyvaluep).module_fields)); } -#line 2076 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 143: /* global_fields */ -#line 237 "src/wast-parser.y" /* yacc.c:1257 */ - { destroy_module_field_list(&((*yyvaluep).module_fields)); } -#line 2082 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 144: /* import_desc */ -#line 241 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).import); } -#line 2088 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 146: /* inline_import */ -#line 241 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).import); } -#line 2094 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 147: /* export_desc */ -#line 234 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).export_); } -#line 2100 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 149: /* inline_export */ -#line 234 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).export_); } -#line 2106 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 152: /* module_field */ -#line 237 "src/wast-parser.y" /* yacc.c:1257 */ - { destroy_module_field_list(&((*yyvaluep).module_fields)); } -#line 2112 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 153: /* module_fields_opt */ -#line 243 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).module); } -#line 2118 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 154: /* module_fields */ -#line 243 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).module); } -#line 2124 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 155: /* module */ -#line 243 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).module); } -#line 2130 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 156: /* inline_module */ -#line 243 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).module); } -#line 2136 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 157: /* script_var_opt */ -#line 248 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).var); } -#line 2142 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 158: /* script_module */ -#line 244 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).script_module); } -#line 2148 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 159: /* action */ -#line 229 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).action); } -#line 2154 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 160: /* assertion */ -#line 231 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).command); } -#line 2160 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 161: /* cmd */ -#line 231 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).command); } -#line 2166 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 162: /* cmd_list */ -#line 232 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).commands); } -#line 2172 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 164: /* const_list */ -#line 233 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).consts); } -#line 2178 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - case 165: /* script */ -#line 245 "src/wast-parser.y" /* yacc.c:1257 */ - { delete ((*yyvaluep).script); } -#line 2184 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1257 */ - break; - - - default: - break; - } - YY_IGNORE_MAYBE_UNINITIALIZED_END -} - - - - -/*----------. -| yyparse. | -`----------*/ - -int -yyparse (::wabt::WastLexer* lexer, ::wabt::WastParser* parser) -{ -/* The lookahead symbol. */ -int yychar; - - -/* The semantic value of the lookahead symbol. */ -/* Default value used for initialization, for pacifying older GCCs - or non-GCC compilers. */ -YY_INITIAL_VALUE (static YYSTYPE yyval_default;) -YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); - -/* Location data for the lookahead symbol. */ -static YYLTYPE yyloc_default -# if defined WABT_WAST_PARSER_LTYPE_IS_TRIVIAL && WABT_WAST_PARSER_LTYPE_IS_TRIVIAL - = { 1, 1, 1, 1 } -# endif -; -YYLTYPE yylloc = yyloc_default; - - /* Number of syntax errors so far. */ - int yynerrs; - - int yystate; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - 'yyss': related to states. - 'yyvs': related to semantic values. - 'yyls': related to locations. - - Refer to the stacks through separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss; - yytype_int16 *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; - - /* The location stack. */ - YYLTYPE yylsa[YYINITDEPTH]; - YYLTYPE *yyls; - YYLTYPE *yylsp; - - /* The locations where the error started and ended. */ - YYLTYPE yyerror_range[3]; - - YYSIZE_T yystacksize; - - int yyn; - int yyresult; - /* Lookahead token as an internal (translated) token number. */ - int yytoken = 0; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - YYLTYPE yyloc; - -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif - -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; - - yyssp = yyss = yyssa; - yyvsp = yyvs = yyvsa; - yylsp = yyls = yylsa; - yystacksize = YYINITDEPTH; - - YYDPRINTF ((stderr, "Starting parse\n")); - - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ - yylsp[0] = yylloc; - goto yysetstate; - -/*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | -`------------------------------------------------------------*/ - yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; - - yysetstate: - *yyssp = yystate; - - if (yyss + yystacksize - 1 <= yyssp) - { - /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; - -#ifdef yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; - YYLTYPE *yyls1 = yyls; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yyls1, yysize * sizeof (*yylsp), - &yystacksize); - - yyls = yyls1; - yyss = yyss1; - yyvs = yyvs1; - } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; - - { - yytype_int16 *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); - YYSTACK_RELOCATE (yyls_alloc, yyls); -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif -#endif /* no yyoverflow */ - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - yylsp = yyls + yysize - 1; - - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); - - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; - } - - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - - if (yystate == YYFINAL) - YYACCEPT; - - goto yybackup; - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - - /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yypact_value_is_default (yyn)) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token: ")); - yychar = yylex (&yylval, &yylloc); - } - - if (yychar <= YYEOF) - { - yychar = yytoken = YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else - { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); - } - - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; - yyn = yytable[yyn]; - if (yyn <= 0) - { - if (yytable_value_is_error (yyn)) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - /* Shift the lookahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - - /* Discard the shifted token. */ - yychar = YYEMPTY; - - yystate = yyn; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - *++yylsp = yylloc; - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- Do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - '$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - /* Default location. */ - YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); - YY_REDUCE_PRINT (yyn); - switch (yyn) - { - case 2: -#line 262 "src/wast-parser.y" /* yacc.c:1646 */ - { - TextListNode* node = new TextListNode(); - DUPTEXT(node->text, (yyvsp[0].text)); - node->next = nullptr; - (yyval.text_list).first = (yyval.text_list).last = node; - } -#line 2483 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 3: -#line 268 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.text_list) = (yyvsp[-1].text_list); - TextListNode* node = new TextListNode(); - DUPTEXT(node->text, (yyvsp[0].text)); - node->next = nullptr; - (yyval.text_list).last->next = node; - (yyval.text_list).last = node; - } -#line 2496 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 4: -#line 278 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.text_list).first = (yyval.text_list).last = nullptr; } -#line 2502 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 6: -#line 283 "src/wast-parser.y" /* yacc.c:1646 */ - { - TextListNode node; - node.text = (yyvsp[0].text); - node.next = nullptr; - TextList text_list; - text_list.first = &node; - text_list.last = &node; - char* data; - size_t size; - dup_text_list(&text_list, &data, &size); - (yyval.text).start = data; - (yyval.text).length = size; - } -#line 2520 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 7: -#line 301 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.types) = new TypeVector(); } -#line 2526 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 8: -#line 302 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.types) = (yyvsp[-1].types); - (yyval.types)->push_back((yyvsp[0].type)); - } -#line 2535 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 9: -#line 308 "src/wast-parser.y" /* yacc.c:1646 */ - {} -#line 2541 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 10: -#line 311 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.global) = new Global(); - (yyval.global)->type = (yyvsp[0].type); - (yyval.global)->mutable_ = false; - } -#line 2551 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 11: -#line 316 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.global) = new Global(); - (yyval.global)->type = (yyvsp[-1].type); - (yyval.global)->mutable_ = true; - } -#line 2561 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 12: -#line 324 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.func_sig) = (yyvsp[-1].func_sig); } -#line 2567 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 14: -#line 329 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.func_sig) = (yyvsp[0].func_sig); - (yyval.func_sig)->param_types.insert((yyval.func_sig)->param_types.begin(), (yyvsp[-2].types)->begin(), (yyvsp[-2].types)->end()); - delete (yyvsp[-2].types); - } -#line 2577 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 15: -#line 334 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.func_sig) = (yyvsp[0].func_sig); - (yyval.func_sig)->param_types.insert((yyval.func_sig)->param_types.begin(), (yyvsp[-2].type)); - // Ignore bind_var. - destroy_string_slice(&(yyvsp[-3].text)); - } -#line 2588 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 16: -#line 343 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.func_sig) = new FuncSignature(); } -#line 2594 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 17: -#line 344 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.func_sig) = (yyvsp[0].func_sig); - (yyval.func_sig)->result_types.insert((yyval.func_sig)->result_types.begin(), (yyvsp[-2].types)->begin(), (yyvsp[-2].types)->end()); - delete (yyvsp[-2].types); - } -#line 2604 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 18: -#line 352 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.table) = new Table(); - (yyval.table)->elem_limits = (yyvsp[-1].limits); - } -#line 2613 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 19: -#line 358 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.memory) = new Memory(); - (yyval.memory)->page_limits = (yyvsp[0].limits); - } -#line 2622 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 20: -#line 364 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.limits).has_max = false; - (yyval.limits).initial = (yyvsp[0].u64); - (yyval.limits).max = 0; - } -#line 2632 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 21: -#line 369 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.limits).has_max = true; - (yyval.limits).initial = (yyvsp[-1].u64); - (yyval.limits).max = (yyvsp[0].u64); - } -#line 2642 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 22: -#line 376 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.var) = (yyvsp[-1].var); } -#line 2648 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 23: -#line 382 "src/wast-parser.y" /* yacc.c:1646 */ - { - if (WABT_FAILED(parse_uint64((yyvsp[0].literal).text.start, - (yyvsp[0].literal).text.start + (yyvsp[0].literal).text.length, &(yyval.u64)))) { - wast_parser_error(&(yylsp[0]), lexer, parser, - "invalid int " PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG((yyvsp[0].literal).text)); - } - } -#line 2661 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 24: -#line 393 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.literal).type = (yyvsp[0].literal).type; - DUPTEXT((yyval.literal).text, (yyvsp[0].literal).text); - } -#line 2670 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 25: -#line 397 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.literal).type = (yyvsp[0].literal).type; - DUPTEXT((yyval.literal).text, (yyvsp[0].literal).text); - } -#line 2679 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 26: -#line 401 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.literal).type = (yyvsp[0].literal).type; - DUPTEXT((yyval.literal).text, (yyvsp[0].literal).text); - } -#line 2688 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 27: -#line 408 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.var) = new Var((yyvsp[0].u64)); - (yyval.var)->loc = (yylsp[0]); - } -#line 2697 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 28: -#line 412 "src/wast-parser.y" /* yacc.c:1646 */ - { - StringSlice name; - DUPTEXT(name, (yyvsp[0].text)); - (yyval.var) = new Var(name); - (yyval.var)->loc = (yylsp[0]); - } -#line 2708 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 29: -#line 420 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.vars) = new VarVector(); } -#line 2714 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 30: -#line 421 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.vars) = (yyvsp[-1].vars); - (yyval.vars)->emplace_back(std::move(*(yyvsp[0].var))); - delete (yyvsp[0].var); - } -#line 2724 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 31: -#line 428 "src/wast-parser.y" /* yacc.c:1646 */ - { WABT_ZERO_MEMORY((yyval.text)); } -#line 2730 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 33: -#line 432 "src/wast-parser.y" /* yacc.c:1646 */ - { DUPTEXT((yyval.text), (yyvsp[0].text)); } -#line 2736 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 34: -#line 436 "src/wast-parser.y" /* yacc.c:1646 */ - { WABT_ZERO_MEMORY((yyval.text)); } -#line 2742 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 36: -#line 441 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.u64) = 0; } -#line 2748 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 37: -#line 442 "src/wast-parser.y" /* yacc.c:1646 */ - { - uint64_t offset64; - if (WABT_FAILED(parse_int64((yyvsp[0].text).start, (yyvsp[0].text).start + (yyvsp[0].text).length, &offset64, - ParseIntType::SignedAndUnsigned))) { - wast_parser_error(&(yylsp[0]), lexer, parser, - "invalid offset \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG((yyvsp[0].text))); - } - if (offset64 > UINT32_MAX) { - wast_parser_error(&(yylsp[0]), lexer, parser, - "offset must be less than or equal to 0xffffffff"); - } - (yyval.u64) = static_cast(offset64); - } -#line 2767 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 38: -#line 458 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.u32) = USE_NATURAL_ALIGNMENT; } -#line 2773 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 39: -#line 459 "src/wast-parser.y" /* yacc.c:1646 */ - { - if (WABT_FAILED(parse_int32((yyvsp[0].text).start, (yyvsp[0].text).start + (yyvsp[0].text).length, &(yyval.u32), - ParseIntType::UnsignedOnly))) { - wast_parser_error(&(yylsp[0]), lexer, parser, - "invalid alignment \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG((yyvsp[0].text))); - } - - if ((yyval.u32) != WABT_USE_NATURAL_ALIGNMENT && !is_power_of_two((yyval.u32))) { - wast_parser_error(&(yylsp[0]), lexer, parser, "alignment must be power-of-two"); - } - } -#line 2790 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 40: -#line 474 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.expr_list) = join_exprs1(&(yylsp[0]), (yyvsp[0].expr)); } -#line 2796 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 41: -#line 475 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.expr_list) = join_exprs1(&(yylsp[0]), (yyvsp[0].expr)); } -#line 2802 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 43: -#line 480 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateUnreachable(); - } -#line 2810 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 44: -#line 483 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateNop(); - } -#line 2818 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 45: -#line 486 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateDrop(); - } -#line 2826 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 46: -#line 489 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateSelect(); - } -#line 2834 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 47: -#line 492 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateBr(std::move(*(yyvsp[0].var))); - delete (yyvsp[0].var); - } -#line 2843 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 48: -#line 496 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateBrIf(std::move(*(yyvsp[0].var))); - delete (yyvsp[0].var); - } -#line 2852 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 49: -#line 500 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateBrTable((yyvsp[-1].vars), std::move(*(yyvsp[0].var))); - delete (yyvsp[0].var); - } -#line 2861 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 50: -#line 504 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateReturn(); - } -#line 2869 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 51: -#line 507 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateCall(std::move(*(yyvsp[0].var))); - delete (yyvsp[0].var); - } -#line 2878 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 52: -#line 511 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateCallIndirect(std::move(*(yyvsp[0].var))); - delete (yyvsp[0].var); - } -#line 2887 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 53: -#line 515 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateGetLocal(std::move(*(yyvsp[0].var))); - delete (yyvsp[0].var); - } -#line 2896 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 54: -#line 519 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateSetLocal(std::move(*(yyvsp[0].var))); - delete (yyvsp[0].var); - } -#line 2905 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 55: -#line 523 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateTeeLocal(std::move(*(yyvsp[0].var))); - delete (yyvsp[0].var); - } -#line 2914 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 56: -#line 527 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateGetGlobal(std::move(*(yyvsp[0].var))); - delete (yyvsp[0].var); - } -#line 2923 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 57: -#line 531 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateSetGlobal(std::move(*(yyvsp[0].var))); - delete (yyvsp[0].var); - } -#line 2932 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 58: -#line 535 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateLoad((yyvsp[-2].opcode), (yyvsp[0].u32), (yyvsp[-1].u64)); - } -#line 2940 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 59: -#line 538 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateStore((yyvsp[-2].opcode), (yyvsp[0].u32), (yyvsp[-1].u64)); - } -#line 2948 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 60: -#line 541 "src/wast-parser.y" /* yacc.c:1646 */ - { - Const const_; - WABT_ZERO_MEMORY(const_); - const_.loc = (yylsp[-1]); - if (WABT_FAILED(parse_const((yyvsp[-1].type), (yyvsp[0].literal).type, (yyvsp[0].literal).text.start, - (yyvsp[0].literal).text.start + (yyvsp[0].literal).text.length, &const_))) { - wast_parser_error(&(yylsp[0]), lexer, parser, - "invalid literal \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG((yyvsp[0].literal).text)); - } - delete [] (yyvsp[0].literal).text.start; - (yyval.expr) = Expr::CreateConst(const_); - } -#line 2966 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 61: -#line 554 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateUnary((yyvsp[0].opcode)); - } -#line 2974 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 62: -#line 557 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateBinary((yyvsp[0].opcode)); - } -#line 2982 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 63: -#line 560 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateCompare((yyvsp[0].opcode)); - } -#line 2990 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 64: -#line 563 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateConvert((yyvsp[0].opcode)); - } -#line 2998 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 65: -#line 566 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateCurrentMemory(); - } -#line 3006 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 66: -#line 569 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateGrowMemory(); - } -#line 3014 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 67: -#line 572 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateThrow(std::move(*(yyvsp[0].var))); - delete (yyvsp[0].var); - } -#line 3023 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 68: -#line 576 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateRethrow(std::move(*(yyvsp[0].var))); - delete (yyvsp[0].var); - } -#line 3032 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 69: -#line 583 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateBlock((yyvsp[-2].block)); - (yyval.expr)->block->label = (yyvsp[-3].text); - CHECK_END_LABEL((yylsp[0]), (yyval.expr)->block->label, (yyvsp[0].text)); - } -#line 3042 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 70: -#line 588 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateLoop((yyvsp[-2].block)); - (yyval.expr)->loop->label = (yyvsp[-3].text); - CHECK_END_LABEL((yylsp[0]), (yyval.expr)->loop->label, (yyvsp[0].text)); - } -#line 3052 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 71: -#line 593 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateIf((yyvsp[-2].block), nullptr); - (yyval.expr)->if_.true_->label = (yyvsp[-3].text); - CHECK_END_LABEL((yylsp[0]), (yyval.expr)->if_.true_->label, (yyvsp[0].text)); - } -#line 3062 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 72: -#line 598 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = Expr::CreateIf((yyvsp[-5].block), (yyvsp[-2].expr_list).first); - (yyval.expr)->if_.true_->label = (yyvsp[-6].text); - CHECK_END_LABEL((yylsp[-3]), (yyval.expr)->if_.true_->label, (yyvsp[-3].text)); - CHECK_END_LABEL((yylsp[0]), (yyval.expr)->if_.true_->label, (yyvsp[0].text)); - } -#line 3073 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 73: -#line 604 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyvsp[-3].block)->label = (yyvsp[-4].text); - (yyval.expr) = Expr::CreateTry((yyvsp[-3].block), (yyvsp[-2].expr_list).first); - CHECK_END_LABEL((yylsp[0]), (yyvsp[-3].block)->label, (yyvsp[0].text)); - } -#line 3083 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 74: -#line 612 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.types) = (yyvsp[-1].types); } -#line 3089 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 75: -#line 615 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.block) = (yyvsp[0].block); - (yyval.block)->sig.insert((yyval.block)->sig.end(), (yyvsp[-1].types)->begin(), (yyvsp[-1].types)->end()); - delete (yyvsp[-1].types); - } -#line 3099 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 76: -#line 620 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.block) = new Block(); - (yyval.block)->first = (yyvsp[0].expr_list).first; - } -#line 3108 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 77: -#line 627 "src/wast-parser.y" /* yacc.c:1646 */ - { - Expr* expr = Expr::CreateCatch(std::move(*(yyvsp[-1].var)), (yyvsp[0].expr_list).first); - delete (yyvsp[-1].var); - (yyval.expr_list) = join_exprs1(&(yylsp[-2]), expr); - } -#line 3118 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 78: -#line 632 "src/wast-parser.y" /* yacc.c:1646 */ - { - Expr* expr = Expr::CreateCatchAll((yyvsp[0].expr_list).first); - (yyval.expr_list) = join_exprs1(&(yylsp[-1]), expr); - } -#line 3127 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 80: -#line 640 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr_list) = join_expr_lists(&(yyvsp[-1].expr_list), &(yyvsp[0].expr_list)); - } -#line 3135 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 81: -#line 646 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.expr_list) = (yyvsp[-1].expr_list); } -#line 3141 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 82: -#line 650 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr_list) = join_exprs2(&(yylsp[-1]), &(yyvsp[0].expr_list), (yyvsp[-1].expr)); - } -#line 3149 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 83: -#line 653 "src/wast-parser.y" /* yacc.c:1646 */ - { - Expr* expr = Expr::CreateBlock((yyvsp[0].block)); - expr->block->label = (yyvsp[-1].text); - (yyval.expr_list) = join_exprs1(&(yylsp[-2]), expr); - } -#line 3159 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 84: -#line 658 "src/wast-parser.y" /* yacc.c:1646 */ - { - Expr* expr = Expr::CreateLoop((yyvsp[0].block)); - expr->loop->label = (yyvsp[-1].text); - (yyval.expr_list) = join_exprs1(&(yylsp[-2]), expr); - } -#line 3169 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 85: -#line 663 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr_list) = (yyvsp[0].expr_list); - Expr* if_ = (yyvsp[0].expr_list).last; - assert(if_->type == ExprType::If); - if_->if_.true_->label = (yyvsp[-1].text); - } -#line 3180 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 86: -#line 669 "src/wast-parser.y" /* yacc.c:1646 */ - { - Block* block = (yyvsp[0].expr)->try_block.block; - block->label = (yyvsp[-1].text); - (yyval.expr_list) = join_exprs1(&(yylsp[-2]), (yyvsp[0].expr)); - } -#line 3190 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 87: -#line 677 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = (yyvsp[0].expr); - Block* block = (yyval.expr)->try_block.block; - block->sig.insert(block->sig.end(), (yyvsp[-1].types)->begin(), (yyvsp[-1].types)->end()); - delete (yyvsp[-1].types); - } -#line 3201 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 89: -#line 687 "src/wast-parser.y" /* yacc.c:1646 */ - { - Block* block = new Block(); - (yyval.expr) = Expr::CreateTry(block, (yyvsp[0].expr_list).first); - } -#line 3210 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 90: -#line 691 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr) = (yyvsp[0].expr); - Block* block = (yyval.expr)->try_block.block; - if ((yyvsp[-1].expr_list).last) { - (yyvsp[-1].expr_list).last->next = block->first; - } else { - (yyvsp[-1].expr_list).first->next = block->first; - } - block->first = (yyvsp[-1].expr_list).first; - } -#line 3225 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 91: -#line 704 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr_list) = (yyvsp[-1].expr_list); - } -#line 3233 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 92: -#line 707 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr_list) = join_expr_lists(&(yyvsp[-2].expr_list), &(yyvsp[0].expr_list)); - } -#line 3241 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 93: -#line 713 "src/wast-parser.y" /* yacc.c:1646 */ - { - Expr* if_ = (yyvsp[0].expr_list).last; - assert(if_->type == ExprType::If); - (yyval.expr_list) = (yyvsp[0].expr_list); - Block* true_ = if_->if_.true_; - true_->sig.insert(true_->sig.end(), (yyvsp[-1].types)->begin(), (yyvsp[-1].types)->end()); - delete (yyvsp[-1].types); - } -#line 3254 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 95: -#line 724 "src/wast-parser.y" /* yacc.c:1646 */ - { - Expr* expr = Expr::CreateIf(new Block((yyvsp[-5].expr_list).first), (yyvsp[-1].expr_list).first); - (yyval.expr_list) = join_exprs1(&(yylsp[-7]), expr); - } -#line 3263 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 96: -#line 728 "src/wast-parser.y" /* yacc.c:1646 */ - { - Expr* expr = Expr::CreateIf(new Block((yyvsp[-1].expr_list).first), nullptr); - (yyval.expr_list) = join_exprs1(&(yylsp[-3]), expr); - } -#line 3272 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 97: -#line 732 "src/wast-parser.y" /* yacc.c:1646 */ - { - Expr* expr = Expr::CreateIf(new Block((yyvsp[-5].expr_list).first), (yyvsp[-1].expr_list).first); - (yyval.expr_list) = join_exprs2(&(yylsp[-8]), &(yyvsp[-8].expr_list), expr); - } -#line 3281 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 98: -#line 736 "src/wast-parser.y" /* yacc.c:1646 */ - { - Expr* expr = Expr::CreateIf(new Block((yyvsp[-1].expr_list).first), nullptr); - (yyval.expr_list) = join_exprs2(&(yylsp[-4]), &(yyvsp[-4].expr_list), expr); - } -#line 3290 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 99: -#line 740 "src/wast-parser.y" /* yacc.c:1646 */ - { - Expr* expr = Expr::CreateIf(new Block((yyvsp[-1].expr_list).first), (yyvsp[0].expr_list).first); - (yyval.expr_list) = join_exprs2(&(yylsp[-2]), &(yyvsp[-2].expr_list), expr); - } -#line 3299 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 100: -#line 744 "src/wast-parser.y" /* yacc.c:1646 */ - { - Expr* expr = Expr::CreateIf(new Block((yyvsp[0].expr_list).first), nullptr); - (yyval.expr_list) = join_exprs2(&(yylsp[-1]), &(yyvsp[-1].expr_list), expr); - } -#line 3308 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 101: -#line 751 "src/wast-parser.y" /* yacc.c:1646 */ - { - CHECK_ALLOW_EXCEPTIONS(&(yylsp[0]), "rethrow"); - } -#line 3316 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 102: -#line 756 "src/wast-parser.y" /* yacc.c:1646 */ - { - CHECK_ALLOW_EXCEPTIONS(&(yylsp[0]), "throw"); - } -#line 3324 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 103: -#line 762 "src/wast-parser.y" /* yacc.c:1646 */ - { - CHECK_ALLOW_EXCEPTIONS(&(yylsp[0]), "try"); - } -#line 3332 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 104: -#line 768 "src/wast-parser.y" /* yacc.c:1646 */ - { WABT_ZERO_MEMORY((yyval.expr_list)); } -#line 3338 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 105: -#line 769 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr_list).first = (yyvsp[-1].expr_list).first; - (yyvsp[-1].expr_list).last->next = (yyvsp[0].expr_list).first; - (yyval.expr_list).last = (yyvsp[0].expr_list).last ? (yyvsp[0].expr_list).last : (yyvsp[-1].expr_list).last; - (yyval.expr_list).size = (yyvsp[-1].expr_list).size + (yyvsp[0].expr_list).size; - } -#line 3349 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 106: -#line 777 "src/wast-parser.y" /* yacc.c:1646 */ - { WABT_ZERO_MEMORY((yyval.expr_list)); } -#line 3355 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 107: -#line 778 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr_list).first = (yyvsp[-1].expr_list).first; - (yyvsp[-1].expr_list).last->next = (yyvsp[0].expr_list).first; - (yyval.expr_list).last = (yyvsp[0].expr_list).last ? (yyvsp[0].expr_list).last : (yyvsp[-1].expr_list).last; - (yyval.expr_list).size = (yyvsp[-1].expr_list).size + (yyvsp[0].expr_list).size; - } -#line 3366 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 109: -#line 791 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.exception) = new Exception(); - (yyval.exception)->name = (yyvsp[-2].text); - (yyval.exception)->sig = std::move(*(yyvsp[-1].types)); - delete (yyvsp[-1].types); - } -#line 3377 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 110: -#line 799 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.module_field) = new ModuleField(ModuleFieldType::Except); - (yyval.module_field)->loc = (yylsp[0]); - (yyval.module_field)->except = (yyvsp[0].exception); - } -#line 3387 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 111: -#line 808 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.module_fields) = (yyvsp[-1].module_fields); - ModuleField* main = (yyval.module_fields).first; - main->loc = (yylsp[-3]); - if (main->type == ModuleFieldType::Func) { - main->func->name = (yyvsp[-2].text); - } else { - assert(main->type == ModuleFieldType::Import); - main->import->func->name = (yyvsp[-2].text); - } - } -#line 3403 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 112: -#line 822 "src/wast-parser.y" /* yacc.c:1646 */ - { - ModuleField* field = new ModuleField(ModuleFieldType::Func); - field->func = (yyvsp[0].func); - field->func->decl.has_func_type = true; - field->func->decl.type_var = std::move(*(yyvsp[-1].var)); - delete (yyvsp[-1].var); - (yyval.module_fields).first = (yyval.module_fields).last = field; - } -#line 3416 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 113: -#line 830 "src/wast-parser.y" /* yacc.c:1646 */ - { - ModuleField* field = new ModuleField(ModuleFieldType::Func); - field->func = (yyvsp[0].func); - (yyval.module_fields).first = (yyval.module_fields).last = field; - } -#line 3426 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 114: -#line 835 "src/wast-parser.y" /* yacc.c:1646 */ - { - ModuleField* field = new ModuleField(ModuleFieldType::Import); - field->loc = (yylsp[-2]); - field->import = (yyvsp[-2].import); - field->import->kind = ExternalKind::Func; - field->import->func = (yyvsp[0].func); - field->import->func->decl.has_func_type = true; - field->import->func->decl.type_var = std::move(*(yyvsp[-1].var)); - delete (yyvsp[-1].var); - (yyval.module_fields).first = (yyval.module_fields).last = field; - } -#line 3442 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 115: -#line 846 "src/wast-parser.y" /* yacc.c:1646 */ - { - ModuleField* field = new ModuleField(ModuleFieldType::Import); - field->loc = (yylsp[-1]); - field->import = (yyvsp[-1].import); - field->import->kind = ExternalKind::Func; - field->import->func = (yyvsp[0].func); - (yyval.module_fields).first = (yyval.module_fields).last = field; - } -#line 3455 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 116: -#line 854 "src/wast-parser.y" /* yacc.c:1646 */ - { - ModuleField* field = new ModuleField(ModuleFieldType::Export); - field->loc = (yylsp[-1]); - field->export_ = (yyvsp[-1].export_); - field->export_->kind = ExternalKind::Func; - (yyval.module_fields).first = (yyvsp[0].module_fields).first; - (yyval.module_fields).last = (yyvsp[0].module_fields).last->next = field; - } -#line 3468 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 117: -#line 865 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.func) = (yyvsp[0].func); - reverse_bindings(&(yyval.func)->decl.sig.param_types, &(yyval.func)->param_bindings); - } -#line 3477 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 119: -#line 873 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.func) = (yyvsp[0].func); - (yyval.func)->decl.sig.param_types.insert((yyval.func)->decl.sig.param_types.begin(), - (yyvsp[-2].types)->begin(), (yyvsp[-2].types)->end()); - delete (yyvsp[-2].types); - } -#line 3488 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 120: -#line 879 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.func) = (yyvsp[0].func); - (yyval.func)->param_bindings.emplace(string_slice_to_string((yyvsp[-3].text)), - Binding((yylsp[-3]), (yyval.func)->decl.sig.param_types.size())); - destroy_string_slice(&(yyvsp[-3].text)); - (yyval.func)->decl.sig.param_types.insert((yyval.func)->decl.sig.param_types.begin(), (yyvsp[-2].type)); - } -#line 3500 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 121: -#line 889 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.func) = new Func(); } -#line 3506 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 122: -#line 890 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.func) = (yyvsp[0].func); - (yyval.func)->decl.sig.result_types.insert((yyval.func)->decl.sig.result_types.begin(), - (yyvsp[-2].types)->begin(), (yyvsp[-2].types)->end()); - delete (yyvsp[-2].types); - } -#line 3517 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 123: -#line 899 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.func) = (yyvsp[0].func); - reverse_bindings(&(yyval.func)->decl.sig.param_types, &(yyval.func)->param_bindings); - } -#line 3526 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 125: -#line 907 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.func) = (yyvsp[0].func); - (yyval.func)->decl.sig.param_types.insert((yyval.func)->decl.sig.param_types.begin(), - (yyvsp[-2].types)->begin(), (yyvsp[-2].types)->end()); - delete (yyvsp[-2].types); - } -#line 3537 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 126: -#line 913 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.func) = (yyvsp[0].func); - (yyval.func)->param_bindings.emplace(string_slice_to_string((yyvsp[-3].text)), - Binding((yylsp[-3]), (yyval.func)->decl.sig.param_types.size())); - destroy_string_slice(&(yyvsp[-3].text)); - (yyval.func)->decl.sig.param_types.insert((yyval.func)->decl.sig.param_types.begin(), (yyvsp[-2].type)); - } -#line 3549 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 128: -#line 924 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.func) = (yyvsp[0].func); - (yyval.func)->decl.sig.result_types.insert((yyval.func)->decl.sig.result_types.begin(), - (yyvsp[-2].types)->begin(), (yyvsp[-2].types)->end()); - delete (yyvsp[-2].types); - } -#line 3560 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 129: -#line 933 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.func) = (yyvsp[0].func); - reverse_bindings(&(yyval.func)->local_types, &(yyval.func)->local_bindings); - } -#line 3569 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 130: -#line 940 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.func) = new Func(); - (yyval.func)->first_expr = (yyvsp[0].expr_list).first; - } -#line 3578 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 131: -#line 944 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.func) = (yyvsp[0].func); - (yyval.func)->local_types.insert((yyval.func)->local_types.begin(), (yyvsp[-2].types)->begin(), (yyvsp[-2].types)->end()); - delete (yyvsp[-2].types); - } -#line 3588 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 132: -#line 949 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.func) = (yyvsp[0].func); - (yyval.func)->local_bindings.emplace(string_slice_to_string((yyvsp[-3].text)), - Binding((yylsp[-3]), (yyval.func)->local_types.size())); - destroy_string_slice(&(yyvsp[-3].text)); - (yyval.func)->local_types.insert((yyval.func)->local_types.begin(), (yyvsp[-2].type)); - } -#line 3600 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 133: -#line 961 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.expr_list) = (yyvsp[-1].expr_list); - } -#line 3608 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 135: -#line 968 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.module_field) = new ModuleField(ModuleFieldType::ElemSegment); - (yyval.module_field)->loc = (yylsp[-4]); - (yyval.module_field)->elem_segment = new ElemSegment(); - (yyval.module_field)->elem_segment->table_var = std::move(*(yyvsp[-3].var)); - delete (yyvsp[-3].var); - (yyval.module_field)->elem_segment->offset = (yyvsp[-2].expr_list).first; - (yyval.module_field)->elem_segment->vars = std::move(*(yyvsp[-1].vars)); - delete (yyvsp[-1].vars); - } -#line 3623 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 136: -#line 978 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.module_field) = new ModuleField(ModuleFieldType::ElemSegment); - (yyval.module_field)->loc = (yylsp[-3]); - (yyval.module_field)->elem_segment = new ElemSegment(); - (yyval.module_field)->elem_segment->table_var.loc = (yylsp[-3]); - (yyval.module_field)->elem_segment->table_var.type = VarType::Index; - (yyval.module_field)->elem_segment->table_var.index = 0; - (yyval.module_field)->elem_segment->offset = (yyvsp[-2].expr_list).first; - (yyval.module_field)->elem_segment->vars = std::move(*(yyvsp[-1].vars)); - delete (yyvsp[-1].vars); - } -#line 3639 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 137: -#line 992 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.module_fields) = (yyvsp[-1].module_fields); - ModuleField* main = (yyval.module_fields).first; - main->loc = (yylsp[-3]); - if (main->type == ModuleFieldType::Table) { - main->table->name = (yyvsp[-2].text); - } else { - assert(main->type == ModuleFieldType::Import); - main->import->table->name = (yyvsp[-2].text); - } - } -#line 3655 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 138: -#line 1006 "src/wast-parser.y" /* yacc.c:1646 */ - { - ModuleField* field = new ModuleField(ModuleFieldType::Table); - field->loc = (yylsp[0]); - field->table = (yyvsp[0].table); - (yyval.module_fields).first = (yyval.module_fields).last = field; - } -#line 3666 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 139: -#line 1012 "src/wast-parser.y" /* yacc.c:1646 */ - { - ModuleField* field = new ModuleField(ModuleFieldType::Import); - field->loc = (yylsp[-1]); - field->import = (yyvsp[-1].import); - field->import->kind = ExternalKind::Table; - field->import->table = (yyvsp[0].table); - (yyval.module_fields).first = (yyval.module_fields).last = field; - } -#line 3679 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 140: -#line 1020 "src/wast-parser.y" /* yacc.c:1646 */ - { - ModuleField* field = new ModuleField(ModuleFieldType::Export); - field->loc = (yylsp[-1]); - field->export_ = (yyvsp[-1].export_); - field->export_->kind = ExternalKind::Table; - (yyval.module_fields).first = (yyvsp[0].module_fields).first; - (yyval.module_fields).last = (yyvsp[0].module_fields).last->next = field; - } -#line 3692 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 141: -#line 1028 "src/wast-parser.y" /* yacc.c:1646 */ - { - ModuleField* table_field = new ModuleField(ModuleFieldType::Table); - Table* table = table_field->table = new Table(); - table->elem_limits.initial = (yyvsp[-1].vars)->size(); - table->elem_limits.max = (yyvsp[-1].vars)->size(); - table->elem_limits.has_max = true; - ModuleField* elem_field = new ModuleField(ModuleFieldType::ElemSegment); - elem_field->loc = (yylsp[-2]); - ElemSegment* elem_segment = elem_field->elem_segment = new ElemSegment(); - elem_segment->table_var = Var(kInvalidIndex); - elem_segment->offset = Expr::CreateConst(Const(Const::I32(), 0)); - elem_segment->offset->loc = (yylsp[-2]); - elem_segment->vars = std::move(*(yyvsp[-1].vars)); - delete (yyvsp[-1].vars); - (yyval.module_fields).first = table_field; - (yyval.module_fields).last = table_field->next = elem_field; - } -#line 3714 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 142: -#line 1048 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.module_field) = new ModuleField(ModuleFieldType::DataSegment); - (yyval.module_field)->loc = (yylsp[-4]); - (yyval.module_field)->data_segment = new DataSegment(); - (yyval.module_field)->data_segment->memory_var = std::move(*(yyvsp[-3].var)); - delete (yyvsp[-3].var); - (yyval.module_field)->data_segment->offset = (yyvsp[-2].expr_list).first; - dup_text_list(&(yyvsp[-1].text_list), &(yyval.module_field)->data_segment->data, &(yyval.module_field)->data_segment->size); - destroy_text_list(&(yyvsp[-1].text_list)); - } -#line 3729 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 143: -#line 1058 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.module_field) = new ModuleField(ModuleFieldType::DataSegment); - (yyval.module_field)->loc = (yylsp[-3]); - (yyval.module_field)->data_segment = new DataSegment(); - (yyval.module_field)->data_segment->memory_var.loc = (yylsp[-3]); - (yyval.module_field)->data_segment->memory_var.type = VarType::Index; - (yyval.module_field)->data_segment->memory_var.index = 0; - (yyval.module_field)->data_segment->offset = (yyvsp[-2].expr_list).first; - dup_text_list(&(yyvsp[-1].text_list), &(yyval.module_field)->data_segment->data, &(yyval.module_field)->data_segment->size); - destroy_text_list(&(yyvsp[-1].text_list)); - } -#line 3745 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 144: -#line 1072 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.module_fields) = (yyvsp[-1].module_fields); - ModuleField* main = (yyval.module_fields).first; - main->loc = (yylsp[-3]); - if (main->type == ModuleFieldType::Memory) { - main->memory->name = (yyvsp[-2].text); - } else { - assert(main->type == ModuleFieldType::Import); - main->import->memory->name = (yyvsp[-2].text); - } - } -#line 3761 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 145: -#line 1086 "src/wast-parser.y" /* yacc.c:1646 */ - { - ModuleField* field = new ModuleField(ModuleFieldType::Memory); - field->memory = (yyvsp[0].memory); - (yyval.module_fields).first = (yyval.module_fields).last = field; - } -#line 3771 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 146: -#line 1091 "src/wast-parser.y" /* yacc.c:1646 */ - { - ModuleField* field = new ModuleField(ModuleFieldType::Import); - field->loc = (yylsp[-1]); - field->import = (yyvsp[-1].import); - field->import->kind = ExternalKind::Memory; - field->import->memory = (yyvsp[0].memory); - (yyval.module_fields).first = (yyval.module_fields).last = field; - } -#line 3784 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 147: -#line 1099 "src/wast-parser.y" /* yacc.c:1646 */ - { - ModuleField* field = new ModuleField(ModuleFieldType::Export); - field->loc = (yylsp[-1]); - field->export_ = (yyvsp[-1].export_); - field->export_->kind = ExternalKind::Memory; - (yyval.module_fields).first = (yyvsp[0].module_fields).first; - (yyval.module_fields).last = (yyvsp[0].module_fields).last->next = field; - } -#line 3797 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 148: -#line 1107 "src/wast-parser.y" /* yacc.c:1646 */ - { - ModuleField* data_field = new ModuleField(ModuleFieldType::DataSegment); - data_field->loc = (yylsp[-2]); - DataSegment* data_segment = data_field->data_segment = new DataSegment(); - data_segment->memory_var = Var(kInvalidIndex); - data_segment->offset = Expr::CreateConst(Const(Const::I32(), 0)); - data_segment->offset->loc = (yylsp[-2]); - dup_text_list(&(yyvsp[-1].text_list), &data_segment->data, &data_segment->size); - destroy_text_list(&(yyvsp[-1].text_list)); - uint32_t byte_size = WABT_ALIGN_UP_TO_PAGE(data_segment->size); - uint32_t page_size = WABT_BYTES_TO_PAGES(byte_size); - - ModuleField* memory_field = new ModuleField(ModuleFieldType::Memory); - memory_field->loc = (yylsp[-2]); - Memory* memory = memory_field->memory = new Memory(); - memory->page_limits.initial = page_size; - memory->page_limits.max = page_size; - memory->page_limits.has_max = true; - (yyval.module_fields).first = memory_field; - (yyval.module_fields).last = memory_field->next = data_field; - } -#line 3823 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 149: -#line 1131 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.module_fields) = (yyvsp[-1].module_fields); - ModuleField* main = (yyval.module_fields).first; - main->loc = (yylsp[-3]); - if (main->type == ModuleFieldType::Global) { - main->global->name = (yyvsp[-2].text); - } else { - assert(main->type == ModuleFieldType::Import); - main->import->global->name = (yyvsp[-2].text); - } - } -#line 3839 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 150: -#line 1145 "src/wast-parser.y" /* yacc.c:1646 */ - { - ModuleField* field = new ModuleField(ModuleFieldType::Global); - field->global = (yyvsp[-1].global); - field->global->init_expr = (yyvsp[0].expr_list).first; - (yyval.module_fields).first = (yyval.module_fields).last = field; - } -#line 3850 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 151: -#line 1151 "src/wast-parser.y" /* yacc.c:1646 */ - { - ModuleField* field = new ModuleField(ModuleFieldType::Import); - field->loc = (yylsp[-1]); - field->import = (yyvsp[-1].import); - field->import->kind = ExternalKind::Global; - field->import->global = (yyvsp[0].global); - (yyval.module_fields).first = (yyval.module_fields).last = field; - } -#line 3863 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 152: -#line 1159 "src/wast-parser.y" /* yacc.c:1646 */ - { - ModuleField* field = new ModuleField(ModuleFieldType::Export); - field->loc = (yylsp[-1]); - field->export_ = (yyvsp[-1].export_); - field->export_->kind = ExternalKind::Global; - (yyval.module_fields).first = (yyvsp[0].module_fields).first; - (yyval.module_fields).last = (yyvsp[0].module_fields).last->next = field; - } -#line 3876 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 153: -#line 1172 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.import) = new Import(); - (yyval.import)->kind = ExternalKind::Func; - (yyval.import)->func = new Func(); - (yyval.import)->func->name = (yyvsp[-2].text); - (yyval.import)->func->decl.has_func_type = true; - (yyval.import)->func->decl.type_var = std::move(*(yyvsp[-1].var)); - delete (yyvsp[-1].var); - } -#line 3890 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 154: -#line 1181 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.import) = new Import(); - (yyval.import)->kind = ExternalKind::Func; - (yyval.import)->func = new Func(); - (yyval.import)->func->name = (yyvsp[-2].text); - (yyval.import)->func->decl.sig = std::move(*(yyvsp[-1].func_sig)); - delete (yyvsp[-1].func_sig); - } -#line 3903 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 155: -#line 1189 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.import) = new Import(); - (yyval.import)->kind = ExternalKind::Table; - (yyval.import)->table = (yyvsp[-1].table); - (yyval.import)->table->name = (yyvsp[-2].text); - } -#line 3914 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 156: -#line 1195 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.import) = new Import(); - (yyval.import)->kind = ExternalKind::Memory; - (yyval.import)->memory = (yyvsp[-1].memory); - (yyval.import)->memory->name = (yyvsp[-2].text); - } -#line 3925 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 157: -#line 1201 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.import) = new Import(); - (yyval.import)->kind = ExternalKind::Global; - (yyval.import)->global = (yyvsp[-1].global); - (yyval.import)->global->name = (yyvsp[-2].text); - } -#line 3936 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 158: -#line 1207 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.import) = new Import(); - (yyval.import)->kind = ExternalKind::Except; - (yyval.import)->except = (yyvsp[0].exception); - } -#line 3946 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 159: -#line 1215 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.module_field) = new ModuleField(ModuleFieldType::Import); - (yyval.module_field)->loc = (yylsp[-4]); - (yyval.module_field)->import = (yyvsp[-1].import); - (yyval.module_field)->import->module_name = (yyvsp[-3].text); - (yyval.module_field)->import->field_name = (yyvsp[-2].text); - } -#line 3958 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 160: -#line 1225 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.import) = new Import(); - (yyval.import)->module_name = (yyvsp[-2].text); - (yyval.import)->field_name = (yyvsp[-1].text); - } -#line 3968 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 161: -#line 1233 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.export_) = new Export(); - (yyval.export_)->kind = ExternalKind::Func; - (yyval.export_)->var = std::move(*(yyvsp[-1].var)); - delete (yyvsp[-1].var); - } -#line 3979 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 162: -#line 1239 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.export_) = new Export(); - (yyval.export_)->kind = ExternalKind::Table; - (yyval.export_)->var = std::move(*(yyvsp[-1].var)); - delete (yyvsp[-1].var); - } -#line 3990 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 163: -#line 1245 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.export_) = new Export(); - (yyval.export_)->kind = ExternalKind::Memory; - (yyval.export_)->var = std::move(*(yyvsp[-1].var)); - delete (yyvsp[-1].var); - } -#line 4001 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 164: -#line 1251 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.export_) = new Export(); - (yyval.export_)->kind = ExternalKind::Global; - (yyval.export_)->var = std::move(*(yyvsp[-1].var)); - delete (yyvsp[-1].var); - } -#line 4012 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 165: -#line 1257 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.export_) = new Export(); - (yyval.export_)->kind = ExternalKind::Except; - (yyval.export_)->var = std::move(*(yyvsp[-1].var)); - delete (yyvsp[-1].var); - } -#line 4023 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 166: -#line 1265 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.module_field) = new ModuleField(ModuleFieldType::Export); - (yyval.module_field)->loc = (yylsp[-3]); - (yyval.module_field)->export_ = (yyvsp[-1].export_); - (yyval.module_field)->export_->name = (yyvsp[-2].text); - } -#line 4034 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 167: -#line 1274 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.export_) = new Export(); - (yyval.export_)->name = (yyvsp[-1].text); - } -#line 4043 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 168: -#line 1284 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.module_field) = new ModuleField(ModuleFieldType::FuncType); - (yyval.module_field)->loc = (yylsp[-2]); - (yyval.module_field)->func_type = new FuncType(); - (yyval.module_field)->func_type->sig = std::move(*(yyvsp[-1].func_sig)); - delete (yyvsp[-1].func_sig); - } -#line 4055 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 169: -#line 1291 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.module_field) = new ModuleField(ModuleFieldType::FuncType); - (yyval.module_field)->loc = (yylsp[-3]); - (yyval.module_field)->func_type = new FuncType(); - (yyval.module_field)->func_type->name = (yyvsp[-2].text); - (yyval.module_field)->func_type->sig = std::move(*(yyvsp[-1].func_sig)); - delete (yyvsp[-1].func_sig); - } -#line 4068 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 170: -#line 1302 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.module_field) = new ModuleField(ModuleFieldType::Start); - (yyval.module_field)->loc = (yylsp[-2]); - (yyval.module_field)->start = std::move(*(yyvsp[-1].var)); - delete (yyvsp[-1].var); - } -#line 4079 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 171: -#line 1311 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.module_fields).first = (yyval.module_fields).last = (yyvsp[0].module_field); } -#line 4085 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 176: -#line 1316 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.module_fields).first = (yyval.module_fields).last = (yyvsp[0].module_field); } -#line 4091 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 177: -#line 1317 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.module_fields).first = (yyval.module_fields).last = (yyvsp[0].module_field); } -#line 4097 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 178: -#line 1318 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.module_fields).first = (yyval.module_fields).last = (yyvsp[0].module_field); } -#line 4103 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 179: -#line 1319 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.module_fields).first = (yyval.module_fields).last = (yyvsp[0].module_field); } -#line 4109 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 180: -#line 1320 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.module_fields).first = (yyval.module_fields).last = (yyvsp[0].module_field); } -#line 4115 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 181: -#line 1321 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.module_fields).first = (yyval.module_fields).last = (yyvsp[0].module_field); } -#line 4121 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 182: -#line 1325 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.module) = new Module(); } -#line 4127 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 184: -#line 1330 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.module) = new Module(); - check_import_ordering(&(yylsp[0]), lexer, parser, (yyval.module), (yyvsp[0].module_fields).first); - append_module_fields((yyval.module), (yyvsp[0].module_fields).first); - } -#line 4137 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 185: -#line 1335 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.module) = (yyvsp[-1].module); - check_import_ordering(&(yylsp[0]), lexer, parser, (yyval.module), (yyvsp[0].module_fields).first); - append_module_fields((yyval.module), (yyvsp[0].module_fields).first); - } -#line 4147 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 186: -#line 1343 "src/wast-parser.y" /* yacc.c:1646 */ - { - if ((yyvsp[0].script_module)->type == ScriptModule::Type::Text) { - (yyval.module) = (yyvsp[0].script_module)->text; - (yyvsp[0].script_module)->text = nullptr; - } else { - assert((yyvsp[0].script_module)->type == ScriptModule::Type::Binary); - (yyval.module) = new Module(); - ReadBinaryOptions options = WABT_READ_BINARY_OPTIONS_DEFAULT; - BinaryErrorHandlerModule error_handler(&(yyvsp[0].script_module)->binary.loc, lexer, parser); - read_binary_ir((yyvsp[0].script_module)->binary.data, (yyvsp[0].script_module)->binary.size, &options, - &error_handler, (yyval.module)); - (yyval.module)->name = (yyvsp[0].script_module)->binary.name; - (yyval.module)->loc = (yyvsp[0].script_module)->binary.loc; - WABT_ZERO_MEMORY((yyvsp[0].script_module)->binary.name); - } - delete (yyvsp[0].script_module); - } -#line 4169 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 188: -#line 1370 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.var) = new Var(kInvalidIndex); - } -#line 4177 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 189: -#line 1373 "src/wast-parser.y" /* yacc.c:1646 */ - { - StringSlice name; - DUPTEXT(name, (yyvsp[0].text)); - (yyval.var) = new Var(name); - } -#line 4187 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 190: -#line 1381 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.script_module) = new ScriptModule(); - (yyval.script_module)->type = ScriptModule::Type::Text; - (yyval.script_module)->text = (yyvsp[-1].module); - (yyval.script_module)->text->name = (yyvsp[-2].text); - (yyval.script_module)->text->loc = (yylsp[-3]); - - // Resolve func type variables where the signature was not specified - // explicitly. - for (Func* func: (yyvsp[-1].module)->funcs) { - if (func->decl.has_func_type && is_empty_signature(&func->decl.sig)) { - FuncType* func_type = (yyvsp[-1].module)->GetFuncType(func->decl.type_var); - if (func_type) { - func->decl.sig = func_type->sig; - } - } - } - } -#line 4210 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 191: -#line 1399 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.script_module) = new ScriptModule(); - (yyval.script_module)->type = ScriptModule::Type::Binary; - (yyval.script_module)->binary.name = (yyvsp[-3].text); - (yyval.script_module)->binary.loc = (yylsp[-4]); - dup_text_list(&(yyvsp[-1].text_list), &(yyval.script_module)->binary.data, &(yyval.script_module)->binary.size); - destroy_text_list(&(yyvsp[-1].text_list)); - } -#line 4223 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 192: -#line 1407 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.script_module) = new ScriptModule(); - (yyval.script_module)->type = ScriptModule::Type::Quoted; - (yyval.script_module)->quoted.name = (yyvsp[-3].text); - (yyval.script_module)->quoted.loc = (yylsp[-4]); - dup_text_list(&(yyvsp[-1].text_list), &(yyval.script_module)->quoted.data, &(yyval.script_module)->quoted.size); - destroy_text_list(&(yyvsp[-1].text_list)); - } -#line 4236 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 193: -#line 1418 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.action) = new Action(); - (yyval.action)->loc = (yylsp[-4]); - (yyval.action)->module_var = std::move(*(yyvsp[-3].var)); - delete (yyvsp[-3].var); - (yyval.action)->type = ActionType::Invoke; - (yyval.action)->name = (yyvsp[-2].text); - (yyval.action)->invoke = new ActionInvoke(); - (yyval.action)->invoke->args = std::move(*(yyvsp[-1].consts)); - delete (yyvsp[-1].consts); - } -#line 4252 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 194: -#line 1429 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.action) = new Action(); - (yyval.action)->loc = (yylsp[-3]); - (yyval.action)->module_var = std::move(*(yyvsp[-2].var)); - delete (yyvsp[-2].var); - (yyval.action)->type = ActionType::Get; - (yyval.action)->name = (yyvsp[-1].text); - } -#line 4265 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 195: -#line 1440 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.command) = new Command(); - (yyval.command)->type = CommandType::AssertMalformed; - (yyval.command)->assert_malformed.module = (yyvsp[-2].script_module); - (yyval.command)->assert_malformed.text = (yyvsp[-1].text); - } -#line 4276 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 196: -#line 1446 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.command) = new Command(); - (yyval.command)->type = CommandType::AssertInvalid; - (yyval.command)->assert_invalid.module = (yyvsp[-2].script_module); - (yyval.command)->assert_invalid.text = (yyvsp[-1].text); - } -#line 4287 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 197: -#line 1452 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.command) = new Command(); - (yyval.command)->type = CommandType::AssertUnlinkable; - (yyval.command)->assert_unlinkable.module = (yyvsp[-2].script_module); - (yyval.command)->assert_unlinkable.text = (yyvsp[-1].text); - } -#line 4298 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 198: -#line 1458 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.command) = new Command(); - (yyval.command)->type = CommandType::AssertUninstantiable; - (yyval.command)->assert_uninstantiable.module = (yyvsp[-2].script_module); - (yyval.command)->assert_uninstantiable.text = (yyvsp[-1].text); - } -#line 4309 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 199: -#line 1464 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.command) = new Command(); - (yyval.command)->type = CommandType::AssertReturn; - (yyval.command)->assert_return.action = (yyvsp[-2].action); - (yyval.command)->assert_return.expected = (yyvsp[-1].consts); - } -#line 4320 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 200: -#line 1470 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.command) = new Command(); - (yyval.command)->type = CommandType::AssertReturnCanonicalNan; - (yyval.command)->assert_return_canonical_nan.action = (yyvsp[-1].action); - } -#line 4330 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 201: -#line 1475 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.command) = new Command(); - (yyval.command)->type = CommandType::AssertReturnArithmeticNan; - (yyval.command)->assert_return_arithmetic_nan.action = (yyvsp[-1].action); - } -#line 4340 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 202: -#line 1480 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.command) = new Command(); - (yyval.command)->type = CommandType::AssertTrap; - (yyval.command)->assert_trap.action = (yyvsp[-2].action); - (yyval.command)->assert_trap.text = (yyvsp[-1].text); - } -#line 4351 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 203: -#line 1486 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.command) = new Command(); - (yyval.command)->type = CommandType::AssertExhaustion; - (yyval.command)->assert_trap.action = (yyvsp[-2].action); - (yyval.command)->assert_trap.text = (yyvsp[-1].text); - } -#line 4362 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 204: -#line 1495 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.command) = new Command(); - (yyval.command)->type = CommandType::Action; - (yyval.command)->action = (yyvsp[0].action); - } -#line 4372 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 206: -#line 1501 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.command) = new Command(); - (yyval.command)->type = CommandType::Module; - (yyval.command)->module = (yyvsp[0].module); - } -#line 4382 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 207: -#line 1506 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.command) = new Command(); - (yyval.command)->type = CommandType::Register; - (yyval.command)->register_.module_name = (yyvsp[-2].text); - (yyval.command)->register_.var = std::move(*(yyvsp[-1].var)); - delete (yyvsp[-1].var); - (yyval.command)->register_.var.loc = (yylsp[-1]); - } -#line 4395 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 208: -#line 1516 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.commands) = new CommandPtrVector(); - (yyval.commands)->emplace_back((yyvsp[0].command)); - } -#line 4404 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 209: -#line 1520 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.commands) = (yyvsp[-1].commands); - (yyval.commands)->emplace_back((yyvsp[0].command)); - } -#line 4413 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 210: -#line 1527 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.const_).loc = (yylsp[-2]); - if (WABT_FAILED(parse_const((yyvsp[-2].type), (yyvsp[-1].literal).type, (yyvsp[-1].literal).text.start, - (yyvsp[-1].literal).text.start + (yyvsp[-1].literal).text.length, &(yyval.const_)))) { - wast_parser_error(&(yylsp[-1]), lexer, parser, - "invalid literal \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG((yyvsp[-1].literal).text)); - } - delete [] (yyvsp[-1].literal).text.start; - } -#line 4428 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 211: -#line 1539 "src/wast-parser.y" /* yacc.c:1646 */ - { (yyval.consts) = new ConstVector(); } -#line 4434 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 212: -#line 1540 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.consts) = (yyvsp[-1].consts); - (yyval.consts)->push_back((yyvsp[0].const_)); - } -#line 4443 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 213: -#line 1547 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.script) = new Script(); - } -#line 4451 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 214: -#line 1550 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.script) = new Script(); - (yyval.script)->commands = std::move(*(yyvsp[0].commands)); - delete (yyvsp[0].commands); - - int last_module_index = -1; - for (size_t i = 0; i < (yyval.script)->commands.size(); ++i) { - Command& command = *(yyval.script)->commands[i].get(); - Var* module_var = nullptr; - switch (command.type) { - case CommandType::Module: { - last_module_index = i; - - /* Wire up module name bindings. */ - Module* module = command.module; - if (module->name.length == 0) - continue; - - (yyval.script)->module_bindings.emplace(string_slice_to_string(module->name), - Binding(module->loc, i)); - break; - } - - case CommandType::AssertReturn: - module_var = &command.assert_return.action->module_var; - goto has_module_var; - case CommandType::AssertReturnCanonicalNan: - module_var = - &command.assert_return_canonical_nan.action->module_var; - goto has_module_var; - case CommandType::AssertReturnArithmeticNan: - module_var = - &command.assert_return_arithmetic_nan.action->module_var; - goto has_module_var; - case CommandType::AssertTrap: - case CommandType::AssertExhaustion: - module_var = &command.assert_trap.action->module_var; - goto has_module_var; - case CommandType::Action: - module_var = &command.action->module_var; - goto has_module_var; - case CommandType::Register: - module_var = &command.register_.var; - goto has_module_var; - - has_module_var: { - /* Resolve actions with an invalid index to use the preceding - * module. */ - if (module_var->type == VarType::Index && - module_var->index == kInvalidIndex) { - module_var->index = last_module_index; - } - break; - } - - default: - break; - } - } - } -#line 4516 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 215: -#line 1610 "src/wast-parser.y" /* yacc.c:1646 */ - { - (yyval.script) = new Script(); - Command* command = new Command(); - command->type = CommandType::Module; - command->module = (yyvsp[0].module); - (yyval.script)->commands.emplace_back(command); - } -#line 4528 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - case 216: -#line 1622 "src/wast-parser.y" /* yacc.c:1646 */ - { parser->script = (yyvsp[0].script); } -#line 4534 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - break; - - -#line 4538 "src/prebuilt/wast-parser-gen.cc" /* yacc.c:1646 */ - default: break; - } - /* User semantic actions sometimes alter yychar, and that requires - that yytoken be updated with the new translation. We take the - approach of translating immediately before every use of yytoken. - One alternative is translating here after every semantic action, - but that translation would be missed if the semantic action invokes - YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or - if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an - incorrect destructor might then be invoked immediately. In the - case of YYERROR or YYBACKUP, subsequent parser actions might lead - to an incorrect destructor call or verbose syntax error message - before the lookahead is translated. */ - YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); - - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - - *++yyvsp = yyval; - *++yylsp = yyloc; - - /* Now 'shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; - - goto yynewstate; - - -/*--------------------------------------. -| yyerrlab -- here on detecting error. | -`--------------------------------------*/ -yyerrlab: - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); - - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; -#if ! YYERROR_VERBOSE - yyerror (&yylloc, lexer, parser, YY_("syntax error")); -#else -# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ - yyssp, yytoken) - { - char const *yymsgp = YY_("syntax error"); - int yysyntax_error_status; - yysyntax_error_status = YYSYNTAX_ERROR; - if (yysyntax_error_status == 0) - yymsgp = yymsg; - else if (yysyntax_error_status == 1) - { - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); - if (!yymsg) - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - yysyntax_error_status = 2; - } - else - { - yysyntax_error_status = YYSYNTAX_ERROR; - yymsgp = yymsg; - } - } - yyerror (&yylloc, lexer, parser, yymsgp); - if (yysyntax_error_status == 2) - goto yyexhaustedlab; - } -# undef YYSYNTAX_ERROR -#endif - } - - yyerror_range[1] = yylloc; - - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval, &yylloc, lexer, parser); - yychar = YYEMPTY; - } - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - goto yyerrlab1; - - -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: - - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; - - yyerror_range[1] = yylsp[1-yylen]; - /* Do not reclaim the symbols of the rule whose action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; - - -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ - - for (;;) - { - yyn = yypact[yystate]; - if (!yypact_value_is_default (yyn)) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; - - yyerror_range[1] = *yylsp; - yydestruct ("Error: popping", - yystos[yystate], yyvsp, yylsp, lexer, parser); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - - yyerror_range[2] = yylloc; - /* Using YYLLOC is tempting, but would change the location of - the lookahead. YYLOC is available though. */ - YYLLOC_DEFAULT (yyloc, yyerror_range, 2); - *++yylsp = yyloc; - - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; - -#if !defined yyoverflow || YYERROR_VERBOSE -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ -yyexhaustedlab: - yyerror (&yylloc, lexer, parser, YY_("memory exhausted")); - yyresult = 2; - /* Fall through. */ -#endif - -yyreturn: - if (yychar != YYEMPTY) - { - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = YYTRANSLATE (yychar); - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, &yylloc, lexer, parser); - } - /* Do not reclaim the symbols of the rule whose action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp, yylsp, lexer, parser); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif -#if YYERROR_VERBOSE - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); -#endif - return yyresult; -} -#line 1625 "src/wast-parser.y" /* yacc.c:1906 */ - - -void append_expr_list(ExprList* expr_list, ExprList* expr) { - if (!expr->first) - return; - if (expr_list->last) - expr_list->last->next = expr->first; - else - expr_list->first = expr->first; - expr_list->last = expr->last; - expr_list->size += expr->size; -} - -void append_expr(ExprList* expr_list, Expr* expr) { - if (expr_list->last) - expr_list->last->next = expr; - else - expr_list->first = expr; - expr_list->last = expr; - expr_list->size++; -} - -ExprList join_exprs1(Location* loc, Expr* expr1) { - ExprList result; - WABT_ZERO_MEMORY(result); - append_expr(&result, expr1); - expr1->loc = *loc; - return result; -} - -ExprList join_exprs2(Location* loc, ExprList* expr1, Expr* expr2) { - ExprList result; - WABT_ZERO_MEMORY(result); - append_expr_list(&result, expr1); - append_expr(&result, expr2); - expr2->loc = *loc; - return result; -} - -ExprList join_expr_lists(ExprList* expr1, ExprList* expr2) { - ExprList result; - WABT_ZERO_MEMORY(result); - append_expr_list(&result, expr1); - append_expr_list(&result, expr2); - return result; -} - -Result parse_const(Type type, - LiteralType literal_type, - const char* s, - const char* end, - Const* out) { - out->type = type; - switch (type) { - case Type::I32: - return parse_int32(s, end, &out->u32, ParseIntType::SignedAndUnsigned); - case Type::I64: - return parse_int64(s, end, &out->u64, ParseIntType::SignedAndUnsigned); - case Type::F32: - return parse_float(literal_type, s, end, &out->f32_bits); - case Type::F64: - return parse_double(literal_type, s, end, &out->f64_bits); - default: - assert(0); - break; - } - return Result::Error; -} - -size_t copy_string_contents(StringSlice* text, char* dest) { - const char* src = text->start + 1; - const char* end = text->start + text->length - 1; - - char* dest_start = dest; - - while (src < end) { - if (*src == '\\') { - src++; - switch (*src) { - case 'n': - *dest++ = '\n'; - break; - case 'r': - *dest++ = '\r'; - break; - case 't': - *dest++ = '\t'; - break; - case '\\': - *dest++ = '\\'; - break; - case '\'': - *dest++ = '\''; - break; - case '\"': - *dest++ = '\"'; - break; - default: { - // The string should be validated already, so we know this is a hex - // sequence. - uint32_t hi; - uint32_t lo; - if (WABT_SUCCEEDED(parse_hexdigit(src[0], &hi)) && - WABT_SUCCEEDED(parse_hexdigit(src[1], &lo))) { - *dest++ = (hi << 4) | lo; - } else { - assert(0); - } - src++; - break; - } - } - src++; - } else { - *dest++ = *src++; - } - } - /* return the data length */ - return dest - dest_start; -} - -void dup_text_list(TextList* text_list, char** out_data, size_t* out_size) { - /* walk the linked list to see how much total space is needed */ - size_t total_size = 0; - for (TextListNode* node = text_list->first; node; node = node->next) { - /* Always allocate enough space for the entire string including the escape - * characters. It will only get shorter, and this way we only have to - * iterate through the string once. */ - const char* src = node->text.start + 1; - const char* end = node->text.start + node->text.length - 1; - size_t size = (end > src) ? (end - src) : 0; - total_size += size; - } - char* result = new char [total_size]; - char* dest = result; - for (TextListNode* node = text_list->first; node; node = node->next) { - size_t actual_size = copy_string_contents(&node->text, dest); - dest += actual_size; - } - *out_data = result; - *out_size = dest - result; -} - -void reverse_bindings(TypeVector* types, BindingHash* bindings) { - for (auto& pair : *bindings) { - pair.second.index = types->size() - pair.second.index - 1; - } -} - -bool is_empty_signature(const FuncSignature* sig) { - return sig->result_types.empty() && sig->param_types.empty(); -} - -void append_implicit_func_declaration(Location* loc, - Module* module, - FuncDeclaration* decl) { - if (decl->has_func_type) - return; - - int sig_index = module->GetFuncTypeIndex(*decl); - if (sig_index == -1) { - module->AppendImplicitFuncType(*loc, decl->sig); - } else { - decl->sig = module->func_types[sig_index]->sig; - } -} - -void check_import_ordering(Location* loc, WastLexer* lexer, WastParser* parser, - Module* module, ModuleField* first) { - for (ModuleField* field = first; field; field = field->next) { - if (field->type == ModuleFieldType::Import) { - if (module->funcs.size() != module->num_func_imports || - module->tables.size() != module->num_table_imports || - module->memories.size() != module->num_memory_imports || - module->globals.size() != module->num_global_imports || - module->excepts.size() != module->num_except_imports) { - wast_parser_error( - loc, lexer, parser, - "imports must occur before all non-import definitions"); - } - } - } -} - -void append_module_fields(Module* module, ModuleField* first) { - ModuleField* main_field = first; - Index main_index = kInvalidIndex; - - for (ModuleField* field = first; field; field = field->next) { - StringSlice* name = nullptr; - BindingHash* bindings = nullptr; - Index index = kInvalidIndex; - - switch (field->type) { - case ModuleFieldType::Func: - append_implicit_func_declaration(&field->loc, module, - &field->func->decl); - name = &field->func->name; - bindings = &module->func_bindings; - index = module->funcs.size(); - module->funcs.push_back(field->func); - break; - - case ModuleFieldType::Global: - name = &field->global->name; - bindings = &module->global_bindings; - index = module->globals.size(); - module->globals.push_back(field->global); - break; - - case ModuleFieldType::Import: - switch (field->import->kind) { - case ExternalKind::Func: - append_implicit_func_declaration(&field->loc, module, - &field->import->func->decl); - name = &field->import->func->name; - bindings = &module->func_bindings; - index = module->funcs.size(); - module->funcs.push_back(field->import->func); - ++module->num_func_imports; - break; - case ExternalKind::Table: - name = &field->import->table->name; - bindings = &module->table_bindings; - index = module->tables.size(); - module->tables.push_back(field->import->table); - ++module->num_table_imports; - break; - case ExternalKind::Memory: - name = &field->import->memory->name; - bindings = &module->memory_bindings; - index = module->memories.size(); - module->memories.push_back(field->import->memory); - ++module->num_memory_imports; - break; - case ExternalKind::Global: - name = &field->import->global->name; - bindings = &module->global_bindings; - index = module->globals.size(); - module->globals.push_back(field->import->global); - ++module->num_global_imports; - break; - case ExternalKind::Except: - name = &field->import->except->name; - bindings = &module->except_bindings; - index = module->excepts.size(); - module->excepts.push_back(field->except); - ++module->num_except_imports; - break; - } - module->imports.push_back(field->import); - break; - - case ModuleFieldType::Export: - if (field != main_field) { - // If this is not the main field, it must be an inline export. - field->export_->var.type = VarType::Index; - field->export_->var.index = main_index; - } - name = &field->export_->name; - bindings = &module->export_bindings; - index = module->exports.size(); - module->exports.push_back(field->export_); - break; - - case ModuleFieldType::FuncType: - name = &field->func_type->name; - bindings = &module->func_type_bindings; - index = module->func_types.size(); - module->func_types.push_back(field->func_type); - break; - - case ModuleFieldType::Table: - name = &field->table->name; - bindings = &module->table_bindings; - index = module->tables.size(); - module->tables.push_back(field->table); - break; - - case ModuleFieldType::ElemSegment: - if (field != main_field) { - // If this is not the main field, it must be an inline elem segment. - field->elem_segment->table_var.type = VarType::Index; - field->elem_segment->table_var.index = main_index; - } - module->elem_segments.push_back(field->elem_segment); - break; - - case ModuleFieldType::Memory: - name = &field->memory->name; - bindings = &module->memory_bindings; - index = module->memories.size(); - module->memories.push_back(field->memory); - break; - - case ModuleFieldType::DataSegment: - if (field != main_field) { - // If this is not the main field, it must be an inline data segment. - field->data_segment->memory_var.type = VarType::Index; - field->data_segment->memory_var.index = main_index; - } - module->data_segments.push_back(field->data_segment); - break; - - case ModuleFieldType::Except: - name = &field->except->name; - bindings = &module->except_bindings; - index = module->excepts.size(); - module->excepts.push_back(field->except); - break; - - case ModuleFieldType::Start: - module->start = &field->start; - break; - } - - if (field == main_field) - main_index = index; - - if (module->last_field) - module->last_field->next = field; - else - module->first_field = field; - module->last_field = field; - - if (name && bindings) { - // Exported names are allowed to be empty; other names aren't. - if (bindings == &module->export_bindings || - !string_slice_is_empty(name)) { - bindings->emplace(string_slice_to_string(*name), - Binding(field->loc, index)); - } - } - } -} - -Result parse_wast(WastLexer* lexer, Script** out_script, - SourceErrorHandler* error_handler, - WastParseOptions* options) { - WastParser parser; - WABT_ZERO_MEMORY(parser); - static WastParseOptions default_options; - if (options == nullptr) - options = &default_options; - parser.options = options; - parser.error_handler = error_handler; - wabt_wast_parser_debug = int(options->debug_parsing); - int result = wabt_wast_parser_parse(lexer, &parser); - delete [] parser.yyssa; - delete [] parser.yyvsa; - delete [] parser.yylsa; - if (out_script) { - *out_script = parser.script; - } else { - delete parser.script; - } - return result == 0 && parser.errors == 0 ? Result::Ok : Result::Error; -} - -BinaryErrorHandlerModule::BinaryErrorHandlerModule( - Location* loc, WastLexer* lexer, WastParser* parser) - : loc_(loc), lexer_(lexer), parser_(parser) {} - -bool BinaryErrorHandlerModule::OnError(Offset offset, - const std::string& error) { - if (offset == kInvalidOffset) { - wast_parser_error(loc_, lexer_, parser_, "error in binary module: %s", - error.c_str()); - } else { - wast_parser_error(loc_, lexer_, parser_, - "error in binary module: @0x%08" PRIzx ": %s", offset, - error.c_str()); - } - return true; -} - -} // namespace wabt diff --git a/lib/wabt/src/prebuilt/wast-parser-gen.hh b/lib/wabt/src/prebuilt/wast-parser-gen.hh deleted file mode 100644 index b20d1b92a34..00000000000 --- a/lib/wabt/src/prebuilt/wast-parser-gen.hh +++ /dev/null @@ -1,162 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.0.2. */ - -/* Bison interface for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -#ifndef YY_WABT_WAST_PARSER_SRC_PREBUILT_WAST_PARSER_GEN_HH_INCLUDED -# define YY_WABT_WAST_PARSER_SRC_PREBUILT_WAST_PARSER_GEN_HH_INCLUDED -/* Debug traces. */ -#ifndef WABT_WAST_PARSER_DEBUG -# if defined YYDEBUG -#if YYDEBUG -# define WABT_WAST_PARSER_DEBUG 1 -# else -# define WABT_WAST_PARSER_DEBUG 0 -# endif -# else /* ! defined YYDEBUG */ -# define WABT_WAST_PARSER_DEBUG 0 -# endif /* ! defined YYDEBUG */ -#endif /* ! defined WABT_WAST_PARSER_DEBUG */ -#if WABT_WAST_PARSER_DEBUG -extern int wabt_wast_parser_debug; -#endif - -/* Token type. */ -#ifndef WABT_WAST_PARSER_TOKENTYPE -# define WABT_WAST_PARSER_TOKENTYPE - enum wabt_wast_parser_tokentype - { - WABT_TOKEN_TYPE_EOF = 0, - WABT_TOKEN_TYPE_LPAR = 258, - WABT_TOKEN_TYPE_RPAR = 259, - WABT_TOKEN_TYPE_NAT = 260, - WABT_TOKEN_TYPE_INT = 261, - WABT_TOKEN_TYPE_FLOAT = 262, - WABT_TOKEN_TYPE_TEXT = 263, - WABT_TOKEN_TYPE_VAR = 264, - WABT_TOKEN_TYPE_VALUE_TYPE = 265, - WABT_TOKEN_TYPE_ANYFUNC = 266, - WABT_TOKEN_TYPE_MUT = 267, - WABT_TOKEN_TYPE_NOP = 268, - WABT_TOKEN_TYPE_DROP = 269, - WABT_TOKEN_TYPE_BLOCK = 270, - WABT_TOKEN_TYPE_END = 271, - WABT_TOKEN_TYPE_IF = 272, - WABT_TOKEN_TYPE_THEN = 273, - WABT_TOKEN_TYPE_ELSE = 274, - WABT_TOKEN_TYPE_LOOP = 275, - WABT_TOKEN_TYPE_BR = 276, - WABT_TOKEN_TYPE_BR_IF = 277, - WABT_TOKEN_TYPE_BR_TABLE = 278, - WABT_TOKEN_TYPE_TRY = 279, - WABT_TOKEN_TYPE_CATCH = 280, - WABT_TOKEN_TYPE_CATCH_ALL = 281, - WABT_TOKEN_TYPE_THROW = 282, - WABT_TOKEN_TYPE_RETHROW = 283, - WABT_TOKEN_TYPE_CALL = 284, - WABT_TOKEN_TYPE_CALL_INDIRECT = 285, - WABT_TOKEN_TYPE_RETURN = 286, - WABT_TOKEN_TYPE_GET_LOCAL = 287, - WABT_TOKEN_TYPE_SET_LOCAL = 288, - WABT_TOKEN_TYPE_TEE_LOCAL = 289, - WABT_TOKEN_TYPE_GET_GLOBAL = 290, - WABT_TOKEN_TYPE_SET_GLOBAL = 291, - WABT_TOKEN_TYPE_LOAD = 292, - WABT_TOKEN_TYPE_STORE = 293, - WABT_TOKEN_TYPE_OFFSET_EQ_NAT = 294, - WABT_TOKEN_TYPE_ALIGN_EQ_NAT = 295, - WABT_TOKEN_TYPE_CONST = 296, - WABT_TOKEN_TYPE_UNARY = 297, - WABT_TOKEN_TYPE_BINARY = 298, - WABT_TOKEN_TYPE_COMPARE = 299, - WABT_TOKEN_TYPE_CONVERT = 300, - WABT_TOKEN_TYPE_SELECT = 301, - WABT_TOKEN_TYPE_UNREACHABLE = 302, - WABT_TOKEN_TYPE_CURRENT_MEMORY = 303, - WABT_TOKEN_TYPE_GROW_MEMORY = 304, - WABT_TOKEN_TYPE_FUNC = 305, - WABT_TOKEN_TYPE_START = 306, - WABT_TOKEN_TYPE_TYPE = 307, - WABT_TOKEN_TYPE_PARAM = 308, - WABT_TOKEN_TYPE_RESULT = 309, - WABT_TOKEN_TYPE_LOCAL = 310, - WABT_TOKEN_TYPE_GLOBAL = 311, - WABT_TOKEN_TYPE_TABLE = 312, - WABT_TOKEN_TYPE_ELEM = 313, - WABT_TOKEN_TYPE_MEMORY = 314, - WABT_TOKEN_TYPE_DATA = 315, - WABT_TOKEN_TYPE_OFFSET = 316, - WABT_TOKEN_TYPE_IMPORT = 317, - WABT_TOKEN_TYPE_EXPORT = 318, - WABT_TOKEN_TYPE_EXCEPT = 319, - WABT_TOKEN_TYPE_MODULE = 320, - WABT_TOKEN_TYPE_BIN = 321, - WABT_TOKEN_TYPE_QUOTE = 322, - WABT_TOKEN_TYPE_REGISTER = 323, - WABT_TOKEN_TYPE_INVOKE = 324, - WABT_TOKEN_TYPE_GET = 325, - WABT_TOKEN_TYPE_ASSERT_MALFORMED = 326, - WABT_TOKEN_TYPE_ASSERT_INVALID = 327, - WABT_TOKEN_TYPE_ASSERT_UNLINKABLE = 328, - WABT_TOKEN_TYPE_ASSERT_RETURN = 329, - WABT_TOKEN_TYPE_ASSERT_RETURN_CANONICAL_NAN = 330, - WABT_TOKEN_TYPE_ASSERT_RETURN_ARITHMETIC_NAN = 331, - WABT_TOKEN_TYPE_ASSERT_TRAP = 332, - WABT_TOKEN_TYPE_ASSERT_EXHAUSTION = 333, - WABT_TOKEN_TYPE_LOW = 334 - }; -#endif - -/* Value type. */ -#if ! defined WABT_WAST_PARSER_STYPE && ! defined WABT_WAST_PARSER_STYPE_IS_DECLARED -typedef ::wabt::Token WABT_WAST_PARSER_STYPE; -# define WABT_WAST_PARSER_STYPE_IS_TRIVIAL 1 -# define WABT_WAST_PARSER_STYPE_IS_DECLARED 1 -#endif - -/* Location type. */ -#if ! defined WABT_WAST_PARSER_LTYPE && ! defined WABT_WAST_PARSER_LTYPE_IS_DECLARED -typedef struct WABT_WAST_PARSER_LTYPE WABT_WAST_PARSER_LTYPE; -struct WABT_WAST_PARSER_LTYPE -{ - int first_line; - int first_column; - int last_line; - int last_column; -}; -# define WABT_WAST_PARSER_LTYPE_IS_DECLARED 1 -# define WABT_WAST_PARSER_LTYPE_IS_TRIVIAL 1 -#endif - - - -int wabt_wast_parser_parse (::wabt::WastLexer* lexer, ::wabt::WastParser* parser); - -#endif /* !YY_WABT_WAST_PARSER_SRC_PREBUILT_WAST_PARSER_GEN_HH_INCLUDED */ diff --git a/lib/wabt/src/prebuilt/wast-parser-gen.output b/lib/wabt/src/prebuilt/wast-parser-gen.output deleted file mode 100644 index 1c4f03ec8e4..00000000000 --- a/lib/wabt/src/prebuilt/wast-parser-gen.output +++ /dev/null @@ -1,6436 +0,0 @@ -Grammar - - 0 $accept: script_start "EOF" - - 1 text_list: TEXT - 2 | text_list TEXT - - 3 text_list_opt: %empty - 4 | text_list - - 5 quoted_text: TEXT - - 6 value_type_list: %empty - 7 | value_type_list VALUE_TYPE - - 8 elem_type: ANYFUNC - - 9 global_type: VALUE_TYPE - 10 | "(" MUT VALUE_TYPE ")" - - 11 func_type: "(" FUNC func_sig ")" - - 12 func_sig: func_sig_result - 13 | "(" PARAM value_type_list ")" func_sig - 14 | "(" PARAM bind_var VALUE_TYPE ")" func_sig - - 15 func_sig_result: %empty - 16 | "(" RESULT value_type_list ")" func_sig_result - - 17 table_sig: limits elem_type - - 18 memory_sig: limits - - 19 limits: nat - 20 | nat nat - - 21 type_use: "(" TYPE var ")" - - 22 nat: NAT - - 23 literal: NAT - 24 | INT - 25 | FLOAT - - 26 var: nat - 27 | VAR - - 28 var_list: %empty - 29 | var_list var - - 30 bind_var_opt: %empty - 31 | bind_var - - 32 bind_var: VAR - - 33 labeling_opt: %empty - 34 | bind_var - - 35 offset_opt: %empty - 36 | OFFSET_EQ_NAT - - 37 align_opt: %empty - 38 | ALIGN_EQ_NAT - - 39 instr: plain_instr - 40 | block_instr - 41 | expr - - 42 plain_instr: UNREACHABLE - 43 | NOP - 44 | DROP - 45 | SELECT - 46 | BR var - 47 | BR_IF var - 48 | BR_TABLE var_list var - 49 | RETURN - 50 | CALL var - 51 | CALL_INDIRECT var - 52 | GET_LOCAL var - 53 | SET_LOCAL var - 54 | TEE_LOCAL var - 55 | GET_GLOBAL var - 56 | SET_GLOBAL var - 57 | LOAD offset_opt align_opt - 58 | STORE offset_opt align_opt - 59 | CONST literal - 60 | UNARY - 61 | BINARY - 62 | COMPARE - 63 | CONVERT - 64 | CURRENT_MEMORY - 65 | GROW_MEMORY - 66 | throw_check var - 67 | rethrow_check var - - 68 block_instr: BLOCK labeling_opt block END labeling_opt - 69 | LOOP labeling_opt block END labeling_opt - 70 | IF labeling_opt block END labeling_opt - 71 | IF labeling_opt block ELSE labeling_opt instr_list END labeling_opt - 72 | try_check labeling_opt block catch_instr_list END labeling_opt - - 73 block_sig: "(" RESULT value_type_list ")" - - 74 block: block_sig block - 75 | instr_list - - 76 catch_instr: CATCH var instr_list - 77 | CATCH_ALL instr_list - - 78 catch_instr_list: catch_instr - 79 | catch_instr catch_instr_list - - 80 expr: "(" expr1 ")" - - 81 expr1: plain_instr expr_list - 82 | BLOCK labeling_opt block - 83 | LOOP labeling_opt block - 84 | IF labeling_opt if_block - 85 | try_check labeling_opt try_ - - 86 try_: block_sig try_ - 87 | try_instr_list - - 88 try_instr_list: catch_list - 89 | instr try_instr_list - - 90 catch_list: "(" catch_instr ")" - 91 | "(" catch_instr ")" catch_list - - 92 if_block: block_sig if_block - 93 | if_ - - 94 if_: "(" THEN instr_list ")" "(" ELSE instr_list ")" - 95 | "(" THEN instr_list ")" - 96 | expr "(" THEN instr_list ")" "(" ELSE instr_list ")" - 97 | expr "(" THEN instr_list ")" - 98 | expr expr expr - 99 | expr expr - - 100 rethrow_check: RETHROW - - 101 throw_check: THROW - - 102 try_check: TRY - - 103 instr_list: %empty - 104 | instr instr_list - - 105 expr_list: %empty - 106 | expr expr_list - - 107 const_expr: instr_list - - 108 exception: "(" EXCEPT bind_var_opt value_type_list ")" - - 109 exception_field: exception - - 110 func: "(" FUNC bind_var_opt func_fields ")" - - 111 func_fields: type_use func_fields_body - 112 | func_fields_body - 113 | inline_import type_use func_fields_import - 114 | inline_import func_fields_import - 115 | inline_export func_fields - - 116 func_fields_import: func_fields_import1 - - 117 func_fields_import1: func_fields_import_result - 118 | "(" PARAM value_type_list ")" func_fields_import1 - 119 | "(" PARAM bind_var VALUE_TYPE ")" func_fields_import1 - - 120 func_fields_import_result: %empty - 121 | "(" RESULT value_type_list ")" func_fields_import_result - - 122 func_fields_body: func_fields_body1 - - 123 func_fields_body1: func_result_body - 124 | "(" PARAM value_type_list ")" func_fields_body1 - 125 | "(" PARAM bind_var VALUE_TYPE ")" func_fields_body1 - - 126 func_result_body: func_body - 127 | "(" RESULT value_type_list ")" func_result_body - - 128 func_body: func_body1 - - 129 func_body1: instr_list - 130 | "(" LOCAL value_type_list ")" func_body1 - 131 | "(" LOCAL bind_var VALUE_TYPE ")" func_body1 - - 132 offset: "(" OFFSET const_expr ")" - 133 | expr - - 134 elem: "(" ELEM var offset var_list ")" - 135 | "(" ELEM offset var_list ")" - - 136 table: "(" TABLE bind_var_opt table_fields ")" - - 137 table_fields: table_sig - 138 | inline_import table_sig - 139 | inline_export table_fields - 140 | elem_type "(" ELEM var_list ")" - - 141 data: "(" DATA var offset text_list_opt ")" - 142 | "(" DATA offset text_list_opt ")" - - 143 memory: "(" MEMORY bind_var_opt memory_fields ")" - - 144 memory_fields: memory_sig - 145 | inline_import memory_sig - 146 | inline_export memory_fields - 147 | "(" DATA text_list_opt ")" - - 148 global: "(" GLOBAL bind_var_opt global_fields ")" - - 149 global_fields: global_type const_expr - 150 | inline_import global_type - 151 | inline_export global_fields - - 152 import_desc: "(" FUNC bind_var_opt type_use ")" - 153 | "(" FUNC bind_var_opt func_sig ")" - 154 | "(" TABLE bind_var_opt table_sig ")" - 155 | "(" MEMORY bind_var_opt memory_sig ")" - 156 | "(" GLOBAL bind_var_opt global_type ")" - 157 | exception - - 158 import: "(" IMPORT quoted_text quoted_text import_desc ")" - - 159 inline_import: "(" IMPORT quoted_text quoted_text ")" - - 160 export_desc: "(" FUNC var ")" - 161 | "(" TABLE var ")" - 162 | "(" MEMORY var ")" - 163 | "(" GLOBAL var ")" - 164 | "(" EXCEPT var ")" - - 165 export: "(" EXPORT quoted_text export_desc ")" - - 166 inline_export: "(" EXPORT quoted_text ")" - - 167 type_def: "(" TYPE func_type ")" - 168 | "(" TYPE bind_var func_type ")" - - 169 start: "(" START var ")" - - 170 module_field: type_def - 171 | global - 172 | table - 173 | memory - 174 | func - 175 | elem - 176 | data - 177 | start - 178 | import - 179 | export - 180 | exception_field - - 181 module_fields_opt: %empty - 182 | module_fields - - 183 module_fields: module_field - 184 | module_fields module_field - - 185 module: script_module - - 186 inline_module: module_fields - - 187 script_var_opt: %empty - 188 | VAR - - 189 script_module: "(" MODULE bind_var_opt module_fields_opt ")" - 190 | "(" MODULE bind_var_opt BIN text_list ")" - 191 | "(" MODULE bind_var_opt QUOTE text_list ")" - - 192 action: "(" INVOKE script_var_opt quoted_text const_list ")" - 193 | "(" GET script_var_opt quoted_text ")" - - 194 assertion: "(" ASSERT_MALFORMED script_module quoted_text ")" - 195 | "(" ASSERT_INVALID script_module quoted_text ")" - 196 | "(" ASSERT_UNLINKABLE script_module quoted_text ")" - 197 | "(" ASSERT_TRAP script_module quoted_text ")" - 198 | "(" ASSERT_RETURN action const_list ")" - 199 | "(" ASSERT_RETURN_CANONICAL_NAN action ")" - 200 | "(" ASSERT_RETURN_ARITHMETIC_NAN action ")" - 201 | "(" ASSERT_TRAP action quoted_text ")" - 202 | "(" ASSERT_EXHAUSTION action quoted_text ")" - - 203 cmd: action - 204 | assertion - 205 | module - 206 | "(" REGISTER quoted_text script_var_opt ")" - - 207 cmd_list: cmd - 208 | cmd_list cmd - - 209 const: "(" CONST literal ")" - - 210 const_list: %empty - 211 | const_list const - - 212 script: %empty - 213 | cmd_list - 214 | inline_module - - 215 script_start: script - - -Terminals, with rules where they appear - -"EOF" (0) 0 -error (256) -"(" (258) 10 11 13 14 16 21 73 80 90 91 94 95 96 97 108 110 118 119 - 121 124 125 127 130 131 132 134 135 136 140 141 142 143 147 148 - 152 153 154 155 156 158 159 160 161 162 163 164 165 166 167 168 - 169 189 190 191 192 193 194 195 196 197 198 199 200 201 202 206 - 209 -")" (259) 10 11 13 14 16 21 73 80 90 91 94 95 96 97 108 110 118 119 - 121 124 125 127 130 131 132 134 135 136 140 141 142 143 147 148 - 152 153 154 155 156 158 159 160 161 162 163 164 165 166 167 168 - 169 189 190 191 192 193 194 195 196 197 198 199 200 201 202 206 - 209 -NAT (260) 22 23 -INT (261) 24 -FLOAT (262) 25 -TEXT (263) 1 2 5 -VAR (264) 27 32 188 -VALUE_TYPE (265) 7 9 10 14 119 125 131 -ANYFUNC (266) 8 -MUT (267) 10 -NOP (268) 43 -DROP (269) 44 -BLOCK (270) 68 82 -END (271) 68 69 70 71 72 -IF (272) 70 71 84 -THEN (273) 94 95 96 97 -ELSE (274) 71 94 96 -LOOP (275) 69 83 -BR (276) 46 -BR_IF (277) 47 -BR_TABLE (278) 48 -TRY (279) 102 -CATCH (280) 76 -CATCH_ALL (281) 77 -THROW (282) 101 -RETHROW (283) 100 -CALL (284) 50 -CALL_INDIRECT (285) 51 -RETURN (286) 49 -GET_LOCAL (287) 52 -SET_LOCAL (288) 53 -TEE_LOCAL (289) 54 -GET_GLOBAL (290) 55 -SET_GLOBAL (291) 56 -LOAD (292) 57 -STORE (293) 58 -OFFSET_EQ_NAT (294) 36 -ALIGN_EQ_NAT (295) 38 -CONST (296) 59 209 -UNARY (297) 60 -BINARY (298) 61 -COMPARE (299) 62 -CONVERT (300) 63 -SELECT (301) 45 -UNREACHABLE (302) 42 -CURRENT_MEMORY (303) 64 -GROW_MEMORY (304) 65 -FUNC (305) 11 110 152 153 160 -START (306) 169 -TYPE (307) 21 167 168 -PARAM (308) 13 14 118 119 124 125 -RESULT (309) 16 73 121 127 -LOCAL (310) 130 131 -GLOBAL (311) 148 156 163 -TABLE (312) 136 154 161 -ELEM (313) 134 135 140 -MEMORY (314) 143 155 162 -DATA (315) 141 142 147 -OFFSET (316) 132 -IMPORT (317) 158 159 -EXPORT (318) 165 166 -EXCEPT (319) 108 164 -MODULE (320) 189 190 191 -BIN (321) 190 -QUOTE (322) 191 -REGISTER (323) 206 -INVOKE (324) 192 -GET (325) 193 -ASSERT_MALFORMED (326) 194 -ASSERT_INVALID (327) 195 -ASSERT_UNLINKABLE (328) 196 -ASSERT_RETURN (329) 198 -ASSERT_RETURN_CANONICAL_NAN (330) 199 -ASSERT_RETURN_ARITHMETIC_NAN (331) 200 -ASSERT_TRAP (332) 197 201 -ASSERT_EXHAUSTION (333) 202 -LOW (334) - - -Nonterminals, with rules where they appear - -$accept (80) - on left: 0 -text_list (81) - on left: 1 2, on right: 2 4 190 191 -text_list_opt (82) - on left: 3 4, on right: 141 142 147 -quoted_text (83) - on left: 5, on right: 158 159 165 166 192 193 194 195 196 197 201 - 202 206 -value_type_list (84) - on left: 6 7, on right: 7 13 16 73 108 118 121 124 127 130 -elem_type (85) - on left: 8, on right: 17 140 -global_type (86) - on left: 9 10, on right: 149 150 156 -func_type (87) - on left: 11, on right: 167 168 -func_sig (88) - on left: 12 13 14, on right: 11 13 14 153 -func_sig_result (89) - on left: 15 16, on right: 12 16 -table_sig (90) - on left: 17, on right: 137 138 154 -memory_sig (91) - on left: 18, on right: 144 145 155 -limits (92) - on left: 19 20, on right: 17 18 -type_use (93) - on left: 21, on right: 111 113 152 -nat (94) - on left: 22, on right: 19 20 26 -literal (95) - on left: 23 24 25, on right: 59 209 -var (96) - on left: 26 27, on right: 21 29 46 47 48 50 51 52 53 54 55 56 66 - 67 76 134 141 160 161 162 163 164 169 -var_list (97) - on left: 28 29, on right: 29 48 134 135 140 -bind_var_opt (98) - on left: 30 31, on right: 108 110 136 143 148 152 153 154 155 156 - 189 190 191 -bind_var (99) - on left: 32, on right: 14 31 34 119 125 131 168 -labeling_opt (100) - on left: 33 34, on right: 68 69 70 71 72 82 83 84 85 -offset_opt (101) - on left: 35 36, on right: 57 58 -align_opt (102) - on left: 37 38, on right: 57 58 -instr (103) - on left: 39 40 41, on right: 89 104 -plain_instr (104) - on left: 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 - 60 61 62 63 64 65 66 67, on right: 39 81 -block_instr (105) - on left: 68 69 70 71 72, on right: 40 -block_sig (106) - on left: 73, on right: 74 86 92 -block (107) - on left: 74 75, on right: 68 69 70 71 72 74 82 83 -catch_instr (108) - on left: 76 77, on right: 78 79 90 91 -catch_instr_list (109) - on left: 78 79, on right: 72 79 -expr (110) - on left: 80, on right: 41 96 97 98 99 106 133 -expr1 (111) - on left: 81 82 83 84 85, on right: 80 -try_ (112) - on left: 86 87, on right: 85 86 -try_instr_list (113) - on left: 88 89, on right: 87 89 -catch_list (114) - on left: 90 91, on right: 88 91 -if_block (115) - on left: 92 93, on right: 84 92 -if_ (116) - on left: 94 95 96 97 98 99, on right: 93 -rethrow_check (117) - on left: 100, on right: 67 -throw_check (118) - on left: 101, on right: 66 -try_check (119) - on left: 102, on right: 72 85 -instr_list (120) - on left: 103 104, on right: 71 75 76 77 94 95 96 97 104 107 129 -expr_list (121) - on left: 105 106, on right: 81 106 -const_expr (122) - on left: 107, on right: 132 149 -exception (123) - on left: 108, on right: 109 157 -exception_field (124) - on left: 109, on right: 180 -func (125) - on left: 110, on right: 174 -func_fields (126) - on left: 111 112 113 114 115, on right: 110 115 -func_fields_import (127) - on left: 116, on right: 113 114 -func_fields_import1 (128) - on left: 117 118 119, on right: 116 118 119 -func_fields_import_result (129) - on left: 120 121, on right: 117 121 -func_fields_body (130) - on left: 122, on right: 111 112 -func_fields_body1 (131) - on left: 123 124 125, on right: 122 124 125 -func_result_body (132) - on left: 126 127, on right: 123 127 -func_body (133) - on left: 128, on right: 126 -func_body1 (134) - on left: 129 130 131, on right: 128 130 131 -offset (135) - on left: 132 133, on right: 134 135 141 142 -elem (136) - on left: 134 135, on right: 175 -table (137) - on left: 136, on right: 172 -table_fields (138) - on left: 137 138 139 140, on right: 136 139 -data (139) - on left: 141 142, on right: 176 -memory (140) - on left: 143, on right: 173 -memory_fields (141) - on left: 144 145 146 147, on right: 143 146 -global (142) - on left: 148, on right: 171 -global_fields (143) - on left: 149 150 151, on right: 148 151 -import_desc (144) - on left: 152 153 154 155 156 157, on right: 158 -import (145) - on left: 158, on right: 178 -inline_import (146) - on left: 159, on right: 113 114 138 145 150 -export_desc (147) - on left: 160 161 162 163 164, on right: 165 -export (148) - on left: 165, on right: 179 -inline_export (149) - on left: 166, on right: 115 139 146 151 -type_def (150) - on left: 167 168, on right: 170 -start (151) - on left: 169, on right: 177 -module_field (152) - on left: 170 171 172 173 174 175 176 177 178 179 180, on right: - 183 184 -module_fields_opt (153) - on left: 181 182, on right: 189 -module_fields (154) - on left: 183 184, on right: 182 184 186 -module (155) - on left: 185, on right: 205 -inline_module (156) - on left: 186, on right: 214 -script_var_opt (157) - on left: 187 188, on right: 192 193 206 -script_module (158) - on left: 189 190 191, on right: 185 194 195 196 197 -action (159) - on left: 192 193, on right: 198 199 200 201 202 203 -assertion (160) - on left: 194 195 196 197 198 199 200 201 202, on right: 204 -cmd (161) - on left: 203 204 205 206, on right: 207 208 -cmd_list (162) - on left: 207 208, on right: 208 213 -const (163) - on left: 209, on right: 211 -const_list (164) - on left: 210 211, on right: 192 198 211 -script (165) - on left: 212 213 214, on right: 215 -script_start (166) - on left: 215, on right: 0 - - -State 0 - - 0 $accept: . script_start "EOF" - - "(" shift, and go to state 1 - - $default reduce using rule 212 (script) - - exception go to state 2 - exception_field go to state 3 - func go to state 4 - elem go to state 5 - table go to state 6 - data go to state 7 - memory go to state 8 - global go to state 9 - import go to state 10 - export go to state 11 - type_def go to state 12 - start go to state 13 - module_field go to state 14 - module_fields go to state 15 - module go to state 16 - inline_module go to state 17 - script_module go to state 18 - action go to state 19 - assertion go to state 20 - cmd go to state 21 - cmd_list go to state 22 - script go to state 23 - script_start go to state 24 - - -State 1 - - 108 exception: "(" . EXCEPT bind_var_opt value_type_list ")" - 110 func: "(" . FUNC bind_var_opt func_fields ")" - 134 elem: "(" . ELEM var offset var_list ")" - 135 | "(" . ELEM offset var_list ")" - 136 table: "(" . TABLE bind_var_opt table_fields ")" - 141 data: "(" . DATA var offset text_list_opt ")" - 142 | "(" . DATA offset text_list_opt ")" - 143 memory: "(" . MEMORY bind_var_opt memory_fields ")" - 148 global: "(" . GLOBAL bind_var_opt global_fields ")" - 158 import: "(" . IMPORT quoted_text quoted_text import_desc ")" - 165 export: "(" . EXPORT quoted_text export_desc ")" - 167 type_def: "(" . TYPE func_type ")" - 168 | "(" . TYPE bind_var func_type ")" - 169 start: "(" . START var ")" - 189 script_module: "(" . MODULE bind_var_opt module_fields_opt ")" - 190 | "(" . MODULE bind_var_opt BIN text_list ")" - 191 | "(" . MODULE bind_var_opt QUOTE text_list ")" - 192 action: "(" . INVOKE script_var_opt quoted_text const_list ")" - 193 | "(" . GET script_var_opt quoted_text ")" - 194 assertion: "(" . ASSERT_MALFORMED script_module quoted_text ")" - 195 | "(" . ASSERT_INVALID script_module quoted_text ")" - 196 | "(" . ASSERT_UNLINKABLE script_module quoted_text ")" - 197 | "(" . ASSERT_TRAP script_module quoted_text ")" - 198 | "(" . ASSERT_RETURN action const_list ")" - 199 | "(" . ASSERT_RETURN_CANONICAL_NAN action ")" - 200 | "(" . ASSERT_RETURN_ARITHMETIC_NAN action ")" - 201 | "(" . ASSERT_TRAP action quoted_text ")" - 202 | "(" . ASSERT_EXHAUSTION action quoted_text ")" - 206 cmd: "(" . REGISTER quoted_text script_var_opt ")" - - FUNC shift, and go to state 25 - START shift, and go to state 26 - TYPE shift, and go to state 27 - GLOBAL shift, and go to state 28 - TABLE shift, and go to state 29 - ELEM shift, and go to state 30 - MEMORY shift, and go to state 31 - DATA shift, and go to state 32 - IMPORT shift, and go to state 33 - EXPORT shift, and go to state 34 - EXCEPT shift, and go to state 35 - MODULE shift, and go to state 36 - REGISTER shift, and go to state 37 - INVOKE shift, and go to state 38 - GET shift, and go to state 39 - ASSERT_MALFORMED shift, and go to state 40 - ASSERT_INVALID shift, and go to state 41 - ASSERT_UNLINKABLE shift, and go to state 42 - ASSERT_RETURN shift, and go to state 43 - ASSERT_RETURN_CANONICAL_NAN shift, and go to state 44 - ASSERT_RETURN_ARITHMETIC_NAN shift, and go to state 45 - ASSERT_TRAP shift, and go to state 46 - ASSERT_EXHAUSTION shift, and go to state 47 - - -State 2 - - 109 exception_field: exception . - - $default reduce using rule 109 (exception_field) - - -State 3 - - 180 module_field: exception_field . - - $default reduce using rule 180 (module_field) - - -State 4 - - 174 module_field: func . - - $default reduce using rule 174 (module_field) - - -State 5 - - 175 module_field: elem . - - $default reduce using rule 175 (module_field) - - -State 6 - - 172 module_field: table . - - $default reduce using rule 172 (module_field) - - -State 7 - - 176 module_field: data . - - $default reduce using rule 176 (module_field) - - -State 8 - - 173 module_field: memory . - - $default reduce using rule 173 (module_field) - - -State 9 - - 171 module_field: global . - - $default reduce using rule 171 (module_field) - - -State 10 - - 178 module_field: import . - - $default reduce using rule 178 (module_field) - - -State 11 - - 179 module_field: export . - - $default reduce using rule 179 (module_field) - - -State 12 - - 170 module_field: type_def . - - $default reduce using rule 170 (module_field) - - -State 13 - - 177 module_field: start . - - $default reduce using rule 177 (module_field) - - -State 14 - - 183 module_fields: module_field . - - $default reduce using rule 183 (module_fields) - - -State 15 - - 184 module_fields: module_fields . module_field - 186 inline_module: module_fields . - - "(" shift, and go to state 48 - - $default reduce using rule 186 (inline_module) - - exception go to state 2 - exception_field go to state 3 - func go to state 4 - elem go to state 5 - table go to state 6 - data go to state 7 - memory go to state 8 - global go to state 9 - import go to state 10 - export go to state 11 - type_def go to state 12 - start go to state 13 - module_field go to state 49 - - -State 16 - - 205 cmd: module . - - $default reduce using rule 205 (cmd) - - -State 17 - - 214 script: inline_module . - - $default reduce using rule 214 (script) - - -State 18 - - 185 module: script_module . - - $default reduce using rule 185 (module) - - -State 19 - - 203 cmd: action . - - $default reduce using rule 203 (cmd) - - -State 20 - - 204 cmd: assertion . - - $default reduce using rule 204 (cmd) - - -State 21 - - 207 cmd_list: cmd . - - $default reduce using rule 207 (cmd_list) - - -State 22 - - 208 cmd_list: cmd_list . cmd - 213 script: cmd_list . - - "(" shift, and go to state 50 - - $default reduce using rule 213 (script) - - module go to state 16 - script_module go to state 18 - action go to state 19 - assertion go to state 20 - cmd go to state 51 - - -State 23 - - 215 script_start: script . - - $default reduce using rule 215 (script_start) - - -State 24 - - 0 $accept: script_start . "EOF" - - "EOF" shift, and go to state 52 - - -State 25 - - 110 func: "(" FUNC . bind_var_opt func_fields ")" - - VAR shift, and go to state 53 - - $default reduce using rule 30 (bind_var_opt) - - bind_var_opt go to state 54 - bind_var go to state 55 - - -State 26 - - 169 start: "(" START . var ")" - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 59 - - -State 27 - - 167 type_def: "(" TYPE . func_type ")" - 168 | "(" TYPE . bind_var func_type ")" - - "(" shift, and go to state 60 - VAR shift, and go to state 53 - - func_type go to state 61 - bind_var go to state 62 - - -State 28 - - 148 global: "(" GLOBAL . bind_var_opt global_fields ")" - - VAR shift, and go to state 53 - - $default reduce using rule 30 (bind_var_opt) - - bind_var_opt go to state 63 - bind_var go to state 55 - - -State 29 - - 136 table: "(" TABLE . bind_var_opt table_fields ")" - - VAR shift, and go to state 53 - - $default reduce using rule 30 (bind_var_opt) - - bind_var_opt go to state 64 - bind_var go to state 55 - - -State 30 - - 134 elem: "(" ELEM . var offset var_list ")" - 135 | "(" ELEM . offset var_list ")" - - "(" shift, and go to state 65 - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 66 - expr go to state 67 - offset go to state 68 - - -State 31 - - 143 memory: "(" MEMORY . bind_var_opt memory_fields ")" - - VAR shift, and go to state 53 - - $default reduce using rule 30 (bind_var_opt) - - bind_var_opt go to state 69 - bind_var go to state 55 - - -State 32 - - 141 data: "(" DATA . var offset text_list_opt ")" - 142 | "(" DATA . offset text_list_opt ")" - - "(" shift, and go to state 65 - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 70 - expr go to state 67 - offset go to state 71 - - -State 33 - - 158 import: "(" IMPORT . quoted_text quoted_text import_desc ")" - - TEXT shift, and go to state 72 - - quoted_text go to state 73 - - -State 34 - - 165 export: "(" EXPORT . quoted_text export_desc ")" - - TEXT shift, and go to state 72 - - quoted_text go to state 74 - - -State 35 - - 108 exception: "(" EXCEPT . bind_var_opt value_type_list ")" - - VAR shift, and go to state 53 - - $default reduce using rule 30 (bind_var_opt) - - bind_var_opt go to state 75 - bind_var go to state 55 - - -State 36 - - 189 script_module: "(" MODULE . bind_var_opt module_fields_opt ")" - 190 | "(" MODULE . bind_var_opt BIN text_list ")" - 191 | "(" MODULE . bind_var_opt QUOTE text_list ")" - - VAR shift, and go to state 53 - - $default reduce using rule 30 (bind_var_opt) - - bind_var_opt go to state 76 - bind_var go to state 55 - - -State 37 - - 206 cmd: "(" REGISTER . quoted_text script_var_opt ")" - - TEXT shift, and go to state 72 - - quoted_text go to state 77 - - -State 38 - - 192 action: "(" INVOKE . script_var_opt quoted_text const_list ")" - - VAR shift, and go to state 78 - - $default reduce using rule 187 (script_var_opt) - - script_var_opt go to state 79 - - -State 39 - - 193 action: "(" GET . script_var_opt quoted_text ")" - - VAR shift, and go to state 78 - - $default reduce using rule 187 (script_var_opt) - - script_var_opt go to state 80 - - -State 40 - - 194 assertion: "(" ASSERT_MALFORMED . script_module quoted_text ")" - - "(" shift, and go to state 81 - - script_module go to state 82 - - -State 41 - - 195 assertion: "(" ASSERT_INVALID . script_module quoted_text ")" - - "(" shift, and go to state 81 - - script_module go to state 83 - - -State 42 - - 196 assertion: "(" ASSERT_UNLINKABLE . script_module quoted_text ")" - - "(" shift, and go to state 81 - - script_module go to state 84 - - -State 43 - - 198 assertion: "(" ASSERT_RETURN . action const_list ")" - - "(" shift, and go to state 85 - - action go to state 86 - - -State 44 - - 199 assertion: "(" ASSERT_RETURN_CANONICAL_NAN . action ")" - - "(" shift, and go to state 85 - - action go to state 87 - - -State 45 - - 200 assertion: "(" ASSERT_RETURN_ARITHMETIC_NAN . action ")" - - "(" shift, and go to state 85 - - action go to state 88 - - -State 46 - - 197 assertion: "(" ASSERT_TRAP . script_module quoted_text ")" - 201 | "(" ASSERT_TRAP . action quoted_text ")" - - "(" shift, and go to state 89 - - script_module go to state 90 - action go to state 91 - - -State 47 - - 202 assertion: "(" ASSERT_EXHAUSTION . action quoted_text ")" - - "(" shift, and go to state 85 - - action go to state 92 - - -State 48 - - 108 exception: "(" . EXCEPT bind_var_opt value_type_list ")" - 110 func: "(" . FUNC bind_var_opt func_fields ")" - 134 elem: "(" . ELEM var offset var_list ")" - 135 | "(" . ELEM offset var_list ")" - 136 table: "(" . TABLE bind_var_opt table_fields ")" - 141 data: "(" . DATA var offset text_list_opt ")" - 142 | "(" . DATA offset text_list_opt ")" - 143 memory: "(" . MEMORY bind_var_opt memory_fields ")" - 148 global: "(" . GLOBAL bind_var_opt global_fields ")" - 158 import: "(" . IMPORT quoted_text quoted_text import_desc ")" - 165 export: "(" . EXPORT quoted_text export_desc ")" - 167 type_def: "(" . TYPE func_type ")" - 168 | "(" . TYPE bind_var func_type ")" - 169 start: "(" . START var ")" - - FUNC shift, and go to state 25 - START shift, and go to state 26 - TYPE shift, and go to state 27 - GLOBAL shift, and go to state 28 - TABLE shift, and go to state 29 - ELEM shift, and go to state 30 - MEMORY shift, and go to state 31 - DATA shift, and go to state 32 - IMPORT shift, and go to state 33 - EXPORT shift, and go to state 34 - EXCEPT shift, and go to state 35 - - -State 49 - - 184 module_fields: module_fields module_field . - - $default reduce using rule 184 (module_fields) - - -State 50 - - 189 script_module: "(" . MODULE bind_var_opt module_fields_opt ")" - 190 | "(" . MODULE bind_var_opt BIN text_list ")" - 191 | "(" . MODULE bind_var_opt QUOTE text_list ")" - 192 action: "(" . INVOKE script_var_opt quoted_text const_list ")" - 193 | "(" . GET script_var_opt quoted_text ")" - 194 assertion: "(" . ASSERT_MALFORMED script_module quoted_text ")" - 195 | "(" . ASSERT_INVALID script_module quoted_text ")" - 196 | "(" . ASSERT_UNLINKABLE script_module quoted_text ")" - 197 | "(" . ASSERT_TRAP script_module quoted_text ")" - 198 | "(" . ASSERT_RETURN action const_list ")" - 199 | "(" . ASSERT_RETURN_CANONICAL_NAN action ")" - 200 | "(" . ASSERT_RETURN_ARITHMETIC_NAN action ")" - 201 | "(" . ASSERT_TRAP action quoted_text ")" - 202 | "(" . ASSERT_EXHAUSTION action quoted_text ")" - 206 cmd: "(" . REGISTER quoted_text script_var_opt ")" - - MODULE shift, and go to state 36 - REGISTER shift, and go to state 37 - INVOKE shift, and go to state 38 - GET shift, and go to state 39 - ASSERT_MALFORMED shift, and go to state 40 - ASSERT_INVALID shift, and go to state 41 - ASSERT_UNLINKABLE shift, and go to state 42 - ASSERT_RETURN shift, and go to state 43 - ASSERT_RETURN_CANONICAL_NAN shift, and go to state 44 - ASSERT_RETURN_ARITHMETIC_NAN shift, and go to state 45 - ASSERT_TRAP shift, and go to state 46 - ASSERT_EXHAUSTION shift, and go to state 47 - - -State 51 - - 208 cmd_list: cmd_list cmd . - - $default reduce using rule 208 (cmd_list) - - -State 52 - - 0 $accept: script_start "EOF" . - - $default accept - - -State 53 - - 32 bind_var: VAR . - - $default reduce using rule 32 (bind_var) - - -State 54 - - 110 func: "(" FUNC bind_var_opt . func_fields ")" - - "(" shift, and go to state 93 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - type_use go to state 124 - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 132 - func_fields go to state 133 - func_fields_body go to state 134 - func_fields_body1 go to state 135 - func_result_body go to state 136 - func_body go to state 137 - func_body1 go to state 138 - inline_import go to state 139 - inline_export go to state 140 - - -State 55 - - 31 bind_var_opt: bind_var . - - $default reduce using rule 31 (bind_var_opt) - - -State 56 - - 22 nat: NAT . - - $default reduce using rule 22 (nat) - - -State 57 - - 27 var: VAR . - - $default reduce using rule 27 (var) - - -State 58 - - 26 var: nat . - - $default reduce using rule 26 (var) - - -State 59 - - 169 start: "(" START var . ")" - - ")" shift, and go to state 141 - - -State 60 - - 11 func_type: "(" . FUNC func_sig ")" - - FUNC shift, and go to state 142 - - -State 61 - - 167 type_def: "(" TYPE func_type . ")" - - ")" shift, and go to state 143 - - -State 62 - - 168 type_def: "(" TYPE bind_var . func_type ")" - - "(" shift, and go to state 60 - - func_type go to state 144 - - -State 63 - - 148 global: "(" GLOBAL bind_var_opt . global_fields ")" - - "(" shift, and go to state 145 - VALUE_TYPE shift, and go to state 146 - - global_type go to state 147 - global_fields go to state 148 - inline_import go to state 149 - inline_export go to state 150 - - -State 64 - - 136 table: "(" TABLE bind_var_opt . table_fields ")" - - "(" shift, and go to state 151 - NAT shift, and go to state 56 - ANYFUNC shift, and go to state 152 - - elem_type go to state 153 - table_sig go to state 154 - limits go to state 155 - nat go to state 156 - table_fields go to state 157 - inline_import go to state 158 - inline_export go to state 159 - - -State 65 - - 80 expr: "(" . expr1 ")" - 132 offset: "(" . OFFSET const_expr ")" - - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 160 - IF shift, and go to state 161 - LOOP shift, and go to state 162 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - OFFSET shift, and go to state 163 - - plain_instr go to state 164 - expr1 go to state 165 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 166 - - -State 66 - - 134 elem: "(" ELEM var . offset var_list ")" - - "(" shift, and go to state 65 - - expr go to state 67 - offset go to state 167 - - -State 67 - - 133 offset: expr . - - $default reduce using rule 133 (offset) - - -State 68 - - 135 elem: "(" ELEM offset . var_list ")" - - $default reduce using rule 28 (var_list) - - var_list go to state 168 - - -State 69 - - 143 memory: "(" MEMORY bind_var_opt . memory_fields ")" - - "(" shift, and go to state 169 - NAT shift, and go to state 56 - - memory_sig go to state 170 - limits go to state 171 - nat go to state 156 - memory_fields go to state 172 - inline_import go to state 173 - inline_export go to state 174 - - -State 70 - - 141 data: "(" DATA var . offset text_list_opt ")" - - "(" shift, and go to state 65 - - expr go to state 67 - offset go to state 175 - - -State 71 - - 142 data: "(" DATA offset . text_list_opt ")" - - TEXT shift, and go to state 176 - - $default reduce using rule 3 (text_list_opt) - - text_list go to state 177 - text_list_opt go to state 178 - - -State 72 - - 5 quoted_text: TEXT . - - $default reduce using rule 5 (quoted_text) - - -State 73 - - 158 import: "(" IMPORT quoted_text . quoted_text import_desc ")" - - TEXT shift, and go to state 72 - - quoted_text go to state 179 - - -State 74 - - 165 export: "(" EXPORT quoted_text . export_desc ")" - - "(" shift, and go to state 180 - - export_desc go to state 181 - - -State 75 - - 108 exception: "(" EXCEPT bind_var_opt . value_type_list ")" - - $default reduce using rule 6 (value_type_list) - - value_type_list go to state 182 - - -State 76 - - 189 script_module: "(" MODULE bind_var_opt . module_fields_opt ")" - 190 | "(" MODULE bind_var_opt . BIN text_list ")" - 191 | "(" MODULE bind_var_opt . QUOTE text_list ")" - - "(" shift, and go to state 48 - BIN shift, and go to state 183 - QUOTE shift, and go to state 184 - - $default reduce using rule 181 (module_fields_opt) - - exception go to state 2 - exception_field go to state 3 - func go to state 4 - elem go to state 5 - table go to state 6 - data go to state 7 - memory go to state 8 - global go to state 9 - import go to state 10 - export go to state 11 - type_def go to state 12 - start go to state 13 - module_field go to state 14 - module_fields_opt go to state 185 - module_fields go to state 186 - - -State 77 - - 206 cmd: "(" REGISTER quoted_text . script_var_opt ")" - - VAR shift, and go to state 78 - - $default reduce using rule 187 (script_var_opt) - - script_var_opt go to state 187 - - -State 78 - - 188 script_var_opt: VAR . - - $default reduce using rule 188 (script_var_opt) - - -State 79 - - 192 action: "(" INVOKE script_var_opt . quoted_text const_list ")" - - TEXT shift, and go to state 72 - - quoted_text go to state 188 - - -State 80 - - 193 action: "(" GET script_var_opt . quoted_text ")" - - TEXT shift, and go to state 72 - - quoted_text go to state 189 - - -State 81 - - 189 script_module: "(" . MODULE bind_var_opt module_fields_opt ")" - 190 | "(" . MODULE bind_var_opt BIN text_list ")" - 191 | "(" . MODULE bind_var_opt QUOTE text_list ")" - - MODULE shift, and go to state 36 - - -State 82 - - 194 assertion: "(" ASSERT_MALFORMED script_module . quoted_text ")" - - TEXT shift, and go to state 72 - - quoted_text go to state 190 - - -State 83 - - 195 assertion: "(" ASSERT_INVALID script_module . quoted_text ")" - - TEXT shift, and go to state 72 - - quoted_text go to state 191 - - -State 84 - - 196 assertion: "(" ASSERT_UNLINKABLE script_module . quoted_text ")" - - TEXT shift, and go to state 72 - - quoted_text go to state 192 - - -State 85 - - 192 action: "(" . INVOKE script_var_opt quoted_text const_list ")" - 193 | "(" . GET script_var_opt quoted_text ")" - - INVOKE shift, and go to state 38 - GET shift, and go to state 39 - - -State 86 - - 198 assertion: "(" ASSERT_RETURN action . const_list ")" - - $default reduce using rule 210 (const_list) - - const_list go to state 193 - - -State 87 - - 199 assertion: "(" ASSERT_RETURN_CANONICAL_NAN action . ")" - - ")" shift, and go to state 194 - - -State 88 - - 200 assertion: "(" ASSERT_RETURN_ARITHMETIC_NAN action . ")" - - ")" shift, and go to state 195 - - -State 89 - - 189 script_module: "(" . MODULE bind_var_opt module_fields_opt ")" - 190 | "(" . MODULE bind_var_opt BIN text_list ")" - 191 | "(" . MODULE bind_var_opt QUOTE text_list ")" - 192 action: "(" . INVOKE script_var_opt quoted_text const_list ")" - 193 | "(" . GET script_var_opt quoted_text ")" - - MODULE shift, and go to state 36 - INVOKE shift, and go to state 38 - GET shift, and go to state 39 - - -State 90 - - 197 assertion: "(" ASSERT_TRAP script_module . quoted_text ")" - - TEXT shift, and go to state 72 - - quoted_text go to state 196 - - -State 91 - - 201 assertion: "(" ASSERT_TRAP action . quoted_text ")" - - TEXT shift, and go to state 72 - - quoted_text go to state 197 - - -State 92 - - 202 assertion: "(" ASSERT_EXHAUSTION action . quoted_text ")" - - TEXT shift, and go to state 72 - - quoted_text go to state 198 - - -State 93 - - 21 type_use: "(" . TYPE var ")" - 80 expr: "(" . expr1 ")" - 124 func_fields_body1: "(" . PARAM value_type_list ")" func_fields_body1 - 125 | "(" . PARAM bind_var VALUE_TYPE ")" func_fields_body1 - 127 func_result_body: "(" . RESULT value_type_list ")" func_result_body - 130 func_body1: "(" . LOCAL value_type_list ")" func_body1 - 131 | "(" . LOCAL bind_var VALUE_TYPE ")" func_body1 - 159 inline_import: "(" . IMPORT quoted_text quoted_text ")" - 166 inline_export: "(" . EXPORT quoted_text ")" - - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 160 - IF shift, and go to state 161 - LOOP shift, and go to state 162 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - TYPE shift, and go to state 199 - PARAM shift, and go to state 200 - RESULT shift, and go to state 201 - LOCAL shift, and go to state 202 - IMPORT shift, and go to state 203 - EXPORT shift, and go to state 204 - - plain_instr go to state 164 - expr1 go to state 165 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 166 - - -State 94 - - 43 plain_instr: NOP . - - $default reduce using rule 43 (plain_instr) - - -State 95 - - 44 plain_instr: DROP . - - $default reduce using rule 44 (plain_instr) - - -State 96 - - 68 block_instr: BLOCK . labeling_opt block END labeling_opt - - VAR shift, and go to state 53 - - $default reduce using rule 33 (labeling_opt) - - bind_var go to state 205 - labeling_opt go to state 206 - - -State 97 - - 70 block_instr: IF . labeling_opt block END labeling_opt - 71 | IF . labeling_opt block ELSE labeling_opt instr_list END labeling_opt - - VAR shift, and go to state 53 - - $default reduce using rule 33 (labeling_opt) - - bind_var go to state 205 - labeling_opt go to state 207 - - -State 98 - - 69 block_instr: LOOP . labeling_opt block END labeling_opt - - VAR shift, and go to state 53 - - $default reduce using rule 33 (labeling_opt) - - bind_var go to state 205 - labeling_opt go to state 208 - - -State 99 - - 46 plain_instr: BR . var - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 209 - - -State 100 - - 47 plain_instr: BR_IF . var - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 210 - - -State 101 - - 48 plain_instr: BR_TABLE . var_list var - - $default reduce using rule 28 (var_list) - - var_list go to state 211 - - -State 102 - - 102 try_check: TRY . - - $default reduce using rule 102 (try_check) - - -State 103 - - 101 throw_check: THROW . - - $default reduce using rule 101 (throw_check) - - -State 104 - - 100 rethrow_check: RETHROW . - - $default reduce using rule 100 (rethrow_check) - - -State 105 - - 50 plain_instr: CALL . var - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 212 - - -State 106 - - 51 plain_instr: CALL_INDIRECT . var - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 213 - - -State 107 - - 49 plain_instr: RETURN . - - $default reduce using rule 49 (plain_instr) - - -State 108 - - 52 plain_instr: GET_LOCAL . var - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 214 - - -State 109 - - 53 plain_instr: SET_LOCAL . var - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 215 - - -State 110 - - 54 plain_instr: TEE_LOCAL . var - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 216 - - -State 111 - - 55 plain_instr: GET_GLOBAL . var - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 217 - - -State 112 - - 56 plain_instr: SET_GLOBAL . var - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 218 - - -State 113 - - 57 plain_instr: LOAD . offset_opt align_opt - - OFFSET_EQ_NAT shift, and go to state 219 - - $default reduce using rule 35 (offset_opt) - - offset_opt go to state 220 - - -State 114 - - 58 plain_instr: STORE . offset_opt align_opt - - OFFSET_EQ_NAT shift, and go to state 219 - - $default reduce using rule 35 (offset_opt) - - offset_opt go to state 221 - - -State 115 - - 59 plain_instr: CONST . literal - - NAT shift, and go to state 222 - INT shift, and go to state 223 - FLOAT shift, and go to state 224 - - literal go to state 225 - - -State 116 - - 60 plain_instr: UNARY . - - $default reduce using rule 60 (plain_instr) - - -State 117 - - 61 plain_instr: BINARY . - - $default reduce using rule 61 (plain_instr) - - -State 118 - - 62 plain_instr: COMPARE . - - $default reduce using rule 62 (plain_instr) - - -State 119 - - 63 plain_instr: CONVERT . - - $default reduce using rule 63 (plain_instr) - - -State 120 - - 45 plain_instr: SELECT . - - $default reduce using rule 45 (plain_instr) - - -State 121 - - 42 plain_instr: UNREACHABLE . - - $default reduce using rule 42 (plain_instr) - - -State 122 - - 64 plain_instr: CURRENT_MEMORY . - - $default reduce using rule 64 (plain_instr) - - -State 123 - - 65 plain_instr: GROW_MEMORY . - - $default reduce using rule 65 (plain_instr) - - -State 124 - - 111 func_fields: type_use . func_fields_body - - "(" shift, and go to state 226 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 132 - func_fields_body go to state 227 - func_fields_body1 go to state 135 - func_result_body go to state 136 - func_body go to state 137 - func_body1 go to state 138 - - -State 125 - - 104 instr_list: instr . instr_list - - "(" shift, and go to state 228 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 229 - - -State 126 - - 39 instr: plain_instr . - - $default reduce using rule 39 (instr) - - -State 127 - - 40 instr: block_instr . - - $default reduce using rule 40 (instr) - - -State 128 - - 41 instr: expr . - - $default reduce using rule 41 (instr) - - -State 129 - - 67 plain_instr: rethrow_check . var - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 230 - - -State 130 - - 66 plain_instr: throw_check . var - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 231 - - -State 131 - - 72 block_instr: try_check . labeling_opt block catch_instr_list END labeling_opt - - VAR shift, and go to state 53 - - $default reduce using rule 33 (labeling_opt) - - bind_var go to state 205 - labeling_opt go to state 232 - - -State 132 - - 129 func_body1: instr_list . - - $default reduce using rule 129 (func_body1) - - -State 133 - - 110 func: "(" FUNC bind_var_opt func_fields . ")" - - ")" shift, and go to state 233 - - -State 134 - - 112 func_fields: func_fields_body . - - $default reduce using rule 112 (func_fields) - - -State 135 - - 122 func_fields_body: func_fields_body1 . - - $default reduce using rule 122 (func_fields_body) - - -State 136 - - 123 func_fields_body1: func_result_body . - - $default reduce using rule 123 (func_fields_body1) - - -State 137 - - 126 func_result_body: func_body . - - $default reduce using rule 126 (func_result_body) - - -State 138 - - 128 func_body: func_body1 . - - $default reduce using rule 128 (func_body) - - -State 139 - - 113 func_fields: inline_import . type_use func_fields_import - 114 | inline_import . func_fields_import - - "(" shift, and go to state 234 - - $default reduce using rule 120 (func_fields_import_result) - - type_use go to state 235 - func_fields_import go to state 236 - func_fields_import1 go to state 237 - func_fields_import_result go to state 238 - - -State 140 - - 115 func_fields: inline_export . func_fields - - "(" shift, and go to state 93 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - type_use go to state 124 - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 132 - func_fields go to state 239 - func_fields_body go to state 134 - func_fields_body1 go to state 135 - func_result_body go to state 136 - func_body go to state 137 - func_body1 go to state 138 - inline_import go to state 139 - inline_export go to state 140 - - -State 141 - - 169 start: "(" START var ")" . - - $default reduce using rule 169 (start) - - -State 142 - - 11 func_type: "(" FUNC . func_sig ")" - - "(" shift, and go to state 240 - - $default reduce using rule 15 (func_sig_result) - - func_sig go to state 241 - func_sig_result go to state 242 - - -State 143 - - 167 type_def: "(" TYPE func_type ")" . - - $default reduce using rule 167 (type_def) - - -State 144 - - 168 type_def: "(" TYPE bind_var func_type . ")" - - ")" shift, and go to state 243 - - -State 145 - - 10 global_type: "(" . MUT VALUE_TYPE ")" - 159 inline_import: "(" . IMPORT quoted_text quoted_text ")" - 166 inline_export: "(" . EXPORT quoted_text ")" - - MUT shift, and go to state 244 - IMPORT shift, and go to state 203 - EXPORT shift, and go to state 204 - - -State 146 - - 9 global_type: VALUE_TYPE . - - $default reduce using rule 9 (global_type) - - -State 147 - - 149 global_fields: global_type . const_expr - - "(" shift, and go to state 228 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 245 - const_expr go to state 246 - - -State 148 - - 148 global: "(" GLOBAL bind_var_opt global_fields . ")" - - ")" shift, and go to state 247 - - -State 149 - - 150 global_fields: inline_import . global_type - - "(" shift, and go to state 248 - VALUE_TYPE shift, and go to state 146 - - global_type go to state 249 - - -State 150 - - 151 global_fields: inline_export . global_fields - - "(" shift, and go to state 145 - VALUE_TYPE shift, and go to state 146 - - global_type go to state 147 - global_fields go to state 250 - inline_import go to state 149 - inline_export go to state 150 - - -State 151 - - 159 inline_import: "(" . IMPORT quoted_text quoted_text ")" - 166 inline_export: "(" . EXPORT quoted_text ")" - - IMPORT shift, and go to state 203 - EXPORT shift, and go to state 204 - - -State 152 - - 8 elem_type: ANYFUNC . - - $default reduce using rule 8 (elem_type) - - -State 153 - - 140 table_fields: elem_type . "(" ELEM var_list ")" - - "(" shift, and go to state 251 - - -State 154 - - 137 table_fields: table_sig . - - $default reduce using rule 137 (table_fields) - - -State 155 - - 17 table_sig: limits . elem_type - - ANYFUNC shift, and go to state 152 - - elem_type go to state 252 - - -State 156 - - 19 limits: nat . - 20 | nat . nat - - NAT shift, and go to state 56 - - $default reduce using rule 19 (limits) - - nat go to state 253 - - -State 157 - - 136 table: "(" TABLE bind_var_opt table_fields . ")" - - ")" shift, and go to state 254 - - -State 158 - - 138 table_fields: inline_import . table_sig - - NAT shift, and go to state 56 - - table_sig go to state 255 - limits go to state 155 - nat go to state 156 - - -State 159 - - 139 table_fields: inline_export . table_fields - - "(" shift, and go to state 151 - NAT shift, and go to state 56 - ANYFUNC shift, and go to state 152 - - elem_type go to state 153 - table_sig go to state 154 - limits go to state 155 - nat go to state 156 - table_fields go to state 256 - inline_import go to state 158 - inline_export go to state 159 - - -State 160 - - 82 expr1: BLOCK . labeling_opt block - - VAR shift, and go to state 53 - - $default reduce using rule 33 (labeling_opt) - - bind_var go to state 205 - labeling_opt go to state 257 - - -State 161 - - 84 expr1: IF . labeling_opt if_block - - VAR shift, and go to state 53 - - $default reduce using rule 33 (labeling_opt) - - bind_var go to state 205 - labeling_opt go to state 258 - - -State 162 - - 83 expr1: LOOP . labeling_opt block - - VAR shift, and go to state 53 - - $default reduce using rule 33 (labeling_opt) - - bind_var go to state 205 - labeling_opt go to state 259 - - -State 163 - - 132 offset: "(" OFFSET . const_expr ")" - - "(" shift, and go to state 228 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 245 - const_expr go to state 260 - - -State 164 - - 81 expr1: plain_instr . expr_list - - "(" shift, and go to state 228 - - $default reduce using rule 105 (expr_list) - - expr go to state 261 - expr_list go to state 262 - - -State 165 - - 80 expr: "(" expr1 . ")" - - ")" shift, and go to state 263 - - -State 166 - - 85 expr1: try_check . labeling_opt try_ - - VAR shift, and go to state 53 - - $default reduce using rule 33 (labeling_opt) - - bind_var go to state 205 - labeling_opt go to state 264 - - -State 167 - - 134 elem: "(" ELEM var offset . var_list ")" - - $default reduce using rule 28 (var_list) - - var_list go to state 265 - - -State 168 - - 29 var_list: var_list . var - 135 elem: "(" ELEM offset var_list . ")" - - ")" shift, and go to state 266 - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 267 - - -State 169 - - 147 memory_fields: "(" . DATA text_list_opt ")" - 159 inline_import: "(" . IMPORT quoted_text quoted_text ")" - 166 inline_export: "(" . EXPORT quoted_text ")" - - DATA shift, and go to state 268 - IMPORT shift, and go to state 203 - EXPORT shift, and go to state 204 - - -State 170 - - 144 memory_fields: memory_sig . - - $default reduce using rule 144 (memory_fields) - - -State 171 - - 18 memory_sig: limits . - - $default reduce using rule 18 (memory_sig) - - -State 172 - - 143 memory: "(" MEMORY bind_var_opt memory_fields . ")" - - ")" shift, and go to state 269 - - -State 173 - - 145 memory_fields: inline_import . memory_sig - - NAT shift, and go to state 56 - - memory_sig go to state 270 - limits go to state 171 - nat go to state 156 - - -State 174 - - 146 memory_fields: inline_export . memory_fields - - "(" shift, and go to state 169 - NAT shift, and go to state 56 - - memory_sig go to state 170 - limits go to state 171 - nat go to state 156 - memory_fields go to state 271 - inline_import go to state 173 - inline_export go to state 174 - - -State 175 - - 141 data: "(" DATA var offset . text_list_opt ")" - - TEXT shift, and go to state 176 - - $default reduce using rule 3 (text_list_opt) - - text_list go to state 177 - text_list_opt go to state 272 - - -State 176 - - 1 text_list: TEXT . - - $default reduce using rule 1 (text_list) - - -State 177 - - 2 text_list: text_list . TEXT - 4 text_list_opt: text_list . - - TEXT shift, and go to state 273 - - $default reduce using rule 4 (text_list_opt) - - -State 178 - - 142 data: "(" DATA offset text_list_opt . ")" - - ")" shift, and go to state 274 - - -State 179 - - 158 import: "(" IMPORT quoted_text quoted_text . import_desc ")" - - "(" shift, and go to state 275 - - exception go to state 276 - import_desc go to state 277 - - -State 180 - - 160 export_desc: "(" . FUNC var ")" - 161 | "(" . TABLE var ")" - 162 | "(" . MEMORY var ")" - 163 | "(" . GLOBAL var ")" - 164 | "(" . EXCEPT var ")" - - FUNC shift, and go to state 278 - GLOBAL shift, and go to state 279 - TABLE shift, and go to state 280 - MEMORY shift, and go to state 281 - EXCEPT shift, and go to state 282 - - -State 181 - - 165 export: "(" EXPORT quoted_text export_desc . ")" - - ")" shift, and go to state 283 - - -State 182 - - 7 value_type_list: value_type_list . VALUE_TYPE - 108 exception: "(" EXCEPT bind_var_opt value_type_list . ")" - - ")" shift, and go to state 284 - VALUE_TYPE shift, and go to state 285 - - -State 183 - - 190 script_module: "(" MODULE bind_var_opt BIN . text_list ")" - - TEXT shift, and go to state 176 - - text_list go to state 286 - - -State 184 - - 191 script_module: "(" MODULE bind_var_opt QUOTE . text_list ")" - - TEXT shift, and go to state 176 - - text_list go to state 287 - - -State 185 - - 189 script_module: "(" MODULE bind_var_opt module_fields_opt . ")" - - ")" shift, and go to state 288 - - -State 186 - - 182 module_fields_opt: module_fields . - 184 module_fields: module_fields . module_field - - "(" shift, and go to state 48 - - $default reduce using rule 182 (module_fields_opt) - - exception go to state 2 - exception_field go to state 3 - func go to state 4 - elem go to state 5 - table go to state 6 - data go to state 7 - memory go to state 8 - global go to state 9 - import go to state 10 - export go to state 11 - type_def go to state 12 - start go to state 13 - module_field go to state 49 - - -State 187 - - 206 cmd: "(" REGISTER quoted_text script_var_opt . ")" - - ")" shift, and go to state 289 - - -State 188 - - 192 action: "(" INVOKE script_var_opt quoted_text . const_list ")" - - $default reduce using rule 210 (const_list) - - const_list go to state 290 - - -State 189 - - 193 action: "(" GET script_var_opt quoted_text . ")" - - ")" shift, and go to state 291 - - -State 190 - - 194 assertion: "(" ASSERT_MALFORMED script_module quoted_text . ")" - - ")" shift, and go to state 292 - - -State 191 - - 195 assertion: "(" ASSERT_INVALID script_module quoted_text . ")" - - ")" shift, and go to state 293 - - -State 192 - - 196 assertion: "(" ASSERT_UNLINKABLE script_module quoted_text . ")" - - ")" shift, and go to state 294 - - -State 193 - - 198 assertion: "(" ASSERT_RETURN action const_list . ")" - 211 const_list: const_list . const - - "(" shift, and go to state 295 - ")" shift, and go to state 296 - - const go to state 297 - - -State 194 - - 199 assertion: "(" ASSERT_RETURN_CANONICAL_NAN action ")" . - - $default reduce using rule 199 (assertion) - - -State 195 - - 200 assertion: "(" ASSERT_RETURN_ARITHMETIC_NAN action ")" . - - $default reduce using rule 200 (assertion) - - -State 196 - - 197 assertion: "(" ASSERT_TRAP script_module quoted_text . ")" - - ")" shift, and go to state 298 - - -State 197 - - 201 assertion: "(" ASSERT_TRAP action quoted_text . ")" - - ")" shift, and go to state 299 - - -State 198 - - 202 assertion: "(" ASSERT_EXHAUSTION action quoted_text . ")" - - ")" shift, and go to state 300 - - -State 199 - - 21 type_use: "(" TYPE . var ")" - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 301 - - -State 200 - - 124 func_fields_body1: "(" PARAM . value_type_list ")" func_fields_body1 - 125 | "(" PARAM . bind_var VALUE_TYPE ")" func_fields_body1 - - VAR shift, and go to state 53 - - $default reduce using rule 6 (value_type_list) - - value_type_list go to state 302 - bind_var go to state 303 - - -State 201 - - 127 func_result_body: "(" RESULT . value_type_list ")" func_result_body - - $default reduce using rule 6 (value_type_list) - - value_type_list go to state 304 - - -State 202 - - 130 func_body1: "(" LOCAL . value_type_list ")" func_body1 - 131 | "(" LOCAL . bind_var VALUE_TYPE ")" func_body1 - - VAR shift, and go to state 53 - - $default reduce using rule 6 (value_type_list) - - value_type_list go to state 305 - bind_var go to state 306 - - -State 203 - - 159 inline_import: "(" IMPORT . quoted_text quoted_text ")" - - TEXT shift, and go to state 72 - - quoted_text go to state 307 - - -State 204 - - 166 inline_export: "(" EXPORT . quoted_text ")" - - TEXT shift, and go to state 72 - - quoted_text go to state 308 - - -State 205 - - 34 labeling_opt: bind_var . - - $default reduce using rule 34 (labeling_opt) - - -State 206 - - 68 block_instr: BLOCK labeling_opt . block END labeling_opt - - "(" shift, and go to state 309 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - block_sig go to state 310 - block go to state 311 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 312 - - -State 207 - - 70 block_instr: IF labeling_opt . block END labeling_opt - 71 | IF labeling_opt . block ELSE labeling_opt instr_list END labeling_opt - - "(" shift, and go to state 309 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - block_sig go to state 310 - block go to state 313 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 312 - - -State 208 - - 69 block_instr: LOOP labeling_opt . block END labeling_opt - - "(" shift, and go to state 309 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - block_sig go to state 310 - block go to state 314 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 312 - - -State 209 - - 46 plain_instr: BR var . - - $default reduce using rule 46 (plain_instr) - - -State 210 - - 47 plain_instr: BR_IF var . - - $default reduce using rule 47 (plain_instr) - - -State 211 - - 29 var_list: var_list . var - 48 plain_instr: BR_TABLE var_list . var - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 315 - - -State 212 - - 50 plain_instr: CALL var . - - $default reduce using rule 50 (plain_instr) - - -State 213 - - 51 plain_instr: CALL_INDIRECT var . - - $default reduce using rule 51 (plain_instr) - - -State 214 - - 52 plain_instr: GET_LOCAL var . - - $default reduce using rule 52 (plain_instr) - - -State 215 - - 53 plain_instr: SET_LOCAL var . - - $default reduce using rule 53 (plain_instr) - - -State 216 - - 54 plain_instr: TEE_LOCAL var . - - $default reduce using rule 54 (plain_instr) - - -State 217 - - 55 plain_instr: GET_GLOBAL var . - - $default reduce using rule 55 (plain_instr) - - -State 218 - - 56 plain_instr: SET_GLOBAL var . - - $default reduce using rule 56 (plain_instr) - - -State 219 - - 36 offset_opt: OFFSET_EQ_NAT . - - $default reduce using rule 36 (offset_opt) - - -State 220 - - 57 plain_instr: LOAD offset_opt . align_opt - - ALIGN_EQ_NAT shift, and go to state 316 - - $default reduce using rule 37 (align_opt) - - align_opt go to state 317 - - -State 221 - - 58 plain_instr: STORE offset_opt . align_opt - - ALIGN_EQ_NAT shift, and go to state 316 - - $default reduce using rule 37 (align_opt) - - align_opt go to state 318 - - -State 222 - - 23 literal: NAT . - - $default reduce using rule 23 (literal) - - -State 223 - - 24 literal: INT . - - $default reduce using rule 24 (literal) - - -State 224 - - 25 literal: FLOAT . - - $default reduce using rule 25 (literal) - - -State 225 - - 59 plain_instr: CONST literal . - - $default reduce using rule 59 (plain_instr) - - -State 226 - - 80 expr: "(" . expr1 ")" - 124 func_fields_body1: "(" . PARAM value_type_list ")" func_fields_body1 - 125 | "(" . PARAM bind_var VALUE_TYPE ")" func_fields_body1 - 127 func_result_body: "(" . RESULT value_type_list ")" func_result_body - 130 func_body1: "(" . LOCAL value_type_list ")" func_body1 - 131 | "(" . LOCAL bind_var VALUE_TYPE ")" func_body1 - - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 160 - IF shift, and go to state 161 - LOOP shift, and go to state 162 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - PARAM shift, and go to state 200 - RESULT shift, and go to state 201 - LOCAL shift, and go to state 202 - - plain_instr go to state 164 - expr1 go to state 165 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 166 - - -State 227 - - 111 func_fields: type_use func_fields_body . - - $default reduce using rule 111 (func_fields) - - -State 228 - - 80 expr: "(" . expr1 ")" - - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 160 - IF shift, and go to state 161 - LOOP shift, and go to state 162 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - plain_instr go to state 164 - expr1 go to state 165 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 166 - - -State 229 - - 104 instr_list: instr instr_list . - - $default reduce using rule 104 (instr_list) - - -State 230 - - 67 plain_instr: rethrow_check var . - - $default reduce using rule 67 (plain_instr) - - -State 231 - - 66 plain_instr: throw_check var . - - $default reduce using rule 66 (plain_instr) - - -State 232 - - 72 block_instr: try_check labeling_opt . block catch_instr_list END labeling_opt - - "(" shift, and go to state 309 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - block_sig go to state 310 - block go to state 319 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 312 - - -State 233 - - 110 func: "(" FUNC bind_var_opt func_fields ")" . - - $default reduce using rule 110 (func) - - -State 234 - - 21 type_use: "(" . TYPE var ")" - 118 func_fields_import1: "(" . PARAM value_type_list ")" func_fields_import1 - 119 | "(" . PARAM bind_var VALUE_TYPE ")" func_fields_import1 - 121 func_fields_import_result: "(" . RESULT value_type_list ")" func_fields_import_result - - TYPE shift, and go to state 199 - PARAM shift, and go to state 320 - RESULT shift, and go to state 321 - - -State 235 - - 113 func_fields: inline_import type_use . func_fields_import - - "(" shift, and go to state 322 - - $default reduce using rule 120 (func_fields_import_result) - - func_fields_import go to state 323 - func_fields_import1 go to state 237 - func_fields_import_result go to state 238 - - -State 236 - - 114 func_fields: inline_import func_fields_import . - - $default reduce using rule 114 (func_fields) - - -State 237 - - 116 func_fields_import: func_fields_import1 . - - $default reduce using rule 116 (func_fields_import) - - -State 238 - - 117 func_fields_import1: func_fields_import_result . - - $default reduce using rule 117 (func_fields_import1) - - -State 239 - - 115 func_fields: inline_export func_fields . - - $default reduce using rule 115 (func_fields) - - -State 240 - - 13 func_sig: "(" . PARAM value_type_list ")" func_sig - 14 | "(" . PARAM bind_var VALUE_TYPE ")" func_sig - 16 func_sig_result: "(" . RESULT value_type_list ")" func_sig_result - - PARAM shift, and go to state 324 - RESULT shift, and go to state 325 - - -State 241 - - 11 func_type: "(" FUNC func_sig . ")" - - ")" shift, and go to state 326 - - -State 242 - - 12 func_sig: func_sig_result . - - $default reduce using rule 12 (func_sig) - - -State 243 - - 168 type_def: "(" TYPE bind_var func_type ")" . - - $default reduce using rule 168 (type_def) - - -State 244 - - 10 global_type: "(" MUT . VALUE_TYPE ")" - - VALUE_TYPE shift, and go to state 327 - - -State 245 - - 107 const_expr: instr_list . - - $default reduce using rule 107 (const_expr) - - -State 246 - - 149 global_fields: global_type const_expr . - - $default reduce using rule 149 (global_fields) - - -State 247 - - 148 global: "(" GLOBAL bind_var_opt global_fields ")" . - - $default reduce using rule 148 (global) - - -State 248 - - 10 global_type: "(" . MUT VALUE_TYPE ")" - - MUT shift, and go to state 244 - - -State 249 - - 150 global_fields: inline_import global_type . - - $default reduce using rule 150 (global_fields) - - -State 250 - - 151 global_fields: inline_export global_fields . - - $default reduce using rule 151 (global_fields) - - -State 251 - - 140 table_fields: elem_type "(" . ELEM var_list ")" - - ELEM shift, and go to state 328 - - -State 252 - - 17 table_sig: limits elem_type . - - $default reduce using rule 17 (table_sig) - - -State 253 - - 20 limits: nat nat . - - $default reduce using rule 20 (limits) - - -State 254 - - 136 table: "(" TABLE bind_var_opt table_fields ")" . - - $default reduce using rule 136 (table) - - -State 255 - - 138 table_fields: inline_import table_sig . - - $default reduce using rule 138 (table_fields) - - -State 256 - - 139 table_fields: inline_export table_fields . - - $default reduce using rule 139 (table_fields) - - -State 257 - - 82 expr1: BLOCK labeling_opt . block - - "(" shift, and go to state 309 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - block_sig go to state 310 - block go to state 329 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 312 - - -State 258 - - 84 expr1: IF labeling_opt . if_block - - "(" shift, and go to state 330 - - block_sig go to state 331 - expr go to state 332 - if_block go to state 333 - if_ go to state 334 - - -State 259 - - 83 expr1: LOOP labeling_opt . block - - "(" shift, and go to state 309 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - block_sig go to state 310 - block go to state 335 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 312 - - -State 260 - - 132 offset: "(" OFFSET const_expr . ")" - - ")" shift, and go to state 336 - - -State 261 - - 106 expr_list: expr . expr_list - - "(" shift, and go to state 228 - - $default reduce using rule 105 (expr_list) - - expr go to state 261 - expr_list go to state 337 - - -State 262 - - 81 expr1: plain_instr expr_list . - - $default reduce using rule 81 (expr1) - - -State 263 - - 80 expr: "(" expr1 ")" . - - $default reduce using rule 80 (expr) - - -State 264 - - 85 expr1: try_check labeling_opt . try_ - - "(" shift, and go to state 338 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - instr go to state 339 - plain_instr go to state 126 - block_instr go to state 127 - block_sig go to state 340 - expr go to state 128 - try_ go to state 341 - try_instr_list go to state 342 - catch_list go to state 343 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - - -State 265 - - 29 var_list: var_list . var - 134 elem: "(" ELEM var offset var_list . ")" - - ")" shift, and go to state 344 - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 267 - - -State 266 - - 135 elem: "(" ELEM offset var_list ")" . - - $default reduce using rule 135 (elem) - - -State 267 - - 29 var_list: var_list var . - - $default reduce using rule 29 (var_list) - - -State 268 - - 147 memory_fields: "(" DATA . text_list_opt ")" - - TEXT shift, and go to state 176 - - $default reduce using rule 3 (text_list_opt) - - text_list go to state 177 - text_list_opt go to state 345 - - -State 269 - - 143 memory: "(" MEMORY bind_var_opt memory_fields ")" . - - $default reduce using rule 143 (memory) - - -State 270 - - 145 memory_fields: inline_import memory_sig . - - $default reduce using rule 145 (memory_fields) - - -State 271 - - 146 memory_fields: inline_export memory_fields . - - $default reduce using rule 146 (memory_fields) - - -State 272 - - 141 data: "(" DATA var offset text_list_opt . ")" - - ")" shift, and go to state 346 - - -State 273 - - 2 text_list: text_list TEXT . - - $default reduce using rule 2 (text_list) - - -State 274 - - 142 data: "(" DATA offset text_list_opt ")" . - - $default reduce using rule 142 (data) - - -State 275 - - 108 exception: "(" . EXCEPT bind_var_opt value_type_list ")" - 152 import_desc: "(" . FUNC bind_var_opt type_use ")" - 153 | "(" . FUNC bind_var_opt func_sig ")" - 154 | "(" . TABLE bind_var_opt table_sig ")" - 155 | "(" . MEMORY bind_var_opt memory_sig ")" - 156 | "(" . GLOBAL bind_var_opt global_type ")" - - FUNC shift, and go to state 347 - GLOBAL shift, and go to state 348 - TABLE shift, and go to state 349 - MEMORY shift, and go to state 350 - EXCEPT shift, and go to state 35 - - -State 276 - - 157 import_desc: exception . - - $default reduce using rule 157 (import_desc) - - -State 277 - - 158 import: "(" IMPORT quoted_text quoted_text import_desc . ")" - - ")" shift, and go to state 351 - - -State 278 - - 160 export_desc: "(" FUNC . var ")" - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 352 - - -State 279 - - 163 export_desc: "(" GLOBAL . var ")" - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 353 - - -State 280 - - 161 export_desc: "(" TABLE . var ")" - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 354 - - -State 281 - - 162 export_desc: "(" MEMORY . var ")" - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 355 - - -State 282 - - 164 export_desc: "(" EXCEPT . var ")" - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 356 - - -State 283 - - 165 export: "(" EXPORT quoted_text export_desc ")" . - - $default reduce using rule 165 (export) - - -State 284 - - 108 exception: "(" EXCEPT bind_var_opt value_type_list ")" . - - $default reduce using rule 108 (exception) - - -State 285 - - 7 value_type_list: value_type_list VALUE_TYPE . - - $default reduce using rule 7 (value_type_list) - - -State 286 - - 2 text_list: text_list . TEXT - 190 script_module: "(" MODULE bind_var_opt BIN text_list . ")" - - ")" shift, and go to state 357 - TEXT shift, and go to state 273 - - -State 287 - - 2 text_list: text_list . TEXT - 191 script_module: "(" MODULE bind_var_opt QUOTE text_list . ")" - - ")" shift, and go to state 358 - TEXT shift, and go to state 273 - - -State 288 - - 189 script_module: "(" MODULE bind_var_opt module_fields_opt ")" . - - $default reduce using rule 189 (script_module) - - -State 289 - - 206 cmd: "(" REGISTER quoted_text script_var_opt ")" . - - $default reduce using rule 206 (cmd) - - -State 290 - - 192 action: "(" INVOKE script_var_opt quoted_text const_list . ")" - 211 const_list: const_list . const - - "(" shift, and go to state 295 - ")" shift, and go to state 359 - - const go to state 297 - - -State 291 - - 193 action: "(" GET script_var_opt quoted_text ")" . - - $default reduce using rule 193 (action) - - -State 292 - - 194 assertion: "(" ASSERT_MALFORMED script_module quoted_text ")" . - - $default reduce using rule 194 (assertion) - - -State 293 - - 195 assertion: "(" ASSERT_INVALID script_module quoted_text ")" . - - $default reduce using rule 195 (assertion) - - -State 294 - - 196 assertion: "(" ASSERT_UNLINKABLE script_module quoted_text ")" . - - $default reduce using rule 196 (assertion) - - -State 295 - - 209 const: "(" . CONST literal ")" - - CONST shift, and go to state 360 - - -State 296 - - 198 assertion: "(" ASSERT_RETURN action const_list ")" . - - $default reduce using rule 198 (assertion) - - -State 297 - - 211 const_list: const_list const . - - $default reduce using rule 211 (const_list) - - -State 298 - - 197 assertion: "(" ASSERT_TRAP script_module quoted_text ")" . - - $default reduce using rule 197 (assertion) - - -State 299 - - 201 assertion: "(" ASSERT_TRAP action quoted_text ")" . - - $default reduce using rule 201 (assertion) - - -State 300 - - 202 assertion: "(" ASSERT_EXHAUSTION action quoted_text ")" . - - $default reduce using rule 202 (assertion) - - -State 301 - - 21 type_use: "(" TYPE var . ")" - - ")" shift, and go to state 361 - - -State 302 - - 7 value_type_list: value_type_list . VALUE_TYPE - 124 func_fields_body1: "(" PARAM value_type_list . ")" func_fields_body1 - - ")" shift, and go to state 362 - VALUE_TYPE shift, and go to state 285 - - -State 303 - - 125 func_fields_body1: "(" PARAM bind_var . VALUE_TYPE ")" func_fields_body1 - - VALUE_TYPE shift, and go to state 363 - - -State 304 - - 7 value_type_list: value_type_list . VALUE_TYPE - 127 func_result_body: "(" RESULT value_type_list . ")" func_result_body - - ")" shift, and go to state 364 - VALUE_TYPE shift, and go to state 285 - - -State 305 - - 7 value_type_list: value_type_list . VALUE_TYPE - 130 func_body1: "(" LOCAL value_type_list . ")" func_body1 - - ")" shift, and go to state 365 - VALUE_TYPE shift, and go to state 285 - - -State 306 - - 131 func_body1: "(" LOCAL bind_var . VALUE_TYPE ")" func_body1 - - VALUE_TYPE shift, and go to state 366 - - -State 307 - - 159 inline_import: "(" IMPORT quoted_text . quoted_text ")" - - TEXT shift, and go to state 72 - - quoted_text go to state 367 - - -State 308 - - 166 inline_export: "(" EXPORT quoted_text . ")" - - ")" shift, and go to state 368 - - -State 309 - - 73 block_sig: "(" . RESULT value_type_list ")" - 80 expr: "(" . expr1 ")" - - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 160 - IF shift, and go to state 161 - LOOP shift, and go to state 162 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - RESULT shift, and go to state 369 - - plain_instr go to state 164 - expr1 go to state 165 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 166 - - -State 310 - - 74 block: block_sig . block - - "(" shift, and go to state 309 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - block_sig go to state 310 - block go to state 370 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 312 - - -State 311 - - 68 block_instr: BLOCK labeling_opt block . END labeling_opt - - END shift, and go to state 371 - - -State 312 - - 75 block: instr_list . - - $default reduce using rule 75 (block) - - -State 313 - - 70 block_instr: IF labeling_opt block . END labeling_opt - 71 | IF labeling_opt block . ELSE labeling_opt instr_list END labeling_opt - - END shift, and go to state 372 - ELSE shift, and go to state 373 - - -State 314 - - 69 block_instr: LOOP labeling_opt block . END labeling_opt - - END shift, and go to state 374 - - -State 315 - - 29 var_list: var_list var . - 48 plain_instr: BR_TABLE var_list var . - - NAT reduce using rule 29 (var_list) - VAR reduce using rule 29 (var_list) - $default reduce using rule 48 (plain_instr) - - -State 316 - - 38 align_opt: ALIGN_EQ_NAT . - - $default reduce using rule 38 (align_opt) - - -State 317 - - 57 plain_instr: LOAD offset_opt align_opt . - - $default reduce using rule 57 (plain_instr) - - -State 318 - - 58 plain_instr: STORE offset_opt align_opt . - - $default reduce using rule 58 (plain_instr) - - -State 319 - - 72 block_instr: try_check labeling_opt block . catch_instr_list END labeling_opt - - CATCH shift, and go to state 375 - CATCH_ALL shift, and go to state 376 - - catch_instr go to state 377 - catch_instr_list go to state 378 - - -State 320 - - 118 func_fields_import1: "(" PARAM . value_type_list ")" func_fields_import1 - 119 | "(" PARAM . bind_var VALUE_TYPE ")" func_fields_import1 - - VAR shift, and go to state 53 - - $default reduce using rule 6 (value_type_list) - - value_type_list go to state 379 - bind_var go to state 380 - - -State 321 - - 121 func_fields_import_result: "(" RESULT . value_type_list ")" func_fields_import_result - - $default reduce using rule 6 (value_type_list) - - value_type_list go to state 381 - - -State 322 - - 118 func_fields_import1: "(" . PARAM value_type_list ")" func_fields_import1 - 119 | "(" . PARAM bind_var VALUE_TYPE ")" func_fields_import1 - 121 func_fields_import_result: "(" . RESULT value_type_list ")" func_fields_import_result - - PARAM shift, and go to state 320 - RESULT shift, and go to state 321 - - -State 323 - - 113 func_fields: inline_import type_use func_fields_import . - - $default reduce using rule 113 (func_fields) - - -State 324 - - 13 func_sig: "(" PARAM . value_type_list ")" func_sig - 14 | "(" PARAM . bind_var VALUE_TYPE ")" func_sig - - VAR shift, and go to state 53 - - $default reduce using rule 6 (value_type_list) - - value_type_list go to state 382 - bind_var go to state 383 - - -State 325 - - 16 func_sig_result: "(" RESULT . value_type_list ")" func_sig_result - - $default reduce using rule 6 (value_type_list) - - value_type_list go to state 384 - - -State 326 - - 11 func_type: "(" FUNC func_sig ")" . - - $default reduce using rule 11 (func_type) - - -State 327 - - 10 global_type: "(" MUT VALUE_TYPE . ")" - - ")" shift, and go to state 385 - - -State 328 - - 140 table_fields: elem_type "(" ELEM . var_list ")" - - $default reduce using rule 28 (var_list) - - var_list go to state 386 - - -State 329 - - 82 expr1: BLOCK labeling_opt block . - - $default reduce using rule 82 (expr1) - - -State 330 - - 73 block_sig: "(" . RESULT value_type_list ")" - 80 expr: "(" . expr1 ")" - 94 if_: "(" . THEN instr_list ")" "(" ELSE instr_list ")" - 95 | "(" . THEN instr_list ")" - - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 160 - IF shift, and go to state 161 - THEN shift, and go to state 387 - LOOP shift, and go to state 162 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - RESULT shift, and go to state 369 - - plain_instr go to state 164 - expr1 go to state 165 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 166 - - -State 331 - - 92 if_block: block_sig . if_block - - "(" shift, and go to state 330 - - block_sig go to state 331 - expr go to state 332 - if_block go to state 388 - if_ go to state 334 - - -State 332 - - 96 if_: expr . "(" THEN instr_list ")" "(" ELSE instr_list ")" - 97 | expr . "(" THEN instr_list ")" - 98 | expr . expr expr - 99 | expr . expr - - "(" shift, and go to state 389 - - expr go to state 390 - - -State 333 - - 84 expr1: IF labeling_opt if_block . - - $default reduce using rule 84 (expr1) - - -State 334 - - 93 if_block: if_ . - - $default reduce using rule 93 (if_block) - - -State 335 - - 83 expr1: LOOP labeling_opt block . - - $default reduce using rule 83 (expr1) - - -State 336 - - 132 offset: "(" OFFSET const_expr ")" . - - $default reduce using rule 132 (offset) - - -State 337 - - 106 expr_list: expr expr_list . - - $default reduce using rule 106 (expr_list) - - -State 338 - - 73 block_sig: "(" . RESULT value_type_list ")" - 80 expr: "(" . expr1 ")" - 90 catch_list: "(" . catch_instr ")" - 91 | "(" . catch_instr ")" catch_list - - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 160 - IF shift, and go to state 161 - LOOP shift, and go to state 162 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - CATCH shift, and go to state 375 - CATCH_ALL shift, and go to state 376 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - RESULT shift, and go to state 369 - - plain_instr go to state 164 - catch_instr go to state 391 - expr1 go to state 165 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 166 - - -State 339 - - 89 try_instr_list: instr . try_instr_list - - "(" shift, and go to state 392 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - instr go to state 339 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - try_instr_list go to state 393 - catch_list go to state 343 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - - -State 340 - - 86 try_: block_sig . try_ - - "(" shift, and go to state 338 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - instr go to state 339 - plain_instr go to state 126 - block_instr go to state 127 - block_sig go to state 340 - expr go to state 128 - try_ go to state 394 - try_instr_list go to state 342 - catch_list go to state 343 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - - -State 341 - - 85 expr1: try_check labeling_opt try_ . - - $default reduce using rule 85 (expr1) - - -State 342 - - 87 try_: try_instr_list . - - $default reduce using rule 87 (try_) - - -State 343 - - 88 try_instr_list: catch_list . - - $default reduce using rule 88 (try_instr_list) - - -State 344 - - 134 elem: "(" ELEM var offset var_list ")" . - - $default reduce using rule 134 (elem) - - -State 345 - - 147 memory_fields: "(" DATA text_list_opt . ")" - - ")" shift, and go to state 395 - - -State 346 - - 141 data: "(" DATA var offset text_list_opt ")" . - - $default reduce using rule 141 (data) - - -State 347 - - 152 import_desc: "(" FUNC . bind_var_opt type_use ")" - 153 | "(" FUNC . bind_var_opt func_sig ")" - - VAR shift, and go to state 53 - - $default reduce using rule 30 (bind_var_opt) - - bind_var_opt go to state 396 - bind_var go to state 55 - - -State 348 - - 156 import_desc: "(" GLOBAL . bind_var_opt global_type ")" - - VAR shift, and go to state 53 - - $default reduce using rule 30 (bind_var_opt) - - bind_var_opt go to state 397 - bind_var go to state 55 - - -State 349 - - 154 import_desc: "(" TABLE . bind_var_opt table_sig ")" - - VAR shift, and go to state 53 - - $default reduce using rule 30 (bind_var_opt) - - bind_var_opt go to state 398 - bind_var go to state 55 - - -State 350 - - 155 import_desc: "(" MEMORY . bind_var_opt memory_sig ")" - - VAR shift, and go to state 53 - - $default reduce using rule 30 (bind_var_opt) - - bind_var_opt go to state 399 - bind_var go to state 55 - - -State 351 - - 158 import: "(" IMPORT quoted_text quoted_text import_desc ")" . - - $default reduce using rule 158 (import) - - -State 352 - - 160 export_desc: "(" FUNC var . ")" - - ")" shift, and go to state 400 - - -State 353 - - 163 export_desc: "(" GLOBAL var . ")" - - ")" shift, and go to state 401 - - -State 354 - - 161 export_desc: "(" TABLE var . ")" - - ")" shift, and go to state 402 - - -State 355 - - 162 export_desc: "(" MEMORY var . ")" - - ")" shift, and go to state 403 - - -State 356 - - 164 export_desc: "(" EXCEPT var . ")" - - ")" shift, and go to state 404 - - -State 357 - - 190 script_module: "(" MODULE bind_var_opt BIN text_list ")" . - - $default reduce using rule 190 (script_module) - - -State 358 - - 191 script_module: "(" MODULE bind_var_opt QUOTE text_list ")" . - - $default reduce using rule 191 (script_module) - - -State 359 - - 192 action: "(" INVOKE script_var_opt quoted_text const_list ")" . - - $default reduce using rule 192 (action) - - -State 360 - - 209 const: "(" CONST . literal ")" - - NAT shift, and go to state 222 - INT shift, and go to state 223 - FLOAT shift, and go to state 224 - - literal go to state 405 - - -State 361 - - 21 type_use: "(" TYPE var ")" . - - $default reduce using rule 21 (type_use) - - -State 362 - - 124 func_fields_body1: "(" PARAM value_type_list ")" . func_fields_body1 - - "(" shift, and go to state 226 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 132 - func_fields_body1 go to state 406 - func_result_body go to state 136 - func_body go to state 137 - func_body1 go to state 138 - - -State 363 - - 125 func_fields_body1: "(" PARAM bind_var VALUE_TYPE . ")" func_fields_body1 - - ")" shift, and go to state 407 - - -State 364 - - 127 func_result_body: "(" RESULT value_type_list ")" . func_result_body - - "(" shift, and go to state 408 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 132 - func_result_body go to state 409 - func_body go to state 137 - func_body1 go to state 138 - - -State 365 - - 130 func_body1: "(" LOCAL value_type_list ")" . func_body1 - - "(" shift, and go to state 410 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 132 - func_body1 go to state 411 - - -State 366 - - 131 func_body1: "(" LOCAL bind_var VALUE_TYPE . ")" func_body1 - - ")" shift, and go to state 412 - - -State 367 - - 159 inline_import: "(" IMPORT quoted_text quoted_text . ")" - - ")" shift, and go to state 413 - - -State 368 - - 166 inline_export: "(" EXPORT quoted_text ")" . - - $default reduce using rule 166 (inline_export) - - -State 369 - - 73 block_sig: "(" RESULT . value_type_list ")" - - $default reduce using rule 6 (value_type_list) - - value_type_list go to state 414 - - -State 370 - - 74 block: block_sig block . - - $default reduce using rule 74 (block) - - -State 371 - - 68 block_instr: BLOCK labeling_opt block END . labeling_opt - - VAR shift, and go to state 53 - - $default reduce using rule 33 (labeling_opt) - - bind_var go to state 205 - labeling_opt go to state 415 - - -State 372 - - 70 block_instr: IF labeling_opt block END . labeling_opt - - VAR shift, and go to state 53 - - $default reduce using rule 33 (labeling_opt) - - bind_var go to state 205 - labeling_opt go to state 416 - - -State 373 - - 71 block_instr: IF labeling_opt block ELSE . labeling_opt instr_list END labeling_opt - - VAR shift, and go to state 53 - - $default reduce using rule 33 (labeling_opt) - - bind_var go to state 205 - labeling_opt go to state 417 - - -State 374 - - 69 block_instr: LOOP labeling_opt block END . labeling_opt - - VAR shift, and go to state 53 - - $default reduce using rule 33 (labeling_opt) - - bind_var go to state 205 - labeling_opt go to state 418 - - -State 375 - - 76 catch_instr: CATCH . var instr_list - - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 419 - - -State 376 - - 77 catch_instr: CATCH_ALL . instr_list - - "(" shift, and go to state 228 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 420 - - -State 377 - - 78 catch_instr_list: catch_instr . - 79 | catch_instr . catch_instr_list - - CATCH shift, and go to state 375 - CATCH_ALL shift, and go to state 376 - - $default reduce using rule 78 (catch_instr_list) - - catch_instr go to state 377 - catch_instr_list go to state 421 - - -State 378 - - 72 block_instr: try_check labeling_opt block catch_instr_list . END labeling_opt - - END shift, and go to state 422 - - -State 379 - - 7 value_type_list: value_type_list . VALUE_TYPE - 118 func_fields_import1: "(" PARAM value_type_list . ")" func_fields_import1 - - ")" shift, and go to state 423 - VALUE_TYPE shift, and go to state 285 - - -State 380 - - 119 func_fields_import1: "(" PARAM bind_var . VALUE_TYPE ")" func_fields_import1 - - VALUE_TYPE shift, and go to state 424 - - -State 381 - - 7 value_type_list: value_type_list . VALUE_TYPE - 121 func_fields_import_result: "(" RESULT value_type_list . ")" func_fields_import_result - - ")" shift, and go to state 425 - VALUE_TYPE shift, and go to state 285 - - -State 382 - - 7 value_type_list: value_type_list . VALUE_TYPE - 13 func_sig: "(" PARAM value_type_list . ")" func_sig - - ")" shift, and go to state 426 - VALUE_TYPE shift, and go to state 285 - - -State 383 - - 14 func_sig: "(" PARAM bind_var . VALUE_TYPE ")" func_sig - - VALUE_TYPE shift, and go to state 427 - - -State 384 - - 7 value_type_list: value_type_list . VALUE_TYPE - 16 func_sig_result: "(" RESULT value_type_list . ")" func_sig_result - - ")" shift, and go to state 428 - VALUE_TYPE shift, and go to state 285 - - -State 385 - - 10 global_type: "(" MUT VALUE_TYPE ")" . - - $default reduce using rule 10 (global_type) - - -State 386 - - 29 var_list: var_list . var - 140 table_fields: elem_type "(" ELEM var_list . ")" - - ")" shift, and go to state 429 - NAT shift, and go to state 56 - VAR shift, and go to state 57 - - nat go to state 58 - var go to state 267 - - -State 387 - - 94 if_: "(" THEN . instr_list ")" "(" ELSE instr_list ")" - 95 | "(" THEN . instr_list ")" - - "(" shift, and go to state 228 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 430 - - -State 388 - - 92 if_block: block_sig if_block . - - $default reduce using rule 92 (if_block) - - -State 389 - - 80 expr: "(" . expr1 ")" - 96 if_: expr "(" . THEN instr_list ")" "(" ELSE instr_list ")" - 97 | expr "(" . THEN instr_list ")" - - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 160 - IF shift, and go to state 161 - THEN shift, and go to state 431 - LOOP shift, and go to state 162 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - plain_instr go to state 164 - expr1 go to state 165 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 166 - - -State 390 - - 98 if_: expr expr . expr - 99 | expr expr . - - "(" shift, and go to state 228 - - $default reduce using rule 99 (if_) - - expr go to state 432 - - -State 391 - - 90 catch_list: "(" catch_instr . ")" - 91 | "(" catch_instr . ")" catch_list - - ")" shift, and go to state 433 - - -State 392 - - 80 expr: "(" . expr1 ")" - 90 catch_list: "(" . catch_instr ")" - 91 | "(" . catch_instr ")" catch_list - - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 160 - IF shift, and go to state 161 - LOOP shift, and go to state 162 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - CATCH shift, and go to state 375 - CATCH_ALL shift, and go to state 376 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - plain_instr go to state 164 - catch_instr go to state 391 - expr1 go to state 165 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 166 - - -State 393 - - 89 try_instr_list: instr try_instr_list . - - $default reduce using rule 89 (try_instr_list) - - -State 394 - - 86 try_: block_sig try_ . - - $default reduce using rule 86 (try_) - - -State 395 - - 147 memory_fields: "(" DATA text_list_opt ")" . - - $default reduce using rule 147 (memory_fields) - - -State 396 - - 152 import_desc: "(" FUNC bind_var_opt . type_use ")" - 153 | "(" FUNC bind_var_opt . func_sig ")" - - "(" shift, and go to state 434 - - $default reduce using rule 15 (func_sig_result) - - func_sig go to state 435 - func_sig_result go to state 242 - type_use go to state 436 - - -State 397 - - 156 import_desc: "(" GLOBAL bind_var_opt . global_type ")" - - "(" shift, and go to state 248 - VALUE_TYPE shift, and go to state 146 - - global_type go to state 437 - - -State 398 - - 154 import_desc: "(" TABLE bind_var_opt . table_sig ")" - - NAT shift, and go to state 56 - - table_sig go to state 438 - limits go to state 155 - nat go to state 156 - - -State 399 - - 155 import_desc: "(" MEMORY bind_var_opt . memory_sig ")" - - NAT shift, and go to state 56 - - memory_sig go to state 439 - limits go to state 171 - nat go to state 156 - - -State 400 - - 160 export_desc: "(" FUNC var ")" . - - $default reduce using rule 160 (export_desc) - - -State 401 - - 163 export_desc: "(" GLOBAL var ")" . - - $default reduce using rule 163 (export_desc) - - -State 402 - - 161 export_desc: "(" TABLE var ")" . - - $default reduce using rule 161 (export_desc) - - -State 403 - - 162 export_desc: "(" MEMORY var ")" . - - $default reduce using rule 162 (export_desc) - - -State 404 - - 164 export_desc: "(" EXCEPT var ")" . - - $default reduce using rule 164 (export_desc) - - -State 405 - - 209 const: "(" CONST literal . ")" - - ")" shift, and go to state 440 - - -State 406 - - 124 func_fields_body1: "(" PARAM value_type_list ")" func_fields_body1 . - - $default reduce using rule 124 (func_fields_body1) - - -State 407 - - 125 func_fields_body1: "(" PARAM bind_var VALUE_TYPE ")" . func_fields_body1 - - "(" shift, and go to state 226 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 132 - func_fields_body1 go to state 441 - func_result_body go to state 136 - func_body go to state 137 - func_body1 go to state 138 - - -State 408 - - 80 expr: "(" . expr1 ")" - 127 func_result_body: "(" . RESULT value_type_list ")" func_result_body - 130 func_body1: "(" . LOCAL value_type_list ")" func_body1 - 131 | "(" . LOCAL bind_var VALUE_TYPE ")" func_body1 - - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 160 - IF shift, and go to state 161 - LOOP shift, and go to state 162 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - RESULT shift, and go to state 201 - LOCAL shift, and go to state 202 - - plain_instr go to state 164 - expr1 go to state 165 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 166 - - -State 409 - - 127 func_result_body: "(" RESULT value_type_list ")" func_result_body . - - $default reduce using rule 127 (func_result_body) - - -State 410 - - 80 expr: "(" . expr1 ")" - 130 func_body1: "(" . LOCAL value_type_list ")" func_body1 - 131 | "(" . LOCAL bind_var VALUE_TYPE ")" func_body1 - - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 160 - IF shift, and go to state 161 - LOOP shift, and go to state 162 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - LOCAL shift, and go to state 202 - - plain_instr go to state 164 - expr1 go to state 165 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 166 - - -State 411 - - 130 func_body1: "(" LOCAL value_type_list ")" func_body1 . - - $default reduce using rule 130 (func_body1) - - -State 412 - - 131 func_body1: "(" LOCAL bind_var VALUE_TYPE ")" . func_body1 - - "(" shift, and go to state 410 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 132 - func_body1 go to state 442 - - -State 413 - - 159 inline_import: "(" IMPORT quoted_text quoted_text ")" . - - $default reduce using rule 159 (inline_import) - - -State 414 - - 7 value_type_list: value_type_list . VALUE_TYPE - 73 block_sig: "(" RESULT value_type_list . ")" - - ")" shift, and go to state 443 - VALUE_TYPE shift, and go to state 285 - - -State 415 - - 68 block_instr: BLOCK labeling_opt block END labeling_opt . - - $default reduce using rule 68 (block_instr) - - -State 416 - - 70 block_instr: IF labeling_opt block END labeling_opt . - - $default reduce using rule 70 (block_instr) - - -State 417 - - 71 block_instr: IF labeling_opt block ELSE labeling_opt . instr_list END labeling_opt - - "(" shift, and go to state 228 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 444 - - -State 418 - - 69 block_instr: LOOP labeling_opt block END labeling_opt . - - $default reduce using rule 69 (block_instr) - - -State 419 - - 76 catch_instr: CATCH var . instr_list - - "(" shift, and go to state 228 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 445 - - -State 420 - - 77 catch_instr: CATCH_ALL instr_list . - - $default reduce using rule 77 (catch_instr) - - -State 421 - - 79 catch_instr_list: catch_instr catch_instr_list . - - $default reduce using rule 79 (catch_instr_list) - - -State 422 - - 72 block_instr: try_check labeling_opt block catch_instr_list END . labeling_opt - - VAR shift, and go to state 53 - - $default reduce using rule 33 (labeling_opt) - - bind_var go to state 205 - labeling_opt go to state 446 - - -State 423 - - 118 func_fields_import1: "(" PARAM value_type_list ")" . func_fields_import1 - - "(" shift, and go to state 322 - - $default reduce using rule 120 (func_fields_import_result) - - func_fields_import1 go to state 447 - func_fields_import_result go to state 238 - - -State 424 - - 119 func_fields_import1: "(" PARAM bind_var VALUE_TYPE . ")" func_fields_import1 - - ")" shift, and go to state 448 - - -State 425 - - 121 func_fields_import_result: "(" RESULT value_type_list ")" . func_fields_import_result - - "(" shift, and go to state 449 - - $default reduce using rule 120 (func_fields_import_result) - - func_fields_import_result go to state 450 - - -State 426 - - 13 func_sig: "(" PARAM value_type_list ")" . func_sig - - "(" shift, and go to state 240 - - $default reduce using rule 15 (func_sig_result) - - func_sig go to state 451 - func_sig_result go to state 242 - - -State 427 - - 14 func_sig: "(" PARAM bind_var VALUE_TYPE . ")" func_sig - - ")" shift, and go to state 452 - - -State 428 - - 16 func_sig_result: "(" RESULT value_type_list ")" . func_sig_result - - "(" shift, and go to state 453 - - $default reduce using rule 15 (func_sig_result) - - func_sig_result go to state 454 - - -State 429 - - 140 table_fields: elem_type "(" ELEM var_list ")" . - - $default reduce using rule 140 (table_fields) - - -State 430 - - 94 if_: "(" THEN instr_list . ")" "(" ELSE instr_list ")" - 95 | "(" THEN instr_list . ")" - - ")" shift, and go to state 455 - - -State 431 - - 96 if_: expr "(" THEN . instr_list ")" "(" ELSE instr_list ")" - 97 | expr "(" THEN . instr_list ")" - - "(" shift, and go to state 228 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 456 - - -State 432 - - 98 if_: expr expr expr . - - $default reduce using rule 98 (if_) - - -State 433 - - 90 catch_list: "(" catch_instr ")" . - 91 | "(" catch_instr ")" . catch_list - - "(" shift, and go to state 457 - - $default reduce using rule 90 (catch_list) - - catch_list go to state 458 - - -State 434 - - 13 func_sig: "(" . PARAM value_type_list ")" func_sig - 14 | "(" . PARAM bind_var VALUE_TYPE ")" func_sig - 16 func_sig_result: "(" . RESULT value_type_list ")" func_sig_result - 21 type_use: "(" . TYPE var ")" - - TYPE shift, and go to state 199 - PARAM shift, and go to state 324 - RESULT shift, and go to state 325 - - -State 435 - - 153 import_desc: "(" FUNC bind_var_opt func_sig . ")" - - ")" shift, and go to state 459 - - -State 436 - - 152 import_desc: "(" FUNC bind_var_opt type_use . ")" - - ")" shift, and go to state 460 - - -State 437 - - 156 import_desc: "(" GLOBAL bind_var_opt global_type . ")" - - ")" shift, and go to state 461 - - -State 438 - - 154 import_desc: "(" TABLE bind_var_opt table_sig . ")" - - ")" shift, and go to state 462 - - -State 439 - - 155 import_desc: "(" MEMORY bind_var_opt memory_sig . ")" - - ")" shift, and go to state 463 - - -State 440 - - 209 const: "(" CONST literal ")" . - - $default reduce using rule 209 (const) - - -State 441 - - 125 func_fields_body1: "(" PARAM bind_var VALUE_TYPE ")" func_fields_body1 . - - $default reduce using rule 125 (func_fields_body1) - - -State 442 - - 131 func_body1: "(" LOCAL bind_var VALUE_TYPE ")" func_body1 . - - $default reduce using rule 131 (func_body1) - - -State 443 - - 73 block_sig: "(" RESULT value_type_list ")" . - - $default reduce using rule 73 (block_sig) - - -State 444 - - 71 block_instr: IF labeling_opt block ELSE labeling_opt instr_list . END labeling_opt - - END shift, and go to state 464 - - -State 445 - - 76 catch_instr: CATCH var instr_list . - - $default reduce using rule 76 (catch_instr) - - -State 446 - - 72 block_instr: try_check labeling_opt block catch_instr_list END labeling_opt . - - $default reduce using rule 72 (block_instr) - - -State 447 - - 118 func_fields_import1: "(" PARAM value_type_list ")" func_fields_import1 . - - $default reduce using rule 118 (func_fields_import1) - - -State 448 - - 119 func_fields_import1: "(" PARAM bind_var VALUE_TYPE ")" . func_fields_import1 - - "(" shift, and go to state 322 - - $default reduce using rule 120 (func_fields_import_result) - - func_fields_import1 go to state 465 - func_fields_import_result go to state 238 - - -State 449 - - 121 func_fields_import_result: "(" . RESULT value_type_list ")" func_fields_import_result - - RESULT shift, and go to state 321 - - -State 450 - - 121 func_fields_import_result: "(" RESULT value_type_list ")" func_fields_import_result . - - $default reduce using rule 121 (func_fields_import_result) - - -State 451 - - 13 func_sig: "(" PARAM value_type_list ")" func_sig . - - $default reduce using rule 13 (func_sig) - - -State 452 - - 14 func_sig: "(" PARAM bind_var VALUE_TYPE ")" . func_sig - - "(" shift, and go to state 240 - - $default reduce using rule 15 (func_sig_result) - - func_sig go to state 466 - func_sig_result go to state 242 - - -State 453 - - 16 func_sig_result: "(" . RESULT value_type_list ")" func_sig_result - - RESULT shift, and go to state 325 - - -State 454 - - 16 func_sig_result: "(" RESULT value_type_list ")" func_sig_result . - - $default reduce using rule 16 (func_sig_result) - - -State 455 - - 94 if_: "(" THEN instr_list ")" . "(" ELSE instr_list ")" - 95 | "(" THEN instr_list ")" . - - "(" shift, and go to state 467 - - $default reduce using rule 95 (if_) - - -State 456 - - 96 if_: expr "(" THEN instr_list . ")" "(" ELSE instr_list ")" - 97 | expr "(" THEN instr_list . ")" - - ")" shift, and go to state 468 - - -State 457 - - 90 catch_list: "(" . catch_instr ")" - 91 | "(" . catch_instr ")" catch_list - - CATCH shift, and go to state 375 - CATCH_ALL shift, and go to state 376 - - catch_instr go to state 391 - - -State 458 - - 91 catch_list: "(" catch_instr ")" catch_list . - - $default reduce using rule 91 (catch_list) - - -State 459 - - 153 import_desc: "(" FUNC bind_var_opt func_sig ")" . - - $default reduce using rule 153 (import_desc) - - -State 460 - - 152 import_desc: "(" FUNC bind_var_opt type_use ")" . - - $default reduce using rule 152 (import_desc) - - -State 461 - - 156 import_desc: "(" GLOBAL bind_var_opt global_type ")" . - - $default reduce using rule 156 (import_desc) - - -State 462 - - 154 import_desc: "(" TABLE bind_var_opt table_sig ")" . - - $default reduce using rule 154 (import_desc) - - -State 463 - - 155 import_desc: "(" MEMORY bind_var_opt memory_sig ")" . - - $default reduce using rule 155 (import_desc) - - -State 464 - - 71 block_instr: IF labeling_opt block ELSE labeling_opt instr_list END . labeling_opt - - VAR shift, and go to state 53 - - $default reduce using rule 33 (labeling_opt) - - bind_var go to state 205 - labeling_opt go to state 469 - - -State 465 - - 119 func_fields_import1: "(" PARAM bind_var VALUE_TYPE ")" func_fields_import1 . - - $default reduce using rule 119 (func_fields_import1) - - -State 466 - - 14 func_sig: "(" PARAM bind_var VALUE_TYPE ")" func_sig . - - $default reduce using rule 14 (func_sig) - - -State 467 - - 94 if_: "(" THEN instr_list ")" "(" . ELSE instr_list ")" - - ELSE shift, and go to state 470 - - -State 468 - - 96 if_: expr "(" THEN instr_list ")" . "(" ELSE instr_list ")" - 97 | expr "(" THEN instr_list ")" . - - "(" shift, and go to state 471 - - $default reduce using rule 97 (if_) - - -State 469 - - 71 block_instr: IF labeling_opt block ELSE labeling_opt instr_list END labeling_opt . - - $default reduce using rule 71 (block_instr) - - -State 470 - - 94 if_: "(" THEN instr_list ")" "(" ELSE . instr_list ")" - - "(" shift, and go to state 228 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 472 - - -State 471 - - 96 if_: expr "(" THEN instr_list ")" "(" . ELSE instr_list ")" - - ELSE shift, and go to state 473 - - -State 472 - - 94 if_: "(" THEN instr_list ")" "(" ELSE instr_list . ")" - - ")" shift, and go to state 474 - - -State 473 - - 96 if_: expr "(" THEN instr_list ")" "(" ELSE . instr_list ")" - - "(" shift, and go to state 228 - NOP shift, and go to state 94 - DROP shift, and go to state 95 - BLOCK shift, and go to state 96 - IF shift, and go to state 97 - LOOP shift, and go to state 98 - BR shift, and go to state 99 - BR_IF shift, and go to state 100 - BR_TABLE shift, and go to state 101 - TRY shift, and go to state 102 - THROW shift, and go to state 103 - RETHROW shift, and go to state 104 - CALL shift, and go to state 105 - CALL_INDIRECT shift, and go to state 106 - RETURN shift, and go to state 107 - GET_LOCAL shift, and go to state 108 - SET_LOCAL shift, and go to state 109 - TEE_LOCAL shift, and go to state 110 - GET_GLOBAL shift, and go to state 111 - SET_GLOBAL shift, and go to state 112 - LOAD shift, and go to state 113 - STORE shift, and go to state 114 - CONST shift, and go to state 115 - UNARY shift, and go to state 116 - BINARY shift, and go to state 117 - COMPARE shift, and go to state 118 - CONVERT shift, and go to state 119 - SELECT shift, and go to state 120 - UNREACHABLE shift, and go to state 121 - CURRENT_MEMORY shift, and go to state 122 - GROW_MEMORY shift, and go to state 123 - - $default reduce using rule 103 (instr_list) - - instr go to state 125 - plain_instr go to state 126 - block_instr go to state 127 - expr go to state 128 - rethrow_check go to state 129 - throw_check go to state 130 - try_check go to state 131 - instr_list go to state 475 - - -State 474 - - 94 if_: "(" THEN instr_list ")" "(" ELSE instr_list ")" . - - $default reduce using rule 94 (if_) - - -State 475 - - 96 if_: expr "(" THEN instr_list ")" "(" ELSE instr_list . ")" - - ")" shift, and go to state 476 - - -State 476 - - 96 if_: expr "(" THEN instr_list ")" "(" ELSE instr_list ")" . - - $default reduce using rule 96 (if_) diff --git a/lib/wabt/src/resolve-names.cc b/lib/wabt/src/resolve-names.cc index a55ec3c96f0..c18dd557c16 100644 --- a/lib/wabt/src/resolve-names.cc +++ b/lib/wabt/src/resolve-names.cc @@ -19,46 +19,50 @@ #include #include +#include "cast.h" +#include "error-handler.h" #include "expr-visitor.h" #include "ir.h" +#include "wast-lexer.h" #include "wast-parser-lexer-shared.h" namespace wabt { namespace { -typedef Label* LabelPtr; - class NameResolver : public ExprVisitor::DelegateNop { public: - NameResolver(WastLexer* lexer, - Script* script, - SourceErrorHandler* error_handler); + NameResolver(WastLexer* lexer, Script* script, ErrorHandler* error_handler); Result VisitModule(Module* module); Result VisitScript(Script* script); // Implementation of ExprVisitor::DelegateNop. - Result BeginBlockExpr(Expr*) override; - Result EndBlockExpr(Expr*) override; - Result OnBrExpr(Expr*) override; - Result OnBrIfExpr(Expr*) override; - Result OnBrTableExpr(Expr*) override; - Result OnCallExpr(Expr*) override; - Result OnCallIndirectExpr(Expr*) override; - Result OnGetGlobalExpr(Expr*) override; - Result OnGetLocalExpr(Expr*) override; - Result BeginIfExpr(Expr*) override; - Result EndIfExpr(Expr*) override; - Result BeginLoopExpr(Expr*) override; - Result EndLoopExpr(Expr*) override; - Result OnSetGlobalExpr(Expr*) override; - Result OnSetLocalExpr(Expr*) override; - Result OnTeeLocalExpr(Expr*) override; + Result BeginBlockExpr(BlockExpr*) override; + Result EndBlockExpr(BlockExpr*) override; + Result OnBrExpr(BrExpr*) override; + Result OnBrIfExpr(BrIfExpr*) override; + Result OnBrTableExpr(BrTableExpr*) override; + Result OnCallExpr(CallExpr*) override; + Result OnCallIndirectExpr(CallIndirectExpr*) override; + Result OnCatchExpr(TryExpr*, Catch*) override; + Result OnGetGlobalExpr(GetGlobalExpr*) override; + Result OnGetLocalExpr(GetLocalExpr*) override; + Result BeginIfExpr(IfExpr*) override; + Result EndIfExpr(IfExpr*) override; + Result BeginLoopExpr(LoopExpr*) override; + Result EndLoopExpr(LoopExpr*) override; + Result OnSetGlobalExpr(SetGlobalExpr*) override; + Result OnSetLocalExpr(SetLocalExpr*) override; + Result OnTeeLocalExpr(TeeLocalExpr*) override; + Result BeginTryExpr(TryExpr*) override; + Result EndTryExpr(TryExpr*) override; + Result OnThrowExpr(ThrowExpr*) override; + Result OnRethrowExpr(RethrowExpr*) override; private: void PrintError(const Location* loc, const char* fmt, ...); - void PushLabel(Label* label); + void PushLabel(const std::string& label); void PopLabel(); void CheckDuplicateBindings(const BindingHash* bindings, const char* desc); void ResolveLabelVar(Var* var); @@ -68,6 +72,7 @@ class NameResolver : public ExprVisitor::DelegateNop { void ResolveFuncTypeVar(Var* var); void ResolveTableVar(Var* var); void ResolveMemoryVar(Var* var); + void ResolveExceptionVar(Var* var); void ResolveLocalVar(Var* var); void VisitFunc(Func* func); void VisitExport(Export* export_); @@ -77,25 +82,25 @@ class NameResolver : public ExprVisitor::DelegateNop { void VisitScriptModule(ScriptModule* script_module); void VisitCommand(Command* command); - SourceErrorHandler* error_handler_ = nullptr; + ErrorHandler* error_handler_ = nullptr; WastLexer* lexer_ = nullptr; Script* script_ = nullptr; Module* current_module_ = nullptr; Func* current_func_ = nullptr; ExprVisitor visitor_; - std::vector labels_; + std::vector labels_; Result result_ = Result::Ok; }; NameResolver::NameResolver(WastLexer* lexer, Script* script, - SourceErrorHandler* error_handler) + ErrorHandler* error_handler) : error_handler_(error_handler), lexer_(lexer), script_(script), visitor_(this) {} -} // namespace +} // end anonymous namespace void WABT_PRINTF_FORMAT(3, 4) NameResolver::PrintError(const Location* loc, const char* fmt, @@ -103,11 +108,11 @@ void WABT_PRINTF_FORMAT(3, 4) NameResolver::PrintError(const Location* loc, result_ = Result::Error; va_list args; va_start(args, fmt); - wast_format_error(error_handler_, loc, lexer_, fmt, args); + WastFormatError(error_handler_, loc, lexer_, fmt, args); va_end(args); } -void NameResolver::PushLabel(Label* label) { +void NameResolver::PushLabel(const std::string& label) { labels_.push_back(label); } @@ -129,35 +134,31 @@ void NameResolver::CheckDuplicateBindings(const BindingHash* bindings, } void NameResolver::ResolveLabelVar(Var* var) { - if (var->type == VarType::Name) { + if (var->is_name()) { for (int i = labels_.size() - 1; i >= 0; --i) { - Label* label = labels_[i]; - if (string_slices_are_equal(label, &var->name)) { - destroy_string_slice(&var->name); - var->type = VarType::Index; - var->index = labels_.size() - i - 1; + const std::string& label = labels_[i]; + if (label == var->name()) { + var->set_index(labels_.size() - i - 1); return; } } - PrintError(&var->loc, "undefined label variable \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG(var->name)); + PrintError(&var->loc, "undefined label variable \"%s\"", + var->name().c_str()); } } void NameResolver::ResolveVar(const BindingHash* bindings, Var* var, const char* desc) { - if (var->type == VarType::Name) { + if (var->is_name()) { Index index = bindings->FindIndex(*var); if (index == kInvalidIndex) { - PrintError(&var->loc, "undefined %s variable \"" PRIstringslice "\"", - desc, WABT_PRINTF_STRING_SLICE_ARG(var->name)); + PrintError(&var->loc, "undefined %s variable \"%s\"", desc, + var->name().c_str()); return; } - destroy_string_slice(&var->name); - var->index = index; - var->type = VarType::Index; + var->set_index(index); } } @@ -181,103 +182,133 @@ void NameResolver::ResolveMemoryVar(Var* var) { ResolveVar(¤t_module_->memory_bindings, var, "memory"); } +void NameResolver::ResolveExceptionVar(Var* var) { + ResolveVar(¤t_module_->except_bindings, var, "exception"); +} + void NameResolver::ResolveLocalVar(Var* var) { - if (var->type == VarType::Name) { + if (var->is_name()) { if (!current_func_) return; Index index = current_func_->GetLocalIndex(*var); if (index == kInvalidIndex) { - PrintError(&var->loc, "undefined local variable \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG(var->name)); + PrintError(&var->loc, "undefined local variable \"%s\"", + var->name().c_str()); return; } - destroy_string_slice(&var->name); - var->index = index; - var->type = VarType::Index; + var->set_index(index); } } -Result NameResolver::BeginBlockExpr(Expr* expr) { - PushLabel(&expr->block->label); +Result NameResolver::BeginBlockExpr(BlockExpr* expr) { + PushLabel(expr->block->label); return Result::Ok; } -Result NameResolver::EndBlockExpr(Expr* expr) { +Result NameResolver::EndBlockExpr(BlockExpr* expr) { PopLabel(); return Result::Ok; } -Result NameResolver::BeginLoopExpr(Expr* expr) { - PushLabel(&expr->loop->label); +Result NameResolver::BeginLoopExpr(LoopExpr* expr) { + PushLabel(expr->block->label); return Result::Ok; } -Result NameResolver::EndLoopExpr(Expr* expr) { +Result NameResolver::EndLoopExpr(LoopExpr* expr) { PopLabel(); return Result::Ok; } -Result NameResolver::OnBrExpr(Expr* expr) { - ResolveLabelVar(&expr->br.var); +Result NameResolver::OnBrExpr(BrExpr* expr) { + ResolveLabelVar(&expr->var); return Result::Ok; } -Result NameResolver::OnBrIfExpr(Expr* expr) { - ResolveLabelVar(&expr->br_if.var); +Result NameResolver::OnBrIfExpr(BrIfExpr* expr) { + ResolveLabelVar(&expr->var); return Result::Ok; } -Result NameResolver::OnBrTableExpr(Expr* expr) { - for (Var& target : *expr->br_table.targets) +Result NameResolver::OnBrTableExpr(BrTableExpr* expr) { + for (Var& target : *expr->targets) ResolveLabelVar(&target); - ResolveLabelVar(&expr->br_table.default_target); + ResolveLabelVar(&expr->default_target); return Result::Ok; } -Result NameResolver::OnCallExpr(Expr* expr) { - ResolveFuncVar(&expr->call.var); +Result NameResolver::OnCallExpr(CallExpr* expr) { + ResolveFuncVar(&expr->var); return Result::Ok; } -Result NameResolver::OnCallIndirectExpr(Expr* expr) { - ResolveFuncTypeVar(&expr->call_indirect.var); +Result NameResolver::OnCallIndirectExpr(CallIndirectExpr* expr) { + ResolveFuncTypeVar(&expr->var); return Result::Ok; } -Result NameResolver::OnGetGlobalExpr(Expr* expr) { - ResolveGlobalVar(&expr->get_global.var); +Result NameResolver::OnGetGlobalExpr(GetGlobalExpr* expr) { + ResolveGlobalVar(&expr->var); return Result::Ok; } -Result NameResolver::OnGetLocalExpr(Expr* expr) { - ResolveLocalVar(&expr->get_local.var); +Result NameResolver::OnGetLocalExpr(GetLocalExpr* expr) { + ResolveLocalVar(&expr->var); return Result::Ok; } -Result NameResolver::BeginIfExpr(Expr* expr) { - PushLabel(&expr->if_.true_->label); +Result NameResolver::BeginIfExpr(IfExpr* expr) { + PushLabel(expr->true_->label); return Result::Ok; } -Result NameResolver::EndIfExpr(Expr* expr) { +Result NameResolver::EndIfExpr(IfExpr* expr) { PopLabel(); return Result::Ok; } -Result NameResolver::OnSetGlobalExpr(Expr* expr) { - ResolveGlobalVar(&expr->set_global.var); +Result NameResolver::OnSetGlobalExpr(SetGlobalExpr* expr) { + ResolveGlobalVar(&expr->var); + return Result::Ok; +} + +Result NameResolver::OnSetLocalExpr(SetLocalExpr* expr) { + ResolveLocalVar(&expr->var); return Result::Ok; } -Result NameResolver::OnSetLocalExpr(Expr* expr) { - ResolveLocalVar(&expr->set_local.var); +Result NameResolver::OnTeeLocalExpr(TeeLocalExpr* expr) { + ResolveLocalVar(&expr->var); return Result::Ok; } -Result NameResolver::OnTeeLocalExpr(Expr* expr) { - ResolveLocalVar(&expr->tee_local.var); +Result NameResolver::BeginTryExpr(TryExpr* expr) { + PushLabel(expr->block->label); + return Result::Ok; +} + +Result NameResolver::EndTryExpr(TryExpr*) { + PopLabel(); + return Result::Ok; +} + +Result NameResolver::OnCatchExpr(TryExpr* expr, Catch* catch_) { + if (!catch_->IsCatchAll()) + ResolveExceptionVar(&catch_->var); + return Result::Ok; +} + +Result NameResolver::OnThrowExpr(ThrowExpr* expr) { + ResolveExceptionVar(&expr->var); + return Result::Ok; +} + +Result NameResolver::OnRethrowExpr(RethrowExpr* expr) { + // Note: the variable refers to corresponding (enclosing) catch, using the try + // block label for context. + ResolveLabelVar(&expr->var); return Result::Ok; } @@ -312,7 +343,7 @@ void NameResolver::VisitExport(Export* export_) { break; case ExternalKind::Except: - WABT_FATAL("NameResolver::VisitExport(except) not defined\n"); + ResolveExceptionVar(&export_->var); break; } } @@ -340,6 +371,7 @@ Result NameResolver::VisitModule(Module* module) { CheckDuplicateBindings(&module->func_type_bindings, "function type"); CheckDuplicateBindings(&module->table_bindings, "table"); CheckDuplicateBindings(&module->memory_bindings, "memory"); + CheckDuplicateBindings(&module->except_bindings, "except"); for (Func* func : module->funcs) VisitFunc(func); @@ -365,7 +397,7 @@ void NameResolver::VisitScriptModule(ScriptModule* script_module) { void NameResolver::VisitCommand(Command* command) { switch (command->type) { case CommandType::Module: - VisitModule(command->module); + VisitModule(cast(command)->module); break; case CommandType::Action: @@ -385,31 +417,22 @@ void NameResolver::VisitCommand(Command* command) { break; case CommandType::AssertInvalid: { + auto* assert_invalid_command = cast(command); /* The module may be invalid because the names cannot be resolved; we * don't want to print errors or fail if that's the case, but we still * should try to resolve names when possible. */ - SourceErrorHandlerNop new_error_handler; - + ErrorHandlerNop new_error_handler; NameResolver new_resolver(lexer_, script_, &new_error_handler); - new_resolver.VisitScriptModule(command->assert_invalid.module); - if (WABT_FAILED(new_resolver.result_)) { - command->type = CommandType::AssertInvalidNonBinary; - } + new_resolver.VisitScriptModule(assert_invalid_command->module); break; } - case CommandType::AssertInvalidNonBinary: - /* The only reason a module would be "non-binary" is if the names cannot - * be resolved. So we assume name resolution has already been tried and - * failed, so skip it. */ - break; - case CommandType::AssertUnlinkable: - VisitScriptModule(command->assert_unlinkable.module); + VisitScriptModule(cast(command)->module); break; case CommandType::AssertUninstantiable: - VisitScriptModule(command->assert_uninstantiable.module); + VisitScriptModule(cast(command)->module); break; } } @@ -420,16 +443,16 @@ Result NameResolver::VisitScript(Script* script) { return result_; } -Result resolve_names_module(WastLexer* lexer, - Module* module, - SourceErrorHandler* error_handler) { +Result ResolveNamesModule(WastLexer* lexer, + Module* module, + ErrorHandler* error_handler) { NameResolver resolver(lexer, nullptr, error_handler); return resolver.VisitModule(module); } -Result resolve_names_script(WastLexer* lexer, - Script* script, - SourceErrorHandler* error_handler) { +Result ResolveNamesScript(WastLexer* lexer, + Script* script, + ErrorHandler* error_handler) { NameResolver resolver(lexer, script, error_handler); return resolver.VisitScript(script); } diff --git a/lib/wabt/src/resolve-names.h b/lib/wabt/src/resolve-names.h index 2ae7a0f90bf..b064775b9f5 100644 --- a/lib/wabt/src/resolve-names.h +++ b/lib/wabt/src/resolve-names.h @@ -24,10 +24,10 @@ namespace wabt { class WastLexer; struct Module; struct Script; -class SourceErrorHandler; +class ErrorHandler; -Result resolve_names_module(WastLexer*, Module*, SourceErrorHandler*); -Result resolve_names_script(WastLexer*, Script*, SourceErrorHandler*); +Result ResolveNamesModule(WastLexer*, Module*, ErrorHandler*); +Result ResolveNamesScript(WastLexer*, Script*, ErrorHandler*); } // namespace wabt diff --git a/lib/wabt/src/source-error-handler.cc b/lib/wabt/src/source-error-handler.cc deleted file mode 100644 index 96db134642c..00000000000 --- a/lib/wabt/src/source-error-handler.cc +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2017 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. - */ - -#include "source-error-handler.h" - -#include - -namespace wabt { - -std::string SourceErrorHandler::DefaultErrorMessage( - const Location* loc, - const std::string& error, - const std::string& source_line, - size_t source_line_column_offset, - int indent) { - std::string indent_str(indent, ' '); - std::string result = - string_printf("%s%s:%d:%d: %s\n", indent_str.c_str(), loc->filename, - loc->line, loc->first_column, error.c_str()); - result += indent_str; - if (!source_line.empty()) { - result += source_line; - result += '\n'; - result += indent_str; - - size_t num_spaces = (loc->first_column - 1) - source_line_column_offset; - size_t num_carets = loc->last_column - loc->first_column; - num_carets = std::min(num_carets, source_line.size() - num_spaces); - num_carets = std::max(num_carets, 1); - result.append(num_spaces, ' '); - result.append(num_carets, '^'); - result += '\n'; - } - return result; -} - -SourceErrorHandlerFile::SourceErrorHandlerFile(FILE* file, - const std::string& header, - PrintHeader print_header, - size_t source_line_max_length) - : file_(file), - header_(header), - print_header_(print_header), - source_line_max_length_(source_line_max_length) {} - -bool SourceErrorHandlerFile::OnError(const Location* loc, - const std::string& error, - const std::string& source_line, - size_t source_line_column_offset) { - PrintErrorHeader(); - int indent = header_.empty() ? 0 : 2; - std::string message = DefaultErrorMessage(loc, error, source_line, - source_line_column_offset, indent); - fwrite(message.data(), 1, message.size(), file_); - return true; -} - -void SourceErrorHandlerFile::PrintErrorHeader() { - if (header_.empty()) - return; - - switch (print_header_) { - case PrintHeader::Never: - break; - - case PrintHeader::Once: - print_header_ = PrintHeader::Never; - // Fallthrough. - - case PrintHeader::Always: - fprintf(file_, "%s:\n", header_.c_str()); - break; - } -} - -SourceErrorHandlerBuffer::SourceErrorHandlerBuffer( - size_t source_line_max_length) - : source_line_max_length_(source_line_max_length) {} - -bool SourceErrorHandlerBuffer::OnError(const Location* loc, - const std::string& error, - const std::string& source_line, - size_t source_line_column_offset) { - buffer_ += DefaultErrorMessage(loc, error, source_line, - source_line_column_offset, 0); - return true; -} - -} // namespace wabt diff --git a/lib/wabt/src/stream.cc b/lib/wabt/src/stream.cc index e6e989f28ce..a94bcbb6321 100644 --- a/lib/wabt/src/stream.cc +++ b/lib/wabt/src/stream.cc @@ -39,10 +39,10 @@ void Stream::WriteDataAt(size_t at, size_t size, const char* desc, PrintChars print_chars) { - if (WABT_FAILED(result_)) + if (Failed(result_)) return; if (log_stream_) { - log_stream_->WriteMemoryDump(src, size, at, nullptr, desc, print_chars); + log_stream_->WriteMemoryDump(src, size, at, print_chars, nullptr, desc); } result_ = writer_->WriteData(at, src, size); } @@ -56,7 +56,7 @@ void Stream::WriteData(const void* src, } void Stream::MoveData(size_t dst_offset, size_t src_offset, size_t size) { - if (WABT_FAILED(result_)) + if (Failed(result_)) return; if (log_stream_) { log_stream_->Writef( @@ -74,9 +74,9 @@ void Stream::Writef(const char* format, ...) { void Stream::WriteMemoryDump(const void* start, size_t size, size_t offset, + PrintChars print_chars, const char* prefix, - const char* desc, - PrintChars print_chars) { + const char* desc) { const uint8_t* p = static_cast(start); const uint8_t* end = p + size; while (p < end) { @@ -114,11 +114,19 @@ void Stream::WriteMemoryDump(const void* start, MemoryStream::MemoryStream() : Stream(&writer_) {} -FileStream::FileStream(const char* filename) +FileStream::FileStream(string_view filename) : Stream(&writer_), writer_(filename) {} FileStream::FileStream(FILE* file) : Stream(&writer_), writer_(file) {} +FileStream::FileStream(FileStream&& other) + : Stream(&writer_), writer_(std::move(other.writer_)) {} + +FileStream& FileStream::operator=(FileStream&& other) { + writer_ = std::move(other.writer_); + return *this; +} + // static std::unique_ptr FileStream::CreateStdout() { return std::unique_ptr(new FileStream(stdout)); diff --git a/lib/wabt/src/stream.h b/lib/wabt/src/stream.h index a43c5c121ce..89ee73c99bb 100644 --- a/lib/wabt/src/stream.h +++ b/lib/wabt/src/stream.h @@ -19,6 +19,7 @@ #include #include +#include #include "common.h" #include "writer.h" @@ -57,7 +58,14 @@ class Stream { size_t size, const char* desc = nullptr, PrintChars = PrintChars::No); - void MoveData(size_t dst_offset, size_t src_offset, size_t size); + + template + void WriteData(const std::vector src, + const char* desc, + PrintChars print_chars = PrintChars::No) { + if (!src.empty()) + WriteData(src.data(), src.size() * sizeof(T), desc, print_chars); + } void WriteDataAt(size_t offset, const void* src, @@ -65,6 +73,8 @@ class Stream { const char* desc = nullptr, PrintChars = PrintChars::No); + void MoveData(size_t dst_offset, size_t src_offset, size_t size); + void WABT_PRINTF_FORMAT(2, 3) Writef(const char* format, ...); // Specified as uint32_t instead of uint8_t so we can check if the value @@ -95,9 +105,9 @@ class Stream { void WriteMemoryDump(const void* start, size_t size, size_t offset = 0, + PrintChars print_chars = PrintChars::No, const char* prefix = nullptr, - const char* desc = nullptr, - PrintChars print_chars = PrintChars::No); + const char* desc = nullptr); // Convenience functions for writing enums. template @@ -122,6 +132,7 @@ class Stream { class MemoryStream : public Stream { public: + WABT_DISALLOW_COPY_AND_ASSIGN(MemoryStream); MemoryStream(); MemoryWriter& writer() { return writer_; } @@ -130,7 +141,7 @@ class MemoryStream : public Stream { return writer_.ReleaseOutputBuffer(); } - Result WriteToFile(const char* filename) { + Result WriteToFile(string_view filename) { return writer_.output_buffer().WriteToFile(filename); } @@ -140,8 +151,11 @@ class MemoryStream : public Stream { class FileStream : public Stream { public: - explicit FileStream(const char* filename); + WABT_DISALLOW_COPY_AND_ASSIGN(FileStream); + explicit FileStream(string_view filename); explicit FileStream(FILE*); + FileStream(FileStream&&); + FileStream& operator=(FileStream&&); FileWriter& writer() { return writer_; } diff --git a/lib/wabt/src/string-view.cc b/lib/wabt/src/string-view.cc index dc72f7dd811..e796207b9c8 100644 --- a/lib/wabt/src/string-view.cc +++ b/lib/wabt/src/string-view.cc @@ -123,9 +123,9 @@ string_view::size_type string_view::find(const char* s, size_type pos) const { string_view::size_type string_view::rfind(string_view s, size_type pos) const noexcept { - pos = std::min(pos, size_ - s.size_); - reverse_iterator iter = std::search(reverse_iterator(begin() + pos + s.size_), - rend(), s.rbegin(), s.rend()); + pos = std::min(std::min(pos, size_ - s.size_) + s.size_, size_); + reverse_iterator iter = std::search(reverse_iterator(begin() + pos), rend(), + s.rbegin(), s.rend()); return iter == rend() ? npos : (rend() - iter - s.size_); } diff --git a/lib/wabt/src/string-view.h b/lib/wabt/src/string-view.h index bc90130f33a..e6823b3728f 100644 --- a/lib/wabt/src/string-view.h +++ b/lib/wabt/src/string-view.h @@ -279,7 +279,7 @@ namespace std { template <> struct hash<::wabt::string_view> { ::wabt::hash_code operator()(const ::wabt::string_view& sv) { - return ::wabt::hash_range(sv.begin(), sv.end()); + return ::wabt::HashRange(sv.begin(), sv.end()); } }; diff --git a/lib/wabt/src/test-intrusive-list.cc b/lib/wabt/src/test-intrusive-list.cc new file mode 100644 index 00000000000..734fb6e8389 --- /dev/null +++ b/lib/wabt/src/test-intrusive-list.cc @@ -0,0 +1,585 @@ +/* + * Copyright 2017 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. + */ + +#include "gtest/gtest.h" + +#include + +#include "intrusive-list.h" + +using namespace wabt; + +namespace { + +struct TestObject : intrusive_list_base { + static int creation_count; + + TestObject(int data = 0, int data2 = 0) : data(data), data2(data2) { + ++creation_count; + } + + // Allow move. + TestObject(TestObject&& other) { + // Don't increment creation_count; we're moving from other. + *this = std::move(other); + } + + TestObject& operator=(TestObject&& other) { + data = other.data; + data2 = other.data2; + other.moved = true; + return *this; + } + + // Disallow copy. + TestObject(const TestObject&) = delete; + TestObject& operator=(const TestObject&) = delete; + + ~TestObject() { + if (!moved) + creation_count--; + } + + int data; + int data2; + bool moved = false; +}; + +// static +int TestObject::creation_count = 0; + +typedef intrusive_list TestObjectList; + +class IntrusiveListTest : public ::testing::Test { + protected: + virtual void SetUp() { + // Reset to 0 even if the previous test leaked objects to keep the tests + // independent. + TestObject::creation_count = 0; + } + + virtual void TearDown() { + ASSERT_EQ(0, TestObject::creation_count); + } + + TestObjectList NewList(const std::vector& data_values) { + TestObjectList result; + for (auto data_value : data_values) + result.emplace_back(data_value); + return result; + } + + void AssertListEq(const TestObjectList& list, + const std::vector& expected) { + size_t count = 0; + for (const TestObject& node : list) { + ASSERT_EQ(expected[count++], node.data); + } + ASSERT_EQ(count, expected.size()); + } + + void AssertListEq(const TestObjectList& list, + const std::vector& expected, + const std::vector& expected2) { + assert(expected.size() == expected2.size()); + size_t count = 0; + for (const TestObject& node : list) { + ASSERT_EQ(expected[count], node.data); + ASSERT_EQ(expected2[count], node.data2); + count++; + } + ASSERT_EQ(count, expected.size()); + } +}; + +} // end anonymous namespace + +TEST_F(IntrusiveListTest, default_constructor) { + TestObjectList list; +} + +TEST_F(IntrusiveListTest, node_constructor) { + TestObjectList list(new TestObject(1)); + AssertListEq(list, {1}); +} + +TEST_F(IntrusiveListTest, node_move_constructor) { + TestObjectList list(TestObject(1)); + AssertListEq(list, {1}); +} + +TEST_F(IntrusiveListTest, move_constructor) { + TestObjectList list1 = NewList({1, 2, 3}); + TestObjectList list2(std::move(list1)); + AssertListEq(list1, {}); + AssertListEq(list2, {1, 2, 3}); +} + +TEST_F(IntrusiveListTest, move_assignment_operator) { + TestObjectList list1 = NewList({1, 2, 3}); + TestObjectList list2; + + list2 = std::move(list1); + AssertListEq(list1, {}); + AssertListEq(list2, {1, 2, 3}); +} + +namespace { + +class IntrusiveListIteratorTest : public IntrusiveListTest { + protected: + virtual void SetUp() { + IntrusiveListTest::SetUp(); + + list_.emplace_back(1); + list_.emplace_back(2); + list_.emplace_back(3); + } + + virtual void TearDown() { + list_.clear(); + + IntrusiveListTest::TearDown(); + } + + template + void TestForward(Iter first, Iter last, const std::vector& expected) { + size_t count = 0; + while (first != last) { + ASSERT_EQ(expected[count], first->data); + ++first; + ++count; + } + ASSERT_EQ(count, expected.size()); + } + + template + void TestBackward(Iter first, Iter last, const std::vector& expected) { + size_t count = 0; + while (first != last) { + --last; + ASSERT_EQ(expected[count], last->data); + ++count; + } + ASSERT_EQ(count, expected.size()); + } + + + TestObjectList list_; + const TestObjectList& clist_ = list_; +}; + +} // end of anonymous namespace + +TEST_F(IntrusiveListIteratorTest, begin_end_forward) { + TestForward(list_.begin(), list_.end(), {1, 2, 3}); + TestForward(clist_.begin(), clist_.end(), {1, 2, 3}); +} + +TEST_F(IntrusiveListIteratorTest, rbegin_rend_forward) { + TestForward(list_.rbegin(), list_.rend(), {3, 2, 1}); + TestForward(clist_.rbegin(), clist_.rend(), {3, 2, 1}); +} + +TEST_F(IntrusiveListIteratorTest, cbegin_cend_forward) { + TestForward(list_.cbegin(), list_.cend(), {1, 2, 3}); + TestForward(clist_.cbegin(), clist_.cend(), {1, 2, 3}); +} + +TEST_F(IntrusiveListIteratorTest, crbegin_crend_forward) { + TestForward(list_.crbegin(), list_.crend(), {3, 2, 1}); + TestForward(clist_.crbegin(), clist_.crend(), {3, 2, 1}); +} + +TEST_F(IntrusiveListIteratorTest, begin_end_backward) { + TestBackward(list_.begin(), list_.end(), {3, 2, 1}); + TestBackward(clist_.begin(), clist_.end(), {3, 2, 1}); +} + +TEST_F(IntrusiveListIteratorTest, rbegin_rend_backward) { + TestBackward(list_.rbegin(), list_.rend(), {1, 2, 3}); + TestBackward(clist_.rbegin(), clist_.rend(), {1, 2, 3}); +} + +TEST_F(IntrusiveListIteratorTest, cbegin_cend_backward) { + TestBackward(list_.cbegin(), list_.cend(), {3, 2, 1}); + TestBackward(clist_.cbegin(), clist_.cend(), {3, 2, 1}); +} + +TEST_F(IntrusiveListIteratorTest, crbegin_crend_backward) { + TestBackward(list_.crbegin(), list_.crend(), {1, 2, 3}); + TestBackward(clist_.crbegin(), clist_.crend(), {1, 2, 3}); +} + +TEST_F(IntrusiveListTest, size_empty) { + TestObjectList list; + ASSERT_EQ(0U, list.size()); + ASSERT_TRUE(list.empty()); + + list.emplace_back(1); + ASSERT_EQ(1U, list.size()); + ASSERT_FALSE(list.empty()); +} + +TEST_F(IntrusiveListTest, front_back) { + TestObjectList list; + + list.emplace_back(1); + ASSERT_EQ(1, list.front().data); + ASSERT_EQ(1, list.back().data); + + list.emplace_back(2); + ASSERT_EQ(1, list.front().data); + ASSERT_EQ(2, list.back().data); + + const TestObjectList& clist = list; + ASSERT_EQ(1, clist.front().data); + ASSERT_EQ(2, clist.back().data); +} + +TEST_F(IntrusiveListTest, emplace_front) { + TestObjectList list; + + // Pass an additional arg to show that forwarding works properly. + list.emplace_front(1, 100); + list.emplace_front(2, 200); + list.emplace_front(3, 300); + list.emplace_front(4, 400); + + AssertListEq(list, {4, 3, 2, 1}, {400, 300, 200, 100}); +} + +TEST_F(IntrusiveListTest, emplace_back) { + TestObjectList list; + + // Pass an additional arg to show that forwarding works properly. + list.emplace_back(1, 100); + list.emplace_back(2, 200); + list.emplace_back(3, 300); + list.emplace_back(4, 400); + + AssertListEq(list, {1, 2, 3, 4}, {100, 200, 300, 400}); +} + +TEST_F(IntrusiveListTest, push_front_pointer) { + TestObjectList list; + + list.push_front(new TestObject(1)); + list.push_front(new TestObject(2)); + list.push_front(new TestObject(3)); + + AssertListEq(list, {3, 2, 1}); +} + +TEST_F(IntrusiveListTest, push_back_pointer) { + TestObjectList list; + + list.push_back(new TestObject(1)); + list.push_back(new TestObject(2)); + list.push_back(new TestObject(3)); + + AssertListEq(list, {1, 2, 3}); +} + +TEST_F(IntrusiveListTest, push_front_move) { + TestObjectList list; + + list.push_front(TestObject(1)); + list.push_front(TestObject(2)); + list.push_front(TestObject(3)); + + AssertListEq(list, {3, 2, 1}); +} + +TEST_F(IntrusiveListTest, push_back_move) { + TestObjectList list; + + list.push_back(TestObject(1)); + list.push_back(TestObject(2)); + list.push_back(TestObject(3)); + + AssertListEq(list, {1, 2, 3}); +} + +TEST_F(IntrusiveListTest, pop_front) { + TestObjectList list = NewList({1, 2, 3, 4}); + + list.pop_front(); + AssertListEq(list, {2, 3, 4}); + list.pop_front(); + AssertListEq(list, {3, 4}); + list.pop_front(); + AssertListEq(list, {4}); + list.pop_front(); + AssertListEq(list, {}); +} + +TEST_F(IntrusiveListTest, pop_back) { + TestObjectList list = NewList({1, 2, 3, 4}); + + list.pop_back(); + AssertListEq(list, {1, 2, 3}); + list.pop_back(); + AssertListEq(list, {1, 2}); + list.pop_back(); + AssertListEq(list, {1}); + list.pop_back(); + AssertListEq(list, {}); +} + +TEST_F(IntrusiveListTest, extract_front) { + TestObjectList list = NewList({1, 2, 3}); + + std::unique_ptr t1(list.extract_front()); + ASSERT_EQ(1, t1->data); + AssertListEq(list, {2, 3}); + + std::unique_ptr t2(list.extract_front()); + ASSERT_EQ(2, t2->data); + AssertListEq(list, {3}); + + std::unique_ptr t3(list.extract_front()); + ASSERT_EQ(3, t3->data); + AssertListEq(list, {}); +} + +TEST_F(IntrusiveListTest, extract_back) { + TestObjectList list = NewList({1, 2, 3}); + + std::unique_ptr t1(list.extract_back()); + ASSERT_EQ(3, t1->data); + AssertListEq(list, {1, 2}); + + std::unique_ptr t2(list.extract_back()); + ASSERT_EQ(2, t2->data); + AssertListEq(list, {1}); + + std::unique_ptr t3(list.extract_back()); + ASSERT_EQ(1, t3->data); + AssertListEq(list, {}); +} + +TEST_F(IntrusiveListTest, emplace) { + TestObjectList list; + + // Pass an additional arg to show that forwarding works properly. + list.emplace(list.begin(), 2, 200); + list.emplace(list.end(), 4, 400); + list.emplace(std::next(list.begin()), 3, 300); + list.emplace(list.begin(), 1, 100); + + AssertListEq(list, {1, 2, 3, 4}, {100, 200, 300, 400}); +} + +TEST_F(IntrusiveListTest, insert_pointer) { + TestObjectList list; + + list.insert(list.begin(), new TestObject(2)); + list.insert(list.end(), new TestObject(4)); + list.insert(std::next(list.begin()), new TestObject(3)); + list.insert(list.begin(), new TestObject(1)); + + AssertListEq(list, {1, 2, 3, 4}); +} + +TEST_F(IntrusiveListTest, insert_move) { + TestObjectList list; + + list.insert(list.begin(), TestObject(2)); + list.insert(list.end(), TestObject(4)); + list.insert(std::next(list.begin()), TestObject(3)); + list.insert(list.begin(), TestObject(1)); + + AssertListEq(list, {1, 2, 3, 4}); +} + +TEST_F(IntrusiveListTest, extract) { + TestObjectList list = NewList({1, 2, 3, 4}); + + TestObjectList::iterator t1_iter = std::next(list.begin(), 0); + TestObjectList::iterator t2_iter = std::next(list.begin(), 1); + TestObjectList::iterator t3_iter = std::next(list.begin(), 2); + TestObjectList::iterator t4_iter = std::next(list.begin(), 3); + + std::unique_ptr t2(list.extract(t2_iter)); + ASSERT_EQ(2, t2->data); + AssertListEq(list, {1, 3, 4}); + + std::unique_ptr t4(list.extract(t4_iter)); + ASSERT_EQ(4, t4->data); + AssertListEq(list, {1, 3}); + + std::unique_ptr t1(list.extract(t1_iter)); + ASSERT_EQ(1, t1->data); + AssertListEq(list, {3}); + + std::unique_ptr t3(list.extract(t3_iter)); + ASSERT_EQ(3, t3->data); + AssertListEq(list, {}); +} + +TEST_F(IntrusiveListTest, erase) { + TestObjectList list = NewList({1, 2, 3, 4}); + + TestObjectList::iterator t1_iter = std::next(list.begin(), 0); + TestObjectList::iterator t2_iter = std::next(list.begin(), 1); + TestObjectList::iterator t3_iter = std::next(list.begin(), 2); + TestObjectList::iterator t4_iter = std::next(list.begin(), 3); + + // erase returns an iterator to the following node. + ASSERT_EQ(3, list.erase(t2_iter)->data); + AssertListEq(list, {1, 3, 4}); + + ASSERT_EQ(list.end(), list.erase(t4_iter)); + AssertListEq(list, {1, 3}); + + ASSERT_EQ(3, list.erase(t1_iter)->data); + AssertListEq(list, {3}); + + ASSERT_EQ(list.end(), list.erase(t3_iter)); + AssertListEq(list, {}); +} + +TEST_F(IntrusiveListTest, erase_range) { + TestObjectList list = NewList({1, 2, 3, 4, 5, 6}); + + // OK to erase an empty range. + list.erase(list.begin(), list.begin()); + list.erase(list.end(), list.end()); + + // Erase the first element (1). + list.erase(list.begin(), std::next(list.begin())); + AssertListEq(list, {2, 3, 4, 5, 6}); + + // Erase the last element (6). + list.erase(std::prev(list.end()), list.end()); + AssertListEq(list, {2, 3, 4, 5}); + + // Erase [3, 4] => [2, 5] + list.erase(std::next(list.begin()), std::prev(list.end())); + AssertListEq(list, {2, 5}); + + // Erase the rest. + list.erase(list.begin(), list.end()); + AssertListEq(list, {}); +} + +TEST_F(IntrusiveListTest, swap) { + TestObjectList list1 = NewList({1, 2, 3, 4}); + + TestObjectList list2 = NewList({100, 200, 300}); + + AssertListEq(list1, {1, 2, 3, 4}); + AssertListEq(list2, {100, 200, 300}); + + list1.swap(list2); + + AssertListEq(list1, {100, 200, 300}); + AssertListEq(list2, {1, 2, 3, 4}); +} + +TEST_F(IntrusiveListTest, clear) { + TestObjectList list = NewList({1, 2, 3, 4}); + + ASSERT_FALSE(list.empty()); + + list.clear(); + + ASSERT_EQ(0U, list.size()); + ASSERT_TRUE(list.empty()); +} + +TEST_F(IntrusiveListTest, splice_list) { + TestObjectList list1 = NewList({1, 2, 3}); + + // Splice at beginning. + TestObjectList list2 = NewList({100, 200}); + list1.splice(list1.begin(), list2); + AssertListEq(list1, {100, 200, 1, 2, 3}); + AssertListEq(list2, {}); + + // Splice at end. + TestObjectList list3 = NewList({500, 600, 700}); + list1.splice(list1.end(), list3); + AssertListEq(list1, {100, 200, 1, 2, 3, 500, 600, 700}); + AssertListEq(list3, {}); + + // Splice in the middle. + TestObjectList list4 = NewList({400}); + list1.splice(std::next(list1.begin(), 4), list4); + AssertListEq(list1, {100, 200, 1, 2, 400, 3, 500, 600, 700}); + AssertListEq(list4, {}); +} + +TEST_F(IntrusiveListTest, splice_list_move) { + TestObjectList list1 = NewList({1, 2, 3}); + + // Splice at beginning. + list1.splice(list1.begin(), NewList({100, 200})); + AssertListEq(list1, {100, 200, 1, 2, 3}); + + // Splice at end. + list1.splice(list1.end(), NewList({500, 600, 700})); + AssertListEq(list1, {100, 200, 1, 2, 3, 500, 600, 700}); + + // Splice in the middle. + list1.splice(std::next(list1.begin(), 4), NewList({400})); + AssertListEq(list1, {100, 200, 1, 2, 400, 3, 500, 600, 700}); +} + +TEST_F(IntrusiveListTest, splice_node) { + TestObjectList list1 = NewList({1, 2, 3}); + + // Splice at beginning. + TestObjectList list2 = NewList({100, 200}); + list1.splice(list1.begin(), list2, list2.begin()); + AssertListEq(list1, {100, 1, 2, 3}); + AssertListEq(list2, {200}); + + // Splice at end. + TestObjectList list3 = NewList({500, 600, 700}); + list1.splice(list1.end(), list3, std::next(list3.begin(), 2)); + AssertListEq(list1, {100, 1, 2, 3, 700}); + AssertListEq(list3, {500, 600}); + + // Splice in the middle. + TestObjectList list4 = NewList({400}); + list1.splice(std::next(list1.begin(), 3), list4, list4.begin()); + AssertListEq(list1, {100, 1, 2, 400, 3, 700}); + AssertListEq(list4, {}); +} + +TEST_F(IntrusiveListTest, splice_range) { + TestObjectList list1 = NewList({1, 2, 3}); + + // Splice at beginning. + TestObjectList list2 = NewList({100, 200, 300}); + list1.splice(list1.begin(), list2, list2.begin(), std::prev(list2.end())); + AssertListEq(list1, {100, 200, 1, 2, 3}); + AssertListEq(list2, {300}); + + // Splice at end. + TestObjectList list3 = NewList({500, 600, 700}); + list1.splice(list1.end(), list3, std::next(list3.begin()), list3.end()); + AssertListEq(list1, {100, 200, 1, 2, 3, 600, 700}); + AssertListEq(list3, {500}); + + // Splice in the middle. + TestObjectList list4 = NewList({400}); + list1.splice(std::next(list1.begin(), 4), list4, list4.begin(), list4.end()); + AssertListEq(list1, {100, 200, 1, 2, 400, 3, 600, 700}); + AssertListEq(list4, {}); +} diff --git a/lib/wabt/src/test-string-view.cc b/lib/wabt/src/test-string-view.cc index 9a7636f7945..bba972f6168 100644 --- a/lib/wabt/src/test-string-view.cc +++ b/lib/wabt/src/test-string-view.cc @@ -25,7 +25,7 @@ using namespace wabt; namespace { -void assert_string_view_eq(const char* s, const string_view& sv) { +void assert_string_view_eq(const char* s, string_view sv) { size_t len = std::strlen(s); ASSERT_EQ(len, sv.size()); for (size_t i = 0; i < len; ++i) { @@ -35,7 +35,7 @@ void assert_string_view_eq(const char* s, const string_view& sv) { constexpr string_view::size_type npos = string_view::npos; -} // namespace +} // end anonymous namespace TEST(string_view, default_constructor) { assert_string_view_eq("", string_view()); @@ -299,6 +299,7 @@ TEST(string_view, rfind0) { ASSERT_EQ(5U, string_view("find fins").rfind(string_view("fin"))); ASSERT_EQ(0U, string_view("find fins").rfind(string_view("fin"), 4)); ASSERT_EQ(npos, string_view("find fins").rfind(string_view("no"))); + ASSERT_EQ(npos, string_view("foo").rfind(string_view("foobar"))); } TEST(string_view, rfind1) { @@ -311,12 +312,14 @@ TEST(string_view, rfind2) { ASSERT_EQ(6U, string_view("012340123").rfind("12345", npos, 2)); ASSERT_EQ(1U, string_view("012340123").rfind("12345", 4, 2)); ASSERT_EQ(npos, string_view("012340123").rfind("12345", npos, 5)); + ASSERT_EQ(npos, string_view("012").rfind("12345", npos, 5)); } TEST(string_view, rfind3) { ASSERT_EQ(6U, string_view("012340123").rfind("12")); ASSERT_EQ(1U, string_view("012340123").rfind("12", 2)); ASSERT_EQ(npos, string_view("012340123").rfind("12", 0)); + ASSERT_EQ(npos, string_view("012").rfind("12345")); } TEST(string_view, find_first_of0) { diff --git a/lib/wabt/src/test-utf8.cc b/lib/wabt/src/test-utf8.cc index 4c7430edf71..61bbfabfcc8 100644 --- a/lib/wabt/src/test-utf8.cc +++ b/lib/wabt/src/test-utf8.cc @@ -35,12 +35,12 @@ void assert_is_valid_utf8(bool expected, // Make sure it fails if there are continuation bytes past the end of the // string. for (int bad_length = 1; bad_length < length; ++bad_length) { - ASSERT_FALSE(is_valid_utf8(buf, bad_length)) << cu0 << ", " << cu1 << ", " - << cu2 << ", " << cu3; + ASSERT_FALSE(IsValidUtf8(buf, bad_length)) + << cu0 << ", " << cu1 << ", " << cu2 << ", " << cu3; } } - ASSERT_TRUE(expected == is_valid_utf8(buf, length)) + ASSERT_TRUE(expected == IsValidUtf8(buf, length)) << cu0 << ", " << cu1 << ", " << cu2 << ", " << cu3; } @@ -48,7 +48,7 @@ bool is_in_range(int x, int low, int high) { return x >= low && x < high; } -} // namespace +} // end anonymous namespace #define FOR_RANGE(var, low, high) for (int var = low; var < high; var++) #define FOR_EACH_BYTE(var) FOR_RANGE(var, 0, 0x100) diff --git a/lib/wabt/src/tools/wasm-interp.cc b/lib/wabt/src/tools/wasm-interp.cc index 2ef89804966..df9f8e4ce67 100644 --- a/lib/wabt/src/tools/wasm-interp.cc +++ b/lib/wabt/src/tools/wasm-interp.cc @@ -23,13 +23,13 @@ #include #include -#include "binary-error-handler.h" #include "binary-reader-interpreter.h" #include "binary-reader.h" +#include "error-handler.h" +#include "feature.h" #include "interpreter.h" #include "literal.h" #include "option-parser.h" -#include "source-error-handler.h" #include "stream.h" #include "wast-lexer.h" #include "wast-parser.h" @@ -43,12 +43,11 @@ static const char* s_trap_strings[] = {FOREACH_INTERPRETER_RESULT(V)}; static int s_verbose; static const char* s_infile; -static ReadBinaryOptions s_read_binary_options = - WABT_READ_BINARY_OPTIONS_DEFAULT; static Thread::Options s_thread_options; static bool s_trace; static bool s_spec; static bool s_run_all_exports; +static Features s_features; static std::unique_ptr s_log_stream; static std::unique_ptr s_stdout_stream; @@ -80,15 +79,15 @@ R"( read a file in the wasm binary format, and run in it a stack-based $ wasm-interp test.wasm -V 100 --run-all-exports )"; -static void parse_options(int argc, char** argv) { +static void ParseOptions(int argc, char** argv) { OptionParser parser("wasm-interp", s_description); parser.AddOption('v', "verbose", "Use multiple times for more info", []() { s_verbose++; s_log_stream = FileStream::CreateStdout(); - s_read_binary_options.log_stream = s_log_stream.get(); }); parser.AddHelpOption(); + s_features.AddOptions(&parser); parser.AddOption('V', "value-stack-size", "SIZE", "Size in elements of the value stack", [](const std::string& argument) { @@ -122,33 +121,27 @@ enum class ModuleType { Binary, }; -static StringSlice get_dirname(const char* s) { - /* strip everything after and including the last slash (or backslash), e.g.: - * - * s = "foo/bar/baz", => "foo/bar" - * s = "/usr/local/include/stdio.h", => "/usr/local/include" - * s = "foo.bar", => "" - * s = "some\windows\directory", => "some\windows" - */ - const char* last_slash = strrchr(s, '/'); - const char* last_backslash = strrchr(s, '\\'); - if (!last_slash) - last_slash = s; - if (!last_backslash) - last_backslash = s; - - StringSlice result; - result.start = s; - result.length = std::max(last_slash, last_backslash) - s; - return result; +static string_view GetDirname(string_view path) { + // Strip everything after and including the last slash (or backslash), e.g.: + // + // s = "foo/bar/baz", => "foo/bar" + // s = "/usr/local/include/stdio.h", => "/usr/local/include" + // s = "foo.bar", => "" + // s = "some\windows\directory", => "some\windows" + size_t last_slash = path.find_last_of('/'); + size_t last_backslash = path.find_last_of('\\'); + if (last_slash == string_view::npos) + last_slash = 0; + if (last_backslash == string_view::npos) + last_backslash = 0; + + return path.substr(0, std::max(last_slash, last_backslash)); } /* Not sure, but 100 chars is probably safe */ #define MAX_TYPED_VALUE_CHARS 100 -static void sprint_typed_value(char* buffer, - size_t size, - const TypedValue* tv) { +static void SPrintTypedValue(char* buffer, size_t size, const TypedValue* tv) { switch (tv->type) { case Type::I32: snprintf(buffer, size, "i32:%u", tv->value.i32); @@ -178,57 +171,57 @@ static void sprint_typed_value(char* buffer, } } -static void print_typed_value(const TypedValue* tv) { +static void PrintTypedValue(const TypedValue* tv) { char buffer[MAX_TYPED_VALUE_CHARS]; - sprint_typed_value(buffer, sizeof(buffer), tv); + SPrintTypedValue(buffer, sizeof(buffer), tv); printf("%s", buffer); } -static void print_typed_value_vector(const std::vector& values) { +static void PrintTypedValueVector(const std::vector& values) { for (size_t i = 0; i < values.size(); ++i) { - print_typed_value(&values[i]); + PrintTypedValue(&values[i]); if (i != values.size() - 1) printf(", "); } } -static void print_interpreter_result(const char* desc, - interpreter::Result iresult) { +static void PrintInterpreterResult(const char* desc, + interpreter::Result iresult) { printf("%s: %s\n", desc, s_trap_strings[static_cast(iresult)]); } -static void print_call(StringSlice module_name, - StringSlice func_name, - const std::vector& args, - const std::vector& results, - interpreter::Result iresult) { - if (module_name.length) - printf(PRIstringslice ".", WABT_PRINTF_STRING_SLICE_ARG(module_name)); - printf(PRIstringslice "(", WABT_PRINTF_STRING_SLICE_ARG(func_name)); - print_typed_value_vector(args); +static void PrintCall(string_view module_name, + string_view func_name, + const std::vector& args, + const std::vector& results, + interpreter::Result iresult) { + if (!module_name.empty()) + printf(PRIstringview ".", WABT_PRINTF_STRING_VIEW_ARG(module_name)); + printf(PRIstringview "(", WABT_PRINTF_STRING_VIEW_ARG(func_name)); + PrintTypedValueVector(args); printf(") =>"); if (iresult == interpreter::Result::Ok) { if (results.size() > 0) { printf(" "); - print_typed_value_vector(results); + PrintTypedValueVector(results); } printf("\n"); } else { - print_interpreter_result(" error", iresult); + PrintInterpreterResult(" error", iresult); } } -static interpreter::Result run_function(Thread* thread, - Index func_index, - const std::vector& args, - std::vector* out_results) { +static interpreter::Result RunFunction(Thread* thread, + Index func_index, + const std::vector& args, + std::vector* out_results) { return s_trace ? thread->TraceFunction(func_index, s_stdout_stream.get(), args, out_results) : thread->RunFunction(func_index, args, out_results); } -static interpreter::Result run_start_function(Thread* thread, - DefinedModule* module) { +static interpreter::Result RunStartFunction(Thread* thread, + DefinedModule* module) { if (module->start_func_index == kInvalidIndex) return interpreter::Result::Ok; @@ -237,100 +230,100 @@ static interpreter::Result run_start_function(Thread* thread, std::vector args; std::vector results; interpreter::Result iresult = - run_function(thread, module->start_func_index, args, &results); + RunFunction(thread, module->start_func_index, args, &results); assert(results.size() == 0); return iresult; } -static interpreter::Result run_export(Thread* thread, - const Export* export_, - const std::vector& args, - std::vector* out_results) { +static interpreter::Result RunExport(Thread* thread, + const interpreter::Export* export_, + const std::vector& args, + std::vector* out_results) { if (s_trace) { - printf(">>> running export \"" PRIstringslice "\":\n", - WABT_PRINTF_STRING_SLICE_ARG(export_->name)); + printf(">>> running export \"" PRIstringview "\":\n", + WABT_PRINTF_STRING_VIEW_ARG(export_->name)); } assert(export_->kind == ExternalKind::Func); - return run_function(thread, export_->index, args, out_results); + return RunFunction(thread, export_->index, args, out_results); } -static interpreter::Result run_export_by_name( - Thread* thread, - Module* module, - const StringSlice* name, - const std::vector& args, - std::vector* out_results, - RunVerbosity verbose) { - Export* export_ = module->GetExport(*name); +static interpreter::Result RunExportByName(Thread* thread, + interpreter::Module* module, + string_view name, + const std::vector& args, + std::vector* out_results, + RunVerbosity verbose) { + interpreter::Export* export_ = module->GetExport(name); if (!export_) return interpreter::Result::UnknownExport; if (export_->kind != ExternalKind::Func) return interpreter::Result::ExportKindMismatch; - return run_export(thread, export_, args, out_results); + return RunExport(thread, export_, args, out_results); } -static interpreter::Result get_global_export_by_name( +static interpreter::Result GetGlobalExportByName( Thread* thread, - Module* module, - const StringSlice* name, + interpreter::Module* module, + string_view name, std::vector* out_results) { - Export* export_ = module->GetExport(*name); + interpreter::Export* export_ = module->GetExport(name); if (!export_) return interpreter::Result::UnknownExport; if (export_->kind != ExternalKind::Global) return interpreter::Result::ExportKindMismatch; - Global* global = thread->env()->GetGlobal(export_->index); + interpreter::Global* global = thread->env()->GetGlobal(export_->index); out_results->clear(); out_results->push_back(global->typed_value); return interpreter::Result::Ok; } -static void run_all_exports(Module* module, - Thread* thread, - RunVerbosity verbose) { +static void RunAllExports(interpreter::Module* module, + Thread* thread, + RunVerbosity verbose) { std::vector args; std::vector results; - for (const Export& export_ : module->exports) { - interpreter::Result iresult = run_export(thread, &export_, args, &results); + for (const interpreter::Export& export_ : module->exports) { + interpreter::Result iresult = RunExport(thread, &export_, args, &results); if (verbose == RunVerbosity::Verbose) { - print_call(empty_string_slice(), export_.name, args, results, iresult); + PrintCall(string_view(), export_.name, args, results, iresult); } } } -static wabt::Result read_module(const char* module_filename, - Environment* env, - BinaryErrorHandler* error_handler, - DefinedModule** out_module) { +static wabt::Result ReadModule(const char* module_filename, + Environment* env, + ErrorHandler* error_handler, + DefinedModule** out_module) { wabt::Result result; - char* data; - size_t size; + std::vector file_data; *out_module = nullptr; - result = read_file(module_filename, &data, &size); - if (WABT_SUCCEEDED(result)) { - result = read_binary_interpreter(env, data, size, &s_read_binary_options, - error_handler, out_module); + result = ReadFile(module_filename, &file_data); + if (Succeeded(result)) { + ReadBinaryOptions options(s_features, s_log_stream.get(), + true /* read_debug_names */); + result = ReadBinaryInterpreter(env, DataOrNull(file_data), file_data.size(), + &options, error_handler, out_module); - if (WABT_SUCCEEDED(result)) { + if (Succeeded(result)) { if (s_verbose) env->DisassembleModule(s_stdout_stream.get(), *out_module); } - delete[] data; } return result; } -static interpreter::Result default_host_callback(const HostFunc* func, - const FuncSignature* sig, - Index num_args, - TypedValue* args, - Index num_results, - TypedValue* out_results, - void* user_data) { +static interpreter::Result DefaultHostCallback( + const HostFunc* func, + const interpreter::FuncSignature* sig, + Index num_args, + TypedValue* args, + Index num_results, + TypedValue* out_results, + void* user_data) { memset(out_results, 0, sizeof(TypedValue) * num_results); for (Index i = 0; i < num_results; ++i) out_results[i].type = sig->result_types[i]; @@ -339,24 +332,24 @@ static interpreter::Result default_host_callback(const HostFunc* func, std::vector vec_results(out_results, out_results + num_results); printf("called host "); - print_call(func->module_name, func->field_name, vec_args, vec_results, - interpreter::Result::Ok); + PrintCall(func->module_name, func->field_name, vec_args, vec_results, + interpreter::Result::Ok); return interpreter::Result::Ok; } -#define PRIimport "\"" PRIstringslice "." PRIstringslice "\"" +#define PRIimport "\"" PRIstringview "." PRIstringview "\"" #define PRINTF_IMPORT_ARG(x) \ - WABT_PRINTF_STRING_SLICE_ARG((x).module_name) \ - , WABT_PRINTF_STRING_SLICE_ARG((x).field_name) + WABT_PRINTF_STRING_VIEW_ARG((x).module_name) \ + , WABT_PRINTF_STRING_VIEW_ARG((x).field_name) class SpectestHostImportDelegate : public HostImportDelegate { public: - wabt::Result ImportFunc(Import* import, - Func* func, - FuncSignature* func_sig, + wabt::Result ImportFunc(interpreter::Import* import, + interpreter::Func* func, + interpreter::FuncSignature* func_sig, const ErrorCallback& callback) override { - if (string_slice_eq_cstr(&import->field_name, "print")) { - func->as_host()->callback = default_host_callback; + if (import->field_name == "print") { + func->as_host()->callback = DefaultHostCallback; return wabt::Result::Ok; } else { PrintError(callback, "unknown host function import " PRIimport, @@ -365,10 +358,10 @@ class SpectestHostImportDelegate : public HostImportDelegate { } } - wabt::Result ImportTable(Import* import, - Table* table, + wabt::Result ImportTable(interpreter::Import* import, + interpreter::Table* table, const ErrorCallback& callback) override { - if (string_slice_eq_cstr(&import->field_name, "table")) { + if (import->field_name == "table") { table->limits.has_max = true; table->limits.initial = 10; table->limits.max = 20; @@ -380,10 +373,10 @@ class SpectestHostImportDelegate : public HostImportDelegate { } } - wabt::Result ImportMemory(Import* import, - Memory* memory, + wabt::Result ImportMemory(interpreter::Import* import, + interpreter::Memory* memory, const ErrorCallback& callback) override { - if (string_slice_eq_cstr(&import->field_name, "memory")) { + if (import->field_name == "memory") { memory->page_limits.has_max = true; memory->page_limits.initial = 1; memory->page_limits.max = 2; @@ -396,10 +389,10 @@ class SpectestHostImportDelegate : public HostImportDelegate { } } - wabt::Result ImportGlobal(Import* import, - Global* global, + wabt::Result ImportGlobal(interpreter::Import* import, + interpreter::Global* global, const ErrorCallback& callback) override { - if (string_slice_eq_cstr(&import->field_name, "global")) { + if (import->field_name == "global") { switch (global->typed_value.type) { case Type::I32: global->typed_value.value.i32 = 666; @@ -442,138 +435,189 @@ class SpectestHostImportDelegate : public HostImportDelegate { } }; -static void init_environment(Environment* env) { - HostModule* host_module = - env->AppendHostModule(string_slice_from_cstr("spectest")); +static void InitEnvironment(Environment* env) { + HostModule* host_module = env->AppendHostModule("spectest"); host_module->import_delegate.reset(new SpectestHostImportDelegate()); } -static wabt::Result read_and_run_module(const char* module_filename) { +static wabt::Result ReadAndRunModule(const char* module_filename) { wabt::Result result; Environment env; - init_environment(&env); + InitEnvironment(&env); - BinaryErrorHandlerFile error_handler; + ErrorHandlerFile error_handler(Location::Type::Binary); DefinedModule* module = nullptr; - result = read_module(module_filename, &env, &error_handler, &module); - if (WABT_SUCCEEDED(result)) { + result = ReadModule(module_filename, &env, &error_handler, &module); + if (Succeeded(result)) { Thread thread(&env, s_thread_options); - interpreter::Result iresult = run_start_function(&thread, module); + interpreter::Result iresult = RunStartFunction(&thread, module); if (iresult == interpreter::Result::Ok) { if (s_run_all_exports) - run_all_exports(module, &thread, RunVerbosity::Verbose); + RunAllExports(module, &thread, RunVerbosity::Verbose); } else { - print_interpreter_result("error running start function", iresult); + PrintInterpreterResult("error running start function", iresult); } } return result; } -/* An extremely simple JSON parser that only knows how to parse the expected - * format from wast2wasm. */ -struct Context { - Context() - : thread(&env, s_thread_options), - last_module(nullptr), - json_data(nullptr), - json_data_size(0), - json_offset(0), - has_prev_loc(0), - command_line_number(0), - passed(0), - total(0) { - WABT_ZERO_MEMORY(source_filename); - WABT_ZERO_MEMORY(loc); - WABT_ZERO_MEMORY(prev_loc); - } - - Environment env; - Thread thread; - DefinedModule* last_module; - - /* Parsing info */ - char* json_data; - size_t json_data_size; - StringSlice source_filename; - size_t json_offset; - Location loc; - Location prev_loc; - bool has_prev_loc; - uint32_t command_line_number; - - /* Test info */ - int passed; - int total; -}; - enum class ActionType { Invoke, Get, }; struct Action { - Action() { - WABT_ZERO_MEMORY(module_name); - WABT_ZERO_MEMORY(field_name); - } - - ActionType type = ActionType::Invoke; - StringSlice module_name; - StringSlice field_name; + ::ActionType type = ::ActionType::Invoke; + std::string module_name; + std::string field_name; std::vector args; }; +// An extremely simple JSON parser that only knows how to parse the expected +// format from wast2wasm. +class SpecJSONParser { + public: + SpecJSONParser() : thread_(&env_, s_thread_options) {} + + wabt::Result ReadFile(const char* spec_json_filename); + wabt::Result ParseCommands(); + + int passed() const { return passed_; } + int total() const { return total_; } + + private: + void WABT_PRINTF_FORMAT(2, 3) PrintParseError(const char* format, ...); + void WABT_PRINTF_FORMAT(2, 3) PrintCommandError(const char* format, ...); + + void PutbackChar(); + int ReadChar(); + void SkipWhitespace(); + bool Match(const char* s); + wabt::Result Expect(const char* s); + wabt::Result ExpectKey(const char* key); + wabt::Result ParseUint32(uint32_t* out_int); + wabt::Result ParseString(std::string* out_string); + wabt::Result ParseKeyStringValue(const char* key, std::string* out_string); + wabt::Result ParseOptNameStringValue(std::string* out_string); + wabt::Result ParseLine(); + wabt::Result ParseTypeObject(Type* out_type); + wabt::Result ParseTypeVector(TypeVector* out_types); + wabt::Result ParseConst(TypedValue* out_value); + wabt::Result ParseConstVector(std::vector* out_values); + wabt::Result ParseAction(::Action* out_action); + wabt::Result ParseModuleType(ModuleType* out_type); + + std::string CreateModulePath(string_view filename); + + wabt::Result OnModuleCommand(string_view filename, string_view name); + wabt::Result RunAction(::Action* action, + interpreter::Result* out_iresult, + std::vector* out_results, + RunVerbosity verbose); + wabt::Result OnActionCommand(::Action* action); + wabt::Result ReadInvalidTextModule(const char* module_filename, + Environment* env, + ErrorHandler* error_handler); + wabt::Result ReadInvalidModule(const char* module_filename, + Environment* env, + ModuleType module_type, + const char* desc); + wabt::Result OnAssertMalformedCommand(string_view filename, + string_view text, + ModuleType module_type); + wabt::Result OnRegisterCommand(string_view name, string_view as); + wabt::Result OnAssertUnlinkableCommand(string_view filename, + string_view text, + ModuleType module_type); + wabt::Result OnAssertInvalidCommand(string_view filename, + string_view text, + ModuleType module_type); + wabt::Result OnAssertUninstantiableCommand(string_view filename, + string_view text, + ModuleType module_type); + wabt::Result OnAssertReturnCommand(::Action* action, + const std::vector& expected); + wabt::Result OnAssertReturnNanCommand(::Action* action, bool canonical); + wabt::Result OnAssertTrapCommand(::Action* action, string_view text); + wabt::Result OnAssertExhaustionCommand(::Action* action); + wabt::Result ParseCommand(); + + Environment env_; + Thread thread_; + DefinedModule* last_module_ = nullptr; + + // Parsing info. + std::vector json_data_; + std::string source_filename_; + size_t json_offset_ = 0; + Location loc_; + Location prev_loc_; + bool has_prev_loc_ = false; + uint32_t command_line_number_ = 0; + + // Test info. + int passed_ = 0; + int total_ = 0; +}; + #define CHECK_RESULT(x) \ do { \ - if (WABT_FAILED(x)) \ + if (Failed(x)) \ return wabt::Result::Error; \ } while (0) -#define EXPECT(x) CHECK_RESULT(expect(ctx, x)) -#define EXPECT_KEY(x) CHECK_RESULT(expect_key(ctx, x)) +#define EXPECT(x) CHECK_RESULT(Expect(x)) +#define EXPECT_KEY(x) CHECK_RESULT(ExpectKey(x)) #define PARSE_KEY_STRING_VALUE(key, value) \ - CHECK_RESULT(parse_key_string_value(ctx, key, value)) + CHECK_RESULT(ParseKeyStringValue(key, value)) -static void WABT_PRINTF_FORMAT(2, 3) - print_parse_error(Context* ctx, const char* format, ...) { +wabt::Result SpecJSONParser::ReadFile(const char* spec_json_filename) { + loc_.filename = spec_json_filename; + loc_.line = 1; + loc_.first_column = 1; + InitEnvironment(&env_); + + return wabt::ReadFile(spec_json_filename, &json_data_); +} + +void SpecJSONParser::PrintParseError(const char* format, ...) { WABT_SNPRINTF_ALLOCA(buffer, length, format); - fprintf(stderr, "%s:%d:%d: %s\n", ctx->loc.filename, ctx->loc.line, - ctx->loc.first_column, buffer); + fprintf(stderr, "%s:%d:%d: %s\n", loc_.filename, loc_.line, loc_.first_column, + buffer); } -static void WABT_PRINTF_FORMAT(2, 3) - print_command_error(Context* ctx, const char* format, ...) { +void SpecJSONParser::PrintCommandError(const char* format, ...) { WABT_SNPRINTF_ALLOCA(buffer, length, format); - printf(PRIstringslice ":%u: %s\n", - WABT_PRINTF_STRING_SLICE_ARG(ctx->source_filename), - ctx->command_line_number, buffer); + printf(PRIstringview ":%u: %s\n", + WABT_PRINTF_STRING_VIEW_ARG(source_filename_), command_line_number_, + buffer); } -static void putback_char(Context* ctx) { - assert(ctx->has_prev_loc); - ctx->json_offset--; - ctx->loc = ctx->prev_loc; - ctx->has_prev_loc = false; +void SpecJSONParser::PutbackChar() { + assert(has_prev_loc_); + json_offset_--; + loc_ = prev_loc_; + has_prev_loc_ = false; } -static int read_char(Context* ctx) { - if (ctx->json_offset >= ctx->json_data_size) +int SpecJSONParser::ReadChar() { + if (json_offset_ >= json_data_.size()) return -1; - ctx->prev_loc = ctx->loc; - char c = ctx->json_data[ctx->json_offset++]; + prev_loc_ = loc_; + char c = json_data_[json_offset_++]; if (c == '\n') { - ctx->loc.line++; - ctx->loc.first_column = 1; + loc_.line++; + loc_.first_column = 1; } else { - ctx->loc.first_column++; + loc_.first_column++; } - ctx->has_prev_loc = true; + has_prev_loc_ = true; return c; } -static void skip_whitespace(Context* ctx) { +void SpecJSONParser::SkipWhitespace() { while (1) { - switch (read_char(ctx)) { + switch (ReadChar()) { case -1: return; @@ -584,38 +628,38 @@ static void skip_whitespace(Context* ctx) { break; default: - putback_char(ctx); + PutbackChar(); return; } } } -static bool match(Context* ctx, const char* s) { - skip_whitespace(ctx); - Location start_loc = ctx->loc; - size_t start_offset = ctx->json_offset; - while (*s && *s == read_char(ctx)) +bool SpecJSONParser::Match(const char* s) { + SkipWhitespace(); + Location start_loc = loc_; + size_t start_offset = json_offset_; + while (*s && *s == ReadChar()) s++; if (*s == 0) { return true; } else { - ctx->json_offset = start_offset; - ctx->loc = start_loc; + json_offset_ = start_offset; + loc_ = start_loc; return false; } } -static wabt::Result expect(Context* ctx, const char* s) { - if (match(ctx, s)) { +wabt::Result SpecJSONParser::Expect(const char* s) { + if (Match(s)) { return wabt::Result::Ok; } else { - print_parse_error(ctx, "expected %s", s); + PrintParseError("expected %s", s); return wabt::Result::Error; } } -static wabt::Result expect_key(Context* ctx, const char* key) { +wabt::Result SpecJSONParser::ExpectKey(const char* key) { size_t keylen = strlen(key); size_t quoted_len = keylen + 2 + 1; char* quoted = static_cast(alloca(quoted_len)); @@ -625,20 +669,20 @@ static wabt::Result expect_key(Context* ctx, const char* key) { return wabt::Result::Ok; } -static wabt::Result parse_uint32(Context* ctx, uint32_t* out_int) { +wabt::Result SpecJSONParser::ParseUint32(uint32_t* out_int) { uint32_t result = 0; - skip_whitespace(ctx); + SkipWhitespace(); while (1) { - int c = read_char(ctx); + int c = ReadChar(); if (c >= '0' && c <= '9') { uint32_t last_result = result; result = result * 10 + static_cast(c - '0'); if (result < last_result) { - print_parse_error(ctx, "uint32 overflow"); + PrintParseError("uint32 overflow"); return wabt::Result::Error; } } else { - putback_char(ctx); + PutbackChar(); break; } } @@ -646,35 +690,29 @@ static wabt::Result parse_uint32(Context* ctx, uint32_t* out_int) { return wabt::Result::Ok; } -static wabt::Result parse_string(Context* ctx, StringSlice* out_string) { - WABT_ZERO_MEMORY(*out_string); +wabt::Result SpecJSONParser::ParseString(std::string* out_string) { + out_string->clear(); - skip_whitespace(ctx); - if (read_char(ctx) != '"') { - print_parse_error(ctx, "expected string"); + SkipWhitespace(); + if (ReadChar() != '"') { + PrintParseError("expected string"); return wabt::Result::Error; } - /* Modify json_data in-place so we can use the StringSlice directly - * without having to allocate additional memory; this is only necessary when - * the string contains an escape, but we do it always because the code is - * simpler. */ - char* start = &ctx->json_data[ctx->json_offset]; - char* p = start; - out_string->start = start; + while (1) { - int c = read_char(ctx); + int c = ReadChar(); if (c == '"') { break; } else if (c == '\\') { /* The only escape supported is \uxxxx. */ - c = read_char(ctx); + c = ReadChar(); if (c != 'u') { - print_parse_error(ctx, "expected escape: \\uxxxx"); + PrintParseError("expected escape: \\uxxxx"); return wabt::Result::Error; } uint16_t code = 0; for (int i = 0; i < 4; ++i) { - c = read_char(ctx); + c = ReadChar(); int cval; if (c >= '0' && c <= '9') { cval = c - '0'; @@ -683,309 +721,289 @@ static wabt::Result parse_string(Context* ctx, StringSlice* out_string) { } else if (c >= 'A' && c <= 'F') { cval = c - 'A' + 10; } else { - print_parse_error(ctx, "expected hex char"); + PrintParseError("expected hex char"); return wabt::Result::Error; } code = (code << 4) + cval; } if (code < 256) { - *p++ = code; + *out_string += code; } else { - print_parse_error(ctx, "only escape codes < 256 allowed, got %u\n", - code); + PrintParseError("only escape codes < 256 allowed, got %u\n", code); } } else { - *p++ = c; + *out_string += c; } } - out_string->length = p - start; return wabt::Result::Ok; } -static wabt::Result parse_key_string_value(Context* ctx, - const char* key, - StringSlice* out_string) { - WABT_ZERO_MEMORY(*out_string); +wabt::Result SpecJSONParser::ParseKeyStringValue(const char* key, + std::string* out_string) { + out_string->clear(); EXPECT_KEY(key); - return parse_string(ctx, out_string); + return ParseString(out_string); } -static wabt::Result parse_opt_name_string_value(Context* ctx, - StringSlice* out_string) { - WABT_ZERO_MEMORY(*out_string); - if (match(ctx, "\"name\"")) { +wabt::Result SpecJSONParser::ParseOptNameStringValue(std::string* out_string) { + out_string->clear(); + if (Match("\"name\"")) { EXPECT(":"); - CHECK_RESULT(parse_string(ctx, out_string)); + CHECK_RESULT(ParseString(out_string)); EXPECT(","); } return wabt::Result::Ok; } -static wabt::Result parse_line(Context* ctx) { +wabt::Result SpecJSONParser::ParseLine() { EXPECT_KEY("line"); - CHECK_RESULT(parse_uint32(ctx, &ctx->command_line_number)); + CHECK_RESULT(ParseUint32(&command_line_number_)); return wabt::Result::Ok; } -static wabt::Result parse_type_object(Context* ctx, Type* out_type) { - StringSlice type_str; +wabt::Result SpecJSONParser::ParseTypeObject(Type* out_type) { + std::string type_str; EXPECT("{"); PARSE_KEY_STRING_VALUE("type", &type_str); EXPECT("}"); - if (string_slice_eq_cstr(&type_str, "i32")) { + if (type_str == "i32") { *out_type = Type::I32; return wabt::Result::Ok; - } else if (string_slice_eq_cstr(&type_str, "f32")) { + } else if (type_str == "f32") { *out_type = Type::F32; return wabt::Result::Ok; - } else if (string_slice_eq_cstr(&type_str, "i64")) { + } else if (type_str == "i64") { *out_type = Type::I64; return wabt::Result::Ok; - } else if (string_slice_eq_cstr(&type_str, "f64")) { + } else if (type_str == "f64") { *out_type = Type::F64; return wabt::Result::Ok; } else { - print_parse_error(ctx, "unknown type: \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG(type_str)); + PrintParseError("unknown type: \"" PRIstringview "\"", + WABT_PRINTF_STRING_VIEW_ARG(type_str)); return wabt::Result::Error; } } -static wabt::Result parse_type_vector(Context* ctx, TypeVector* out_types) { +wabt::Result SpecJSONParser::ParseTypeVector(TypeVector* out_types) { out_types->clear(); EXPECT("["); bool first = true; - while (!match(ctx, "]")) { + while (!Match("]")) { if (!first) EXPECT(","); Type type; - CHECK_RESULT(parse_type_object(ctx, &type)); + CHECK_RESULT(ParseTypeObject(&type)); first = false; out_types->push_back(type); } return wabt::Result::Ok; } -static wabt::Result parse_const(Context* ctx, TypedValue* out_value) { - StringSlice type_str; - StringSlice value_str; +wabt::Result SpecJSONParser::ParseConst(TypedValue* out_value) { + std::string type_str; + std::string value_str; EXPECT("{"); PARSE_KEY_STRING_VALUE("type", &type_str); EXPECT(","); PARSE_KEY_STRING_VALUE("value", &value_str); EXPECT("}"); - const char* value_start = value_str.start; - const char* value_end = value_str.start + value_str.length; + const char* value_start = value_str.data(); + const char* value_end = value_str.data() + value_str.size(); - if (string_slice_eq_cstr(&type_str, "i32")) { + if (type_str == "i32") { uint32_t value; - CHECK_RESULT(parse_int32(value_start, value_end, &value, - ParseIntType::UnsignedOnly)); + CHECK_RESULT( + ParseInt32(value_start, value_end, &value, ParseIntType::UnsignedOnly)); out_value->type = Type::I32; out_value->value.i32 = value; return wabt::Result::Ok; - } else if (string_slice_eq_cstr(&type_str, "f32")) { + } else if (type_str == "f32") { uint32_t value_bits; - CHECK_RESULT(parse_int32(value_start, value_end, &value_bits, - ParseIntType::UnsignedOnly)); + CHECK_RESULT(ParseInt32(value_start, value_end, &value_bits, + ParseIntType::UnsignedOnly)); out_value->type = Type::F32; out_value->value.f32_bits = value_bits; return wabt::Result::Ok; - } else if (string_slice_eq_cstr(&type_str, "i64")) { + } else if (type_str == "i64") { uint64_t value; - CHECK_RESULT(parse_int64(value_start, value_end, &value, - ParseIntType::UnsignedOnly)); + CHECK_RESULT( + ParseInt64(value_start, value_end, &value, ParseIntType::UnsignedOnly)); out_value->type = Type::I64; out_value->value.i64 = value; return wabt::Result::Ok; - } else if (string_slice_eq_cstr(&type_str, "f64")) { + } else if (type_str == "f64") { uint64_t value_bits; - CHECK_RESULT(parse_int64(value_start, value_end, &value_bits, - ParseIntType::UnsignedOnly)); + CHECK_RESULT(ParseInt64(value_start, value_end, &value_bits, + ParseIntType::UnsignedOnly)); out_value->type = Type::F64; out_value->value.f64_bits = value_bits; return wabt::Result::Ok; } else { - print_parse_error(ctx, "unknown type: \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG(type_str)); + PrintParseError("unknown type: \"" PRIstringview "\"", + WABT_PRINTF_STRING_VIEW_ARG(type_str)); return wabt::Result::Error; } } -static wabt::Result parse_const_vector(Context* ctx, - std::vector* out_values) { +wabt::Result SpecJSONParser::ParseConstVector( + std::vector* out_values) { out_values->clear(); EXPECT("["); bool first = true; - while (!match(ctx, "]")) { + while (!Match("]")) { if (!first) EXPECT(","); TypedValue value; - CHECK_RESULT(parse_const(ctx, &value)); + CHECK_RESULT(ParseConst(&value)); out_values->push_back(value); first = false; } return wabt::Result::Ok; } -static wabt::Result parse_action(Context* ctx, Action* out_action) { +wabt::Result SpecJSONParser::ParseAction(::Action* out_action) { EXPECT_KEY("action"); EXPECT("{"); EXPECT_KEY("type"); - if (match(ctx, "\"invoke\"")) { - out_action->type = ActionType::Invoke; + if (Match("\"invoke\"")) { + out_action->type = ::ActionType::Invoke; } else { EXPECT("\"get\""); - out_action->type = ActionType::Get; + out_action->type = ::ActionType::Get; } EXPECT(","); - if (match(ctx, "\"module\"")) { + if (Match("\"module\"")) { EXPECT(":"); - CHECK_RESULT(parse_string(ctx, &out_action->module_name)); + CHECK_RESULT(ParseString(&out_action->module_name)); EXPECT(","); } PARSE_KEY_STRING_VALUE("field", &out_action->field_name); - if (out_action->type == ActionType::Invoke) { + if (out_action->type == ::ActionType::Invoke) { EXPECT(","); EXPECT_KEY("args"); - CHECK_RESULT(parse_const_vector(ctx, &out_action->args)); + CHECK_RESULT(ParseConstVector(&out_action->args)); } EXPECT("}"); return wabt::Result::Ok; } -static wabt::Result parse_module_type(Context* ctx, ModuleType* out_type) { - StringSlice module_type_str; - WABT_ZERO_MEMORY(module_type_str); +wabt::Result SpecJSONParser::ParseModuleType(ModuleType* out_type) { + std::string module_type_str; PARSE_KEY_STRING_VALUE("module_type", &module_type_str); - if (string_slice_eq_cstr(&module_type_str, "text")) { + if (module_type_str == "text") { *out_type = ModuleType::Text; return wabt::Result::Ok; - } else if (string_slice_eq_cstr(&module_type_str, "binary")) { + } else if (module_type_str == "binary") { *out_type = ModuleType::Binary; return wabt::Result::Ok; } else { - print_parse_error(ctx, "unknown module type: \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG(module_type_str)); + PrintParseError("unknown module type: \"" PRIstringview "\"", + WABT_PRINTF_STRING_VIEW_ARG(module_type_str)); return wabt::Result::Error; } } -static void convert_backslash_to_slash(char* s, size_t length) { - for (size_t i = 0; i < length; ++i) - if (s[i] == '\\') - s[i] = '/'; -} - -static char* create_module_path(Context* ctx, StringSlice filename) { - const char* spec_json_filename = ctx->loc.filename; - StringSlice dirname = get_dirname(spec_json_filename); - size_t path_len = dirname.length + 1 + filename.length + 1; - char* path = new char[path_len]; +std::string SpecJSONParser::CreateModulePath(string_view filename) { + const char* spec_json_filename = loc_.filename; + string_view dirname = GetDirname(spec_json_filename); + std::string path; - if (dirname.length == 0) { - snprintf(path, path_len, PRIstringslice, - WABT_PRINTF_STRING_SLICE_ARG(filename)); + if (dirname.size() == 0) { + path = filename.to_string(); } else { - snprintf(path, path_len, PRIstringslice "/" PRIstringslice, - WABT_PRINTF_STRING_SLICE_ARG(dirname), - WABT_PRINTF_STRING_SLICE_ARG(filename)); + path = dirname.to_string(); + path += '/'; + path += filename.to_string(); } - convert_backslash_to_slash(path, path_len); + ConvertBackslashToSlash(&path); return path; } -static wabt::Result on_module_command(Context* ctx, - StringSlice filename, - StringSlice name) { - char* path = create_module_path(ctx, filename); - Environment::MarkPoint mark = ctx->env.Mark(); - BinaryErrorHandlerFile error_handler; +wabt::Result SpecJSONParser::OnModuleCommand(string_view filename, + string_view name) { + std::string path = CreateModulePath(filename); + Environment::MarkPoint mark = env_.Mark(); + ErrorHandlerFile error_handler(Location::Type::Binary); wabt::Result result = - read_module(path, &ctx->env, &error_handler, &ctx->last_module); + ReadModule(path.c_str(), &env_, &error_handler, &last_module_); - if (WABT_FAILED(result)) { - ctx->env.ResetToMarkPoint(mark); - print_command_error(ctx, "error reading module: \"%s\"", path); - delete[] path; + if (Failed(result)) { + env_.ResetToMarkPoint(mark); + PrintCommandError("error reading module: \"%s\"", path.c_str()); return wabt::Result::Error; } - delete[] path; - - interpreter::Result iresult = - run_start_function(&ctx->thread, ctx->last_module); + interpreter::Result iresult = RunStartFunction(&thread_, last_module_); if (iresult != interpreter::Result::Ok) { - ctx->env.ResetToMarkPoint(mark); - print_interpreter_result("error running start function", iresult); + env_.ResetToMarkPoint(mark); + PrintInterpreterResult("error running start function", iresult); return wabt::Result::Error; } - if (!string_slice_is_empty(&name)) { - ctx->last_module->name = dup_string_slice(name); - ctx->env.EmplaceModuleBinding(string_slice_to_string(name), - Binding(ctx->env.GetModuleCount() - 1)); + if (!name.empty()) { + last_module_->name = name.to_string(); + env_.EmplaceModuleBinding(name.to_string(), + Binding(env_.GetModuleCount() - 1)); } return wabt::Result::Ok; } -static wabt::Result run_action(Context* ctx, - Action* action, - interpreter::Result* out_iresult, - std::vector* out_results, - RunVerbosity verbose) { +wabt::Result SpecJSONParser::RunAction(::Action* action, + interpreter::Result* out_iresult, + std::vector* out_results, + RunVerbosity verbose) { out_results->clear(); - Module* module; - if (!string_slice_is_empty(&action->module_name)) { - module = ctx->env.FindModule(action->module_name); + interpreter::Module* module; + if (!action->module_name.empty()) { + module = env_.FindModule(action->module_name); } else { - module = ctx->env.GetLastModule(); + module = env_.GetLastModule(); } assert(module); switch (action->type) { - case ActionType::Invoke: - *out_iresult = - run_export_by_name(&ctx->thread, module, &action->field_name, - action->args, out_results, verbose); + case ::ActionType::Invoke: + *out_iresult = RunExportByName(&thread_, module, action->field_name, + action->args, out_results, verbose); if (verbose == RunVerbosity::Verbose) { - print_call(empty_string_slice(), action->field_name, action->args, - *out_results, *out_iresult); + PrintCall(string_view(), action->field_name, action->args, *out_results, + *out_iresult); } return wabt::Result::Ok; - case ActionType::Get: { - *out_iresult = get_global_export_by_name( - &ctx->thread, module, &action->field_name, out_results); + case ::ActionType::Get: { + *out_iresult = GetGlobalExportByName(&thread_, module, action->field_name, + out_results); return wabt::Result::Ok; } default: - print_command_error(ctx, "invalid action type %d", - static_cast(action->type)); + PrintCommandError("invalid action type %d", + static_cast(action->type)); return wabt::Result::Error; } } -static wabt::Result on_action_command(Context* ctx, Action* action) { +wabt::Result SpecJSONParser::OnActionCommand(::Action* action) { std::vector results; interpreter::Result iresult; - ctx->total++; + total_++; wabt::Result result = - run_action(ctx, action, &iresult, &results, RunVerbosity::Verbose); - if (WABT_SUCCEEDED(result)) { + RunAction(action, &iresult, &results, RunVerbosity::Verbose); + if (Succeeded(result)) { if (iresult == interpreter::Result::Ok) { - ctx->passed++; + passed_++; } else { - print_command_error(ctx, "unexpected trap: %s", - s_trap_strings[static_cast(iresult)]); + PrintCommandError("unexpected trap: %s", + s_trap_strings[static_cast(iresult)]); result = wabt::Result::Error; } } @@ -993,38 +1011,37 @@ static wabt::Result on_action_command(Context* ctx, Action* action) { return result; } -static wabt::Result read_invalid_text_module( +wabt::Result SpecJSONParser::ReadInvalidTextModule( const char* module_filename, Environment* env, - SourceErrorHandler* source_error_handler) { + ErrorHandler* error_handler) { std::unique_ptr lexer = WastLexer::CreateFileLexer(module_filename); - wabt::Result result = parse_wast(lexer.get(), nullptr, source_error_handler); + wabt::Result result = ParseWast(lexer.get(), nullptr, error_handler); return result; } -static wabt::Result read_invalid_module(Context* ctx, - const char* module_filename, - Environment* env, - ModuleType module_type, - const char* desc) { +wabt::Result SpecJSONParser::ReadInvalidModule(const char* module_filename, + Environment* env, + ModuleType module_type, + const char* desc) { std::string header = - string_printf(PRIstringslice ":%d: %s passed", - WABT_PRINTF_STRING_SLICE_ARG(ctx->source_filename), - ctx->command_line_number, desc); + StringPrintf(PRIstringview ":%d: %s passed", + WABT_PRINTF_STRING_VIEW_ARG(source_filename_), + command_line_number_, desc); switch (module_type) { case ModuleType::Text: { - SourceErrorHandlerFile error_handler( - stdout, header, SourceErrorHandlerFile::PrintHeader::Once); - return read_invalid_text_module(module_filename, env, &error_handler); + ErrorHandlerFile error_handler(Location::Type::Text, stdout, header, + ErrorHandlerFile::PrintHeader::Once); + return ReadInvalidTextModule(module_filename, env, &error_handler); } case ModuleType::Binary: { DefinedModule* module; - BinaryErrorHandlerFile error_handler( - stdout, header, BinaryErrorHandlerFile::PrintHeader::Once); - return read_module(module_filename, env, &error_handler, &module); + ErrorHandlerFile error_handler(Location::Type::Binary, stdout, header, + ErrorHandlerFile::PrintHeader::Once); + return ReadModule(module_filename, env, &error_handler, &module); } default: @@ -1032,128 +1049,119 @@ static wabt::Result read_invalid_module(Context* ctx, } } -static wabt::Result on_assert_malformed_command(Context* ctx, - StringSlice filename, - StringSlice text, - ModuleType module_type) { +wabt::Result SpecJSONParser::OnAssertMalformedCommand(string_view filename, + string_view text, + ModuleType module_type) { Environment env; - init_environment(&env); + InitEnvironment(&env); - ctx->total++; - char* path = create_module_path(ctx, filename); + total_++; + std::string path = CreateModulePath(filename); wabt::Result result = - read_invalid_module(ctx, path, &env, module_type, "assert_malformed"); - if (WABT_FAILED(result)) { - ctx->passed++; + ReadInvalidModule(path.c_str(), &env, module_type, "assert_malformed"); + if (Failed(result)) { + passed_++; result = wabt::Result::Ok; } else { - print_command_error(ctx, "expected module to be malformed: \"%s\"", path); + PrintCommandError("expected module to be malformed: \"%s\"", path.c_str()); result = wabt::Result::Error; } - delete[] path; return result; } -static wabt::Result on_register_command(Context* ctx, - StringSlice name, - StringSlice as) { +wabt::Result SpecJSONParser::OnRegisterCommand(string_view name, + string_view as) { Index module_index; - if (!string_slice_is_empty(&name)) { - module_index = ctx->env.FindModuleIndex(name); + if (!name.empty()) { + module_index = env_.FindModuleIndex(name); } else { - module_index = ctx->env.GetLastModuleIndex(); + module_index = env_.GetLastModuleIndex(); } if (module_index == kInvalidIndex) { - print_command_error(ctx, "unknown module in register"); + PrintCommandError("unknown module in register"); return wabt::Result::Error; } - ctx->env.EmplaceRegisteredModuleBinding(string_slice_to_string(as), - Binding(module_index)); + env_.EmplaceRegisteredModuleBinding(as.to_string(), Binding(module_index)); return wabt::Result::Ok; } -static wabt::Result on_assert_unlinkable_command(Context* ctx, - StringSlice filename, - StringSlice text, - ModuleType module_type) { - ctx->total++; - char* path = create_module_path(ctx, filename); - Environment::MarkPoint mark = ctx->env.Mark(); - wabt::Result result = read_invalid_module(ctx, path, &ctx->env, module_type, - "assert_unlinkable"); - ctx->env.ResetToMarkPoint(mark); - - if (WABT_FAILED(result)) { - ctx->passed++; +wabt::Result SpecJSONParser::OnAssertUnlinkableCommand(string_view filename, + string_view text, + ModuleType module_type) { + total_++; + std::string path = CreateModulePath(filename); + Environment::MarkPoint mark = env_.Mark(); + wabt::Result result = + ReadInvalidModule(path.c_str(), &env_, module_type, "assert_unlinkable"); + env_.ResetToMarkPoint(mark); + + if (Failed(result)) { + passed_++; result = wabt::Result::Ok; } else { - print_command_error(ctx, "expected module to be unlinkable: \"%s\"", path); + PrintCommandError("expected module to be unlinkable: \"%s\"", path.c_str()); result = wabt::Result::Error; } - delete[] path; return result; } -static wabt::Result on_assert_invalid_command(Context* ctx, - StringSlice filename, - StringSlice text, - ModuleType module_type) { +wabt::Result SpecJSONParser::OnAssertInvalidCommand(string_view filename, + string_view text, + ModuleType module_type) { Environment env; - init_environment(&env); + InitEnvironment(&env); - ctx->total++; - char* path = create_module_path(ctx, filename); + total_++; + std::string path = CreateModulePath(filename); wabt::Result result = - read_invalid_module(ctx, path, &env, module_type, "assert_invalid"); - if (WABT_FAILED(result)) { - ctx->passed++; + ReadInvalidModule(path.c_str(), &env, module_type, "assert_invalid"); + if (Failed(result)) { + passed_++; result = wabt::Result::Ok; } else { - print_command_error(ctx, "expected module to be invalid: \"%s\"", path); + PrintCommandError("expected module to be invalid: \"%s\"", path.c_str()); result = wabt::Result::Error; } - delete[] path; return result; } -static wabt::Result on_assert_uninstantiable_command(Context* ctx, - StringSlice filename, - StringSlice text, - ModuleType module_type) { - BinaryErrorHandlerFile error_handler; - ctx->total++; - char* path = create_module_path(ctx, filename); +wabt::Result SpecJSONParser::OnAssertUninstantiableCommand( + string_view filename, + string_view text, + ModuleType module_type) { + ErrorHandlerFile error_handler(Location::Type::Binary); + total_++; + std::string path = CreateModulePath(filename); DefinedModule* module; - Environment::MarkPoint mark = ctx->env.Mark(); - wabt::Result result = read_module(path, &ctx->env, &error_handler, &module); + Environment::MarkPoint mark = env_.Mark(); + wabt::Result result = + ReadModule(path.c_str(), &env_, &error_handler, &module); - if (WABT_SUCCEEDED(result)) { - interpreter::Result iresult = run_start_function(&ctx->thread, module); + if (Succeeded(result)) { + interpreter::Result iresult = RunStartFunction(&thread_, module); if (iresult == interpreter::Result::Ok) { - print_command_error(ctx, "expected error running start function: \"%s\"", - path); + PrintCommandError("expected error running start function: \"%s\"", + path.c_str()); result = wabt::Result::Error; } else { - ctx->passed++; + passed_++; result = wabt::Result::Ok; } } else { - print_command_error(ctx, "error reading module: \"%s\"", path); + PrintCommandError("error reading module: \"%s\"", path.c_str()); result = wabt::Result::Error; } - ctx->env.ResetToMarkPoint(mark); - delete[] path; + env_.ResetToMarkPoint(mark); return result; } -static bool typed_values_are_equal(const TypedValue* tv1, - const TypedValue* tv2) { +static bool TypedValuesAreEqual(const TypedValue* tv1, const TypedValue* tv2) { if (tv1->type != tv2->type) return false; @@ -1172,138 +1180,127 @@ static bool typed_values_are_equal(const TypedValue* tv1, } } -static wabt::Result on_assert_return_command( - Context* ctx, - Action* action, +wabt::Result SpecJSONParser::OnAssertReturnCommand( + ::Action* action, const std::vector& expected) { std::vector results; interpreter::Result iresult; - ctx->total++; + total_++; wabt::Result result = - run_action(ctx, action, &iresult, &results, RunVerbosity::Quiet); + RunAction(action, &iresult, &results, RunVerbosity::Quiet); - if (WABT_SUCCEEDED(result)) { + if (Succeeded(result)) { if (iresult == interpreter::Result::Ok) { if (results.size() == expected.size()) { for (size_t i = 0; i < results.size(); ++i) { const TypedValue* expected_tv = &expected[i]; const TypedValue* actual_tv = &results[i]; - if (!typed_values_are_equal(expected_tv, actual_tv)) { + if (!TypedValuesAreEqual(expected_tv, actual_tv)) { char expected_str[MAX_TYPED_VALUE_CHARS]; char actual_str[MAX_TYPED_VALUE_CHARS]; - sprint_typed_value(expected_str, sizeof(expected_str), expected_tv); - sprint_typed_value(actual_str, sizeof(actual_str), actual_tv); - print_command_error(ctx, - "mismatch in result %" PRIzd - " of assert_return: expected %s, got %s", - i, expected_str, actual_str); + SPrintTypedValue(expected_str, sizeof(expected_str), expected_tv); + SPrintTypedValue(actual_str, sizeof(actual_str), actual_tv); + PrintCommandError("mismatch in result %" PRIzd + " of assert_return: expected %s, got %s", + i, expected_str, actual_str); result = wabt::Result::Error; } } } else { - print_command_error( - ctx, + PrintCommandError( "result length mismatch in assert_return: expected %" PRIzd ", got %" PRIzd, expected.size(), results.size()); result = wabt::Result::Error; } } else { - print_command_error(ctx, "unexpected trap: %s", - s_trap_strings[static_cast(iresult)]); + PrintCommandError("unexpected trap: %s", + s_trap_strings[static_cast(iresult)]); result = wabt::Result::Error; } } - if (WABT_SUCCEEDED(result)) - ctx->passed++; + if (Succeeded(result)) + passed_++; return result; } -static wabt::Result on_assert_return_nan_command(Context* ctx, - Action* action, - bool canonical) { +wabt::Result SpecJSONParser::OnAssertReturnNanCommand(::Action* action, + bool canonical) { std::vector results; interpreter::Result iresult; - ctx->total++; + total_++; wabt::Result result = - run_action(ctx, action, &iresult, &results, RunVerbosity::Quiet); - if (WABT_SUCCEEDED(result)) { + RunAction(action, &iresult, &results, RunVerbosity::Quiet); + if (Succeeded(result)) { if (iresult == interpreter::Result::Ok) { if (results.size() != 1) { - print_command_error(ctx, "expected one result, got %" PRIzd, - results.size()); + PrintCommandError("expected one result, got %" PRIzd, results.size()); result = wabt::Result::Error; } const TypedValue& actual = results[0]; switch (actual.type) { case Type::F32: { - typedef bool (*IsNanFunc)(uint32_t); - IsNanFunc is_nan_func = - canonical ? is_canonical_nan_f32 : is_arithmetic_nan_f32; - if (!is_nan_func(actual.value.f32_bits)) { + bool is_nan = canonical ? IsCanonicalNan(actual.value.f32_bits) + : IsArithmeticNan(actual.value.f32_bits); + if (!is_nan) { char actual_str[MAX_TYPED_VALUE_CHARS]; - sprint_typed_value(actual_str, sizeof(actual_str), &actual); - print_command_error(ctx, "expected result to be nan, got %s", - actual_str); + SPrintTypedValue(actual_str, sizeof(actual_str), &actual); + PrintCommandError("expected result to be nan, got %s", actual_str); result = wabt::Result::Error; } break; } case Type::F64: { - typedef bool (*IsNanFunc)(uint64_t); - IsNanFunc is_nan_func = - canonical ? is_canonical_nan_f64 : is_arithmetic_nan_f64; - if (!is_nan_func(actual.value.f64_bits)) { + bool is_nan = canonical ? IsCanonicalNan(actual.value.f64_bits) + : IsArithmeticNan(actual.value.f64_bits); + if (!is_nan) { char actual_str[MAX_TYPED_VALUE_CHARS]; - sprint_typed_value(actual_str, sizeof(actual_str), &actual); - print_command_error(ctx, "expected result to be nan, got %s", - actual_str); + SPrintTypedValue(actual_str, sizeof(actual_str), &actual); + PrintCommandError("expected result to be nan, got %s", actual_str); result = wabt::Result::Error; } break; } default: - print_command_error(ctx, - "expected result type to be f32 or f64, got %s", - get_type_name(actual.type)); + PrintCommandError("expected result type to be f32 or f64, got %s", + GetTypeName(actual.type)); result = wabt::Result::Error; break; } } else { - print_command_error(ctx, "unexpected trap: %s", - s_trap_strings[static_cast(iresult)]); + PrintCommandError("unexpected trap: %s", + s_trap_strings[static_cast(iresult)]); result = wabt::Result::Error; } } - if (WABT_SUCCEEDED(result)) - ctx->passed++; + if (Succeeded(result)) + passed_++; return wabt::Result::Ok; } -static wabt::Result on_assert_trap_command(Context* ctx, - Action* action, - StringSlice text) { +wabt::Result SpecJSONParser::OnAssertTrapCommand(::Action* action, + string_view text) { std::vector results; interpreter::Result iresult; - ctx->total++; + total_++; wabt::Result result = - run_action(ctx, action, &iresult, &results, RunVerbosity::Quiet); - if (WABT_SUCCEEDED(result)) { + RunAction(action, &iresult, &results, RunVerbosity::Quiet); + if (Succeeded(result)) { if (iresult != interpreter::Result::Ok) { - ctx->passed++; + passed_++; } else { - print_command_error(ctx, "expected trap: \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG(text)); + PrintCommandError("expected trap: \"" PRIstringview "\"", + WABT_PRINTF_STRING_VIEW_ARG(text)); result = wabt::Result::Error; } } @@ -1311,19 +1308,19 @@ static wabt::Result on_assert_trap_command(Context* ctx, return result; } -static wabt::Result on_assert_exhaustion_command(Context* ctx, Action* action) { +wabt::Result SpecJSONParser::OnAssertExhaustionCommand(::Action* action) { std::vector results; interpreter::Result iresult; - ctx->total++; + total_++; wabt::Result result = - run_action(ctx, action, &iresult, &results, RunVerbosity::Quiet); - if (WABT_SUCCEEDED(result)) { + RunAction(action, &iresult, &results, RunVerbosity::Quiet); + if (Succeeded(result)) { if (iresult == interpreter::Result::TrapCallStackExhausted || iresult == interpreter::Result::TrapValueStackExhausted) { - ctx->passed++; + passed_++; } else { - print_command_error(ctx, "expected call stack exhaustion"); + PrintCommandError("expected call stack exhaustion"); result = wabt::Result::Error; } } @@ -1331,227 +1328,195 @@ static wabt::Result on_assert_exhaustion_command(Context* ctx, Action* action) { return result; } -static wabt::Result parse_command(Context* ctx) { +wabt::Result SpecJSONParser::ParseCommand() { EXPECT("{"); EXPECT_KEY("type"); - if (match(ctx, "\"module\"")) { - StringSlice name; - StringSlice filename; - WABT_ZERO_MEMORY(name); - WABT_ZERO_MEMORY(filename); + if (Match("\"module\"")) { + std::string name; + std::string filename; EXPECT(","); - CHECK_RESULT(parse_line(ctx)); + CHECK_RESULT(ParseLine()); EXPECT(","); - CHECK_RESULT(parse_opt_name_string_value(ctx, &name)); + CHECK_RESULT(ParseOptNameStringValue(&name)); PARSE_KEY_STRING_VALUE("filename", &filename); - on_module_command(ctx, filename, name); - } else if (match(ctx, "\"action\"")) { - Action action; + OnModuleCommand(filename, name); + } else if (Match("\"action\"")) { + ::Action action; EXPECT(","); - CHECK_RESULT(parse_line(ctx)); + CHECK_RESULT(ParseLine()); EXPECT(","); - CHECK_RESULT(parse_action(ctx, &action)); - on_action_command(ctx, &action); - } else if (match(ctx, "\"register\"")) { - StringSlice as; - StringSlice name; - WABT_ZERO_MEMORY(as); - WABT_ZERO_MEMORY(name); + CHECK_RESULT(ParseAction(&action)); + OnActionCommand(&action); + } else if (Match("\"register\"")) { + std::string as; + std::string name; EXPECT(","); - CHECK_RESULT(parse_line(ctx)); + CHECK_RESULT(ParseLine()); EXPECT(","); - CHECK_RESULT(parse_opt_name_string_value(ctx, &name)); + CHECK_RESULT(ParseOptNameStringValue(&name)); PARSE_KEY_STRING_VALUE("as", &as); - on_register_command(ctx, name, as); - } else if (match(ctx, "\"assert_malformed\"")) { - StringSlice filename; - StringSlice text; + OnRegisterCommand(name, as); + } else if (Match("\"assert_malformed\"")) { + std::string filename; + std::string text; ModuleType module_type; - WABT_ZERO_MEMORY(filename); - WABT_ZERO_MEMORY(text); EXPECT(","); - CHECK_RESULT(parse_line(ctx)); + CHECK_RESULT(ParseLine()); EXPECT(","); PARSE_KEY_STRING_VALUE("filename", &filename); EXPECT(","); PARSE_KEY_STRING_VALUE("text", &text); EXPECT(","); - CHECK_RESULT(parse_module_type(ctx, &module_type)); - on_assert_malformed_command(ctx, filename, text, module_type); - } else if (match(ctx, "\"assert_invalid\"")) { - StringSlice filename; - StringSlice text; + CHECK_RESULT(ParseModuleType(&module_type)); + OnAssertMalformedCommand(filename, text, module_type); + } else if (Match("\"assert_invalid\"")) { + std::string filename; + std::string text; ModuleType module_type; - WABT_ZERO_MEMORY(filename); - WABT_ZERO_MEMORY(text); EXPECT(","); - CHECK_RESULT(parse_line(ctx)); + CHECK_RESULT(ParseLine()); EXPECT(","); PARSE_KEY_STRING_VALUE("filename", &filename); EXPECT(","); PARSE_KEY_STRING_VALUE("text", &text); EXPECT(","); - CHECK_RESULT(parse_module_type(ctx, &module_type)); - on_assert_invalid_command(ctx, filename, text, module_type); - } else if (match(ctx, "\"assert_unlinkable\"")) { - StringSlice filename; - StringSlice text; + CHECK_RESULT(ParseModuleType(&module_type)); + OnAssertInvalidCommand(filename, text, module_type); + } else if (Match("\"assert_unlinkable\"")) { + std::string filename; + std::string text; ModuleType module_type; - WABT_ZERO_MEMORY(filename); - WABT_ZERO_MEMORY(text); EXPECT(","); - CHECK_RESULT(parse_line(ctx)); + CHECK_RESULT(ParseLine()); EXPECT(","); PARSE_KEY_STRING_VALUE("filename", &filename); EXPECT(","); PARSE_KEY_STRING_VALUE("text", &text); EXPECT(","); - CHECK_RESULT(parse_module_type(ctx, &module_type)); - on_assert_unlinkable_command(ctx, filename, text, module_type); - } else if (match(ctx, "\"assert_uninstantiable\"")) { - StringSlice filename; - StringSlice text; + CHECK_RESULT(ParseModuleType(&module_type)); + OnAssertUnlinkableCommand(filename, text, module_type); + } else if (Match("\"assert_uninstantiable\"")) { + std::string filename; + std::string text; ModuleType module_type; - WABT_ZERO_MEMORY(filename); - WABT_ZERO_MEMORY(text); EXPECT(","); - CHECK_RESULT(parse_line(ctx)); + CHECK_RESULT(ParseLine()); EXPECT(","); PARSE_KEY_STRING_VALUE("filename", &filename); EXPECT(","); PARSE_KEY_STRING_VALUE("text", &text); EXPECT(","); - CHECK_RESULT(parse_module_type(ctx, &module_type)); - on_assert_uninstantiable_command(ctx, filename, text, module_type); - } else if (match(ctx, "\"assert_return\"")) { - Action action; + CHECK_RESULT(ParseModuleType(&module_type)); + OnAssertUninstantiableCommand(filename, text, module_type); + } else if (Match("\"assert_return\"")) { + ::Action action; std::vector expected; EXPECT(","); - CHECK_RESULT(parse_line(ctx)); + CHECK_RESULT(ParseLine()); EXPECT(","); - CHECK_RESULT(parse_action(ctx, &action)); + CHECK_RESULT(ParseAction(&action)); EXPECT(","); EXPECT_KEY("expected"); - CHECK_RESULT(parse_const_vector(ctx, &expected)); - on_assert_return_command(ctx, &action, expected); - } else if (match(ctx, "\"assert_return_canonical_nan\"")) { - Action action; + CHECK_RESULT(ParseConstVector(&expected)); + OnAssertReturnCommand(&action, expected); + } else if (Match("\"assert_return_canonical_nan\"")) { + ::Action action; TypeVector expected; EXPECT(","); - CHECK_RESULT(parse_line(ctx)); + CHECK_RESULT(ParseLine()); EXPECT(","); - CHECK_RESULT(parse_action(ctx, &action)); + CHECK_RESULT(ParseAction(&action)); EXPECT(","); /* Not needed for wabt-interp, but useful for other parsers. */ EXPECT_KEY("expected"); - CHECK_RESULT(parse_type_vector(ctx, &expected)); - on_assert_return_nan_command(ctx, &action, true); - } else if (match(ctx, "\"assert_return_arithmetic_nan\"")) { - Action action; + CHECK_RESULT(ParseTypeVector(&expected)); + OnAssertReturnNanCommand(&action, true); + } else if (Match("\"assert_return_arithmetic_nan\"")) { + ::Action action; TypeVector expected; EXPECT(","); - CHECK_RESULT(parse_line(ctx)); + CHECK_RESULT(ParseLine()); EXPECT(","); - CHECK_RESULT(parse_action(ctx, &action)); + CHECK_RESULT(ParseAction(&action)); EXPECT(","); /* Not needed for wabt-interp, but useful for other parsers. */ EXPECT_KEY("expected"); - CHECK_RESULT(parse_type_vector(ctx, &expected)); - on_assert_return_nan_command(ctx, &action, false); - } else if (match(ctx, "\"assert_trap\"")) { - Action action; - StringSlice text; - WABT_ZERO_MEMORY(text); + CHECK_RESULT(ParseTypeVector(&expected)); + OnAssertReturnNanCommand(&action, false); + } else if (Match("\"assert_trap\"")) { + ::Action action; + std::string text; EXPECT(","); - CHECK_RESULT(parse_line(ctx)); + CHECK_RESULT(ParseLine()); EXPECT(","); - CHECK_RESULT(parse_action(ctx, &action)); + CHECK_RESULT(ParseAction(&action)); EXPECT(","); PARSE_KEY_STRING_VALUE("text", &text); - on_assert_trap_command(ctx, &action, text); - } else if (match(ctx, "\"assert_exhaustion\"")) { - Action action; - StringSlice text; - WABT_ZERO_MEMORY(text); + OnAssertTrapCommand(&action, text); + } else if (Match("\"assert_exhaustion\"")) { + ::Action action; + std::string text; EXPECT(","); - CHECK_RESULT(parse_line(ctx)); + CHECK_RESULT(ParseLine()); EXPECT(","); - CHECK_RESULT(parse_action(ctx, &action)); - on_assert_exhaustion_command(ctx, &action); + CHECK_RESULT(ParseAction(&action)); + OnAssertExhaustionCommand(&action); } else { - print_command_error(ctx, "unknown command type"); + PrintCommandError("unknown command type"); return wabt::Result::Error; } EXPECT("}"); return wabt::Result::Ok; } -static wabt::Result parse_commands(Context* ctx) { +wabt::Result SpecJSONParser::ParseCommands() { EXPECT("{"); - PARSE_KEY_STRING_VALUE("source_filename", &ctx->source_filename); + PARSE_KEY_STRING_VALUE("source_filename", &source_filename_); EXPECT(","); EXPECT_KEY("commands"); EXPECT("["); bool first = true; - while (!match(ctx, "]")) { + while (!Match("]")) { if (!first) EXPECT(","); - CHECK_RESULT(parse_command(ctx)); + CHECK_RESULT(ParseCommand()); first = false; } EXPECT("}"); return wabt::Result::Ok; } -static void destroy_context(Context* ctx) { - delete[] ctx->json_data; -} - -static wabt::Result read_and_run_spec_json(const char* spec_json_filename) { - Context ctx; - ctx.loc.filename = spec_json_filename; - ctx.loc.line = 1; - ctx.loc.first_column = 1; - init_environment(&ctx.env); - - char* data; - size_t size; - wabt::Result result = read_file(spec_json_filename, &data, &size); - if (WABT_FAILED(result)) - return wabt::Result::Error; - - ctx.json_data = data; - ctx.json_data_size = size; - - result = parse_commands(&ctx); - printf("%d/%d tests passed.\n", ctx.passed, ctx.total); - destroy_context(&ctx); +static wabt::Result ReadAndRunSpecJSON(const char* spec_json_filename) { + SpecJSONParser parser; + CHECK_RESULT(parser.ReadFile(spec_json_filename)); + wabt::Result result = parser.ParseCommands(); + printf("%d/%d tests passed.\n", parser.passed(), parser.total()); return result; } int ProgramMain(int argc, char** argv) { - init_stdio(); - parse_options(argc, argv); + InitStdio(); + ParseOptions(argc, argv); s_stdout_stream = FileStream::CreateStdout(); wabt::Result result; if (s_spec) { - result = read_and_run_spec_json(s_infile); + result = ReadAndRunSpecJSON(s_infile); } else { - result = read_and_run_module(s_infile); + result = ReadAndRunModule(s_infile); } return result != wabt::Result::Ok; } diff --git a/lib/wabt/src/tools/wasm-link.cc b/lib/wabt/src/tools/wasm-link.cc index 522982c96bc..870507543b3 100644 --- a/lib/wabt/src/tools/wasm-link.cc +++ b/lib/wabt/src/tools/wasm-link.cc @@ -44,16 +44,7 @@ static const char* s_outfile = "a.wasm"; static std::vector s_infiles; static std::unique_ptr s_log_stream; -struct Context { - WABT_DISALLOW_COPY_AND_ASSIGN(Context); - Context() {} - - MemoryStream stream; - std::vector> inputs; - ssize_t current_section_payload_offset = 0; -}; - -static void parse_options(int argc, char** argv) { +static void ParseOptions(int argc, char** argv) { OptionParser parser("wasm-link", s_description); parser.AddOption("debug", @@ -84,7 +75,7 @@ Section::Section() payload_offset(0), count(0), output_payload_offset(0) { - WABT_ZERO_MEMORY(data); + ZeroMemory(data); } Section::~Section() { @@ -94,11 +85,9 @@ Section::~Section() { } LinkerInputBinary::LinkerInputBinary(const char* filename, - uint8_t* data, - size_t size) + const std::vector& data) : filename(filename), data(data), - size(size), active_function_imports(0), active_global_imports(0), type_index_offset(0), @@ -109,10 +98,6 @@ LinkerInputBinary::LinkerInputBinary(const char* filename, memory_page_offset(0), table_elem_count(0) {} -LinkerInputBinary::~LinkerInputBinary() { - delete[] data; -} - bool LinkerInputBinary::IsFunctionImport(Index index) { assert(IsValidFunctionIndex(index)); return index < function_imports.size(); @@ -129,11 +114,11 @@ bool LinkerInputBinary::IsValidFunctionIndex(Index index) { Index LinkerInputBinary::RelocateFuncIndex(Index function_index) { Index offset; if (!IsFunctionImport(function_index)) { - /* locally declared function call */ + // locally declared function call. offset = function_index_offset; LOG_DEBUG("func reloc %d + %d\n", function_index, offset); } else { - /* imported function call */ + // imported function call. FunctionImport* import = &function_imports[function_index]; if (!import->active) { function_index = import->foreign_index; @@ -164,14 +149,14 @@ Index LinkerInputBinary::RelocateGlobalIndex(Index global_index) { return global_index + offset; } -static void apply_relocation(Section* section, Reloc* r) { +static void ApplyRelocation(const Section* section, const Reloc* r) { LinkerInputBinary* binary = section->binary; uint8_t* section_data = &binary->data[section->offset]; size_t section_size = section->size; Index cur_value = 0, new_value = 0; - read_u32_leb128(section_data + r->offset, section_data + section_size, - &cur_value); + ReadU32Leb128(section_data + r->offset, section_data + section_size, + &cur_value); switch (r->type) { case RelocType::FuncIndexLEB: @@ -187,67 +172,91 @@ static void apply_relocation(Section* section, Reloc* r) { new_value = binary->RelocateGlobalIndex(cur_value); break; default: - WABT_FATAL("unhandled relocation type: %s\n", - get_reloc_type_name(r->type)); + WABT_FATAL("unhandled relocation type: %s\n", GetRelocTypeName(r->type)); break; } - write_fixed_u32_leb128_raw(section_data + r->offset, - section_data + section_size, new_value); + WriteFixedU32Leb128Raw(section_data + r->offset, section_data + section_size, + new_value); } -static void apply_relocations(Section* section) { +static void ApplyRelocations(const Section* section) { if (!section->relocations.size()) return; - LOG_DEBUG("apply_relocations: %s\n", get_section_name(section->section_code)); - - /* Perform relocations in-place */ - for (Reloc& reloc: section->relocations) { - apply_relocation(section, &reloc); - } -} + LOG_DEBUG("ApplyRelocations: %s\n", GetSectionName(section->section_code)); + + // Perform relocations in-place. + for (const auto& reloc: section->relocations) { + ApplyRelocation(section, &reloc); + } +} + +class Linker { + public: + WABT_DISALLOW_COPY_AND_ASSIGN(Linker); + Linker() = default; + + void AppendBinary(LinkerInputBinary* binary) { inputs_.emplace_back(binary); } + Result PerformLink(); + + private: + typedef std::pair Fixup; + Fixup WriteUnknownSize(); + void FixupSize(Fixup); + + void WriteSectionPayload(Section* sec); + void WriteTableSection(const SectionPtrVector& sections); + void WriteExportSection(); + void WriteElemSection(const SectionPtrVector& sections); + void WriteMemorySection(const SectionPtrVector& sections); + void WriteFunctionImport(const FunctionImport& import, Index offset); + void WriteGlobalImport(const GlobalImport& import); + void WriteImportSection(); + void WriteFunctionSection(const SectionPtrVector& sections, + Index total_count); + void WriteDataSegment(const DataSegment& segment, Address offset); + void WriteDataSection(const SectionPtrVector& sections, Index total_count); + void WriteNamesSection(); + void WriteRelocSection(BinarySection section_code, + const SectionPtrVector& sections); + bool WriteCombinedSection(BinarySection section_code, + const SectionPtrVector& sections); + void ResolveSymbols(); + void CalculateRelocOffsets(); + void WriteBinary(); + void DumpRelocOffsets(); + + MemoryStream stream_; + std::vector> inputs_; + ssize_t current_section_payload_offset_ = 0; +}; -static void write_section_payload(Context* ctx, Section* sec) { - assert(ctx->current_section_payload_offset != -1); +void Linker::WriteSectionPayload(Section* sec) { + assert(current_section_payload_offset_ != -1); sec->output_payload_offset = - ctx->stream.offset() - ctx->current_section_payload_offset; + stream_.offset() - current_section_payload_offset_; uint8_t* payload = &sec->binary->data[sec->payload_offset]; - ctx->stream.WriteData(payload, sec->payload_size, "section content"); + stream_.WriteData(payload, sec->payload_size, "section content"); } -static void write_c_str(Stream* stream, const char* str, const char* desc) { - write_str(stream, str, strlen(str), desc, PrintChars::Yes); +Linker::Fixup Linker::WriteUnknownSize() { + Offset fixup_offset = stream_.offset(); + WriteFixedU32Leb128(&stream_, 0, "unknown size"); + current_section_payload_offset_ = stream_.offset(); + return std::make_pair(fixup_offset, current_section_payload_offset_); } -static void write_slice(Stream* stream, StringSlice str, const char* desc) { - write_str(stream, str.start, str.length, desc, PrintChars::Yes); +void Linker::FixupSize(Fixup fixup) { + WriteFixedU32Leb128At(&stream_, fixup.first, stream_.offset() - fixup.second, + "fixup size"); } -static void write_string(Stream* stream, - const std::string& str, - const char* desc) { - write_str(stream, str.data(), str.length(), desc, PrintChars::Yes); -} - -#define WRITE_UNKNOWN_SIZE(STREAM) \ - { \ - Offset fixup_offset = (STREAM)->offset(); \ - write_fixed_u32_leb128(STREAM, 0, "unknown size"); \ - ctx->current_section_payload_offset = (STREAM)->offset(); \ - Offset start = (STREAM)->offset(); - -#define FIXUP_SIZE(STREAM) \ - write_fixed_u32_leb128_at(STREAM, fixup_offset, (STREAM)->offset() - start, \ - "fixup size"); \ - } - -static void write_table_section(Context* ctx, - const SectionPtrVector& sections) { - /* Total section size includes the element count leb128 which is - * always 1 in the current spec */ +void Linker::WriteTableSection(const SectionPtrVector& sections) { + // Total section size includes the element count leb128 which is always 1 in + // the current spec. Index table_count = 1; uint32_t flags = WABT_BINARY_LIMITS_HAS_MAX_FLAG; Index elem_count = 0; @@ -256,30 +265,28 @@ static void write_table_section(Context* ctx, elem_count += section->binary->table_elem_count; } - Stream* stream = &ctx->stream; - WRITE_UNKNOWN_SIZE(stream); - write_u32_leb128(stream, table_count, "table count"); - write_type(stream, Type::Anyfunc); - write_u32_leb128(stream, flags, "table elem flags"); - write_u32_leb128(stream, elem_count, "table initial length"); - write_u32_leb128(stream, elem_count, "table max length"); - FIXUP_SIZE(stream); + auto fixup = WriteUnknownSize(); + WriteU32Leb128(&stream_, table_count, "table count"); + WriteType(&stream_, Type::Anyfunc); + WriteU32Leb128(&stream_, flags, "table elem flags"); + WriteU32Leb128(&stream_, elem_count, "table initial length"); + WriteU32Leb128(&stream_, elem_count, "table max length"); + FixupSize(fixup); } -static void write_export_section(Context* ctx) { +void Linker::WriteExportSection() { Index total_exports = 0; - for (const std::unique_ptr& binary: ctx->inputs) { + for (const std::unique_ptr& binary : inputs_) { total_exports += binary->exports.size(); } - Stream* stream = &ctx->stream; - WRITE_UNKNOWN_SIZE(stream); - write_u32_leb128(stream, total_exports, "export count"); + auto fixup = WriteUnknownSize(); + WriteU32Leb128(&stream_, total_exports, "export count"); - for (const std::unique_ptr& binary : ctx->inputs) { + for (const std::unique_ptr& binary : inputs_) { for (const Export& export_ : binary->exports) { - write_slice(stream, export_.name, "export name"); - stream->WriteU8Enum(export_.kind, "export kind"); + WriteStr(&stream_, export_.name, "export name"); + stream_.WriteU8Enum(export_.kind, "export kind"); Index index = export_.index; switch (export_.kind) { case ExternalKind::Func: @@ -290,121 +297,104 @@ static void write_export_section(Context* ctx) { static_cast(export_.kind)); break; } - write_u32_leb128(stream, index, "export index"); + WriteU32Leb128(&stream_, index, "export index"); } } - FIXUP_SIZE(stream); + + FixupSize(fixup); } -static void write_elem_section(Context* ctx, - const SectionPtrVector& sections) { - Stream* stream = &ctx->stream; - WRITE_UNKNOWN_SIZE(stream); +void Linker::WriteElemSection(const SectionPtrVector& sections) { + auto fixup = WriteUnknownSize(); Index total_elem_count = 0; for (Section* section : sections) { total_elem_count += section->binary->table_elem_count; } - write_u32_leb128(stream, 1, "segment count"); - write_u32_leb128(stream, 0, "table index"); - write_opcode(&ctx->stream, Opcode::I32Const); - write_i32_leb128(&ctx->stream, 0, "elem init literal"); - write_opcode(&ctx->stream, Opcode::End); - write_u32_leb128(stream, total_elem_count, "num elements"); + WriteU32Leb128(&stream_, 1, "segment count"); + WriteU32Leb128(&stream_, 0, "table index"); + WriteOpcode(&stream_, Opcode::I32Const); + WriteI32Leb128(&stream_, 0, "elem init literal"); + WriteOpcode(&stream_, Opcode::End); + WriteU32Leb128(&stream_, total_elem_count, "num elements"); - ctx->current_section_payload_offset = stream->offset(); + current_section_payload_offset_ = stream_.offset(); for (Section* section : sections) { - apply_relocations(section); - write_section_payload(ctx, section); + ApplyRelocations(section); + WriteSectionPayload(section); } - FIXUP_SIZE(stream); + FixupSize(fixup); } -static void write_memory_section(Context* ctx, - const SectionPtrVector& sections) { - Stream* stream = &ctx->stream; - WRITE_UNKNOWN_SIZE(stream); +void Linker::WriteMemorySection(const SectionPtrVector& sections) { + auto fixup = WriteUnknownSize(); - write_u32_leb128(stream, 1, "memory count"); + WriteU32Leb128(&stream_, 1, "memory count"); Limits limits; - WABT_ZERO_MEMORY(limits); + ZeroMemory(limits); limits.has_max = true; - for (size_t i = 0; i < sections.size(); i++) { - Section* sec = sections[i]; - limits.initial += sec->data.memory_limits.initial; + for (Section* section: sections) { + limits.initial += section->data.memory_limits.initial; } limits.max = limits.initial; - write_limits(stream, &limits); + WriteLimits(&stream_, &limits); - FIXUP_SIZE(stream); + FixupSize(fixup); } -static void write_function_import(Context* ctx, - FunctionImport* import, - Index offset) { - write_slice(&ctx->stream, import->module_name, "import module name"); - write_slice(&ctx->stream, import->name, "import field name"); - ctx->stream.WriteU8Enum(ExternalKind::Func, "import kind"); - write_u32_leb128(&ctx->stream, import->sig_index + offset, - "import signature index"); +void Linker::WriteFunctionImport(const FunctionImport& import, Index offset) { + WriteStr(&stream_, import.module_name, "import module name"); + WriteStr(&stream_, import.name, "import field name"); + stream_.WriteU8Enum(ExternalKind::Func, "import kind"); + WriteU32Leb128(&stream_, import.sig_index + offset, "import signature index"); } -static void write_global_import(Context* ctx, GlobalImport* import) { - write_slice(&ctx->stream, import->module_name, "import module name"); - write_slice(&ctx->stream, import->name, "import field name"); - ctx->stream.WriteU8Enum(ExternalKind::Global, "import kind"); - write_type(&ctx->stream, import->type); - ctx->stream.WriteU8(import->mutable_, "global mutability"); +void Linker::WriteGlobalImport(const GlobalImport& import) { + WriteStr(&stream_, import.module_name, "import module name"); + WriteStr(&stream_, import.name, "import field name"); + stream_.WriteU8Enum(ExternalKind::Global, "import kind"); + WriteType(&stream_, import.type); + stream_.WriteU8(import.mutable_, "global mutability"); } -static void write_import_section(Context* ctx) { +void Linker::WriteImportSection() { Index num_imports = 0; - for (size_t i = 0; i < ctx->inputs.size(); i++) { - LinkerInputBinary* binary = ctx->inputs[i].get(); - std::vector& imports = binary->function_imports; - for (size_t j = 0; j < imports.size(); j++) { - FunctionImport* import = &imports[j]; - if (import->active) + for (const auto& binary: inputs_) { + for (const auto& import : binary->function_imports) { + if (import.active) num_imports++; } num_imports += binary->global_imports.size(); } - WRITE_UNKNOWN_SIZE(&ctx->stream); - write_u32_leb128(&ctx->stream, num_imports, "num imports"); + auto fixup = WriteUnknownSize(); + WriteU32Leb128(&stream_, num_imports, "num imports"); - for (size_t i = 0; i < ctx->inputs.size(); i++) { - LinkerInputBinary* binary = ctx->inputs[i].get(); - std::vector& imports = binary->function_imports; - for (size_t j = 0; j < imports.size(); j++) { - FunctionImport* import = &imports[j]; - if (import->active) - write_function_import(ctx, import, binary->type_index_offset); + for (const auto& binary: inputs_) { + for (const auto& function_import : binary->function_imports) { + if (function_import.active) + WriteFunctionImport(function_import, binary->type_index_offset); } - std::vector& globals = binary->global_imports; - for (size_t j = 0; j < globals.size(); j++) { - write_global_import(ctx, &globals[j]); + for (const auto& global_import : binary->global_imports) { + WriteGlobalImport(global_import); } } - FIXUP_SIZE(&ctx->stream); + FixupSize(fixup); } -static void write_function_section(Context* ctx, - const SectionPtrVector& sections, - Index total_count) { - Stream* stream = &ctx->stream; - WRITE_UNKNOWN_SIZE(stream); +void Linker::WriteFunctionSection(const SectionPtrVector& sections, + Index total_count) { + auto fixup = WriteUnknownSize(); - write_u32_leb128(stream, total_count, "function count"); + WriteU32Leb128(&stream_, total_count, "function count"); - for (size_t i = 0; i < sections.size(); i++) { - Section* sec = sections[i]; + for (Section* sec: sections) { Index count = sec->count; Offset input_offset = 0; Index sig_index = 0; @@ -412,49 +402,43 @@ static void write_function_section(Context* ctx, const uint8_t* end = &sec->binary->data[sec->payload_offset + sec->payload_size]; while (count--) { - input_offset += read_u32_leb128(start + input_offset, end, &sig_index); - write_u32_leb128(stream, sec->binary->RelocateTypeIndex(sig_index), - "sig"); + input_offset += ReadU32Leb128(start + input_offset, end, &sig_index); + WriteU32Leb128(&stream_, sec->binary->RelocateTypeIndex(sig_index), + "sig"); } } - FIXUP_SIZE(stream); + FixupSize(fixup); } -static void write_data_segment(Stream* stream, - const DataSegment& segment, - Address offset) { +void Linker::WriteDataSegment(const DataSegment& segment, Address offset) { assert(segment.memory_index == 0); - write_u32_leb128(stream, segment.memory_index, "memory index"); - write_opcode(stream, Opcode::I32Const); - write_u32_leb128(stream, segment.offset + offset, "offset"); - write_opcode(stream, Opcode::End); - write_u32_leb128(stream, segment.size, "segment size"); - stream->WriteData(segment.data, segment.size, "segment data"); -} - -static void write_data_section(Context* ctx, - const SectionPtrVector& sections, - Index total_count) { - Stream* stream = &ctx->stream; - WRITE_UNKNOWN_SIZE(stream); - - write_u32_leb128(stream, total_count, "data segment count"); - for (size_t i = 0; i < sections.size(); i++) { - Section* sec = sections[i]; - for (size_t j = 0; j < sec->data.data_segments->size(); j++) { - const DataSegment& segment = (*sec->data.data_segments)[j]; - write_data_segment(stream, segment, - sec->binary->memory_page_offset * WABT_PAGE_SIZE); + WriteU32Leb128(&stream_, segment.memory_index, "memory index"); + WriteOpcode(&stream_, Opcode::I32Const); + WriteU32Leb128(&stream_, segment.offset + offset, "offset"); + WriteOpcode(&stream_, Opcode::End); + WriteU32Leb128(&stream_, segment.size, "segment size"); + stream_.WriteData(segment.data, segment.size, "segment data"); +} + +void Linker::WriteDataSection(const SectionPtrVector& sections, + Index total_count) { + auto fixup = WriteUnknownSize(); + + WriteU32Leb128(&stream_, total_count, "data segment count"); + for (const Section* sec: sections) { + for (const auto& segment: *sec->data.data_segments) { + WriteDataSegment(segment, + sec->binary->memory_page_offset * WABT_PAGE_SIZE); } } - FIXUP_SIZE(stream); + FixupSize(fixup); } -static void write_names_section(Context* ctx) { +void Linker::WriteNamesSection() { Index total_count = 0; - for (const std::unique_ptr& binary: ctx->inputs) { + for (const auto& binary : inputs_) { for (size_t i = 0; i < binary->debug_names.size(); i++) { if (binary->debug_names[i].empty()) continue; @@ -467,70 +451,65 @@ static void write_names_section(Context* ctx) { if (!total_count) return; - Stream* stream = &ctx->stream; - stream->WriteU8Enum(BinarySection::Custom, "section code"); - WRITE_UNKNOWN_SIZE(stream); - write_c_str(stream, "name", "custom section name"); + stream_.WriteU8Enum(BinarySection::Custom, "section code"); + auto fixup_section = WriteUnknownSize(); + WriteStr(&stream_, "name", "custom section name"); - stream->WriteU8Enum(NameSectionSubsection::Function, "subsection code"); - WRITE_UNKNOWN_SIZE(stream); - write_u32_leb128(stream, total_count, "element count"); + stream_.WriteU8Enum(NameSectionSubsection::Function, "subsection code"); + auto fixup_subsection = WriteUnknownSize(); + WriteU32Leb128(&stream_, total_count, "element count"); - // Write import names - for (const std::unique_ptr& binary: ctx->inputs) { + // Write import names. + for (const auto& binary : inputs_) { for (size_t i = 0; i < binary->debug_names.size(); i++) { if (binary->debug_names[i].empty() || !binary->IsFunctionImport(i)) continue; if (binary->IsInactiveFunctionImport(i)) continue; - write_u32_leb128(stream, binary->RelocateFuncIndex(i), "function index"); - write_string(stream, binary->debug_names[i], "function name"); + WriteU32Leb128(&stream_, binary->RelocateFuncIndex(i), "function index"); + WriteStr(&stream_, binary->debug_names[i], "function name"); } } - // Write non-import names - for (const std::unique_ptr& binary: ctx->inputs) { + // Write non-import names. + for (const auto& binary : inputs_) { for (size_t i = 0; i < binary->debug_names.size(); i++) { if (binary->debug_names[i].empty() || binary->IsFunctionImport(i)) continue; - write_u32_leb128(stream, binary->RelocateFuncIndex(i), "function index"); - write_string(stream, binary->debug_names[i], "function name"); + WriteU32Leb128(&stream_, binary->RelocateFuncIndex(i), "function index"); + WriteStr(&stream_, binary->debug_names[i], "function name"); } } - FIXUP_SIZE(stream); - - FIXUP_SIZE(stream); + FixupSize(fixup_subsection); + FixupSize(fixup_section); } -static void write_reloc_section(Context* ctx, - BinarySection section_code, - const SectionPtrVector& sections) { +void Linker::WriteRelocSection(BinarySection section_code, + const SectionPtrVector& sections) { Index total_relocs = 0; - /* First pass to know total reloc count */ + // First pass to know total reloc count. for (Section* sec: sections) total_relocs += sec->relocations.size(); if (!total_relocs) return; - char section_name[128]; - snprintf(section_name, sizeof(section_name), "%s.%s", - WABT_BINARY_SECTION_RELOC, get_section_name(section_code)); + std::string section_name = StringPrintf("%s.%s", WABT_BINARY_SECTION_RELOC, + GetSectionName(section_code)); - Stream* stream = &ctx->stream; - stream->WriteU8Enum(BinarySection::Custom, "section code"); - WRITE_UNKNOWN_SIZE(stream); - write_c_str(stream, section_name, "reloc section name"); - write_u32_leb128_enum(&ctx->stream, section_code, "reloc section"); - write_u32_leb128(&ctx->stream, total_relocs, "num relocs"); + stream_.WriteU8Enum(BinarySection::Custom, "section code"); + auto fixup = WriteUnknownSize(); + WriteStr(&stream_, section_name, "reloc section name"); + WriteU32Leb128Enum(&stream_, section_code, "reloc section"); + WriteU32Leb128(&stream_, total_relocs, "num relocs"); for (Section* sec: sections) { for (const Reloc& reloc: sec->relocations) { - write_u32_leb128_enum(&ctx->stream, reloc.type, "reloc type"); + WriteU32Leb128Enum(&stream_, reloc.type, "reloc type"); Offset new_offset = reloc.offset + sec->output_payload_offset; - write_u32_leb128(&ctx->stream, new_offset, "reloc offset"); + WriteU32Leb128(&stream_, new_offset, "reloc offset"); Index relocated_index; switch (reloc.type) { case RelocType::FuncIndexLEB: @@ -544,73 +523,72 @@ static void write_reloc_section(Context* ctx, break; // TODO(sbc): Handle other relocation types. default: - WABT_FATAL("Unhandled reloc type: %s\n", get_reloc_type_name(reloc.type)); + WABT_FATAL("Unhandled reloc type: %s\n", + GetRelocTypeName(reloc.type)); break; } - write_u32_leb128(&ctx->stream, relocated_index, "reloc index"); + WriteU32Leb128(&stream_, relocated_index, "reloc index"); } } - FIXUP_SIZE(stream); + FixupSize(fixup); } -static bool write_combined_section(Context* ctx, - BinarySection section_code, - const SectionPtrVector& sections) { +bool Linker::WriteCombinedSection(BinarySection section_code, + const SectionPtrVector& sections) { if (!sections.size()) return false; if (section_code == BinarySection::Start && sections.size() > 1) { WABT_FATAL("Don't know how to combine sections of type: %s\n", - get_section_name(section_code)); + GetSectionName(section_code)); } Index total_count = 0; Index total_size = 0; - /* Sum section size and element count */ - for (Section* sec: sections) { + // Sum section size and element count. + for (Section* sec : sections) { total_size += sec->payload_size; total_count += sec->count; } - ctx->stream.WriteU8Enum(section_code, "section code"); - ctx->current_section_payload_offset = -1; + stream_.WriteU8Enum(section_code, "section code"); + current_section_payload_offset_ = -1; switch (section_code) { case BinarySection::Import: - write_import_section(ctx); + WriteImportSection(); break; case BinarySection::Function: - write_function_section(ctx, sections, total_count); + WriteFunctionSection(sections, total_count); break; case BinarySection::Table: - write_table_section(ctx, sections); + WriteTableSection(sections); break; case BinarySection::Export: - write_export_section(ctx); + WriteExportSection(); break; case BinarySection::Elem: - write_elem_section(ctx, sections); + WriteElemSection(sections); break; case BinarySection::Memory: - write_memory_section(ctx, sections); + WriteMemorySection(sections); break; case BinarySection::Data: - write_data_section(ctx, sections, total_count); + WriteDataSection(sections, total_count); break; default: { - /* Total section size includes the element count leb128. */ - total_size += u32_leb128_length(total_count); - - /* Write section to stream */ - Stream* stream = &ctx->stream; - write_u32_leb128(stream, total_size, "section size"); - write_u32_leb128(stream, total_count, "element count"); - ctx->current_section_payload_offset = ctx->stream.offset(); - for (Section* sec: sections) { - apply_relocations(sec); - write_section_payload(ctx, sec); + // Total section size includes the element count leb128. + total_size += U32Leb128Length(total_count); + + // Write section to stream. + WriteU32Leb128(&stream_, total_size, "section size"); + WriteU32Leb128(&stream_, total_count, "element count"); + current_section_payload_offset_ = stream_.offset(); + for (Section* sec : sections) { + ApplyRelocations(sec); + WriteSectionPayload(sec); } } } @@ -626,52 +604,44 @@ struct ExportInfo { LinkerInputBinary* binary; }; -static void resolve_symbols(Context* ctx) { - /* Create hashmap of all exported symbols from all inputs */ +void Linker::ResolveSymbols() { + // Create hashmap of all exported symbols from all inputs. BindingHash export_map; std::vector export_list; - for (size_t i = 0; i < ctx->inputs.size(); i++) { - LinkerInputBinary* binary = ctx->inputs[i].get(); - for (size_t j = 0; j < binary->exports.size(); j++) { - Export* export_ = &binary->exports[j]; - export_list.emplace_back(export_, binary); + for (const auto& binary: inputs_) { + for (auto& export_ : binary->exports) { + export_list.emplace_back(&export_, binary.get()); - /* TODO(sbc): Handle duplicate names */ - export_map.emplace(string_slice_to_string(export_->name), - Binding(export_list.size() - 1)); + // TODO(sbc): Handle duplicate names. + export_map.emplace(export_.name, Binding(export_list.size() - 1)); } } - /* - * Iterate through all imported functions resolving them against exported - * ones. - */ - for (size_t i = 0; i < ctx->inputs.size(); i++) { - LinkerInputBinary* binary = ctx->inputs[i].get(); - for (size_t j = 0; j < binary->function_imports.size(); j++) { - FunctionImport* import = &binary->function_imports[j]; - int export_index = export_map.FindIndex(import->name); - if (export_index == -1) { + // Iterate through all imported functions resolving them against exported + // ones. + for (auto& binary: inputs_) { + for (auto& import: binary->function_imports) { + Index export_index = export_map.FindIndex(import.name); + if (export_index == kInvalidIndex) { if (!s_relocatable) - WABT_FATAL("undefined symbol: " PRIstringslice "\n", - WABT_PRINTF_STRING_SLICE_ARG(import->name)); + WABT_FATAL("undefined symbol: %s\n", import.name.c_str()); continue; } - /* We found the symbol exported by another module */ - ExportInfo* export_info = &export_list[export_index]; + // We found the symbol exported by another module. + const ExportInfo& export_info = export_list[export_index]; - /* TODO(sbc): verify the foriegn function has the correct signature */ - import->active = false; - import->foreign_binary = export_info->binary; - import->foreign_index = export_info->export_->index; + // TODO(sbc): verify the foriegn function has the correct signature. + import.active = false; + import.foreign_binary = export_info.binary; + import.foreign_index = export_info.export_->index; binary->active_function_imports--; } } } -static void calculate_reloc_offsets(Context* ctx) { +void Linker::CalculateRelocOffsets() { Index memory_page_offset = 0; Index type_count = 0; Index global_count = 0; @@ -679,11 +649,11 @@ static void calculate_reloc_offsets(Context* ctx) { Index table_elem_count = 0; Index total_function_imports = 0; Index total_global_imports = 0; - for (size_t i = 0; i < ctx->inputs.size(); i++) { - LinkerInputBinary* binary = ctx->inputs[i].get(); - /* The imported_function_index_offset is the sum of all the function - * imports from objects that precede this one. i.e. the current running - * total */ + + for (auto& binary : inputs_) { + // The imported_function_index_offset is the sum of all the function + // imports from objects that precede this one. i.e. the current running + // total. binary->imported_function_index_offset = total_function_imports; binary->imported_global_index_offset = total_global_imports; binary->memory_page_offset = memory_page_offset; @@ -694,7 +664,7 @@ static void calculate_reloc_offsets(Context* ctx) { delta++; } else { binary->function_imports[i].relocated_function_index = - total_function_imports + i - delta; + total_function_imports + i - delta; } } @@ -703,12 +673,10 @@ static void calculate_reloc_offsets(Context* ctx) { total_global_imports += binary->global_imports.size(); } - for (size_t i = 0; i < ctx->inputs.size(); i++) { - LinkerInputBinary* binary = ctx->inputs[i].get(); + for (auto& binary : inputs_) { binary->table_index_offset = table_elem_count; table_elem_count += binary->table_elem_count; - for (size_t j = 0; j < binary->sections.size(); j++) { - Section* sec = binary->sections[j].get(); + for (auto& sec : binary->sections) { switch (sec->section_code) { case BinarySection::Type: binary->type_index_offset = type_count; @@ -733,69 +701,66 @@ static void calculate_reloc_offsets(Context* ctx) { } } -static void write_binary(Context* ctx) { - /* Find all the sections of each type */ +void Linker::WriteBinary() { + // Find all the sections of each type. SectionPtrVector sections[kBinarySectionCount]; - for (size_t j = 0; j < ctx->inputs.size(); j++) { - LinkerInputBinary* binary = ctx->inputs[j].get(); - for (size_t i = 0; i < binary->sections.size(); i++) { - Section* s = binary->sections[i].get(); - SectionPtrVector& sec_list = sections[static_cast(s->section_code)]; - sec_list.push_back(s); + for (auto& binary : inputs_) { + for (auto& sec : binary->sections) { + SectionPtrVector& sec_list = + sections[static_cast(sec->section_code)]; + sec_list.push_back(sec.get()); } } - /* Write the final binary */ - ctx->stream.WriteU32(WABT_BINARY_MAGIC, "WABT_BINARY_MAGIC"); - ctx->stream.WriteU32(WABT_BINARY_VERSION, "WABT_BINARY_VERSION"); + // Write the final binary. + stream_.WriteU32(WABT_BINARY_MAGIC, "WABT_BINARY_MAGIC"); + stream_.WriteU32(WABT_BINARY_VERSION, "WABT_BINARY_VERSION"); - /* Write known sections first */ + // Write known sections first. for (size_t i = FIRST_KNOWN_SECTION; i < kBinarySectionCount; i++) { - write_combined_section(ctx, static_cast(i), sections[i]); + WriteCombinedSection(static_cast(i), sections[i]); } - write_names_section(ctx); + WriteNamesSection(); - /* Generate a new set of reloction sections */ + // Generate a new set of reloction sections. for (size_t i = FIRST_KNOWN_SECTION; i < kBinarySectionCount; i++) { - write_reloc_section(ctx, static_cast(i), sections[i]); + WriteRelocSection(static_cast(i), sections[i]); } } -static void dump_reloc_offsets(Context* ctx) { +void Linker::DumpRelocOffsets() { if (s_debug) { - for (size_t i = 0; i < ctx->inputs.size(); i++) { - LinkerInputBinary* binary = ctx->inputs[i].get(); + for (const auto& binary : inputs_) { LOG_DEBUG("Relocation info for: %s\n", binary->filename); - LOG_DEBUG(" - type index offset : %d\n", - binary->type_index_offset); + LOG_DEBUG(" - type index offset : %d\n", binary->type_index_offset); LOG_DEBUG(" - mem page offset : %d\n", - binary->memory_page_offset); + binary->memory_page_offset); LOG_DEBUG(" - function index offset : %d\n", - binary->function_index_offset); + binary->function_index_offset); LOG_DEBUG(" - global index offset : %d\n", - binary->global_index_offset); + binary->global_index_offset); LOG_DEBUG(" - imported function offset: %d\n", - binary->imported_function_index_offset); + binary->imported_function_index_offset); LOG_DEBUG(" - imported global offset : %d\n", - binary->imported_global_index_offset); + binary->imported_global_index_offset); } } } -static Result perform_link(Context* ctx) { +Result Linker::PerformLink() { if (s_debug) - ctx->stream.set_log_stream(s_log_stream.get()); + stream_.set_log_stream(s_log_stream.get()); LOG_DEBUG("writing file: %s\n", s_outfile); - calculate_reloc_offsets(ctx); - resolve_symbols(ctx); - calculate_reloc_offsets(ctx); - dump_reloc_offsets(ctx); - write_binary(ctx); + CalculateRelocOffsets(); + ResolveSymbols(); + CalculateRelocOffsets(); + DumpRelocOffsets(); + WriteBinary(); - if (WABT_FAILED(ctx->stream.WriteToFile(s_outfile))) { + if (Failed(stream_.WriteToFile(s_outfile))) { WABT_FATAL("error writing linked output to file\n"); } @@ -803,33 +768,32 @@ static Result perform_link(Context* ctx) { } int ProgramMain(int argc, char** argv) { - init_stdio(); + InitStdio(); - Context context; + Linker linker; - parse_options(argc, argv); + ParseOptions(argc, argv); Result result = Result::Ok; - for (size_t i = 0; i < s_infiles.size(); i++) { - const std::string& input_filename = s_infiles[i]; + for (const auto& input_filename: s_infiles) { LOG_DEBUG("reading file: %s\n", input_filename.c_str()); - char* data; - size_t size; - result = read_file(input_filename.c_str(), &data, &size); - if (WABT_FAILED(result)) + std::vector file_data; + result = ReadFile(input_filename.c_str(), &file_data); + if (Failed(result)) return result != Result::Ok; - LinkerInputBinary* b = new LinkerInputBinary( - input_filename.c_str(), reinterpret_cast(data), size); - context.inputs.emplace_back(b); + + auto binary = new LinkerInputBinary(input_filename.c_str(), file_data); + linker.AppendBinary(binary); + LinkOptions options = { NULL }; if (s_debug) options.log_stream = s_log_stream.get(); - result = read_binary_linker(b, &options); - if (WABT_FAILED(result)) + result = ReadBinaryLinker(binary, &options); + if (Failed(result)) WABT_FATAL("error parsing file: %s\n", input_filename.c_str()); } - result = perform_link(&context); + result = linker.PerformLink(); return result != Result::Ok; } diff --git a/lib/wabt/src/tools/wasm-objdump.cc b/lib/wabt/src/tools/wasm-objdump.cc index ec967c4eac4..3739da7d7e1 100644 --- a/lib/wabt/src/tools/wasm-objdump.cc +++ b/lib/wabt/src/tools/wasm-objdump.cc @@ -19,6 +19,7 @@ #include #include "common.h" +#include "feature.h" #include "option-parser.h" #include "stream.h" #include "writer.h" @@ -35,12 +36,13 @@ R"( Print information about the contents of wasm binaries. )"; static ObjdumpOptions s_objdump_options; +static Features s_features; static std::vector s_infiles; static std::unique_ptr s_log_stream; -static void parse_options(int argc, char** argv) { +static void ParseOptions(int argc, char** argv) { OptionParser parser("wasm-objdump", s_description); parser.AddOption('h', "headers", "Print headers", @@ -57,6 +59,7 @@ static void parse_options(int argc, char** argv) { s_log_stream = FileStream::CreateStdout(); s_objdump_options.log_stream = s_log_stream.get(); }); + s_features.AddOptions(&parser); parser.AddOption('x', "details", "Show section details", []() { s_objdump_options.details = true; }); parser.AddOption('r', "reloc", "Show relocations inline with disassembly", @@ -70,67 +73,66 @@ static void parse_options(int argc, char** argv) { } Result dump_file(const char* filename) { - char* char_data; - size_t size; - Result result = read_file(filename, &char_data, &size); - if (WABT_FAILED(result)) + std::vector file_data; + Result result = ReadFile(filename, &file_data); + if (Failed(result)) return result; - uint8_t* data = reinterpret_cast(char_data); + uint8_t* data = DataOrNull(file_data); + size_t size = file_data.size(); // Perform serveral passed over the binary in order to print out different // types of information. s_objdump_options.filename = filename; + s_objdump_options.features = s_features; printf("\n"); ObjdumpState state; // Pass 0: Prepass s_objdump_options.mode = ObjdumpMode::Prepass; - result = read_binary_objdump(data, size, &s_objdump_options, &state); - if (WABT_FAILED(result)) - goto done; + result = ReadBinaryObjdump(data, size, &s_objdump_options, &state); + if (Failed(result)) + return result; s_objdump_options.log_stream = nullptr; // Pass 1: Print the section headers if (s_objdump_options.headers) { s_objdump_options.mode = ObjdumpMode::Headers; - result = read_binary_objdump(data, size, &s_objdump_options, &state); - if (WABT_FAILED(result)) - goto done; + result = ReadBinaryObjdump(data, size, &s_objdump_options, &state); + if (Failed(result)) + return result; } // Pass 2: Print extra information based on section type if (s_objdump_options.details) { s_objdump_options.mode = ObjdumpMode::Details; - result = read_binary_objdump(data, size, &s_objdump_options, &state); - if (WABT_FAILED(result)) - goto done; + result = ReadBinaryObjdump(data, size, &s_objdump_options, &state); + if (Failed(result)) + return result; } // Pass 3: Disassemble code section if (s_objdump_options.disassemble) { s_objdump_options.mode = ObjdumpMode::Disassemble; - result = read_binary_objdump(data, size, &s_objdump_options, &state); - if (WABT_FAILED(result)) - goto done; + result = ReadBinaryObjdump(data, size, &s_objdump_options, &state); + if (Failed(result)) + return result; } // Pass 4: Dump to raw contents of the sections if (s_objdump_options.raw) { s_objdump_options.mode = ObjdumpMode::RawData; - result = read_binary_objdump(data, size, &s_objdump_options, &state); + result = ReadBinaryObjdump(data, size, &s_objdump_options, &state); } -done: - delete[] data; return result; } int ProgramMain(int argc, char** argv) { - init_stdio(); + InitStdio(); - parse_options(argc, argv); + ParseOptions(argc, argv); if (!s_objdump_options.headers && !s_objdump_options.details && !s_objdump_options.disassemble && !s_objdump_options.raw) { fprintf(stderr, "At least one of the following switches must be given:\n"); @@ -142,7 +144,7 @@ int ProgramMain(int argc, char** argv) { } for (const char* filename: s_infiles) { - if (WABT_FAILED(dump_file(filename))) { + if (Failed(dump_file(filename))) { return 1; } } diff --git a/lib/wabt/src/tools/wasm-opcodecnt.cc b/lib/wabt/src/tools/wasm-opcodecnt.cc index 3571871eb75..6677fb576b9 100644 --- a/lib/wabt/src/tools/wasm-opcodecnt.cc +++ b/lib/wabt/src/tools/wasm-opcodecnt.cc @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include "binary-reader.h" #include "binary-reader-opcnt.h" @@ -37,9 +39,7 @@ static const char* s_outfile; static size_t s_cutoff = 0; static const char* s_separator = ": "; -static ReadBinaryOptions s_read_binary_options = - WABT_READ_BINARY_OPTIONS_DEFAULT; - +static ReadBinaryOptions s_read_binary_options; static std::unique_ptr s_log_stream; static const char s_description[] = @@ -51,7 +51,7 @@ R"( Read a file in the wasm binary format, and count opcode usage for $ wasm-opcodecnt test.wasm -o test.dist )"; -static void parse_options(int argc, char** argv) { +static void ParseOptions(int argc, char** argv) { OptionParser parser("wasm-opcodecnt", s_description); parser.AddOption('v', "verbose", "Use multiple times for more info", []() { @@ -78,206 +78,97 @@ static void parse_options(int argc, char** argv) { parser.Parse(argc, argv); } -typedef int(int_counter_lt_fcn)(const IntCounter&, const IntCounter&); - -typedef int(int_pair_counter_lt_fcn)(const IntPairCounter&, - const IntPairCounter&); - -typedef void (*display_name_fcn)(FILE* out, intmax_t value); - -static void display_opcode_name(FILE* out, intmax_t opcode) { - if (opcode >= 0 && opcode < kOpcodeCount) - fprintf(out, "%s", get_opcode_name(static_cast(opcode))); - else - fprintf(out, "?(%" PRIdMAX ")", opcode); -} - -static void display_intmax(FILE* out, intmax_t value) { - fprintf(out, "%" PRIdMAX, value); -} - -static void display_int_counter_vector(FILE* out, - const IntCounterVector& vec, - display_name_fcn display_fcn, - const char* opcode_name) { - for (const IntCounter& counter : vec) { - if (counter.count == 0) - continue; - if (opcode_name) - fprintf(out, "(%s ", opcode_name); - display_fcn(out, counter.value); - if (opcode_name) - fprintf(out, ")"); - fprintf(out, "%s%" PRIzd "\n", s_separator, counter.count); +template +struct SortByCountDescending { + bool operator()(const T& lhs, const T& rhs) const { + return lhs.second > rhs.second; } -} +}; -static void display_int_pair_counter_vector(FILE* out, - const IntPairCounterVector& vec, - display_name_fcn display_first_fcn, - display_name_fcn display_second_fcn, - const char* opcode_name) { - for (const IntPairCounter& pair : vec) { - if (pair.count == 0) - continue; - if (opcode_name) - fprintf(out, "(%s ", opcode_name); - display_first_fcn(out, pair.first); - fputc(' ', out); - display_second_fcn(out, pair.second); - if (opcode_name) - fprintf(out, ")"); - fprintf(out, "%s%" PRIzd "\n", s_separator, pair.count); +template +struct WithinCutoff { + bool operator()(const T& pair) const { + return pair.second >= s_cutoff; } -} +}; -static int opcode_counter_gt(const IntCounter& counter_1, - const IntCounter& counter_2) { - if (counter_1.count > counter_2.count) - return 1; - if (counter_1.count < counter_2.count) - return 0; - const char* name_1 = "?1"; - const char* name_2 = "?2"; - if (counter_1.value < kOpcodeCount) { - const char* opcode_name = - get_opcode_name(static_cast(counter_1.value)); - if (opcode_name) - name_1 = opcode_name; - } - if (counter_2.value < kOpcodeCount) { - const char* opcode_name = - get_opcode_name(static_cast(counter_2.value)); - if (opcode_name) - name_2 = opcode_name; - } - int diff = strcmp(name_1, name_2); - if (diff > 0) - return 1; - return 0; -} +void WriteCounts(Stream& stream, const OpcodeInfoCounts& info_counts) { + typedef std::pair OpcodeCountPair; -static int int_counter_gt(const IntCounter& counter_1, - const IntCounter& counter_2) { - if (counter_1.count < counter_2.count) - return 0; - if (counter_1.count > counter_2.count) - return 1; - if (counter_1.value < counter_2.value) - return 0; - if (counter_1.value > counter_2.value) - return 1; - return 0; -} + std::map counts; + for (auto& info_count_pair: info_counts) { + Opcode opcode = info_count_pair.first.opcode(); + size_t count = info_count_pair.second; + counts[opcode] += count; + } -static int int_pair_counter_gt(const IntPairCounter& counter_1, - const IntPairCounter& counter_2) { - if (counter_1.count < counter_2.count) - return 0; - if (counter_1.count > counter_2.count) - return 1; - if (counter_1.first < counter_2.first) - return 0; - if (counter_1.first > counter_2.first) - return 1; - if (counter_1.second < counter_2.second) - return 0; - if (counter_1.second > counter_2.second) - return 1; - return 0; -} + std::vector sorted; + std::copy_if(counts.begin(), counts.end(), std::back_inserter(sorted), + WithinCutoff()); -static void display_sorted_int_counter_vector(FILE* out, - const char* title, - const IntCounterVector& vec, - int_counter_lt_fcn lt_fcn, - display_name_fcn display_fcn, - const char* opcode_name) { - if (vec.size() == 0) - return; + // Use a stable sort to keep the elements with the same count in opcode + // order (since the Opcode map is sorted). + std::stable_sort(sorted.begin(), sorted.end(), + SortByCountDescending()); - /* First filter out values less than cutoff. This speeds up sorting. */ - IntCounterVector filtered_vec; - for (const IntCounter& counter: vec) { - if (counter.count < s_cutoff) - continue; - filtered_vec.push_back(counter); + for (auto& pair : sorted) { + Opcode opcode = pair.first; + size_t count = pair.second; + stream.Writef("%s%s%" PRIzd "\n", opcode.GetName(), s_separator, count); } - std::sort(filtered_vec.begin(), filtered_vec.end(), lt_fcn); - fprintf(out, "%s\n", title); - display_int_counter_vector(out, filtered_vec, display_fcn, opcode_name); } -static void display_sorted_int_pair_counter_vector( - FILE* out, - const char* title, - const IntPairCounterVector& vec, - int_pair_counter_lt_fcn lt_fcn, - display_name_fcn display_first_fcn, - display_name_fcn display_second_fcn, - const char* opcode_name) { - if (vec.size() == 0) - return; - - IntPairCounterVector filtered_vec; - for (const IntPairCounter& pair : vec) { - if (pair.count < s_cutoff) - continue; - filtered_vec.push_back(pair); +void WriteCountsWithImmediates(Stream& stream, + const OpcodeInfoCounts& counts) { + // Remove const from the key type so we can sort below. + typedef std::pair::type, + OpcodeInfoCounts::mapped_type> + OpcodeInfoCountPair; + + std::vector sorted; + std::copy_if(counts.begin(), counts.end(), std::back_inserter(sorted), + WithinCutoff()); + + // Use a stable sort to keep the elements with the same count in opcode info + // order (since the OpcodeInfoCounts map is sorted). + std::stable_sort(sorted.begin(), sorted.end(), + SortByCountDescending()); + + for (auto& pair : sorted) { + auto&& info = pair.first; + size_t count = pair.second; + info.Write(stream); + stream.Writef("%s%" PRIzd "\n", s_separator, count); } - std::sort(filtered_vec.begin(), filtered_vec.end(), lt_fcn); - fprintf(out, "%s\n", title); - display_int_pair_counter_vector(out, filtered_vec, display_first_fcn, - display_second_fcn, opcode_name); } int ProgramMain(int argc, char** argv) { - init_stdio(); - parse_options(argc, argv); + InitStdio(); + ParseOptions(argc, argv); - char* data; - size_t size; - Result result = read_file(s_infile, &data, &size); - if (WABT_FAILED(result)) { + std::vector file_data; + Result result = ReadFile(s_infile, &file_data); + if (Failed(result)) { const char* input_name = s_infile ? s_infile : "stdin"; ERROR("Unable to parse: %s", input_name); - delete[] data; - } - FILE* out = stdout; - if (s_outfile) { - out = fopen(s_outfile, "w"); - if (!out) - ERROR("fopen \"%s\" failed, errno=%d\n", s_outfile, errno); - result = Result::Error; + return 1; } - if (WABT_SUCCEEDED(result)) { - OpcntData opcnt_data; - result = read_binary_opcnt(data, size, &s_read_binary_options, &opcnt_data); - if (WABT_SUCCEEDED(result)) { - display_sorted_int_counter_vector( - out, "Opcode counts:", opcnt_data.opcode_vec, opcode_counter_gt, - display_opcode_name, nullptr); - display_sorted_int_counter_vector( - out, "\ni32.const:", opcnt_data.i32_const_vec, int_counter_gt, - display_intmax, get_opcode_name(Opcode::I32Const)); - display_sorted_int_counter_vector( - out, "\nget_local:", opcnt_data.get_local_vec, int_counter_gt, - display_intmax, get_opcode_name(Opcode::GetLocal)); - display_sorted_int_counter_vector( - out, "\nset_local:", opcnt_data.set_local_vec, int_counter_gt, - display_intmax, get_opcode_name(Opcode::SetLocal)); - display_sorted_int_counter_vector( - out, "\ntee_local:", opcnt_data.tee_local_vec, int_counter_gt, - display_intmax, get_opcode_name(Opcode::TeeLocal)); - display_sorted_int_pair_counter_vector( - out, "\ni32.load:", opcnt_data.i32_load_vec, int_pair_counter_gt, - display_intmax, display_intmax, get_opcode_name(Opcode::I32Load)); - display_sorted_int_pair_counter_vector( - out, "\ni32.store:", opcnt_data.i32_store_vec, int_pair_counter_gt, - display_intmax, display_intmax, get_opcode_name(Opcode::I32Store)); + + FileStream stream(s_outfile ? FileStream(s_outfile) : FileStream(stdout)); + + if (Succeeded(result)) { + OpcodeInfoCounts counts; + result = ReadBinaryOpcnt(DataOrNull(file_data), file_data.size(), + &s_read_binary_options, &counts); + if (Succeeded(result)) { + stream.Writef("Opcode counts:\n"); + WriteCounts(stream, counts); + + stream.Writef("\nOpcode counts with immediates:\n"); + WriteCountsWithImmediates(stream, counts); } } - delete[] data; + return result != Result::Ok; } diff --git a/lib/wabt/src/tools/wasm2wast.cc b/lib/wabt/src/tools/wasm2wast.cc index 45ce4bcdf1c..ab8c4f9ca04 100644 --- a/lib/wabt/src/tools/wasm2wast.cc +++ b/lib/wabt/src/tools/wasm2wast.cc @@ -20,25 +20,30 @@ #include #include "apply-names.h" -#include "binary-error-handler.h" #include "binary-reader.h" #include "binary-reader-ir.h" +#include "error-handler.h" +#include "feature.h" #include "generate-names.h" #include "ir.h" #include "option-parser.h" #include "stream.h" +#include "validator.h" +#include "wast-lexer.h" #include "wat-writer.h" #include "writer.h" using namespace wabt; static int s_verbose; -static const char* s_infile; -static const char* s_outfile; -static ReadBinaryOptions s_read_binary_options = {nullptr, true}; +static std::string s_infile; +static std::string s_outfile; +static Features s_features; static WriteWatOptions s_write_wat_options; static bool s_generate_names; +static bool s_read_debug_names = true; static std::unique_ptr s_log_stream; +static bool s_validate = true; static const char s_description[] = R"( read a file in the wasm binary format, and convert it to the wasm @@ -52,66 +57,79 @@ R"( read a file in the wasm binary format, and convert it to the wasm $ wasm2wast test.wasm --no-debug-names -o test.wast )"; -static void parse_options(int argc, char** argv) { +static void ParseOptions(int argc, char** argv) { OptionParser parser("wasm2wast", s_description); parser.AddOption('v', "verbose", "Use multiple times for more info", []() { s_verbose++; s_log_stream = FileStream::CreateStdout(); - s_read_binary_options.log_stream = s_log_stream.get(); }); parser.AddHelpOption(); parser.AddOption( 'o', "output", "FILENAME", "Output file for the generated wast file, by default use stdout", - [](const char* argument) { s_outfile = argument; }); + [](const char* argument) { + s_outfile = argument; + ConvertBackslashToSlash(&s_outfile); + }); parser.AddOption('f', "fold-exprs", "Write folded expressions where possible", []() { s_write_wat_options.fold_exprs = true; }); + s_features.AddOptions(&parser); parser.AddOption("inline-exports", "Write all exports inline", []() { s_write_wat_options.inline_export = true; }); parser.AddOption("no-debug-names", "Ignore debug names in the binary file", - []() { s_read_binary_options.read_debug_names = false; }); + []() { s_read_debug_names = false; }); parser.AddOption( "generate-names", "Give auto-generated names to non-named functions, types, etc.", []() { s_generate_names = true; }); + parser.AddOption("no-check", "Don't check for invalid modules", + []() { s_validate = false; }); parser.AddArgument("filename", OptionParser::ArgumentCount::One, - [](const char* argument) { s_infile = argument; }); + [](const char* argument) { + s_infile = argument; + ConvertBackslashToSlash(&s_infile); + }); parser.Parse(argc, argv); } int ProgramMain(int argc, char** argv) { Result result; - init_stdio(); - parse_options(argc, argv); + InitStdio(); + ParseOptions(argc, argv); - char* data; - size_t size; - result = read_file(s_infile, &data, &size); - if (WABT_SUCCEEDED(result)) { - BinaryErrorHandlerFile error_handler; + std::vector file_data; + result = ReadFile(s_infile.c_str(), &file_data); + if (Succeeded(result)) { + ErrorHandlerFile error_handler(Location::Type::Binary); Module module; - result = read_binary_ir(data, size, &s_read_binary_options, &error_handler, - &module); - if (WABT_SUCCEEDED(result)) { + ReadBinaryOptions options(s_features, s_log_stream.get(), + s_read_debug_names); + result = ReadBinaryIr(s_infile.c_str(), DataOrNull(file_data), + file_data.size(), &options, &error_handler, &module); + if (Succeeded(result)) { + if (Succeeded(result) && s_validate) { + WastLexer* lexer = nullptr; + result = ValidateModule(lexer, &module, &error_handler); + } + if (s_generate_names) - result = generate_names(&module); + result = GenerateNames(&module); - if (WABT_SUCCEEDED(result)) { + if (Succeeded(result)) { /* TODO(binji): This shouldn't fail; if a name can't be applied * (because the index is invalid, say) it should just be skipped. */ - Result dummy_result = apply_names(&module); + Result dummy_result = ApplyNames(&module); WABT_USE(dummy_result); } - if (WABT_SUCCEEDED(result)) { - FileWriter writer(s_outfile ? FileWriter(s_outfile) - : FileWriter(stdout)); - result = write_wat(&writer, &module, &s_write_wat_options); + if (Succeeded(result)) { + FileWriter writer(!s_outfile.empty() ? FileWriter(s_outfile.c_str()) + : FileWriter(stdout)); + result = WriteWat(&writer, &module, &s_write_wat_options); } } - delete[] data; } return result != Result::Ok; } diff --git a/lib/wabt/src/tools/wast-desugar.cc b/lib/wabt/src/tools/wast-desugar.cc index 55caf7d08ed..43246d194d1 100644 --- a/lib/wabt/src/tools/wast-desugar.cc +++ b/lib/wabt/src/tools/wast-desugar.cc @@ -23,10 +23,11 @@ #include "apply-names.h" #include "common.h" #include "config.h" +#include "error-handler.h" +#include "feature.h" #include "generate-names.h" #include "ir.h" #include "option-parser.h" -#include "source-error-handler.h" #include "stream.h" #include "wast-parser.h" #include "wat-writer.h" @@ -38,6 +39,8 @@ static const char* s_infile; static const char* s_outfile; static WriteWatOptions s_write_wat_options; static bool s_generate_names; +static bool s_debug_parsing; +static Features s_features; static const char s_description[] = R"( read a file in the wasm s-expression format and format it. @@ -53,14 +56,17 @@ R"( read a file in the wasm s-expression format and format it. $ wast-desugar --generate-names test.wast )"; -static void parse_options(int argc, char** argv) { +static void ParseOptions(int argc, char** argv) { OptionParser parser("wast-desugar", s_description); parser.AddHelpOption(); parser.AddOption('o', "output", "FILE", "Output file for the formatted file", [](const char* argument) { s_outfile = argument; }); + parser.AddOption("debug-parser", "Turn on debugging the parser of wast files", + []() { s_debug_parsing = true; }); parser.AddOption('f', "fold-exprs", "Write folded expressions where possible", []() { s_write_wat_options.fold_exprs = true; }); + s_features.AddOptions(&parser); parser.AddOption( "generate-names", "Give auto-generated names to non-named functions, types, etc.", @@ -72,31 +78,33 @@ static void parse_options(int argc, char** argv) { } int ProgramMain(int argc, char** argv) { - init_stdio(); - parse_options(argc, argv); + InitStdio(); + ParseOptions(argc, argv); std::unique_ptr lexer(WastLexer::CreateFileLexer(s_infile)); if (!lexer) WABT_FATAL("unable to read %s\n", s_infile); - SourceErrorHandlerFile error_handler; + ErrorHandlerFile error_handler(Location::Type::Text); Script* script; - Result result = parse_wast(lexer.get(), &script, &error_handler); + WastParseOptions parse_wast_options(s_features); + Result result = + ParseWast(lexer.get(), &script, &error_handler, &parse_wast_options); - if (WABT_SUCCEEDED(result)) { + if (Succeeded(result)) { Module* module = script->GetFirstModule(); if (!module) WABT_FATAL("no module in file.\n"); if (s_generate_names) - result = generate_names(module); + result = GenerateNames(module); - if (WABT_SUCCEEDED(result)) - result = apply_names(module); + if (Succeeded(result)) + result = ApplyNames(module); - if (WABT_SUCCEEDED(result)) { + if (Succeeded(result)) { FileWriter writer(s_outfile ? FileWriter(s_outfile) : FileWriter(stdout)); - result = write_wat(&writer, module, &s_write_wat_options); + result = WriteWat(&writer, module, &s_write_wat_options); } } diff --git a/lib/wabt/src/tools/wast2wasm.cc b/lib/wabt/src/tools/wast2wasm.cc index 4bfc2e7c205..1926ad83b0f 100644 --- a/lib/wabt/src/tools/wast2wasm.cc +++ b/lib/wabt/src/tools/wast2wasm.cc @@ -26,10 +26,11 @@ #include "binary-writer.h" #include "binary-writer-spec.h" #include "common.h" +#include "error-handler.h" +#include "feature.h" #include "ir.h" #include "option-parser.h" #include "resolve-names.h" -#include "source-error-handler.h" #include "stream.h" #include "validator.h" #include "wast-parser.h" @@ -41,13 +42,11 @@ static const char* s_infile; static const char* s_outfile; static bool s_dump_module; static int s_verbose; -static WriteBinaryOptions s_write_binary_options = - WABT_WRITE_BINARY_OPTIONS_DEFAULT; -static WriteBinarySpecOptions s_write_binary_spec_options = - WABT_WRITE_BINARY_SPEC_OPTIONS_DEFAULT; +static WriteBinaryOptions s_write_binary_options; static bool s_spec; static bool s_validate = true; -static WastParseOptions s_parse_options; +static bool s_debug_parsing; +static Features s_features; static std::unique_ptr s_log_stream; @@ -71,7 +70,7 @@ R"( read a file in the wasm s-expression format, check it for errors, and $ wast2wasm spec-test.wast --spec -o spec-test.json )"; -static void parse_options(int argc, char* argv[]) { +static void ParseOptions(int argc, char* argv[]) { OptionParser parser("wast2wasm", s_description); parser.AddOption('v', "verbose", "Use multiple times for more info", []() { @@ -81,13 +80,11 @@ static void parse_options(int argc, char* argv[]) { }); parser.AddHelpOption(); parser.AddOption("debug-parser", "Turn on debugging the parser of wast files", - []() { s_parse_options.debug_parsing = true; }); + []() { s_debug_parsing = true; }); parser.AddOption('d', "dump-module", "Print a hexdump of the module to stdout", []() { s_dump_module = true; }); - parser.AddOption("future-exceptions", - "Test future extension for exception handling", - []() { s_parse_options.allow_exceptions = true; }); + s_features.AddOptions(&parser); parser.AddOption('o', "output", "FILE", "output wasm binary file", [](const char* argument) { s_outfile = argument; }); parser.AddOption( @@ -113,8 +110,8 @@ static void parse_options(int argc, char* argv[]) { parser.Parse(argc, argv); } -static void write_buffer_to_file(const char* filename, - const OutputBuffer& buffer) { +static void WriteBufferToFile(const char* filename, + const OutputBuffer& buffer) { if (s_dump_module) { if (s_verbose) s_log_stream->Writef(";; dump\n"); @@ -129,44 +126,44 @@ static void write_buffer_to_file(const char* filename, } int ProgramMain(int argc, char** argv) { - init_stdio(); + InitStdio(); - parse_options(argc, argv); + ParseOptions(argc, argv); std::unique_ptr lexer = WastLexer::CreateFileLexer(s_infile); if (!lexer) WABT_FATAL("unable to read file: %s\n", s_infile); - SourceErrorHandlerFile error_handler; + ErrorHandlerFile error_handler(Location::Type::Text); Script* script; - Result result = parse_wast(lexer.get(), &script, &error_handler, - &s_parse_options); + WastParseOptions parse_wast_options(s_features); + Result result = + ParseWast(lexer.get(), &script, &error_handler, &parse_wast_options); - if (WABT_SUCCEEDED(result)) { - result = resolve_names_script(lexer.get(), script, &error_handler); + if (Succeeded(result)) { + result = ResolveNamesScript(lexer.get(), script, &error_handler); - if (WABT_SUCCEEDED(result) && s_validate) - result = validate_script(lexer.get(), script, &error_handler); + if (Succeeded(result) && s_validate) + result = ValidateScript(lexer.get(), script, &error_handler); - if (WABT_SUCCEEDED(result)) { + if (Succeeded(result)) { if (s_spec) { - s_write_binary_spec_options.json_filename = s_outfile; - s_write_binary_spec_options.write_binary_options = - s_write_binary_options; - result = write_binary_spec_script(script, s_infile, - &s_write_binary_spec_options); + WriteBinarySpecOptions write_binary_spec_options; + write_binary_spec_options.json_filename = s_outfile; + write_binary_spec_options.write_binary_options = s_write_binary_options; + result = + WriteBinarySpecScript(script, s_infile, &write_binary_spec_options); } else { MemoryWriter writer; const Module* module = script->GetFirstModule(); if (module) { - result = - write_binary_module(&writer, module, &s_write_binary_options); + result = WriteBinaryModule(&writer, module, &s_write_binary_options); } else { WABT_FATAL("no module found\n"); } - if (WABT_SUCCEEDED(result)) - write_buffer_to_file(s_outfile, writer.output_buffer()); + if (Succeeded(result)) + WriteBufferToFile(s_outfile, writer.output_buffer()); } } } diff --git a/lib/wabt/src/tracing.cc b/lib/wabt/src/tracing.cc new file mode 100644 index 00000000000..f46698949c9 --- /dev/null +++ b/lib/wabt/src/tracing.cc @@ -0,0 +1,70 @@ +/* + * Copyright 2017 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. + */ + +#define WABT_TRACING 1 +#include "tracing.h" + +namespace { + +size_t indent = 0; +const char* indent_text = " "; + +void Fill() { + for (size_t i = 0; i < indent; ++i) + fputs(indent_text, stderr); +} + +void Indent() { + Fill(); + ++indent; +} + +void Dedent() { + if (indent) + --indent; + Fill(); +} + +} // end of anonymous namespace + +namespace wabt { + +// static + +TraceScope::TraceScope(const char* method) : method_(method) { + PrintEnter(method); + PrintNewline(); +} + +TraceScope::~TraceScope() { + Dedent(); + fputs("<- ", stderr); + fputs(method_, stderr); + fputc('\n', stderr); +} + +void TraceScope::PrintEnter(const char* method) { + Indent(); + fputs("-> ", stderr); + fputs(method, stderr); + fputs("(", stderr); +} + +void TraceScope::PrintNewline() { + fputs(")\n", stderr); +} + +} // end of namespace wabt diff --git a/lib/wabt/src/tracing.h b/lib/wabt/src/tracing.h new file mode 100644 index 00000000000..dce1b89a35f --- /dev/null +++ b/lib/wabt/src/tracing.h @@ -0,0 +1,73 @@ +/* + * Copyright 2017 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 WABT_TRACING_H_ +#define WABT_TRACING_H_ + +// Provides a simple tracing class that automatically generates enter/exit +// messages using the scope of the instance. +// +// It also assumes that this file is only included in .cc files. +// Immediately before the inclusion of this file, there is a define of +// for WABT_TRACING, defining whether tracing should be compiled in for +// that source file. + +#ifndef WABT_TRACING +#define WABT_TRACING 0 +#endif + +#include "common.h" + +namespace wabt { + +#if WABT_TRACING + +// Scoped class that automatically prints enter("->") and exit("<-") +// lines, indented by trace level. +struct TraceScope { + WABT_DISALLOW_COPY_AND_ASSIGN(TraceScope); + TraceScope() = delete; + TraceScope(const char* method); + template + TraceScope(const char* method, const char* format, Args&&... args) + : method_(method) { + PrintEnter(method); + fprintf(stderr, format, std::forward(args)...); + PrintNewline(); + } + ~TraceScope(); + + private: + const char* method_; + void PrintEnter(const char* method); + void PrintNewline(); +}; + +#define WABT_TRACE(method_name) TraceScope _func_(#method_name) + +#define WABT_TRACE_ARGS(method_name, format, ...) \ + TraceScope _func_(#method_name, format, __VA_ARGS__) + +#else + +#define WABT_TRACE(method) +#define WABT_TRACE_ARGS(method_name, format, ...) + +#endif + +} // end namespace wabt + +#endif // WABT_TRACING_H_ diff --git a/lib/wabt/src/type-checker.cc b/lib/wabt/src/type-checker.cc index eba23c75f21..ef38a1bc05d 100644 --- a/lib/wabt/src/type-checker.cc +++ b/lib/wabt/src/type-checker.cc @@ -18,7 +18,7 @@ #define CHECK_RESULT(expr) \ do { \ - if (WABT_FAILED(expr)) \ + if (Failed(expr)) \ return Result::Error; \ } while (0) @@ -66,7 +66,7 @@ Result TypeChecker::TopLabel(Label** out_label) { bool TypeChecker::IsUnreachable() { Label* label; - if (WABT_FAILED(TopLabel(&label))) + if (Failed(TopLabel(&label))) return true; return label->unreachable; } @@ -172,7 +172,7 @@ Result TypeChecker::CheckTypeStackEnd(const char* desc) { Result TypeChecker::CheckType(Type actual, Type expected, const char* desc) { if (expected != actual && expected != Type::Any && actual != Type::Any) { PrintError("type mismatch in %s, expected %s but got %s.", desc, - get_type_name(expected), get_type_name(actual)); + GetTypeName(expected), GetTypeName(actual)); return Result::Error; } return Result::Ok; @@ -249,17 +249,15 @@ Result TypeChecker::PopAndCheck2TypesAreEqual(Type* out_type, } Result TypeChecker::CheckOpcode1(Opcode opcode) { - Result result = PopAndCheck1Type(get_opcode_param_type_1(opcode), - get_opcode_name(opcode)); - PushType(get_opcode_result_type(opcode)); + Result result = PopAndCheck1Type(opcode.GetParamType1(), opcode.GetName()); + PushType(opcode.GetResultType()); return result; } Result TypeChecker::CheckOpcode2(Opcode opcode) { - Result result = PopAndCheck2Types(get_opcode_param_type_1(opcode), - get_opcode_param_type_2(opcode), - get_opcode_name(opcode)); - PushType(get_opcode_result_type(opcode)); + Result result = PopAndCheck2Types(opcode.GetParamType1(), + opcode.GetParamType2(), opcode.GetName()); + PushType(opcode.GetResultType()); return result; } @@ -294,8 +292,10 @@ Result TypeChecker::OnBrIf(Index depth) { COMBINE_RESULT(result, PopAndCheck1Type(Type::I32, "br_if")); Label* label; CHECK_RESULT(GetLabel(depth, &label)); - if (label->label_type != LabelType::Loop) - COMBINE_RESULT(result, CheckSignature(label->sig, "br_if")); + if (label->label_type != LabelType::Loop) { + COMBINE_RESULT(result, PopAndCheckSignature(label->sig, "br_if")); + PushTypes(label->sig); + } return result; } @@ -346,6 +346,24 @@ Result TypeChecker::OnCompare(Opcode opcode) { return CheckOpcode2(opcode); } +Result TypeChecker::OnCatch(const TypeVector* sig) { + PushTypes(*sig); + return Result::Ok; +} + +Result TypeChecker::OnCatchBlock(const TypeVector* sig) { + Result result = Result::Ok; + Label* label; + CHECK_RESULT(TopLabel(&label)); + COMBINE_RESULT(result, CheckLabelType(label, LabelType::Try)); + COMBINE_RESULT(result, PopAndCheckSignature(label->sig, "try block")); + COMBINE_RESULT(result, CheckTypeStackEnd("try block")); + ResetTypeStackToLabel(label); + label->label_type = LabelType::Catch; + label->unreachable = false; + return result; +} + Result TypeChecker::OnConst(Type type) { PushType(type); return Result::Ok; @@ -396,7 +414,8 @@ Result TypeChecker::OnEnd(Label* label, Result TypeChecker::OnEnd() { Result result = Result::Ok; static const char* s_label_type_name[] = {"function", "block", "loop", "if", - "if false branch"}; + "if false branch", "try", + "try catch"}; WABT_STATIC_ASSERT(WABT_ARRAY_SIZE(s_label_type_name) == kLabelTypeCount); Label* label; CHECK_RESULT(TopLabel(&label)); @@ -441,6 +460,39 @@ Result TypeChecker::OnLoop(const TypeVector* sig) { return Result::Ok; } +Result TypeChecker::OnRethrow(Index depth) { + Result result = Result::Ok; + Label* label; + CHECK_RESULT(GetLabel(depth, &label)); + if (label->label_type != LabelType::Catch) { + std::string candidates; + size_t last = label_stack_.size() - 1; + for (size_t i = 0; i < label_stack_.size(); ++i) { + if (label_stack_[last - i].label_type == LabelType::Catch) { + if (!candidates.empty()) + candidates.append(", "); + candidates.append(std::to_string(i)); + } + } + if (candidates.empty()) { + PrintError("Rethrow not in try catch block"); + } else { + PrintError("invalid rethrow depth: %" PRIindex " (catches: %s)", depth, + candidates.c_str()); + } + result = Result::Error; + } + CHECK_RESULT(SetUnreachable()); + return result; +} + +Result TypeChecker::OnThrow(const TypeVector* sig) { + Result result = Result::Ok; + COMBINE_RESULT(result, PopAndCheckSignature(*sig, "throw")); + CHECK_RESULT(SetUnreachable()); + return result; +} + Result TypeChecker::OnReturn() { Result result = Result::Ok; Label* func_label; @@ -471,12 +523,15 @@ Result TypeChecker::OnStore(Opcode opcode) { return CheckOpcode2(opcode); } +Result TypeChecker::OnTryBlock(const TypeVector* sig) { + PushLabel(LabelType::Try, *sig); + return Result::Ok; +} + Result TypeChecker::OnTeeLocal(Type type) { Result result = Result::Ok; - Type value = Type::Any; - COMBINE_RESULT(result, CheckTypeStackLimit(1, "tee_local")); - COMBINE_RESULT(result, TopType(&value)); - COMBINE_RESULT(result, CheckType(value, type, "tee_local")); + COMBINE_RESULT(result, PopAndCheck1Type(type, "tee_local")); + PushType(type); return result; } diff --git a/lib/wabt/src/type-checker.h b/lib/wabt/src/type-checker.h index f7238365c90..849c701d124 100644 --- a/lib/wabt/src/type-checker.h +++ b/lib/wabt/src/type-checker.h @@ -61,6 +61,8 @@ class TypeChecker { Result OnCall(const TypeVector* param_types, const TypeVector* result_types); Result OnCallIndirect(const TypeVector* param_types, const TypeVector* result_types); + Result OnCatch(const TypeVector* sig); + Result OnCatchBlock(const TypeVector* sig); Result OnCompare(Opcode); Result OnConst(Type); Result OnConvert(Opcode); @@ -74,12 +76,15 @@ class TypeChecker { Result OnIf(const TypeVector* sig); Result OnLoad(Opcode); Result OnLoop(const TypeVector* sig); + Result OnRethrow(Index depth); Result OnReturn(); Result OnSelect(); Result OnSetGlobal(Type); Result OnSetLocal(Type); Result OnStore(Opcode); Result OnTeeLocal(Type); + Result OnThrow(const TypeVector* sig); + Result OnTryBlock(const TypeVector* sig); Result OnUnary(Opcode); Result OnUnreachable(); Result EndFunction(); diff --git a/lib/wabt/src/utf8.cc b/lib/wabt/src/utf8.cc index f582d7609fc..3855fb71dc6 100644 --- a/lib/wabt/src/utf8.cc +++ b/lib/wabt/src/utf8.cc @@ -43,13 +43,13 @@ const int s_utf8_length[256] = { }; // Returns true if this is a valid continuation byte. -bool is_cont(uint8_t c) { +bool IsCont(uint8_t c) { return (c & 0xc0) == 0x80; } -} // namespace +} // end anonymous namespace -bool is_valid_utf8(const char* s, size_t s_length) { +bool IsValidUtf8(const char* s, size_t s_length) { const uint8_t* p = reinterpret_cast(s); const uint8_t* end = p + s_length; while (p < end) { @@ -68,7 +68,7 @@ bool is_valid_utf8(const char* s, size_t s_length) { case 2: p++; - if (!is_cont(*p++)) + if (!IsCont(*p++)) return false; break; @@ -76,7 +76,7 @@ bool is_valid_utf8(const char* s, size_t s_length) { p++; uint8_t cu1 = *p++; uint8_t cu2 = *p++; - if (!(is_cont(cu1) && is_cont(cu2)) || + if (!(IsCont(cu1) && IsCont(cu2)) || (cu0 == 0xe0 && cu1 < 0xa0) || // Overlong encoding. (cu0 == 0xed && cu1 >= 0xa0)) // UTF-16 surrogate halves. return false; @@ -88,7 +88,7 @@ bool is_valid_utf8(const char* s, size_t s_length) { uint8_t cu1 = *p++; uint8_t cu2 = *p++; uint8_t cu3 = *p++; - if (!(is_cont(cu1) && is_cont(cu2) && is_cont(cu3)) || + if (!(IsCont(cu1) && IsCont(cu2) && IsCont(cu3)) || (cu0 == 0xf0 && cu1 < 0x90) || // Overlong encoding. (cu0 == 0xf4 && cu1 >= 0x90)) // Code point >= 0x11000. return false; diff --git a/lib/wabt/src/utf8.h b/lib/wabt/src/utf8.h index 387006219d8..9bab1de75d9 100644 --- a/lib/wabt/src/utf8.h +++ b/lib/wabt/src/utf8.h @@ -21,7 +21,7 @@ namespace wabt { -bool is_valid_utf8(const char* s, size_t length); +bool IsValidUtf8(const char* s, size_t length); } // namespace wabt diff --git a/lib/wabt/src/validator.cc b/lib/wabt/src/validator.cc index b652bf3e7e0..a1afab1ef61 100644 --- a/lib/wabt/src/validator.cc +++ b/lib/wabt/src/validator.cc @@ -23,7 +23,9 @@ #include #include "binary-reader.h" -#include "source-error-handler.h" +#include "cast.h" +#include "error-handler.h" +#include "ir.h" #include "type-checker.h" #include "wast-parser-lexer-shared.h" @@ -34,8 +36,9 @@ namespace { class Validator { public: WABT_DISALLOW_COPY_AND_ASSIGN(Validator); - Validator(SourceErrorHandler*, WastLexer*, const Script*); + Validator(ErrorHandler*, WastLexer*, const Script*); + Result CheckModule(const Module* module); Result CheckScript(const Script* script); private: @@ -52,6 +55,11 @@ class Validator { }; }; + struct TryContext { + const TryExpr* try_ = nullptr; + const Catch* catch_ = nullptr; + }; + void WABT_PRINTF_FORMAT(3, 4) PrintError(const Location* loc, const char* fmt, ...); void OnTypecheckerError(const char* msg); @@ -98,7 +106,7 @@ class Validator { void CheckAssertReturnNanType(const Location* loc, Type actual, const char* desc); - void CheckExprList(const Location* loc, const Expr* first); + void CheckExprList(const Location* loc, const ExprList& exprs); void CheckHasMemory(const Location* loc, Opcode opcode); void CheckBlockSig(const Location* loc, Opcode opcode, @@ -110,7 +118,7 @@ class Validator { void CheckFunc(const Location* loc, const Func* func); void PrintConstExprError(const Location* loc, const char* desc); void CheckConstInitExpr(const Location* loc, - const Expr* expr, + const ExprList& expr, Type expected_type, const char* desc); void CheckGlobal(const Location* loc, const Global* global); @@ -126,14 +134,16 @@ class Validator { void CheckExport(const Location* loc, const Export* export_); void CheckDuplicateExportBindings(const Module* module); - void CheckModule(const Module* module); const TypeVector* CheckInvoke(const Action* action); Result CheckGet(const Action* action, Type* out_type); ActionResult CheckAction(const Action* action); void CheckAssertReturnNanCommand(const Action* action); void CheckCommand(const Command* command); - SourceErrorHandler* error_handler_ = nullptr; + void CheckExcept(const Location* loc, const Exception* Except); + Result CheckExceptVar(const Var* var, const Exception** out_except); + + ErrorHandler* error_handler_ = nullptr; WastLexer* lexer_ = nullptr; const Script* script_ = nullptr; const Module* current_module_ = nullptr; @@ -142,13 +152,15 @@ class Validator { Index current_memory_index_ = 0; Index current_global_index_ = 0; Index num_imported_globals_ = 0; + Index current_except_index_ = 0; TypeChecker typechecker_; // Cached for access by OnTypecheckerError. const Location* expr_loc_ = nullptr; Result result_ = Result::Ok; + std::vector try_contexts_; }; -Validator::Validator(SourceErrorHandler* error_handler, +Validator::Validator(ErrorHandler* error_handler, WastLexer* lexer, const Script* script) : error_handler_(error_handler), lexer_(lexer), script_(script) { @@ -160,7 +172,7 @@ void Validator::PrintError(const Location* loc, const char* fmt, ...) { result_ = Result::Error; va_list args; va_start(args, fmt); - wast_format_error(error_handler_, loc, lexer_, fmt, args); + WastFormatError(error_handler_, loc, lexer_, fmt, args); va_end(args); } @@ -173,7 +185,7 @@ static bool is_power_of_two(uint32_t x) { } static Address get_opcode_natural_alignment(Opcode opcode) { - Address memory_size = get_opcode_memory_size(opcode); + Address memory_size = opcode.GetMemorySize(); assert(memory_size != 0); return memory_size; } @@ -182,10 +194,9 @@ Result Validator::CheckVar(Index max_index, const Var* var, const char* desc, Index* out_index) { - assert(var->type == VarType::Index); - if (var->index < max_index) { + if (var->index() < max_index) { if (out_index) - *out_index = var->index; + *out_index = var->index(); return Result::Ok; } PrintError(&var->loc, "%s variable out of range (max %" PRIindex ")", desc, @@ -195,7 +206,7 @@ Result Validator::CheckVar(Index max_index, Result Validator::CheckFuncVar(const Var* var, const Func** out_func) { Index index; - if (WABT_FAILED( + if (Failed( CheckVar(current_module_->funcs.size(), var, "function", &index))) { return Result::Error; } @@ -209,7 +220,7 @@ Result Validator::CheckGlobalVar(const Var* var, const Global** out_global, Index* out_global_index) { Index index; - if (WABT_FAILED( + if (Failed( CheckVar(current_module_->globals.size(), var, "global", &index))) { return Result::Error; } @@ -223,7 +234,7 @@ Result Validator::CheckGlobalVar(const Var* var, Type Validator::GetGlobalVarTypeOrAny(const Var* var) { const Global* global; - if (WABT_SUCCEEDED(CheckGlobalVar(var, &global, nullptr))) + if (Succeeded(CheckGlobalVar(var, &global, nullptr))) return global->type; return Type::Any; } @@ -231,8 +242,8 @@ Type Validator::GetGlobalVarTypeOrAny(const Var* var) { Result Validator::CheckFuncTypeVar(const Var* var, const FuncType** out_func_type) { Index index; - if (WABT_FAILED(CheckVar(current_module_->func_types.size(), var, - "function type", &index))) { + if (Failed(CheckVar(current_module_->func_types.size(), var, + "function type", &index))) { return Result::Error; } @@ -243,8 +254,7 @@ Result Validator::CheckFuncTypeVar(const Var* var, Result Validator::CheckTableVar(const Var* var, const Table** out_table) { Index index; - if (WABT_FAILED( - CheckVar(current_module_->tables.size(), var, "table", &index))) { + if (Failed(CheckVar(current_module_->tables.size(), var, "table", &index))) { return Result::Error; } @@ -255,7 +265,7 @@ Result Validator::CheckTableVar(const Var* var, const Table** out_table) { Result Validator::CheckMemoryVar(const Var* var, const Memory** out_memory) { Index index; - if (WABT_FAILED( + if (Failed( CheckVar(current_module_->memories.size(), var, "memory", &index))) { return Result::Error; } @@ -281,9 +291,9 @@ Result Validator::CheckLocalVar(const Var* var, Type* out_type) { return Result::Ok; } - if (var->type == VarType::Name) { - PrintError(&var->loc, "undefined local variable \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG(var->name)); + if (var->is_name()) { + PrintError(&var->loc, "undefined local variable \"%s\"", + var->name().c_str()); } else { PrintError(&var->loc, "local variable out of range (max %" PRIindex ")", max_index); @@ -317,7 +327,7 @@ void Validator::CheckType(const Location* loc, const char* desc) { if (expected != actual) { PrintError(loc, "type mismatch at %s. got %s, expected %s", desc, - get_type_name(actual), get_type_name(expected)); + GetTypeName(actual), GetTypeName(expected)); } } @@ -328,10 +338,9 @@ void Validator::CheckTypeIndex(const Location* loc, Index index, const char* index_kind) { if (expected != actual && expected != Type::Any && actual != Type::Any) { - PrintError(loc, - "type mismatch for %s %" PRIindex " of %s. got %s, expected %s", - index_kind, index, desc, get_type_name(actual), - get_type_name(expected)); + PrintError( + loc, "type mismatch for %s %" PRIindex " of %s. got %s, expected %s", + index_kind, index, desc, GetTypeName(actual), GetTypeName(expected)); } } @@ -381,21 +390,19 @@ void Validator::CheckAssertReturnNanType(const Location* loc, // so we special case it here. if (actual != Type::F32 && actual != Type::F64) { PrintError(loc, "type mismatch at %s. got %s, expected f32 or f64", desc, - get_type_name(actual)); + GetTypeName(actual)); } } -void Validator::CheckExprList(const Location* loc, const Expr* first) { - if (first) { - for (const Expr* expr = first; expr; expr = expr->next) - CheckExpr(expr); - } +void Validator::CheckExprList(const Location* loc, const ExprList& exprs) { + for (const Expr& expr : exprs) + CheckExpr(&expr); } void Validator::CheckHasMemory(const Location* loc, Opcode opcode) { if (current_module_->memories.size() == 0) { PrintError(loc, "%s requires an imported or defined memory.", - get_opcode_name(opcode)); + opcode.GetName()); } } @@ -405,7 +412,7 @@ void Validator::CheckBlockSig(const Location* loc, if (sig->size() > 1) { PrintError(loc, "multiple %s signature result types not currently supported.", - get_opcode_name(opcode)); + opcode.GetName()); } } @@ -414,37 +421,40 @@ void Validator::CheckExpr(const Expr* expr) { switch (expr->type) { case ExprType::Binary: - typechecker_.OnBinary(expr->binary.opcode); + typechecker_.OnBinary(cast(expr)->opcode); break; - case ExprType::Block: - CheckBlockSig(&expr->loc, Opcode::Block, &expr->block->sig); - typechecker_.OnBlock(&expr->block->sig); - CheckExprList(&expr->loc, expr->block->first); + case ExprType::Block: { + auto block_expr = cast(expr); + CheckBlockSig(&block_expr->loc, Opcode::Block, &block_expr->block->sig); + typechecker_.OnBlock(&block_expr->block->sig); + CheckExprList(&block_expr->loc, block_expr->block->exprs); typechecker_.OnEnd(); break; + } case ExprType::Br: - typechecker_.OnBr(expr->br.var.index); + typechecker_.OnBr(cast(expr)->var.index()); break; case ExprType::BrIf: - typechecker_.OnBrIf(expr->br_if.var.index); + typechecker_.OnBrIf(cast(expr)->var.index()); break; case ExprType::BrTable: { + auto br_table_expr = cast(expr); typechecker_.BeginBrTable(); - for (Var& var : *expr->br_table.targets) { - typechecker_.OnBrTableTarget(var.index); + for (Var& var : *br_table_expr->targets) { + typechecker_.OnBrTableTarget(var.index()); } - typechecker_.OnBrTableTarget(expr->br_table.default_target.index); + typechecker_.OnBrTableTarget(br_table_expr->default_target.index()); typechecker_.EndBrTable(); break; } case ExprType::Call: { const Func* callee; - if (WABT_SUCCEEDED(CheckFuncVar(&expr->call.var, &callee))) { + if (Succeeded(CheckFuncVar(&cast(expr)->var, &callee))) { typechecker_.OnCall(&callee->decl.sig.param_types, &callee->decl.sig.result_types); } @@ -456,34 +466,24 @@ void Validator::CheckExpr(const Expr* expr) { if (current_module_->tables.size() == 0) { PrintError(&expr->loc, "found call_indirect operator, but no table"); } - if (WABT_SUCCEEDED( - CheckFuncTypeVar(&expr->call_indirect.var, &func_type))) { + if (Succeeded(CheckFuncTypeVar(&cast(expr)->var, + &func_type))) { typechecker_.OnCallIndirect(&func_type->sig.param_types, &func_type->sig.result_types); } break; } - case ExprType::Catch: - // TODO(karlschimpf) Define. - PrintError(&expr->loc, "Catch: don't know how to validate"); - break; - - case ExprType::CatchAll: - // TODO(karlschimpf) Define. - PrintError(&expr->loc, "CatchAll: don't know how to validate"); - break; - case ExprType::Compare: - typechecker_.OnCompare(expr->compare.opcode); + typechecker_.OnCompare(cast(expr)->opcode); break; case ExprType::Const: - typechecker_.OnConst(expr->const_.type); + typechecker_.OnConst(cast(expr)->const_.type); break; case ExprType::Convert: - typechecker_.OnConvert(expr->convert.opcode); + typechecker_.OnConvert(cast(expr)->opcode); break; case ExprType::Drop: @@ -491,11 +491,13 @@ void Validator::CheckExpr(const Expr* expr) { break; case ExprType::GetGlobal: - typechecker_.OnGetGlobal(GetGlobalVarTypeOrAny(&expr->get_global.var)); + typechecker_.OnGetGlobal( + GetGlobalVarTypeOrAny(&cast(expr)->var)); break; case ExprType::GetLocal: - typechecker_.OnGetLocal(GetLocalVarTypeOrAny(&expr->get_local.var)); + typechecker_.OnGetLocal( + GetLocalVarTypeOrAny(&cast(expr)->var)); break; case ExprType::GrowMemory: @@ -503,30 +505,36 @@ void Validator::CheckExpr(const Expr* expr) { typechecker_.OnGrowMemory(); break; - case ExprType::If: - CheckBlockSig(&expr->loc, Opcode::If, &expr->if_.true_->sig); - typechecker_.OnIf(&expr->if_.true_->sig); - CheckExprList(&expr->loc, expr->if_.true_->first); - if (expr->if_.false_) { + case ExprType::If: { + auto if_expr = cast(expr); + CheckBlockSig(&if_expr->loc, Opcode::If, &if_expr->true_->sig); + typechecker_.OnIf(&if_expr->true_->sig); + CheckExprList(&if_expr->loc, if_expr->true_->exprs); + if (!if_expr->false_.empty()) { typechecker_.OnElse(); - CheckExprList(&expr->loc, expr->if_.false_); + CheckExprList(&if_expr->loc, if_expr->false_); } typechecker_.OnEnd(); break; + } - case ExprType::Load: - CheckHasMemory(&expr->loc, expr->load.opcode); - CheckAlign(&expr->loc, expr->load.align, - get_opcode_natural_alignment(expr->load.opcode)); - typechecker_.OnLoad(expr->load.opcode); + case ExprType::Load: { + auto load_expr = cast(expr); + CheckHasMemory(&load_expr->loc, load_expr->opcode); + CheckAlign(&load_expr->loc, load_expr->align, + get_opcode_natural_alignment(load_expr->opcode)); + typechecker_.OnLoad(load_expr->opcode); break; + } - case ExprType::Loop: - CheckBlockSig(&expr->loc, Opcode::Loop, &expr->loop->sig); - typechecker_.OnLoop(&expr->loop->sig); - CheckExprList(&expr->loc, expr->loop->first); + case ExprType::Loop: { + auto loop_expr = cast(expr); + CheckBlockSig(&loop_expr->loc, Opcode::Loop, &loop_expr->block->sig); + typechecker_.OnLoop(&loop_expr->block->sig); + CheckExprList(&loop_expr->loc, loop_expr->block->exprs); typechecker_.OnEnd(); break; + } case ExprType::CurrentMemory: CheckHasMemory(&expr->loc, Opcode::CurrentMemory); @@ -537,8 +545,7 @@ void Validator::CheckExpr(const Expr* expr) { break; case ExprType::Rethrow: - // TODO(karlschimpf) Define. - PrintError(&expr->loc, "Rethrow: don't know how to validate"); + typechecker_.OnRethrow(cast(expr)->var.index()); break; case ExprType::Return: @@ -550,36 +557,71 @@ void Validator::CheckExpr(const Expr* expr) { break; case ExprType::SetGlobal: - typechecker_.OnSetGlobal(GetGlobalVarTypeOrAny(&expr->set_global.var)); + typechecker_.OnSetGlobal( + GetGlobalVarTypeOrAny(&cast(expr)->var)); break; case ExprType::SetLocal: - typechecker_.OnSetLocal(GetLocalVarTypeOrAny(&expr->set_local.var)); + typechecker_.OnSetLocal( + GetLocalVarTypeOrAny(&cast(expr)->var)); break; - case ExprType::Store: - CheckHasMemory(&expr->loc, expr->store.opcode); - CheckAlign(&expr->loc, expr->store.align, - get_opcode_natural_alignment(expr->store.opcode)); - typechecker_.OnStore(expr->store.opcode); + case ExprType::Store: { + auto store_expr = cast(expr); + CheckHasMemory(&store_expr->loc, store_expr->opcode); + CheckAlign(&store_expr->loc, store_expr->align, + get_opcode_natural_alignment(store_expr->opcode)); + typechecker_.OnStore(store_expr->opcode); break; + } case ExprType::TeeLocal: - typechecker_.OnTeeLocal(GetLocalVarTypeOrAny(&expr->tee_local.var)); + typechecker_.OnTeeLocal( + GetLocalVarTypeOrAny(&cast(expr)->var)); break; case ExprType::Throw: - // TODO(karlschimpf) Define. - PrintError(&expr->loc, "Throw: don't know how to validate"); + const Exception* except; + if (Succeeded(CheckExceptVar(&cast(expr)->var, &except))) { + typechecker_.OnThrow(&except->sig); + } break; - case ExprType::TryBlock: - // TODO(karlschimpf) Define. - PrintError(&expr->loc, "TryBlock: don't know how to validate"); + case ExprType::TryBlock: { + auto try_expr = cast(expr); + TryContext context; + context.try_ = try_expr; + try_contexts_.push_back(context); + CheckBlockSig(&try_expr->loc, Opcode::Try, &try_expr->block->sig); + + typechecker_.OnTryBlock(&try_expr->block->sig); + CheckExprList(&try_expr->loc, try_expr->block->exprs); + + if (try_expr->catches.empty()) + PrintError(&try_expr->loc, "TryBlock: doesn't have any catch clauses"); + bool found_catch_all = false; + for (const Catch* catch_ : try_expr->catches) { + try_contexts_.back().catch_ = catch_; + typechecker_.OnCatchBlock(&try_expr->block->sig); + if (catch_->IsCatchAll()) { + found_catch_all = true; + } else { + if (found_catch_all) + PrintError(&catch_->loc, "Appears after catch all block"); + const Exception* except = nullptr; + if (Succeeded(CheckExceptVar(&catch_->var, &except))) { + typechecker_.OnCatch(&except->sig); + } + } + CheckExprList(&catch_->loc, catch_->exprs); + } + typechecker_.OnEnd(); + try_contexts_.pop_back(); break; + } case ExprType::Unary: - typechecker_.OnUnary(expr->unary.opcode); + typechecker_.OnUnary(cast(expr)->opcode); break; case ExprType::Unreachable: @@ -606,14 +648,14 @@ void Validator::CheckFunc(const Location* loc, const Func* func) { } if (func->decl.has_func_type) { const FuncType* func_type; - if (WABT_SUCCEEDED(CheckFuncTypeVar(&func->decl.type_var, &func_type))) { + if (Succeeded(CheckFuncTypeVar(&func->decl.type_var, &func_type))) { CheckFuncSignatureMatchesFuncType(loc, func->decl.sig, func_type); } } expr_loc_ = loc; typechecker_.BeginFunction(&func->decl.sig.result_types); - CheckExprList(loc, func->first_expr); + CheckExprList(loc, func->exprs); typechecker_.EndFunction(); current_func_ = nullptr; } @@ -626,26 +668,29 @@ void Validator::PrintConstExprError(const Location* loc, const char* desc) { } void Validator::CheckConstInitExpr(const Location* loc, - const Expr* expr, + const ExprList& exprs, Type expected_type, const char* desc) { Type type = Type::Void; - if (expr) { - if (expr->next) { + if (!exprs.empty()) { + if (exprs.size() > 1) { PrintConstExprError(loc, desc); return; } + const Expr* expr = &exprs.front(); + loc = &expr->loc; + switch (expr->type) { case ExprType::Const: - type = expr->const_.type; + type = cast(expr)->const_.type; break; case ExprType::GetGlobal: { const Global* ref_global = nullptr; Index ref_global_index; - if (WABT_FAILED(CheckGlobalVar(&expr->get_global.var, &ref_global, - &ref_global_index))) { + if (Failed(CheckGlobalVar(&cast(expr)->var, + &ref_global, &ref_global_index))) { return; } @@ -669,7 +714,7 @@ void Validator::CheckConstInitExpr(const Location* loc, } } - CheckType(expr ? &expr->loc : loc, type, expected_type, desc); + CheckType(loc, type, expected_type, desc); } void Validator::CheckGlobal(const Location* loc, const Global* global) { @@ -707,22 +752,21 @@ void Validator::CheckTable(const Location* loc, const Table* table) { } void Validator::CheckElemSegments(const Module* module) { - for (ModuleField* field = module->first_field; field; field = field->next) { - if (field->type != ModuleFieldType::ElemSegment) - continue; + for (const ModuleField& field : module->fields) { + if (auto elem_segment_field = dyn_cast(&field)) { + ElemSegment* elem_segment = elem_segment_field->elem_segment; + const Table* table; + if (!Succeeded(CheckTableVar(&elem_segment->table_var, &table))) + continue; - ElemSegment* elem_segment = field->elem_segment; - const Table* table; - if (!WABT_SUCCEEDED(CheckTableVar(&elem_segment->table_var, &table))) - continue; + for (const Var& var : elem_segment->vars) { + if (!Succeeded(CheckFuncVar(&var, nullptr))) + continue; + } - for (const Var& var : elem_segment->vars) { - if (!WABT_SUCCEEDED(CheckFuncVar(&var, nullptr))) - continue; + CheckConstInitExpr(&field.loc, elem_segment->offset, Type::I32, + "elem segment offset"); } - - CheckConstInitExpr(&field->loc, elem_segment->offset, Type::I32, - "elem segment offset"); } } @@ -733,25 +777,24 @@ void Validator::CheckMemory(const Location* loc, const Memory* memory) { } void Validator::CheckDataSegments(const Module* module) { - for (ModuleField* field = module->first_field; field; field = field->next) { - if (field->type != ModuleFieldType::DataSegment) - continue; - - DataSegment* data_segment = field->data_segment; - const Memory* memory; - if (!WABT_SUCCEEDED(CheckMemoryVar(&data_segment->memory_var, &memory))) - continue; + for (const ModuleField& field : module->fields) { + if (auto data_segment_field = dyn_cast(&field)) { + DataSegment* data_segment = data_segment_field->data_segment; + const Memory* memory; + if (!Succeeded(CheckMemoryVar(&data_segment->memory_var, &memory))) + continue; - CheckConstInitExpr(&field->loc, data_segment->offset, Type::I32, - "data segment offset"); + CheckConstInitExpr(&field.loc, data_segment->offset, Type::I32, + "data segment offset"); + } } } void Validator::CheckImport(const Location* loc, const Import* import) { switch (import->kind) { case ExternalKind::Except: - // TODO(karlschimpf) Define. - PrintError(loc, "import except: don't know how to validate"); + ++current_except_index_; + CheckExcept(loc, import->except); break; case ExternalKind::Func: if (import->func->decl.has_func_type) @@ -759,18 +802,18 @@ void Validator::CheckImport(const Location* loc, const Import* import) { break; case ExternalKind::Table: CheckTable(loc, import->table); - current_table_index_++; + ++current_table_index_; break; case ExternalKind::Memory: CheckMemory(loc, import->memory); - current_memory_index_++; + ++current_memory_index_; break; case ExternalKind::Global: if (import->global->mutable_) { PrintError(loc, "mutable globals cannot be imported"); } - num_imported_globals_++; - current_global_index_++; + ++num_imported_globals_; + ++current_global_index_; break; } } @@ -778,8 +821,7 @@ void Validator::CheckImport(const Location* loc, const Import* import) { void Validator::CheckExport(const Location* loc, const Export* export_) { switch (export_->kind) { case ExternalKind::Except: - // TODO(karlschimpf) Define. - PrintError(loc, "except: don't know how to validate export"); + CheckExceptVar(&export_->var, nullptr); break; case ExternalKind::Func: CheckFuncVar(&export_->var, nullptr); @@ -792,7 +834,7 @@ void Validator::CheckExport(const Location* loc, const Export* export_) { break; case ExternalKind::Global: { const Global* global; - if (WABT_SUCCEEDED(CheckGlobalVar(&export_->var, &global, nullptr))) { + if (Succeeded(CheckGlobalVar(&export_->var, &global, nullptr))) { if (global->mutable_) { PrintError(&export_->var.loc, "mutable globals cannot be exported"); } @@ -813,7 +855,7 @@ void Validator::CheckDuplicateExportBindings(const Module* module) { }); } -void Validator::CheckModule(const Module* module) { +Result Validator::CheckModule(const Module* module) { bool seen_start = false; current_module_ = module; @@ -821,32 +863,34 @@ void Validator::CheckModule(const Module* module) { current_memory_index_ = 0; current_global_index_ = 0; num_imported_globals_ = 0; + current_except_index_ = 0; - for (ModuleField* field = module->first_field; field; field = field->next) { - switch (field->type) { + for (const ModuleField& field : module->fields) { + switch (field.type) { case ModuleFieldType::Except: - // TODO(karlschimpf) Define. - PrintError(&field->loc, "except clause: don't know how to validate"); + ++current_except_index_; + CheckExcept(&field.loc, cast(&field)->except); break; + case ModuleFieldType::Func: - CheckFunc(&field->loc, field->func); + CheckFunc(&field.loc, cast(&field)->func); break; case ModuleFieldType::Global: - CheckGlobal(&field->loc, field->global); + CheckGlobal(&field.loc, cast(&field)->global); current_global_index_++; break; case ModuleFieldType::Import: - CheckImport(&field->loc, field->import); + CheckImport(&field.loc, cast(&field)->import); break; case ModuleFieldType::Export: - CheckExport(&field->loc, field->export_); + CheckExport(&field.loc, cast(&field)->export_); break; case ModuleFieldType::Table: - CheckTable(&field->loc, field->table); + CheckTable(&field.loc, cast(&field)->table); current_table_index_++; break; @@ -855,7 +899,7 @@ void Validator::CheckModule(const Module* module) { break; case ModuleFieldType::Memory: - CheckMemory(&field->loc, field->memory); + CheckMemory(&field.loc, cast(&field)->memory); current_memory_index_++; break; @@ -868,18 +912,18 @@ void Validator::CheckModule(const Module* module) { case ModuleFieldType::Start: { if (seen_start) { - PrintError(&field->loc, "only one start function allowed"); + PrintError(&field.loc, "only one start function allowed"); } const Func* start_func = nullptr; - CheckFuncVar(&field->start, &start_func); + CheckFuncVar(&cast(&field)->start, &start_func); if (start_func) { if (start_func->GetNumParams() != 0) { - PrintError(&field->loc, "start function must be nullary"); + PrintError(&field.loc, "start function must be nullary"); } if (start_func->GetNumResults() != 0) { - PrintError(&field->loc, "start function must not return anything"); + PrintError(&field.loc, "start function must not return anything"); } } seen_start = true; @@ -891,6 +935,8 @@ void Validator::CheckModule(const Module* module) { CheckElemSegments(module); CheckDataSegments(module); CheckDuplicateExportBindings(module); + + return result_; } // Returns the result type of the invoked function, checked by the caller; @@ -906,8 +952,8 @@ const TypeVector* Validator::CheckInvoke(const Action* action) { const Export* export_ = module->GetExport(action->name); if (!export_) { - PrintError(&action->loc, "unknown function export \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG(action->name)); + PrintError(&action->loc, "unknown function export \"%s\"", + action->name.c_str()); return nullptr; } @@ -944,8 +990,8 @@ Result Validator::CheckGet(const Action* action, Type* out_type) { const Export* export_ = module->GetExport(action->name); if (!export_) { - PrintError(&action->loc, "unknown global export \"" PRIstringslice "\"", - WABT_PRINTF_STRING_SLICE_ARG(action->name)); + PrintError(&action->loc, "unknown global export \"%s\"", + action->name.c_str()); return Result::Error; } @@ -959,9 +1005,35 @@ Result Validator::CheckGet(const Action* action, Type* out_type) { return Result::Ok; } +Result Validator::CheckExceptVar(const Var* var, const Exception** out_except) { + Index index; + if (Failed( + CheckVar(current_module_->excepts.size(), var, "except", &index))) { + return Result::Error; + } + if (out_except) + *out_except = current_module_->excepts[index]; + return Result::Ok; +} + +void Validator::CheckExcept(const Location* loc, const Exception* except) { + for (Type ty : except->sig) { + switch (ty) { + case Type::I32: + case Type::I64: + case Type::F32: + case Type::F64: + break; + default: + PrintError(loc, "Invalid exception type: %s", GetTypeName(ty)); + break; + } + } +} + Validator::ActionResult Validator::CheckAction(const Action* action) { ActionResult result; - WABT_ZERO_MEMORY(result); + ZeroMemory(result); switch (action->type) { case ActionType::Invoke: @@ -971,7 +1043,7 @@ Validator::ActionResult Validator::CheckAction(const Action* action) { break; case ActionType::Get: - if (WABT_SUCCEEDED(CheckGet(action, &result.type))) + if (Succeeded(CheckGet(action, &result.type))) result.kind = ActionResult::Kind::Type; else result.kind = ActionResult::Kind::Error; @@ -1006,35 +1078,35 @@ void Validator::CheckAssertReturnNanCommand(const Action* action) { void Validator::CheckCommand(const Command* command) { switch (command->type) { case CommandType::Module: - CheckModule(command->module); + CheckModule(cast(command)->module); break; case CommandType::Action: // Ignore result type. - CheckAction(command->action); + CheckAction(cast(command)->action); break; case CommandType::Register: case CommandType::AssertMalformed: case CommandType::AssertInvalid: - case CommandType::AssertInvalidNonBinary: case CommandType::AssertUnlinkable: case CommandType::AssertUninstantiable: // Ignore. break; case CommandType::AssertReturn: { - const Action* action = command->assert_return.action; + auto* assert_return_command = cast(command); + const Action* action = assert_return_command->action; ActionResult result = CheckAction(action); switch (result.kind) { case ActionResult::Kind::Types: CheckConstTypes(&action->loc, *result.types, - *command->assert_return.expected, "action"); + *assert_return_command->expected, "action"); break; case ActionResult::Kind::Type: CheckConstType(&action->loc, result.type, - *command->assert_return.expected, "action"); + *assert_return_command->expected, "action"); break; case ActionResult::Kind::Error: @@ -1045,17 +1117,22 @@ void Validator::CheckCommand(const Command* command) { } case CommandType::AssertReturnCanonicalNan: - CheckAssertReturnNanCommand(command->assert_return_canonical_nan.action); + CheckAssertReturnNanCommand( + cast(command)->action); break; case CommandType::AssertReturnArithmeticNan: - CheckAssertReturnNanCommand(command->assert_return_arithmetic_nan.action); + CheckAssertReturnNanCommand( + cast(command)->action); break; case CommandType::AssertTrap: + // ignore result type. + CheckAction(cast(command)->action); + break; case CommandType::AssertExhaustion: // ignore result type. - CheckAction(command->assert_trap.action); + CheckAction(cast(command)->action); break; } } @@ -1066,14 +1143,22 @@ Result Validator::CheckScript(const Script* script) { return result_; } -} // namespace +} // end anonymous namespace -Result validate_script(WastLexer* lexer, - const Script* script, - SourceErrorHandler* error_handler) { +Result ValidateScript(WastLexer* lexer, + const Script* script, + ErrorHandler* error_handler) { Validator validator(error_handler, lexer, script); return validator.CheckScript(script); } +Result ValidateModule(WastLexer* lexer, + const Module* module, + ErrorHandler* error_handler) { + Validator validator(error_handler, lexer, nullptr); + + return validator.CheckModule(module); +} + } // namespace wabt diff --git a/lib/wabt/src/validator.h b/lib/wabt/src/validator.h index fc0ccf1b665..bcb5b10f826 100644 --- a/lib/wabt/src/validator.h +++ b/lib/wabt/src/validator.h @@ -23,11 +23,12 @@ namespace wabt { struct Module; struct Script; -class SourceErrorHandler; +class ErrorHandler; // Perform all checks on the script. It is valid if and only if this function // succeeds. -Result validate_script(WastLexer*, const Script*, SourceErrorHandler*); +Result ValidateScript(WastLexer*, const Script*, ErrorHandler*); +Result ValidateModule(WastLexer*, const Module*, ErrorHandler*); } // namespace wabt diff --git a/lib/wabt/src/wabt.post.js b/lib/wabt/src/wabt.post.js index bca6efa25cb..d7270a5e6c0 100644 --- a/lib/wabt/src/wabt.post.js +++ b/lib/wabt/src/wabt.post.js @@ -119,44 +119,33 @@ OutputBuffer.prototype.destroy = function() { }; -/// SourceErrorHandler -function SourceErrorHandler() { - this.addr = Module._wabt_new_source_error_handler_buffer(); -} -SourceErrorHandler.prototype = Object.create(Object.prototype); - -SourceErrorHandler.prototype.getMessage = function() { - var addr = Module._wabt_source_error_handler_buffer_get_data(this.addr); - var size = Module._wabt_source_error_handler_buffer_get_size(this.addr); - return Module.Pointer_stringify(addr, size); -} - -SourceErrorHandler.prototype.destroy = function() { - Module._wabt_destroy_source_error_handler_buffer(this.addr); -}; - - -/// BinaryErrorHandler -function BinaryErrorHandler() { - this.addr = Module._wabt_new_binary_error_handler_buffer(); +/// ErrorHandler +function ErrorHandler(kind) { + if (kind == 'text') { + this.addr = Module._wabt_new_text_error_handler_buffer(); + } else if (kind == 'binary') { + this.addr = Module._wabt_new_binary_error_handler_buffer(); + } else { + throw new Error('Invalid ErrorHandler kind: ' + kind); + } } -BinaryErrorHandler.prototype = Object.create(Object.prototype); +ErrorHandler.prototype = Object.create(Object.prototype); -BinaryErrorHandler.prototype.getMessage = function() { - var addr = Module._wabt_binary_error_handler_buffer_get_data(this.addr); - var size = Module._wabt_binary_error_handler_buffer_get_size(this.addr); +ErrorHandler.prototype.getMessage = function() { + var addr = Module._wabt_error_handler_buffer_get_data(this.addr); + var size = Module._wabt_error_handler_buffer_get_size(this.addr); return Module.Pointer_stringify(addr, size); } -BinaryErrorHandler.prototype.destroy = function() { - Module._wabt_destroy_binary_error_handler_buffer(this.addr); +ErrorHandler.prototype.destroy = function() { + Module._wabt_destroy_error_handler_buffer(this.addr); }; /// parseWast function parseWast(filename, buffer) { var lexer = new Lexer(filename, buffer); - var errorHandler = new SourceErrorHandler(); + var errorHandler = new ErrorHandler('text'); try { var parseResult_addr = @@ -187,7 +176,7 @@ function parseWast(filename, buffer) { // readWasm function readWasm(buffer, options) { var bufferObj = allocateBuffer(buffer); - var errorHandler = new BinaryErrorHandler(); + var errorHandler = new ErrorHandler('binary'); var readDebugNames = booleanOrDefault(options.readDebugNames, false); try { @@ -220,7 +209,7 @@ function WasmScript(lexer, script_addr) { WasmScript.prototype = Object.create(Object.prototype); WasmScript.prototype.resolveNames = function() { - var errorHandler = new SourceErrorHandler(); + var errorHandler = new ErrorHandler('text'); try { var result = Module._wabt_resolve_names_script( this.lexer.addr, this.script_addr, errorHandler.addr); @@ -233,7 +222,7 @@ WasmScript.prototype.resolveNames = function() { }; WasmScript.prototype.validate = function() { - var errorHandler = new SourceErrorHandler(); + var errorHandler = new ErrorHandler('text'); try { var result = Module._wabt_validate_script( this.lexer.addr, this.script_addr, errorHandler.addr); @@ -350,10 +339,17 @@ WasmModule.prototype.destroy = function() { Module._wabt_destroy_module(this.module_addr); }; -return { +var exports = { ready: Promise.resolve(), parseWast: parseWast, readWasm: readWasm, }; +if (typeof module !== "undefined" && module && module.exports) + module.exports = exports; +else if (typeof define === "function" && define.amd) + define(function() { return exports; }); +else + (typeof global !== "undefined" && global || typeof window !== "undefined" && window || this).wabt = exports; + })(); // Call IIFE from wabt.pre.js. diff --git a/lib/wabt/src/wabt.pre.js b/lib/wabt/src/wabt.pre.js index e53f9182acd..5cc41d0b194 100644 --- a/lib/wabt/src/wabt.pre.js +++ b/lib/wabt/src/wabt.pre.js @@ -14,5 +14,5 @@ * limitations under the License. */ -var wabt = (function() { +(function() { "use strict"; diff --git a/lib/wabt/src/wasm-link.h b/lib/wabt/src/wasm-link.h index 86cdecb5d83..c1509802c4d 100644 --- a/lib/wabt/src/wasm-link.h +++ b/lib/wabt/src/wasm-link.h @@ -29,8 +29,8 @@ namespace link { class LinkerInputBinary; struct FunctionImport { - StringSlice module_name; - StringSlice name; + std::string module_name; + std::string name; Index sig_index; bool active; /* Is this import present in the linked binary */ Index relocated_function_index; @@ -39,8 +39,8 @@ struct FunctionImport { }; struct GlobalImport { - StringSlice module_name; - StringSlice name; + std::string module_name; + std::string name; Type type; bool mutable_; }; @@ -54,15 +54,10 @@ struct DataSegment { struct Export { ExternalKind kind; - StringSlice name; + std::string name; Index index; }; -struct SectionDataCustom { - /* Reference to string data stored in the containing InputBinary */ - StringSlice name; -}; - struct Section { WABT_DISALLOW_COPY_AND_ASSIGN(Section); Section(); @@ -83,8 +78,6 @@ struct Section { Index count; union { - /* CUSTOM section data */ - SectionDataCustom custom; /* DATA section data */ std::vector* data_segments; /* MEMORY section data */ @@ -101,8 +94,7 @@ typedef std::vector SectionPtrVector; class LinkerInputBinary { public: WABT_DISALLOW_COPY_AND_ASSIGN(LinkerInputBinary); - LinkerInputBinary(const char* filename, uint8_t* data, size_t size); - ~LinkerInputBinary(); + LinkerInputBinary(const char* filename, const std::vector& data); Index RelocateFuncIndex(Index findex); Index RelocateTypeIndex(Index index); @@ -113,8 +105,7 @@ class LinkerInputBinary { bool IsInactiveFunctionImport(Index index); const char* filename; - uint8_t* data; - size_t size; + std::vector data; std::vector> sections; std::vector exports; diff --git a/lib/wabt/src/wast-lexer.cc b/lib/wabt/src/wast-lexer.cc index bf1bb138a71..05cdd60e846 100644 --- a/lib/wabt/src/wast-lexer.cc +++ b/lib/wabt/src/wast-lexer.cc @@ -21,39 +21,23 @@ #include "config.h" +#include "circular-array.h" +#include "error-handler.h" #include "lexer-source.h" #include "wast-parser.h" -#include "wast-parser-lexer-shared.h" - -/* must be included after so some typedefs will be defined */ -#include "wast-parser-gen.hh" /*!max:re2c */ #define INITIAL_LEXER_BUFFER_SIZE (64 * 1024) -#define YY_USER_ACTION \ - { \ - loc->filename = filename_; \ - loc->line = line_; \ - loc->first_column = COLUMN(token_); \ - loc->last_column = COLUMN(cursor_); \ - } - -#define RETURN(name) \ - YY_USER_ACTION; \ - return WABT_TOKEN_TYPE_##name - -#define ERROR(...) \ - YY_USER_ACTION; \ - wast_parser_error(loc, this, parser, __VA_ARGS__) +#define ERROR(...) parser->Error(GetLocation(), __VA_ARGS__) #define BEGIN(c) cond = (c) -#define FILL(n) \ - do { \ - if (WABT_FAILED(Fill(loc, parser, (n)))) { \ - RETURN(EOF); \ - } \ +#define FILL(n) \ + do { \ + if (Failed(Fill((n)))) { \ + RETURN(Eof); \ + } \ } while (0) #define MAYBE_MALFORMED_UTF8(desc) \ @@ -62,8 +46,8 @@ } \ continue -#define yytext (token_) -#define yyleng (cursor_ - token_) +#define yytext (next_pos_) +#define yyleng (cursor_ - next_pos_) /* p must be a pointer somewhere in the lexer buffer */ #define FILE_OFFSET(p) ((p) - (buffer_) + buffer_file_offset_) @@ -76,25 +60,167 @@ line_file_offset_ = FILE_OFFSET(cursor_); \ } while (0) -#define TEXT \ - lval->text.start = yytext; \ - lval->text.length = yyleng +#define RETURN(token) return Token(GetLocation(), TokenType::token); -#define TEXT_AT(offset) \ - lval->text.start = yytext + offset; \ - lval->text.length = yyleng - offset +#define RETURN_LITERAL(token, literal) \ + return Token(GetLocation(), TokenType::token, \ + MakeLiteral(LiteralType::literal)) -#define TYPE(type_) lval->type = Type::type_ +#define RETURN_TYPE(token, type) \ + return Token(GetLocation(), TokenType::token, Type::type) -#define OPCODE(name) lval->opcode = Opcode::name +#define RETURN_OPCODE0(token) \ + return Token(GetLocation(), TokenType::token, Opcode::token) -#define LITERAL(type_) \ - lval->literal.type = LiteralType::type_; \ - lval->literal.text.start = yytext; \ - lval->literal.text.length = yyleng +#define RETURN_OPCODE(token, opcode) \ + return Token(GetLocation(), TokenType::token, Opcode::opcode) + +#define RETURN_TEXT(token) \ + return Token(GetLocation(), TokenType::token, GetText()) + +#define RETURN_TEXT_AT(token, at) \ + return Token(GetLocation(), TokenType::token, GetText(at)) namespace wabt { +const char* GetTokenTypeName(TokenType token_type) { + static const char* s_names[] = { + "Invalid", + "Reserved", + "EOF", + "(", + ")", + "NAT", + "INT", + "FLOAT", + "TEXT", + "VAR", + "VALUETYPE", + "anyfunc", + "mut", + "nop", + "drop", + "block", + "end", + "if", + "then", + "else", + "loop", + "br", + "br_if", + "br_table", + "try", + "catch", + "catch_all", + "throw", + "rethrow", + "call", + "call_indirect", + "return", + "get_local", + "set_local", + "tee_local", + "get_global", + "set_global", + "LOAD", + "STORE", + "offset=", + "align=", + "CONST", + "UNARY", + "BINARY", + "COMPARE", + "CONVERT", + "select", + "unreachable", + "current_memory", + "grow_memory", + "func", + "start", + "type", + "param", + "result", + "local", + "global", + "table", + "elem", + "memory", + "data", + "offset", + "import", + "export", + "except", + "module", + "bin", + "quote", + "register", + "invoke", + "get", + "assert_malformed", + "assert_invalid", + "assert_unlinkable", + "assert_return", + "assert_return_canonical_nan", + "assert_return_arithmetic_nan", + "assert_trap", + "assert_exhaustion", + }; + + static_assert( + WABT_ARRAY_SIZE(s_names) == WABT_ENUM_COUNT(TokenType), + "Expected TokenType names list length to match number of TokenTypes."); + + int x = static_cast(token_type); + if (x < WABT_ENUM_COUNT(TokenType)) + return s_names[x]; + + return "Invalid"; +} + +Token::Token(Location loc, TokenType token_type) + : loc(loc), token_type(token_type) {} + +Token::Token(Location loc, TokenType token_type, Type type) + : loc(loc), token_type(token_type), type(type) {} + +Token::Token(Location loc, TokenType token_type, StringTerminal text) + : loc(loc), token_type(token_type), text(text) {} + +Token::Token(Location loc, TokenType token_type, Opcode opcode) + : loc(loc), token_type(token_type), opcode(opcode) {} + +Token::Token(Location loc, TokenType token_type, LiteralTerminal literal) + : loc(loc), token_type(token_type), literal(literal) {} + +std::string Token::to_string() const { + switch (token_type) { + case TokenType::Nat: + case TokenType::Int: + case TokenType::Float: + return literal.text.to_string(); + + case TokenType::Reserved: + case TokenType::Text: + case TokenType::Var: + return text.to_string(); + + case TokenType::ValueType: + return GetTypeName(type); + + case TokenType::Load: + case TokenType::Store: + case TokenType::Const: + case TokenType::Unary: + case TokenType::Binary: + case TokenType::Compare: + case TokenType::Convert: + return opcode.GetName(); + + default: + return GetTokenTypeName(token_type); + } +} + WastLexer::WastLexer(std::unique_ptr source, const char* filename) : source_(std::move(source)), line_finder_(source_->Clone()), @@ -107,7 +233,7 @@ WastLexer::WastLexer(std::unique_ptr source, const char* filename) buffer_(nullptr), buffer_size_(0), marker_(nullptr), - token_(nullptr), + next_pos_(nullptr), cursor_(nullptr), limit_(nullptr) {} @@ -129,10 +255,22 @@ std::unique_ptr WastLexer::CreateBufferLexer(const char* filename, return std::unique_ptr(new WastLexer(std::move(source), filename)); } -Result WastLexer::Fill(Location* loc, WastParser* parser, size_t need) { +Location WastLexer::GetLocation() { + return Location(filename_, line_, COLUMN(next_pos_), COLUMN(cursor_)); +} + +LiteralTerminal WastLexer::MakeLiteral(LiteralType type) { + return LiteralTerminal(type, GetText()); +} + +StringTerminal WastLexer::GetText(size_t offset) { + return StringTerminal(yytext + offset, yyleng - offset); +} + +Result WastLexer::Fill(size_t need) { if (eof_) return Result::Error; - size_t free = token_ - buffer_; + size_t free = next_pos_ - buffer_; assert(static_cast(cursor_ - buffer_) >= free); // Our buffer is too small, need to realloc. if (free < need) { @@ -147,11 +285,11 @@ Result WastLexer::Fill(Location* loc, WastParser* parser, size_t need) { new_buffer_size *= 2; char* new_buffer = new char[new_buffer_size]; - if (limit_ > token_) - memmove(new_buffer, token_, limit_ - token_); + if (limit_ > next_pos_) + memmove(new_buffer, next_pos_, limit_ - next_pos_); buffer_ = new_buffer; buffer_size_ = new_buffer_size; - token_ = new_buffer + (token_ - old_buffer) - free; + next_pos_ = new_buffer + (next_pos_ - old_buffer) - free; marker_ = new_buffer + (marker_ - old_buffer) - free; cursor_ = new_buffer + (cursor_ - old_buffer) - free; limit_ = new_buffer + (limit_ - old_buffer) - free; @@ -160,9 +298,9 @@ Result WastLexer::Fill(Location* loc, WastParser* parser, size_t need) { delete[] old_buffer; } else { // Shift everything down to make more room in the buffer. - if (limit_ > token_) - memmove(buffer_, token_, limit_ - token_); - token_ -= free; + if (limit_ > next_pos_) + memmove(buffer_, next_pos_, limit_ - next_pos_); + next_pos_ -= free; marker_ -= free; cursor_ -= free; limit_ -= free; @@ -183,17 +321,12 @@ Result WastLexer::Fill(Location* loc, WastParser* parser, size_t need) { return Result::Ok; } -int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { - enum { - YYCOND_INIT, - YYCOND_BAD_TEXT, - YYCOND_LINE_COMMENT, - YYCOND_BLOCK_COMMENT, - YYCOND_i = YYCOND_INIT, - } cond = YYCOND_INIT; +Token WastLexer::GetToken(WastParser* parser) { + /*!types:re2c*/ + YYCONDTYPE cond = YYCOND_i; // i is the initial state. for (;;) { - token_ = cursor_; + next_pos_ = cursor_; /*!re2c re2c:condprefix = YYCOND_; re2c:condenumprefix = YYCOND_; @@ -208,37 +341,40 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { digit = [0-9]; hexdigit = [0-9a-fA-F]; - num = digit+; - hexnum = hexdigit+; + num = digit ("_"? digit)*; + hexnum = hexdigit ("_"? hexdigit)*; letter = [a-zA-Z]; - symbol = [+\-*\/\\\^~=<>!?@#$%&|:`.']; + symbol = [+\-*\\/^~=<>!?@#$%&|:`.']; character = [^"\\\x00-\x1f] | "\\" [nrt\\'"] | "\\" hexdigit hexdigit; sign = [+-]; nat = num | "0x" hexnum; int = sign nat; - hexfloat = sign? "0x" hexnum ("." hexdigit*)? "p" sign? num; + frac = num; + hexfrac = hexnum; + hexfloat = sign? "0x" hexnum "." hexfrac? + | sign? "0x" hexnum ("." hexfrac?)? [pP] sign? num; infinity = sign? "inf"; nan = sign? "nan" | sign? "nan:0x" hexnum; - float = sign? num "." digit* - | sign? num ("." digit*)? [eE] sign? num; + float = sign? num "." frac? + | sign? num ("." frac?)? [eE] sign? num; text = '"' character* '"'; name = "$" (letter | digit | "_" | symbol)+; // Should be ([\x21-\x7e] \ [()"; ])+ , but re2c doesn't like this... - reserved = [\x21\x23-\x27\x2a-\x3a\x3c-\x7e]+; - - "(" { RETURN(LPAR); } - ")" { RETURN(RPAR); } - nat { LITERAL(Int); RETURN(NAT); } - int { LITERAL(Int); RETURN(INT); } - float { LITERAL(Float); RETURN(FLOAT); } - hexfloat { LITERAL(Hexfloat); RETURN(FLOAT); } - infinity { LITERAL(Infinity); RETURN(FLOAT); } - nan { LITERAL(Nan); RETURN(FLOAT); } - text { TEXT; RETURN(TEXT); } + reserved = [\x21\x23-\x27\x2a-\x3a\x3c-\x7e]+; + + "(" { RETURN(Lpar); } + ")" { RETURN(Rpar); } + nat { RETURN_LITERAL(Nat, Int); } + int { RETURN_LITERAL(Int, Int); } + float { RETURN_LITERAL(Float, Float); } + hexfloat { RETURN_LITERAL(Float, Hexfloat); } + infinity { RETURN_LITERAL(Float, Infinity); } + nan { RETURN_LITERAL(Float, Nan); } + text { RETURN_TEXT(Text); } '"' => BAD_TEXT { continue; } character { continue; } "\n" => i { ERROR("newline in string"); @@ -247,246 +383,250 @@ int WastLexer::GetToken(Token* lval, Location* loc, WastParser* parser) { "\\". { ERROR("bad escape \"%.*s\"", static_cast(yyleng), yytext); continue; } - '"' => i { TEXT; RETURN(TEXT); } + '"' => i { RETURN_TEXT(Text); } [^] { ERROR("illegal character in string"); continue; } * { MAYBE_MALFORMED_UTF8(" in string"); } - "i32" { TYPE(I32); RETURN(VALUE_TYPE); } - "i64" { TYPE(I64); RETURN(VALUE_TYPE); } - "f32" { TYPE(F32); RETURN(VALUE_TYPE); } - "f64" { TYPE(F64); RETURN(VALUE_TYPE); } - "anyfunc" { RETURN(ANYFUNC); } - "mut" { RETURN(MUT); } - "nop" { RETURN(NOP); } - "block" { RETURN(BLOCK); } - "if" { RETURN(IF); } - "then" { RETURN(THEN); } - "else" { RETURN(ELSE); } - "loop" { RETURN(LOOP); } - "br" { RETURN(BR); } - "br_if" { RETURN(BR_IF); } - "br_table" { RETURN(BR_TABLE); } - "call" { RETURN(CALL); } - "call_indirect" { RETURN(CALL_INDIRECT); } - "drop" { RETURN(DROP); } - "end" { RETURN(END); } - "return" { RETURN(RETURN); } - "get_local" { RETURN(GET_LOCAL); } - "set_local" { RETURN(SET_LOCAL); } - "tee_local" { RETURN(TEE_LOCAL); } - "get_global" { RETURN(GET_GLOBAL); } - "set_global" { RETURN(SET_GLOBAL); } - "i32.load" { OPCODE(I32Load); RETURN(LOAD); } - "i64.load" { OPCODE(I64Load); RETURN(LOAD); } - "f32.load" { OPCODE(F32Load); RETURN(LOAD); } - "f64.load" { OPCODE(F64Load); RETURN(LOAD); } - "i32.store" { OPCODE(I32Store); RETURN(STORE); } - "i64.store" { OPCODE(I64Store); RETURN(STORE); } - "f32.store" { OPCODE(F32Store); RETURN(STORE); } - "f64.store" { OPCODE(F64Store); RETURN(STORE); } - "i32.load8_s" { OPCODE(I32Load8S); RETURN(LOAD); } - "i64.load8_s" { OPCODE(I64Load8S); RETURN(LOAD); } - "i32.load8_u" { OPCODE(I32Load8U); RETURN(LOAD); } - "i64.load8_u" { OPCODE(I64Load8U); RETURN(LOAD); } - "i32.load16_s" { OPCODE(I32Load16S); RETURN(LOAD); } - "i64.load16_s" { OPCODE(I64Load16S); RETURN(LOAD); } - "i32.load16_u" { OPCODE(I32Load16U); RETURN(LOAD); } - "i64.load16_u" { OPCODE(I64Load16U); RETURN(LOAD); } - "i64.load32_s" { OPCODE(I64Load32S); RETURN(LOAD); } - "i64.load32_u" { OPCODE(I64Load32U); RETURN(LOAD); } - "i32.store8" { OPCODE(I32Store8); RETURN(STORE); } - "i64.store8" { OPCODE(I64Store8); RETURN(STORE); } - "i32.store16" { OPCODE(I32Store16); RETURN(STORE); } - "i64.store16" { OPCODE(I64Store16); RETURN(STORE); } - "i64.store32" { OPCODE(I64Store32); RETURN(STORE); } - "offset=" nat { TEXT_AT(7); RETURN(OFFSET_EQ_NAT); } - "align=" nat { TEXT_AT(6); RETURN(ALIGN_EQ_NAT); } - "i32.const" { TYPE(I32); RETURN(CONST); } - "i64.const" { TYPE(I64); RETURN(CONST); } - "f32.const" { TYPE(F32); RETURN(CONST); } - "f64.const" { TYPE(F64); RETURN(CONST); } - "i32.eqz" { OPCODE(I32Eqz); RETURN(CONVERT); } - "i64.eqz" { OPCODE(I64Eqz); RETURN(CONVERT); } - "i32.clz" { OPCODE(I32Clz); RETURN(UNARY); } - "i64.clz" { OPCODE(I64Clz); RETURN(UNARY); } - "i32.ctz" { OPCODE(I32Ctz); RETURN(UNARY); } - "i64.ctz" { OPCODE(I64Ctz); RETURN(UNARY); } - "i32.popcnt" { OPCODE(I32Popcnt); RETURN(UNARY); } - "i64.popcnt" { OPCODE(I64Popcnt); RETURN(UNARY); } - "f32.neg" { OPCODE(F32Neg); RETURN(UNARY); } - "f64.neg" { OPCODE(F64Neg); RETURN(UNARY); } - "f32.abs" { OPCODE(F32Abs); RETURN(UNARY); } - "f64.abs" { OPCODE(F64Abs); RETURN(UNARY); } - "f32.sqrt" { OPCODE(F32Sqrt); RETURN(UNARY); } - "f64.sqrt" { OPCODE(F64Sqrt); RETURN(UNARY); } - "f32.ceil" { OPCODE(F32Ceil); RETURN(UNARY); } - "f64.ceil" { OPCODE(F64Ceil); RETURN(UNARY); } - "f32.floor" { OPCODE(F32Floor); RETURN(UNARY); } - "f64.floor" { OPCODE(F64Floor); RETURN(UNARY); } - "f32.trunc" { OPCODE(F32Trunc); RETURN(UNARY); } - "f64.trunc" { OPCODE(F64Trunc); RETURN(UNARY); } - "f32.nearest" { OPCODE(F32Nearest); RETURN(UNARY); } - "f64.nearest" { OPCODE(F64Nearest); RETURN(UNARY); } - "i32.add" { OPCODE(I32Add); RETURN(BINARY); } - "i64.add" { OPCODE(I64Add); RETURN(BINARY); } - "i32.sub" { OPCODE(I32Sub); RETURN(BINARY); } - "i64.sub" { OPCODE(I64Sub); RETURN(BINARY); } - "i32.mul" { OPCODE(I32Mul); RETURN(BINARY); } - "i64.mul" { OPCODE(I64Mul); RETURN(BINARY); } - "i32.div_s" { OPCODE(I32DivS); RETURN(BINARY); } - "i64.div_s" { OPCODE(I64DivS); RETURN(BINARY); } - "i32.div_u" { OPCODE(I32DivU); RETURN(BINARY); } - "i64.div_u" { OPCODE(I64DivU); RETURN(BINARY); } - "i32.rem_s" { OPCODE(I32RemS); RETURN(BINARY); } - "i64.rem_s" { OPCODE(I64RemS); RETURN(BINARY); } - "i32.rem_u" { OPCODE(I32RemU); RETURN(BINARY); } - "i64.rem_u" { OPCODE(I64RemU); RETURN(BINARY); } - "i32.and" { OPCODE(I32And); RETURN(BINARY); } - "i64.and" { OPCODE(I64And); RETURN(BINARY); } - "i32.or" { OPCODE(I32Or); RETURN(BINARY); } - "i64.or" { OPCODE(I64Or); RETURN(BINARY); } - "i32.xor" { OPCODE(I32Xor); RETURN(BINARY); } - "i64.xor" { OPCODE(I64Xor); RETURN(BINARY); } - "i32.shl" { OPCODE(I32Shl); RETURN(BINARY); } - "i64.shl" { OPCODE(I64Shl); RETURN(BINARY); } - "i32.shr_s" { OPCODE(I32ShrS); RETURN(BINARY); } - "i64.shr_s" { OPCODE(I64ShrS); RETURN(BINARY); } - "i32.shr_u" { OPCODE(I32ShrU); RETURN(BINARY); } - "i64.shr_u" { OPCODE(I64ShrU); RETURN(BINARY); } - "i32.rotl" { OPCODE(I32Rotl); RETURN(BINARY); } - "i64.rotl" { OPCODE(I64Rotl); RETURN(BINARY); } - "i32.rotr" { OPCODE(I32Rotr); RETURN(BINARY); } - "i64.rotr" { OPCODE(I64Rotr); RETURN(BINARY); } - "f32.add" { OPCODE(F32Add); RETURN(BINARY); } - "f64.add" { OPCODE(F64Add); RETURN(BINARY); } - "f32.sub" { OPCODE(F32Sub); RETURN(BINARY); } - "f64.sub" { OPCODE(F64Sub); RETURN(BINARY); } - "f32.mul" { OPCODE(F32Mul); RETURN(BINARY); } - "f64.mul" { OPCODE(F64Mul); RETURN(BINARY); } - "f32.div" { OPCODE(F32Div); RETURN(BINARY); } - "f64.div" { OPCODE(F64Div); RETURN(BINARY); } - "f32.min" { OPCODE(F32Min); RETURN(BINARY); } - "f64.min" { OPCODE(F64Min); RETURN(BINARY); } - "f32.max" { OPCODE(F32Max); RETURN(BINARY); } - "f64.max" { OPCODE(F64Max); RETURN(BINARY); } - "f32.copysign" { OPCODE(F32Copysign); RETURN(BINARY); } - "f64.copysign" { OPCODE(F64Copysign); RETURN(BINARY); } - "i32.eq" { OPCODE(I32Eq); RETURN(COMPARE); } - "i64.eq" { OPCODE(I64Eq); RETURN(COMPARE); } - "i32.ne" { OPCODE(I32Ne); RETURN(COMPARE); } - "i64.ne" { OPCODE(I64Ne); RETURN(COMPARE); } - "i32.lt_s" { OPCODE(I32LtS); RETURN(COMPARE); } - "i64.lt_s" { OPCODE(I64LtS); RETURN(COMPARE); } - "i32.lt_u" { OPCODE(I32LtU); RETURN(COMPARE); } - "i64.lt_u" { OPCODE(I64LtU); RETURN(COMPARE); } - "i32.le_s" { OPCODE(I32LeS); RETURN(COMPARE); } - "i64.le_s" { OPCODE(I64LeS); RETURN(COMPARE); } - "i32.le_u" { OPCODE(I32LeU); RETURN(COMPARE); } - "i64.le_u" { OPCODE(I64LeU); RETURN(COMPARE); } - "i32.gt_s" { OPCODE(I32GtS); RETURN(COMPARE); } - "i64.gt_s" { OPCODE(I64GtS); RETURN(COMPARE); } - "i32.gt_u" { OPCODE(I32GtU); RETURN(COMPARE); } - "i64.gt_u" { OPCODE(I64GtU); RETURN(COMPARE); } - "i32.ge_s" { OPCODE(I32GeS); RETURN(COMPARE); } - "i64.ge_s" { OPCODE(I64GeS); RETURN(COMPARE); } - "i32.ge_u" { OPCODE(I32GeU); RETURN(COMPARE); } - "i64.ge_u" { OPCODE(I64GeU); RETURN(COMPARE); } - "f32.eq" { OPCODE(F32Eq); RETURN(COMPARE); } - "f64.eq" { OPCODE(F64Eq); RETURN(COMPARE); } - "f32.ne" { OPCODE(F32Ne); RETURN(COMPARE); } - "f64.ne" { OPCODE(F64Ne); RETURN(COMPARE); } - "f32.lt" { OPCODE(F32Lt); RETURN(COMPARE); } - "f64.lt" { OPCODE(F64Lt); RETURN(COMPARE); } - "f32.le" { OPCODE(F32Le); RETURN(COMPARE); } - "f64.le" { OPCODE(F64Le); RETURN(COMPARE); } - "f32.gt" { OPCODE(F32Gt); RETURN(COMPARE); } - "f64.gt" { OPCODE(F64Gt); RETURN(COMPARE); } - "f32.ge" { OPCODE(F32Ge); RETURN(COMPARE); } - "f64.ge" { OPCODE(F64Ge); RETURN(COMPARE); } - "i64.extend_s/i32" { OPCODE(I64ExtendSI32); RETURN(CONVERT); } - "i64.extend_u/i32" { OPCODE(I64ExtendUI32); RETURN(CONVERT); } - "i32.wrap/i64" { OPCODE(I32WrapI64); RETURN(CONVERT); } - "i32.trunc_s/f32" { OPCODE(I32TruncSF32); RETURN(CONVERT); } - "i64.trunc_s/f32" { OPCODE(I64TruncSF32); RETURN(CONVERT); } - "i32.trunc_s/f64" { OPCODE(I32TruncSF64); RETURN(CONVERT); } - "i64.trunc_s/f64" { OPCODE(I64TruncSF64); RETURN(CONVERT); } - "i32.trunc_u/f32" { OPCODE(I32TruncUF32); RETURN(CONVERT); } - "i64.trunc_u/f32" { OPCODE(I64TruncUF32); RETURN(CONVERT); } - "i32.trunc_u/f64" { OPCODE(I32TruncUF64); RETURN(CONVERT); } - "i64.trunc_u/f64" { OPCODE(I64TruncUF64); RETURN(CONVERT); } - "f32.convert_s/i32" { OPCODE(F32ConvertSI32); RETURN(CONVERT); } - "f64.convert_s/i32" { OPCODE(F64ConvertSI32); RETURN(CONVERT); } - "f32.convert_s/i64" { OPCODE(F32ConvertSI64); RETURN(CONVERT); } - "f64.convert_s/i64" { OPCODE(F64ConvertSI64); RETURN(CONVERT); } - "f32.convert_u/i32" { OPCODE(F32ConvertUI32); RETURN(CONVERT); } - "f64.convert_u/i32" { OPCODE(F64ConvertUI32); RETURN(CONVERT); } - "f32.convert_u/i64" { OPCODE(F32ConvertUI64); RETURN(CONVERT); } - "f64.convert_u/i64" { OPCODE(F64ConvertUI64); RETURN(CONVERT); } - "f64.promote/f32" { OPCODE(F64PromoteF32); RETURN(CONVERT); } - "f32.demote/f64" { OPCODE(F32DemoteF64); RETURN(CONVERT); } - "f32.reinterpret/i32" { OPCODE(F32ReinterpretI32); RETURN(CONVERT); } - "i32.reinterpret/f32" { OPCODE(I32ReinterpretF32); RETURN(CONVERT); } - "f64.reinterpret/i64" { OPCODE(F64ReinterpretI64); RETURN(CONVERT); } - "i64.reinterpret/f64" { OPCODE(I64ReinterpretF64); RETURN(CONVERT); } - "select" { RETURN(SELECT); } - "unreachable" { RETURN(UNREACHABLE); } - "current_memory" { RETURN(CURRENT_MEMORY); } - "grow_memory" { RETURN(GROW_MEMORY); } - "type" { RETURN(TYPE); } - "func" { RETURN(FUNC); } - "param" { RETURN(PARAM); } - "result" { RETURN(RESULT); } - "local" { RETURN(LOCAL); } - "global" { RETURN(GLOBAL); } - "module" { RETURN(MODULE); } - "binary" { RETURN(BIN); } - "quote" { RETURN(QUOTE); } - "table" { RETURN(TABLE); } - "memory" { RETURN(MEMORY); } - "start" { RETURN(START); } - "elem" { RETURN(ELEM); } - "data" { RETURN(DATA); } - "offset" { RETURN(OFFSET); } - "import" { RETURN(IMPORT); } - "export" { RETURN(EXPORT); } - "except" { RETURN(EXCEPT); } - "register" { RETURN(REGISTER); } - "invoke" { RETURN(INVOKE); } - "get" { RETURN(GET); } - "assert_malformed" { RETURN(ASSERT_MALFORMED); } - "assert_invalid" { RETURN(ASSERT_INVALID); } - "assert_unlinkable" { RETURN(ASSERT_UNLINKABLE); } - "assert_return" { RETURN(ASSERT_RETURN); } - "assert_return_canonical_nan" { - RETURN(ASSERT_RETURN_CANONICAL_NAN); } - "assert_return_arithmetic_nan" { - RETURN(ASSERT_RETURN_ARITHMETIC_NAN); } - "assert_trap" { RETURN(ASSERT_TRAP); } - "assert_exhaustion" { RETURN(ASSERT_EXHAUSTION); } - "try" { RETURN(TRY); } - "catch" { RETURN(CATCH); } - "catch_all" { RETURN(CATCH_ALL); } - "throw" { RETURN(THROW); } - "rethrow" { RETURN(RETHROW); } - name { TEXT; RETURN(VAR); } + "i32" { RETURN_TYPE(ValueType, I32); } + "i64" { RETURN_TYPE(ValueType, I64); } + "f32" { RETURN_TYPE(ValueType, F32); } + "f64" { RETURN_TYPE(ValueType, F64); } + "anyfunc" { RETURN(Anyfunc); } + "mut" { RETURN(Mut); } + "nop" { RETURN(Nop); } + "block" { RETURN(Block); } + "if" { RETURN_OPCODE0(If); } + "then" { RETURN(Then); } + "else" { RETURN(Else); } + "loop" { RETURN_OPCODE0(Loop); } + "br" { RETURN_OPCODE0(Br); } + "br_if" { RETURN_OPCODE0(BrIf); } + "br_table" { RETURN_OPCODE0(BrTable); } + "call" { RETURN_OPCODE0(Call); } + "call_indirect" { RETURN_OPCODE0(CallIndirect); } + "drop" { RETURN_OPCODE0(Drop); } + "end" { RETURN_OPCODE0(End); } + "return" { RETURN_OPCODE0(Return); } + "get_local" { RETURN_OPCODE0(GetLocal); } + "set_local" { RETURN_OPCODE0(SetLocal); } + "tee_local" { RETURN_OPCODE0(TeeLocal); } + "get_global" { RETURN_OPCODE0(GetGlobal); } + "set_global" { RETURN_OPCODE0(SetGlobal); } + "i32.load" { RETURN_OPCODE(Load, I32Load); } + "i64.load" { RETURN_OPCODE(Load, I64Load); } + "f32.load" { RETURN_OPCODE(Load, F32Load); } + "f64.load" { RETURN_OPCODE(Load, F64Load); } + "i32.store" { RETURN_OPCODE(Store, I32Store); } + "i64.store" { RETURN_OPCODE(Store, I64Store); } + "f32.store" { RETURN_OPCODE(Store, F32Store); } + "f64.store" { RETURN_OPCODE(Store, F64Store); } + "i32.load8_s" { RETURN_OPCODE(Load, I32Load8S); } + "i64.load8_s" { RETURN_OPCODE(Load, I64Load8S); } + "i32.load8_u" { RETURN_OPCODE(Load, I32Load8U); } + "i64.load8_u" { RETURN_OPCODE(Load, I64Load8U); } + "i32.load16_s" { RETURN_OPCODE(Load, I32Load16S); } + "i64.load16_s" { RETURN_OPCODE(Load, I64Load16S); } + "i32.load16_u" { RETURN_OPCODE(Load, I32Load16U); } + "i64.load16_u" { RETURN_OPCODE(Load, I64Load16U); } + "i64.load32_s" { RETURN_OPCODE(Load, I64Load32S); } + "i64.load32_u" { RETURN_OPCODE(Load, I64Load32U); } + "i32.store8" { RETURN_OPCODE(Store, I32Store8); } + "i64.store8" { RETURN_OPCODE(Store, I64Store8); } + "i32.store16" { RETURN_OPCODE(Store, I32Store16); } + "i64.store16" { RETURN_OPCODE(Store, I64Store16); } + "i64.store32" { RETURN_OPCODE(Store, I64Store32); } + "offset=" nat { RETURN_TEXT_AT(OffsetEqNat, 7); } + "align=" nat { RETURN_TEXT_AT(AlignEqNat, 6); } + "i32.const" { RETURN_OPCODE(Const, I32Const); } + "i64.const" { RETURN_OPCODE(Const, I64Const); } + "f32.const" { RETURN_OPCODE(Const, F32Const); } + "f64.const" { RETURN_OPCODE(Const, F64Const); } + "i32.eqz" { RETURN_OPCODE(Convert, I32Eqz); } + "i64.eqz" { RETURN_OPCODE(Convert, I64Eqz); } + "i32.clz" { RETURN_OPCODE(Unary, I32Clz); } + "i64.clz" { RETURN_OPCODE(Unary, I64Clz); } + "i32.ctz" { RETURN_OPCODE(Unary, I32Ctz); } + "i64.ctz" { RETURN_OPCODE(Unary, I64Ctz); } + "i32.popcnt" { RETURN_OPCODE(Unary, I32Popcnt); } + "i64.popcnt" { RETURN_OPCODE(Unary, I64Popcnt); } + "f32.neg" { RETURN_OPCODE(Unary, F32Neg); } + "f64.neg" { RETURN_OPCODE(Unary, F64Neg); } + "f32.abs" { RETURN_OPCODE(Unary, F32Abs); } + "f64.abs" { RETURN_OPCODE(Unary, F64Abs); } + "f32.sqrt" { RETURN_OPCODE(Unary, F32Sqrt); } + "f64.sqrt" { RETURN_OPCODE(Unary, F64Sqrt); } + "f32.ceil" { RETURN_OPCODE(Unary, F32Ceil); } + "f64.ceil" { RETURN_OPCODE(Unary, F64Ceil); } + "f32.floor" { RETURN_OPCODE(Unary, F32Floor); } + "f64.floor" { RETURN_OPCODE(Unary, F64Floor); } + "f32.trunc" { RETURN_OPCODE(Unary, F32Trunc); } + "f64.trunc" { RETURN_OPCODE(Unary, F64Trunc); } + "f32.nearest" { RETURN_OPCODE(Unary, F32Nearest); } + "f64.nearest" { RETURN_OPCODE(Unary, F64Nearest); } + "i32.add" { RETURN_OPCODE(Binary, I32Add); } + "i64.add" { RETURN_OPCODE(Binary, I64Add); } + "i32.sub" { RETURN_OPCODE(Binary, I32Sub); } + "i64.sub" { RETURN_OPCODE(Binary, I64Sub); } + "i32.mul" { RETURN_OPCODE(Binary, I32Mul); } + "i64.mul" { RETURN_OPCODE(Binary, I64Mul); } + "i32.div_s" { RETURN_OPCODE(Binary, I32DivS); } + "i64.div_s" { RETURN_OPCODE(Binary, I64DivS); } + "i32.div_u" { RETURN_OPCODE(Binary, I32DivU); } + "i64.div_u" { RETURN_OPCODE(Binary, I64DivU); } + "i32.rem_s" { RETURN_OPCODE(Binary, I32RemS); } + "i64.rem_s" { RETURN_OPCODE(Binary, I64RemS); } + "i32.rem_u" { RETURN_OPCODE(Binary, I32RemU); } + "i64.rem_u" { RETURN_OPCODE(Binary, I64RemU); } + "i32.and" { RETURN_OPCODE(Binary, I32And); } + "i64.and" { RETURN_OPCODE(Binary, I64And); } + "i32.or" { RETURN_OPCODE(Binary, I32Or); } + "i64.or" { RETURN_OPCODE(Binary, I64Or); } + "i32.xor" { RETURN_OPCODE(Binary, I32Xor); } + "i64.xor" { RETURN_OPCODE(Binary, I64Xor); } + "i32.shl" { RETURN_OPCODE(Binary, I32Shl); } + "i64.shl" { RETURN_OPCODE(Binary, I64Shl); } + "i32.shr_s" { RETURN_OPCODE(Binary, I32ShrS); } + "i64.shr_s" { RETURN_OPCODE(Binary, I64ShrS); } + "i32.shr_u" { RETURN_OPCODE(Binary, I32ShrU); } + "i64.shr_u" { RETURN_OPCODE(Binary, I64ShrU); } + "i32.rotl" { RETURN_OPCODE(Binary, I32Rotl); } + "i64.rotl" { RETURN_OPCODE(Binary, I64Rotl); } + "i32.rotr" { RETURN_OPCODE(Binary, I32Rotr); } + "i64.rotr" { RETURN_OPCODE(Binary, I64Rotr); } + "f32.add" { RETURN_OPCODE(Binary, F32Add); } + "f64.add" { RETURN_OPCODE(Binary, F64Add); } + "f32.sub" { RETURN_OPCODE(Binary, F32Sub); } + "f64.sub" { RETURN_OPCODE(Binary, F64Sub); } + "f32.mul" { RETURN_OPCODE(Binary, F32Mul); } + "f64.mul" { RETURN_OPCODE(Binary, F64Mul); } + "f32.div" { RETURN_OPCODE(Binary, F32Div); } + "f64.div" { RETURN_OPCODE(Binary, F64Div); } + "f32.min" { RETURN_OPCODE(Binary, F32Min); } + "f64.min" { RETURN_OPCODE(Binary, F64Min); } + "f32.max" { RETURN_OPCODE(Binary, F32Max); } + "f64.max" { RETURN_OPCODE(Binary, F64Max); } + "f32.copysign" { RETURN_OPCODE(Binary, F32Copysign); } + "f64.copysign" { RETURN_OPCODE(Binary, F64Copysign); } + "i32.eq" { RETURN_OPCODE(Compare, I32Eq); } + "i64.eq" { RETURN_OPCODE(Compare, I64Eq); } + "i32.ne" { RETURN_OPCODE(Compare, I32Ne); } + "i64.ne" { RETURN_OPCODE(Compare, I64Ne); } + "i32.lt_s" { RETURN_OPCODE(Compare, I32LtS); } + "i64.lt_s" { RETURN_OPCODE(Compare, I64LtS); } + "i32.lt_u" { RETURN_OPCODE(Compare, I32LtU); } + "i64.lt_u" { RETURN_OPCODE(Compare, I64LtU); } + "i32.le_s" { RETURN_OPCODE(Compare, I32LeS); } + "i64.le_s" { RETURN_OPCODE(Compare, I64LeS); } + "i32.le_u" { RETURN_OPCODE(Compare, I32LeU); } + "i64.le_u" { RETURN_OPCODE(Compare, I64LeU); } + "i32.gt_s" { RETURN_OPCODE(Compare, I32GtS); } + "i64.gt_s" { RETURN_OPCODE(Compare, I64GtS); } + "i32.gt_u" { RETURN_OPCODE(Compare, I32GtU); } + "i64.gt_u" { RETURN_OPCODE(Compare, I64GtU); } + "i32.ge_s" { RETURN_OPCODE(Compare, I32GeS); } + "i64.ge_s" { RETURN_OPCODE(Compare, I64GeS); } + "i32.ge_u" { RETURN_OPCODE(Compare, I32GeU); } + "i64.ge_u" { RETURN_OPCODE(Compare, I64GeU); } + "f32.eq" { RETURN_OPCODE(Compare, F32Eq); } + "f64.eq" { RETURN_OPCODE(Compare, F64Eq); } + "f32.ne" { RETURN_OPCODE(Compare, F32Ne); } + "f64.ne" { RETURN_OPCODE(Compare, F64Ne); } + "f32.lt" { RETURN_OPCODE(Compare, F32Lt); } + "f64.lt" { RETURN_OPCODE(Compare, F64Lt); } + "f32.le" { RETURN_OPCODE(Compare, F32Le); } + "f64.le" { RETURN_OPCODE(Compare, F64Le); } + "f32.gt" { RETURN_OPCODE(Compare, F32Gt); } + "f64.gt" { RETURN_OPCODE(Compare, F64Gt); } + "f32.ge" { RETURN_OPCODE(Compare, F32Ge); } + "f64.ge" { RETURN_OPCODE(Compare, F64Ge); } + "i64.extend_s/i32" { RETURN_OPCODE(Convert, I64ExtendSI32); } + "i64.extend_u/i32" { RETURN_OPCODE(Convert, I64ExtendUI32); } + "i32.wrap/i64" { RETURN_OPCODE(Convert, I32WrapI64); } + "i32.trunc_s/f32" { RETURN_OPCODE(Convert, I32TruncSF32); } + "i64.trunc_s/f32" { RETURN_OPCODE(Convert, I64TruncSF32); } + "i32.trunc_s/f64" { RETURN_OPCODE(Convert, I32TruncSF64); } + "i64.trunc_s/f64" { RETURN_OPCODE(Convert, I64TruncSF64); } + "i32.trunc_u/f32" { RETURN_OPCODE(Convert, I32TruncUF32); } + "i64.trunc_u/f32" { RETURN_OPCODE(Convert, I64TruncUF32); } + "i32.trunc_u/f64" { RETURN_OPCODE(Convert, I32TruncUF64); } + "i64.trunc_u/f64" { RETURN_OPCODE(Convert, I64TruncUF64); } + "i32.trunc_s:sat/f32" { RETURN_OPCODE(Convert, I32TruncSSatF32); } + "i64.trunc_s:sat/f32" { RETURN_OPCODE(Convert, I64TruncSSatF32); } + "i32.trunc_s:sat/f64" { RETURN_OPCODE(Convert, I32TruncSSatF64); } + "i64.trunc_s:sat/f64" { RETURN_OPCODE(Convert, I64TruncSSatF64); } + "i32.trunc_u:sat/f32" { RETURN_OPCODE(Convert, I32TruncUSatF32); } + "i64.trunc_u:sat/f32" { RETURN_OPCODE(Convert, I64TruncUSatF32); } + "i32.trunc_u:sat/f64" { RETURN_OPCODE(Convert, I32TruncUSatF64); } + "i64.trunc_u:sat/f64" { RETURN_OPCODE(Convert, I64TruncUSatF64); } + "f32.convert_s/i32" { RETURN_OPCODE(Convert, F32ConvertSI32); } + "f64.convert_s/i32" { RETURN_OPCODE(Convert, F64ConvertSI32); } + "f32.convert_s/i64" { RETURN_OPCODE(Convert, F32ConvertSI64); } + "f64.convert_s/i64" { RETURN_OPCODE(Convert, F64ConvertSI64); } + "f32.convert_u/i32" { RETURN_OPCODE(Convert, F32ConvertUI32); } + "f64.convert_u/i32" { RETURN_OPCODE(Convert, F64ConvertUI32); } + "f32.convert_u/i64" { RETURN_OPCODE(Convert, F32ConvertUI64); } + "f64.convert_u/i64" { RETURN_OPCODE(Convert, F64ConvertUI64); } + "f64.promote/f32" { RETURN_OPCODE(Convert, F64PromoteF32); } + "f32.demote/f64" { RETURN_OPCODE(Convert, F32DemoteF64); } + "f32.reinterpret/i32" { RETURN_OPCODE(Convert, F32ReinterpretI32); } + "i32.reinterpret/f32" { RETURN_OPCODE(Convert, I32ReinterpretF32); } + "f64.reinterpret/i64" { RETURN_OPCODE(Convert, F64ReinterpretI64); } + "i64.reinterpret/f64" { RETURN_OPCODE(Convert, I64ReinterpretF64); } + "select" { RETURN_OPCODE0(Select); } + "unreachable" { RETURN_OPCODE0(Unreachable); } + "current_memory" { RETURN_OPCODE0(CurrentMemory); } + "grow_memory" { RETURN_OPCODE0(GrowMemory); } + "type" { RETURN(Type); } + "func" { RETURN(Func); } + "param" { RETURN(Param); } + "result" { RETURN(Result); } + "local" { RETURN(Local); } + "global" { RETURN(Global); } + "module" { RETURN(Module); } + "binary" { RETURN(Bin); } + "quote" { RETURN(Quote); } + "table" { RETURN(Table); } + "memory" { RETURN(Memory); } + "start" { RETURN(Start); } + "elem" { RETURN(Elem); } + "data" { RETURN(Data); } + "offset" { RETURN(Offset); } + "import" { RETURN(Import); } + "export" { RETURN(Export); } + "except" { RETURN(Except); } + "register" { RETURN(Register); } + "invoke" { RETURN(Invoke); } + "get" { RETURN(Get); } + "assert_malformed" { RETURN(AssertMalformed); } + "assert_invalid" { RETURN(AssertInvalid); } + "assert_unlinkable" { RETURN(AssertUnlinkable); } + "assert_return" { RETURN(AssertReturn); } + "assert_return_canonical_nan" { RETURN(AssertReturnCanonicalNan); } + "assert_return_arithmetic_nan" { RETURN(AssertReturnArithmeticNan); } + "assert_trap" { RETURN(AssertTrap); } + "assert_exhaustion" { RETURN(AssertExhaustion); } + "try" { RETURN_OPCODE0(Try); } + "catch" { RETURN_OPCODE0(Catch); } + "catch_all" { RETURN_OPCODE0(CatchAll); } + "throw" { RETURN_OPCODE0(Throw); } + "rethrow" { RETURN_OPCODE0(Rethrow); } + name { RETURN_TEXT(Var); } ";;" => LINE_COMMENT { continue; } "\n" => i { NEWLINE; continue; } - [^\n]* { continue; } + [^\n]+ { continue; } "(;" => BLOCK_COMMENT { COMMENT_NESTING = 1; continue; } "(;" { COMMENT_NESTING++; continue; } ";)" { if (--COMMENT_NESTING == 0) - BEGIN(YYCOND_INIT); + BEGIN(YYCOND_i); continue; } "\n" { NEWLINE; continue; } [^] { continue; } * { MAYBE_MALFORMED_UTF8(" in block comment"); } "\n" { NEWLINE; continue; } [ \t\r]+ { continue; } - reserved { ERROR("unexpected token \"%.*s\"", - static_cast(yyleng), yytext); - continue; } - <*> [^] { ERROR("unexpected char"); continue; } + reserved { RETURN_TEXT(Reserved); } + [^] { ERROR("unexpected char"); continue; } <*> * { MAYBE_MALFORMED_UTF8(""); } */ } diff --git a/lib/wabt/src/wast-lexer.h b/lib/wabt/src/wast-lexer.h index 40ecd43f32d..20ef2bb664b 100644 --- a/lib/wabt/src/wast-lexer.h +++ b/lib/wabt/src/wast-lexer.h @@ -23,15 +23,148 @@ #include "common.h" #include "lexer-source-line-finder.h" +#include "literal.h" +#include "opcode.h" namespace wabt { -union Token; -struct WastParser; +class ErrorHandler; class LexerSource; +class WastParser; + +struct StringTerminal { + StringTerminal() = default; + StringTerminal(const char* data, size_t size) : data(data), size(size) {} + + const char* data; + size_t size; + + // Helper functions. + std::string to_string() const { return std::string(data, size); } + string_view to_string_view() const { return string_view(data, size); } +}; + +struct LiteralTerminal { + LiteralTerminal() = default; + LiteralTerminal(LiteralType type, StringTerminal text) + : type(type), text(text) {} + + LiteralType type; + StringTerminal text; +}; + +enum class TokenType { + Invalid, + Reserved, + Eof, + Lpar, + Rpar, + Nat, + Int, + Float, + Text, + Var, + ValueType, + Anyfunc, + Mut, + Nop, + Drop, + Block, + End, + If, + Then, + Else, + Loop, + Br, + BrIf, + BrTable, + Try, + Catch, + CatchAll, + Throw, + Rethrow, + Call, + CallIndirect, + Return, + GetLocal, + SetLocal, + TeeLocal, + GetGlobal, + SetGlobal, + Load, + Store, + OffsetEqNat, + AlignEqNat, + Const, + Unary, + Binary, + Compare, + Convert, + Select, + Unreachable, + CurrentMemory, + GrowMemory, + Func, + Start, + Type, + Param, + Result, + Local, + Global, + Table, + Elem, + Memory, + Data, + Offset, + Import, + Export, + Except, + Module, + Bin, + Quote, + Register, + Invoke, + Get, + AssertMalformed, + AssertInvalid, + AssertUnlinkable, + AssertReturn, + AssertReturnCanonicalNan, + AssertReturnArithmeticNan, + AssertTrap, + AssertExhaustion, + + First = Invalid, + Last = AssertExhaustion, +}; + +const char* GetTokenTypeName(TokenType); + +struct Token { + Token() : token_type(TokenType::Invalid) {} + Token(Location, TokenType); + Token(Location, TokenType, Type); + Token(Location, TokenType, StringTerminal); + Token(Location, TokenType, Opcode); + Token(Location, TokenType, LiteralTerminal); + + Location loc; + TokenType token_type; + + union { + StringTerminal text; + Type type; + Opcode opcode; + LiteralTerminal literal; + }; + + std::string to_string() const; +}; class WastLexer { public: + WABT_DISALLOW_COPY_AND_ASSIGN(WastLexer); + WastLexer(std::unique_ptr source, const char* filename); ~WastLexer(); @@ -41,12 +174,17 @@ class WastLexer { const void* data, size_t size); - int GetToken(Token* lval, Location* loc, WastParser* parser); - Result Fill(Location* loc, WastParser* parser, size_t need); + Token GetToken(WastParser* parser); + Result Fill(size_t need); + // TODO(binji): Move this out of the lexer. LexerSourceLineFinder& line_finder() { return line_finder_; } private: + Location GetLocation(); + LiteralTerminal MakeLiteral(LiteralType); + StringTerminal GetText(size_t at = 0); + std::unique_ptr source_; LexerSourceLineFinder line_finder_; const char* filename_; @@ -60,11 +198,9 @@ class WastLexer { char* buffer_; size_t buffer_size_; char* marker_; - char* token_; + char* next_pos_; char* cursor_; char* limit_; - - WABT_DISALLOW_COPY_AND_ASSIGN(WastLexer); }; } // namespace wabt diff --git a/lib/wabt/src/wast-parser-lexer-shared.cc b/lib/wabt/src/wast-parser-lexer-shared.cc index 34bf7ebe50a..80a9b8bdf8d 100644 --- a/lib/wabt/src/wast-parser-lexer-shared.cc +++ b/lib/wabt/src/wast-parser-lexer-shared.cc @@ -16,30 +16,17 @@ #include "wast-parser-lexer-shared.h" -#include -#include -#include -#include +#include "common.h" +#include "error-handler.h" +#include "wast-lexer.h" namespace wabt { -void wast_parser_error(Location* loc, - WastLexer* lexer, - WastParser* parser, - const char* format, - ...) { - parser->errors++; - va_list args; - va_start(args, format); - wast_format_error(parser->error_handler, loc, lexer, format, args); - va_end(args); -} - -void wast_format_error(SourceErrorHandler* error_handler, - const struct Location* loc, - WastLexer* lexer, - const char* format, - va_list args) { +void WastFormatError(ErrorHandler* error_handler, + const Location* loc, + WastLexer* lexer, + const char* format, + va_list args) { va_list args_copy; va_copy(args_copy, args); char fixed_buf[WABT_DEFAULT_SNPRINTF_ALLOCA_BUFSIZE]; @@ -55,35 +42,16 @@ void wast_format_error(SourceErrorHandler* error_handler, size_t source_line_max_length = error_handler->source_line_max_length(); Result result = lexer->line_finder().GetSourceLine( *loc, source_line_max_length, &source_line); - if (WABT_FAILED(result)) { + if (Failed(result)) { // If this fails, it means that we've probably screwed up the lexer. Blow // up. WABT_FATAL("error getting the source line.\n"); } } - error_handler->OnError(loc, std::string(buffer), source_line.line, + error_handler->OnError(*loc, std::string(buffer), source_line.line, source_line.column_offset); va_end(args_copy); } -void destroy_text_list(TextList* text_list) { - TextListNode* node = text_list->first; - while (node) { - TextListNode* next = node->next; - destroy_string_slice(&node->text); - delete node; - node = next; - } -} - -void destroy_module_field_list(ModuleFieldList* fields) { - ModuleField* field = fields->first; - while (field) { - ModuleField* next = field->next; - delete field; - field = next; - } -} - } // namespace wabt diff --git a/lib/wabt/src/wast-parser-lexer-shared.h b/lib/wabt/src/wast-parser-lexer-shared.h index 76be8f31f5f..f3b4607a594 100644 --- a/lib/wabt/src/wast-parser-lexer-shared.h +++ b/lib/wabt/src/wast-parser-lexer-shared.h @@ -18,111 +18,19 @@ #define WABT_WAST_PARSER_LEXER_SHARED_H_ #include -#include - -#include "common.h" -#include "ir.h" -#include "source-error-handler.h" -#include "wast-parser.h" - -#define WABT_WAST_PARSER_STYPE Token -#define WABT_WAST_PARSER_LTYPE Location -#define YYSTYPE WABT_WAST_PARSER_STYPE -#define YYLTYPE WABT_WAST_PARSER_LTYPE namespace wabt { -struct ExprList { - Expr* first; - Expr* last; - size_t size; -}; - -struct TextListNode { - StringSlice text; - struct TextListNode* next; -}; - -struct TextList { - TextListNode* first; - TextListNode* last; -}; - -struct ModuleFieldList { - ModuleField* first; - ModuleField* last; -}; - -union Token { - /* terminals */ - StringSlice text; - Type type; - Opcode opcode; - Literal literal; - - /* non-terminals */ - /* some of these use pointers to keep the size of Token down; copying the - tokens is a hotspot when parsing large files. */ - Action* action; - Block* block; - Command* command; - CommandPtrVector* commands; - Const const_; - ConstVector* consts; - DataSegment* data_segment; - ElemSegment* elem_segment; - Exception* exception; - Export* export_; - Expr* expr; - ExprList expr_list; - Func* func; - FuncSignature* func_sig; - FuncType* func_type; - Global* global; - Import* import; - Limits limits; - Memory* memory; - Module* module; - ModuleField* module_field; - ModuleFieldList module_fields; - ScriptModule* script_module; - Script* script; - Table* table; - TextList text_list; - TypeVector* types; - uint32_t u32; - uint64_t u64; - Var* var; - VarVector* vars; -}; - -struct WastParser { - Script* script; - SourceErrorHandler* error_handler; - int errors; - /* Cached pointers to reallocated parser buffers, so they don't leak. */ - int16_t* yyssa; - YYSTYPE* yyvsa; - YYLTYPE* yylsa; - WastParseOptions* options; -}; +class ErrorHandler; +struct Location; +class WastLexer; -int wast_lexer_lex(union Token*, - struct Location*, - WastLexer*, - struct WastParser*); -void WABT_PRINTF_FORMAT(4, 5) wast_parser_error(struct Location*, - WastLexer*, - struct WastParser*, - const char*, - ...); -void wast_format_error(SourceErrorHandler*, - const struct Location*, - WastLexer*, - const char* format, - va_list); -void destroy_text_list(TextList*); -void destroy_module_field_list(ModuleFieldList*); +// TODO(binji): Move this somewhere else. +void WastFormatError(ErrorHandler*, + const Location*, + WastLexer*, + const char* format, + va_list); } // namespace wabt diff --git a/lib/wabt/src/wast-parser.cc b/lib/wabt/src/wast-parser.cc new file mode 100644 index 00000000000..139f5a7af0b --- /dev/null +++ b/lib/wabt/src/wast-parser.cc @@ -0,0 +1,2008 @@ +/* + * Copyright 2017 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. + */ + +#include "wast-parser.h" + +#include "binary-reader.h" +#include "binary-reader-ir.h" +#include "cast.h" +#include "error-handler.h" +#include "wast-parser-lexer-shared.h" + +#define WABT_TRACING 0 +#include "tracing.h" + +#define CHECK_RESULT(expr) \ + do { \ + if (Failed(expr)) \ + return Result::Error; \ + } while (0) + +#define EXPECT(token_type) CHECK_RESULT(Expect(TokenType::token_type)) + +namespace wabt { + +namespace { + +bool IsPowerOfTwo(uint32_t x) { + return x && ((x & (x - 1)) == 0); +} + +template +void RemoveEscapes(string_view text, OutputIter dest) { + // Remove surrounding quotes; if any. This may be empty if the string was + // invalid (e.g. if it contained a bad escape sequence). + if (text.size() <= 2) + return; + + text = text.substr(1, text.size() - 2); + + const char* src = text.data(); + const char* end = text.data() + text.size(); + + while (src < end) { + if (*src == '\\') { + src++; + switch (*src) { + case 'n': + *dest++ = '\n'; + break; + case 'r': + *dest++ = '\r'; + break; + case 't': + *dest++ = '\t'; + break; + case '\\': + *dest++ = '\\'; + break; + case '\'': + *dest++ = '\''; + break; + case '\"': + *dest++ = '\"'; + break; + default: { + // The string should be validated already, so we know this is a hex + // sequence. + uint32_t hi; + uint32_t lo; + if (Succeeded(ParseHexdigit(src[0], &hi)) && + Succeeded(ParseHexdigit(src[1], &lo))) { + *dest++ = (hi << 4) | lo; + } else { + assert(0); + } + src++; + break; + } + } + src++; + } else { + *dest++ = *src++; + } + } +} + +typedef std::vector TextVector; + +template +void RemoveEscapes(const TextVector& texts, OutputIter out) { + for (const std::string& text: texts) + RemoveEscapes(text, out); +} + +class BinaryErrorHandlerModule : public ErrorHandler { + public: + BinaryErrorHandlerModule(Location* loc, WastParser* parser); + bool OnError(const Location&, + const std::string& error, + const std::string& source_line, + size_t source_line_column_offset) override; + + // Unused. + size_t source_line_max_length() const override { return 0; } + + private: + Location* loc_; + WastParser* parser_; +}; + +BinaryErrorHandlerModule::BinaryErrorHandlerModule(Location* loc, + WastParser* parser) + : ErrorHandler(Location::Type::Binary), loc_(loc), parser_(parser) {} + +bool BinaryErrorHandlerModule::OnError(const Location& binary_loc, + const std::string& error, + const std::string& source_line, + size_t source_line_column_offset) { + if (binary_loc.offset == kInvalidOffset) { + parser_->Error(*loc_, "error in binary module: %s", error.c_str()); + } else { + parser_->Error(*loc_, "error in binary module: @0x%08" PRIzx ": %s", + binary_loc.offset, error.c_str()); + } + return true; +} + +bool IsPlainInstr(TokenType token_type) { + switch (token_type) { + case TokenType::Unreachable: + case TokenType::Nop: + case TokenType::Drop: + case TokenType::Select: + case TokenType::Br: + case TokenType::BrIf: + case TokenType::BrTable: + case TokenType::Return: + case TokenType::Call: + case TokenType::CallIndirect: + case TokenType::GetLocal: + case TokenType::SetLocal: + case TokenType::TeeLocal: + case TokenType::GetGlobal: + case TokenType::SetGlobal: + case TokenType::Load: + case TokenType::Store: + case TokenType::Const: + case TokenType::Unary: + case TokenType::Binary: + case TokenType::Compare: + case TokenType::Convert: + case TokenType::CurrentMemory: + case TokenType::GrowMemory: + case TokenType::Throw: + case TokenType::Rethrow: + return true; + default: + return false; + } +} + +bool IsBlockInstr(TokenType token_type) { + switch (token_type) { + case TokenType::Block: + case TokenType::Loop: + case TokenType::If: + case TokenType::Try: + return true; + default: + return false; + } +} + +bool IsPlainOrBlockInstr(TokenType token_type) { + return IsPlainInstr(token_type) || IsBlockInstr(token_type); +} + +bool IsExpr(TokenTypePair pair) { + return pair[0] == TokenType::Lpar && IsPlainOrBlockInstr(pair[1]); +} + +bool IsInstr(TokenTypePair pair) { + return IsPlainOrBlockInstr(pair[0]) || IsExpr(pair); +} + +bool IsCatch(TokenType token_type) { + return token_type == TokenType::Catch || token_type == TokenType::CatchAll; +} + +bool IsModuleField(TokenTypePair pair) { + if (pair[0] != TokenType::Lpar) + return false; + + switch (pair[1]) { + case TokenType::Data: + case TokenType::Elem: + case TokenType::Except: + case TokenType::Export: + case TokenType::Func: + case TokenType::Type: + case TokenType::Global: + case TokenType::Import: + case TokenType::Memory: + case TokenType::Start: + case TokenType::Table: + return true; + default: + return false; + } +} + +bool IsCommand(TokenTypePair pair) { + if (pair[0] != TokenType::Lpar) + return false; + + switch (pair[1]) { + case TokenType::AssertExhaustion: + case TokenType::AssertInvalid: + case TokenType::AssertMalformed: + case TokenType::AssertReturn: + case TokenType::AssertReturnArithmeticNan: + case TokenType::AssertReturnCanonicalNan: + case TokenType::AssertTrap: + case TokenType::AssertUnlinkable: + case TokenType::Get: + case TokenType::Invoke: + case TokenType::Module: + case TokenType::Register: + return true; + default: + return false; + } +} + +bool IsEmptySignature(const FuncSignature* sig) { + return sig->result_types.empty() && sig->param_types.empty(); +} + +void ResolveFuncTypes(Module* module) { + for (ModuleField& field : module->fields) { + Func* func = nullptr; + if (field.type == ModuleFieldType::Func) { + func = dyn_cast(&field)->func; + } else if (field.type == ModuleFieldType::Import) { + Import* import = dyn_cast(&field)->import; + if (import->kind == ExternalKind::Func) { + func = import->func; + } else { + continue; + } + } else { + continue; + } + + // Resolve func type variables where the signature was not specified + // explicitly, e.g.: (func (type 1) ...) + if (func->decl.has_func_type && IsEmptySignature(&func->decl.sig)) { + FuncType* func_type = module->GetFuncType(func->decl.type_var); + if (func_type) { + func->decl.sig = func_type->sig; + } + } + + // Resolve implicitly defined function types, e.g.: (func (param i32) ...) + if (!func->decl.has_func_type) { + Index func_type_index = module->GetFuncTypeIndex(func->decl.sig); + if (func_type_index == kInvalidIndex) { + auto func_type = new FuncType(); + func_type->sig = func->decl.sig; + module->AppendField(new FuncTypeModuleField(func_type, field.loc)); + } + } + } +} + +void AppendInlineExportFields(Module* module, + ModuleFieldList* fields, + Index index) { + Location last_field_loc = module->fields.back().loc; + + for (const ModuleField& field: *fields) { + auto* export_field = cast(&field); + export_field->export_->var = Var(index, last_field_loc); + } + + module->AppendFields(fields); +} + +} // End of anonymous namespace + +WastParser::WastParser(WastLexer* lexer, + ErrorHandler* error_handler, + WastParseOptions* options) + : lexer_(lexer), error_handler_(error_handler), options_(options) {} + +void WastParser::Error(Location loc, const char* format, ...) { + errors_++; + va_list args; + va_start(args, format); + WastFormatError(error_handler_, &loc, lexer_, format, args); + va_end(args); +} + +Token WastParser::GetToken() { + if (tokens_.empty()) + tokens_.push_back(lexer_->GetToken(this)); + return tokens_.front(); +} + +Location WastParser::GetLocation() { + return GetToken().loc; +} + +TokenType WastParser::Peek(size_t n) { + while (tokens_.size() <= n) + tokens_.push_back(lexer_->GetToken(this)); + return tokens_.at(n).token_type; +} + +TokenTypePair WastParser::PeekPair() { + return TokenTypePair{{Peek(), Peek(1)}}; +} + +bool WastParser::PeekMatch(TokenType type) { + return Peek() == type; +} + +bool WastParser::PeekMatchLpar(TokenType type) { + return Peek() == TokenType::Lpar && Peek(1) == type; +} + +bool WastParser::PeekMatchExpr() { + return IsExpr(PeekPair()); +} + +bool WastParser::Match(TokenType type) { + if (PeekMatch(type)) { + Consume(); + return true; + } + return false; +} + +bool WastParser::MatchLpar(TokenType type) { + if (PeekMatchLpar(type)) { + Consume(); + Consume(); + return true; + } + return false; +} + +Result WastParser::Expect(TokenType type) { + if (!Match(type)) { + auto token = Consume(); + Error(token.loc, "unexpected token %s, expected %s.", + token.to_string().c_str(), GetTokenTypeName(type)); + return Result::Error; + } + + return Result::Ok; +} + +Token WastParser::Consume() { + assert(!tokens_.empty()); + auto token = tokens_.front(); + tokens_.pop_front(); + return token; +} + +Result WastParser::Synchronize(SynchronizeFunc func) { + static const int kMaxConsumed = 10; + for (int i = 0; i < kMaxConsumed; ++i) { + if (func(PeekPair())) + return Result::Ok; + + auto token = Consume(); + if (token.token_type == TokenType::Reserved) { + Error(token.loc, "unexpected token %s.", token.to_string().c_str()); + } + } + + return Result::Error; +} + +void WastParser::ErrorUnlessOpcodeEnabled(const Token& token) { + Opcode opcode = token.opcode; + if (!opcode.IsEnabled(options_->features)) + Error(token.loc, "opcode not allowed: %s", opcode.GetName()); +} + +Result WastParser::ErrorExpected(const std::vector& expected, + const char* example) { + auto token = Consume(); + std::string expected_str; + if (!expected.empty()) { + expected_str = ", expected "; + for (size_t i = 0; i < expected.size(); ++i) { + if (i != 0) { + if (i == expected.size() - 1) + expected_str += " or "; + else + expected_str += ", "; + } + + expected_str += expected[i]; + } + + if (example) { + expected_str += " (e.g. "; + expected_str += example; + expected_str += ")"; + } + } + + Error(token.loc, "unexpected token \"%s\"%s.", token.to_string().c_str(), + expected_str.c_str()); + return Result::Error; +} + +Result WastParser::ErrorIfLpar(const std::vector& expected, + const char* example) { + if (Match(TokenType::Lpar)) + return ErrorExpected(expected, example); + return Result::Ok; +} + +void WastParser::ParseBindVarOpt(std::string* name) { + WABT_TRACE(ParseBindVarOpt); + if (PeekMatch(TokenType::Var)) { + auto token = Consume(); + *name = token.text.to_string(); + } +} + +Result WastParser::ParseVar(Var* out_var) { + WABT_TRACE(ParseVar); + if (PeekMatch(TokenType::Nat)) { + auto token = Consume(); + string_view sv = token.literal.text.to_string_view(); + uint64_t index = kInvalidIndex; + if (Failed(ParseUint64(sv.begin(), sv.end(), &index))) { + // Print an error, but don't fail parsing. + Error(token.loc, "invalid int \"" PRIstringview "\"", + WABT_PRINTF_STRING_VIEW_ARG(sv)); + } + + *out_var = Var(index, token.loc); + return Result::Ok; + } else if (PeekMatch(TokenType::Var)) { + auto token = Consume(); + *out_var = Var(token.text.to_string_view(), token.loc); + return Result::Ok; + } else { + return ErrorExpected({"a numeric index", "a name"}, "12 or $foo"); + } +} + +bool WastParser::ParseVarOpt(Var* out_var, Var default_var) { + WABT_TRACE(ParseVarOpt); + if (PeekMatch(TokenType::Nat) || PeekMatch(TokenType::Var)) { + Result result = ParseVar(out_var); + // Should always succeed, the only way it could fail is if the token + // doesn't match. + assert(Succeeded(result)); + WABT_USE(result); + return true; + } else { + *out_var = default_var; + return false; + } +} + +Result WastParser::ParseOffsetExpr(ExprList* out_expr_list) { + WABT_TRACE(ParseOffsetExpr); + if (MatchLpar(TokenType::Offset)) { + CHECK_RESULT(ParseTerminatingInstrList(out_expr_list)); + EXPECT(Rpar); + } else if (PeekMatchExpr()) { + CHECK_RESULT(ParseExpr(out_expr_list)); + } else { + return ErrorExpected({"an offset expr"}, "(i32.const 123)"); + } + return Result::Ok; +} + +Result WastParser::ParseTextList(std::vector* out_data) { + WABT_TRACE(ParseTextList); + if (!ParseTextListOpt(out_data)) { + return Result::Error; + } + + return Result::Ok; +} + +bool WastParser::ParseTextListOpt(std::vector* out_data) { + WABT_TRACE(ParseTextListOpt); + TextVector texts; + while (PeekMatch(TokenType::Text)) + texts.push_back(Consume().text.to_string()); + + RemoveEscapes(texts, std::back_inserter(*out_data)); + return !texts.empty(); +} + +Result WastParser::ParseVarList(VarVector* out_var_list) { + WABT_TRACE(ParseVarList); + if (!ParseVarListOpt(out_var_list)) { + return Result::Error; + } + + return Result::Ok; +} + +bool WastParser::ParseVarListOpt(VarVector* out_var_list) { + WABT_TRACE(ParseVarListOpt); + Var var; + while (ParseVarOpt(&var)) + out_var_list->push_back(var); + + return !out_var_list->empty(); +} + +Result WastParser::ParseValueType(Type* out_type) { + WABT_TRACE(ParseValueType); + if (!PeekMatch(TokenType::ValueType)) + return ErrorExpected({"i32", "i64", "f32", "f64"}); + + *out_type = Consume().type; + return Result::Ok; +} + +Result WastParser::ParseValueTypeList(TypeVector* out_type_list) { + WABT_TRACE(ParseValueTypeList); + while (PeekMatch(TokenType::ValueType)) + out_type_list->push_back(Consume().type); + + CHECK_RESULT(ErrorIfLpar({"i32", "i64", "f32", "f64"})); + return Result::Ok; +} + +Result WastParser::ParseQuotedText(std::string* text) { + WABT_TRACE(ParseQuotedText); + if (!PeekMatch(TokenType::Text)) + return ErrorExpected({"a quoted string"}, "\"foo\""); + + RemoveEscapes(Consume().text.to_string_view(), std::back_inserter(*text)); + return Result::Ok; +} + +bool WastParser::ParseOffsetOpt(uint32_t* out_offset) { + WABT_TRACE(ParseOffsetOpt); + if (PeekMatch(TokenType::OffsetEqNat)) { + auto token = Consume(); + uint64_t offset64; + string_view sv = token.text.to_string_view(); + if (Failed(ParseInt64(sv.begin(), sv.end(), &offset64, + ParseIntType::SignedAndUnsigned))) { + Error(token.loc, "invalid offset \"" PRIstringview "\"", + WABT_PRINTF_STRING_VIEW_ARG(sv)); + } + if (offset64 > UINT32_MAX) { + Error(token.loc, "offset must be less than or equal to 0xffffffff"); + } + + *out_offset = static_cast(offset64); + return true; + } else { + *out_offset = 0; + return false; + } +} + +bool WastParser::ParseAlignOpt(uint32_t* out_align) { + WABT_TRACE(ParseAlignOpt); + if (PeekMatch(TokenType::AlignEqNat)) { + auto token = Consume(); + string_view sv = token.text.to_string_view(); + if (Failed(ParseInt32(sv.begin(), sv.end(), out_align, + ParseIntType::UnsignedOnly))) { + Error(token.loc, "invalid alignment \"" PRIstringview "\"", + WABT_PRINTF_STRING_VIEW_ARG(sv)); + } + + if (!IsPowerOfTwo(*out_align)) { + Error(token.loc, "alignment must be power-of-two"); + } + + return true; + } else { + *out_align = WABT_USE_NATURAL_ALIGNMENT; + return false; + } +} + +Result WastParser::ParseLimits(Limits* out_limits) { + WABT_TRACE(ParseLimits); + CHECK_RESULT(ParseNat(&out_limits->initial)); + + if (PeekMatch(TokenType::Nat)) { + CHECK_RESULT(ParseNat(&out_limits->max)); + out_limits->has_max = true; + } else { + out_limits->has_max = false; + } + + return Result::Ok; +} + +Result WastParser::ParseNat(uint64_t* out_nat) { + WABT_TRACE(ParseNat); + if (!PeekMatch(TokenType::Nat)) + return ErrorExpected({"a natural number"}, "123"); + + auto token = Consume(); + string_view sv = token.literal.text.to_string_view(); + if (Failed(ParseUint64(sv.begin(), sv.end(), out_nat))) { + Error(token.loc, "invalid int \"" PRIstringview "\"", + WABT_PRINTF_STRING_VIEW_ARG(sv)); + } + + return Result::Ok; +} + +Result WastParser::ParseScript(Script* script) { + WABT_TRACE(ParseScript); + script_ = script; + + // Don't consume the Lpar yet, even though it is required. This way the + // sub-parser functions (e.g. ParseFuncModuleField) can consume it and keep + // the parsing structure more regular. + if (IsModuleField(PeekPair())) { + // Parse an inline module (i.e. one with no surrounding (module)). + auto module = make_unique(); + module->loc = GetLocation(); + CHECK_RESULT(ParseModuleFieldList(module.get())); + script->commands.emplace_back(make_unique(module.release())); + } else if (IsCommand(PeekPair())) { + CHECK_RESULT(ParseCommandList(&script->commands)); + } else { + ConsumeIfLpar(); + ErrorExpected({"a module field", "a command"}); + } + + EXPECT(Eof); + return errors_ == 0 ? Result::Ok : Result::Error; +} + +Result WastParser::ParseModuleFieldList(Module* module) { + WABT_TRACE(ParseModuleFieldList); + while (PeekMatch(TokenType::Lpar)) { + if (Failed(ParseModuleField(module))) { + CHECK_RESULT(Synchronize(IsModuleField)); + } + } + ResolveFuncTypes(module); + return Result::Ok; +} + +Result WastParser::ParseModuleField(Module* module) { + WABT_TRACE(ParseModuleField); + switch (Peek(1)) { + case TokenType::Data: return ParseDataModuleField(module); + case TokenType::Elem: return ParseElemModuleField(module); + case TokenType::Except: return ParseExceptModuleField(module); + case TokenType::Export: return ParseExportModuleField(module); + case TokenType::Func: return ParseFuncModuleField(module); + case TokenType::Type: return ParseTypeModuleField(module); + case TokenType::Global: return ParseGlobalModuleField(module); + case TokenType::Import: return ParseImportModuleField(module); + case TokenType::Memory: return ParseMemoryModuleField(module); + case TokenType::Start: return ParseStartModuleField(module); + case TokenType::Table: return ParseTableModuleField(module); + default: + assert( + !"ParseModuleField should only be called if IsModuleField() is true"); + return Result::Error; + } +} + +Result WastParser::ParseDataModuleField(Module* module) { + WABT_TRACE(ParseDataModuleField); + EXPECT(Lpar); + auto loc = GetLocation(); + EXPECT(Data); + auto data_segment = make_unique(); + ParseVarOpt(&data_segment->memory_var, Var(0, loc)); + CHECK_RESULT(ParseOffsetExpr(&data_segment->offset)); + ParseTextListOpt(&data_segment->data); + EXPECT(Rpar); + module->AppendField(new DataSegmentModuleField(data_segment.release(), loc)); + return Result::Ok; +} + +Result WastParser::ParseElemModuleField(Module* module) { + WABT_TRACE(ParseElemModuleField); + EXPECT(Lpar); + auto loc = GetLocation(); + EXPECT(Elem); + auto elem_segment = make_unique(); + ParseVarOpt(&elem_segment->table_var, Var(0, loc)); + CHECK_RESULT(ParseOffsetExpr(&elem_segment->offset)); + ParseVarListOpt(&elem_segment->vars); + EXPECT(Rpar); + module->AppendField(new ElemSegmentModuleField(elem_segment.release(), loc)); + return Result::Ok; +} + +Result WastParser::ParseExceptModuleField(Module* module) { + WABT_TRACE(ParseExceptModuleField); + EXPECT(Lpar); + auto loc = GetLocation(); + EXPECT(Except); + auto exception = make_unique(); + ParseBindVarOpt(&exception->name); + ParseValueTypeList(&exception->sig); + EXPECT(Rpar); + module->AppendField(new ExceptionModuleField(exception.release(), loc)); + return Result::Ok; +} + +Result WastParser::ParseExportModuleField(Module* module) { + WABT_TRACE(ParseExportModuleField); + EXPECT(Lpar); + auto loc = GetLocation(); + EXPECT(Export); + auto export_ = make_unique(); + CHECK_RESULT(ParseQuotedText(&export_->name)); + CHECK_RESULT(ParseExportDesc(export_.get())); + EXPECT(Rpar); + module->AppendField(new ExportModuleField(export_.release(), loc)); + return Result::Ok; +} + +Result WastParser::ParseFuncModuleField(Module* module) { + WABT_TRACE(ParseFuncModuleField); + EXPECT(Lpar); + auto loc = GetLocation(); + EXPECT(Func); + auto func = make_unique(); + ParseBindVarOpt(&func->name); + + ModuleFieldList export_fields; + CHECK_RESULT(ParseInlineExports(&export_fields, ExternalKind::Func)); + + if (PeekMatchLpar(TokenType::Import)) { + CheckImportOrdering(module); + auto import_loc = GetLocation(); + auto import = make_unique(); + import->kind = ExternalKind::Func; + import->func = func.release(); + CHECK_RESULT(ParseInlineImport(import.get())); + CHECK_RESULT(ParseTypeUseOpt(&import->func->decl)); + CHECK_RESULT(ParseFuncSignature(&import->func->decl.sig, + &import->func->param_bindings)); + CHECK_RESULT(ErrorIfLpar({"type", "param", "result"})); + module->AppendField(new ImportModuleField(import.release(), import_loc)); + } else { + CHECK_RESULT(ParseTypeUseOpt(&func->decl)); + CHECK_RESULT(ParseFuncSignature(&func->decl.sig, &func->param_bindings)); + CHECK_RESULT(ParseBoundValueTypeList(TokenType::Local, &func->local_types, + &func->local_bindings)); + CHECK_RESULT(ParseTerminatingInstrList(&func->exprs)); + module->AppendField(new FuncModuleField(func.release(), loc)); + } + + AppendInlineExportFields(module, &export_fields, module->funcs.size() - 1); + + EXPECT(Rpar); + return Result::Ok; +} + +Result WastParser::ParseTypeModuleField(Module* module) { + WABT_TRACE(ParseTypeModuleField); + EXPECT(Lpar); + auto loc = GetLocation(); + EXPECT(Type); + auto func_type = make_unique(); + ParseBindVarOpt(&func_type->name); + EXPECT(Lpar); + EXPECT(Func); + BindingHash bindings; + CHECK_RESULT(ParseFuncSignature(&func_type->sig, &bindings)); + CHECK_RESULT(ErrorIfLpar({"param", "result"})); + EXPECT(Rpar); + EXPECT(Rpar); + module->AppendField(new FuncTypeModuleField(func_type.release(), loc)); + return Result::Ok; +} + +Result WastParser::ParseGlobalModuleField(Module* module) { + WABT_TRACE(ParseGlobalModuleField); + EXPECT(Lpar); + auto loc = GetLocation(); + EXPECT(Global); + auto global = make_unique(); + ParseBindVarOpt(&global->name); + + ModuleFieldList export_fields; + CHECK_RESULT(ParseInlineExports(&export_fields, ExternalKind::Global)); + + if (PeekMatchLpar(TokenType::Import)) { + CheckImportOrdering(module); + auto import_loc = GetLocation(); + auto import = make_unique(); + import->kind = ExternalKind::Global; + import->global = global.release(); + CHECK_RESULT(ParseInlineImport(import.get())); + CHECK_RESULT(ParseGlobalType(import->global)); + module->AppendField(new ImportModuleField(import.release(), import_loc)); + } else { + CHECK_RESULT(ParseGlobalType(global.get())); + CHECK_RESULT(ParseTerminatingInstrList(&global->init_expr)); + module->AppendField(new GlobalModuleField(global.release(), loc)); + } + + AppendInlineExportFields(module, &export_fields, module->globals.size() - 1); + + EXPECT(Rpar); + return Result::Ok; +} + +Result WastParser::ParseImportModuleField(Module* module) { + WABT_TRACE(ParseImportModuleField); + EXPECT(Lpar); + auto loc = GetLocation(); + CheckImportOrdering(module); + EXPECT(Import); + auto import = make_unique(); + CHECK_RESULT(ParseQuotedText(&import->module_name)); + CHECK_RESULT(ParseQuotedText(&import->field_name)); + EXPECT(Lpar); + switch (Peek()) { + case TokenType::Func: + Consume(); + import->kind = ExternalKind::Func; + import->func = new Func(); + ParseBindVarOpt(&import->func->name); + if (PeekMatchLpar(TokenType::Type)) { + import->func->decl.has_func_type = true; + CHECK_RESULT(ParseTypeUseOpt(&import->func->decl)); + EXPECT(Rpar); + } else { + CHECK_RESULT(ParseFuncSignature(&import->func->decl.sig, + &import->func->param_bindings)); + CHECK_RESULT(ErrorIfLpar({"param", "result"})); + EXPECT(Rpar); + } + break; + + case TokenType::Table: + Consume(); + import->kind = ExternalKind::Table; + import->table = new Table(); + ParseBindVarOpt(&import->table->name); + CHECK_RESULT(ParseLimits(&import->table->elem_limits)); + EXPECT(Anyfunc); + EXPECT(Rpar); + break; + + case TokenType::Memory: + Consume(); + import->kind = ExternalKind::Memory; + import->memory = new Memory(); + ParseBindVarOpt(&import->memory->name); + CHECK_RESULT(ParseLimits(&import->memory->page_limits)); + EXPECT(Rpar); + break; + + case TokenType::Global: + Consume(); + import->kind = ExternalKind::Global; + import->global = new Global(); + ParseBindVarOpt(&import->global->name); + CHECK_RESULT(ParseGlobalType(import->global)); + EXPECT(Rpar); + break; + + case TokenType::Except: + Consume(); + import->kind = ExternalKind::Except; + import->except = new Exception(); + ParseBindVarOpt(&import->except->name); + ParseValueTypeList(&import->except->sig); + EXPECT(Rpar); + break; + + default: + return ErrorExpected({"an external kind"}); + } + + module->AppendField(new ImportModuleField(import.release(), loc)); + EXPECT(Rpar); + return Result::Ok; +} + +Result WastParser::ParseMemoryModuleField(Module* module) { + WABT_TRACE(ParseMemoryModuleField); + EXPECT(Lpar); + auto loc = GetLocation(); + EXPECT(Memory); + auto memory = make_unique(); + ParseBindVarOpt(&memory->name); + + ModuleFieldList export_fields; + CHECK_RESULT(ParseInlineExports(&export_fields, ExternalKind::Memory)); + + if (PeekMatchLpar(TokenType::Import)) { + CheckImportOrdering(module); + auto import_loc = GetLocation(); + auto import = make_unique(); + import->kind = ExternalKind::Memory; + import->memory = memory.release(); + CHECK_RESULT(ParseInlineImport(import.get())); + CHECK_RESULT(ParseLimits(&import->memory->page_limits)); + module->AppendField(new ImportModuleField(import.release(), import_loc)); + } else if (MatchLpar(TokenType::Data)) { + auto data_segment = make_unique(); + data_segment->memory_var = Var(module->memories.size()); + data_segment->offset.push_back(new ConstExpr(Const(Const::I32(), 0))); + data_segment->offset.back().loc = loc; + ParseTextListOpt(&data_segment->data); + EXPECT(Rpar); + + uint32_t byte_size = WABT_ALIGN_UP_TO_PAGE(data_segment->data.size()); + uint32_t page_size = WABT_BYTES_TO_PAGES(byte_size); + memory->page_limits.initial = page_size; + memory->page_limits.max = page_size; + memory->page_limits.has_max = true; + + module->AppendField(new MemoryModuleField(memory.release(), loc)); + module->AppendField( + new DataSegmentModuleField(data_segment.release(), loc)); + } else { + CHECK_RESULT(ParseLimits(&memory->page_limits)); + module->AppendField(new MemoryModuleField(memory.release(), loc)); + } + + AppendInlineExportFields(module, &export_fields, module->memories.size() - 1); + + EXPECT(Rpar); + return Result::Ok; +} + +Result WastParser::ParseStartModuleField(Module* module) { + WABT_TRACE(ParseStartModuleField); + EXPECT(Lpar); + auto loc = GetLocation(); + EXPECT(Start); + Var var; + CHECK_RESULT(ParseVar(&var)); + EXPECT(Rpar); + module->AppendField(new StartModuleField(var, loc)); + return Result::Ok; +} + +Result WastParser::ParseTableModuleField(Module* module) { + WABT_TRACE(ParseTableModuleField); + EXPECT(Lpar); + auto loc = GetLocation(); + EXPECT(Table); + auto table = make_unique(); + ParseBindVarOpt(&table->name); + + ModuleFieldList export_fields; + CHECK_RESULT(ParseInlineExports(&export_fields, ExternalKind::Table)); + + if (PeekMatchLpar(TokenType::Import)) { + CheckImportOrdering(module); + auto import_loc = GetLocation(); + auto import = make_unique(); + import->kind = ExternalKind::Table; + import->table = table.release(); + CHECK_RESULT(ParseInlineImport(import.get())); + CHECK_RESULT(ParseLimits(&import->table->elem_limits)); + EXPECT(Anyfunc); + module->AppendField(new ImportModuleField(import.release(), import_loc)); + } else if (Match(TokenType::Anyfunc)) { + EXPECT(Lpar); + EXPECT(Elem); + + auto elem_segment = make_unique(); + elem_segment->table_var = Var(module->tables.size()); + elem_segment->offset.push_back(new ConstExpr(Const(Const::I32(), 0))); + elem_segment->offset.back().loc = loc; + CHECK_RESULT(ParseVarList(&elem_segment->vars)); + EXPECT(Rpar); + + table->elem_limits.initial = elem_segment->vars.size(); + table->elem_limits.max = elem_segment->vars.size(); + table->elem_limits.has_max = true; + module->AppendField(new TableModuleField(table.release(), loc)); + module->AppendField( + new ElemSegmentModuleField(elem_segment.release(), loc)); + } else { + CHECK_RESULT(ParseLimits(&table->elem_limits)); + EXPECT(Anyfunc); + module->AppendField(new TableModuleField(table.release(), loc)); + } + + AppendInlineExportFields(module, &export_fields, module->tables.size() - 1); + + EXPECT(Rpar); + return Result::Ok; +} + +Result WastParser::ParseExportDesc(Export* export_) { + WABT_TRACE(ParseExportDesc); + EXPECT(Lpar); + switch (Peek()) { + case TokenType::Func: export_->kind = ExternalKind::Func; break; + case TokenType::Table: export_->kind = ExternalKind::Table; break; + case TokenType::Memory: export_->kind = ExternalKind::Memory; break; + case TokenType::Global: export_->kind = ExternalKind::Global; break; + case TokenType::Except: export_->kind = ExternalKind::Except; break; + default: + return ErrorExpected({"an external kind"}); + } + Consume(); + CHECK_RESULT(ParseVar(&export_->var)); + EXPECT(Rpar); + return Result::Ok; +} + +Result WastParser::ParseInlineExports(ModuleFieldList* fields, + ExternalKind kind) { + WABT_TRACE(ParseInlineExports); + while (PeekMatchLpar(TokenType::Export)) { + EXPECT(Lpar); + auto loc = GetLocation(); + EXPECT(Export); + auto export_ = make_unique(); + export_->kind = kind; + CHECK_RESULT(ParseQuotedText(&export_->name)); + EXPECT(Rpar); + fields->push_back(new ExportModuleField(export_.release(), loc)); + } + return Result::Ok; +} + +Result WastParser::ParseInlineImport(Import* import) { + WABT_TRACE(ParseInlineImport); + EXPECT(Lpar); + EXPECT(Import); + CHECK_RESULT(ParseQuotedText(&import->module_name)); + CHECK_RESULT(ParseQuotedText(&import->field_name)); + EXPECT(Rpar); + return Result::Ok; +} + +Result WastParser::ParseTypeUseOpt(FuncDeclaration* decl) { + WABT_TRACE(ParseTypeUseOpt); + if (MatchLpar(TokenType::Type)) { + decl->has_func_type = true;; + CHECK_RESULT(ParseVar(&decl->type_var)); + EXPECT(Rpar); + } else { + decl->has_func_type = false; + } + return Result::Ok; +} + +Result WastParser::ParseFuncSignature(FuncSignature* sig, + BindingHash* param_bindings) { + WABT_TRACE(ParseFuncSignature); + CHECK_RESULT(ParseBoundValueTypeList(TokenType::Param, &sig->param_types, + param_bindings)); + CHECK_RESULT(ParseResultList(&sig->result_types)); + return Result::Ok; +} + +Result WastParser::ParseBoundValueTypeList(TokenType token, + TypeVector* types, + BindingHash* bindings) { + WABT_TRACE(ParseBoundValueTypeList); + while (MatchLpar(token)) { + if (PeekMatch(TokenType::Var)) { + std::string name; + Type type; + auto loc = GetLocation(); + ParseBindVarOpt(&name); + CHECK_RESULT(ParseValueType(&type)); + bindings->emplace(name, Binding(loc, types->size())); + types->push_back(type); + } else { + ParseValueTypeList(types); + } + EXPECT(Rpar); + } + return Result::Ok; +} + +Result WastParser::ParseResultList(TypeVector* result_types) { + WABT_TRACE(ParseResultList); + while (MatchLpar(TokenType::Result)) { + ParseValueTypeList(result_types); + EXPECT(Rpar); + } + return Result::Ok; +} + +Result WastParser::ParseInstrList(ExprList* exprs) { + WABT_TRACE(ParseInstrList); + ExprList new_exprs; + while (IsInstr(PeekPair())) { + if (Succeeded(ParseInstr(&new_exprs))) { + exprs->splice(exprs->end(), new_exprs); + } else { + CHECK_RESULT(Synchronize(IsInstr)); + } + } + return Result::Ok; +} + +Result WastParser::ParseTerminatingInstrList(ExprList* exprs) { + WABT_TRACE(ParseTerminatingInstrList); + Result result = ParseInstrList(exprs); + // An InstrList often has no further Lpar following it, because it would have + // gobbled it up. So if there is a following Lpar it is an error. If we + // handle it here we can produce a nicer error message. + CHECK_RESULT(ErrorIfLpar({"an instr"})); + return result; +} + +Result WastParser::ParseInstr(ExprList* exprs) { + WABT_TRACE(ParseInstr); + if (IsPlainInstr(Peek())) { + std::unique_ptr expr; + CHECK_RESULT(ParsePlainInstr(&expr)); + exprs->push_back(expr.release()); + return Result::Ok; + } else if (IsBlockInstr(Peek())) { + std::unique_ptr expr; + CHECK_RESULT(ParseBlockInstr(&expr)); + exprs->push_back(expr.release()); + return Result::Ok; + } else if (PeekMatchExpr()) { + return ParseExpr(exprs); + } else { + assert(!"ParseInstr should only be called when IsInstr() is true"); + return Result::Error; + } +} + +template +Result WastParser::ParsePlainInstrVar(Location loc, + std::unique_ptr* out_expr) { + Var var; + CHECK_RESULT(ParseVar(&var)); + out_expr->reset(new T(var, loc)); + return Result::Ok; +} + +Result WastParser::ParsePlainInstr(std::unique_ptr* out_expr) { + WABT_TRACE(ParsePlainInstr); + auto loc = GetLocation(); + switch (Peek()) { + case TokenType::Unreachable: + Consume(); + out_expr->reset(new UnreachableExpr(loc)); + break; + + case TokenType::Nop: + Consume(); + out_expr->reset(new NopExpr(loc)); + break; + + case TokenType::Drop: + Consume(); + out_expr->reset(new DropExpr(loc)); + break; + + case TokenType::Select: + Consume(); + out_expr->reset(new SelectExpr(loc)); + break; + + case TokenType::Br: + Consume(); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + + case TokenType::BrIf: + Consume(); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + + case TokenType::BrTable: { + Consume(); + auto var_list = make_unique(); + CHECK_RESULT(ParseVarList(var_list.get())); + Var var = var_list->back(); + var_list->pop_back(); + out_expr->reset(new BrTableExpr(var_list.release(), var, loc)); + break; + } + + case TokenType::Return: + Consume(); + out_expr->reset(new ReturnExpr(loc)); + break; + + case TokenType::Call: + Consume(); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + + case TokenType::CallIndirect: + Consume(); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + + case TokenType::GetLocal: + Consume(); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + + case TokenType::SetLocal: + Consume(); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + + case TokenType::TeeLocal: + Consume(); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + + case TokenType::GetGlobal: + Consume(); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + + case TokenType::SetGlobal: + Consume(); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + + case TokenType::Load: { + Opcode opcode = Consume().opcode; + uint32_t offset; + uint32_t align; + ParseOffsetOpt(&offset); + ParseAlignOpt(&align); + out_expr->reset(new LoadExpr(opcode, align, offset, loc)); + break; + } + + case TokenType::Store: { + Opcode opcode = Consume().opcode; + uint32_t offset; + uint32_t align; + ParseOffsetOpt(&offset); + ParseAlignOpt(&align); + out_expr->reset(new StoreExpr(opcode, align, offset, loc)); + break; + } + + case TokenType::Const: { + Const const_; + CHECK_RESULT(ParseConst(&const_)); + out_expr->reset(new ConstExpr(const_, loc)); + break; + } + + case TokenType::Unary: + out_expr->reset(new UnaryExpr(Consume().opcode, loc)); + break; + + case TokenType::Binary: + out_expr->reset(new BinaryExpr(Consume().opcode, loc)); + break; + + case TokenType::Compare: + out_expr->reset(new CompareExpr(Consume().opcode, loc)); + break; + + case TokenType::Convert: { + auto token = Consume(); + ErrorUnlessOpcodeEnabled(token); + out_expr->reset(new ConvertExpr(token.opcode, loc)); + break; + } + + case TokenType::CurrentMemory: + Consume(); + out_expr->reset(new CurrentMemoryExpr(loc)); + break; + + case TokenType::GrowMemory: + Consume(); + out_expr->reset(new GrowMemoryExpr(loc)); + break; + + case TokenType::Throw: + ErrorUnlessOpcodeEnabled(Consume()); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + + case TokenType::Rethrow: + ErrorUnlessOpcodeEnabled(Consume()); + CHECK_RESULT(ParsePlainInstrVar(loc, out_expr)); + break; + + default: + assert( + !"ParsePlainInstr should only be called when IsPlainInstr() is true"); + return Result::Error; + } + + return Result::Ok; +} + +Result WastParser::ParseConst(Const* const_) { + WABT_TRACE(ParseConst); + auto opcode = Consume().opcode; + LiteralTerminal literal; + + auto loc = GetLocation(); + + switch (Peek()) { + case TokenType::Nat: + case TokenType::Int: + case TokenType::Float: + literal = Consume().literal; + break; + + default: + return ErrorExpected({"a numeric literal"}, "123, -45, 6.7e8"); + } + + string_view sv = literal.text.to_string_view(); + const char* s = sv.begin(); + const char* end = sv.end(); + + Result result; + switch (opcode) { + case Opcode::I32Const: + const_->type = Type::I32; + result = + ParseInt32(s, end, &const_->u32, ParseIntType::SignedAndUnsigned); + break; + + case Opcode::I64Const: + const_->type = Type::I64; + result = + ParseInt64(s, end, &const_->u64, ParseIntType::SignedAndUnsigned); + break; + + case Opcode::F32Const: + const_->type = Type::F32; + result = ParseFloat(literal.type, s, end, &const_->f32_bits); + break; + + case Opcode::F64Const: + const_->type = Type::F64; + result = ParseDouble(literal.type, s, end, &const_->f64_bits); + break; + + default: + assert(!"ParseConst called with invalid opcode"); + return Result::Error; + } + + if (Failed(result)) { + Error(loc, "invalid literal \"%s\"", literal.text.to_string().c_str()); + } + + return Result::Ok; +} + +Result WastParser::ParseConstList(ConstVector* consts) { + WABT_TRACE(ParseConstList); + while (PeekMatchLpar(TokenType::Const)) { + Consume(); + Const const_; + CHECK_RESULT(ParseConst(&const_)); + EXPECT(Rpar); + consts->push_back(const_); + } + + return Result::Ok; +} + +Result WastParser::ParseBlockInstr(std::unique_ptr* out_expr) { + WABT_TRACE(ParseBlockInstr); + auto loc = GetLocation(); + + switch (Peek()) { + case TokenType::Block: { + Consume(); + auto block = make_unique(); + CHECK_RESULT(ParseLabelOpt(&block->label)); + CHECK_RESULT(ParseBlock(block.get())); + EXPECT(End); + CHECK_RESULT(ParseEndLabelOpt(block->label)); + out_expr->reset(new BlockExpr(block.release(), loc)); + break; + } + + case TokenType::Loop: { + Consume(); + auto block = make_unique(); + CHECK_RESULT(ParseLabelOpt(&block->label)); + CHECK_RESULT(ParseBlock(block.get())); + EXPECT(End); + CHECK_RESULT(ParseEndLabelOpt(block->label)); + out_expr->reset(new LoopExpr(block.release(), loc)); + break; + } + + case TokenType::If: { + Consume(); + auto true_ = make_unique(); + ExprList false_; + CHECK_RESULT(ParseLabelOpt(&true_->label)); + CHECK_RESULT(ParseBlock(true_.get())); + if (Match(TokenType::Else)) { + CHECK_RESULT(ParseEndLabelOpt(true_->label)); + CHECK_RESULT(ParseTerminatingInstrList(&false_)); + } + EXPECT(End); + CHECK_RESULT(ParseEndLabelOpt(true_->label)); + out_expr->reset(new IfExpr(true_.release(), std::move(false_), loc)); + break; + } + + case TokenType::Try: { + ErrorUnlessOpcodeEnabled(Consume()); + auto expr = make_unique(loc); + expr->block = new Block(); + CatchVector catches; + CHECK_RESULT(ParseLabelOpt(&expr->block->label)); + CHECK_RESULT(ParseBlock(expr->block)); + CHECK_RESULT(ParseCatchInstrList(&expr->catches)); + CHECK_RESULT(ErrorIfLpar({"a catch expr"})); + EXPECT(End); + CHECK_RESULT(ParseEndLabelOpt(expr->block->label)); + *out_expr = std::move(expr); + break; + } + + default: + assert( + !"ParseBlockInstr should only be called when IsBlockInstr() is true"); + return Result::Error; + } + + return Result::Ok; +} + +Result WastParser::ParseLabelOpt(std::string* out_label) { + WABT_TRACE(ParseLabelOpt); + if (PeekMatch(TokenType::Var)) { + *out_label = Consume().text.to_string(); + } else { + out_label->clear(); + } + return Result::Ok; +} + +Result WastParser::ParseEndLabelOpt(const std::string& begin_label) { + WABT_TRACE(ParseEndLabelOpt); + auto loc = GetLocation(); + std::string end_label; + CHECK_RESULT(ParseLabelOpt(&end_label)); + if (!end_label.empty()) { + if (begin_label.empty()) { + Error(loc, "unexpected label \"%s\"", end_label.c_str()); + } else if (begin_label != end_label) { + Error(loc, "mismatching label \"%s\" != \"%s\"", begin_label.c_str(), + end_label.c_str()); + } + } + return Result::Ok; +} + +Result WastParser::ParseBlock(Block* block) { + WABT_TRACE(ParseBlock); + CHECK_RESULT(ParseResultList(&block->sig)); + CHECK_RESULT(ParseInstrList(&block->exprs)); + return Result::Ok; +} + +Result WastParser::ParseExprList(ExprList* exprs) { + WABT_TRACE(ParseExprList); + ExprList new_exprs; + while (PeekMatchExpr()) { + if (Succeeded(ParseExpr(&new_exprs))) { + exprs->splice(exprs->end(), new_exprs); + } else { + CHECK_RESULT(Synchronize(IsExpr)); + } + } + return Result::Ok; +} + +Result WastParser::ParseExpr(ExprList* exprs) { + WABT_TRACE(ParseExpr); + if (!PeekMatch(TokenType::Lpar)) + return Result::Error; + + if (IsPlainInstr(Peek(1))) { + Consume(); + std::unique_ptr expr; + CHECK_RESULT(ParsePlainInstr(&expr)); + CHECK_RESULT(ParseExprList(exprs)); + CHECK_RESULT(ErrorIfLpar({"an expr"})); + exprs->push_back(expr.release()); + } else { + auto loc = GetLocation(); + + switch (Peek(1)) { + case TokenType::Block: { + Consume(); + Consume(); + auto block = make_unique(); + CHECK_RESULT(ParseLabelOpt(&block->label)); + CHECK_RESULT(ParseBlock(block.get())); + exprs->push_back(new BlockExpr(block.release(), loc)); + break; + } + + case TokenType::Loop: { + Consume(); + Consume(); + auto block = make_unique(); + CHECK_RESULT(ParseLabelOpt(&block->label)); + CHECK_RESULT(ParseBlock(block.get())); + exprs->push_back(new LoopExpr(block.release(), loc)); + break; + } + + case TokenType::If: { + Consume(); + Consume(); + auto true_ = make_unique(); + ExprList false_; + + CHECK_RESULT(ParseLabelOpt(&true_->label)); + CHECK_RESULT(ParseResultList(&true_->sig)); + + if (PeekMatchExpr()) { + ExprList cond; + CHECK_RESULT(ParseExpr(&cond)); + exprs->splice(exprs->end(), cond); + } + + if (MatchLpar(TokenType::Then)) { + CHECK_RESULT(ParseTerminatingInstrList(&true_->exprs)); + EXPECT(Rpar); + + if (MatchLpar(TokenType::Else)) { + CHECK_RESULT(ParseTerminatingInstrList(&false_)); + EXPECT(Rpar); + } else if (PeekMatchExpr()) { + CHECK_RESULT(ParseExpr(&false_)); + } + } else if (PeekMatchExpr()) { + CHECK_RESULT(ParseExpr(&true_->exprs)); + if (PeekMatchExpr()) { + CHECK_RESULT(ParseExpr(&false_)); + } + } else { + ConsumeIfLpar(); + return ErrorExpected({"then block"}, "(then ...)"); + } + + exprs->push_back(new IfExpr(true_.release(), std::move(false_), loc)); + break; + } + + case TokenType::Try: { + Consume(); + ErrorUnlessOpcodeEnabled(Consume()); + + auto block = make_unique(); + CHECK_RESULT(ParseLabelOpt(&block->label)); + CHECK_RESULT(ParseResultList(&block->sig)); + CHECK_RESULT(ParseInstrList(&block->exprs)); + auto try_ = make_unique(loc); + try_->block = block.release(); + CHECK_RESULT(ParseCatchExprList(&try_->catches)); + CHECK_RESULT(ErrorIfLpar({"a catch expr"})); + + exprs->push_back(try_.release()); + break; + } + + default: + assert(!"ParseExpr should only be called when IsExpr() is true"); + return Result::Error; + } + } + + EXPECT(Rpar); + return Result::Ok; +} + +Result WastParser::ParseCatchInstrList(CatchVector* catches) { + WABT_TRACE(ParseCatchInstrList); + while (IsCatch(Peek())) { + auto catch_ = make_unique(); + catch_->loc = GetLocation(); + + if (Consume().token_type == TokenType::Catch) + CHECK_RESULT(ParseVar(&catch_->var)); + + CHECK_RESULT(ParseInstrList(&catch_->exprs)); + catches->push_back(catch_.release()); + } + + return Result::Ok; +} + +Result WastParser::ParseCatchExprList(CatchVector* catches) { + WABT_TRACE(ParseCatchExprList); + while (PeekMatch(TokenType::Lpar) && IsCatch(Peek(1))) { + Consume(); + auto catch_ = make_unique(); + catch_->loc = GetLocation(); + + if (Consume().token_type == TokenType::Catch) + CHECK_RESULT(ParseVar(&catch_->var)); + + CHECK_RESULT(ParseTerminatingInstrList(&catch_->exprs)); + EXPECT(Rpar); + catches->push_back(catch_.release()); + } + + return Result::Ok; +} + +Result WastParser::ParseGlobalType(Global* global) { + WABT_TRACE(ParseGlobalType); + if (MatchLpar(TokenType::Mut)) { + global->mutable_ = true; + CHECK_RESULT(ParseValueType(&global->type)); + CHECK_RESULT(ErrorIfLpar({"i32", "i64", "f32", "f64"})); + EXPECT(Rpar); + } else { + CHECK_RESULT(ParseValueType(&global->type)); + } + + return Result::Ok; +} + +Result WastParser::ParseCommandList(CommandPtrVector* commands) { + WABT_TRACE(ParseCommandList); + while (PeekMatch(TokenType::Lpar)) { + CommandPtr command; + if (Succeeded(ParseCommand(&command))) { + commands->push_back(std::move(command)); + } else { + CHECK_RESULT(Synchronize(IsCommand)); + } + } + return Result::Ok; +} + +Result WastParser::ParseCommand(CommandPtr* out_command) { + WABT_TRACE(ParseCommand); + switch (Peek(1)) { + case TokenType::AssertExhaustion: + return ParseAssertExhaustionCommand(out_command); + + case TokenType::AssertInvalid: + return ParseAssertInvalidCommand(out_command); + + case TokenType::AssertMalformed: + return ParseAssertMalformedCommand(out_command); + + case TokenType::AssertReturn: + return ParseAssertReturnCommand(out_command); + + case TokenType::AssertReturnArithmeticNan: + return ParseAssertReturnArithmeticNanCommand(out_command); + + case TokenType::AssertReturnCanonicalNan: + return ParseAssertReturnCanonicalNanCommand(out_command); + + case TokenType::AssertTrap: + return ParseAssertTrapCommand(out_command); + + case TokenType::AssertUnlinkable: + return ParseAssertUnlinkableCommand(out_command); + + case TokenType::Get: + case TokenType::Invoke: + return ParseActionCommand(out_command); + + case TokenType::Module: + return ParseModuleCommand(out_command); + + case TokenType::Register: + return ParseRegisterCommand(out_command); + + default: + assert(!"ParseCommand should only be called when IsCommand() is true"); + return Result::Error; + } +} + +Result WastParser::ParseAssertExhaustionCommand(CommandPtr* out_command) { + WABT_TRACE(ParseAssertExhaustionCommand); + return ParseAssertActionTextCommand( + TokenType::AssertExhaustion, out_command); +} + +Result WastParser::ParseAssertInvalidCommand(CommandPtr* out_command) { + WABT_TRACE(ParseAssertInvalidCommand); + return ParseAssertScriptModuleCommand( + TokenType::AssertInvalid, out_command); +} + +Result WastParser::ParseAssertMalformedCommand(CommandPtr* out_command) { + WABT_TRACE(ParseAssertMalformedCommand); + return ParseAssertScriptModuleCommand( + TokenType::AssertMalformed, out_command); +} + +Result WastParser::ParseAssertReturnCommand(CommandPtr* out_command) { + WABT_TRACE(ParseAssertReturnCommand); + EXPECT(Lpar); + EXPECT(AssertReturn); + auto action = make_unique(); + auto consts = make_unique(); + CHECK_RESULT(ParseAction(action.get())); + CHECK_RESULT(ParseConstList(consts.get())); + EXPECT(Rpar); + out_command->reset( + new AssertReturnCommand(action.release(), consts.release())); + return Result::Ok; +} + +Result WastParser::ParseAssertReturnArithmeticNanCommand( + CommandPtr* out_command) { + WABT_TRACE(ParseAssertReturnArithmeticNanCommand); + return ParseAssertActionCommand( + TokenType::AssertReturnArithmeticNan, out_command); +} + +Result WastParser::ParseAssertReturnCanonicalNanCommand( + CommandPtr* out_command) { + WABT_TRACE(ParseAssertReturnCanonicalNanCommand); + return ParseAssertActionCommand( + TokenType::AssertReturnCanonicalNan, out_command); +} + +Result WastParser::ParseAssertTrapCommand(CommandPtr* out_command) { + WABT_TRACE(ParseAssertTrapCommand); + EXPECT(Lpar); + EXPECT(AssertTrap); + if (PeekMatchLpar(TokenType::Module)) { + std::unique_ptr module; + std::string text; + CHECK_RESULT(ParseScriptModule(&module)); + CHECK_RESULT(ParseQuotedText(&text)); + out_command->reset(new AssertUninstantiableCommand(module.release(), text)); + } else { + auto action = make_unique(); + std::string text; + CHECK_RESULT(ParseAction(action.get())); + CHECK_RESULT(ParseQuotedText(&text)); + out_command->reset(new AssertTrapCommand(action.release(), text)); + } + EXPECT(Rpar); + return Result::Ok; +} + +Result WastParser::ParseAssertUnlinkableCommand(CommandPtr* out_command) { + WABT_TRACE(ParseAssertUnlinkableCommand); + return ParseAssertScriptModuleCommand( + TokenType::AssertUnlinkable, out_command); +} + +Result WastParser::ParseActionCommand(CommandPtr* out_command) { + WABT_TRACE(ParseActionCommand); + auto action = make_unique(); + CHECK_RESULT(ParseAction(action.get())); + out_command->reset(new ActionCommand(action.release())); + return Result::Ok; +} + +Result WastParser::ParseModuleCommand(CommandPtr* out_command) { + WABT_TRACE(ParseModuleCommand); + std::unique_ptr script_module; + CHECK_RESULT(ParseScriptModule(&script_module)); + + std::unique_ptr module; + + switch (script_module->type) { + case ScriptModule::Type::Text: + module.reset(script_module->text); + script_module->text = nullptr; + break; + + case ScriptModule::Type::Binary: { + module.reset(new Module()); + ReadBinaryOptions options; + BinaryErrorHandlerModule error_handler(&script_module->binary.loc, this); + const char* filename = ""; + ReadBinaryIr(filename, script_module->binary.data.data(), + script_module->binary.data.size(), &options, &error_handler, + module.get()); + module->name = script_module->binary.name; + module->loc = script_module->binary.loc; + break; + } + + case ScriptModule::Type::Quoted: + return ErrorExpected({"a binary module", "a text module"}); + } + + Index command_index = script_->commands.size(); + + if (!module->name.empty()) { + script_->module_bindings.emplace(module->name, + Binding(module->loc, command_index)); + } + + last_module_index_ = command_index; + + out_command->reset(new ModuleCommand(module.release())); + return Result::Ok; +} + +Result WastParser::ParseRegisterCommand(CommandPtr* out_command) { + WABT_TRACE(ParseRegisterCommand); + EXPECT(Lpar); + auto loc = GetLocation(); + EXPECT(Register); + std::string text; + Var var; + CHECK_RESULT(ParseQuotedText(&text)); + ParseVarOpt(&var, Var(last_module_index_, loc)); + EXPECT(Rpar); + out_command->reset(new RegisterCommand(text, var)); + return Result::Ok; +} + +Result WastParser::ParseAction(Action* out_action) { + WABT_TRACE(ParseAction); + EXPECT(Lpar); + auto loc = GetLocation(); + + switch (Peek()) { + case TokenType::Invoke: + out_action->loc = loc; + out_action->type = ActionType::Invoke; + out_action->invoke = new ActionInvoke(); + + Consume(); + ParseVarOpt(&out_action->module_var, Var(last_module_index_, loc)); + CHECK_RESULT(ParseQuotedText(&out_action->name)); + CHECK_RESULT(ParseConstList(&out_action->invoke->args)); + break; + + case TokenType::Get: + out_action->loc = loc; + out_action->type = ActionType::Get; + + Consume(); + ParseVarOpt(&out_action->module_var, Var(last_module_index_, loc)); + CHECK_RESULT(ParseQuotedText(&out_action->name)); + break; + + default: + return ErrorExpected({"invoke", "get"}); + } + EXPECT(Rpar); + return Result::Ok; +} + +Result WastParser::ParseScriptModule( + std::unique_ptr* out_module) { + WABT_TRACE(ParseScriptModule); + EXPECT(Lpar); + auto loc = GetLocation(); + EXPECT(Module); + std::string name; + ParseBindVarOpt(&name); + + std::unique_ptr script_module; + + switch (Peek()) { + case TokenType::Bin: { + Consume(); + std::vector data; + CHECK_RESULT(ParseTextList(&data)); + + script_module = make_unique(ScriptModule::Type::Binary); + script_module->binary.name = name; + script_module->binary.loc = loc; + script_module->binary.data = std::move(data); + break; + } + + case TokenType::Quote: { + Consume(); + std::vector data; + CHECK_RESULT(ParseTextList(&data)); + + script_module = make_unique(ScriptModule::Type::Quoted); + script_module->quoted.name = name; + script_module->quoted.loc = loc; + script_module->quoted.data = std::move(data); + break; + } + + default: { + script_module = make_unique(ScriptModule::Type::Text); + auto module = make_unique(); + module->loc = loc; + module->name = name; + CHECK_RESULT(ParseModuleFieldList(module.get())); + script_module->text = module.release(); + break; + } + } + + *out_module = std::move(script_module); + + EXPECT(Rpar); + return Result::Ok; +} + +template +Result WastParser::ParseAssertActionCommand(TokenType token_type, + CommandPtr* out_command) { + WABT_TRACE(ParseAssertActionCommand); + EXPECT(Lpar); + CHECK_RESULT(Expect(token_type)); + auto action = make_unique(); + CHECK_RESULT(ParseAction(action.get())); + EXPECT(Rpar); + out_command->reset(new T(action.release())); + return Result::Ok; +} + +template +Result WastParser::ParseAssertActionTextCommand(TokenType token_type, + CommandPtr* out_command) { + WABT_TRACE(ParseAssertActionTextCommand); + EXPECT(Lpar); + CHECK_RESULT(Expect(token_type)); + auto action = make_unique(); + std::string text; + CHECK_RESULT(ParseAction(action.get())); + CHECK_RESULT(ParseQuotedText(&text)); + EXPECT(Rpar); + out_command->reset(new T(action.release(), text)); + return Result::Ok; +} + +template +Result WastParser::ParseAssertScriptModuleCommand(TokenType token_type, + CommandPtr* out_command) { + WABT_TRACE(ParseAssertScriptModuleCommand); + EXPECT(Lpar); + CHECK_RESULT(Expect(token_type)); + std::unique_ptr module; + std::string text; + CHECK_RESULT(ParseScriptModule(&module)); + CHECK_RESULT(ParseQuotedText(&text)); + EXPECT(Rpar); + out_command->reset(new T(module.release(), text)); + return Result::Ok; +} + +void WastParser::CheckImportOrdering(Module* module) { + if (module->funcs.size() != module->num_func_imports || + module->tables.size() != module->num_table_imports || + module->memories.size() != module->num_memory_imports || + module->globals.size() != module->num_global_imports || + module->excepts.size() != module->num_except_imports) { + Error(GetLocation(), + "imports must occur before all non-import definitions"); + } +} + +Result ParseWast(WastLexer* lexer, + Script** out_script, + ErrorHandler* error_handler, + WastParseOptions* options) { + auto script = make_unique