1781: Cranelift upgrade r=syrusakbary a=syrusakbary

<!-- 
Prior to submitting a PR, review the CONTRIBUTING.md document for recommendations on how to test:
https://github.com/wasmerio/wasmer/blob/master/CONTRIBUTING.md#pull-requests

-->

# Description

Upgrade Cranelift to `0.67`. This upgrade also enables all SIMD tests (with one small exception operator that is still not fixed in Cranelift).

<!-- 
Provide details regarding the change including motivation,
links to related issues, and the context of the PR.
-->


Co-authored-by: Syrus <me@syrusakbary.com>
Co-authored-by: Syrus Akbary <me@syrusakbary.com>
This commit is contained in:
bors[bot]
2020-10-30 04:47:24 +00:00
committed by GitHub
25 changed files with 1128 additions and 475 deletions

33
Cargo.lock generated
View File

@@ -317,18 +317,18 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
[[package]] [[package]]
name = "cranelift-bforest" name = "cranelift-bforest"
version = "0.65.0" version = "0.67.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9413a2c6bdb01ab8acc867421bd7343ddea491d015453f4e56f4f60c816d120" checksum = "0f065f6889758f817f61a230220d1811ba99a9762af2fb69ae23048314f75ff2"
dependencies = [ dependencies = [
"cranelift-entity", "cranelift-entity",
] ]
[[package]] [[package]]
name = "cranelift-codegen" name = "cranelift-codegen"
version = "0.65.0" version = "0.67.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f28d389588c2375bb95292e0bc6cbf010e7f30fb4e9734738b576521b737826a" checksum = "510aa2ab4307644100682b94e449940a0ea15c5887f1d4b9678b8dd5ef31e736"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"cranelift-bforest", "cranelift-bforest",
@@ -347,9 +347,9 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-codegen-meta" name = "cranelift-codegen-meta"
version = "0.65.0" version = "0.67.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74dd3cf6f107c1df4c2b8aab91ec4181aee7ff17289673fcbec63325e7e40a83" checksum = "b4cb0c7e87c60d63b35f9670c15479ee4a5e557dd127efab88b2f9b2ca83c9a0"
dependencies = [ dependencies = [
"cranelift-codegen-shared", "cranelift-codegen-shared",
"cranelift-entity", "cranelift-entity",
@@ -357,24 +357,24 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-codegen-shared" name = "cranelift-codegen-shared"
version = "0.65.0" version = "0.67.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efaf050fab2dbf324544489443ff3cc8c67c9420c8902ec6628bd906bd7393e9" checksum = "60636227098693e06de8d6d88beea2a7d32ecf8a8030dacdb57c68e06f381826"
[[package]] [[package]]
name = "cranelift-entity" name = "cranelift-entity"
version = "0.65.0" version = "0.67.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f07eb8aa0a5da94b56339e4e3052c496a3df4354357cd5da8c7b02c6e8f1dc1d" checksum = "6156db73e0c9f65f80c512988d63ec736be0dee3dd66bf951e3e28aed9dc02d3"
dependencies = [ dependencies = [
"serde", "serde",
] ]
[[package]] [[package]]
name = "cranelift-frontend" name = "cranelift-frontend"
version = "0.65.0" version = "0.67.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f6fe1d3e968576f4b60d23f40ee90281f8de2cdf23d2110f3b0296ff420555e" checksum = "e09cd158c9a820a4cc14a34076811da225cce1d31dc6d03c5ef85b91aef560b9"
dependencies = [ dependencies = [
"cranelift-codegen", "cranelift-codegen",
"hashbrown 0.7.2", "hashbrown 0.7.2",
@@ -1568,9 +1568,9 @@ checksum = "d813022b2e00774a48eaf43caaa3c20b45f040ba8cbf398e2e8911a06668dbe6"
[[package]] [[package]]
name = "regalloc" name = "regalloc"
version = "0.0.26" version = "0.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c03092d79e0fd610932d89ed53895a38c0dd3bcd317a0046e69940de32f1d95" checksum = "2041c2d34f6ff346d6f428974f03d8bf12679b0c816bb640dc5eb1d48848d8d1"
dependencies = [ dependencies = [
"log", "log",
"rustc-hash", "rustc-hash",
@@ -1855,9 +1855,9 @@ dependencies = [
[[package]] [[package]]
name = "target-lexicon" name = "target-lexicon"
version = "0.10.0" version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab0e7238dcc7b40a7be719a25365910f6807bd864f4cce6b2e6b873658e2b19d" checksum = "4ee5a98e506fb7231a304c3a1bd7c132a55016cf65001e0282480665870dfcb9"
[[package]] [[package]]
name = "tempfile" name = "tempfile"
@@ -2263,6 +2263,7 @@ dependencies = [
"more-asserts", "more-asserts",
"rayon", "rayon",
"serde", "serde",
"smallvec",
"target-lexicon", "target-lexicon",
"tracing", "tracing",
"wasmer-compiler", "wasmer-compiler",

View File

@@ -25,7 +25,7 @@ cfg-if = "0.1"
wat = { version = "1.0", optional = true } wat = { version = "1.0", optional = true }
thiserror = "1.0" thiserror = "1.0"
more-asserts = "0.2" more-asserts = "0.2"
target-lexicon = { version = "0.10", default-features = false } target-lexicon = { version = "0.11", default-features = false }
[target.'cfg(target_os = "windows")'.dependencies] [target.'cfg(target_os = "windows")'.dependencies]
winapi = "0.3" winapi = "0.3"

View File

@@ -15,18 +15,19 @@ edition = "2018"
wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4", features = ["translator"], default-features = false } wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4", features = ["translator"], default-features = false }
wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" }
wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4", default-features = false, features = ["std"] } wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4", default-features = false, features = ["std"] }
cranelift-codegen = { version = "0.65", default-features = false, features = ["x86", "arm64"] } cranelift-codegen = { version = "0.67", default-features = false, features = ["x86", "arm64"] }
cranelift-frontend = { version = "0.65", default-features = false } cranelift-frontend = { version = "0.67", default-features = false }
tracing = "0.1" tracing = "0.1"
hashbrown = { version = "0.8", optional = true } hashbrown = { version = "0.8", optional = true }
rayon = "1.3" rayon = "1.3"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
more-asserts = "0.2" more-asserts = "0.2"
gimli = { version = "0.21", optional = true } gimli = { version = "0.21", optional = true }
smallvec = "1.0.0"
[dev-dependencies] [dev-dependencies]
target-lexicon = { version = "0.10", default-features = false } target-lexicon = { version = "0.11", default-features = false }
cranelift-codegen = { version = "0.65", features = ["enable-serde", "all-arch"] } cranelift-codegen = { version = "0.67", features = ["enable-serde", "all-arch"] }
lazy_static = "1.4" lazy_static = "1.4"
[badges] [badges]
@@ -35,6 +36,6 @@ maintenance = { status = "actively-developed" }
[features] [features]
default = ["std", "enable-serde", "unwind"] default = ["std", "enable-serde", "unwind"]
unwind = ["cranelift-codegen/unwind", "gimli"] unwind = ["cranelift-codegen/unwind", "gimli"]
enable-serde = ["wasmer-compiler/enable-serde", "cranelift-codegen/enable-serde", "wasmer-types/enable-serde"] enable-serde = ["wasmer-compiler/enable-serde", "wasmer-types/enable-serde"]
std = ["cranelift-codegen/std", "cranelift-frontend/std", "wasmer-compiler/std", "wasmer-types/std"] std = ["cranelift-codegen/std", "cranelift-frontend/std", "wasmer-compiler/std", "wasmer-types/std"]
core = ["hashbrown", "cranelift-codegen/core", "cranelift-frontend/core"] core = ["hashbrown", "cranelift-codegen/core", "cranelift-frontend/core"]

View File

@@ -95,7 +95,7 @@ impl Compiler for CraneliftCompiler {
}; };
let functions = function_body_inputs let functions = function_body_inputs
.into_iter() .iter()
.collect::<Vec<(LocalFunctionIndex, &FunctionBodyData<'_>)>>() .collect::<Vec<(LocalFunctionIndex, &FunctionBodyData<'_>)>>()
.par_iter() .par_iter()
.map_init(FuncTranslator::new, |func_translator, (i, input)| { .map_init(FuncTranslator::new, |func_translator, (i, input)| {
@@ -127,7 +127,7 @@ impl Compiler for CraneliftCompiler {
let mut code_buf: Vec<u8> = Vec::new(); let mut code_buf: Vec<u8> = Vec::new();
let mut reloc_sink = RelocSink::new(module, func_index); let mut reloc_sink = RelocSink::new(module, func_index);
let mut trap_sink = TrapSink::new(); let mut trap_sink = TrapSink::new();
let mut stackmap_sink = binemit::NullStackmapSink {}; let mut stackmap_sink = binemit::NullStackMapSink {};
context context
.compile_and_emit( .compile_and_emit(
&*isa, &*isa,

View File

@@ -11,7 +11,9 @@ use cranelift_codegen::ir::immediates::{Offset32, Uimm64};
use cranelift_codegen::ir::types::*; use cranelift_codegen::ir::types::*;
use cranelift_codegen::ir::{AbiParam, ArgumentPurpose, Function, InstBuilder, Signature}; use cranelift_codegen::ir::{AbiParam, ArgumentPurpose, Function, InstBuilder, Signature};
use cranelift_codegen::isa::TargetFrontendConfig; use cranelift_codegen::isa::TargetFrontendConfig;
use cranelift_frontend::FunctionBuilder;
use std::convert::TryFrom; use std::convert::TryFrom;
use wasmer_compiler::wasmparser::Type;
use wasmer_compiler::{WasmError, WasmResult}; use wasmer_compiler::{WasmError, WasmResult};
use wasmer_types::entity::EntityRef; use wasmer_types::entity::EntityRef;
use wasmer_types::entity::PrimaryMap; use wasmer_types::entity::PrimaryMap;
@@ -538,10 +540,11 @@ impl<'module_environment> BaseFuncEnvironment for FuncEnvironment<'module_enviro
fn translate_table_grow( fn translate_table_grow(
&mut self, &mut self,
_: cranelift_codegen::cursor::FuncCursor<'_>, mut _pos: cranelift_codegen::cursor::FuncCursor<'_>,
_: TableIndex, _table_index: TableIndex,
_: ir::Value, _table: ir::Table,
_: ir::Value, _delta: ir::Value,
_init_value: ir::Value,
) -> WasmResult<ir::Value> { ) -> WasmResult<ir::Value> {
Err(WasmError::Unsupported( Err(WasmError::Unsupported(
"the `table.grow` instruction is not supported yet".into(), "the `table.grow` instruction is not supported yet".into(),
@@ -550,9 +553,10 @@ impl<'module_environment> BaseFuncEnvironment for FuncEnvironment<'module_enviro
fn translate_table_get( fn translate_table_get(
&mut self, &mut self,
_: cranelift_codegen::cursor::FuncCursor<'_>, _builder: &mut FunctionBuilder,
_: TableIndex, _table_index: TableIndex,
_: ir::Value, _table: ir::Table,
_index: ir::Value,
) -> WasmResult<ir::Value> { ) -> WasmResult<ir::Value> {
Err(WasmError::Unsupported( Err(WasmError::Unsupported(
"the `table.get` instruction is not supported yet".into(), "the `table.get` instruction is not supported yet".into(),
@@ -561,10 +565,11 @@ impl<'module_environment> BaseFuncEnvironment for FuncEnvironment<'module_enviro
fn translate_table_set( fn translate_table_set(
&mut self, &mut self,
_: cranelift_codegen::cursor::FuncCursor<'_>, _builder: &mut FunctionBuilder,
_: TableIndex, _table_index: TableIndex,
_: ir::Value, _table: ir::Table,
_: ir::Value, _value: ir::Value,
_index: ir::Value,
) -> WasmResult<()> { ) -> WasmResult<()> {
Err(WasmError::Unsupported( Err(WasmError::Unsupported(
"the `table.set` instruction is not supported yet".into(), "the `table.set` instruction is not supported yet".into(),
@@ -573,21 +578,56 @@ impl<'module_environment> BaseFuncEnvironment for FuncEnvironment<'module_enviro
fn translate_table_fill( fn translate_table_fill(
&mut self, &mut self,
_: cranelift_codegen::cursor::FuncCursor<'_>, mut _pos: cranelift_codegen::cursor::FuncCursor<'_>,
_: TableIndex, _table_index: TableIndex,
_: ir::Value, _dst: ir::Value,
_: ir::Value, _val: ir::Value,
_: ir::Value, _len: ir::Value,
) -> WasmResult<()> { ) -> WasmResult<()> {
Err(WasmError::Unsupported( Err(WasmError::Unsupported(
"the `table.fill` instruction is not supported yet".into(), "the `table.fill` instruction is not supported yet".into(),
)) ))
} }
fn translate_ref_null(
&mut self,
mut pos: cranelift_codegen::cursor::FuncCursor,
ty: Type,
) -> WasmResult<ir::Value> {
Ok(match ty {
Type::FuncRef => pos.ins().iconst(self.pointer_type(), 0),
// Type::ExternRef => pos.ins().null(self.reference_type(ty)),
_ => {
return Err(WasmError::Unsupported(
"`ref.null T` that is not a `funcref`".into(),
));
}
})
}
fn translate_ref_is_null(
&mut self,
mut pos: cranelift_codegen::cursor::FuncCursor,
value: ir::Value,
) -> WasmResult<ir::Value> {
let bool_is_null = match pos.func.dfg.value_type(value) {
// `externref`
ty if ty.is_ref() => pos.ins().is_null(value),
// `funcref`
ty if ty == self.pointer_type() => {
pos.ins()
.icmp_imm(cranelift_codegen::ir::condcodes::IntCC::Equal, value, 0)
}
_ => unreachable!(),
};
Ok(pos.ins().bint(ir::types::I32, bool_is_null))
}
fn translate_ref_func( fn translate_ref_func(
&mut self, &mut self,
_: cranelift_codegen::cursor::FuncCursor<'_>, mut _pos: cranelift_codegen::cursor::FuncCursor<'_>,
_: u32, _func_index: FunctionIndex,
) -> WasmResult<ir::Value> { ) -> WasmResult<ir::Value> {
Err(WasmError::Unsupported( Err(WasmError::Unsupported(
"the `ref.func` instruction is not supported yet".into(), "the `ref.func` instruction is not supported yet".into(),
@@ -596,17 +636,17 @@ impl<'module_environment> BaseFuncEnvironment for FuncEnvironment<'module_enviro
fn translate_custom_global_get( fn translate_custom_global_get(
&mut self, &mut self,
_: cranelift_codegen::cursor::FuncCursor<'_>, mut _pos: cranelift_codegen::cursor::FuncCursor<'_>,
_: GlobalIndex, _index: GlobalIndex,
) -> WasmResult<ir::Value> { ) -> WasmResult<ir::Value> {
unreachable!("we don't make any custom globals") unreachable!("we don't make any custom globals")
} }
fn translate_custom_global_set( fn translate_custom_global_set(
&mut self, &mut self,
_: cranelift_codegen::cursor::FuncCursor<'_>, mut _pos: cranelift_codegen::cursor::FuncCursor<'_>,
_: GlobalIndex, _index: GlobalIndex,
_: ir::Value, _value: ir::Value,
) -> WasmResult<()> { ) -> WasmResult<()> {
unreachable!("we don't make any custom globals") unreachable!("we don't make any custom globals")
} }
@@ -771,7 +811,7 @@ impl<'module_environment> BaseFuncEnvironment for FuncEnvironment<'module_enviro
match self.table_styles[table_index] { match self.table_styles[table_index] {
TableStyle::CallerChecksSignature => { TableStyle::CallerChecksSignature => {
let sig_id_size = self.offsets.size_of_vmshared_signature_index(); let sig_id_size = self.offsets.size_of_vmshared_signature_index();
let sig_id_type = Type::int(u16::from(sig_id_size) * 8).unwrap(); let sig_id_type = ir::Type::int(u16::from(sig_id_size) * 8).unwrap();
let vmctx = self.vmctx(pos.func); let vmctx = self.vmctx(pos.func);
let base = pos.ins().global_value(pointer_type, vmctx); let base = pos.ins().global_value(pointer_type, vmctx);
let offset = let offset =
@@ -897,24 +937,22 @@ impl<'module_environment> BaseFuncEnvironment for FuncEnvironment<'module_enviro
fn translate_memory_copy( fn translate_memory_copy(
&mut self, &mut self,
mut pos: FuncCursor, mut pos: FuncCursor,
memory_index: MemoryIndex, src_index: MemoryIndex,
_heap: ir::Heap, _src_heap: ir::Heap,
_dst_index: MemoryIndex,
_dst_heap: ir::Heap,
dst: ir::Value, dst: ir::Value,
src: ir::Value, src: ir::Value,
len: ir::Value, len: ir::Value,
) -> WasmResult<()> { ) -> WasmResult<()> {
let (func_sig, memory_index, func_idx) = let (func_sig, src_index, func_idx) = self.get_memory_copy_func(&mut pos.func, src_index);
self.get_memory_copy_func(&mut pos.func, memory_index);
let memory_index_arg = pos.ins().iconst(I32, memory_index as i64); let src_index_arg = pos.ins().iconst(I32, src_index as i64);
let (vmctx, func_addr) = self.translate_load_builtin_function_address(&mut pos, func_idx); let (vmctx, func_addr) = self.translate_load_builtin_function_address(&mut pos, func_idx);
pos.ins().call_indirect( pos.ins()
func_sig, .call_indirect(func_sig, func_addr, &[vmctx, src_index_arg, dst, src, len]);
func_addr,
&[vmctx, memory_index_arg, dst, src, len],
);
Ok(()) Ok(())
} }
@@ -981,8 +1019,8 @@ impl<'module_environment> BaseFuncEnvironment for FuncEnvironment<'module_enviro
fn translate_table_size( fn translate_table_size(
&mut self, &mut self,
_pos: FuncCursor, mut _pos: FuncCursor,
_index: TableIndex, _table_index: TableIndex,
_table: ir::Table, _table: ir::Table,
) -> WasmResult<ir::Value> { ) -> WasmResult<ir::Value> {
Err(WasmError::Unsupported( Err(WasmError::Unsupported(
@@ -1064,4 +1102,31 @@ impl<'module_environment> BaseFuncEnvironment for FuncEnvironment<'module_enviro
Ok(()) Ok(())
} }
fn translate_atomic_wait(
&mut self,
_pos: FuncCursor,
_index: MemoryIndex,
_heap: ir::Heap,
_addr: ir::Value,
_expected: ir::Value,
_timeout: ir::Value,
) -> WasmResult<ir::Value> {
Err(WasmError::Unsupported(
"wasm atomics (fn translate_atomic_wait)".to_string(),
))
}
fn translate_atomic_notify(
&mut self,
_pos: FuncCursor,
_index: MemoryIndex,
_heap: ir::Heap,
_addr: ir::Value,
_count: ir::Value,
) -> WasmResult<ir::Value> {
Err(WasmError::Unsupported(
"wasm atomics (fn translate_atomic_notify)".to_string(),
))
}
} }

View File

@@ -124,6 +124,7 @@ fn translate_ir_trapcode(trap: ir::TrapCode) -> TrapCode {
match trap { match trap {
ir::TrapCode::StackOverflow => TrapCode::StackOverflow, ir::TrapCode::StackOverflow => TrapCode::StackOverflow,
ir::TrapCode::HeapOutOfBounds => TrapCode::HeapAccessOutOfBounds, ir::TrapCode::HeapOutOfBounds => TrapCode::HeapAccessOutOfBounds,
ir::TrapCode::HeapMisaligned => TrapCode::HeapMisaligned,
ir::TrapCode::TableOutOfBounds => TrapCode::TableAccessOutOfBounds, ir::TrapCode::TableOutOfBounds => TrapCode::TableAccessOutOfBounds,
ir::TrapCode::IndirectCallToNull => TrapCode::IndirectCallToNull, ir::TrapCode::IndirectCallToNull => TrapCode::IndirectCallToNull,
ir::TrapCode::BadSignature => TrapCode::BadSignature, ir::TrapCode::BadSignature => TrapCode::BadSignature,

View File

@@ -110,7 +110,7 @@ pub fn make_trampoline_dynamic_function(
let mut code_buf = Vec::new(); let mut code_buf = Vec::new();
let mut reloc_sink = TrampolineRelocSink {}; let mut reloc_sink = TrampolineRelocSink {};
let mut trap_sink = binemit::NullTrapSink {}; let mut trap_sink = binemit::NullTrapSink {};
let mut stackmap_sink = binemit::NullStackmapSink {}; let mut stackmap_sink = binemit::NullStackMapSink {};
context context
.compile_and_emit( .compile_and_emit(
isa, isa,

View File

@@ -108,7 +108,7 @@ pub fn make_trampoline_function_call(
let mut code_buf = Vec::new(); let mut code_buf = Vec::new();
let mut reloc_sink = TrampolineRelocSink {}; let mut reloc_sink = TrampolineRelocSink {};
let mut trap_sink = binemit::NullTrapSink {}; let mut trap_sink = binemit::NullTrapSink {};
let mut stackmap_sink = binemit::NullStackmapSink {}; let mut stackmap_sink = binemit::NullStackMapSink {};
context context
.compile_and_emit( .compile_and_emit(

View File

@@ -12,7 +12,7 @@ pub use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
pub mod binemit { pub mod binemit {
pub use cranelift_codegen::binemit::NullTrapSink; pub use cranelift_codegen::binemit::NullTrapSink;
pub use cranelift_codegen::binemit::{CodeOffset, NullStackmapSink, TrapSink}; pub use cranelift_codegen::binemit::{CodeOffset, NullStackMapSink, TrapSink};
use cranelift_codegen::{binemit, ir}; use cranelift_codegen::{binemit, ir};

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@ use cranelift_codegen::ir::immediates::Offset32;
use cranelift_codegen::ir::{self, InstBuilder}; use cranelift_codegen::ir::{self, InstBuilder};
use cranelift_codegen::isa::TargetFrontendConfig; use cranelift_codegen::isa::TargetFrontendConfig;
use cranelift_frontend::FunctionBuilder; use cranelift_frontend::FunctionBuilder;
use wasmer_compiler::wasmparser::Operator; use wasmer_compiler::wasmparser::{Operator, Type};
use wasmer_compiler::WasmResult; use wasmer_compiler::WasmResult;
use wasmer_types::{FunctionIndex, GlobalIndex, MemoryIndex, SignatureIndex, TableIndex}; use wasmer_types::{FunctionIndex, GlobalIndex, MemoryIndex, SignatureIndex, TableIndex};
@@ -229,8 +229,10 @@ pub trait FuncEnvironment: TargetEnvironment {
fn translate_memory_copy( fn translate_memory_copy(
&mut self, &mut self,
pos: FuncCursor, pos: FuncCursor,
index: MemoryIndex, src_index: MemoryIndex,
heap: ir::Heap, src_heap: ir::Heap,
dst_index: MemoryIndex,
dst_heap: ir::Heap,
dst: ir::Value, dst: ir::Value,
src: ir::Value, src: ir::Value,
len: ir::Value, len: ir::Value,
@@ -283,6 +285,7 @@ pub trait FuncEnvironment: TargetEnvironment {
&mut self, &mut self,
pos: FuncCursor, pos: FuncCursor,
table_index: TableIndex, table_index: TableIndex,
table: ir::Table,
delta: ir::Value, delta: ir::Value,
init_value: ir::Value, init_value: ir::Value,
) -> WasmResult<ir::Value>; ) -> WasmResult<ir::Value>;
@@ -290,16 +293,18 @@ pub trait FuncEnvironment: TargetEnvironment {
/// Translate a `table.get` WebAssembly instruction. /// Translate a `table.get` WebAssembly instruction.
fn translate_table_get( fn translate_table_get(
&mut self, &mut self,
pos: FuncCursor, builder: &mut FunctionBuilder,
table_index: TableIndex, table_index: TableIndex,
table: ir::Table,
index: ir::Value, index: ir::Value,
) -> WasmResult<ir::Value>; ) -> WasmResult<ir::Value>;
/// Translate a `table.set` WebAssembly instruction. /// Translate a `table.set` WebAssembly instruction.
fn translate_table_set( fn translate_table_set(
&mut self, &mut self,
pos: FuncCursor, builder: &mut FunctionBuilder,
table_index: TableIndex, table_index: TableIndex,
table: ir::Table,
value: ir::Value, value: ir::Value,
index: ir::Value, index: ir::Value,
) -> WasmResult<()>; ) -> WasmResult<()>;
@@ -344,8 +349,44 @@ pub trait FuncEnvironment: TargetEnvironment {
/// Translate a `elem.drop` WebAssembly instruction. /// Translate a `elem.drop` WebAssembly instruction.
fn translate_elem_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>; fn translate_elem_drop(&mut self, pos: FuncCursor, seg_index: u32) -> WasmResult<()>;
/// Translate a `ref.null T` WebAssembly instruction.
///
/// By default, translates into a null reference type.
///
/// Override this if you don't use Cranelift reference types for all Wasm
/// reference types (e.g. you use a raw pointer for `funcref`s) or if the
/// null sentinel is not a null reference type pointer for your type. If you
/// override this method, then you should also override
/// `translate_ref_is_null` as well.
fn translate_ref_null(&mut self, pos: FuncCursor, ty: Type) -> WasmResult<ir::Value>;
// {
// let _ = ty;
// Ok(pos.ins().null(self.reference_type(ty)))
// }
/// Translate a `ref.is_null` WebAssembly instruction.
///
/// By default, assumes that `value` is a Cranelift reference type, and that
/// a null Cranelift reference type is the null value for all Wasm reference
/// types.
///
/// If you override this method, you probably also want to override
/// `translate_ref_null` as well.
fn translate_ref_is_null(
&mut self,
mut pos: FuncCursor,
value: ir::Value,
) -> WasmResult<ir::Value> {
let is_null = pos.ins().is_null(value);
Ok(pos.ins().bint(ir::types::I32, is_null))
}
/// Translate a `ref.func` WebAssembly instruction. /// Translate a `ref.func` WebAssembly instruction.
fn translate_ref_func(&mut self, pos: FuncCursor, func_index: u32) -> WasmResult<ir::Value>; fn translate_ref_func(
&mut self,
pos: FuncCursor,
func_index: FunctionIndex,
) -> WasmResult<ir::Value>;
/// Translate a `global.get` WebAssembly instruction at `pos` for a global /// Translate a `global.get` WebAssembly instruction at `pos` for a global
/// that is custom. /// that is custom.
@@ -364,6 +405,38 @@ pub trait FuncEnvironment: TargetEnvironment {
val: ir::Value, val: ir::Value,
) -> WasmResult<()>; ) -> WasmResult<()>;
/// Translate an `i32.atomic.wait` or `i64.atomic.wait` WebAssembly instruction.
/// The `index` provided identifies the linear memory containing the value
/// to wait on, and `heap` is the heap reference returned by `make_heap`
/// for the same index. Whether the waited-on value is 32- or 64-bit can be
/// determined by examining the type of `expected`, which must be only I32 or I64.
///
/// Returns an i32, which is negative if the helper call failed.
fn translate_atomic_wait(
&mut self,
pos: FuncCursor,
index: MemoryIndex,
heap: ir::Heap,
addr: ir::Value,
expected: ir::Value,
timeout: ir::Value,
) -> WasmResult<ir::Value>;
/// Translate an `atomic.notify` WebAssembly instruction.
/// The `index` provided identifies the linear memory containing the value
/// to wait on, and `heap` is the heap reference returned by `make_heap`
/// for the same index.
///
/// Returns an i64, which is negative if the helper call failed.
fn translate_atomic_notify(
&mut self,
pos: FuncCursor,
index: MemoryIndex,
heap: ir::Heap,
addr: ir::Value,
count: ir::Value,
) -> WasmResult<ir::Value>;
/// Emit code at the beginning of every wasm loop. /// Emit code at the beginning of every wasm loop.
/// ///
/// This can be used to insert explicit interrupt or safepoint checking at /// This can be used to insert explicit interrupt or safepoint checking at

View File

@@ -132,7 +132,9 @@ impl ControlStackFrame {
Self::Loop { header, .. } => header, Self::Loop { header, .. } => header,
} }
} }
pub fn original_stack_size(&self) -> usize { /// Private helper. Use `truncate_value_stack_to_else_params()` or
/// `truncate_value_stack_to_original_size()` to restore value-stack state.
fn original_stack_size(&self) -> usize {
match *self { match *self {
Self::If { Self::If {
original_stack_size, original_stack_size,
@@ -182,6 +184,33 @@ impl ControlStackFrame {
Self::Loop { .. } => {} Self::Loop { .. } => {}
} }
} }
/// Pop values from the value stack so that it is left at the
/// input-parameters to an else-block.
pub fn truncate_value_stack_to_else_params(&self, stack: &mut Vec<Value>) {
debug_assert!(matches!(self, &ControlStackFrame::If { .. }));
stack.truncate(self.original_stack_size());
}
/// Pop values from the value stack so that it is left at the state it was
/// before this control-flow frame.
pub fn truncate_value_stack_to_original_size(&self, stack: &mut Vec<Value>) {
// The "If" frame pushes its parameters twice, so they're available to the else block
// (see also `FuncTranslationState::push_if`).
// Yet, the original_stack_size member accounts for them only once, so that the else
// block can see the same number of parameters as the consequent block. As a matter of
// fact, we need to substract an extra number of parameter values for if blocks.
let num_duplicated_params = match self {
&ControlStackFrame::If {
num_param_values, ..
} => {
debug_assert!(num_param_values <= self.original_stack_size());
num_param_values
}
_ => 0,
};
stack.truncate(self.original_stack_size() - num_duplicated_params);
}
} }
/// Contains information passed along during a function's translation and that records: /// Contains information passed along during a function's translation and that records:
@@ -219,6 +248,16 @@ pub struct FuncTranslationState {
functions: HashMap<FunctionIndex, (ir::FuncRef, usize)>, functions: HashMap<FunctionIndex, (ir::FuncRef, usize)>,
} }
// Public methods that are exposed to non-`cranelift_wasm` API consumers.
impl FuncTranslationState {
/// True if the current translation state expresses reachable code, false if it is unreachable.
#[inline]
#[allow(dead_code)]
pub fn reachable(&self) -> bool {
self.reachable
}
}
impl FuncTranslationState { impl FuncTranslationState {
/// Construct a new, empty, `FuncTranslationState` /// Construct a new, empty, `FuncTranslationState`
pub(crate) fn new() -> Self { pub(crate) fn new() -> Self {
@@ -441,7 +480,7 @@ impl FuncTranslationState {
/// Get the `Table` reference that should be used to access table `index`. /// Get the `Table` reference that should be used to access table `index`.
/// Create the reference if necessary. /// Create the reference if necessary.
pub(crate) fn get_table<FE: FuncEnvironment + ?Sized>( pub(crate) fn get_or_create_table<FE: FuncEnvironment + ?Sized>(
&mut self, &mut self,
func: &mut ir::Function, func: &mut ir::Function,
index: u32, index: u32,

View File

@@ -176,12 +176,9 @@ fn parse_local_decls<FE: FuncEnvironment + ?Sized>(
let mut next_local = num_params; let mut next_local = num_params;
let local_count = reader.read_local_count().map_err(to_wasm_error)?; let local_count = reader.read_local_count().map_err(to_wasm_error)?;
let mut locals_total = 0;
for _ in 0..local_count { for _ in 0..local_count {
builder.set_srcloc(cur_srcloc(reader)); builder.set_srcloc(cur_srcloc(reader));
let (count, ty) = reader let (count, ty) = reader.read_local_decl().map_err(to_wasm_error)?;
.read_local_decl(&mut locals_total)
.map_err(to_wasm_error)?;
declare_locals(builder, count, ty, &mut next_local, environ)?; declare_locals(builder, count, ty, &mut next_local, environ)?;
} }

View File

@@ -15,7 +15,7 @@ edition = "2018"
wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4", features = ["translator"] } wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4", features = ["translator"] }
wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" }
wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" }
target-lexicon = { version = "0.10", default-features = false } target-lexicon = { version = "0.11", default-features = false }
smallvec = "1" smallvec = "1"
goblin = "0.2" goblin = "0.2"
libc = { version = "^0.2.69", default-features = false } libc = { version = "^0.2.69", default-features = false }

View File

@@ -124,7 +124,7 @@ impl LLVMCompiler {
compile_info compile_info
.module .module
.signatures .signatures
.into_iter() .iter()
.collect::<Vec<_>>() .collect::<Vec<_>>()
.par_iter() .par_iter()
.map_init( .map_init(
@@ -149,7 +149,7 @@ impl LLVMCompiler {
compile_info compile_info
.module .module
.functions .functions
.into_iter() .iter()
.collect::<Vec<_>>() .collect::<Vec<_>>()
.par_iter() .par_iter()
.map_init( .map_init(
@@ -248,7 +248,7 @@ impl Compiler for LLVMCompiler {
let mut frame_section_bytes = vec![]; let mut frame_section_bytes = vec![];
let mut frame_section_relocations = vec![]; let mut frame_section_relocations = vec![];
let functions = function_body_inputs let functions = function_body_inputs
.into_iter() .iter()
.collect::<Vec<(LocalFunctionIndex, &FunctionBodyData<'_>)>>() .collect::<Vec<(LocalFunctionIndex, &FunctionBodyData<'_>)>>()
.par_iter() .par_iter()
.map_init( .map_init(

View File

@@ -184,10 +184,7 @@ impl FuncTranslator {
let mut locals = vec![]; let mut locals = vec![];
let num_locals = reader.read_local_count().map_err(to_wasm_error)?; let num_locals = reader.read_local_count().map_err(to_wasm_error)?;
for _ in 0..num_locals { for _ in 0..num_locals {
let mut counter = 0; let (count, ty) = reader.read_local_decl().map_err(to_wasm_error)?;
let (count, ty) = reader
.read_local_decl(&mut counter)
.map_err(to_wasm_error)?;
let ty = wptype_to_type(ty).map_err(to_compile_error)?; let ty = wptype_to_type(ty).map_err(to_compile_error)?;
let ty = type_to_llvm(&intrinsics, ty)?; let ty = type_to_llvm(&intrinsics, ty)?;
for _ in 0..count { for _ in 0..count {

View File

@@ -69,7 +69,7 @@ impl Compiler for SinglepassCompiler {
.into_iter() .into_iter()
.collect(); .collect();
let functions = function_body_inputs let functions = function_body_inputs
.into_iter() .iter()
.collect::<Vec<(LocalFunctionIndex, &FunctionBodyData<'_>)>>() .collect::<Vec<(LocalFunctionIndex, &FunctionBodyData<'_>)>>()
.par_iter() .par_iter()
.map(|(i, input)| { .map(|(i, input)| {
@@ -82,10 +82,7 @@ impl Compiler for SinglepassCompiler {
let mut locals = vec![]; let mut locals = vec![];
let num_locals = reader.read_local_count().map_err(to_compile_error)?; let num_locals = reader.read_local_count().map_err(to_compile_error)?;
for _ in 0..num_locals { for _ in 0..num_locals {
let mut counter = 0; let (count, ty) = reader.read_local_decl().map_err(to_compile_error)?;
let (count, ty) = reader
.read_local_decl(&mut counter)
.map_err(to_compile_error)?;
for _ in 0..count { for _ in 0..count {
locals.push(ty); locals.push(ty);
} }

View File

@@ -14,7 +14,7 @@ edition = "2018"
wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" }
wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4", default-features = false } wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4", default-features = false }
wasmparser = { version = "0.65", optional = true, default-features = false } wasmparser = { version = "0.65", optional = true, default-features = false }
target-lexicon = { version = "0.10", default-features = false } target-lexicon = { version = "0.11", default-features = false }
enumset = "1.0" enumset = "1.0"
hashbrown = { version = "0.8", optional = true } hashbrown = { version = "0.8", optional = true }
serde = { version = "1.0", features = ["derive"], optional = true } serde = { version = "1.0", features = ["derive"], optional = true }

View File

@@ -99,7 +99,7 @@ impl<'a> MiddlewareBinaryReader<'a> {
} }
/// Read a `(count, value_type)` declaration of local variables of the same type. /// Read a `(count, value_type)` declaration of local variables of the same type.
pub fn read_local_decl(&mut self, locals_total: &mut usize) -> WpResult<(u32, Type)> { pub fn read_local_decl(&mut self) -> WpResult<(u32, Type)> {
let count = self.state.inner.read_var_u32()?; let count = self.state.inner.read_var_u32()?;
let ty = self.state.inner.read_type()?; let ty = self.state.inner.read_type()?;
Ok((count, ty)) Ok((count, ty))

View File

@@ -81,7 +81,7 @@ pub fn link_module(
apply_relocation(body, r, allocated_functions, jt_offsets, allocated_sections); apply_relocation(body, r, allocated_functions, jt_offsets, allocated_sections);
} }
} }
for (i, function_relocs) in function_relocations.into_iter() { for (i, function_relocs) in function_relocations.iter() {
let fatptr: *const [VMFunctionBody] = allocated_functions[i].0; let fatptr: *const [VMFunctionBody] = allocated_functions[i].0;
let body = fatptr as *const VMFunctionBody as usize; let body = fatptr as *const VMFunctionBody as usize;
for r in function_relocs { for r in function_relocs {

View File

@@ -14,7 +14,7 @@ edition = "2018"
wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" } wasmer-types = { path = "../wasmer-types", version = "1.0.0-alpha4" }
wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4" } wasmer-compiler = { path = "../compiler", version = "1.0.0-alpha4" }
wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" } wasmer-vm = { path = "../vm", version = "1.0.0-alpha4" }
target-lexicon = { version = "0.10", default-features = false } target-lexicon = { version = "0.11", default-features = false }
# flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" } # flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" }
backtrace = "0.3" backtrace = "0.3"
rustc-demangle = "0.1" rustc-demangle = "0.1"

View File

@@ -32,44 +32,47 @@ pub enum TrapCode {
/// offset-guard pages. /// offset-guard pages.
HeapAccessOutOfBounds = 2, HeapAccessOutOfBounds = 2,
/// A `heap_addr` instruction was misaligned.
HeapMisaligned = 3,
/// Table Elements doesn't fit the table size. /// Table Elements doesn't fit the table size.
/// ///
/// This only can happen during instantiation. /// This only can happen during instantiation.
TableSetterOutOfBounds = 3, TableSetterOutOfBounds = 4,
/// A `table_addr` instruction detected an out-of-bounds error. /// A `table_addr` instruction detected an out-of-bounds error.
TableAccessOutOfBounds = 4, TableAccessOutOfBounds = 5,
/// Other bounds checking error. /// Other bounds checking error.
OutOfBounds = 5, OutOfBounds = 6,
/// Indirect call to a null table entry. /// Indirect call to a null table entry.
IndirectCallToNull = 6, IndirectCallToNull = 7,
/// Signature mismatch on indirect call. /// Signature mismatch on indirect call.
BadSignature = 7, BadSignature = 8,
/// An integer arithmetic operation caused an overflow. /// An integer arithmetic operation caused an overflow.
IntegerOverflow = 8, IntegerOverflow = 9,
/// An integer division by zero. /// An integer division by zero.
IntegerDivisionByZero = 9, IntegerDivisionByZero = 10,
/// Failed float-to-int conversion. /// Failed float-to-int conversion.
BadConversionToInteger = 10, BadConversionToInteger = 11,
/// Code that was supposed to have been unreachable was reached. /// Code that was supposed to have been unreachable was reached.
UnreachableCodeReached = 11, UnreachableCodeReached = 12,
/// Execution has potentially run too long and may be interrupted. /// Execution has potentially run too long and may be interrupted.
/// This trap is resumable. /// This trap is resumable.
Interrupt = 12, Interrupt = 13,
/// An atomic memory access was attempted with an unaligned pointer. /// An atomic memory access was attempted with an unaligned pointer.
UnalignedAtomic = 13, UnalignedAtomic = 14,
/// A trap indicating that the runtime was unable to allocate sufficient memory. /// A trap indicating that the runtime was unable to allocate sufficient memory.
VMOutOfMemory = 14, VMOutOfMemory = 15,
// /// A user-defined trap code. // /// A user-defined trap code.
// User(u16), // User(u16),
} }
@@ -81,6 +84,7 @@ impl TrapCode {
Self::StackOverflow => "call stack exhausted", Self::StackOverflow => "call stack exhausted",
Self::HeapSetterOutOfBounds => "memory out of bounds: data segment does not fit", Self::HeapSetterOutOfBounds => "memory out of bounds: data segment does not fit",
Self::HeapAccessOutOfBounds => "out of bounds memory access", Self::HeapAccessOutOfBounds => "out of bounds memory access",
Self::HeapMisaligned => "misaligned heap",
Self::TableSetterOutOfBounds => "table out of bounds: elements segment does not fit", Self::TableSetterOutOfBounds => "table out of bounds: elements segment does not fit",
Self::TableAccessOutOfBounds => "undefined element: out of bounds table access", Self::TableAccessOutOfBounds => "undefined element: out of bounds table access",
Self::OutOfBounds => "out of bounds", Self::OutOfBounds => "out of bounds",
@@ -104,6 +108,7 @@ impl Display for TrapCode {
Self::StackOverflow => "stk_ovf", Self::StackOverflow => "stk_ovf",
Self::HeapSetterOutOfBounds => "heap_set_oob", Self::HeapSetterOutOfBounds => "heap_set_oob",
Self::HeapAccessOutOfBounds => "heap_get_oob", Self::HeapAccessOutOfBounds => "heap_get_oob",
Self::HeapMisaligned => "heap_misaligned",
Self::TableSetterOutOfBounds => "table_set_oob", Self::TableSetterOutOfBounds => "table_set_oob",
Self::TableAccessOutOfBounds => "table_get_oob", Self::TableAccessOutOfBounds => "table_get_oob",
Self::OutOfBounds => "oob", Self::OutOfBounds => "oob",
@@ -131,6 +136,7 @@ impl FromStr for TrapCode {
"stk_ovf" => Ok(StackOverflow), "stk_ovf" => Ok(StackOverflow),
"heap_set_oob" => Ok(HeapSetterOutOfBounds), "heap_set_oob" => Ok(HeapSetterOutOfBounds),
"heap_get_oob" => Ok(HeapAccessOutOfBounds), "heap_get_oob" => Ok(HeapAccessOutOfBounds),
"heap_misaligned" => Ok(HeapMisaligned),
"table_set_oob" => Ok(TableSetterOutOfBounds), "table_set_oob" => Ok(TableSetterOutOfBounds),
"table_get_oob" => Ok(TableAccessOutOfBounds), "table_get_oob" => Ok(TableAccessOutOfBounds),
"oob" => Ok(OutOfBounds), "oob" => Ok(OutOfBounds),
@@ -154,10 +160,11 @@ mod tests {
use super::*; use super::*;
// Everything but user-defined codes. // Everything but user-defined codes.
const CODES: [TrapCode; 14] = [ const CODES: [TrapCode; 15] = [
TrapCode::StackOverflow, TrapCode::StackOverflow,
TrapCode::HeapSetterOutOfBounds, TrapCode::HeapSetterOutOfBounds,
TrapCode::HeapAccessOutOfBounds, TrapCode::HeapAccessOutOfBounds,
TrapCode::HeapMisaligned,
TrapCode::TableSetterOutOfBounds, TrapCode::TableSetterOutOfBounds,
TrapCode::TableAccessOutOfBounds, TrapCode::TableAccessOutOfBounds,
TrapCode::OutOfBounds, TrapCode::OutOfBounds,

View File

@@ -13,7 +13,7 @@ edition = "2018"
[dependencies] [dependencies]
# We use `cranelift-entity` here because it's a lightweight dependency and it contains # We use `cranelift-entity` here because it's a lightweight dependency and it contains
# some useful data structures # some useful data structures
cranelift-entity = "0.65" cranelift-entity = "0.67"
serde = { version = "1.0", features = ["derive"], optional = true, default-features = false } serde = { version = "1.0", features = ["derive"], optional = true, default-features = false }
[features] [features]

View File

@@ -2,17 +2,8 @@
singlepass::spec::multi_value singlepass::spec::multi_value
singlepass::spec::simd singlepass::spec::simd
## SIMD in Cranelift 0.65 is not fully supported ## SIMD in Cranelift 0.67 has a small bug
cranelift::spec::simd::simd_conversions
cranelift::spec::simd::simd_f32x4
cranelift::spec::simd::simd_f64x2
cranelift::spec::simd::simd_f64x2_arith cranelift::spec::simd::simd_f64x2_arith
cranelift::spec::simd::simd_i16x8_arith2
cranelift::spec::simd::simd_i32x4_arith2
cranelift::spec::simd::simd_i8x16_arith2
cranelift::spec::simd::simd_load
cranelift::spec::simd::simd_splat
singlepass on windows # Singlepass is not yet supported on Windows singlepass on windows # Singlepass is not yet supported on Windows

View File

@@ -6,7 +6,7 @@ publish = false
[dependencies] [dependencies]
anyhow = "1.0" anyhow = "1.0"
target-lexicon = "0.10" target-lexicon = "0.11"
[features] [features]
test-native = [] test-native = []