diff --git a/lib/c-api/src/wasm_c_api/externals/function.rs b/lib/c-api/src/wasm_c_api/externals/function.rs index 22366809f0a..86e7a84b2e5 100644 --- a/lib/c-api/src/wasm_c_api/externals/function.rs +++ b/lib/c-api/src/wasm_c_api/externals/function.rs @@ -60,8 +60,11 @@ pub unsafe extern "C" fn wasm_func_new( num_rets ]; - let _traps = callback(processed_args.as_ptr(), results.as_mut_ptr()); - // TODO: do something with `traps` + let trap = callback(processed_args.as_ptr(), results.as_mut_ptr()); + if !trap.is_null() { + let trap: Box = Box::from_raw(trap); + RuntimeError::raise(Box::new(trap.inner)); + } let processed_results = results .into_iter() @@ -134,7 +137,7 @@ pub unsafe extern "C" fn wasm_func_call( func: &wasm_func_t, args: *const wasm_val_t, results: *mut wasm_val_t, -) -> Option> { +) -> Option> { let num_params = func.inner.ty().params().len(); let params: Vec = (0..num_params) .map(|i| (&(*args.add(i))).try_into()) @@ -149,7 +152,7 @@ pub unsafe extern "C" fn wasm_func_call( } None } - Err(e) => Some(NonNull::new_unchecked(Box::into_raw(Box::new(e)) as _)), + Err(e) => Some(Box::new(e.into())), } } diff --git a/lib/c-api/src/wasm_c_api/macros.rs b/lib/c-api/src/wasm_c_api/macros.rs index 9a022ce3869..36dbf47f6e5 100644 --- a/lib/c-api/src/wasm_c_api/macros.rs +++ b/lib/c-api/src/wasm_c_api/macros.rs @@ -36,6 +36,37 @@ macro_rules! wasm_declare_vec { pub data: *mut [], } + impl<'a> From]>> for [] { + fn from(other: Vec<[]>) -> Self { + let mut boxed_slice = other.into_boxed_slice(); + let size = boxed_slice.len(); + let data = boxed_slice.as_mut_ptr(); + ::std::mem::forget(boxed_slice); + Self { + size, + data, + } + } + } + + impl<'a, T: Into<[]> + Clone> From<&'a [T]> for [] { + fn from(other: &'a [T]) -> Self { + let size = other.len(); + let mut copied_data = other + .iter() + .cloned() + .map(Into::into) + .collect::]>>() + .into_boxed_slice(); + let data = copied_data.as_mut_ptr(); + ::std::mem::forget(copied_data); + Self { + size, + data, + } + } + } + impl [] { pub unsafe fn into_slice(&self) -> Option<&[[]]>{ if self.data.is_null() { diff --git a/lib/c-api/src/wasm_c_api/trap.rs b/lib/c-api/src/wasm_c_api/trap.rs index 104cabe9767..6bb4758be69 100644 --- a/lib/c-api/src/wasm_c_api/trap.rs +++ b/lib/c-api/src/wasm_c_api/trap.rs @@ -1,51 +1,59 @@ -use super::types::wasm_byte_vec_t; -use std::mem; -use std::ptr::NonNull; +use super::store::wasm_store_t; +use super::types::{wasm_byte_vec_t, wasm_frame_t, wasm_frame_vec_t, wasm_message_t}; use wasmer::RuntimeError; // opaque type which is a `RuntimeError` /// cbindgen:ignore #[allow(non_camel_case_types)] -pub struct wasm_trap_t {} +pub struct wasm_trap_t { + pub(crate) inner: RuntimeError, +} + +impl From for wasm_trap_t { + fn from(other: RuntimeError) -> Self { + Self { inner: other } + } +} /// cbindgen:ignore #[no_mangle] -pub unsafe extern "C" fn wasm_trap_delete(trap: Option>) { - if let Some(t_inner) = trap { - let _ = Box::from_raw(t_inner.cast::().as_ptr()); - } +pub unsafe extern "C" fn wasm_trap_new( + _store: &mut wasm_store_t, + message: &wasm_message_t, +) -> Option> { + let message_bytes: &[u8] = message.into_slice()?; + let message_str = c_try!(std::str::from_utf8(message_bytes)); + let runtime_error = RuntimeError::new(message_str); + let trap = runtime_error.into(); + + Some(Box::new(trap)) } /// cbindgen:ignore #[no_mangle] -pub unsafe extern "C" fn wasm_trap_message( - trap: *const wasm_trap_t, - out_ptr: *mut wasm_byte_vec_t, -) { - let re = &*(trap as *const RuntimeError); - // this code assumes no nul bytes appear in the message - let mut message = format!("{}\0", re); - message.shrink_to_fit(); - - // TODO use `String::into_raw_parts` when it gets stabilized - (*out_ptr).size = message.as_bytes().len(); - (*out_ptr).data = message.as_mut_ptr(); - mem::forget(message); +pub unsafe extern "C" fn wasm_trap_delete(_trap: Option>) {} + +/// cbindgen:ignore +#[no_mangle] +pub unsafe extern "C" fn wasm_trap_message(trap: &wasm_trap_t, out_ptr: &mut wasm_byte_vec_t) { + let message = trap.inner.message(); + let byte_vec: wasm_byte_vec_t = message.into_bytes().into(); + out_ptr.size = byte_vec.size; + out_ptr.data = byte_vec.data; } -// in trap/RuntimeError we need to store -// 1. message -// 2. origin (frame); frame contains: -// 1. func index -// 2. func offset -// 3. module offset -// 4. which instance this was apart of - -/*#[no_mangle] -pub unsafe extern "C" fn wasm_trap_trace(trap: *const wasm_trap_t, out_ptr: *mut wasm_frame_vec_t) { - let re = &*(trap as *const RuntimeError); - todo!() -}*/ - -//wasm_declare_ref!(trap); -//wasm_declare_ref!(foreign); +/// cbindgen:ignore +#[no_mangle] +pub unsafe extern "C" fn wasm_trap_origin(trap: &wasm_trap_t) -> Option> { + trap.inner.trace().first().map(Into::into).map(Box::new) +} + +/// cbindgen:ignore +#[no_mangle] +pub unsafe extern "C" fn wasm_trap_trace(trap: &wasm_trap_t, out_ptr: &mut wasm_frame_vec_t) { + let frames = trap.inner.trace(); + let frame_vec: wasm_frame_vec_t = frames.into(); + + out_ptr.size = frame_vec.size; + out_ptr.data = frame_vec.data; +} diff --git a/lib/c-api/src/wasm_c_api/types/frame.rs b/lib/c-api/src/wasm_c_api/types/frame.rs new file mode 100644 index 00000000000..9fc841671ac --- /dev/null +++ b/lib/c-api/src/wasm_c_api/types/frame.rs @@ -0,0 +1,51 @@ +use super::super::instance::wasm_instance_t; +use wasmer::FrameInfo; + +#[derive(Debug, Clone)] +#[repr(C)] +pub struct wasm_frame_t { + info: FrameInfo, +} + +impl<'a> From<&'a FrameInfo> for wasm_frame_t { + fn from(other: &'a FrameInfo) -> Self { + other.clone().into() + } +} + +impl From for wasm_frame_t { + fn from(other: FrameInfo) -> Self { + Self { info: other } + } +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_copy(frame: &wasm_frame_t) -> Box { + Box::new(frame.clone()) +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_delete(_frame: Option>) {} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_instance(frame: &wasm_frame_t) -> *const wasm_instance_t { + //todo!("wasm_frame_instance") + std::ptr::null() +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_func_index(frame: &wasm_frame_t) -> u32 { + frame.info.func_index() +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_func_offset(frame: &wasm_frame_t) -> usize { + frame.info.func_offset() +} + +#[no_mangle] +pub unsafe extern "C" fn wasm_frame_module_offset(frame: &wasm_frame_t) -> usize { + frame.info.module_offset() +} + +wasm_declare_vec!(frame); diff --git a/lib/c-api/src/wasm_c_api/types/mod.rs b/lib/c-api/src/wasm_c_api/types/mod.rs index 65bd9e6d31b..c2212a76099 100644 --- a/lib/c-api/src/wasm_c_api/types/mod.rs +++ b/lib/c-api/src/wasm_c_api/types/mod.rs @@ -1,5 +1,6 @@ mod export; mod extern_; +mod frame; mod function; mod global; mod import; @@ -10,6 +11,7 @@ mod value; pub use export::*; pub use extern_::*; +pub use frame::*; pub use function::*; pub use global::*; pub use import::*; @@ -23,12 +25,6 @@ pub type wasm_byte_t = u8; wasm_declare_vec!(byte); -#[derive(Debug)] -#[repr(C)] -pub struct wasm_frame_t {} - -wasm_declare_vec!(frame); - /// cbindgen:ignore #[allow(non_camel_case_types)] pub type wasm_name_t = wasm_byte_vec_t; @@ -37,3 +33,7 @@ pub type wasm_name_t = wasm_byte_vec_t; /// cbindgen:ignore #[allow(non_camel_case_types)] pub struct wasm_ref_t; + +/// cbindgen:ignore +#[allow(non_camel_case_types)] +pub type wasm_message_t = wasm_byte_vec_t;