Implement crash in gen-wasm

This commit is contained in:
Ayaz Hafiz 2022-11-22 17:04:49 -06:00
parent a8122662c2
commit 32400e37e1
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
4 changed files with 32 additions and 14 deletions

View file

@ -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

View file

@ -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!(

View file

@ -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<Mutex<Option<i32>>> = Default::default();
let panic_msg: Rc<Mutex<Option<(i32, u32)>>> = 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<Mutex<Option<i32>>> = Default::default();
let panic_msg: Rc<Mutex<Option<(i32, u32)>>> = 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<Mutex<Option<i32>>>) {
fn link_module(module: &mut Module, panic_msg: Rc<Mutex<Option<(i32, u32)>>>) {
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(())
},
);

View file

@ -1,4 +1,5 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@ -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);
}