mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-07 13:18:20 +00:00
Update Cranelift to 0.82
This commit is contained in:
48
Cargo.lock
generated
48
Cargo.lock
generated
@@ -8,7 +8,7 @@ version = "0.17.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
|
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gimli 0.26.1",
|
"gimli",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -434,24 +434,24 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-bforest"
|
name = "cranelift-bforest"
|
||||||
version = "0.76.0"
|
version = "0.82.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7e6bea67967505247f54fa2c85cf4f6e0e31c4e5692c9b70e4ae58e339067333"
|
checksum = "d16922317bd7dd104d509a373887822caa0242fc1def00de66abb538db221db4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-entity",
|
"cranelift-entity",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-codegen"
|
name = "cranelift-codegen"
|
||||||
version = "0.76.0"
|
version = "0.82.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "48194035d2752bdd5bdae429e3ab88676e95f52a2b1355a5d4e809f9e39b1d74"
|
checksum = "8b80bf40380256307b68a3dcbe1b91cac92a533e212b5b635abc3e4525781a0a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-bforest",
|
"cranelift-bforest",
|
||||||
"cranelift-codegen-meta",
|
"cranelift-codegen-meta",
|
||||||
"cranelift-codegen-shared",
|
"cranelift-codegen-shared",
|
||||||
"cranelift-entity",
|
"cranelift-entity",
|
||||||
"gimli 0.25.0",
|
"gimli",
|
||||||
"hashbrown 0.9.1",
|
"hashbrown 0.9.1",
|
||||||
"log",
|
"log",
|
||||||
"regalloc",
|
"regalloc",
|
||||||
@@ -461,31 +461,30 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-codegen-meta"
|
name = "cranelift-codegen-meta"
|
||||||
version = "0.76.0"
|
version = "0.82.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "976efb22fcab4f2cd6bd4e9913764616a54d895c1a23530128d04e03633c555f"
|
checksum = "703d0ed7d3bc6c7a814ca12858175bf4e93167a3584127858c686e4b5dd6e432"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-codegen-shared",
|
"cranelift-codegen-shared",
|
||||||
"cranelift-entity",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-codegen-shared"
|
name = "cranelift-codegen-shared"
|
||||||
version = "0.76.0"
|
version = "0.82.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9dabb5fe66e04d4652e434195b45ae65b5c8172d520247b8f66d8df42b2b45dc"
|
checksum = "80f52311e1c90de12dcf8c4b9999c6ebfd1ed360373e88c357160936844511f6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-entity"
|
name = "cranelift-entity"
|
||||||
version = "0.76.0"
|
version = "0.82.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3329733e4d4b8e91c809efcaa4faee80bf66f20164e3dd16d707346bd3494799"
|
checksum = "66bc82ef522c1f643baf7d4d40b7c52643ee4549d8960b0e6a047daacb83f897"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-frontend"
|
name = "cranelift-frontend"
|
||||||
version = "0.76.0"
|
version = "0.82.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "279afcc0d3e651b773f94837c3d581177b348c8d69e928104b2e9fccb226f921"
|
checksum = "3cc35e4251864b17515845ba47447bca88fec9ca1a4186b19fe42526e36140e8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-codegen",
|
"cranelift-codegen",
|
||||||
"hashbrown 0.9.1",
|
"hashbrown 0.9.1",
|
||||||
@@ -960,17 +959,6 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "gimli"
|
|
||||||
version = "0.25.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7"
|
|
||||||
dependencies = [
|
|
||||||
"fallible-iterator",
|
|
||||||
"indexmap",
|
|
||||||
"stable_deref_trait",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.26.1"
|
version = "0.26.1"
|
||||||
@@ -1800,9 +1788,9 @@ checksum = "a0d51660a68078997855ba5602f73ab3a5031bd7ad480a9d4c90fbbf04e1fff0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regalloc"
|
name = "regalloc"
|
||||||
version = "0.0.31"
|
version = "0.0.34"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "571f7f397d61c4755285cd37853fe8e03271c243424a907415909379659381c5"
|
checksum = "62446b1d3ebf980bdc68837700af1d77b37bc430e524bf95319c6eada2a4cc02"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
@@ -2913,7 +2901,7 @@ dependencies = [
|
|||||||
"cranelift-codegen",
|
"cranelift-codegen",
|
||||||
"cranelift-entity",
|
"cranelift-entity",
|
||||||
"cranelift-frontend",
|
"cranelift-frontend",
|
||||||
"gimli 0.25.0",
|
"gimli",
|
||||||
"hashbrown 0.11.2",
|
"hashbrown 0.11.2",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"loupe",
|
"loupe",
|
||||||
@@ -2957,7 +2945,7 @@ dependencies = [
|
|||||||
"byteorder",
|
"byteorder",
|
||||||
"dynasm",
|
"dynasm",
|
||||||
"dynasmrt",
|
"dynasmrt",
|
||||||
"gimli 0.26.1",
|
"gimli",
|
||||||
"hashbrown 0.11.2",
|
"hashbrown 0.11.2",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"loupe",
|
"loupe",
|
||||||
|
|||||||
@@ -15,20 +15,20 @@ edition = "2018"
|
|||||||
wasmer-compiler = { path = "../compiler", version = "=2.2.1", features = ["translator"], default-features = false }
|
wasmer-compiler = { path = "../compiler", version = "=2.2.1", features = ["translator"], default-features = false }
|
||||||
wasmer-vm = { path = "../vm", version = "=2.2.1" }
|
wasmer-vm = { path = "../vm", version = "=2.2.1" }
|
||||||
wasmer-types = { path = "../types", version = "=2.2.1", default-features = false, features = ["std"] }
|
wasmer-types = { path = "../types", version = "=2.2.1", default-features = false, features = ["std"] }
|
||||||
cranelift-entity = { version = "0.76", default-features = false }
|
cranelift-entity = { version = "0.82", default-features = false }
|
||||||
cranelift-codegen = { version = "0.76", default-features = false, features = ["x86", "arm64"] }
|
cranelift-codegen = { version = "0.82", default-features = false, features = ["x86", "arm64"] }
|
||||||
cranelift-frontend = { version = "0.76", default-features = false }
|
cranelift-frontend = { version = "0.82", default-features = false }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
hashbrown = { version = "0.11", optional = true }
|
hashbrown = { version = "0.11", optional = true }
|
||||||
rayon = "1.5"
|
rayon = "1.5"
|
||||||
more-asserts = "0.2"
|
more-asserts = "0.2"
|
||||||
gimli = { version = "0.25", optional = true }
|
gimli = { version = "0.26", optional = true }
|
||||||
smallvec = "1.6"
|
smallvec = "1.6"
|
||||||
loupe = "0.1"
|
loupe = "0.1"
|
||||||
target-lexicon = { version = "0.12.2", default-features = false }
|
target-lexicon = { version = "0.12.2", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
cranelift-codegen = { version = "0.76", features = ["all-arch"] }
|
cranelift-codegen = { version = "0.82", features = ["all-arch"] }
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
// This file contains code from external sources.
|
// This file contains code from external sources.
|
||||||
// Attributions: https://github.com/wasmerio/wasmer/blob/master/ATTRIBUTIONS.md
|
// Attributions: https://github.com/wasmerio/wasmer/blob/master/ATTRIBUTIONS.md
|
||||||
|
|
||||||
|
use cranelift_codegen::Context;
|
||||||
use cranelift_codegen::MachSrcLoc;
|
use cranelift_codegen::MachSrcLoc;
|
||||||
use cranelift_codegen::{isa, Context};
|
|
||||||
use wasmer_compiler::{wasmparser::Range, FunctionAddressMap, InstructionAddressMap, SourceLoc};
|
use wasmer_compiler::{wasmparser::Range, FunctionAddressMap, InstructionAddressMap, SourceLoc};
|
||||||
|
|
||||||
pub fn get_function_address_map<'data>(
|
pub fn get_function_address_map<'data>(
|
||||||
context: &Context,
|
context: &Context,
|
||||||
range: Range,
|
range: Range,
|
||||||
body_len: usize,
|
body_len: usize,
|
||||||
isa: &dyn isa::TargetIsa,
|
|
||||||
) -> FunctionAddressMap {
|
) -> FunctionAddressMap {
|
||||||
let mut instructions = Vec::new();
|
let mut instructions = Vec::new();
|
||||||
|
|
||||||
if let Some(ref mcr) = &context.mach_compile_result {
|
|
||||||
// New-style backend: we have a `MachCompileResult` that will give us `MachSrcLoc` mapping
|
// New-style backend: we have a `MachCompileResult` that will give us `MachSrcLoc` mapping
|
||||||
// tuples.
|
// tuples.
|
||||||
|
let mcr = context.mach_compile_result.as_ref().unwrap();
|
||||||
for &MachSrcLoc { start, end, loc } in mcr.buffer.get_srclocs_sorted() {
|
for &MachSrcLoc { start, end, loc } in mcr.buffer.get_srclocs_sorted() {
|
||||||
instructions.push(InstructionAddressMap {
|
instructions.push(InstructionAddressMap {
|
||||||
srcloc: SourceLoc::new(loc.bits()),
|
srcloc: SourceLoc::new(loc.bits()),
|
||||||
@@ -23,23 +22,6 @@ pub fn get_function_address_map<'data>(
|
|||||||
code_len: (end - start) as usize,
|
code_len: (end - start) as usize,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
let func = &context.func;
|
|
||||||
let mut blocks = func.layout.blocks().collect::<Vec<_>>();
|
|
||||||
blocks.sort_by_key(|block| func.offsets[*block]); // Ensure inst offsets always increase
|
|
||||||
|
|
||||||
let encinfo = isa.encoding_info();
|
|
||||||
for block in blocks {
|
|
||||||
for (offset, inst, size) in func.inst_offsets(block, &encinfo) {
|
|
||||||
let srcloc = func.srclocs[inst];
|
|
||||||
instructions.push(InstructionAddressMap {
|
|
||||||
srcloc: SourceLoc::new(srcloc.bits()),
|
|
||||||
code_offset: offset as usize,
|
|
||||||
code_len: size as usize,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate artificial srcloc for function start/end to identify boundary
|
// Generate artificial srcloc for function start/end to identify boundary
|
||||||
// within module. Similar to FuncTranslator::cur_srcloc(): it will wrap around
|
// within module. Similar to FuncTranslator::cur_srcloc(): it will wrap around
|
||||||
|
|||||||
@@ -5,32 +5,35 @@ use crate::config::Cranelift;
|
|||||||
#[cfg(feature = "unwind")]
|
#[cfg(feature = "unwind")]
|
||||||
use crate::dwarf::WriterRelocate;
|
use crate::dwarf::WriterRelocate;
|
||||||
use crate::func_environ::{get_function_name, FuncEnvironment};
|
use crate::func_environ::{get_function_name, FuncEnvironment};
|
||||||
use crate::sink::{RelocSink, TrapSink};
|
|
||||||
use crate::trampoline::{
|
use crate::trampoline::{
|
||||||
make_trampoline_dynamic_function, make_trampoline_function_call, FunctionBuilderContext,
|
make_trampoline_dynamic_function, make_trampoline_function_call, FunctionBuilderContext,
|
||||||
};
|
};
|
||||||
use crate::translator::{
|
use crate::translator::{
|
||||||
compiled_function_unwind_info, signature_to_cranelift_ir, transform_jump_table,
|
compiled_function_unwind_info, irlibcall_to_libcall, irreloc_to_relocationkind,
|
||||||
CraneliftUnwindInfo, FuncTranslator,
|
signature_to_cranelift_ir, CraneliftUnwindInfo, FuncTranslator,
|
||||||
};
|
};
|
||||||
use cranelift_codegen::ir;
|
use cranelift_codegen::ir::ExternalName;
|
||||||
use cranelift_codegen::print_errors::pretty_error;
|
use cranelift_codegen::print_errors::pretty_error;
|
||||||
use cranelift_codegen::{binemit, Context};
|
use cranelift_codegen::{ir, MachReloc};
|
||||||
|
use cranelift_codegen::{Context, MachTrap};
|
||||||
#[cfg(feature = "unwind")]
|
#[cfg(feature = "unwind")]
|
||||||
use gimli::write::{Address, EhFrame, FrameTable};
|
use gimli::write::{Address, EhFrame, FrameTable};
|
||||||
use loupe::MemoryUsage;
|
use loupe::MemoryUsage;
|
||||||
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wasmer_compiler::CompileError;
|
use wasmer_compiler::{
|
||||||
use wasmer_compiler::{CallingConvention, ModuleTranslationState, Target};
|
CallingConvention, ModuleTranslationState, RelocationTarget, Target, TrapInformation,
|
||||||
|
};
|
||||||
use wasmer_compiler::{
|
use wasmer_compiler::{
|
||||||
Compilation, CompileModuleInfo, CompiledFunction, CompiledFunctionFrameInfo,
|
Compilation, CompileModuleInfo, CompiledFunction, CompiledFunctionFrameInfo,
|
||||||
CompiledFunctionUnwindInfo, Compiler, Dwarf, FunctionBinaryReader, FunctionBody,
|
CompiledFunctionUnwindInfo, Compiler, Dwarf, FunctionBinaryReader, FunctionBody,
|
||||||
FunctionBodyData, MiddlewareBinaryReader, ModuleMiddleware, ModuleMiddlewareChain,
|
FunctionBodyData, MiddlewareBinaryReader, ModuleMiddleware, ModuleMiddlewareChain,
|
||||||
SectionIndex,
|
SectionIndex,
|
||||||
};
|
};
|
||||||
|
use wasmer_compiler::{CompileError, Relocation};
|
||||||
use wasmer_types::entity::{EntityRef, PrimaryMap};
|
use wasmer_types::entity::{EntityRef, PrimaryMap};
|
||||||
use wasmer_types::{FunctionIndex, LocalFunctionIndex, SignatureIndex};
|
use wasmer_types::{FunctionIndex, LocalFunctionIndex, ModuleInfo, SignatureIndex};
|
||||||
|
use wasmer_vm::TrapCode;
|
||||||
|
|
||||||
/// A compiler that compiles a WebAssembly module with Cranelift, translating the Wasm to Cranelift IR,
|
/// A compiler that compiles a WebAssembly module with Cranelift, translating the Wasm to Cranelift IR,
|
||||||
/// optimizing it and then translating to assembly.
|
/// optimizing it and then translating to assembly.
|
||||||
@@ -66,7 +69,10 @@ impl Compiler for CraneliftCompiler {
|
|||||||
module_translation_state: &ModuleTranslationState,
|
module_translation_state: &ModuleTranslationState,
|
||||||
function_body_inputs: PrimaryMap<LocalFunctionIndex, FunctionBodyData<'_>>,
|
function_body_inputs: PrimaryMap<LocalFunctionIndex, FunctionBodyData<'_>>,
|
||||||
) -> Result<Compilation, CompileError> {
|
) -> Result<Compilation, CompileError> {
|
||||||
let isa = self.config().isa(target);
|
let isa = self
|
||||||
|
.config()
|
||||||
|
.isa(target)
|
||||||
|
.map_err(|error| CompileError::Codegen(error.to_string()))?;
|
||||||
let frontend_config = isa.frontend_config();
|
let frontend_config = isa.frontend_config();
|
||||||
let memory_styles = &compile_info.memory_styles;
|
let memory_styles = &compile_info.memory_styles;
|
||||||
let table_styles = &compile_info.table_styles;
|
let table_styles = &compile_info.table_styles;
|
||||||
@@ -139,20 +145,24 @@ 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 trap_sink = TrapSink::new();
|
|
||||||
let mut stackmap_sink = binemit::NullStackMapSink {};
|
|
||||||
context
|
context
|
||||||
.compile_and_emit(
|
.compile_and_emit(&*isa, &mut code_buf)
|
||||||
&*isa,
|
.map_err(|error| CompileError::Codegen(pretty_error(&context.func, error)))?;
|
||||||
&mut code_buf,
|
|
||||||
&mut reloc_sink,
|
let result = context.mach_compile_result.as_ref().unwrap();
|
||||||
&mut trap_sink,
|
let func_relocs = result
|
||||||
&mut stackmap_sink,
|
.buffer
|
||||||
)
|
.relocs()
|
||||||
.map_err(|error| {
|
.into_iter()
|
||||||
CompileError::Codegen(pretty_error(&context.func, Some(&*isa), error))
|
.map(|r| mach_reloc_to_reloc(module, r))
|
||||||
})?;
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let traps = result
|
||||||
|
.buffer
|
||||||
|
.traps()
|
||||||
|
.into_iter()
|
||||||
|
.map(mach_trap_to_trap)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let (unwind_info, fde) = match compiled_function_unwind_info(&*isa, &context)? {
|
let (unwind_info, fde) = match compiled_function_unwind_info(&*isa, &context)? {
|
||||||
#[cfg(feature = "unwind")]
|
#[cfg(feature = "unwind")]
|
||||||
@@ -182,10 +192,7 @@ impl Compiler for CraneliftCompiler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let range = reader.range();
|
let range = reader.range();
|
||||||
let address_map = get_function_address_map(&context, range, code_buf.len(), &*isa);
|
let address_map = get_function_address_map(&context, range, code_buf.len());
|
||||||
|
|
||||||
// We transform the Cranelift JumpTable's into compiler JumpTables
|
|
||||||
let func_jt_offsets = transform_jump_table(context.func.jt_offsets);
|
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
CompiledFunction {
|
CompiledFunction {
|
||||||
@@ -193,12 +200,8 @@ impl Compiler for CraneliftCompiler {
|
|||||||
body: code_buf,
|
body: code_buf,
|
||||||
unwind_info,
|
unwind_info,
|
||||||
},
|
},
|
||||||
jt_offsets: func_jt_offsets,
|
relocations: func_relocs,
|
||||||
relocations: reloc_sink.func_relocs,
|
frame_info: CompiledFunctionFrameInfo { address_map, traps },
|
||||||
frame_info: CompiledFunctionFrameInfo {
|
|
||||||
address_map,
|
|
||||||
traps: trap_sink.traps,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
fde,
|
fde,
|
||||||
))
|
))
|
||||||
@@ -262,3 +265,63 @@ impl Compiler for CraneliftCompiler {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mach_reloc_to_reloc(module: &ModuleInfo, reloc: &MachReloc) -> Relocation {
|
||||||
|
let &MachReloc {
|
||||||
|
offset,
|
||||||
|
srcloc: _,
|
||||||
|
kind,
|
||||||
|
ref name,
|
||||||
|
addend,
|
||||||
|
} = reloc;
|
||||||
|
let reloc_target = if let ExternalName::User { namespace, index } = *name {
|
||||||
|
debug_assert_eq!(namespace, 0);
|
||||||
|
RelocationTarget::LocalFunc(
|
||||||
|
module
|
||||||
|
.local_func_index(FunctionIndex::from_u32(index))
|
||||||
|
.expect("The provided function should be local"),
|
||||||
|
)
|
||||||
|
} else if let ExternalName::LibCall(libcall) = *name {
|
||||||
|
RelocationTarget::LibCall(irlibcall_to_libcall(libcall))
|
||||||
|
} else {
|
||||||
|
panic!("unrecognized external name")
|
||||||
|
};
|
||||||
|
Relocation {
|
||||||
|
kind: irreloc_to_relocationkind(kind),
|
||||||
|
reloc_target,
|
||||||
|
offset,
|
||||||
|
addend,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mach_trap_to_trap(trap: &MachTrap) -> TrapInformation {
|
||||||
|
let &MachTrap {
|
||||||
|
offset,
|
||||||
|
srcloc: _,
|
||||||
|
code,
|
||||||
|
} = trap;
|
||||||
|
TrapInformation {
|
||||||
|
code_offset: offset,
|
||||||
|
trap_code: translate_ir_trapcode(code),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Translates the Cranelift IR TrapCode into generic Trap Code
|
||||||
|
fn translate_ir_trapcode(trap: ir::TrapCode) -> TrapCode {
|
||||||
|
match trap {
|
||||||
|
ir::TrapCode::StackOverflow => TrapCode::StackOverflow,
|
||||||
|
ir::TrapCode::HeapOutOfBounds => TrapCode::HeapAccessOutOfBounds,
|
||||||
|
ir::TrapCode::HeapMisaligned => TrapCode::HeapMisaligned,
|
||||||
|
ir::TrapCode::TableOutOfBounds => TrapCode::TableAccessOutOfBounds,
|
||||||
|
ir::TrapCode::IndirectCallToNull => TrapCode::IndirectCallToNull,
|
||||||
|
ir::TrapCode::BadSignature => TrapCode::BadSignature,
|
||||||
|
ir::TrapCode::IntegerOverflow => TrapCode::IntegerOverflow,
|
||||||
|
ir::TrapCode::IntegerDivisionByZero => TrapCode::IntegerDivisionByZero,
|
||||||
|
ir::TrapCode::BadConversionToInteger => TrapCode::BadConversionToInteger,
|
||||||
|
ir::TrapCode::UnreachableCodeReached => TrapCode::UnreachableCodeReached,
|
||||||
|
ir::TrapCode::Interrupt => unimplemented!("Interrupts not supported"),
|
||||||
|
ir::TrapCode::User(_user_code) => unimplemented!("User trap code not supported"),
|
||||||
|
// ir::TrapCode::Interrupt => TrapCode::Interrupt,
|
||||||
|
// ir::TrapCode::User(user_code) => TrapCode::User(user_code),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use crate::compiler::CraneliftCompiler;
|
use crate::compiler::CraneliftCompiler;
|
||||||
use cranelift_codegen::isa::{lookup, TargetIsa};
|
use cranelift_codegen::isa::{lookup, TargetIsa};
|
||||||
use cranelift_codegen::settings::{self, Configurable};
|
use cranelift_codegen::settings::{self, Configurable};
|
||||||
|
use cranelift_codegen::CodegenResult;
|
||||||
use loupe::MemoryUsage;
|
use loupe::MemoryUsage;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wasmer_compiler::{
|
use wasmer_compiler::{
|
||||||
@@ -67,7 +68,7 @@ impl Cranelift {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generates the ISA for the provided target
|
/// Generates the ISA for the provided target
|
||||||
pub fn isa(&self, target: &Target) -> Box<dyn TargetIsa> {
|
pub fn isa(&self, target: &Target) -> CodegenResult<Box<dyn TargetIsa>> {
|
||||||
let mut builder =
|
let mut builder =
|
||||||
lookup(target.triple().clone()).expect("construct Cranelift ISA for triple");
|
lookup(target.triple().clone()).expect("construct Cranelift ISA for triple");
|
||||||
// Cpu Features
|
// Cpu Features
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ mod debug;
|
|||||||
#[cfg(feature = "unwind")]
|
#[cfg(feature = "unwind")]
|
||||||
mod dwarf;
|
mod dwarf;
|
||||||
mod func_environ;
|
mod func_environ;
|
||||||
mod sink;
|
|
||||||
mod trampoline;
|
mod trampoline;
|
||||||
mod translator;
|
mod translator;
|
||||||
|
|
||||||
|
|||||||
@@ -1,132 +0,0 @@
|
|||||||
//! Support for compiling with Cranelift.
|
|
||||||
|
|
||||||
use crate::translator::{irlibcall_to_libcall, irreloc_to_relocationkind};
|
|
||||||
use cranelift_codegen::binemit;
|
|
||||||
use cranelift_codegen::ir::{self, ExternalName};
|
|
||||||
use cranelift_entity::EntityRef as CraneliftEntityRef;
|
|
||||||
use wasmer_compiler::{JumpTable, Relocation, RelocationTarget, TrapInformation};
|
|
||||||
use wasmer_types::entity::EntityRef;
|
|
||||||
use wasmer_types::{FunctionIndex, LocalFunctionIndex, ModuleInfo};
|
|
||||||
use wasmer_vm::TrapCode;
|
|
||||||
|
|
||||||
/// Implementation of a relocation sink that just saves all the information for later
|
|
||||||
pub(crate) struct RelocSink<'a> {
|
|
||||||
module: &'a ModuleInfo,
|
|
||||||
|
|
||||||
/// Current function index.
|
|
||||||
local_func_index: LocalFunctionIndex,
|
|
||||||
|
|
||||||
/// Relocations recorded for the function.
|
|
||||||
pub func_relocs: Vec<Relocation>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> binemit::RelocSink for RelocSink<'a> {
|
|
||||||
fn reloc_external(
|
|
||||||
&mut self,
|
|
||||||
offset: binemit::CodeOffset,
|
|
||||||
_source_loc: ir::SourceLoc,
|
|
||||||
reloc: binemit::Reloc,
|
|
||||||
name: &ExternalName,
|
|
||||||
addend: binemit::Addend,
|
|
||||||
) {
|
|
||||||
let reloc_target = if let ExternalName::User { namespace, index } = *name {
|
|
||||||
debug_assert_eq!(namespace, 0);
|
|
||||||
RelocationTarget::LocalFunc(
|
|
||||||
self.module
|
|
||||||
.local_func_index(FunctionIndex::from_u32(index))
|
|
||||||
.expect("The provided function should be local"),
|
|
||||||
)
|
|
||||||
} else if let ExternalName::LibCall(libcall) = *name {
|
|
||||||
RelocationTarget::LibCall(irlibcall_to_libcall(libcall))
|
|
||||||
} else {
|
|
||||||
panic!("unrecognized external name")
|
|
||||||
};
|
|
||||||
self.func_relocs.push(Relocation {
|
|
||||||
kind: irreloc_to_relocationkind(reloc),
|
|
||||||
reloc_target,
|
|
||||||
offset,
|
|
||||||
addend,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reloc_constant(
|
|
||||||
&mut self,
|
|
||||||
_code_offset: binemit::CodeOffset,
|
|
||||||
_reloc: binemit::Reloc,
|
|
||||||
_constant_offset: ir::ConstantOffset,
|
|
||||||
) {
|
|
||||||
// Do nothing for now: cranelift emits constant data after the function code and also emits
|
|
||||||
// function code with correct relative offsets to the constant data.
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reloc_jt(&mut self, offset: binemit::CodeOffset, reloc: binemit::Reloc, jt: ir::JumpTable) {
|
|
||||||
self.func_relocs.push(Relocation {
|
|
||||||
kind: irreloc_to_relocationkind(reloc),
|
|
||||||
reloc_target: RelocationTarget::JumpTable(
|
|
||||||
self.local_func_index,
|
|
||||||
JumpTable::new(jt.index()),
|
|
||||||
),
|
|
||||||
offset,
|
|
||||||
addend: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> RelocSink<'a> {
|
|
||||||
/// Return a new `RelocSink` instance.
|
|
||||||
pub fn new(module: &'a ModuleInfo, func_index: FunctionIndex) -> Self {
|
|
||||||
let local_func_index = module
|
|
||||||
.local_func_index(func_index)
|
|
||||||
.expect("The provided function should be local");
|
|
||||||
Self {
|
|
||||||
module,
|
|
||||||
local_func_index,
|
|
||||||
func_relocs: Vec::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct TrapSink {
|
|
||||||
pub traps: Vec<TrapInformation>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TrapSink {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self { traps: Vec::new() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl binemit::TrapSink for TrapSink {
|
|
||||||
fn trap(
|
|
||||||
&mut self,
|
|
||||||
code_offset: binemit::CodeOffset,
|
|
||||||
_source_loc: ir::SourceLoc,
|
|
||||||
trap_code: ir::TrapCode,
|
|
||||||
) {
|
|
||||||
self.traps.push(TrapInformation {
|
|
||||||
code_offset,
|
|
||||||
// TODO: Translate properly environment Trapcode into cranelift IR
|
|
||||||
trap_code: translate_ir_trapcode(trap_code),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Translates the Cranelift IR TrapCode into generic Trap Code
|
|
||||||
fn translate_ir_trapcode(trap: ir::TrapCode) -> TrapCode {
|
|
||||||
match trap {
|
|
||||||
ir::TrapCode::StackOverflow => TrapCode::StackOverflow,
|
|
||||||
ir::TrapCode::HeapOutOfBounds => TrapCode::HeapAccessOutOfBounds,
|
|
||||||
ir::TrapCode::HeapMisaligned => TrapCode::HeapMisaligned,
|
|
||||||
ir::TrapCode::TableOutOfBounds => TrapCode::TableAccessOutOfBounds,
|
|
||||||
ir::TrapCode::IndirectCallToNull => TrapCode::IndirectCallToNull,
|
|
||||||
ir::TrapCode::BadSignature => TrapCode::BadSignature,
|
|
||||||
ir::TrapCode::IntegerOverflow => TrapCode::IntegerOverflow,
|
|
||||||
ir::TrapCode::IntegerDivisionByZero => TrapCode::IntegerDivisionByZero,
|
|
||||||
ir::TrapCode::BadConversionToInteger => TrapCode::BadConversionToInteger,
|
|
||||||
ir::TrapCode::UnreachableCodeReached => TrapCode::UnreachableCodeReached,
|
|
||||||
ir::TrapCode::Interrupt => unimplemented!("Interrupts not supported"),
|
|
||||||
ir::TrapCode::User(_user_code) => unimplemented!("User trap code not supported"),
|
|
||||||
// ir::TrapCode::Interrupt => TrapCode::Interrupt,
|
|
||||||
// ir::TrapCode::User(user_code) => TrapCode::User(user_code),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,15 +3,14 @@
|
|||||||
|
|
||||||
//! A trampoline generator for calling dynamic host functions from Wasm.
|
//! A trampoline generator for calling dynamic host functions from Wasm.
|
||||||
|
|
||||||
use super::binemit::TrampolineRelocSink;
|
|
||||||
use crate::translator::{compiled_function_unwind_info, signature_to_cranelift_ir};
|
use crate::translator::{compiled_function_unwind_info, signature_to_cranelift_ir};
|
||||||
|
use cranelift_codegen::ir;
|
||||||
use cranelift_codegen::ir::{
|
use cranelift_codegen::ir::{
|
||||||
ExternalName, Function, InstBuilder, MemFlags, StackSlotData, StackSlotKind,
|
ExternalName, Function, InstBuilder, MemFlags, StackSlotData, StackSlotKind,
|
||||||
};
|
};
|
||||||
use cranelift_codegen::isa::TargetIsa;
|
use cranelift_codegen::isa::TargetIsa;
|
||||||
use cranelift_codegen::print_errors::pretty_error;
|
use cranelift_codegen::print_errors::pretty_error;
|
||||||
use cranelift_codegen::Context;
|
use cranelift_codegen::Context;
|
||||||
use cranelift_codegen::{binemit, ir};
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
@@ -108,18 +107,9 @@ 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 trap_sink = binemit::NullTrapSink {};
|
|
||||||
let mut stackmap_sink = binemit::NullStackMapSink {};
|
|
||||||
context
|
context
|
||||||
.compile_and_emit(
|
.compile_and_emit(isa, &mut code_buf)
|
||||||
isa,
|
.map_err(|error| CompileError::Codegen(pretty_error(&context.func, error)))?;
|
||||||
&mut code_buf,
|
|
||||||
&mut reloc_sink,
|
|
||||||
&mut trap_sink,
|
|
||||||
&mut stackmap_sink,
|
|
||||||
)
|
|
||||||
.map_err(|error| CompileError::Codegen(pretty_error(&context.func, Some(isa), error)))?;
|
|
||||||
|
|
||||||
let unwind_info = compiled_function_unwind_info(isa, &context)?.maybe_into_to_windows_unwind();
|
let unwind_info = compiled_function_unwind_info(isa, &context)?.maybe_into_to_windows_unwind();
|
||||||
|
|
||||||
|
|||||||
@@ -8,15 +8,12 @@
|
|||||||
//! let my_func = instance.exports.get("func");
|
//! let my_func = instance.exports.get("func");
|
||||||
//! my_func.call([1, 2])
|
//! my_func.call([1, 2])
|
||||||
//! ```
|
//! ```
|
||||||
use super::binemit::TrampolineRelocSink;
|
use crate::translator::{compiled_function_unwind_info, signature_to_cranelift_ir};
|
||||||
use crate::translator::{
|
use cranelift_codegen::ir;
|
||||||
compiled_function_unwind_info, signature_to_cranelift_ir, /*transform_jump_table, */
|
|
||||||
};
|
|
||||||
use cranelift_codegen::ir::InstBuilder;
|
use cranelift_codegen::ir::InstBuilder;
|
||||||
use cranelift_codegen::isa::TargetIsa;
|
use cranelift_codegen::isa::TargetIsa;
|
||||||
use cranelift_codegen::print_errors::pretty_error;
|
use cranelift_codegen::print_errors::pretty_error;
|
||||||
use cranelift_codegen::Context;
|
use cranelift_codegen::Context;
|
||||||
use cranelift_codegen::{binemit, ir};
|
|
||||||
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
|
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use wasmer_compiler::{CompileError, FunctionBody};
|
use wasmer_compiler::{CompileError, FunctionBody};
|
||||||
@@ -106,25 +103,15 @@ 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 trap_sink = binemit::NullTrapSink {};
|
|
||||||
let mut stackmap_sink = binemit::NullStackMapSink {};
|
|
||||||
|
|
||||||
context
|
context
|
||||||
.compile_and_emit(
|
.compile_and_emit(isa, &mut code_buf)
|
||||||
isa,
|
.map_err(|error| CompileError::Codegen(pretty_error(&context.func, error)))?;
|
||||||
&mut code_buf,
|
|
||||||
&mut reloc_sink,
|
|
||||||
&mut trap_sink,
|
|
||||||
&mut stackmap_sink,
|
|
||||||
)
|
|
||||||
.map_err(|error| CompileError::Codegen(pretty_error(&context.func, Some(isa), error)))?;
|
|
||||||
|
|
||||||
let unwind_info = compiled_function_unwind_info(isa, &context)?.maybe_into_to_windows_unwind();
|
let unwind_info = compiled_function_unwind_info(isa, &context)?.maybe_into_to_windows_unwind();
|
||||||
|
|
||||||
Ok(FunctionBody {
|
Ok(FunctionBody {
|
||||||
body: code_buf,
|
body: code_buf,
|
||||||
unwind_info,
|
unwind_info,
|
||||||
// jt_offsets: transform_jump_table(context.func.jt_offsets),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,43 +9,3 @@ pub use self::function_call::make_trampoline_function_call;
|
|||||||
pub use cranelift_codegen::print_errors::pretty_error;
|
pub use cranelift_codegen::print_errors::pretty_error;
|
||||||
pub use cranelift_codegen::Context;
|
pub use cranelift_codegen::Context;
|
||||||
pub use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
|
pub use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
|
||||||
|
|
||||||
pub mod binemit {
|
|
||||||
pub use cranelift_codegen::binemit::NullTrapSink;
|
|
||||||
pub use cranelift_codegen::binemit::{CodeOffset, NullStackMapSink, TrapSink};
|
|
||||||
|
|
||||||
use cranelift_codegen::{binemit, ir};
|
|
||||||
|
|
||||||
/// We don't expect trampoline compilation to produce any relocations, so
|
|
||||||
/// this `RelocSink` just asserts that it doesn't recieve any.
|
|
||||||
pub struct TrampolineRelocSink {}
|
|
||||||
|
|
||||||
impl binemit::RelocSink for TrampolineRelocSink {
|
|
||||||
fn reloc_external(
|
|
||||||
&mut self,
|
|
||||||
_offset: binemit::CodeOffset,
|
|
||||||
_source_loc: ir::SourceLoc,
|
|
||||||
_reloc: binemit::Reloc,
|
|
||||||
_name: &ir::ExternalName,
|
|
||||||
_addend: binemit::Addend,
|
|
||||||
) {
|
|
||||||
panic!("trampoline compilation should not produce external symbol relocs");
|
|
||||||
}
|
|
||||||
fn reloc_constant(
|
|
||||||
&mut self,
|
|
||||||
_code_offset: binemit::CodeOffset,
|
|
||||||
_reloc: binemit::Reloc,
|
|
||||||
_constant_offset: ir::ConstantOffset,
|
|
||||||
) {
|
|
||||||
panic!("trampoline compilation should not produce constant relocs");
|
|
||||||
}
|
|
||||||
fn reloc_jt(
|
|
||||||
&mut self,
|
|
||||||
_offset: binemit::CodeOffset,
|
|
||||||
_reloc: binemit::Reloc,
|
|
||||||
_jt: ir::JumpTable,
|
|
||||||
) {
|
|
||||||
panic!("trampoline compilation should not produce jump table relocs");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1868,14 +1868,43 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
let a = pop1_with_bitcast(state, I32X4, builder);
|
let a = pop1_with_bitcast(state, I32X4, builder);
|
||||||
state.push1(builder.ins().fcvt_low_from_sint(F64X2, a));
|
state.push1(builder.ins().fcvt_low_from_sint(F64X2, a));
|
||||||
}
|
}
|
||||||
|
Operator::F64x2ConvertLowI32x4U => {
|
||||||
|
let a = pop1_with_bitcast(state, I32X4, builder);
|
||||||
|
let widened_a = builder.ins().uwiden_low(a);
|
||||||
|
state.push1(builder.ins().fcvt_from_uint(F64X2, widened_a));
|
||||||
|
}
|
||||||
|
Operator::F64x2PromoteLowF32x4 => {
|
||||||
|
let a = pop1_with_bitcast(state, F32X4, builder);
|
||||||
|
state.push1(builder.ins().fvpromote_low(a));
|
||||||
|
}
|
||||||
|
Operator::F32x4DemoteF64x2Zero => {
|
||||||
|
let a = pop1_with_bitcast(state, F64X2, builder);
|
||||||
|
state.push1(builder.ins().fvdemote(a));
|
||||||
|
}
|
||||||
Operator::I32x4TruncSatF32x4S => {
|
Operator::I32x4TruncSatF32x4S => {
|
||||||
let a = pop1_with_bitcast(state, F32X4, builder);
|
let a = pop1_with_bitcast(state, F32X4, builder);
|
||||||
state.push1(builder.ins().fcvt_to_sint_sat(I32X4, a))
|
state.push1(builder.ins().fcvt_to_sint_sat(I32X4, a))
|
||||||
}
|
}
|
||||||
|
Operator::I32x4TruncSatF64x2SZero => {
|
||||||
|
let a = pop1_with_bitcast(state, F64X2, builder);
|
||||||
|
let converted_a = builder.ins().fcvt_to_sint_sat(I64X2, a);
|
||||||
|
let handle = builder.func.dfg.constants.insert(vec![0u8; 16].into());
|
||||||
|
let zero = builder.ins().vconst(I64X2, handle);
|
||||||
|
|
||||||
|
state.push1(builder.ins().snarrow(converted_a, zero));
|
||||||
|
}
|
||||||
Operator::I32x4TruncSatF32x4U => {
|
Operator::I32x4TruncSatF32x4U => {
|
||||||
let a = pop1_with_bitcast(state, F32X4, builder);
|
let a = pop1_with_bitcast(state, F32X4, builder);
|
||||||
state.push1(builder.ins().fcvt_to_uint_sat(I32X4, a))
|
state.push1(builder.ins().fcvt_to_uint_sat(I32X4, a))
|
||||||
}
|
}
|
||||||
|
Operator::I32x4TruncSatF64x2UZero => {
|
||||||
|
let a = pop1_with_bitcast(state, F64X2, builder);
|
||||||
|
let converted_a = builder.ins().fcvt_to_uint_sat(I64X2, a);
|
||||||
|
let handle = builder.func.dfg.constants.insert(vec![0u8; 16].into());
|
||||||
|
let zero = builder.ins().vconst(I64X2, handle);
|
||||||
|
|
||||||
|
state.push1(builder.ins().uunarrow(converted_a, zero));
|
||||||
|
}
|
||||||
Operator::I8x16NarrowI16x8S => {
|
Operator::I8x16NarrowI16x8S => {
|
||||||
let (a, b) = pop2_with_bitcast(state, I16X8, builder);
|
let (a, b) = pop2_with_bitcast(state, I16X8, builder);
|
||||||
state.push1(builder.ins().snarrow(a, b))
|
state.push1(builder.ins().snarrow(a, b))
|
||||||
@@ -1925,6 +1954,46 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
state.push1(builder.ins().uwiden_high(a))
|
state.push1(builder.ins().uwiden_high(a))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Operator::I64x2ExtendLowI32x4S => {
|
||||||
|
let a = pop1_with_bitcast(state, I32X4, builder);
|
||||||
|
state.push1(builder.ins().swiden_low(a))
|
||||||
|
}
|
||||||
|
Operator::I64x2ExtendHighI32x4S => {
|
||||||
|
let a = pop1_with_bitcast(state, I32X4, builder);
|
||||||
|
state.push1(builder.ins().swiden_high(a))
|
||||||
|
}
|
||||||
|
Operator::I64x2ExtendLowI32x4U => {
|
||||||
|
let a = pop1_with_bitcast(state, I32X4, builder);
|
||||||
|
state.push1(builder.ins().uwiden_low(a))
|
||||||
|
}
|
||||||
|
Operator::I64x2ExtendHighI32x4U => {
|
||||||
|
let a = pop1_with_bitcast(state, I32X4, builder);
|
||||||
|
state.push1(builder.ins().uwiden_high(a))
|
||||||
|
}
|
||||||
|
Operator::I16x8ExtAddPairwiseI8x16S => {
|
||||||
|
let a = pop1_with_bitcast(state, I8X16, builder);
|
||||||
|
let widen_low = builder.ins().swiden_low(a);
|
||||||
|
let widen_high = builder.ins().swiden_high(a);
|
||||||
|
state.push1(builder.ins().iadd_pairwise(widen_low, widen_high));
|
||||||
|
}
|
||||||
|
Operator::I32x4ExtAddPairwiseI16x8S => {
|
||||||
|
let a = pop1_with_bitcast(state, I16X8, builder);
|
||||||
|
let widen_low = builder.ins().swiden_low(a);
|
||||||
|
let widen_high = builder.ins().swiden_high(a);
|
||||||
|
state.push1(builder.ins().iadd_pairwise(widen_low, widen_high));
|
||||||
|
}
|
||||||
|
Operator::I16x8ExtAddPairwiseI8x16U => {
|
||||||
|
let a = pop1_with_bitcast(state, I8X16, builder);
|
||||||
|
let widen_low = builder.ins().uwiden_low(a);
|
||||||
|
let widen_high = builder.ins().uwiden_high(a);
|
||||||
|
state.push1(builder.ins().iadd_pairwise(widen_low, widen_high));
|
||||||
|
}
|
||||||
|
Operator::I32x4ExtAddPairwiseI16x8U => {
|
||||||
|
let a = pop1_with_bitcast(state, I16X8, builder);
|
||||||
|
let widen_low = builder.ins().uwiden_low(a);
|
||||||
|
let widen_high = builder.ins().uwiden_high(a);
|
||||||
|
state.push1(builder.ins().iadd_pairwise(widen_low, widen_high));
|
||||||
|
}
|
||||||
Operator::F32x4Ceil | Operator::F64x2Ceil => {
|
Operator::F32x4Ceil | Operator::F64x2Ceil => {
|
||||||
// This is something of a misuse of `type_of`, because that produces the return type
|
// This is something of a misuse of `type_of`, because that produces the return type
|
||||||
// of `op`. In this case we want the arg type, but we know it's the same as the
|
// of `op`. In this case we want the arg type, but we know it's the same as the
|
||||||
@@ -1948,34 +2017,90 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
let (a, b) = pop2_with_bitcast(state, I16X8, builder);
|
let (a, b) = pop2_with_bitcast(state, I16X8, builder);
|
||||||
state.push1(builder.ins().widening_pairwise_dot_product_s(a, b));
|
state.push1(builder.ins().widening_pairwise_dot_product_s(a, b));
|
||||||
}
|
}
|
||||||
Operator::I64x2ExtendLowI32x4S
|
Operator::I8x16Popcnt => {
|
||||||
| Operator::I64x2ExtendHighI32x4S
|
let arg = pop1_with_bitcast(state, type_of(op), builder);
|
||||||
| Operator::I64x2ExtendLowI32x4U
|
state.push1(builder.ins().popcnt(arg));
|
||||||
| Operator::I64x2ExtendHighI32x4U
|
}
|
||||||
| Operator::I16x8Q15MulrSatS
|
Operator::I16x8Q15MulrSatS => {
|
||||||
| Operator::I16x8ExtMulLowI8x16S
|
let (a, b) = pop2_with_bitcast(state, I16X8, builder);
|
||||||
| Operator::I16x8ExtMulHighI8x16S
|
state.push1(builder.ins().sqmul_round_sat(a, b))
|
||||||
| Operator::I16x8ExtMulLowI8x16U
|
}
|
||||||
| Operator::I16x8ExtMulHighI8x16U
|
Operator::I16x8ExtMulLowI8x16S => {
|
||||||
| Operator::I32x4ExtMulLowI16x8S
|
let (a, b) = pop2_with_bitcast(state, I8X16, builder);
|
||||||
| Operator::I32x4ExtMulHighI16x8S
|
let a_low = builder.ins().swiden_low(a);
|
||||||
| Operator::I32x4ExtMulLowI16x8U
|
let b_low = builder.ins().swiden_low(b);
|
||||||
| Operator::I32x4ExtMulHighI16x8U
|
state.push1(builder.ins().imul(a_low, b_low));
|
||||||
| Operator::I64x2ExtMulLowI32x4S
|
}
|
||||||
| Operator::I64x2ExtMulHighI32x4S
|
Operator::I16x8ExtMulHighI8x16S => {
|
||||||
| Operator::I64x2ExtMulLowI32x4U
|
let (a, b) = pop2_with_bitcast(state, I8X16, builder);
|
||||||
| Operator::I64x2ExtMulHighI32x4U
|
let a_high = builder.ins().swiden_high(a);
|
||||||
| Operator::I16x8ExtAddPairwiseI8x16S
|
let b_high = builder.ins().swiden_high(b);
|
||||||
| Operator::I16x8ExtAddPairwiseI8x16U
|
state.push1(builder.ins().imul(a_high, b_high));
|
||||||
| Operator::I32x4ExtAddPairwiseI16x8S
|
}
|
||||||
| Operator::I32x4ExtAddPairwiseI16x8U
|
Operator::I16x8ExtMulLowI8x16U => {
|
||||||
| Operator::F32x4DemoteF64x2Zero
|
let (a, b) = pop2_with_bitcast(state, I8X16, builder);
|
||||||
| Operator::F64x2PromoteLowF32x4
|
let a_low = builder.ins().uwiden_low(a);
|
||||||
| Operator::F64x2ConvertLowI32x4U
|
let b_low = builder.ins().uwiden_low(b);
|
||||||
| Operator::I32x4TruncSatF64x2SZero
|
state.push1(builder.ins().imul(a_low, b_low));
|
||||||
| Operator::I32x4TruncSatF64x2UZero
|
}
|
||||||
| Operator::I8x16Popcnt
|
Operator::I16x8ExtMulHighI8x16U => {
|
||||||
| Operator::I8x16RelaxedSwizzle
|
let (a, b) = pop2_with_bitcast(state, I8X16, builder);
|
||||||
|
let a_high = builder.ins().uwiden_high(a);
|
||||||
|
let b_high = builder.ins().uwiden_high(b);
|
||||||
|
state.push1(builder.ins().imul(a_high, b_high));
|
||||||
|
}
|
||||||
|
Operator::I32x4ExtMulLowI16x8S => {
|
||||||
|
let (a, b) = pop2_with_bitcast(state, I16X8, builder);
|
||||||
|
let a_low = builder.ins().swiden_low(a);
|
||||||
|
let b_low = builder.ins().swiden_low(b);
|
||||||
|
state.push1(builder.ins().imul(a_low, b_low));
|
||||||
|
}
|
||||||
|
Operator::I32x4ExtMulHighI16x8S => {
|
||||||
|
let (a, b) = pop2_with_bitcast(state, I16X8, builder);
|
||||||
|
let a_high = builder.ins().swiden_high(a);
|
||||||
|
let b_high = builder.ins().swiden_high(b);
|
||||||
|
state.push1(builder.ins().imul(a_high, b_high));
|
||||||
|
}
|
||||||
|
Operator::I32x4ExtMulLowI16x8U => {
|
||||||
|
let (a, b) = pop2_with_bitcast(state, I16X8, builder);
|
||||||
|
let a_low = builder.ins().uwiden_low(a);
|
||||||
|
let b_low = builder.ins().uwiden_low(b);
|
||||||
|
state.push1(builder.ins().imul(a_low, b_low));
|
||||||
|
}
|
||||||
|
Operator::I32x4ExtMulHighI16x8U => {
|
||||||
|
let (a, b) = pop2_with_bitcast(state, I16X8, builder);
|
||||||
|
let a_high = builder.ins().uwiden_high(a);
|
||||||
|
let b_high = builder.ins().uwiden_high(b);
|
||||||
|
state.push1(builder.ins().imul(a_high, b_high));
|
||||||
|
}
|
||||||
|
Operator::I64x2ExtMulLowI32x4S => {
|
||||||
|
let (a, b) = pop2_with_bitcast(state, I32X4, builder);
|
||||||
|
let a_low = builder.ins().swiden_low(a);
|
||||||
|
let b_low = builder.ins().swiden_low(b);
|
||||||
|
state.push1(builder.ins().imul(a_low, b_low));
|
||||||
|
}
|
||||||
|
Operator::I64x2ExtMulHighI32x4S => {
|
||||||
|
let (a, b) = pop2_with_bitcast(state, I32X4, builder);
|
||||||
|
let a_high = builder.ins().swiden_high(a);
|
||||||
|
let b_high = builder.ins().swiden_high(b);
|
||||||
|
state.push1(builder.ins().imul(a_high, b_high));
|
||||||
|
}
|
||||||
|
Operator::I64x2ExtMulLowI32x4U => {
|
||||||
|
let (a, b) = pop2_with_bitcast(state, I32X4, builder);
|
||||||
|
let a_low = builder.ins().uwiden_low(a);
|
||||||
|
let b_low = builder.ins().uwiden_low(b);
|
||||||
|
state.push1(builder.ins().imul(a_low, b_low));
|
||||||
|
}
|
||||||
|
Operator::I64x2ExtMulHighI32x4U => {
|
||||||
|
let (a, b) = pop2_with_bitcast(state, I32X4, builder);
|
||||||
|
let a_high = builder.ins().uwiden_high(a);
|
||||||
|
let b_high = builder.ins().uwiden_high(b);
|
||||||
|
state.push1(builder.ins().imul(a_high, b_high));
|
||||||
|
}
|
||||||
|
Operator::ReturnCall { .. } | Operator::ReturnCallIndirect { .. } => {
|
||||||
|
return Err(wasm_unsupported!("proposed tail-call operator {:?}", op));
|
||||||
|
}
|
||||||
|
Operator::I8x16RelaxedSwizzle
|
||||||
| Operator::I32x4RelaxedTruncSatF32x4S
|
| Operator::I32x4RelaxedTruncSatF32x4S
|
||||||
| Operator::I32x4RelaxedTruncSatF32x4U
|
| Operator::I32x4RelaxedTruncSatF32x4U
|
||||||
| Operator::I32x4RelaxedTruncSatF64x2SZero
|
| Operator::I32x4RelaxedTruncSatF64x2SZero
|
||||||
@@ -1992,10 +2117,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
| Operator::F32x4RelaxedMax
|
| Operator::F32x4RelaxedMax
|
||||||
| Operator::F64x2RelaxedMin
|
| Operator::F64x2RelaxedMin
|
||||||
| Operator::F64x2RelaxedMax => {
|
| Operator::F64x2RelaxedMax => {
|
||||||
return Err(wasm_unsupported!("proposed simd operator {:?}", op));
|
return Err(wasm_unsupported!("proposed relaxed-simd operator {:?}", op));
|
||||||
}
|
|
||||||
Operator::ReturnCall { .. } | Operator::ReturnCallIndirect { .. } => {
|
|
||||||
return Err(wasm_unsupported!("proposed tail-call operator {:?}", op));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -2697,7 +2819,8 @@ fn type_of(operator: &Operator) -> Type {
|
|||||||
| Operator::I8x16MaxS
|
| Operator::I8x16MaxS
|
||||||
| Operator::I8x16MaxU
|
| Operator::I8x16MaxU
|
||||||
| Operator::I8x16RoundingAverageU
|
| Operator::I8x16RoundingAverageU
|
||||||
| Operator::I8x16Bitmask => I8X16,
|
| Operator::I8x16Bitmask
|
||||||
|
| Operator::I8x16Popcnt => I8X16,
|
||||||
|
|
||||||
Operator::I16x8Splat
|
Operator::I16x8Splat
|
||||||
| Operator::V128Load16Splat { .. }
|
| Operator::V128Load16Splat { .. }
|
||||||
@@ -2765,9 +2888,9 @@ fn type_of(operator: &Operator) -> Type {
|
|||||||
| Operator::I32x4MinU
|
| Operator::I32x4MinU
|
||||||
| Operator::I32x4MaxS
|
| Operator::I32x4MaxS
|
||||||
| Operator::I32x4MaxU
|
| Operator::I32x4MaxU
|
||||||
| Operator::F32x4ConvertI32x4S
|
|
||||||
| Operator::F32x4ConvertI32x4U
|
|
||||||
| Operator::I32x4Bitmask
|
| Operator::I32x4Bitmask
|
||||||
|
| Operator::I32x4TruncSatF32x4S
|
||||||
|
| Operator::I32x4TruncSatF32x4U
|
||||||
| Operator::V128Load32Zero { .. } => I32X4,
|
| Operator::V128Load32Zero { .. } => I32X4,
|
||||||
|
|
||||||
Operator::I64x2Splat
|
Operator::I64x2Splat
|
||||||
@@ -2814,8 +2937,8 @@ fn type_of(operator: &Operator) -> Type {
|
|||||||
| Operator::F32x4Max
|
| Operator::F32x4Max
|
||||||
| Operator::F32x4PMin
|
| Operator::F32x4PMin
|
||||||
| Operator::F32x4PMax
|
| Operator::F32x4PMax
|
||||||
| Operator::I32x4TruncSatF32x4S
|
| Operator::F32x4ConvertI32x4S
|
||||||
| Operator::I32x4TruncSatF32x4U
|
| Operator::F32x4ConvertI32x4U
|
||||||
| Operator::F32x4Ceil
|
| Operator::F32x4Ceil
|
||||||
| Operator::F32x4Floor
|
| Operator::F32x4Floor
|
||||||
| Operator::F32x4Trunc
|
| Operator::F32x4Trunc
|
||||||
|
|||||||
@@ -12,6 +12,6 @@ pub use self::func_state::FuncTranslationState;
|
|||||||
pub use self::func_translator::FuncTranslator;
|
pub use self::func_translator::FuncTranslator;
|
||||||
pub use self::translation_utils::{
|
pub use self::translation_utils::{
|
||||||
get_vmctx_value_label, irlibcall_to_libcall, irreloc_to_relocationkind,
|
get_vmctx_value_label, irlibcall_to_libcall, irreloc_to_relocationkind,
|
||||||
signature_to_cranelift_ir, transform_jump_table, type_to_irtype,
|
signature_to_cranelift_ir, type_to_irtype,
|
||||||
};
|
};
|
||||||
pub(crate) use self::unwind::{compiled_function_unwind_info, CraneliftUnwindInfo};
|
pub(crate) use self::unwind::{compiled_function_unwind_info, CraneliftUnwindInfo};
|
||||||
|
|||||||
@@ -6,13 +6,11 @@ use core::u32;
|
|||||||
use cranelift_codegen::binemit::Reloc;
|
use cranelift_codegen::binemit::Reloc;
|
||||||
use cranelift_codegen::ir::{self, AbiParam};
|
use cranelift_codegen::ir::{self, AbiParam};
|
||||||
use cranelift_codegen::isa::TargetFrontendConfig;
|
use cranelift_codegen::isa::TargetFrontendConfig;
|
||||||
use cranelift_entity::{EntityRef as CraneliftEntityRef, SecondaryMap as CraneliftSecondaryMap};
|
|
||||||
use cranelift_frontend::FunctionBuilder;
|
use cranelift_frontend::FunctionBuilder;
|
||||||
use wasmer_compiler::wasm_unsupported;
|
use wasmer_compiler::wasm_unsupported;
|
||||||
use wasmer_compiler::wasmparser;
|
use wasmer_compiler::wasmparser;
|
||||||
use wasmer_compiler::{JumpTable, RelocationKind};
|
use wasmer_compiler::RelocationKind;
|
||||||
use wasmer_compiler::{WasmError, WasmResult};
|
use wasmer_compiler::{WasmError, WasmResult};
|
||||||
use wasmer_types::entity::{EntityRef, SecondaryMap};
|
|
||||||
use wasmer_types::{FunctionType, Type};
|
use wasmer_types::{FunctionType, Type};
|
||||||
use wasmer_vm::libcalls::LibCall;
|
use wasmer_vm::libcalls::LibCall;
|
||||||
|
|
||||||
@@ -86,7 +84,6 @@ pub fn irreloc_to_relocationkind(reloc: Reloc) -> RelocationKind {
|
|||||||
Reloc::Abs4 => RelocationKind::Abs4,
|
Reloc::Abs4 => RelocationKind::Abs4,
|
||||||
Reloc::Abs8 => RelocationKind::Abs8,
|
Reloc::Abs8 => RelocationKind::Abs8,
|
||||||
Reloc::X86PCRel4 => RelocationKind::X86PCRel4,
|
Reloc::X86PCRel4 => RelocationKind::X86PCRel4,
|
||||||
Reloc::X86PCRelRodata4 => RelocationKind::X86PCRelRodata4,
|
|
||||||
Reloc::X86CallPCRel4 => RelocationKind::X86CallPCRel4,
|
Reloc::X86CallPCRel4 => RelocationKind::X86CallPCRel4,
|
||||||
Reloc::X86CallPLTRel4 => RelocationKind::X86CallPLTRel4,
|
Reloc::X86CallPLTRel4 => RelocationKind::X86CallPLTRel4,
|
||||||
Reloc::X86GOTPCRel4 => RelocationKind::X86GOTPCRel4,
|
Reloc::X86GOTPCRel4 => RelocationKind::X86GOTPCRel4,
|
||||||
@@ -148,16 +145,3 @@ pub fn get_vmctx_value_label() -> ir::ValueLabel {
|
|||||||
const VMCTX_LABEL: u32 = 0xffff_fffe;
|
const VMCTX_LABEL: u32 = 0xffff_fffe;
|
||||||
ir::ValueLabel::from_u32(VMCTX_LABEL)
|
ir::ValueLabel::from_u32(VMCTX_LABEL)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transforms Cranelift JumpTable's into runtime JumpTables
|
|
||||||
pub fn transform_jump_table(
|
|
||||||
jt_offsets: CraneliftSecondaryMap<ir::JumpTable, u32>,
|
|
||||||
) -> SecondaryMap<JumpTable, u32> {
|
|
||||||
let mut func_jt_offsets = SecondaryMap::with_capacity(jt_offsets.capacity());
|
|
||||||
|
|
||||||
for (key, value) in jt_offsets.iter() {
|
|
||||||
let new_key = JumpTable::new(key.index());
|
|
||||||
func_jt_offsets[new_key] = *value;
|
|
||||||
}
|
|
||||||
func_jt_offsets
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ pub(crate) fn compiled_function_unwind_info(
|
|||||||
) -> Result<CraneliftUnwindInfo, CompileError> {
|
) -> Result<CraneliftUnwindInfo, CompileError> {
|
||||||
let unwind_info = context
|
let unwind_info = context
|
||||||
.create_unwind_info(isa)
|
.create_unwind_info(isa)
|
||||||
.map_err(|error| CompileError::Codegen(pretty_error(&context.func, Some(isa), error)))?;
|
.map_err(|error| CompileError::Codegen(pretty_error(&context.func, error)))?;
|
||||||
|
|
||||||
match unwind_info {
|
match unwind_info {
|
||||||
Some(UnwindInfo::WindowsX64(unwind)) => {
|
Some(UnwindInfo::WindowsX64(unwind)) => {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use wasmer_compiler::{
|
|||||||
CustomSections, FunctionAddressMap, FunctionBody, InstructionAddressMap, Relocation,
|
CustomSections, FunctionAddressMap, FunctionBody, InstructionAddressMap, Relocation,
|
||||||
RelocationKind, RelocationTarget, SectionBody, SectionIndex, SourceLoc,
|
RelocationKind, RelocationTarget, SectionBody, SectionIndex, SourceLoc,
|
||||||
};
|
};
|
||||||
use wasmer_types::entity::{PrimaryMap, SecondaryMap};
|
use wasmer_types::entity::PrimaryMap;
|
||||||
use wasmer_vm::libcalls::LibCall;
|
use wasmer_vm::libcalls::LibCall;
|
||||||
|
|
||||||
fn map_tryfromint_err(error: TryFromIntError) -> CompileError {
|
fn map_tryfromint_err(error: TryFromIntError) -> CompileError {
|
||||||
@@ -331,7 +331,6 @@ where
|
|||||||
Ok(CompiledFunction {
|
Ok(CompiledFunction {
|
||||||
compiled_function: wasmer_compiler::CompiledFunction {
|
compiled_function: wasmer_compiler::CompiledFunction {
|
||||||
body: function_body,
|
body: function_body,
|
||||||
jt_offsets: SecondaryMap::new(),
|
|
||||||
relocations: relocations
|
relocations: relocations
|
||||||
.remove_entry(&root_section_index)
|
.remove_entry(&root_section_index)
|
||||||
.map_or(vec![], |(_, v)| v),
|
.map_or(vec![], |(_, v)| v),
|
||||||
|
|||||||
@@ -155,11 +155,6 @@ impl FuncTrampoline {
|
|||||||
"trampoline generation produced relocations".into(),
|
"trampoline generation produced relocations".into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if !compiled_function.jt_offsets.is_empty() {
|
|
||||||
return Err(CompileError::Codegen(
|
|
||||||
"trampoline generation produced jump tables".into(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
// Ignore CompiledFunctionFrameInfo. Extra frame info isn't a problem.
|
// Ignore CompiledFunctionFrameInfo. Extra frame info isn't a problem.
|
||||||
|
|
||||||
Ok(FunctionBody {
|
Ok(FunctionBody {
|
||||||
@@ -280,11 +275,6 @@ impl FuncTrampoline {
|
|||||||
"trampoline generation produced relocations".into(),
|
"trampoline generation produced relocations".into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if !compiled_function.jt_offsets.is_empty() {
|
|
||||||
return Err(CompileError::Codegen(
|
|
||||||
"trampoline generation produced jump tables".into(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
// Ignore CompiledFunctionFrameInfo. Extra frame info isn't a problem.
|
// Ignore CompiledFunctionFrameInfo. Extra frame info isn't a problem.
|
||||||
|
|
||||||
Ok(FunctionBody {
|
Ok(FunctionBody {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ use wasmer_compiler::{
|
|||||||
Relocation, RelocationTarget, SectionIndex,
|
Relocation, RelocationTarget, SectionIndex,
|
||||||
};
|
};
|
||||||
use wasmer_types::{
|
use wasmer_types::{
|
||||||
entity::{EntityRef, PrimaryMap, SecondaryMap},
|
entity::{EntityRef, PrimaryMap},
|
||||||
FunctionType,
|
FunctionType,
|
||||||
};
|
};
|
||||||
use wasmer_types::{
|
use wasmer_types::{
|
||||||
@@ -5935,7 +5935,6 @@ impl<'a, M: Machine> FuncGen<'a, M> {
|
|||||||
unwind_info,
|
unwind_info,
|
||||||
},
|
},
|
||||||
relocations: self.relocations.clone(),
|
relocations: self.relocations.clone(),
|
||||||
jt_offsets: SecondaryMap::new(),
|
|
||||||
frame_info: CompiledFunctionFrameInfo {
|
frame_info: CompiledFunctionFrameInfo {
|
||||||
traps: traps,
|
traps: traps,
|
||||||
address_map,
|
address_map,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
use crate::lib::std::vec::Vec;
|
use crate::lib::std::vec::Vec;
|
||||||
use crate::section::{CustomSection, SectionIndex};
|
use crate::section::{CustomSection, SectionIndex};
|
||||||
use crate::trap::TrapInformation;
|
use crate::trap::TrapInformation;
|
||||||
use crate::{CompiledFunctionUnwindInfo, FunctionAddressMap, JumpTableOffsets, Relocation};
|
use crate::{CompiledFunctionUnwindInfo, FunctionAddressMap, Relocation};
|
||||||
use loupe::MemoryUsage;
|
use loupe::MemoryUsage;
|
||||||
#[cfg(feature = "enable-rkyv")]
|
#[cfg(feature = "enable-rkyv")]
|
||||||
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
||||||
@@ -70,9 +70,6 @@ pub struct CompiledFunction {
|
|||||||
/// The relocations (in the body)
|
/// The relocations (in the body)
|
||||||
pub relocations: Vec<Relocation>,
|
pub relocations: Vec<Relocation>,
|
||||||
|
|
||||||
/// The jump tables offsets (in the body).
|
|
||||||
pub jt_offsets: JumpTableOffsets,
|
|
||||||
|
|
||||||
/// The frame information.
|
/// The frame information.
|
||||||
pub frame_info: CompiledFunctionFrameInfo,
|
pub frame_info: CompiledFunctionFrameInfo,
|
||||||
}
|
}
|
||||||
@@ -206,14 +203,6 @@ impl Compilation {
|
|||||||
.collect::<PrimaryMap<LocalFunctionIndex, _>>()
|
.collect::<PrimaryMap<LocalFunctionIndex, _>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets functions jump table offsets.
|
|
||||||
pub fn get_jt_offsets(&self) -> PrimaryMap<LocalFunctionIndex, JumpTableOffsets> {
|
|
||||||
self.functions
|
|
||||||
.iter()
|
|
||||||
.map(|(_, func)| func.jt_offsets.clone())
|
|
||||||
.collect::<PrimaryMap<LocalFunctionIndex, _>>()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets functions frame info.
|
/// Gets functions frame info.
|
||||||
pub fn get_frame_info(&self) -> PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo> {
|
pub fn get_frame_info(&self) -> PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo> {
|
||||||
self.functions
|
self.functions
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
//! A jump table is a method of transferring program control (branching)
|
|
||||||
//! to another part of a program (or a different program that may have
|
|
||||||
//! been dynamically loaded) using a table of branch or jump instructions.
|
|
||||||
//!
|
|
||||||
//! [Learn more](https://en.wikipedia.org/wiki/Branch_table).
|
|
||||||
|
|
||||||
use super::CodeOffset;
|
|
||||||
use loupe::MemoryUsage;
|
|
||||||
#[cfg(feature = "enable-rkyv")]
|
|
||||||
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
|
||||||
#[cfg(feature = "enable-serde")]
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use wasmer_types::entity::{entity_impl, SecondaryMap};
|
|
||||||
|
|
||||||
/// An opaque reference to a [jump table](https://en.wikipedia.org/wiki/Branch_table).
|
|
||||||
///
|
|
||||||
/// `JumpTable`s are used for indirect branching and are specialized for dense,
|
|
||||||
/// 0-based jump offsets.
|
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
|
||||||
#[cfg_attr(
|
|
||||||
feature = "enable-rkyv",
|
|
||||||
derive(RkyvSerialize, RkyvDeserialize, Archive)
|
|
||||||
)]
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, MemoryUsage)]
|
|
||||||
pub struct JumpTable(u32);
|
|
||||||
|
|
||||||
entity_impl!(JumpTable, "jt");
|
|
||||||
|
|
||||||
impl JumpTable {
|
|
||||||
/// Create a new jump table reference from its number.
|
|
||||||
///
|
|
||||||
/// This method is for use by the parser.
|
|
||||||
pub fn with_number(n: u32) -> Option<Self> {
|
|
||||||
if n < u32::max_value() {
|
|
||||||
Some(Self(n))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Code offsets for Jump Tables.
|
|
||||||
pub type JumpTableOffsets = SecondaryMap<JumpTable, CodeOffset>;
|
|
||||||
@@ -54,7 +54,6 @@ mod address_map;
|
|||||||
mod compiler;
|
mod compiler;
|
||||||
mod error;
|
mod error;
|
||||||
mod function;
|
mod function;
|
||||||
mod jump_table;
|
|
||||||
mod module;
|
mod module;
|
||||||
mod relocation;
|
mod relocation;
|
||||||
mod target;
|
mod target;
|
||||||
@@ -76,7 +75,6 @@ pub use crate::function::{
|
|||||||
Compilation, CompiledFunction, CompiledFunctionFrameInfo, CustomSections, Dwarf, FunctionBody,
|
Compilation, CompiledFunction, CompiledFunctionFrameInfo, CustomSections, Dwarf, FunctionBody,
|
||||||
Functions,
|
Functions,
|
||||||
};
|
};
|
||||||
pub use crate::jump_table::{JumpTable, JumpTableOffsets};
|
|
||||||
pub use crate::module::CompileModuleInfo;
|
pub use crate::module::CompileModuleInfo;
|
||||||
pub use crate::relocation::{Relocation, RelocationKind, RelocationTarget, Relocations};
|
pub use crate::relocation::{Relocation, RelocationKind, RelocationTarget, Relocations};
|
||||||
pub use crate::section::{CustomSection, CustomSectionProtection, SectionBody, SectionIndex};
|
pub use crate::section::{CustomSection, CustomSectionProtection, SectionBody, SectionIndex};
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
use crate::lib::std::fmt;
|
use crate::lib::std::fmt;
|
||||||
use crate::lib::std::vec::Vec;
|
use crate::lib::std::vec::Vec;
|
||||||
use crate::section::SectionIndex;
|
use crate::section::SectionIndex;
|
||||||
use crate::{Addend, CodeOffset, JumpTable};
|
use crate::{Addend, CodeOffset};
|
||||||
use loupe::MemoryUsage;
|
use loupe::MemoryUsage;
|
||||||
#[cfg(feature = "enable-rkyv")]
|
#[cfg(feature = "enable-rkyv")]
|
||||||
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
||||||
@@ -38,8 +38,6 @@ pub enum RelocationKind {
|
|||||||
X86PCRel4,
|
X86PCRel4,
|
||||||
/// x86 PC-relative 8-byte
|
/// x86 PC-relative 8-byte
|
||||||
X86PCRel8,
|
X86PCRel8,
|
||||||
/// x86 PC-relative 4-byte offset to trailing rodata
|
|
||||||
X86PCRelRodata4,
|
|
||||||
/// x86 call to PC-relative 4-byte
|
/// x86 call to PC-relative 4-byte
|
||||||
X86CallPCRel4,
|
X86CallPCRel4,
|
||||||
/// x86 call to PLT-relative 4-byte
|
/// x86 call to PLT-relative 4-byte
|
||||||
@@ -67,7 +65,6 @@ impl fmt::Display for RelocationKind {
|
|||||||
Self::Abs8 => write!(f, "Abs8"),
|
Self::Abs8 => write!(f, "Abs8"),
|
||||||
Self::X86PCRel4 => write!(f, "PCRel4"),
|
Self::X86PCRel4 => write!(f, "PCRel4"),
|
||||||
Self::X86PCRel8 => write!(f, "PCRel8"),
|
Self::X86PCRel8 => write!(f, "PCRel8"),
|
||||||
Self::X86PCRelRodata4 => write!(f, "PCRelRodata4"),
|
|
||||||
Self::X86CallPCRel4 => write!(f, "CallPCRel4"),
|
Self::X86CallPCRel4 => write!(f, "CallPCRel4"),
|
||||||
Self::X86CallPLTRel4 => write!(f, "CallPLTRel4"),
|
Self::X86CallPLTRel4 => write!(f, "CallPLTRel4"),
|
||||||
Self::X86GOTPCRel4 => write!(f, "GOTPCRel4"),
|
Self::X86GOTPCRel4 => write!(f, "GOTPCRel4"),
|
||||||
@@ -108,8 +105,6 @@ pub enum RelocationTarget {
|
|||||||
LocalFunc(LocalFunctionIndex),
|
LocalFunc(LocalFunctionIndex),
|
||||||
/// A compiler-generated libcall.
|
/// A compiler-generated libcall.
|
||||||
LibCall(LibCall),
|
LibCall(LibCall),
|
||||||
/// Jump table index.
|
|
||||||
JumpTable(LocalFunctionIndex, JumpTable),
|
|
||||||
/// Custom sections generated by the compiler
|
/// Custom sections generated by the compiler
|
||||||
CustomSection(SectionIndex),
|
CustomSection(SectionIndex),
|
||||||
}
|
}
|
||||||
@@ -163,9 +158,6 @@ impl Relocation {
|
|||||||
.wrapping_add(reloc_addend as u64);
|
.wrapping_add(reloc_addend as u64);
|
||||||
(reloc_address, reloc_delta_u32)
|
(reloc_address, reloc_delta_u32)
|
||||||
}
|
}
|
||||||
// RelocationKind::X86PCRelRodata4 => {
|
|
||||||
// (start, target_func_address)
|
|
||||||
// }
|
|
||||||
_ => panic!("Relocation kind unsupported"),
|
_ => panic!("Relocation kind unsupported"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,7 +123,6 @@ impl UniversalArtifact {
|
|||||||
let serializable_compilation = SerializableCompilation {
|
let serializable_compilation = SerializableCompilation {
|
||||||
function_bodies: compilation.get_function_bodies(),
|
function_bodies: compilation.get_function_bodies(),
|
||||||
function_relocations: compilation.get_relocations(),
|
function_relocations: compilation.get_relocations(),
|
||||||
function_jt_offsets: compilation.get_jt_offsets(),
|
|
||||||
function_frame_info: frame_infos,
|
function_frame_info: frame_infos,
|
||||||
function_call_trampolines,
|
function_call_trampolines,
|
||||||
dynamic_function_trampolines,
|
dynamic_function_trampolines,
|
||||||
@@ -193,7 +192,6 @@ impl UniversalArtifact {
|
|||||||
link_module(
|
link_module(
|
||||||
&serializable.compile_info.module,
|
&serializable.compile_info.module,
|
||||||
&finished_functions,
|
&finished_functions,
|
||||||
&serializable.compilation.function_jt_offsets,
|
|
||||||
serializable.compilation.function_relocations.clone(),
|
serializable.compilation.function_relocations.clone(),
|
||||||
&custom_sections,
|
&custom_sections,
|
||||||
&serializable.compilation.custom_section_relocations,
|
&serializable.compilation.custom_section_relocations,
|
||||||
|
|||||||
@@ -2,12 +2,9 @@
|
|||||||
|
|
||||||
use crate::trampoline::get_libcall_trampoline;
|
use crate::trampoline::get_libcall_trampoline;
|
||||||
use std::ptr::{read_unaligned, write_unaligned};
|
use std::ptr::{read_unaligned, write_unaligned};
|
||||||
use wasmer_compiler::{
|
use wasmer_compiler::{Relocation, RelocationKind, RelocationTarget, Relocations, SectionIndex};
|
||||||
JumpTable, JumpTableOffsets, Relocation, RelocationKind, RelocationTarget, Relocations,
|
|
||||||
SectionIndex,
|
|
||||||
};
|
|
||||||
use wasmer_engine::FunctionExtent;
|
use wasmer_engine::FunctionExtent;
|
||||||
use wasmer_types::entity::{EntityRef, PrimaryMap};
|
use wasmer_types::entity::PrimaryMap;
|
||||||
use wasmer_types::{LocalFunctionIndex, ModuleInfo};
|
use wasmer_types::{LocalFunctionIndex, ModuleInfo};
|
||||||
use wasmer_vm::SectionBodyPtr;
|
use wasmer_vm::SectionBodyPtr;
|
||||||
|
|
||||||
@@ -15,7 +12,6 @@ fn apply_relocation(
|
|||||||
body: usize,
|
body: usize,
|
||||||
r: &Relocation,
|
r: &Relocation,
|
||||||
allocated_functions: &PrimaryMap<LocalFunctionIndex, FunctionExtent>,
|
allocated_functions: &PrimaryMap<LocalFunctionIndex, FunctionExtent>,
|
||||||
jt_offsets: &PrimaryMap<LocalFunctionIndex, JumpTableOffsets>,
|
|
||||||
allocated_sections: &PrimaryMap<SectionIndex, SectionBodyPtr>,
|
allocated_sections: &PrimaryMap<SectionIndex, SectionBodyPtr>,
|
||||||
libcall_trampolines: SectionIndex,
|
libcall_trampolines: SectionIndex,
|
||||||
libcall_trampoline_len: usize,
|
libcall_trampoline_len: usize,
|
||||||
@@ -38,13 +34,6 @@ fn apply_relocation(
|
|||||||
RelocationTarget::CustomSection(custom_section) => {
|
RelocationTarget::CustomSection(custom_section) => {
|
||||||
*allocated_sections[custom_section] as usize
|
*allocated_sections[custom_section] as usize
|
||||||
}
|
}
|
||||||
RelocationTarget::JumpTable(func_index, jt) => {
|
|
||||||
let offset = *jt_offsets
|
|
||||||
.get(func_index)
|
|
||||||
.and_then(|ofs| ofs.get(JumpTable::new(jt.index())))
|
|
||||||
.expect("func jump table");
|
|
||||||
*allocated_functions[func_index].ptr as usize + offset as usize
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match r.kind {
|
match r.kind {
|
||||||
@@ -67,7 +56,6 @@ fn apply_relocation(
|
|||||||
let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
|
let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
|
||||||
write_unaligned(reloc_address as *mut u32, reloc_delta as _);
|
write_unaligned(reloc_address as *mut u32, reloc_delta as _);
|
||||||
},
|
},
|
||||||
RelocationKind::X86PCRelRodata4 => {}
|
|
||||||
RelocationKind::Arm64Call => unsafe {
|
RelocationKind::Arm64Call => unsafe {
|
||||||
let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
|
let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
|
||||||
if (reloc_delta as i64).abs() >= 0x1000_0000 {
|
if (reloc_delta as i64).abs() >= 0x1000_0000 {
|
||||||
@@ -95,7 +83,6 @@ fn apply_relocation(
|
|||||||
pub fn link_module(
|
pub fn link_module(
|
||||||
_module: &ModuleInfo,
|
_module: &ModuleInfo,
|
||||||
allocated_functions: &PrimaryMap<LocalFunctionIndex, FunctionExtent>,
|
allocated_functions: &PrimaryMap<LocalFunctionIndex, FunctionExtent>,
|
||||||
jt_offsets: &PrimaryMap<LocalFunctionIndex, JumpTableOffsets>,
|
|
||||||
function_relocations: Relocations,
|
function_relocations: Relocations,
|
||||||
allocated_sections: &PrimaryMap<SectionIndex, SectionBodyPtr>,
|
allocated_sections: &PrimaryMap<SectionIndex, SectionBodyPtr>,
|
||||||
section_relocations: &PrimaryMap<SectionIndex, Vec<Relocation>>,
|
section_relocations: &PrimaryMap<SectionIndex, Vec<Relocation>>,
|
||||||
@@ -109,7 +96,6 @@ pub fn link_module(
|
|||||||
body,
|
body,
|
||||||
r,
|
r,
|
||||||
allocated_functions,
|
allocated_functions,
|
||||||
jt_offsets,
|
|
||||||
allocated_sections,
|
allocated_sections,
|
||||||
libcall_trampolines,
|
libcall_trampolines,
|
||||||
trampoline_len,
|
trampoline_len,
|
||||||
@@ -123,7 +109,6 @@ pub fn link_module(
|
|||||||
body,
|
body,
|
||||||
r,
|
r,
|
||||||
allocated_functions,
|
allocated_functions,
|
||||||
jt_offsets,
|
|
||||||
allocated_sections,
|
allocated_sections,
|
||||||
libcall_trampolines,
|
libcall_trampolines,
|
||||||
trampoline_len,
|
trampoline_len,
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ use rkyv::{
|
|||||||
Serialize as RkyvSerialize,
|
Serialize as RkyvSerialize,
|
||||||
};
|
};
|
||||||
use wasmer_compiler::{
|
use wasmer_compiler::{
|
||||||
CompileModuleInfo, CompiledFunctionFrameInfo, CustomSection, Dwarf, FunctionBody,
|
CompileModuleInfo, CompiledFunctionFrameInfo, CustomSection, Dwarf, FunctionBody, Relocation,
|
||||||
JumpTableOffsets, Relocation, SectionIndex,
|
SectionIndex,
|
||||||
};
|
};
|
||||||
use wasmer_engine::{DeserializeError, SerializeError};
|
use wasmer_engine::{DeserializeError, SerializeError};
|
||||||
use wasmer_types::entity::PrimaryMap;
|
use wasmer_types::entity::PrimaryMap;
|
||||||
@@ -17,7 +17,6 @@ use wasmer_types::{FunctionIndex, LocalFunctionIndex, OwnedDataInitializer, Sign
|
|||||||
pub struct SerializableCompilation {
|
pub struct SerializableCompilation {
|
||||||
pub function_bodies: PrimaryMap<LocalFunctionIndex, FunctionBody>,
|
pub function_bodies: PrimaryMap<LocalFunctionIndex, FunctionBody>,
|
||||||
pub function_relocations: PrimaryMap<LocalFunctionIndex, Vec<Relocation>>,
|
pub function_relocations: PrimaryMap<LocalFunctionIndex, Vec<Relocation>>,
|
||||||
pub function_jt_offsets: PrimaryMap<LocalFunctionIndex, JumpTableOffsets>,
|
|
||||||
pub function_frame_info: PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>,
|
pub function_frame_info: PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>,
|
||||||
pub function_call_trampolines: PrimaryMap<SignatureIndex, FunctionBody>,
|
pub function_call_trampolines: PrimaryMap<SignatureIndex, FunctionBody>,
|
||||||
pub dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBody>,
|
pub dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBody>,
|
||||||
|
|||||||
@@ -292,8 +292,6 @@ pub fn emit_compilation(
|
|||||||
Reloc::X86GOTPCRel4 => {
|
Reloc::X86GOTPCRel4 => {
|
||||||
(RelocationKind::GotRelative, RelocationEncoding::Generic, 32)
|
(RelocationKind::GotRelative, RelocationEncoding::Generic, 32)
|
||||||
}
|
}
|
||||||
// Reloc::X86PCRelRodata4 => {
|
|
||||||
// }
|
|
||||||
Reloc::Arm64Call => (
|
Reloc::Arm64Call => (
|
||||||
match obj.format() {
|
match obj.format() {
|
||||||
object::BinaryFormat::Elf => RelocationKind::Elf(elf::R_AARCH64_CALL26),
|
object::BinaryFormat::Elf => RelocationKind::Elf(elf::R_AARCH64_CALL26),
|
||||||
@@ -378,9 +376,6 @@ pub fn emit_compilation(
|
|||||||
)
|
)
|
||||||
.map_err(ObjectError::Write)?;
|
.map_err(ObjectError::Write)?;
|
||||||
}
|
}
|
||||||
RelocationTarget::JumpTable(_func_index, _jt) => {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user