Added APIs to support conditional emscripten instantiation

This commit is contained in:
Syrus Akbary 2018-11-20 20:51:11 -08:00
parent 3f1a6e5ac6
commit 5ad5606b39
6 changed files with 84 additions and 12 deletions

View File

@ -4,9 +4,11 @@ use crate::webassembly::{ImportObject, ImportValue};
mod memory; mod memory;
mod process; mod process;
mod io; mod io;
mod utils;
// SYSCALLS // SYSCALLS
use super::host; use super::host;
pub use self::utils::is_emscripten_module;
pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> {
let mut import_object = ImportObject::new(); let mut import_object = ImportObject::new();

View File

@ -0,0 +1,9 @@
(module
(table 0 anyfunc)
(memory $0 1)
(export "memory" (memory $0))
(export "main" (func $main))
(func $main (; 1 ;) (result i32)
(i32.const 0)
)
)

View File

@ -0,0 +1,17 @@
(module
(type $FUNCSIG$ii (func (param i32) (result i32)))
(import "env" "puts" (func $puts (param i32) (result i32)))
(table 0 anyfunc)
(memory $0 1)
(data (i32.const 16) "hello, world!\00")
(export "memory" (memory $0))
(export "main" (func $main))
(func $main (; 1 ;) (result i32)
(drop
(call $puts
(i32.const 16)
)
)
(i32.const 0)
)
)

View File

@ -0,0 +1,35 @@
use crate::webassembly::module::Module;
/// We check if a provided module is an Emscripten generated one
pub fn is_emscripten_module(module: &Module) -> bool {
for (module, field) in &module.info.imported_funcs {
if module == "env" {
return true;
}
}
return false;
}
#[cfg(test)]
mod tests {
use crate::webassembly::instantiate;
use super::is_emscripten_module;
use super::super::generate_emscripten_env;
#[test]
fn should_detect_emscripten_files() {
let wasm_bytes = include_wast2wasm_bytes!("tests/is_emscripten_true.wast");
let import_object = generate_emscripten_env();
let result_object = instantiate(wasm_bytes, import_object).expect("Not compiled properly");
assert!(is_emscripten_module(&result_object.module));
}
#[test]
fn should_detect_non_emscripten_files() {
let wasm_bytes = include_wast2wasm_bytes!("tests/is_emscripten_false.wast");
let import_object = generate_emscripten_env();
let result_object = instantiate(wasm_bytes, import_object).expect("Not compiled properly");
assert!(!is_emscripten_module(&result_object.module));
}
}

View File

@ -1,5 +1,4 @@
pub mod emscripten; pub mod emscripten;
pub mod host; pub mod host;
pub use self::emscripten::generate_emscripten_env; pub use self::emscripten::{generate_emscripten_env, is_emscripten_module};

View File

@ -71,22 +71,32 @@ fn execute_wasm(wasm_path: PathBuf) -> Result<(), String> {
wasm_binary = wabt::wat2wasm(wasm_binary) wasm_binary = wabt::wat2wasm(wasm_binary)
.map_err(|err| format!("Can't convert from wast to wasm: {:?}", err))?; .map_err(|err| format!("Can't convert from wast to wasm: {:?}", err))?;
} }
// 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 import_object = apis::generate_emscripten_env();
let webassembly::ResultObject { module, instance } = let webassembly::ResultObject { module, instance } =
webassembly::instantiate(wasm_binary, import_object) webassembly::instantiate(wasm_binary, import_object)
.map_err(|err| format!("Can't instantiate the WebAssembly module: {}", err))?; .map_err(|err| format!("Can't instantiate the WebAssembly module: {}", err))?;
// webassembly::utils::print_instance_offsets(&instance); if apis::is_emscripten_module(&module) {
let func_index = match module.info.exports.get("main") {
Some(&webassembly::Export::Function(index)) => index,
_ => panic!("_main emscripten function not found"),
};
let main: extern fn(u32, u32, &webassembly::Instance) = get_instance_function!(instance, func_index);
main(0, 0, &instance);
}
else {
let func_index = instance let func_index = instance
.start_func .start_func
.unwrap_or_else(|| match module.info.exports.get("main").or(module.info.exports.get("_main")) { .unwrap_or_else(|| match module.info.exports.get("main") {
Some(&webassembly::Export::Function(index)) => index, Some(&webassembly::Export::Function(index)) => index,
_ => panic!("Main function not found"), _ => panic!("Main function not found"),
}); });
let main: extern fn(u32, u32, &webassembly::Instance) = get_instance_function!(instance, func_index); let main: extern fn(&webassembly::Instance) = get_instance_function!(instance, func_index);
main(0, 0, &instance); main(&instance);
}
Ok(()) Ok(())
} }