Add signatures conversion

This commit is contained in:
Steve Akinyemi 2018-12-31 14:20:05 +01:00
parent 95dc292637
commit 9af9e75bfd
3 changed files with 178 additions and 143 deletions

View File

@ -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!()
}
}

View File

@ -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

View File

@ -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();