Support parsing the text format in wasmtime crate (#813)

* Support parsing the text format in `wasmtime` crate

This commit adds support to the `wasmtime::Module` type to parse the
text format. This is often quite convenient to support in testing or
tinkering with the runtime. Additionally the `wat` parser is pretty
lightweight and easy to add to builds, so it's relatively easy for us to
support as well!

The exact manner that this is now supported comes with a few updates to
the existing API:

* A new optional feature of the `wasmtime` crate, `wat`, has been added.
  This is enabled by default.
* The `Module::new` API now takes `impl AsRef<[u8]>` instead of just
  `&[u8]`, and when the `wat` feature is enabled it will attempt to
  interpret it either as a wasm binary or as the text format. Note that
  this check is quite cheap since you just check the first byte.
* A `Module::from_file` API was added as a convenience to parse a file
  from disk, allowing error messages for `*.wat` files on disk to be a
  bit nicer.
* APIs like `Module::new_unchecked` and `Module::validate` remain
  unchanged, they require the binary format to be called.

The intention here is to make this as convenient as possible for new
developers of the `wasmtime` crate. By changing the default behavior
though this has ramifications such as, for example, supporting the text
format implicitly through the C API now.

* Handle review comments

* Update more tests to avoid usage of `wat` crate

* Go back to unchecked for now in wasm_module_new

Looks like C# tests rely on this?
This commit is contained in:
Alex Crichton
2020-01-24 14:20:51 -06:00
committed by GitHub
parent 47d6db0be8
commit 16804673a2
15 changed files with 185 additions and 168 deletions

View File

@@ -13,16 +13,14 @@ fn test_trap_return() -> Result<()> {
}
let store = Store::default();
let binary = wat::parse_str(
r#"
(module
(func $hello (import "" "hello"))
(func (export "run") (call $hello))
)
"#,
)?;
let wat = r#"
(module
(func $hello (import "" "hello"))
(func (export "run") (call $hello))
)
"#;
let module = Module::new(&store, &binary)?;
let module = Module::new(&store, wat)?;
let hello_type = FuncType::new(Box::new([]), Box::new([]));
let hello_func = Func::new(&store, hello_type, Rc::new(HelloCallback));
@@ -41,16 +39,14 @@ fn test_trap_return() -> Result<()> {
#[test]
fn test_trap_trace() -> Result<()> {
let store = Store::default();
let binary = wat::parse_str(
r#"
(module $hello_mod
(func (export "run") (call $hello))
(func $hello (unreachable))
)
"#,
)?;
let wat = r#"
(module $hello_mod
(func (export "run") (call $hello))
(func $hello (unreachable))
)
"#;
let module = Module::new(&store, &binary)?;
let module = Module::new(&store, wat)?;
let instance = Instance::new(&module, &[])?;
let run_func = instance.exports()[0]
.func()
@@ -82,20 +78,18 @@ fn test_trap_trace_cb() -> Result<()> {
}
let store = Store::default();
let binary = wat::parse_str(
r#"
(module $hello_mod
(import "" "throw" (func $throw))
(func (export "run") (call $hello))
(func $hello (call $throw))
)
"#,
)?;
let wat = r#"
(module $hello_mod
(import "" "throw" (func $throw))
(func (export "run") (call $hello))
(func $hello (call $throw))
)
"#;
let fn_type = FuncType::new(Box::new([]), Box::new([]));
let fn_func = Func::new(&store, fn_type, Rc::new(ThrowCallback));
let module = Module::new(&store, &binary)?;
let module = Module::new(&store, wat)?;
let instance = Instance::new(&module, &[fn_func.into()])?;
let run_func = instance.exports()[0]
.func()
@@ -117,15 +111,13 @@ fn test_trap_trace_cb() -> Result<()> {
#[test]
fn test_trap_stack_overflow() -> Result<()> {
let store = Store::default();
let binary = wat::parse_str(
r#"
(module $rec_mod
(func $run (export "run") (call $run))
)
"#,
)?;
let wat = r#"
(module $rec_mod
(func $run (export "run") (call $run))
)
"#;
let module = Module::new(&store, &binary)?;
let module = Module::new(&store, wat)?;
let instance = Instance::new(&module, &[])?;
let run_func = instance.exports()[0]
.func()
@@ -148,18 +140,16 @@ fn test_trap_stack_overflow() -> Result<()> {
#[test]
fn trap_display_pretty() -> Result<()> {
let store = Store::default();
let binary = wat::parse_str(
r#"
(module $m
(func $die unreachable)
(func call $die)
(func $foo call 1)
(func (export "bar") call $foo)
)
"#,
)?;
let wat = r#"
(module $m
(func $die unreachable)
(func call $die)
(func $foo call 1)
(func (export "bar") call $foo)
)
"#;
let module = Module::new(&store, &binary)?;
let module = Module::new(&store, wat)?;
let instance = Instance::new(&module, &[])?;
let run_func = instance.exports()[0]
.func()
@@ -183,31 +173,27 @@ wasm backtrace:
#[test]
fn trap_display_multi_module() -> Result<()> {
let store = Store::default();
let binary = wat::parse_str(
r#"
(module $a
(func $die unreachable)
(func call $die)
(func $foo call 1)
(func (export "bar") call $foo)
)
"#,
)?;
let wat = r#"
(module $a
(func $die unreachable)
(func call $die)
(func $foo call 1)
(func (export "bar") call $foo)
)
"#;
let module = Module::new(&store, &binary)?;
let module = Module::new(&store, wat)?;
let instance = Instance::new(&module, &[])?;
let bar = instance.exports()[0].clone();
let binary = wat::parse_str(
r#"
(module $b
(import "" "" (func $bar))
(func $middle call $bar)
(func (export "bar2") call $middle)
)
"#,
)?;
let module = Module::new(&store, &binary)?;
let wat = r#"
(module $b
(import "" "" (func $bar))
(func $middle call $bar)
(func (export "bar2") call $middle)
)
"#;
let module = Module::new(&store, wat)?;
let instance = Instance::new(&module, &[bar])?;
let bar2 = instance.exports()[0]
.func()