1 use crate::{wasm_extern_t, wasm_extern_vec_t, wasm_module_t, wasm_trap_t}; 2 use crate::{wasm_instancetype_t, wasm_store_t, wasmtime_error_t}; 3 use anyhow::Result; 4 use std::ptr; 5 use wasmtime::{Extern, Instance, Trap}; 6 7 #[derive(Clone)] 8 #[repr(transparent)] 9 pub struct wasm_instance_t { 10 ext: wasm_extern_t, 11 } 12 13 wasmtime_c_api_macros::declare_ref!(wasm_instance_t); 14 15 impl wasm_instance_t { 16 pub(crate) fn new(instance: Instance) -> wasm_instance_t { 17 wasm_instance_t { 18 ext: wasm_extern_t { 19 which: instance.into(), 20 }, 21 } 22 } 23 24 pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_instance_t> { 25 match &e.which { 26 Extern::Instance(_) => Some(unsafe { &*(e as *const _ as *const _) }), 27 _ => None, 28 } 29 } 30 31 pub(crate) fn instance(&self) -> &Instance { 32 match &self.ext.which { 33 Extern::Instance(i) => i, 34 _ => unreachable!(), 35 } 36 } 37 } 38 39 #[no_mangle] 40 pub unsafe extern "C" fn wasm_instance_new( 41 store: &wasm_store_t, 42 wasm_module: &wasm_module_t, 43 imports: *const Box<wasm_extern_t>, 44 result: Option<&mut *mut wasm_trap_t>, 45 ) -> Option<Box<wasm_instance_t>> { 46 let mut instance = ptr::null_mut(); 47 let mut trap = ptr::null_mut(); 48 let err = wasmtime_instance_new( 49 store, 50 wasm_module, 51 imports, 52 wasm_module.module().imports().len(), 53 &mut instance, 54 &mut trap, 55 ); 56 match err { 57 Some(err) => { 58 assert!(trap.is_null()); 59 assert!(instance.is_null()); 60 if let Some(result) = result { 61 *result = Box::into_raw(err.to_trap()); 62 } 63 None 64 } 65 None => { 66 if instance.is_null() { 67 assert!(!trap.is_null()); 68 if let Some(result) = result { 69 *result = trap; 70 } else { 71 drop(Box::from_raw(trap)) 72 } 73 None 74 } else { 75 assert!(trap.is_null()); 76 Some(Box::from_raw(instance)) 77 } 78 } 79 } 80 } 81 82 #[no_mangle] 83 pub unsafe extern "C" fn wasmtime_instance_new( 84 store: &wasm_store_t, 85 module: &wasm_module_t, 86 imports: *const Box<wasm_extern_t>, 87 num_imports: usize, 88 instance_ptr: &mut *mut wasm_instance_t, 89 trap_ptr: &mut *mut wasm_trap_t, 90 ) -> Option<Box<wasmtime_error_t>> { 91 _wasmtime_instance_new( 92 store, 93 module, 94 std::slice::from_raw_parts(imports, num_imports), 95 instance_ptr, 96 trap_ptr, 97 ) 98 } 99 100 fn _wasmtime_instance_new( 101 store: &wasm_store_t, 102 module: &wasm_module_t, 103 imports: &[Box<wasm_extern_t>], 104 instance_ptr: &mut *mut wasm_instance_t, 105 trap_ptr: &mut *mut wasm_trap_t, 106 ) -> Option<Box<wasmtime_error_t>> { 107 let store = &store.store; 108 let imports = imports 109 .iter() 110 .map(|import| import.which.clone()) 111 .collect::<Vec<_>>(); 112 handle_instantiate( 113 Instance::new(store, module.module(), &imports), 114 instance_ptr, 115 trap_ptr, 116 ) 117 } 118 119 pub fn handle_instantiate( 120 instance: Result<Instance>, 121 instance_ptr: &mut *mut wasm_instance_t, 122 trap_ptr: &mut *mut wasm_trap_t, 123 ) -> Option<Box<wasmtime_error_t>> { 124 fn write<T>(ptr: &mut *mut T, val: T) { 125 *ptr = Box::into_raw(Box::new(val)) 126 } 127 128 match instance { 129 Ok(instance) => { 130 write(instance_ptr, wasm_instance_t::new(instance)); 131 None 132 } 133 Err(e) => match e.downcast::<Trap>() { 134 Ok(trap) => { 135 write(trap_ptr, wasm_trap_t::new(trap)); 136 None 137 } 138 Err(e) => Some(Box::new(e.into())), 139 }, 140 } 141 } 142 143 #[no_mangle] 144 pub extern "C" fn wasm_instance_as_extern(m: &wasm_instance_t) -> &wasm_extern_t { 145 &m.ext 146 } 147 148 #[no_mangle] 149 pub extern "C" fn wasm_instance_exports(instance: &wasm_instance_t, out: &mut wasm_extern_vec_t) { 150 out.set_buffer( 151 instance 152 .instance() 153 .exports() 154 .map(|e| { 155 Some(Box::new(wasm_extern_t { 156 which: e.into_extern(), 157 })) 158 }) 159 .collect(), 160 ); 161 } 162 163 #[no_mangle] 164 pub extern "C" fn wasm_instance_type(f: &wasm_instance_t) -> Box<wasm_instancetype_t> { 165 Box::new(wasm_instancetype_t::new(f.instance().ty())) 166 } 167