mirror of
https://github.com/fluencelabs/wasmer
synced 2025-03-16 08:10:49 +00:00
Add getting main arguments
This commit is contained in:
parent
c3b0a79877
commit
8661a0096e
@ -16,17 +16,17 @@ use crate::{
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub(crate) struct InstanceInner {
|
||||
pub struct InstanceInner {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) backing: LocalBacking,
|
||||
import_backing: ImportBacking,
|
||||
vmctx: Box<vm::Ctx>,
|
||||
pub vmctx: Box<vm::Ctx>,
|
||||
}
|
||||
|
||||
/// A WebAssembly instance
|
||||
pub struct Instance {
|
||||
pub module: Rc<ModuleInner>,
|
||||
inner: Box<InstanceInner>,
|
||||
pub inner: Box<InstanceInner>,
|
||||
#[allow(dead_code)]
|
||||
imports: Box<ImportObject>,
|
||||
}
|
||||
@ -138,6 +138,33 @@ impl Instance {
|
||||
|
||||
Ok(returns)
|
||||
}
|
||||
|
||||
pub fn get_signature(&self, name: &str) -> CallResult<&FuncSig> {
|
||||
let export_index =
|
||||
self.module
|
||||
.exports
|
||||
.get(name)
|
||||
.ok_or_else(|| CallError::NoSuchExport {
|
||||
name: name.to_string(),
|
||||
})?;
|
||||
|
||||
let func_index = if let ExportIndex::Func(func_index) = export_index {
|
||||
*func_index
|
||||
} else {
|
||||
return Err(CallError::ExportNotFunc {
|
||||
name: name.to_string(),
|
||||
}
|
||||
.into());
|
||||
};
|
||||
|
||||
let sig_index = *self
|
||||
.module
|
||||
.func_assoc
|
||||
.get(func_index)
|
||||
.expect("broken invariant, incorrect func index");
|
||||
|
||||
Ok(self.module.sig_registry.lookup_func_sig(sig_index))
|
||||
}
|
||||
}
|
||||
|
||||
impl InstanceInner {
|
||||
|
@ -70,10 +70,10 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||
.map_err(|e| format!("Can't compile module: {:?}", e))?;
|
||||
|
||||
let (_abi, import_object) = if wasmer_emscripten::is_emscripten_module(&module) {
|
||||
let emscripten_globals = wasmer_emscripten::EmscriptenGlobals::new();
|
||||
let mut emscripten_globals = wasmer_emscripten::EmscriptenGlobals::new();
|
||||
(
|
||||
InstanceABI::Emscripten,
|
||||
wasmer_emscripten::generate_emscripten_env(&emscripten_globals),
|
||||
wasmer_emscripten::generate_emscripten_env(&mut emscripten_globals),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
|
@ -1,14 +1,16 @@
|
||||
pub mod utils;
|
||||
|
||||
use std::{mem::size_of, panic, slice};
|
||||
use wasmer_runtime::{
|
||||
self as runtime,
|
||||
error::CallError,
|
||||
error::{CallResult, Result},
|
||||
import::ImportObject,
|
||||
instance::Instance,
|
||||
module::Module,
|
||||
types::{FuncSig, Type, Value},
|
||||
};
|
||||
|
||||
use std::panic;
|
||||
use wasmer_emscripten::is_emscripten_module;
|
||||
|
||||
pub struct ResultObject {
|
||||
@ -85,7 +87,7 @@ pub fn run_instance(
|
||||
module: &Module,
|
||||
instance: &mut Instance,
|
||||
_path: &str,
|
||||
_args: Vec<&str>,
|
||||
args: Vec<&str>,
|
||||
) -> CallResult<()> {
|
||||
let main_name = if is_emscripten_module(module) {
|
||||
"_main"
|
||||
@ -93,9 +95,120 @@ pub fn run_instance(
|
||||
"main"
|
||||
};
|
||||
|
||||
// TODO handle args
|
||||
instance.call(main_name, &[])?;
|
||||
// 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(())
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user