1 use crate::host_ref::HostRef;
2 use crate::{wasm_frame_vec_t, wasm_instance_t, wasm_name_t, wasm_store_t};
3 use once_cell::unsync::OnceCell;
4 use wasmtime::{Store, Trap};
5 
6 #[repr(C)]
7 #[derive(Clone)]
8 pub struct wasm_trap_t {
9     pub(crate) trap: HostRef<Trap>,
10 }
11 
12 wasmtime_c_api_macros::declare_ref!(wasm_trap_t);
13 
14 impl wasm_trap_t {
new(store: &Store, trap: Trap) -> wasm_trap_t15     pub(crate) fn new(store: &Store, trap: Trap) -> wasm_trap_t {
16         wasm_trap_t {
17             trap: HostRef::new(store, trap),
18         }
19     }
20 
externref(&self) -> wasmtime::ExternRef21     fn externref(&self) -> wasmtime::ExternRef {
22         self.trap.clone().into()
23     }
24 }
25 
26 #[repr(C)]
27 #[derive(Clone)]
28 pub struct wasm_frame_t {
29     trap: HostRef<Trap>,
30     idx: usize,
31     func_name: OnceCell<Option<wasm_name_t>>,
32     module_name: OnceCell<Option<wasm_name_t>>,
33 }
34 
35 wasmtime_c_api_macros::declare_own!(wasm_frame_t);
36 
37 pub type wasm_message_t = wasm_name_t;
38 
39 #[no_mangle]
wasm_trap_new( store: &wasm_store_t, message: &wasm_message_t, ) -> Box<wasm_trap_t>40 pub extern "C" fn wasm_trap_new(
41     store: &wasm_store_t,
42     message: &wasm_message_t,
43 ) -> Box<wasm_trap_t> {
44     let message = message.as_slice();
45     if message[message.len() - 1] != 0 {
46         panic!("wasm_trap_new message stringz expected");
47     }
48     let message = String::from_utf8_lossy(&message[..message.len() - 1]);
49     Box::new(wasm_trap_t {
50         trap: HostRef::new(&store.store, Trap::new(message)),
51     })
52 }
53 
54 #[no_mangle]
wasm_trap_message(trap: &wasm_trap_t, out: &mut wasm_message_t)55 pub extern "C" fn wasm_trap_message(trap: &wasm_trap_t, out: &mut wasm_message_t) {
56     let mut buffer = Vec::new();
57     buffer.extend_from_slice(trap.trap.borrow().to_string().as_bytes());
58     buffer.reserve_exact(1);
59     buffer.push(0);
60     out.set_buffer(buffer);
61 }
62 
63 #[no_mangle]
wasm_trap_origin(raw: &wasm_trap_t) -> Option<Box<wasm_frame_t>>64 pub extern "C" fn wasm_trap_origin(raw: &wasm_trap_t) -> Option<Box<wasm_frame_t>> {
65     let trap = raw.trap.borrow();
66     if trap.trace().len() > 0 {
67         Some(Box::new(wasm_frame_t {
68             trap: raw.trap.clone(),
69             idx: 0,
70             func_name: OnceCell::new(),
71             module_name: OnceCell::new(),
72         }))
73     } else {
74         None
75     }
76 }
77 
78 #[no_mangle]
wasm_trap_trace(raw: &wasm_trap_t, out: &mut wasm_frame_vec_t)79 pub extern "C" fn wasm_trap_trace(raw: &wasm_trap_t, out: &mut wasm_frame_vec_t) {
80     let trap = raw.trap.borrow();
81     let vec = (0..trap.trace().len())
82         .map(|idx| {
83             Some(Box::new(wasm_frame_t {
84                 trap: raw.trap.clone(),
85                 idx,
86                 func_name: OnceCell::new(),
87                 module_name: OnceCell::new(),
88             }))
89         })
90         .collect();
91     out.set_buffer(vec);
92 }
93 
94 #[no_mangle]
wasm_frame_func_index(frame: &wasm_frame_t) -> u3295 pub extern "C" fn wasm_frame_func_index(frame: &wasm_frame_t) -> u32 {
96     frame.trap.borrow().trace()[frame.idx].func_index()
97 }
98 
99 #[no_mangle]
wasmtime_frame_func_name(frame: &wasm_frame_t) -> Option<&wasm_name_t>100 pub extern "C" fn wasmtime_frame_func_name(frame: &wasm_frame_t) -> Option<&wasm_name_t> {
101     frame
102         .func_name
103         .get_or_init(|| {
104             let trap = frame.trap.borrow();
105             trap.trace()[frame.idx]
106                 .func_name()
107                 .map(|s| wasm_name_t::from(s.to_string().into_bytes()))
108         })
109         .as_ref()
110 }
111 
112 #[no_mangle]
wasmtime_frame_module_name(frame: &wasm_frame_t) -> Option<&wasm_name_t>113 pub extern "C" fn wasmtime_frame_module_name(frame: &wasm_frame_t) -> Option<&wasm_name_t> {
114     frame
115         .module_name
116         .get_or_init(|| {
117             let trap = frame.trap.borrow();
118             trap.trace()[frame.idx]
119                 .module_name()
120                 .map(|s| wasm_name_t::from(s.to_string().into_bytes()))
121         })
122         .as_ref()
123 }
124 
125 #[no_mangle]
wasm_frame_func_offset(frame: &wasm_frame_t) -> usize126 pub extern "C" fn wasm_frame_func_offset(frame: &wasm_frame_t) -> usize {
127     let trap = frame.trap.borrow();
128     trap.trace()[frame.idx].func_offset()
129 }
130 
131 #[no_mangle]
wasm_frame_instance(_arg1: *const wasm_frame_t) -> *mut wasm_instance_t132 pub extern "C" fn wasm_frame_instance(_arg1: *const wasm_frame_t) -> *mut wasm_instance_t {
133     unimplemented!("wasm_frame_instance")
134 }
135 
136 #[no_mangle]
wasm_frame_module_offset(frame: &wasm_frame_t) -> usize137 pub extern "C" fn wasm_frame_module_offset(frame: &wasm_frame_t) -> usize {
138     let trap = frame.trap.borrow();
139     trap.trace()[frame.idx].module_offset()
140 }
141