diff --git a/crates/compiler/gen_wasm/src/backend.rs b/crates/compiler/gen_wasm/src/backend.rs index 0782039768..2e0b54fc67 100644 --- a/crates/compiler/gen_wasm/src/backend.rs +++ b/crates/compiler/gen_wasm/src/backend.rs @@ -718,7 +718,7 @@ impl<'a> WasmBackend<'a> { Stmt::ExpectFx { .. } => todo!("expect-fx is not implemented in the wasm backend"), Stmt::RuntimeError(msg) => self.stmt_runtime_error(msg), - Stmt::Crash(_, _) => todo!(), + Stmt::Crash(sym, _) => self.stmt_crash(*sym), } } @@ -1016,6 +1016,16 @@ impl<'a> WasmBackend<'a> { self.code_builder.unreachable_(); } + pub fn stmt_crash(&mut self, msg: Symbol) { + let tag_id = 1; + // load the pointer + self.storage.load_symbols(&mut self.code_builder, &[msg]); + self.code_builder.i32_const(tag_id); + self.call_host_fn_after_loading_args("roc_panic", 2, false); + + self.code_builder.unreachable_(); + } + /********************************************************** EXPRESSIONS diff --git a/crates/compiler/test_gen/src/gen_panic.rs b/crates/compiler/test_gen/src/gen_panic.rs index 0822c90086..b0bbfba263 100644 --- a/crates/compiler/test_gen/src/gen_panic.rs +++ b/crates/compiler/test_gen/src/gen_panic.rs @@ -7,7 +7,7 @@ use crate::helpers::llvm::expect_runtime_error_panic; use crate::helpers::wasm::expect_runtime_error_panic; #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] #[should_panic = r#"User crash with message: "hello crash""#] fn crash_literal() { expect_runtime_error_panic!(indoc!( @@ -20,7 +20,7 @@ fn crash_literal() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] #[should_panic = r#"User crash with message: "hello crash""#] fn crash_variable() { expect_runtime_error_panic!(indoc!( @@ -35,7 +35,7 @@ fn crash_variable() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] #[should_panic = r#"User crash with message: "turns out this was fallible""#] fn crash_in_call() { expect_runtime_error_panic!(indoc!( @@ -55,7 +55,7 @@ fn crash_in_call() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] #[should_panic = r#"User crash with message: "no new even primes""#] fn crash_in_passed_closure() { expect_runtime_error_panic!(indoc!( diff --git a/crates/compiler/test_gen/src/helpers/wasm.rs b/crates/compiler/test_gen/src/helpers/wasm.rs index 835222ab74..3ae67fb57a 100644 --- a/crates/compiler/test_gen/src/helpers/wasm.rs +++ b/crates/compiler/test_gen/src/helpers/wasm.rs @@ -194,7 +194,7 @@ where let parsed = Module::parse(&env, &wasm_bytes[..]).expect("Unable to parse module"); let mut module = rt.load_module(parsed).expect("Unable to load module"); - let panic_msg: Rc>> = Default::default(); + let panic_msg: Rc>> = Default::default(); link_module(&mut module, panic_msg.clone()); let test_wrapper = module @@ -203,11 +203,18 @@ where match test_wrapper.call() { Err(e) => { - if let Some(msg_ptr) = *panic_msg.lock().unwrap() { + if let Some((msg_ptr, tag)) = *panic_msg.lock().unwrap() { let memory: &[u8] = get_memory(&rt); let msg = RocStr::decode(memory, msg_ptr as _); - Err(format!("Roc failed with message: \"{}\"", msg)) + dbg!(tag); + let msg = match tag { + 0 => format!(r#"Roc failed with message: "{}""#, msg), + 1 => format!(r#"User crash with message: "{}""#, msg), + tag => format!(r#"Got an invald panic tag: "{}""#, tag), + }; + + Err(msg) } else { Err(format!("{}", e)) } @@ -253,7 +260,7 @@ where let parsed = Module::parse(&env, wasm_bytes).expect("Unable to parse module"); let mut module = rt.load_module(parsed).expect("Unable to load module"); - let panic_msg: Rc>> = Default::default(); + let panic_msg: Rc>> = Default::default(); link_module(&mut module, panic_msg.clone()); let expected_len = num_refcounts as i32; @@ -316,13 +323,13 @@ fn read_i32(memory: &[u8], ptr: usize) -> i32 { i32::from_le_bytes(bytes) } -fn link_module(module: &mut Module, panic_msg: Rc>>) { +fn link_module(module: &mut Module, panic_msg: Rc>>) { let try_link_panic = module.link_closure( "env", "send_panic_msg_to_rust", - move |_call_context, msg_ptr: i32| { + move |_call_context, (msg_ptr, tag): (i32, u32)| { let mut w = panic_msg.lock().unwrap(); - *w = Some(msg_ptr); + *w = Some((msg_ptr, tag)); Ok(()) }, ); diff --git a/crates/compiler/test_gen/src/helpers/wasm_test_platform.c b/crates/compiler/test_gen/src/helpers/wasm_test_platform.c index 0b3aec64c6..28ea77de78 100644 --- a/crates/compiler/test_gen/src/helpers/wasm_test_platform.c +++ b/crates/compiler/test_gen/src/helpers/wasm_test_platform.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -123,11 +124,11 @@ void roc_dealloc(void *ptr, unsigned int alignment) //-------------------------- -extern void send_panic_msg_to_rust(void* msg); +extern void send_panic_msg_to_rust(void* msg, uint32_t tag_id); void roc_panic(void* msg, unsigned int tag_id) { - send_panic_msg_to_rust(msg); + send_panic_msg_to_rust(msg, tag_id); exit(101); }