* Validate modules while translating
This commit is a change to cranelift-wasm to validate each function body
as it is translated. Additionally top-level module translation functions
will perform module validation. This commit builds on changes in
wasmparser to perform module validation interwtwined with parsing and
translation. This will be necessary for future wasm features such as
module linking where the type behind a function index, for example, can
be far away in another module. Additionally this also brings a nice
benefit where parsing the binary only happens once (instead of having an
up-front serial validation step) and validation can happen in parallel
for each function.
Most of the changes in this commit are plumbing to make sure everything
lines up right. The major functional change here is that module
compilation should be faster by validating in parallel (or skipping
function validation entirely in the case of a cache hit). Otherwise from
a user-facing perspective nothing should be that different.
This commit does mean that cranelift's translation now inherently
validates the input wasm module. This means that the Spidermonkey
integration of cranelift-wasm will also be validating the function as
it's being translated with cranelift. The associated PR for wasmparser
(bytecodealliance/wasmparser#62) provides the necessary tools to create
a `FuncValidator` for Gecko, but this is something I'll want careful
review for before landing!
* Read function operators until EOF
This way we can let the validator take care of any issues with
mismatched `end` instructions and/or trailing operators/bytes.
* Don't re-parse wasm for debuginfo
This commit updates debuginfo parsing to happen during the main
translation of the original wasm module. This avoid re-parsing the wasm
module twice (at least the section-level headers). Additionally this
ties debuginfo directly to a `ModuleTranslation` which makes it easier
to process debuginfo for nested modules in the upcoming module linking
proposal.
The changes here are summarized by taking the `read_debuginfo` function
and merging it with the main module translation that happens which is
driven by cranelift. Some new hooks were added to the module environment
trait to support this, but most of it was integrating with existing hooks.
* Fix tests in debug crate
This commit is intended to update wasmparser to 0.59.0. This primarily
includes bytecodealliance/wasm-tools#40 which is a large update to how
parsing and validation works. The impact on Wasmtime is pretty small at
this time, but over time I'd like to refactor the internals here to lean
more heavily on that upstream wasmparser refactoring.
For now, though, the intention is to get on the train of wasmparser's
latest `main` branch to ensure we get bug fixes and such.
As part of this update a few other crates and such were updated. This is
primarily to handle the new encoding of `ref.is_null` where the type is
not part of the instruction encoding any more.
* cranelift-wasm: replace `WasmTypesMap` with `ModuleTranslationState`
The `ModuleTranslationState` contains information decoded from the Wasm module
that must be referenced during each Wasm function's translation.
This is only for data that is maintained by `cranelift-wasm` itself, as opposed
to being maintained by the embedder. Data that is maintained by the embedder is
represented with `ModuleEnvironment`.
A `ModuleTranslationState` is returned by `translate_module`, and can then be
used when translating functions from that module.
* cranelift-wasm: rename `TranslationState` to `FuncTranslationState`
To disambiguate a bit with the new `ModuleTranslationState`.
* cranelift-wasm: Reorganize the internal `state` module into submodules
One module for the `ModuleTranslationState` and another for the
`FuncTranslationState`.
* cranelift-wasm: replace `FuncTranslator` with methods on `ModuleTranslationState`
`FuncTranslator` was two methods that always took ownership of `self`, so it
didn't really make sense as an object as opposed to two different functions, or
in this case methods on the object that actually persists for a longer time.
I think this improves ergonomics nicely.
Before:
```rust
let module_translation = translate_module(...)?;
for body in func_bodies {
let mut translator = FuncTranslator::new();
translator.translate(body, ...)?;
}
```
After:
```rust
let module_translation = translate_module(...)?;
for body in func_bodies {
module_translation.translate_func(body, ...)?;
}
```
Note that this commit does not remove `FuncTranslator`. It still exists, but is
just a wrapper over the `ModuleTranslationState` methods, and it is marked
deprecated, so that downstream users get a heads up. This should make the
transition easier.
* Revert "cranelift-wasm: replace `FuncTranslator` with methods on `ModuleTranslationState`"
This reverts commit 075f9ae933bcaae39348b61287c8f78a4009340d.
This commit introduces initial support for multi-value Wasm. Wasm blocks and
calls can now take and return an arbitrary number of values.
The encoding for multi-value blocks means that we need to keep the contents of
the "Types" section around when translating function bodies. To do this, we
introduce a `WasmTypesMap` type that maps the type indices to their parameters
and returns, construct it when parsing the "Types" section, and shepherd it
through a bunch of functions and methods when translating function bodies.
This commit adds a hook to the `ModuleEnvironment` trait to learn when a
custom section in a wasm file is read. This hook can in theory be used
to parse and handle custom sections as they appear in the wasm file
without having to re-iterate over the wasm file after cranelift has
already parsed the wasm file.
The `translate_module` function is now less strict in that it doesn't
require sections to be in a particular order, but it's figured that the
wasm file is already validated elsewhere to verify the section order.