Merge pull request #2497 from alexcrichton/fuzz-module-linking
Enable fuzzing the module linking implementation
This commit is contained in:
60
Cargo.lock
generated
60
Cargo.lock
generated
@@ -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]]
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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"] }
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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(¶ms).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(¶ms);
|
||||
}
|
||||
}
|
||||
@@ -509,7 +466,7 @@ impl wasm_smith::Config for DifferentialWasmiModuleConfig {
|
||||
1
|
||||
}
|
||||
|
||||
fn max_memories(&self) -> u32 {
|
||||
fn max_memories(&self) -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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"]
|
||||
|
||||
Reference in New Issue
Block a user