Files
wasmtime/crates/c-api/src/trap.rs
Alex Crichton 7a1b7cdf92 Implement RFC 11: Redesigning Wasmtime's APIs (#2897)
Implement Wasmtime's new API as designed by RFC 11. This is quite a large commit which has had lots of discussion externally, so for more information it's best to read the RFC thread and the PR thread.
2021-06-03 09:10:53 -05:00

153 lines
3.9 KiB
Rust

use crate::{wasm_frame_vec_t, wasm_instance_t, wasm_name_t, wasm_store_t};
use once_cell::unsync::OnceCell;
use wasmtime::Trap;
#[repr(C)]
#[derive(Clone)]
pub struct wasm_trap_t {
pub(crate) trap: Trap,
}
wasmtime_c_api_macros::declare_ref!(wasm_trap_t);
impl wasm_trap_t {
pub(crate) fn new(trap: Trap) -> wasm_trap_t {
wasm_trap_t { trap: trap }
}
}
#[repr(C)]
#[derive(Clone)]
pub struct wasm_frame_t {
trap: Trap,
idx: usize,
func_name: OnceCell<Option<wasm_name_t>>,
module_name: OnceCell<Option<wasm_name_t>>,
}
wasmtime_c_api_macros::declare_own!(wasm_frame_t);
pub type wasm_message_t = wasm_name_t;
#[no_mangle]
pub extern "C" fn wasm_trap_new(
_store: &wasm_store_t,
message: &wasm_message_t,
) -> Box<wasm_trap_t> {
let message = message.as_slice();
if message[message.len() - 1] != 0 {
panic!("wasm_trap_new message stringz expected");
}
let message = String::from_utf8_lossy(&message[..message.len() - 1]);
Box::new(wasm_trap_t {
trap: Trap::new(message),
})
}
#[no_mangle]
pub unsafe extern "C" fn wasmtime_trap_new(message: *const u8, len: usize) -> Box<wasm_trap_t> {
let bytes = crate::slice_from_raw_parts(message, len);
let message = String::from_utf8_lossy(&bytes);
Box::new(wasm_trap_t {
trap: Trap::new(message),
})
}
#[no_mangle]
pub extern "C" fn wasm_trap_message(trap: &wasm_trap_t, out: &mut wasm_message_t) {
let mut buffer = Vec::new();
buffer.extend_from_slice(trap.trap.to_string().as_bytes());
buffer.reserve_exact(1);
buffer.push(0);
out.set_buffer(buffer);
}
#[no_mangle]
pub extern "C" fn wasm_trap_origin(raw: &wasm_trap_t) -> Option<Box<wasm_frame_t>> {
if raw.trap.trace().len() > 0 {
Some(Box::new(wasm_frame_t {
trap: raw.trap.clone(),
idx: 0,
func_name: OnceCell::new(),
module_name: OnceCell::new(),
}))
} else {
None
}
}
#[no_mangle]
pub extern "C" fn wasm_trap_trace(raw: &wasm_trap_t, out: &mut wasm_frame_vec_t) {
let vec = (0..raw.trap.trace().len())
.map(|idx| {
Some(Box::new(wasm_frame_t {
trap: raw.trap.clone(),
idx,
func_name: OnceCell::new(),
module_name: OnceCell::new(),
}))
})
.collect();
out.set_buffer(vec);
}
#[no_mangle]
pub extern "C" fn wasmtime_trap_exit_status(raw: &wasm_trap_t, status: &mut i32) -> bool {
match raw.trap.i32_exit_status() {
Some(i) => {
*status = i;
true
}
None => false,
}
}
#[no_mangle]
pub extern "C" fn wasm_frame_func_index(frame: &wasm_frame_t) -> u32 {
frame.trap.trace()[frame.idx].func_index()
}
#[no_mangle]
pub extern "C" fn wasmtime_frame_func_name(frame: &wasm_frame_t) -> Option<&wasm_name_t> {
frame
.func_name
.get_or_init(|| {
frame.trap.trace()[frame.idx]
.func_name()
.map(|s| wasm_name_t::from(s.to_string().into_bytes()))
})
.as_ref()
}
#[no_mangle]
pub extern "C" fn wasmtime_frame_module_name(frame: &wasm_frame_t) -> Option<&wasm_name_t> {
frame
.module_name
.get_or_init(|| {
frame.trap.trace()[frame.idx]
.module_name()
.map(|s| wasm_name_t::from(s.to_string().into_bytes()))
})
.as_ref()
}
#[no_mangle]
pub extern "C" fn wasm_frame_func_offset(frame: &wasm_frame_t) -> usize {
frame.trap.trace()[frame.idx].func_offset()
}
#[no_mangle]
pub extern "C" fn wasm_frame_instance(_arg1: *const wasm_frame_t) -> *mut wasm_instance_t {
unimplemented!("wasm_frame_instance")
}
#[no_mangle]
pub extern "C" fn wasm_frame_module_offset(frame: &wasm_frame_t) -> usize {
frame.trap.trace()[frame.idx].module_offset()
}
#[no_mangle]
pub extern "C" fn wasm_frame_copy(frame: &wasm_frame_t) -> Box<wasm_frame_t> {
Box::new(frame.clone())
}