* Migrate back to `std::` stylistically This commit moves away from idioms such as `alloc::` and `core::` as imports of standard data structures and types. Instead it migrates all crates to uniformly use `std::` for importing standard data structures and types. This also removes the `std` and `core` features from all crates to and removes any conditional checking for `feature = "std"` All of this support was previously added in #407 in an effort to make wasmtime/cranelift "`no_std` compatible". Unfortunately though this change comes at a cost: * The usage of `alloc` and `core` isn't idiomatic. Especially trying to dual between types like `HashMap` from `std` as well as from `hashbrown` causes imports to be surprising in some cases. * Unfortunately there was no CI check that crates were `no_std`, so none of them actually were. Many crates still imported from `std` or depended on crates that used `std`. It's important to note, however, that **this does not mean that wasmtime will not run in embedded environments**. The style of the code today and idioms aren't ready in Rust to support this degree of multiplexing and makes it somewhat difficult to keep up with the style of `wasmtime`. Instead it's intended that embedded runtime support will be added as necessary. Currently only `std` is necessary to build `wasmtime`, and platforms that natively need to execute `wasmtime` will need to use a Rust target that supports `std`. Note though that not all of `std` needs to be supported, but instead much of it could be configured off to return errors, and `wasmtime` would be configured to gracefully handle errors. The goal of this PR is to move `wasmtime` back to idiomatic usage of features/`std`/imports/etc and help development in the short-term. Long-term when platform concerns arise (if any) they can be addressed by moving back to `no_std` crates (but fixing the issues mentioned above) or ensuring that the target in Rust has `std` available. * Start filling out platform support doc
232 lines
6.9 KiB
Rust
232 lines
6.9 KiB
Rust
#![allow(improper_ctypes)]
|
|
|
|
use cranelift_codegen::ir::types;
|
|
use cranelift_codegen::{ir, isa};
|
|
use cranelift_entity::PrimaryMap;
|
|
use cranelift_wasm::{DefinedFuncIndex, Global, GlobalInit, Memory, Table, TableElementType};
|
|
use std::cell::RefCell;
|
|
use std::collections::hash_map::HashMap;
|
|
use std::rc::Rc;
|
|
use target_lexicon::HOST;
|
|
use wasmtime_environ::{translate_signature, Export, MemoryPlan, Module, TablePlan};
|
|
use wasmtime_jit::target_tunables;
|
|
use wasmtime_runtime::{Imports, InstanceHandle, InstantiationError, VMContext, VMFunctionBody};
|
|
|
|
extern "C" fn spectest_print() {}
|
|
|
|
#[allow(clippy::print_stdout)]
|
|
extern "C" fn spectest_print_i32(_vmctx: &mut VMContext, x: i32) {
|
|
println!("{}: i32", x);
|
|
}
|
|
|
|
#[allow(clippy::print_stdout)]
|
|
extern "C" fn spectest_print_i64(_vmctx: &mut VMContext, x: i64) {
|
|
println!("{}: i64", x);
|
|
}
|
|
|
|
#[allow(clippy::print_stdout)]
|
|
extern "C" fn spectest_print_f32(_vmctx: &mut VMContext, x: f32) {
|
|
println!("{}: f32", x);
|
|
}
|
|
|
|
#[allow(clippy::print_stdout)]
|
|
extern "C" fn spectest_print_f64(_vmctx: &mut VMContext, x: f64) {
|
|
println!("{}: f64", x);
|
|
}
|
|
|
|
#[allow(clippy::print_stdout)]
|
|
extern "C" fn spectest_print_i32_f32(_vmctx: &mut VMContext, x: i32, y: f32) {
|
|
println!("{}: i32", x);
|
|
println!("{}: f32", y);
|
|
}
|
|
|
|
#[allow(clippy::print_stdout)]
|
|
extern "C" fn spectest_print_f64_f64(_vmctx: &mut VMContext, x: f64, y: f64) {
|
|
println!("{}: f64", x);
|
|
println!("{}: f64", y);
|
|
}
|
|
|
|
/// Return an instance implementing the "spectest" interface used in the
|
|
/// spec testsuite.
|
|
pub fn instantiate_spectest() -> Result<InstanceHandle, InstantiationError> {
|
|
let call_conv = isa::CallConv::triple_default(&HOST);
|
|
let pointer_type = types::Type::triple_pointer_type(&HOST);
|
|
let mut module = Module::new();
|
|
let mut finished_functions: PrimaryMap<DefinedFuncIndex, *const VMFunctionBody> =
|
|
PrimaryMap::new();
|
|
|
|
let sig = module.signatures.push(translate_signature(
|
|
ir::Signature {
|
|
params: vec![],
|
|
returns: vec![],
|
|
call_conv,
|
|
},
|
|
pointer_type,
|
|
));
|
|
let func = module.functions.push(sig);
|
|
module
|
|
.exports
|
|
.insert("print".to_owned(), Export::Function(func));
|
|
finished_functions.push(spectest_print as *const VMFunctionBody);
|
|
|
|
let sig = module.signatures.push(translate_signature(
|
|
ir::Signature {
|
|
params: vec![ir::AbiParam::new(types::I32)],
|
|
returns: vec![],
|
|
call_conv,
|
|
},
|
|
pointer_type,
|
|
));
|
|
let func = module.functions.push(sig);
|
|
module
|
|
.exports
|
|
.insert("print_i32".to_owned(), Export::Function(func));
|
|
finished_functions.push(spectest_print_i32 as *const VMFunctionBody);
|
|
|
|
let sig = module.signatures.push(translate_signature(
|
|
ir::Signature {
|
|
params: vec![ir::AbiParam::new(types::I64)],
|
|
returns: vec![],
|
|
call_conv,
|
|
},
|
|
pointer_type,
|
|
));
|
|
let func = module.functions.push(sig);
|
|
module
|
|
.exports
|
|
.insert("print_i64".to_owned(), Export::Function(func));
|
|
finished_functions.push(spectest_print_i64 as *const VMFunctionBody);
|
|
|
|
let sig = module.signatures.push(translate_signature(
|
|
ir::Signature {
|
|
params: vec![ir::AbiParam::new(types::F32)],
|
|
returns: vec![],
|
|
call_conv,
|
|
},
|
|
pointer_type,
|
|
));
|
|
let func = module.functions.push(sig);
|
|
module
|
|
.exports
|
|
.insert("print_f32".to_owned(), Export::Function(func));
|
|
finished_functions.push(spectest_print_f32 as *const VMFunctionBody);
|
|
|
|
let sig = module.signatures.push(translate_signature(
|
|
ir::Signature {
|
|
params: vec![ir::AbiParam::new(types::F64)],
|
|
returns: vec![],
|
|
call_conv,
|
|
},
|
|
pointer_type,
|
|
));
|
|
let func = module.functions.push(sig);
|
|
module
|
|
.exports
|
|
.insert("print_f64".to_owned(), Export::Function(func));
|
|
finished_functions.push(spectest_print_f64 as *const VMFunctionBody);
|
|
|
|
let sig = module.signatures.push(translate_signature(
|
|
ir::Signature {
|
|
params: vec![ir::AbiParam::new(types::I32), ir::AbiParam::new(types::F32)],
|
|
returns: vec![],
|
|
call_conv,
|
|
},
|
|
pointer_type,
|
|
));
|
|
let func = module.functions.push(sig);
|
|
module
|
|
.exports
|
|
.insert("print_i32_f32".to_owned(), Export::Function(func));
|
|
finished_functions.push(spectest_print_i32_f32 as *const VMFunctionBody);
|
|
|
|
let sig = module.signatures.push(translate_signature(
|
|
ir::Signature {
|
|
params: vec![ir::AbiParam::new(types::F64), ir::AbiParam::new(types::F64)],
|
|
returns: vec![],
|
|
call_conv,
|
|
},
|
|
pointer_type,
|
|
));
|
|
let func = module.functions.push(sig);
|
|
module
|
|
.exports
|
|
.insert("print_f64_f64".to_owned(), Export::Function(func));
|
|
finished_functions.push(spectest_print_f64_f64 as *const VMFunctionBody);
|
|
|
|
let global = module.globals.push(Global {
|
|
ty: types::I32,
|
|
mutability: false,
|
|
initializer: GlobalInit::I32Const(666),
|
|
});
|
|
module
|
|
.exports
|
|
.insert("global_i32".to_owned(), Export::Global(global));
|
|
|
|
let global = module.globals.push(Global {
|
|
ty: types::I64,
|
|
mutability: false,
|
|
initializer: GlobalInit::I64Const(666),
|
|
});
|
|
module
|
|
.exports
|
|
.insert("global_i64".to_owned(), Export::Global(global));
|
|
|
|
let global = module.globals.push(Global {
|
|
ty: types::F32,
|
|
mutability: false,
|
|
initializer: GlobalInit::F32Const(0x44268000),
|
|
});
|
|
module
|
|
.exports
|
|
.insert("global_f32".to_owned(), Export::Global(global));
|
|
|
|
let global = module.globals.push(Global {
|
|
ty: types::F64,
|
|
mutability: false,
|
|
initializer: GlobalInit::F64Const(0x4084d00000000000),
|
|
});
|
|
module
|
|
.exports
|
|
.insert("global_f64".to_owned(), Export::Global(global));
|
|
|
|
let tunables = target_tunables(&HOST);
|
|
let table = module.table_plans.push(TablePlan::for_table(
|
|
Table {
|
|
ty: TableElementType::Func,
|
|
minimum: 10,
|
|
maximum: Some(20),
|
|
},
|
|
&tunables,
|
|
));
|
|
module
|
|
.exports
|
|
.insert("table".to_owned(), Export::Table(table));
|
|
|
|
let memory = module.memory_plans.push(MemoryPlan::for_memory(
|
|
Memory {
|
|
minimum: 1,
|
|
maximum: Some(2),
|
|
shared: false,
|
|
},
|
|
&tunables,
|
|
));
|
|
module
|
|
.exports
|
|
.insert("memory".to_owned(), Export::Memory(memory));
|
|
|
|
let imports = Imports::none();
|
|
let data_initializers = Vec::new();
|
|
let signatures = PrimaryMap::new();
|
|
|
|
InstanceHandle::new(
|
|
Rc::new(module),
|
|
Rc::new(RefCell::new(HashMap::new())),
|
|
finished_functions.into_boxed_slice(),
|
|
imports,
|
|
&data_initializers,
|
|
signatures.into_boxed_slice(),
|
|
None,
|
|
Box::new(()),
|
|
)
|
|
}
|