mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-26 15:11:37 +00:00
Move the em specific run_instance code into em lib
This commit is contained in:
@ -5,15 +5,20 @@ use byteorder::{ByteOrder, LittleEndian};
|
|||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use std::{mem::size_of, panic, slice};
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
|
error::{CallError, CallResult},
|
||||||
export::{Context, Export, FuncPointer, GlobalPointer, MemoryPointer, TablePointer},
|
export::{Context, Export, FuncPointer, GlobalPointer, MemoryPointer, TablePointer},
|
||||||
import::{ImportObject, Namespace},
|
import::{ImportObject, Namespace},
|
||||||
|
instance::Instance,
|
||||||
memory::LinearMemory,
|
memory::LinearMemory,
|
||||||
|
module::Module,
|
||||||
structures::TypedIndex,
|
structures::TypedIndex,
|
||||||
table::TableBacking,
|
table::TableBacking,
|
||||||
types::{
|
types::{
|
||||||
ElementType, FuncSig, GlobalDesc, LocalMemoryIndex, Memory, Table,
|
ElementType, FuncSig, GlobalDesc, LocalMemoryIndex, Memory, Table,
|
||||||
Type::{self, *},
|
Type::{self, *},
|
||||||
|
Value,
|
||||||
},
|
},
|
||||||
vm::LocalGlobal,
|
vm::LocalGlobal,
|
||||||
vm::LocalMemory,
|
vm::LocalMemory,
|
||||||
@ -86,6 +91,135 @@ fn dynamictop_ptr(static_bump: u32) -> u32 {
|
|||||||
// pub jumps: Vec<UnsafeCell<[c_int; 27]>>,
|
// pub jumps: Vec<UnsafeCell<[c_int; 27]>>,
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
pub fn run_emscripten_instance(
|
||||||
|
module: &Module,
|
||||||
|
instance: &mut Instance,
|
||||||
|
_path: &str,
|
||||||
|
args: Vec<&str>,
|
||||||
|
) -> CallResult<()> {
|
||||||
|
// TODO atinit and atexit for emscripten
|
||||||
|
|
||||||
|
// Get main arguments.
|
||||||
|
let main_args = get_main_args("_main", args, instance).unwrap();
|
||||||
|
|
||||||
|
// Call main function with the arguments.
|
||||||
|
instance.call("_main", &main_args)?;
|
||||||
|
|
||||||
|
// TODO atinit and atexit for emscripten
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Passes arguments from the host to the WebAssembly instance.
|
||||||
|
fn get_main_args(
|
||||||
|
main_name: &str,
|
||||||
|
args: Vec<&str>,
|
||||||
|
instance: &mut Instance,
|
||||||
|
) -> CallResult<Vec<Value>> {
|
||||||
|
// Getting main function signature.
|
||||||
|
let func_sig = instance.get_signature(main_name)?;
|
||||||
|
let params = &func_sig.params;
|
||||||
|
|
||||||
|
// Check for a () or (i32, i32) sig.
|
||||||
|
match params.as_slice() {
|
||||||
|
&[Type::I32, Type::I32] => {
|
||||||
|
// Copy strings into wasm memory and get addresses to them.
|
||||||
|
let string_addresses = args
|
||||||
|
.iter()
|
||||||
|
.map(|string| copy_string_into_wasm(instance, (*string).to_string()).unwrap())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Create a wasm array to the strings.
|
||||||
|
let array = create_wasm_array(instance, string_addresses).unwrap();
|
||||||
|
|
||||||
|
Ok(vec![
|
||||||
|
Value::I32(array as i32),
|
||||||
|
Value::I32(args.len() as i32),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
&[] => Ok(vec![]),
|
||||||
|
_ => Err(CallError::Signature {
|
||||||
|
expected: FuncSig {
|
||||||
|
params: vec![Type::I32, Type::I32],
|
||||||
|
returns: vec![],
|
||||||
|
},
|
||||||
|
found: params.to_vec(),
|
||||||
|
}
|
||||||
|
.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copy rust string to wasm instance.
|
||||||
|
fn copy_string_into_wasm(instance: &mut Instance, string: String) -> CallResult<u32> {
|
||||||
|
let string_len = string.len();
|
||||||
|
|
||||||
|
let space_offset = instance
|
||||||
|
.call("_malloc", &[Value::I32((string_len as i32) + 1)])
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let space_offset = match space_offset.as_slice() {
|
||||||
|
&[Value::I32(res)] => Some(res as u32),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let raw_memory = instance.inner.vmctx.memory(0)[space_offset as usize] as *mut u8;
|
||||||
|
|
||||||
|
let slice = unsafe { slice::from_raw_parts_mut(raw_memory, string_len) };
|
||||||
|
|
||||||
|
for (byte, loc) in string.bytes().zip(slice.iter_mut()) {
|
||||||
|
*loc = byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { *raw_memory.add(string_len) = 0 };
|
||||||
|
|
||||||
|
Ok(space_offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a pointer to an array of items in a wasm memory
|
||||||
|
fn create_wasm_array(instance: &mut Instance, values: Vec<u32>) -> CallResult<u32> {
|
||||||
|
let values_len = values.len();
|
||||||
|
|
||||||
|
// Space to store pointers to values
|
||||||
|
let values_offset = instance
|
||||||
|
.call(
|
||||||
|
"_malloc",
|
||||||
|
&[Value::I32((size_of::<u32>() * values.len()) as i32)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let values_offset = match values_offset.as_slice() {
|
||||||
|
&[Value::I32(res)] => Some(res as u32),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let raw_memory = instance.inner.vmctx.memory(0)[values_offset as usize] as *mut u32;
|
||||||
|
|
||||||
|
let slice = unsafe { slice::from_raw_parts_mut(raw_memory, values_len) };
|
||||||
|
|
||||||
|
for (value, loc) in values.iter().zip(slice.iter_mut()) {
|
||||||
|
*loc = value.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Space to store pointer to array
|
||||||
|
let array_offset = instance
|
||||||
|
.call("_malloc", &[Value::I32(size_of::<u32>() as i32)])
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let array_offset = match array_offset.as_slice() {
|
||||||
|
&[Value::I32(res)] => Some(res as u32),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let raw_memory = instance.inner.vmctx.memory(0)[values_offset as usize] as *mut u32;
|
||||||
|
|
||||||
|
unsafe { *raw_memory = values_offset };
|
||||||
|
|
||||||
|
Ok(array_offset)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn emscripten_set_up_memory(memory: &mut LinearMemory) {
|
pub fn emscripten_set_up_memory(memory: &mut LinearMemory) {
|
||||||
let dynamictop_ptr = dynamictop_ptr(STATIC_BUMP) as usize;
|
let dynamictop_ptr = dynamictop_ptr(STATIC_BUMP) as usize;
|
||||||
let dynamictop_ptr_offset = dynamictop_ptr + mem::size_of::<u32>();
|
let dynamictop_ptr_offset = dynamictop_ptr + mem::size_of::<u32>();
|
||||||
|
@ -22,26 +22,17 @@ macro_rules! assert_emscripten_output {
|
|||||||
let mut instance = module.instantiate(import_object)
|
let mut instance = module.instantiate(import_object)
|
||||||
.map_err(|err| format!("Can't instantiate the WebAssembly module: {:?}", err)).unwrap(); // NOTE: Need to figure what the unwrap is for ??
|
.map_err(|err| format!("Can't instantiate the WebAssembly module: {:?}", err)).unwrap(); // NOTE: Need to figure what the unwrap is for ??
|
||||||
|
|
||||||
// start_instance(
|
|
||||||
// Arc::clone(&module),
|
|
||||||
// &mut instance,
|
|
||||||
// $name,
|
|
||||||
// $args,
|
|
||||||
// );
|
|
||||||
|
|
||||||
assert!(false, "Emscripten tests are mocked");
|
|
||||||
|
|
||||||
let capturer = StdioCapturer::new();
|
let capturer = StdioCapturer::new();
|
||||||
|
|
||||||
instance.call("_main", &[]).map(|_o| ()).unwrap();
|
instance.call("_main", &[]).map(|_o| ()).unwrap();
|
||||||
// TODO handle start instance logic
|
// TODO handle start instance logic
|
||||||
// start_instance(
|
wasmer_emscripten::run_emscripten_instance(
|
||||||
// Arc::clone(&result_object.module),
|
&module,
|
||||||
// &mut result_object.instance,
|
&mut instance,
|
||||||
// $name,
|
$name,
|
||||||
// $args,
|
$args,
|
||||||
// )
|
);
|
||||||
// .unwrap();
|
|
||||||
let output = capturer.end().unwrap().0;
|
let output = capturer.end().unwrap().0;
|
||||||
let expected_output = include_str!($expected);
|
let expected_output = include_str!($expected);
|
||||||
assert!(false, "Emscripten tests are mocked");
|
assert!(false, "Emscripten tests are mocked");
|
||||||
|
@ -11,7 +11,7 @@ use wasmer_runtime::{
|
|||||||
types::{FuncSig, Type, Value},
|
types::{FuncSig, Type, Value},
|
||||||
};
|
};
|
||||||
|
|
||||||
use wasmer_emscripten::is_emscripten_module;
|
use wasmer_emscripten::{is_emscripten_module, run_emscripten_instance};
|
||||||
|
|
||||||
pub struct ResultObject {
|
pub struct ResultObject {
|
||||||
/// A webassembly::Module object representing the compiled WebAssembly module.
|
/// A webassembly::Module object representing the compiled WebAssembly module.
|
||||||
@ -86,129 +86,14 @@ pub fn compile(buffer_source: &[u8]) -> Result<Module> {
|
|||||||
pub fn run_instance(
|
pub fn run_instance(
|
||||||
module: &Module,
|
module: &Module,
|
||||||
instance: &mut Instance,
|
instance: &mut Instance,
|
||||||
_path: &str,
|
path: &str,
|
||||||
args: Vec<&str>,
|
args: Vec<&str>,
|
||||||
) -> CallResult<()> {
|
) -> CallResult<()> {
|
||||||
let main_name = if is_emscripten_module(module) {
|
if is_emscripten_module(module) {
|
||||||
"_main"
|
run_emscripten_instance(module, instance, path, args);
|
||||||
} else {
|
} else {
|
||||||
"main"
|
instance.call("main", &[])?;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get main arguments.
|
|
||||||
let main_args = get_main_args(main_name, args, instance).unwrap();
|
|
||||||
|
|
||||||
// Call main function with the arguments.
|
|
||||||
instance.call(main_name, &main_args)?;
|
|
||||||
|
|
||||||
// TODO atinit and atexit for emscripten
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Passes arguments from the host to the WebAssembly instance.
|
|
||||||
fn get_main_args(
|
|
||||||
main_name: &str,
|
|
||||||
args: Vec<&str>,
|
|
||||||
instance: &mut Instance,
|
|
||||||
) -> CallResult<Vec<Value>> {
|
|
||||||
// Getting main function signature.
|
|
||||||
let func_sig = instance.get_signature(main_name)?;
|
|
||||||
let params = &func_sig.params;
|
|
||||||
|
|
||||||
// Check for a () or (i32, i32) sig.
|
|
||||||
match params.as_slice() {
|
|
||||||
&[Type::I32, Type::I32] => {
|
|
||||||
// Copy strings into wasm memory and get addresses to them.
|
|
||||||
let string_addresses = args
|
|
||||||
.iter()
|
|
||||||
.map(|string| copy_string_into_wasm(instance, (*string).to_string()).unwrap())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Create a wasm array to the strings.
|
|
||||||
let array = create_wasm_array(instance, string_addresses).unwrap();
|
|
||||||
|
|
||||||
Ok(vec![
|
|
||||||
Value::I32(array as i32),
|
|
||||||
Value::I32(args.len() as i32),
|
|
||||||
])
|
|
||||||
}
|
|
||||||
&[] => Ok(vec![]),
|
|
||||||
_ => Err(CallError::Signature {
|
|
||||||
expected: FuncSig {
|
|
||||||
params: vec![Type::I32, Type::I32],
|
|
||||||
returns: vec![],
|
|
||||||
},
|
|
||||||
found: params.to_vec(),
|
|
||||||
}
|
|
||||||
.into()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Copy rust string to wasm instance.
|
|
||||||
fn copy_string_into_wasm(instance: &mut Instance, string: String) -> CallResult<u32> {
|
|
||||||
let string_len = string.len();
|
|
||||||
|
|
||||||
let space_offset = instance
|
|
||||||
.call("_malloc", &[Value::I32((string_len as i32) + 1)])
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let space_offset = match space_offset.as_slice() {
|
|
||||||
&[Value::I32(res)] => Some(res as u32),
|
|
||||||
_ => None,
|
|
||||||
}.unwrap();
|
|
||||||
|
|
||||||
let raw_memory = instance.inner.vmctx.memory(0)[space_offset as usize] as *mut u8;
|
|
||||||
|
|
||||||
let slice = unsafe { slice::from_raw_parts_mut(raw_memory, string_len) };
|
|
||||||
|
|
||||||
for (byte, loc) in string.bytes().zip(slice.iter_mut()) {
|
|
||||||
*loc = byte;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { *raw_memory.add(string_len) = 0 };
|
|
||||||
|
|
||||||
Ok(space_offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a pointer to an array of items in a wasm memory
|
|
||||||
fn create_wasm_array(instance: &mut Instance, values: Vec<u32>) -> CallResult<u32> {
|
|
||||||
let values_len = values.len();
|
|
||||||
|
|
||||||
// Space to store pointers to values
|
|
||||||
let values_offset = instance
|
|
||||||
.call(
|
|
||||||
"_malloc",
|
|
||||||
&[Value::I32((size_of::<u32>() * values.len()) as i32)],
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let values_offset = match values_offset.as_slice() {
|
|
||||||
&[Value::I32(res)] => Some(res as u32),
|
|
||||||
_ => None,
|
|
||||||
}.unwrap();
|
|
||||||
|
|
||||||
let raw_memory = instance.inner.vmctx.memory(0)[values_offset as usize] as *mut u32;
|
|
||||||
|
|
||||||
let slice = unsafe { slice::from_raw_parts_mut(raw_memory, values_len) };
|
|
||||||
|
|
||||||
for (value, loc) in values.iter().zip(slice.iter_mut()) {
|
|
||||||
*loc = value.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Space to store pointer to array
|
|
||||||
let array_offset = instance
|
|
||||||
.call("_malloc", &[Value::I32(size_of::<u32>() as i32)])
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let array_offset = match array_offset.as_slice() {
|
|
||||||
&[Value::I32(res)] => Some(res as u32),
|
|
||||||
_ => None,
|
|
||||||
}.unwrap();
|
|
||||||
|
|
||||||
let raw_memory = instance.inner.vmctx.memory(0)[values_offset as usize] as *mut u32;
|
|
||||||
|
|
||||||
unsafe { *raw_memory = values_offset };
|
|
||||||
|
|
||||||
Ok(array_offset)
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user