Support for multi-value wasm (#399)
* deps: bump wasmparser to 0.39.2 This has a bug fix for multi-value Wasm validation that is required for getting the spec tests passing. https://github.com/yurydelendik/wasmparser.rs/pull/135 * Update cranelift to 0.46.1 to get multi-value Wasm support The `cranelift_wasm` APIs had to change a little bit to maintain state necessary when translating multi-value Wasm blocks. The `translate_module` function now returns a `ModuleTranslationState` that is borrowed during each function's translation. * Enable multi-value proposal's spec tests This enables all the Wasm multi-value proposal's spec tests other than the ones that rely on functions having more return values than registers available on the target. That is not supported by cranelift yet. * wasmtime-interface-types: always use multi-value Wasm And remove the return pointer hacks that work around the lack of multi-value.
This commit is contained in:
committed by
Dan Gohman
parent
9d54f84a32
commit
842faf5aa6
@@ -11,10 +11,10 @@ edition = "2018"
|
||||
default-run = "wasmtime"
|
||||
|
||||
[dependencies]
|
||||
cranelift-codegen = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-native = "0.44.0"
|
||||
cranelift-codegen = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-native = "0.46.1"
|
||||
wasmtime-api = { path = "wasmtime-api" }
|
||||
wasmtime-debug = { path = "wasmtime-debug" }
|
||||
wasmtime-environ = { path = "wasmtime-environ" }
|
||||
|
||||
28
build.rs
28
build.rs
@@ -37,6 +37,12 @@ fn main() {
|
||||
strategy,
|
||||
)
|
||||
.expect("generating tests");
|
||||
|
||||
let multi_value_suite = Path::new("spec_testsuite")
|
||||
.join("proposals")
|
||||
.join("multi-value");
|
||||
let multi_value_suite = multi_value_suite.display().to_string();
|
||||
test_directory(&mut out, &multi_value_suite, strategy).expect("generating tests");
|
||||
} else {
|
||||
println!("cargo:warning=The spec testsuite is disabled. To enable, run `git submodule update --remote`.");
|
||||
}
|
||||
@@ -94,7 +100,8 @@ fn start_test_module(out: &mut File, testsuite: &str) -> io::Result<()> {
|
||||
.expect("testsuite filename should have a stem")
|
||||
.to_str()
|
||||
.expect("testsuite filename should be representable as a string")
|
||||
.replace("-", "_"),
|
||||
.replace("-", "_")
|
||||
.replace("/", "_")
|
||||
)?;
|
||||
writeln!(
|
||||
out,
|
||||
@@ -131,7 +138,8 @@ fn write_testsuite_tests(
|
||||
)?;
|
||||
writeln!(
|
||||
out,
|
||||
" let features = Features {{ simd: true, ..Default::default() }};"
|
||||
" let features = Features {{ simd: true, multi_value: {}, ..Default::default() }};",
|
||||
testsuite.contains("multi-value")
|
||||
)?;
|
||||
writeln!(
|
||||
out,
|
||||
@@ -159,18 +167,32 @@ fn write_testsuite_tests(
|
||||
|
||||
/// Ignore tests that aren't supported yet.
|
||||
fn ignore(testsuite: &str, name: &str, strategy: &str) -> bool {
|
||||
let is_multi_value = testsuite.ends_with("multi-value");
|
||||
match strategy {
|
||||
#[cfg(feature = "lightbeam")]
|
||||
"Lightbeam" => match (testsuite, name) {
|
||||
("single_file_spec_test", "simd_const") => return true,
|
||||
(_, _) if is_multi_value => return true,
|
||||
_ => (),
|
||||
},
|
||||
"Cranelift" => {}
|
||||
"Cranelift" => match (testsuite, name) {
|
||||
// We don't currently support more return values than available
|
||||
// registers, and this contains a function with many, many more
|
||||
// return values than that.
|
||||
(_, "func") if is_multi_value => return true,
|
||||
_ => {}
|
||||
},
|
||||
_ => panic!("unrecognized strategy"),
|
||||
}
|
||||
|
||||
if cfg!(windows) {
|
||||
return match (testsuite, name) {
|
||||
// Currently, our multi-value support only works with however many
|
||||
// extra return registers we have available, and windows' fastcall
|
||||
// ABI only has a single return register, so we need to wait on full
|
||||
// multi-value support in Cranelift.
|
||||
(_, _) if is_multi_value => true,
|
||||
|
||||
("spec_testsuite", "address") => true,
|
||||
("spec_testsuite", "align") => true,
|
||||
("spec_testsuite", "call") => true,
|
||||
|
||||
@@ -11,11 +11,11 @@ cargo-fuzz = true
|
||||
[dependencies]
|
||||
wasmtime-environ = { path = "../wasmtime-environ" }
|
||||
wasmtime-jit = { path = "../wasmtime-jit" }
|
||||
cranelift-codegen = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-native = "0.44.0"
|
||||
cranelift-codegen = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-native = "0.46.1"
|
||||
libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer-sys.git" }
|
||||
wasmparser = { version = "0.39.1", default-features = false }
|
||||
wasmparser = { version = "0.39.2", default-features = false }
|
||||
binaryen = "0.5.0"
|
||||
|
||||
[features]
|
||||
|
||||
@@ -19,7 +19,7 @@ itertools = "0.8"
|
||||
capstone = "0.6.0"
|
||||
failure = "0.1.3"
|
||||
failure_derive = "0.1.3"
|
||||
cranelift-codegen = "0.44"
|
||||
cranelift-codegen = "0.46.1"
|
||||
multi_mut = "0.1"
|
||||
either = "1.5"
|
||||
typemap = "0.3"
|
||||
|
||||
@@ -12,11 +12,11 @@ name = "_wasmtime"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
cranelift-codegen = "0.44.0"
|
||||
cranelift-native = "0.44.0"
|
||||
cranelift-entity = "0.44.0"
|
||||
cranelift-wasm = "0.44.0"
|
||||
cranelift-frontend = "0.44.0"
|
||||
cranelift-codegen = "0.46.1"
|
||||
cranelift-native = "0.46.1"
|
||||
cranelift-entity = "0.46.1"
|
||||
cranelift-wasm = "0.46.1"
|
||||
cranelift-frontend = "0.46.1"
|
||||
wasmtime-environ = { path = "../../wasmtime-environ" }
|
||||
wasmtime-interface-types = { path = "../../wasmtime-interface-types" }
|
||||
wasmtime-jit = { path = "../../wasmtime-jit" }
|
||||
@@ -24,7 +24,7 @@ wasmtime-runtime = { path = "../../wasmtime-runtime" }
|
||||
target-lexicon = { version = "0.8.1", default-features = false }
|
||||
failure = "0.1"
|
||||
region = "2.0.0"
|
||||
wasmparser = "0.39.1"
|
||||
wasmparser = "0.39.2"
|
||||
|
||||
[dependencies.pyo3]
|
||||
version = "0.8.0"
|
||||
|
||||
@@ -12,8 +12,8 @@ test = false
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
cranelift-codegen = "0.44.0"
|
||||
cranelift-native = "0.44.0"
|
||||
cranelift-codegen = "0.46.1"
|
||||
cranelift-native = "0.46.1"
|
||||
failure = "0.1.5"
|
||||
wasmtime-interface-types = { path = "../../wasmtime-interface-types" }
|
||||
wasmtime-jit = { path = "../../wasmtime-jit" }
|
||||
|
||||
@@ -59,7 +59,10 @@ fn generate_load(item: &syn::ItemTrait) -> syn::Result<TokenStream> {
|
||||
let mut cx = #root::wasmtime_jit::Context::with_isa(
|
||||
isa,
|
||||
#root::wasmtime_jit::CompilationStrategy::Auto
|
||||
);
|
||||
).with_features(#root::wasmtime_jit::Features {
|
||||
multi_value: true,
|
||||
..Default::default()
|
||||
});
|
||||
let data = #root::wasmtime_interface_types::ModuleData::new(&bytes)?;
|
||||
let handle = cx.instantiate_module(None, &bytes)?;
|
||||
|
||||
|
||||
@@ -238,7 +238,13 @@ fn handle_module(
|
||||
// Decide how to compile.
|
||||
let strategy = pick_compilation_strategy(cranelift, lightbeam);
|
||||
|
||||
let (module, lazy_function_body_inputs, lazy_data_initializers, target_config) = {
|
||||
let (
|
||||
module,
|
||||
module_translation,
|
||||
lazy_function_body_inputs,
|
||||
lazy_data_initializers,
|
||||
target_config,
|
||||
) = {
|
||||
let environ = ModuleEnvironment::new(isa.frontend_config(), tunables);
|
||||
|
||||
let translation = environ
|
||||
@@ -247,6 +253,7 @@ fn handle_module(
|
||||
|
||||
(
|
||||
translation.module,
|
||||
translation.module_translation.unwrap(),
|
||||
translation.function_body_inputs,
|
||||
translation.data_initializers,
|
||||
translation.target_config,
|
||||
@@ -259,6 +266,7 @@ fn handle_module(
|
||||
CompilationStrategy::Auto | CompilationStrategy::Cranelift => {
|
||||
Cranelift::compile_module(
|
||||
&module,
|
||||
&module_translation,
|
||||
lazy_function_body_inputs,
|
||||
&*isa,
|
||||
generate_debug_info,
|
||||
@@ -268,6 +276,7 @@ fn handle_module(
|
||||
#[cfg(feature = "lightbeam")]
|
||||
CompilationStrategy::Lightbeam => Lightbeam::compile_module(
|
||||
&module,
|
||||
&module_translation,
|
||||
lazy_function_body_inputs,
|
||||
&*isa,
|
||||
generate_debug_info,
|
||||
|
||||
@@ -12,15 +12,15 @@ name = "wasmtime_api"
|
||||
crate-type = ["lib", "staticlib", "cdylib"]
|
||||
|
||||
[dependencies]
|
||||
cranelift-codegen = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-native = "0.44.0"
|
||||
cranelift-entity = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-frontend = "0.44.0"
|
||||
cranelift-codegen = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-native = "0.46.1"
|
||||
cranelift-entity = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-frontend = "0.46.1"
|
||||
wasmtime-runtime = { path="../wasmtime-runtime" }
|
||||
wasmtime-environ = { path="../wasmtime-environ" }
|
||||
wasmtime-jit = { path="../wasmtime-jit" }
|
||||
wasmparser = { version = "0.39.1", default-features = false }
|
||||
wasmparser = { version = "0.39.2", default-features = false }
|
||||
failure = { version = "0.1.3", default-features = false }
|
||||
failure_derive = { version = "0.1.3", default-features = false }
|
||||
target-lexicon = { version = "0.8.1", default-features = false }
|
||||
|
||||
@@ -13,10 +13,10 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
gimli = "0.19.0"
|
||||
wasmparser = { version = "0.39.1" }
|
||||
cranelift-codegen = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.44.0", features = ["enable-serde"] }
|
||||
wasmparser = "0.39.2"
|
||||
cranelift-codegen = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.46.1", features = ["enable-serde"] }
|
||||
faerie = "0.11.0"
|
||||
wasmtime-environ = { path = "../wasmtime-environ", default-features = false }
|
||||
target-lexicon = { version = "0.8.1", default-features = false }
|
||||
|
||||
@@ -12,9 +12,9 @@ readme = "README.md"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cranelift-codegen = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-codegen = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.46.1", features = ["enable-serde"] }
|
||||
lightbeam = { path = "../lightbeam", optional = true }
|
||||
failure = { version = "0.1.3", default-features = false }
|
||||
failure_derive = { version = "0.1.3", default-features = false }
|
||||
@@ -44,7 +44,7 @@ tempfile = "3"
|
||||
target-lexicon = { version = "0.8.1", default-features = false }
|
||||
pretty_env_logger = "0.3.0"
|
||||
rand = { version = "0.7.0", features = ["small_rng"] }
|
||||
cranelift-codegen = { version = "0.44.0", features = ["enable-serde", "all-arch"] }
|
||||
cranelift-codegen = { version = "0.46.1", features = ["enable-serde", "all-arch"] }
|
||||
filetime = "0.2.7"
|
||||
|
||||
[features]
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::module_environ::FunctionBodyData;
|
||||
use alloc::vec::Vec;
|
||||
use cranelift_codegen::{binemit, ir, isa, CodegenError};
|
||||
use cranelift_entity::PrimaryMap;
|
||||
use cranelift_wasm::{DefinedFuncIndex, FuncIndex, WasmError};
|
||||
use cranelift_wasm::{DefinedFuncIndex, FuncIndex, ModuleTranslationState, WasmError};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::ops::Range;
|
||||
|
||||
@@ -164,6 +164,7 @@ pub trait Compiler {
|
||||
/// Compile a parsed module with the given `TargetIsa`.
|
||||
fn compile_module<'data, 'module>(
|
||||
module: &'module module::Module,
|
||||
module_translation: &ModuleTranslationState,
|
||||
function_body_inputs: PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
|
||||
isa: &dyn isa::TargetIsa,
|
||||
generate_debug_info: bool,
|
||||
|
||||
@@ -21,7 +21,7 @@ use cranelift_codegen::ir::ExternalName;
|
||||
use cranelift_codegen::isa;
|
||||
use cranelift_codegen::Context;
|
||||
use cranelift_entity::PrimaryMap;
|
||||
use cranelift_wasm::{DefinedFuncIndex, FuncIndex, FuncTranslator};
|
||||
use cranelift_wasm::{DefinedFuncIndex, FuncIndex, FuncTranslator, ModuleTranslationState};
|
||||
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
||||
|
||||
/// Implementation of a relocation sink that just saves all the information for later
|
||||
@@ -177,6 +177,7 @@ impl crate::compilation::Compiler for Cranelift {
|
||||
/// associated relocations.
|
||||
fn compile_module<'data, 'module>(
|
||||
module: &'module Module,
|
||||
module_translation: &ModuleTranslationState,
|
||||
function_body_inputs: PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
|
||||
isa: &dyn isa::TargetIsa,
|
||||
generate_debug_info: bool,
|
||||
@@ -213,71 +214,74 @@ impl crate::compilation::Compiler for Cranelift {
|
||||
.into_iter()
|
||||
.collect::<Vec<(DefinedFuncIndex, &FunctionBodyData<'data>)>>()
|
||||
.par_iter()
|
||||
.map(|(i, input)| {
|
||||
let func_index = module.func_index(*i);
|
||||
let mut context = Context::new();
|
||||
context.func.name = get_func_name(func_index);
|
||||
context.func.signature =
|
||||
module.signatures[module.functions[func_index]].clone();
|
||||
if generate_debug_info {
|
||||
context.func.collect_debug_info();
|
||||
}
|
||||
.map_init(
|
||||
|| FuncTranslator::new(),
|
||||
|func_translator, (i, input)| {
|
||||
let func_index = module.func_index(*i);
|
||||
let mut context = Context::new();
|
||||
context.func.name = get_func_name(func_index);
|
||||
context.func.signature =
|
||||
module.signatures[module.functions[func_index]].clone();
|
||||
if generate_debug_info {
|
||||
context.func.collect_debug_info();
|
||||
}
|
||||
|
||||
let mut trans = FuncTranslator::new();
|
||||
trans
|
||||
.translate(
|
||||
input.data,
|
||||
input.module_offset,
|
||||
&mut context.func,
|
||||
&mut FuncEnvironment::new(isa.frontend_config(), module),
|
||||
)
|
||||
.map_err(CompileError::Wasm)?;
|
||||
func_translator
|
||||
.translate(
|
||||
module_translation,
|
||||
input.data,
|
||||
input.module_offset,
|
||||
&mut context.func,
|
||||
&mut FuncEnvironment::new(isa.frontend_config(), module),
|
||||
)
|
||||
.map_err(CompileError::Wasm)?;
|
||||
|
||||
let mut code_buf: Vec<u8> = Vec::new();
|
||||
let mut reloc_sink = RelocSink::new(func_index);
|
||||
let mut trap_sink = TrapSink::new();
|
||||
let mut stackmap_sink = binemit::NullStackmapSink {};
|
||||
context
|
||||
.compile_and_emit(
|
||||
isa,
|
||||
&mut code_buf,
|
||||
&mut reloc_sink,
|
||||
&mut trap_sink,
|
||||
&mut stackmap_sink,
|
||||
)
|
||||
.map_err(CompileError::Codegen)?;
|
||||
let mut code_buf: Vec<u8> = Vec::new();
|
||||
let mut reloc_sink = RelocSink::new(func_index);
|
||||
let mut trap_sink = TrapSink::new();
|
||||
let mut stackmap_sink = binemit::NullStackmapSink {};
|
||||
context
|
||||
.compile_and_emit(
|
||||
isa,
|
||||
&mut code_buf,
|
||||
&mut reloc_sink,
|
||||
&mut trap_sink,
|
||||
&mut stackmap_sink,
|
||||
)
|
||||
.map_err(CompileError::Codegen)?;
|
||||
|
||||
let jt_offsets = context.func.jt_offsets.clone();
|
||||
let jt_offsets = context.func.jt_offsets.clone();
|
||||
|
||||
let address_transform = if generate_debug_info {
|
||||
let body_len = code_buf.len();
|
||||
Some(get_function_address_map(&context, input, body_len, isa))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let address_transform = if generate_debug_info {
|
||||
let body_len = code_buf.len();
|
||||
Some(get_function_address_map(&context, input, body_len, isa))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let ranges = if generate_debug_info {
|
||||
Some(
|
||||
context
|
||||
.build_value_labels_ranges(isa)
|
||||
.map_err(CompileError::Codegen)?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let ranges = if generate_debug_info {
|
||||
Some(
|
||||
context
|
||||
.build_value_labels_ranges(isa)
|
||||
.map_err(CompileError::Codegen)?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let stack_slots = context.func.stack_slots.clone();
|
||||
let stack_slots = context.func.stack_slots.clone();
|
||||
|
||||
Ok((
|
||||
code_buf,
|
||||
jt_offsets,
|
||||
reloc_sink.func_relocs,
|
||||
address_transform,
|
||||
ranges,
|
||||
stack_slots,
|
||||
trap_sink.traps,
|
||||
))
|
||||
})
|
||||
Ok((
|
||||
code_buf,
|
||||
jt_offsets,
|
||||
reloc_sink.func_relocs,
|
||||
address_transform,
|
||||
ranges,
|
||||
stack_slots,
|
||||
trap_sink.traps,
|
||||
))
|
||||
},
|
||||
)
|
||||
.collect::<Result<Vec<_>, CompileError>>()?
|
||||
.into_iter()
|
||||
.for_each(
|
||||
|
||||
@@ -20,6 +20,7 @@ impl crate::compilation::Compiler for Lightbeam {
|
||||
/// associated relocations.
|
||||
fn compile_module<'data, 'module>(
|
||||
module: &'module Module,
|
||||
module_translation: &ModuleTranslationState,
|
||||
function_body_inputs: PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
|
||||
isa: &dyn isa::TargetIsa,
|
||||
// TODO
|
||||
|
||||
@@ -11,7 +11,7 @@ use cranelift_codegen::isa::TargetFrontendConfig;
|
||||
use cranelift_entity::PrimaryMap;
|
||||
use cranelift_wasm::{
|
||||
self, translate_module, DefinedFuncIndex, FuncIndex, Global, GlobalIndex, Memory, MemoryIndex,
|
||||
SignatureIndex, Table, TableIndex, WasmResult,
|
||||
ModuleTranslationState, SignatureIndex, Table, TableIndex, WasmResult,
|
||||
};
|
||||
|
||||
/// Contains function data: byte code and its offset in the module.
|
||||
@@ -42,6 +42,9 @@ pub struct ModuleTranslation<'data> {
|
||||
|
||||
/// Tunable parameters.
|
||||
pub tunables: Tunables,
|
||||
|
||||
/// The decoded Wasm types for the module.
|
||||
pub module_translation: Option<ModuleTranslationState>,
|
||||
}
|
||||
|
||||
impl<'data> ModuleTranslation<'data> {
|
||||
@@ -67,6 +70,7 @@ impl<'data> ModuleEnvironment<'data> {
|
||||
function_body_inputs: PrimaryMap::new(),
|
||||
data_initializers: Vec::new(),
|
||||
tunables,
|
||||
module_translation: None,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -78,8 +82,9 @@ impl<'data> ModuleEnvironment<'data> {
|
||||
/// Translate a wasm module using this environment. This consumes the
|
||||
/// `ModuleEnvironment` and produces a `ModuleTranslation`.
|
||||
pub fn translate(mut self, data: &'data [u8]) -> WasmResult<ModuleTranslation<'data>> {
|
||||
translate_module(data, &mut self)?;
|
||||
|
||||
assert!(self.result.module_translation.is_none());
|
||||
let module_translation = translate_module(data, &mut self)?;
|
||||
self.result.module_translation = Some(module_translation);
|
||||
Ok(self.result)
|
||||
}
|
||||
}
|
||||
@@ -320,6 +325,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
||||
|
||||
fn define_function_body(
|
||||
&mut self,
|
||||
_module_translation: &ModuleTranslationState,
|
||||
body_bytes: &'data [u8],
|
||||
body_offset: usize,
|
||||
) -> WasmResult<()> {
|
||||
|
||||
@@ -11,10 +11,10 @@ readme = "README.md"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cranelift-codegen = { version = "0.44.0", default-features = false }
|
||||
cranelift-codegen = { version = "0.46.1", default-features = false }
|
||||
failure = { version = "0.1", default-features = false }
|
||||
walrus = "0.12.0"
|
||||
wasmparser = { version = "0.39.1", default-features = false }
|
||||
wasmparser = { version = "0.39.2", default-features = false }
|
||||
wasm-webidl-bindings = "0.5.0"
|
||||
wasmtime-jit = { path = '../wasmtime-jit', default-features = false }
|
||||
wasmtime-runtime = { path = '../wasmtime-runtime', default-features = false }
|
||||
|
||||
@@ -114,26 +114,12 @@ impl ModuleData {
|
||||
let incoming = binding.param_bindings()?;
|
||||
let outgoing = binding.result_bindings()?;
|
||||
|
||||
// We have a magical dummy binding which indicates that this wasm
|
||||
// function is using a return pointer. This is a total hack around
|
||||
// multi-value, and we really should just implement multi-value in
|
||||
// wasm-bindgen. In the meantime though this synthesizes a return
|
||||
// pointer going as the first argument and translating outgoing
|
||||
// arguments reads from the return pointer.
|
||||
let (base, incoming, outgoing) = if uses_retptr(&outgoing) {
|
||||
(Some(8), &incoming[1..], &outgoing[1..])
|
||||
} else {
|
||||
(None, incoming.as_slice(), outgoing.as_slice())
|
||||
};
|
||||
let mut wasm_args = translate_incoming(cx, handle, &incoming, base.is_some() as u32, args)?;
|
||||
if let Some(n) = base {
|
||||
wasm_args.insert(0, RuntimeValue::I32(n as i32));
|
||||
}
|
||||
let wasm_args = translate_incoming(cx, handle, &incoming, args)?;
|
||||
let wasm_results = match cx.invoke(handle, export, &wasm_args)? {
|
||||
ActionOutcome::Returned { values } => values,
|
||||
ActionOutcome::Trapped { message } => bail!("trapped: {}", message),
|
||||
};
|
||||
translate_outgoing(cx, handle, &outgoing, base, &wasm_results)
|
||||
translate_outgoing(cx, handle, &outgoing, &wasm_results)
|
||||
}
|
||||
|
||||
/// Returns an appropriate binding for the `name` export in this module
|
||||
@@ -217,14 +203,8 @@ impl ExportBinding<'_> {
|
||||
ast::WebidlCompoundType::Function(f) => f,
|
||||
_ => bail!("webidl type for function must be of function type"),
|
||||
};
|
||||
let skip = if uses_retptr(&binding.result.bindings) {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
func.params
|
||||
.iter()
|
||||
.skip(skip)
|
||||
.map(|param| match param {
|
||||
ast::WebidlTypeRef::Id(_) => bail!("function arguments cannot be compound"),
|
||||
ast::WebidlTypeRef::Scalar(s) => Ok(*s),
|
||||
@@ -303,12 +283,11 @@ fn translate_incoming(
|
||||
cx: &mut Context,
|
||||
handle: &mut InstanceHandle,
|
||||
bindings: &[ast::IncomingBindingExpression],
|
||||
offset: u32,
|
||||
args: &[Value],
|
||||
) -> Result<Vec<RuntimeValue>, Error> {
|
||||
let get = |expr: &ast::IncomingBindingExpression| match expr {
|
||||
ast::IncomingBindingExpression::Get(g) => args
|
||||
.get((g.idx - offset) as usize)
|
||||
.get(g.idx as usize)
|
||||
.ok_or_else(|| format_err!("argument index out of bounds: {}", g.idx)),
|
||||
_ => bail!("unsupported incoming binding expr {:?}", expr),
|
||||
};
|
||||
@@ -395,7 +374,6 @@ fn translate_outgoing(
|
||||
cx: &mut Context,
|
||||
handle: &mut InstanceHandle,
|
||||
bindings: &[ast::OutgoingBindingExpression],
|
||||
retptr: Option<u32>,
|
||||
args: &[RuntimeValue],
|
||||
) -> Result<Vec<Value>, Error> {
|
||||
let mut values = Vec::new();
|
||||
@@ -414,25 +392,10 @@ fn translate_outgoing(
|
||||
))
|
||||
};
|
||||
|
||||
if retptr.is_some() {
|
||||
assert!(args.is_empty());
|
||||
}
|
||||
|
||||
let get = |idx: u32| match retptr {
|
||||
Some(i) => {
|
||||
let bytes = raw_memory()?;
|
||||
let base = &bytes[(i + idx * 4) as usize..][..4];
|
||||
Ok(RuntimeValue::I32(
|
||||
((base[0] as i32) << 0)
|
||||
| ((base[1] as i32) << 8)
|
||||
| ((base[2] as i32) << 16)
|
||||
| ((base[3] as i32) << 24),
|
||||
))
|
||||
}
|
||||
None => args
|
||||
.get(idx as usize)
|
||||
let get = |idx: u32| {
|
||||
args.get(idx as usize)
|
||||
.cloned()
|
||||
.ok_or_else(|| format_err!("argument index out of bounds: {}", idx)),
|
||||
.ok_or_else(|| format_err!("argument index out of bounds: {}", idx))
|
||||
};
|
||||
|
||||
for expr in bindings {
|
||||
@@ -496,10 +459,3 @@ fn translate_outgoing(
|
||||
|
||||
Ok(values)
|
||||
}
|
||||
|
||||
fn uses_retptr(outgoing: &[ast::OutgoingBindingExpression]) -> bool {
|
||||
match outgoing.get(0) {
|
||||
Some(ast::OutgoingBindingExpression::As(e)) => e.idx == u32::max_value(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,10 +11,10 @@ readme = "README.md"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cranelift-codegen = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-frontend = "0.44.0"
|
||||
cranelift-codegen = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-frontend = "0.46.1"
|
||||
wasmtime-environ = { path = "../wasmtime-environ", default-features = false }
|
||||
wasmtime-runtime = { path = "../wasmtime-runtime", default-features = false }
|
||||
wasmtime-debug = { path = "../wasmtime-debug", default-features = false }
|
||||
@@ -23,7 +23,7 @@ failure = { version = "0.1.3", default-features = false }
|
||||
failure_derive = { version = "0.1.3", default-features = false }
|
||||
target-lexicon = { version = "0.8.1", default-features = false }
|
||||
hashbrown = { version = "0.6.0", optional = true }
|
||||
wasmparser = { version = "0.39.1", default-features = false }
|
||||
wasmparser = { version = "0.39.2", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
|
||||
@@ -14,7 +14,7 @@ use cranelift_codegen::Context;
|
||||
use cranelift_codegen::{binemit, ir};
|
||||
use cranelift_entity::{EntityRef, PrimaryMap};
|
||||
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
|
||||
use cranelift_wasm::{DefinedFuncIndex, DefinedMemoryIndex};
|
||||
use cranelift_wasm::{DefinedFuncIndex, DefinedMemoryIndex, ModuleTranslationState};
|
||||
use wasmtime_debug::{emit_debugsections_image, DebugInfoData};
|
||||
use wasmtime_environ::{
|
||||
Compilation, CompileError, Compiler as _C, FunctionBodyData, Module, ModuleVmctxInfo,
|
||||
@@ -104,6 +104,7 @@ impl Compiler {
|
||||
pub(crate) fn compile<'data>(
|
||||
&mut self,
|
||||
module: &Module,
|
||||
module_translation: &ModuleTranslationState,
|
||||
function_body_inputs: PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
|
||||
debug_data: Option<DebugInfoData>,
|
||||
) -> Result<
|
||||
@@ -122,6 +123,7 @@ impl Compiler {
|
||||
CompilationStrategy::Auto | CompilationStrategy::Cranelift => {
|
||||
wasmtime_environ::cranelift::Cranelift::compile_module(
|
||||
module,
|
||||
module_translation,
|
||||
function_body_inputs,
|
||||
&*self.isa,
|
||||
debug_data.is_some(),
|
||||
|
||||
@@ -80,6 +80,7 @@ impl<'data> RawCompiledModule<'data> {
|
||||
|
||||
let (allocated_functions, jt_offsets, relocations, dbg_image) = compiler.compile(
|
||||
&translation.module,
|
||||
translation.module_translation.as_ref().unwrap(),
|
||||
translation.function_body_inputs,
|
||||
debug_data,
|
||||
)?;
|
||||
|
||||
@@ -11,8 +11,8 @@ readme = "README.md"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cranelift-codegen = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-codegen = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.46.1", features = ["enable-serde"] }
|
||||
wasmtime-environ = { path = "../wasmtime-environ" }
|
||||
faerie = "0.11.0"
|
||||
|
||||
@@ -11,9 +11,9 @@ readme = "README.md"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cranelift-codegen = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-codegen = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.46.1", features = ["enable-serde"] }
|
||||
wasmtime-environ = { path = "../wasmtime-environ", default-features = false }
|
||||
region = "2.0.0"
|
||||
lazy_static = "1.2.0"
|
||||
|
||||
@@ -12,9 +12,9 @@ readme = "README.md"
|
||||
wasmtime-runtime = { path = "../wasmtime-runtime" }
|
||||
wasmtime-environ = { path = "../wasmtime-environ" }
|
||||
wasmtime-jit = { path = "../wasmtime-jit" }
|
||||
cranelift-codegen = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-codegen = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.46.1", features = ["enable-serde"] }
|
||||
target-lexicon = "0.8.1"
|
||||
log = { version = "0.4.8", default-features = false }
|
||||
libc = "0.2.60"
|
||||
|
||||
@@ -14,9 +14,9 @@ wasmtime-runtime = { path = "../wasmtime-runtime" }
|
||||
wasmtime-environ = { path = "../wasmtime-environ" }
|
||||
wasmtime-jit = { path = "../wasmtime-jit" }
|
||||
wasi-common = { git = "https://github.com/CraneStation/wasi-common", rev = "c3bf040"}
|
||||
cranelift-codegen = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-codegen = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.46.1", features = ["enable-serde"] }
|
||||
target-lexicon = "0.8.1"
|
||||
log = { version = "0.4.8", default-features = false }
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ readme = "README.md"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cranelift-codegen = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.44.0", features = ["enable-serde"] }
|
||||
cranelift-codegen = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-entity = { version = "0.46.1", features = ["enable-serde"] }
|
||||
cranelift-wasm = { version = "0.46.1", features = ["enable-serde"] }
|
||||
wasmtime-jit = { path = "../wasmtime-jit" }
|
||||
wasmtime-runtime = { path = "../wasmtime-runtime" }
|
||||
wasmtime-environ = { path = "../wasmtime-environ" }
|
||||
|
||||
Reference in New Issue
Block a user