diff --git a/Cargo.lock b/Cargo.lock index 0b062168f..5eddfcff2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1204,6 +1204,7 @@ dependencies = [ "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "wasmer-clif-backend 0.1.2", "wasmer-emscripten 0.1.0", + "wasmer-golang 0.1.0", "wasmer-runtime 0.1.4", "wasmer-runtime-core 0.1.2", ] @@ -1246,6 +1247,21 @@ dependencies = [ "wasmer-runtime-core 0.1.2", ] +[[package]] +name = "wasmer-golang" +version = "0.1.0" +dependencies = [ + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (git+https://github.com/rust-lang/libc)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmer-clif-backend 0.1.2", + "wasmer-runtime-core 0.1.2", +] + [[package]] name = "wasmer-runtime" version = "0.1.4" diff --git a/Cargo.toml b/Cargo.toml index 15b09e542..a0b24bfbd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,9 +25,10 @@ wasmer-clif-backend = { path = "lib/clif-backend" } wasmer-runtime = { path = "lib/runtime" } wasmer-runtime-core = { path = "lib/runtime-core" } wasmer-emscripten = { path = "lib/emscripten" } +wasmer-golang = { path = "lib/golang" } [workspace] -members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api"] +members = ["lib/clif-backend", "lib/runtime", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/golang"] [build-dependencies] wabt = "0.7.2" diff --git a/lib/golang/Cargo.toml b/lib/golang/Cargo.toml new file mode 100644 index 000000000..5917288a6 --- /dev/null +++ b/lib/golang/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "wasmer-golang" +version = "0.1.0" +description = "Wasmer runtime golang implementation library" +license = "MIT" +authors = ["The Wasmer Engineering Team "] +repository = "https://github.com/wasmerio/wasmer" +edition = "2018" + +[dependencies] +wasmer-runtime-core = { path = "../runtime-core", version = "0.1.0" } +lazy_static = "1.2.0" +libc = { git = "https://github.com/rust-lang/libc" } +byteorder = "1" +time = "0.1.41" + +[target.'cfg(windows)'.dependencies] +rand = "0.6" + +[dev-dependencies] +wasmer-clif-backend = { path = "../clif-backend", version = "0.1.0" } +wabt = "0.7.2" + +[build-dependencies] +glob = "0.2.11" diff --git a/lib/golang/README.md b/lib/golang/README.md new file mode 100644 index 000000000..bde447c96 --- /dev/null +++ b/lib/golang/README.md @@ -0,0 +1,14 @@ + +# Wasmer Golang Library +This library is to support Go programs + +## Running Example +`cargo run run hello.wasm` + +## Go version +The `examples/hello.wasm` file was compiled with go version 1.11.5. + +## TODOs +- Complete implementation +- Add tests +- Output main args \ No newline at end of file diff --git a/lib/golang/src/lib.rs b/lib/golang/src/lib.rs new file mode 100644 index 000000000..1b759603a --- /dev/null +++ b/lib/golang/src/lib.rs @@ -0,0 +1,129 @@ +#[macro_use] +extern crate wasmer_runtime_core; +use std::ffi::c_void; +use wasmer_runtime_core::{ + error::CallResult, import::ImportObject, module::Module, types::Value, vm::Ctx, Instance, +}; + +/// We check if a provided module is an Golang generated one +pub fn is_golang_module(module: &Module) -> bool { + for (_, import_name) in &module.info().imported_functions { + let namespace = module + .info() + .namespace_table + .get(import_name.namespace_index); + let field = module.info().name_table.get(import_name.name_index); + if field == "debug" && namespace == "go" { + return true; + } + } + false +} + +pub fn run_golang_instance( + _module: &Module, + instance: &mut Instance, + path: &str, + args: Vec<&str>, +) -> CallResult<()> { + let main_func = instance.dyn_func("run")?; + let num_params = main_func.signature().params().len(); + let _result = match num_params { + 2 => { + // TODO let (argc, argv) = store_module_arguments(instance.context_mut(), path, args); + instance.call("run", &[Value::I32(0), Value::I32(0)])?; + // TODO instance.call("run", &[Value::I32(argc as i32), Value::I32(argv as i32)])?; + } + 0 => { + instance.call("run", &[])?; + } + _ => panic!( + "The golang main function has received an incorrect number of params {}", + num_params + ), + }; + + Ok(()) +} + +fn debug(_ctx: &mut Ctx, val: i32) { + panic!("debug not yet implemented"); +} + +fn runtimeWasmExit(_ctx: &mut Ctx, val: i32) { + panic!("runtimeWasmExit not yet implemented"); +} + +fn runtimeWasmWrite(_ctx: &mut Ctx, val: i32) { + panic!("runtimeWasmWrite not yet implemented"); +} + +fn runtimeNanotime(_ctx: &mut Ctx, val: i32) { + panic!("runtimeNanotime not yet implemented"); +} + +fn runtimeScheduleCallback(_ctx: &mut Ctx, val: i32) { + panic!("runtimeScheduleCallback not yet implemented"); +} + +fn runtimeClearScheduledCallback(_ctx: &mut Ctx, val: i32) { + panic!("runtimeClearScheduledCallback not yet implemented"); +} + +fn runtimeGetRandomData(_ctx: &mut Ctx, val: i32) { + panic!("runtimeGetRandomData not yet implemented"); +} + +fn syscallJsStringVal(_ctx: &mut Ctx, val: i32) { + panic!("syscallJsStringVal not yet implemented"); +} + +fn syscallJsValueGet(_ctx: &mut Ctx, val: i32) { + panic!("syscallJsValueGet not yet implemented"); +} + +fn syscallJsValueSet(_ctx: &mut Ctx, val: i32) { + panic!("syscallJsValueSet not yet implemented"); +} + +fn syscallJsValueSetIndex(_ctx: &mut Ctx, val: i32) { + panic!("syscallJsValueSetIndex not yet implemented"); +} + +fn syscallJsValueCall(_ctx: &mut Ctx, val: i32) { + panic!("syscallJsValueCall not yet implemented"); +} + +fn syscallJsValueNew(_ctx: &mut Ctx, val: i32) { + panic!("syscallJsValueNew not yet implemented"); +} + +fn syscallJsValuePrepareString(_ctx: &mut Ctx, val: i32) { + panic!("syscallJsValuePrepareString not yet implemented"); +} + +fn syscallJsValueLoadString(_ctx: &mut Ctx, val: i32) { + panic!("syscallJsValueLoadString not yet implemented"); +} + +pub fn generate_golang_env() -> ImportObject { + imports! { + "go" => { + "debug" => func!(crate::debug), + "runtime.wasmExit" => func!(crate::runtimeWasmExit), + "runtime.wasmWrite" => func!(crate::runtimeWasmWrite), + "runtime.nanotime" => func!(crate::runtimeNanotime), + "runtime.scheduleCallback" => func!(crate::runtimeScheduleCallback), + "runtime.clearScheduledCallback" => func!(crate::runtimeClearScheduledCallback), + "runtime.getRandomData" => func!(crate::runtimeGetRandomData), + "syscall/js.stringVal" => func!(crate::syscallJsStringVal), + "syscall/js.valueGet" => func!(crate::syscallJsValueGet), + "syscall/js.valueSet" => func!(crate::syscallJsValueSet), + "syscall/js.valueSetIndex" => func!(crate::syscallJsValueSetIndex), + "syscall/js.valueCall" => func!(crate::syscallJsValueCall), + "syscall/js.valueNew" => func!(crate::syscallJsValueNew), + "syscall/js.valuePrepareString" => func!(crate::syscallJsValuePrepareString), + "syscall/js.valueLoadString" => func!(crate::syscallJsValueLoadString), + }, + } +} diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index 6b8c9b54b..373db7f92 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -145,9 +145,11 @@ fn execute_wasm(options: &Run) -> Result<(), String> { wasmer_emscripten::generate_emscripten_env(&mut emscripten_globals), Some(emscripten_globals), // TODO Em Globals is here to extend, lifetime, find better solution ) + } else if wasmer_golang::is_golang_module(&module) { + (InstanceABI::Go, wasmer_golang::generate_golang_env(), None) } else { ( - InstanceABI::None, + InstanceABI::Go, wasmer_runtime_core::import::ImportObject::new(), None, ) diff --git a/src/webassembly.rs b/src/webassembly.rs index bbe50b4d6..b178e1814 100644 --- a/src/webassembly.rs +++ b/src/webassembly.rs @@ -6,6 +6,7 @@ use wasmer_runtime::{ }; use wasmer_emscripten::{is_emscripten_module, run_emscripten_instance}; +use wasmer_golang::{is_golang_module, run_golang_instance}; pub struct ResultObject { /// A webassembly::Module object representing the compiled WebAssembly module. @@ -19,6 +20,7 @@ pub struct ResultObject { #[derive(PartialEq)] pub enum InstanceABI { Emscripten, + Go, None, } @@ -83,8 +85,10 @@ pub fn run_instance( path: &str, args: Vec<&str>, ) -> CallResult<()> { - if is_emscripten_module(module) { + if is_emscripten_module(&module) { run_emscripten_instance(module, instance, path, args)?; + } else if is_golang_module(&module) { + run_golang_instance(module, instance, path, args)?; } else { instance.call("main", &[])?; };