Enable fuzzing the module linking implementation

This commit updates all the wasm-tools crates that we use and enables
fuzzing of the module linking proposal in our various fuzz targets. This
also refactors some of the dummy value generation logic to not be
fallible and to always succeed, the thinking being that we don't want to
accidentally hide errors while fuzzing. Additionally instantiation is
only allowed to fail with a `Trap`, other failure reasons are unwrapped.
This commit is contained in:
Alex Crichton
2020-12-07 15:57:35 -08:00
parent e09b9400f8
commit 25000afe69
22 changed files with 377 additions and 152 deletions

60
Cargo.lock generated
View File

@@ -394,7 +394,7 @@ dependencies = [
"souper-ir",
"target-lexicon",
"thiserror",
"wast 28.0.0",
"wast 29.0.0",
]
[[package]]
@@ -597,7 +597,7 @@ dependencies = [
"smallvec",
"target-lexicon",
"thiserror",
"wasmparser 0.69.2",
"wasmparser 0.70.0",
"wat",
]
@@ -1167,7 +1167,7 @@ dependencies = [
"smallvec",
"thiserror",
"typemap",
"wasmparser 0.69.2",
"wasmparser 0.70.0",
"wat",
]
@@ -1411,7 +1411,7 @@ dependencies = [
"peepmatic-test-operator",
"peepmatic-traits",
"serde",
"wast 28.0.0",
"wast 29.0.0",
"z3",
]
@@ -1439,7 +1439,7 @@ dependencies = [
"peepmatic-traits",
"rand",
"serde",
"wast 28.0.0",
"wast 29.0.0",
]
[[package]]
@@ -1464,7 +1464,7 @@ dependencies = [
"serde",
"serde_test",
"thiserror",
"wast 28.0.0",
"wast 29.0.0",
]
[[package]]
@@ -1476,7 +1476,7 @@ dependencies = [
"peepmatic",
"peepmatic-test-operator",
"souper-ir",
"wast 28.0.0",
"wast 29.0.0",
]
[[package]]
@@ -1497,7 +1497,7 @@ version = "0.68.0"
dependencies = [
"peepmatic-traits",
"serde",
"wast 28.0.0",
"wast 29.0.0",
]
[[package]]
@@ -2356,18 +2356,18 @@ dependencies = [
[[package]]
name = "wasm-encoder"
version = "0.1.0"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49891b7c581cf9e0090b25cd274e6498ad478f0a7819319ea96da2f253caaacb"
checksum = "ed89eaf99e08b84f96e477a16588a07dd3b51dc5f07291c3706782f62a10a5e1"
dependencies = [
"leb128",
]
[[package]]
name = "wasm-smith"
version = "0.1.12"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7fdf8c9ba2fdc0d8ffe3f7e5b23b5aac377eeca817a9885c058f27c8de5c500"
checksum = "cdd382e46cf44347f4d0c29122143cbab85cf248b9a8f680845c0239b6842a85"
dependencies = [
"arbitrary",
"leb128",
@@ -2406,18 +2406,18 @@ checksum = "32fddd575d477c6e9702484139cf9f23dcd554b06d185ed0f56c857dd3a47aa6"
[[package]]
name = "wasmparser"
version = "0.69.2"
version = "0.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd2dd6dadf3a723971297bcc0ec103e0aa8118bf68e23f49cb575e21621894a8"
checksum = "ed1b3f9e9cf01a580b9f3281214dfdb1922b5dfb8494ee312ca03ae10036c2a2"
[[package]]
name = "wasmprinter"
version = "0.2.16"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dba006f5c5bf41a2a5c3b45e861ea6eb067382acb022b6a35a00a0390f9547f6"
checksum = "f89b2b24dce17e27fe9c09c28331cbd77067fcde5c6ea2508ac84bcbd5d3e018"
dependencies = [
"anyhow",
"wasmparser 0.69.2",
"wasmparser 0.70.0",
]
[[package]]
@@ -2438,7 +2438,7 @@ dependencies = [
"smallvec",
"target-lexicon",
"tempfile",
"wasmparser 0.69.2",
"wasmparser 0.70.0",
"wasmtime-cache",
"wasmtime-environ",
"wasmtime-jit",
@@ -2516,7 +2516,7 @@ dependencies = [
"test-programs",
"tracing-subscriber",
"wasi-common",
"wasmparser 0.69.2",
"wasmparser 0.70.0",
"wasmtime",
"wasmtime-cache",
"wasmtime-debug",
@@ -2552,7 +2552,7 @@ dependencies = [
"object",
"target-lexicon",
"thiserror",
"wasmparser 0.69.2",
"wasmparser 0.70.0",
"wasmtime-environ",
]
@@ -2571,7 +2571,7 @@ dependencies = [
"more-asserts",
"serde",
"thiserror",
"wasmparser 0.69.2",
"wasmparser 0.70.0",
]
[[package]]
@@ -2600,7 +2600,7 @@ dependencies = [
"rayon",
"wasm-smith",
"wasmi",
"wasmparser 0.69.2",
"wasmparser 0.70.0",
"wasmprinter",
"wasmtime",
"wasmtime-wast",
@@ -2628,7 +2628,7 @@ dependencies = [
"serde",
"target-lexicon",
"thiserror",
"wasmparser 0.69.2",
"wasmparser 0.70.0",
"wasmtime-cranelift",
"wasmtime-debug",
"wasmtime-environ",
@@ -2645,7 +2645,7 @@ version = "0.21.0"
dependencies = [
"cranelift-codegen",
"lightbeam",
"wasmparser 0.69.2",
"wasmparser 0.70.0",
"wasmtime-environ",
]
@@ -2752,7 +2752,7 @@ version = "0.21.0"
dependencies = [
"anyhow",
"wasmtime",
"wast 28.0.0",
"wast 29.0.0",
]
[[package]]
@@ -2788,20 +2788,20 @@ dependencies = [
[[package]]
name = "wast"
version = "28.0.0"
version = "29.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c0586061bfacc035034672c8d760802b428ab4c80a92e2a392425c516df9be1"
checksum = "dcf2268937131d63c3d833242bf5e075406f9ed868b4265f3280e15dac29ac18"
dependencies = [
"leb128",
]
[[package]]
name = "wat"
version = "1.0.29"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06d55b5ec4f9d9396fa99abaafa0688597395e57827dffd89731412ae90c9bf"
checksum = "0d11a88d953b298172d218d18f22853f4e6e12873b62755d05617b864d312c68"
dependencies = [
"wast 28.0.0",
"wast 29.0.0",
]
[[package]]

View File

@@ -38,12 +38,12 @@ anyhow = "1.0.19"
target-lexicon = { version = "0.11.0", default-features = false }
pretty_env_logger = "0.4.0"
file-per-thread-logger = "0.1.1"
wat = "1.0.29"
wat = "1.0.30"
libc = "0.2.60"
log = "0.4.8"
rayon = "1.2.1"
humantime = "2.0.0"
wasmparser = "0.69.2"
wasmparser = "0.70.0"
[dev-dependencies]
env_logger = "0.8.1"

View File

@@ -30,7 +30,7 @@ peepmatic-traits = { path = "../peepmatic/crates/traits", optional = true, versi
peepmatic-runtime = { path = "../peepmatic/crates/runtime", optional = true, version = "0.68.0" }
regalloc = { version = "0.0.31" }
souper-ir = { version = "2.1.0", optional = true }
wast = { version = "28.0.0", optional = true }
wast = { version = "29.0.0", optional = true }
# It is a goal of the cranelift-codegen crate to have minimal external dependencies.
# Please don't add any unless they are essential to the task of creating binary
# machine code. Integration tests that need external dependencies can be

View File

@@ -15,7 +15,7 @@ peepmatic-macro = { version = "0.68.0", path = "crates/macro" }
peepmatic-runtime = { version = "0.68.0", path = "crates/runtime", features = ["construct"] }
peepmatic-traits = { version = "0.68.0", path = "crates/traits" }
serde = { version = "1.0.105", features = ["derive"] }
wast = "28.0.0"
wast = "29.0.0"
z3 = { version = "0.7.1", features = ["static-link-z3"] }
[dev-dependencies]

View File

@@ -21,4 +21,4 @@ peepmatic-test-operator = { path = "../test-operator" }
peepmatic-traits = { path = "../traits" }
rand = { version = "0.7.3", features = ["small_rng"] }
serde = "1.0.106"
wast = "28.0.0"
wast = "29.0.0"

View File

@@ -16,7 +16,7 @@ peepmatic-automata = { version = "0.68.0", path = "../automata", features = ["se
peepmatic-traits = { version = "0.68.0", path = "../traits" }
serde = { version = "1.0.105", features = ["derive"] }
thiserror = "1.0.15"
wast = { version = "28.0.0", optional = true }
wast = { version = "29.0.0", optional = true }
[dev-dependencies]
peepmatic-test-operator = { version = "0.68.0", path = "../test-operator" }

View File

@@ -16,4 +16,4 @@ log = "0.4.8"
[dev-dependencies]
peepmatic = { path = "../..", version = "0.68.0" }
peepmatic-test-operator = { version = "0.68.0", path = "../test-operator" }
wast = "28.0.0"
wast = "29.0.0"

View File

@@ -9,4 +9,4 @@ edition = "2018"
[dependencies]
peepmatic-traits = { version = "0.68.0", path = "../traits" }
serde = { version = "1.0.105", features = ["derive"] }
wast = "28.0.0"
wast = "29.0.0"

View File

@@ -12,7 +12,7 @@ keywords = ["webassembly", "wasm"]
edition = "2018"
[dependencies]
wasmparser = { version = "0.69.2", default-features = false }
wasmparser = { version = "0.70", default-features = false }
cranelift-codegen = { path = "../codegen", version = "0.68.0", default-features = false }
cranelift-entity = { path = "../entity", version = "0.68.0" }
cranelift-frontend = { path = "../frontend", version = "0.68.0", default-features = false }

View File

@@ -538,10 +538,10 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
}
/********************************** Exception handing **********************************/
Operator::Try { .. }
| Operator::Catch
| Operator::BrOnExn { .. }
| Operator::Catch { .. }
| Operator::Throw { .. }
| Operator::Rethrow => {
| Operator::Unwind
| Operator::Rethrow { .. } => {
return Err(wasm_unsupported!(
"proposed exception handling operator {:?}",
op

View File

@@ -13,7 +13,7 @@ edition = "2018"
[dependencies]
gimli = "0.23.0"
wasmparser = "0.69.2"
wasmparser = "0.70"
object = { version = "0.22.0", default-features = false, features = ["read", "write"] }
wasmtime-environ = { path = "../environ", version = "0.21.0" }
target-lexicon = { version = "0.11.0", default-features = false }

View File

@@ -16,7 +16,7 @@ anyhow = "1.0"
cranelift-codegen = { path = "../../cranelift/codegen", version = "0.68.0", features = ["enable-serde"] }
cranelift-entity = { path = "../../cranelift/entity", version = "0.68.0", features = ["enable-serde"] }
cranelift-wasm = { path = "../../cranelift/wasm", version = "0.68.0", features = ["enable-serde"] }
wasmparser = "0.69.2"
wasmparser = "0.70"
indexmap = { version = "1.0.2", features = ["serde-1"] }
thiserror = "1.0.4"
serde = { version = "1.0.94", features = ["derive"] }

View File

@@ -12,11 +12,11 @@ arbitrary = { version = "0.4.1", features = ["derive"] }
env_logger = "0.8.1"
log = "0.4.8"
rayon = "1.2.1"
wasmparser = "0.69.2"
wasmprinter = "0.2.16"
wasmparser = "0.70"
wasmprinter = "0.2.17"
wasmtime = { path = "../wasmtime" }
wasmtime-wast = { path = "../wast" }
wasm-smith = "0.1.12"
wasm-smith = "0.2.0"
wasmi = "0.7.0"
[dev-dependencies]

View File

@@ -38,6 +38,7 @@ pub fn fuzz_default_config(strategy: wasmtime::Strategy) -> anyhow::Result<wasmt
.cranelift_nan_canonicalization(true)
.wasm_bulk_memory(true)
.wasm_reference_types(true)
.wasm_module_linking(true)
.strategy(strategy)?;
Ok(config)
}

View File

@@ -91,26 +91,15 @@ pub fn instantiate_with_config(wasm: &[u8], mut config: Config, timeout: Option<
}
log_wasm(wasm);
let module = match Module::new(&engine, wasm) {
Ok(module) => module,
Err(_) => return,
};
let module = Module::new(&engine, wasm).unwrap();
let imports = dummy_imports(&store, module.imports());
let imports = match dummy_imports(&store, module.imports()) {
Ok(imps) => imps,
Err(_) => {
// There are some value types that we can't synthesize a
// dummy value for (e.g. externrefs) and for modules that
// import things of these types we skip instantiation.
return;
}
};
// Don't unwrap this: there can be instantiation-/link-time errors that
// aren't caught during validation or compilation. For example, an imported
// table might not have room for an element segment that we want to
// initialize into it.
let _result = Instance::new(&store, &module, &imports);
match Instance::new(&store, &module, &imports) {
Ok(_) => {}
// Allow traps which can happen normally with `unreachable`
Err(e) if e.downcast_ref::<Trap>().is_some() => {}
Err(e) => panic!("failed to instantiate {}", e),
}
}
/// Compile the Wasm buffer, and implicitly fail if we have an unexpected
@@ -162,31 +151,14 @@ pub fn differential_execution(
let engine = Engine::new(config);
let store = Store::new(&engine);
let module = match Module::new(&engine, &wasm) {
Ok(module) => module,
// The module might rely on some feature that our config didn't
// enable or something like that.
Err(e) => {
eprintln!("Warning: failed to compile `wasm-opt -ttf` module: {}", e);
continue;
}
};
let module = Module::new(&engine, &wasm).unwrap();
// TODO: we should implement tracing versions of these dummy imports
// that record a trace of the order that imported functions were called
// in and with what values. Like the results of exported functions,
// calls to imports should also yield the same values for each
// configuration, and we should assert that.
let imports = match dummy_imports(&store, module.imports()) {
Ok(imps) => imps,
Err(e) => {
// There are some value types that we can't synthesize a
// dummy value for (e.g. externrefs) and for modules that
// import things of these types we skip instantiation.
eprintln!("Warning: failed to synthesize dummy imports: {}", e);
continue;
}
};
let imports = dummy_imports(&store, module.imports());
// Don't unwrap this: there can be instantiation-/link-time errors that
// aren't caught during validation or compilation. For example, an imported
@@ -212,10 +184,7 @@ pub fn differential_execution(
init_hang_limit(&instance);
let ty = f.ty();
let params = match dummy::dummy_values(ty.params()) {
Ok(p) => p,
Err(_) => continue,
};
let params = dummy::dummy_values(ty.params());
let this_result = f.call(&params).map_err(|e| e.downcast::<Trap>().unwrap());
let existing_result = export_func_results
@@ -353,16 +322,7 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) {
};
let store = store.as_ref().unwrap();
let imports = match dummy_imports(store, module.imports()) {
Ok(imps) => imps,
Err(_) => {
// There are some value types that we can't synthesize a
// dummy value for (e.g. externrefs) and for modules that
// import things of these types we skip instantiation.
continue;
}
};
let imports = dummy_imports(store, module.imports());
// Don't unwrap this: there can be instantiation-/link-time errors that
// aren't caught during validation or compilation. For example, an imported
@@ -408,10 +368,7 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) {
let nth = nth % funcs.len();
let f = &funcs[nth];
let ty = f.ty();
let params = match dummy::dummy_values(ty.params()) {
Ok(p) => p,
Err(_) => continue,
};
let params = dummy::dummy_values(ty.params());
let _ = f.call(&params);
}
}
@@ -509,7 +466,7 @@ impl wasm_smith::Config for DifferentialWasmiModuleConfig {
1
}
fn max_memories(&self) -> u32 {
fn max_memories(&self) -> usize {
1
}

View File

@@ -1,27 +1,23 @@
//! Dummy implementations of things that a Wasm module can import.
use wasmtime::{
Extern, ExternType, Func, FuncType, Global, GlobalType, ImportType, Memory, MemoryType, Store,
Table, TableType, Trap, Val, ValType,
};
use std::fmt::Write;
use wasmtime::*;
/// Create a set of dummy functions/globals/etc for the given imports.
pub fn dummy_imports<'module>(
store: &Store,
import_tys: impl Iterator<Item = ImportType<'module>>,
) -> Result<Vec<Extern>, Trap> {
) -> Vec<Extern> {
import_tys
.map(|imp| {
Ok(match imp.ty() {
ExternType::Func(func_ty) => Extern::Func(dummy_func(&store, func_ty)),
ExternType::Global(global_ty) => Extern::Global(dummy_global(&store, global_ty)?),
ExternType::Table(table_ty) => Extern::Table(dummy_table(&store, table_ty)?),
ExternType::Memory(mem_ty) => Extern::Memory(dummy_memory(&store, mem_ty)),
// FIXME(#2094)
ExternType::Instance(_) => unimplemented!(),
ExternType::Module(_) => unimplemented!(),
})
.map(|imp| match imp.ty() {
ExternType::Func(func_ty) => Extern::Func(dummy_func(&store, func_ty)),
ExternType::Global(global_ty) => Extern::Global(dummy_global(&store, global_ty)),
ExternType::Table(table_ty) => Extern::Table(dummy_table(&store, table_ty)),
ExternType::Memory(mem_ty) => Extern::Memory(dummy_memory(&store, mem_ty)),
ExternType::Instance(instance_ty) => {
Extern::Instance(dummy_instance(&store, instance_ty))
}
ExternType::Module(module_ty) => Extern::Module(dummy_module(&store, module_ty)),
})
.collect()
}
@@ -30,55 +26,326 @@ pub fn dummy_imports<'module>(
pub fn dummy_func(store: &Store, ty: FuncType) -> Func {
Func::new(store, ty.clone(), move |_, _, results| {
for (ret_ty, result) in ty.results().zip(results) {
*result = dummy_value(ret_ty)?;
*result = dummy_value(ret_ty);
}
Ok(())
})
}
/// Construct a dummy value for the given value type.
pub fn dummy_value(val_ty: ValType) -> Result<Val, Trap> {
Ok(match val_ty {
pub fn dummy_value(val_ty: ValType) -> Val {
match val_ty {
ValType::I32 => Val::I32(0),
ValType::I64 => Val::I64(0),
ValType::F32 => Val::F32(0),
ValType::F64 => Val::F64(0),
ValType::V128 => {
return Err(Trap::new(
"dummy_value: unsupported function return type: v128".to_string(),
))
}
ValType::ExternRef => {
return Err(Trap::new(
"dummy_value: unsupported function return type: externref".to_string(),
))
}
ValType::FuncRef => {
return Err(Trap::new(
"dummy_value: unsupported function return type: funcref".to_string(),
))
}
})
ValType::V128 => Val::V128(0),
ValType::ExternRef => Val::ExternRef(None),
ValType::FuncRef => Val::FuncRef(None),
}
}
/// Construct a sequence of dummy values for the given types.
pub fn dummy_values(val_tys: impl IntoIterator<Item = ValType>) -> Result<Vec<Val>, Trap> {
pub fn dummy_values(val_tys: impl IntoIterator<Item = ValType>) -> Vec<Val> {
val_tys.into_iter().map(dummy_value).collect()
}
/// Construct a dummy global for the given global type.
pub fn dummy_global(store: &Store, ty: GlobalType) -> Result<Global, Trap> {
let val = dummy_value(ty.content().clone())?;
Ok(Global::new(store, ty, val).unwrap())
pub fn dummy_global(store: &Store, ty: GlobalType) -> Global {
let val = dummy_value(ty.content().clone());
Global::new(store, ty, val).unwrap()
}
/// Construct a dummy table for the given table type.
pub fn dummy_table(store: &Store, ty: TableType) -> Result<Table, Trap> {
let init_val = dummy_value(ty.element().clone())?;
Ok(Table::new(store, ty, init_val).unwrap())
pub fn dummy_table(store: &Store, ty: TableType) -> Table {
let init_val = dummy_value(ty.element().clone());
Table::new(store, ty, init_val).unwrap()
}
/// Construct a dummy memory for the given memory type.
pub fn dummy_memory(store: &Store, ty: MemoryType) -> Memory {
Memory::new(store, ty)
}
/// Construct a dummy instance for the given instance type.
///
/// This is done by using the expected type to generate a module on-the-fly
/// which we the instantiate.
pub fn dummy_instance(store: &Store, ty: InstanceType) -> Instance {
let mut wat = WatGenerator::new();
for ty in ty.exports() {
wat.export(&ty);
}
let module = Module::new(store.engine(), &wat.finish()).unwrap();
Instance::new(store, &module, &[]).unwrap()
}
/// Construct a dummy module for the given module type.
///
/// This is done by using the expected type to generate a module on-the-fly.
pub fn dummy_module(store: &Store, ty: ModuleType) -> Module {
let mut wat = WatGenerator::new();
for ty in ty.imports() {
wat.import(&ty);
}
for ty in ty.exports() {
wat.export(&ty);
}
Module::new(store.engine(), &wat.finish()).unwrap()
}
struct WatGenerator {
tmp: usize,
dst: String,
}
impl WatGenerator {
fn new() -> WatGenerator {
WatGenerator {
tmp: 0,
dst: String::from("(module\n"),
}
}
fn finish(mut self) -> String {
self.dst.push_str(")\n");
self.dst
}
fn import(&mut self, ty: &ImportType<'_>) {
write!(self.dst, "(import ").unwrap();
self.str(ty.module());
write!(self.dst, " ").unwrap();
if let Some(field) = ty.name() {
self.str(field);
write!(self.dst, " ").unwrap();
}
self.item_ty(&ty.ty());
writeln!(self.dst, ")").unwrap();
}
fn item_ty(&mut self, ty: &ExternType) {
match ty {
ExternType::Memory(mem) => {
write!(
self.dst,
"(memory {} {})",
mem.limits().min(),
match mem.limits().max() {
Some(max) => max.to_string(),
None => String::new(),
}
)
.unwrap();
}
ExternType::Table(table) => {
write!(
self.dst,
"(table {} {} {})",
table.limits().min(),
match table.limits().max() {
Some(max) => max.to_string(),
None => String::new(),
},
wat_ty(table.element()),
)
.unwrap();
}
ExternType::Global(ty) => {
if ty.mutability() == Mutability::Const {
write!(self.dst, "(global {})", wat_ty(ty.content())).unwrap();
} else {
write!(self.dst, "(global (mut {}))", wat_ty(ty.content())).unwrap();
}
}
ExternType::Func(ty) => {
write!(self.dst, "(func ").unwrap();
self.func_sig(ty);
write!(self.dst, ")").unwrap();
}
ExternType::Instance(ty) => {
writeln!(self.dst, "(instance").unwrap();
for ty in ty.exports() {
write!(self.dst, "(export ").unwrap();
self.str(ty.name());
write!(self.dst, " ").unwrap();
self.item_ty(&ty.ty());
writeln!(self.dst, ")").unwrap();
}
write!(self.dst, ")").unwrap();
}
ExternType::Module(ty) => {
writeln!(self.dst, "(module").unwrap();
for ty in ty.imports() {
self.import(&ty);
writeln!(self.dst, "").unwrap();
}
for ty in ty.exports() {
write!(self.dst, "(export ").unwrap();
self.str(ty.name());
write!(self.dst, " ").unwrap();
self.item_ty(&ty.ty());
writeln!(self.dst, ")").unwrap();
}
write!(self.dst, ")").unwrap();
}
}
}
fn export(&mut self, ty: &ExportType<'_>) {
let wat_name = format!("item{}", self.tmp);
self.tmp += 1;
let item_ty = ty.ty();
self.item(&wat_name, &item_ty);
write!(self.dst, "(export ").unwrap();
self.str(ty.name());
write!(self.dst, " (").unwrap();
match item_ty {
ExternType::Memory(_) => write!(self.dst, "memory").unwrap(),
ExternType::Global(_) => write!(self.dst, "global").unwrap(),
ExternType::Func(_) => write!(self.dst, "func").unwrap(),
ExternType::Instance(_) => write!(self.dst, "instance").unwrap(),
ExternType::Table(_) => write!(self.dst, "table").unwrap(),
ExternType::Module(_) => write!(self.dst, "module").unwrap(),
}
writeln!(self.dst, " ${}))", wat_name).unwrap();
}
fn item(&mut self, name: &str, ty: &ExternType) {
match ty {
ExternType::Memory(mem) => {
write!(
self.dst,
"(memory ${} {} {})\n",
name,
mem.limits().min(),
match mem.limits().max() {
Some(max) => max.to_string(),
None => String::new(),
}
)
.unwrap();
}
ExternType::Table(table) => {
write!(
self.dst,
"(table ${} {} {} {})\n",
name,
table.limits().min(),
match table.limits().max() {
Some(max) => max.to_string(),
None => String::new(),
},
wat_ty(table.element()),
)
.unwrap();
}
ExternType::Global(ty) => {
write!(self.dst, "(global ${} ", name).unwrap();
if ty.mutability() == Mutability::Var {
write!(self.dst, "(mut ").unwrap();
}
write!(self.dst, "{}", wat_ty(ty.content())).unwrap();
if ty.mutability() == Mutability::Var {
write!(self.dst, ")").unwrap();
}
write!(self.dst, " (").unwrap();
self.value(ty.content());
writeln!(self.dst, "))").unwrap();
}
ExternType::Func(ty) => {
write!(self.dst, "(func ${} ", name).unwrap();
self.func_sig(ty);
for ty in ty.results() {
writeln!(self.dst, "").unwrap();
self.value(&ty);
}
writeln!(self.dst, ")").unwrap();
}
ExternType::Module(ty) => {
writeln!(self.dst, "(module ${}", name).unwrap();
for ty in ty.imports() {
self.import(&ty);
}
for ty in ty.exports() {
self.export(&ty);
}
self.dst.push_str(")\n");
}
ExternType::Instance(ty) => {
writeln!(self.dst, "(module ${}_module", name).unwrap();
for ty in ty.exports() {
self.export(&ty);
}
self.dst.push_str(")\n");
writeln!(self.dst, "(instance ${} (instantiate ${0}_module))", name).unwrap();
}
}
}
fn func_sig(&mut self, ty: &FuncType) {
write!(self.dst, "(param ").unwrap();
for ty in ty.params() {
write!(self.dst, "{} ", wat_ty(&ty)).unwrap();
}
write!(self.dst, ") (result ").unwrap();
for ty in ty.results() {
write!(self.dst, "{} ", wat_ty(&ty)).unwrap();
}
write!(self.dst, ")").unwrap();
}
fn value(&mut self, ty: &ValType) {
match ty {
ValType::I32 => write!(self.dst, "i32.const 0").unwrap(),
ValType::I64 => write!(self.dst, "i64.const 0").unwrap(),
ValType::F32 => write!(self.dst, "f32.const 0").unwrap(),
ValType::F64 => write!(self.dst, "f64.const 0").unwrap(),
ValType::V128 => write!(self.dst, "v128.const i32x4 0 0 0 0").unwrap(),
ValType::ExternRef => write!(self.dst, "ref.null extern").unwrap(),
ValType::FuncRef => write!(self.dst, "ref.null func").unwrap(),
}
}
fn str(&mut self, name: &str) {
let mut bytes = [0; 4];
self.dst.push_str("\"");
for c in name.chars() {
let v = c as u32;
if v >= 0x20 && v < 0x7f && c != '"' && c != '\\' && v < 0xff {
self.dst.push(c);
} else {
for byte in c.encode_utf8(&mut bytes).as_bytes() {
self.hex_byte(*byte);
}
}
}
self.dst.push_str("\"");
}
fn hex_byte(&mut self, byte: u8) {
fn to_hex(b: u8) -> char {
if b < 10 {
(b'0' + b) as char
} else {
(b'a' + b - 10) as char
}
}
self.dst.push('\\');
self.dst.push(to_hex((byte >> 4) & 0xf));
self.dst.push(to_hex(byte & 0xf));
}
}
fn wat_ty(ty: &ValType) -> &'static str {
match ty {
ValType::I32 => "i32",
ValType::I64 => "i64",
ValType::F32 => "f32",
ValType::F64 => "f64",
ValType::V128 => "v128",
ValType::ExternRef => "externref",
ValType::FuncRef => "funcref",
}
}

View File

@@ -28,7 +28,7 @@ rayon = { version = "1.0", optional = true }
region = "2.1.0"
thiserror = "1.0.4"
target-lexicon = { version = "0.11.0", default-features = false }
wasmparser = "0.69.2"
wasmparser = "0.70"
more-asserts = "0.2.1"
anyhow = "1.0"
cfg-if = "1.0"

View File

@@ -24,7 +24,7 @@ more-asserts = "0.2.1"
smallvec = "1.0.0"
thiserror = "1.0.9"
typemap = "0.3"
wasmparser = "0.69.2"
wasmparser = "0.70"
[dev-dependencies]
lazy_static = "1.2"

View File

@@ -13,6 +13,6 @@ edition = "2018"
[dependencies]
lightbeam = { path = "..", version = "0.21.0" }
wasmparser = "0.69.2"
wasmparser = "0.70"
cranelift-codegen = { path = "../../../cranelift/codegen", version = "0.68.0" }
wasmtime-environ = { path = "../../environ", version = "0.21.0" }

View File

@@ -16,7 +16,7 @@ wasmtime-jit = { path = "../jit", version = "0.21.0" }
wasmtime-cache = { path = "../cache", version = "0.21.0", optional = true }
wasmtime-profiling = { path = "../profiling", version = "0.21.0" }
target-lexicon = { version = "0.11.0", default-features = false }
wasmparser = "0.69.2"
wasmparser = "0.70"
anyhow = "1.0.19"
region = "2.2.0"
libc = "0.2"

View File

@@ -13,7 +13,7 @@ edition = "2018"
[dependencies]
anyhow = "1.0.19"
wasmtime = { path = "../wasmtime", version = "0.21.0", default-features = false }
wast = "28.0.0"
wast = "29.0.0"
[badges]
maintenance = { status = "actively-developed" }

View File

@@ -17,7 +17,7 @@ target-lexicon = "0.11"
peepmatic-fuzzing = { path = "../cranelift/peepmatic/crates/fuzzing", optional = true }
wasmtime = { path = "../crates/wasmtime" }
wasmtime-fuzzing = { path = "../crates/fuzzing" }
wasm-smith = "0.1.12"
wasm-smith = "0.2.0"
[features]
experimental_x64 = ["wasmtime-fuzzing/experimental_x64"]