diff --git a/compiler/test_gen/src/helpers/wasm.rs b/compiler/test_gen/src/helpers/wasm.rs index 100669c3f7..fb19a8a677 100644 --- a/compiler/test_gen/src/helpers/wasm.rs +++ b/compiler/test_gen/src/helpers/wasm.rs @@ -1,6 +1,8 @@ use core::cell::Cell; +use libc::c_char; use roc_gen_wasm::wasm_module::{Export, ExportType}; use std::collections::hash_map::DefaultHasher; +use std::ffi::CStr; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::path::{Path, PathBuf}; @@ -17,7 +19,7 @@ const OUT_DIR_VAR: &str = "TEST_GEN_OUT"; const TEST_WRAPPER_NAME: &str = "test_wrapper"; const INIT_REFCOUNT_NAME: &str = "init_refcount_test"; -const GET_PANIC_MSG_NAME: &str = "get_panic_msg"; +const PANIC_MSG_NAME: &str = "panic_msg"; fn promote_expr_to_module(src: &str) -> String { let mut buffer = String::from("app \"test\" provides [ main ] to \"./platform\"\n\nmain =\n"); @@ -135,15 +137,6 @@ fn compile_roc_to_wasm_bytes<'a, T: Wasm32Result>( index: init_refcount_idx, }); - // Export the getter function for panic messages - let get_panic_msg_bytes = GET_PANIC_MSG_NAME.as_bytes(); - let get_panic_msg_idx = module.names.functions[get_panic_msg_bytes]; - module.export.append(Export { - name: arena.alloc_slice_copy(get_panic_msg_bytes), - ty: ExportType::Func, - index: get_panic_msg_idx, - }); - module.remove_dead_preloads(env.arena, called_preload_fns); let mut app_module_bytes = std::vec::Vec::with_capacity(module.size()); @@ -202,10 +195,22 @@ where let test_wrapper = instance.exports.get_function(TEST_WRAPPER_NAME).unwrap(); match test_wrapper.call(&[]) { - Err(e) => match get_panic_msg(&instance, memory) { - Ok(msg) => Err(msg), - Err(_) => Err(format!("{}", e)), - }, + Err(e) => { + // Check if the error is from roc_panic + // Our test roc_panic stores a pointer to its message in a global variable so we can find it. + let panic_msg_global = instance.exports.get_global(PANIC_MSG_NAME).unwrap(); + let panic_msg_index = panic_msg_global.get().unwrap_i32() as usize; + if panic_msg_index == 0 { + // Pointer is null. The error isn't a roc_panic. + Err(e.to_string()) + } else { + let memory_bytes = unsafe { memory.data_unchecked() }; + let msg_ptr = memory_bytes[panic_msg_index..].as_ptr() as *const c_char; + let msg_cstr = unsafe { CStr::from_ptr(msg_ptr) }; + let msg_str = msg_cstr.to_str().unwrap(); + Err(msg_str.into()) + } + } Ok(result) => { let address = result[0].unwrap_i32(); @@ -226,35 +231,6 @@ where } } -/// Call our test platform's getter function for panic messages -fn get_panic_msg(instance: &wasmer::Instance, memory: &wasmer::Memory) -> Result { - let msg_getter = instance - .exports - .get_function(GET_PANIC_MSG_NAME) - .map_err(|e| format!("{:?}", e))?; - - let msg_result = msg_getter.call(&[]).map_err(|e| format!("{:?}", e))?; - - let msg_addr: i32 = match msg_result[0] { - wasmer::Value::I32(a) => a, - _ => panic!(), - }; - if msg_addr == 0 { - return Err("no panic msg".to_string()); - } - - let msg_index = msg_addr as usize; - let memory_bytes = unsafe { memory.data_unchecked() }; - let msg_len = memory_bytes[msg_index..] - .iter() - .position(|c| *c == 0) - .unwrap(); - - let msg_bytes = &memory_bytes[msg_index..msg_len]; - let msg = unsafe { String::from_utf8_unchecked(msg_bytes.to_vec()) }; - Ok(msg) -} - #[allow(dead_code)] pub fn assert_wasm_refcounts_help( src: &str, diff --git a/compiler/test_gen/src/helpers/wasm_test_platform.c b/compiler/test_gen/src/helpers/wasm_test_platform.c index c67853604e..2a70f8dc65 100644 --- a/compiler/test_gen/src/helpers/wasm_test_platform.c +++ b/compiler/test_gen/src/helpers/wasm_test_platform.c @@ -124,9 +124,6 @@ void roc_dealloc(void *ptr, unsigned int alignment) // Allow the test to probe the panic message char* panic_msg; -char* get_panic_msg() { - return panic_msg; -} void roc_panic(char *msg, unsigned int tag_id) {