Stack allocate arguments

This commit is contained in:
Lachlan Sneff 2018-12-06 15:21:58 -05:00
parent 266ced4311
commit 28a668f38c
3 changed files with 34 additions and 15 deletions

View File

@ -17,30 +17,41 @@ pub fn is_emscripten_module(module: &Module) -> bool {
return false;
}
pub unsafe fn copy_cstr_into_wasm(instance: &Instance, cstr: *const c_char) -> u32 {
pub unsafe fn copy_cstr_into_wasm(instance: &mut Instance, cstr: *const c_char) -> u32 {
let s = CStr::from_ptr(cstr).to_str().unwrap();
let space_offset = (instance.emscripten_data.as_ref().unwrap().malloc)(s.len() as _, instance);
let cstr_len = s.len();
let space_offset = (instance.emscripten_data.as_ref().unwrap().stack_alloc)((cstr_len as u32) + 1, instance);
let raw_memory = instance.memory_offset_addr(0, space_offset as _) as *mut u8;
let slice = slice::from_raw_parts_mut(raw_memory, s.len());
let slice = slice::from_raw_parts_mut(raw_memory, cstr_len);
for (byte, loc) in s.bytes().zip(slice.iter_mut()) {
*loc = byte;
}
*raw_memory.add(cstr_len) = 0;
space_offset
}
pub unsafe fn copy_cstr_array_into_wasm(array_count: u32, array: *mut *mut c_char, instance: &Instance) -> u32 {
let array_offset = (instance.emscripten_data.as_ref().unwrap().malloc)((array_count as usize * size_of::<u32>()) as _, instance);
pub unsafe fn copy_cstr_array_into_wasm(array_count: u32, array: *mut *mut c_char, instance: &mut Instance) -> u32 {
let array_offset = (instance.emscripten_data.as_ref().unwrap().stack_alloc)((array_count as usize * size_of::<u32>()) as _, instance);
let array_addr = instance.memory_offset_addr(0, array_offset as _) as *mut u32;
for i in 0..array_count {
let offset = copy_cstr_into_wasm(
instance,
*array.offset(i as isize)
);
*array_addr.offset(i as isize) = offset;
let array_slice = slice::from_raw_parts_mut(array_addr, array_count as usize);
for (i, ptr) in array_slice.iter_mut().enumerate() {
let offset = copy_cstr_into_wasm(instance, *array.add(i));
*ptr = offset;
}
// for i in 0..array_count {
// let offset = copy_cstr_into_wasm(
// instance,
// *array.offset(i as isize)
// );
// *array_addr.offset(i as isize) = offset;
// }
// let first_arg_addr = instance.memory_offset_addr(0, *array_addr.offset(0) as _) as *const i8;
// debug!("###### argv[0] = {:?}", CStr::from_ptr(first_arg_addr));

View File

@ -68,7 +68,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
// TODO: We should instantiate after compilation, so we provide the
// emscripten environment conditionally based on the module
let import_object = apis::generate_emscripten_env();
let webassembly::ResultObject { module, instance } =
let webassembly::ResultObject { module, mut instance } =
webassembly::instantiate(wasm_binary, import_object)
.map_err(|err| format!("Can't instantiate the WebAssembly module: {}", err))?;
@ -91,7 +91,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
let main: extern "C" fn(u32, u32, &webassembly::Instance) =
get_instance_function!(instance, func_index);
let (argc, argv) = get_module_arguments(options, &instance);
let (argc, argv) = get_module_arguments(options, &mut instance);
return call_protected!(main(argc, argv, &instance)).map_err(|err| format!("{}", err));
// TODO: We should implement emscripten __ATEXIT__
@ -128,7 +128,7 @@ fn main() {
}
}
fn get_module_arguments(options: &Run, instance: &webassembly::Instance) -> (u32, u32) {
fn get_module_arguments(options: &Run, instance: &mut webassembly::Instance) -> (u32, u32) {
// Application Arguments
let mut arg_values: Vec<String> = Vec::new();
let mut arg_addrs: Vec<*const u8> = Vec::new();
@ -153,7 +153,7 @@ fn get_module_arguments(options: &Run, instance: &webassembly::Instance) -> (u32
// Copy the the arguments into the wasm memory and get offset
let argv_offset = unsafe {
copy_cstr_array_into_wasm(argc, argv, &instance)
copy_cstr_array_into_wasm(argc, argv, instance)
};
debug!("argc = {:?}", argc);

View File

@ -74,6 +74,7 @@ pub struct EmscriptenData {
pub free: extern "C" fn(i32, &mut Instance),
pub memalign: extern "C" fn (u32, u32, &mut Instance) -> u32,
pub memset: extern "C" fn(u32, i32, u32, &mut Instance) -> u32,
pub stack_alloc: extern "C" fn (u32, &mut Instance) -> u32,
}
impl fmt::Debug for EmscriptenData {
@ -550,11 +551,13 @@ impl Instance {
let free_export = module.info.exports.get("_free");
let memalign_export = module.info.exports.get("_memalign");
let memset_export = module.info.exports.get("_memset");
let stack_alloc_export = module.info.exports.get("stackAlloc");
let mut malloc_addr = 0 as *const u8;
let mut free_addr = 0 as *const u8;
let mut memalign_addr = 0 as *const u8;
let mut memset_addr = 0 as *const u8;
let mut stack_alloc_addr = 0 as _;
if malloc_export.is_none() && free_export.is_none() && memalign_export.is_none() && memset_export.is_none() {
None
@ -575,11 +578,16 @@ impl Instance {
memset_addr = get_function_addr(&memset_index, &import_functions, &functions);
}
if let Some(Export::Function(stack_alloc_index)) = stack_alloc_export {
stack_alloc_addr = get_function_addr(&stack_alloc_index, &import_functions, &functions);
}
Some(EmscriptenData {
malloc: mem::transmute(malloc_addr),
free: mem::transmute(free_addr),
memalign: mem::transmute(memalign_addr),
memset: mem::transmute(memset_addr),
stack_alloc: mem::transmute(stack_alloc_addr),
})
}
}