From 29aa68a565f847574b2f89e1dff13c4bb7a07483 Mon Sep 17 00:00:00 2001 From: Edoardo Vacchi Date: Fri, 30 Aug 2024 10:03:02 +0200 Subject: [PATCH] Introduce the Store + fixes to validation (#495) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #486 Introduces the Store abstraction and adopts it in the test cases, cleaning up a lot of unnecessary test cases. ~~I am opening the PR in draft, as it needs rebasing anyway.~~ The change is relatively simple, it introduces the `Store` as described in #486, with a fluent interface of the type: ```java var store = new Store() .addFunctions(f1, ...) .addGlobals(g1, ...) ``` This API is copied over from `HostImports`, although this is not a subclass; it is still "related" to it; in fact: - it is possible to get the contents of a store ("converting" it, if you will) to a `HostImports` instance with `store.toHostImports()`; - the `Store` also accepts an entire `HostImports` instance as a shorthand for registering all of the items in it with `store.addHostImports(hostImports)` It also provides shorthands to register all of the exports in a module as qualified "HostGlobal"s, "HostFunction"s etc. ```java store.register("name", instance); // now each export `e` in instance, is stored as the qualified name `name.e` ``` It is also possible to instantiate and register in one move: ```java var instance = store.instantiate("name", module); ``` this is equivalent to: ```java var instance = Instance.builder(module).withHostImports(store.toHostImports()).build() store.register("name", instance) ``` The Store is deterministic, in that its behavior is known: when clashing instances (i.e. where their qualified name `n.e` is clashing) are registered to the store, the latest registration overwrites the oldest. Internally each type(*) (globals, funcs, etc) is kept in separate LinkedHashMaps. Introducing the `Store` enormously simplifies the definition of the spec tests, because such tests actually expect changes to "stick" across cases; i.e. they mutate sequentially a shared `store` instance adding and updating memories, functions, globals, tables. In fact, introducing the store highlighted a bunch of issues with validation, that I am fixing contextually: even though we would not let any invalid instance slip, we would raise `UnlinkableException`s during the initialization of the instance, instead of throwing an `InvalidException` at validation time. Potentially this allows us to avoid the second check at the time of instantiation, because we could assume that validation has passed. (*) note: this actually means that clashes might exists if two different types have the same qualified name 🤔 e.g. `n.e` is a func, but there is also a `n.e` that is a global 🤔 --------- Signed-off-by: Edoardo Vacchi Co-authored-by: Andrea Peruffo --- README.md | 51 ++++ .../imports/SpecV1BinaryLeb128HostFuncs.java | 27 -- .../chicory/imports/SpecV1DataHostFuncs.java | 38 --- .../chicory/imports/SpecV1ElemHostFuncs.java | 84 ------ .../imports/SpecV1ExportsHostFuncs.java | 45 --- .../imports/SpecV1FuncPtrsHostFuncs.java | 27 -- .../imports/SpecV1GlobalHostFuncs.java | 26 -- .../imports/SpecV1ImportsHostFuncs.java | 279 ------------------ .../imports/SpecV1LinkingHostFuncs.java | 270 ----------------- .../chicory/imports/SpecV1NamesHostFuncs.java | 27 -- .../imports/SpecV1RefFuncHostFuncs.java | 32 -- .../chicory/imports/SpecV1StartHostFuncs.java | 35 --- .../imports/SpecV1TableCopyHostFuncs.java | 49 --- .../chicory/imports/SpecV1TableHostFuncs.java | 23 -- .../imports/SpecV1TableInitHostFuncs.java | 49 --- .../imports/SpecV1TokensHostFuncs.java | 26 -- .../com/dylibso/chicory/testing/Spectest.java | 77 +++++ .../dylibso/chicory/testing/TestModule.java | 24 +- .../imports/SpecV1BinaryLeb128HostFuncs.java | 27 -- .../chicory/imports/SpecV1DataHostFuncs.java | 38 --- .../chicory/imports/SpecV1ElemHostFuncs.java | 84 ------ .../imports/SpecV1ExportsHostFuncs.java | 45 --- .../imports/SpecV1FuncPtrsHostFuncs.java | 27 -- .../imports/SpecV1GlobalHostFuncs.java | 26 -- .../imports/SpecV1ImportsHostFuncs.java | 279 ------------------ .../imports/SpecV1LinkingHostFuncs.java | 270 ----------------- .../chicory/imports/SpecV1NamesHostFuncs.java | 27 -- .../imports/SpecV1RefFuncHostFuncs.java | 32 -- .../chicory/imports/SpecV1StartHostFuncs.java | 35 --- .../imports/SpecV1TableCopyHostFuncs.java | 49 --- .../chicory/imports/SpecV1TableHostFuncs.java | 23 -- .../imports/SpecV1TableInitHostFuncs.java | 49 --- .../imports/SpecV1TokensHostFuncs.java | 26 -- .../com/dylibso/chicory/testing/Spectest.java | 77 +++++ .../dylibso/chicory/testing/TestModule.java | 15 +- .../com/dylibso/chicory/runtime/Instance.java | 23 +- .../com/dylibso/chicory/runtime/Store.java | 166 +++++++++++ .../dylibso/chicory/runtime/StoreTest.java | 133 +++++++++ .../dylibso/chicory/maven/JavaTestGen.java | 83 ++---- .../main/resources/compiled/exports.wat.wasm | Bin 0 -> 158 bytes .../src/main/resources/wat/exports.wat | 12 + .../java/com/dylibso/chicory/wasm/Module.java | 3 + .../com/dylibso/chicory/wasm/Validator.java | 116 ++++++++ 43 files changed, 694 insertions(+), 2160 deletions(-) delete mode 100644 aot/src/test/java/com/dylibso/chicory/imports/SpecV1BinaryLeb128HostFuncs.java delete mode 100644 aot/src/test/java/com/dylibso/chicory/imports/SpecV1DataHostFuncs.java delete mode 100644 aot/src/test/java/com/dylibso/chicory/imports/SpecV1ElemHostFuncs.java delete mode 100644 aot/src/test/java/com/dylibso/chicory/imports/SpecV1ExportsHostFuncs.java delete mode 100644 aot/src/test/java/com/dylibso/chicory/imports/SpecV1FuncPtrsHostFuncs.java delete mode 100644 aot/src/test/java/com/dylibso/chicory/imports/SpecV1GlobalHostFuncs.java delete mode 100644 aot/src/test/java/com/dylibso/chicory/imports/SpecV1ImportsHostFuncs.java delete mode 100644 aot/src/test/java/com/dylibso/chicory/imports/SpecV1LinkingHostFuncs.java delete mode 100644 aot/src/test/java/com/dylibso/chicory/imports/SpecV1NamesHostFuncs.java delete mode 100644 aot/src/test/java/com/dylibso/chicory/imports/SpecV1RefFuncHostFuncs.java delete mode 100644 aot/src/test/java/com/dylibso/chicory/imports/SpecV1StartHostFuncs.java delete mode 100644 aot/src/test/java/com/dylibso/chicory/imports/SpecV1TableCopyHostFuncs.java delete mode 100644 aot/src/test/java/com/dylibso/chicory/imports/SpecV1TableHostFuncs.java delete mode 100644 aot/src/test/java/com/dylibso/chicory/imports/SpecV1TableInitHostFuncs.java delete mode 100644 aot/src/test/java/com/dylibso/chicory/imports/SpecV1TokensHostFuncs.java create mode 100644 aot/src/test/java/com/dylibso/chicory/testing/Spectest.java delete mode 100644 runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1BinaryLeb128HostFuncs.java delete mode 100644 runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1DataHostFuncs.java delete mode 100644 runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1ElemHostFuncs.java delete mode 100644 runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1ExportsHostFuncs.java delete mode 100644 runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1FuncPtrsHostFuncs.java delete mode 100644 runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1GlobalHostFuncs.java delete mode 100644 runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1ImportsHostFuncs.java delete mode 100644 runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1LinkingHostFuncs.java delete mode 100644 runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1NamesHostFuncs.java delete mode 100644 runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1RefFuncHostFuncs.java delete mode 100644 runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1StartHostFuncs.java delete mode 100644 runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1TableCopyHostFuncs.java delete mode 100644 runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1TableHostFuncs.java delete mode 100644 runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1TableInitHostFuncs.java delete mode 100644 runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1TokensHostFuncs.java create mode 100644 runtime-tests/src/test/java/com/dylibso/chicory/testing/Spectest.java create mode 100644 runtime/src/main/java/com/dylibso/chicory/runtime/Store.java create mode 100644 runtime/src/test/java/com/dylibso/chicory/runtime/StoreTest.java create mode 100644 wasm-corpus/src/main/resources/compiled/exports.wat.wasm create mode 100644 wasm-corpus/src/main/resources/wat/exports.wat diff --git a/README.md b/README.md index 39ce74d63..b88bd5221 100644 --- a/README.md +++ b/README.md @@ -291,6 +291,57 @@ writeResultFile("hostFunction.result", hostFunctionResult); ``` --> +### Store and Instantiating Multiple Modules + +A [Store][spec] is an intermediate-level abstraction that collects Wasm function, global, memory, and table instances +as named entities. + +It simplifies creating instances when there are a lot of interdependencies, by collecting all the + +In the simplest case, it allows to register single host functions, globals, memories and tables: + +```java +import com.dylibso.chicory.runtime.Store; + +// instantiate the store +var store = new Store(); +// registers `console.log` in the store (see the previous section for the definition of `func`) +store.addHostFunction(func); +``` + +However, the store also automatically exposes the exports of a module to the other instances that are registered. + +```java +// registers the `instance` created earlier (see the previous section) with the name `logger` +store.register("logger", instance); +// now the exported function `logIt` can be imported by other modules as `logger.logIt` +``` + +There is also a shorthand method to instantiate a module and register the resulting instance: + +```java +var logger2 = store.instantiate("logger2", Parser.parse(new File("./logger.wasm"))); +``` + +This is equivalent to: + +```java +var hostImports = store.toHostImports(); +var instance = Instance.builder(m).withHostImports(hostImports).build(); +store.register("logger2", instance); +``` + +Notice that registering two instances with the same name results in overwriting the +functions, globals, memories, tables with matching names. In this case, the new `logger2.logIt` function +overwrote the old `logger2.logIt` function. + +The current `Store` is a mutable object, not meant to be shared (it is not thread-safe). + +A `Store` _does not_ resolve interdependencies between modules in itself: if your set of modules +have interdependencies, you will have to instantiate and register them in the right order. + +[spec]: https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#store%E2%91%A0 + ## Development ### Why is this needed? diff --git a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1BinaryLeb128HostFuncs.java b/aot/src/test/java/com/dylibso/chicory/imports/SpecV1BinaryLeb128HostFuncs.java deleted file mode 100644 index 15ccafad8..000000000 --- a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1BinaryLeb128HostFuncs.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1BinaryLeb128HostFuncs { - - private SpecV1BinaryLeb128HostFuncs() {} - - public static HostImports fallback() { - return HostImports.builder() - .addFunction( - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32", - List.of(ValueType.I32), - List.of())) - .build(); - } -} diff --git a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1DataHostFuncs.java b/aot/src/test/java/com/dylibso/chicory/imports/SpecV1DataHostFuncs.java deleted file mode 100644 index 080d183ac..000000000 --- a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1DataHostFuncs.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.GlobalInstance; -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostGlobal; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.HostMemory; -import com.dylibso.chicory.runtime.HostTable; -import com.dylibso.chicory.runtime.Memory; -import com.dylibso.chicory.wasm.types.MemoryLimits; -import com.dylibso.chicory.wasm.types.MutabilityType; -import com.dylibso.chicory.wasm.types.Value; - -public final class SpecV1DataHostFuncs { - - private SpecV1DataHostFuncs() {} - - public static HostImports fallback() { - - return new HostImports( - new HostFunction[] {}, - new HostGlobal[] { - new HostGlobal("spectest", "global_i32", new GlobalInstance(Value.i32(666))), - new HostGlobal("spectest", "global_i64", new GlobalInstance(Value.i64(666))), - new HostGlobal("test", "global-i32", new GlobalInstance(Value.i32(0))), - new HostGlobal( - "test", - "global-mut-i32", - new GlobalInstance(Value.i32(0), MutabilityType.Var)), - new HostGlobal( - "test", "g", new GlobalInstance(Value.i32(0), MutabilityType.Var)) - }, - new HostMemory[] { - new HostMemory("spectest", "memory", new Memory(new MemoryLimits(1, 1))) - }, - new HostTable[] {}); - } -} diff --git a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1ElemHostFuncs.java b/aot/src/test/java/com/dylibso/chicory/imports/SpecV1ElemHostFuncs.java deleted file mode 100644 index 0fff0117a..000000000 --- a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1ElemHostFuncs.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.dylibso.chicory.imports; - -import static com.dylibso.chicory.test.gen.SpecV1ElemTest.mInstance; -import static com.dylibso.chicory.test.gen.SpecV1ElemTest.module1Instance; -import static com.dylibso.chicory.test.gen.SpecV1ElemTest.module4Instance; - -import com.dylibso.chicory.runtime.GlobalInstance; -import com.dylibso.chicory.runtime.HostGlobal; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.HostTable; -import com.dylibso.chicory.runtime.TableInstance; -import com.dylibso.chicory.wasm.types.Limits; -import com.dylibso.chicory.wasm.types.MutabilityType; -import com.dylibso.chicory.wasm.types.Table; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; - -public final class SpecV1ElemHostFuncs { - - private static GlobalInstance glob = new GlobalInstance(Value.i32(123)); - - private SpecV1ElemHostFuncs() {} - - public static HostImports fallback() { - return HostImports.builder() - .addGlobal( - new HostGlobal("test", "global-i32", new GlobalInstance(Value.i32(0))), - new HostGlobal("spectest", "global_i32", glob), - new HostGlobal( - "test", - "global-mut-i32", - new GlobalInstance(Value.i32(0), MutabilityType.Var)), - new HostGlobal( - "test", "g", new GlobalInstance(Value.i32(0), MutabilityType.Var))) - .addTable( - new HostTable( - "spectest", - "table", - new TableInstance(new Table(ValueType.FuncRef, new Limits(10))))) - .build(); - } - - public static HostImports testModule17() { - return new HostImports( - new HostTable[] { - new HostTable( - "spectest", - "table", - new TableInstance(new Table(ValueType.FuncRef, new Limits(1, 100)))) - }); - } - - public static HostImports testModule19() { - return new HostImports( - new HostTable[] { - new HostTable( - "spectest", - "table", - new TableInstance(new Table(ValueType.FuncRef, new Limits(10, 30)))) - }); - } - - private static HostTable module1SharedTable() { - return new HostTable("module1", "shared-table", module1Instance.table(0)); - } - - public static HostImports module2() { - return new HostImports(new HostTable[] {module1SharedTable()}); - } - - public static HostImports module3() { - return new HostImports(new HostTable[] {module1SharedTable()}); - } - - public static HostImports testModule28() { - return new HostImports( - new HostTable[] {new HostTable("exporter", "table", mInstance.table(0))}); - } - - public static HostImports testModule30() { - return new HostImports( - new HostGlobal[] {new HostGlobal("module4", "f", module4Instance.global(0))}); - } -} diff --git a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1ExportsHostFuncs.java b/aot/src/test/java/com/dylibso/chicory/imports/SpecV1ExportsHostFuncs.java deleted file mode 100644 index c311061ce..000000000 --- a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1ExportsHostFuncs.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.GlobalInstance; -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostGlobal; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.HostMemory; -import com.dylibso.chicory.runtime.HostTable; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.runtime.Memory; -import com.dylibso.chicory.runtime.TableInstance; -import com.dylibso.chicory.wasm.types.Limits; -import com.dylibso.chicory.wasm.types.MemoryLimits; -import com.dylibso.chicory.wasm.types.Table; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1ExportsHostFuncs { - - private SpecV1ExportsHostFuncs() {} - - public static HostImports fallback() { - return HostImports.builder() - .addFunction( - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32", - List.of(ValueType.I32), - List.of())) - .addTable( - new HostTable( - "spectest", - "table", - new TableInstance( - new Table(ValueType.FuncRef, new Limits(10, 20))))) - .addMemory(new HostMemory("spectest", "memory", new Memory(new MemoryLimits(1, 2)))) - .addGlobal( - new HostGlobal("spectest", "global_i32", new GlobalInstance(Value.i32(0)))) - .build(); - } -} diff --git a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1FuncPtrsHostFuncs.java b/aot/src/test/java/com/dylibso/chicory/imports/SpecV1FuncPtrsHostFuncs.java deleted file mode 100644 index dd5f03236..000000000 --- a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1FuncPtrsHostFuncs.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1FuncPtrsHostFuncs { - - private SpecV1FuncPtrsHostFuncs() {} - - public static HostImports fallback() { - return new HostImports( - new HostFunction[] { - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32", - List.of(ValueType.I32), - List.of()) - }); - } -} diff --git a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1GlobalHostFuncs.java b/aot/src/test/java/com/dylibso/chicory/imports/SpecV1GlobalHostFuncs.java deleted file mode 100644 index 796b6fec9..000000000 --- a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1GlobalHostFuncs.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.GlobalInstance; -import com.dylibso.chicory.runtime.HostGlobal; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.wasm.types.MutabilityType; -import com.dylibso.chicory.wasm.types.Value; - -public final class SpecV1GlobalHostFuncs { - - private SpecV1GlobalHostFuncs() {} - - public static HostImports fallback() { - return new HostImports( - new HostGlobal[] { - new HostGlobal("spectest", "global_i32", new GlobalInstance(Value.i32(666))), - new HostGlobal("spectest", "global_i64", new GlobalInstance(Value.i64(666))), - new HostGlobal("test", "global-i32", new GlobalInstance(Value.i32(0))), - new HostGlobal( - "test", - "global-mut-i32", - new GlobalInstance(Value.i32(0), MutabilityType.Var)), - new HostGlobal("", "", new GlobalInstance(Value.externRef(0))), - }); - } -} diff --git a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1ImportsHostFuncs.java b/aot/src/test/java/com/dylibso/chicory/imports/SpecV1ImportsHostFuncs.java deleted file mode 100644 index d1fa0ec08..000000000 --- a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1ImportsHostFuncs.java +++ /dev/null @@ -1,279 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.GlobalInstance; -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostGlobal; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.HostMemory; -import com.dylibso.chicory.runtime.HostTable; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.runtime.Memory; -import com.dylibso.chicory.runtime.TableInstance; -import com.dylibso.chicory.wasm.types.Limits; -import com.dylibso.chicory.wasm.types.MemoryLimits; -import com.dylibso.chicory.wasm.types.MutabilityType; -import com.dylibso.chicory.wasm.types.Table; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1ImportsHostFuncs { - - private SpecV1ImportsHostFuncs() {} - - public static HostImports testModule11() { - return HostImports.builder() - .addGlobal( - new HostGlobal( - "spectest", "global_i32", new GlobalInstance(Value.i32(666))), - new HostGlobal( - "spectest", "global_i32_1", new GlobalInstance(Value.i32(666))), - new HostGlobal( - "spectest", "global_i32_2", new GlobalInstance(Value.i32(666))), - new HostGlobal( - "spectest", "global_i32_3", new GlobalInstance(Value.i32(666))), - new HostGlobal( - "spectest", "global_i64", new GlobalInstance(Value.i64(666))), - new HostGlobal("spectest", "global_f32", new GlobalInstance(Value.f32(1))), - new HostGlobal("spectest", "global_f64", new GlobalInstance(Value.f64(1)))) - .build(); - } - - // similar to: - // https://github.com/tetratelabs/wazero/blob/c345ddf2b5d65f69ee4daa1bb49fe896d1306778/internal/integration_test/spectest/v1/testdata/imports.wast#L417-L419 - public static HostImports testModule40() { - return new HostImports( - new HostMemory("test", "memory-2-inf", new Memory(new MemoryLimits(2)))); - } - - public static HostImports testModule41() { - return new HostImports( - new HostMemory("test", "memory-2-inf", new Memory(new MemoryLimits(1)))); - } - - public static HostImports testModule42() { - return new HostImports( - new HostMemory("test", "memory-2-inf", new Memory(new MemoryLimits(0)))); - } - - public static HostImports testModule49() { - return new HostImports( - new HostMemory("spectest", "memory", new Memory(new MemoryLimits(1, 2)))); - } - - public static HostImports Mgim1() { - return new HostImports( - new HostMemory("grown-memory", "memory", new Memory(new MemoryLimits(2)))); - } - - public static HostImports Mgim2() { - return new HostImports( - new HostMemory("grown-imported-memory", "memory", new Memory(new MemoryLimits(3)))); - } - - public static HostImports fallback() { - var testFunc = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "test", - "func", - List.of(), - List.of()); - var testFuncI32 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "test", - "func-i32", - List.of(ValueType.I32), - List.of()); - var testFuncToI32 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "test", - "func->i32", - List.of(), - List.of(ValueType.I32)); - var testFuncI32ToI32 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "test", - "func-i32->i32", - List.of(ValueType.I32), - List.of(ValueType.I32)); - var testFuncI64 = - new HostFunction( - (Instance instance, Value... args) -> { - return new Value[] {args[0]}; - }, - "test", - "func-i64->i64", - List.of(ValueType.I64), - List.of(ValueType.I64)); - var testFuncF32 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "test", - "func-f32", - List.of(ValueType.F32), - List.of()); - var testFuncToF32 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "test", - "func->f32", - List.of(), - List.of(ValueType.F32)); - var printI32 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32", - List.of(ValueType.I32), - List.of()); - var printI32_1 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32_1", - List.of(ValueType.I32), - List.of()); - var printI32_2 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32_2", - List.of(ValueType.I32), - List.of()); - var printF32 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_f32", - List.of(ValueType.F32), - List.of()); - var printI32F32 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32_f32", - List.of(ValueType.I32, ValueType.F32), - List.of()); - var printI64 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i64", - List.of(ValueType.I64), - List.of()); - var printI64_1 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i64_1", - List.of(ValueType.I64), - List.of()); - var printI64_2 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i64_2", - List.of(ValueType.I64), - List.of()); - var printF64 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_f64", - List.of(ValueType.F64), - List.of()); - var printF64F64 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_f64_f64", - List.of(ValueType.F64, ValueType.F64), - List.of()); - - var table = - new HostTable( - "spectest", - "table", - new TableInstance(new Table(ValueType.FuncRef, new Limits(10, 20)))); - var table10Inf = - new HostTable( - "test", - "table-10-inf", - new TableInstance(new Table(ValueType.FuncRef, new Limits(10)))); - var table1020 = - new HostTable( - "test", - "table-10-20", - new TableInstance(new Table(ValueType.FuncRef, new Limits(10, 20)))); - - return HostImports.builder() - .addFunction( - printI32, - printI32_1, - printI32_2, - printF32, - printI32F32, - printI64, - printI64_1, - printI64_2, - printF64, - printF64F64, - testFunc, - testFuncI32, - testFuncToI32, - testFuncI32ToI32, - testFuncI64, - testFuncF32, - testFuncToF32) - .addGlobal( - new HostGlobal("spectest", "global_i32", new GlobalInstance(Value.i32(0))), - new HostGlobal("test", "global-i32", new GlobalInstance(Value.i32(0))), - new HostGlobal("test", "global-f32", new GlobalInstance(Value.f32(0))), - new HostGlobal( - "test", - "global-mut-i64", - new GlobalInstance(Value.i64(0), MutabilityType.Var))) - .addMemory( - new HostMemory("spectest", "memory", new Memory(new MemoryLimits(1))), - new HostMemory( - "test", "memory-2-inf", new Memory(MemoryLimits.defaultLimits()))) - .addTable(table, table10Inf, table1020) - .build(); - } -} diff --git a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1LinkingHostFuncs.java b/aot/src/test/java/com/dylibso/chicory/imports/SpecV1LinkingHostFuncs.java deleted file mode 100644 index 973d11e0a..000000000 --- a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1LinkingHostFuncs.java +++ /dev/null @@ -1,270 +0,0 @@ -package com.dylibso.chicory.imports; - -import static com.dylibso.chicory.test.gen.SpecV1LinkingTest.MgInstance; -import static com.dylibso.chicory.test.gen.SpecV1LinkingTest.MmInstance; -import static com.dylibso.chicory.test.gen.SpecV1LinkingTest.MsInstance; -import static com.dylibso.chicory.test.gen.SpecV1LinkingTest.MtInstance; - -import com.dylibso.chicory.runtime.GlobalInstance; -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostGlobal; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.HostMemory; -import com.dylibso.chicory.runtime.HostTable; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.runtime.Memory; -import com.dylibso.chicory.runtime.TableInstance; -import com.dylibso.chicory.test.gen.SpecV1LinkingTest; -import com.dylibso.chicory.wasm.types.Limits; -import com.dylibso.chicory.wasm.types.MemoryLimits; -import com.dylibso.chicory.wasm.types.MutabilityType; -import com.dylibso.chicory.wasm.types.Table; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1LinkingHostFuncs { - - private static HostFunction MfCall = - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(2)}, - "Mf", - "call", - List.of(), - List.of(ValueType.I32)); - - private SpecV1LinkingHostFuncs() {} - - public static HostImports Mf() { - return new HostImports(new HostFunction[] {MfCall}); - } - - public static HostImports Nf() { - return new HostImports(new HostFunction[] {MfCall}); - } - - public static HostImports Mg() { - return HostImports.empty(); - } - - public static HostImports Mt() { - return HostImports.empty(); - } - - private static HostFunction Mth() { - return new HostFunction( - (Instance instance, Value... args) -> { - return MtInstance.export("h").apply(args); - }, - "Mt", - "h", - List.of(), - List.of(ValueType.I32)); - } - - private static HostFunction Mtcall() { - return new HostFunction( - (Instance instance, Value... args) -> { - return MtInstance.export("call").apply(args); - }, - "Mt", - "call", - List.of(ValueType.I32), - List.of(ValueType.I32)); - } - - public static HostImports Nt() { - return new HostImports(new HostFunction[] {Mtcall(), Mth()}); - } - - public static HostImports Ng() { - return HostImports.builder() - .addFunction( - new HostFunction( - (Instance instance, Value... args) -> - new Value[] {SpecV1LinkingTest.MgInstance.readGlobal(0)}, - "Mg", - "get", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> - new Value[] {SpecV1LinkingTest.MgInstance.readGlobal(1)}, - "Mg", - "get_mut", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> { - SpecV1LinkingTest.MgInstance.writeGlobal(1, args[0]); - return null; - }, - "Mg", - "set_mut", - List.of(ValueType.I32), - List.of())) - .addGlobal( - new HostGlobal("Mg", "glob", MgInstance.global(0)), - new HostGlobal("Mg", "mut_glob", MgInstance.global(1))) - .build(); - } - - private static HostTable MtTab() { - return new HostTable("Mt", "tab", MtInstance.table(0)); - } - - public static HostImports Ot() { - return HostImports.builder().addFunction(Mth()).addTable(MtTab()).build(); - } - - public static HostImports testModule10() { - return HostImports.builder().addTable(MtTab()).build(); - } - - public static HostImports G2() { - return HostImports.builder() - .addGlobal(new HostGlobal("G1", "g", new GlobalInstance(Value.i32(5)))) - .build(); - } - - private static HostMemory MmMem() { - return new HostMemory("Mm", "mem", MmInstance.memory()); - } - - public static HostImports Om() { - return new HostImports(new HostMemory[] {MmMem()}); - } - - public static HostImports testModule18() { - return new HostImports(new HostMemory[] {MmMem()}); - } - - public static HostImports Pm() { - return new HostImports(new HostMemory[] {MmMem()}); - } - - public static HostImports Nm() { - return new HostImports( - new HostFunction[] { - new HostFunction( - (Instance instance, Value... args) -> { - return MmInstance.export("load").apply(args); - }, - "Mm", - "load", - List.of(ValueType.I32), - List.of(ValueType.I32)) - }); - } - - public static HostImports Mm() { - return new HostImports(new HostMemory("Mm", "mem", new Memory(new MemoryLimits(1, 5)))); - } - - public static HostImports Ms() { - return HostImports.builder() - .addMemory(new HostMemory("Ms", "memory", new Memory(new MemoryLimits(1, 5)))) - .addTable( - new HostTable( - "Ms", - "table", - new TableInstance(new Table(ValueType.FuncRef, new Limits(10))))) - .build(); - } - - public static HostImports Mref_im() { - return HostImports.builder() - .addGlobal( - new HostGlobal( - "Mref_ex", "g-const-func", new GlobalInstance(Value.funcRef(0)))) - .addGlobal( - new HostGlobal( - "Mref_ex", - "g-const-extern", - new GlobalInstance(Value.externRef(0)))) - .addGlobal( - new HostGlobal( - "Mref_ex", - "g-var-func", - new GlobalInstance(Value.funcRef(0), MutabilityType.Var))) - .addGlobal( - new HostGlobal( - "Mref_ex", - "g-var-extern", - new GlobalInstance(Value.externRef(0), MutabilityType.Var))) - .build(); - } - - public static HostImports fallback() { - var builder = - HostImports.builder() - .addFunction( - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32", - List.of(ValueType.I32), - List.of()), - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "reexport_f", - "print", - List.of(), - List.of())) - .addGlobal( - new HostGlobal( - "Mref_ex", - "g-const-func", - new GlobalInstance(Value.funcRef(0)))) - .addGlobal( - new HostGlobal( - "Mref_ex", - "g-const-extern", - new GlobalInstance(Value.externRef(0)))) - .addGlobal( - new HostGlobal( - "Mref_ex", - "g-var-func", - new GlobalInstance(Value.funcRef(0), MutabilityType.Var))) - .addGlobal( - new HostGlobal( - "Mref_ex", - "g-var-extern", - new GlobalInstance(Value.externRef(0), MutabilityType.Var))) - .addTable( - new HostTable( - "Mtable_ex", - "t-func", - new TableInstance( - new Table(ValueType.FuncRef, new Limits(1))))) - .addTable( - new HostTable( - "Mtable_ex", - "t-extern", - new TableInstance( - new Table(ValueType.ExternRef, new Limits(1))))); - - if (MgInstance != null) { - builder.addGlobal( - new HostGlobal("Mg", "glob", MgInstance.global(0)), - new HostGlobal("Mg", "mut_glob", MgInstance.global(1))); - } - - if (MsInstance != null) { - builder.addMemory(new HostMemory("Ms", "memory", MsInstance.memory())) - .addTable(new HostTable("Ms", "table", MsInstance.table(0))); - } - if (MmInstance != null) { - builder.addMemory(MmMem()); - } - if (MtInstance != null) { - builder.addTable(new HostTable("Mt", "tab", MtInstance.table(0))); - } - - return builder.build(); - } -} diff --git a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1NamesHostFuncs.java b/aot/src/test/java/com/dylibso/chicory/imports/SpecV1NamesHostFuncs.java deleted file mode 100644 index ba8b094e6..000000000 --- a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1NamesHostFuncs.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1NamesHostFuncs { - - private SpecV1NamesHostFuncs() {} - - public static HostImports fallback() { - return new HostImports( - new HostFunction[] { - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32", - List.of(ValueType.I32), - List.of()) - }); - } -} diff --git a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1RefFuncHostFuncs.java b/aot/src/test/java/com/dylibso/chicory/imports/SpecV1RefFuncHostFuncs.java deleted file mode 100644 index 9ca93b9fc..000000000 --- a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1RefFuncHostFuncs.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1RefFuncHostFuncs { - - private SpecV1RefFuncHostFuncs() {} - - public static HostImports fallback() { - return HostImports.builder() - .addFunction( - new HostFunction( - (Instance instance, Value... args) -> args, - "M", - "f", - List.of(ValueType.I32), - List.of(ValueType.I32))) - .addFunction( - new HostFunction( - (Instance instance, Value... args) -> args, - "M", - "g", - List.of(ValueType.I32), - List.of(ValueType.I32))) - .build(); - } -} diff --git a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1StartHostFuncs.java b/aot/src/test/java/com/dylibso/chicory/imports/SpecV1StartHostFuncs.java deleted file mode 100644 index b1a47c7eb..000000000 --- a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1StartHostFuncs.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1StartHostFuncs { - - private SpecV1StartHostFuncs() {} - - public static HostImports fallback() { - return new HostImports( - new HostFunction[] { - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32", - List.of(ValueType.I32), - List.of()), - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print", - List.of(), - List.of()) - }); - } -} diff --git a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1TableCopyHostFuncs.java b/aot/src/test/java/com/dylibso/chicory/imports/SpecV1TableCopyHostFuncs.java deleted file mode 100644 index 8f2131a5e..000000000 --- a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1TableCopyHostFuncs.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1TableCopyHostFuncs { - - private SpecV1TableCopyHostFuncs() {} - - public static HostImports fallback() { - return new HostImports( - new HostFunction[] { - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(0)}, - "a", - "ef0", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(1)}, - "a", - "ef1", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(2)}, - "a", - "ef2", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(3)}, - "a", - "ef3", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(4)}, - "a", - "ef4", - List.of(), - List.of(ValueType.I32)) - }); - } -} diff --git a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1TableHostFuncs.java b/aot/src/test/java/com/dylibso/chicory/imports/SpecV1TableHostFuncs.java deleted file mode 100644 index 939c11735..000000000 --- a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1TableHostFuncs.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.HostTable; -import com.dylibso.chicory.runtime.TableInstance; -import com.dylibso.chicory.wasm.types.Limits; -import com.dylibso.chicory.wasm.types.Table; -import com.dylibso.chicory.wasm.types.ValueType; - -public final class SpecV1TableHostFuncs { - - private SpecV1TableHostFuncs() {} - - public static HostImports fallback() { - return HostImports.builder() - .addTable( - new HostTable( - "spectest", - "table", - new TableInstance(new Table(ValueType.FuncRef, new Limits(10))))) - .build(); - } -} diff --git a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1TableInitHostFuncs.java b/aot/src/test/java/com/dylibso/chicory/imports/SpecV1TableInitHostFuncs.java deleted file mode 100644 index 8e9ba5147..000000000 --- a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1TableInitHostFuncs.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1TableInitHostFuncs { - - private SpecV1TableInitHostFuncs() {} - - public static HostImports fallback() { - return new HostImports( - new HostFunction[] { - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(0)}, - "a", - "ef0", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(1)}, - "a", - "ef1", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(2)}, - "a", - "ef2", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(3)}, - "a", - "ef3", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(4)}, - "a", - "ef4", - List.of(), - List.of(ValueType.I32)) - }); - } -} diff --git a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1TokensHostFuncs.java b/aot/src/test/java/com/dylibso/chicory/imports/SpecV1TokensHostFuncs.java deleted file mode 100644 index 7b115ef16..000000000 --- a/aot/src/test/java/com/dylibso/chicory/imports/SpecV1TokensHostFuncs.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.types.Value; -import java.util.List; - -public final class SpecV1TokensHostFuncs { - - private SpecV1TokensHostFuncs() {} - - public static HostImports fallback() { - return HostImports.builder() - .addFunction( - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print", - List.of(), - List.of())) - .build(); - } -} diff --git a/aot/src/test/java/com/dylibso/chicory/testing/Spectest.java b/aot/src/test/java/com/dylibso/chicory/testing/Spectest.java new file mode 100644 index 000000000..8706a2dae --- /dev/null +++ b/aot/src/test/java/com/dylibso/chicory/testing/Spectest.java @@ -0,0 +1,77 @@ +package com.dylibso.chicory.testing; + +import com.dylibso.chicory.runtime.GlobalInstance; +import com.dylibso.chicory.runtime.HostFunction; +import com.dylibso.chicory.runtime.HostGlobal; +import com.dylibso.chicory.runtime.HostImports; +import com.dylibso.chicory.runtime.HostMemory; +import com.dylibso.chicory.runtime.HostTable; +import com.dylibso.chicory.runtime.Instance; +import com.dylibso.chicory.runtime.Memory; +import com.dylibso.chicory.runtime.TableInstance; +import com.dylibso.chicory.runtime.WasmFunctionHandle; +import com.dylibso.chicory.wasm.types.Limits; +import com.dylibso.chicory.wasm.types.MemoryLimits; +import com.dylibso.chicory.wasm.types.Table; +import com.dylibso.chicory.wasm.types.Value; +import com.dylibso.chicory.wasm.types.ValueType; +import java.util.List; + +// https://github.com/WebAssembly/spec/blob/ee82c8e50c5106e0cedada0a083d4cc4129034a2/interpreter/host/spectest.ml +public final class Spectest { + private static final WasmFunctionHandle noop = (Instance instance, Value... args) -> null; + + private Spectest() {} + + public static HostImports toHostImports() { + return new HostImports( + new HostFunction[] { + new HostFunction(noop, "spectest", "print", List.of(), List.of()), + new HostFunction( + noop, "spectest", "print_i32", List.of(ValueType.I32), List.of()), + new HostFunction( + noop, "spectest", "print_i32_1", List.of(ValueType.I32), List.of()), + new HostFunction( + noop, "spectest", "print_i32_2", List.of(ValueType.I32), List.of()), + new HostFunction( + noop, "spectest", "print_f32", List.of(ValueType.F32), List.of()), + new HostFunction( + noop, + "spectest", + "print_i32_f32", + List.of(ValueType.I32, ValueType.F32), + List.of()), + new HostFunction( + noop, "spectest", "print_i64", List.of(ValueType.I64), List.of()), + new HostFunction( + noop, "spectest", "print_i64_1", List.of(ValueType.I64), List.of()), + new HostFunction( + noop, "spectest", "print_i64_2", List.of(ValueType.I64), List.of()), + new HostFunction( + noop, "spectest", "print_f64", List.of(ValueType.F64), List.of()), + new HostFunction( + noop, + "spectest", + "print_f64_f64", + List.of(ValueType.F64, ValueType.F64), + List.of()) + }, + new HostGlobal[] { + new HostGlobal("spectest", "global_i32", new GlobalInstance(Value.i32(666))), + new HostGlobal("spectest", "global_i64", new GlobalInstance(Value.i64(666))), + new HostGlobal( + "spectest", "global_f32", new GlobalInstance(Value.fromFloat(666.6f))), + new HostGlobal( + "spectest", "global_f64", new GlobalInstance(Value.fromDouble(666.6))), + }, + new HostMemory[] { + new HostMemory("spectest", "memory", new Memory(new MemoryLimits(1, 2))) + }, + new HostTable[] { + new HostTable( + "spectest", + "table", + new TableInstance(new Table(ValueType.FuncRef, new Limits(10, 20)))) + }); + } +} diff --git a/aot/src/test/java/com/dylibso/chicory/testing/TestModule.java b/aot/src/test/java/com/dylibso/chicory/testing/TestModule.java index 5a507b628..410c0d3d6 100644 --- a/aot/src/test/java/com/dylibso/chicory/testing/TestModule.java +++ b/aot/src/test/java/com/dylibso/chicory/testing/TestModule.java @@ -3,6 +3,7 @@ import com.dylibso.chicory.aot.AotMachine; import com.dylibso.chicory.runtime.HostImports; import com.dylibso.chicory.runtime.Instance; +import com.dylibso.chicory.runtime.Store; import com.dylibso.chicory.wabt.Wat2Wasm; import com.dylibso.chicory.wasm.Module; import com.dylibso.chicory.wasm.Parser; @@ -11,10 +12,7 @@ public class TestModule { - private Module module; - private Instance instance; - - private HostImports imports; + private final Module module; private static final String HACK_MATCH_ALL_MALFORMED_EXCEPTION_TEXT = "Matching keywords to get the WebAssembly testsuite to pass: " @@ -63,17 +61,11 @@ public TestModule(Module module) { this.module = module; } - public Instance build() { - this.instance = - Instance.builder(module) - .withHostImports(imports) - .withMachineFactory(AotMachine::new) - .build(); - return this.instance; - } - - public TestModule withHostImports(HostImports imports) { - this.imports = imports; - return this; + public Instance instantiate(Store s) { + HostImports hostImports = s.toHostImports(); + return Instance.builder(module) + .withHostImports(hostImports) + .withMachineFactory(AotMachine::new) + .build(); } } diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1BinaryLeb128HostFuncs.java b/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1BinaryLeb128HostFuncs.java deleted file mode 100644 index 15ccafad8..000000000 --- a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1BinaryLeb128HostFuncs.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1BinaryLeb128HostFuncs { - - private SpecV1BinaryLeb128HostFuncs() {} - - public static HostImports fallback() { - return HostImports.builder() - .addFunction( - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32", - List.of(ValueType.I32), - List.of())) - .build(); - } -} diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1DataHostFuncs.java b/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1DataHostFuncs.java deleted file mode 100644 index 080d183ac..000000000 --- a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1DataHostFuncs.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.GlobalInstance; -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostGlobal; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.HostMemory; -import com.dylibso.chicory.runtime.HostTable; -import com.dylibso.chicory.runtime.Memory; -import com.dylibso.chicory.wasm.types.MemoryLimits; -import com.dylibso.chicory.wasm.types.MutabilityType; -import com.dylibso.chicory.wasm.types.Value; - -public final class SpecV1DataHostFuncs { - - private SpecV1DataHostFuncs() {} - - public static HostImports fallback() { - - return new HostImports( - new HostFunction[] {}, - new HostGlobal[] { - new HostGlobal("spectest", "global_i32", new GlobalInstance(Value.i32(666))), - new HostGlobal("spectest", "global_i64", new GlobalInstance(Value.i64(666))), - new HostGlobal("test", "global-i32", new GlobalInstance(Value.i32(0))), - new HostGlobal( - "test", - "global-mut-i32", - new GlobalInstance(Value.i32(0), MutabilityType.Var)), - new HostGlobal( - "test", "g", new GlobalInstance(Value.i32(0), MutabilityType.Var)) - }, - new HostMemory[] { - new HostMemory("spectest", "memory", new Memory(new MemoryLimits(1, 1))) - }, - new HostTable[] {}); - } -} diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1ElemHostFuncs.java b/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1ElemHostFuncs.java deleted file mode 100644 index 0fff0117a..000000000 --- a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1ElemHostFuncs.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.dylibso.chicory.imports; - -import static com.dylibso.chicory.test.gen.SpecV1ElemTest.mInstance; -import static com.dylibso.chicory.test.gen.SpecV1ElemTest.module1Instance; -import static com.dylibso.chicory.test.gen.SpecV1ElemTest.module4Instance; - -import com.dylibso.chicory.runtime.GlobalInstance; -import com.dylibso.chicory.runtime.HostGlobal; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.HostTable; -import com.dylibso.chicory.runtime.TableInstance; -import com.dylibso.chicory.wasm.types.Limits; -import com.dylibso.chicory.wasm.types.MutabilityType; -import com.dylibso.chicory.wasm.types.Table; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; - -public final class SpecV1ElemHostFuncs { - - private static GlobalInstance glob = new GlobalInstance(Value.i32(123)); - - private SpecV1ElemHostFuncs() {} - - public static HostImports fallback() { - return HostImports.builder() - .addGlobal( - new HostGlobal("test", "global-i32", new GlobalInstance(Value.i32(0))), - new HostGlobal("spectest", "global_i32", glob), - new HostGlobal( - "test", - "global-mut-i32", - new GlobalInstance(Value.i32(0), MutabilityType.Var)), - new HostGlobal( - "test", "g", new GlobalInstance(Value.i32(0), MutabilityType.Var))) - .addTable( - new HostTable( - "spectest", - "table", - new TableInstance(new Table(ValueType.FuncRef, new Limits(10))))) - .build(); - } - - public static HostImports testModule17() { - return new HostImports( - new HostTable[] { - new HostTable( - "spectest", - "table", - new TableInstance(new Table(ValueType.FuncRef, new Limits(1, 100)))) - }); - } - - public static HostImports testModule19() { - return new HostImports( - new HostTable[] { - new HostTable( - "spectest", - "table", - new TableInstance(new Table(ValueType.FuncRef, new Limits(10, 30)))) - }); - } - - private static HostTable module1SharedTable() { - return new HostTable("module1", "shared-table", module1Instance.table(0)); - } - - public static HostImports module2() { - return new HostImports(new HostTable[] {module1SharedTable()}); - } - - public static HostImports module3() { - return new HostImports(new HostTable[] {module1SharedTable()}); - } - - public static HostImports testModule28() { - return new HostImports( - new HostTable[] {new HostTable("exporter", "table", mInstance.table(0))}); - } - - public static HostImports testModule30() { - return new HostImports( - new HostGlobal[] {new HostGlobal("module4", "f", module4Instance.global(0))}); - } -} diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1ExportsHostFuncs.java b/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1ExportsHostFuncs.java deleted file mode 100644 index c311061ce..000000000 --- a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1ExportsHostFuncs.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.GlobalInstance; -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostGlobal; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.HostMemory; -import com.dylibso.chicory.runtime.HostTable; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.runtime.Memory; -import com.dylibso.chicory.runtime.TableInstance; -import com.dylibso.chicory.wasm.types.Limits; -import com.dylibso.chicory.wasm.types.MemoryLimits; -import com.dylibso.chicory.wasm.types.Table; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1ExportsHostFuncs { - - private SpecV1ExportsHostFuncs() {} - - public static HostImports fallback() { - return HostImports.builder() - .addFunction( - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32", - List.of(ValueType.I32), - List.of())) - .addTable( - new HostTable( - "spectest", - "table", - new TableInstance( - new Table(ValueType.FuncRef, new Limits(10, 20))))) - .addMemory(new HostMemory("spectest", "memory", new Memory(new MemoryLimits(1, 2)))) - .addGlobal( - new HostGlobal("spectest", "global_i32", new GlobalInstance(Value.i32(0)))) - .build(); - } -} diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1FuncPtrsHostFuncs.java b/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1FuncPtrsHostFuncs.java deleted file mode 100644 index dd5f03236..000000000 --- a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1FuncPtrsHostFuncs.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1FuncPtrsHostFuncs { - - private SpecV1FuncPtrsHostFuncs() {} - - public static HostImports fallback() { - return new HostImports( - new HostFunction[] { - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32", - List.of(ValueType.I32), - List.of()) - }); - } -} diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1GlobalHostFuncs.java b/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1GlobalHostFuncs.java deleted file mode 100644 index 796b6fec9..000000000 --- a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1GlobalHostFuncs.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.GlobalInstance; -import com.dylibso.chicory.runtime.HostGlobal; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.wasm.types.MutabilityType; -import com.dylibso.chicory.wasm.types.Value; - -public final class SpecV1GlobalHostFuncs { - - private SpecV1GlobalHostFuncs() {} - - public static HostImports fallback() { - return new HostImports( - new HostGlobal[] { - new HostGlobal("spectest", "global_i32", new GlobalInstance(Value.i32(666))), - new HostGlobal("spectest", "global_i64", new GlobalInstance(Value.i64(666))), - new HostGlobal("test", "global-i32", new GlobalInstance(Value.i32(0))), - new HostGlobal( - "test", - "global-mut-i32", - new GlobalInstance(Value.i32(0), MutabilityType.Var)), - new HostGlobal("", "", new GlobalInstance(Value.externRef(0))), - }); - } -} diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1ImportsHostFuncs.java b/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1ImportsHostFuncs.java deleted file mode 100644 index d1fa0ec08..000000000 --- a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1ImportsHostFuncs.java +++ /dev/null @@ -1,279 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.GlobalInstance; -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostGlobal; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.HostMemory; -import com.dylibso.chicory.runtime.HostTable; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.runtime.Memory; -import com.dylibso.chicory.runtime.TableInstance; -import com.dylibso.chicory.wasm.types.Limits; -import com.dylibso.chicory.wasm.types.MemoryLimits; -import com.dylibso.chicory.wasm.types.MutabilityType; -import com.dylibso.chicory.wasm.types.Table; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1ImportsHostFuncs { - - private SpecV1ImportsHostFuncs() {} - - public static HostImports testModule11() { - return HostImports.builder() - .addGlobal( - new HostGlobal( - "spectest", "global_i32", new GlobalInstance(Value.i32(666))), - new HostGlobal( - "spectest", "global_i32_1", new GlobalInstance(Value.i32(666))), - new HostGlobal( - "spectest", "global_i32_2", new GlobalInstance(Value.i32(666))), - new HostGlobal( - "spectest", "global_i32_3", new GlobalInstance(Value.i32(666))), - new HostGlobal( - "spectest", "global_i64", new GlobalInstance(Value.i64(666))), - new HostGlobal("spectest", "global_f32", new GlobalInstance(Value.f32(1))), - new HostGlobal("spectest", "global_f64", new GlobalInstance(Value.f64(1)))) - .build(); - } - - // similar to: - // https://github.com/tetratelabs/wazero/blob/c345ddf2b5d65f69ee4daa1bb49fe896d1306778/internal/integration_test/spectest/v1/testdata/imports.wast#L417-L419 - public static HostImports testModule40() { - return new HostImports( - new HostMemory("test", "memory-2-inf", new Memory(new MemoryLimits(2)))); - } - - public static HostImports testModule41() { - return new HostImports( - new HostMemory("test", "memory-2-inf", new Memory(new MemoryLimits(1)))); - } - - public static HostImports testModule42() { - return new HostImports( - new HostMemory("test", "memory-2-inf", new Memory(new MemoryLimits(0)))); - } - - public static HostImports testModule49() { - return new HostImports( - new HostMemory("spectest", "memory", new Memory(new MemoryLimits(1, 2)))); - } - - public static HostImports Mgim1() { - return new HostImports( - new HostMemory("grown-memory", "memory", new Memory(new MemoryLimits(2)))); - } - - public static HostImports Mgim2() { - return new HostImports( - new HostMemory("grown-imported-memory", "memory", new Memory(new MemoryLimits(3)))); - } - - public static HostImports fallback() { - var testFunc = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "test", - "func", - List.of(), - List.of()); - var testFuncI32 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "test", - "func-i32", - List.of(ValueType.I32), - List.of()); - var testFuncToI32 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "test", - "func->i32", - List.of(), - List.of(ValueType.I32)); - var testFuncI32ToI32 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "test", - "func-i32->i32", - List.of(ValueType.I32), - List.of(ValueType.I32)); - var testFuncI64 = - new HostFunction( - (Instance instance, Value... args) -> { - return new Value[] {args[0]}; - }, - "test", - "func-i64->i64", - List.of(ValueType.I64), - List.of(ValueType.I64)); - var testFuncF32 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "test", - "func-f32", - List.of(ValueType.F32), - List.of()); - var testFuncToF32 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "test", - "func->f32", - List.of(), - List.of(ValueType.F32)); - var printI32 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32", - List.of(ValueType.I32), - List.of()); - var printI32_1 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32_1", - List.of(ValueType.I32), - List.of()); - var printI32_2 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32_2", - List.of(ValueType.I32), - List.of()); - var printF32 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_f32", - List.of(ValueType.F32), - List.of()); - var printI32F32 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32_f32", - List.of(ValueType.I32, ValueType.F32), - List.of()); - var printI64 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i64", - List.of(ValueType.I64), - List.of()); - var printI64_1 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i64_1", - List.of(ValueType.I64), - List.of()); - var printI64_2 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i64_2", - List.of(ValueType.I64), - List.of()); - var printF64 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_f64", - List.of(ValueType.F64), - List.of()); - var printF64F64 = - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_f64_f64", - List.of(ValueType.F64, ValueType.F64), - List.of()); - - var table = - new HostTable( - "spectest", - "table", - new TableInstance(new Table(ValueType.FuncRef, new Limits(10, 20)))); - var table10Inf = - new HostTable( - "test", - "table-10-inf", - new TableInstance(new Table(ValueType.FuncRef, new Limits(10)))); - var table1020 = - new HostTable( - "test", - "table-10-20", - new TableInstance(new Table(ValueType.FuncRef, new Limits(10, 20)))); - - return HostImports.builder() - .addFunction( - printI32, - printI32_1, - printI32_2, - printF32, - printI32F32, - printI64, - printI64_1, - printI64_2, - printF64, - printF64F64, - testFunc, - testFuncI32, - testFuncToI32, - testFuncI32ToI32, - testFuncI64, - testFuncF32, - testFuncToF32) - .addGlobal( - new HostGlobal("spectest", "global_i32", new GlobalInstance(Value.i32(0))), - new HostGlobal("test", "global-i32", new GlobalInstance(Value.i32(0))), - new HostGlobal("test", "global-f32", new GlobalInstance(Value.f32(0))), - new HostGlobal( - "test", - "global-mut-i64", - new GlobalInstance(Value.i64(0), MutabilityType.Var))) - .addMemory( - new HostMemory("spectest", "memory", new Memory(new MemoryLimits(1))), - new HostMemory( - "test", "memory-2-inf", new Memory(MemoryLimits.defaultLimits()))) - .addTable(table, table10Inf, table1020) - .build(); - } -} diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1LinkingHostFuncs.java b/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1LinkingHostFuncs.java deleted file mode 100644 index 973d11e0a..000000000 --- a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1LinkingHostFuncs.java +++ /dev/null @@ -1,270 +0,0 @@ -package com.dylibso.chicory.imports; - -import static com.dylibso.chicory.test.gen.SpecV1LinkingTest.MgInstance; -import static com.dylibso.chicory.test.gen.SpecV1LinkingTest.MmInstance; -import static com.dylibso.chicory.test.gen.SpecV1LinkingTest.MsInstance; -import static com.dylibso.chicory.test.gen.SpecV1LinkingTest.MtInstance; - -import com.dylibso.chicory.runtime.GlobalInstance; -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostGlobal; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.HostMemory; -import com.dylibso.chicory.runtime.HostTable; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.runtime.Memory; -import com.dylibso.chicory.runtime.TableInstance; -import com.dylibso.chicory.test.gen.SpecV1LinkingTest; -import com.dylibso.chicory.wasm.types.Limits; -import com.dylibso.chicory.wasm.types.MemoryLimits; -import com.dylibso.chicory.wasm.types.MutabilityType; -import com.dylibso.chicory.wasm.types.Table; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1LinkingHostFuncs { - - private static HostFunction MfCall = - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(2)}, - "Mf", - "call", - List.of(), - List.of(ValueType.I32)); - - private SpecV1LinkingHostFuncs() {} - - public static HostImports Mf() { - return new HostImports(new HostFunction[] {MfCall}); - } - - public static HostImports Nf() { - return new HostImports(new HostFunction[] {MfCall}); - } - - public static HostImports Mg() { - return HostImports.empty(); - } - - public static HostImports Mt() { - return HostImports.empty(); - } - - private static HostFunction Mth() { - return new HostFunction( - (Instance instance, Value... args) -> { - return MtInstance.export("h").apply(args); - }, - "Mt", - "h", - List.of(), - List.of(ValueType.I32)); - } - - private static HostFunction Mtcall() { - return new HostFunction( - (Instance instance, Value... args) -> { - return MtInstance.export("call").apply(args); - }, - "Mt", - "call", - List.of(ValueType.I32), - List.of(ValueType.I32)); - } - - public static HostImports Nt() { - return new HostImports(new HostFunction[] {Mtcall(), Mth()}); - } - - public static HostImports Ng() { - return HostImports.builder() - .addFunction( - new HostFunction( - (Instance instance, Value... args) -> - new Value[] {SpecV1LinkingTest.MgInstance.readGlobal(0)}, - "Mg", - "get", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> - new Value[] {SpecV1LinkingTest.MgInstance.readGlobal(1)}, - "Mg", - "get_mut", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> { - SpecV1LinkingTest.MgInstance.writeGlobal(1, args[0]); - return null; - }, - "Mg", - "set_mut", - List.of(ValueType.I32), - List.of())) - .addGlobal( - new HostGlobal("Mg", "glob", MgInstance.global(0)), - new HostGlobal("Mg", "mut_glob", MgInstance.global(1))) - .build(); - } - - private static HostTable MtTab() { - return new HostTable("Mt", "tab", MtInstance.table(0)); - } - - public static HostImports Ot() { - return HostImports.builder().addFunction(Mth()).addTable(MtTab()).build(); - } - - public static HostImports testModule10() { - return HostImports.builder().addTable(MtTab()).build(); - } - - public static HostImports G2() { - return HostImports.builder() - .addGlobal(new HostGlobal("G1", "g", new GlobalInstance(Value.i32(5)))) - .build(); - } - - private static HostMemory MmMem() { - return new HostMemory("Mm", "mem", MmInstance.memory()); - } - - public static HostImports Om() { - return new HostImports(new HostMemory[] {MmMem()}); - } - - public static HostImports testModule18() { - return new HostImports(new HostMemory[] {MmMem()}); - } - - public static HostImports Pm() { - return new HostImports(new HostMemory[] {MmMem()}); - } - - public static HostImports Nm() { - return new HostImports( - new HostFunction[] { - new HostFunction( - (Instance instance, Value... args) -> { - return MmInstance.export("load").apply(args); - }, - "Mm", - "load", - List.of(ValueType.I32), - List.of(ValueType.I32)) - }); - } - - public static HostImports Mm() { - return new HostImports(new HostMemory("Mm", "mem", new Memory(new MemoryLimits(1, 5)))); - } - - public static HostImports Ms() { - return HostImports.builder() - .addMemory(new HostMemory("Ms", "memory", new Memory(new MemoryLimits(1, 5)))) - .addTable( - new HostTable( - "Ms", - "table", - new TableInstance(new Table(ValueType.FuncRef, new Limits(10))))) - .build(); - } - - public static HostImports Mref_im() { - return HostImports.builder() - .addGlobal( - new HostGlobal( - "Mref_ex", "g-const-func", new GlobalInstance(Value.funcRef(0)))) - .addGlobal( - new HostGlobal( - "Mref_ex", - "g-const-extern", - new GlobalInstance(Value.externRef(0)))) - .addGlobal( - new HostGlobal( - "Mref_ex", - "g-var-func", - new GlobalInstance(Value.funcRef(0), MutabilityType.Var))) - .addGlobal( - new HostGlobal( - "Mref_ex", - "g-var-extern", - new GlobalInstance(Value.externRef(0), MutabilityType.Var))) - .build(); - } - - public static HostImports fallback() { - var builder = - HostImports.builder() - .addFunction( - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32", - List.of(ValueType.I32), - List.of()), - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "reexport_f", - "print", - List.of(), - List.of())) - .addGlobal( - new HostGlobal( - "Mref_ex", - "g-const-func", - new GlobalInstance(Value.funcRef(0)))) - .addGlobal( - new HostGlobal( - "Mref_ex", - "g-const-extern", - new GlobalInstance(Value.externRef(0)))) - .addGlobal( - new HostGlobal( - "Mref_ex", - "g-var-func", - new GlobalInstance(Value.funcRef(0), MutabilityType.Var))) - .addGlobal( - new HostGlobal( - "Mref_ex", - "g-var-extern", - new GlobalInstance(Value.externRef(0), MutabilityType.Var))) - .addTable( - new HostTable( - "Mtable_ex", - "t-func", - new TableInstance( - new Table(ValueType.FuncRef, new Limits(1))))) - .addTable( - new HostTable( - "Mtable_ex", - "t-extern", - new TableInstance( - new Table(ValueType.ExternRef, new Limits(1))))); - - if (MgInstance != null) { - builder.addGlobal( - new HostGlobal("Mg", "glob", MgInstance.global(0)), - new HostGlobal("Mg", "mut_glob", MgInstance.global(1))); - } - - if (MsInstance != null) { - builder.addMemory(new HostMemory("Ms", "memory", MsInstance.memory())) - .addTable(new HostTable("Ms", "table", MsInstance.table(0))); - } - if (MmInstance != null) { - builder.addMemory(MmMem()); - } - if (MtInstance != null) { - builder.addTable(new HostTable("Mt", "tab", MtInstance.table(0))); - } - - return builder.build(); - } -} diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1NamesHostFuncs.java b/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1NamesHostFuncs.java deleted file mode 100644 index ba8b094e6..000000000 --- a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1NamesHostFuncs.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1NamesHostFuncs { - - private SpecV1NamesHostFuncs() {} - - public static HostImports fallback() { - return new HostImports( - new HostFunction[] { - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32", - List.of(ValueType.I32), - List.of()) - }); - } -} diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1RefFuncHostFuncs.java b/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1RefFuncHostFuncs.java deleted file mode 100644 index 9ca93b9fc..000000000 --- a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1RefFuncHostFuncs.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1RefFuncHostFuncs { - - private SpecV1RefFuncHostFuncs() {} - - public static HostImports fallback() { - return HostImports.builder() - .addFunction( - new HostFunction( - (Instance instance, Value... args) -> args, - "M", - "f", - List.of(ValueType.I32), - List.of(ValueType.I32))) - .addFunction( - new HostFunction( - (Instance instance, Value... args) -> args, - "M", - "g", - List.of(ValueType.I32), - List.of(ValueType.I32))) - .build(); - } -} diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1StartHostFuncs.java b/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1StartHostFuncs.java deleted file mode 100644 index b1a47c7eb..000000000 --- a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1StartHostFuncs.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1StartHostFuncs { - - private SpecV1StartHostFuncs() {} - - public static HostImports fallback() { - return new HostImports( - new HostFunction[] { - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print_i32", - List.of(ValueType.I32), - List.of()), - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print", - List.of(), - List.of()) - }); - } -} diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1TableCopyHostFuncs.java b/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1TableCopyHostFuncs.java deleted file mode 100644 index 8f2131a5e..000000000 --- a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1TableCopyHostFuncs.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1TableCopyHostFuncs { - - private SpecV1TableCopyHostFuncs() {} - - public static HostImports fallback() { - return new HostImports( - new HostFunction[] { - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(0)}, - "a", - "ef0", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(1)}, - "a", - "ef1", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(2)}, - "a", - "ef2", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(3)}, - "a", - "ef3", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(4)}, - "a", - "ef4", - List.of(), - List.of(ValueType.I32)) - }); - } -} diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1TableHostFuncs.java b/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1TableHostFuncs.java deleted file mode 100644 index 939c11735..000000000 --- a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1TableHostFuncs.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.HostTable; -import com.dylibso.chicory.runtime.TableInstance; -import com.dylibso.chicory.wasm.types.Limits; -import com.dylibso.chicory.wasm.types.Table; -import com.dylibso.chicory.wasm.types.ValueType; - -public final class SpecV1TableHostFuncs { - - private SpecV1TableHostFuncs() {} - - public static HostImports fallback() { - return HostImports.builder() - .addTable( - new HostTable( - "spectest", - "table", - new TableInstance(new Table(ValueType.FuncRef, new Limits(10))))) - .build(); - } -} diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1TableInitHostFuncs.java b/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1TableInitHostFuncs.java deleted file mode 100644 index 8e9ba5147..000000000 --- a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1TableInitHostFuncs.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.types.Value; -import com.dylibso.chicory.wasm.types.ValueType; -import java.util.List; - -public final class SpecV1TableInitHostFuncs { - - private SpecV1TableInitHostFuncs() {} - - public static HostImports fallback() { - return new HostImports( - new HostFunction[] { - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(0)}, - "a", - "ef0", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(1)}, - "a", - "ef1", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(2)}, - "a", - "ef2", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(3)}, - "a", - "ef3", - List.of(), - List.of(ValueType.I32)), - new HostFunction( - (Instance instance, Value... args) -> new Value[] {Value.i32(4)}, - "a", - "ef4", - List.of(), - List.of(ValueType.I32)) - }); - } -} diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1TokensHostFuncs.java b/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1TokensHostFuncs.java deleted file mode 100644 index 7b115ef16..000000000 --- a/runtime-tests/src/test/java/com/dylibso/chicory/imports/SpecV1TokensHostFuncs.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.dylibso.chicory.imports; - -import com.dylibso.chicory.runtime.HostFunction; -import com.dylibso.chicory.runtime.HostImports; -import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.types.Value; -import java.util.List; - -public final class SpecV1TokensHostFuncs { - - private SpecV1TokensHostFuncs() {} - - public static HostImports fallback() { - return HostImports.builder() - .addFunction( - new HostFunction( - (Instance instance, Value... args) -> { - return null; - }, - "spectest", - "print", - List.of(), - List.of())) - .build(); - } -} diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/testing/Spectest.java b/runtime-tests/src/test/java/com/dylibso/chicory/testing/Spectest.java new file mode 100644 index 000000000..8706a2dae --- /dev/null +++ b/runtime-tests/src/test/java/com/dylibso/chicory/testing/Spectest.java @@ -0,0 +1,77 @@ +package com.dylibso.chicory.testing; + +import com.dylibso.chicory.runtime.GlobalInstance; +import com.dylibso.chicory.runtime.HostFunction; +import com.dylibso.chicory.runtime.HostGlobal; +import com.dylibso.chicory.runtime.HostImports; +import com.dylibso.chicory.runtime.HostMemory; +import com.dylibso.chicory.runtime.HostTable; +import com.dylibso.chicory.runtime.Instance; +import com.dylibso.chicory.runtime.Memory; +import com.dylibso.chicory.runtime.TableInstance; +import com.dylibso.chicory.runtime.WasmFunctionHandle; +import com.dylibso.chicory.wasm.types.Limits; +import com.dylibso.chicory.wasm.types.MemoryLimits; +import com.dylibso.chicory.wasm.types.Table; +import com.dylibso.chicory.wasm.types.Value; +import com.dylibso.chicory.wasm.types.ValueType; +import java.util.List; + +// https://github.com/WebAssembly/spec/blob/ee82c8e50c5106e0cedada0a083d4cc4129034a2/interpreter/host/spectest.ml +public final class Spectest { + private static final WasmFunctionHandle noop = (Instance instance, Value... args) -> null; + + private Spectest() {} + + public static HostImports toHostImports() { + return new HostImports( + new HostFunction[] { + new HostFunction(noop, "spectest", "print", List.of(), List.of()), + new HostFunction( + noop, "spectest", "print_i32", List.of(ValueType.I32), List.of()), + new HostFunction( + noop, "spectest", "print_i32_1", List.of(ValueType.I32), List.of()), + new HostFunction( + noop, "spectest", "print_i32_2", List.of(ValueType.I32), List.of()), + new HostFunction( + noop, "spectest", "print_f32", List.of(ValueType.F32), List.of()), + new HostFunction( + noop, + "spectest", + "print_i32_f32", + List.of(ValueType.I32, ValueType.F32), + List.of()), + new HostFunction( + noop, "spectest", "print_i64", List.of(ValueType.I64), List.of()), + new HostFunction( + noop, "spectest", "print_i64_1", List.of(ValueType.I64), List.of()), + new HostFunction( + noop, "spectest", "print_i64_2", List.of(ValueType.I64), List.of()), + new HostFunction( + noop, "spectest", "print_f64", List.of(ValueType.F64), List.of()), + new HostFunction( + noop, + "spectest", + "print_f64_f64", + List.of(ValueType.F64, ValueType.F64), + List.of()) + }, + new HostGlobal[] { + new HostGlobal("spectest", "global_i32", new GlobalInstance(Value.i32(666))), + new HostGlobal("spectest", "global_i64", new GlobalInstance(Value.i64(666))), + new HostGlobal( + "spectest", "global_f32", new GlobalInstance(Value.fromFloat(666.6f))), + new HostGlobal( + "spectest", "global_f64", new GlobalInstance(Value.fromDouble(666.6))), + }, + new HostMemory[] { + new HostMemory("spectest", "memory", new Memory(new MemoryLimits(1, 2))) + }, + new HostTable[] { + new HostTable( + "spectest", + "table", + new TableInstance(new Table(ValueType.FuncRef, new Limits(10, 20)))) + }); + } +} diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/testing/TestModule.java b/runtime-tests/src/test/java/com/dylibso/chicory/testing/TestModule.java index 014e99ee7..c8cebb144 100644 --- a/runtime-tests/src/test/java/com/dylibso/chicory/testing/TestModule.java +++ b/runtime-tests/src/test/java/com/dylibso/chicory/testing/TestModule.java @@ -2,6 +2,7 @@ import com.dylibso.chicory.runtime.HostImports; import com.dylibso.chicory.runtime.Instance; +import com.dylibso.chicory.runtime.Store; import com.dylibso.chicory.wabt.Wat2Wasm; import com.dylibso.chicory.wasm.Module; import com.dylibso.chicory.wasm.Parser; @@ -11,9 +12,6 @@ public class TestModule { private Module module; - private Instance instance; - - private HostImports imports; private static final String HACK_MATCH_ALL_MALFORMED_EXCEPTION_TEXT = "Matching keywords to get the WebAssembly testsuite to pass: " @@ -62,13 +60,8 @@ public TestModule(Module module) { this.module = module; } - public Instance build() { - this.instance = Instance.builder(module).withHostImports(imports).build(); - return this.instance; - } - - public TestModule withHostImports(HostImports imports) { - this.imports = imports; - return this; + public Instance instantiate(Store s) { + HostImports hostImports = s.toHostImports(); + return Instance.builder(module).withHostImports(hostImports).build(); } } diff --git a/runtime/src/main/java/com/dylibso/chicory/runtime/Instance.java b/runtime/src/main/java/com/dylibso/chicory/runtime/Instance.java index 6d5e25657..29a7f4cc9 100644 --- a/runtime/src/main/java/com/dylibso/chicory/runtime/Instance.java +++ b/runtime/src/main/java/com/dylibso/chicory/runtime/Instance.java @@ -457,19 +457,26 @@ private void validateHostTableType(TableImport i, HostTable t) { } private void validateHostMemoryType(MemoryImport i, HostMemory m) { - var initialExpected = m.memory().initialPages(); - var maxExpected = m.memory().maximumPages(); - var initialCurrent = i.limits().initialPages(); - var maxCurrent = + // Notice we do not compare to m.memory().initialPages() + // because m might have grown in the meantime. + // Instead, we use the current number of pages. + var hostMemCurrentPages = m.memory().pages(); + var hostMemMaxPages = m.memory().maximumPages(); + var importInitialPages = i.limits().initialPages(); + var importMaxPages = (i.limits().maximumPages() == MemoryLimits.MAX_PAGES) ? Memory.RUNTIME_MAX_PAGES : i.limits().maximumPages(); - if (initialCurrent > initialExpected - || (maxCurrent < maxExpected && maxCurrent == initialCurrent)) { + + // HostMem bounds [x,y] must be within the import bounds [a, b]; i.e., a <= x, y >= b. + // In other words, the bounds are not valid when: + // - HostMem current number of pages cannot be less than the import lower bound. + // - HostMem upper bound cannot be larger than the given upper bound. + if (hostMemCurrentPages < importInitialPages || hostMemMaxPages > importMaxPages) { throw new UnlinkableException( - "incompatible import type, non-compatible limits, expected: " + "incompatible import type, non-compatible limits, import: " + i.limits() - + ", current: " + + ", host: " + m.memory().limits() + " on memory: " + m.moduleName() diff --git a/runtime/src/main/java/com/dylibso/chicory/runtime/Store.java b/runtime/src/main/java/com/dylibso/chicory/runtime/Store.java new file mode 100644 index 000000000..ea6993013 --- /dev/null +++ b/runtime/src/main/java/com/dylibso/chicory/runtime/Store.java @@ -0,0 +1,166 @@ +package com.dylibso.chicory.runtime; + +import com.dylibso.chicory.wasm.Module; +import com.dylibso.chicory.wasm.types.Export; +import com.dylibso.chicory.wasm.types.ExportSection; +import com.dylibso.chicory.wasm.types.FunctionType; +import java.util.LinkedHashMap; +import java.util.Objects; + +/** + * The runtime storage for all function, global, memory, table instances. + */ +public class Store { + final LinkedHashMap functions = new LinkedHashMap<>(); + final LinkedHashMap globals = new LinkedHashMap<>(); + final LinkedHashMap memories = new LinkedHashMap<>(); + final LinkedHashMap tables = new LinkedHashMap<>(); + + public Store() {} + + /** + * Add a function to the store. + */ + public Store addFunction(HostFunction... function) { + for (var f : function) { + functions.put(new QualifiedName(f.moduleName(), f.fieldName()), f); + } + return this; + } + + /** + * Add a global to the store. + */ + public Store addGlobal(HostGlobal... global) { + for (var g : global) { + globals.put(new QualifiedName(g.moduleName(), g.fieldName()), g); + } + return this; + } + + /** + * Add a memory to the store. + */ + public Store addMemory(HostMemory... memory) { + for (var m : memory) { + memories.put(new QualifiedName(m.moduleName(), m.fieldName()), m); + } + return this; + } + + /** + * Add a table to the store. + */ + public Store addTable(HostTable... table) { + for (var t : table) { + tables.put(new QualifiedName(t.moduleName(), t.fieldName()), t); + } + return this; + } + + /** + * Add the contents of a {@link HostImports} instance to the store. + */ + public Store addHostImports(HostImports hostImports) { + return this.addGlobal(hostImports.globals()) + .addFunction(hostImports.functions()) + .addMemory(hostImports.memories()) + .addTable(hostImports.tables()); + } + + /** + * Convert the contents of a store to a {@link HostImports} instance. + */ + public HostImports toHostImports() { + return new HostImports( + functions.values().toArray(new HostFunction[0]), + globals.values().toArray(new HostGlobal[0]), + memories.values().toArray(new HostMemory[0]), + tables.values().toArray(new HostTable[0])); + } + + /** + * Register an instance in the store with the given name. + * All the exported functions, globals, memories, and tables are added to the store + * with the given name. + * + * For instance, if a module named "myModule" exports a function + * named "myFunction", the function will be added to the store with the name "myFunction.myModule". + * + */ + public Store register(String name, Instance instance) { + ExportSection exportSection = instance.module().exportSection(); + for (int i = 0; i < exportSection.exportCount(); i++) { + Export export = exportSection.getExport(i); + String exportName = export.name(); + switch (export.exportType()) { + case FUNCTION: + ExportFunction f = instance.export(exportName); + FunctionType ftype = instance.exportType(exportName); + this.addFunction( + new HostFunction( + (inst, args) -> f.apply(args), + name, + exportName, + ftype.params(), + ftype.returns())); + break; + + case TABLE: + this.addTable(new HostTable(name, exportName, instance.table(export.index()))); + break; + + case MEMORY: + this.addMemory(new HostMemory(name, exportName, instance.memory())); + break; + + case GLOBAL: + GlobalInstance g = instance.global(export.index()); + this.addGlobal(new HostGlobal(name, exportName, g)); + break; + } + } + return this; + } + + /** + * A shorthand for instantiating a module and registering it in the store. + */ + public Instance instantiate(String name, Module m) { + HostImports hostImports = toHostImports(); + Instance instance = Instance.builder(m).withHostImports(hostImports).build(); + register(name, instance); + return instance; + } + + /** + * QualifiedName is internally used to use pairs (moduleName, name) as keys in the store. + */ + static class QualifiedName { + private final String moduleName; + private final String fieldName; + + public QualifiedName(String moduleName, String fieldName) { + this.moduleName = moduleName; + this.fieldName = fieldName; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof QualifiedName)) { + return false; + } + QualifiedName qualifiedName = (QualifiedName) o; + return Objects.equals(moduleName, qualifiedName.moduleName) + && Objects.equals(fieldName, qualifiedName.fieldName); + } + + @Override + public int hashCode() { + return Objects.hash(moduleName, fieldName); + } + } +} diff --git a/runtime/src/test/java/com/dylibso/chicory/runtime/StoreTest.java b/runtime/src/test/java/com/dylibso/chicory/runtime/StoreTest.java new file mode 100644 index 000000000..f1ed16315 --- /dev/null +++ b/runtime/src/test/java/com/dylibso/chicory/runtime/StoreTest.java @@ -0,0 +1,133 @@ +package com.dylibso.chicory.runtime; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.dylibso.chicory.wasm.Module; +import com.dylibso.chicory.wasm.Parser; +import java.util.List; +import org.junit.jupiter.api.Test; + +public class StoreTest { + + private static Module loadModule(String fileName) { + return Parser.parse(ModuleTest.class.getResourceAsStream("/" + fileName)); + } + + @Test + public void nameClashesShouldOverwriteTheStore() { + Store store = new Store(); + + HostFunction f1 = new HostFunction(null, "m", "f", null, null); + store.addFunction(f1); + assertEquals(f1, store.functions.get(new Store.QualifiedName("m", "f"))); + + HostFunction f2 = new HostFunction(null, "m", "f", null, null); + store.addFunction(f2); + assertEquals(f2, store.functions.get(new Store.QualifiedName("m", "f"))); + } + + @Test + public void exportsShouldBeRegistered() { + var instance = Instance.builder(loadModule("compiled/exports.wat.wasm")).build(); + var store = new Store(); + String moduleName = "exports-module"; + store.register(moduleName, instance); + + // memories + assertEquals(1, store.memories.size()); + assertTrue(store.memories.containsKey(new Store.QualifiedName(moduleName, "mem"))); + + // tables + assertEquals(1, store.tables.size()); + assertTrue(store.tables.containsKey(new Store.QualifiedName(moduleName, "tab"))); + + // globals + assertEquals(4, store.globals.size()); + assertTrue(store.globals.containsKey(new Store.QualifiedName(moduleName, "glob1"))); + assertTrue(store.globals.containsKey(new Store.QualifiedName(moduleName, "glob2"))); + assertTrue(store.globals.containsKey(new Store.QualifiedName(moduleName, "glob3"))); + assertTrue(store.globals.containsKey(new Store.QualifiedName(moduleName, "glob4"))); + + // funcs + assertEquals(4, store.functions.size()); + assertTrue(store.functions.containsKey(new Store.QualifiedName(moduleName, "get-1"))); + assertTrue(store.functions.containsKey(new Store.QualifiedName(moduleName, "get-2"))); + assertTrue(store.functions.containsKey(new Store.QualifiedName(moduleName, "get-3"))); + assertTrue(store.functions.containsKey(new Store.QualifiedName(moduleName, "get-4"))); + } + + @Test + public void instantiateShouldRegisterInstance() { + var store = new Store(); + String moduleName = "exports-module"; + var inst = store.instantiate(moduleName, loadModule("compiled/exports.wat.wasm")); + assertNotNull(inst); + + // memories + assertEquals(1, store.memories.size()); + assertTrue(store.memories.containsKey(new Store.QualifiedName(moduleName, "mem"))); + + // tables + assertEquals(1, store.tables.size()); + assertTrue(store.tables.containsKey(new Store.QualifiedName(moduleName, "tab"))); + + // globals + assertEquals(4, store.globals.size()); + assertTrue(store.globals.containsKey(new Store.QualifiedName(moduleName, "glob1"))); + assertTrue(store.globals.containsKey(new Store.QualifiedName(moduleName, "glob2"))); + assertTrue(store.globals.containsKey(new Store.QualifiedName(moduleName, "glob3"))); + assertTrue(store.globals.containsKey(new Store.QualifiedName(moduleName, "glob4"))); + + // funcs + assertEquals(4, store.functions.size()); + assertTrue(store.functions.containsKey(new Store.QualifiedName(moduleName, "get-1"))); + assertTrue(store.functions.containsKey(new Store.QualifiedName(moduleName, "get-2"))); + assertTrue(store.functions.containsKey(new Store.QualifiedName(moduleName, "get-3"))); + assertTrue(store.functions.containsKey(new Store.QualifiedName(moduleName, "get-4"))); + } + + @Test + public void registerMultipleInstancesDifferentNamesCauseNoClash() { + var store = new Store(); + + String name1 = "exports-module-1"; + store.instantiate(name1, loadModule("compiled/exports.wat.wasm")); + + String name2 = "exports-module-2"; + store.instantiate(name2, loadModule("compiled/exports.wat.wasm")); + + var names = List.of(name1, name2); + + // memories + assertEquals(2, store.memories.size()); + for (var name : names) { + assertTrue(store.memories.containsKey(new Store.QualifiedName(name, "mem"))); + } + + // tables + assertEquals(2, store.tables.size()); + for (var name : names) { + assertTrue(store.tables.containsKey(new Store.QualifiedName(name, "tab"))); + } + + // globals + assertEquals(8, store.globals.size()); + for (var name : names) { + assertTrue(store.globals.containsKey(new Store.QualifiedName(name, "glob1"))); + assertTrue(store.globals.containsKey(new Store.QualifiedName(name, "glob2"))); + assertTrue(store.globals.containsKey(new Store.QualifiedName(name, "glob3"))); + assertTrue(store.globals.containsKey(new Store.QualifiedName(name, "glob4"))); + } + + // funcs + assertEquals(8, store.functions.size()); + for (var name : names) { + assertTrue(store.functions.containsKey(new Store.QualifiedName(name, "get-1"))); + assertTrue(store.functions.containsKey(new Store.QualifiedName(name, "get-2"))); + assertTrue(store.functions.containsKey(new Store.QualifiedName(name, "get-3"))); + assertTrue(store.functions.containsKey(new Store.QualifiedName(name, "get-4"))); + } + } +} diff --git a/test-gen-plugin/src/main/java/com/dylibso/chicory/maven/JavaTestGen.java b/test-gen-plugin/src/main/java/com/dylibso/chicory/maven/JavaTestGen.java index 74710e842..b2fefe98d 100644 --- a/test-gen-plugin/src/main/java/com/dylibso/chicory/maven/JavaTestGen.java +++ b/test-gen-plugin/src/main/java/com/dylibso/chicory/maven/JavaTestGen.java @@ -28,7 +28,6 @@ import com.github.javaparser.utils.SourceRoot; import com.github.javaparser.utils.StringEscapeUtils; import java.io.File; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -74,7 +73,6 @@ public CompilationUnit generate( String name, Wast wast, File wasmFilesFolder, SourceRoot importsSourceRoot) { var cu = new CompilationUnit("com.dylibso.chicory.test.gen"); var testName = "SpecV1" + capitalize(escapedCamelCase(name)) + "Test"; - var importsName = "SpecV1" + capitalize(escapedCamelCase(name)) + "HostFuncs"; cu.setStorage(sourceTargetFolder.toPath().resolve(testName + ".java")); // all the imports @@ -107,8 +105,10 @@ public CompilationUnit generate( cu.addImport("com.dylibso.chicory.wasm.exceptions.UnlinkableException"); cu.addImport("com.dylibso.chicory.wasm.types.Value"); - // import for host functions - cu.addImport("com.dylibso.chicory.imports.*"); + // import for Store instance + cu.addImport("com.dylibso.chicory.runtime.Store"); + // import for shared Spectest host module + cu.addImport("com.dylibso.chicory.testing.Spectest"); var testClass = cu.addClass(testName); testClass.addSingleMemberAnnotation( @@ -131,6 +131,11 @@ public CompilationUnit generate( .map(t -> t.substring(testName.length() + 1)) .collect(Collectors.toList()); + testClass.addFieldWithInitializer( + "Store", + "store", + new NameExpr("new Store().addHostImports(Spectest.toHostImports())")); + String currentWasmFile = null; for (var cmd : wast.commands()) { switch (cmd.type()) { @@ -144,8 +149,6 @@ public CompilationUnit generate( lastModuleVarName = cmd.name().replace("$", ""); lastInstanceVarName = cmd.name().replace("$", "") + "Instance"; } - String hostFuncs = - detectImports(importsName, lastModuleVarName, importsSourceRoot); testClass.addFieldWithInitializer( "Instance", lastInstanceVarName, @@ -175,8 +178,6 @@ public CompilationUnit generate( new NameExpr(lastInstanceVarName), generateModuleInstantiation( currentWasmFile, - importsName, - hostFuncs, getExcluded( CommandType.ASSERT_INVALID, name)), @@ -220,7 +221,24 @@ public CompilationUnit generate( break; } case REGISTER: - // should be irrelevant + String lastInstanceVarName = lastModuleVarName + "Instance"; + + generateRegisterInstance(cmd.as(), lastInstanceVarName); + + var instantiateMethodName = "register_" + lastInstanceVarName; + var instantiateMethod = + testClass.addMethod(instantiateMethodName, Modifier.Keyword.PUBLIC); + // It needs to be a test to be executed + instantiateMethod.addAnnotation("Test"); + instantiateMethod.addSingleMemberAnnotation( + "Order", new IntegerLiteralExpr(Integer.toString(testNumber++))); + + instantiateMethod.setBody( + new BlockStmt() + .addStatement( + generateRegisterInstance( + cmd.as(), lastInstanceVarName))); + break; case ASSERT_MALFORMED: case ASSERT_INVALID: @@ -234,14 +252,10 @@ public CompilationUnit generate( testClass, testNumber++, excludedMethods); - String hostFuncs = - detectImports(importsName, "fallback", importsSourceRoot); generateAssertThrows( wasmFilesFolder, cmd, method, - importsName, - hostFuncs, getExcluded(cmd.type(), name), getExceptionType(cmd.type())); break; @@ -428,8 +442,7 @@ private List generateInvoke(String varName, Command cmd) { private static final String TAB = " "; private static final String INDENT = TAB + TAB + TAB + TAB + TAB; - private static NameExpr generateModuleInstantiation( - String wasmFile, String importsName, String hostFuncs, boolean excludeInvalid) { + private static NameExpr generateModuleInstantiation(String wasmFile, boolean excludeInvalid) { return new NameExpr( "TestModule.of(\n" + INDENT @@ -438,41 +451,12 @@ private static NameExpr generateModuleInstantiation( + wasmFile + "\"))\n" + ((excludeInvalid) ? INDENT + ".withTypeValidation(false)\n" : "") - + ((hostFuncs != null) - ? INDENT - + ".withHostImports(" - + importsName - + "." - + hostFuncs - + "())\n" - : "") + INDENT - + ".build()"); + + ".instantiate(store)"); } - private String detectImports(String importsName, String varName, SourceRoot testSourcesRoot) { - String hostFuncs = null; - try { - var parsed = - testSourcesRoot.tryToParse( - "com.dylibso.chicory.imports", importsName + ".java"); - if (parsed.isSuccessful()) { - var methods = - parsed.getResult().get().getClassByName(importsName).get().getMethods(); - - for (int i = 0; i < methods.size(); i++) { - if (methods.get(i).getName().asString().equals(varName)) { - hostFuncs = varName; - } - } - if (hostFuncs == null) { - hostFuncs = "fallback"; - } - } - } catch (IOException e) { - // ignore - } - return hostFuncs; + private static NameExpr generateRegisterInstance(String name, String instance) { + return new NameExpr("store.register(\"" + name + "\", " + instance + ")"); } private String getWasmFile(Command cmd, File folder) { @@ -488,8 +472,6 @@ private void generateAssertThrows( File wasmFilesFolder, Command cmd, MethodDeclaration method, - String importsName, - String hostFuncs, boolean excluded, String exceptionType) { @@ -503,8 +485,7 @@ private void generateAssertThrows( + "assertThrows(" + exceptionType + ".class, () -> " - + generateModuleInstantiation( - wasmFile, importsName, hostFuncs, false) + + generateModuleInstantiation(wasmFile, false) + ")"); method.getBody().get().addStatement(assertThrows); diff --git a/wasm-corpus/src/main/resources/compiled/exports.wat.wasm b/wasm-corpus/src/main/resources/compiled/exports.wat.wasm new file mode 100644 index 0000000000000000000000000000000000000000..4cb49f4ce8cc45fc7d03e23fb7f0633d84f24269 GIT binary patch literal 158 zcmXAiyA6Xt5JYEhc5Ue{rUGZS3HUTX0q(&dArhZ#336KZ9whH+^n$^-W&t23Z^%wl zA5fJaqS4Ex(jCJ+IUWVif;wGak$KJm+{Q^@%jY{aJl#@`-7y^QNn7TvZs6VB`de`a R@9rLql`3vX4k-u)On;qq7@+_F literal 0 HcmV?d00001 diff --git a/wasm-corpus/src/main/resources/wat/exports.wat b/wasm-corpus/src/main/resources/wat/exports.wat new file mode 100644 index 000000000..80cd824e5 --- /dev/null +++ b/wasm-corpus/src/main/resources/wat/exports.wat @@ -0,0 +1,12 @@ +(module + (memory (export "mem") 0) + (table (export "tab") 10 funcref) + (global $glob1 (export "glob1") i32 (i32.const 42)) + (global $glob2 (export "glob2") i32 (i32.const 43)) + (global $glob3 (export "glob3") i32 (i32.const 44)) + (global $glob4 (export "glob4") i32 (i32.const 45)) + (func (export "get-1") (result i32) (global.get $glob1)) + (func (export "get-2") (result i32) (global.get $glob2)) + (func (export "get-3") (result i32) (global.get $glob3)) + (func (export "get-4") (result i32) (global.get $glob4)) +) diff --git a/wasm/src/main/java/com/dylibso/chicory/wasm/Module.java b/wasm/src/main/java/com/dylibso/chicory/wasm/Module.java index cf97dbfe6..1caed4f60 100644 --- a/wasm/src/main/java/com/dylibso/chicory/wasm/Module.java +++ b/wasm/src/main/java/com/dylibso/chicory/wasm/Module.java @@ -256,6 +256,9 @@ public Module build() { validator.validateModule(); if (validate) { validator.validateFunctions(); + validator.validateGlobals(); + validator.validateElements(); + validator.validateData(); } return module; diff --git a/wasm/src/main/java/com/dylibso/chicory/wasm/Validator.java b/wasm/src/main/java/com/dylibso/chicory/wasm/Validator.java index c5a3f3ae3..25a518b5e 100644 --- a/wasm/src/main/java/com/dylibso/chicory/wasm/Validator.java +++ b/wasm/src/main/java/com/dylibso/chicory/wasm/Validator.java @@ -7,6 +7,8 @@ import com.dylibso.chicory.wasm.exceptions.InvalidException; import com.dylibso.chicory.wasm.exceptions.MalformedException; +import com.dylibso.chicory.wasm.types.ActiveDataSegment; +import com.dylibso.chicory.wasm.types.ActiveElement; import com.dylibso.chicory.wasm.types.AnnotatedInstruction; import com.dylibso.chicory.wasm.types.DeclarativeElement; import com.dylibso.chicory.wasm.types.Element; @@ -337,6 +339,120 @@ public void validateModule() { } } + public void validateData() { + // Validate offsets. + for (var ds : module.dataSection().dataSegments()) { + if (ds instanceof ActiveDataSegment) { + var ads = (ActiveDataSegment) ds; + validateConstantExpression(ads.offsetInstructions(), ValueType.I32); + } + } + } + + public void validateElements() { + // Validate offsets. + for (Element el : module.elementSection().elements()) { + if (el instanceof ActiveElement) { + var ae = (ActiveElement) el; + validateConstantExpression(ae.offset(), ValueType.I32); + } + } + } + + public void validateGlobals() { + for (Global g : module.globalSection().globals()) { + validateConstantExpression(g.initInstructions(), g.valueType()); + } + } + + private void validateConstantExpression( + List expr, ValueType expectedType) { + int allFuncCount = this.functionImports.size() + module.functionSection().functionCount(); + int constInstrCount = 0; + for (var instruction : expr) { + ValueType exprType = null; + + long[] operands = instruction.operands(); + switch (instruction.opcode()) { + case I32_CONST: + exprType = ValueType.I32; + constInstrCount++; + break; + case I64_CONST: + exprType = ValueType.I64; + constInstrCount++; + break; + case F32_CONST: + exprType = ValueType.F32; + constInstrCount++; + break; + case F64_CONST: + exprType = ValueType.F64; + constInstrCount++; + break; + case REF_NULL: + { + exprType = ValueType.refTypeForId((int) operands[0]); + constInstrCount++; + if (exprType != ValueType.ExternRef && exprType != ValueType.FuncRef) { + throw new IllegalStateException( + "Unexpected wrong type for ref.null instruction"); + } + break; + } + case REF_FUNC: + { + exprType = ValueType.FuncRef; + constInstrCount++; + long idx = operands[0]; + + if (idx < 0 || idx > allFuncCount) { + throw new InvalidException("unknown function " + idx); + } + + break; + } + case GLOBAL_GET: + { + var idx = (int) operands[0]; + if (idx < globalImports.size()) { + var global = globalImports.get(idx); + if (global.mutabilityType() != MutabilityType.Const) { + throw new InvalidException( + "constant expression required, initializer expression" + + " cannot reference a mutable global"); + } + exprType = global.valueType(); + } else { + throw new InvalidException( + "unknown global " + + idx + + ", initializer expression can only reference" + + " an imported global"); + } + constInstrCount++; + break; + } + case END: + break; + default: + throw new InvalidException( + "constant expression required, but non-constant instruction" + + " encountered: " + + instruction); + } + + if (exprType != null && exprType != expectedType) { + throw new InvalidException("type mismatch"); + } + + // There must be at most one constant instruction. + if (constInstrCount > 1) { + throw new InvalidException("type mismatch, multiple constant expressions found"); + } + } + } + public void validateFunctions() { for (var i = 0; i < module.codeSection().functionBodyCount(); i++) { var body = module.codeSection().getFunctionBody(i);