mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-07 05:08:19 +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"
|
||||
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
|
||||
dependencies = [
|
||||
"gimli 0.26.1",
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -434,24 +434,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.76.0"
|
||||
version = "0.82.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e6bea67967505247f54fa2c85cf4f6e0e31c4e5692c9b70e4ae58e339067333"
|
||||
checksum = "d16922317bd7dd104d509a373887822caa0242fc1def00de66abb538db221db4"
|
||||
dependencies = [
|
||||
"cranelift-entity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.76.0"
|
||||
version = "0.82.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48194035d2752bdd5bdae429e3ab88676e95f52a2b1355a5d4e809f9e39b1d74"
|
||||
checksum = "8b80bf40380256307b68a3dcbe1b91cac92a533e212b5b635abc3e4525781a0a"
|
||||
dependencies = [
|
||||
"cranelift-bforest",
|
||||
"cranelift-codegen-meta",
|
||||
"cranelift-codegen-shared",
|
||||
"cranelift-entity",
|
||||
"gimli 0.25.0",
|
||||
"gimli",
|
||||
"hashbrown 0.9.1",
|
||||
"log",
|
||||
"regalloc",
|
||||
@@ -461,31 +461,30 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.76.0"
|
||||
version = "0.82.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "976efb22fcab4f2cd6bd4e9913764616a54d895c1a23530128d04e03633c555f"
|
||||
checksum = "703d0ed7d3bc6c7a814ca12858175bf4e93167a3584127858c686e4b5dd6e432"
|
||||
dependencies = [
|
||||
"cranelift-codegen-shared",
|
||||
"cranelift-entity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.76.0"
|
||||
version = "0.82.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9dabb5fe66e04d4652e434195b45ae65b5c8172d520247b8f66d8df42b2b45dc"
|
||||
checksum = "80f52311e1c90de12dcf8c4b9999c6ebfd1ed360373e88c357160936844511f6"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.76.0"
|
||||
version = "0.82.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3329733e4d4b8e91c809efcaa4faee80bf66f20164e3dd16d707346bd3494799"
|
||||
checksum = "66bc82ef522c1f643baf7d4d40b7c52643ee4549d8960b0e6a047daacb83f897"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.76.0"
|
||||
version = "0.82.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "279afcc0d3e651b773f94837c3d581177b348c8d69e928104b2e9fccb226f921"
|
||||
checksum = "3cc35e4251864b17515845ba47447bca88fec9ca1a4186b19fe42526e36140e8"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"hashbrown 0.9.1",
|
||||
@@ -960,17 +959,6 @@ dependencies = [
|
||||
"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]]
|
||||
name = "gimli"
|
||||
version = "0.26.1"
|
||||
@@ -1800,9 +1788,9 @@ checksum = "a0d51660a68078997855ba5602f73ab3a5031bd7ad480a9d4c90fbbf04e1fff0"
|
||||
|
||||
[[package]]
|
||||
name = "regalloc"
|
||||
version = "0.0.31"
|
||||
version = "0.0.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "571f7f397d61c4755285cd37853fe8e03271c243424a907415909379659381c5"
|
||||
checksum = "62446b1d3ebf980bdc68837700af1d77b37bc430e524bf95319c6eada2a4cc02"
|
||||
dependencies = [
|
||||
"log",
|
||||
"rustc-hash",
|
||||
@@ -2913,7 +2901,7 @@ dependencies = [
|
||||
"cranelift-codegen",
|
||||
"cranelift-entity",
|
||||
"cranelift-frontend",
|
||||
"gimli 0.25.0",
|
||||
"gimli",
|
||||
"hashbrown 0.11.2",
|
||||
"lazy_static",
|
||||
"loupe",
|
||||
@@ -2957,7 +2945,7 @@ dependencies = [
|
||||
"byteorder",
|
||||
"dynasm",
|
||||
"dynasmrt",
|
||||
"gimli 0.26.1",
|
||||
"gimli",
|
||||
"hashbrown 0.11.2",
|
||||
"lazy_static",
|
||||
"loupe",
|
||||
|
||||
@@ -15,20 +15,20 @@ edition = "2018"
|
||||
wasmer-compiler = { path = "../compiler", version = "=2.2.1", features = ["translator"], default-features = false }
|
||||
wasmer-vm = { path = "../vm", version = "=2.2.1" }
|
||||
wasmer-types = { path = "../types", version = "=2.2.1", default-features = false, features = ["std"] }
|
||||
cranelift-entity = { version = "0.76", default-features = false }
|
||||
cranelift-codegen = { version = "0.76", default-features = false, features = ["x86", "arm64"] }
|
||||
cranelift-frontend = { version = "0.76", default-features = false }
|
||||
cranelift-entity = { version = "0.82", default-features = false }
|
||||
cranelift-codegen = { version = "0.82", default-features = false, features = ["x86", "arm64"] }
|
||||
cranelift-frontend = { version = "0.82", default-features = false }
|
||||
tracing = "0.1"
|
||||
hashbrown = { version = "0.11", optional = true }
|
||||
rayon = "1.5"
|
||||
more-asserts = "0.2"
|
||||
gimli = { version = "0.25", optional = true }
|
||||
gimli = { version = "0.26", optional = true }
|
||||
smallvec = "1.6"
|
||||
loupe = "0.1"
|
||||
target-lexicon = { version = "0.12.2", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
cranelift-codegen = { version = "0.76", features = ["all-arch"] }
|
||||
cranelift-codegen = { version = "0.82", features = ["all-arch"] }
|
||||
lazy_static = "1.4"
|
||||
|
||||
[badges]
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
// This file contains code from external sources.
|
||||
// Attributions: https://github.com/wasmerio/wasmer/blob/master/ATTRIBUTIONS.md
|
||||
|
||||
use cranelift_codegen::Context;
|
||||
use cranelift_codegen::MachSrcLoc;
|
||||
use cranelift_codegen::{isa, Context};
|
||||
use wasmer_compiler::{wasmparser::Range, FunctionAddressMap, InstructionAddressMap, SourceLoc};
|
||||
|
||||
pub fn get_function_address_map<'data>(
|
||||
context: &Context,
|
||||
range: Range,
|
||||
body_len: usize,
|
||||
isa: &dyn isa::TargetIsa,
|
||||
) -> FunctionAddressMap {
|
||||
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
|
||||
// tuples.
|
||||
let mcr = context.mach_compile_result.as_ref().unwrap();
|
||||
for &MachSrcLoc { start, end, loc } in mcr.buffer.get_srclocs_sorted() {
|
||||
instructions.push(InstructionAddressMap {
|
||||
srcloc: SourceLoc::new(loc.bits()),
|
||||
@@ -23,23 +22,6 @@ pub fn get_function_address_map<'data>(
|
||||
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
|
||||
// within module. Similar to FuncTranslator::cur_srcloc(): it will wrap around
|
||||
|
||||
@@ -5,32 +5,35 @@ use crate::config::Cranelift;
|
||||
#[cfg(feature = "unwind")]
|
||||
use crate::dwarf::WriterRelocate;
|
||||
use crate::func_environ::{get_function_name, FuncEnvironment};
|
||||
use crate::sink::{RelocSink, TrapSink};
|
||||
use crate::trampoline::{
|
||||
make_trampoline_dynamic_function, make_trampoline_function_call, FunctionBuilderContext,
|
||||
};
|
||||
use crate::translator::{
|
||||
compiled_function_unwind_info, signature_to_cranelift_ir, transform_jump_table,
|
||||
CraneliftUnwindInfo, FuncTranslator,
|
||||
compiled_function_unwind_info, irlibcall_to_libcall, irreloc_to_relocationkind,
|
||||
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::{binemit, Context};
|
||||
use cranelift_codegen::{ir, MachReloc};
|
||||
use cranelift_codegen::{Context, MachTrap};
|
||||
#[cfg(feature = "unwind")]
|
||||
use gimli::write::{Address, EhFrame, FrameTable};
|
||||
use loupe::MemoryUsage;
|
||||
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
||||
use std::sync::Arc;
|
||||
use wasmer_compiler::CompileError;
|
||||
use wasmer_compiler::{CallingConvention, ModuleTranslationState, Target};
|
||||
use wasmer_compiler::{
|
||||
CallingConvention, ModuleTranslationState, RelocationTarget, Target, TrapInformation,
|
||||
};
|
||||
use wasmer_compiler::{
|
||||
Compilation, CompileModuleInfo, CompiledFunction, CompiledFunctionFrameInfo,
|
||||
CompiledFunctionUnwindInfo, Compiler, Dwarf, FunctionBinaryReader, FunctionBody,
|
||||
FunctionBodyData, MiddlewareBinaryReader, ModuleMiddleware, ModuleMiddlewareChain,
|
||||
SectionIndex,
|
||||
};
|
||||
use wasmer_compiler::{CompileError, Relocation};
|
||||
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,
|
||||
/// optimizing it and then translating to assembly.
|
||||
@@ -66,7 +69,10 @@ impl Compiler for CraneliftCompiler {
|
||||
module_translation_state: &ModuleTranslationState,
|
||||
function_body_inputs: PrimaryMap<LocalFunctionIndex, FunctionBodyData<'_>>,
|
||||
) -> 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 memory_styles = &compile_info.memory_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 reloc_sink = RelocSink::new(&module, func_index);
|
||||
let mut trap_sink = TrapSink::new();
|
||||
let mut stackmap_sink = binemit::NullStackMapSink {};
|
||||
context
|
||||
.compile_and_emit(
|
||||
&*isa,
|
||||
&mut code_buf,
|
||||
&mut reloc_sink,
|
||||
&mut trap_sink,
|
||||
&mut stackmap_sink,
|
||||
)
|
||||
.map_err(|error| {
|
||||
CompileError::Codegen(pretty_error(&context.func, Some(&*isa), error))
|
||||
})?;
|
||||
.compile_and_emit(&*isa, &mut code_buf)
|
||||
.map_err(|error| CompileError::Codegen(pretty_error(&context.func, error)))?;
|
||||
|
||||
let result = context.mach_compile_result.as_ref().unwrap();
|
||||
let func_relocs = result
|
||||
.buffer
|
||||
.relocs()
|
||||
.into_iter()
|
||||
.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)? {
|
||||
#[cfg(feature = "unwind")]
|
||||
@@ -182,10 +192,7 @@ impl Compiler for CraneliftCompiler {
|
||||
};
|
||||
|
||||
let range = reader.range();
|
||||
let address_map = get_function_address_map(&context, range, code_buf.len(), &*isa);
|
||||
|
||||
// We transform the Cranelift JumpTable's into compiler JumpTables
|
||||
let func_jt_offsets = transform_jump_table(context.func.jt_offsets);
|
||||
let address_map = get_function_address_map(&context, range, code_buf.len());
|
||||
|
||||
Ok((
|
||||
CompiledFunction {
|
||||
@@ -193,12 +200,8 @@ impl Compiler for CraneliftCompiler {
|
||||
body: code_buf,
|
||||
unwind_info,
|
||||
},
|
||||
jt_offsets: func_jt_offsets,
|
||||
relocations: reloc_sink.func_relocs,
|
||||
frame_info: CompiledFunctionFrameInfo {
|
||||
address_map,
|
||||
traps: trap_sink.traps,
|
||||
},
|
||||
relocations: func_relocs,
|
||||
frame_info: CompiledFunctionFrameInfo { address_map, traps },
|
||||
},
|
||||
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 cranelift_codegen::isa::{lookup, TargetIsa};
|
||||
use cranelift_codegen::settings::{self, Configurable};
|
||||
use cranelift_codegen::CodegenResult;
|
||||
use loupe::MemoryUsage;
|
||||
use std::sync::Arc;
|
||||
use wasmer_compiler::{
|
||||
@@ -67,7 +68,7 @@ impl Cranelift {
|
||||
}
|
||||
|
||||
/// 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 =
|
||||
lookup(target.triple().clone()).expect("construct Cranelift ISA for triple");
|
||||
// Cpu Features
|
||||
|
||||
@@ -51,7 +51,6 @@ mod debug;
|
||||
#[cfg(feature = "unwind")]
|
||||
mod dwarf;
|
||||
mod func_environ;
|
||||
mod sink;
|
||||
mod trampoline;
|
||||
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.
|
||||
|
||||
use super::binemit::TrampolineRelocSink;
|
||||
use crate::translator::{compiled_function_unwind_info, signature_to_cranelift_ir};
|
||||
use cranelift_codegen::ir;
|
||||
use cranelift_codegen::ir::{
|
||||
ExternalName, Function, InstBuilder, MemFlags, StackSlotData, StackSlotKind,
|
||||
};
|
||||
use cranelift_codegen::isa::TargetIsa;
|
||||
use cranelift_codegen::print_errors::pretty_error;
|
||||
use cranelift_codegen::Context;
|
||||
use cranelift_codegen::{binemit, ir};
|
||||
use std::cmp;
|
||||
use std::mem;
|
||||
|
||||
@@ -108,18 +107,9 @@ pub fn make_trampoline_dynamic_function(
|
||||
}
|
||||
|
||||
let mut code_buf = Vec::new();
|
||||
let mut reloc_sink = TrampolineRelocSink {};
|
||||
let mut trap_sink = binemit::NullTrapSink {};
|
||||
let mut stackmap_sink = binemit::NullStackMapSink {};
|
||||
context
|
||||
.compile_and_emit(
|
||||
isa,
|
||||
&mut code_buf,
|
||||
&mut reloc_sink,
|
||||
&mut trap_sink,
|
||||
&mut stackmap_sink,
|
||||
)
|
||||
.map_err(|error| CompileError::Codegen(pretty_error(&context.func, Some(isa), error)))?;
|
||||
.compile_and_emit(isa, &mut code_buf)
|
||||
.map_err(|error| CompileError::Codegen(pretty_error(&context.func, error)))?;
|
||||
|
||||
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");
|
||||
//! my_func.call([1, 2])
|
||||
//! ```
|
||||
use super::binemit::TrampolineRelocSink;
|
||||
use crate::translator::{
|
||||
compiled_function_unwind_info, signature_to_cranelift_ir, /*transform_jump_table, */
|
||||
};
|
||||
use crate::translator::{compiled_function_unwind_info, signature_to_cranelift_ir};
|
||||
use cranelift_codegen::ir;
|
||||
use cranelift_codegen::ir::InstBuilder;
|
||||
use cranelift_codegen::isa::TargetIsa;
|
||||
use cranelift_codegen::print_errors::pretty_error;
|
||||
use cranelift_codegen::Context;
|
||||
use cranelift_codegen::{binemit, ir};
|
||||
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
|
||||
use std::mem;
|
||||
use wasmer_compiler::{CompileError, FunctionBody};
|
||||
@@ -106,25 +103,15 @@ pub fn make_trampoline_function_call(
|
||||
}
|
||||
|
||||
let mut code_buf = Vec::new();
|
||||
let mut reloc_sink = TrampolineRelocSink {};
|
||||
let mut trap_sink = binemit::NullTrapSink {};
|
||||
let mut stackmap_sink = binemit::NullStackMapSink {};
|
||||
|
||||
context
|
||||
.compile_and_emit(
|
||||
isa,
|
||||
&mut code_buf,
|
||||
&mut reloc_sink,
|
||||
&mut trap_sink,
|
||||
&mut stackmap_sink,
|
||||
)
|
||||
.map_err(|error| CompileError::Codegen(pretty_error(&context.func, Some(isa), error)))?;
|
||||
.compile_and_emit(isa, &mut code_buf)
|
||||
.map_err(|error| CompileError::Codegen(pretty_error(&context.func, error)))?;
|
||||
|
||||
let unwind_info = compiled_function_unwind_info(isa, &context)?.maybe_into_to_windows_unwind();
|
||||
|
||||
Ok(FunctionBody {
|
||||
body: code_buf,
|
||||
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::Context;
|
||||
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);
|
||||
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 => {
|
||||
let a = pop1_with_bitcast(state, F32X4, builder);
|
||||
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 => {
|
||||
let a = pop1_with_bitcast(state, F32X4, builder);
|
||||
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 => {
|
||||
let (a, b) = pop2_with_bitcast(state, I16X8, builder);
|
||||
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))
|
||||
}
|
||||
|
||||
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 => {
|
||||
// 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
|
||||
@@ -1948,34 +2017,90 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
let (a, b) = pop2_with_bitcast(state, I16X8, builder);
|
||||
state.push1(builder.ins().widening_pairwise_dot_product_s(a, b));
|
||||
}
|
||||
Operator::I64x2ExtendLowI32x4S
|
||||
| Operator::I64x2ExtendHighI32x4S
|
||||
| Operator::I64x2ExtendLowI32x4U
|
||||
| Operator::I64x2ExtendHighI32x4U
|
||||
| Operator::I16x8Q15MulrSatS
|
||||
| Operator::I16x8ExtMulLowI8x16S
|
||||
| Operator::I16x8ExtMulHighI8x16S
|
||||
| Operator::I16x8ExtMulLowI8x16U
|
||||
| Operator::I16x8ExtMulHighI8x16U
|
||||
| Operator::I32x4ExtMulLowI16x8S
|
||||
| Operator::I32x4ExtMulHighI16x8S
|
||||
| Operator::I32x4ExtMulLowI16x8U
|
||||
| Operator::I32x4ExtMulHighI16x8U
|
||||
| Operator::I64x2ExtMulLowI32x4S
|
||||
| Operator::I64x2ExtMulHighI32x4S
|
||||
| Operator::I64x2ExtMulLowI32x4U
|
||||
| Operator::I64x2ExtMulHighI32x4U
|
||||
| Operator::I16x8ExtAddPairwiseI8x16S
|
||||
| Operator::I16x8ExtAddPairwiseI8x16U
|
||||
| Operator::I32x4ExtAddPairwiseI16x8S
|
||||
| Operator::I32x4ExtAddPairwiseI16x8U
|
||||
| Operator::F32x4DemoteF64x2Zero
|
||||
| Operator::F64x2PromoteLowF32x4
|
||||
| Operator::F64x2ConvertLowI32x4U
|
||||
| Operator::I32x4TruncSatF64x2SZero
|
||||
| Operator::I32x4TruncSatF64x2UZero
|
||||
| Operator::I8x16Popcnt
|
||||
| Operator::I8x16RelaxedSwizzle
|
||||
Operator::I8x16Popcnt => {
|
||||
let arg = pop1_with_bitcast(state, type_of(op), builder);
|
||||
state.push1(builder.ins().popcnt(arg));
|
||||
}
|
||||
Operator::I16x8Q15MulrSatS => {
|
||||
let (a, b) = pop2_with_bitcast(state, I16X8, builder);
|
||||
state.push1(builder.ins().sqmul_round_sat(a, b))
|
||||
}
|
||||
Operator::I16x8ExtMulLowI8x16S => {
|
||||
let (a, b) = pop2_with_bitcast(state, I8X16, 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::I16x8ExtMulHighI8x16S => {
|
||||
let (a, b) = pop2_with_bitcast(state, I8X16, 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::I16x8ExtMulLowI8x16U => {
|
||||
let (a, b) = pop2_with_bitcast(state, I8X16, 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::I16x8ExtMulHighI8x16U => {
|
||||
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::I32x4RelaxedTruncSatF32x4U
|
||||
| Operator::I32x4RelaxedTruncSatF64x2SZero
|
||||
@@ -1992,10 +2117,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
| Operator::F32x4RelaxedMax
|
||||
| Operator::F64x2RelaxedMin
|
||||
| Operator::F64x2RelaxedMax => {
|
||||
return Err(wasm_unsupported!("proposed simd operator {:?}", op));
|
||||
}
|
||||
Operator::ReturnCall { .. } | Operator::ReturnCallIndirect { .. } => {
|
||||
return Err(wasm_unsupported!("proposed tail-call operator {:?}", op));
|
||||
return Err(wasm_unsupported!("proposed relaxed-simd operator {:?}", op));
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
@@ -2697,7 +2819,8 @@ fn type_of(operator: &Operator) -> Type {
|
||||
| Operator::I8x16MaxS
|
||||
| Operator::I8x16MaxU
|
||||
| Operator::I8x16RoundingAverageU
|
||||
| Operator::I8x16Bitmask => I8X16,
|
||||
| Operator::I8x16Bitmask
|
||||
| Operator::I8x16Popcnt => I8X16,
|
||||
|
||||
Operator::I16x8Splat
|
||||
| Operator::V128Load16Splat { .. }
|
||||
@@ -2765,9 +2888,9 @@ fn type_of(operator: &Operator) -> Type {
|
||||
| Operator::I32x4MinU
|
||||
| Operator::I32x4MaxS
|
||||
| Operator::I32x4MaxU
|
||||
| Operator::F32x4ConvertI32x4S
|
||||
| Operator::F32x4ConvertI32x4U
|
||||
| Operator::I32x4Bitmask
|
||||
| Operator::I32x4TruncSatF32x4S
|
||||
| Operator::I32x4TruncSatF32x4U
|
||||
| Operator::V128Load32Zero { .. } => I32X4,
|
||||
|
||||
Operator::I64x2Splat
|
||||
@@ -2814,8 +2937,8 @@ fn type_of(operator: &Operator) -> Type {
|
||||
| Operator::F32x4Max
|
||||
| Operator::F32x4PMin
|
||||
| Operator::F32x4PMax
|
||||
| Operator::I32x4TruncSatF32x4S
|
||||
| Operator::I32x4TruncSatF32x4U
|
||||
| Operator::F32x4ConvertI32x4S
|
||||
| Operator::F32x4ConvertI32x4U
|
||||
| Operator::F32x4Ceil
|
||||
| Operator::F32x4Floor
|
||||
| Operator::F32x4Trunc
|
||||
|
||||
@@ -12,6 +12,6 @@ pub use self::func_state::FuncTranslationState;
|
||||
pub use self::func_translator::FuncTranslator;
|
||||
pub use self::translation_utils::{
|
||||
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};
|
||||
|
||||
@@ -6,13 +6,11 @@ use core::u32;
|
||||
use cranelift_codegen::binemit::Reloc;
|
||||
use cranelift_codegen::ir::{self, AbiParam};
|
||||
use cranelift_codegen::isa::TargetFrontendConfig;
|
||||
use cranelift_entity::{EntityRef as CraneliftEntityRef, SecondaryMap as CraneliftSecondaryMap};
|
||||
use cranelift_frontend::FunctionBuilder;
|
||||
use wasmer_compiler::wasm_unsupported;
|
||||
use wasmer_compiler::wasmparser;
|
||||
use wasmer_compiler::{JumpTable, RelocationKind};
|
||||
use wasmer_compiler::RelocationKind;
|
||||
use wasmer_compiler::{WasmError, WasmResult};
|
||||
use wasmer_types::entity::{EntityRef, SecondaryMap};
|
||||
use wasmer_types::{FunctionType, Type};
|
||||
use wasmer_vm::libcalls::LibCall;
|
||||
|
||||
@@ -86,7 +84,6 @@ pub fn irreloc_to_relocationkind(reloc: Reloc) -> RelocationKind {
|
||||
Reloc::Abs4 => RelocationKind::Abs4,
|
||||
Reloc::Abs8 => RelocationKind::Abs8,
|
||||
Reloc::X86PCRel4 => RelocationKind::X86PCRel4,
|
||||
Reloc::X86PCRelRodata4 => RelocationKind::X86PCRelRodata4,
|
||||
Reloc::X86CallPCRel4 => RelocationKind::X86CallPCRel4,
|
||||
Reloc::X86CallPLTRel4 => RelocationKind::X86CallPLTRel4,
|
||||
Reloc::X86GOTPCRel4 => RelocationKind::X86GOTPCRel4,
|
||||
@@ -148,16 +145,3 @@ pub fn get_vmctx_value_label() -> ir::ValueLabel {
|
||||
const VMCTX_LABEL: u32 = 0xffff_fffe;
|
||||
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> {
|
||||
let unwind_info = context
|
||||
.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 {
|
||||
Some(UnwindInfo::WindowsX64(unwind)) => {
|
||||
|
||||
@@ -9,7 +9,7 @@ use wasmer_compiler::{
|
||||
CustomSections, FunctionAddressMap, FunctionBody, InstructionAddressMap, Relocation,
|
||||
RelocationKind, RelocationTarget, SectionBody, SectionIndex, SourceLoc,
|
||||
};
|
||||
use wasmer_types::entity::{PrimaryMap, SecondaryMap};
|
||||
use wasmer_types::entity::PrimaryMap;
|
||||
use wasmer_vm::libcalls::LibCall;
|
||||
|
||||
fn map_tryfromint_err(error: TryFromIntError) -> CompileError {
|
||||
@@ -331,7 +331,6 @@ where
|
||||
Ok(CompiledFunction {
|
||||
compiled_function: wasmer_compiler::CompiledFunction {
|
||||
body: function_body,
|
||||
jt_offsets: SecondaryMap::new(),
|
||||
relocations: relocations
|
||||
.remove_entry(&root_section_index)
|
||||
.map_or(vec![], |(_, v)| v),
|
||||
|
||||
@@ -155,11 +155,6 @@ impl FuncTrampoline {
|
||||
"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.
|
||||
|
||||
Ok(FunctionBody {
|
||||
@@ -280,11 +275,6 @@ impl FuncTrampoline {
|
||||
"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.
|
||||
|
||||
Ok(FunctionBody {
|
||||
|
||||
@@ -18,7 +18,7 @@ use wasmer_compiler::{
|
||||
Relocation, RelocationTarget, SectionIndex,
|
||||
};
|
||||
use wasmer_types::{
|
||||
entity::{EntityRef, PrimaryMap, SecondaryMap},
|
||||
entity::{EntityRef, PrimaryMap},
|
||||
FunctionType,
|
||||
};
|
||||
use wasmer_types::{
|
||||
@@ -5935,7 +5935,6 @@ impl<'a, M: Machine> FuncGen<'a, M> {
|
||||
unwind_info,
|
||||
},
|
||||
relocations: self.relocations.clone(),
|
||||
jt_offsets: SecondaryMap::new(),
|
||||
frame_info: CompiledFunctionFrameInfo {
|
||||
traps: traps,
|
||||
address_map,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
use crate::lib::std::vec::Vec;
|
||||
use crate::section::{CustomSection, SectionIndex};
|
||||
use crate::trap::TrapInformation;
|
||||
use crate::{CompiledFunctionUnwindInfo, FunctionAddressMap, JumpTableOffsets, Relocation};
|
||||
use crate::{CompiledFunctionUnwindInfo, FunctionAddressMap, Relocation};
|
||||
use loupe::MemoryUsage;
|
||||
#[cfg(feature = "enable-rkyv")]
|
||||
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
||||
@@ -70,9 +70,6 @@ pub struct CompiledFunction {
|
||||
/// The relocations (in the body)
|
||||
pub relocations: Vec<Relocation>,
|
||||
|
||||
/// The jump tables offsets (in the body).
|
||||
pub jt_offsets: JumpTableOffsets,
|
||||
|
||||
/// The frame information.
|
||||
pub frame_info: CompiledFunctionFrameInfo,
|
||||
}
|
||||
@@ -206,14 +203,6 @@ impl Compilation {
|
||||
.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.
|
||||
pub fn get_frame_info(&self) -> PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo> {
|
||||
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 error;
|
||||
mod function;
|
||||
mod jump_table;
|
||||
mod module;
|
||||
mod relocation;
|
||||
mod target;
|
||||
@@ -76,7 +75,6 @@ pub use crate::function::{
|
||||
Compilation, CompiledFunction, CompiledFunctionFrameInfo, CustomSections, Dwarf, FunctionBody,
|
||||
Functions,
|
||||
};
|
||||
pub use crate::jump_table::{JumpTable, JumpTableOffsets};
|
||||
pub use crate::module::CompileModuleInfo;
|
||||
pub use crate::relocation::{Relocation, RelocationKind, RelocationTarget, Relocations};
|
||||
pub use crate::section::{CustomSection, CustomSectionProtection, SectionBody, SectionIndex};
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
use crate::lib::std::fmt;
|
||||
use crate::lib::std::vec::Vec;
|
||||
use crate::section::SectionIndex;
|
||||
use crate::{Addend, CodeOffset, JumpTable};
|
||||
use crate::{Addend, CodeOffset};
|
||||
use loupe::MemoryUsage;
|
||||
#[cfg(feature = "enable-rkyv")]
|
||||
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
|
||||
@@ -38,8 +38,6 @@ pub enum RelocationKind {
|
||||
X86PCRel4,
|
||||
/// x86 PC-relative 8-byte
|
||||
X86PCRel8,
|
||||
/// x86 PC-relative 4-byte offset to trailing rodata
|
||||
X86PCRelRodata4,
|
||||
/// x86 call to PC-relative 4-byte
|
||||
X86CallPCRel4,
|
||||
/// x86 call to PLT-relative 4-byte
|
||||
@@ -67,7 +65,6 @@ impl fmt::Display for RelocationKind {
|
||||
Self::Abs8 => write!(f, "Abs8"),
|
||||
Self::X86PCRel4 => write!(f, "PCRel4"),
|
||||
Self::X86PCRel8 => write!(f, "PCRel8"),
|
||||
Self::X86PCRelRodata4 => write!(f, "PCRelRodata4"),
|
||||
Self::X86CallPCRel4 => write!(f, "CallPCRel4"),
|
||||
Self::X86CallPLTRel4 => write!(f, "CallPLTRel4"),
|
||||
Self::X86GOTPCRel4 => write!(f, "GOTPCRel4"),
|
||||
@@ -108,8 +105,6 @@ pub enum RelocationTarget {
|
||||
LocalFunc(LocalFunctionIndex),
|
||||
/// A compiler-generated libcall.
|
||||
LibCall(LibCall),
|
||||
/// Jump table index.
|
||||
JumpTable(LocalFunctionIndex, JumpTable),
|
||||
/// Custom sections generated by the compiler
|
||||
CustomSection(SectionIndex),
|
||||
}
|
||||
@@ -163,9 +158,6 @@ impl Relocation {
|
||||
.wrapping_add(reloc_addend as u64);
|
||||
(reloc_address, reloc_delta_u32)
|
||||
}
|
||||
// RelocationKind::X86PCRelRodata4 => {
|
||||
// (start, target_func_address)
|
||||
// }
|
||||
_ => panic!("Relocation kind unsupported"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +123,6 @@ impl UniversalArtifact {
|
||||
let serializable_compilation = SerializableCompilation {
|
||||
function_bodies: compilation.get_function_bodies(),
|
||||
function_relocations: compilation.get_relocations(),
|
||||
function_jt_offsets: compilation.get_jt_offsets(),
|
||||
function_frame_info: frame_infos,
|
||||
function_call_trampolines,
|
||||
dynamic_function_trampolines,
|
||||
@@ -193,7 +192,6 @@ impl UniversalArtifact {
|
||||
link_module(
|
||||
&serializable.compile_info.module,
|
||||
&finished_functions,
|
||||
&serializable.compilation.function_jt_offsets,
|
||||
serializable.compilation.function_relocations.clone(),
|
||||
&custom_sections,
|
||||
&serializable.compilation.custom_section_relocations,
|
||||
|
||||
@@ -2,12 +2,9 @@
|
||||
|
||||
use crate::trampoline::get_libcall_trampoline;
|
||||
use std::ptr::{read_unaligned, write_unaligned};
|
||||
use wasmer_compiler::{
|
||||
JumpTable, JumpTableOffsets, Relocation, RelocationKind, RelocationTarget, Relocations,
|
||||
SectionIndex,
|
||||
};
|
||||
use wasmer_compiler::{Relocation, RelocationKind, RelocationTarget, Relocations, SectionIndex};
|
||||
use wasmer_engine::FunctionExtent;
|
||||
use wasmer_types::entity::{EntityRef, PrimaryMap};
|
||||
use wasmer_types::entity::PrimaryMap;
|
||||
use wasmer_types::{LocalFunctionIndex, ModuleInfo};
|
||||
use wasmer_vm::SectionBodyPtr;
|
||||
|
||||
@@ -15,7 +12,6 @@ fn apply_relocation(
|
||||
body: usize,
|
||||
r: &Relocation,
|
||||
allocated_functions: &PrimaryMap<LocalFunctionIndex, FunctionExtent>,
|
||||
jt_offsets: &PrimaryMap<LocalFunctionIndex, JumpTableOffsets>,
|
||||
allocated_sections: &PrimaryMap<SectionIndex, SectionBodyPtr>,
|
||||
libcall_trampolines: SectionIndex,
|
||||
libcall_trampoline_len: usize,
|
||||
@@ -38,13 +34,6 @@ fn apply_relocation(
|
||||
RelocationTarget::CustomSection(custom_section) => {
|
||||
*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 {
|
||||
@@ -67,7 +56,6 @@ fn apply_relocation(
|
||||
let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
|
||||
write_unaligned(reloc_address as *mut u32, reloc_delta as _);
|
||||
},
|
||||
RelocationKind::X86PCRelRodata4 => {}
|
||||
RelocationKind::Arm64Call => unsafe {
|
||||
let (reloc_address, reloc_delta) = r.for_address(body, target_func_address as u64);
|
||||
if (reloc_delta as i64).abs() >= 0x1000_0000 {
|
||||
@@ -95,7 +83,6 @@ fn apply_relocation(
|
||||
pub fn link_module(
|
||||
_module: &ModuleInfo,
|
||||
allocated_functions: &PrimaryMap<LocalFunctionIndex, FunctionExtent>,
|
||||
jt_offsets: &PrimaryMap<LocalFunctionIndex, JumpTableOffsets>,
|
||||
function_relocations: Relocations,
|
||||
allocated_sections: &PrimaryMap<SectionIndex, SectionBodyPtr>,
|
||||
section_relocations: &PrimaryMap<SectionIndex, Vec<Relocation>>,
|
||||
@@ -109,7 +96,6 @@ pub fn link_module(
|
||||
body,
|
||||
r,
|
||||
allocated_functions,
|
||||
jt_offsets,
|
||||
allocated_sections,
|
||||
libcall_trampolines,
|
||||
trampoline_len,
|
||||
@@ -123,7 +109,6 @@ pub fn link_module(
|
||||
body,
|
||||
r,
|
||||
allocated_functions,
|
||||
jt_offsets,
|
||||
allocated_sections,
|
||||
libcall_trampolines,
|
||||
trampoline_len,
|
||||
|
||||
@@ -5,8 +5,8 @@ use rkyv::{
|
||||
Serialize as RkyvSerialize,
|
||||
};
|
||||
use wasmer_compiler::{
|
||||
CompileModuleInfo, CompiledFunctionFrameInfo, CustomSection, Dwarf, FunctionBody,
|
||||
JumpTableOffsets, Relocation, SectionIndex,
|
||||
CompileModuleInfo, CompiledFunctionFrameInfo, CustomSection, Dwarf, FunctionBody, Relocation,
|
||||
SectionIndex,
|
||||
};
|
||||
use wasmer_engine::{DeserializeError, SerializeError};
|
||||
use wasmer_types::entity::PrimaryMap;
|
||||
@@ -17,7 +17,6 @@ use wasmer_types::{FunctionIndex, LocalFunctionIndex, OwnedDataInitializer, Sign
|
||||
pub struct SerializableCompilation {
|
||||
pub function_bodies: PrimaryMap<LocalFunctionIndex, FunctionBody>,
|
||||
pub function_relocations: PrimaryMap<LocalFunctionIndex, Vec<Relocation>>,
|
||||
pub function_jt_offsets: PrimaryMap<LocalFunctionIndex, JumpTableOffsets>,
|
||||
pub function_frame_info: PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>,
|
||||
pub function_call_trampolines: PrimaryMap<SignatureIndex, FunctionBody>,
|
||||
pub dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBody>,
|
||||
|
||||
@@ -292,8 +292,6 @@ pub fn emit_compilation(
|
||||
Reloc::X86GOTPCRel4 => {
|
||||
(RelocationKind::GotRelative, RelocationEncoding::Generic, 32)
|
||||
}
|
||||
// Reloc::X86PCRelRodata4 => {
|
||||
// }
|
||||
Reloc::Arm64Call => (
|
||||
match obj.format() {
|
||||
object::BinaryFormat::Elf => RelocationKind::Elf(elf::R_AARCH64_CALL26),
|
||||
@@ -378,9 +376,6 @@ pub fn emit_compilation(
|
||||
)
|
||||
.map_err(ObjectError::Write)?;
|
||||
}
|
||||
RelocationTarget::JumpTable(_func_index, _jt) => {
|
||||
// do nothing
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user