diff --git a/.gitignore b/.gitignore index 87635559c0..fcd25052b9 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ zig-cache *.rs.bk *.o *.tmp +*.wasm # llvm human-readable output *.ll diff --git a/compiler/test_gen/src/helpers/wasm.rs b/compiler/test_gen/src/helpers/wasm.rs index cdf2a93629..e3389be87e 100644 --- a/compiler/test_gen/src/helpers/wasm.rs +++ b/compiler/test_gen/src/helpers/wasm.rs @@ -50,7 +50,7 @@ pub fn compile_and_load<'a, T: Wasm32Result>( save_wasm_file(&compiled_bytes, build_dir_hash) }; - load_bytes_into_runtime(compiled_bytes) + load_bytes_into_runtime(&compiled_bytes) } fn get_preprocessed_host_path() -> PathBuf { @@ -173,12 +173,12 @@ fn save_wasm_file(app_module_bytes: &[u8], build_dir_hash: u64) { ); } -fn load_bytes_into_runtime(bytes: Vec) -> wasmer::Instance { +fn load_bytes_into_runtime(bytes: &[u8]) -> wasmer::Instance { use wasmer::{Module, Store}; use wasmer_wasi::WasiState; let store = Store::default(); - let wasmer_module = Module::new(&store, &bytes).unwrap(); + let wasmer_module = Module::new(&store, bytes).unwrap(); // First, we create the `WasiEnv` let mut wasi_env = WasiState::new("hello").finalize().unwrap(); diff --git a/compiler/gen_wasm/tests/linking_tests_host.zig b/compiler/test_gen/src/helpers/wasm_linking_test_host.zig similarity index 100% rename from compiler/gen_wasm/tests/linking_tests_host.zig rename to compiler/test_gen/src/helpers/wasm_linking_test_host.zig diff --git a/compiler/test_gen/src/tests.rs b/compiler/test_gen/src/tests.rs index b5ab6f3633..f872a72c8f 100644 --- a/compiler/test_gen/src/tests.rs +++ b/compiler/test_gen/src/tests.rs @@ -19,6 +19,9 @@ pub mod gen_tags; mod helpers; pub mod wasm_str; +#[cfg(feature = "gen-wasm")] +pub mod wasm_linking; + use core::ffi::c_void; /// # Safety diff --git a/compiler/gen_wasm/tests/linking_tests.rs b/compiler/test_gen/src/wasm_linking.rs similarity index 82% rename from compiler/gen_wasm/tests/linking_tests.rs rename to compiler/test_gen/src/wasm_linking.rs index b3b5b65e3a..28ffaa9931 100644 --- a/compiler/gen_wasm/tests/linking_tests.rs +++ b/compiler/test_gen/src/wasm_linking.rs @@ -1,3 +1,5 @@ +#![cfg(feature = "gen-wasm")] + use bumpalo::Bump; use roc_gen_wasm::Env; use std::fs; @@ -17,8 +19,8 @@ use roc_mono::ir::{ }; use roc_mono::layout::{Builtin, Layout}; -const TEST_HOST_SOURCE: &str = "tests/linking_tests_host.zig"; -const TEST_HOST_TARGET: &str = "tests/linking_tests_host.wasm"; +const TEST_HOST_SOURCE: &str = "src/helpers/wasm_linking_test_host.zig"; +const TEST_HOST_TARGET: &str = "src/helpers/wasm_linking_test_host.wasm"; fn build_host() -> std::vec::Vec { let args = [ @@ -171,6 +173,29 @@ impl<'a> BackendInputs<'a> { } } +fn load_bytes_into_runtime(bytes: &[u8]) -> wasmer::Instance { + use wasmer::{Function, Module, Store}; + + let store = Store::default(); + let wasmer_module = Module::new(&store, bytes).unwrap(); + + let import_object = wasmer::imports!( + "env" => { + "js_called_indirectly_from_roc" => Function::new_native(&store, wasmer_import), + "js_called_indirectly_from_main" => Function::new_native(&store, wasmer_import), + "js_unused" => Function::new_native(&store, wasmer_import), + "js_called_directly_from_roc" => Function::new_native(&store, wasmer_import), + "js_called_directly_from_main" => Function::new_native(&store, wasmer_import), + } + ); + + wasmer::Instance::new(&wasmer_module, &import_object).unwrap() +} + +fn wasmer_import(x: i32) -> i32 { + x + 100 +} + #[test] fn test_linking_without_dce() { let arena = Bump::new(); @@ -201,10 +226,11 @@ fn test_linking_without_dce() { let (final_module, _called_preload_fns, _roc_main_index) = roc_gen_wasm::build_app_module(&env, &mut interns, host_module, procedures); + let mut buffer = Vec::with_capacity(final_module.size()); + final_module.serialize(&mut buffer); + if std::env::var("DEBUG_WASM").is_ok() { - let mut buffer = Vec::with_capacity(final_module.size()); - final_module.serialize(&mut buffer); - fs::write("tests/without_dce.wasm", buffer).unwrap(); + fs::write("tests/without_dce.wasm", &buffer).unwrap(); } let final_import_names = Vec::from_iter(final_module.import.imports.iter().map(|i| i.name)); @@ -219,6 +245,11 @@ fn test_linking_without_dce() { "js_called_directly_from_main", ] ); + + // Try to run it, make sure it doesn't crash + let instance = load_bytes_into_runtime(&buffer); + let start = instance.exports.get_function("_start").unwrap(); + start.call(&[]).unwrap(); } #[test] @@ -255,10 +286,10 @@ fn test_linking_with_dce() { final_module.eliminate_dead_code(env.arena, &called_preload_fns); + let mut buffer = Vec::with_capacity(final_module.size()); + final_module.serialize(&mut buffer); if std::env::var("DEBUG_WASM").is_ok() { - let mut buffer = Vec::with_capacity(final_module.size()); - final_module.serialize(&mut buffer); - fs::write("tests/with_dce.wasm", buffer).unwrap(); + fs::write("tests/with_dce.wasm", &buffer).unwrap(); } let final_import_names = Vec::from_iter(final_module.import.imports.iter().map(|i| i.name)); @@ -283,4 +314,9 @@ fn test_linking_with_dce() { (4, "js_unused"), ] ); + + // Try to run it, make sure it doesn't crash + let instance = load_bytes_into_runtime(&buffer); + let start = instance.exports.get_function("_start").unwrap(); + start.call(&[]).unwrap(); }