mirror of
https://github.com/fluencelabs/wasmer
synced 2025-05-30 18:31:20 +00:00
Add signatures conversion
This commit is contained in:
parent
95dc292637
commit
9af9e75bfd
@ -1,3 +1,17 @@
|
|||||||
|
use crate::runtime::{
|
||||||
|
backend::FuncResolver,
|
||||||
|
memory::LinearMemory,
|
||||||
|
module::{DataInitializer, Export, ImportName, Module as WasmerModule, TableInitializer},
|
||||||
|
types::{
|
||||||
|
ElementType as WasmerElementType, FuncIndex as WasmerFuncIndex, FuncSig as WasmerSignature,
|
||||||
|
Global as WasmerGlobal, GlobalDesc as WasmerGlobalDesc, GlobalIndex as WasmerGlobalIndex,
|
||||||
|
Initializer as WasmerInitializer, Map, MapIndex, Memory as WasmerMemory,
|
||||||
|
MemoryIndex as WasmerMemoryIndex, SigIndex as WasmerSignatureIndex, Table as WasmerTable,
|
||||||
|
TableIndex as WasmerTableIndex, Type as WasmerType,
|
||||||
|
},
|
||||||
|
vm::{self, Ctx as WasmerVMContext},
|
||||||
|
};
|
||||||
|
use crate::webassembly::errors::ErrorKind;
|
||||||
use cranelift_codegen::cursor::FuncCursor;
|
use cranelift_codegen::cursor::FuncCursor;
|
||||||
use cranelift_codegen::ir::immediates::{Offset32, Uimm64};
|
use cranelift_codegen::ir::immediates::{Offset32, Uimm64};
|
||||||
use cranelift_codegen::ir::types::{self, *};
|
use cranelift_codegen::ir::types::{self, *};
|
||||||
@ -5,81 +19,63 @@ use cranelift_codegen::ir::{
|
|||||||
self, AbiParam, ArgumentPurpose, ExtFuncData, ExternalName, FuncRef, InstBuilder, Signature,
|
self, AbiParam, ArgumentPurpose, ExtFuncData, ExternalName, FuncRef, InstBuilder, Signature,
|
||||||
TrapCode,
|
TrapCode,
|
||||||
};
|
};
|
||||||
use cranelift_codegen::isa::{self, CallConv, TargetFrontendConfig};
|
use cranelift_codegen::isa::TargetFrontendConfig;
|
||||||
use cranelift_codegen::settings::{self, Configurable};
|
|
||||||
use cranelift_entity::{EntityRef, PrimaryMap};
|
use cranelift_entity::{EntityRef, PrimaryMap};
|
||||||
use cranelift_wasm::{
|
use cranelift_wasm::{
|
||||||
translate_module, DefinedFuncIndex, FuncEnvironment as FuncEnvironmentTrait, FuncIndex,
|
translate_module, DefinedFuncIndex, FuncEnvironment as FuncEnvironmentTrait, FuncIndex,
|
||||||
FuncTranslator, Global, GlobalIndex, GlobalVariable, Memory, MemoryIndex, ModuleEnvironment,
|
FuncTranslator, Global, GlobalIndex, GlobalVariable, Memory, MemoryIndex, ModuleEnvironment,
|
||||||
ReturnMode, SignatureIndex, Table, TableIndex, WasmResult,
|
ReturnMode, SignatureIndex, Table, TableIndex, WasmResult,
|
||||||
};
|
};
|
||||||
|
use hashbrown::HashMap;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
use target_lexicon;
|
use target_lexicon;
|
||||||
use crate::webassembly::errors::ErrorKind;
|
|
||||||
use crate::runtime::{
|
|
||||||
module::{DataInitializer, Export, ImportName, Module as WasmerModule, TableInitializer},
|
|
||||||
types::{
|
|
||||||
Type as WasmerType,
|
|
||||||
FuncIndex as WasmerFuncIndex,
|
|
||||||
GlobalIndex as WasmerGlobalIndex,
|
|
||||||
Global as WasmerGlobal,
|
|
||||||
GlobalDesc as WasmerGlobalDesc,
|
|
||||||
MemoryIndex as WasmerMemoryIndex,
|
|
||||||
Memory as WasmerMemory,
|
|
||||||
Table as WasmerTable,
|
|
||||||
TableIndex as WasmerTableIndex,
|
|
||||||
Initializer as WasmerInitializer,
|
|
||||||
ElementType as WasmerElementType,
|
|
||||||
FuncSig as WasmerSignature,
|
|
||||||
SigIndex as WasmerSignatureIndex,
|
|
||||||
MapIndex,
|
|
||||||
Map,
|
|
||||||
},
|
|
||||||
vm::{
|
|
||||||
self,
|
|
||||||
Ctx as WasmerVMContext,
|
|
||||||
},
|
|
||||||
memory::{
|
|
||||||
LinearMemory,
|
|
||||||
},
|
|
||||||
backend::{
|
|
||||||
FuncResolver,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
use hashbrown::HashMap;
|
|
||||||
|
|
||||||
/// The converter namespace contains functions for converting a Cranelift module
|
/// The converter namespace contains functions for converting a Cranelift module
|
||||||
/// to a wasmer module.
|
/// to a Wasmer module.
|
||||||
pub mod converter {
|
pub mod converter {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// Converts a Cranelift module to a wasmer module.
|
/// Converts a Cranelift module to a Wasmer module.
|
||||||
pub fn convert_module(cranelift_module: CraneliftModule) -> WasmerModule {
|
pub fn convert_module(cranelift_module: CraneliftModule) -> WasmerModule {
|
||||||
// Convert Cranelift globals to wasmer globals
|
// Convert Cranelift globals to Wasmer globals
|
||||||
let mut globals: Map<WasmerGlobalIndex, WasmerGlobal> = Map::with_capacity(cranelift_module.globals.len());
|
let mut globals: Map<WasmerGlobalIndex, WasmerGlobal> =
|
||||||
|
Map::with_capacity(cranelift_module.globals.len());
|
||||||
for global in cranelift_module.globals {
|
for global in cranelift_module.globals {
|
||||||
globals.push(convert_global(global));
|
globals.push(convert_global(global));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert Cranelift memories to wasmer memories.
|
// Convert Cranelift memories to Wasmer memories.
|
||||||
let mut memories: Map<WasmerMemoryIndex, WasmerMemory> = Map::with_capacity(cranelift_module.memories.len());
|
let mut memories: Map<WasmerMemoryIndex, WasmerMemory> =
|
||||||
|
Map::with_capacity(cranelift_module.memories.len());
|
||||||
for memory in cranelift_module.memories {
|
for memory in cranelift_module.memories {
|
||||||
memories.push(convert_memory(memory));
|
memories.push(convert_memory(memory));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert Cranelift tables to wasmer tables.
|
// Convert Cranelift tables to Wasmer tables.
|
||||||
let mut tables: Map<WasmerTableIndex, WasmerTable> = Map::with_capacity(cranelift_module.tables.len());
|
let mut tables: Map<WasmerTableIndex, WasmerTable> =
|
||||||
|
Map::with_capacity(cranelift_module.tables.len());
|
||||||
for table in cranelift_module.tables {
|
for table in cranelift_module.tables {
|
||||||
tables.push(convert_table(table));
|
tables.push(convert_table(table));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: signatures, signatures_assoc, func_resolver
|
// Convert Cranelift signatures to Wasmer signatures.
|
||||||
let signatures_len = cranelift_module.signatures.len();
|
let mut signatures: Map<WasmerSignatureIndex, WasmerSignature> =
|
||||||
let signatures: Map<WasmerSignatureIndex, WasmerSignature> = Map::with_capacity(signatures_len);
|
Map::with_capacity(cranelift_module.signatures.len());
|
||||||
let signature_assoc: Map<WasmerFuncIndex, WasmerSignatureIndex> = Map::with_capacity(signatures_len);
|
for signature in cranelift_module.signatures {
|
||||||
let func_resolver = cranelift_module.func_resolver.unwrap();
|
signatures.push(convert_signature(signature));
|
||||||
|
}
|
||||||
|
|
||||||
// Get other fields directly from the cranelift_module.
|
// Convert Cranelift signature indices to Wasmer signature indices.
|
||||||
|
let mut signature_assoc: Map<WasmerFuncIndex, WasmerSignatureIndex> =
|
||||||
|
Map::with_capacity(cranelift_module.functions.len());
|
||||||
|
for (_, signature_index) in cranelift_module.functions.iter() {
|
||||||
|
signature_assoc.push(WasmerSignatureIndex::new(signature_index.index()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create func_resolver.
|
||||||
|
let func_resolver = Box::new(CraneliftFunctionResolver::new());
|
||||||
|
|
||||||
|
// Get other fields from the cranelift_module.
|
||||||
let CraneliftModule {
|
let CraneliftModule {
|
||||||
imported_functions,
|
imported_functions,
|
||||||
imported_memories,
|
imported_memories,
|
||||||
@ -92,7 +88,7 @@ pub mod converter {
|
|||||||
..
|
..
|
||||||
} = cranelift_module;
|
} = cranelift_module;
|
||||||
|
|
||||||
// Create wasmer module from data above
|
// Create Wasmer module from data above
|
||||||
WasmerModule {
|
WasmerModule {
|
||||||
func_resolver,
|
func_resolver,
|
||||||
memories,
|
memories,
|
||||||
@ -111,7 +107,7 @@ pub mod converter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts from Cranelift type to a wasmer type.
|
/// Converts from Cranelift type to a Wasmer type.
|
||||||
pub fn convert_type(ty: types::Type) -> WasmerType {
|
pub fn convert_type(ty: types::Type) -> WasmerType {
|
||||||
match ty {
|
match ty {
|
||||||
I32 => WasmerType::I32,
|
I32 => WasmerType::I32,
|
||||||
@ -122,7 +118,7 @@ pub mod converter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a Cranelift global to a wasmer global.
|
/// Converts a Cranelift global to a Wasmer global.
|
||||||
pub fn convert_global(global: Global) -> WasmerGlobal {
|
pub fn convert_global(global: Global) -> WasmerGlobal {
|
||||||
let desc = WasmerGlobalDesc {
|
let desc = WasmerGlobalDesc {
|
||||||
mutable: global.mutability,
|
mutable: global.mutability,
|
||||||
@ -138,17 +134,16 @@ pub mod converter {
|
|||||||
I64Const(val) => Const(val.into()),
|
I64Const(val) => Const(val.into()),
|
||||||
F32Const(val) => Const((val as f32).into()),
|
F32Const(val) => Const((val as f32).into()),
|
||||||
F64Const(val) => Const((val as f64).into()),
|
F64Const(val) => Const((val as f64).into()),
|
||||||
GlobalInit::GetGlobal(index) =>
|
GlobalInit::GetGlobal(index) => {
|
||||||
WasmerInitializer::GetGlobal(
|
WasmerInitializer::GetGlobal(WasmerGlobalIndex::new(index.index()))
|
||||||
WasmerGlobalIndex::new(index.index())
|
}
|
||||||
),
|
|
||||||
Import => unimplemented!("TODO: imported globals are not supported yet!"),
|
Import => unimplemented!("TODO: imported globals are not supported yet!"),
|
||||||
};
|
};
|
||||||
|
|
||||||
WasmerGlobal {desc, init}
|
WasmerGlobal { desc, init }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a Cranelift table to a wasmer table.
|
/// Converts a Cranelift table to a Wasmer table.
|
||||||
pub fn convert_table(table: Table) -> WasmerTable {
|
pub fn convert_table(table: Table) -> WasmerTable {
|
||||||
use cranelift_wasm::TableElementType::*;
|
use cranelift_wasm::TableElementType::*;
|
||||||
|
|
||||||
@ -164,7 +159,7 @@ pub mod converter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a Cranelift table to a wasmer table.
|
/// Converts a Cranelift table to a Wasmer table.
|
||||||
pub fn convert_memory(memory: Memory) -> WasmerMemory {
|
pub fn convert_memory(memory: Memory) -> WasmerMemory {
|
||||||
WasmerMemory {
|
WasmerMemory {
|
||||||
shared: memory.shared,
|
shared: memory.shared,
|
||||||
@ -173,15 +168,19 @@ pub mod converter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a Cranelift signature to a wasmer signature.
|
/// Converts a Cranelift signature to a Wasmer signature.
|
||||||
pub fn convert_signature(sig: ir::Signature) -> WasmerSignature {
|
pub fn convert_signature(sig: ir::Signature) -> WasmerSignature {
|
||||||
WasmerSignature {
|
WasmerSignature {
|
||||||
params: sig.params.iter().map(
|
params: sig
|
||||||
|param| convert_type(param.value_type)
|
.params
|
||||||
).collect(),
|
.iter()
|
||||||
returns: sig.returns.iter().map(
|
.map(|param| convert_type(param.value_type))
|
||||||
|ret| convert_type(ret.value_type)
|
.collect(),
|
||||||
).collect(),
|
returns: sig
|
||||||
|
.returns
|
||||||
|
.iter()
|
||||||
|
.map(|ret| convert_type(ret.value_type))
|
||||||
|
.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -215,7 +214,7 @@ pub struct CraneliftModule {
|
|||||||
/// The external function declaration for implementing wasm's `grow_memory`.
|
/// The external function declaration for implementing wasm's `grow_memory`.
|
||||||
pub grow_memory_extfunc: Option<FuncRef>,
|
pub grow_memory_extfunc: Option<FuncRef>,
|
||||||
|
|
||||||
/// A function that takes a wasmer module and resolves a function index to a vm::Func.
|
/// A function that takes a Wasmer module and resolves a function index to a vm::Func.
|
||||||
pub func_resolver: Option<Box<dyn FuncResolver>>,
|
pub func_resolver: Option<Box<dyn FuncResolver>>,
|
||||||
|
|
||||||
// An array holding information about the wasm instance memories.
|
// An array holding information about the wasm instance memories.
|
||||||
@ -252,11 +251,10 @@ pub struct CraneliftModule {
|
|||||||
pub start_func: Option<WasmerFuncIndex>,
|
pub start_func: Option<WasmerFuncIndex>,
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
impl CraneliftModule {
|
impl CraneliftModule {
|
||||||
/// Translates wasm bytes into a Cranelift module
|
/// Translates wasm bytes into a Cranelift module
|
||||||
pub fn from_bytes(
|
pub fn from_bytes(
|
||||||
buffer_source: Vec<u8>,
|
buffer_source: &Vec<u8>,
|
||||||
config: TargetFrontendConfig,
|
config: TargetFrontendConfig,
|
||||||
) -> Result<Self, ErrorKind> {
|
) -> Result<Self, ErrorKind> {
|
||||||
// Create a cranelift module
|
// Create a cranelift module
|
||||||
@ -270,7 +268,7 @@ impl CraneliftModule {
|
|||||||
memories_base: None,
|
memories_base: None,
|
||||||
current_memory_extfunc: None,
|
current_memory_extfunc: None,
|
||||||
grow_memory_extfunc: None,
|
grow_memory_extfunc: None,
|
||||||
func_resolver: Some(Box::new(MockFuncResolver {})),
|
func_resolver: None,
|
||||||
memories: Vec::new(),
|
memories: Vec::new(),
|
||||||
globals: Vec::new(),
|
globals: Vec::new(),
|
||||||
tables: Vec::new(),
|
tables: Vec::new(),
|
||||||
@ -291,10 +289,21 @@ impl CraneliftModule {
|
|||||||
// Return translated module.
|
// Return translated module.
|
||||||
Ok(cranelift_module)
|
Ok(cranelift_module)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new `FuncEnvironment` for the module.
|
// Resolves a function index to a function address.
|
||||||
fn func_env(&self) -> FuncEnvironment {
|
pub struct CraneliftFunctionResolver {}
|
||||||
FuncEnvironment::new(&self)
|
|
||||||
|
impl CraneliftFunctionResolver {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements FuncResolver trait.
|
||||||
|
impl FuncResolver for CraneliftFunctionResolver {
|
||||||
|
fn get(&self, module: &WasmerModule, index: WasmerFuncIndex) -> Option<NonNull<vm::Func>> {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,6 +341,7 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Gets native pointers types.
|
/// Gets native pointers types.
|
||||||
|
///
|
||||||
/// `I64` on 64-bit arch; `I32` on 32-bit arch.
|
/// `I64` on 64-bit arch; `I32` on 32-bit arch.
|
||||||
fn pointer_type(&self) -> ir::Type {
|
fn pointer_type(&self) -> ir::Type {
|
||||||
ir::Type::int(u16::from(self.module.config.pointer_bits())).unwrap()
|
ir::Type::int(u16::from(self.module.config.pointer_bits())).unwrap()
|
||||||
@ -377,11 +387,8 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
|||||||
///
|
///
|
||||||
/// The index space covers both imported and locally declared memories.
|
/// The index space covers both imported and locally declared memories.
|
||||||
fn make_heap(&mut self, func: &mut ir::Function, index: MemoryIndex) -> ir::Heap {
|
fn make_heap(&mut self, func: &mut ir::Function, index: MemoryIndex) -> ir::Heap {
|
||||||
debug_assert_eq!(
|
// Only the first memory is supported for now.
|
||||||
index.index(),
|
debug_assert_eq!(index.index(), 0, "non-default memories not supported yet");
|
||||||
0,
|
|
||||||
"non-default memories not supported yet"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create VMContext value.
|
// Create VMContext value.
|
||||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||||
@ -425,11 +432,8 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
|||||||
///
|
///
|
||||||
/// The index space covers both imported and locally declared tables.
|
/// The index space covers both imported and locally declared tables.
|
||||||
fn make_table(&mut self, func: &mut ir::Function, index: TableIndex) -> ir::Table {
|
fn make_table(&mut self, func: &mut ir::Function, index: TableIndex) -> ir::Table {
|
||||||
debug_assert_eq!(
|
// Only the first table is supported for now.
|
||||||
index.index(),
|
debug_assert_eq!(index.index(), 0, "non-default tables not supported yet");
|
||||||
0,
|
|
||||||
"non-default tables not supported yet"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create VMContext value.
|
// Create VMContext value.
|
||||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext);
|
||||||
@ -474,10 +478,12 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets up a signature definition in `func`'s preamble
|
/// Sets up a signature definition in `func`'s preamble.
|
||||||
|
///
|
||||||
/// Signature may contain additional argument, but arguments marked as ArgumentPurpose::Normal`
|
/// Signature may contain additional argument, but arguments marked as ArgumentPurpose::Normal`
|
||||||
/// must correspond to the arguments in the wasm signature
|
/// must correspond to the arguments in the wasm signature
|
||||||
fn make_indirect_sig(&mut self, func: &mut ir::Function, index: SignatureIndex) -> ir::SigRef {
|
fn make_indirect_sig(&mut self, func: &mut ir::Function, index: SignatureIndex) -> ir::SigRef {
|
||||||
|
// Create a signature reference out of specified signature (with VMContext param added).
|
||||||
func.import_signature(self.generate_signature(index))
|
func.import_signature(self.generate_signature(index))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,9 +492,16 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
|||||||
///
|
///
|
||||||
/// The index space covers both imported functions and functions defined in the current module.
|
/// The index space covers both imported functions and functions defined in the current module.
|
||||||
fn make_direct_func(&mut self, func: &mut ir::Function, index: FuncIndex) -> ir::FuncRef {
|
fn make_direct_func(&mut self, func: &mut ir::Function, index: FuncIndex) -> ir::FuncRef {
|
||||||
|
// Get signature of function.
|
||||||
let signature_index = self.module.get_func_type(index);
|
let signature_index = self.module.get_func_type(index);
|
||||||
|
|
||||||
|
// Create a signature reference from specified signature (with VMContext param added).
|
||||||
let signature = func.import_signature(self.generate_signature(signature_index));
|
let signature = func.import_signature(self.generate_signature(signature_index));
|
||||||
|
|
||||||
|
// Get name of function.
|
||||||
let name = ExternalName::user(0, index.as_u32());
|
let name = ExternalName::user(0, index.as_u32());
|
||||||
|
|
||||||
|
// Create function reference from fuction data.
|
||||||
func.import_function(ir::ExtFuncData {
|
func.import_function(ir::ExtFuncData {
|
||||||
name,
|
name,
|
||||||
signature,
|
signature,
|
||||||
@ -496,10 +509,12 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates an indirect call IR with `callee` and `call_args`
|
/// Generates an indirect call IR with `callee` and `call_args`.
|
||||||
|
///
|
||||||
/// Inserts instructions at `pos` to the function `callee` in the table
|
/// Inserts instructions at `pos` to the function `callee` in the table
|
||||||
/// `table_index` with WebAssembly signature `sig_index`
|
/// `table_index` with WebAssembly signature `sig_index`
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
|
/// TODO: Generate bounds checking code.
|
||||||
|
#[cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))]
|
||||||
fn translate_call_indirect(
|
fn translate_call_indirect(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut pos: FuncCursor,
|
mut pos: FuncCursor,
|
||||||
@ -510,29 +525,30 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
|||||||
callee: ir::Value,
|
callee: ir::Value,
|
||||||
call_args: &[ir::Value],
|
call_args: &[ir::Value],
|
||||||
) -> WasmResult<ir::Inst> {
|
) -> WasmResult<ir::Inst> {
|
||||||
// Pass the current function's vmctx parameter on to the callee.
|
// Create a VMContext value.
|
||||||
let vmctx = pos
|
let vmctx = pos
|
||||||
.func
|
.func
|
||||||
.special_param(ir::ArgumentPurpose::VMContext)
|
.special_param(ir::ArgumentPurpose::VMContext)
|
||||||
.expect("Missing vmctx parameter");
|
.expect("missing vmctx parameter");
|
||||||
|
|
||||||
|
// Get the pointer type based on machine's pointer size.
|
||||||
|
let ptr_type = self.pointer_type();
|
||||||
|
|
||||||
// The `callee` value is an index into a table of function pointers.
|
// The `callee` value is an index into a table of function pointers.
|
||||||
// Apparently, that table is stored at absolute address 0 in this dummy environment.
|
// Set callee to an appropriate type based on machine's pointer size.
|
||||||
// TODO: Generate bounds checking code.
|
|
||||||
let ptr_type = self.pointer_type();
|
|
||||||
let callee_offset = if ptr_type == I32 {
|
let callee_offset = if ptr_type == I32 {
|
||||||
callee
|
callee
|
||||||
} else {
|
} else {
|
||||||
pos.ins().uextend(ptr_type, callee)
|
pos.ins().uextend(ptr_type, callee)
|
||||||
};
|
};
|
||||||
// let entry_size = native_pointer_size() as i64 * 2;
|
|
||||||
// let callee_scaled = pos.ins().imul_imm(callee_offset, entry_size);
|
|
||||||
|
|
||||||
|
// The `callee` value is an index into a table of function pointers.
|
||||||
let entry_addr = pos.ins().table_addr(ptr_type, table, callee_offset, 0);
|
let entry_addr = pos.ins().table_addr(ptr_type, table, callee_offset, 0);
|
||||||
|
|
||||||
let mut mflags = ir::MemFlags::new();
|
let mut mflags = ir::MemFlags::new();
|
||||||
mflags.set_notrap();
|
mflags.set_notrap();
|
||||||
mflags.set_aligned();
|
mflags.set_aligned();
|
||||||
|
|
||||||
let func_ptr = pos.ins().load(ptr_type, mflags, entry_addr, 0);
|
let func_ptr = pos.ins().load(ptr_type, mflags, entry_addr, 0);
|
||||||
|
|
||||||
pos.ins().trapz(func_ptr, TrapCode::IndirectCallToNull);
|
pos.ins().trapz(func_ptr, TrapCode::IndirectCallToNull);
|
||||||
@ -560,12 +576,16 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
|||||||
callee: ir::FuncRef,
|
callee: ir::FuncRef,
|
||||||
call_args: &[ir::Value],
|
call_args: &[ir::Value],
|
||||||
) -> WasmResult<ir::Inst> {
|
) -> WasmResult<ir::Inst> {
|
||||||
|
// Insert call instructions for `callee`.
|
||||||
Ok(pos.ins().call(callee, call_args))
|
Ok(pos.ins().call(callee, call_args))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates code corresponding to wasm `memory.grow`
|
/// Generates code corresponding to wasm `memory.grow`.
|
||||||
|
///
|
||||||
/// `index` refers to the linear memory to query.
|
/// `index` refers to the linear memory to query.
|
||||||
|
///
|
||||||
/// `heap` refers to the IR generated by `make_heap`.
|
/// `heap` refers to the IR generated by `make_heap`.
|
||||||
|
///
|
||||||
/// `val` refers the value to grow the memory by.
|
/// `val` refers the value to grow the memory by.
|
||||||
fn translate_memory_grow(
|
fn translate_memory_grow(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -574,96 +594,114 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> {
|
|||||||
heap: ir::Heap,
|
heap: ir::Heap,
|
||||||
val: ir::Value,
|
val: ir::Value,
|
||||||
) -> WasmResult<ir::Value> {
|
) -> WasmResult<ir::Value> {
|
||||||
|
// Only the first memory is supported for now.
|
||||||
let grow_mem_func = self.module.grow_memory_extfunc.unwrap_or_else(|| {
|
let grow_mem_func = self.module.grow_memory_extfunc.unwrap_or_else(|| {
|
||||||
let sig_ref = pos.func.import_signature(Signature {
|
// Create signature reference from specified signature.
|
||||||
call_conv: CallConv::SystemV,
|
let signature_ref = pos.func.import_signature(Signature {
|
||||||
// argument_bytes: None,
|
// Get the default calling convention of the isa.
|
||||||
|
call_conv: self.module.config.default_call_conv,
|
||||||
|
// Paramters types.
|
||||||
params: vec![
|
params: vec![
|
||||||
// Size
|
// Param for new size.
|
||||||
AbiParam::new(I32),
|
AbiParam::new(I32),
|
||||||
// Memory index
|
// Param for memory index.
|
||||||
AbiParam::new(I32),
|
AbiParam::new(I32),
|
||||||
// VMContext
|
// Param for VMcontext.
|
||||||
AbiParam::special(self.pointer_type(), ArgumentPurpose::VMContext),
|
AbiParam::special(self.pointer_type(), ArgumentPurpose::VMContext),
|
||||||
],
|
],
|
||||||
|
// Return type for previous memory size.
|
||||||
returns: vec![AbiParam::new(I32)],
|
returns: vec![AbiParam::new(I32)],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Create function reference to a linked `grow_memory` function.
|
||||||
pos.func.import_function(ExtFuncData {
|
pos.func.import_function(ExtFuncData {
|
||||||
name: ExternalName::testcase("grow_memory"),
|
name: ExternalName::testcase("grow_memory"),
|
||||||
signature: sig_ref,
|
signature: signature_ref,
|
||||||
colocated: false,
|
colocated: false,
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
// self.mod_info.grow_memory_extfunc = Some(grow_mem_func);
|
// Create a memory index value.
|
||||||
let memory_index_value = pos.ins().iconst(I32, to_imm64(index.index()));
|
let memory_index = pos.ins().iconst(I32, to_imm64(index.index()));
|
||||||
let vmctx = pos.func.special_param(ArgumentPurpose::VMContext).unwrap();
|
|
||||||
|
|
||||||
let call_inst = pos
|
// Create a VMContext value.
|
||||||
.ins()
|
let vmctx = pos
|
||||||
.call(grow_mem_func, &[val, memory_index_value, vmctx]);
|
.func
|
||||||
|
.special_param(ArgumentPurpose::VMContext)
|
||||||
|
.expect("missing vmctx parameter");
|
||||||
|
|
||||||
|
// Insert call instructions for `grow_memory`.
|
||||||
|
let call_inst = pos.ins().call(grow_mem_func, &[val, memory_index, vmctx]);
|
||||||
|
|
||||||
|
// Return value.
|
||||||
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates code corresponding to wasm `memory.size`
|
/// Generates code corresponding to wasm `memory.size`.
|
||||||
|
///
|
||||||
/// `index` refers to the linear memory to query.
|
/// `index` refers to the linear memory to query.
|
||||||
/// `heap` refers to the IR generated by `make_heap`
|
///
|
||||||
|
/// `heap` refers to the IR generated by `make_heap`.
|
||||||
fn translate_memory_size(
|
fn translate_memory_size(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut pos: FuncCursor,
|
mut pos: FuncCursor,
|
||||||
index: MemoryIndex,
|
index: MemoryIndex,
|
||||||
heap: ir::Heap,
|
heap: ir::Heap,
|
||||||
) -> WasmResult<ir::Value> {
|
) -> WasmResult<ir::Value> {
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(index.index(), 0, "non-default memories not supported yet");
|
||||||
index.index(),
|
// Only the first memory is supported for now.
|
||||||
0,
|
|
||||||
"non-default memories not supported yet"
|
|
||||||
);
|
|
||||||
|
|
||||||
let cur_mem_func = self.module.current_memory_extfunc.unwrap_or_else(|| {
|
let cur_mem_func = self.module.current_memory_extfunc.unwrap_or_else(|| {
|
||||||
let sig_ref = pos.func.import_signature(Signature {
|
// Create signature reference from specified signature.
|
||||||
call_conv: CallConv::SystemV,
|
let signature_ref = pos.func.import_signature(Signature {
|
||||||
// argument_bytes: None,
|
// Get the default calling convention of the isa.
|
||||||
|
call_conv: self.module.config.default_call_conv,
|
||||||
|
// Paramters types.
|
||||||
params: vec![
|
params: vec![
|
||||||
// The memory index
|
// Param for memory index.
|
||||||
AbiParam::new(I32),
|
AbiParam::new(I32),
|
||||||
// The vmctx reference
|
// Param for VMcontext.
|
||||||
AbiParam::special(self.pointer_type(), ArgumentPurpose::VMContext),
|
AbiParam::special(self.pointer_type(), ArgumentPurpose::VMContext),
|
||||||
// AbiParam::special(I64, ArgumentPurpose::VMContext),
|
|
||||||
],
|
],
|
||||||
|
// Return type for current memory size.
|
||||||
returns: vec![AbiParam::new(I32)],
|
returns: vec![AbiParam::new(I32)],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Create function reference to a linked `current_memory` function.
|
||||||
pos.func.import_function(ExtFuncData {
|
pos.func.import_function(ExtFuncData {
|
||||||
name: ExternalName::testcase("current_memory"),
|
name: ExternalName::testcase("current_memory"),
|
||||||
signature: sig_ref,
|
signature: signature_ref,
|
||||||
colocated: false,
|
colocated: false,
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
// self.mod_info.current_memory_extfunc = cur_mem_func;
|
// Create a memory index value.
|
||||||
|
|
||||||
let memory_index_value = pos.ins().iconst(I32, to_imm64(index.index()));
|
let memory_index_value = pos.ins().iconst(I32, to_imm64(index.index()));
|
||||||
|
|
||||||
|
// Create a VMContext value.
|
||||||
let vmctx = pos.func.special_param(ArgumentPurpose::VMContext).unwrap();
|
let vmctx = pos.func.special_param(ArgumentPurpose::VMContext).unwrap();
|
||||||
|
|
||||||
|
// Insert call instructions for `current_memory`.
|
||||||
let call_inst = pos.ins().call(cur_mem_func, &[memory_index_value, vmctx]);
|
let call_inst = pos.ins().call(cur_mem_func, &[memory_index_value, vmctx]);
|
||||||
|
|
||||||
|
// Return value.
|
||||||
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates code at the beginning of loops.
|
/// Generates code at the beginning of loops.
|
||||||
|
///
|
||||||
/// Currently not used.
|
/// Currently not used.
|
||||||
fn translate_loop_header(&mut self, _pos: FuncCursor) {
|
fn translate_loop_header(&mut self, _pos: FuncCursor) {
|
||||||
// By default, don't emit anything.
|
// By default, don't emit anything.
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines the type of return each function should have.
|
/// Determines the type of return each function should have.
|
||||||
/// It normal returns for now.
|
///
|
||||||
|
/// It is normal returns for now.
|
||||||
fn return_mode(&self) -> ReturnMode {
|
fn return_mode(&self) -> ReturnMode {
|
||||||
ReturnMode::NormalReturns
|
ReturnMode::NormalReturns
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a usize offset into a `Imm64` for an iadd_imm.
|
/// Convert a usize offset into a `Imm64` for an iadd_imm.
|
||||||
fn to_imm64(offset: usize) -> ir::immediates::Imm64 {
|
fn to_imm64(offset: usize) -> ir::immediates::Imm64 {
|
||||||
(offset as i64).into()
|
(offset as i64).into()
|
||||||
@ -678,7 +716,6 @@ impl<'data> ModuleEnvironment<'data> for CraneliftModule {
|
|||||||
/// Declares a function signature to the environment.
|
/// Declares a function signature to the environment.
|
||||||
fn declare_signature(&mut self, sig: &ir::Signature) {
|
fn declare_signature(&mut self, sig: &ir::Signature) {
|
||||||
self.signatures.push(sig.clone());
|
self.signatures.push(sig.clone());
|
||||||
// TODO: push to signatures_assoc here.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the signature with the given index.
|
/// Return the signature with the given index.
|
||||||
@ -698,9 +735,8 @@ impl<'data> ModuleEnvironment<'data> for CraneliftModule {
|
|||||||
self.functions.push(sig_index);
|
self.functions.push(sig_index);
|
||||||
|
|
||||||
// Add import names to list of imported functions
|
// Add import names to list of imported functions
|
||||||
self.imported_functions.push(
|
self.imported_functions
|
||||||
(String::from(module), String::from(field)).into()
|
.push((String::from(module), String::from(field)).into());
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the number of imported funcs.
|
/// Return the number of imported funcs.
|
||||||
@ -742,7 +778,7 @@ impl<'data> ModuleEnvironment<'data> for CraneliftModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Declares a table to the environment.
|
/// Declares a table to the environment.
|
||||||
fn declare_table(&mut self, table: Table){
|
fn declare_table(&mut self, table: Table) {
|
||||||
// Add table ir to the list of tables
|
// Add table ir to the list of tables
|
||||||
self.tables.push(table);
|
self.tables.push(table);
|
||||||
}
|
}
|
||||||
@ -775,9 +811,10 @@ impl<'data> ModuleEnvironment<'data> for CraneliftModule {
|
|||||||
table_index: WasmerTableIndex::new(table_index.index()),
|
table_index: WasmerTableIndex::new(table_index.index()),
|
||||||
base,
|
base,
|
||||||
offset,
|
offset,
|
||||||
elements: elements.iter().map(
|
elements: elements
|
||||||
|index| WasmerFuncIndex::new(index.index())
|
.iter()
|
||||||
).collect(),
|
.map(|index| WasmerFuncIndex::new(index.index()))
|
||||||
|
.collect(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -874,8 +911,7 @@ impl<'data> ModuleEnvironment<'data> for CraneliftModule {
|
|||||||
let mut function = ir::Function::with_name_signature(name, sig);
|
let mut function = ir::Function::with_name_signature(name, sig);
|
||||||
|
|
||||||
// Complete function creation with translated function body.
|
// Complete function creation with translated function body.
|
||||||
FuncTranslator::new()
|
FuncTranslator::new().translate(body_bytes, &mut function, &mut func_environ)?;
|
||||||
.translate(body_bytes, &mut function, &mut func_environ)?;
|
|
||||||
|
|
||||||
function
|
function
|
||||||
};
|
};
|
||||||
@ -886,10 +922,3 @@ impl<'data> ModuleEnvironment<'data> for CraneliftModule {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MockFuncResolver {}
|
|
||||||
impl FuncResolver for MockFuncResolver {
|
|
||||||
fn get(&self, module: &WasmerModule, index: WasmerFuncIndex) -> Option<NonNull<vm::Func>> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -10,6 +10,12 @@ use crate::webassembly;
|
|||||||
|
|
||||||
pub struct CraneliftCompiler {}
|
pub struct CraneliftCompiler {}
|
||||||
|
|
||||||
|
impl CraneliftCompiler {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Compiler for CraneliftCompiler {
|
impl Compiler for CraneliftCompiler {
|
||||||
// Compiles wasm binary to a wasmer module
|
// Compiles wasm binary to a wasmer module
|
||||||
fn compile(&self, wasm: &[u8]) -> Result<Arc<Module>, String> {
|
fn compile(&self, wasm: &[u8]) -> Result<Arc<Module>, String> {
|
||||||
@ -17,7 +23,7 @@ impl Compiler for CraneliftCompiler {
|
|||||||
|
|
||||||
let isa = webassembly::get_isa();
|
let isa = webassembly::get_isa();
|
||||||
// Generate a Cranlift module from wasm binary
|
// Generate a Cranlift module from wasm binary
|
||||||
let cranelift_module = CraneliftModule::from_bytes(wasm.to_vec(), isa.frontend_config())
|
let cranelift_module = CraneliftModule::from_bytes(&wasm.to_vec(), isa.frontend_config())
|
||||||
.map_err(|err| format!("{}", err))?;
|
.map_err(|err| format!("{}", err))?;
|
||||||
|
|
||||||
// Convert Cranelift module to wasmer module
|
// Convert Cranelift module to wasmer module
|
||||||
|
@ -65,7 +65,7 @@ pub fn instantiate(
|
|||||||
debug!("webassembly - creating instance");
|
debug!("webassembly - creating instance");
|
||||||
|
|
||||||
//let instance = Instance::new(&module, import_object, options)?;
|
//let instance = Instance::new(&module, import_object, options)?;
|
||||||
let instance = runtime::instantiate(buffer_source, &CraneliftCompiler {}, import_object)
|
let instance = runtime::instantiate(buffer_source, &CraneliftCompiler::new(), import_object)
|
||||||
.map_err(|e| ErrorKind::CompileError(e))?;
|
.map_err(|e| ErrorKind::CompileError(e))?;
|
||||||
|
|
||||||
let isa = get_isa();
|
let isa = get_isa();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user